界面问题修复

This commit is contained in:
2026-03-13 15:12:18 +08:00
parent d73e8bff58
commit a7753d33e0
6 changed files with 247 additions and 58 deletions
+1 -1
View File
@@ -1 +1 @@
VITE_APP_VERSION=1.2.20260313-20 VITE_APP_VERSION=1.3.20260313-70
+34 -20
View File
@@ -4,30 +4,44 @@ import { createStore } from 'vuex'
const store = createStore({ const store = createStore({
state: { state: {
name: '访客预约系统', name: '访客预约系统',
// 状态映射表(与后端枚举对应)
statusMap: {
// 待审核分组(-1)
0: { statusName: '待审批', className: 'wait', group: -1 },
90: { statusName: '逾期未审', className: 'overdue', group: -1 },
// 待来访分组(-2)
1: { statusName: '已审批', className: 'pass', group: -2 },
11: { statusName: '待到访', className: 'pending', group: -2 },
12: { statusName: '已到访', className: 'visited', group: -2 },
91: { statusName: '未到访', className: 'not-visited', group: -2 },
99: { statusName: '已完成', className: 'finished', group: -2 },
// 已结束分组(-3)
2: { statusName: '已拒绝', className: 'refuse', group: -3 },
3: { statusName: '已撤销', className: 'cancel', group: null } // 不在任何分组
},
// 状态分类Tab(筛选用,与后端状态分组对应)
statusTabs: [
{ label: '待审核', value: -1, className: 'wait', count: 0, fetched: false },
{ label: '待来访', value: -2, className: 'pass', count: 0, fetched: false },
{ label: '已结束', value: -3, className: 'end', count: 0, fetched: false }
],
// 兼容旧版
stateEnum: { stateEnum: {
0: { 0: { statusName: '待审核', className: 'status', statusText: '您的来访预约还未审核,请耐心等待', status: 0 },
statusName:'待审核', 1: { statusName: '已通过', className: 'pass', statusText: '预约审核通过', status: 1 },
className: 'status', 2: { statusName: '未通过', className: 'refuse', statusText: '预约审核已拒绝', status: 2 }
statusText: '您的来访预约还未审核,请耐心等待',
status: 0
},
1: {
statusName: '已通过',
className: 'pass',
statusText: '预约审核通过',
status: 1
},
2: {
statusName:'未通过',
className: 'refuse',
statusText: '预约审核已拒绝',
status: 2
}
} }
}, },
getters: { getters: {
// 根据status获取状态信息
getStatusInfo: (state) => (status) => {
return state.statusMap[status] || { statusName: '未知', className: 'default', group: null }
},
// 获取状态分组值
getStatusGroup: (state) => (status) => {
const info = state.statusMap[status]
return info ? info.group : null
}
}, },
mutations: { mutations: {
+48 -1
View File
@@ -40,7 +40,7 @@
<p><span>随行人数</span><span>{{ item.visitingNum }} </span></p> <p><span>随行人数</span><span>{{ item.visitingNum }} </span></p>
<p><span>来访事由</span><span>{{ item.reason }}</span></p> <p><span>来访事由</span><span>{{ item.reason }}</span></p>
</div> </div>
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div> <div class="status" :class="getStatusInfo(item.status).className">{{ getStatusInfo(item.status).statusName }}</div>
</div> </div>
</div> </div>
<div v-if="isLoading && isDataLoaded && recordArr.length === 0" class="no-have"> <div v-if="isLoading && isDataLoaded && recordArr.length === 0" class="no-have">
@@ -83,6 +83,12 @@ const query = reactive({
}) })
const recordArr = ref([]) const recordArr = ref([])
const stateEnum = store.state.stateEnum const stateEnum = store.state.stateEnum
// 获取完整状态信息
const getStatusInfo = (status) => {
return store.getters.getStatusInfo(status)
}
token.value = localStorage.getItem('token') token.value = localStorage.getItem('token')
localStorage.setItem('redirect', '/adminHome') localStorage.setItem('redirect', '/adminHome')
@@ -439,6 +445,47 @@ onMounted(() => {
color: #30BF78; color: #30BF78;
background: #E7F8F5; background: #E7F8F5;
} }
// 新增状态样式
.wait {
color: #E6A23C;
background: #FFF7CC;
}
.cancel {
color: #909399;
background: #F4F4F5;
}
.pending {
color: #409EFF;
background: #ECF5FF;
}
.visited {
color: #67C23A;
background: #F0F9EB;
}
.overdue {
color: #E6A23C;
background: #FEF0F0;
}
.not-visited {
color: #909399;
background: #F4F4F5;
}
.finished {
color: #999999;
background: #F5F5F5;
}
.default {
color: #666666;
background: #F5F5F5;
}
} }
} }
+33 -3
View File
@@ -3,8 +3,8 @@
<div v-for="item in recordArr" class="apply-list" :key="item.id"> <div v-for="item in recordArr" class="apply-list" :key="item.id">
<h3 class="h3"> <h3 class="h3">
<span>提交时间{{ item.createTime }}</span> <span>提交时间{{ item.createTime }}</span>
<!-- refuse拒绝 pass通过 状态 --> <!-- 显示完整状态 -->
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div> <div class="status" :class="getStatusInfo(item.status).className">{{ getStatusInfo(item.status).statusName }}</div>
</h3> </h3>
<div class="apply-content"> <div class="apply-content">
<div class="user-info"> <div class="user-info">
@@ -16,7 +16,7 @@
<span>拜访时间{{ item.hours }}</span> <span>拜访时间{{ item.hours }}</span>
</div> </div>
<p> <p>
{{ item.status == 2 && item.remark ? item.remark : stateEnum[item.status].statusText }} {{ item.status == 2 && item.remark ? item.remark : getStatusInfo(item.status).statusText }}
<span class="triangle"></span> <span class="triangle"></span>
</p> </p>
</div> </div>
@@ -45,6 +45,11 @@ import { Toast, ImagePreview } from 'vant';
const recordArr = ref([]) const recordArr = ref([])
const stateEnum = store.state.stateEnum const stateEnum = store.state.stateEnum
// 获取完整状态信息
const getStatusInfo = (status) => {
return store.getters.getStatusInfo(status)
}
/* @setup */ /* @setup */
console.log(localStorage.getItem('userToken')) console.log(localStorage.getItem('userToken'))
let windowHeight = document.documentElement.clientHeight || document.body.clientHeight; let windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
@@ -142,6 +147,31 @@ import { Toast, ImagePreview } from 'vant';
.refuse{ .refuse{
color: #FF6643; color: #FF6643;
} }
// 新增状态样式
.wait{
color: #E6A23C;
}
.cancel{
color: #909399;
}
.pending{
color: #409EFF;
}
.visited{
color: #67C23A;
}
.overdue{
color: #E6A23C;
}
.not-visited{
color: #909399;
}
.finished{
color: #999999;
}
.default{
color: #666666;
}
} }
.apply-content{ .apply-content{
width: 100%; width: 100%;
+74 -22
View File
@@ -1,9 +1,15 @@
<template> <template>
<div class="visitor-manage-page"> <div class="visitor-manage-page">
<div class="status-tabs"> <div class="status-tabs">
<span :class="{ active: visitorStatus === 1 }" @click="changeVisitorStatus(1)">已通过</span> <span
<span :class="{ active: visitorStatus === 0 }" @click="changeVisitorStatus(0)">待审批</span> v-for="tab in statusTabs"
<span :class="{ active: visitorStatus === 2 }" @click="changeVisitorStatus(2)">已拒绝</span> :key="tab.value"
:class="{ active: visitorStatus === tab.value }"
@click="changeVisitorStatus(tab.value)"
>
{{ tab.label }}
<span v-if="tab.fetched && tab.count > -1" class="count">({{ tab.count }})</span>
</span>
</div> </div>
<van-loading v-if="visitorLoading" /> <van-loading v-if="visitorLoading" />
<div v-else class="visitor-list"> <div v-else class="visitor-list">
@@ -15,8 +21,8 @@
<p><span>被访人</span>{{ item.visitingName }}</p> <p><span>被访人</span>{{ item.visitingName }}</p>
<p><span>来访事由</span>{{ item.reason }}</p> <p><span>来访事由</span>{{ item.reason }}</p>
</div> </div>
<div class="visitor-status" :class="visitorStatusMap[item.status]?.className || 'default'"> <div class="visitor-status" :class="getStatusInfo(item.status).className">
{{ visitorStatusMap[item.status]?.name || '未知' }} {{ getStatusInfo(item.status).statusName }}
</div> </div>
</div> </div>
<div v-if="visitorRecordList.length === 0" class="no-data">暂无数据</div> <div v-if="visitorRecordList.length === 0" class="no-data">暂无数据</div>
@@ -25,28 +31,44 @@
</template> </template>
<script setup> <script setup>
import {onMounted, reactive, ref} from 'vue' import {onMounted, reactive, ref, computed} from 'vue'
import {useStore} from 'vuex'
import {getVisitorRecord} from '@/api/admin.js' import {getVisitorRecord} from '@/api/admin.js'
import {Toast} from 'vant' import {Toast} from 'vant'
const store = useStore()
const visitorRecordList = ref([]) const visitorRecordList = ref([])
const visitorLoading = ref(false) const visitorLoading = ref(false)
const visitorStatus = ref(1) const visitorStatus = ref(-2) // 默认待来访
const visitorQuery = reactive({ const visitorQuery = reactive({
status: 1, status: -2,
size: 100, size: 100,
current: 1 current: 1
}) })
const visitorStatusMap = { // 使用computed确保响应式
0: {name: '待审批', className: 'wait'}, const statusTabs = computed(() => store.state.statusTabs)
1: {name: '已通过', className: 'pass'}, const getStatusInfo = (status) => store.getters.getStatusInfo(status)
2: {name: '已拒绝', className: 'reject'},
11: {name: '待到访', className: 'pending'}, // 初始查询各分组数量
12: {name: '已到访', className: 'visited'}, const fetchCounts = () => {
90: {name: '待审批', className: 'wait'}, const groups = [
91: {name: '已通过', className: 'pass'}, { value: -1, query: { status: -1, size: 1000, current: 1 } },
99: {name: '已完成', className: 'finished'} { value: -2, query: { status: -2, size: 1000, current: 1 } },
{ value: -3, query: { status: -3, size: 1000, current: 1 } }
]
return Promise.all(groups.map(g => getVisitorRecord(g.query)))
.then(results => {
results.forEach((res, index) => {
statusTabs.value[index].count = res.data?.length || 0
statusTabs.value[index].fetched = true // 标记为已查询
})
})
.catch(err => {
console.error('获取分组数量失败:', err)
})
} }
const fetchVisitorRecords = () => { const fetchVisitorRecords = () => {
@@ -61,6 +83,12 @@ const fetchVisitorRecords = () => {
}) })
} }
// 初始加载
const init = async () => {
await fetchCounts() // 获取各分组数量
fetchVisitorRecords() // 获取当前tab数据
}
const changeVisitorStatus = (status) => { const changeVisitorStatus = (status) => {
visitorStatus.value = status visitorStatus.value = status
visitorQuery.status = status visitorQuery.status = status
@@ -68,7 +96,7 @@ const changeVisitorStatus = (status) => {
} }
onMounted(() => { onMounted(() => {
fetchVisitorRecords() init()
}) })
</script> </script>
@@ -88,13 +116,17 @@ onMounted(() => {
flex: 1; flex: 1;
text-align: center; text-align: center;
padding: 0.2rem; padding: 0.2rem;
background: #fff;
border-radius: 0.2rem;
font-size: 0.37rem; font-size: 0.37rem;
&.active { &.active {
background: #1989fa; color: #1989fa;
color: #fff; font-weight: bold;
}
.count {
font-size: 0.28rem;
color: #666;
margin-left: 0.1rem;
} }
} }
} }
@@ -145,6 +177,11 @@ onMounted(() => {
color: #f56c6c; color: #f56c6c;
} }
&.cancel {
background: #fef0f0;
color: #909399;
}
&.pending { &.pending {
background: #ecf5ff; background: #ecf5ff;
color: #409eff; color: #409eff;
@@ -155,11 +192,26 @@ onMounted(() => {
color: #67c23a; color: #67c23a;
} }
&.overdue {
background: #fef0f0;
color: #e6a23c;
}
&.not-visited {
background: #f4f4f5;
color: #909399;
}
&.finished { &.finished {
background: #f5f5f5; background: #f5f5f5;
color: #999; color: #999;
} }
&.end {
background: #f5f5f5;
color: #909399;
}
&.default { &.default {
background: #f5f5f5; background: #f5f5f5;
color: #666; color: #666;
+57 -11
View File
@@ -1,10 +1,10 @@
<template> <template>
<div class='box'> <div class='box'>
<header class="tabbar"> <header class="tabbar">
<div @click="onClickTabbar(item)" v-for="item in stateEnum" class="tabbar-li" :key="item.status" <div @click="onClickTabbar(item)" v-for="item in statusTabs" class="tabbar-li" :key="item.value"
:class="query.status === item.status ? 'active' : ''"> :class="query.status === item.value ? 'active' : ''">
{{ item.statusName }} {{ item.label }}
<img v-if="query.status === item.status" src="../assets/maomaochong.png" alt=""> <img v-if="query.status === item.value" src="../assets/maomaochong.png" alt="">
</div> </div>
</header> </header>
@@ -18,8 +18,8 @@
<p><span>随行人数</span><span>{{ item.visitingNum }} </span></p> <p><span>随行人数</span><span>{{ item.visitingNum }} </span></p>
<p><span>来访事由</span><span>{{ item.reason }}</span></p> <p><span>来访事由</span><span>{{ item.reason }}</span></p>
</div> </div>
<!-- refuse 拒绝 pass 通过 状态 --> <!-- 显示完整状态 -->
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div> <div class="status" :class="getStatusInfo(item.status).className">{{ getStatusInfo(item.status).statusName }}</div>
</div> </div>
</div> </div>
<div v-if="isLoading && recordArr.length === 0" class="content"> <div v-if="isLoading && recordArr.length === 0" class="content">
@@ -31,7 +31,7 @@
</template> </template>
<script setup> <script setup>
import {ref, reactive} from 'vue' import {ref, reactive, computed} from 'vue'
import {useRouter, useRoute} from 'vue-router' import {useRouter, useRoute} from 'vue-router'
import {useStore} from 'vuex' import {useStore} from 'vuex'
import dd from 'dingtalk-jsapi' import dd from 'dingtalk-jsapi'
@@ -44,12 +44,17 @@ import {getToken, getVisitorRecord} from '@/api/admin.js'
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const store = useStore() const store = useStore()
const stateEnum = store.state.stateEnum const statusTabs = computed(() => store.state.statusTabs)
const recordArr = ref([]) const recordArr = ref([])
const isLoading = ref(false) const isLoading = ref(false)
// 获取状态信息
const getStatusInfo = (status) => {
return store.getters.getStatusInfo(status)
}
const query = reactive({ const query = reactive({
status: 0, status: -1, // 默认待处理(父状态)
size: -1, size: -1,
current: 1, current: 1,
}) })
@@ -81,8 +86,8 @@ const onClickItem = (item) => {
} }
const onClickTabbar = (item) => { const onClickTabbar = (item) => {
if (query.status !== item.status) { if (query.status !== item.value) {
query.status = item.status query.status = item.value
recordArr.value = [] recordArr.value = []
visitorList() visitorList()
} }
@@ -233,6 +238,47 @@ visitorList()
color: #30BF78; color: #30BF78;
background: #E7F8F5; background: #E7F8F5;
} }
// 新增状态样式
.wait {
color: #E6A23C;
background: #FFF7CC;
}
.cancel {
color: #909399;
background: #F4F4F5;
}
.pending {
color: #409EFF;
background: #ECF5FF;
}
.visited {
color: #67C23A;
background: #F0F9EB;
}
.overdue {
color: #E6A23C;
background: #FEF0F0;
}
.not-visited {
color: #909399;
background: #F4F4F5;
}
.finished {
color: #999999;
background: #F5F5F5;
}
.default {
color: #666666;
background: #F5F5F5;
}
} }
} }
} }