Parcourir la source

feat(monthlyAssess): 重构扣分指标弹窗,支持多明细奖惩管理

1.  将原有的单条奖惩改为多条明细管理,支持按发生次数动态生成明细项
2.  新增表单校验规则,必填校验指标名称
3.  拆分奖励/扣罚模块,根据分值自动显示对应表单
4.  新增总分计算逻辑,自动汇总明细金额
5.  调整表单布局与样式,优化交互体验
6.  修复原有表单绑定与初始化逻辑问题
huoyi il y a 1 mois
Parent
commit
5e3addadf7
1 fichiers modifiés avec 79 ajouts et 38 suppressions
  1. 79 38
      src/views/performanceManage/monthlyAssess/index.vue

+ 79 - 38
src/views/performanceManage/monthlyAssess/index.vue

@@ -481,16 +481,16 @@
481 481
 
482 482
     <!-- 第二个模态框:添加/编辑扣分指标 -->
483 483
     <el-dialog :title="indicatorDialog.title" v-model="indicatorDialog.visible" width="60%">
484
-      <el-form label-width="150px" class="indicator-form">
485
-        <el-form-item label="指标名称" prop="indicatorId">
486
-          <div style="display: flex; align-items: center; gap: 10px; width: 100%;">
484
+      <el-form label-width="150px" class="indicator-form" :model="indicatorDialog.form" :rules="indicatorDialog.rules">
485
+        <el-form-item label="指标名称" prop="indicatorId" required>
486
+   
487 487
             <el-select v-model="indicatorDialog.form.indicatorId" placeholder="搜索指标名称" filterable remote reserve-keyword
488 488
               :remote-method="searchIndicators" :loading="indicatorDialog.loading" style="flex: 1;"
489 489
               @change="onIndicatorNameChange">
490 490
               <el-option v-for="item in indicatorDialog.indicatorOptions" :key="item.id" :label="item.name"
491 491
                 :value="item.id" />
492 492
             </el-select>
493
-          </div>
493
+        
494 494
         </el-form-item>
495 495
 
496 496
         <el-form-item label="分值/单位">
@@ -508,34 +508,38 @@
508 508
           </div>
509 509
         </el-form-item>
510 510
 
511
-        <el-form-item label="检查部门">
512
-          <el-select v-model="indicatorDialog.form.qcDeptType" placeholder="请选择" style="width: 200px;">
513
-            <el-option v-for="item in base_performance_indicator_qc_dept_type" :key="item.value" :label="item.label"
514
-              :value="item.value" />
515
-          </el-select>
516
-        </el-form-item>
517
-
518
-        <el-form-item label="奖励明细">
519
-          <el-input v-model="indicatorDialog.form.rewardDetails" type="textarea" :rows="2" />
520
-        </el-form-item>
521
-
522
-        <el-form-item label="奖励">
523
-          <div style="display: flex; align-items: center; gap: 10px;">
524
-            <el-input-number v-model="indicatorDialog.form.reward" :min="0" :precision="2" style="width: 200px;" />
525
-            <span>元</span>
511
+        <template v-for="(detail, index) in (indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList || [])" :key="index">
512
+          <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
513
+            <h4 style="margin: 0;">明细{{ index + 1 }}</h4>
514
+            <el-button type="danger" size="small" @click="removeRewardPunishmentDetail(index)">删除</el-button>
526 515
           </div>
527
-        </el-form-item>
528
-
529
-        <el-form-item label="惩罚明细">
530
-          <el-input v-model="indicatorDialog.form.penaltyDetails" type="textarea" :rows="2" />
531
-        </el-form-item>
532
-
533
-        <el-form-item label="扣罚">
534
-          <div style="display: flex; align-items: center; gap: 10px;">
535
-            <el-input-number v-model="indicatorDialog.form.penalty" :min="0" :precision="2" style="width: 200px;" />
536
-            <span>元</span>
537
-          </div>
538
-        </el-form-item>
516
+          <el-form-item label="检查部门">
517
+            <div style="display: flex; align-items: center; gap: 10px; width: 100%;">
518
+              <el-select v-model="detail.qcDeptType" placeholder="请选择" style="width: 200px;">
519
+                <el-option v-for="item in base_performance_indicator_qc_dept_type" :key="item.value" :label="item.label"
520
+                  :value="item.value" />
521
+              </el-select>
522
+            </div>
523
+          </el-form-item>
524
+          <el-form-item v-if="indicatorDialog.form.score > 0" label="奖励明细">
525
+            <el-input v-model="detail.rewardPunishmentDetail" type="textarea" :rows="2" />
526
+          </el-form-item>
527
+          <el-form-item v-if="indicatorDialog.form.score > 0" label="奖励">
528
+            <div style="display: flex; align-items: center; gap: 10px;">
529
+              <el-input-number v-model="detail.amount" :min="0" :precision="2" style="width: 200px;" @change="updateTotal" />
530
+              <span>元</span>
531
+            </div>
532
+          </el-form-item>
533
+          <el-form-item v-if="indicatorDialog.form.score < 0" label="惩罚明细">
534
+            <el-input v-model="detail.rewardPunishmentDetail" type="textarea" :rows="2" />
535
+          </el-form-item>
536
+          <el-form-item v-if="indicatorDialog.form.score < 0" label="扣罚">
537
+            <div style="display: flex; align-items: center; gap: 10px;">
538
+              <el-input-number v-model="detail.amount" :min="0" :precision="2" style="width: 200px;" @change="updateTotal" />
539
+              <span>元</span>
540
+            </div>
541
+          </el-form-item>
542
+        </template>
539 543
       </el-form>
