闪电 1 dzień temu
rodzic
commit
1a42cf41dd

+ 78 - 0
apps/web-ele/src/api/system/infoEntry/employeeSettings/employeeSettings.ts

@@ -0,0 +1,78 @@
1
+import type { EmployeeSettingsModel } from './model';
2
+
3
+import type { BaseResult } from '#/api/base-result';
4
+
5
+import { commonExport } from '#/api/helper';
6
+import { requestClient } from '#/api/request';
7
+
8
+// API路径常量枚举
9
+enum Api {
10
+  // 导出
11
+  export = '/sysEvaluation/evaluation/export',
12
+  // 列表查询
13
+  list = '/sysEvaluation/evaluation/list',
14
+  // 基础路径
15
+  root = '/sysEvaluation/evaluation',
16
+}
17
+
18
+/**
19
+ * 查询员工评价项设置列表
20
+ * @param params 查询参数
21
+ * @returns 分页结果
22
+ */
23
+export function employeeSettingsList(params: any) {
24
+  return requestClient.get<BaseResult<EmployeeSettingsModel[]>>(Api.list, {
25
+    params,
26
+  });
27
+}
28
+
29
+/**
30
+ * 获取员工评价项设置详细信息
31
+ * @param id 员工评价项设置ID
32
+ * @returns 员工评价项设置详情
33
+ */
34
+export function getEmployeeSettingsDetail(id: number) {
35
+  return requestClient.get<EmployeeSettingsModel>(`${Api.root}/${id}`);
36
+}
37
+
38
+/**
39
+ * 新增员工评价项设置
40
+ * @param data 员工评价项设置数据
41
+ * @returns 操作结果
42
+ */
43
+export function addEmployeeSettings(data: EmployeeSettingsModel) {
44
+  return requestClient.post(Api.root, data, {
45
+    successMessageMode: 'message',
46
+  });
47
+}
48
+
49
+/**
50
+ * 修改员工评价项设置
51
+ * @param data 员工评价项设置数据
52
+ * @returns 操作结果
53
+ */
54
+export function updateEmployeeSettings(data: EmployeeSettingsModel) {
55
+  return requestClient.put(Api.root, data, {
56
+    successMessageMode: 'message',
57
+  });
58
+}
59
+
60
+/**
61
+ * 删除员工评价项设置
62
+ * @param ids 员工评价项设置ID数组
63
+ * @returns 操作结果
64
+ */
65
+export function deleteEmployeeSettings(ids: number[]) {
66
+  return requestClient.delete(`${Api.root}/${ids.join(',')}`, {
67
+    successMessageMode: 'message',
68
+  });
69
+}
70
+
71
+/**
72
+ * 导出员工评价项设置列表
73
+ * @param data 导出参数
74
+ * @returns 导出结果
75
+ */
76
+export function exportEmployeeSettings(data: Partial<EmployeeSettingsModel>) {
77
+  return commonExport(Api.export, data);
78
+}

+ 22 - 0
apps/web-ele/src/api/system/infoEntry/employeeSettings/model.ts

@@ -0,0 +1,22 @@
1
+export interface EmployeeSettingsModel {
2
+  // 主键id
3
+  id?: number;
4
+  // 考核项
5
+  itemName?: string;
6
+  // 分数
7
+  standardScore?: number;
8
+  // 排序
9
+  sortOrder?: number;
10
+  // 详细说明
11
+  description?: string;
12
+  // 逻辑删除标识
13
+  delFlag?: number;
14
+  // 创建人
15
+  createBy?: string;
16
+  // 创建时间
17
+  createTime?: string;
18
+  // 更新人
19
+  updateBy?: string;
20
+  // 更新时间
21
+  updateTime?: string;
22
+}

+ 18 - 0
apps/web-ele/src/api/system/infoEntry/scoreEntry/model.ts

@@ -0,0 +1,18 @@
1
+export interface ScoreEntryModel {
2
+  // 主键id
3
+  id?: number;
4
+  // 创建人
5
+  createBy?: string;
6
+  // 创建时间
7
+  createTime?: string;
8
+  // 删除标记
9
+  delFlag?: number;
10
+  // 备注
11
+  remark?: string;
12
+  // 更新人
13
+  updateBy?: string;
14
+  // 更新时间
15
+  updateTime?: string;
16
+  // 其他评分标准相关字段
17
+  // 可根据实际需求添加
18
+}

+ 56 - 0
apps/web-ele/src/api/system/infoEntry/scoreEntry/scoreEntry.ts

@@ -0,0 +1,56 @@
1
+import type { ScoreEntryModel } from './model';
2
+
3
+import type { BaseResult } from '#/api/base-result';
4
+
5
+import { commonExport } from '#/api/helper';
6
+import { requestClient } from '#/api/request';
7
+
8
+// API路径常量枚举
9
+enum Api {
10
+  // 导出
11
+  export = '/sysScoreStandard/standard/export',
12
+  // 列表查询
13
+  list = '/sysScoreStandard/standard/list',
14
+  // 基础路径
15
+  root = '/sysScoreStandard/standard',
16
+}
17
+
18
+/**
19
+ * 查询评分标准设置列表
20
+ * @param params 查询参数
21
+ * @returns 分页结果
22
+ */
23
+export function scoreEntryList(params: any) {
24
+  return requestClient.get<BaseResult<ScoreEntryModel[]>>(Api.list, {
25
+    params,
26
+  });
27
+}
28
+
29
+/**
30
+ * 获取评分标准设置详细信息
31
+ * @param id 评分标准设置ID
32
+ * @returns 评分标准设置详情
33
+ */
34
+export function getScoreEntryDetail(id: number) {
35
+  return requestClient.get<ScoreEntryModel>(`${Api.root}/${id}`);
36
+}
37
+
38
+/**
39
+ * 修改评分标准设置
40
+ * @param data 评分标准设置数据
41
+ * @returns 操作结果
42
+ */
43
+export function updateScoreEntry(data: ScoreEntryModel) {
44
+  return requestClient.put(Api.root, data, {
45
+    successMessageMode: 'message',
46
+  });
47
+}
48
+
49
+/**
50
+ * 导出评分标准设置列表
51
+ * @param data 导出参数
52
+ * @returns 导出结果
53
+ */
54
+export function exportScoreEntry(data: Partial<ScoreEntryModel>) {
55
+  return commonExport(Api.export, data);
56
+}

+ 209 - 538
apps/web-ele/src/views/system/infoEntry/scoreEntry/index.vue

@@ -1,21 +1,38 @@
1 1
 <script lang="ts" setup>
2 2
 // 导入部分
3
-import { ref, computed } from 'vue';
3
+import { ref, computed, onMounted } from 'vue';
4 4
 import { Page } from '@vben/common-ui';
5
-import { ElTable, ElTableColumn, ElButton, ElInput, ElTabs, ElTabPane } from 'element-plus';
5
+import { ElTable, ElTableColumn, ElButton, ElInput, ElTabs, ElTabPane, ElSelect, ElOption } from 'element-plus';
6
+
7
+// API 导入
8
+import { scoreEntryList, updateScoreEntry } from '#/api/system/infoEntry/scoreEntry/scoreEntry';
9
+// 数据字典导入
10
+import { getDictOptions } from '#/utils/dict';
6 11
 
