Parcourir la Source

mod: 应急演练

闪电 il y a 1 mois
Parent
commit
648595ff79

+ 30 - 0
.trae/documents/调整应急演练页面字段.md

@@ -0,0 +1,30 @@
1
+1. 修改 config-data.tsx 文件:
2
+
3
+   * 删除原来的 otherDivision 和 otherDivisionId 字段
4
+
5
+   * 添加一个新的字段 otherDivisionList,使用插槽 otherDivision
6
+
7
+2. 修改 index.vue 文件:
8
+
9
+   * 定义 otherDivisionList 数组来存储其他分工数据
10
+
11
+   * 实现 otherDivision 插槽内容:
12
+
13
+     * 添加按钮,用于动态添加输入框
14
+
15
+     * 动态渲染输入框列表,每个输入框包含:
16
+
17
+       * prepend 插槽显示人员名称,默认为"未选择"
18
+
19
+       * 选择按钮,调用现有 handleClick 函数选择人员
20
+
21
+       * 输入框用于输入分工内容
22
+
23
+       * 删除按钮,用于删除当前输入框
24
+
25
+   * 实现添加、删除和人员选择逻辑
26
+
27
+   * 在表单提交时,将 otherDivisionList 转换为合适的格式
28
+
29
+3. 确保现有功能不受影响,特别是人员选择功能
30
+

+ 20 - 0
apps/web-ele/src/api/task/index.ts

@@ -1,6 +1,8 @@
1 1
 import { requestClient } from '#/api/request';
2 2
 
