Pārlūkot izejas kodu

Merge branch 'runData' into dev

huoyi 1 mēnesi atpakaļ
vecāks
revīzija
c132f1e6b0

+ 72 - 0
src/api/runData/collectWaitingAreaData.js

@@ -0,0 +1,72 @@
1
+import request from '@/utils/request'
2
+
3
+// 查询候检区数据列表
4
+export function listCollectWaitingAreaData(query) {
5
+  return request({
6
+    url: '/item/hkPendingConfiscate/list',
7
+    method: 'get',
8
+    params: query
9
+  })
10
+}
11
+
12
+// 查询候检区数据详细
13
+export function getCollectWaitingAreaData(id) {
14
+  return request({
15
+    url: '/item/hkPendingConfiscate/' + id,
16
+    method: 'get'
17
+  })
18
+}
19
+
20
+// 新增候检区数据
21
+export function addCollectWaitingAreaData(data) {
22
+  return request({
23
+    url: '/item/hkPendingConfiscate',
24
+    method: 'post',
25
+    data: data
26
+  })
27
+}
28
+
29
+// 修改候检区数据
30
+export function updateCollectWaitingAreaData(data) {
31
+  return request({
32
+    url: '/item/hkPendingConfiscate',
33
+    method: 'put',
34
+    data: data
35
+  })
36
+}
37
+
38
+// 删除候检区数据
39
+export function delCollectWaitingAreaData(id) {
40
+  return request({
41
+    url: '/item/hkPendingConfiscate/' + id,
42
+    method: 'delete'
43
+  })
44
+}
45
+
46
+// 导出候检区数据
47
+export function exportCollectWaitingAreaData(data) {
48
+  return request({
49
+    url: '/item/hkPendingConfiscate/export',
50
+    method: 'post',
51
+    data: data,
52
+    responseType: 'blob'
53
+  })
54
+}
55
+
56
+// 下载导入模板
57
+export function importTemplate() {
58
+  return request({
59
+    url: '/item/hkPendingConfiscate/importTemplate',
60
+    method: 'post',
61
+    responseType: 'blob'
62
+  })
63
+}
64
+
65
+// 导入候检区数据
66
+export function importCollectWaitingAreaData(data) {
67
+  return request({
68
+    url: '/item/hkPendingConfiscate/importData',
69
+    method: 'post',
70
+    data: data
71
+  })
72
+}

+ 72 - 0
src/api/runData/dailyRunData.js

@@ -0,0 +1,72 @@
1
+import request from '@/utils/request'
2
+
3
+// 查询日常运行数据列表
4
+export function listDailyRunData(query) {
5
+  return request({
6
+    url: '/item/hkOperationData/list',
7
+    method: 'get',
8
+    params: query
9
+  })
10
+}
11
+
12
+// 查询日常运行数据详细
13
+export function getDailyRunData(id) {
14
+  return request({
15
+    url: '/item/hkOperationData/' + id,
16
+    method: 'get'
17
+  })
18
+}
19
+
20
+// 新增日常运行数据
21
+export function addDailyRunData(data) {
22
+  return request({
23
+    url: '/item/hkOperationData',
24
+    method: 'post',
25
+    data: data
26
+  })
27
+}
28
+
29
+// 修改日常运行数据
30
+export function updateDailyRunData(data) {
31
+  return request({
32
+    url: '/item/hkOperationData',
33
+    method: 'put',
34
+    data: data
35
+  })
36
+}
37
+
38
+// 删除日常运行数据
39
+export function delDailyRunData(id) {
40
+  return request({
41
+    url: '/item/hkOperationData/' + id,
42
+    method: 'delete'
43
+  })
44
+}
45
+
46
+// 导出日常运行数据
47
+export function exportDailyRunData(data) {
48
+  return request({
49
+    url: '/item/hkOperationData/export',
50
+    method: 'post',
51
+    data: data,
52
+    responseType: 'blob'
53
+  })
54
+}
55
+
56
+// 下载导入模板
57
+export function importTemplate() {
58
+  return request({
59
+    url: '/item/hkOperationData/importTemplate',
60
+    method: 'post',
61
+    responseType: 'blob'
62
+  })
63
+}
64
+
65
+// 导入日常运行数据
66
+export function importDailyRunData(data) {
67
+  return request({
68
+    url: '/item/hkOperationData/importData',
69
+    method: 'post',
70
+    data: data
71
+  })
72
+}

+ 72 - 0
src/api/runData/discouragePowerBanksData.js

@@ -0,0 +1,72 @@
1
+import request from '@/utils/request'
2
+
3
+// 查询劝阻充电宝数据列表
4
+export function listDiscouragePowerBanksData(query) {
5
+  return request({
6
+    url: '/item/hkPersuadePowerBank/list',
7
+    method: 'get',
8
+    params: query
9
+  })
10
+}
11
+
12
+// 查询劝阻充电宝数据详细
13
+export function getDiscouragePowerBanksData(id) {
14
+  return request({
15
+    url: '/item/hkPersuadePowerBank/' + id,
16
+    method: 'get'
17
+  })
18
+}
19
+
20
+// 新增劝阻充电宝数据
21
+export function addDiscouragePowerBanksData(data) {
22
+  return request({
23
+    url: '/item/hkPersuadePowerBank',
24
+    method: 'post',
25
+    data: data
26
+  })
27
+}
28
+
29
+// 修改劝阻充电宝数据
30
+export function updateDiscouragePowerBanksData(data) {
31
+  return request({
32
+    url: '/item/hkPersuadePowerBank',
33
+    method: 'put',
34
+    data: data
35
+  })
36
+}
37
+
38
+// 删除劝阻充电宝数据
39
+export function delDiscouragePowerBanksData(id) {
40
+  return request({
41
+    url: '/item/hkPersuadePowerBank/' + id,
42
+    method: 'delete'
43
+  })
44
+}
45
+
46
+// 导出劝阻充电宝数据
47
+export function exportDiscouragePowerBanksData(data) {
48
+  return request({
49
+    url: '/item/hkPersuadePowerBank/export',
50
+    method: 'post',
51
+    data: data,
52
+    responseType: 'blob'
53
+  })
54
+}
55
+
56
+// 下载导入模板
57
+export function importTemplate() {
58
+  return request({
59
+    url: '/item/hkPersuadePowerBank/importTemplate',
60
+    method: 'post',
61
+    responseType: 'blob'
62
+  })
63
+}
64
+
65
+// 导入劝阻充电宝数据
66
+export function importDiscouragePowerBanksData(data) {
67
+  return request({
68
+    url: '/item/hkPersuadePowerBank/importData',
69
+    method: 'post',
70
+    data: data
71
+  })
72
+}

+ 95 - 0
src/api/runData/runScreen.js

@@ -0,0 +1,95 @@
1
+import request from '@/utils/request'
2
+
3
+// 模块一:运行数据
4
+
5
+// 运行数据汇总(5个数字卡片)
6
+export function getOperationSummary(query) {
7
+  return request({
8
+    url: '/hk/screen/operationSummary',
9
+    method: 'get',
10
+    params: query
11
+  })
12
+}
13
+
14
+// T1旅检过检人数趋势(A区/B区折线图)
15
+export function getT1PassengerTrend(query) {
16
+  return request({
17
+    url: '/hk/screen/t1PassengerTrend',
18
+    method: 'get',
19
+    params: query
20
+  })
21
+}
22
+
23
+// T2旅检过检人数趋势(国内/国际旅检折线图)
24
+export function getT2PassengerTrend(query) {
25
+  return request({
26
+    url: '/hk/screen/t2PassengerTrend',
27
+    method: 'get',
28
+    params: query
29
+  })
30
+}
31
+
32
+// 行检过检数趋势(T1/T2行检折线图)
33
+export function getLuggageCheckTrend(query) {
34
+  return request({
35
+    url: '/hk/screen/luggageCheckTrend',
36
+    method: 'get',
37
+    params: query
38
+  })
39
+}
40
+
41
+// 货物过检数趋势(国内/国际货站折线图)
42
+export function getCargoTrend(query) {
43
+  return request({
44
+    url: '/hk/screen/cargoTrend',
45
+    method: 'get',
46
+    params: query
47
+  })
48
+}
49
+
50
+// 车辆过检数趋势(南侧/北侧车检折线图)
51
+export function getVehicleCheckTrend(query) {
52
+  return request({
53
+    url: '/hk/screen/vehicleCheckTrend',
54
+    method: 'get',
55
+    params: query
56
+  })
57
+}
58
+
59
+// 模块二:查获/收缴数据
60
+
61
+// 查获数据分类(环形图)
62
+export function getSeizureCategory(query) {
63
+  return request({
64
+    url: '/hk/screen/seizureCategory',
65
+    method: 'get',
66
+    params: query
67
+  })
68
+}
69
+
70
+// 大队查获数对比(柱状图)
71
+export function getBrigadeSeizureCompare(query) {
72
+  return request({
73
+    url: '/hk/screen/brigadeSeizureCompare',
74
+    method: 'get',
75
+    params: query
76
+  })
77
+}
78
+
79
+// 不合规充电宝数据(环形图)
80
+export function getPowerBankSummary(query) {
81
+  return request({
82
+    url: '/hk/screen/powerBankSummary',
83
+    method: 'get',
84
+    params: query
85
+  })
86
+}
87
+
88
+// 待检区收缴物品数据(环形图)
89
+export function getPendingConfiscate(query) {
90
+  return request({
91
+    url: '/hk/screen/pendingConfiscate',
92
+    method: 'get',
93
+    params: query
94
+  })
95
+}

+ 72 - 0
src/api/runData/seizeData.js

@@ -0,0 +1,72 @@
1
+import request from '@/utils/request'
2
+
3
+// 查询查获数据列表
4
+export function listSeizeData(query) {
5
+  return request({
6
+    url: '/item/hkSeizureStat/list',
7
+    method: 'get',
8
+    params: query
9
+  })
10
+}
11
+
12
+// 查询查获数据详细
13
+export function getSeizeData(id) {
14
+  return request({
15
+    url: '/item/hkSeizureStat/' + id,
16
+    method: 'get'
17
+  })
18
+}
19
+
20
+// 新增查获数据
21
+export function addSeizeData(data) {
22
+  return request({
23
+    url: '/item/hkSeizureStat',
24
+    method: 'post',
25
+    data: data
26
+  })
27
+}
28
+
29
+// 修改查获数据
30
+export function updateSeizeData(data) {
31
+  return request({
32
+    url: '/item/hkSeizureStat',
33
+    method: 'put',
34
+    data: data
35
+  })
36
+}
37
+
38
+// 删除查获数据
39
+export function delSeizeData(id) {
40
+  return request({
41
+    url: '/item/hkSeizureStat/' + id,
42
+    method: 'delete'
43
+  })
44
+}
45
+
46
+// 导出查获数据
47
+export function exportSeizeData(data) {
48
+  return request({
49
+    url: '/item/hkSeizureStat/export',
50
+    method: 'post',
51
+    data: data,
52
+    responseType: 'blob'
53
+  })
54
+}
55
+
56
+// 下载导入模板
57
+export function importTemplate() {
58
+  return request({
59
+    url: '/item/hkSeizureStat/importTemplate',
60
+    method: 'post',
61
+    responseType: 'blob'
62
+  })
63
+}
64
+
65
+// 导入查获数据
66
+export function importSeizeData(data) {
67
+  return request({
68
+    url: '/item/hkSeizureStat/importData',
69
+    method: 'post',
70
+    data: data
71
+  })
72
+}

+ 477 - 0
src/views/runData/collectWaitingAreaData/index.vue

