|
|
|
|
|
<template>
|
|
|
|
|
|
<view class="page">
|
|
|
|
|
|
<!-- 门岗访客管理页面 -->
|
|
|
|
|
|
<view class="gate-container">
|
|
|
|
|
|
<!-- 头部导航 -->
|
|
|
|
|
|
<view class="gate-header">
|
|
|
|
|
|
<view class="gate-left">
|
|
|
|
|
|
<view class="today-visitors" @click="openList">今日访客</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="gate-right">
|
|
|
|
|
|
<view class="gate-info">
|
|
|
|
|
|
<text class="gate-name">{{ gateName }}</text>
|
|
|
|
|
|
<text class="switch-gate" @click="showGateSelector">切换</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<!-- #ifdef H5 -->
|
|
|
|
|
|
<view class="fullscreen-btn" @click="toggleFullscreen">
|
|
|
|
|
|
{{ fullscreen ? '取消全屏' : '打开全屏' }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<!-- #endif -->
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 主要内容区域 -->
|
|
|
|
|
|
<view class="gate-content">
|
|
|
|
|
|
<view class="form-container">
|
|
|
|
|
|
<!-- 拜访日期选择 -->
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">拜访日期:</text>
|
|
|
|
|
|
<u-datetime-picker
|
|
|
|
|
|
v-model="datePickerShow"
|
|
|
|
|
|
mode="range"
|
|
|
|
|
|
:start-year="2020"
|
|
|
|
|
|
:end-year="2030"
|
|
|
|
|
|
@confirm="onDateConfirm"
|
|
|
|
|
|
@cancel="datePickerShow = false">
|
|
|
|
|
|
</u-datetime-picker>
|
|
|
|
|
|
<u-input
|
|
|
|
|
|
v-model="dateRangeText"
|
|
|
|
|
|
placeholder="选择日期范围"
|
|
|
|
|
|
@click="datePickerShow = true"
|
|
|
|
|
|
readonly
|
|
|
|
|
|
class="date-input">
|
|
|
|
|
|
<u-icon name="calendar-fill" slot="suffix" color="#c0c4cc"></u-icon>
|
|
|
|
|
|
</u-input>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 核验销码输入 -->
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">核验销码:</text>
|
|
|
|
|
|
<u-input
|
|
|
|
|
|
v-model="select.code"
|
|
|
|
|
|
placeholder="请输入核销码或扫码"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
@change="onCodeChange"
|
|
|
|
|
|
class="form-input">
|
|
|
|
|
|
</u-input>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 身份证输入 -->
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">身份证件:</text>
|
|
|
|
|
|
<view class="id-input-group">
|
|
|
|
|
|
<u-input
|
|
|
|
|
|
v-model="select.idcard"
|
|
|
|
|
|
placeholder="请输入身份证"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
class="id-input">
|
|
|
|
|
|
</u-input>
|
|
|
|
|
|
<u-button type="primary" @click="getIdcard" class="id-btn">查询身份证</u-button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 查询按钮 -->
|
|
|
|
|
|
<view class="form-item query-btn-container">
|
|
|
|
|
|
<u-button type="primary" @click="getList" class="query-btn" :loading="loading">查询</u-button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 门岗人员选择弹窗 -->
|
|
|
|
|
|
<u-modal v-model="gateShow" title="请先选择门岗人员" :show-cancel-button="false" :mask-close-able="false">
|
|
|
|
|
|
<view class="gate-selector">
|
|
|
|
|
|
<u-radio-group v-model="gateAdminId" @change="onGateChange">
|
|
|
|
|
|
<u-radio
|
|
|
|
|
|
v-for="item in gateData"
|
|
|
|
|
|
:key="item.id"
|
|
|
|
|
|
:name="item.id"
|
|
|
|
|
|
class="gate-radio">
|
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
|
</u-radio>
|
|
|
|
|
|
</u-radio-group>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view slot="confirm-button">
|
|
|
|
|
|
<u-button type="primary" @click="confirmGate">确定</u-button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</u-modal>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 访客信息弹窗 -->
|
|
|
|
|
|
<u-modal v-model="visitShow" title="访客信息" width="90%" :show-cancel-button="false">
|
|
|
|
|
|
<view class="visit-info" v-if="visitData">
|
|
|
|
|
|
<view class="info-item">
|
|
|
|
|
|
<text class="info-label">姓名:</text>
|
|
|
|
|
|
<text class="info-value">{{ visitData.name }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="info-item">
|
|
|
|
|
|
<text class="info-label">状态:</text>
|
|
|
|
|
|
<text class="info-value">{{ visitData.audit_status_text }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="info-item">
|
|
|
|
|
|
<text class="info-label">被访人:</text>
|
|
|
|
|
|
<text class="info-value">{{ visitData.accept_admin ? visitData.accept_admin.name : '-' }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="info-item">
|
|
|
|
|
|
<text class="info-label">联系电话:</text>
|
|
|
|
|
|
<text class="info-value">{{ visitData.mobile }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view slot="confirm-button">
|
|
|
|
|
|
<u-button type="primary" @click="closeVisitModal">关闭</u-button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</u-modal>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 今日访客列表弹窗 -->
|
|
|
|
|
|
<u-modal v-model="listShow" title="今日访客" width="90%">
|
|
|
|
|
|
<view class="visitor-list">
|
|
|
|
|
|
<view v-if="todayVisitors.length === 0" class="empty-state">
|
|
|
|
|
|
<text>今日暂无访客</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else>
|
|
|
|
|
|
<view v-for="visitor in todayVisitors" :key="visitor.id" class="visitor-item">
|
|
|
|
|
|
<view class="visitor-name">{{ visitor.name }}</view>
|
|
|
|
|
|
<view class="visitor-status">{{ visitor.audit_status_text }}</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</u-modal>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
export default {
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
fullscreen: false,
|
|
|
|
|
|
gateShow: false,
|
|
|
|
|
|
gateAdminId: '',
|
|
|
|
|
|
gateName: '',
|
|
|
|
|
|
gateData: [],
|
|
|
|
|
|
gateUser: {},
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
datePickerShow: false,
|
|
|
|
|
|
dateRangeText: '',
|
|
|
|
|
|
select: {
|
|
|
|
|
|
page: 1,
|
|
|
|
|
|
rows: 10,
|
|
|
|
|
|
keyword: '',
|
|
|
|
|
|
audit_status: '',
|
|
|
|
|
|
start_date: '',
|
|
|
|
|
|
end_date: '',
|
|
|
|
|
|
is_export: 0,
|
|
|
|
|
|
code: '',
|
|
|
|
|
|
idcard: ''
|
|
|
|
|
|
},
|
|
|
|
|
|
visitShow: false,
|
|
|
|
|
|
visitData: null,
|
|
|
|
|
|
listShow: false,
|
|
|
|
|
|
todayVisitors: []
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
onLoad() {
|
|
|
|
|
|
this.getUserList()
|
|
|
|
|
|
this.getToday()
|
|
|
|
|
|
},
|
|
|
|
|
|
onReachBottom() {
|
|
|
|
|
|
// 上拉加载更多
|
|
|
|
|
|
},
|
|
|
|
|
|
onPullDownRefresh() {
|
|
|
|
|
|
// 下拉刷新
|
|
|
|
|
|
this.getToday()
|
|
|
|
|
|
uni.stopPullDownRefresh()
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
// 打开今日访客列表
|
|
|
|
|
|
openList() {
|
|
|
|
|
|
this.getTodayVisitors()
|
|
|
|
|
|
this.listShow = true
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 获取今日日期
|
|
|
|
|
|
getToday() {
|
|
|
|
|
|
const now = new Date()
|
|
|
|
|
|
const year = now.getFullYear()
|
|
|
|
|
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
|
|
|
|
|
const day = String(now.getDate()).padStart(2, '0')
|
|
|
|
|
|
const today = `${year}-${month}-${day}`
|
|
|
|
|
|
|
|
|
|
|
|
this.select.start_date = today
|
|
|
|
|
|
this.select.end_date = today
|
|
|
|
|
|
this.dateRangeText = `${today} 至 ${today}`
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 日期选择确认
|
|
|
|
|
|
onDateConfirm(data) {
|
|
|
|
|
|
this.select.start_date = data.startDate
|
|
|
|
|
|
this.select.end_date = data.endDate
|
|
|
|
|
|
this.dateRangeText = `${data.startDate} 至 ${data.endDate}`
|
|
|
|
|
|
this.datePickerShow = false
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 核销码变化
|
|
|
|
|
|
onCodeChange() {
|
|
|
|
|
|
if (this.select.code) {
|
|
|
|
|
|
this.getList()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 清空输入
|
|
|
|
|
|
clearInputs() {
|
|
|
|
|
|
this.select.code = ''
|
|
|
|
|
|
this.select.idcard = ''
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 查询访客信息
|
|
|
|
|
|
async getList() {
|
|
|
|
|
|
if (!this.select.code && !this.select.idcard) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '请输入核销码或身份证件',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.loading = true
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 这里需要根据实际情况替换API调用
|
|
|
|
|
|
const res = await this.apiGetList(this.select)
|
|
|
|
|
|
|
|
|
|
|
|
if (res && res.data && res.data.length > 0) {
|
|
|
|
|
|
const visitor = res.data[0]
|
|
|
|
|
|
if (visitor.audit_status == 1 || visitor.audit_status == 3) {
|
|
|
|
|
|
this.visitData = visitor
|
|
|
|
|
|
this.visitShow = true
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: visitor.audit_status_text,
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '未查询到记录',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '查询失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
this.loading = false
|
|
|
|
|
|
this.clearInputs()
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 获取门岗人员列表
|
|
|
|
|
|
async getUserList() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 从存储中获取门岗用户信息
|
|
|
|
|
|
const gateUser = uni.getStorageSync('gateUser')
|
|
|
|
|
|
if (gateUser) {
|
|
|
|
|
|
this.gateUser = gateUser
|
|
|
|
|
|
this.gateAdminId = gateUser.gateAdminId
|
|
|
|
|
|
this.gateName = gateUser.gateName
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取门岗人员列表
|
|
|
|
|
|
const res = await this.apiGetUserList()
|
|
|
|
|
|
this.gateData = res || []
|
|
|
|
|
|
|
|
|
|
|
|
if (!this.gateAdminId && this.gateData.length > 0) {
|
|
|
|
|
|
this.gateShow = true
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取门岗人员列表失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 门岗人员选择变化
|
|
|
|
|
|
onGateChange(value) {
|
|
|
|
|
|
this.gateAdminId = value
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 显示门岗选择器
|
|
|
|
|
|
showGateSelector() {
|
|
|
|
|
|
this.gateShow = true
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 确认门岗选择
|
|
|
|
|
|
confirmGate() {
|
|
|
|
|
|
if (!this.gateAdminId) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '请先选择门岗',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const selectedGate = this.gateData.find(item => item.id == this.gateAdminId)
|
|
|
|
|
|
if (selectedGate) {
|
|
|
|
|
|
this.gateName = selectedGate.name
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到存储
|
|
|
|
|
|
const gateUser = {
|
|
|
|
|
|
gateName: this.gateName,
|
|
|
|
|
|
gateAdminId: this.gateAdminId
|
|
|
|
|
|
}
|
|
|
|
|
|
uni.setStorageSync('gateUser', gateUser)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.gateShow = false
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 读取身份证
|
|
|
|
|
|
getIdcard() {
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
// H5环境下的身份证读取逻辑
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: 'https://127.0.0.1:24011/ZKIDROnline/ScanReadIdCardInfo?OP-DEV=1&CMD-URL=4&REPEAT=1&READTYPE=1',
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
header: {
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
},
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.data) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const data1 = res.data.split('"IDNumber"')
|
|
|
|
|
|
if (data1.length > 1) {
|
|
|
|
|
|
const data2 = data1[1].split(',')
|
|
|
|
|
|
const idNumber = data2[0].replace(/[^\d]/g, '')
|
|
|
|
|
|
this.select.idcard = idNumber
|
|
|
|
|
|
this.getList()
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('解析身份证信息失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (error) => {
|
|
|
|
|
|
console.error('读取身份证失败:', error)
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '读取身份证失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
|
|
|
|
|
|
// #ifndef H5
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '该功能仅支持H5环境',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 切换全屏
|
|
|
|
|
|
toggleFullscreen() {
|
|
|
|
|
|
// #ifdef H5
|
|
|
|
|
|
const element = document.documentElement
|
|
|
|
|
|
if (this.fullscreen) {
|
|
|
|
|
|
if (document.exitFullscreen) {
|
|
|
|
|
|
document.exitFullscreen()
|
|
|
|
|
|
} else if (document.webkitCancelFullScreen) {
|
|
|
|
|
|
document.webkitCancelFullScreen()
|
|
|
|
|
|
} else if (document.mozCancelFullScreen) {
|
|
|
|
|
|
document.mozCancelFullScreen()
|
|
|
|
|
|
} else if (document.msExitFullscreen) {
|
|
|
|
|
|
document.msExitFullscreen()
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (element.requestFullscreen) {
|
|
|
|
|
|
element.requestFullscreen()
|
|
|
|
|
|
} else if (element.webkitRequestFullScreen) {
|
|
|
|
|
|
element.webkitRequestFullScreen()
|
|
|
|
|
|
} else if (element.mozRequestFullScreen) {
|
|
|
|
|
|
element.mozRequestFullScreen()
|
|
|
|
|
|
} else if (element.msRequestFullscreen) {
|
|
|
|
|
|
element.msRequestFullscreen()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
this.fullscreen = !this.fullscreen
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 关闭访客信息弹窗
|
|
|
|
|
|
closeVisitModal() {
|
|
|
|
|
|
this.visitShow = false
|
|
|
|
|
|
this.visitData = null
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 获取今日访客列表
|
|
|
|
|
|
async getTodayVisitors() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 这里需要根据实际情况替换API调用
|
|
|
|
|
|
const todayParam = {
|
|
|
|
|
|
start_date: this.select.start_date,
|
|
|
|
|
|
end_date: this.select.end_date
|
|
|
|
|
|
}
|
|
|
|
|
|
const res = await this.apiGetTodayVisitors(todayParam)
|
|
|
|
|
|
this.todayVisitors = res?.data || []
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取今日访客列表失败:', error)
|
|
|
|
|
|
this.todayVisitors = []
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// API调用方法(需要根据实际情况调整)
|
|
|
|
|
|
async apiGetList(params) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: '/api/gate/list', // 替换为实际API地址
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
data: params,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
resolve(res.data)
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (error) => {
|
|
|
|
|
|
reject(error)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async apiGetUserList() {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: '/api/gate/users', // 替换为实际API地址
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
resolve(res.data)
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (error) => {
|
|
|
|
|
|
reject(error)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async apiGetTodayVisitors(params) {
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.request({
|
|
|
|
|
|
url: '/api/gate/today-visitors', // 替换为实际API地址
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
data: params,
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
resolve(res.data)
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (error) => {
|
|
|
|
|
|
reject(error)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.page {
|
|
|
|
|
|
background: linear-gradient(135deg, #e4eafa, #f1f7fa);
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 门岗容器样式 */
|
|
|
|
|
|
.gate-container {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
min-height: calc(100vh - 40rpx);
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 头部导航样式 */
|
|
|
|
|
|
.gate-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 30rpx 40rpx;
|
|
|
|
|
|
border-bottom: 2rpx solid #f0f0f0;
|
|
|
|
|
|
background: #fafafa;
|
|
|
|
|
|
|
|
|
|
|
|
/* 移动端样式 */
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
padding: 20rpx 30rpx;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.gate-left {
|
|
|
|
|
|
.today-visitors {
|
|
|
|
|
|
color: #004593;
|
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.gate-right {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 40rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.gate-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.gate-name {
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.switch-gate {
|
|
|
|
|
|
color: #004593;
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.fullscreen-btn {
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
color: #004593;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 主要内容区域 */
|
|
|
|
|
|
.gate-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 40rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
padding: 40rpx 30rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-width: 1000rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
|
max-width: 1200rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-item {
|
|
|
|
|
|
margin-bottom: 50rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
margin-bottom: 40rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-label {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
|
font-size: 40rpx;
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-input, .date-input {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.id-input-group {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.id-input {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.id-btn {
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
|
min-width: 240rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.query-btn-container {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-top: 60rpx;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
margin-top: 50rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.query-btn {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100rpx;
|
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
height: 88rpx;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
|
height: 120rpx;
|
|
|
|
|
|
font-size: 48rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 弹窗样式 */
|
|
|
|
|
|
.gate-selector {
|
|
|
|
|
|
padding: 20rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.gate-radio {
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
border: 2rpx solid #e4e7ed;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.visit-info {
|
|
|
|
|
|
padding: 20rpx 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-label {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
min-width: 120rpx;
|
|
|
|
|
|
margin-right: 20rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-value {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.visitor-list {
|
|
|
|
|
|
max-height: 60vh;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-state {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
padding: 60rpx 20rpx;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.visitor-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.visitor-name {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.visitor-status {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
padding: 8rpx 16rpx;
|
|
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* uView组件样式覆盖 */
|
|
|
|
|
|
::v-deep .u-input {
|
|
|
|
|
|
.u-input__input {
|
|
|
|
|
|
height: 88rpx !important;
|
|
|
|
|
|
font-size: 32rpx !important;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
height: 80rpx !important;
|
|
|
|
|
|
font-size: 28rpx !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
|
height: 100rpx !important;
|
|
|
|
|
|
font-size: 36rpx !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .u-button {
|
|
|
|
|
|
height: 88rpx !important;
|
|
|
|
|
|
font-size: 28rpx !important;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
height: 80rpx !important;
|
|
|
|
|
|
font-size: 26rpx !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
|
height: 100rpx !important;
|
|
|
|
|
|
font-size: 32rpx !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .u-modal {
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
.u-modal__content {
|
|
|
|
|
|
width: 90% !important;
|
|
|
|
|
|
margin-top: 15vh !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .u-radio-group {
|
|
|
|
|
|
.u-radio {
|
|
|
|
|
|
margin-bottom: 20rpx !important;
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|