540 544
 
541 545
       <template #footer>
@@ -704,6 +708,11 @@ const indicatorDialog = reactive({
704 708
   itemIndex: null,
705 709
   loading: false,
706 710
   indicatorOptions: [],
711
+  rules: {
712
+    indicatorId: [
713
+      { required: true, message: '请选择指标名称', trigger: 'change' }
714
+    ]
715
+  },
707 716
   form: {
708 717
     indicatorId: '',
709 718
     name: '',
@@ -711,6 +720,7 @@ const indicatorDialog = reactive({
711 720
     occurCount: 1,
712 721
     qcDeptType: '',
713 722
     scoreResult: 0,
723
+    amountResult: 0,
714 724
     rewardDetails: '',
715 725
     reward: 0,
716 726
     penaltyDetails: '',
@@ -1121,14 +1131,14 @@ const addIndicator = () => {
1121 1131
   indicatorDialog.itemIndex = null
1122 1132
   indicatorDialog.form = {
1123 1133
     name: '',
1124
-    score: -3,
1134
+    score: 0,
1125 1135
     occurCount: 1,
1126 1136
     qcDeptType: '',
1127 1137
     scoreResult: 0,
1128
-    rewardDetails: '',
1129
-    reward: 0,
1130
-    penaltyDetails: '',
1131
-    penalty: 0
1138
+    amountResult: 0,
1139
+    rewardPunishmentDetail: '',
1140
+    amount: 0,
1141
+    personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList: []
1132 1142
   }
1133 1143
 }
1134 1144
 
@@ -1141,6 +1151,9 @@ const editIndicator = (groupIndex, itemIndex) => {
1141 1151
   indicatorDialog.groupIndex = groupIndex
1142 1152
   indicatorDialog.itemIndex = itemIndex
1143 1153
   indicatorDialog.form = { ...item }
1154
+  if (!indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList) {
1155
+    indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList = []
1156
+  }
1144 1157
 }
1145 1158
 
1146 1159
 // 删除指标
@@ -1160,7 +1173,7 @@ const onIndicatorNameChange = (value) => {
1160 1173
   console.log(value, indicatorDialog.indicatorOptions, "indicatorDialog.indicatorOptions")
1161 1174
   const selected = indicatorDialog.indicatorOptions.find(item => item.id === value)
1162 1175
   if (selected) {
1163
-    indicatorDialog.form = { ...selected, occurCount: 1 }
1176
+    indicatorDialog.form = { ...selected, occurCount: 1, personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList: [] }
1164 1177
     updateTotal()
1165 1178
   }
1166 1179
 }
@@ -1168,6 +1181,23 @@ const onIndicatorNameChange = (value) => {
1168 1181
 // 更新总分
1169 1182
 const updateTotal = () => {
1170 1183
   indicatorDialog.form.scoreResult = indicatorDialog.form.score * indicatorDialog.form.occurCount
1184
+  const list = indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList
1185
+  if (!list) {
1186
+    indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList = []
1187
+    indicatorDialog.form.amountResult = 0
1188
+    return
1189
+  }
1190
+  const targetCount = indicatorDialog.form.occurCount
1191
+  if (list.length < targetCount) {
1192
+    for (let i = list.length; i < targetCount; i++) {
1193
+      list.push({
1194
+        qcDeptType: '',
1195
+        rewardPunishmentDetail: '',
1196
+        amount: 0
1197
+      })
1198
+    }
1199
+  }
1200
+  indicatorDialog.form.amountResult = list.reduce((sum, item) => sum + (Number(item.amount) || 0), 0)
1171 1201
 }
1172 1202
 
1173 1203
 // 保存指标
@@ -1177,6 +1207,12 @@ const saveIndicator = () => {
1177 1207
     return
1178 1208
   }
1179 1209
 
1210
+  const list = indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList || []
1211
+  if (list.length !== indicatorDialog.form.occurCount) {
1212
+    ElMessage.error(`发生次数为 ${indicatorDialog.form.occurCount},但明细数量为 ${list.length},请删除多余的明细`)
1213
+    return
1214
+  }
1215
+
1180 1216
   if (indicatorDialog.mode === 'add') {
1181 1217
     addIndicatorToGroup({ ...indicatorDialog.form })
1182 1218
     ElMessage.success('添加成功')
@@ -1189,6 +1225,12 @@ const saveIndicator = () => {
1189 1225
   indicatorDialog.visible = false
1190 1226
 }
1191 1227
 
1228
+// 删除奖励/惩罚明细
1229
+const removeRewardPunishmentDetail = (index) => {
1230
+  indicatorDialog.form.personnelMonthlyAssessmentIndicatorRewardPunishmentDetailList.splice(index, 1)
1231
+  updateTotal()
1232
+}
1233
+
1192 1234
 // 监听Tab切换
1193 1235
 const handleTabChange = () => {
1194 1236
   queryParams.pageNum = 1
@@ -1366,7 +1408,6 @@ onMounted(() => {
1366 1408
 }
1367 1409
 
1368 1410
 .indicator-form :deep(.el-form-item__label) {
1369
-  font-size: 20px;
1370 1411
   font-weight: 500;
1371 1412
   color: #303133;
1372 1413
 }