@@ -0,0 +1,477 @@
1
+<template>
2
+  <div class="app-container">
3
+    <!-- 查询条件 -->
4
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
5
+      <el-form-item label="日期" prop="recordDate">
6
+        <el-date-picker v-model="queryParams.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
7
+          style="width: 200px" />
8
+      </el-form-item>
9
+      <el-form-item label="时间段" prop="timeSlot">
10
+        <el-time-picker v-model="queryParams.timeSlot" is-range range-separator="-" start-placeholder="开始时间"
11
+          end-placeholder="结束时间" value-format="HH:mm" format="HH:mm" placeholder="请选择时间段" clearable
12
+          style="width: 200px" />
13
+      </el-form-item>
14
+      <el-form-item>
15
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
16
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
17
+      </el-form-item>
18
+    </el-form>
19
+
20
+    <!-- 按钮区域 -->
21
+    <el-row :gutter="10" class="mb8">
22
+      <el-col :span="1.5">
23
+        <el-button type="primary" plain icon="Plus" @click="handleAdd"
24
+          v-hasPermi="['runData:collectWaitingAreaData:add']">新增</el-button>
25
+      </el-col>
26
+
27
+      <el-col :span="1.5">
28
+        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
29
+          v-hasPermi="['runData:collectWaitingAreaData:remove']">删除</el-button>
30
+      </el-col>
31
+      <el-col :span="1.5">
32
+        <el-button type="info" plain icon="Upload" @click="handleImport"
33
+          v-hasPermi="['runData:collectWaitingAreaData:import']">导入</el-button>
34
+      </el-col>
35
+      <el-col :span="1.5">
36
+        <el-button type="warning" plain icon="Download" @click="handleExport"
37
+          v-hasPermi="['runData:collectWaitingAreaData:export']">导出</el-button>
38
+      </el-col>
39
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
40
+    </el-row>
41
+
42
+    <!-- 数据表格 -->
43
+    <el-table v-loading="loading" :data="collectWaitingAreaDataList" @selection-change="handleSelectionChange">
44
+      <el-table-column type="selection" width="55" align="center" />
45
+      <el-table-column label="日期" align="center" prop="recordDate" />
46
+      <el-table-column label="时间段" align="center" prop="timeSlot" />
47
+
48
+      <!-- T1区域数据 -->
49
+      <el-table-column label="T1A区火种" align="center" prop="t1AFireSource" />
50
+      <el-table-column label="T1A区液态物品" align="center" prop="t1ALiquid" />
51
+      <el-table-column label="T1A区其他物品" align="center" prop="t1AOther" />
52
+      <el-table-column label="T1B区火种" align="center" prop="t1BFireSource" />
53
+      <el-table-column label="T1B区液态物品" align="center" prop="t1BLiquid" />
54
+      <el-table-column label="T1B区其他物品" align="center" prop="t1BOther" />
55
+
56
+      <!-- T2区域数据 -->
57
+      <el-table-column label="T2国内火种" align="center" prop="t2DomesticFireSource" />
58
+      <el-table-column label="T2国内液态物品" align="center" prop="t2DomesticLiquid" />
59
+      <el-table-column label="T2国内其他物品" align="center" prop="t2DomesticOther" />
60
+      <el-table-column label="T2国际火种" align="center" prop="t2IntlFireSource" />
61
+      <el-table-column label="T2国际液态物品" align="center" prop="t2IntlLiquid" />
62
+      <el-table-column label="T2国际其他物品" align="center" prop="t2IntlOther" />
63
+      <el-table-column label="T2中转火种" align="center" prop="t2TransitFireSource" />
64
+      <el-table-column label="T2中转液态物品" align="center" prop="t2TransitLiquid" />
65
+      <el-table-column label="T2中转其他物品" align="center" prop="t2TransitOther" />
66
+
67
+      <el-table-column label="操作" width="180" align="center" class-name="small-padding fixed-width">
68
+        <template #default="scope">
69
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
70
+            v-hasPermi="['runData:collectWaitingAreaData:edit']">修改</el-button>
71
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
72
+            v-hasPermi="['runData:collectWaitingAreaData:remove']">删除</el-button>
73
+        </template>
74
+      </el-table-column>
75
+    </el-table>
76
+
77
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
78
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
79
+
80
+    <!-- 添加或修改候检区数据对话框 -->
81
+    <el-dialog :title="title" v-model="open" width="1000px" append-to-body>
82
+      <el-form ref="collectWaitingAreaDataRef" :model="form" :rules="rules" label-width="140px">
83
+        <el-row :gutter="20">
84
+          <el-col :span="12">
85
+            <el-form-item label="日期" prop="recordDate">
86
+              <el-date-picker v-model="form.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
87
+                style="width: 100%" />
88
+            </el-form-item>
89
+          </el-col>
90
+          <el-col :span="12">
91
+            <el-form-item label="时间段" prop="timeSlot">
92
+              <el-time-picker v-model="form.timeSlot" is-range range-separator="至" start-placeholder="开始时间"
93
+                end-placeholder="结束时间" value-format="HH:mm" format="HH:mm" placeholder="请选择时间段" style="width: 100%" />
94
+            </el-form-item>
95
+          </el-col>
96
+        </el-row>
97
+
98
+        <!-- T1区域 -->
99
+        <el-divider content-position="left">T1区域数据</el-divider>
100
+        <el-row :gutter="20">
101
+          <el-col :span="12">
102
+            <h4 style="margin-bottom: 15px;">T1A区</h4>
103
+            <el-form-item label="T1A区火种" prop="t1AFireSource">
104
+              <el-input-number :precision="0" v-model="form.t1AFireSource" :min="0" placeholder="请输入T1A区火种" style="width: 100%" />
105
+            </el-form-item>
106
+            <el-form-item label="T1A区液态物品" prop="t1ALiquid">
107
+              <el-input-number :precision="0" v-model="form.t1ALiquid" :min="0" placeholder="请输入T1A区液态物品" style="width: 100%" />
108
+            </el-form-item>
109
+            <el-form-item label="T1A区其他物品" prop="t1AOther">
110
+              <el-input-number :precision="0" v-model="form.t1AOther" :min="0" placeholder="请输入T1A区其他物品" style="width: 100%" />
111
+            </el-form-item>
112
+          </el-col>
113
+          <el-col :span="12">
114
+            <h4 style="margin-bottom: 15px;">T1B区</h4>
115
+            <el-form-item label="T1B区火种" prop="t1BFireSource">
116
+              <el-input-number :precision="0" v-model="form.t1BFireSource" :min="0" placeholder="请输入T1B区火种" style="width: 100%" />
117
+            </el-form-item>
118
+            <el-form-item label="T1B区液态物品" prop="t1BLiquid">
119
+              <el-input-number :precision="0" v-model="form.t1BLiquid" :min="0" placeholder="请输入T1B区液态物品" style="width: 100%" />
120
+            </el-form-item>
121
+            <el-form-item label="T1B区其他物品" prop="t1BOther">
122
+              <el-input-number :precision="0" v-model="form.t1BOther" :min="0" placeholder="请输入T1B区其他物品" style="width: 100%" />
123
+            </el-form-item>
124
+          </el-col>
125
+        </el-row>
126
+
127
+        <!-- T2区域 -->
128
+        <el-divider content-position="left">T2区域数据</el-divider>
129
+        <el-row :gutter="20">
130
+          <el-col :span="8">
131
+            <h4 style="margin-bottom: 15px;">T2国内</h4>
132
+            <el-form-item label="T2国内火种" prop="t2DomesticFireSource">
133
+              <el-input-number :precision="0" v-model="form.t2DomesticFireSource" :min="0" placeholder="请输入T2国内火种"
134
+                style="width: 100%" />
135
+            </el-form-item>
136
+            <el-form-item label="T2国内液态物品" prop="t2DomesticLiquid">
137
+              <el-input-number :precision="0" v-model="form.t2DomesticLiquid" :min="0" placeholder="请输入T2国内液态物品" style="width: 100%" />
138
+            </el-form-item>
139
+            <el-form-item label="T2国内其他物品" prop="t2DomesticOther">
140
+              <el-input-number :precision="0" v-model="form.t2DomesticOther" :min="0" placeholder="请输入T2国内其他物品" style="width: 100%" />
141
+            </el-form-item>
142
+          </el-col>
143
+          <el-col :span="8">
144
+            <h4 style="margin-bottom: 15px;">T2国际</h4>
145
+            <el-form-item label="T2国际火种" prop="t2IntlFireSource">
146
+              <el-input-number :precision="0" v-model="form.t2IntlFireSource" :min="0" placeholder="请输入T2国际火种" style="width: 100%" />
147
+            </el-form-item>
148
+            <el-form-item label="T2国际液态物品" prop="t2IntlLiquid">
149
+              <el-input-number :precision="0" v-model="form.t2IntlLiquid" :min="0" placeholder="请输入T2国际液态物品" style="width: 100%" />
150
+            </el-form-item>
151
+            <el-form-item label="T2国际其他物品" prop="t2IntlOther">
152
+              <el-input-number :precision="0" v-model="form.t2IntlOther" :min="0" placeholder="请输入T2国际其他物品" style="width: 100%" />
153
+            </el-form-item>
154
+          </el-col>
155
+          <el-col :span="8">
156
+            <h4 style="margin-bottom: 15px;">T2中转</h4>
157
+            <el-form-item label="T2中转火种" prop="t2TransitFireSource">
158
+              <el-input-number :precision="0" v-model="form.t2TransitFireSource" :min="0" placeholder="请输入T2中转火种"
159
+                style="width: 100%" />
160
+            </el-form-item>
161
+            <el-form-item label="T2中转液态物品" prop="t2TransitLiquid">
162
+              <el-input-number :precision="0" v-model="form.t2TransitLiquid" :min="0" placeholder="请输入T2中转液态物品" style="width: 100%" />
163
+            </el-form-item>
164
+            <el-form-item label="T2中转其他物品" prop="t2TransitOther">
165
+              <el-input-number :precision="0" v-model="form.t2TransitOther" :min="0" placeholder="请输入T2中转其他物品" style="width: 100%" />
166
+            </el-form-item>
167
+          </el-col>
168
+        </el-row>
169
+      </el-form>
170
+      <template #footer>
171
+        <div class="dialog-footer">
172
+          <el-button type="primary" @click="submitForm">确 定</el-button>
173
+          <el-button @click="cancel">取 消</el-button>
174
+        </div>
175
+      </template>
176
+    </el-dialog>
177
+
178
+    <!-- 导入对话框 -->
179
+    <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
180
+      <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
181
+        :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
182
+        :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
183
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
184
+        <div class="el-upload__text">
185
+          将文件拖到此处,或<em>点击上传</em>
186
+        </div>
187
+        <template #tip>
188
+          <div class="el-upload__tip">
189
+            <span>仅允许导入xls、xlsx格式文件。</span>
190
+            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
191
+              @click="importTemplate">下载模板</el-link>
192
+          </div>
193
+        </template>
194
+      </el-upload>
195
+      <template #footer>
196
+        <div class="dialog-footer">
197
+          <el-button type="primary" @click="submitFileForm">确 定</el-button>
198
+          <el-button @click="upload.open = false">取 消</el-button>
199
+        </div>
200
+      </template>
201
+    </el-dialog>
202
+  </div>
203
+</template>
204
+
205
+<script setup name="CollectWaitingAreaData">
206
+import { listCollectWaitingAreaData, getCollectWaitingAreaData, delCollectWaitingAreaData, addCollectWaitingAreaData, updateCollectWaitingAreaData } from "@/api/runData/collectWaitingAreaData"
207
+import { getToken } from '@/utils/auth'
208
+
209
+const { proxy } = getCurrentInstance()
210
+
211
+const collectWaitingAreaDataList = ref([])
212
+const open = ref(false)
213
+const loading = ref(true)
214
+const showSearch = ref(true)
215
+const ids = ref([])
216
+const single = ref(true)
217
+const multiple = ref(true)
218
+const total = ref(0)
219
+const title = ref("")
220
+
221
+// 导入参数
222
+const upload = reactive({
223
+  // 是否显示弹出层
224
+  open: false,
225
+  // 弹出层标题
226
+  title: "",
227
+  // 是否禁用上传
228
+  isUploading: false,
229
+  // 是否更新已经存在的候检区数据
230
+  updateSupport: 0,
231
+  // 设置上传的请求头部
232
+  headers: { Authorization: "Bearer " + getToken() },
233
+  // 上传的地址
234
+  url: import.meta.env.VITE_APP_BASE_API + "/item/hkPendingConfiscate/importData"
235
+})
236
+
237
+const uploadRef = ref()
238
+
239
+const data = reactive({
240
+  form: {},
241
+  queryParams: {
242
+    pageNum: 1,
243
+    pageSize: 10,
244
+    recordDate: null,
245
+    timeSlot: null
246
+  },
247
+  rules: {
248
+    recordDate: [
249
+      { required: true, message: "日期不能为空", trigger: "change" }
250
+    ],
251
+    timeSlot: [
252
+      { required: true, message: "时间段不能为空", trigger: "change" }
253
+    ],
254
+    t1AFireSource: [
255
+      { type: "integer", message: "T1A区火种必须为整数", trigger: "blur" }
256
+    ],
257
+    t1ALiquid: [
258
+      { type: "integer", message: "T1A区液态物品必须为整数", trigger: "blur" }
259
+    ],
260
+    t1AOther: [
261
+      { type: "integer", message: "T1A区其他物品必须为整数", trigger: "blur" }
262
+    ],
263
+    t1BFireSource: [
264
+      { type: "integer", message: "T1B区火种必须为整数", trigger: "blur" }
265
+    ],
266
+    t1BLiquid: [
267
+      { type: "integer", message: "T1B区液态物品必须为整数", trigger: "blur" }
268
+    ],
269
+    t1BOther: [
270
+      { type: "integer", message: "T1B区其他物品必须为整数", trigger: "blur" }
271
+    ],
272
+    t2DomesticFireSource: [
273
+      { type: "integer", message: "T2国内火种必须为整数", trigger: "blur" }
274
+    ],
275
+    t2DomesticLiquid: [
276
+      { type: "integer", message: "T2国内液态物品必须为整数", trigger: "blur" }
277
+    ],
278
+    t2DomesticOther: [
279
+      { type: "integer", message: "T2国内其他物品必须为整数", trigger: "blur" }
280
+    ],
281
+    t2IntlFireSource: [
282
+      { type: "integer", message: "T2国际火种必须为整数", trigger: "blur" }
283
+    ],
284
+    t2IntlLiquid: [
285
+      { type: "integer", message: "T2国际液态物品必须为整数", trigger: "blur" }
286
+    ],
287
+    t2IntlOther: [
288
+      { type: "integer", message: "T2国际其他物品必须为整数", trigger: "blur" }
289
+    ],
290
+    t2TransitFireSource: [
291
+      { type: "integer", message: "T2中转火种必须为整数", trigger: "blur" }
292
+    ],
293
+    t2TransitLiquid: [
294
+      { type: "integer", message: "T2中转液态物品必须为整数", trigger: "blur" }
295
+    ],
296
+    t2TransitOther: [
297
+      { type: "integer", message: "T2中转其他物品必须为整数", trigger: "blur" }
298
+    ]
299
+  }
300
+})
301
+
302
+const { queryParams, form, rules } = toRefs(data)
303
+
304
+/** 查询候检区数据列表 */
305
+function getList() {
306
+  loading.value = true
307
+  const params = { ...queryParams.value }
308
+  if (params.timeSlot && Array.isArray(params.timeSlot)) {
309
+    params.timeSlot = params.timeSlot.join('-')
310
+  }
311
+  listCollectWaitingAreaData(params).then(response => {
312
+    collectWaitingAreaDataList.value = response.rows
313
+    total.value = response.total
314
+    loading.value = false
315
+  })
316
+}
317
+
318
+// 取消按钮
319
+function cancel() {
320
+  open.value = false
321
+  reset()
322
+}
323
+
324
+// 表单重置
325
+function reset() {
326
+  form.value = {
327
+    id: null,
328
+    recordDate: null,
329
+    timeSlot: null,
330
+    // T1区域数据
331
+    t1AFireSource: null,
332
+    t1ALiquid: null,
333
+    t1AOther: null,
334
+    t1BFireSource: null,
335
+    t1BLiquid: null,
336
+    t1BOther: null,
337
+    // T2区域数据
338
+    t2DomesticFireSource: null,
339
+    t2DomesticLiquid: null,
340
+    t2DomesticOther: null,
341
+    t2IntlFireSource: null,
342
+    t2IntlLiquid: null,
343
+    t2IntlOther: null,
344
+    t2TransitFireSource: null,
345
+    t2TransitLiquid: null,
346
+    t2TransitOther: null
347
+  }
348
+  proxy.resetForm("collectWaitingAreaDataRef")
349
+}
350
+
351
+/** 搜索按钮操作 */
352
+function handleQuery() {
353
+  queryParams.value.pageNum = 1
354
+  getList()
355
+}
356
+
357
+/** 重置按钮操作 */
358
+function resetQuery() {
359
+  proxy.resetForm("queryRef")
360
+  handleQuery()
361
+}
362
+
363
+// 多选框选中数据
364
+function handleSelectionChange(selection) {
365
+  ids.value = selection.map(item => item.id)
366
+  single.value = selection.length != 1
367
+  multiple.value = !selection.length
368
+}
369
+
370
+/** 新增按钮操作 */
371
+function handleAdd() {
372
+  reset()
373
+  open.value = true
374
+  title.value = "添加候检区数据"
375
+}
376
+
377
+/** 修改按钮操作 */
378
+function handleUpdate(row) {
379
+  reset()
380
+  const _id = row.id || ids.value
381
+  getCollectWaitingAreaData(_id).then(response => {
382
+    const data = response.data
383
+    // 转换时间段字符串为数组格式
384
+    if (data.timeSlot && typeof data.timeSlot === 'string' && data.timeSlot.includes('-')) {
385
+      data.timeSlot = data.timeSlot.split('-')
386
+    }
387
+    form.value = data
388
+    open.value = true
389
+    title.value = "修改候检区数据"
390
+  })
391
+}
392
+
393
+/** 提交按钮 */
394
+function submitForm() {
395
+  proxy.$refs["collectWaitingAreaDataRef"].validate(valid => {
396
+    if (valid) {
397
+      const submitData = { ...form.value }
398
+      // 转换时间段为字符串格式 08:00-17:00
399
+      if (submitData.timeSlot && Array.isArray(submitData.timeSlot)) {
400
+        submitData.timeSlot = submitData.timeSlot.join('-')
401
+      }
402
+      if (submitData.id != null) {
403
+        updateCollectWaitingAreaData(submitData).then(response => {
404
+          proxy.$modal.msgSuccess("修改成功")
405
+          open.value = false
406
+          getList()
407
+        })
408
+      } else {
409
+        addCollectWaitingAreaData(submitData).then(response => {
410
+          proxy.$modal.msgSuccess("新增成功")
411
+          open.value = false
412
+          getList()
413
+        })
414
+      }
415
+    }
416
+  })
417
+}
418
+
419
+/** 删除按钮操作 */
420
+function handleDelete(row) {
421
+  const _ids = row.id || ids.value
422
+  proxy.$modal.confirm('是否确认删除数据项?').then(function () {
423
+    return delCollectWaitingAreaData(_ids)
424
+  }).then(() => {
425
+    getList()
426
+    proxy.$modal.msgSuccess("删除成功")
427
+  }).catch(() => { })
428
+}
429
+
430
+/** 导出按钮操作 */
431
+function handleExport() {
432
+  // 过滤掉值为null的参数,但保留分页参数
433
+  const filteredParams = Object.fromEntries(
434
+    Object.entries(queryParams.value).filter(([key, value]) => {
435
+      // 保留分页参数
436
+      if (key === 'pageNum' || key === 'pageSize') return true
437
+      // 过滤掉其他为null的参数
438
+      return value !== null
439
+    })
440
+  )
441
+
442
+  proxy.download('/item/hkPendingConfiscate/export', filteredParams, `collectWaitingAreaData_${new Date().getTime()}.xlsx`)
443
+}
444
+
445
+/** 导入按钮操作 */
446
+function handleImport() {
447
+  upload.title = "候检区数据导入"
448
+  upload.open = true
449
+}
450
+
451
+/** 下载模板操作 */
452
+function importTemplate() {
453
+  proxy.download('/item/hkPendingConfiscate/importTemplate', {
454
+  }, `候检区数据导入模板_${new Date().getTime()}.xlsx`)
455
+}
456
+
457
+/** 文件上传中处理 */
458
+const handleFileUploadProgress = (event, file, fileList) => {
459
+  upload.isUploading = true
460
+}
461
+
462
+/** 文件上传成功处理 */
463
+const handleFileSuccess = (response, file, fileList) => {
464
+  upload.open = false
465
+  upload.isUploading = false
466
+  uploadRef.value.handleRemove(file)
467
+  proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
468
+  getList()
469
+}
470
+
471
+/** 提交上传文件 */
472
+function submitFileForm() {
473
+  uploadRef.value.submit()
474
+}
475
+
476
+getList()
477
+</script>

+ 0 - 0
src/views/runData/collectWaitingAreaData/待检区收缴数据


+ 500 - 0
src/views/runData/dailyRunData/index.vue

