Browse Source

单位考核评价和计划管理修改

wangqi 1 week ago
parent
commit
7c3b7854b5

BIN
public/images/unitsPerformance.png View File


+ 6
- 1
src/router/index.ts View File

@@ -551,7 +551,7 @@ const router = createRouter({
551 551
 		},
552 552
 		{
553 553
 			path: '/planManagement',
554
-			name: '计划任务汇报',
554
+			name: '计划管理',
555 555
 			component: () => import('@/view/planManagement/index.vue')
556 556
 		},
557 557
 		{
@@ -569,6 +569,11 @@ const router = createRouter({
569 569
 			name: '任务清单汇报',
570 570
 			component: () => import('@/view/planManagement/manifestReport.vue')
571 571
 		},
572
+		{
573
+			path: '/performanceReview/units',
574
+			name: '单位绩效评估',
575
+			component: () => import('@/view/performanceReview/units.vue')
576
+		},
572 577
 		{
573 578
 			path: '/accidentManager/accidentBaoGaoLedger/index',
574 579
 			name: 'accidentBaoGaoLedger',

+ 13
- 3
src/view/Home2.vue View File

@@ -128,7 +128,6 @@
128 128
           <img src="../../public/images/dt.png" width="45rpx" />
129 129
           <span class="vanicon_text">逢查必考</span>
130 130
         </van-grid-item>
131
-
132 131
         <van-grid-item to="/examtask" v-if="showCheckTake">
133 132
           <img src="../../public/images/zyqk.png" width="45rpx" />
134 133
           <span class="vanicon_text">考试任务</span>
@@ -203,6 +202,15 @@
203 202
         </van-grid-item>
204 203
       </van-grid>
205 204
     </div>
205
+    <div class="card">
206
+      <div class="title">考核评价</div>
207
+      <van-grid :border="false" :column-num="4">
208
+        <van-grid-item to="/performanceReview/units">
209
+          <img src="../../public/images/unitsPerformance.png" width="45rpx" />
210
+          <span class="vanicon_text">单位考核</span>
211
+        </van-grid-item>
212
+      </van-grid>
213
+    </div>
206 214
     <div class="card">
207 215
       <div class="title">考核管理</div>
208 216
       <van-grid :border="false" :column-num="4" v-if="showCheckTakeN">
@@ -381,7 +389,8 @@ const getNameByPath = (path) => {
381 389
     '/projectManage/projectConstructionOperation': '项目施工作业管理',
382 390
     '/projectManage/projectWorkLedger': '项目作业台账',
383 391
     '/keyMatters': '重点事项',
384
-    '/planManagement': '计划任务'
392
+    '/planManagement': '计划任务',
393
+    '/performanceReview/units': '单位考核'
385 394
 
386 395
   };
387 396
   return recentlyUsedMapping[path];
@@ -417,7 +426,8 @@ const getPicPathByPath = (path) => {
417 426
     '/projectManage/projectConstructionOperation': 'images/xm.png',
418 427
     '/projectManage/projectWorkLedger': 'images/xm.png',
419 428
     '/keyMatters': 'images/keyMatters.png',
420
-    '/planManagement': 'images/planManagement.png'
429
+    '/planManagement': 'images/planManagement.png',
430
+    '/performanceReview/units': 'images/unitsPerformance.png'
421 431
   };
422 432
   return recentlyUsedMapping[path];
423 433
 };

+ 712
- 0
src/view/performanceReview/units.vue View File

@@ -0,0 +1,712 @@
1
+<script setup>
2
+import { getCurrentInstance, ref, onMounted, watch, reactive, toRefs, toRaw } from 'vue';
3
+import { showFailToast, showToast } from 'vant';
4
+import { useRouter } from 'vue-router';
5
+
6
+const base_url = '/sgsafe/DeptPerformance';
7
+const performance_url = '/sgsafe/SafePerformance';
8
+const { proxy } = getCurrentInstance();
9
+const router = useRouter();
10
+
11
+const fetchData = reactive({
12
+  deptLevel: '0',
13
+  deptCode: '公司级'
14
+});
15
+const { deptLevel, deptCode } = toRefs(fetchData);
16
+const currentLevelName = ref('');
17
+
18
+// 查询当前用户控制权限
19
+const defaultDeptLevel = ref('');
20
+const defaultDeptCode = ref('');
21
+const queryRoleCode = async () => {
22
+  const url = performance_url + '/getDeptRole';
23
+  const param = {};
24
+  const res = await proxy.$axios.get(url, param);
25
+  if (res.data.code === 0) {
26
+    const responseStr = res.data.data.split('-');
27
+    switch (responseStr[0]) {
28
+      case '0':
29
+        defaultDeptLevel.value = '0';
30
+        defaultDeptCode.value = responseStr[1];
31
+        break;
32
+      default:
33
+        defaultDeptLevel.value = '2';
34
+        defaultDeptCode.value = responseStr[1];
35
+        break;
36
+    }
37
+  } else {
38
+    showFailToast('操作失败!' + res.data.msg);
39
+  }
40
+};
41
+
42
+/* 预处理部门数组 */
43
+const ensureLeafFlag = (tree, fieldNames = { children: 'children' }) => {
44
+  const { children: childrenKey } = fieldNames;
45
+  return tree.map(node => {
46
+    const children = node[childrenKey];
47
+    const hasValidChildren = Array.isArray(children) && children.length > 0;
48
+
49
+    const newNode = {
50
+      ...node,
51
+      isLeaf: !hasValidChildren
52
+    };
53
+
54
+    if (!newNode.isLeaf) {
55
+      newNode[childrenKey] = ensureLeafFlag(children, fieldNames);
56
+    } else {
57
+      // 可选:清理空 children
58
+      delete newNode[childrenKey];
59
+    }
60
+
61
+    return newNode;
62
+  });
63
+};
64
+
65
+// 获取默认值对应的名称
66
+const findTextByValue = (tree, targetValue, fieldNames = {}) => {
67
+  const { value: v = 'value', text: t = 'label', children: c = 'children' } = fieldNames;
68
+  if (!Array.isArray(tree)) return;
69
+
70
+  for (const node of tree) {
71
+    if (node[v] === targetValue) return node[t];
72
+    if (node[c]) {
73
+      const found = findTextByValue(node[c], targetValue, fieldNames);
74
+      if (found !== undefined) return found;
75
+    }
76
+  }
77
+};
78
+const getDefaultDeptName = () => {
79
+  currentLevelName.value = findTextByValue(deptMenu.value, defaultDeptCode.value, {
80
+    text: 'label',
81
+    value: 'value',
82
+    children: 'children'
83
+  });
84
+};
85
+
86
+// 查询对应筛选菜单
87
+const deptMenu = ref([]);
88
+const queryDeptMenu = async () => {
89
+  const url = performance_url + '/queryDeptMenu';
90
+  const param = { deptLevel: deptLevel.value };
91
+  const res = await proxy.$axios.post(url, param);
92
+  if (res.data.code === 0) {
93
+    deptMenu.value = res.data.data;
94
+    deptMenu.value = ensureLeafFlag(deptMenu.value, {
95
+      children: 'children'
96
+    });
97
+    console.log('deptMenu', deptMenu.value);
98
+  } else {
99
+    showToast({ message: '操作失败!' + res.data.msg, type: 'fail' });
100
+  }
101
+};
102
+
103
+// 隐患
104
+const hiddenDangerData = ref([]);
105
+const queryHiddenDanger = async () => {
106
+  const url = base_url + '/queryHiddenDanger';
107
+  const rawData = toRaw(fetchData);
108
+  rawData.startYear = currentYear.value;
109
+  rawData.endYear = currentYear.value;
110
+  if (currentQuarter.value) {
111
+    switch (currentQuarter.value) {
112
+      case 'Q1':
113
+        rawData.startMonth = '1';
114
+        rawData.endMonth = '4';
115
+        break;
116
+      case 'Q2':
117
+        rawData.startMonth = '4';
118
+        rawData.endMonth = '7';
119
+        break;
120
+      case 'Q3':
121
+        rawData.startMonth = '7';
122
+        rawData.endMonth = '10';
123
+        break;
124
+      case 'Q4':
125
+        rawData.startMonth = '10';
126
+        rawData.endYear = String(Number.parseInt(currentYear.value) + 1);
127
+        rawData.endMonth = '1';
128
+        break;
129
+    }
130
+  } else if (currentMonth.value) {
131
+    rawData.startMonth = currentMonth.value;
132
+    rawData.endMonth = String((Number(currentMonth.value) + 1) % 12);
133
+    if (rawData.endMonth === '0') {
134
+      rawData.endMonth = '12';
135
+    }
136
+    if (rawData.startMonth === '12') {
137
+      rawData.endYear = String(Number.parseInt(currentYear.value) + 1);
138
+    }
139
+  } else {
140
+    rawData.endYear = String(Number.parseInt(currentYear.value) + 1);
141
+  }
142
+  const param = { json: JSON.stringify(rawData) };
143
+  const res = await proxy.$axios.post(url, param);
144
+  if (res.data.code === 0) {
145
+    hiddenDangerData.value = res.data.data;
146
+  } else {
147
+    showToast({ message: '操作失败!' + res.data.msg, type: 'fail' });
148
+  }
149
+};
150
+
151
+const refreshHiddenDanger = () => {
152
+  currentYear.value = new Date().getFullYear();
153
+  currentQuarter.value = '';
154
+  currentMonth.value = '';
155
+  queryHiddenDanger();
156
+};
157
+
158
+// 履职
159
+const performDutiesData = ref([]);
160
+const queryPerformDuties = async () => {
161
+  const url = base_url + '/queryPerformDuties';
162
+  const param = { json: JSON.stringify(toRaw(fetchData)) };
163
+  const res = await proxy.$axios.post(url, param);
164
+  if (res.data.code === 0) {
165
+    performDutiesData.value = res.data.data;
166
+  } else {
167
+    showToast({ message: '操作失败!' + res.data.msg, type: 'fail' });
168
+  }
169
+};
170
+
171
+// 培训计划及记录
172
+const trainRecordData = ref([]);
173
+const queryTrainRecord = async () => {
174
+  const url = base_url + '/queryTrainRecord';
175
+  const param = { json: JSON.stringify(toRaw(fetchData)) };
176
+  const res = await proxy.$axios.post(url, param);
177
+  if (res.data.code === 0) {
178
+    trainRecordData.value = res.data.data;
179
+  } else {
180
+    showToast({ message: '操作失败!' + res.data.msg, type: 'fail' });
181
+  }
182
+};
183
+
184
+// 应急演练
185
+const emergencyDrillsData = ref([]);
186
+const queryEmergencyDrills = async () => {
187
+  const url = base_url + '/queryEmergencyDrills';
188
+  const param = { json: JSON.stringify(toRaw(fetchData)) };
189
+  const res = await proxy.$axios.post(url, param);
190
+  if (res.data.code === 0) {
191
+    emergencyDrillsData.value = res.data.data;
192
+  } else {
193
+    showToast({ message: '操作失败!' + res.data.msg, type: 'fail' });
194
+  }
195
+};
196
+
197
+// 切换事业部/班组
198
+const switchSelected = async () => {
199
+  await queryDeptMenu();
200
+  getDefaultDeptName();
201
+  deptCode.value = defaultDeptCode.value;
202
+  switch (activeName.value) {
203
+    case 'first':
204
+      await queryHiddenDanger();
205
+      break;
206
+    case 'second':
207
+      await queryPerformDuties();
208
+      break;
209
+    case 'third':
210
+      await queryTrainRecord();
211
+      break;
212
+    case 'fourth':
213
+      await queryEmergencyDrills();
214
+      break;
215
+  }
216
+};
217
+
218
+// 模拟 cascader change(Vant 无 cascader,此处简化处理)
219
+const handleChange = (value) => {
220
+  deptCode.value = value;
221
+  currentLevelName.value = value; // 假设 value 就是部门名
222
+};
223
+
224
+const activeName = ref('first');
225
+const handleClick = async (tab) => {
226
+  await queryDeptMenu();
227
+  getDefaultDeptName();
228
+  deptLevel.value = defaultDeptLevel.value;
229
+  deptCode.value = defaultDeptCode.value;
230
+  switch (activeName.value) {
231
+    case 'first':
232
+      await queryHiddenDanger();
233
+      break;
234
+    case 'second':
235
+      await queryPerformDuties();
236
+      break;
237
+    case 'third':
238
+      await queryTrainRecord();
239
+      break;
240
+    case 'fourth':
241
+      await queryEmergencyDrills();
242
+      break;
243
+  }
244
+};
245
+
246
+const currentYear = ref(new Date().getFullYear());
247
+const yearList = [
248
+  { text: String(currentYear.value - 2), value: String(currentYear.value - 2) },
249
+  { text: String(currentYear.value - 1), value: String(currentYear.value - 1) },
250
+  { text: String(currentYear.value), value: String(currentYear.value) }
251
+];
252
+const currentMonth = ref('');
253
+const monthList = [
254
+  { text: '1', value: '1' },
255
+  { text: '2', value: '2' },
256
+  { text: '3', value: '3' },
257
+  { text: '4', value: '4' },
258
+  { text: '5', value: '5' },
259
+  { text: '6', value: '6' },
260
+  { text: '7', value: '7' },
261
+  { text: '8', value: '8' },
262
+  { text: '9', value: '9' },
263
+  { text: '10', value: '10' },
264
+  { text: '11', value: '11' },
265
+  { text: '12', value: '12' }
266
+];
267
+const currentQuarter = ref('');
268
+const quarterList = [
269
+  { text: 'Q1', value: 'Q1' },
270
+  { text: 'Q2', value: 'Q2' },
271
+  { text: 'Q3', value: 'Q3' },
272
+  { text: 'Q4', value: 'Q4' }
273
+];
274
+
275
+const updateQuarter = () => {
276
+  currentMonth.value = '';
277
+
278
+  queryHiddenDanger();
279
+};
280
+
281
+const updateMonth = () => {
282
+  currentQuarter.value = '';
283
+
284
+  queryHiddenDanger();
285
+};
286
+
287
+const switchQuery = () => {
288
+  switch (activeName.value) {
289
+    case 'first':
290
+      queryHiddenDanger();
291
+      break;
292
+    case 'second':
293
+      queryPerformDuties();
294
+      break;
295
+    case 'third':
296
+      queryTrainRecord();
297
+      break;
298
+    case 'fourth':
299
+      queryEmergencyDrills();
300
+      break;
301
+  }
302
+};
303
+
304
+watch(() => [deptCode.value, deptLevel.value], () => {
305
+  switchQuery();
306
+});
307
+
308
+/* 部门层级相关 */
309
+const openCascader = () => {
310
+  showBottom.value = true;
311
+};
312
+
313
+const showBottom = ref(false);
314
+const cascadeValue = ref();
315
+const onFinish = ({ selectedOptions }) => {
316
+  currentLevelName.value = selectedOptions[selectedOptions.length - 1].label;
317
+};
318
+
319
+const handleConfirm = () => {
320
+  showBottom.value = false;
321
+  console.log('cascadeValue', cascadeValue.value);
322
+  fetchData.deptCode = cascadeValue.value;
323
+  switchQuery();
324
+};
325
+
326
+onMounted(async () => {
327
+  await queryRoleCode();
328
+  deptLevel.value = defaultDeptLevel.value;
329
+  deptCode.value = defaultDeptCode.value;
330
+  await queryDeptMenu();
331
+
332
+  cascadeValue.value = defaultDeptCode.value;
333
+  fetchData.deptCode = defaultDeptCode.value;
334
+  getDefaultDeptName();
335
+  await queryHiddenDanger();
336
+  await queryPerformDuties();
337
+  await queryTrainRecord();
338
+  await queryEmergencyDrills();
339
+});
340
+</script>
341
+
342
+<template>
343
+  <div class="layout-container">
344
+    <van-tabs v-model:active="activeName" @change="handleClick" color="#1989fa">
345
+      <van-tab title="隐患" name="first">
346
+        <div class="query-form">
347
+          <div class="form-item">
348
+            <van-field
349
+              label="具体部门:"
350
+              v-model="currentLevelName"
351
+              @click="openCascader"
352
+            />
353
+          </div>
354
+        </div>
355
+        <div class="query-form">
356
+          <div class="form-item">
357
+            <span class="label">部门层级:</span>
358
+            <van-radio-group v-model="deptLevel" direction="horizontal" @change="switchSelected">
359
+              <van-radio v-if="defaultDeptLevel !== '2'" name="0">事业部</van-radio>
360
+              <van-radio name="2">班组</van-radio>
361
+            </van-radio-group>
362
+          </div>
363
+        </div>
364
+        <div class="query-form">
365
+          <div class="form-item">
366
+            <span class="label">年度:</span>
367
+            <van-dropdown-menu>
368
+              <van-dropdown-item
369
+                v-model="currentYear"
370
+                :options="yearList"
371
+                @change="queryHiddenDanger"
372
+              />
373
+            </van-dropdown-menu>
374
+          </div>
375
+          <div class="form-item">
376
+            <span class="label">季度:</span>
377
+            <van-dropdown-menu>
378
+              <van-dropdown-item
379
+                ref="quarterRef"
380
+                v-model="currentQuarter"
381
+                :options="quarterList"
382
+                @change="updateQuarter"
383
+              />
384
+            </van-dropdown-menu>
385
+          </div>
386
+          <div class="form-item">
387
+            <span class="label">月度:</span>
388
+            <van-dropdown-menu>
389
+              <van-dropdown-item
390
+                ref="monthRef"
391
+                v-model="currentMonth"
392
+                :options="monthList"
393
+                @change="updateMonth"
394
+              />
395
+            </van-dropdown-menu>
396
+          </div>
397
+          <div class="form-item">
398
+            <van-button type="primary" size="small" @click="refreshHiddenDanger">重置</van-button>
399
+          </div>
400
+        </div>
401
+
402
+        <van-list>
403
+          <van-cell-group>
404
+            <van-cell
405
+              v-for="(row, index) in hiddenDangerData"
406
+              :key="index"
407
+              :title="row.deptName"
408
+              clickable
409
+              class="card-like-cell"
410
+            >
411
+              <template #label>
412
+                <div class="stats-row">
413
+                  <span class="stat-item">发现: {{ row.total }}</span>
414
+                  <span class="stat-item stat-item-highlight">完成: {{ row.finished }}</span>
415
+                  <span class="stat-item">未完成: {{ row.continued }}</span>
416
+                </div>
417
+              </template>
418
+            </van-cell>
419
+          </van-cell-group>
420
+        </van-list>
421
+      </van-tab>
422
+
423
+      <!-- 履职 -->
424
+      <van-tab title="履职" name="second">
425
+        <div class="query-form">
426
+          <div class="form-item">
427
+            <van-field
428
+              label="具体部门"
429
+              v-model="currentLevelName"
430
+              @click="openCascader"
431
+            />
432
+          </div>
433
+        </div>
434
+        <div class="query-form">
435
+          <div class="form-item">
436
+            <span class="label">部门层级:</span>
437
+            <van-radio-group v-model="deptLevel" direction="horizontal" @change="switchSelected">
438
+              <van-radio v-if="defaultDeptLevel !== '2'" name="0">事业部</van-radio>
439
+              <van-radio name="2">班组</van-radio>
440
+            </van-radio-group>
441
+          </div>
442
+        </div>
443
+        <van-list>
444
+          <van-cell-group>
445
+            <van-cell
446
+              v-for="(row, index) in performDutiesData"
447
+              :key="index"
448
+              :title="row.deptName"
449
+              clickable
450
+              class="card-like-cell"
451
+            >
452
+              <template #label>
453
+                <div class="stats-row">
454
+                  <span class="stat-item stat-item-highlight">平均分: {{ row.avgScore }}</span>
455
+                  <span class="stat-item">本年: {{ row.yearCount }}</span>
456
+                  <span class="stat-item">本月: {{ row.monthCount }}</span>
457
+                  <span class="stat-item">本周: {{ row.weekCount }}</span>
458
+                </div>
459
+              </template>
460
+            </van-cell>
461
+          </van-cell-group>
462
+        </van-list>
463
+      </van-tab>
464
+
465
+      <!-- 培训计划 -->
466
+      <van-tab title="培训计划" name="third">
467
+        <div class="query-form">
468
+          <div class="form-item">
469
+            <van-field
470
+              label="具体部门"
471
+              v-model="currentLevelName"
472
+              @click="openCascader"
473
+            />
474
+          </div>
475
+        </div>
476
+        <div class="query-form">
477
+          <div class="form-item">
478
+            <span class="label">部门层级:</span>
479
+            <van-radio-group v-model="deptLevel" direction="horizontal" @change="switchSelected">
480
+              <van-radio v-if="defaultDeptLevel !== '2'" name="0">事业部</van-radio>
481
+              <van-radio name="2">班组</van-radio>
482
+            </van-radio-group>
483
+          </div>
484
+        </div>
485
+        <van-list>
486
+          <van-cell-group>
487
+            <van-cell
488
+              v-for="(row, index) in trainRecordData"
489
+              :key="index"
490
+              :title="row.deptName"
491
+              clickable
492
+              class="card-like-cell"
493
+            >
494
+              <template #label>
495
+                <div class="stats-row">
496
+                  <span class="stat-item">计划: {{ row.total }}</span>
497
+                  <span class="stat-item stat-item-highlight">完成: {{ row.finished }}</span>
498
+                  <span class="stat-item">学时: {{ row.hours }}</span>
499
+                </div>
500
+              </template>
501
+            </van-cell>
502
+          </van-cell-group>
503
+        </van-list>
504
+      </van-tab>
505
+
506
+      <!-- 应急演练 -->
507
+      <van-tab title="应急演练" name="fourth">
508
+        <div class="query-form">
509
+          <div class="form-item">
510
+            <van-field
511
+              label="具体部门"
512
+              v-model="currentLevelName"
513
+              @click="openCascader"
514
+            />
515
+          </div>
516
+        </div>
517
+        <div class="query-form">
518
+          <div class="form-item">
519
+            <span class="label">部门层级:</span>
520
+            <van-radio-group v-model="deptLevel" direction="horizontal" @change="switchSelected">
521
+              <van-radio v-if="defaultDeptLevel !== '2'" name="0">事业部</van-radio>
522
+              <van-radio name="2">班组</van-radio>
523
+            </van-radio-group>
524
+          </div>
525
+        </div>
526
+
527
+        <van-list>
528
+          <van-cell-group>
529
+            <van-cell
530
+              v-for="(row, index) in emergencyDrillsData"
531
+              :key="index"
532
+              :title="row.deptName"
533
+              clickable
534
+              class="card-like-cell"
535
+            >
536
+              <template #label>
537
+                <div class="stats-row">
538
+                  <span class="stat-item">计划: {{ row.total }}</span>
539
+                  <span class="stat-item stat-item-highlight">完成: {{ row.finished }}</span>
540
+                </div>
541
+              </template>
542
+            </van-cell>
543
+          </van-cell-group>
544
+        </van-list>
545
+      </van-tab>
546
+    </van-tabs>
547
+  </div>
548
+
549
+  <van-popup :close-on-click-overlay="false" :lazy-render="false" v-model:show="showBottom" position="bottom">
550
+    <div class="popup-container">
551
+      <!-- 操作按钮 - 固定在顶部 -->
552
+      <div class="action-buttons-container">
553
+        <div @click="showBottom = false">取消</div>
554
+        <div>部门选择</div>
555
+        <div style="color: #007bff" @click="handleConfirm">确定</div>
556
+      </div>
557
+      <div class="cascade-container">
558
+        <van-cascader
559
+          v-model="cascadeValue"
560
+          title="请选择具体部门"
561
+          :options="deptMenu"
562
+          :swipeable="true"
563
+          :columns-num="3"
564
+          @finish="onFinish"
565
+          :field-names="{
566
+            text: 'label',
567
+            value: 'value',
568
+            children: 'children'
569
+          }"
570
+        />
571
+      </div>
572
+    </div>
573
+  </van-popup>
574
+
575
+</template>
576
+
577
+<style scoped>
578
+.layout-container {
579
+  background-color: #fff;
580
+  height: 86.8vh;
581
+  overflow-y: auto;
582
+  padding: 10px;
583
+}
584
+
585
+.query-form {
586
+  display: flex;
587
+  flex-wrap: wrap;
588
+  gap: 10px;
589
+  padding: 10px 0;
590
+  align-items: center;
591
+}
592
+
593
+.form-item {
594
+  display: flex;
595
+  align-items: center;
596
+  gap: 5px;
597
+}
598
+
599
+.label {
600
+  font-size: 14px;
601
+  white-space: nowrap;
602
+}
603
+
604
+/* Vant 下拉菜单默认宽度较小,可适当调整 */
605
+:deep(.van-dropdown-menu__item) {
606
+  min-width: 80px;
607
+}
608
+
609
+:deep(.van-cell) {
610
+  padding: 0 5px;
611
+}
612
+
613
+.popup-container {
614
+  height: 100%;
615
+  display: flex;
616
+  flex-direction: column;
617
+  background: #f8fafd;
618
+}
619
+
620
+/* 选择器容器 */
621
+.cascade-container {
622
+  flex: 1;
623
+  overflow: hidden;
624
+  background: rgb(255, 255, 255);
625
+}
626
+
627
+/* 确保 van-cascade 占满剩余空间 */
628
+.cascade-container :deep(.van-cascader) {
629
+  height: 100%;
630
+}
631
+
632
+.cascade-container :deep(.van-cascader__content) {
633
+  height: calc(100% - 44px);
634
+  /* 减去标题栏高度 */
635
+}
636
+
637
+/* 为 van-cascader 选项添加分割线 */
638
+.cascade-container :deep(.van-cascader__option) {
639
+  border-bottom: 1px solid #e4e4e4;
640
+}
641
+
642
+.cascade-container :deep(.van-cascader__option:last-child) {
643
+  border-bottom: none;
644
+}
645
+
646
+/* 操作按钮样式 - 固定在顶部 */
647
+.action-buttons-container {
648
+  display: flex;
649
+  justify-content: space-between;
650
+  align-items: center;
651
+  padding: 15px 20px;
652
+  background: white;
653
+  border-bottom: 1px solid #e8e8e8;
654
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
655
+  z-index: 10;
656
+}
657
+
658
+
659
+.card-like-cell {
660
+  --van-cell-background: #ffffff;
661
+  --van-cell-font-size: 16px;
662
+  --van-cell-title-line-height: 1.4;
663
+  --van-cell-label-line-height: 1.3;
664
+  min-height: 56px;
665
+
666
+  /* 关键:卡片样式 */
667
+  border: 1px solid #f0f0f0; /* 极浅边框 */
668
+  border-radius: 6px; /* 微圆角,移动端友好 */
669
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); /* 超轻微阴影,提升层次 */
670
+  margin-bottom: 8px; /* 行间距(可选,若必须 ≤5px 则改为 5px) */
671
+
672
+  /* 内部留白控制 */
673
+  padding: 8px 12px !important; /* Vant cell 默认 padding 覆盖,总内边距合理 */
674
+}
675
+
676
+/* 去掉 Vant 默认的下划线(因为已有边框) */
677
+.card-like-cell::after {
678
+  display: none !important;
679
+}
680
+
681
+/* 统计信息 */
682
+.stats-row {
683
+  display: flex;
684
+  gap: 8px;
685
+  margin-top: 4px;
686
+  color: #666;
687
+  font-size: 13px;
688
+}
689
+
690
+.stat-item {
691
+  background-color: #f8f9fa;
692
+  padding: 2px 6px;
693
+  border-radius: 3px;
694
+  white-space: nowrap;
695
+}
696
+
697
+.stat-item-highlight {
698
+  color: #e6a23c;
699
+  font-weight: 500;
700
+}
701
+
702
+/*.stat-item:nth-child(3) {
703
+  color: #e6a23c;
704
+  font-weight: 500;
705
+}*/
706
+
707
+/* 点击态:加深背景,保留反馈 */
708
+.card-like-cell:active {
709
+  background-color: #f9f9f9;
710
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
711
+}
712
+</style>

+ 3
- 4
src/view/planManagement/manifest.vue View File

@@ -151,13 +151,12 @@ onMounted(() => {
151 151
     showFailToast('数据传递出错,请联系管理员')
152 152
     router.go(-1)
153 153
   }
154
-
155
-  fetchData.value.owningPlanId = plan.value.planManifestId
156
-  console.log('planId', plan.value.planManifestId);
154
+  fetchData.value.owningPlanId = plan.value.id
155
+  // console.log('planId', plan.value.id);
157 156
   if (emergencyInfo.childQueryAttributes) {
158 157
     fetchData.value.work = emergencyInfo.childQueryAttributes;
159 158
   }
160
-  console.log(fetchData.value);
159
+  // console.log(fetchData.value);
161 160
   basicReset();
162 161
   onLoad();
163 162
 })

