update: 重构顶部模块包含logo、PC菜单、移动端菜单、登录注册开店流程交互;干掉之前的index全局样式,全部挪到组件里面。

This commit is contained in:
mixtan 2025-06-16 14:55:34 +08:00
parent 5c3f301eb9
commit 3f9b13020a
9 changed files with 370 additions and 442 deletions

3
components.d.ts vendored
View File

@ -18,6 +18,9 @@ declare module 'vue' {
ElCol: typeof import('element-plus/es')['ElCol']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']

View File

@ -76,217 +76,3 @@ html{
color: inherit;
background: inherit;
}
/* 页面头部 */
.header {
height: 70px;
}
/* 固定定位*/
.header-list {
width: 100%;
height: 70px;
background-color: #fff;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.header-list .el-row{
width: 100%;
max-width: 1440px;
margin: auto;
}
.header-top {
max-width: 1440px;
width: 100%;
height: 70px;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
}
/* logo */
.logo {
width: 60px;
padding-left: 20px;
}
.logo a {
background: url("../../assets/image/logo.jpg") no-repeat;
width: 48px;
height: 48px;
border-radius: 5px;
display: inline-block;
background-size: contain;
outline: none;
}
/*头部导航*/
.header-top ul {
flex: 1;
display: flex;
line-height: 60px;
}
.header-menu {
display: flex;
}
.header-menu li {
margin: 0 30px;
list-style: none;
position: relative;
color: #333;
}
.header-menu a {
text-decoration: none;
color: inherit;
}
.header-menu li span {
font-size: 16px;
}
/* 伪元素添加下滑选中线 */
.header-menu li:hover span,
.header-menu .router-link-active span
{
color: var(--bgcolor);
}
/*TODO 记得搞一个导航active的*/
.header-menu li::before
{
content: "";
position: absolute;
bottom: 0px;
left: 50%;
width: 0;
height: 100%;
border-bottom: 3px solid var(--bgcolor);
transition: all 0.2s;
}
.header-menu li:hover::before,
.header-menu .router-link-active li::before
{
content: "";
left: 0;
width: 100%;
}
.header-right {
display: flex;
justify-content: flex-end;
}
.header-right .start {
margin-right: 20px;
}
.header-right .start .start-button {
background-color: black;
border-radius: 20px;
}
.header-right .login{
margin-right: 20px;
}
.header-right .login .login-button {
}
.header-right .logout {
margin-right: 20px;
}
.header-right .logout .logout-button {
border: none;
}
/*公司*/
.company-detail {
display: flex;
}
.company-detail img {
width: 100%;
height: 100%;
object-fit: cover;
padding-right:20px;
}
.company-introduce {
padding: 20px;
letter-spacing: 2px;
line-height: 34px;
padding-bottom: 0;
}
/*轮播图*/
.banner-list {
width: 100%;
max-width: 1200px;
margin: auto;
position: relative;
}
.banner-list .el-carousel__container {
width: 100%;
padding-bottom: 50%; /* 高度自适应宽度的一半 */
position: relative;
}
.banner-list .el-carousel__item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.banner-list .el-carousel__item img {
width: 100%;
height: 100%;
object-fit: cover;
}
/*服务*/
.container-bg {
padding: 50px 0;
}
.service-contain {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
padding-top: 30px;
}
.service-list {
width: 100%;
}
.service-list ul {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
align-items: center;
width: 100%;
}
.service-list ul li {
list-style: none;
width: 30%;
height: 211.6px;
padding: 30px 20px;
text-align: center;
box-shadow: 0 15px 25px 0 rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
.service-list ul li i::before {
font-size: 70px;
color: #353535;
transition: 0.3s;
}
.service-list ul li h4 {
font-size: 26px;
font-weight: 500;
margin-top: 10px;
transition: 0.3s;
}
.service-list ul li:hover {
background: linear-gradient(90.54deg, #ec4b2b 0.42%, #f85535 102.71%);
}
.service-list ul li:hover i::before {
color: #fff;
}
.service-list ul li:hover h4 {
color: #fff;
}
.service-list ul li:hover i::before p {
color: #fff;
}

View File

@ -158,7 +158,7 @@ const register = async () => {
if (approvalRes.data.code === 0 && approvalRes.data.status === 200) {
const approvalStatus = approvalRes.data.approval_status;
localStorage.setItem("approval_status", approvalStatus);
if (approvalStatus == "4") {
if (approvalStatus == "4" || approvalRes.data==null) {
router.push({ name: "start" });
} else {
router.push({ name: "check" });

View File

@ -1,131 +1,161 @@
<template>
<div class="header">
<div class="header-list">
<el-row>
<div class="header-top">
<el-col :span="4">
<div class="logo">
<img src="@/assets/image/logo.png">
<img src="@/assets/image/logo.png" />
</div>
</el-col>
<el-col :span="12">
<ul class="header-menu">
<router-link v-for="(item, index) in headlist" :key="index" :to="item.path">
<li><span>{{ item.title }}</span></li>
<router-link
v-for="(item, index) in headlist"
:key="index"
:to="item.path"
>
<li>
<span>{{ item.title }}</span>
</li>
</router-link>
</ul>
</el-col>
<el-col :span="8">
<div class="header-right">
<div class="start">
<el-button color="#ea4322" @click="handleOpenStartPage">
立即入驻
<el-button plain type="danger" @click="handleOpenStartPage">
{{
approval_status == 4 || !isLoggedIn ? "立即入驻" : "查看审核状态"
}}
</el-button>
</div>
<!-- <div class="login">
<!-- <div v-if="!isLoggedIn" class="login">
<el-button plain color="#f85535" @click="openLoginForm" class="login-button">
商家登录
</el-button>
</div> -->
<div class="avatar">
<div class="icon_avatar">
<el-icon size="20"><Avatar /></el-icon>
</div>
<el-button
link
@click="handleUserInfoClick"
:title="approval_status == 4 ? '点击立即入驻' : '点击查看审核详情'"
>
{{ mobile }}
</el-button>
</div>
<div v-if="isLoggedIn" class="logout">
<el-button type="danger" plain @click="logout" class="logout-button">
<el-button type="info" plain @click="logout" class="logout-button">
退出
</el-button>
</div>
</div>
</el-col>
</div>
</el-row>
</div>
<div class="login-register-module">
<span @click="handleOpenStartPage">立即入驻</span>
<span>|</span>
<span @click="openLoginForm">商家登录</span>
<span v-if="isLoggedIn" @click="logout">退出</span>
<div class="sub_menu">
<el-dropdown placement="bottom-end">
<el-icon size="24"><Menu /></el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
v-for="(item, index) in headlist"
@click="toRouter(item.path)"
:key="index"
>{{ item.title }}</el-dropdown-item
>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<!-- 汉堡菜单 -->
<div class="hamburger-menu" @click="toggleMenu">
<span :class="{ 'hamburger-icon': true, 'rotate-top': isMenuOpen, }"></span>
<span :class="{ 'hamburger-icon': true, 'hide-middle': isMenuOpen }"></span>
<span :class="{ 'hamburger-icon': true, 'rotate-bottom': isMenuOpen }"></span>
</div>
<div :class="{ 'mobile-menu': true, 'open': isMenuOpen }">
<ul class="mobile-menu-list">
<li v-for="(item, index) in headlist" :key="index">
<router-link :to="item.path" @click="toggleMenu">
<span>{{ item.title }}</span>
</router-link>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';
import { useUserStore } from '@/stores/userStore';
import { getApproval_status } from '@/api/login';
import { ref, onMounted, watch, onUnmounted } from "vue";
import { useRouter } from "vue-router";
import { useUserStore } from "@/stores/userStore";
import { Menu,Avatar } from "@element-plus/icons-vue";
import { getApproval_status } from "@/api/login";
const emits = defineEmits(['open-login-form', 'open-register-form']);
const emits = defineEmits(["open-login-form", "open-register-form"]);
const openLoginForm = () => {
emits('open-login-form');
emits("open-login-form");
};
const openRegisterForm = () => {
emits('open-register-form');
emits("open-register-form");
};
//
const headlist = ref([
{ title: '首页', path: '/index' },
{ title: '使用教程', path: '/help' },
{ title: '关于我们', path: '/about' },
{ title: "首页", path: "/index" },
{ title: "使用教程", path: "/help" },
{ title: "关于我们", path: "/about" },
]);
const toRouter=(pathString:string)=>{
router.push({path:pathString})
}
const toRouter = (pathString: string) => {
router.push({ path: pathString });
};
const router = useRouter();
const userStore = useUserStore();
// userStore
const isLoggedIn = ref(userStore.isLoggedIn);
const mobile = ref("");
const approval_status = ref("");
// token
onMounted(() => {
const storedToken = localStorage.getItem('token');
const storedToken = localStorage.getItem("token");
const mobilePhone = localStorage.getItem("mobilePhone");
console.log(mobilePhone);
if (mobilePhone) {
mobile.value = mobilePhone.replace(/(^\d{3})(\d+)(\d{4})/g, "$1****$2");
}
if (storedToken) {
userStore.setToken(storedToken); // token token
}
isLoggedIn.value = userStore.isLoggedIn; //
getApproval_status().then((res) => {
if (res.code === 0 && res.status === 200) {
approval_status.value = res.data.approval_status;
console.log("res.data.approval_status", res.data.approval_status);
}
});
});
// userStore.isLoggedIn
watch(() => userStore.isLoggedIn, (newVal) => {
watch(
() => userStore.isLoggedIn,
(newVal) => {
isLoggedIn.value = newVal; // isLoggedIn userStore.isLoggedIn
if (isLoggedIn.value === null) console.log("登陆过期");
// getApproval_status().then((res) => {
// if (res.code === 0 && res.status === 200) {
// localStorage.setItem('approval_status', res.data.approval_status);
// } else {
// }
// });
});
}
);
//
const handleOpenStartPage = () => {
if (isLoggedIn.value) {
if (localStorage.getItem('approval_status') != null && localStorage.getItem('approval_status') === '4') {
router.push({ name: 'start' });
} else {
router.push({ name: 'check' }); // check
}
} else {
if (!isLoggedIn.value) {
openRegisterForm(); //
return;
}
if (approval_status == 4) {
router.push({ name: "start" });
} else {
router.push({ name: "check" }); // check
}
};
const handleUserInfoClick = () => {
if (approval_status == 4) {
router.push({ name: "start" });
} else {
router.push({ name: "check" });
}
};
@ -135,7 +165,7 @@ const logout = () => {
userStore.removeMobilePhone();
userStore.removeIdentity();
isLoggedIn.value = false; //
router.push('/'); //
router.push("/"); //
};
//
@ -155,123 +185,137 @@ onMounted(() => {
isMenuOpen.value = false;
}
};
window.addEventListener('resize', resizeHandler);
window.addEventListener("resize", resizeHandler);
});
onUnmounted(() => {
window.removeEventListener('resize', resizeHandler);
window.removeEventListener("resize", resizeHandler);
});
</script>
<style scoped>
.hamburger-menu {
position: fixed; /* 修改为固定定位 */
top: 20px; /* 调整顶部位置 */
right: 20px; /* 调整右侧位置 */
width: 25px;
height: 25px;
cursor: pointer;
z-index: 10011; /* 设置比 header-list 更高的 z-index */
display: none;
}
.hamburger-icon {
display: block;
<style lang="scss" scoped>
.header {
height: 70px;
width: 100%;
height: 3px;
background-color: #303133;
margin: 5px 0;
transition: all 0.3s ease-in-out;
transform-origin: center;
padding: 15px 20px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #fff;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
}
.rotate-top {
transform: translateY(8px) rotate(45deg);
}
.header-menu {
flex: 1;
display: flex;
.hide-middle {
opacity: 0;
}
li {
margin: 0 20px;
list-style: none;
position: relative;
color: #333;
.rotate-bottom {
transform: translateY(-8px) rotate(-45deg);
}
span {
font-size: 16px;
}
.mobile-menu {
position: fixed;
top: 70px; /* 移动到 header-top 下方 */
&:hover span {
color: var(--bgcolor);
}
&::before {
content: "";
position: absolute;
bottom: 0px;
left: 50%;
width: 0;
height: 100%;
border-bottom: 3px solid var(--bgcolor);
transition: all 0.2s;
}
&:hover::before {
content: "";
left: 0;
width: 100%;
height: 100%;
background-color: #fff; /* 修改背景颜色为白色 */
z-index: 10010;
display: flex;
flex-direction: column;
align-items: center;
transition: all 0.3s ease-in-out;
opacity: 0; /* 初始设置为透明 */
visibility: hidden; /* 初始隐藏 */
}
}
}
.mobile-menu.open {
opacity: 1; /* 显示时不透明 */
visibility: visible; /* 显示 */
}
.router-link-active li::before {
content: "";
left: 0;
width: 100%;
}
.mobile-menu-list {
list-style: none;
padding: 0;
margin: 0;
width: 90%;
max-width: 300px;
border-radius: 10px;
overflow: hidden;
z-index: 10010;
}
.router-link-active span {
color: var(--bgcolor);
}
.mobile-menu-list li {
padding: 10px;
line-height: 30PX;
border-bottom: 1px solid #DCDCDC;
}
.mobile-menu-list li a {
a {
text-decoration: none;
}
.mobile-menu-list li:last-child {
border-bottom: none;
}
.login-register-module {
position: fixed;
top: 20px;
right: 60px;
z-index: 10010;
display: flex;
justify-content: center;
align-items: center;
display: none;
}
.login-register-module span {
margin-right: 10px;
line-height: 35px;
cursor: pointer;
}
.login-register-module span:hover {
color: blue;
color: inherit;
}
}
.logo {
display: inline-block;
img{
height: 48px;
margin-right: 20px;
img {
height: 40px;
}
}
.icon_avatar{
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
background: #eee;
border-radius: 100%;
}
.start {
display: flex;
justify-content: flex-end;
align-items: center;
margin-right: 5px;
}
.avatar {
display: flex;
justify-content: flex-end;
align-items: center;
}
.header-right {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 20px;
}
.sub_menu {
display: none;
cursor: pointer;
}
@media (max-width: 768px) {
.header {
padding: 0 10px;
}
.header-menu {
display: none;
}
.hamburger-menu {
display: block;
}
.logo {
img {
height: 28px;
}
}
}
</style>

View File

@ -32,11 +32,33 @@
]
</script>
<style lang="scss">
.banner-list {
width: 100%;
max-width: 1200px;
margin: auto;
position: relative;
margin-top: 15px;
}
.banner-list .el-carousel__container {
width: 100%;
padding-bottom: 50%; /* 高度自适应宽度的一半 */
position: relative;
}
.banner-list .el-carousel__item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.banner-list .el-carousel__item img {
width: 100%;
height: 100%;
object-fit: cover;
}
.banner{
padding-top: 20px;
}
.banner-list{
margin-top: 15px;
}
</style>

View File

@ -59,7 +59,6 @@
text-indent: 2em;
}
.index-title {
width: 1200px;
text-align: center;
@ -67,18 +66,30 @@
h3 {
font-size: 40px;
}
}
p{
p {
font-size: 20px;
}
}
}
.company-detail {
display: flex;
width: 1200px;
margin: 15px auto 0;
}
.company-detail img {
width: 100%;
height: 100%;
object-fit: cover;
padding-right: 20px;
}
.company-introduce {
padding: 20px;
letter-spacing: 2px;
line-height: 34px;
padding-bottom: 0;
}
@media (max-width: 768px) {
.index-title {

View File

@ -1,21 +1,21 @@
<script setup lang="ts">
let serviceList=[
{id:1,title:"同城零售",icon:"iconfont icon-icon-test"},
{id:2,title:"企业招聘",icon:"iconfont icon-qiyezhaopin"},
{id:3,title:"租赁服务",icon:"iconfont icon-zulinfuwuicon"},
{id:4,title:"二手交易",icon:"iconfont icon-ershoujiaoyi"},
{id:5,title:"安装维修",icon:"iconfont icon-anzhuangweixiu"},
{id:6,title:"家政保洁",icon:"iconfont icon-jiazhengbaojieanbao"}
]
let serviceList = [
{ id: 1, title: "同城零售", icon: "iconfont icon-icon-test" },
{ id: 2, title: "企业招聘", icon: "iconfont icon-qiyezhaopin" },
{ id: 3, title: "租赁服务", icon: "iconfont icon-zulinfuwuicon" },
{ id: 4, title: "二手交易", icon: "iconfont icon-ershoujiaoyi" },
{ id: 5, title: "安装维修", icon: "iconfont icon-anzhuangweixiu" },
{ id: 6, title: "家政保洁", icon: "iconfont icon-jiazhengbaojieanbao" },
];
</script>
<template>
<div class="service-contain">
<div class="index-title">
<h3>我们的服务</h3>
<p>我们拥有专业的团队和丰富的经验为您解决生活中的各种问题为您提供便捷高效优质的服务</p>
<p>
我们拥有专业的团队和丰富的经验为您解决生活中的各种问题为您提供便捷高效优质的服务
</p>
</div>
<div class="service-list">
<ul>
@ -27,21 +27,70 @@
</div>
</div>
<div>
</div>
<div></div>
</template>
<style lang="scss">
.service-list{
.service-contain {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
padding-top: 30px;
}
.service-list {
width: 100%;
}
.service-list ul {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
align-items: center;
width: 100%;
}
.service-list ul li {
list-style: none;
width: 30%;
height: 211.6px;
padding: 30px 20px;
text-align: center;
box-shadow: 0 15px 25px 0 rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
.service-list ul li i::before {
font-size: 70px;
color: #353535;
transition: 0.3s;
}
.service-list ul li h4 {
font-size: 26px;
font-weight: 500;
margin-top: 10px;
transition: 0.3s;
}
.service-list ul li:hover {
background: linear-gradient(90.54deg, #ec4b2b 0.42%, #f85535 102.71%);
}
.service-list ul li:hover i::before {
color: #fff;
}
.service-list ul li:hover h4 {
color: #fff;
}
.service-list ul li:hover i::before p {
color: #fff;
}
.service-list {
width: 1200px;
margin: 15px 0;
}
@media (max-width: 768px) {
.service-list{
}
@media (max-width: 768px) {
.service-list {
width: auto;
}
}
</style>

View File

@ -164,8 +164,8 @@ const formatter2 = (value: number) => {
.sub {
position: absolute;
top: 65%;
transform: translateY(65%);
top: 58%;
transform: translateY(58%);
left: 150px;
}
}

View File

@ -174,6 +174,7 @@
<script lang="ts" setup>
import { ref, reactive, onMounted, watch } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { Plus,Search } from "@element-plus/icons-vue";
@ -218,6 +219,7 @@ const orcImgTypeConf = {
};
const userStore = useUserStore();
const router = useRouter();
const processData = () => {
const { provinceData, cityData: cityList, areaData } = cityData;
@ -323,6 +325,7 @@ const applyFormData = reactive({
bank_image: "",
email: "",
});
const isLoggedIn = ref(userStore.isLoggedIn);
const license_type = ref('1')
const optionsPermitType = [
{
@ -422,6 +425,11 @@ const handleGetAuditInfo = async () => {
mobile: localStorage.getItem("mobilePhone"),
})) as any;
if(res.data==null||res.data.approval_status==4){
router.push({ name: "start" });
return
}
let arr = JSON.parse(res.data.approval_invalid_col);
let legal_person_card = ['legal_person_id_addr','legal_person_id_period_begin','legal_person_id_period_end']
let individual_id_card = ['individual_id_addr','individual_id_period_begin','individual_id_period_end']
@ -984,6 +992,11 @@ const clearOtherFields = () => {
onMounted(() => {
// bankListRemoteMethod();
if(!isLoggedIn.value){
router.push({ name: "index" });
return
}
handleGetAuditInfo();
GetStoreCategories()