@@ -0,0 +1,500 @@
1
+<template>
2
+  <div class="app-container">
3
+    <!-- 查询条件 -->
4
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
5
+      <el-form-item label="日期" prop="date">
6
+        <el-date-picker v-model="queryParams.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
7
+          style="width: 200px" />
8
+      </el-form-item>
9
+      <el-form-item>
10
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
11
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
12
+      </el-form-item>
13
+    </el-form>
14
+
15
+    <!-- 按钮区域 -->
16
+    <el-row :gutter="10" class="mb8">
17
+      <el-col :span="1.5">
18
+        <el-button type="primary" plain icon="Plus" @click="handleAdd"
19
+          v-hasPermi="['runData:dailyRunData:add']">新增</el-button>
20
+      </el-col>
21
+
22
+      <el-col :span="1.5">
23
+        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
24
+          v-hasPermi="['runData:dailyRunData:remove']">删除</el-button>
25
+      </el-col>
26
+      <el-col :span="1.5">
27
+        <el-button type="info" plain icon="Upload" @click="handleImport"
28
+          v-hasPermi="['runData:dailyRunData:import']">导入</el-button>
29
+      </el-col>
30
+      <el-col :span="1.5">
31
+        <el-button type="warning" plain icon="Download" @click="handleExport"
32
+          v-hasPermi="['runData:dailyRunData:export']">导出</el-button>
33
+      </el-col>
34
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
35
+    </el-row>
36
+
37
+    <!-- 数据表格 -->
38
+    <el-table v-loading="loading" :data="dailyRunDataList" @selection-change="handleSelectionChange">
39
+      <el-table-column type="selection" width="55" align="center" />
40
+      <el-table-column label="日期" align="center" prop="recordDate" />
41
+      <el-table-column label="A区" align="center" prop="azone" />
42
+      <el-table-column label="B区" align="center" prop="bzone" />
43
+      <el-table-column label="贵宾" align="center" prop="vip" />
44
+      <el-table-column label="国内旅检" align="center" prop="domesticPassenger" />
45
+      <el-table-column label="国际旅检" align="center" prop="intlPassenger" />
46
+      <el-table-column label="贵宾通道" align="center" prop="vipChannel" />
47
+      <el-table-column label="T1回流通道" align="center" prop="t1ReturnChannel" />
48
+      <el-table-column label="T1行检" align="center" prop="t1LuggageCheck" />
49
+      <el-table-column label="一楼员工" align="center" prop="floor1Staff" />
50
+      <el-table-column label="T2回流通道" align="center" prop="t2ReturnChannel" />
51
+      <el-table-column label="T2行检" align="center" prop="t2LuggageCheck" />
52
+      <el-table-column label="三楼" align="center" prop="floor3EastStaff" />
53
+      <el-table-column label="一楼" align="center" prop="floor1CenterStaff" />
54
+      <el-table-column label="负一楼" align="center" prop="floorB1WestStaff" />
55
+      <el-table-column label="国内货站" align="center" prop="domesticCargo" />
56
+      <el-table-column label="道口" align="center" prop="domesticGate" />
57
+      <el-table-column label="南侧车检" align="center" prop="southVehicleCheck" />
58
+      <el-table-column label="防爆" align="center" prop="domesticBomb" />
59
+      <el-table-column label="国际货站" align="center" prop="intlCargo" />
60
+      <el-table-column label="道口" align="center" prop="intlGate" />
61
+      <el-table-column label="北侧车检" align="center" prop="northVehicleCheck" />
62
+      <el-table-column label="防爆" align="center" prop="intlBomb" />
63
+      <el-table-column label="操作" width="180px" align="center" class-name="small-padding fixed-width">
64
+        <template #default="scope">
65
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
66
+            v-hasPermi="['runData:dailyRunData:edit']">修改</el-button>
67
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
68
+            v-hasPermi="['runData:dailyRunData:remove']">删除</el-button>
69
+        </template>
70
+      </el-table-column>
71
+    </el-table>
72
+
73
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
74
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
75
+
76
+    <!-- 添加或修改日常运行数据对话框 -->
77
+    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
78
+      <el-form ref="dailyRunDataRef" :model="form" :rules="rules" label-width="120px">
79
+        <el-form-item label="日期" prop="recordDate">
80
+          <el-date-picker v-model="form.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
81
+            style="width: 100%" />
82
+        </el-form-item>
83
+
84
+        <el-row :gutter="20">
85
+          <el-col :span="12">
86
+            <el-form-item label="A区" prop="azone">
87
+              <el-input-number :precision="0" v-model="form.azone" :min="0" placeholder="请输入A区数据" style="width: 100%" />
88
+            </el-form-item>
89
+            <el-form-item label="B区" prop="bzone">
90
+              <el-input-number :precision="0" v-model="form.bzone" :min="0" placeholder="请输入B区数据" style="width: 100%" />
91
+            </el-form-item>
92
+            <el-form-item label="贵宾" prop="vip">
93
+              <el-input-number :precision="0" v-model="form.vip" :min="0" placeholder="请输入贵宾数据" style="width: 100%" />
94
+            </el-form-item>
95
+            <el-form-item label="国内旅检" prop="domesticPassenger">
96
+              <el-input-number :precision="0" v-model="form.domesticPassenger" :min="0" placeholder="请输入国内旅检数据"
97
+                style="width: 100%" />
98
+            </el-form-item>
99
+            <el-form-item label="国际旅检" prop="intlPassenger">
100
+              <el-input-number :precision="0" v-model="form.intlPassenger" :min="0" placeholder="请输入国际旅检数据"
101
+                style="width: 100%" />
102
+            </el-form-item>
103
+            <el-form-item label="贵宾通道" prop="vipChannel">
104
+              <el-input-number :precision="0" v-model="form.vipChannel" :min="0" placeholder="请输入贵宾通道数据" style="width: 100%" />
105
+            </el-form-item>
106
+            <el-form-item label="T1回流通道" prop="t1ReturnChannel">
107
+              <el-input-number :precision="0" v-model="form.t1ReturnChannel" :min="0" placeholder="请输入T1回流通道数据" style="width: 100%" />
108
+            </el-form-item>
109
+            <el-form-item label="T1行检" prop="t1LuggageCheck">
110
+              <el-input-number :precision="0" v-model="form.t1LuggageCheck" :min="0" placeholder="请输入T1行检数据" style="width: 100%" />
111
+            </el-form-item>
112
+            <el-form-item label="一楼员工" prop="floor1Staff">
113
+              <el-input-number :precision="0" v-model="form.floor1Staff" :min="0" placeholder="请输入一楼员工数据" style="width: 100%" />
114
+            </el-form-item>
115
+            <el-form-item label="T2回流通道" prop="t2ReturnChannel">
116
+              <el-input-number :precision="0" v-model="form.t2ReturnChannel" :min="0" placeholder="请输入T2回流通道数据" style="width: 100%" />
117
+            </el-form-item>
118
+            <el-form-item label="T2行检" prop="t2LuggageCheck">
119
+              <el-input-number :precision="0" v-model="form.t2LuggageCheck" :min="0" placeholder="请输入T2行检数据" style="width: 100%" />
120
+            </el-form-item>
121
+
122
+          </el-col>
123
+
124
+          <el-col :span="12">
125
+            <el-form-item label="三楼" prop="floor3EastStaff">
126
+              <el-input-number :precision="0" v-model="form.floor3EastStaff" :min="0" placeholder="请输入三楼数据" style="width: 100%" />
127
+            </el-form-item>
128
+            <el-form-item label="一楼" prop="floor1CenterStaff">
129
+              <el-input-number :precision="0" v-model="form.floor1CenterStaff" :min="0" placeholder="请输入一楼数据" style="width: 100%" />
130
+            </el-form-item>
131
+            <el-form-item label="负一楼" prop="floorB1WestStaff">
132
+              <el-input-number :precision="0" v-model="form.floorB1WestStaff" :min="0" placeholder="请输入负一楼数据" style="width: 100%" />
133
+            </el-form-item>
134
+            <el-form-item label="国内货站" prop="domesticCargo">
135
+              <el-input-number :precision="0" v-model="form.domesticCargo" :min="0" placeholder="请输入国内货站数据" style="width: 100%" />
136
+            </el-form-item>
137
+            <el-form-item label="道口" prop="domesticGate">
138
+              <el-input-number :precision="0" v-model="form.domesticGate" :min="0" placeholder="请输入道口数据" style="width: 100%" />
139
+            </el-form-item>
140
+            <el-form-item label="南侧车检" prop="southVehicleCheck">
141
+              <el-input-number :precision="0" v-model="form.southVehicleCheck" :min="0" placeholder="请输入南侧车检数据"
142
+                style="width: 100%" />
143
+            </el-form-item>
144
+            <el-form-item label="防爆" prop="domesticBomb">
145
+              <el-input-number :precision="0" v-model="form.domesticBomb" :min="0" placeholder="请输入防爆数据" style="width: 100%" />
146
+            </el-form-item>
147
+            <el-form-item label="国际货站" prop="intlCargo">
148
+              <el-input-number :precision="0" v-model="form.intlCargo" :min="0" placeholder="请输入国际货站数据" style="width: 100%" />
149
+            </el-form-item>
150
+            <el-form-item label="道口" prop="intlGate">
151
+              <el-input-number :precision="0" v-model="form.intlGate" :min="0" placeholder="请输入道口数据" style="width: 100%" />
152
+            </el-form-item>
153
+            <el-form-item label="北侧车检" prop="northVehicleCheck">
154
+              <el-input-number :precision="0" v-model="form.northVehicleCheck" :min="0" placeholder="请输入北侧车检数据"
155
+                style="width: 100%" />
156
+            </el-form-item>
157
+            <el-form-item label="防爆" prop="intlBomb">
158
+              <el-input-number :precision="0" v-model="form.intlBomb" :min="0" placeholder="请输入防爆数据" style="width: 100%" />
159
+            </el-form-item>
160
+          </el-col>
161
+        </el-row>
162
+      </el-form>
163
+      <template #footer>
164
+        <div class="dialog-footer">
165
+          <el-button type="primary" @click="submitForm">确 定</el-button>
166
+          <el-button @click="cancel">取 消</el-button>
167
+        </div>
168
+      </template>
169
+    </el-dialog>
170
+
171
+    <!-- 导入对话框 -->
172
+    <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
173
+      <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
174
+        :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
175
+        :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
176
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
177
+        <div class="el-upload__text">
178
+          将文件拖到此处,或<em>点击上传</em>
179
+        </div>
180
+        <template #tip>
181
+          <div class="el-upload__tip">
182
+            <span>仅允许导入xls、xlsx格式文件。</span>
183
+            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
184
+              @click="importTemplate">下载模板</el-link>
185
+          </div>
186
+        </template>
187
+      </el-upload>
188
+      <template #footer>
189
+        <div class="dialog-footer">
190
+          <el-button type="primary" @click="submitFileForm">确 定</el-button>
191
+          <el-button @click="upload.open = false">取 消</el-button>
192
+        </div>
193
+      </template>
194
+    </el-dialog>
195
+  </div>
196
+</template>
197
+
198
+<script setup name="DailyRunData">
199
+import { listDailyRunData, getDailyRunData, delDailyRunData, addDailyRunData, updateDailyRunData } from "@/api/runData/dailyRunData"
200
+import { getToken } from '@/utils/auth'
201
+
202
+const { proxy } = getCurrentInstance()
203
+
204
+const dailyRunDataList = ref([])
205
+const open = ref(false)
206
+const loading = ref(true)
207
+const showSearch = ref(true)
208
+const ids = ref([])
209
+const single = ref(true)
210
+const multiple = ref(true)
211
+const total = ref(0)
212
+const title = ref("")
213
+
214
+// 导入参数
215
+const upload = reactive({
216
+  // 是否显示弹出层
217
+  open: false,
218
+  // 弹出层标题
219
+  title: "",
220
+  // 是否禁用上传
221
+  isUploading: false,
222
+  // 是否更新已经存在的日常运行数据
223
+  updateSupport: 0,
224
+  // 设置上传的请求头部
225
+  headers: { Authorization: "Bearer " + getToken() },
226
+  // 上传的地址
227
+  url: import.meta.env.VITE_APP_BASE_API + "/item/hkOperationData/importData"
228
+})
229
+
230
+const uploadRef = ref()
231
+
232
+const data = reactive({
233
+  form: {},
234
+  queryParams: {
235
+    pageNum: 1,
236
+    pageSize: 10,
237
+    recordDate: null
238
+  },
239
+  rules: {
240
+    recordDate: [
241
+      { required: true, message: "日期不能为空", trigger: "blur" }
242
+    ],
243
+    azone: [
244
+      { required: true, message: "A区数据不能为空", trigger: "blur" },
245
+      { type: "integer", message: "A区数据必须为整数", trigger: "blur" }
246
+    ],
247
+    bzone: [
248
+      { required: true, message: "B区数据不能为空", trigger: "blur" },
249
+      { type: "integer", message: "B区数据必须为整数", trigger: "blur" }
250
+    ],
251
+    vip: [
252
+      { required: true, message: "贵宾数据不能为空", trigger: "blur" },
253
+      { type: "integer", message: "贵宾数据必须为整数", trigger: "blur" }
254
+    ],
255
+    domesticPassenger: [
256
+      { required: true, message: "国内旅检数据不能为空", trigger: "blur" },
257
+      { type: "integer", message: "国内旅检数据必须为整数", trigger: "blur" }
258
+    ],
259
+    intlPassenger: [
260
+      { required: true, message: "国际旅检数据不能为空", trigger: "blur" },
261
+      { type: "integer", message: "国际旅检数据必须为整数", trigger: "blur" }
262
+    ],
263
+    vipChannel: [
264
+      { required: true, message: "贵宾通道数据不能为空", trigger: "blur" },
265
+      { type: "integer", message: "贵宾通道数据必须为整数", trigger: "blur" }
266
+    ],
267
+    t1ReturnChannel: [
268
+      { required: true, message: "T1回流通道数据不能为空", trigger: "blur" },
269
+      { type: "integer", message: "T1回流通道数据必须为整数", trigger: "blur" }
270
+    ],
271
+    t1LuggageCheck: [
272
+      { required: true, message: "T1行检数据不能为空", trigger: "blur" },
273
+      { type: "integer", message: "T1行检数据必须为整数", trigger: "blur" }
274
+    ],
275
+    floor1Staff: [
276
+      { required: true, message: "一楼员工数据不能为空", trigger: "blur" },
277
+      { type: "integer", message: "一楼员工数据必须为整数", trigger: "blur" }
278
+    ],
279
+    t2ReturnChannel: [
280
+      { required: true, message: "T2回流通道数据不能为空", trigger: "blur" },
281
+      { type: "integer", message: "T2回流通道数据必须为整数", trigger: "blur" }
282
+    ],
283
+    t2LuggageCheck: [
284
+      { required: true, message: "T2行检数据不能为空", trigger: "blur" },
285
+      { type: "integer", message: "T2行检数据必须为整数", trigger: "blur" }
286
+    ],
287
+    floor3EastStaff: [
288
+      { required: true, message: "三楼数据不能为空", trigger: "blur" },
289
+      { type: "integer", message: "三楼数据必须为整数", trigger: "blur" }
290
+    ],
291
+    floor1CenterStaff: [
292
+      { required: true, message: "一楼数据不能为空", trigger: "blur" },
293
+      { type: "integer", message: "一楼数据必须为整数", trigger: "blur" }
294
+    ],
295
+    floorB1WestStaff: [
296
+      { required: true, message: "负一楼数据不能为空", trigger: "blur" },
297
+      { type: "integer", message: "负一楼数据必须为整数", trigger: "blur" }
298
+    ],
299
+    domesticCargo: [
300
+      { required: true, message: "国内货站数据不能为空", trigger: "blur" },
301
+      { type: "integer", message: "国内货站数据必须为整数", trigger: "blur" }
302
+    ],
303
+    domesticGate: [
304
+      { required: true, message: "道口数据不能为空", trigger: "blur" },
305
+      { type: "integer", message: "道口数据必须为整数", trigger: "blur" }
306
+    ],
307
+    southVehicleCheck: [
308
+      { required: true, message: "南侧车检数据不能为空", trigger: "blur" },
309
+      { type: "integer", message: "南侧车检数据必须为整数", trigger: "blur" }
310
+    ],
311
+    domesticBomb: [
312
+      { required: true, message: "防爆数据不能为空", trigger: "blur" },
313
+      { type: "integer", message: "防爆数据必须为整数", trigger: "blur" }
314
+    ],
315
+    intlCargo: [
316
+      { required: true, message: "国际货站数据不能为空", trigger: "blur" },
317
+      { type: "integer", message: "国际货站数据必须为整数", trigger: "blur" }
318
+    ],
319
+    intlGate: [
320
+      { required: true, message: "道口数据不能为空", trigger: "blur" },
321
+      { type: "integer", message: "道口数据必须为整数", trigger: "blur" }
322
+    ],
323
+    northVehicleCheck: [
324
+      { required: true, message: "北侧车检数据不能为空", trigger: "blur" },
325
+      { type: "integer", message: "北侧车检数据必须为整数", trigger: "blur" }
326
+    ],
327
+    intlBomb: [
328
+      { required: true, message: "防爆数据不能为空", trigger: "blur" },
329
+      { type: "integer", message: "防爆数据必须为整数", trigger: "blur" }
330
+    ]
331
+  }
332
+})
333
+
334
+const { queryParams, form, rules } = toRefs(data)
335
+
336
+/** 查询日常运行数据列表 */
337
+function getList() {
338
+  loading.value = true
339
+  listDailyRunData(queryParams.value).then(response => {
340
+    dailyRunDataList.value = response.rows
341
+    total.value = response.total
342
+    loading.value = false
343
+  })
344
+}
345
+
346
+// 取消按钮
347
+function cancel() {
348
+  open.value = false
349
+  reset()
350
+}
351
+
352
+// 表单重置
353
+function reset() {
354
+  form.value = {
355
+    id: null,
356
+    recordDate: null,
357
+    azone: null,
358
+    bzone: null,
359
+    vip: null,
360
+    domesticPassenger: null,
361
+    intlPassenger: null,
362
+    vipChannel: null,
363
+    t1ReturnChannel: null,
364
+    t1LuggageCheck: null,
365
+    floor1Staff: null,
366
+    t2ReturnChannel: null,
367
+    t2LuggageCheck: null,
368
+    floor3EastStaff: null,
369
+    floor1CenterStaff: null,
370
+    floorB1WestStaff: null,
371
+    floor3WestStaff: null,
372
+    domesticCargo: null,
373
+    domesticGate: null,
374
+    southVehicleCheck: null,
375
+    domesticBomb: null,
376
+    intlCargo: null,
377
+    intlGate: null,
378
+    northVehicleCheck: null,
379
+    intlBomb: null
380
+  }
381
+  proxy.resetForm("dailyRunDataRef")
382
+}
383
+
384
+/** 搜索按钮操作 */
385
+function handleQuery() {
386
+  queryParams.value.pageNum = 1
387
+  getList()
388
+}
389
+
390
+/** 重置按钮操作 */
391
+function resetQuery() {
392
+  proxy.resetForm("queryRef")
393
+  handleQuery()
394
+}
395
+
396
+// 多选框选中数据
397
+function handleSelectionChange(selection) {
398
+  ids.value = selection.map(item => item.id)
399
+  single.value = selection.length != 1
400
+  multiple.value = !selection.length
401
+}
402
+
403
+/** 新增按钮操作 */
404
+function handleAdd() {
405
+  reset()
406
+  open.value = true
407
+  title.value = "添加日常运行数据"
408
+}
409
+
410
+/** 修改按钮操作 */
411
+function handleUpdate(row) {
412
+  reset()
413
+  const _id = row.id || ids.value
414
+  getDailyRunData(_id).then(response => {
415
+    form.value = response.data
416
+    open.value = true
417
+    title.value = "修改日常运行数据"
418
+  })
419
+}
420
+
421
+/** 提交按钮 */
422
+function submitForm() {
423
+  proxy.$refs["dailyRunDataRef"].validate(valid => {
424
+    if (valid) {
425
+      if (form.value.id != null) {
426
+        updateDailyRunData(form.value).then(response => {
427
+          proxy.$modal.msgSuccess("修改成功")
428
+          open.value = false
429
+          getList()
430
+        })
431
+      } else {
432
+        addDailyRunData(form.value).then(response => {
433
+          proxy.$modal.msgSuccess("新增成功")
434
+          open.value = false
435
+          getList()
436
+        })
437
+      }
438
+    }
439
+  })
440
+}
441
+
442
+/** 删除按钮操作 */
443
+function handleDelete(row) {
444
+  const _ids = row.id || ids.value
445
+  proxy.$modal.confirm('是否确认删除数据项?').then(function () {
446
+    return delDailyRunData(_ids)
447
+  }).then(() => {
448
+    getList()
449
+    proxy.$modal.msgSuccess("删除成功")
450
+  }).catch(() => { })
451
+}
452
+
453
+/** 导出按钮操作 */
454
+function handleExport() {
455
+  // 过滤掉值为null的参数,但保留分页参数
456
+  const filteredParams = Object.fromEntries(
457
+    Object.entries(queryParams.value).filter(([key, value]) => {
458
+      // 保留分页参数
459
+      if (key === 'pageNum' || key === 'pageSize') return true
460
+      // 过滤掉其他为null的参数
461
+      return value !== null
462
+    })
463
+  )
464
+
465
+  proxy.download('/item/hkOperationData/export', filteredParams, `dailyRunData_${new Date().getTime()}.xlsx`)
466
+}
467
+
468
+/** 导入按钮操作 */
469
+function handleImport() {
470
+  upload.title = "日常运行数据导入"
471
+  upload.open = true
472
+}
473
+
474
+/** 下载模板操作 */
475
+function importTemplate() {
476
+  proxy.download('/item/hkOperationData/importTemplate', {
477
+  }, `日常运行数据导入模板_${new Date().getTime()}.xlsx`)
478
+}
479
+
480
+/** 文件上传中处理 */
481
+const handleFileUploadProgress = (event, file, fileList) => {
482
+  upload.isUploading = true
483
+}
484
+
485
+/** 文件上传成功处理 */
486
+const handleFileSuccess = (response, file, fileList) => {
487
+  upload.open = false
488
+  upload.isUploading = false
489
+  uploadRef.value.handleRemove(file)
490
+  proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
491
+  getList()
492
+}
493
+
494
+/** 提交上传文件 */
495
+function submitFileForm() {
496
+  uploadRef.value.submit()
497
+}
498
+
499
+getList()
500
+</script>

