完成邀约接口

This commit is contained in:
2025-09-09 20:52:35 +08:00
parent d061b4d470
commit 2e58309db4
11 changed files with 1362 additions and 1372 deletions

View File

@@ -95,7 +95,8 @@ const install = (Vue, vm) => {
// APP公共服务 // APP公共服务
upgradeCheck: () => vm.$u.post('/app/upgrade/check', {appCode: config.appCode, appVersion: config.appVersion}), upgradeCheck: () => vm.$u.post('/app/upgrade/check', {appCode: config.appCode, appVersion: config.appVersion}),
commentSave: (params = {}) => vm.$u.post('/app/comment/save', params), commentSave: (params = {}) => vm.$u.post('/app/comment/save', params),
//获取访客类型
getType:(params = {}) => vm.$u.get(config.adminPath+'/property/xcx/system/type/'+params),
// 个人信息修改 // 个人信息修改
user: { user: {
saveUserInfo: (params = {}) => vm.$u.post(config.adminPath+'/mobile/user/saveUserInfo', params), saveUserInfo: (params = {}) => vm.$u.post(config.adminPath+'/mobile/user/saveUserInfo', params),
@@ -118,6 +119,19 @@ const install = (Vue, vm) => {
queryEmployeeById:(params = {}) => vm.$u.get(config.adminPath+'/property/xcx/person/'+ params.id), queryEmployeeById:(params = {}) => vm.$u.get(config.adminPath+'/property/xcx/person/'+ params.id),
queryEmployee:(params = {}) => vm.$u.get(config.adminPath+'/property/xcx/person/list', params), queryEmployee:(params = {}) => vm.$u.get(config.adminPath+'/property/xcx/person/list', params),
updateEmployee:(params = {}) => vm.$u.put(config.adminPath+'/property/xcx/person', params), updateEmployee:(params = {}) => vm.$u.put(config.adminPath+'/property/xcx/person', params),
},
// 单位管理
repair:{
addRepair:(params = {}) => vm.$u.post(config.adminPath+'/property/xcx/workOrders', params),
getWorkOrdersType:(params = {}) => vm.$u.get(config.adminPath+'/property/xcx/workOrdersType/typeTree/'+ params.parentId),
getMyOrderList:(params = {})=>vm.$u.get(config.adminPath+'/property/xcx/workOrders/list',params),
updateOrder:(params = {})=>vm.$u.put(config.adminPath+'/property/xcx/workOrders',params),
},
visitor:{
//我的访客列表
getMyVisitor:(params = {})=>vm.$u.get(config.adminPath+'/property/xcx/visitorManagement/list/'+params.type),
addVisitor:(params = {})=>vm.$u.post(config.adminPath+'/property/xcx/visitorManagement',params),
qrCodeVisitor:(params = {})=>vm.$u.get(config.adminPath+'/property/xcx/visitorManagement/qrCode/'+params.id),
}, },
// 增删改查例子 // 增删改查例子
testData: { testData: {

View File

@@ -54,7 +54,7 @@
}, },
{ {
icon: '/static/ic_mine_visitor.png', icon: '/static/ic_mine_visitor.png',
text: '我的访客1111' text: '我的访客'
}, },
{ {
icon: '/static/ic_mine_check.png', icon: '/static/ic_mine_check.png',

View File

@@ -41,10 +41,6 @@
</template> </template>
<script> <script>
// 导入MediaSelector和MediaType
import MediaSelector, {
MediaType
} from '@/utils/mediaSelector';
import { import {
uploadFiles uploadFiles
} from '@/common/upload.js'; } from '@/common/upload.js';
@@ -54,7 +50,7 @@
return { return {
repairInfo: { repairInfo: {
location: '', location: '',
type: '1942879389453230082', type: '',
orderImgUrl: '', orderImgUrl: '',
remark: '' remark: ''
}, },
@@ -71,14 +67,45 @@
this.selectedType = item; this.selectedType = item;
}, },
async getOrderType() { async getOrderType() {
try {
let params = { let params = {
parentId: '1952989217332658178' parentId: '1952989217332658178'
};
let params1 = {
parentId: '1943128289816682498'
};
// 使用Promise.all同时发起两次请求
const [res1, res2] = await Promise.all([
this.$u.api.repair.getWorkOrdersType(params),
this.$u.api.repair.getWorkOrdersType(params1)
]);
if (res1.code === 200 && res2.code === 200) {
// 合并children数组
const combinedChildren = [
...(res1.data[0]?.children || []),
...(res2.data[0]?.children || [])
];
// 创建合并后的数据结构
const combinedData = [{
...res1.data[0],
children: combinedChildren,
childrenid: res1.data[0].childrenid || res2.data[0].childrenid
}];
this.repairTypes = combinedChildren;
this.repairInfo.type = combinedData[0].id;
this.selectType(combinedChildren[0]?.orderTypeName || '');
} else {
uni.showToast({
title: '获取工单类型失败',
icon: 'none'
});
} }
let res = await this.$u.api.getRepairTypes(params); } catch (error) {
if (res.code == '200') { uni.showToast({
this.repairTypes = res.data title: '获取工单类型异常',
this.repairInfo.type = res.data[0].id; icon: 'none'
this.selectType(res.data[0].orderTypeName) });
} }
}, },
// 删除图片 // 删除图片
@@ -131,7 +158,8 @@
}, },
async realSubmit() { async realSubmit() {
let res = await this.$u.api.addOrder2(this.repairInfo); this.repairInfo.orderName="工单"
let res = await this.$u.api.repair.addRepair(this.repairInfo);
if (res.code == '200') { if (res.code == '200') {
uni.navigateTo({ uni.navigateTo({
url: '/pages/sys/user/myRepair/repaired' url: '/pages/sys/user/myRepair/repaired'

View File

@@ -14,10 +14,10 @@
<!-- 空状态 --> <!-- 空状态 -->
<view v-if="records.length === 0 && !loading" class="repair-empty-box"> <view v-if="records.length === 0 && !loading" class="repair-empty-box">
<view class="repair-empty-img-box"> <view class="repair-empty-img-box">
<image src="/static/ic_my_repair_01.png" class="repair-empty-img" /> <image src="/static/ic_my_repair_01.png" class="repair-empty-img"/>
</view> </view>
<view class="repair-add-btn-box"> <view class="repair-add-btn-box">
<image src="/static/ic_my_repair_02.png" class="repair-add-btn" @click="addRepair" /> <image src="/static/ic_my_repair_02.png" class="repair-add-btn" @click="addRepair"/>
</view> </view>
</view> </view>
@@ -30,11 +30,11 @@
{{ getStatusLabel(item.status) }} {{ getStatusLabel(item.status) }}
</view> </view>
</view> </view>
<image class="repair-line-image" src="/static/ic_my_repair_03.png" /> <image class="repair-line-image" src="/static/ic_my_repair_03.png"/>
<view class="repair-info">建立时间{{ item.createTime }}</view> <view class="repair-info">建立时间{{ item.createTime }}</view>
<view class="repair-info">报事内容{{ item.typeName }}</view> <view class="repair-info">报事内容{{ item.typeName }}</view>
<view class="repair-info">报事位置{{ item.location }}</view> <view class="repair-info">报事位置{{ item.location }}</view>
<view v-if="getStatusLabel(item.status) === '已结束'" class="repair-eval-btn eval-btn-right">服务评价</view> <view v-if="getStatusLabel(item.status) === '已结束'&&item.serviceEvalua===null" class="repair-eval-btn eval-btn-right" @click.stop="goTEvaluate(item)">服务评价</view>
</view> </view>
<!-- 加载提示 --> <!-- 加载提示 -->
@@ -47,7 +47,7 @@
<!-- 悬浮新增按钮 --> <!-- 悬浮新增按钮 -->
<image src="/static/ic_my_repair_02.png" :class="['repair-add-btn-fixed', { 'hide': isAddBtnHidden }]" <image src="/static/ic_my_repair_02.png" :class="['repair-add-btn-fixed', { 'hide': isAddBtnHidden }]"
@click="addRepair" /> @click="addRepair"/>
</view> </view>
</scroll-view> </scroll-view>
@@ -55,7 +55,7 @@
<view v-if="showDetailDialog" class="repair-detail-mask" @click.self="closeDetail"> <view v-if="showDetailDialog" class="repair-detail-mask" @click.self="closeDetail">
<view class="repair-detail-dialog"> <view class="repair-detail-dialog">
<view class="repair-detail-title">报事详情 <view class="repair-detail-title">报事详情
<image src="/static/ic_close_01.png" class="repair-detail-close" @click.stop="closeDetail" /> <image src="/static/ic_close_01.png" class="repair-detail-close" @click.stop="closeDetail"/>
</view> </view>
<view class="repair-detail-progress-box"> <view class="repair-detail-progress-box">
<view class="repair-detail-progress"> <view class="repair-detail-progress">
@@ -74,15 +74,13 @@
<view class="repair-detail-info">建立时间{{ detailItem.createTime }}</view> <view class="repair-detail-info">建立时间{{ detailItem.createTime }}</view>
<view class="repair-detail-info">报事内容{{ detailItem.typeName }}</view> <view class="repair-detail-info">报事内容{{ detailItem.typeName }}</view>
<view class="repair-detail-info">报事位置{{ detailItem.location }}</view> <view class="repair-detail-info">报事位置{{ detailItem.location }}</view>
<button v-if="getStatusLabel(detailItem.status) === '已结束'" class="repair-detail-btn"
@click="goTEvaluate">评价服务</button>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
records: [], records: [],
@@ -130,13 +128,12 @@
this.loading = true; this.loading = true;
let params = { let params = {
type: "1952989217332658178",
pageNum: this.pageNum, pageNum: this.pageNum,
pageSize: this.pageSize pageSize: this.pageSize
}; };
let res = await this.$u.api.getOrderList(params); let res = await this.$u.api.repair.getMyOrderList(params);
if (res.code == '200') { if (res.code == 200) {
const rows = res.rows || []; const rows = res.data || [];
if (reset) { if (reset) {
this.records = rows; this.records = rows;
} else { } else {
@@ -208,8 +205,8 @@
}; };
return statusMap[status] || ''; return statusMap[status] || '';
}, },
goTEvaluate() { goTEvaluate(item) {
const detailItemStr = encodeURIComponent(JSON.stringify(this.detailItem)); const detailItemStr = item.id;
uni.navigateTo({ uni.navigateTo({
url: `/pages/sys/user/myRepair/repairEvaluate?detailItem=${detailItemStr}` url: `/pages/sys/user/myRepair/repairEvaluate?detailItem=${detailItemStr}`
}); });
@@ -225,62 +222,71 @@
this.lastScrollTop = scrollTop; this.lastScrollTop = scrollTop;
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.repair-container { .repair-container {
height: 100vh; height: 100vh;
background: #f7f7f7; background: #f7f7f7;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.repair-scroll-content {
.repair-scroll-content {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
padding-bottom: 40rpx; padding-bottom: 40rpx;
} }
.repair-empty-box {
.repair-empty-box {
margin: 48rpx 24rpx 0 24rpx; margin: 48rpx 24rpx 0 24rpx;
position: relative; position: relative;
} }
.repair-empty-img-box {
.repair-empty-img-box {
width: 100%; width: 100%;
height: 500rpx; height: 500rpx;
display: flex; display: flex;
} }
.repair-empty-img {
.repair-empty-img {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: contain; object-fit: contain;
margin: 24rpx auto; margin: 24rpx auto;
} }
.repair-add-btn-box {
.repair-add-btn-box {
position: absolute; position: absolute;
top: 500rpx; top: 500rpx;
right: -20rpx; right: -20rpx;
bottom: -40rpx; bottom: -40rpx;
} }
.repair-add-btn {
.repair-add-btn {
width: 100rpx; width: 100rpx;
height: 100rpx; height: 100rpx;
border-radius: 50%; border-radius: 50%;
background: #fff; background: #fff;
} }
.repair-list-box {
.repair-list-box {
margin: 32rpx 0 0 0; margin: 32rpx 0 0 0;
padding: 0 24rpx; padding: 0 24rpx;
position: relative; position: relative;
} }
.repair-card {
.repair-card {
background: #fff; background: #fff;
border-radius: 12rpx; border-radius: 12rpx;
margin-bottom: 24rpx; margin-bottom: 24rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03); box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
padding-top: 25rpx; padding-top: 25rpx;
padding-bottom: 32rpx; padding-bottom: 32rpx;
} }
.repair-row {
.repair-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -288,32 +294,46 @@
margin-top: 25rpx; margin-top: 25rpx;
margin-left: 19rpx; margin-left: 19rpx;
margin-right: 50rpx; margin-right: 50rpx;
} }
.repair-no {
.repair-no {
font-size: 24rpx; font-size: 24rpx;
color: #0B0B0B; color: #0B0B0B;
font-weight: 500; font-weight: 500;
} }
.repair-status {
.repair-status {
font-size: 24rpx; font-size: 24rpx;
font-weight: 500; font-weight: 500;
} }
.repair-status.orange { color: #F3AB44; }
.repair-status.doing { color: #00C9AA; } .repair-status.orange {
.repair-status.done { color: #8A8A8A; } color: #F3AB44;
.repair-line-image { }
.repair-status.doing {
color: #00C9AA;
}
.repair-status.done {
color: #8A8A8A;
}
.repair-line-image {
margin-left: 29rpx; margin-left: 29rpx;
margin-right: 39rpx; margin-right: 39rpx;
height: 2rpx; height: 2rpx;
margin-bottom: 29rpx; margin-bottom: 29rpx;
} }
.repair-info {
.repair-info {
font-size: 24rpx; font-size: 24rpx;
color: #888; color: #888;
margin-bottom: 30rpx; margin-bottom: 30rpx;
margin-left: 47rpx; margin-left: 47rpx;
} }
.repair-eval-btn {
.repair-eval-btn {
margin-top: -20rpx; margin-top: -20rpx;
margin-bottom: 0; margin-bottom: 0;
margin-left: auto; margin-left: auto;
@@ -331,8 +351,9 @@
background: #fff; background: #fff;
font-weight: 500; font-weight: 500;
width: fit-content; width: fit-content;
} }
.repair-add-btn-fixed {
.repair-add-btn-fixed {
position: fixed; position: fixed;
right: 5rpx; right: 5rpx;
bottom: 80rpx; bottom: 80rpx;
@@ -342,9 +363,13 @@
transition: transform 0.3s ease; transition: transform 0.3s ease;
top: 50%; top: 50%;
transform: translateX(0); transform: translateX(0);
} }
.repair-add-btn-fixed.hide { transform: translateX(200%); }
.repair-detail-mask { .repair-add-btn-fixed.hide {
transform: translateX(200%);
}
.repair-detail-mask {
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
@@ -355,30 +380,34 @@
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
justify-content: center; justify-content: center;
} }
.repair-detail-dialog {
.repair-detail-dialog {
width: 100vw; width: 100vw;
background: #fff; background: #fff;
border-radius: 18rpx 18rpx 0 0; border-radius: 18rpx 18rpx 0 0;
box-shadow: 0 -2rpx 24rpx rgba(0, 0, 0, 0.10); box-shadow: 0 -2rpx 24rpx rgba(0, 0, 0, 0.10);
padding: 52rpx 56rpx 69rpx 56rpx; padding: 52rpx 56rpx 69rpx 56rpx;
margin-bottom: 0; margin-bottom: 0;
} }
.repair-detail-title {
.repair-detail-title {
font-size: 36rpx; font-size: 36rpx;
color: #000; color: #000;
text-align: center; text-align: center;
position: relative; position: relative;
margin-bottom: 48rpx; margin-bottom: 48rpx;
} }
.repair-detail-close {
.repair-detail-close {
width: 32rpx; width: 32rpx;
height: 32rpx; height: 32rpx;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
} }
.repair-detail-progress-box {
.repair-detail-progress-box {
height: 107rpx; height: 107rpx;
margin-bottom: 41rpx; margin-bottom: 41rpx;
background: #F7F7F7; background: #F7F7F7;
@@ -387,22 +416,25 @@
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: stretch; align-items: stretch;
} }
.repair-detail-progress {
.repair-detail-progress {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-bottom: 5rpx; margin-bottom: 5rpx;
margin-left: 75rpx; margin-left: 75rpx;
width: 100%; width: 100%;
} }
.repair-detail-step {
.repair-detail-step {
display: flex; display: flex;
align-items: center; align-items: center;
flex: 1; flex: 1;
position: relative; position: relative;
} }
.repair-detail-dot {
.repair-detail-dot {
width: 22rpx; width: 22rpx;
height: 22rpx; height: 22rpx;
border-radius: 50%; border-radius: 50%;
@@ -410,45 +442,55 @@
border: 2rpx solid #BDBDBD; border: 2rpx solid #BDBDBD;
position: relative; position: relative;
z-index: 2; z-index: 2;
} }
.repair-detail-dot.active {
.repair-detail-dot.active {
background: #2186FF; background: #2186FF;
border-color: #2186FF; border-color: #2186FF;
} }
.repair-detail-dot.current {
.repair-detail-dot.current {
background: #EF8D00; background: #EF8D00;
border-color: #EF8D00; border-color: #EF8D00;
} }
.repair-detail-line {
.repair-detail-line {
flex: 1; flex: 1;
height: 4rpx; height: 4rpx;
background: #BDBDBD; background: #BDBDBD;
margin: 0 2rpx; margin: 0 2rpx;
z-index: 1; z-index: 1;
} }
.repair-detail-line.active { background: #2186FF; }
.repair-detail-progress-labels { .repair-detail-line.active {
background: #2186FF;
}
.repair-detail-progress-labels {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-left: 0; margin-left: 0;
width: 100%; width: 100%;
} }
.repair-detail-label {
.repair-detail-label {
font-size: 22rpx; font-size: 22rpx;
color: #888; color: #888;
text-align: center; text-align: center;
flex: 1; flex: 1;
position: relative; position: relative;
top: 8rpx; top: 8rpx;
} }
.repair-detail-info {
.repair-detail-info {
font-size: 26rpx; font-size: 26rpx;
color: #222; color: #222;
margin-bottom: 30rpx; margin-bottom: 30rpx;
} }
.repair-detail-btn {
.repair-detail-btn {
width: 445rpx; width: 445rpx;
height: 73rpx; height: 83rpx;
background: linear-gradient(90deg, #005DE9 0%, #4B9BFF 100%); background: linear-gradient(90deg, #005DE9 0%, #4B9BFF 100%);
color: #fff; color: #fff;
font-size: 32rpx; font-size: 32rpx;
@@ -456,11 +498,14 @@
border-radius: 30rpx; border-radius: 30rpx;
margin-top: 100rpx; margin-top: 100rpx;
font-weight: 600; font-weight: 600;
} z-index: 10; /* 确保在最上层 */
/* 让服务评价按钮靠右 */ position: relative; /* 需要设置position才能使用z-index */
.eval-btn-right { }
/* 让服务评价按钮靠右 */
.eval-btn-right {
margin-left: auto; margin-left: auto;
display: block; display: block;
width: fit-content; width: fit-content;
} }
</style> </style>

View File

@@ -8,7 +8,7 @@
<view class="evaluate-stars"> <view class="evaluate-stars">
<image v-for="i in 5" :key="i" <image v-for="i in 5" :key="i"
:src="detailItem.serviceEvalua >= i ? '/static/ic_evaluate_select.png' : '/static/ic_evaluate_disselect.png'" :src="detailItem.serviceEvalua >= i ? '/static/ic_evaluate_select.png' : '/static/ic_evaluate_disselect.png'"
class="evaluate-star" @click="detailItem.serviceEvalua = i" /> class="evaluate-star" @click.stop="setRating(i)" />
</view> </view>
</view> </view>
</view> </view>
@@ -41,20 +41,27 @@
return { return {
comment: '', comment: '',
selectedImages: [], // 存储已选图片 selectedImages: [], // 存储已选图片
detailItem: null // 接收传递的详情项 detailItem: {} // 接收传递的详情项
}
},
onLoad(options) {
// 接收传递的detailItem参数
if (options.detailItem) {
try {
this.detailItem.id = options.detailItem;
} catch (e) {
console.error('解析detailItem参数失败', e);
}
} }
}, },
// onLoad(options) {
// // 接收传递的detailItem参数
// if (options.detailItem) {
// try {
// this.detailItem = JSON.parse(decodeURIComponent(options.detailItem));
// } catch (e) {
// console.error('解析detailItem参数失败', e);
// }
// }
// },
methods: { methods: {
setRating(score) {
if (!this.detailItem) {
this.detailItem = {};
}
this.$set(this.detailItem, 'serviceEvalua', score);
console.log('当前评分:', score);
},
// 删除图片 // 删除图片
deletePic(event) { deletePic(event) {
this.selectedImages.splice(event.index, 1); this.selectedImages.splice(event.index, 1);
@@ -73,7 +80,7 @@
vm: this // 关键:用于注入 token 等 vm: this // 关键:用于注入 token 等
}); });
if (result.code == '200') { if (result.code == 200) {
// 遍历result获取data.url加上,分割 // 遍历result获取data.url加上,分割
const urls = result.map(item => item.data?.url || '').filter(url => url !== ''); const urls = result.map(item => item.data?.url || '').filter(url => url !== '');
this.detailItem.imgUrl = urls.join(','); this.detailItem.imgUrl = urls.join(',');
@@ -82,7 +89,8 @@
}, },
async realSubmit() { async realSubmit() {
let res = await this.$u.api.updateOrder(this.detailItem); console.log(this.detailItem);
let res = await this.$u.api.repair.updateOrder(this.detailItem);
if (res.code == '200') { if (res.code == '200') {
// 关闭页面前发送事件通知前页面刷新 // 关闭页面前发送事件通知前页面刷新
uni.$emit('refreshData', ''); uni.$emit('refreshData', '');

View File

@@ -6,34 +6,30 @@
<!-- 访客信息 --> <!-- 访客信息 -->
<view class="info"> <view class="info">
<view class="cv-section-title">访客信息</view> <view class="cv-section-title">访客信息</view>
<!-- <view class="cv-avatar-upload" @click="chooseAvatar">-->
<!-- <view v-if="!header" class="cv-avatar-placeholder">上传正脸照</view>-->
<!-- <image v-else :src="header" class="cv-avatar-img" />-->
<!-- </view>-->
<!-- <input class="cv-input-name" placeholder="请输入姓名" v-model="form.visitorName" />-->
<!-- <input class="cv-input-phone" placeholder="请输入来访人电话" v-model="form.visitorPhone" />-->
<!-- <input class="cv-input" placeholder="请输入来访人身份证/军官证" v-model="form.idCard" />-->
<view class="cv-section-tag">姓名</view> <view class="cv-section-tag">姓名</view>
<input class="cv-input" placeholder="请输入姓名" v-model="form.visitorName" /> <input class="cv-input" placeholder="请输入姓名" v-model="form.visitorName"/>
<view class="cv-section-tag">电话</view> <view class="cv-section-tag">电话</view>
<input class="cv-input" placeholder="请输入联系电话" v-model="form.visitorPhone" /> <input class="cv-input" placeholder="请输入联系电话" v-model="form.visitorPhone"/>
<view class="cv-section-tag">所属公司</view>
<input class="cv-input" placeholder="请输入所属公司" v-model="form.visitorUnit"/>
</view> </view>
<!-- 选择来访目的 --> <!-- 选择来访目的 -->
<view class="cv-section"> <view class="cv-section">
<view class="cv-section-title">来访目的</view> <view class="cv-section-title">来访目的</view>
<view class="cv-form-group"> <view class="cv-form-group">
<view class="cv-select"> <view class="cv-select">
<view class="cv-select-header" @click="togglePurposeDropdown" :class="{'dropdown-open': purposeDropdownOpen}"> <view class="cv-select-header" @click="togglePurposeDropdown"
<span>{{ form.visitingReason || '请选择来访目的' }}</span> :class="{'dropdown-open': purposeDropdownOpen}">
<span>{{ getReasonLabel(form.visitingReason) || '请选择拜访事由' }}</span>
<view class="cv-select-arrow" :class="{open: purposeDropdownOpen}"></view> <view class="cv-select-arrow" :class="{open: purposeDropdownOpen}"></view>
</view> </view>
<view class="cv-select-options" :class="{open: purposeDropdownOpen}"> <view class="cv-select-options" :class="{open: purposeDropdownOpen}">
<view v-for="(purpose, index) in purposes" <view v-for="(purpose, dictValue) in purposes"
:key="index" :key="dictValue"
class="cv-option" class="cv-option"
:class="{selected: form.visitingReason === purpose}" :class="{selected: form.visitingReason === purpose}"
@click="selectPurpose(purpose)"> @click="selectPurpose(purpose)">
{{ purpose }} {{ purpose.dictLabel }}
</view> </view>
</view> </view>
</view> </view>
@@ -43,33 +39,12 @@
<view class="cv-section"> <view class="cv-section">
<view class="cv-section-title">来访时间</view> <view class="cv-section-title">来访时间</view>
<view class="datetime-row"> <view class="datetime-row">
<uni-datetime-picker class="datetime-picker" type="datetime" hide-second="true" v-model="startTime" @change="changeLog" /> <uni-datetime-picker class="datetime-picker" type="datetime" :hide-second="true" v-model="form.visitingBeginTime"/>
<view class="separator-line"></view> <view class="separator-line"></view>
<uni-datetime-picker class="datetime-picker" type="datetime" hide-second="true" v-model="endTime" @change="changeLog" /> <uni-datetime-picker class="datetime-picker" type="datetime" :hide-second="true" v-model="form.visitingEndTime"/>
</view> </view>
</view> </view>
<!-- 是否预约车位 -->
<!-- <view class="cv-section">-->
<!-- <view class="cv-parking-row">-->
<!-- <view class="cv-section-title">是否预约车位</view>-->
<!-- <view class="cv-radio-label" @click="form.bookingParkingSpace = true">-->
<!-- <view :class="['cv-radio-custom', {checked: form.bookingParkingSpace === true}]" />-->
<!-- <text></text>-->
<!-- </view>-->
<!-- <view class="cv-radio-label" @click="form.bookingParkingSpace = false">-->
<!-- <view :class="['cv-radio-custom', {checked: form.bookingParkingSpace === false}]" />-->
<!-- <text></text>-->
<!-- </view>-->
<!-- <text class="cv-parking-count">-->
<!-- <text class="cv-parking-num">50</text><text class="cv-parking-total">/100</text>-->
<!-- </text>-->
<!-- </view>-->
<!-- <view class="cv-room-select" @click="chooseCarNumber">-->
<!-- <text>{{ form.licensePlate || '请选择车牌号' }}</text>-->
<!-- <image class="cv-arrow" src="/static/ic_right_arrow_g.png" />-->
<!-- </view>-->
<!-- </view>-->
<!-- 提交按钮 --> <!-- 提交按钮 -->
<button class="cv-submit-btn" @click="submit">提交</button> <button class="cv-submit-btn" @click="submit">提交</button>
</view> </view>
@@ -77,38 +52,28 @@
</template> </template>
<script> <script>
import MediaSelector, { export default {
MediaType
} from '@/utils/mediaSelector';
import {
uploadFiles
} from '@/common/upload.js';
export default {
data() { data() {
return { return {
header: '', header: '',
form: { form: {
visitorName: '', visitorName: '',
visitorPhone: '', visitorPhone: '',
// idCard: '',
facePictures: '',
visitingReason: '', visitingReason: '',
// room: '', visitingBeginTime: '',
visitingBeginTime: '2025-07-29', visitingEndTime: '',
bookingParkingSpace: false, interviewedPerson:"sdada",
licensePlate: '' InterviewedUnit:'dasdas',
visitorUnit:''
}, },
purposes: ['商务合作', '园区参观', '面试签到', '装修放行', '家政服务', '送货上门'], purposes: [],
times: ['今天(2025-07-04)', '明天(2025-07-04)'],
purposeDropdownOpen: false, purposeDropdownOpen: false,
single: '',
range: ['2021-02-1', '2021-3-28'],
startTime: '',
endTime: '',
start: Date.now() - 1000000000,
end: Date.now() + 1000000000
} }
}, },
onLoad() {
// 获取业务类型
this.getTypes();
},
onShow() { onShow() {
uni.$once('selectPlate', plate => { uni.$once('selectPlate', plate => {
this.form.licensePlate = plate; this.form.licensePlate = plate;
@@ -119,40 +84,27 @@
this.purposeDropdownOpen = !this.purposeDropdownOpen; this.purposeDropdownOpen = !this.purposeDropdownOpen;
}, },
selectPurpose(purpose) { selectPurpose(purpose) {
this.form.visitingReason = purpose; this.form.visitingReason = purpose.dictValue;
this.purposeDropdownOpen = false; this.purposeDropdownOpen = false;
}, },
// 新增:处理图片上传 //提交
async chooseAvatar() { async submit() {
try { let res = await this.$u.api.visitor.addVisitor(this.form);
// 调用MediaSelector选择图片最多选择3张 if (res.code == 200) {
const images = await MediaSelector.choose({ uni.navigateTo({
type: MediaType.IMAGE, url: '/pages/sys/user/myVisitor/myVisitor'
count: 1 // 根据剩余数量选择
}); });
// 将选择的图片添加到selectedImages数组
this.header = images[0].path
} catch (error) {
} }
}, },
async submit() { async getTypes() {
let images = ['']; let res = await this.$u.api.getType("reason_for_visit");
let filePath = this.header.replace('file://', ''); if (res.code == '200') {
images[0] = filePath; this.purposes = res.data;
const result = await uploadFiles({
files: images,
url: this.vuex_config.baseUrl + '/resource/oss/upload',
name: 'file',
vm: this // 关键:用于注入 token 等
});
if (result.code == '200') {
data = result.data.url
} }
},
this.form.facePictures = result.url getReasonLabel(value) {
const item = this.purposes.find(item => item.dictValue === value);
return item ? item.dictLabel : '';
}, },
chooseRoom() { chooseRoom() {
// 这里可弹出选择房间号 // 这里可弹出选择房间号
@@ -167,54 +119,56 @@
}); });
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.cv-container { .cv-container {
background: #fff; background: #fff;
height: 100vh; height: 100vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.cv-scroll-content { .cv-scroll-content {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
padding-bottom: 120rpx; padding-bottom: 120rpx;
} }
.cv-section { .cv-section {
margin: 36rpx 56rpx 0 56rpx; margin: 36rpx 56rpx 0 56rpx;
} }
.info { .info {
position: relative; position: relative;
margin: 36rpx 56rpx 0 56rpx; margin: 36rpx 56rpx 0 56rpx;
} }
.cv-section-title { .cv-section-title {
font-size: 32rpx; font-size: 32rpx;
color: #000; color: #000;
font-weight: 600; font-weight: 600;
} }
.cv-section-tag { .cv-section-tag {
font-size: 28rpx; font-size: 28rpx;
color: #000; color: #000;
font-weight: 500; font-weight: 500;
margin: 36rpx 0 16rpx 0; margin: 36rpx 0 16rpx 0;
} }
/* 下拉框样式 */ /* 下拉框样式 */
.cv-select { .cv-select {
position: relative; position: relative;
width: 100%; width: 100%;
} }
.cv-form-group {
.cv-form-group {
margin: 36rpx 0 16rpx 0; margin: 36rpx 0 16rpx 0;
} }
.cv-select-header {
.cv-select-header {
padding: 14px 16px; padding: 14px 16px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 10px; border-radius: 10px;
@@ -226,22 +180,22 @@
cursor: pointer; cursor: pointer;
z-index: 2; /* 确保选择框在下拉框上方 */ z-index: 2; /* 确保选择框在下拉框上方 */
position: relative; /* 添加定位 */ position: relative; /* 添加定位 */
} }
.cv-select-arrow { .cv-select-arrow {
width: 0; width: 0;
height: 0; height: 0;
border-left: 6px solid transparent; border-left: 6px solid transparent;
border-right: 6px solid transparent; border-right: 6px solid transparent;
border-top: 8px solid #777; border-top: 8px solid #777;
transition: transform 0.3s; transition: transform 0.3s;
} }
.cv-select-arrow.open { .cv-select-arrow.open {
transform: rotate(180deg); transform: rotate(180deg);
} }
.cv-select-options { .cv-select-options {
position: absolute; position: absolute;
top: calc(100% - 1px); top: calc(100% - 1px);
left: 0; left: 0;
@@ -258,83 +212,67 @@
/* 修复隐藏时的黑线问题 */ /* 修复隐藏时的黑线问题 */
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
} }
.cv-select-options.open { .cv-select-options.open {
max-height: 300px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
/* 显示时恢复可见性 */ /* 显示时恢复可见性 */
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
} }
.cv-option { .cv-option {
padding: 14px 16px; padding: 14px 16px;
font-size: 28rpx; font-size: 28rpx;
cursor: pointer; cursor: pointer;
transition: background 0.2s; transition: background 0.2s;
} }
.cv-option:hover { .cv-option:hover {
background: #f0f7ff; background: #f0f7ff;
} }
/* 下拉框打开时持续显示阴影 */
.cv-select-header.dropdown-open { /* 下拉框打开时持续显示阴影 */
.cv-select-header.dropdown-open {
border-color: #007cff; border-color: #007cff;
border-radius: 10px 10px 0 0; /* 打开时上圆角下直角 */ border-radius: 10px 10px 0 0; /* 打开时上圆角下直角 */
border-bottom: 1px solid #007cff; /* 添加底部边框与下拉框衔接 */ border-bottom: 1px solid #007cff; /* 添加底部边框与下拉框衔接 */
} }
.cv-option.selected { .cv-option.selected {
background: #007cff; background: #007cff;
color: white; color: white;
} }
.datetime-row {
.datetime-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
gap: 15rpx; gap: 15rpx;
margin: 36rpx 0 0 0; margin: 36rpx 0 0 0;
} }
.datetime-picker {
.datetime-picker {
flex: 1; flex: 1;
max-width: 500rpx; max-width: 500rpx;
position: relative; position: relative;
} }
::v-deep .uni-date__x-input {
::v-deep .uni-date__x-input {
font-size: 11px; font-size: 11px;
font-weight: 600; font-weight: 600;
} }
.separator-line {
.separator-line {
width: 10rpx; width: 10rpx;
height: 2px; height: 2px;
background: #bdc3c7; background: #bdc3c7;
border-radius: 1px; border-radius: 1px;
} }
.cv-inputs {
flex: 1;
display: flex;
flex-direction: column;
gap: 18rpx;
}
.cv-input-name { .cv-input {
width: 233rpx;
height: 73rpx;
background: #F7F7F7;
border-radius: 10rpx;
font-size: 24rpx;
color: #222;
padding: 0 24rpx;
margin-bottom: 29rpx;
margin-top: 23rpx;
border: none;
outline: none;
}
.cv-input-phone {
width: 363rpx;
height: 73rpx; height: 73rpx;
background: #F7F7F7; background: #F7F7F7;
border-radius: 10rpx; border-radius: 10rpx;
@@ -344,128 +282,9 @@
margin-bottom: 29rpx; margin-bottom: 29rpx;
border: none; border: none;
outline: none; outline: none;
} }
.cv-input { .cv-submit-btn {
height: 73rpx;
background: #F7F7F7;
border-radius: 10rpx;
font-size: 24rpx;
color: #222;
padding: 0 24rpx;
margin-bottom: 29rpx;
border: none;
outline: none;
}
.cv-avatar-upload {
position: absolute;
width: 163rpx;
height: 183rpx;
top: 50rpx;
right: 0rpx;
background: #F7F8FA;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: 24rpx;
}
.cv-avatar-placeholder {
color: #bbb;
font-size: 24rpx;
text-align: center;
}
.cv-avatar-img {
width: 163rpx;
height: 183rpx;
border-radius: 12rpx;
}
.cv-room-select {
width: 435rpx;
height: 73rpx;
background: #F7F7F7;
border-radius: 10rpx;
font-size: 24rpx;
color: #808080;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24rpx;
margin-top: 12rpx;
}
.cv-arrow {
width: 11rpx;
height: 21rpx;
}
.cv-parking-row {
display: flex;
align-items: center;
gap: 24rpx;
margin-bottom: 18rpx;
}
.cv-radio-label {
font-size: 24rpx;
color: #0B0B0B;
display: flex;
align-items: center;
margin-left: 30rpx;
cursor: pointer;
}
.cv-radio-label2 {
font-size: 24rpx;
color: #0B0B0B;
display: flex;
align-items: center;
margin-left: 30rpx;
cursor: pointer;
}
.cv-radio-custom {
width: 22rpx;
height: 22rpx;
border-radius: 50%;
border: 1rpx solid #007CFF;
background: #fff;
margin-right: 12rpx;
box-sizing: border-box;
transition: background 0.2s, border 0.2s;
}
.cv-radio-custom.checked {
background: #007CFF;
border: 1rpx solid #007CFF;
}
.cv-parking-count {
margin-left: 24rpx;
font-size: 24rpx;
background: #EBF5FF;
border-radius: 8rpx;
padding: 0 18rpx;
height: 54rpx;
display: flex;
align-items: center;
}
.cv-parking-num {
color: #007CFF;
}
.cv-parking-total {
color: #0B0B0B;
}
.cv-submit-btn {
width: 90vw; width: 90vw;
height: 90rpx; height: 90rpx;
background: #0090FF; background: #0090FF;
@@ -477,5 +296,5 @@
display: block; display: block;
font-weight: bold; font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18); box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
} }
</style> </style>

View File

@@ -20,7 +20,7 @@
<view v-for="(item, index) in tabData[idx]" :key="index" class="visitor-card" @click="showVisitorDetail(item)"> <view v-for="(item, index) in tabData[idx]" :key="index" class="visitor-card" @click="showVisitorDetail(item)">
<view class="card-row"> <view class="card-row">
<view class="card-type">{{ item.visitorUnit }}</view> <view class="card-type">{{ item.visitorUnit }}</view>
<view class="card-status" :class="getStatusColor(item.serveStatus)">{{ getStatusLabel(item.serveStatus) }}</view>
</view> </view>
<view class="card-info">{{ item.visitorName }} <view class="card-info">{{ item.visitorName }}
<text class="card-phone">{{ item.visitorPhone }}</text> <text class="card-phone">{{ item.visitorPhone }}</text>
@@ -32,33 +32,43 @@
</scroll-view> </scroll-view>
</view> </view>
<!-- 底部按钮 --> <!-- 底部按钮 -->
<button class="visitor-btn-fixed" @click="goCreateVisitor">访客邀约</button> <button class="visitor-btn-fixed" v-if="activeTab===1" @click="goCreateVisitor">访客邀约</button>
<view v-if="showDetail" class="visitor-detail-mask" @click.self="closeVisitorDetail"> <view v-if="showDetail" class="visitor-detail-mask" @click.self="closeVisitorDetail">
<view class="visitor-detail-dialog"> <view class="visitor-detail-dialog">
<view class="visitor-detail-title-row"> <view class="visitor-detail-title-row">
<text class="visitor-detail-title">访客详情</text> <text class="visitor-detail-title">访客详情</text>
<image src="/static/ic_close_01.png" class="visitor-detail-close" @click="closeVisitorDetail" /> <image src="/static/ic_close_01.png" class="visitor-detail-close" @click="closeVisitorDetail"/>
</view> </view>
<view class="visitor-detail-info"> <view class="visitor-detail-info">
<view>{{ detailData.visitorName }} {{ detailData.visitorPhone }}</view> <view>{{ detailData.visitorName }} {{ detailData.visitorPhone }}</view>
<view v-if="detailData.idCard">{{ detailData.idCard}}</view> <view v-if="detailData.idCard">{{ detailData.idCard }}</view>
<view v-if="detailData.carNumber">车牌号{{ detailData.carNumber}}</view> <view v-if="detailData.carNumber">车牌号{{ detailData.carNumber }}</view>
<view>访问目的{{ detailData.visitingReason}}</view> <view>访问目的{{ detailData.visitingReason }}</view>
<view>来访时间{{ detailData.visitingBeginTime }}</view> <view>来访时间{{ detailData.visitingBeginTime }}</view>
<view>访问地址{{ detailData.visitorUnit}}</view> <view>访问地址{{ detailData.visitorUnit }}</view>
<image <view class="visitor-detail-qrCode" @click="showQRCode">查看二维码</view>
:src="detailData.statusClass === 'orange' ? '/static/ic_my_visitor_01.png' : '/static/ic_my_visitor_02.png'" </view>
class="visitor-detail-status-img" /> <!-- 二维码弹窗 -->
<view v-if="showQRCodeDialog" class="qr-code-mask" @click.self="closeQRCodeDialog">
<view class="qr-code-dialog">
<view class="qr-code-border">
<canvas id="qrcode" canvas-id="qrcode" style="width: 200px;height: 200px;"></canvas>
</view>
<view class="visitor-detail-qrCode" @click="closeQRCodeDialog">关闭</view>
</view>
</view> </view>
<!-- <button class="visitor-detail-btn">修改</button>-->
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { // 引入二维码生成库
import uQRCode from 'uqrcodejs';
export default {
data() { data() {
return { return {
tabs: ['我的预约', '我的邀约'], tabs: ['我的预约', '我的邀约'],
@@ -71,6 +81,8 @@
loading: false, loading: false,
showDetail: false, showDetail: false,
detailData: {}, detailData: {},
showQRCodeDialog: false,
qrCodeImage: '/static/qr-code-placeholder.png' // 替换为实际的二维码图片路径
} }
}, },
computed: { computed: {
@@ -90,7 +102,16 @@
url: '/pages/sys/user/myVisitor/creatVisitor' url: '/pages/sys/user/myVisitor/creatVisitor'
}); });
}, },
showQRCode() {
this.showQRCodeDialog = true;
this.$nextTick(() => {
this.makeQRCode();
});
},
closeQRCodeDialog() {
this.showQRCodeDialog = false;
},
async changeTab(idx) { async changeTab(idx) {
this.activeTab = idx; this.activeTab = idx;
// 移除切换标签时的加载逻辑,避免重复调用接口 // 移除切换标签时的加载逻辑,避免重复调用接口
@@ -100,34 +121,61 @@
} }
*/ */
}, },
makeQRCode() {
console.log(this.detailData.id)
let params = {}
params = {
"id": this.detailData.id
}
// 设置二维码内容
this.$u.api.visitor.qrCodeVisitor(params).then(res => {
if (res.code == 200) {
// 获取uQRCode实例
var qr = new uQRCode();
//获取二维码数据
qr.data = res.data
// 设置二维码大小单位px
qr.size = 200;
// 调用制作二维码方法
qr.make();
// 获取canvas上下文
var canvasContext = uni.createCanvasContext('qrcode', this); // 如果是组件this必须传入
// 设置uQRCode实例的canvas上下文
qr.canvasContext = canvasContext;
// 调用绘制方法将二维码图案绘制到canvas上
qr.drawCanvas();
}
}).catch(err => {
console.log(err);
uni.showToast({
title: "二维码获取失败",
icon: "none",
})
})
},
async loadTabData(idx) { async loadTabData(idx) {
this.loading = true; this.loading = true;
// 模拟接口请求不同tab返回不同mock数据 // 模拟接口请求不同tab返回不同mock数据
let params = {} let params = {}
if (idx === 0) {
params = { params = {
"interviewedPerson": this.vuex_user.userId "type": idx
}
} }
let data = []; let data = [];
let res = await this.$u.api.visitor.getMyVisitor(params);
let res = await this.$u.api.getMyVisitor(params); if (res.code == 200) {
if (res.code == '200') { data = res.data
data = res.rows
} }
this.$set(this.tabData, idx, data); this.$set(this.tabData, idx, data);
this.$set(this.tabLoaded, idx, true); this.$set(this.tabLoaded, idx, true);
this.loading = false; this.loading = false;
}, },
async loadAllTabsData() {
for (let i = 0; i < this.tabs.length; i++) {
if (!this.tabLoaded[i]) {
await this.loadTabData(i);
}
}
},
showVisitorDetail(item) { showVisitorDetail(item) {
this.detailData = item; this.detailData = item;
this.showDetail = true; this.showDetail = true;
@@ -145,7 +193,7 @@
}; };
return statusMap[status] || ''; return statusMap[status] || '';
}, },
getStatusColor(status){ getStatusColor(status) {
const statusMap = { const statusMap = {
0: '待确认', 0: '待确认',
1: 'orange', 1: 'orange',
@@ -158,29 +206,29 @@
// 添加预加载所有标签页数据的方法 // 添加预加载所有标签页数据的方法
async loadAllTabsData() { async loadAllTabsData() {
// 并行加载所有标签页数据,提高加载速度 // 并行加载所有标签页数据,提高加载速度
const loadPromises = [0, 1, 2].map((index) => { const loadPromises = [0, 1].map((index) => {
return this.loadTabData(index); return this.loadTabData(index);
}); });
await Promise.all(loadPromises); await Promise.all(loadPromises);
console.log()
// 标记所有标签页已加载 // 标记所有标签页已加载
this.tabLoaded = [true, true, true]; this.tabLoaded = [true, true, true];
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.visitor-container { .visitor-container {
height: 100vh; height: 100vh;
background: #f7f7f7; background: #f7f7f7;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
} }
.visitor-tabs { .visitor-tabs {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
@@ -189,18 +237,18 @@
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
flex-shrink: 0; flex-shrink: 0;
/* 防止被压缩 */ /* 防止被压缩 */
} }
.visitor-list-container { .visitor-list-container {
flex: 1; flex: 1;
position: relative; position: relative;
margin: 25rpx 0 0 0; margin: 25rpx 0 0 0;
padding: 0 35rpx; padding: 0 35rpx;
padding-bottom: 200rpx; padding-bottom: 200rpx;
/* 为底部按钮留出空间 */ /* 为底部按钮留出空间 */
} }
.visitor-tab { .visitor-tab {
flex: 1; flex: 1;
text-align: center; text-align: center;
font-size: 30rpx; font-size: 30rpx;
@@ -210,23 +258,23 @@
padding: 0 0 10rpx 0; padding: 0 0 10rpx 0;
/* tab点击事件 */ /* tab点击事件 */
cursor: pointer; cursor: pointer;
} }
.visitor-tab.active { .visitor-tab.active {
color: #2186FF; color: #2186FF;
font-weight: bold; font-weight: bold;
} }
.tab-underline { .tab-underline {
width: 60rpx; width: 60rpx;
height: 6rpx; height: 6rpx;
background: #2186FF; background: #2186FF;
border-radius: 3rpx; border-radius: 3rpx;
margin: 0 auto; margin: 0 auto;
margin-top: 8rpx; margin-top: 8rpx;
} }
.visitor-list { .visitor-list {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@@ -238,24 +286,24 @@
/* 为底部按钮留出空间 */ /* 为底部按钮留出空间 */
height: calc(100vh - 80rpx - 32rpx - 80rpx); /* 减去顶部tab区域和底部按钮高度 */ height: calc(100vh - 80rpx - 32rpx - 80rpx); /* 减去顶部tab区域和底部按钮高度 */
box-sizing: border-box; box-sizing: border-box;
} }
.visitor-card { .visitor-card {
background: #fff; background: #fff;
border-radius: 16rpx; border-radius: 16rpx;
margin-bottom: 24rpx; margin-bottom: 24rpx;
padding: 20rpx 40rpx 70rpx 12rpx; padding: 20rpx 40rpx 70rpx 12rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03); box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
} }
.card-row { .card-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-bottom: 28rpx; margin-bottom: 28rpx;
} }
.card-type { .card-type {
font-weight: 600; font-weight: 600;
font-size: 26rpx; font-size: 26rpx;
padding: 10rpx 45rpx 10rpx 12rpx; padding: 10rpx 45rpx 10rpx 12rpx;
@@ -263,38 +311,38 @@
color: #fff; color: #fff;
background: linear-gradient(90deg, #007CFF 0%, #FFFFFF 100%); background: linear-gradient(90deg, #007CFF 0%, #FFFFFF 100%);
display: inline-block; display: inline-block;
} }
.card-status { .card-status {
font-size: 28rpx; font-size: 28rpx;
} }
.card-status.orange { .card-status.orange {
color: #F3831F; color: #F3831F;
} }
.card-status.green { .card-status.green {
color: #07C78E; color: #07C78E;
} }
.card-status.gray { .card-status.gray {
color: #8F8F8F; color: #8F8F8F;
} }
.card-info { .card-info {
font-size: 26rpx; font-size: 26rpx;
color: #333; color: #333;
margin-bottom: 8rpx; margin-bottom: 8rpx;
margin-left: 8rpx; margin-left: 8rpx;
display: flex; display: flex;
align-items: center; align-items: center;
} }
.card-phone { .card-phone {
margin: 0 8rpx 0 8rpx; margin: 0 8rpx 0 8rpx;
} }
.card-divider { .card-divider {
width: 1rpx; width: 1rpx;
height: 40rpx; height: 40rpx;
background: #DCDCDC; background: #DCDCDC;
@@ -302,19 +350,19 @@
margin: 0 12rpx; margin: 0 12rpx;
vertical-align: middle; vertical-align: middle;
content: ''; content: '';
} }
.card-address { .card-address {
margin-left: 0; margin-left: 0;
} }
.card-time { .card-time {
font-size: 28rpx; font-size: 28rpx;
color: #626262; color: #626262;
margin-left: 8rpx; margin-left: 8rpx;
} }
.visitor-btn { .visitor-btn {
width: 90vw; width: 90vw;
height: 80rpx; height: 80rpx;
background: #0090FF; background: #0090FF;
@@ -326,9 +374,9 @@
display: block; display: block;
font-weight: bold; font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18); box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
} }
.visitor-btn-fixed { .visitor-btn-fixed {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
@@ -345,9 +393,9 @@
font-weight: bold; font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18); box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
z-index: 99; z-index: 99;
} }
.visitor-detail-mask { .visitor-detail-mask {
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
@@ -358,9 +406,9 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.visitor-detail-dialog { .visitor-detail-dialog {
width: 80vw; width: 80vw;
background: #fff; background: #fff;
border-radius: 36rpx; border-radius: 36rpx;
@@ -370,31 +418,31 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.visitor-detail-title-row { .visitor-detail-title-row {
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: relative; position: relative;
margin-bottom: 52rpx; margin-bottom: 52rpx;
} }
.visitor-detail-title { .visitor-detail-title {
font-size: 36rpx; font-size: 36rpx;
color: #000; color: #000;
} }
.visitor-detail-close { .visitor-detail-close {
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
width: 22rpx; width: 22rpx;
height: 22rpx; height: 22rpx;
} }
.visitor-detail-info { .visitor-detail-info {
width: 100%; width: 100%;
font-size: 28rpx; font-size: 28rpx;
color: #222; color: #222;
@@ -403,29 +451,66 @@
flex-direction: column; flex-direction: column;
gap: 28rpx; gap: 28rpx;
position: relative; position: relative;
} }
.visitor-detail-status-img { .visitor-detail-qrCode {
position: absolute; text-align: center;
color: #2186FF;
font-size: 28rpx;
margin-top: 40rpx;
cursor: pointer;
}
/* 二维码弹窗样式 */
.qr-code-mask {
position: fixed;
left: 0;
top: 0;
right: 0; right: 0;
bottom: -40rpx; bottom: 0;
width: 160rpx; background: rgba(0, 0, 0, 0.7);
height: 160rpx; z-index: 99999;
z-index: 1; display: flex;
pointer-events: none; align-items: center;
} justify-content: center;
}
.visitor-detail-btn { .qr-code-dialog {
width: 320rpx; background: #fff;
height: 80rpx; border-radius: 24rpx;
background: linear-gradient(90deg, #0090FF 0%, #2E9FFF 100%); padding: 40rpx;
color: #fff; display: flex;
font-size: 32rpx; flex-direction: column;
border: none; align-items: center;
border-radius: 40rpx; }
margin-bottom: 30rpx;
display: block; .qr-code-canvas {
font-weight: bold; width: 400rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18); height: 400rpx;
} margin-bottom: 20rpx;
}
.qr-code-border{
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
box-shadow: 0px 0px 12px 1px #00BBFF inset;
background: linear-gradient(to left, #196aa8, #196aa8) left top no-repeat,
linear-gradient(to bottom, #196aa8, #196aa8) left top no-repeat,
linear-gradient(to left, #196aa8, #196aa8) right top no-repeat,
linear-gradient(to bottom, #196aa8, #196aa8) right top no-repeat,
linear-gradient(to left, #196aa8, #196aa8) left bottom no-repeat,
linear-gradient(to bottom, #196aa8, #196aa8) left bottom no-repeat,
linear-gradient(to left, #196aa8, #196aa8) right bottom no-repeat,
linear-gradient(to left, #196aa8, #196aa8) right bottom no-repeat;
background-size:
1px 12px, /* 左上角垂直部分 */
12px 1px, /* 左上角水平部分 */
1px 12px, /* 右上角垂直部分 */
12px 1px, /* 右上角水平部分 */
1px 12px, /* 左下角垂直部分 */
12px 1px, /* 左下角水平部分 */
1px 12px, /* 右下角垂直部分 */
12px 1px; /* 右下角水平部分 */
}
</style> </style>

View File

@@ -6,23 +6,23 @@
<view class="user-info"> <view class="user-info">
<view class="info-row"> <view class="info-row">
<text class="label">用户姓名</text> <text class="label">用户姓名</text>
<text class="value">{{employeeDetail.userName}}</text> <text class="value">{{ employeeDetail.userName }}</text>
</view> </view>
<view class="info-row"> <view class="info-row">
<text class="label">性别</text> <text class="label">性别</text>
<text class="value">{{employeeDetail.gender === 1? '男' : '女'}}</text> <text class="value">{{ employeeDetail.gender === 1 ? '男' : '女' }}</text>
</view> </view>
<view class="info-row"> <view class="info-row">
<text class="label">证件号</text> <text class="label">证件号</text>
<text class="value">{{employeeDetail.idCard}}</text> <text class="value">{{ employeeDetail.idCard }}</text>
</view> </view>
<view class="info-row"> <view class="info-row">
<text class="label">联系电话</text> <text class="label">联系电话</text>
<text class="value">{{employeeDetail.phone}}</text> <text class="value">{{ employeeDetail.phone }}</text>
</view> </view>
<view class="info-row"> <view class="info-row">
<text class="label">所属单位</text> <text class="label">所属单位</text>
<text class="value">{{employeeDetail.unitName}}</text> <text class="value">{{ employeeDetail.unitName }}</text>
</view> </view>
<!-- 人脸图片区域 --> <!-- 人脸图片区域 -->
@@ -41,11 +41,11 @@
<view class="user-info"> <view class="user-info">
<view class="info-row"> <view class="info-row">
<text class="label">邮箱</text> <text class="label">邮箱</text>
<text class="value">{{employeeDetail.email}}</text> <text class="value">{{ employeeDetail.email }}</text>
</view> </view>
<view class="info-row"> <view class="info-row">
<text class="label">车牌号</text> <text class="label">车牌号</text>
<text class="value">{{employeeDetail.carNumber}}</text> <text class="value">{{ employeeDetail.carNumber }}</text>
</view> </view>
</view> </view>
</view> </view>
@@ -54,7 +54,7 @@
<view class="user-info"> <view class="user-info">
<view class="info-row"> <view class="info-row">
<text class="label">入驻时间</text> <text class="label">入驻时间</text>
<text class="value">{{employeeDetail.updateTime}}</text> <text class="value">{{ employeeDetail.updateTime }}</text>
</view> </view>
<view class="info-row"> <view class="info-row">
<text class="label">在职状态</text> <text class="label">在职状态</text>
@@ -94,17 +94,7 @@ export default {
this.queryEmployee(); this.queryEmployee();
} }
}, },
// 原有方法保持不变... queryEmployee() {
handleApprove() {
console.log('approve');
},
handleReject() {
console.log('reject');
},
async submit(action) {
// 提交逻辑...
},
queryEmployee(){
this.$u.api.unit.queryEmployeeById(this.employeeDetail).then(res => { this.$u.api.unit.queryEmployeeById(this.employeeDetail).then(res => {
this.employeeDetail = res.data; this.employeeDetail = res.data;
}); });
@@ -113,15 +103,15 @@ export default {
changeStatus(newState) { changeStatus(newState) {
this.employeeDetail.state = newState; this.employeeDetail.state = newState;
}, },
saveInfo(){ saveInfo() {
console.log( this.employeeDetail); console.log(this.employeeDetail);
this.$u.api.unit.updateEmployee( this.employeeDetail).then(res => { this.$u.api.unit.updateEmployee(this.employeeDetail).then(res => {
if (res.code === 200) { if (res.code === 200) {
uni.showToast({ uni.showToast({
title: '状态更新成功', title: '状态更新成功',
icon: 'success' icon: 'success'
}); });
}else { } else {
uni.showToast({ uni.showToast({
title: '状态更新失败', title: '状态更新失败',
icon: 'none' icon: 'none'
@@ -206,6 +196,7 @@ export default {
font-size: 32rpx; font-size: 32rpx;
font-weight: 500; font-weight: 500;
} }
/* 状态选项容器 */ /* 状态选项容器 */
.status-options { .status-options {
display: flex; display: flex;

View File

@@ -83,12 +83,12 @@
icon: '/static/aaaa_bsbx.png', icon: '/static/aaaa_bsbx.png',
text: '报事报修', text: '报事报修',
url:'/pages/sys/user/myRepair/myRepair' url:'/pages/sys/user/myRepair/myRepair'
} },
// { {
// icon: 'https://picsum.photos/80/80?random=3', icon: '/static/ic_unit.png',
// text: '会议', text: '单位管理',
// url:'/pages/sys/workbench/meet/meet' url:'/pages/sys/workbench/unitManagement/unitManagement'
// }, },
// { // {
// icon: 'https://picsum.photos/80/80?random=3', // icon: 'https://picsum.photos/80/80?random=3',
// text: '添加常用' // text: '添加常用'

BIN
static/ic_unit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB