Files
visitor/src/views/adminHome.vue
T
2026-03-13 15:12:18 +08:00

514 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div v-if="true" class='box'>
<header>
<h3>Hello~{{ userName }}</h3>
<h4>呀 你又来审批预约了啊ㄟ( ▔, ▔ )ㄏ<br/>v{{ appVersion }}</h4>
<div class="plate-box">
<div @click="onClickGo('/Invitation')" class="plate-button">
<img src="../assets/ren.png" alt="">
<div class="right">
<div>我要邀约</div>
<p>保存专属二维码</p>
</div>
</div>
<div @click="onClickGo('/visitorRecord')" class="plate-button">
<img src="../assets/shuben.png" alt="">
<div class="right">
<div>访客记录</div>
<p>查看历史来访记录</p>
</div>
</div>
</div>
<div class="position-img">
<img src="../assets/fangzi.png" alt="">
</div>
</header>
<div class="content">
<h2>
<div>待审批列表</div>
<span @click="onClickGo('/visitorRecord')">查看全部</span>
</h2>
<div class="content-ul">
<div v-for="item in recordArr" @click="onClickItem(item)" class="wait-list" :key="item.id">
<h5>被拜访人:{{ item.visitingName }}</h5>
<h5>拜访时间:{{ item.hours }}</h5>
<div class="apply-box">
<p><span>访客姓名:</span><span>{{ item.name }}</span></p>
<p><span>联系方式:</span><span>{{ item.phone }}</span></p>
<p><span>随行人数:</span><span>{{ item.visitingNum }} </span></p>
<p><span>来访事由:</span><span>{{ item.reason }}</span></p>
</div>
<div class="status" :class="getStatusInfo(item.status).className">{{ getStatusInfo(item.status).statusName }}</div>
</div>
</div>
<div v-if="isLoading && isDataLoaded && recordArr.length === 0" class="no-have">
<img class="" src="../assets/nodata.png" alt="">
<p>暂无待审批数据</p>
</div>
<div v-else-if="isLoading && !isDataLoaded" class="no-have">
<img class="" src="../assets/nodata.png" alt="">
<p>待审批数据加载中...</p>
</div>
</div>
</div>
</template>
<script setup>
import {reactive, ref, onMounted} from 'vue'
import {useRouter} from 'vue-router'
import {useStore} from 'vuex'
import {Toast, ImagePreview} from 'vant';
import dd from 'dingtalk-jsapi'
import {rulesForm, resetForm, rulesPhone} from '@/com/index'
import {getToken, getVisitorRecord, getWhiteCode} from '@/api/admin.js'
/* @data */
const appVersion = ref(import.meta.env.VITE_APP_VERSION || '1.0.0')
const router = useRouter()
const store = useStore()
const isLoading = ref(false)
const isDataLoaded = ref(false)
// 已经在登录处理中
const isLoginInProgress = ref(false);
const token = ref('')
const userName = ref('')
const query = reactive({
status: 0,
size: 2,
current: 1,
})
const recordArr = ref([])
const stateEnum = store.state.stateEnum
// 获取完整状态信息
const getStatusInfo = (status) => {
return store.getters.getStatusInfo(status)
}
token.value = localStorage.getItem('token')
localStorage.setItem('redirect', '/adminHome')
/* @setup */
const login = () => {
// 防止重复登录
if (isLoginInProgress.value) {
return;
}
isLoginInProgress.value = true;
Toast.loading({duration: 0, forbidClick: true, message: '登录中',});
dd.getAuthCode({
corpId: 'ding03f8e88dde9b426835c2f4657eb6378f',
success: (res) => {
const {code} = res;
localStorage.removeItem('token');
localStorage.removeItem('user');
getToken(code).then(data => {
// 验证返回的数据
if (data && data.data && data.data.authorization) {
localStorage.setItem('user', JSON.stringify(data.data));
localStorage.setItem('token', data.data.authorization);
userName.value = data.data.name;
Toast.clear();
Toast.success('登录成功');
visitorList();
} else {
throw new Error('登录数据异常');
}
}).catch(err => {
Toast.clear();
Toast.fail('登录失败');
console.error('登录失败:', err);
}).finally(() => {
isLoginInProgress.value = false;
});
},
fail: (err) => {
},
complete: () => {
},
});
}
// login()
const visitorList = () => {
isDataLoaded.value = false
Toast.loading({duration: 0, forbidClick: true, message: '加载中',});
getVisitorRecord(query).then(res => {
isLoading.value = true
isDataLoaded.value = true
recordArr.value = res.data
}).catch(err => {
isLoading.value = true
isDataLoaded.value = true
recordArr.value = []
})
}
/* @method */
const onClickGo = (url = '/adminHome') => {
router.push(url)
}
// 改进页面加载时的初始化逻辑
const initializeApp = () => {
const token = localStorage.getItem('token');
const userStr = localStorage.getItem('user');
if (token && userStr) {
try {
const user = JSON.parse(userStr);
if (user && user.name) {
userName.value = user.name;
visitorList();
} else {
// 用户数据不完整,重新登录
login();
}
} catch (e) {
// 用户数据解析失败,重新登录
console.error('用户数据解析失败:', e);
login();
}
} else {
// 没有token或用户数据,需要登录
login();
}
};
const onClickItem = (item) => {
// 检查instanceUrl是否存在且非空
let instanceUrl;
if (item.instanceUrl && item.instanceUrl.trim() !== '') {
instanceUrl = item.instanceUrl;
}else{
instanceUrl = `https://aflow.dingtalk.com/dingtalk/mobile/homepage.htm?corpid=ding03f8e88dde9b426835c2f4657eb6378f&dd_share=false&showmenu=false&dd_progress=false&back=native&procInstId=${item.instanceId}&taskId=&swfrom=isv&dinghash=approval&dtaction=os&dd_from=corp#approval`;
}
dd.openLink({
url: instanceUrl,
success: () => {
},
fail: () => {
},
complete: () => {
},
});
}
// 在组件挂载时调用
onMounted(() => {
initializeApp();
});
</script>
<style lang='scss' scoped>
.box {
background-color: #F9FBFC;
display: flex;
flex-direction: column;
header {
position: relative;
width: 100%;
height: 10.4rem /* 780/75 */
;
background: url('../assets/guanlibeijing.png') left top/100% 100% no-repeat;
box-sizing: border-box;
h3 {
padding: 1.0933rem /* 82/75 */
.6933rem /* 52/75 */
.1067rem /* 8/75 */
;
box-sizing: border-box;
line-height: .72rem /* 54/75 */
;
font-size: .48rem /* 36/75 */
;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 500;
color: #222222;
}
h4 {
line-height: .48rem /* 36/75 */
;
font-size: $sm-size;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #FFFFFF;
padding: 0 .6933rem /* 52/75 */
1.12rem /* 84/75 */
;
box-sizing: border-box;
}
.position-img {
position: absolute;
right: .4267rem /* 32/75 */
;
top: .2933rem /* 22/75 */
;
width: 3.6267rem /* 272/75 */
;
height: 2.96rem /* 222/75 */
;
img {
width: 100%;
height: 100%;
}
}
.plate-box {
width: 100%;
padding: 0 .4rem /* 30/75 */
;
box-sizing: border-box;
display: flex;
justify-content: space-between;
.plate-button {
width: 4.4rem /* 330/75 */
;
height: 1.92rem /* 144/75 */
;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0.6) 48%);
border-radius: .2667rem /* 20/75 */
;
border: .0267rem /* 2/75 */
solid #FFFFFF;
display: flex;
align-items: center;
img {
width: .9867rem /* 74/75 */
;
height: .9867rem /* 74/75 */
;
margin-left: .32rem /* 24/75 */
;
}
.right {
margin-left: .3467rem /* 26/75 */
;
div {
line-height: .64rem /* 48/75 */
;
font-size: $lg-size;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 500;
color: #222222;
}
P {
line-height: .4rem /* 30/75 */
;
font-size: .2667rem /* 20/75 */
;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #5F6583;
margin-top: .1067rem /* 8/75 */
;
}
}
}
}
}
.content {
flex: 1;
overflow: auto;
position: relative;
// top: 5.8667rem /* 440/75 */;
margin-top: -4.5333rem /* 340/75 */
;
width: 100%;
padding: 0 .4rem /* 30/75 */
;
box-sizing: border-box;
h2 {
width: 100%;
padding: .2667rem /* 20/75 */
.32rem /* 24/75 */
;
box-sizing: border-box;
display: flex;
justify-content: space-between;
line-height: .72rem /* 54/75 */
;
font-size: .48rem /* 36/75 */
;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 500;
color: #222222;
span {
// line-height: 36px;
font-size: $sm-size;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #999999;
}
}
.content-ul {
.wait-list {
position: relative;
width: 9.2rem /* 690/75 */
;
// height: 470px;
background: #FFFFFF;
border-radius: .2667rem /* 20/75 */
;
padding: .48rem /* 36/75 */
;
box-sizing: border-box;
margin-bottom: .2667rem /* 20/75 */
;
h5 {
height: .6667rem /* 50/75 */
;
font-size: $md-size;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #222222;
}
.apply-box {
width: 100%;
padding: .4rem /* 30/75 */
.3733rem /* 28/75 */
.5067rem /* 38/75 */
;
box-sizing: border-box;
border-radius: .1333rem /* 10/75 */
;
font-size: $md-size;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #999999;
line-height: .72rem /* 54/75 */
;
background: #F5F7F9;
span:last-child {
color: #5F6583;
}
}
.status {
position: absolute;
top: 0;
right: 0;
width: 1.52rem /* 114/75 */
;
height: .6667rem /* 50/75 */
;
line-height: .6667rem /* 50/75 */
;
background: #FFE9E4;
border-radius: 0 .2667rem /* 20/75 */
0 .1333rem /* 10/75 */
;
color: #FF6643;
font-size: $sm-size;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
text-align: center;
}
.refuse {
color: #5F6583;
background: #EAEEF6;
}
.pass {
color: #30BF78;
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;
}
}
}
.no-have {
// display: block;
width: 7.4667rem /* 560/75 */
;
height: 5.3867rem /* 404/75 */
;
margin: .8rem /* 60/75 */
auto;
img {
width: 100%;
height: 100%;
}
// font-size: 15px;
font-family: Source Han Sans CN, 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Source Han Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 400;
color: #999999;
text-align: center;
}
}
}
</style>