+ 0 - 0
src/views/runData/dailyRunData/每日运行数据


+ 476 - 0
src/views/runData/discouragePowerBanksData/index.vue

@@ -0,0 +1,476 @@
1
+<template>
2
+  <div class="app-container">
3
+    <!-- 查询条件 -->
4
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
5
+      <el-form-item label="日期" prop="recordDate">
6
+        <el-date-picker v-model="queryParams.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
7
+          style="width: 200px" />
8
+      </el-form-item>
9
+      <el-form-item label="时间段" prop="timeSlot">
10
+        <el-time-picker
11
+          v-model="queryParams.timeSlot"
12
+          is-range
13
+          range-separator="-"
14
+          start-placeholder="开始时间"
15
+          end-placeholder="结束时间"
16
+          value-format="HH:mm"
17
+          format="HH:mm"
18
+          placeholder="请选择时间段"
19
+          clearable
20
+          style="width: 200px" />
21
+      </el-form-item>
22
+      <el-form-item>
23
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
24
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
25
+      </el-form-item>
26
+    </el-form>
27
+
28
+    <!-- 按钮区域 -->
29
+    <el-row :gutter="10" class="mb8">
30
+      <el-col :span="1.5">
31
+        <el-button type="primary" plain icon="Plus" @click="handleAdd"
32
+          v-hasPermi="['runData:discouragePowerBanksData:add']">新增</el-button>
33
+      </el-col>
34
+   
35
+      <el-col :span="1.5">
36
+        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
37
+          v-hasPermi="['runData:discouragePowerBanksData:remove']">删除</el-button>
38
+      </el-col>
39
+      <el-col :span="1.5">
40
+        <el-button type="info" plain icon="Upload" @click="handleImport"
41
+          v-hasPermi="['runData:discouragePowerBanksData:import']">导入</el-button>
42
+      </el-col>
43
+      <el-col :span="1.5">
44
+        <el-button type="warning" plain icon="Download" @click="handleExport"
45
+          v-hasPermi="['runData:discouragePowerBanksData:export']">导出</el-button>
46
+      </el-col>
47
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
48
+    </el-row>
49
+
50
+    <!-- 数据表格 -->
51
+    <el-table v-loading="loading" :data="discouragePowerBanksDataList" @selection-change="handleSelectionChange">
52
+      <el-table-column type="selection" width="55" align="center" />
53
+      <el-table-column label="日期" align="center" prop="recordDate" />
54
+      <el-table-column label="时间段" align="center" prop="timeSlot" />
55
+      
56
+      <!-- T1区域数据 -->
57
+      <el-table-column label="T1召回充电宝" align="center" prop="t1Recall" />
58
+      <el-table-column label="T1无3C标识" align="center" prop="t1No3c" />
59
+      <el-table-column label="T1标识不清" align="center" prop="t1UnclearMark" />
60
+      <el-table-column label="T1超规数量" align="center" prop="t1ExcessQty" />
61
+      <el-table-column label="T1邮寄" align="center" prop="t1Mail" />
62
+      <el-table-column label="T1自弃" align="center" prop="t1Abandon" />
63
+      <el-table-column label="T1暂存" align="center" prop="t1TempStore" />
64
+      
65
+      <!-- T2区域数据 -->
66
+      <el-table-column label="T2召回充电宝" align="center" prop="t2Recall" />
67
+      <el-table-column label="T2无3C标识" align="center" prop="t2No3c" />
68
+      <el-table-column label="T2标识不清" align="center" prop="t2UnclearMark" />
69
+      <el-table-column label="T2超规数量" align="center" prop="t2ExcessQty" />
70
+      <el-table-column label="T2邮寄" align="center" prop="t2Mail" />
71
+      <el-table-column label="T2自弃" align="center" prop="t2Abandon" />
72
+      <el-table-column label="T2暂存" align="center" prop="t2TempStore" />
73
+      
74
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
75
+        <template #default="scope">
76
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
77
+            v-hasPermi="['runData:discouragePowerBanksData:edit']">修改</el-button>
78
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
79
+            v-hasPermi="['runData:discouragePowerBanksData:remove']">删除</el-button>
80
+        </template>
81
+      </el-table-column>
82
+    </el-table>
83
+
84
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
85
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
86
+
87
+    <!-- 添加或修改劝阻充电宝数据对话框 -->
88
+    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
89
+      <el-form ref="discouragePowerBanksDataRef" :model="form" :rules="rules" label-width="120px">
90
+        <el-row :gutter="20">
91
+          <el-col :span="12">
92
+            <el-form-item label="日期" prop="recordDate">
93
+              <el-date-picker v-model="form.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD"
94
+                style="width: 100%" />
95
+            </el-form-item>
96
+          </el-col>
97
+          <el-col :span="12">
98
+            <el-form-item label="时间段" prop="timeSlot">
99
+              <el-time-picker
100
+                v-model="form.timeSlot"
101
+                is-range
102
+                range-separator="-"
103
+                start-placeholder="开始时间"
104
+                end-placeholder="结束时间"
105
+                value-format="HH:mm"
106
+                format="HH:mm"
107
+                placeholder="请选择时间段"
108
+                style="width: 100%" />
109
+            </el-form-item>
110
+          </el-col>
111
+        </el-row>
112
+        
113
+        <!-- T1区域 -->
114
+        <el-divider content-position="left">T1区域数据</el-divider>
115
+        <el-row :gutter="20">
116
+          <el-col :span="12">
117
+            <el-form-item label="T1召回充电宝" prop="t1Recall">
118
+              <el-input-number :precision="0" v-model="form.t1Recall" :min="0" placeholder="请输入T1召回充电宝" style="width: 100%"  />
119
+            </el-form-item>
120
+            <el-form-item label="T1无3C标识" prop="t1No3c">
121
+              <el-input-number :precision="0" v-model="form.t1No3c" :min="0" placeholder="请输入T1无3C标识" style="width: 100%" />
122
+            </el-form-item>
123
+            <el-form-item label="T1标识不清" prop="t1UnclearMark">
124
+              <el-input-number :precision="0" v-model="form.t1UnclearMark" :min="0" placeholder="请输入T1标识不清" style="width: 100%" />
125
+            </el-form-item>
126
+          </el-col>
127
+          <el-col :span="12">
128
+            <el-form-item label="T1超规数量" prop="t1ExcessQty">
129
+              <el-input-number :precision="0" v-model="form.t1ExcessQty" :min="0" placeholder="请输入T1超规数量" style="width: 100%" />
130
+            </el-form-item>
131
+            <el-form-item label="T1邮寄" prop="t1Mail">
132
+              <el-input-number :precision="0" v-model="form.t1Mail" :min="0" placeholder="请输入T1邮寄" style="width: 100%" />
133
+            </el-form-item>
134
+            <el-form-item label="T1自弃" prop="t1Abandon">
135
+              <el-input-number :precision="0" v-model="form.t1Abandon" :min="0" placeholder="请输入T1自弃" style="width: 100%" />
136
+            </el-form-item>
137
+            <el-form-item label="T1暂存" prop="t1TempStore">
138
+              <el-input-number :precision="0" v-model="form.t1TempStore" :min="0" placeholder="请输入T1暂存" style="width: 100%" />
139
+            </el-form-item>
140
+          </el-col>
141
+        </el-row>
142
+        
143
+        <!-- T2区域 -->
144
+        <el-divider content-position="left">T2区域数据</el-divider>
145
+        <el-row :gutter="20">
146
+          <el-col :span="12">
147
+            <el-form-item label="T2召回充电宝" prop="t2Recall">
148
+              <el-input-number :precision="0" v-model="form.t2Recall" :min="0" placeholder="请输入T2召回充电宝" style="width: 100%" />
149
+            </el-form-item>
150
+            <el-form-item label="T2无3C标识" prop="t2No3c">
151
+              <el-input-number :precision="0" v-model="form.t2No3c" :min="0" placeholder="请输入T2无3C标识" style="width: 100%" />
152
+            </el-form-item>
153
+            <el-form-item label="T2标识不清" prop="t2UnclearMark">
154
+              <el-input-number :precision="0" v-model="form.t2UnclearMark" :min="0" placeholder="请输入T2标识不清" style="width: 100%" />
155
+            </el-form-item>
156
+          </el-col>
157
+          <el-col :span="12">
158
+            <el-form-item label="T2超规数量" prop="t2ExcessQty">
159
+              <el-input-number :precision="0" v-model="form.t2ExcessQty" :min="0" placeholder="请输入T2超规数量" style="width: 100%" />
160
+            </el-form-item>
161
+            <el-form-item label="T2邮寄" prop="t2Mail">
162
+              <el-input-number :precision="0" v-model="form.t2Mail" :min="0" placeholder="请输入T2邮寄" style="width: 100%" />
163
+            </el-form-item>
164
+            <el-form-item label="T2自弃" prop="t2Abandon">
165
+              <el-input-number :precision="0" v-model="form.t2Abandon" :min="0" placeholder="请输入T2自弃" style="width: 100%" />
166
+            </el-form-item>
167
+            <el-form-item label="T2暂存" prop="t2TempStore">
168
+              <el-input-number :precision="0" v-model="form.t2TempStore" :min="0" placeholder="请输入T2暂存" style="width: 100%" />
169
+            </el-form-item>
170
+          </el-col>
171
+        </el-row>
172
+      </el-form>
173
+      <template #footer>
174
+        <div class="dialog-footer">
175
+          <el-button type="primary" @click="submitForm">确 定</el-button>
176
+          <el-button @click="cancel">取 消</el-button>
177
+        </div>
178
+      </template>
179
+    </el-dialog>
180
+
181
+    <!-- 导入对话框 -->
182
+    <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
183
+      <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
184
+        :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
185
+        :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
186
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
187
+        <div class="el-upload__text">
188
+          将文件拖到此处,或<em>点击上传</em>
189
+        </div>
190
+        <template #tip>
191
+          <div class="el-upload__tip">
192
+            <span>仅允许导入xls、xlsx格式文件。</span>
193
+            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
194
+              @click="importTemplate">下载模板</el-link>
195
+          </div>
196
+        </template>
197
+      </el-upload>
198
+      <template #footer>
199
+        <div class="dialog-footer">
200
+          <el-button type="primary" @click="submitFileForm">确 定</el-button>
201
+          <el-button @click="upload.open = false">取 消</el-button>
202
+        </div>
203
+      </template>
204
+    </el-dialog>
205
+  </div>
206
+</template>
207
+
208
+<script setup name="DiscouragePowerBanksData">
209
+import { listDiscouragePowerBanksData, getDiscouragePowerBanksData, delDiscouragePowerBanksData, addDiscouragePowerBanksData, updateDiscouragePowerBanksData } from "@/api/runData/discouragePowerBanksData"
210
+import { getToken } from '@/utils/auth'
211
+
212
+const { proxy } = getCurrentInstance()
213
+
214
+const discouragePowerBanksDataList = ref([])
215
+const open = ref(false)
216
+const loading = ref(true)
217
+const showSearch = ref(true)
218
+const ids = ref([])
219
+const single = ref(true)
220
+const multiple = ref(true)
221
+const total = ref(0)
222
+const title = ref("")
223
+
224
+// 导入参数
225
+const upload = reactive({
226
+  // 是否显示弹出层
227
+  open: false,
228
+  // 弹出层标题
229
+  title: "",
230
+  // 是否禁用上传
231
+  isUploading: false,
232
+  // 是否更新已经存在的劝阻充电宝数据
233
+  updateSupport: 0,
234
+  // 设置上传的请求头部
235
+  headers: { Authorization: "Bearer " + getToken() },
236
+  // 上传的地址
237
+  url: import.meta.env.VITE_APP_BASE_API + "/item/hkPersuadePowerBank/importData"
238
+})
239
+
240
+const uploadRef = ref()
241
+
242
+const data = reactive({
243
+  form: {},
244
+  queryParams: {
245
+    pageNum: 1,
246
+    pageSize: 10,
247
+    recordDate: null,
248
+    timeSlot: null
249
+  },
250
+  rules: {
251
+    recordDate: [
252
+      { required: true, message: "日期不能为空", trigger: "change" }
253
+    ],
254
+    timeSlot: [
255
+      { required: true, message: "时间段不能为空", trigger: "change" }
256
+    ],
257
+    t1Recall: [
258
+      { type: "integer", message: "T1召回充电宝必须为整数", trigger: "blur" }
259
+    ],
260
+    t1No3c: [
261
+      { type: "integer", message: "T1无3C标识必须为整数", trigger: "blur" }
262
+    ],
263
+    t1UnclearMark: [
264
+      { type: "integer", message: "T1标识不清必须为整数", trigger: "blur" }
265
+    ],
266
+    t1ExcessQty: [
267
+      { type: "integer", message: "T1超规数量必须为整数", trigger: "blur" }
268
+    ],
269
+    t1Mail: [
270
+      { type: "integer", message: "T1邮寄必须为整数", trigger: "blur" }
271
+    ],
272
+    t1Abandon: [
273
+      { type: "integer", message: "T1自弃必须为整数", trigger: "blur" }
274
+    ],
275
+    t1TempStore: [
276
+      { type: "integer", message: "T1暂存必须为整数", trigger: "blur" }
277
+    ],
278
+    t2Recall: [
279
+      { type: "integer", message: "T2召回充电宝必须为整数", trigger: "blur" }
280
+    ],
281
+    t2No3c: [
282
+      { type: "integer", message: "T2无3C标识必须为整数", trigger: "blur" }
283
+    ],
284
+    t2UnclearMark: [
285
+      { type: "integer", message: "T2标识不清必须为整数", trigger: "blur" }
286
+    ],
287
+    t2ExcessQty: [
288
+      { type: "integer", message: "T2超规数量必须为整数", trigger: "blur" }
289
+    ],
290
+    t2Mail: [
291
+      { type: "integer", message: "T2邮寄必须为整数", trigger: "blur" }
292
+    ],
293
+    t2Abandon: [
294
+      { type: "integer", message: "T2自弃必须为整数", trigger: "blur" }
295
+    ],
296
+    t2TempStore: [
297
+      { type: "integer", message: "T2暂存必须为整数", trigger: "blur" }
298
+    ]
299
+  }
300
+})
301
+
302
+const { queryParams, form, rules } = toRefs(data)
303
+
304
+/** 查询劝阻充电宝数据列表 */
305
+function getList() {
306
+  loading.value = true
307
+  const params = { ...queryParams.value }
308
+  if (params.timeSlot && Array.isArray(params.timeSlot)) {
309
+    params.timeSlot = params.timeSlot.join('-')
310
+  }
311
+  listDiscouragePowerBanksData(params).then(response => {
312
+    discouragePowerBanksDataList.value = response.rows
313
+    total.value = response.total
314
+    loading.value = false
315
+  })
316
+}
317
+
318
+// 取消按钮
319
+function cancel() {
320
+  open.value = false
321
+  reset()
322
+}
323
+
324
+// 表单重置
325
+function reset() {
326
+  form.value = {
327
+    id: null,
328
+    recordDate: null,
329
+    timeSlot: null,
330
+    // T1区域数据
331
+    t1Recall: null,
332
+    t1No3c: null,
333
+    t1UnclearMark: null,
334
+    t1ExcessQty: null,
335
+    t1Mail: null,
336
+    t1Abandon: null,
337
+    t1TempStore: null,
338
+    // T2区域数据
339
+    t2Recall: null,
340
+    t2No3c: null,
341
+    t2UnclearMark: null,
342
+    t2ExcessQty: null,
343
+    t2Mail: null,
344
+    t2Abandon: null,
345
+    t2TempStore: null
346
+  }
347
+  proxy.resetForm("discouragePowerBanksDataRef")
348
+}
349
+
350
+/** 搜索按钮操作 */
351
+function handleQuery() {
352
+  queryParams.value.pageNum = 1
353
+  getList()
354
+}
355
+
356
+/** 重置按钮操作 */
357
+function resetQuery() {
358
+  proxy.resetForm("queryRef")
359
+  handleQuery()
360
+}
361
+
362
+// 多选框选中数据
363
+function handleSelectionChange(selection) {
364
+  ids.value = selection.map(item => item.id)
365
+  single.value = selection.length != 1
366
+  multiple.value = !selection.length
367
+}
368
+
369
+/** 新增按钮操作 */
370
+function handleAdd() {
371
+  reset()
372
+  open.value = true
373
+  title.value = "添加劝阻充电宝数据"
374
+}
375
+
376
+/** 修改按钮操作 */
377
+function handleUpdate(row) {
378
+  reset()
379
+  const _id = row.id || ids.value
380
+  getDiscouragePowerBanksData(_id).then(response => {
381
+    const data = response.data
382
+    // 转换时间段字符串为数组格式
383
+    if (data.timeSlot && typeof data.timeSlot === 'string' && data.timeSlot.includes('-')) {
384
+      data.timeSlot = data.timeSlot.split('-')
385
+    }
386
+    form.value = data
387
+    open.value = true
388
+    title.value = "修改劝阻充电宝数据"
389
+  })
390
+}
391
+
392
+/** 提交按钮 */
393
+function submitForm() {
394
+  proxy.$refs["discouragePowerBanksDataRef"].validate(valid => {
395
+    if (valid) {
396
+      const submitData = { ...form.value }
397
+      // 转换时间段为字符串格式 08:00-17:00
398
+      if (submitData.timeSlot && Array.isArray(submitData.timeSlot)) {
399
+        submitData.timeSlot = submitData.timeSlot.join('-')
400
+      }
401
+      if (submitData.id != null) {
402
+        updateDiscouragePowerBanksData(submitData).then(response => {
403
+          proxy.$modal.msgSuccess("修改成功")
404
+          open.value = false
405
+          getList()
406
+        })
407
+      } else {
408
+        addDiscouragePowerBanksData(submitData).then(response => {
409
+          proxy.$modal.msgSuccess("新增成功")
410
+          open.value = false
411
+          getList()
412
+        })
413
+      }
414
+    }
415
+  })
416
+}
417
+
418
+/** 删除按钮操作 */
419
+function handleDelete(row) {
420
+  const _ids = row.id || ids.value
421
+  proxy.$modal.confirm('是否确认删除数据项?').then(function () {
422
+    return delDiscouragePowerBanksData(_ids)
423
+  }).then(() => {
424
+    getList()
425
+    proxy.$modal.msgSuccess("删除成功")
426
+  }).catch(() => { })
427
+}
428
+
429
+/** 导出按钮操作 */
430
+function handleExport() {
431
+  // 过滤掉值为null的参数,但保留分页参数
432
+  const filteredParams = Object.fromEntries(
433
+    Object.entries(queryParams.value).filter(([key, value]) => {
434
+      // 保留分页参数
435
+      if (key === 'pageNum' || key === 'pageSize') return true
436
+      // 过滤掉其他为null的参数
437
+      return value !== null
438
+    })
439
+  )
440
+  
441
+  proxy.download('/item/hkPersuadePowerBank/export', filteredParams, `discouragePowerBanksData_${new Date().getTime()}.xlsx`)
442
+}
443
+
444
+/** 导入按钮操作 */
445
+function handleImport() {
446
+  upload.title = "劝阻充电宝数据导入"
447
+  upload.open = true
448
+}
449
+
450
+/** 下载模板操作 */
451
+function importTemplate() {
452
+  proxy.download('/item/hkPersuadePowerBank/importTemplate', {
453
+  }, `劝阻充电宝数据导入模板_${new Date().getTime()}.xlsx`)
454
+}
455
+
456
+/** 文件上传中处理 */
457
+const handleFileUploadProgress = (event, file, fileList) => {
458
+  upload.isUploading = true
459
+}
460
+
461
+/** 文件上传成功处理 */
462
+const handleFileSuccess = (response, file, fileList) => {
463
+  upload.open = false
464
+  upload.isUploading = false
465
+  uploadRef.value.handleRemove(file)
466
+  proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
467
+  getList()
468
+}
469
+
470
+/** 提交上传文件 */
471
+function submitFileForm() {
472
+  uploadRef.value.submit()
473
+}
474
+
475
+getList()
476
+</script>

