|
@@ -0,0 +1,440 @@
|
|
|
|
|
+# 手动进出场操作页面 — 实现计划
|
|
|
|
|
+
|
|
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
|
+
|
|
|
|
|
+**Goal:** 在停车管理下新增"进出场操作"页面,支持手动输入车牌/RFID 完成车辆进场和出场操作
|
|
|
|
|
+
|
|
|
|
|
+**Architecture:** 前端新增 Vue 3 组件 `entryExit.vue`,Tab 切换进场/出场模式,复用已有 `vehicle.js` API。后端仅需在 seed.go 新增菜单记录和权限映射。
|
|
|
|
|
+
|
|
|
|
|
+**Tech Stack:** Vue 3 + Element Plus + Pinia, Go 1.25 + GIN
|
|
|
|
|
+
|
|
|
|
|
+**预估文件变更:** 2 files (1 new + 1 modified)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 文件结构
|
|
|
|
|
+
|
|
|
|
|
+| 文件 | 操作 | 职责 |
|
|
|
|
|
+|------|------|------|
|
|
|
|
|
+| `frontend/src/view/parking/entryExit.vue` | 新建 | 进出场操作页面:输入查询、车辆详情、进场/出场操作 |
|
|
|
|
|
+| `internal/initialize/seed.go` | 修改 | 新增菜单记录(entryExit, ID=31) + authority_menu 映射 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### Task 1: 新增菜单和权限映射
|
|
|
|
|
+
|
|
|
|
|
+**Files:**
|
|
|
|
|
+- Modify: `internal/initialize/seed.go`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: 新增菜单记录**
|
|
|
|
|
+
|
|
|
|
|
+在 `pricing` 菜单之后插入(第 122 行之后):
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+{MenuLevel: 0, ParentId: 20, Path: "entryExit", Name: "entryExit", Hidden: false, Component: "view/parking/entryExit.vue", Sort: 5, Meta: dao.Meta{Title: "进出场操作", Icon: "switch"}},
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: 新增 authority_menu 映射**
|
|
|
|
|
+
|
|
|
|
|
+在第 173 行之后新增:
|
|
|
|
|
+
|
|
|
|
|
+```go
|
|
|
|
|
+// 进出场操作 (31) — admin + operator
|
|
|
|
|
+{MenuId: "31", AuthorityId: "618"}, {MenuId: "31", AuthorityId: "888"}, {MenuId: "31", AuthorityId: "9527"},
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 3: 编译验证**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd lc_garage && go build -o build/bin/smart-parking.exe .
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 4: 提交**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+git add internal/initialize/seed.go
|
|
|
|
|
+git commit -m "feat: 新增进出场操作菜单和权限——MenuId=31, ParentId=20"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### Task 2: 创建进出场操作页面
|
|
|
|
|
+
|
|
|
|
|
+**Files:**
|
|
|
|
|
+- Create: `frontend/src/view/parking/entryExit.vue`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: 完整文件内容(template + script + style)**
|
|
|
|
|
+
|
|
|
|
|
+```vue
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="entry-exit-page">
|
|
|
|
|
+ <!-- Tab 切换进场/出场 -->
|
|
|
|
|
+ <el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
|
|
|
|
+ <el-tab-pane label="车辆进场" name="entry" />
|
|
|
|
|
+ <el-tab-pane label="车辆出场" name="exit" />
|
|
|
|
|
+ </el-tabs>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 输入区:车牌号 + RFID -->
|
|
|
|
|
+ <el-card class="query-card">
|
|
|
|
|
+ <el-form :model="queryForm" inline>
|
|
|
|
|
+ <el-form-item label="车牌号">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="queryForm.plate_number"
|
|
|
|
|
+ placeholder="请输入车牌号"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 200px"
|
|
|
|
|
+ @keyup.enter="queryVehicle"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item label="RFID标签">
|
|
|
|
|
+ <el-input
|
|
|
|
|
+ v-model="queryForm.rfid_tag"
|
|
|
|
|
+ placeholder="请输入RFID标签"
|
|
|
|
|
+ clearable
|
|
|
|
|
+ style="width: 240px"
|
|
|
|
|
+ @keyup.enter="queryVehicle"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item>
|
|
|
|
|
+ <el-button type="primary" icon="Search" @click="queryVehicle">查询</el-button>
|
|
|
|
|
+ <el-button icon="Refresh" @click="resetForm">重置</el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 车辆详情卡片(查询后显示) -->
|
|
|
|
|
+ <el-card v-if="vehicleLoaded" class="detail-card">
|
|
|
|
|
+ <template #header>
|
|
|
|
|
+ <span class="card-title">{{ activeTab === 'entry' ? '车辆信息' : '出场信息' }}</span>
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <el-descriptions :column="3" border>
|
|
|
|
|
+ <el-descriptions-item label="车牌号">
|
|
|
|
|
+ {{ vehicleInfo.plate_number || '-' }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="RFID标签">
|
|
|
|
|
+ {{ vehicleInfo.rfid_tag || '-' }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="车辆类型">
|
|
|
|
|
+ <el-tag v-if="vehicleInfo.VehicleType" :type="vehicleInfo.VehicleType.ID === 1 ? 'warning' : 'success'">
|
|
|
|
|
+ {{ vehicleInfo.VehicleType.name }}
|
|
|
|
|
+ </el-tag>
|
|
|
|
|
+ <el-tag v-else type="warning">临时车</el-tag>
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item v-if="vehicleInfo.Owner" label="车主">
|
|
|
|
|
+ {{ vehicleInfo.Owner.owner_name }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item v-if="vehicleInfo.Owner && vehicleInfo.Owner.is_vip" label="VIP">
|
|
|
|
|
+ <el-tag type="danger">是</el-tag>
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
|
|
+ </el-descriptions>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 进场特有操作区 -->
|
|
|
|
|
+ <div v-if="activeTab === 'entry'" class="action-area">
|
|
|
|
|
+ <el-divider />
|
|
|
|
|
+ <el-form :model="entryForm" inline>
|
|
|
|
|
+ <el-form-item label="选择停车场" required>
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="entryForm.parking_lot_id"
|
|
|
|
|
+ placeholder="请选择停车场"
|
|
|
|
|
+ style="width: 260px"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="lot in parkingLotList"
|
|
|
|
|
+ :key="lot.ID"
|
|
|
|
|
+ :label="lot.lot_name"
|
|
|
|
|
+ :value="lot.ID"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="success"
|
|
|
|
|
+ icon="Check"
|
|
|
|
|
+ :loading="submitting"
|
|
|
|
|
+ @click="confirmEntry"
|
|
|
|
|
+ >
|
|
|
|
|
+ 确认进场
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 出场特有操作区 -->
|
|
|
|
|
+ <div v-if="activeTab === 'exit'" class="action-area">
|
|
|
|
|
+ <el-divider />
|
|
|
|
|
+ <p class="exit-tip">确认后系统将自动计算停车费用</p>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="danger"
|
|
|
|
|
+ icon="Check"
|
|
|
|
|
+ :loading="submitting"
|
|
|
|
|
+ @click="confirmExit"
|
|
|
|
|
+ >
|
|
|
|
|
+ 确认出场并收费
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 查询结果:未找到车辆 -->
|
|
|
|
|
+ <el-result
|
|
|
|
|
+ v-if="notFound"
|
|
|
|
|
+ icon="warning"
|
|
|
|
|
+ title="未找到车辆信息"
|
|
|
|
|
+ :sub-title="activeTab === 'entry' ? '将按临时车处理,请选择停车场后确认进场' : '该车辆未登记,请核实车牌号'"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template v-if="activeTab === 'entry'" #extra>
|
|
|
|
|
+ <el-form :model="entryForm" inline>
|
|
|
|
|
+ <el-form-item label="选择停车场" required>
|
|
|
|
|
+ <el-select
|
|
|
|
|
+ v-model="entryForm.parking_lot_id"
|
|
|
|
|
+ placeholder="请选择停车场"
|
|
|
|
|
+ style="width: 260px"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-option
|
|
|
|
|
+ v-for="lot in parkingLotList"
|
|
|
|
|
+ :key="lot.ID"
|
|
|
|
|
+ :label="lot.lot_name"
|
|
|
|
|
+ :value="lot.ID"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ <el-form-item>
|
|
|
|
|
+ <el-button
|
|
|
|
|
+ type="success"
|
|
|
|
|
+ :loading="submitting"
|
|
|
|
|
+ @click="confirmEntry"
|
|
|
|
|
+ >
|
|
|
|
|
+ 确认进场(临时车)
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-result>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, reactive, onMounted } from 'vue'
|
|
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
|
|
+import { obtainVehicleLicense, vehicleEntry, vehicleAppear } from '@/api/vehicle'
|
|
|
|
|
+import { obtainLotList } from '@/api/pullOver'
|
|
|
|
|
+
|
|
|
|
|
+// ---- 状态 ----
|
|
|
|
|
+const activeTab = ref('entry')
|
|
|
|
|
+const queryForm = reactive({ plate_number: '', rfid_tag: '' })
|
|
|
|
|
+const vehicleInfo = ref(null)
|
|
|
|
|
+const vehicleLoaded = ref(false)
|
|
|
|
|
+const notFound = ref(false)
|
|
|
|
|
+const submitting = ref(false)
|
|
|
|
|
+
|
|
|
|
|
+const entryForm = reactive({ parking_lot_id: null })
|
|
|
|
|
+const parkingLotList = ref([])
|
|
|
|
|
+
|
|
|
|
|
+// ---- 初始化:加载停车场列表 ----
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await obtainLotList({ page: 1, pageSize: 100 })
|
|
|
|
|
+ parkingLotList.value = res.data?.list || []
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('加载停车场列表失败', e)
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// ---- 查询车辆 ----
|
|
|
|
|
+async function queryVehicle() {
|
|
|
|
|
+ const plate = queryForm.plate_number.trim()
|
|
|
|
|
+ const rfid = queryForm.rfid_tag.trim()
|
|
|
|
|
+
|
|
|
|
|
+ if (!plate && !rfid) {
|
|
|
|
|
+ ElMessage.warning('请至少输入车牌号或RFID标签')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ vehicleInfo.value = null
|
|
|
|
|
+ vehicleLoaded.value = false
|
|
|
|
|
+ notFound.value = false
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await obtainVehicleLicense(plate || rfid)
|
|
|
|
|
+ if (res.code === 0 && res.data) {
|
|
|
|
|
+ vehicleInfo.value = res.data
|
|
|
|
|
+ vehicleLoaded.value = true
|
|
|
|
|
+ } else {
|
|
|
|
|
+ notFound.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ notFound.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ---- 确认进场 ----
|
|
|
|
|
+async function confirmEntry() {
|
|
|
|
|
+ if (!entryForm.parking_lot_id) {
|
|
|
|
|
+ ElMessage.warning('请选择停车场')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (submitting.value) return
|
|
|
|
|
+ submitting.value = true
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await vehicleEntry({
|
|
|
|
|
+ plate_number: queryForm.plate_number.trim(),
|
|
|
|
|
+ rfid_tag: queryForm.rfid_tag.trim(),
|
|
|
|
|
+ parking_lot_id: entryForm.parking_lot_id
|
|
|
|
|
+ })
|
|
|
|
|
+ if (res.code === 0) {
|
|
|
|
|
+ const plate = res.data?.data?.plate_number || queryForm.plate_number.trim()
|
|
|
|
|
+ ElMessage.success(`入场成功!${plate} 已进入停车场`)
|
|
|
|
|
+ resetForm()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res.msg || '入场失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ ElMessage.error(e.message || '入场失败')
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ submitting.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ---- 确认出场 ----
|
|
|
|
|
+async function confirmExit() {
|
|
|
|
|
+ const plate = vehicleInfo.value?.plate_number || queryForm.plate_number.trim()
|
|
|
|
|
+
|
|
|
|
|
+ await ElMessageBox.confirm(
|
|
|
|
|
+ `确认车辆 ${plate} 出场?`,
|
|
|
|
|
+ '确认出场',
|
|
|
|
|
+ { confirmButtonText: '确认出场', cancelButtonText: '取消', type: 'warning' }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ if (submitting.value) return
|
|
|
|
|
+ submitting.value = true
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await vehicleAppear({
|
|
|
|
|
+ plate_number: queryForm.plate_number.trim(),
|
|
|
|
|
+ rfid_tag: queryForm.rfid_tag.trim()
|
|
|
|
|
+ })
|
|
|
|
|
+ if (res.code === 0) {
|
|
|
|
|
+ const data = res.data?.data || res.data || {}
|
|
|
|
|
+ const fee = data.fee || 0
|
|
|
|
|
+ const stayTime = data.stay_time || 0
|
|
|
|
|
+ const entryTime = data.entry_time ? new Date(data.entry_time * 1000).toLocaleString('zh-CN') : '-'
|
|
|
|
|
+
|
|
|
|
|
+ ElMessage.success(
|
|
|
|
|
+ `出场成功!进场: ${entryTime} | 停留: ${formatDuration(stayTime)} | 费用: ¥${fee.toFixed(2)}`
|
|
|
|
|
+ )
|
|
|
|
|
+ resetForm()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ElMessage.error(res.msg || '出场失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ ElMessage.error(e.message || '出场失败')
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ submitting.value = false
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ---- 工具 ----
|
|
|
|
|
+function handleTabChange() {
|
|
|
|
|
+ resetForm()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function resetForm() {
|
|
|
|
|
+ queryForm.plate_number = ''
|
|
|
|
|
+ queryForm.rfid_tag = ''
|
|
|
|
|
+ vehicleInfo.value = null
|
|
|
|
|
+ vehicleLoaded.value = false
|
|
|
|
|
+ notFound.value = false
|
|
|
|
|
+ entryForm.parking_lot_id = null
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function formatDuration(minutes) {
|
|
|
|
|
+ if (!minutes && minutes !== 0) return '-'
|
|
|
|
|
+ const h = Math.floor(minutes / 60)
|
|
|
|
|
+ const m = minutes % 60
|
|
|
|
|
+ return h > 0 ? `${h}小时${m}分钟` : `${m}分钟`
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.entry-exit-page {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.query-card {
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.detail-card {
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.card-title {
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.action-area {
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.exit-tip {
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: 提交**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+git add frontend/src/view/parking/entryExit.vue
|
|
|
|
|
+git commit -m "feat: 新增手动进出场操作页面——支持车牌/RFID查询进出场"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### Task 3: 端到端验证
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 1: 启动开发模式**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd lc_garage && wails dev
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 2: 验证菜单显示**
|
|
|
|
|
+
|
|
|
|
|
+1. 登录(admin / 123456)
|
|
|
|
|
+2. 侧边栏 → 停车管理 → 确认"进出场操作"菜单出现
|
|
|
|
|
+3. 点击进入页面,确认 Tab 切换正常
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 3: 验证进场流程**
|
|
|
|
|
+
|
|
|
|
|
+1. 输入新车牌号(如"测试001")
|
|
|
|
|
+2. 点查询 → 确认显示"未找到车辆信息" + 停车场选择
|
|
|
|
|
+3. 选停车场 → 点"确认进场(临时车)"
|
|
|
|
|
+4. 确认绿色"入场成功"提示
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 4: 验证出场流程**
|
|
|
|
|
+
|
|
|
|
|
+1. 切换到"车辆出场"Tab
|
|
|
|
|
+2. 输入刚才的车牌号 → 点查询
|
|
|
|
|
+3. 确认车辆信息卡片显示
|
|
|
|
|
+4. 点"确认出场并收费" → 确认弹窗 → 确认
|
|
|
|
|
+5. 确认成功消息显示费用信息
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 5: 验证边界情况**
|
|
|
|
|
+
|
|
|
|
|
+| 场景 | 预期结果 |
|
|
|
|
|
+|------|---------|
|
|
|
|
|
+| 空输入点查询 | "请至少输入车牌号或RFID标签" |
|
|
|
|
|
+| 未选停车场点确认进场 | "请选择停车场" |
|
|
|
|
|
+| 已出场车辆再次出场 | "车辆未入场或已出场" |
|
|
|
|
|
+| 不在场车辆点出场 | "车辆未入场或已出场" |
|
|
|
|
|
+
|
|
|
|
|
+- [ ] **Step 6: 提交**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+git add -A && git commit -m "verify: 手动进出场页面端到端验证通过"
|
|
|
|
|
+```
|