处理偶尔循环登录问题

This commit is contained in:
2025-08-23 17:51:36 +08:00
parent 9b1947f7c0
commit 81dc87c388
8 changed files with 884 additions and 579 deletions
+19 -17
View File
@@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
import { useRoute, useRouter } from "vue-router"; import {useRoute, useRouter} from "vue-router";
import { useStore } from "vuex"; import {useStore} from "vuex";
import { Toast, Dialog } from "vant"; import {Toast, Dialog} from "vant";
// import { getItem, setItem, removeItem, dalert } from '@/com/index' // import { getItem, setItem, removeItem, dalert } from '@/com/index'
const errorCode = { const errorCode = {
401: "登录状态已过期,即将返回首页重新登录", 401: "登录状态已过期,即将返回首页重新登录",
@@ -22,8 +22,8 @@ const request = axios.create({
// 如果配置了单个的反向代理 --- 字符串模式 // 如果配置了单个的反向代理 --- 字符串模式
// 如果配置了多个的反向代理 --- 对象模式 // 如果配置了多个的反向代理 --- 对象模式
baseURL: isDev baseURL: isDev
? "https://visitor.scdswj.cn/prod-api" ? "/dev-api"
: "https://visitor.scdswj.cn/prod-api", : "/prod-api",
// baseURL: isDev ? 'http://192.168.31.118:8195' : 'https://visitor.scdswj.cn/prod-api' // baseURL: isDev ? 'http://192.168.31.118:8195' : 'https://visitor.scdswj.cn/prod-api'
}); });
// 'http://rap2api.taobao.org/app/mock/297766/example/1643070528065' // 'http://rap2api.taobao.org/app/mock/297766/example/1643070528065'
@@ -58,17 +58,19 @@ request.interceptors.response.use(
Toast.clear(); Toast.clear();
} }
if (code === 401) { if (code === 401) {
console.log("进了"); console.log("调试:401 登录状态已过期!");
Toast.fail(message);
setTimeout(() => {
localStorage.removeItem("token"); localStorage.removeItem("token");
localStorage.removeItem("user"); localStorage.removeItem("user");
const redirectUrl = localStorage.getItem("redirect"); Toast.fail(message);
if (redirectUrl) { setTimeout(() => {
window.location.href = redirectUrl; // const redirectUrl = localStorage.getItem("redirect");
} else { // if (redirectUrl) {
window.location.href = "/adminHome"; // window.location.href = redirectUrl;
} // } else {
// window.location.href = "/adminHome";
// }
// 使用 router 而不是直接修改 window.location
router.push("/adminHome");
}, 2000); }, 2000);
return Promise.reject("登录状态已过期,即将返回首页重新登录。"); return Promise.reject("登录状态已过期,即将返回首页重新登录。");
} else if (code === 500) { } else if (code === 500) {
@@ -89,13 +91,13 @@ request.interceptors.response.use(
(error) => { (error) => {
Toast.clear(); Toast.clear();
console.log(error.message); console.log(error.message);
let { message } = error; let {message} = error;
if (message === "Network Error") { if (message === "Network Error") {
message = "后端接口连接异常"; message = "后端接口连接异常(" + window.location.href + ")";
} else if (message.includes("timeout")) { } else if (message.includes("timeout")) {
message = "系统接口请求超时"; message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"; message = "系统管理接口 " + message.substr(message.length - 3) + " 异常";
} }
console.log(message); console.log(message);
Toast.fail(message); Toast.fail(message);
+6 -6
View File
@@ -18,12 +18,12 @@ const loadNoCloseArr = ["/upload/face"];
// isDev 为假 非开发环境(测试环境,生产环境)- npm run build // isDev 为假 非开发环境(测试环境,生产环境)- npm run build
const isDev = process.env.NODE_ENV === "development"; const isDev = process.env.NODE_ENV === "development";
const request = axios.create({ const request = axios.create({
// 根据环境 设置不同的baseURL // 根据环境 设置不同的baseURL https://visitor.scdswj.cn/prod-api
// 如果配置了单个的反向代理 --- 字符串模式 // 如果配置了单个的反向代理 --- 字符串模式
// 如果配置了多个的反向代理 --- 对象模式 // 如果配置了多个的反向代理 --- 对象模式
baseURL: isDev baseURL: isDev
? "https://visitor.scdswj.cn/prod-api" ? "/dev-api"
: "https://visitor.scdswj.cn/prod-api", : "/prod-api",
// baseURL: isDev ? "http://192.168.31.124:8195" : "http://192.168.31.124:8195", // baseURL: isDev ? "http://192.168.31.124:8195" : "http://192.168.31.124:8195",
}); });
// 'http://rap2api.taobao.org/app/mock/297766/example/1643070528065' // 'http://rap2api.taobao.org/app/mock/297766/example/1643070528065'
@@ -58,11 +58,11 @@ request.interceptors.response.use(
Toast.clear(); Toast.clear();
} }
if (code === 401) { if (code === 401) {
Toast.fail(message);
setTimeout(() => {
localStorage.removeItem("token"); localStorage.removeItem("token");
localStorage.removeItem("user"); localStorage.removeItem("user");
localStorage.removeItem("userToken"); localStorage.removeItem("userToken");
Toast.fail(message);
setTimeout(() => {
const redirectUrl = localStorage.getItem("redirect"); const redirectUrl = localStorage.getItem("redirect");
if (redirectUrl) { if (redirectUrl) {
@@ -96,7 +96,7 @@ request.interceptors.response.use(
} else if (message.includes("timeout")) { } else if (message.includes("timeout")) {
message = "系统接口请求超时"; message = "系统接口请求超时";
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"; message = "系统后台接口" + message.substr(message.length - 3) + "异常";
} }
console.log(message); console.log(message);
Toast.fail(message); Toast.fail(message);
+2 -2
View File
@@ -1,5 +1,5 @@
import request from "./index"; import request from "./index";
// 来访预约接口 // 内部人员头像上传接口
export function uploadApi(data){ export function uploadApi(data){
return request({ return request({
url: '/upload/face', url: '/upload/face',
@@ -8,7 +8,7 @@ export function uploadApi(data){
}) })
} }
// 来访人头像上传接口 // 访客头像上传接口
export function uploadGuestFaceApi(data){ export function uploadGuestFaceApi(data){
return request({ return request({
url: '/upload/guestFace', url: '/upload/guestFace',
+47
View File
@@ -8,3 +8,50 @@ $size30: .4rem /* 30/75 */;
$lg-size: .4267rem /* 32/75 */; $lg-size: .4267rem /* 32/75 */;
// 颜色 // 颜色
$white: #ffffff; $white: #ffffff;
/* PC端适配 - 使用缩放保持比例 */
@media screen and (min-width: 769px) {
body {
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
#app {
// 假设设计稿是750px宽度,我们可以按比例缩放
width: 750px;
height: 100vh;
transform-origin: center top;
// 计算缩放比例,假设PC端最小宽度为1200px
// 可以根据实际需要调整这个值
transform: scale(0.8); // 例如缩放到80%
// 或者根据实际视口宽度动态计算
// transform: scale(calc(100vw / 750));
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
// 为特定高度的屏幕调整缩放
@media screen and (min-width: 1200px) {
#app {
transform: scale(1);
}
}
@media screen and (min-width: 1000px) and (max-width: 1199px) {
#app {
transform: scale(0.9);
}
}
@media screen and (min-width: 769px) and (max-width: 999px) {
#app {
transform: scale(0.8);
}
}
}
+105 -59
View File
@@ -13,148 +13,194 @@
<p class="tips">点击照片框进行人脸照片上传</p> <p class="tips">点击照片框进行人脸照片上传</p>
<div class="button-box"> <div class="button-box">
<div @click="onClickCancel" class="cancel-button">取消</div> <div @click="onClickCancel" class="cancel-button">取消</div>
<div @click="onClickSave" class="save-button">保存</div> <div @click="onClickSave" class="save-button" :class="{ disabled: !file }" :style="{ pointerEvents: file ? 'auto' : 'none' }">保存</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import {ref} from 'vue'
import { useRouter } from 'vue-router' import {useRouter} from 'vue-router'
import { useStore } from 'vuex' import {useStore} from 'vuex'
import { rulesForm, resetForm, rulesPhone } from '@/com/index' import {rulesForm, resetForm, rulesPhone} from '@/com/index'
/* @data */ /* @data */
const router = useRouter() const router = useRouter()
const store = useStore() const store = useStore()
const emits = defineEmits(['change', 'cancel', 'save']) const emits = defineEmits(['change', 'cancel', 'save'])
const props = defineProps({ const props = defineProps({
faceImg: { faceImg: {
default: '' default: ''
}, },
}) })
const file = ref() const file = ref()
/* @setup */ /* @setup */
/* @method */ /* @method */
// 上传图片 // 上传图片
const onChangeFile = (e) =>{ const onChangeFile = (e) => {
file.value = e.target.files[0] file.value = e.target.files[0]
emits('change', e.target.files[0]) emits('change', e.target.files[0])
} }
const onClickCancel = () =>{ const onClickCancel = () => {
emits('cancel') emits('cancel')
}
const onClickSave = () => {
// 如果既没有新文件也没有原始图片,则不允许保存
if (!file.value && !props.faceImg) {
return;
} }
const onClickSave = () =>{
emits('save', file.value) emits('save', file.value)
} }
</script> </script>
<style lang='scss' scoped> <style lang='scss' scoped>
.fixed-model{ .fixed-model {
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(60,60,67,0.6); background: rgba(60, 60, 67, 0.6);
.model{
.model {
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 50%; top: 50%;
transform: translateX(-50%) translateY(-65%) ; transform: translateX(-50%) translateY(-65%);
width: 8.1867rem /* 614/75 */; width: 8.1867rem /* 614/75 */
;
// height: 394px; // height: 394px;
background: #FFFFFF; background: #FFFFFF;
border-radius: .5333rem /* 40/75 */; border-radius: .5333rem /* 40/75 */
padding: 0 0 .7733rem /* 58/75 */; ;
padding: 0 0 .7733rem /* 58/75 */
;
box-sizing: border-box; box-sizing: border-box;
header{
header {
width: 100%; width: 100%;
height: 10.5333rem /* 790/75 */; height: 10.5333rem /* 790/75 */
;
background: #FFFFFF; background: #FFFFFF;
border-radius: .5333rem /* 40/75 */; border-radius: .5333rem /* 40/75 */
;
background: url('../assets/img/renlianbeijing.png') left top/100% 100% no-repeat; background: url('../assets/img/renlianbeijing.png') left top/100% 100% no-repeat;
h3{
line-height: .7733rem /* 58/75 */; h3 {
font-size: .5333rem /* 40/75 */; line-height: .7733rem /* 58/75 */
font-family: Source Han Sans CN, Source Han Sans CN; ;
font-size: .5333rem /* 40/75 */
;
font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #222222; color: #222222;
padding: .8533rem /* 64/75 */ 0 0 ; padding: .8533rem /* 64/75 */
0 0;
text-align: center; text-align: center;
box-sizing: border-box; box-sizing: border-box;
} }
.upload-box{
.upload-box {
position: relative; position: relative;
width: 4.4rem /* 330/75 */; width: 4.4rem /* 330/75 */
height: 4.4rem /* 330/75 */; ;
height: 4.4rem /* 330/75 */
;
background: #FFFFFF; background: #FFFFFF;
box-shadow: 0px .1067rem /* 8/75 */ .8rem /* 60/75 */ .2667rem /* 20/75 */ rgba(68,140,247,0.4); box-shadow: 0px .1067rem /* 8/75 */
border-radius: .2667rem /* 20/75 */; .8rem /* 60/75 */
margin: 1.28rem /* 96/75 */ auto 0; .2667rem /* 20/75 */
rgba(68, 140, 247, 0.4);
border-radius: .2667rem /* 20/75 */
;
margin: 1.28rem /* 96/75 */
auto 0;
overflow: hidden; overflow: hidden;
.span{
.span {
text-align: center; text-align: center;
line-height: 4.4rem /* 330/75 */; line-height: 4.4rem /* 330/75 */
;
font-size: $size30; font-size: $size30;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #999999; color: #999999;
} }
// display: flex; // display: flex;
.face-img, input{ .face-img, input {
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: .2667rem /* 20/75 */; border-radius: .2667rem /* 20/75 */
;
opacity: 0; opacity: 0;
} }
.face-img{
.face-img {
opacity: 1; opacity: 1;
} }
} }
} }
.tips{
line-height: .5333rem /* 40/75 */; .tips {
line-height: .5333rem /* 40/75 */
;
font-size: $md-size; font-size: $md-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #5F6583; color: #5F6583;
text-align: center; text-align: center;
margin-top: -1.6rem /* 120/75 */; margin-top: -1.6rem /* 120/75 */
;
} }
.button-box{
.button-box {
// margin-top: 1.1467rem /* 86/75 */; // margin-top: 1.1467rem /* 86/75 */;
display: flex; display: flex;
padding: 0 .7733rem /* 58/75 */; padding: 0 .7733rem /* 58/75 */
;
box-sizing: border-box; box-sizing: border-box;
margin-top: .6133rem /* 46/75 */; margin-top: .6133rem /* 46/75 */
div{ ;
div {
// width: 240px; // width: 240px;
flex: 1; flex: 1;
height: 1.0667rem /* 80/75 */; height: 1.0667rem /* 80/75 */
line-height: 1.0667rem /* 80/75 */; ;
line-height: 1.0667rem /* 80/75 */
;
background: #448CF7; background: #448CF7;
border-radius: 1.3333rem /* 100/75 */; border-radius: 1.3333rem /* 100/75 */
;
text-align: center; text-align: center;
font-size: $md-size; font-size: $md-size;
color: #FFFFFF; color: #FFFFFF;
} }
.cancel-button{
margin-right: .2667rem /* 20/75 */; .cancel-button {
margin-right: .2667rem /* 20/75 */
;
background: #448CF7; // #D9D9D9;
color: #FFFFFF; // #999999;
}
.save-button {
&.disabled {
background: #D9D9D9; background: #D9D9D9;
color: #999999; color: #999999;
}
} }
} }
} }
+252 -127
View File
@@ -1,7 +1,7 @@
<template> <template>
<div v-if="true" class='box'> <div v-if="true" class='box'>
<header> <header>
<h3>Hello~{{userName}}</h3> <h3>Hello~{{ userName }}</h3>
<h4> 你又来审批预约了啊ㄟ( , )</h4> <h4> 你又来审批预约了啊ㄟ( , )</h4>
<div class="plate-box"> <div class="plate-box">
@@ -43,275 +43,400 @@
<div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div> <div class="status" :class="stateEnum[item.status].className">{{ stateEnum[item.status].statusName }}</div>
</div> </div>
</div> </div>
<div v-if="isLoading && recordArr.length == 0" class="no-have"> <div v-if="isLoading && isDataLoaded && recordArr.length === 0" class="no-have">
<img class="" src="../assets/nodata.png" alt=""> <img class="" src="../assets/nodata.png" alt="">
<p>暂无待审批数据</p> <p>暂无待审批数据</p>
</div> </div>
<div v-else-if="isLoading && !isDataLoaded" class="no-have">
<img class="" src="../assets/nodata.png" alt="">
<p>待审批数据加载中...</p>
</div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { reactive, ref } from 'vue' import {reactive, ref, onMounted} from 'vue'
import { useRouter } from 'vue-router' import {useRouter} from 'vue-router'
import { useStore } from 'vuex' import {useStore} from 'vuex'
import { Toast, ImagePreview } from 'vant'; import {Toast, ImagePreview} from 'vant';
import dd from 'dingtalk-jsapi' import dd from 'dingtalk-jsapi'
import { rulesForm, resetForm, rulesPhone } from '@/com/index' import {rulesForm, resetForm, rulesPhone} from '@/com/index'
import { getToken, getVisitorRecord, getWhiteCode } from '@/api/admin.js' import {getToken, getVisitorRecord, getWhiteCode} from '@/api/admin.js'
/* @data */ /* @data */
const router = useRouter() const router = useRouter()
const store = useStore() const store = useStore()
const isLoading = ref(false) const isLoading = ref(false)
const isDataLoaded = ref(false)
// 已经在登录处理中
const isLoginInProgress = ref(false);
const token = ref('') const token = ref('')
const userName = ref('') const userName = ref('')
const query = reactive({ const query = reactive({
status: 0, status: 0,
size: 2, size: 2,
current: 1, current: 1,
}) })
const recordArr = ref([]) const recordArr = ref([])
const stateEnum = store.state.stateEnum const stateEnum = store.state.stateEnum
token.value = localStorage.getItem('token') token.value = localStorage.getItem('token')
localStorage.setItem('redirect', '/adminHome') localStorage.setItem('redirect', '/adminHome')
/* @setup */ /* @setup */
const login = () =>{ const login = () => {
Toast.loading({ duration: 0, forbidClick: true, message: '登录中', }); // 防止重复登录
if (isLoginInProgress.value) {
return;
}
isLoginInProgress.value = true;
Toast.loading({duration: 0, forbidClick: true, message: '登录中',});
dd.getAuthCode({ dd.getAuthCode({
corpId: 'ding03f8e88dde9b426835c2f4657eb6378f', corpId: 'ding03f8e88dde9b426835c2f4657eb6378f',
success: (res) => { success: (res) => {
const { code } = res; const {code} = res;
localStorage.removeItem('token'); localStorage.removeItem('token');
localStorage.removeItem('user'); localStorage.removeItem('user');
getToken(code).then(data =>{ getToken(code).then(data => {
localStorage.setItem('user', JSON.stringify(data.data) ) // 验证返回的数据
localStorage.setItem('token', data.data.authorization) if (data && data.data && data.data.authorization) {
userName.value = data.data.name localStorage.setItem('user', JSON.stringify(data.data));
localStorage.setItem('token', data.data.authorization);
userName.value = data.data.name;
Toast.clear() Toast.clear();
Toast.success('登录成功') Toast.success('登录成功');
visitorList() visitorList();
}) } else {
throw new Error('登录数据异常');
}
}).catch(err => {
Toast.clear();
Toast.fail('登录失败');
console.error('登录失败:', err);
}).finally(() => {
isLoginInProgress.value = false;
});
}, },
fail: (err) => { fail: (err) => {
}, },
complete: () => {}, complete: () => {
},
}); });
} }
// login() // login()
const visitorList = () =>{ const visitorList = () => {
Toast.loading({ duration: 0, forbidClick: true, message: '加载中', }); isDataLoaded.value = false
getVisitorRecord(query).then(res =>{ Toast.loading({duration: 0, forbidClick: true, message: '加载中',});
getVisitorRecord(query).then(res => {
isLoading.value = true isLoading.value = true
isDataLoaded.value = true
recordArr.value = res.data recordArr.value = res.data
}).catch(err=>{ }).catch(err => {
isLoading.value = true isLoading.value = true
isDataLoaded.value = true
recordArr.value = []
}) })
} }
// visitorList()
if(token.value){
visitorList()
console.log((JSON.parse(localStorage.getItem('user'))).name )
userName.value = JSON.parse(localStorage.getItem('user')).name
}else{
login()
}
/* @method */ /* @method */
const onClickGo = (url = '/adminHome') =>{ const onClickGo = (url = '/adminHome') => {
router.push(url) 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();
}
};
// 在组件挂载时调用
onMounted(() => {
initializeApp();
});
</script> </script>
<style lang='scss' scoped> <style lang='scss' scoped>
.box{ .box {
background-color: #F9FBFC; background-color: #F9FBFC;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
header{
header {
position: relative; position: relative;
width: 100%; width: 100%;
height: 10.4rem /* 780/75 */; height: 10.4rem /* 780/75 */
;
background: url('../assets/guanlibeijing.png') left top/100% 100% no-repeat; background: url('../assets/guanlibeijing.png') left top/100% 100% no-repeat;
box-sizing: border-box; box-sizing: border-box;
h3{
padding: 1.0933rem /* 82/75 */ .6933rem /* 52/75 */ .1067rem /* 8/75 */; h3 {
padding: 1.0933rem /* 82/75 */
.6933rem /* 52/75 */
.1067rem /* 8/75 */
;
box-sizing: border-box; box-sizing: border-box;
line-height: .72rem /* 54/75 */; line-height: .72rem /* 54/75 */
font-size: .48rem /* 36/75 */; ;
font-family: Source Han Sans CN, Source Han Sans CN; font-size: .48rem /* 36/75 */
;
font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #222222; color: #222222;
} }
h4{
line-height: .48rem /* 36/75 */; h4 {
line-height: .48rem /* 36/75 */
;
font-size: $sm-size; font-size: $sm-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #FFFFFF; color: #FFFFFF;
padding: 0 .6933rem /* 52/75 */ 1.12rem /* 84/75 */; padding: 0 .6933rem /* 52/75 */
1.12rem /* 84/75 */
;
box-sizing: border-box; box-sizing: border-box;
} }
.position-img{
.position-img {
position: absolute; position: absolute;
right: .4267rem /* 32/75 */; right: .4267rem /* 32/75 */
top: .2933rem /* 22/75 */; ;
width: 3.6267rem /* 272/75 */; top: .2933rem /* 22/75 */
height: 2.96rem /* 222/75 */; ;
img{ width: 3.6267rem /* 272/75 */
;
height: 2.96rem /* 222/75 */
;
img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.plate-box{
.plate-box {
width: 100%; width: 100%;
padding: 0 .4rem /* 30/75 */; padding: 0 .4rem /* 30/75 */
;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.plate-button{
width: 4.4rem /* 330/75 */; .plate-button {
height: 1.92rem /* 144/75 */; width: 4.4rem /* 330/75 */
background: linear-gradient(180deg, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.6) 48%); ;
border-radius: .2667rem /* 20/75 */; height: 1.92rem /* 144/75 */
border: .0267rem /* 2/75 */ solid #FFFFFF; ;
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; display: flex;
align-items: center; align-items: center;
img{
width: .9867rem /* 74/75 */; img {
height: .9867rem /* 74/75 */; width: .9867rem /* 74/75 */
margin-left: .32rem /* 24/75 */; ;
height: .9867rem /* 74/75 */
;
margin-left: .32rem /* 24/75 */
;
} }
.right{
margin-left: .3467rem /* 26/75 */; .right {
div{ margin-left: .3467rem /* 26/75 */
line-height: .64rem /* 48/75 */; ;
div {
line-height: .64rem /* 48/75 */
;
font-size: $lg-size; font-size: $lg-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #222222; color: #222222;
} }
P{
line-height: .4rem /* 30/75 */; P {
font-size: .2667rem /* 20/75 */; line-height: .4rem /* 30/75 */
font-family: Source Han Sans CN, Source Han Sans CN; ;
font-size: .2667rem /* 20/75 */
;
font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #5F6583; color: #5F6583;
margin-top: .1067rem /* 8/75 */; margin-top: .1067rem /* 8/75 */
;
} }
} }
} }
} }
} }
.content{
.content {
flex: 1; flex: 1;
overflow: auto; overflow: auto;
position: relative; position: relative;
// top: 5.8667rem /* 440/75 */; // top: 5.8667rem /* 440/75 */;
margin-top: -4.5333rem /* 340/75 */; margin-top: -4.5333rem /* 340/75 */
;
width: 100%; width: 100%;
padding: 0 .4rem /* 30/75 */; padding: 0 .4rem /* 30/75 */
;
box-sizing: border-box; box-sizing: border-box;
h2{
h2 {
width: 100%; width: 100%;
padding: .2667rem /* 20/75 */ .32rem /* 24/75 */; padding: .2667rem /* 20/75 */
.32rem /* 24/75 */
;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
line-height: .72rem /* 54/75 */; line-height: .72rem /* 54/75 */
font-size: .48rem /* 36/75 */; ;
font-family: Source Han Sans CN, Source Han Sans CN; font-size: .48rem /* 36/75 */
;
font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #222222; color: #222222;
span{
span {
// line-height: 36px; // line-height: 36px;
font-size: $sm-size; font-size: $sm-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #999999; color: #999999;
} }
} }
.content-ul{
.wait-list{ .content-ul {
.wait-list {
position: relative; position: relative;
width: 9.2rem /* 690/75 */; width: 9.2rem /* 690/75 */
;
// height: 470px; // height: 470px;
background: #FFFFFF; background: #FFFFFF;
border-radius: .2667rem /* 20/75 */; border-radius: .2667rem /* 20/75 */
padding: .48rem /* 36/75 */; ;
padding: .48rem /* 36/75 */
;
box-sizing: border-box; box-sizing: border-box;
margin-bottom: .2667rem /* 20/75 */; margin-bottom: .2667rem /* 20/75 */
h5{ ;
height: .6667rem /* 50/75 */;
h5 {
height: .6667rem /* 50/75 */
;
font-size: $md-size; font-size: $md-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #222222; color: #222222;
} }
.apply-box{
.apply-box {
width: 100%; width: 100%;
padding: .4rem /* 30/75 */ .3733rem /* 28/75 */ .5067rem /* 38/75 */; padding: .4rem /* 30/75 */
.3733rem /* 28/75 */
.5067rem /* 38/75 */
;
box-sizing: border-box; box-sizing: border-box;
border-radius: .1333rem /* 10/75 */; border-radius: .1333rem /* 10/75 */
;
font-size: $md-size; font-size: $md-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #999999; color: #999999;
line-height: .72rem /* 54/75 */; line-height: .72rem /* 54/75 */
;
background: #F5F7F9; background: #F5F7F9;
span:last-child{
span:last-child {
color: #5F6583; color: #5F6583;
} }
} }
.status{
.status {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
width: 1.52rem /* 114/75 */; width: 1.52rem /* 114/75 */
height: .6667rem /* 50/75 */; ;
line-height: .6667rem /* 50/75 */; height: .6667rem /* 50/75 */
;
line-height: .6667rem /* 50/75 */
;
background: #FFE9E4; background: #FFE9E4;
border-radius: 0px .2667rem /* 20/75 */ 0px .1333rem /* 10/75 */; border-radius: 0 .2667rem /* 20/75 */
0 .1333rem /* 10/75 */
;
color: #FF6643; color: #FF6643;
font-size: $sm-size; font-size: $sm-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #FF6643;
text-align: center; text-align: center;
} }
.refuse{
.refuse {
color: #5F6583; color: #5F6583;
background: #EAEEF6; background: #EAEEF6;
} }
.pass{
.pass {
color: #30BF78; color: #30BF78;
background: #E7F8F5; background: #E7F8F5;
} }
} }
} }
.no-have{
.no-have {
// display: block; // display: block;
width: 7.4667rem /* 560/75 */; width: 7.4667rem /* 560/75 */
height: 5.3867rem /* 404/75 */; ;
margin: .8rem /* 60/75 */ auto; height: 5.3867rem /* 404/75 */
img{ ;
margin: .8rem /* 60/75 */
auto;
img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
// font-size: 15px; // font-size: 15px;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #999999; color: #999999;
text-align: center; text-align: center;
+256 -171
View File
@@ -2,7 +2,7 @@
<div class="box"> <div class="box">
<header> <header>
<h2>门禁人脸信息</h2> <h2>门禁人脸信息</h2>
<h3> <img src="../assets/img/dunpai.png" alt=""> 公司门禁系统人脸上传和查看 </h3> <h3><img src="../assets/img/dunpai.png" alt=""> 公司门禁系统人脸上传和查看 </h3>
<div class="entering-box"> <div class="entering-box">
<img src="../assets/img/shenfenzheng.png" alt=""> <img src="../assets/img/shenfenzheng.png" alt="">
<div class="entering-center"> <div class="entering-center">
@@ -13,10 +13,13 @@
</div> </div>
</header> </header>
<div class="content"> <div class="content">
<h2>通讯录</h2><button @click="handleSync" class="entering-button">同步人员信息</button> <h2>通讯录</h2>
<div class="content-box" > <button @click="handleSync" class="entering-button">同步人员信息</button>
<div class="content-box">
<div class="nav"> <div class="nav">
<div @click="onClickDept(item.deptId)" v-for="item in deptArr" class="li" :class="item.deptId == deptId ? 'active' : ''" :style=" item.name.length >= 6 ? 'padding-right: 0.28rem;' : '' " :key="item.userId"> <div @click="onClickDept(item.deptId)" v-for="item in deptArr" class="li"
:class="item.deptId === deptId ? 'active' : ''"
:style=" item.name.length >= 6 ? 'padding-right: 0.28rem;' : '' " :key="item.userId">
{{ item.name }} {{ item.name }}
</div> </div>
</div> </div>
@@ -27,8 +30,8 @@
<img v-if="item.img" :src="item.img" alt=""> <img v-if="item.img" :src="item.img" alt="">
</div> </div>
<div class="name">{{ item.name }}</div> <div class="name">{{ item.name }}</div>
<div @click="onClcikUser(item)" v-if="item.img" class="button">查看</div> <div @click="onClickUser(item)" v-if="item.img" class="button">查看</div>
<div @click="onClcikUser(item)" v-else class="button active-button">上传</div> <div @click="onClickUser(item)" v-else class="button active-button">上传</div>
</div> </div>
</div> </div>
@@ -37,92 +40,100 @@
</div> </div>
</div> </div>
<Facemodel @change="onChangeFile" @cancel="isFace = false; form.face =''" @save="onClciksave" v-if="isFace" :faceImg="form.face" /> <Facemodel @change="onChangeFile" @cancel="isFace = false; form.face =''" @save="onClickSave" v-if="isFace"
:faceImg="form.face"/>
</template> </template>
<script setup> <script setup>
import { rulesPhone, compareTime, timeDiff,formatDate } from '../com/index.js' import {rulesPhone, compareTime, timeDiff, formatDate} from '@/com'
// getShop, getKind // getShop, getKind
import { syncDeptUsers } from '../api/user.js' import {syncDeptUsers} from '@/api/user'
import { reactive, ref } from 'vue' import {reactive, ref} from 'vue'
import { Toast, ImagePreview, Skeleton } from 'vant'; import {Toast, ImagePreview, Skeleton} from 'vant';
import dd from 'dingtalk-jsapi' import dd from 'dingtalk-jsapi'
import { getToken, getDept, getUserListByDept, putUserId } from '@/api/doorAdmin.js' import {getToken, getDept, getUserListByDept, putUserId} from '@/api/doorAdmin.js'
import Facemodel from '@/components/face-model.vue' import Facemodel from '@/components/face-model.vue'
import { uploadApi } from '@/api/upload' import {uploadApi} from '@/api/upload'
import { useRouter } from 'vue-router'; import {useRouter} from 'vue-router';
const router = useRouter() const router = useRouter()
const deptArr = ref([]) // 部门数据 const deptArr = ref([]) // 部门数据
const userArr = ref([]) // 用户 const userArr = ref([]) // 用户
const deptId = ref('') // 选中的部门Id const deptId = ref('') // 选中的部门Id
const isFace = ref(false) const isFace = ref(false)
const form = reactive({ // const form = reactive({ //
face: '', face: '',
userId: '', userId: '',
name: '' name: ''
}) })
const token = ref('') const token = ref('')
const isLoading = ref(false) const isLoading = ref(false)
localStorage.setItem('redirect', '/home') localStorage.setItem('redirect', '/home')
token.value = localStorage.getItem('token') token.value = localStorage.getItem('token')
// setTimeout( ()=>{ // setTimeout( ()=>{
// form.face = 'https://img0.baidu.com/it/u=3229206321,1418550973&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500' // form.face = 'https://img0.baidu.com/it/u=3229206321,1418550973&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500'
// }, 2000) // }, 2000)
// method // method
// 点击预栏图片 // 点击预栏图片
const onClickPreviewImg = (img) =>{ const onClickPreviewImg = (img) => {
dd.previewImage({ dd.previewImage({
urls: [img urls: [img
], ],
current: 1, current: 1,
success: () => {}, success: () => {
fail: () => {}, },
complete: () => {}, fail: () => {
},
complete: () => {
},
}); });
} }
// 点击切换部门 // 点击切换部门
const onClickDept = (Id) =>{ const onClickDept = (Id) => {
if(deptId.value != Id){ if (deptId.value !== Id) {
deptId.value = Id deptId.value = Id
userList() userList()
} }
} }
// 点击上传了文件 // 点击上传了文件
const onChangeFile = (file) =>{ const onChangeFile = (file) => {
console.log(file) console.log(file)
if(file){ if (file) {
let reader = new FileReader() let reader = new FileReader()
reader.readAsDataURL(file) // 转base64 reader.readAsDataURL(file) // 转base64
reader.onload = () =>{ // 简化代码 - 转换完成 reader.onload = () => { // 简化代码 - 转换完成
form.face = reader.result form.face = reader.result
} }
} }
} }
// 点击保存 // 点击保存
const onClciksave = (file) =>{ const onClickSave = (file) => {
if(form.face && file){ if (form.face && file) {
// 有新图片需要上传
let formData = new FormData() let formData = new FormData()
formData.append('file', file) formData.append('file', file)
formData.append('userId', form.userId) formData.append('userId', form.userId)
formData.append('name', form.name) formData.append('name', form.name)
Toast.loading({ duration: 0, forbidClick: true, message: '上传中', }); Toast.loading({duration: 0, forbidClick: true, message: '上传中',});
uploadApi(formData).then(res =>{ uploadApi(formData).then(res => {
form.face = res.data form.face = res.data
let obj = { userId: form.userId, img: form.face } let obj = {userId: form.userId, img: form.face}
putUserId(obj).then(response =>{ putUserId(obj).then(response => {
userList() userList()
isFace.value = false isFace.value = false
Toast.success(response.msg); Toast.success(response.msg);
}) })
}).catch(err => {
Toast.fail('上传失败,请重试');
console.error('上传失败:', err);
}) })
}else if(form.face && !file ){ // 说明之前有数据现在没传 } else if (form.face && !file) { // 说明之前有数据现在没传
isFace.value = false isFace.value = false
}else if(!form.face && !file){ } else if (!form.face && !file) {
Toast.fail('请先上传照片!'); Toast.fail('请先上传照片!');
} }
// if(file){ // 文件是否上传了 // if(file){ // 文件是否上传了
@@ -140,267 +151,341 @@
// Toast.fail('请先上传照片!'); // Toast.fail('请先上传照片!');
// } // }
} }
// 点击用户上传照片或查看 // 点击用户上传照片或查看
const onClcikUser = (item) =>{ const onClickUser = (item) => {
console.log(item) console.log(item)
isFace.value = true isFace.value = true
form.face = item.img form.face = item.img
form.userId = item.userId form.userId = item.userId
form.name = item.name form.name = item.name
} }
const login = () =>{ const login = () => {
Toast.loading({ duration: 0, forbidClick: true, message: '登录中', }); Toast.loading({duration: 0, forbidClick: true, message: '登录中',});
dd.getAuthCode({ dd.getAuthCode({
corpId: 'ding03f8e88dde9b426835c2f4657eb6378f', corpId: 'ding03f8e88dde9b426835c2f4657eb6378f',
success: (res) => { success: (res) => {
const { code } = res; const {code} = res;
localStorage.removeItem('token'); localStorage.removeItem('token');
localStorage.removeItem('user'); localStorage.removeItem('user');
getToken(code).then(data =>{ getToken(code).then(res => {
localStorage.setItem('user', data.data) localStorage.setItem('user', res.data)
localStorage.setItem('token', data.data.authorization) localStorage.setItem('token', res.data.authorization)
alert("登录成功:"+data.data.authorization)
Toast.clear() Toast.clear()
Toast.success('登录成功') Toast.success('登录成功')
deptList() deptList()
}) })
} }
}); });
} }
// 获取部门用户 // 获取部门用户
const userList = () =>{ const userList = () => {
isLoading.value = false isLoading.value = false
getUserListByDept(deptId.value).then(res =>{ getUserListByDept(deptId.value).then(res => {
isLoading.value = true isLoading.value = true
userArr.value = res.data userArr.value = res.data
}) })
} }
// 获取部门列表 // 获取部门列表
const deptList = () =>{ const deptList = () => {
getDept().then(res =>{ getDept().then(res => {
deptArr.value = res.data deptArr.value = res.data
deptId.value = res.data[0].deptId deptId.value = res.data[0].deptId
userList() userList()
}) })
} }
// 跳转特殊人员 // 跳转特殊人员
const onClickGoSpecialCrowd = () =>{ const onClickGoSpecialCrowd = () => {
router.push('/specialCrowd') router.push('/specialCrowd')
} }
// 同步钉钉用户信息 // 同步钉钉用户信息
const handleSync = () =>{ const handleSync = () => {
syncDeptUsers().then(res =>{ syncDeptUsers().then(res => {
Toast.success(res.msg) Toast.success(res.msg)
}) })
} }
if(token.value){ if (token.value) {
// localStorage.setItem('token', 123) // localStorage.setItem('token', 123)
deptList() deptList()
}else{ } else {
login() login()
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.box{ .box {
display: flex; display: flex;
flex-direction:column ; flex-direction: column;
header{
header {
width: 100%; width: 100%;
height: 5.8933rem /* 442/75 */; height: 5.8933rem /* 442/75 */
;
background: url('../assets/img/shouyebeijing.png') left top/100% 100% no-repeat; background: url('../assets/img/shouyebeijing.png') left top/100% 100% no-repeat;
h2{
line-height: 1.12rem /* 84/75 */; h2 {
font-size: .7467rem /* 56/75 */; line-height: 1.12rem /* 84/75 */
font-family: Source Han Sans CN, Source Han Sans CN; ;
font-size: .7467rem /* 56/75 */
;
font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #FFFFFF; color: #FFFFFF;
padding: .8533rem /* 64/75 */ 0 0 .64rem /* 48/75 */; padding: .8533rem /* 64/75 */
0 0 .64rem /* 48/75 */
;
box-sizing: border-box; box-sizing: border-box;
} }
h3{
h3 {
display: flex; display: flex;
padding: .32rem /* 24/75 */ 0 0 .7467rem /* 56/75 */; padding: .32rem /* 24/75 */
0 0 .7467rem /* 56/75 */
;
box-sizing: border-box; box-sizing: border-box;
line-height: .5333rem /* 40/75 */; line-height: .5333rem /* 40/75 */
;
font-size: $sm-size; font-size: $sm-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #FFFFFF; color: #FFFFFF;
img{
width: .5333rem /* 40/75 */; img {
height: .5333rem /* 40/75 */; width: .5333rem /* 40/75 */
margin-right: .1067rem /* 8/75 */; ;
height: .5333rem /* 40/75 */
;
margin-right: .1067rem /* 8/75 */
;
} }
} }
.entering-box{
width: 8rem /* 600/75 */; .entering-box {
height: 1.6rem /* 120/75 */; width: 8rem /* 600/75 */
margin: .6667rem /* 50/75 */ auto 0; ;
height: 1.6rem /* 120/75 */
;
margin: .6667rem /* 50/75 */
auto 0;
background: #202F44; background: #202F44;
border-radius: .5333rem /* 40/75 */ .5333rem /* 40/75 */ 0px 0px; border-radius: .5333rem /* 40/75 */
padding: 0 .4rem /* 30/75 */ .8rem /* 60/75 */ .4533rem /* 34/75 */; .5333rem /* 40/75 */
0 0;
padding: 0 .4rem /* 30/75 */
.8rem /* 60/75 */
.4533rem /* 34/75 */
;
display: flex; display: flex;
align-items: center; align-items: center;
img{
width: .6133rem /* 46/75 */; img {
height: .48rem /* 36/75 */; width: .6133rem /* 46/75 */
margin-right: .2933rem /* 22/75 */; ;
height: .48rem /* 36/75 */
;
margin-right: .2933rem /* 22/75 */
;
} }
.entering-center{
.entering-center {
flex: 1; flex: 1;
font-size: $md-size; font-size: $md-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #FFFFFF; color: #FFFFFF;
p:nth-child(1){
line-height: .56rem /* 42/75 */; p:nth-child(1) {
padding: .2933rem /* 22/75 */ 0 0; line-height: .56rem /* 42/75 */
;
padding: .2933rem /* 22/75 */
0 0;
} }
p:nth-child(2){
line-height: .4533rem /* 34/75 */; p:nth-child(2) {
line-height: .4533rem /* 34/75 */
;
font-size: $sm-size; font-size: $sm-size;
font-weight: 400; font-weight: 400;
color: #B6B7B8; color: #B6B7B8;
} }
} }
.entering-button{
width: 1.4667rem /* 110/75 */; .entering-button {
height: .6933rem /* 52/75 */; width: 1.4667rem /* 110/75 */
;
height: .6933rem /* 52/75 */
;
background: #F6C976; background: #F6C976;
border-radius: .5333rem /* 40/75 */; border-radius: .5333rem /* 40/75 */
;
outline: none; outline: none;
font-size: $size26; font-size: $size26;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #202F44; color: #202F44;
border: none; border: none;
} }
} }
} }
.content{
.content {
width: 100%; width: 100%;
background: #FFFFFF; background: #FFFFFF;
border-radius: .5333rem /* 40/75 */ .5333rem /* 40/75 */ 0px 0px; border-radius: .5333rem /* 40/75 */
.5333rem /* 40/75 */
0 0;
margin-top: -20px; margin-top: -20px;
overflow: auto; overflow: auto;
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column ; flex-direction: column;
h2{
padding: .4267rem /* 32/75 */ .48rem /* 36/75 */; h2 {
padding: .4267rem /* 32/75 */
.48rem /* 36/75 */
;
box-sizing: border-box; box-sizing: border-box;
line-height: .8rem /* 60/75 */; line-height: .8rem /* 60/75 */
font-size: .5333rem /* 40/75 */; ;
font-family: Source Han Sans CN, Source Han Sans CN; font-size: .5333rem /* 40/75 */
;
font-family: Source Han Sans CN, serif;
font-weight: 500; font-weight: 500;
color: #222222; color: #222222;
} }
.content-box{
.content-box {
overflow: auto; overflow: auto;
display: flex; display: flex;
flex: 1; flex: 1;
.nav{
width: 3.6533rem /* 274/75 */; .nav {
width: 3.6533rem /* 274/75 */
;
height: 100%; height: 100%;
// width: 360px; // width: 360px;
padding: 0 0 0 .4rem /* 30/75 */; padding: 0 0 0 .4rem /* 30/75 */
;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
align-content: flex-start; align-content: flex-start;
// flex-direction: column; // flex-direction: column;
flex-wrap: wrap; flex-wrap: wrap;
border-right: .0267rem /* 2/75 */ dashed #D9D9D9; border-right: .0267rem /* 2/75 */
dashed #D9D9D9;
.li{ .li {
display:block; display: block;
box-sizing: border-box; box-sizing: border-box;
height: .9067rem /* 68/75 */; height: .9067rem /* 68/75 */
line-height: .9067rem /* 68/75 */; ;
border-radius: 0px .8rem /* 60/75 */ .8rem /* 60/75 */ 0px ; line-height: .9067rem /* 68/75 */
padding: 0 .48rem /* 36/75 */ 0 .24rem /* 18/75 */; ;
border-radius: 0 .8rem /* 60/75 */
.8rem /* 60/75 */
0;
padding: 0 .48rem /* 36/75 */
0 .24rem /* 18/75 */
;
box-sizing: border-box;
box-sizing: border-box;
font-size: $md-size; font-size: $md-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #5F6583; color: #5F6583;
margin-bottom: .28rem /* 21/75 */; margin-bottom: .28rem /* 21/75 */
;
} }
.active{
.active {
color: #FFFFFF; color: #FFFFFF;
background: #448CF7; background: #448CF7;
} }
} }
.user-content{
.user-content {
flex: 1; flex: 1;
height: 100%; height: 100%;
overflow: auto; overflow: auto;
.user-scroll{ .user-scroll {
width: 100%; width: 100%;
// height: 100%; // height: 100%;
} }
.user-list{ .user-list {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 .4rem /* 30/75 */; padding: 0 .4rem /* 30/75 */
;
box-sizing: border-box; box-sizing: border-box;
margin-bottom: .5333rem /* 40/75 */; margin-bottom: .5333rem /* 40/75 */
.img-box{ ;
width: .9867rem /* 74/75 */;
height: .9867rem /* 74/75 */; .img-box {
border-radius:.1333rem /* 10/75 */; width: .9867rem /* 74/75 */
;
height: .9867rem /* 74/75 */
;
border-radius: .1333rem /* 10/75 */
;
background: #D9D9D9; background: #D9D9D9;
img{
img {
display: block; display: block;
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius:.1333rem /* 10/75 */; border-radius: .1333rem /* 10/75 */
;
} }
} }
.name{ .name {
padding: 0 0 0 .2933rem /* 22/75 */; padding: 0 0 0 .2933rem /* 22/75 */
;
box-sizing: border-box; box-sizing: border-box;
flex: 1; flex: 1;
line-height: .9867rem /* 74/75 */; line-height: .9867rem /* 74/75 */
;
font-size: $size30; font-size: $size30;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #4B4C4E; color: #4B4C4E;
} }
.button{
width: 1.2267rem /* 92/75 */; .button {
height: .6667rem /* 50/75 */; width: 1.2267rem /* 92/75 */
;
height: .6667rem /* 50/75 */
;
background: #EDEDED; background: #EDEDED;
border-radius:.1333rem /* 10/75 */; border-radius: .1333rem /* 10/75 */
;
border: none; border: none;
outline: none; outline: none;
font-size: $sm-size; font-size: $sm-size;
font-family: Source Han Sans CN, Source Han Sans CN; font-family: Source Han Sans CN, serif;
font-weight: 400; font-weight: 400;
color: #999999; color: #999999;
box-sizing: border-box; box-sizing: border-box;
text-align: center; text-align: center;
line-height: .6667rem /* 50/75 */; line-height: .6667rem /* 50/75 */
;
} }
.active-button{
.active-button {
background: #EBFCF4; background: #EBFCF4;
border: .0267rem /* 2/75 */ solid #30BF78; border: .0267rem /* 2/75 */
solid #30BF78;
color: #30BF78; color: #30BF78;
} }
+11 -11
View File
@@ -23,17 +23,17 @@ export default defineConfig({
host: "0.0.0.0", //设置地址:http://localhost host: "0.0.0.0", //设置地址:http://localhost
port: 4000, // 设置服务启动端口号 port: 4000, // 设置服务启动端口号
hmr: false, // 关闭热更新 hmr: false, // 关闭热更新
// open: true, // 设置服务启动时是否自动打开浏览器 open: true, // 设置服务启动时是否自动打开浏览器
// cors: true, // 允许跨域 cors: true, // 允许跨域
// proxy: { proxy: {
// '/api': { '/dev-api': {
// target: 'http://dining.lzyyj.com/prod-api',//代理的地址 target: 'http://localhost:8195',//代理的地址
// changeOrigin: true, changeOrigin: true,
// // 路径重写 pathRewrite无效使用rewrite // 路径重写 pathRewrite无效使用rewrite
// // pathRewrite: { '/api': '' // 用'/api'代替target里面的地址 }, // pathRewrite: { '/api': '' // 用'/api'代替target里面的地址 },
// rewrite: path => path.replace(/^\/api/, '') rewrite: path => path.replace(/^\/dev-api/, '')
// } }
// } }
}, },
resolve: { resolve: {
alias: { alias: {