+ 0 - 0
src/views/runData/discouragePowerBanksData/劝阻充电宝数据


+ 834 - 0
src/views/runData/runScreen/index.vue

@@ -0,0 +1,834 @@
1
+<template>
2
+  <div class="run-screen-container">
3
+    <!-- 页面标题 -->
4
+    <div class="page-title">
5
+      <h1>盛世鹰眸质控系统[生产运行](安检站)</h1>
6
+    </div>
7
+
8
+    <!-- 模块一:运行数据 -->
9
+    <div class="module-title-wrapper">
10
+      <div class="module-title">模块一:运行数据</div>
11
+    </div>
12
+
13
+
14
+
15
+    <!-- 第一行 -->
16
+    <el-row :gutter="20" class="row-margin">
17
+      <!-- 左边50%:两个div -->
18
+      <el-col :span="12">
19
+        <el-row :gutter="20" style="height: 100%;">
20
+          <el-col :span="12">
21
+            <div class="data-card">
22
+              <div class="card-title">旅检过检总人数</div>
23
+              <div class="card-value-wrapper" style="color: #E8B140;">
24
+                <span class="card-value">{{ runData.passengerTotal }}</span>
25
+                <span class="card-unit">人</span>
26
+              </div>
27
+            </div>
28
+          </el-col>
29
+          <el-col :span="12">
30
+            <div class="data-card">
31
+              <div class="card-title">行检过检总行李数</div>
32
+              <div class="card-value-wrapper" style="color: #26B6BE;">
33
+                <span class="card-value">{{ runData.luggageTotal }}</span>
34
+                <span class="card-unit">件</span>
35
+              </div>
36
+            </div>
37
+          </el-col>
38
+        </el-row>
39
+      </el-col>
40
+      <!-- 右边50%:T1旅检过检人数折线图 -->
41
+      <el-col :span="12">
42
+        <div class="chart-card">
43
+          <div class="chart-title">T1旅检过检人数</div>
44
+          <div ref="t1TravelChart" class="chart-container"></div>
45
+        </div>
46
+      </el-col>
47
+    </el-row>
48
+
49
+    <!-- 第二行 -->
50
+    <el-row :gutter="20" class="row-margin">
51
+      <el-col :span="12">
52
+        <div class="chart-card">
53
+          <div class="chart-title">T2旅检过检人数</div>
54
+          <div ref="t2TravelChart" class="chart-container"></div>
55
+        </div>
56
+      </el-col>
57
+      <el-col :span="12">
58
+        <div class="chart-card">
59
+          <div class="chart-title">行检过检数</div>
60
+          <div ref="luggageChart" class="chart-container"></div>
61
+        </div>
62
+      </el-col>
63
+    </el-row>
64
+
65
+    <!-- 第三行 -->
66
+    <el-row :gutter="20" class="row-margin">
67
+      <el-col :span="8">
68
+        <div class="data-card">
69
+          <div class="card-title">国内货站总过检数</div>
70
+          <div class="card-value-wrapper" style="color: #E8B140;padding: 30px;">
71
+            <span class="card-value">{{ runData.domesticCargoTotal }}</span>
72
+            <span class="card-unit">件</span>
73
+          </div>
74
+        </div>
75
+      </el-col>
76
+      <el-col :span="8">
77
+        <div class="data-card">
78
+          <div class="card-title">国际货站总过检数</div>
79
+          <div class="card-value-wrapper" style="color: #26B6BE;padding: 30px;">
80
+            <span class="card-value">{{ runData.intlCargoTotal }}</span>
81
+            <span class="card-unit">件</span>
82
+          </div>
83
+        </div>
84
+      </el-col>
85
+      <el-col :span="8">
86
+        <div class="data-card">
87
+          <div class="card-title">道口车辆过检数</div>
88
+          <div class="card-value-wrapper" style="color: #5680C9;padding: 30px;">
89
+            <span class="card-value">{{ runData.vehicleCheckTotal }}</span>
90
+            <span class="card-unit">辆</span>
91
+          </div>
92
+        </div>
93
+      </el-col>
94
+    </el-row>
95
+
96
+    <!-- 第四行 -->
97
+    <el-row :gutter="20" class="row-margin">
98
+      <el-col :span="12">
99
+        <div class="chart-card">
100
+          <div class="chart-title">货物过检数</div>
101
+          <div ref="cargoChart" class="chart-container"></div>
102
+        </div>
103
+      </el-col>
104
+      <el-col :span="12">
105
+        <div class="chart-card">
106
+          <div class="chart-title">车辆过检数</div>
107
+          <div ref="vehicleChart" class="chart-container"></div>
108
+        </div>
109
+      </el-col>
110
+    </el-row>
111
+
112
+
113
+    <!-- 模块二:查获/收缴数据 -->
114
+    <div class="module-title-wrapper">
115
+      <div class="module-title">模块二:查获/收缴数据</div>
116
+    </div>
117
+
118
+
119
+
120
+    <!-- 第一行 -->
121
+    <el-row :gutter="20" class="row-margin">
122
+      <el-col :span="12">
123
+        <div class="chart-card">
124
+          <div class="chart-title">查获数据</div>
125
+          <div ref="seizePieChart" class="chart-container"></div>
126
+        </div>
127
+      </el-col>
128
+      <el-col :span="12">
129
+        <div class="chart-card">
130
+          <div class="chart-title">大队查获数对比图</div>
131
+          <div ref="teamSeizeBarChart" class="chart-container"></div>
132
+        </div>
133
+      </el-col>
134
+    </el-row>
135
+
136
+    <!-- 第二行 -->
137
+    <el-row :gutter="20" class="row-margin">
138
+      <el-col :span="12">
139
+        <div class="chart-card">
140
+          <div class="chart-title">T1区域各大队查获数对比图</div>
141
+          <div ref="t1TeamBarChart" class="chart-container"></div>
142
+        </div>
143
+      </el-col>
144
+      <el-col :span="12">
145
+        <div class="chart-card">
146
+          <div class="chart-title">T2区域各大队查获数对比图</div>
147
+          <div ref="t2TeamBarChart" class="chart-container"></div>
148
+        </div>
149
+      </el-col>
150
+    </el-row>
151
+
152
+    <!-- 第三行 -->
153
+    <el-row :gutter="20" class="row-margin">
154
+      <el-col :span="12">
155
+        <div class="chart-card">
156
+          <div class="chart-title">不合格充电宝劝阻数组</div>
157
+          <div ref="powerBankPieChart" class="chart-container"></div>
158
+        </div>
159
+      </el-col>
160
+      <el-col :span="12">
161
+        <div class="chart-card">
162
+          <div class="chart-title">待检区收缴禁限带物品数据表</div>
163
+          <div ref="waitingAreaPieChart" class="chart-container"></div>
164
+        </div>
165
+      </el-col>
166
+    </el-row>
167
+
168
+  </div>
169
+</template>
170
+
171
+<script setup name="RunScreen">
172
+import { ref, onMounted, onUnmounted, nextTick } from 'vue'
173
+import * as echarts from 'echarts'
174
+import {
175
+  getOperationSummary,
176
+  getT1PassengerTrend,
177
+  getT2PassengerTrend,
178
+  getLuggageCheckTrend,
179
+  getCargoTrend,
180
+  getVehicleCheckTrend,
181
+  getSeizureCategory,
182
+  getBrigadeSeizureCompare,
183
+  getPowerBankSummary,
184
+  getPendingConfiscate
185
+} from '@/api/runData/runScreen.js'
186
+
187
+// 图表引用
188
+const t1TravelChart = ref(null)
189
+const t2TravelChart = ref(null)
190
+const luggageChart = ref(null)
191
+const cargoChart = ref(null)
192
+const vehicleChart = ref(null)
193
+const seizePieChart = ref(null)
194
+const teamSeizeBarChart = ref(null)
195
+const t1TeamBarChart = ref(null)
196
+const t2TeamBarChart = ref(null)
197
+const powerBankPieChart = ref(null)
198
+const waitingAreaPieChart = ref(null)
199
+
200
+// 图表实例
201
+let t1TravelChartInstance = null
202
+let t2TravelChartInstance = null
203
+let luggageChartInstance = null
204
+let cargoChartInstance = null
205
+let vehicleChartInstance = null
206
+let seizePieChartInstance = null
207
+let teamSeizeBarChartInstance = null
208
+let t1TeamBarChartInstance = null
209
+let t2TeamBarChartInstance = null
210
+let powerBankPieChartInstance = null
211
+let waitingAreaPieChartInstance = null
212
+
213
+// 运行数据
214
+const runData = ref({
215
+  travelInspectionTotal: 0,
216
+  luggageInspectionTotal: 0,
217
+  domesticCargoTotal: 0,
218
+  internationalCargoTotal: 0,
219
+  vehicleInspectionTotal: 0
220
+})
221
+
222
+const t1PassengerData = ref([])
223
+const t2PassengerData = ref([])
224
+const luggageCheckData = ref([])
225
+const cargoData = ref([])
226
+const vehicleCheckData = ref([])
227
+const seizureCategoryData = ref([])
228
+const brigadeSeizureData = ref([])
229
+const powerBankData = ref({})
230
+const pendingConfiscateData = ref({})
231
+
232
+async function loadData() {
233
+  try {
234
+    const query = {}
235
+    
236
+    const [
237
+      summaryRes,
238
+      t1PassengerRes,
239
+      t2PassengerRes,
240
+      luggageRes,
241
+      cargoRes,
242
+      vehicleRes,
243
+      seizureRes,
244
+      brigadeRes,
245
+      powerBankRes,
246
+      pendingRes
247
+    ] = await Promise.all([
248
+      getOperationSummary(query),
249
+      getT1PassengerTrend(query),
250
+      getT2PassengerTrend(query),
251
+      getLuggageCheckTrend(query),
252
+      getCargoTrend(query),
253
+      getVehicleCheckTrend(query),
254
+      getSeizureCategory(query),
255
+      getBrigadeSeizureCompare(query),
256
+      getPowerBankSummary(query),
257
+      getPendingConfiscate(query)
258
+    ])
259
+    
260
+    if (summaryRes.data) {
261
+      runData.value = summaryRes.data
262
+    }
263
+    
264
+    if (t1PassengerRes.data) {
265
+      t1PassengerData.value = t1PassengerRes.data
266
+    }
267
+    
268
+    if (t2PassengerRes.data) {
269
+      t2PassengerData.value = t2PassengerRes.data
270
+    }
271
+    
272
+    if (luggageRes.data) {
273
+      luggageCheckData.value = luggageRes.data
274
+    }
275
+    
276
+    if (cargoRes.data) {
277
+      cargoData.value = cargoRes.data
278
+    }
279
+    
280
+    if (vehicleRes.data) {
281
+      vehicleCheckData.value = vehicleRes.data
282
+    }
283
+    
284
+    if (seizureRes.data) {
285
+      seizureCategoryData.value = seizureRes.data
286
+    }
287
+    
288
+    if (brigadeRes.data) {
289
+      brigadeSeizureData.value = brigadeRes.data
290
+    }
291
+    
292
+    if (powerBankRes.data) {
293
+      powerBankData.value = powerBankRes.data
294
+    }
295
+    
296
+    if (pendingRes.data) {
297
+      pendingConfiscateData.value = pendingRes.data
298
+    }
299
+    
300
+    nextTick(() => {
301
+      initCharts()
302
+    })
303
+  } catch (error) {
304
+    console.error('加载数据失败:', error)
305
+  }
306
+}
307
+
308
+// 初始化所有图表
309
+function initCharts() {
310
+  // T1旅检过检人数折线图
311
+  if (t1TravelChart.value) {
312
+    t1TravelChartInstance = echarts.init(t1TravelChart.value)
313
+    const t1Data = t1PassengerData.value || []
314
+    t1TravelChartInstance.setOption({
315
+      tooltip: { trigger: 'axis' },
316
+      legend: { data: ['A区', 'B区'], top: 30 },
317
+      xAxis: {
318
+        type: 'category',
319
+        data: t1Data.map(item => item.recordDate || item.azone || '')
320
+      },
321
+      yAxis: { type: 'value' },
322
+      series: [
323
+        {
324
+          name: 'A区',
325
+          data: t1Data.map(item => item.azone || 0),
326
+          type: 'line',
327
+          smooth: true,
328
+          lineStyle: { color: '#E8B140' },
329
+          areaStyle: { color: 'rgba(232, 177, 64, 0.2)' }
330
+        },
331
+        {
332
+          name: 'B区',
333
+          data: t1Data.map(item => item.bzone || 0),
334
+          type: 'line',
335
+          smooth: true,
336
+          lineStyle: { color: '#5470c6' },
337
+          areaStyle: { color: 'rgba(84, 112, 198, 0.2)' }
338
+        }
339
+      ]
340
+    })
341
+  }
342
+
343
+  // T2旅检过检人数折线图
344
+  if (t2TravelChart.value) {
345
+    t2TravelChartInstance = echarts.init(t2TravelChart.value)
346
+    const t2Data = t2PassengerData.value || []
347
+    t2TravelChartInstance.setOption({
348
+      tooltip: { trigger: 'axis' },
349
+      legend: { data: ['国内旅检', '国际旅检'], top: 30 },
350
+      xAxis: {
351
+        type: 'category',
352
+        data: t2Data.map(item => item.recordDate || '')
353
+      },
354
+      yAxis: { type: 'value' },
355
+      series: [
356
+        {
357
+          name: '国内旅检',
358
+          data: t2Data.map(item => item.domesticPassenger || 0),
359
+          type: 'line',
360
+          smooth: true,
361
+          lineStyle: { color: '#91cc75' },
362
+          areaStyle: { color: 'rgba(145, 204, 117, 0.2)' }
363
+        },
364
+        {
365
+          name: '国际旅检',
366
+          data: t2Data.map(item => item.intlPassenger || 0),
367
+          type: 'line',
368
+          smooth: true,
369
+          lineStyle: { color: '#fac858' },
370
+          areaStyle: { color: 'rgba(250, 200, 88, 0.2)' }
371
+        }
372
+      ]
373
+    })
374
+  }
375
+
376
+  // 行检过检数折线图
377
+  if (luggageChart.value) {
378
+    luggageChartInstance = echarts.init(luggageChart.value)
379
+    const luggageData = luggageCheckData.value || []
380
+    luggageChartInstance.setOption({
381
+      tooltip: { trigger: 'axis' },
382
+      legend: { data: ['T1行检', 'T2行检'], top: 30 },
383
+      xAxis: {
384
+        type: 'category',
385
+        data: luggageData.map(item => item.recordDate || '')
386
+      },
387
+      yAxis: { type: 'value' },
388
+      series: [
389
+        {
390
+          name: 'T1行检',
391
+          data: luggageData.map(item => item.t1LuggageCheck || 0),
392
+          type: 'line',
393
+          smooth: true,
394
+          lineStyle: { color: '#ee6666' },
395
+          areaStyle: { color: 'rgba(238, 102, 102, 0.2)' }
396
+        },
397
+        {
398
+          name: 'T2行检',
399
+          data: luggageData.map(item => item.t2LuggageCheck || 0),
400
+          type: 'line',
401
+          smooth: true,
402
+          lineStyle: { color: '#73c0de' },
403
+          areaStyle: { color: 'rgba(115, 192, 222, 0.2)' }
404
+        }
405
+      ]
406
+    })
407
+  }
408
+
409
+  // 货物过检数折线图
410
+  if (cargoChart.value) {
411
+    cargoChartInstance = echarts.init(cargoChart.value)
412
+    const cargoTrendData = cargoData.value || []
413
+    cargoChartInstance.setOption({
414
+      tooltip: { trigger: 'axis' },
415
+      legend: { data: ['国内货站', '国际货站'], top: 30 },
416
+      xAxis: {
417
+        type: 'category',
418
+        data: cargoTrendData.map(item => item.recordDate || '')
419
+      },
420
+      yAxis: { type: 'value' },
421
+      series: [
422
+        {
423
+          name: '国内货站',
424
+          data: cargoTrendData.map(item => item.domesticCargo || 0),
425
+          type: 'line',
426
+          smooth: true,
427
+          lineStyle: { color: '#E8B140' },
428
+          areaStyle: { color: 'rgba(232, 177, 64, 0.2)' }
429
+        },
430
+        {
431
+          name: '国际货站',
432
+          data: cargoTrendData.map(item => item.intlCargo || 0),
433
+          type: 'line',
434
+          smooth: true,
435
+          lineStyle: { color: '#26B6BE' },
436
+          areaStyle: { color: 'rgba(38, 182, 190, 0.2)' }
437
+        }
438
+      ]
439
+    })
440
+  }
441
+
442
+  // 车辆过检数折线图
443
+  if (vehicleChart.value) {
444
+    vehicleChartInstance = echarts.init(vehicleChart.value)
445
+    const vehicleData = vehicleCheckData.value || []
446
+    vehicleChartInstance.setOption({
447
+      tooltip: { trigger: 'axis' },
448
+      legend: { data: ['南侧车检', '北侧车检'], top: 30 },
449
+      xAxis: {
450
+        type: 'category',
451
+        data: vehicleData.map(item => item.recordDate || '')
452
+      },
453
+      yAxis: { type: 'value' },
454
+      series: [
455
+        {
456
+          name: '南侧车检',
457
+          data: vehicleData.map(item => item.southVehicleCheck || 0),
458
+          type: 'line',
459
+          smooth: true,
460
+          lineStyle: { color: '#E8B140' },
461
+          areaStyle: { color: 'rgba(232, 177, 64, 0.2)' }
462
+        },
463
+        {
464
+          name: '北侧车检',
465
+          data: vehicleData.map(item => item.northVehicleCheck || 0),
466
+          type: 'line',
467
+          smooth: true,
468
+          lineStyle: { color: '#5470c6' },
469
+          areaStyle: { color: 'rgba(84, 112, 198, 0.2)' }
470
+        }
471
+      ]
472
+    })
473
+  }
474
+
475
+  // 查获数据环形图
476
+  if (seizePieChart.value) {
477
+    seizePieChartInstance = echarts.init(seizePieChart.value)
478
+    const seizureData = seizureCategoryData.value || []
479
+    seizePieChartInstance.setOption({
480
+      tooltip: { trigger: 'item' },
481
+      legend: { orient: 'vertical', right: 10, top: 'center' },
482
+      series: [{
483
+        name: '查获数据',
484
+        type: 'pie',
485
+        radius: ['40%', '70%'],
486
+        center: ['40%', '50%'],
487
+        data: seizureData.map(item => ({ name: item.name, value: item.total })),
488
+        emphasis: {
489
+          itemStyle: {
490
+            shadowBlur: 10,
491
+            shadowOffsetX: 0,
492
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
493
+          }
494
+        }
495
+      }]
496
+    })
497
+  }
498
+
499
+  // 大队查获数对比柱状图
500
+  if (teamSeizeBarChart.value) {
501
+    teamSeizeBarChartInstance = echarts.init(teamSeizeBarChart.value)
502
+    const brigadeData = brigadeSeizureData.value || []
503
+    const shifts = [...new Set(brigadeData.map(item => item.shift))]
504
+    const brigades = [...new Set(brigadeData.map(item => item.brigade))]
505
+    const series = brigades.map(brigade => ({
506
+      name: brigade,
507
+      data: shifts.map(shift => {
508
+        const item = brigadeData.find(d => d.shift === shift && d.brigade === brigade)
509
+        return item ? item.grandTotal : 0
510
+      }),
511
+      type: 'bar'
512
+    }))
513
+    teamSeizeBarChartInstance.setOption({
514
+      tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
515
+      legend: { data: brigades, top: 30 },
516
+      xAxis: {
517
+        type: 'category',
518
+        data: shifts
519
+      },
520
+      yAxis: { type: 'value' },
521
+      series: series
522
+    })
523
+  }
524
+
525
+  // T1区域各大队查获数对比柱状图
526
+  if (t1TeamBarChart.value) {
527
+    t1TeamBarChartInstance = echarts.init(t1TeamBarChart.value)
528
+    const brigadeData = brigadeSeizureData.value || []
529
+    const shifts = [...new Set(brigadeData.map(item => item.shift))]
530
+    const brigades = [...new Set(brigadeData.map(item => item.brigade))]
531
+    const series = brigades.map(brigade => ({
532
+      name: brigade,
533
+      data: shifts.map(shift => {
534
+        const item = brigadeData.find(d => d.shift === shift && d.brigade === brigade)
535
+        return item ? item.t1Total : 0
536
+      }),
537
+      type: 'bar'
538
+    }))
539
+    t1TeamBarChartInstance.setOption({
540
+      tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
541
+      legend: { data: brigades, top: 30 },
542
+      xAxis: {
543
+        type: 'category',
544
+        data: shifts
545
+      },
546
+      yAxis: { type: 'value' },
547
+      series: series
548
+    })
549
+  }
550
+
551
+  // T2区域各大队查获数对比柱状图
552
+  if (t2TeamBarChart.value) {
553
+    t2TeamBarChartInstance = echarts.init(t2TeamBarChart.value)
554
+    const brigadeData = brigadeSeizureData.value || []
555
+    const shifts = [...new Set(brigadeData.map(item => item.shift))]
556
+    const brigades = [...new Set(brigadeData.map(item => item.brigade))]
557
+    const series = brigades.map(brigade => ({
558
+      name: brigade,
559
+      data: shifts.map(shift => {
560
+        const item = brigadeData.find(d => d.shift === shift && d.brigade === brigade)
561
+        return item ? item.t2Total : 0
562
+      }),
563
+      type: 'bar'
564
+    }))
565
+    t2TeamBarChartInstance.setOption({
566
+      tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
567
+      legend: { data: brigades, top: 30 },
568
+      xAxis: {
569
+        type: 'category',
570
+        data: shifts
571
+      },
572
+      yAxis: { type: 'value' },
573
+      series: series
574
+    })
575
+  }
576
+
577
+  // 不合格充电宝劝阻数组环形图
578
+  if (powerBankPieChart.value) {
579
+    powerBankPieChartInstance = echarts.init(powerBankPieChart.value)
580
+    const pbData = powerBankData.value || {}
581
+    const powerBankChartData = [
582
+      { name: '邮寄', value: pbData.mailTotal || 0 },
583
+      { name: '暂存', value: pbData.tempStoreTotal || 0 },
584
+      { name: '自弃', value: pbData.abandonTotal || 0 },
585
+      { name: '召回', value: pbData.recallTotal || 0 },
586
+      { name: '无3C标识', value: pbData.no3cTotal || 0 },
587
+      { name: '标识不清', value: pbData.unclearMarkTotal || 0 },
588
+      { name: '超规数量', value: pbData.excessQtyTotal || 0 },
589
+      { name: '其他', value: pbData.bothTotal || 0 }
590
+    ].filter(item => item.value > 0)
591
+    
592
+    powerBankPieChartInstance.setOption({
593
+      tooltip: { trigger: 'item' },
594
+      legend: { orient: 'vertical', right: 10, top: 'center' },
595
+      series: [{
596
+        name: '不合格充电宝',
597
+        type: 'pie',
598
+        radius: ['40%', '70%'],
599
+        center: ['40%', '50%'],
600
+        data: powerBankChartData,
601
+        emphasis: {
602
+          itemStyle: {
603
+            shadowBlur: 10,
604
+            shadowOffsetX: 0,
605
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
606
+          }
607
+        }
608
+      }]
609
+    })
610
+  }
611
+
612
+  // 待检区收缴禁限带物品数据表环形图
613
+  if (waitingAreaPieChart.value) {
614
+    waitingAreaPieChartInstance = echarts.init(waitingAreaPieChart.value)
615
+    const pendingData = pendingConfiscateData.value || {}
616
+    const pendingChartData = [
617
+      { name: '火种', value: pendingData.fireSourceTotal || 0 },
618
+      { name: '液态物品', value: pendingData.liquidTotal || 0 },
619
+      { name: '其他', value: pendingData.otherTotal || 0 }
620
+    ].filter(item => item.value > 0)
621
+    
622
+    waitingAreaPieChartInstance.setOption({
623
+      tooltip: { trigger: 'item' },
624
+      legend: { orient: 'vertical', right: 10, top: 'center' },
625
+      series: [{
626
+        name: '禁限带物品',
627
+        type: 'pie',
628
+        radius: ['40%', '70%'],
629
+        center: ['40%', '50%'],
630
+        data: pendingChartData,
631
+        emphasis: {
632
+          itemStyle: {
633
+            shadowBlur: 10,
634
+            shadowOffsetX: 0,
635
+            shadowColor: 'rgba(0, 0, 0, 0.5)'
636
+          }
637
+        }
638
+      }]
639
+    })
640
+  }
641
+}
642
+
643
+// 窗口大小变化时重新调整图表大小
644
+function handleResize() {
645
+  const charts = [
646
+    t1TravelChartInstance, t2TravelChartInstance, luggageChartInstance,
647
+    cargoChartInstance, vehicleChartInstance, seizePieChartInstance,
648
+    teamSeizeBarChartInstance, t1TeamBarChartInstance, t2TeamBarChartInstance,
649
+    powerBankPieChartInstance, waitingAreaPieChartInstance
650
+  ]
651
+
652
+  charts.forEach(chart => {
653
+    if (chart) {
654
+      chart.resize()
655
+    }
656
+  })
657
+}
658
+
659
+// 组件挂载时初始化图表
660
+onMounted(() => {
661
+  loadData()
662
+  window.addEventListener('resize', handleResize)
663
+})
664
+
665
+// 组件卸载时销毁图表
666
+onUnmounted(() => {
667
+  const charts = [
668
+    t1TravelChartInstance, t2TravelChartInstance, luggageChartInstance,
669
+    cargoChartInstance, vehicleChartInstance, seizePieChartInstance,
670
+    teamSeizeBarChartInstance, t1TeamBarChartInstance, t2TeamBarChartInstance,
671
+    powerBankPieChartInstance, waitingAreaPieChartInstance
672
+  ]
673
+
674
+  charts.forEach(chart => {
675
+    if (chart) {
676
+      chart.dispose()
677
+    }
678
+  })
679
+
680
+  window.removeEventListener('resize', handleResize)
681
+})
682
+</script>
683
+
684
+<style scoped>
685
+.run-screen-container {
686
+  padding: 20px;
687
+  background: #f0f2f5;
688
+  min-height: 100vh;
689
+}
690
+
691
+.page-title {
692
+  text-align: center;
693
+  margin-bottom: 30px;
694
+}
695
+
696
+.page-title h1 {
697
+  font-size: 28px;
698
+  color: #333;
699
+  font-weight: bold;
700
+  margin: 0;
701
+}
702
+
703
+.module-title-wrapper {
704
+  text-align: center;
705
+  width: 100%;
706
+  background: #fff;
707
+  border-radius: 8px;
708
+  padding: 15px 20px;
709
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
710
+  margin-bottom: 20px;
711
+}
712
+
713
+.module-title {
714
+  font-size: 20px;
715
+  font-weight: bold;
716
+  color: #333;
717
+  margin: 0;
718
+}
719
+
720
+.module-section {
721
+  width: 100%;
722
+  background: #fff;
723
+  border-radius: 8px;
724
+  padding: 20px;
725
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
726
+  margin-bottom: 20px;
727
+}
728
+
729
+.row-margin {
730
+  margin-bottom: 20px;
731
+}
732
+
733
+.data-card {
734
+  background: #fff;
735
+  border-radius: 8px;
736
+  padding: 15px;
737
+  color: #333;
738
+  height: 100%;
739
+
740
+
741
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
742
+  border: 1px solid #e6e8eb;
743
+}
744
+
745
+.card-title {
746
+  font-size: 16px;
747
+  color: #333;
748
+  font-weight: bold;
749
+  text-align: left;
750
+}
751
+
752
+.card-value-wrapper {
753
+  height: 100%;
754
+  display: flex;
755
+  flex-direction: column;
756
+  align-items: center;
757
+  justify-content: center;
758
+}
759
+
760
+.card-value {
761
+  font-size: 50px;
762
+  font-weight: bold;
763
+
764
+}
765
+
766
+.card-unit {
767
+  font-size: 16px;
768
+
769
+}
770
+
771
+.chart-card {
772
+  background: #fff;
773
+  border-radius: 8px;
774
+  padding: 15px;
775
+  border: 1px solid #e6e8eb;
776
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
777
+  height: 300px;
778
+}
779
+
780
+.chart-title {
781
+  font-size: 16px;
782
+  font-weight: bold;
783
+  color: #333;
784
+  margin-bottom: 15px;
785
+  text-align: left;
786
+}
787
+
788
+.chart-container {
789
+  width: 100%;
790
+  height: calc(100% - 30px);
791
+}
792
+
793
+/* 响应式设计 */
794
+@media (max-width: 1200px) {
795
+  .data-card {
796
+    height: 100px;
797
+  }
798
+
799
+  .card-value {
800
+    font-size: 30px;
801
+  }
802
+
803
+  .chart-card {
804
+    height: 250px;
805
+  }
806
+}
807
+
808
+@media (max-width: 768px) {
809
+  .run-screen-container {
810
+    padding: 10px;
811
+  }
812
+
813
+  .module-section {
814
+    padding: 15px;
815
+  }
816
+
817
+  .data-card {
818
+    height: 80px;
819
+    padding: 15px;
820
+  }
821
+
822
+  .card-title {
823
+    font-size: 14px;
824
+  }
825
+
826
+  .card-value {
827
+    font-size: 20px;
828
+  }
829
+
830
+  .chart-card {
831
+    height: 200px;
832
+  }
833
+}
834
+</style>