7 12
 // 类型定义
8 13
 interface TabOption {
9 14
   label: string;
10
-  value: 'stationManager' | 'stationStaff' | 'areaStaff' | 'headquarters' | 'station' | 'area';
15
+  value: string;
16
+  typeValue: string;
17
+}
18
+
19
+interface StandardItem {
20
+  score: number;
21
+  condition: string;
22
+  max_value?: number;
23
+  min_value?: number;
11 24
 }
12 25
 
13 26
 interface ScoreItem {
14
-  id: number;
27
+  id: string;
28
+  type: string;
29
+  typeName: string;
15 30
   dimension: string;
31
+  dimensionName: string;
16 32
   indicator: string;
17
-  standard: string;
18
-  score: number;
33
+  indicatorName: string;
34
+  standardJson: string;
35
+  standards: StandardItem[];
19 36
   isEditing?: boolean;
20 37
   // 拆分后的标准字段
21 38
   threshold1: number;
@@ -29,549 +46,161 @@ interface ScoreItem {
29 46
   threshold6: number;
30 47
   threshold7: number;
31 48
   score4: number;
49
+  // API 响应中的其他字段
50
+  createBy?: string;
51
+  createTime?: string;
52
+  updateBy?: string;
53
+  updateTime?: string;
54
+  remark?: string;
32 55
 }
33 56
 
57
+// 数据字典选项
58
+const typeOptions = ref<any[]>([]);
59
+const dimensionOptions = ref<any[]>([]);
60
+const indicatorOptions = ref<any[]>([]);
61
+
34 62
 // 响应式数据
35 63
 // Tab切换数据
36
-const activeTab = ref<'stationManager' | 'stationStaff' | 'areaStaff' | 'headquarters' | 'station' | 'area'>('stationManager');
64
+const activeTab = ref<string>('stationManager');
37 65
 const tabOptions: TabOption[] = [
38
-  { label: '油站管理人员', value: 'stationManager' },
39
-  { label: '油站员工', value: 'stationStaff' },
40
-  { label: '片区人员', value: 'areaStaff' },
41
-  { label: '总部人员', value: 'headquarters' },
42
-  { label: '油站', value: 'station' },
43
-  { label: '片区', value: 'area' },
66
+  { label: '油站管理人员', value: 'stationManager', typeValue: 'oil_station_manager' },
67
+  { label: '油站员工', value: 'stationStaff', typeValue: 'oil_station_employee' },
68
+  { label: '片区人员', value: 'areaStaff', typeValue: 'region_personnel' },
69
+  { label: '总部人员', value: 'headquarters', typeValue: 'headquarters_personnel' },
70
+  { label: '油站', value: 'station', typeValue: 'oil_station' },
71
+  { label: '片区', value: 'area', typeValue: 'region' },
44 72
 ];
45 73
 
46
-// 油站管理人员评分数据
47
-const stationManagerScores = ref<ScoreItem[]>([
48
-  {
49
-    id: 1,
50
-    dimension: '任务数量',
51
-    indicator: '完成率',
52
-    standard: '(≥ 98% :20分  区间 95% — 98% :16分  区间 90% — 95% :12分  区间 0% — 90% :0分)',
53
-    score: 20,
54
-    isEditing: false,
55
-    // 拆分后的标准字段
56
-    threshold1: 98,
57
-    score1: 20,
58
-    threshold2: 95,
59
-    threshold3: 98,
60
-    score2: 16,
61
-    threshold4: 90,
62
-    threshold5: 95,
63
-    score3: 12,
64
-    threshold6: 0,
65
-    threshold7: 90,
66
-    score4: 0,
67
-  },
68
-  {
69
-    id: 2,
70
-    dimension: '任务质量',
71
-    indicator: '任务得分',
72
-    standard: '(≥ 4.5分 :30分  区间 4分 — 4.5分 :24分  区间 3分 — 4分 :18分  区间 0分 — 3分 :0分)',
73
-    score: 30,
74
-    isEditing: false,
75
-    // 拆分后的标准字段
76
-    threshold1: 4.5,
77
-    score1: 30,
78
-    threshold2: 4,
79
-    threshold3: 4.5,
80
-    score2: 24,
81
-    threshold4: 3,
82
-    threshold5: 4,
83
-    score3: 18,
84
-    threshold6: 0,
85
-    threshold7: 3,
86
-    score4: 0,
87
-  },
88
-  {
89
-    id: 3,
90
-    dimension: '查阅情况',
91
-    indicator: '已阅比例',
92
-    standard: '(≥ 95% :20分  区间 90% — 95% :15分  区间 80% — 90% :9分  区间 0% — 80% :0分)',
93
-    score: 20,
94
-    isEditing: false,
95
-    // 拆分后的标准字段
96
-    threshold1: 95,
97
-    score1: 20,
98
-    threshold2: 90,
99
-    threshold3: 95,
100
-    score2: 15,
101
-    threshold4: 80,
102
-    threshold5: 90,
103
-    score3: 9,
104
-    threshold6: 0,
105
-    threshold7: 80,
106
-    score4: 0,
107
-  },
108
-  {
109
-    id: 4,
110
-    dimension: '授权',
111
-    indicator: '授权点评率',
112
-    standard: '(≥ 70% :30分  区间 60% — 70% :24分  区间 50% — 60% :18分  区间 0% — 50% :0分)',
113
-    score: 30,
114
-    isEditing: false,
115
-    // 拆分后的标准字段
116
-    threshold1: 70,
117
-    score1: 30,
118
-    threshold2: 60,
119
-    threshold3: 70,
120
-    score2: 24,
121
-    threshold4: 50,
122
-    threshold5: 60,
123
-    score3: 18,
124
-    threshold6: 0,
125
-    threshold7: 50,
126
-    score4: 0,
127
-  },
128
-]);
129
-
130
-// 油站员工评分数据
131
-const stationStaffScores = ref<ScoreItem[]>([
132
-  {
133
-    id: 1,
134
-    dimension: '任务数量',
135
-    indicator: '完成率',
136
-    standard: '(≥ 98% :45分  区间 95% — 98% :36分  区间 90% — 95% :27分  区间 0% — 90% :0分)',
137
-    score: 45,
138
-    isEditing: false,
139
-    threshold1: 98,
140
-    score1: 45,
141
-    threshold2: 95,
142
-    threshold3: 98,
143
-    score2: 36,
144
-    threshold4: 90,
145
-    threshold5: 95,
146
-    score3: 27,
147
-    threshold6: 0,
148
-    threshold7: 90,
149
-    score4: 0,
150
-  },
151
-  {
152
-    id: 2,
153
-    dimension: '任务数量',
154
-    indicator: '新增任务率',
155
-    standard: '(≥ 5% :50分  区间 3% — 5% :40分  区间 1% — 3% :30分  区间 0% — 1% :0分)',
156
-    score: 50,
157
-    isEditing: false,
158
-    threshold1: 5,
159
-    score1: 50,
160
-    threshold2: 3,
161
-    threshold3: 5,
162
-    score2: 40,
163
-    threshold4: 1,
164
-    threshold5: 3,
165
-    score3: 30,
166
-    threshold6: 0,
167
-    threshold7: 1,
168
-    score4: 0,
169
-  },
170
-  {
171
-    id: 3,
172
-    dimension: '任务质量',
173
-    indicator: '任务得分',
174
-    standard: '(≥ 4.5分 :5分  区间 4分 — 4.5分 :3分  区间 3分 — 4分 :2分  区间 0分 — 3分 :0分)',
175
-    score: 5,
176
-    isEditing: false,
177
-    threshold1: 4.5,
178
-    score1: 5,
179
-    threshold2: 4,
180
-    threshold3: 4.5,
181
-    score2: 3,
182
-    threshold4: 3,
183
-    threshold5: 4,
184
-    score3: 2,
185
-    threshold6: 0,
186
-    threshold7: 3,
187
-    score4: 0,
188
-  },
189
-]);
190
-
191
-// 片区人员评分数据
192
-const areaStaffScores = ref<ScoreItem[]>([
193
-  {
194
-    id: 1,
195
-    dimension: '任务数量',
196
-    indicator: '完成率',
197
-    standard: '(≥ 98% :40分  区间 95% — 98% :32分  区间 90% — 95% :24分  区间 0% — 90% :0分)',
198
-    score: 40,
199
-    isEditing: false,
200
-    threshold1: 98,
201
-    score1: 40,
202
-    threshold2: 95,
203
-    threshold3: 98,
204
-    score2: 32,
205
-    threshold4: 90,
206
-    threshold5: 95,
207
-    score3: 24,
208
-    threshold6: 0,
209
-    threshold7: 90,
210
-    score4: 0,
211
-  },
212
-  {
213
-    id: 2,
214
-    dimension: '任务质量',
215
-    indicator: '任务得分',
216
-    standard: '(≥ 4.5分 :20分  区间 4分 — 4.5分 :16分  区间 3分 — 4分 :12分  区间 0分 — 3分 :0分)',
217
-    score: 20,
218
-    isEditing: false,
219
-    threshold1: 4.5,
220
-    score1: 20,
221
-    threshold2: 4,
222
-    threshold3: 4.5,
223
-    score2: 16,
224
-    threshold4: 3,
225
-    threshold5: 4,
226
-    score3: 12,
227
-    threshold6: 0,
228
-    threshold7: 3,
229
-    score4: 0,
230
-  },
231
-  {
232
-    id: 3,
233
-    dimension: '点评',
234
-    indicator: '点评完成率',
235
-    standard: '(≥ 95% :25分  区间 90% — 95% :20分  区间 80% — 90% :15分  区间 0% — 80% :0分)',
236
-    score: 25,
237
-    isEditing: false,
238
-    threshold1: 95,
239
-    score1: 25,
240
-    threshold2: 90,
241
-    threshold3: 95,
242
-    score2: 20,
243
-    threshold4: 80,
244
-    threshold5: 90,
245
-    score3: 15,
246
-    threshold6: 0,
247
-    threshold7: 80,
248
-    score4: 0,
249
-  },
250
-  {
251
-    id: 4,
252
-    dimension: '点评',
253
-    indicator: '按时点评率',
254
-    standard: '(≥ 95% :0分  区间 90% — 95% :0分  区间 80% — 90% :0分  区间 0% — 80% :0分)',
255
-    score: 0,
256
-    isEditing: false,
257
-    threshold1: 95,
74
+// 评分数据
75
+const scoreData = ref<ScoreItem[]>([]);
76
+const loading = ref<boolean>(false);
77
+
78
+// 获取当前选中tab对应的typeValue
79
+const getCurrentTypeValue = () => {
80
+  const tab = tabOptions.find(tab => tab.value === activeTab.value);
81
+  return tab ? tab.typeValue : '';
82
+};
83
+
84
+// 解析standardJson字段
85
+const parseStandardJson = (standardJson: string): StandardItem[] => {
86
+  try {
87
+    const parsed = JSON.parse(standardJson);
88
+    return parsed.standards || [];
89
+  } catch (error) {
90
+    console.error('解析standardJson失败:', error);
91
+    return [];
92
+  }
93
+};
94
+
95
+// 格式化标准项为阈值和分数
96
+const formatStandardsToThresholds = (standards: StandardItem[]): Partial<ScoreItem> => {
97
+  // 默认值
98
+  const defaults = {
99
+    threshold1: 0,
258 100
     score1: 0,
259
-    threshold2: 90,
260
-    threshold3: 95,
101
+    threshold2: 0,
102
+    threshold3: 0,
261 103
     score2: 0,
262
-    threshold4: 80,
263
-    threshold5: 90,
104
+    threshold4: 0,
105
+    threshold5: 0,
264 106
     score3: 0,
265 107
     threshold6: 0,
266
-    threshold7: 80,
267
-    score4: 0,
268
-  },
269
-  {
270
-    id: 5,
271
-    dimension: '逾期',
272
-    indicator: '逾期未完成数',
273
-    standard: '(≥ 9个 :0分  区间 6个 — 9个 :5分  区间 3个 — 6个 :10分  区间 0个 — 3个 :15分)',
274
-    score: 15,
275
-    isEditing: false,
276
-    threshold1: 9,
277
-    score1: 0,
278
-    threshold2: 6,
279
-    threshold3: 9,
280
-    score2: 5,
281
-    threshold4: 3,
282
-    threshold5: 6,
283
-    score3: 10,
284
-    threshold6: 0,
285
-    threshold7: 3,
286
-    score4: 15,
287
-  },
288
-]);
289
-
290
-// 总部人员评分数据
291
-const headquartersScores = ref<ScoreItem[]>([
292
-  {
293
-    id: 1,
294
-    dimension: '任务数量',
295
-    indicator: '完成率',
296
-    standard: '(≥ 98% :30分  区间 95% — 98% :24分  区间 90% — 95% :18分  区间 0% — 90% :0分)',
297
-    score: 30,
298
-    isEditing: false,
299
-    threshold1: 98,
300
-    score1: 30,
301
-    threshold2: 95,
302
-    threshold3: 98,
303
-    score2: 24,
304
-    threshold4: 90,
305
-    threshold5: 95,
306
-    score3: 18,
307
-    threshold6: 0,
308
-    threshold7: 90,
309
-    score4: 0,
310
-  },
311
-  {
312
-    id: 2,
313
-    dimension: '任务质量',
314
-    indicator: '任务得分',
315
-    standard: '(≥ 4.5分 :20分  区间 4分 — 4.5分 :16分  区间 3分 — 4分 :12分  区间 0分 — 3分 :0分)',
316
-    score: 20,
317
-    isEditing: false,
318
-    threshold1: 4.5,
319
-    score1: 20,
320
-    threshold2: 4,
321
-    threshold3: 4.5,
322
-    score2: 16,
323
-    threshold4: 3,
324
-    threshold5: 4,
325
-    score3: 12,
326
-    threshold6: 0,
327
-    threshold7: 3,
328
-    score4: 0,
329
-  },
330
-  {
331
-    id: 3,
332
-    dimension: '点评',
333
-    indicator: '点评完成率',
334
-    standard: '(≥ 95% :30分  区间 90% — 95% :20分  区间 80% — 90% :15分  区间 0% — 80% :0分)',
335
-    score: 30,
336
-    isEditing: false,
337
-    threshold1: 95,
338
-    score1: 30,
339
-    threshold2: 90,
340
-    threshold3: 95,
341
-    score2: 20,
342
-    threshold4: 80,
343
-    threshold5: 90,
344
-    score3: 15,
345
-    threshold6: 0,
346
-    threshold7: 80,
347
-    score4: 0,
348
-  },
349
-  {
350
-    id: 4,
351
-    dimension: '点评',
352
-    indicator: '按时点评率',
353
-    standard: '(≥ 95% :20分  区间 90% — 95% :15分  区间 80% — 90% :8分  区间 0% — 80% :0分)',
354
-    score: 20,
355
-    isEditing: false,
356
-    threshold1: 95,
357
-    score1: 20,
358
-    threshold2: 90,
359
-    threshold3: 95,
360
-    score2: 15,
361
-    threshold4: 80,
362
-    threshold5: 90,
363
-    score3: 8,
364
-    threshold6: 0,
365
-    threshold7: 80,
366
-    score4: 0,
367
-  },
368
-]);
369
-
370
-// 油站评分数据
371
-const stationScores = ref<ScoreItem[]>([
372
-  {
373
-    id: 1,
374
-    dimension: '任务数量',
375
-    indicator: '完成率',
376
-    standard: '(≥ 98% :30分  区间 95% — 98% :24分  区间 90% — 95% :18分  区间 0% — 90% :0分)',
377
-    score: 30,
378
-    isEditing: false,
379
-    threshold1: 98,
380
-    score1: 30,
381
-    threshold2: 95,
382
-    threshold3: 98,
383
-    score2: 24,
384
-    threshold4: 90,
385
-    threshold5: 95,
386
-    score3: 18,
387
-    threshold6: 0,
388
-    threshold7: 90,
108
+    threshold7: 0,
389 109
     score4: 0,
390
-  },
391
-  {
392
-    id: 2,
393
-    dimension: '任务质量',
394
-    indicator: '任务得分',
395
-    standard: '(≥ 4.5分 :20分  区间 4分 — 4.5分 :16分  区间 3分 — 4分 :12分  区间 0分 — 3分 :0分)',
396
-    score: 20,
397
-    isEditing: false,
398
-    threshold1: 4.5,
399
-    score1: 20,
400
-    threshold2: 4,
401
-    threshold3: 4.5,
402
-    score2: 16,
403
-    threshold4: 3,
404
-    threshold5: 4,
405
-    score3: 12,
406
-    threshold6: 0,
407
-    threshold7: 3,
408
-    score4: 0,
409
-  },
410
-  {
411
-    id: 3,
412
-    dimension: '绩效',
413
-    indicator: '最多相同分数率',
414
-    standard: '(≥ 60% :0分  区间 40% — 60% :6分  区间 20% — 40% :8分  区间 0% — 20% :10分)',
415
-    score: 10,
416
-    isEditing: false,
417
-    threshold1: 60,
418
-    score1: 0,
419
-    threshold2: 40,
420
-    threshold3: 60,
421
-    score2: 6,
422
-    threshold4: 20,
423
-    threshold5: 40,
424
-    score3: 8,
425
-    threshold6: 0,
426
-    threshold7: 20,
427
-    score4: 10,
428
-  },
429
-  {
430
-    id: 4,
431
-    dimension: '查阅情况',
432
-    indicator: '已阅比例',
433
-    standard: '(≥ 95% :15分  区间 90% — 95% :12分  区间 80% — 90% :9分  区间 0% — 80% :0分)',
434
-    score: 15,
435
-    isEditing: false,
436
-    threshold1: 95,
437
-    score1: 15,
438
-    threshold2: 90,
439
-    threshold3: 95,
440
-    score2: 12,
441
-    threshold4: 80,
442
-    threshold5: 90,
443
-    score3: 9,
444
-    threshold6: 0,
445
-    threshold7: 80,
446
-    score4: 0,
447
-  },
448
-  {
449
-    id: 5,
450
-    dimension: '逾期',
451
-    indicator: '逾期未完成数',
452
-    standard: '(≥ 9个 :0分  区间 6个 — 9个 :5分  区间 3个 — 6个 :12分  区间 0个 — 3个 :20分)',
453
-    score: 20,
454
-    isEditing: false,
455
-    threshold1: 9,
456
-    score1: 0,
457
-    threshold2: 6,
458
-    threshold3: 9,
459
-    score2: 5,
460
-    threshold4: 3,
461
-    threshold5: 6,
462
-    score3: 12,
463
-    threshold6: 0,
464
-    threshold7: 3,
465
-    score4: 20,
466
-  },
467
-]);
468
-
469
-// 片区评分数据
470
-const areaScores = ref<ScoreItem[]>([
471
-  {
472
-    id: 1,
473
-    dimension: '任务数量',
474
-    indicator: '完成率',
475
-    standard: '(≥ 98% :40分  区间 95% — 98% :32分  区间 90% — 95% :24分  区间 0% — 90% :0分)',
476
-    score: 40,
477
-    isEditing: false,
478
-    threshold1: 98,
479
-    score1: 40,
480
-    threshold2: 95,
481
-    threshold3: 98,
482
-    score2: 32,
483
-    threshold4: 90,
484
-    threshold5: 95,
485
-    score3: 24,
486
-    threshold6: 0,
487
-    threshold7: 90,
488
-    score4: 0,
489
-  },
490
-  {
491
-    id: 2,
492
-    dimension: '任务质量',
493
-    indicator: '任务得分',
494
-    standard: '(≥ 4.5分 :20分  区间 4分 — 4.5分 :16分  区间 3分 — 4分 :12分  区间 0分 — 3分 :0分)',
495
-    score: 20,
496
-    isEditing: false,
497
-    threshold1: 4.5,
498
-    score1: 20,
499
-    threshold2: 4,
500
-    threshold3: 4.5,
501
-    score2: 16,
502
-    threshold4: 3,
503
-    threshold5: 4,
504
-    score3: 12,
505
-    threshold6: 0,
506
-    threshold7: 3,
507
-    score4: 0,
508
-  },
509
-  {
510
-    id: 3,
511
-    dimension: '绩效',
512
-    indicator: '最多相同分数率',
513
-    standard: '(≥ 95% :0分  区间 90% — 95% :12分  区间 80% — 90% :9分  区间 0% — 80% :15分)',
514
-    score: 15,
515
-    isEditing: false,
516
-    threshold1: 95,
517
-    score1: 0,
518
-    threshold2: 90,
519
-    threshold3: 95,
520
-    score2: 12,
521
-    threshold4: 80,
522
-    threshold5: 90,
523
-    score3: 9,
524
-    threshold6: 0,
525
-    threshold7: 80,
526
-    score4: 15,
527
-  },
528
-  {
529
-    id: 4,
530
-    dimension: '查阅情况',
531
-    indicator: '已阅比例',
532
-    standard: '(≥ 95% :15分  区间 90% — 95% :12分  区间 80% — 90% :9分  区间 0% — 80% :0分)',
533
-    score: 15,
534
-    isEditing: false,
535
-    threshold1: 95,
536
-    score1: 15,
537
-    threshold2: 90,
538
-    threshold3: 95,
539
-    score2: 12,
540
-    threshold4: 80,
541
-    threshold5: 90,
542
-    score3: 9,
543
-    threshold6: 0,
544
-    threshold7: 80,
545
-    score4: 0,
546
-  },
547
-]);
110
+  };
111
+  
112
+  if (!standards || standards.length === 0) {
113
+    return defaults;
114
+  }
115
+  
116
+  // 按min_value降序排序
117
+  const sortedStandards = [...standards].sort((a, b) => (b.min_value || 0) - (a.min_value || 0));
118
+  
119
+  // 填充阈值和分数
120
+  return {
121
+    threshold1: sortedStandards[0]?.min_value || 0,
122
+    score1: sortedStandards[0]?.score || 0,
123
+    threshold2: sortedStandards[1]?.min_value || 0,
124
+    threshold3: sortedStandards[1]?.max_value || 0,
125
+    score2: sortedStandards[1]?.score || 0,
126
+    threshold4: sortedStandards[2]?.min_value || 0,
127
+    threshold5: sortedStandards[2]?.max_value || 0,
128
+    score3: sortedStandards[2]?.score || 0,
129
+    threshold6: sortedStandards[3]?.min_value || 0,
130
+    threshold7: sortedStandards[3]?.max_value || 0,
131
+    score4: sortedStandards[3]?.score || 0,
132
+  };
133
+};
134
+
135
+// 加载评分数据
136
+const loadScoreData = async () => {
137
+  const typeValue = getCurrentTypeValue();
138
+  if (!typeValue) return;
139
+  
140
+  loading.value = true;
141
+  try {
142
+    const response = await scoreEntryList({ type: typeValue });
143
+    console.log('原始响应:', response);
144
+    if (response.rows) {
145
+      scoreData.value = response.rows.map((item: any) => {
146
+        const standards = parseStandardJson(item.standardJson);
147
+        const thresholds = formatStandardsToThresholds(standards);
148
+        return {
149
+          ...item,
150
+          standards,
151
+          isEditing: false,
152
+          ...thresholds,
153
+        };
154
+      });
155
+    }
156
+  } catch (error) {
157
+    console.error('加载评分数据失败:', error);
158
+  } finally {
159
+    loading.value = false;
160
+  }
161
+};
162
+
163
+// 监听tab切换,重新加载数据
164
+const handleTabChange = () => {
165
+  loadScoreData();
166
+};
548 167
 
549 168
 // 计算当前选中的评分数据
550 169
 const currentScores = computed(() => {
551
-  switch (activeTab.value) {
552
-    case 'stationManager':
553
-      return stationManagerScores.value;
554
-    case 'stationStaff':
555
-      return stationStaffScores.value;
556
-    case 'areaStaff':
557
-      return areaStaffScores.value;
558
-    case 'headquarters':
559
-      return headquartersScores.value;
560
-    case 'station':
561
-      return stationScores.value;
562
-    case 'area':
563
-      return areaScores.value;
564
-    default:
565
-      return [];
566
-  }
170
+  return scoreData.value;
567 171
 });
568 172
 
173
+// 初始化数据
174
+onMounted(async () => {
175
+  // 加载数据字典
176
+  typeOptions.value = getDictOptions("score_standard_type");
177
+  dimensionOptions.value = getDictOptions("score_standard_dimension");
178
+  indicatorOptions.value = getDictOptions("score_standard_indicator");
179
+  
180
+  // 加载初始数据
181
+  await loadScoreData();
182
+});
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
569 198
 // 计算需要合并的行
570 199
 const getRowspan = (scores: ScoreItem[], index: number): number => {
571
-  const currentDimension = scores[index].dimension;
200
+  const currentDimension = scores[index].dimensionName;
572 201
   let rowspan = 1;
573 202
   for (let i = index + 1; i < scores.length; i++) {
574
-    if (scores[i].dimension === currentDimension) {
203
+    if (scores[i].dimensionName === currentDimension) {
575 204
       rowspan++;
576 205
     } else {
577 206
       break;
@@ -585,10 +214,10 @@ const tableSpanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
585 214
   // 只处理维度列的合并
586 215
   if (columnIndex === 0) {
587 216
     const scores = currentScores.value;
588
-    const currentDimension = scores[rowIndex].dimension;
217
+    const currentDimension = scores[rowIndex].dimensionName;
589 218
     
590 219
     // 检查当前行是否是连续相同维度行的第一行
591
-    if (rowIndex === 0 || scores[rowIndex - 1].dimension !== currentDimension) {
220
+    if (rowIndex === 0 || scores[rowIndex - 1].dimensionName !== currentDimension) {
592 221
       const rowspan = getRowspan(scores, rowIndex);
593 222
       return [rowspan, 1];
594 223
     } else {
@@ -601,7 +230,7 @@ const tableSpanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
601 230
 
602 231
 // 事件处理函数
603 232
 // 编辑按钮点击事件
604
-const handleEdit = (id: number) => {
233
+const handleEdit = (id: string) => {
605 234
   const scores = currentScores.value;
606 235
   const item = scores.find(item => item.id === id);
607 236
   if (item) {
@@ -610,13 +239,55 @@ const handleEdit = (id: number) => {
610 239
 };
611 240
 
612 241
 // 保存按钮点击事件
613
-const handleSave = (id: number) => {
242
+const handleSave = async (id: string) => {
614 243
   const scores = currentScores.value;
615 244
   const item = scores.find(item => item.id === id);
616 245
   if (item) {
617
-    // 更新standard字段以保持数据一致性
618
-    item.standard = `≥ ${item.threshold1}% :${item.score1}分  区间 ${item.threshold2}% — ${item.threshold3}% :${item.score2}分  区间 ${item.threshold4}% — ${item.threshold5}% :${item.score3}分  区间 ${item.threshold6}% — ${item.threshold7}% :${item.score4}分`;
619
-    item.isEditing = false;
246
+    // 生成新的standardJson
247
+    const standards = [
248
+      {
249
+        score: item.score1,
250
+        condition: `≥${item.threshold1}%`,
251
+        min_value: item.threshold1,
252
+        max_value: null
253
+      },
254
+      {
255
+        score: item.score2,
256
+        condition: `${item.threshold2}%—${item.threshold3}%`,
257
+        min_value: item.threshold2,
258
+        max_value: item.threshold3
259
+      },
260
+      {
261
+        score: item.score3,
262
+        condition: `${item.threshold4}%—${item.threshold5}%`,
263
+        min_value: item.threshold4,
264
+        max_value: item.threshold5
265
+      },
266
+      {
267
+        score: item.score4,
268
+        condition: `${item.threshold6}%—${item.threshold7}%`,
269
+        min_value: item.threshold6,
270
+        max_value: item.threshold7
271
+      }
272
+    ];
273
+    
274
+    const updatedItem = {
275
+      id: item.id,
276
+      type: item.type,
277
+      dimension: item.dimension,
278
+      indicator: item.indicator,
279
+      standardJson: JSON.stringify({ standards })
280
+    };
281
+    
282
+    try {
283
+      const response = await updateScoreEntry(updatedItem);
284
+      console.log('更新响应:', response);
285
+      item.isEditing = false;
286
+      // 重新加载数据以确保一致性
287
+      await loadScoreData();
288
+    } catch (error) {
289
+      console.error('保存失败:', error);
290
+    }
620 291
   }
621 292
 };
622 293
 
@@ -627,13 +298,13 @@ const handleSave = (id: number) => {
627 298
     <div class="score-entry">
628 299
       <!-- Tab切换区域 -->
629 300
       <div class="tab-container">
630
-        <ElTabs v-model="activeTab">
301
+        <ElTabs v-model="activeTab" @tab-click="handleTabChange">
631 302
           <ElTabPane v-for="tab in tabOptions" :key="tab.value" :label="tab.label" :name="tab.value">
632 303
             <!-- 评分表格 -->
633 304
             <div class="score-table-container">
634 305
               <ElTable :data="currentScores" border stripe style="width: 100%" :span-method="tableSpanMethod">
635
-                <ElTableColumn prop="dimension" label="维度" width="150" />
636
-                <ElTableColumn prop="indicator" label="指标" width="180" />
306
+                <ElTableColumn prop="dimensionName" label="维度" width="150" />
307
+                <ElTableColumn prop="indicatorName" label="指标" width="180" />
637 308
                 <ElTableColumn label="标准及分值">
638 309
                   <template #default="scope">
639 310
                     <div v-if="scope.row.isEditing" class="standard-edit">

+ 0 - 26
apps/web-ele/src/views/workflow/components/approval-content.vue

@@ -1,26 +0,0 @@
1
-<!-- 审批终止 Modal弹窗的content属性专用 用于填写审批意见 -->
2
-<script setup lang="ts">
3
-// import { Textarea } from 'ant-design-vue';
4
-
5
-defineOptions({
6
-  name: 'ApprovalContent',
7
-  inheritAttrs: false,
8
-});
9
-
10
-defineProps<{ description: string; value: string }>();
11
-
12
-defineEmits<{ 'update:value': [string] }>();
13
-</script>
14
-
15
-<template>
16
-  <div class="flex flex-col gap-2">
17
-    <div>{{ description }}</div>
18
-    <ElInput
19
-      :allow-clear="true"
20
-      :auto-size="true"
21
-      :model="value"
22
-      placeholder="审批意见(可选)"
23
-      @change="(e) => $emit('update:value', e.target.value!)"
24
-    />
25
-  </div>
26
-</template>

+ 0 - 38
apps/web-ele/src/views/workflow/components/helper.tsx

@@ -1,11 +1,8 @@
1
-import { defineComponent, h, ref } from 'vue';
2 1
 
3
-import { ElMessageBox } from 'element-plus';
4 2
 import dayjs from 'dayjs';
5 3
 import duration from 'dayjs/plugin/duration';
6 4
 import relativeTime from 'dayjs/plugin/relativeTime';
7 5
 
8
-import ApprovalContent from './approval-content.vue';
9 6
 
10 7
 export interface ApproveWithReasonModalProps {
11 8
   title: string;
@@ -13,41 +10,6 @@ export interface ApproveWithReasonModalProps {
13 10
   onOk: (reason: string) => void;
14 11
 }
15 12
 
16
-/**
17
- * 带审批意见的confirm
18
- * @param props props
19
- */
20
-export function approveWithReasonModal(props: ApproveWithReasonModalProps) {
21
-  const { onOk, title, description } = props;
22
-  const content = ref('');
23
-  ElMessageBox.confirm(
24
-    h(
25
-      defineComponent({
26
-        setup() {
27
-          return () =>
28
-            h(ApprovalContent, {
29
-              description,
30
-              value: content.value,
31
-              'onUpdate:value': (v) => (content.value = v),
32
-            });
33
-        },
34
-      }),
35
-    ),
36
-    title,
37
-    {
38
-      confirmButtonText: '确定',
39
-      cancelButtonText: '取消',
40
-      center: true,
41
-      confirmButtonClass: 'el-button--danger',
42
-      callback: (action) => {
43
-        if (action === 'confirm') {
44
-          onOk(content.value);
45
-        }
46
-      },
47
-    },
48
-  );
49
-}
50
-
51 13
 dayjs.extend(duration);
52 14
 dayjs.extend(relativeTime);
53 15
 /**

+ 9 - 10
apps/web-ele/src/views/workflow/leave/data.tsx

@@ -49,16 +49,15 @@ export const querySchema: FormSchemaGetter = () => [
49 49
 
50 50
 export const columns: VxeGridProps['columns'] = [
51 51
   { type: 'checkbox', width: 60 },
52
-  {
53
-    title: '请假类型',
54
-    field: 'leaveType',
55
-    // slots: {
56
-    //   default: ({ row }) => {
57
-    //     // return renderDict(row.leaveType, leaveTypeOptions);
58
-    //     // return <OptionsTag options={leaveTypeOptions} value={row.leaveType} />;
59
-    //   },
60
-    // },
61
-  },
52
+  // {
53
+  //   title: '请假类型',
54
+  //   field: 'leaveType',
55
+  //   slots: {
56
+  //     default: ({ row }) => {
57
+  //       // return <OptionsTag options={leaveTypeOptions} value={row.leaveType} />;
58
+  //     },
59
+  //   },
60
+  // },
62 61
   {
63 62
     title: '开始时间',
64 63
     field: 'startDate',

+ 0 - 243
apps/web-ele/src/views/workflow/leave/index.vue

@@ -1,243 +0,0 @@
1
-<script setup lang="ts">
2
-import type { VbenFormProps } from '@vben/common-ui';
3
-
4
-import type { LeaveForm } from './api/model';
5
-
6
-import type { VxeGridProps } from '#/adapter/vxe-table';
7
-
8
-import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
9
-import { getVxePopupContainer } from '@vben/utils';
10
-
11
-// import { Modal, Popconfirm, Space } from 'ant-design-vue';
12
-import { useVbenVxeGrid } from '#/adapter/vxe-table';
13
-import { cancelProcessApply } from '#/api/workflow/instance';
14
-import { commonDownloadExcel } from '#/utils/file/download';
15
-
16
-import { applyModal, flowInfoModal } from '../components';
17
-import { leaveExport, leaveList, leaveRemove } from './api';
18
-import { columns, querySchema } from './data';
19
-import { useRouteIdEdit } from './hook';
20
-import leaveDrawer from './leave-drawer.vue';
21
-
22
-const formOptions: VbenFormProps = {
23
-  commonConfig: {
24
-    labelWidth: 80,
25
-    componentProps: {
26
-      allowClear: true,
27
-    },
28
-  },
29
-  schema: querySchema(),
30
-  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
31
-};
32
-
33
-const gridOptions: VxeGridProps = {
34
-  checkboxConfig: {
35
-    // 高亮
36
-    highlight: true,
37
-    // 翻页时保留选中状态
38
-    reserve: true,
39
-    // 选中 需要根据状态判断
40
-    checkMethod: ({ row }) => ['back', 'cancel', 'draft'].includes(row.status),
41
-  },
42
-  columns,
43
-  height: 'auto',
44
-  keepSource: true,
45
-  pagerConfig: {},
46
-  proxyConfig: {
47
-    ajax: {
48
-      query: async ({ page }, formValues = {}) => {
49
-        return await leaveList({
50
-          pageNum: page.currentPage,
51
-          pageSize: page.pageSize,
52
-          ...formValues,
53
-        });
54
-      },
55
-    },
56
-  },
57
-  rowConfig: {
58
-    keyField: 'id',
59
-  },
60
-  // 表格全局唯一表示 保存列配置需要用到
61
-  id: 'workflow-leave-index',
62
-  cellClassName: ({ row }) => {
63
-    // 草稿状态 可点击
64
-    if (row.status !== 'draft') {
65
-      return 'cursor-pointer';
66
-    }
67
-  },
68
-};
69
-
70
-const [BasicTable, tableApi] = useVbenVxeGrid({
71
-  formOptions,
72
-  gridOptions,
73
-  gridEvents: {
74
-    cellClick: ({ row, column }) => {
75
-      // 草稿状态 不做处理
76
-      // 操作列 不做处理
77
-      if (row.status === 'draft' || column.field === 'action') {
78
-        return;
79
-      }
80
-      // 查看详情
81
-      handleInfo(row);
82
-    },
83
-  },
84
-});
85
-
86
-const [ApplyModal, applyModalApi] = useVbenModal({
87
-  connectedComponent: applyModal,
88
-});
89
-const [LeaveDrawer, leaveDrawerApi] = useVbenDrawer({
90
-  connectedComponent: leaveDrawer,
91
-});
92
-
93
-function handleAdd() {
94
-  leaveDrawerApi.setData({ applyModalApi }).open();
95
-}
96
-
97
-async function handleEdit(row: Required<LeaveForm>) {
98
-  leaveDrawerApi.setData({ id: row.id, applyModalApi }).open();
99
-}
100
-
101
-useRouteIdEdit((id) => {
102
-  // 打开编辑
103
-  leaveDrawerApi.setData({ id, applyModalApi }).open();
104
-});
105
-
106
-async function handleCompleteOrCancel() {
107
-  leaveDrawerApi.close();
108
-  tableApi.query();
109
-}
110
-
111
-async function handleDelete(row: Required<LeaveForm>) {
112
-  await leaveRemove(row.id);
113
-  await tableApi.query();
114
-}
115
-
116
-async function handleRevoke(row: Required<LeaveForm>) {
117
-  await cancelProcessApply({
118
-    businessId: row.id,
119
-    message: '申请人撤销流程!',
120
-  });
121
-  await tableApi.query();
122
-}
123
-
124
-function handleMultiDelete() {
125
-  const rows = tableApi.grid.getCheckboxRecords();
126
-  const ids = rows.map((row: Required<LeaveForm>) => row.id);
127
-  Modal.confirm({
128
-    title: '提示',
129
-    okType: 'danger',
130
-    content: `确认删除选中的${ids.length}条记录吗?`,
131
-    onOk: async () => {
132
-      await leaveRemove(ids);
133
-      await tableApi.query();
134
-    },
135
-  });
136
-}
137
-
138
-function handleDownloadExcel() {
139
-  commonDownloadExcel(
140
-    leaveExport,
141
-    '请假申请数据',
142
-    tableApi.formApi.form.values,
143
-    {
144
-      fieldMappingTime: formOptions.fieldMappingTime,
145
-    },
146
-  );
147
-}
148
-const [FlowInfoModal, flowInfoModalApi] = useVbenModal({
149
-  connectedComponent: flowInfoModal,
150
-});
151
-
152
-function handleInfo(row: Required<LeaveForm>) {
153
-  flowInfoModalApi.setData({ businessId: row.id });
154
-  flowInfoModalApi.open();
155
-}
156
-</script>
157
-
158
-<template>
159
-  <Page :auto-content-height="true">
160
-    <BasicTable table-title="请假申请列表">
161
-      <template #toolbar-tools>
162
-        <Space>
163
-          <a-button
164
-            v-access:code="['workflow:leave:export']"
165
-            @click="handleDownloadExcel"
166
-          >
167
-            {{ $t('pages.common.export') }}
168
-          </a-button>
169
-          <a-button
170
-            :disabled="!vxeCheckboxChecked(tableApi)"
171
-            danger
172
-            type="primary"
173
-            v-access:code="['workflow:leave:remove']"
174
-            @click="handleMultiDelete"
175
-          >
176
-            {{ $t('pages.common.delete') }}
177
-          </a-button>
178
-          <a-button
179
-            type="primary"
180
-            v-access:code="['workflow:leave:add']"
181
-            @click="handleAdd"
182
-          >
183
-            {{ $t('pages.common.add') }}
184
-          </a-button>
185
-        </Space>
186
-      </template>
187
-      <template #action="{ row }">
188
-        <a-button
189
-          size="small"
190
-          type="link"
191
-          :disabled="!['draft', 'cancel', 'back'].includes(row.status)"
192
-          v-access:code="['workflow:leave:edit']"
193
-          @click.stop="handleEdit(row)"
194
-        >
195
-          {{ $t('pages.common.edit') }}
196
-        </a-button>
197
-        <Popconfirm
198
-          :get-popup-container="getVxePopupContainer"
199
-          placement="left"
200
-          title="确认撤销?"
201
-          :disabled="!['waiting'].includes(row.status)"
202
-          @confirm.stop="handleRevoke(row)"
203
-          @cancel.stop=""
204
-        >
205
-          <a-button
206
-            size="small"
207
-            type="link"
208
-            :disabled="!['waiting'].includes(row.status)"
209
-            v-access:code="['workflow:leave:edit']"
210
-            @click.stop=""
211
-          >
212
-            撤销
213
-          </a-button>
214
-        </Popconfirm>
215
-        <Popconfirm
216
-          :get-popup-container="getVxePopupContainer"
217
-          placement="left"
218
-          title="确认删除?"
219
-          :disabled="!['draft', 'cancel', 'back'].includes(row.status)"
220
-          @confirm.stop="handleDelete(row)"
221
-          @cancel.stop=""
222
-        >
223
-          <a-button
224
-            size="small"
225
-            type="link"
226
-            :disabled="!['draft', 'cancel', 'back'].includes(row.status)"
227
-            danger
228
-            v-access:code="['workflow:leave:remove']"
229
-            @click.stop=""
230
-          >
231
-            {{ $t('pages.common.delete') }}
232
-          </a-button>
233
-        </Popconfirm>
234
-      </template>
235
-    </BasicTable>
236
-    <FlowInfoModal />
237
-    <ApplyModal
238
-      @complete="handleCompleteOrCancel"
239
-      @cancel="handleCompleteOrCancel"
240
-    />
241
-    <LeaveDrawer @reload="() => tableApi.query()" />
242
-  </Page>
243
-</template>

+ 0 - 190
apps/web-ele/src/views/workflow/leave/leave-drawer.vue

@@ -1,190 +0,0 @@
1
-<script setup lang="ts">
2
-import type { ExtendedModalApi } from '@vben/common-ui';
3
-
4
-import type { StartWorkFlowReqData } from '#/api/workflow/task/model';
5
-
6
-import { computed, ref, shallowRef } from 'vue';
7
-
8
-import { useVbenDrawer } from '@vben/common-ui';
9
-import { $t } from '@vben/locales';
10
-import { cloneDeep } from '@vben/utils';
11
-
12
-import dayjs from 'dayjs';
13
-import { omit } from 'lodash-es';
14
-
15
-import { useVbenForm } from '#/adapter/form';
16
-import { startWorkFlow } from '#/api/workflow/task';
17
-
18
-import {
19
-  leaveAdd,
20
-  leaveInfo,
21
-  leaveUpdate,
22
-  submitAndStartWorkflow,
23
-} from './api';
24
-import { formSchema } from './data';
25
-
26
-const emit = defineEmits<{ reload: [] }>();
27
-
28
-const isUpdate = ref(false);
29
-const title = computed(() => {
30
-  return isUpdate.value ? $t('pages.common.edit') : $t('pages.common.add');
31
-});
32
-
33
-const [BasicForm, formApi] = useVbenForm({
34
-  layout: 'vertical',
35
-  commonConfig: {
36
-    formItemClass: 'col-span-2',
37
-    componentProps: {
38
-      class: 'w-full',
39
-    },
40
-    labelWidth: 100,
41
-  },
42
-  schema: formSchema(),
43
-  showDefaultActions: false,
44
-  wrapperClass: 'grid-cols-2',
45
-});
46
-
47
-const modalApi = shallowRef<ExtendedModalApi | null>(null);
48
-
49
-const [BasicDrawer, drawerApi] = useVbenDrawer({
50
-  closeOnClickModal: false,
51
-  onClosed: handleClosed,
52
-  onConfirm: handleStartWorkFlow,
53
-  async onOpenChange(isOpen) {
54
-    if (!isOpen) {
55
-      return null;
56
-    }
57
-    drawerApi.drawerLoading(true);
58
-
59
-    const { id, applyModalApi } = drawerApi.getData() as {
60
-      applyModalApi: ExtendedModalApi;
61
-      id?: number | string;
62
-    };
63
-    modalApi.value = applyModalApi;
64
-    isUpdate.value = !!id;
65
-    // 赋值
66
-    if (isUpdate.value && id) {
67
-      const resp = await leaveInfo(id);
68
-      await formApi.setValues(resp);
69
-      const dateRange = [dayjs(resp.startDate), dayjs(resp.endDate)];
70
-      await formApi.setFieldValue('dateRange', dateRange);
71
-    }
72
-
73
-    drawerApi.drawerLoading(false);
74
-  },
75
-});
76
-
77
-async function handleClosed() {
78
-  await formApi.resetForm();
79
-}
80
-
81
-/**
82
- * 获取已经处理好的表单参数
83
- */
84
-async function getFormData() {
85
-  const { valid } = await formApi.validate();
86
-  if (!valid) {
87
-    throw new Error('表单验证失败');
88
-  }
89
-  let data = cloneDeep(await formApi.getValues()) as any;
90
-  data = omit(data, 'flowType', 'type');
91
-  // 处理日期
92
-  data.startDate = dayjs(data.dateRange[0]).format('YYYY-MM-DD HH:mm:ss');
93
-  data.endDate = dayjs(data.dateRange[1]).format('YYYY-MM-DD HH:mm:ss');
94
-  return data;
95
-}
96
-
97
-/**
98
- * 暂存/提交 提取通用逻辑
99
- */
100
-async function handleSaveOrUpdate() {
101
-  const data = await getFormData();
102
-  return await (isUpdate.value ? leaveUpdate(data) : leaveAdd(data));
103
-}
104
-
105
-/**
106
- * 暂存 草稿状态
107
- */
108
-async function handleTempSave() {
109
-  try {
110
-    await handleSaveOrUpdate();
111
-    emit('reload');
112
-    drawerApi.close();
113
-  } catch (error) {
114
-    console.error(error);
115
-  }
116
-}
117
-
118
-/**
119
- * 保存业务 & 发起流程
120
- */
121
-async function handleStartWorkFlow() {
122
-  drawerApi.lock(true);
123
-  try {
124
-    const { valid } = await formApi.validate();
125
-    if (!valid) {
126
-      return;
127
-    }
128
-    // 获取发起类型
129
-    const { type } = await formApi.getValues();
130
-    /**
131
-     * 这里只是demo 实际只会用到一种
132
-     */
133
-    switch (type) {
134
-      // 后端发起流程
135
-      case 'backend': {
136
-        const data = await getFormData();
137
-        await submitAndStartWorkflow(data);
138
-        emit('reload');
139
-        drawerApi.close();
140
-        break;
141
-      }
142
-      // 前端发起流程
143
-      case 'frontend': {
144
-        // 保存业务
145
-        const leaveResp = await handleSaveOrUpdate();
146
-        // 启动流程
147
-        const taskVariables = {
148
-          leaveDays: leaveResp!.leaveDays,
149
-          userList: ['1', '3', '4'],
150
-        };
151
-        const formValues = await formApi.getValues();
152
-        const flowCode = formValues?.flowType ?? 'leave1';
153
-        const startWorkFlowData: StartWorkFlowReqData = {
154
-          businessId: leaveResp!.id,
155
-          flowCode,
156
-          variables: taskVariables,
157
-          flowInstanceBizExtBo: {
158
-            businessTitle: '请假申请 - 自定义标题',
159
-            businessCode: leaveResp!.applyCode,
160
-          },
161
-        };
162
-        const { taskId } = await startWorkFlow(startWorkFlowData);
163
-        // 打开窗口
164
-        modalApi.value?.setData({
165
-          taskId,
166
-          taskVariables,
167
-          variables: {},
168
-        });
169
-        modalApi.value?.open();
170
-        break;
171
-      }
172
-    }
173
-    emit('reload');
174
-    drawerApi.close();
175
-  } catch (error) {
176
-    console.error(error);
177
-  } finally {
178
-    drawerApi.lock(false);
179
-  }
180
-}
181
-</script>
182
-
183
-<template>
184
-  <BasicDrawer :title="title" class="w-[600px]">
185
-    <BasicForm />
186
-    <template #center-footer>
187
-      <a-button @click="handleTempSave">暂存</a-button>
188
-    </template>
189
-  </BasicDrawer>
190
-</template>

+ 10 - 12
apps/web-ele/src/views/workflow/task/allTaskWaiting.vue

@@ -8,18 +8,16 @@ import { computed, nextTick, onMounted, ref, useTemplateRef } from 'vue';
8 8
 import { Page } from '@vben/common-ui';
9 9
 import { useTabs } from '@vben/hooks';
10 10
 
11
-// import {
12
-//   Empty,
13
-//   Form,
14
-//   FormItem,
15
-//   Input,
16
-//   InputSearch,
17
-//   Popover,
18
-//   Segmented,
19
-//   Spin,
20
-//   Tooltip,
21
-//   TreeSelect,
22
-// } from 'ant-design-vue';
11
+import { Filter, Refresh } from '@element-plus/icons-vue';
12
+import {
13
+  ElButton,
14
+  ElForm,
15
+  ElFormItem,
16
+  ElInput,
17
+  ElMessage,
18
+  ElPopover,
19
+  ElTooltip,
20
+} from 'element-plus';
23 21
 import { cloneDeep, debounce, uniqueId } from 'lodash-es';
24 22
 
25 23
 import { categoryTree } from '#/api/workflow/category';