|
|
|
|
@ -5,6 +5,7 @@
|
|
|
|
|
<view class="gate-header">
|
|
|
|
|
<view class="gate-left">
|
|
|
|
|
<view class="today-visitors" @click="openList">访客列表</view>
|
|
|
|
|
<view class="export-visitors" @click="exportVisitors">导出访客</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
@ -121,17 +122,17 @@
|
|
|
|
|
visitData.time ? visitData.time : ""
|
|
|
|
|
}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="info-item" v-if="visitData.visit_time_detail">
|
|
|
|
|
<view class="info-item" v-if="visitData.visit_time_detail || visitData.visit_time">
|
|
|
|
|
<text class="info-label">到访时段:</text>
|
|
|
|
|
<text class="info-value"
|
|
|
|
|
>{{ visitData.visit_time_detail.start_time }} -
|
|
|
|
|
{{ visitData.visit_time_detail.end_time }}</text
|
|
|
|
|
>{{ (visitData.visit_time_detail || visitData.visit_time).start_time }} -
|
|
|
|
|
{{ (visitData.visit_time_detail || visitData.visit_time).end_time }}</text
|
|
|
|
|
>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="info-item" v-if="visitData.visit_area_detail">
|
|
|
|
|
<view class="info-item" v-if="visitData.visit_area_detail || visitData.visit_area">
|
|
|
|
|
<text class="info-label">前往区域:</text>
|
|
|
|
|
<text class="info-value">{{
|
|
|
|
|
visitData.visit_area_detail.name
|
|
|
|
|
(visitData.visit_area_detail || visitData.visit_area).name
|
|
|
|
|
}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="info-item" v-if="visitData.reason">
|
|
|
|
|
@ -416,7 +417,7 @@
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import { openDevice, readIdCard, closeDevice } from "@/common/reader.js";
|
|
|
|
|
import { openDevice, scanReadIdCardInfo } from "@/common/reader.js";
|
|
|
|
|
export default {
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
@ -599,6 +600,7 @@ export default {
|
|
|
|
|
1: "普通访客",
|
|
|
|
|
2: "施工访客",
|
|
|
|
|
3: "物流车辆",
|
|
|
|
|
4: "VIP访客",
|
|
|
|
|
};
|
|
|
|
|
return typeMap[type] || "未知类型";
|
|
|
|
|
},
|
|
|
|
|
@ -743,12 +745,9 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
this.personNoValue = visitor.person_no;
|
|
|
|
|
this.remarkValue = visitor.remark;
|
|
|
|
|
if (
|
|
|
|
|
visitor.vehicle_images_detail &&
|
|
|
|
|
visitor.vehicle_images_detail.length > 0
|
|
|
|
|
) {
|
|
|
|
|
if (visitor.file_detail && visitor.file_detail.length > 0) {
|
|
|
|
|
let arr = [];
|
|
|
|
|
visitor.vehicle_images_detail.map((item) => {
|
|
|
|
|
visitor.file_detail.map((item) => {
|
|
|
|
|
arr.push({
|
|
|
|
|
id: item.id,
|
|
|
|
|
url: item.url,
|
|
|
|
|
@ -764,7 +763,8 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
// 核销的值
|
|
|
|
|
this.codeForm.code = visitor.code;
|
|
|
|
|
this.codeForm.type = visitor.audit_status == 1 ? 1 : 2; //(visitor.audit_status == 3 && visitor.accept_admin_sign ? 2 : 0) 离厂陪同人员签字
|
|
|
|
|
// 1(待进厂)/4(已离厂) => 进厂;3(已进厂) => 离厂
|
|
|
|
|
this.codeForm.type = visitor.audit_status == 3 ? 2 : 1;
|
|
|
|
|
|
|
|
|
|
this.visitShow = true;
|
|
|
|
|
} else {
|
|
|
|
|
@ -790,41 +790,72 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 核销
|
|
|
|
|
cancelCode() {
|
|
|
|
|
console.log(this.codeForm);
|
|
|
|
|
if (this.codeForm.type == 0) {
|
|
|
|
|
async cancelCode() {
|
|
|
|
|
if (!this.gateAdminId) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "请提醒陪同人签字",
|
|
|
|
|
title: "请先选择门岗人员",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.$u.api.visitCancel(this.codeForm).then((res) => {
|
|
|
|
|
// if (res.code == 200) {
|
|
|
|
|
// this.$successMessage(res.msg, '', 'success')
|
|
|
|
|
// }
|
|
|
|
|
console.log(res);
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "核销成功",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
const mainPersonNo = this.personNoValue ? [this.personNoValue] : [];
|
|
|
|
|
const followPersonNo = (this.visitData?.follw_people || [])
|
|
|
|
|
.map((person) => person.follw_people_person_no)
|
|
|
|
|
.filter((v) => !!v);
|
|
|
|
|
const personNoArr = [...mainPersonNo, ...followPersonNo];
|
|
|
|
|
const carNoArr = Array.isArray(this.visitData?.cars)
|
|
|
|
|
? this.visitData.cars.filter((v) => !!v)
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
const params = {
|
|
|
|
|
...this.codeForm,
|
|
|
|
|
admin_id: this.gateAdminId,
|
|
|
|
|
person_no: personNoArr,
|
|
|
|
|
car_no: carNoArr,
|
|
|
|
|
};
|
|
|
|
|
await this.$u.api.visitCancel(params);
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "核销成功",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
// 读取身份证
|
|
|
|
|
// 读取身份证(与 szbd-visitor-web gate/visitlist.vue 一致:中控在线 ScanReadIdCardInfo;入口仅 H5 模板展示)
|
|
|
|
|
getIdcard() {
|
|
|
|
|
const that = this;
|
|
|
|
|
this.select.idcard = "";
|
|
|
|
|
readIdCard().then((res) => {
|
|
|
|
|
console.log("读取身份证", res);
|
|
|
|
|
if (res.data.resultFlag == 0) {
|
|
|
|
|
this.select.idcard = res.data.certNumber;
|
|
|
|
|
this.getList();
|
|
|
|
|
} else {
|
|
|
|
|
scanReadIdCardInfo()
|
|
|
|
|
.then((res) => {
|
|
|
|
|
console.log(res);
|
|
|
|
|
console.log(res.data);
|
|
|
|
|
if (!res.data) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const raw =
|
|
|
|
|
typeof res.data === "string" ? res.data : String(res.data);
|
|
|
|
|
const data1 = raw.split('"IDNumber"');
|
|
|
|
|
if (!data1[1]) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "解析身份证数据失败",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const data2 = data1[1].split(",");
|
|
|
|
|
const data3 = data2[0].replace(/[^\d]/g, "");
|
|
|
|
|
that.select.idcard = data3;
|
|
|
|
|
that.getList();
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
console.log(err);
|
|
|
|
|
const msg =
|
|
|
|
|
(err.response && err.response.statusText) ||
|
|
|
|
|
err.message ||
|
|
|
|
|
"读取失败";
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "读取身份证失败",
|
|
|
|
|
title: msg,
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 切换全屏
|
|
|
|
|
@ -1031,16 +1062,15 @@ export default {
|
|
|
|
|
this.updating = true;
|
|
|
|
|
try {
|
|
|
|
|
const updateParams = {
|
|
|
|
|
...this.visitData,
|
|
|
|
|
id: this.visitData.id,
|
|
|
|
|
remark: this.remarkValue,
|
|
|
|
|
person_no: this.personNoValue,
|
|
|
|
|
// follw_people 中包含了每个人员的 follw_people_person_no 字段
|
|
|
|
|
follw_people: this.visitData.follw_people || [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 如果type==3,添加车辆照片数据(做空值防护)
|
|
|
|
|
if (this.visitData.type == 3) {
|
|
|
|
|
updateParams.vehicle_images = (this.vehicleImages || [])
|
|
|
|
|
updateParams.file = (this.vehicleImages || [])
|
|
|
|
|
.filter((img) => img && img.id)
|
|
|
|
|
.map((img) => img.id);
|
|
|
|
|
}
|
|
|
|
|
@ -1084,6 +1114,23 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 物流访客:每次进/离厂都必须先上传当次新照片
|
|
|
|
|
if (this.visitData.type == 3) {
|
|
|
|
|
const currentIds = (this.vehicleImages || [])
|
|
|
|
|
.filter((item) => item && item.id)
|
|
|
|
|
.map((item) => item.id);
|
|
|
|
|
const hasNewPhoto = currentIds.some(
|
|
|
|
|
(id) => !this.originalVehicleImageIds.includes(id)
|
|
|
|
|
);
|
|
|
|
|
if (!hasNewPhoto) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "物流访客每次进/离厂前必须上传当次照片",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 所有类型都弹出确认弹窗
|
|
|
|
|
const isVehicleType = this.visitData.type == 3; // 需要提交照片的类型
|
|
|
|
|
|
|
|
|
|
@ -1137,6 +1184,61 @@ export default {
|
|
|
|
|
this.todayVisitors = [];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 导出访客(不填日期即全量导出)
|
|
|
|
|
exportVisitors() {
|
|
|
|
|
const query = {
|
|
|
|
|
is_export: 1,
|
|
|
|
|
};
|
|
|
|
|
if (this.select.start_date) {
|
|
|
|
|
query.start_date = this.select.start_date;
|
|
|
|
|
}
|
|
|
|
|
if (this.select.end_date) {
|
|
|
|
|
query.end_date = this.select.end_date;
|
|
|
|
|
}
|
|
|
|
|
const queryString = Object.keys(query)
|
|
|
|
|
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
|
|
|
|
|
.join("&");
|
|
|
|
|
const url = `${this.$u.http.config.baseUrl}/api/admin/gate/visit-list?${queryString}`;
|
|
|
|
|
const token = this.$store.state.vuex_token;
|
|
|
|
|
if (!token) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "登录状态无效,请重新登录",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
uni.downloadFile({
|
|
|
|
|
url,
|
|
|
|
|
header: {
|
|
|
|
|
Authorization: `Bearer ${token}`,
|
|
|
|
|
},
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.statusCode === 200) {
|
|
|
|
|
uni.openDocument({
|
|
|
|
|
filePath: res.tempFilePath,
|
|
|
|
|
showMenu: true,
|
|
|
|
|
fail: () => {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "下载成功,请在下载列表查看",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "导出失败",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fail: () => {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "导出失败,请稍后重试",
|
|
|
|
|
icon: "none",
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
@ -1169,6 +1271,10 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.gate-left {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 32rpx;
|
|
|
|
|
|
|
|
|
|
.today-visitors {
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
@ -1183,6 +1289,21 @@ export default {
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.export-visitors {
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.gate-right {
|
|
|
|
|
@ -1421,7 +1542,7 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* #ifdef H5 */
|
|
|
|
|
/* H5下身份证输入宽度为70%,右侧显示查询入口 */
|
|
|
|
|
/* H5 下与门岗页一致:身份证输入 70%,右侧「查询身份证」30% */
|
|
|
|
|
@media all {
|
|
|
|
|
.idcard-group .form-input {
|
|
|
|
|
width: 70%;
|
|
|
|
|
|