+ 624 - 0
src/views/runData/seizeData/index.vue

@@ -0,0 +1,624 @@
1
+<template>
2
+  <div class="app-container">
3
+    <!-- 查询条件 -->
4
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
5
+      <el-form-item label="日期" prop="recordDate">
6
+        <el-date-picker v-model="queryParams.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD" 
7
+          style="width: 200px" />
8
+      </el-form-item>
9
+      <el-form-item label="班次" prop="shift">
10
+        <el-select v-model="queryParams.shift" placeholder="请选择班次" clearable style="width: 200px">
11
+          <el-option v-for="item in shiftOptions" :key="item.value" :label="item.label" :value="item.value" />
12
+        </el-select>
13
+      </el-form-item>
14
+      <el-form-item label="当班大队" prop="brigade">
15
+        <el-select v-model="queryParams.brigade" placeholder="请选择当班大队" clearable style="width: 200px">
16
+          <el-option v-for="item in brigadeOptions" :key="item.value" :label="item.label" :value="item.label" />
17
+        </el-select>
18
+      </el-form-item>
19
+      <el-form-item>
20
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
21
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
22
+      </el-form-item>
23
+    </el-form>
24
+
25
+    <!-- 按钮区域 -->
26
+    <el-row :gutter="10" class="mb8">
27
+      <el-col :span="1.5">
28
+        <el-button type="primary" plain icon="Plus" @click="handleAdd"
29
+          v-hasPermi="['runData:seizeData:add']">新增</el-button>
30
+      </el-col>
31
+
32
+      <el-col :span="1.5">
33
+        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
34
+          v-hasPermi="['runData:seizeData:remove']">删除</el-button>
35
+      </el-col>
36
+      <el-col :span="1.5">
37
+        <el-button type="info" plain icon="Upload" @click="handleImport"
38
+          v-hasPermi="['runData:seizeData:import']">导入</el-button>
39
+      </el-col>
40
+      <el-col :span="1.5">
41
+        <el-button type="warning" plain icon="Download" @click="handleExport"
42
+          v-hasPermi="['runData:seizeData:export']">导出</el-button>
43
+      </el-col>
44
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
45
+    </el-row>
46
+
47
+    <!-- 数据表格 -->
48
+    <el-table v-loading="loading" :data="seizeDataList" @selection-change="handleSelectionChange">
49
+      <el-table-column type="selection" width="55" align="center" />
50
+      <el-table-column label="日期" align="center" prop="recordDate" />
51
+      <el-table-column label="班次" align="center" prop="shift" />
52
+      <el-table-column label="当班大队" align="center" prop="brigade" />
53
+      
54
+      <!-- T1区域数据 -->
55
+      <el-table-column label="T1火种" align="center" prop="t1FireSource" />
56
+      <el-table-column label="T1刀具" align="center" prop="t1Knife" />
57
+      <el-table-column label="T1警械器具" align="center" prop="t1PoliceWeapon" />
58
+      <el-table-column label="T1烟花爆竹" align="center" prop="t1Firework" />
59
+      <el-table-column label="T1活体动物" align="center" prop="t1LiveAnimal" />
60
+      <el-table-column label="T1腐蚀性物品" align="center" prop="t1Corrosive" />
61
+      <el-table-column label="T1用假冒他" align="center" prop="t1FakeId" />
62
+      <el-table-column label="T1爆炸装置" align="center" prop="t1Explosive" />
63
+      <el-table-column label="T1工具" align="center" prop="t1Tool" />
64
+      <el-table-column label="T1枪支弹药" align="center" prop="t1GunAmmo" />
65
+      <el-table-column label="T1扫黄打非" align="center" prop="t1Illegal" />
66
+      <el-table-column label="T1其他" align="center" prop="t1Other" />
67
+      <el-table-column label="T1总数" align="center" prop="t1Total" />
68
+      
69
+      <!-- T2区域数据 -->
70
+      <el-table-column label="T2火种" align="center" prop="t2FireSource" />
71
+      <el-table-column label="T2刀具" align="center" prop="t2Knife" />
72
+      <el-table-column label="T2警械器具" align="center" prop="t2PoliceWeapon" />
73
+      <el-table-column label="T2烟花爆竹" align="center" prop="t2Firework" />
74
+      <el-table-column label="T2活体动物" align="center" prop="t2LiveAnimal" />
75
+      <el-table-column label="T2腐蚀性物品" align="center" prop="t2Corrosive" />
76
+      <el-table-column label="T2用假冒他" align="center" prop="t2FakeId" />
77
+      <el-table-column label="T2爆炸装置" align="center" prop="t2Explosive" />
78
+      <el-table-column label="T2工具" align="center" prop="t2Tool" />
79
+      <el-table-column label="T2枪支弹药" align="center" prop="t2GunAmmo" />
80
+      <el-table-column label="T2扫黄打非" align="center" prop="t2Illegal" />
81
+      <el-table-column label="T2其他" align="center" prop="t2Other" />
82
+      <el-table-column label="T2总数" align="center" prop="t2Total" />
83
+      
84
+      <el-table-column label="T1总数+T2总数" align="center" prop="total" />
85
+      
86
+      <el-table-column label="操作" align="center" width="180" class-name="small-padding fixed-width" fixed="right">  
87
+        <template #default="scope">
88
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
89
+            v-hasPermi="['runData:seizeData:edit']">修改</el-button>
90
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
91
+            v-hasPermi="['runData:seizeData:remove']">删除</el-button>
92
+        </template>
93
+      </el-table-column>
94
+    </el-table>
95
+
96
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
97
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
98
+
99
+    <!-- 添加或修改查获数据对话框 -->
100
+    <el-dialog :title="title" v-model="open" width="1000px" append-to-body>
101
+      <el-form ref="seizeDataRef" :model="form" :rules="rules" label-width="120px">
102
+        <el-row :gutter="20">
103
+          <el-col :span="8">
104
+            <el-form-item label="日期" prop="recordDate">
105
+              <el-date-picker v-model="form.recordDate" type="date" placeholder="请选择日期" value-format="YYYY-MM-DD" 
106
+                style="width: 100%" />
107
+            </el-form-item>
108
+          </el-col>
109
+          <el-col :span="8">
110
+            <el-form-item label="班次" prop="shift">
111
+              <el-select v-model="form.shift" placeholder="请选择班次" filterable style="width: 100%">
112
+                <el-option v-for="item in shiftOptions" :key="item.value" :label="item.label" :value="item.value" />
113
+              </el-select>
114
+            </el-form-item>
115
+          </el-col>
116
+          <el-col :span="8">
117
+            <el-form-item label="当班大队" prop="brigade">
118
+              <el-select v-model="form.brigade" placeholder="请选择当班大队" filterable style="width: 100%">
119
+                <el-option v-for="item in brigadeOptions" :key="item.value" :label="item.label" :value="item.label" />
120
+              </el-select>
121
+            </el-form-item>
122
+          </el-col>
123
+        </el-row>
124
+        
125
+        <!-- T1区域 -->
126
+        <el-divider content-position="left">T1区域数据</el-divider>
127
+        <el-row :gutter="20">
128
+          <el-col :span="8">
129
+            <el-form-item label="T1火种" prop="t1FireSource">
130
+              <el-input-number :precision="0" v-model="form.t1FireSource" :min="0" placeholder="请输入T1火种" style="width: 100%" @change="calculateTotals" />
131
+            </el-form-item>
132
+            <el-form-item label="T1刀具" prop="t1Knife">
133
+              <el-input-number :precision="0" v-model="form.t1Knife" :min="0" placeholder="请输入T1刀具" style="width: 100%" @change="calculateTotals" />
134
+            </el-form-item>
135
+            <el-form-item label="T1警械器具" prop="t1PoliceWeapon">
136
+              <el-input-number :precision="0" v-model="form.t1PoliceWeapon" :min="0" placeholder="请输入T1警械器具" style="width: 100%" @change="calculateTotals" />
137
+            </el-form-item>
138
+            <el-form-item label="T1烟花爆竹" prop="t1Firework">
139
+              <el-input-number :precision="0" v-model="form.t1Firework" :min="0" placeholder="请输入T1烟花爆竹" style="width: 100%" @change="calculateTotals" />
140
+            </el-form-item>
141
+          </el-col>
142
+          <el-col :span="8">
143
+            <el-form-item label="T1活体动物" prop="t1LiveAnimal">
144
+              <el-input-number :precision="0" v-model="form.t1LiveAnimal" :min="0" placeholder="请输入T1活体动物" style="width: 100%" @change="calculateTotals" />
145
+            </el-form-item>
146
+            <el-form-item label="T1腐蚀性物品" prop="t1Corrosive">
147
+              <el-input-number :precision="0" v-model="form.t1Corrosive" :min="0" placeholder="请输入T1腐蚀性物品" style="width: 100%" @change="calculateTotals" />
148
+            </el-form-item>
149
+            <el-form-item label="T1用假冒他" prop="t1FakeId">
150
+              <el-input-number :precision="0" v-model="form.t1FakeId" :min="0" placeholder="请输入T1用假冒他" style="width: 100%" @change="calculateTotals" />
151
+            </el-form-item>
152
+            <el-form-item label="T1爆炸装置" prop="t1Explosive">
153
+              <el-input-number :precision="0" v-model="form.t1Explosive" :min="0" placeholder="请输入T1爆炸装置" style="width: 100%" @change="calculateTotals" />
154
+            </el-form-item>
155
+          </el-col>
156
+          <el-col :span="8">
157
+            <el-form-item label="T1工具" prop="t1Tool">
158
+              <el-input-number :precision="0" v-model="form.t1Tool" :min="0" placeholder="请输入T1工具" style="width: 100%" @change="calculateTotals" />
159
+            </el-form-item>
160
+            <el-form-item label="T1枪支弹药" prop="t1GunAmmo">
161
+              <el-input-number :precision="0" v-model="form.t1GunAmmo" :min="0" placeholder="请输入T1枪支弹药" style="width: 100%" @change="calculateTotals" />
162
+            </el-form-item>
163
+            <el-form-item label="T1扫黄打非" prop="t1Illegal">
164
+              <el-input-number :precision="0" v-model="form.t1Illegal" :min="0" placeholder="请输入T1扫黄打非" style="width: 100%" @change="calculateTotals" />
165
+            </el-form-item>
166
+            <el-form-item label="T1其他" prop="t1Other">
167
+              <el-input-number :precision="0" v-model="form.t1Other" :min="0" placeholder="请输入T1其他" style="width: 100%" @change="calculateTotals" />
168
+            </el-form-item>
169
+          </el-col>
170
+        </el-row>
171
+        <el-row :gutter="20">
172
+          <el-col :span="8">
173
+            <el-form-item label="T1总数" prop="t1Total">
174
+              <el-input v-model="form.t1Total" placeholder="自动计算" readonly style="width: 100%" />
175
+            </el-form-item>
176
+          </el-col>
177
+        </el-row>
178
+        
179
+        <!-- T2区域 -->
180
+        <el-divider content-position="left">T2区域数据</el-divider>
181
+        <el-row :gutter="20">
182
+          <el-col :span="8">
183
+            <el-form-item label="T2火种" prop="t2FireSource">
184
+              <el-input-number :precision="0" v-model="form.t2FireSource" :min="0" placeholder="请输入T2火种" style="width: 100%" @change="calculateTotals" />
185
+            </el-form-item>
186
+            <el-form-item label="T2刀具" prop="t2Knife">
187
+              <el-input-number :precision="0" v-model="form.t2Knife" :min="0" placeholder="请输入T2刀具" style="width: 100%" @change="calculateTotals" />
188
+            </el-form-item>
189
+            <el-form-item label="T2警械器具" prop="t2PoliceWeapon">
190
+              <el-input-number :precision="0" v-model="form.t2PoliceWeapon" :min="0" placeholder="请输入T2警械器具" style="width: 100%" @change="calculateTotals" />
191
+            </el-form-item>
192
+            <el-form-item label="T2烟花爆竹" prop="t2Firework">
193
+              <el-input-number :precision="0" v-model="form.t2Firework" :min="0" placeholder="请输入T2烟花爆竹" style="width: 100%" @change="calculateTotals" />
194
+            </el-form-item>
195
+          </el-col>
196
+          <el-col :span="8">
197
+            <el-form-item label="T2活体动物" prop="t2LiveAnimal">
198
+              <el-input-number :precision="0" v-model="form.t2LiveAnimal" :min="0" placeholder="请输入T2活体动物" style="width: 100%" @change="calculateTotals" />
199
+            </el-form-item>
200
+            <el-form-item label="T2腐蚀性物品" prop="t2Corrosive">
201
+              <el-input-number :precision="0" v-model="form.t2Corrosive" :min="0" placeholder="请输入T2腐蚀性物品" style="width: 100%" @change="calculateTotals" />
202
+            </el-form-item>
203
+            <el-form-item label="T2用假冒他" prop="t2FakeId">
204
+              <el-input-number :precision="0" v-model="form.t2FakeId" :min="0" placeholder="请输入T2用假冒他" style="width: 100%" @change="calculateTotals" />
205
+            </el-form-item>
206
+            <el-form-item label="T2爆炸装置" prop="t2Explosive">
207
+              <el-input-number :precision="0" v-model="form.t2Explosive" :min="0" placeholder="请输入T2爆炸装置" style="width: 100%" @change="calculateTotals" />
208
+            </el-form-item>
209
+          </el-col>
210
+          <el-col :span="8">
211
+            <el-form-item label="T2工具" prop="t2Tool">
212
+              <el-input-number :precision="0" v-model="form.t2Tool" :min="0" placeholder="请输入T2工具" style="width: 100%" @change="calculateTotals" />
213
+            </el-form-item>
214
+            <el-form-item label="T2枪支弹药" prop="t2GunAmmo">
215
+              <el-input-number :precision="0" v-model="form.t2GunAmmo" :min="0" placeholder="请输入T2枪支弹药" style="width: 100%" @change="calculateTotals" />
216
+            </el-form-item>
217
+            <el-form-item label="T2扫黄打非" prop="t2Illegal">
218
+              <el-input-number :precision="0" v-model="form.t2Illegal" :min="0" placeholder="请输入T2扫黄打非" style="width: 100%" @change="calculateTotals" />
219
+            </el-form-item>
220
+            <el-form-item label="T2其他" prop="t2Other">
221
+              <el-input-number :precision="0" v-model="form.t2Other" :min="0" placeholder="请输入T2其他" style="width: 100%" @change="calculateTotals" />
222
+            </el-form-item>
223
+          </el-col>
224
+        </el-row>
225
+        <el-row :gutter="20">
226
+          <el-col :span="8">
227
+            <el-form-item label="T2总数" prop="t2Total">
228
+              <el-input v-model="form.t2Total" placeholder="自动计算" readonly style="width: 100%" />
229
+            </el-form-item>
230
+          </el-col>
231
+          <el-col :span="8">
232
+            <el-form-item label="T1总数+T2总数" prop="total">
233
+              <el-input v-model="form.total" placeholder="自动计算" readonly style="width: 100%" />
234
+            </el-form-item>
235
+          </el-col>
236
+        </el-row>
237
+      </el-form>
238
+      <template #footer>
239
+        <div class="dialog-footer">
240
+          <el-button type="primary" @click="submitForm">确 定</el-button>
241
+          <el-button @click="cancel">取 消</el-button>
242
+        </div>
243
+      </template>
244
+    </el-dialog>
245
+
246
+    <!-- 导入对话框 -->
247
+    <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
248
+      <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers"
249
+        :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
250
+        :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
251
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
252
+        <div class="el-upload__text">
253
+          将文件拖到此处,或<em>点击上传</em>
254
+        </div>
255
+        <template #tip>
256
+          <div class="el-upload__tip">
257
+            <span>仅允许导入xls、xlsx格式文件。</span>
258
+            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;"
259
+              @click="importTemplate">下载模板</el-link>
260
+          </div>
261
+        </template>
262
+      </el-upload>
263
+      <template #footer>
264
+        <div class="dialog-footer">
265
+          <el-button type="primary" @click="submitFileForm">确 定</el-button>
266
+          <el-button @click="upload.open = false">取 消</el-button>
267
+        </div>
268
+      </template>
269
+    </el-dialog>
270
+  </div>
271
+</template>
272
+
273
+<script setup name="SeizeData">
274
+import { listSeizeData, getSeizeData, delSeizeData, addSeizeData, updateSeizeData } from "@/api/runData/seizeData"
275
+import { listDept } from '@/api/system/dept'
276
+import { getToken } from '@/utils/auth'
277
+
278
+const { proxy } = getCurrentInstance()
279
+
280
+const seizeDataList = ref([])
281
+const open = ref(false)
282
+const loading = ref(true)
283
+const showSearch = ref(true)
284
+const ids = ref([])
285
+const single = ref(true)
286
+const multiple = ref(true)
287
+const total = ref(0)
288
+const title = ref("")
289
+
290
+// 班次字典
291
+const shiftOptions = [
292
+  { value: '早班', label: '早班' },
293
+  { value: '晚班', label: '晚班' }
294
+]
295
+
296
+// 大队选项
297
+const brigadeOptions = ref([])
298
+
299
+// 导入参数
300
+const upload = reactive({
301
+  // 是否显示弹出层
302
+  open: false,
303
+  // 弹出层标题
304
+  title: "",
305
+  // 是否禁用上传
306
+  isUploading: false,
307
+  // 是否更新已经存在的查获数据
308
+  updateSupport: 0,
309
+  // 设置上传的请求头部
310
+  headers: { Authorization: "Bearer " + getToken() },
311
+  // 上传的地址
312
+  url: import.meta.env.VITE_APP_BASE_API + "/item/hkSeizureStat/importData"
313
+})
314
+
315
+const uploadRef = ref()
316
+
317
+const data = reactive({
318
+  form: {},
319
+  queryParams: {
320
+    pageNum: 1,
321
+    pageSize: 10,
322
+    recordDate: null,
323
+    shift: null,
324
+    brigade: null
325
+  },
326
+  rules: {
327
+    recordDate: [
328
+      { required: true, message: "日期不能为空", trigger: "blur" }
329
+    ],
330
+    shift: [
331
+      { required: true, message: "班次不能为空", trigger: "blur" }
332
+    ],
333
+    brigade: [
334
+      { required: true, message: "当班大队不能为空", trigger: "blur" }
335
+    ],
336
+    t1FireSource: [
337
+      { type: "integer", message: "T1火种必须为整数", trigger: "blur" }
338
+    ],
339
+    t1Knife: [
340
+      { type: "integer", message: "T1刀具必须为整数", trigger: "blur" }
341
+    ],
342
+    t1PoliceWeapon: [
343
+      { type: "integer", message: "T1警械器具必须为整数", trigger: "blur" }
344
+    ],
345
+    t1Firework: [
346
+      { type: "integer", message: "T1烟花爆竹必须为整数", trigger: "blur" }
347
+    ],
348
+    t1LiveAnimal: [
349
+      { type: "integer", message: "T1活体动物必须为整数", trigger: "blur" }
350
+    ],
351
+    t1Corrosive: [
352
+      { type: "integer", message: "T1腐蚀性物品必须为整数", trigger: "blur" }
353
+    ],
354
+    t1FakeId: [
355
+      { type: "integer", message: "T1用假冒他必须为整数", trigger: "blur" }
356
+    ],
357
+    t1Explosive: [
358
+      { type: "integer", message: "T1爆炸装置必须为整数", trigger: "blur" }
359
+    ],
360
+    t1Tool: [
361
+      { type: "integer", message: "T1工具必须为整数", trigger: "blur" }
362
+    ],
363
+    t1GunAmmo: [
364
+      { type: "integer", message: "T1枪支弹药必须为整数", trigger: "blur" }
365
+    ],
366
+    t1Illegal: [
367
+      { type: "integer", message: "T1扫黄打非必须为整数", trigger: "blur" }
368
+    ],
369
+    t1Other: [
370
+      { type: "integer", message: "T1其他必须为整数", trigger: "blur" }
371
+    ],
372
+    t2FireSource: [
373
+      { type: "integer", message: "T2火种必须为整数", trigger: "blur" }
374
+    ],
375
+    t2Knife: [
376
+      { type: "integer", message: "T2刀具必须为整数", trigger: "blur" }
377
+    ],
378
+    t2PoliceWeapon: [
379
+      { type: "integer", message: "T2警械器具必须为整数", trigger: "blur" }
380
+    ],
381
+    t2Firework: [
382
+      { type: "integer", message: "T2烟花爆竹必须为整数", trigger: "blur" }
383
+    ],
384
+    t2LiveAnimal: [
385
+      { type: "integer", message: "T2活体动物必须为整数", trigger: "blur" }
386
+    ],
387
+    t2Corrosive: [
388
+      { type: "integer", message: "T2腐蚀性物品必须为整数", trigger: "blur" }
389
+    ],
390
+    t2FakeId: [
391
+      { type: "integer", message: "T2用假冒他必须为整数", trigger: "blur" }
392
+    ],
393
+    t2Explosive: [
394
+      { type: "integer", message: "T2爆炸装置必须为整数", trigger: "blur" }
395
+    ],
396
+    t2Tool: [
397
+      { type: "integer", message: "T2工具必须为整数", trigger: "blur" }
398
+    ],
399
+    t2GunAmmo: [
400
+      { type: "integer", message: "T2枪支弹药必须为整数", trigger: "blur" }
401
+    ],
402
+    t2Illegal: [
403
+      { type: "integer", message: "T2扫黄打非必须为整数", trigger: "blur" }
404
+    ],
405
+    t2Other: [
406
+      { type: "integer", message: "T2其他必须为整数", trigger: "blur" }
407
+    ]
408
+  }
409
+})
410
+
411
+const { queryParams, form, rules } = toRefs(data)
412
+
413
+/** 计算总数 */
414
+function calculateTotals() {
415
+  // 计算T1总数
416
+  const t1Fields = ['t1FireSource', 't1Knife', 't1PoliceWeapon', 't1Firework', 't1LiveAnimal', 
417
+                   't1Corrosive', 't1FakeId', 't1Explosive', 't1Tool', 't1GunAmmo', 
418
+                   't1Illegal', 't1Other']
419
+  const t1Total = t1Fields.reduce((sum, field) => {
420
+    return sum + (form.value[field] || 0)
421
+  }, 0)
422
+  form.value.t1Total = t1Total
423
+  
424
+  // 计算T2总数
425
+  const t2Fields = ['t2FireSource', 't2Knife', 't2PoliceWeapon', 't2Firework', 't2LiveAnimal', 
426
+                   't2Corrosive', 't2FakeId', 't2Explosive', 't2Tool', 't2GunAmmo', 
427
+                   't2Illegal', 't2Other']
428
+  const t2Total = t2Fields.reduce((sum, field) => {
429
+    return sum + (form.value[field] || 0)
430
+  }, 0)
431
+  form.value.t2Total = t2Total
432
+  
433
+  // 计算总总数
434
+  form.value.total = t1Total + t2Total
435
+}
436
+
437
+/** 查询查获数据列表 */
438
+function getList() {
439
+  loading.value = true
440
+  listSeizeData(queryParams.value).then(response => {
441
+    seizeDataList.value = response.rows
442
+    total.value = response.total
443
+    loading.value = false
444
+  })
445
+}
446
+
447
+// 取消按钮
448
+function cancel() {
449
+  open.value = false
450
+  reset()
451
+}
452
+
453
+// 表单重置
454
+function reset() {
455
+  form.value = {
456
+    id: null,
457
+    recordDate: null,
458
+    shift: null,
459
+    brigade: null,
460
+    brigadeName: null,
461
+    // T1区域数据
462
+    t1FireSource: null,
463
+    t1Knife: null,
464
+    t1PoliceWeapon: null,
465
+    t1Firework: null,
466
+    t1LiveAnimal: null,
467
+    t1Corrosive: null,
468
+    t1FakeId: null,
469
+    t1Explosive: null,
470
+    t1Tool: null,
471
+    t1GunAmmo: null,
472
+    t1Illegal: null,
473
+    t1Other: null,
474
+    t1Total: null,
475
+    // T2区域数据
476
+    t2FireSource: null,
477
+    t2Knife: null,
478
+    t2PoliceWeapon: null,
479
+    t2Firework: null,
480
+    t2LiveAnimal: null,
481
+    t2Corrosive: null,
482
+    t2FakeId: null,
483
+    t2Explosive: null,
484
+    t2Tool: null,
485
+    t2GunAmmo: null,
486
+    t2Illegal: null,
487
+    t2Other: null,
488
+    t2Total: null,
489
+    total: null
490
+  }
491
+  proxy.resetForm("seizeDataRef")
492
+}
493
+
494
+/** 搜索按钮操作 */
495
+function handleQuery() {
496
+  queryParams.value.pageNum = 1
497
+  getList()
498
+}
499
+
500
+/** 重置按钮操作 */
501
+function resetQuery() {
502
+  proxy.resetForm("queryRef")
503
+  handleQuery()
504
+}
505
+
506
+// 多选框选中数据
507
+function handleSelectionChange(selection) {
508
+  ids.value = selection.map(item => item.id)
509
+  single.value = selection.length != 1
510
+  multiple.value = !selection.length
511
+}
512
+
513
+/** 新增按钮操作 */
514
+function handleAdd() {
515
+  reset()
516
+  open.value = true
517
+  title.value = "添加查获数据"
518
+}
519
+
520
+/** 修改按钮操作 */
521
+function handleUpdate(row) {
522
+  reset()
523
+  const _id = row.id || ids.value
524
+  getSeizeData(_id).then(response => {
525
+    form.value = response.data
526
+    open.value = true
527
+    title.value = "修改查获数据"
528
+  })
529
+}
530
+
531
+/** 提交按钮 */
532
+function submitForm() {
533
+  proxy.$refs["seizeDataRef"].validate(valid => {
534
+    if (valid) {
535
+      // 提交前重新计算总数
536
+      calculateTotals()
537
+      
538
+      if (form.value.id != null) {
539
+        updateSeizeData(form.value).then(response => {
540
+          proxy.$modal.msgSuccess("修改成功")
541
+          open.value = false
542
+          getList()
543
+        })
544
+      } else {
545
+        addSeizeData(form.value).then(response => {
546
+          proxy.$modal.msgSuccess("新增成功")
547
+          open.value = false
548
+          getList()
549
+        })
550
+      }
551
+    }
552
+  })
553
+}
554
+
555
+/** 删除按钮操作 */
556
+function handleDelete(row) {
557
+  const _ids = row.id || ids.value
558
+  proxy.$modal.confirm('是否确认删除数据项?').then(function () {
559
+    return delSeizeData(_ids)
560
+  }).then(() => {
561
+    getList()
562
+    proxy.$modal.msgSuccess("删除成功")
563
+  }).catch(() => { })
564
+}
565
+
566
+/** 导出按钮操作 */
567
+function handleExport() {
568
+  // 过滤掉值为null的参数,但保留分页参数
569
+  const filteredParams = Object.fromEntries(
570
+    Object.entries(queryParams.value).filter(([key, value]) => {
571
+      // 保留分页参数
572
+      if (key === 'pageNum' || key === 'pageSize') return true
573
+      // 过滤掉其他为null的参数
574
+      return value !== null
575
+    })
576
+  )
577
+  
578
+  proxy.download('/item/hkSeizureStat/export', filteredParams, `seizeData_${new Date().getTime()}.xlsx`)
579
+}
580
+
581
+/** 导入按钮操作 */
582
+function handleImport() {
583
+  upload.title = "查获数据导入"
584
+  upload.open = true
585
+}
586
+
587
+/** 下载模板操作 */
588
+function importTemplate() {
589
+  proxy.download('/item/hkSeizureStat/importTemplate', {
590
+  }, `查获数据导入模板_${new Date().getTime()}.xlsx`)
591
+}
592
+
593
+/** 文件上传中处理 */
594
+const handleFileUploadProgress = (event, file, fileList) => {
595
+  upload.isUploading = true
596
+}
597
+
598
+/** 文件上传成功处理 */
599
+const handleFileSuccess = (response, file, fileList) => {
600
+  upload.open = false
601
+  upload.isUploading = false
602
+  uploadRef.value.handleRemove(file)
603
+  proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
604
+  getList()
605
+}
606
+
607
+/** 提交上传文件 */
608
+function submitFileForm() {
609
+  uploadRef.value.submit()
610
+}
611
+
612
+getList()
613
+getDeptList()
614
+
615
+function getDeptList() {
616
+  listDept({}).then(response => {
617
+    const deptList = response.data || []
618
+    brigadeOptions.value = deptList.filter(item => item.deptType === 'BRIGADE' && [311, 314, 315].includes(item.deptId)).map(item => ({
619
+      value: item.deptId,
620
+      label: item.deptName
621
+    }))
622
+  })
623
+}
624
+</script>

+ 0 - 0
src/views/runData/seizeData/查获数据