3 3
 enum Api {
4
+  emergencyWySubmit = '/formEmergencyDrill/drill/submit',
5
+  emergencyWySubmitReport = '/formEmergencyDrill/drill/submitReport',
4 6
   groupLogBase = '/formTeamShiftLog/log/handle',
5 7
   scheduleShiftManagementList = '/scheduleShiftManagement/management/list',
6 8
   // childBase = '/taskCheckSubItem/item',
@@ -23,3 +25,21 @@ export function handleGroupLog(params: any) {
23 25
 export function getScheduleShiftManagementList(params: any) {
24 26
   return requestClient.get(`${Api.scheduleShiftManagementList}`, { params });
25 27
 }
28
+
29
+/**
30
+ * 应急演练提交
31
+ * @param params 提交参数
32
+ * @returns
33
+ */
34
+export function submitEmergencyWy(params: any) {
35
+  return requestClient.put(`${Api.emergencyWySubmit}`, params);
36
+}
37
+
38
+/**
39
+ * 应急演练报告提交
40
+ * @param params 提交参数
41
+ * @returns
42
+ */
43
+export function submitEmergencyWyReport(params: any) {
44
+  return requestClient.put(`${Api.emergencyWySubmitReport}`, params);
45
+}

+ 6 - 7
apps/web-ele/src/views/Archive/HSSEManage/emergencyDrill/config-data.tsx

@@ -1,10 +1,12 @@
1 1
 import type { FormSchemaGetter } from '#/adapter/form';
2 2
 import type { VxeGridProps } from '#/adapter/vxe-table';
3 3
 
4
-import { selectAllSysAreaList, selectAllSysStationAreaList } from '#/api/system/infoEntry/stationInfo/stationInfo';
5
-
6 4
 // 岗位列表接口
7 5
 import { requestClient } from '#/api/request';
6
+import {
7
+  selectAllSysAreaList,
8
+  selectAllSysStationAreaList,
9
+} from '#/api/system/infoEntry/stationInfo/stationInfo';
8 10
 
9 11
 // 获取岗位列表
10 12
 const getPostList = async () => {
@@ -149,7 +151,6 @@ export const querySchema: FormSchemaGetter = () => [
149 151
   },
150 152
 ];
151 153
 
152
-
153 154
 export const columns: VxeGridProps['columns'] = [
154 155
   {
155 156
     type: 'checkbox',
@@ -173,7 +174,7 @@ export const columns: VxeGridProps['columns'] = [
173 174
     minWidth: 150,
174 175
   },
175 176
   {
176
-    field: 'stationId',
177
+    field: 'stationName',
177 178
     title: '油站',
178 179
     minWidth: 120,
179 180
   },
@@ -183,7 +184,7 @@ export const columns: VxeGridProps['columns'] = [
183 184
     minWidth: 120,
184 185
   },
185 186
   {
186
-    field: 'position',
187
+    field: 'positionName',
187 188
     title: '岗位',
188 189
     minWidth: 120,
189 190
   },
@@ -235,5 +236,3 @@ export const columns: VxeGridProps['columns'] = [
235 236
     minWidth: 150,
236 237
   },
237 238
 ];
238
-
239
-

+ 245 - 0
apps/web-ele/src/views/schedule/detail/drawer/emergency/config-data.tsx

@@ -0,0 +1,245 @@
1
+// @ts-ignore: 忽略
2
+import type { FormSchemaGetter } from '#/adapter/form';
3
+// @ts-ignore: 忽略
4
+import type { VxeGridProps } from '#/adapter/vxe-table';
5
+
6
+import { DictEnum } from '@vben/constants';
7
+
8
+// @ts-ignore: 忽略
9
+import { getMultipleImageUploadConfig } from '#/components/upload';
10
+import { getDictOptions } from '#/utils/dict';
11
+
12
+export const reportFormSchema: any | FormSchemaGetter = () => [
13
+  {
14
+    component: 'Select',
15
+    fieldName: 'drillEvaluation',
16
+    label: '演练评估',
17
+    componentProps: {
18
+      placeholder: '请输入演练评估',
19
+      options: getDictOptions(DictEnum.EXERCISE_EVALUATION),
20
+    },
21
+    rules: 'required',
22
+  },
23
+  {
24
+    component: 'Input',
25
+    fieldName: 'mainContent',
26
+    label: '简述演练的主要内容',
27
+    componentProps: {
28
+      placeholder: '请输入演练的主要内容',
29
+      type: 'textarea',
30
+      rows: 3,
31
+    },
32
+    rules: 'required',
33
+  },
34
+  {
35
+    component: 'Input',
36
+    fieldName: 'existingProblems',
37
+    label: '演练过程存在的问题',
38
+    componentProps: {
39
+      placeholder: '请输入演练过程存在的问题',
40
+      type: 'textarea',
41
+      rows: 3,
42
+    },
43
+    rules: 'required',
44
+  },
45
+  {
46
+    component: 'Input',
47
+    fieldName: 'improvementMeasures',
48
+    label: '针对问题的改进措施',
49
+    componentProps: {
50
+      placeholder: '请输入针对问题的改进措施',
51
+      type: 'textarea',
52
+      rows: 3,
53
+    },
54
+    rules: 'required',
55
+  },
56
+
57
+  {
58
+    component: 'Input',
59
+    fieldName: 'managerComment',
60
+    label: '经理点评',
61
+    componentProps: {
62
+      placeholder: '请输入经理点评',
63
+      type: 'textarea',
64
+      rows: 3,
65
+    },
66
+    rules: 'required',
67
+  },
68
+  {
69
+    component: 'Input',
70
+    fieldName: 'images',
71
+    label: '图片',
72
+    componentProps: {
73
+      maxlength: 30,
74
+    },
75
+    dependencies: {
76
+      show: () => false,
77
+      triggerFields: [''],
78
+    },
79
+  },
80
+  {
81
+    component: 'Upload',
82
+    fieldName: 'imagesPaths',
83
+    label: '图片',
84
+    componentProps: (row: any) => {
85
+      return {
86
+        ...getMultipleImageUploadConfig(5),
87
+        multiple: true,
88
+        onSuccess: (res: any, uploadFile: any, uploadFiles: any) => {
89
+          if (res.code === 200) {
90
+            const paths: string[] = [];
91
+            uploadFiles.forEach((item: any) => {
92
+              if (item.response?.code === 200) {
93
+                paths.push(item.response.data.fileName);
94
+              }
95
+            });
96
+            row.images = paths.join(',');
97
+
98
+            return res.data;
99
+          }
100
+        },
101
+      };
102
+    },
103
+    renderComponentContent: () => {
104
+      return {
105
+        default: () => '点击上传',
106
+      };
107
+    },
108
+    rules: 'required',
109
+  },
110
+];
111
+
112
+export const drawerFormSchema: any | FormSchemaGetter = () => [
113
+  // {
114
+  //   component: 'SectionTitle',
115
+  //   fieldName: '_section_title',
116
+  //   hideLabel: true,
117
+  //   componentProps: {
118
+  //     title: '基本信息',
119
+  //   },
120
+  // },
121
+  {
122
+    component: 'Input',
123
+    fieldName: 'drillName',
124
+    label: '应急演练名称',
125
+    componentProps: {
126
+      placeholder: '请输入应急演练名称',
127
+    },
128
+    rules: 'required',
129
+  },
130
+  {
131
+    component: 'DatePicker',
132
+    fieldName: 'drillTime',
133
+    label: '演练时间',
134
+    componentProps: {
135
+      type: 'datetime',
136
+      placeholder: '请选择演练时间',
137
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
138
+    },
139
+    rules: 'required',
140
+  },
141
+  {
142
+    component: 'Input',
143
+    fieldName: 'organizationDepartment',
144
+    label: '组织部门',
145
+    componentProps: {
146
+      placeholder: '请输入组织部门',
147
+    },
148
+    rules: 'required',
149
+  },
150
+  {
151
+    component: 'InputNumber',
152
+    fieldName: 'participantsCount',
153
+    label: '参加人数',
154
+    componentProps: {
155
+      placeholder: '请输入参加人数',
156
+      min: 0,
157
+      step: 1,
158
+    },
159
+    rules: 'required',
160
+  },
161
+  {
162
+    component: 'InputNumber',
163
+    fieldName: 'totalCount',
164
+    label: '总人数',
165
+    componentProps: {
166
+      placeholder: '请输入总人数',
167
+      min: 0,
168
+      step: 1,
169
+    },
170
+    rules: 'required',
171
+  },
172
+  {
173
+    component: 'Input',
174
+    fieldName: 'drillLocation',
175
+    label: '演练地点/装置',
176
+    componentProps: {
177
+      placeholder: '请输入演练地点/装置',
178
+    },
179
+    rules: 'required',
180
+  },
181
+  {
182
+    component: 'Input',
183
+    fieldName: 'drillPurpose',
184
+    label: '演练目的',
185
+    componentProps: {
186
+      placeholder: '请输入演练目的',
187
+      type: 'textarea',
188
+      rows: 3,
189
+    },
190
+    rules: 'required',
191
+  },
192
+  {
193
+    component: 'Input',
194
+    fieldName: 'accidentAssumption',
195
+    label: '事件/事故现场假定',
196
+    componentProps: {
197
+      placeholder: '请输入事件/事故现场假定',
198
+      type: 'textarea',
199
+      rows: 3,
200
+    },
201
+    rules: 'required',
202
+  },
203
+  {
204
+    component: 'Input',
205
+    fieldName: 'drillPlanSummary',
206
+    label: '演练方案简述',
207
+    componentProps: {
208
+      placeholder: '请输入演练方案简述',
209
+      type: 'textarea',
210
+      rows: 3,
211
+    },
212
+    rules: 'required',
213
+  },
214
+  {
215
+    component: 'Input',
216
+    fieldName: 'materialPreparation',
217
+    label: '物资准备',
218
+    componentProps: {
219
+      placeholder: '请输入物资准备',
220
+      type: 'textarea',
221
+      rows: 3,
222
+    },
223
+    rules: 'required',
224
+  },
225
+  {
226
+    component: 'Input',
227
+    fieldName: 'precautions',
228
+    label: '演练注意事项及要求',
229
+    componentProps: {
230
+      placeholder: '请输入演练注意事项及要求',
231
+      type: 'textarea',
232
+      rows: 3,
233
+    },
234
+    rules: 'required',
235
+  },
236
+];
237
+
238
+export const defautTableColumns: VxeGridProps['columns'] = [
239
+  {
240
+    field: 'employeeName',
241
+    title: '员工姓名',
242
+    width: 100,
243
+    fixed: 'left',
244
+  },
245
+];

+ 127 - 0
apps/web-ele/src/views/schedule/detail/drawer/emergency/index.vue

@@ -0,0 +1,127 @@
1
+<script setup lang="ts">
2
+// @ts-ignore
3
+
4
+import { ref } from 'vue';
5
+
6
+// @ts-ignore
7
+import { useVbenDrawer, useVbenForm } from '@vben/common-ui';
8
+
9
+// @ts-ignore
10
+import { submitEmergencyWy, submitEmergencyWyReport } from '#/api/task';
11
+
12
+// @ts-ignore
13
+import { drawerFormSchema, reportFormSchema } from './config-data';
14
+
15
+const emit = defineEmits<{ reload: [] }>();
16
+
17
+// 当前激活的标签页
18
+const activeTab = ref('plan');
19
+
20
+// 应急演练方案表单
21
+const [PlanForm, planFormApi] = useVbenForm({
22
+  showDefaultActions: false,
23
+  schema: drawerFormSchema(),
24
+});
25
+
26
+// 应急演练报告表单
27
+const [ReportForm, reportFormApi] = useVbenForm({
28
+  showDefaultActions: false,
29
+  schema: reportFormSchema(),
30
+});
31
+
32
+const taskParams = ref({
33
+  taskId: '',
34
+  taskName: '',
35
+  taskList: [] as any,
36
+});
37
+
38
+const [Drawer, drawerApi] = useVbenDrawer({
39
+  async onOpenChange(isOpen: any) {
40
+    if (!isOpen) {
41
+      return;
42
+    }
43
+    try {
44
+      drawerApi.drawerLoading(true);
45
+      const { taskId, taskName, taskList } = drawerApi.getData();
46
+      taskParams.value.taskId = taskId;
47
+      taskParams.value.taskName = taskName;
48
+      taskParams.value.taskList = taskList;
49
+      // 填充计划表单
50
+      console.log(taskList, 'taskList');
51
+      planFormApi.setValues(taskList[0]);
52
+      // 填充报告表单
53
+      reportFormApi.setValues(taskList[0]);
54
+
55
+      // 可以在这里获取任务详情并填充表单
56
+    } catch (error) {
57
+      console.error(error);
58
+    } finally {
59
+      drawerApi.drawerLoading(false);
60
+    }
61
+  },
62
+  onClosed() {
63
+    planFormApi.resetForm();
64
+    reportFormApi.resetForm();
65
+  },
66
+  async onConfirm() {
67
+    try {
68
+      this.confirmLoading = true;
69
+
70
+      // 判断是选中的哪个 tabs
71
+      let params: any = {};
72
+      if (activeTab.value === 'plan') {
73
+        const { valid: planValid } = await planFormApi.validate();
74
+        if (!planValid) {
75
+          return;
76
+        }
77
+        params = await planFormApi.getValues();
78
+      } else if (activeTab.value === 'report') {
79
+        const { valid: reportValid } = await reportFormApi.validate();
80
+        if (!reportValid) {
81
+          return;
82
+        }
83
+        params = await reportFormApi.getValues();
84
+      }
85
+
86
+      params.id = drawerApi.getData().taskId;
87
+      // 调用API提交数据
88
+      if (activeTab.value === 'plan') {
89
+        await submitEmergencyWy(params);
90
+      } else if (activeTab.value === 'report') {
91
+        await submitEmergencyWyReport(params);
92
+      }
93
+      emit('reload');
94
+      drawerApi.close();
95
+    } catch (error) {
96
+      console.error(error);
97
+    } finally {
98
+      this.confirmLoading = false;
99
+    }
100
+  },
101
+});
102
+</script>
103
+
104
+<template>
105
+  <Drawer :title="drawerApi.getData().taskName">
106
+    <div class="tabs-container">
107
+      <el-tabs v-model="activeTab">
108
+        <el-tab-pane label="应急演练方案" name="plan">
109
+          <PlanForm />
110
+        </el-tab-pane>
111
+        <el-tab-pane label="应急演练报告" name="report">
112
+          <ReportForm />
113
+        </el-tab-pane>
114
+      </el-tabs>
115
+    </div>
116
+  </Drawer>
117
+</template>
118
+
119
+<style scoped lang="scss">
120
+.tabs-container {
121
+  width: 100%;
122
+}
123
+
124
+:deep(.el-input-number) {
125
+  width: 100%;
126
+}
127
+</style>

+ 1 - 0
apps/web-ele/src/views/schedule/detail/drawer/index.ts

@@ -1,2 +1,3 @@
1
+export { default as EmergencyWyDrawer } from './emergency/index.vue';
1 2
 export { default as GroupLogDrawer } from './groupLog/index.vue';
2 3
 export { default as UploadDrawer } from './upload/index.vue';

+ 6 - 1
apps/web-ele/src/views/schedule/detail/index.vue

@@ -39,7 +39,7 @@ import GroupLogComponent from './components/group-log.vue';
39 39
 // @ts-ignore
40 40
 import WeeklyComponent from './components/weekly.vue';
41 41
 import { mobileTaskTypes } from './config-data';
42
-import { GroupLogDrawer, UploadDrawer } from './drawer';
42
+import { EmergencyWyDrawer, GroupLogDrawer, UploadDrawer } from './drawer';
43 43
 
44 44
 const formTypeOptions: any = ref([]);
45 45
 
@@ -246,6 +246,10 @@ const DynamicDrawerComponent = defineComponent({
246 246
         Component = UploadDrawer;
247 247
       } else if (taskInfo.value.formType === 'form') {
248 248
         switch (taskInfo.value.subFormType) {
249
+          case 'emergency_wy': {
250
+            Component = EmergencyWyDrawer;
251
+            break;
252
+          }
249 253
           case 'group_log': {
250 254
             Component = GroupLogDrawer;
251 255
             break;
@@ -301,6 +305,7 @@ const dealEvent = async () => {
301 305
       params = {
302 306
         taskId: taskInfo.value.taskList?.[0]?.id || '',
303 307
         taskName: taskInfo.value.taskName,
308
+        taskList: taskInfo.value.taskList || [],
304 309
         remark: taskResult.value.content,
305 310
         attachmentUrl: taskResult.value.images,
306 311
       };

+ 1 - 0
packages/@core/base/shared/src/constants/dict-enum.ts

@@ -1,5 +1,6 @@
1 1
 export enum DictEnum {
2 2
   AWARDS_TYPE = 'awards_type', // 荣誉类型
3
+  EXERCISE_EVALUATION = 'exercise_evaluation', // 演练评估
3 4
   ISOLATION_TYPE = 'isolation_type', // 隔离类型
4 5
   OIL_ADDED_SERVICE = 'oil_added_service', // 油站增值服务
5 6
   OIL_FIBER = 'oil_fiber', // 油站光纤运营商