+ 52
- 22
src/view/planManagement/manifestReport.vue View File

@@ -37,14 +37,14 @@ const onConfirmTime = () => {
37 37
 };
38 38
 
39 39
 
40
-const lowerReportForm = ref({
40
+const lowerReceiptForm = ref({
41 41
   associateMasterId: ''
42 42
 })
43 43
 const dataList = ref([])
44 44
 const queryLowerReporting = () => {
45 45
   const url = '/sgsafe/TaskManifestReceipt/queryByManifestId'
46 46
   const param = {
47
-    json: JSON.stringify(lowerReportForm.value)
47
+    json: JSON.stringify(lowerReceiptForm.value)
48 48
   }
49 49
   proxy.$axios.post(url, param).then(res => {
50 50
     if (res.data.code === 0) {
@@ -170,42 +170,72 @@ onMounted(() => {
170 170
 
171 171
 <style scoped>
172 172
 .page-container {
173
-  height: 100vh; /* 关键:外层容器高度设为视口高度 */
173
+  height: 100vh;
174 174
   display: flex;
175 175
   flex-direction: column;
176 176
 }
177 177
 
178
-/*  overflow-y: auto; !* 启用垂直滚动 *!*/
179
-
178
+.mobile-report-card {
179
+  background-color: #ffffff; /* 白色背景 */
180
+  border-radius: 12px;
181
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
182
+  padding: 16px;
183
+  margin-bottom: 16px;
184
+  font-size: 14px;
185
+  line-height: 1.5;
186
+  color: #333;
187
+  overflow: hidden;
188
+  box-sizing: border-box;
189
+}
180 190
 
181
-.scroll-container {
182
-  flex: 1;
183
-  overflow: auto;
184
-  -webkit-overflow-scrolling: touch; /* iOS 平滑滚动 */
191
+/* 卡片头部 */
192
+.card-header {
193
+  margin-bottom: 12px;
194
+  padding-bottom: 10px;
195
+  border-bottom: 1px solid #f0f0f0;
185 196
 }
186 197
 
187
-/* 可选:隐藏滚动条(视觉优化) */
188
-.scroll-container::-webkit-scrollbar {
189
-  display: none;
198
+.card-header h4 {
199
+  margin: 0;
200
+  font-size: 16px;
201
+  font-weight: 600;
202
+  color: #1a73e8; /* 蓝色主色,突出部门名 */
203
+  word-break: break-word;
190 204
 }
191 205
 
192
-.reports-container {
206
+/* 段落样式 */
207
+.mobile-report-card p {
208
+  margin: 8px 0;
193 209
   display: flex;
194 210
   flex-wrap: wrap;
195
-  gap: 16px;
196
-  padding: 16px;
197 211
 }
198 212
 
199
-.report-card .report-header h4 {
200
-  margin-top: 0;
201
-  font-size: 16px;
213
+.mobile-report-card p strong {
214
+  min-width: 72px; /* 固定标签宽度,对齐更整齐 */
215
+  color: #555;
216
+  font-weight: 500;
217
+}
218
+
219
+.mobile-report-card p span {
202 220
   color: #333;
221
+  flex: 1;
203 222
 }
204 223
 
205
-.report-card p {
206
-  margin: 8px 0;
207
-  font-size: 14px;
208
-  line-height: 1.5;
224
+/* 响应式:适配小屏 */
225
+@media (max-width: 375px) {
226
+  .mobile-report-card {
227
+    padding: 14px;
228
+    margin-bottom: 14px;
229
+  }
230
+
231
+  .card-header h4 {
232
+    font-size: 15px;
233
+  }
234
+
235
+  .mobile-report-card p strong {
236
+    min-width: 64px;
237
+    font-size: 13px;
238
+  }
209 239
 }
210 240
 
211 241
 </style>

Loading…
Cancel
Save