浏览代码

📦 按要求增加自查评估表的审核页编辑功能

快乐的梦鱼 2 天之前
父节点
当前提交
1512fa7ba1
共有 1 个文件被更改,包括 252 次插入170 次删除
  1. 252 170
      src/pages/collect/assessment/evaluation-form-review.vue

+ 252 - 170
src/pages/collect/assessment/evaluation-form-review.vue

@@ -4,9 +4,25 @@
     <section class="main-section large">
       <div class="content">
         <div class="title left-right">
-          <a-button :icon="h(ArrowLeftOutlined)" @click="router.back()">返回</a-button>
+          <div class="min-w-30">
+            <a-button :icon="h(ArrowLeftOutlined)" @click="router.back()">返回</a-button>
+          </div>
           <h2>自查评估表审核</h2>
-          <div class="w-20" />
+          <div v-if="canEdit" class="min-w-30 flex flex-row items-center">
+            <a-button :type="isEditMode ? 'primary' : 'text'" @click="isEditMode = true">
+              <template #icon>
+                <EditOutlined />
+              </template>
+              编辑模式
+            </a-button>
+            <a-button :type="isEditMode ? 'text' : 'primary'" @click="isEditMode = false">
+              <template #icon>
+                <CheckOutlined />
+              </template>
+              审核模式
+            </a-button>
+          </div>
+          <div v-else class="w-30" />
         </div>
         <a-spin :spinning="loader.loading.value">
           <div 
@@ -26,186 +42,195 @@
               :message="progressHint"
             />
             <SelfAssessmentFormDisplay
+              ref="blockRef"
               :current-form="(currentForm as SelfAssessmentDetail)"
               :check-item-list="(checkItemList as CheckItemInfo[])"
               :current-form-check-items="(currentFormCheckItems as SelfAssessmentCheckItemAnswer[])"
-              :readonly="true"
+              :readonly="!isEditMode"
               :isReviewer="true"
             />
             <a-divider />
-            <a-card title="审核提交" size="small" class="review-submit-card" :class="{ collapsed: reviewCardCollapsed }">
-              <template #extra>
-                <a-button
-                  size="small"
-                  type="text"
-                  :icon="h(FileTextOutlined)"
-                  @click="goToAssessmentProtocol"
-                >
-                  传承协议审核
-                </a-button>
-                <a-button
-                  size="small"
-                  type="text"
-                  :icon="h(reviewCardCollapsed ? UpOutlined : DownOutlined)"
-                  @click="reviewCardCollapsed = !reviewCardCollapsed"
-                >
-                  {{ reviewCardCollapsed ? '展开' : '收起' }}
-                </a-button>
-              </template>
-              <a-alert
-                v-if="!canSubmitReview"
-                type="warning"
-                show-icon
-                class="mb-4"
-                message="当前账号用户组无权在此环节审核"
-              />
-              <a-alert
-                v-else-if="currentForm.rejectType > 0"
-                type="warning"
-                show-icon
-                class="mb-4"
-                :message="`${getRejectTypeText(currentForm.rejectType)}已退回: ${currentForm.rejectReason}`"
-              />
-              <a-form v-else layout="vertical" size="middle">
-                <div class="flex flex-col md:flex-row lg:flex-row w-full gap-3 py-3">
-                  <!-- 单用户组审核 -->
-                  <template v-if="displayFieldDefs.length === 0">
-                    <div class="flex flex-col flex-1">     
-                      <a-form-item required label="不通过回退:回退原因">
-                        <a-textarea
-                          v-model:value="rejectReason"
-                          allow-clear
-                          placeholder="请输入回退原因"
-                          :rows="5"
-                          :maxlength="500"
-                          show-count
-                        />
-                      </a-form-item>
-                    </div>
-                    <div v-if="displayFieldDefs.length === 0" class="flex flex-col flex-1">
-                      <a-form-item required :label="isNoProgressChange ? `提交意见:${reviewLevelLabel}` : `审核通过:${reviewLevelLabel}`">
-                        <a-select
-                          :value="reviewFields[currentUserGroupId]?.opinion"
-                          allow-clear
-                          placeholder="请选择审核意见"
-                          :options="opinionSelectOptions"
-                          :disabled="alreadySubmitted"
-                          @update:value="(v: number | null) => reviewFields[currentUserGroupId].opinion = v"
-                        />
-                      </a-form-item>
-                      <a-form-item label="评分">
-                        <a-input-number
-                          :value="reviewFields[currentUserGroupId]?.points"
-                          :min="0"
-                          :max="100"
-                          class="w-full"
-                          placeholder="请填写分数"
-                          :disabled="alreadySubmitted"
-                          @update:value="(v: number | null) => reviewFields[currentUserGroupId].points = v"
-                        />
-                      </a-form-item>
-                    </div>
-                  </template>
-                  <!-- 多用户组审核 -->
-                  <template v-else>
-                    <div v-if="displayFieldDefs.length <= 1 && (!isNoProgressChange || reviewProgressInfo?.canReject)" class="flex flex-col flex-1">     
-                      <a-form-item required label="不通过回退:回退原因">
-                        <a-textarea
-                          :value="reviewFields[currentUserGroupId].reason"
-                          @update:value="(v: string | null) => reviewFields[currentUserGroupId].reason = v"
-                          allow-clear
-                          placeholder="请输入回退原因"
-                          :rows="5"
-                          :maxlength="500"
-                          show-count
-                        />
-                      </a-form-item>
-                    </div>
-                    <div
-                      v-for="{ gid, def } in displayFieldDefs"
-                      :key="gid"
-                      class="flex flex-col flex-1"
-                    >
-                      <div class="flex flex-row gap-3">
-                        <a-form-item :required="gid === currentUserGroupId" :label="`${def.label} — 审核意见`">
+            <div class="review-submit-card">
+              <a-card title="审核提交" size="small" :class="{ collapsed: reviewCardCollapsed }">
+                <template #extra>
+                  <a-button
+                    size="small"
+                    type="text"
+                    :icon="h(FileTextOutlined)"
+                    @click="goToAssessmentProtocol"
+                  >
+                    传承协议审核
+                  </a-button>
+                  <a-button
+                    size="small"
+                    type="text"
+                    :icon="h(reviewCardCollapsed ? UpOutlined : DownOutlined)"
+                    @click="reviewCardCollapsed = !reviewCardCollapsed"
+                  >
+                    {{ reviewCardCollapsed ? '展开' : '收起' }}
+                  </a-button>
+                </template>
+                <a-alert
+                  v-if="!canSubmitReview"
+                  type="warning"
+                  show-icon
+                  class="mb-4"
+                  message="当前账号用户组无权在此环节审核"
+                />
+                <a-alert
+                  v-else-if="currentForm.rejectType > 0"
+                  type="warning"
+                  show-icon
+                  class="mb-4"
+                  :message="`${getRejectTypeText(currentForm.rejectType)}已退回: ${currentForm.rejectReason}`"
+                />
+                <a-form v-else layout="vertical" size="middle">
+                  <div class="flex flex-col md:flex-row lg:flex-row w-full gap-3 py-3">
+                    <!-- 单用户组审核 -->
+                    <template v-if="displayFieldDefs.length === 0">
+                      <div class="flex flex-col flex-1">     
+                        <a-form-item required label="不通过回退:回退原因">
+                          <a-textarea
+                            v-model:value="rejectReason"
+                            allow-clear
+                            placeholder="请输入回退原因"
+                            :rows="5"
+                            :maxlength="500"
+                            show-count
+                          />
+                        </a-form-item>
+                      </div>
+                      <div v-if="displayFieldDefs.length === 0" class="flex flex-col flex-1">
+                        <a-form-item required :label="isNoProgressChange ? `提交意见:${reviewLevelLabel}` : `审核通过:${reviewLevelLabel}`">
                           <a-select
-                            :value="reviewFields[gid]?.opinion"
+                            :value="reviewFields[currentUserGroupId]?.opinion"
                             allow-clear
                             placeholder="请选择审核意见"
                             :options="opinionSelectOptions"
-                            @update:value="(v: number | null) => reviewFields[gid].opinion = v"
+                            :disabled="alreadySubmitted"
+                            @update:value="(v: number | null) => reviewFields[currentUserGroupId].opinion = v"
                           />
                         </a-form-item>
-                        <a-form-item :label="`${def.label} — 评分`">
+                        <a-form-item label="评分">
                           <a-input-number
-                            :value="reviewFields[gid]?.points"
+                            :value="reviewFields[currentUserGroupId]?.points"
                             :min="0"
                             :max="100"
                             class="w-full"
                             placeholder="请填写分数"
-                            @update:value="(v: number | null) => reviewFields[gid].points = v"
+                            :disabled="alreadySubmitted"
+                            @update:value="(v: number | null) => reviewFields[currentUserGroupId].points = v"
                           />
                         </a-form-item>
                       </div>
-                      <a-form-item :label="`${def.label} — 修改意见`">
-                        <a-textarea
-                          :value="reviewFields[gid]?.reason"
-                          @update:value="(v: string | null) => reviewFields[gid].reason = v"
-                          allow-clear
-                          placeholder="请输入修改意见/回退原因"
-                          :rows="5"
-                          :maxlength="500"
-                          show-count
-                        />
-                      </a-form-item>
-                      <a-alert
-                        v-if="alreadySubmitted && gid === currentUserGroupId"
-                        type="success"
-                        show-icon
-                        class="mb-4"
-                        message="当前角色已提交意见"
-                      />
-                    </div>
-                  </template>
-                </div>
-                <div class="flex row w-full gap-3">
-                  <template v-if="!alreadySubmitted || isMulitRole">
-                    <div v-if="isMulitRole" class="flex flex-col flex-1">
-                      <a-button
-                        block
-                        :loading="submitLoading"
-                        :disabled="!canSubmitReview"
-                        @click="saveReasions"
-                      >
-                        保存意见
-                      </a-button>
-                    </div>
-                    <div v-if="reviewProgressInfo?.canReject" class="flex flex-col flex-1">
-                      <a-button
-                        block
-                        danger
-                        :loading="rejectLoading"
-                        :disabled="!canSubmitReview"
-                        @click="submitReject"
-                      >
-                        不合格回退
-                      </a-button>
-                    </div>
-                    <div class="flex flex-col flex-1">
-                      <a-button
-                        block
-                        type="primary"
-                        :loading="submitLoading"
-                        :disabled="!canSubmitReview"
-                        @click="submitReview"
+                    </template>
+                    <!-- 多用户组审核 -->
+                    <template v-else>
+                      <div v-if="displayFieldDefs.length <= 1 && (!isNoProgressChange || reviewProgressInfo?.canReject)" class="flex flex-col flex-1">     
+                        <a-form-item required label="不通过回退:回退原因">
+                          <a-textarea
+                            :value="reviewFields[currentUserGroupId].reason"
+                            @update:value="(v: string | null) => reviewFields[currentUserGroupId].reason = v"
+                            allow-clear
+                            placeholder="请输入回退原因"
+                            :rows="5"
+                            :maxlength="500"
+                            show-count
+                          />
+                        </a-form-item>
+                      </div>
+                      <div
+                        v-for="{ gid, def } in displayFieldDefs"
+                        :key="gid"
+                        class="flex flex-col flex-1"
                       >
-                        通过审核
-                      </a-button>
-                    </div>
-                  </template>
-                </div>
-              </a-form>
-            </a-card>
+                        <div class="flex flex-row gap-3">
+                          <a-form-item :required="gid === currentUserGroupId" :label="`${def.label} — 审核意见`">
+                            <a-select
+                              :value="reviewFields[gid]?.opinion"
+                              allow-clear
+                              placeholder="请选择审核意见"
+                              :options="opinionSelectOptions"
+                              @update:value="(v: number | null) => reviewFields[gid].opinion = v"
+                            />
+                          </a-form-item>
+                          <a-form-item :label="`${def.label} — 评分`">
+                            <a-input-number
+                              :value="reviewFields[gid]?.points"
+                              :min="0"
+                              :max="100"
+                              class="w-full"
+                              placeholder="请填写分数"
+                              @update:value="(v: number | null) => reviewFields[gid].points = v"
+                            />
+                          </a-form-item>
+                        </div>
+                        <a-form-item :label="`${def.label} — 修改意见`">
+                          <a-textarea
+                            :value="reviewFields[gid]?.reason"
+                            @update:value="(v: string | null) => reviewFields[gid].reason = v"
+                            allow-clear
+                            placeholder="请输入修改意见/回退原因"
+                            :rows="5"
+                            :maxlength="500"
+                            show-count
+                          />
+                        </a-form-item>
+                        <a-alert
+                          v-if="alreadySubmitted && gid === currentUserGroupId"
+                          type="success"
+                          show-icon
+                          class="mb-4"
+                          message="当前角色已提交意见"
+                        />
+                      </div>
+                    </template>
+                  </div>
+                  <div class="flex row w-full gap-3">
+                    <template v-if="!alreadySubmitted || isMulitRole">
+                      <div v-if="isMulitRole" class="flex flex-col flex-1">
+                        <a-button
+                          block
+                          :loading="submitLoading"
+                          :disabled="!canSubmitReview"
+                          @click="saveReasions"
+                        >
+                          保存意见
+                        </a-button>
+                      </div>
+                      <div v-if="reviewProgressInfo?.canReject" class="flex flex-col flex-1">
+                        <a-button
+                          block
+                          danger
+                          :loading="rejectLoading"
+                          :disabled="!canSubmitReview"
+                          @click="submitReject"
+                        >
+                          不合格回退
+                        </a-button>
+                      </div>
+                      <div class="flex flex-col flex-1">
+                        <a-button
+                          block
+                          type="primary"
+                          :loading="submitLoading"
+                          :disabled="!canSubmitReview"
+                          @click="submitReview"
+                        >
+                          通过审核
+                        </a-button>
+                      </div>
+                    </template>
+                  </div>
+                </a-form>
+              </a-card>
+              <a-card v-if="canEdit && isEditMode" title="编辑保存" size="small">
+                <template #extra>
+                  <span class="text-sm mr-2">提示:您现在处于编辑模式,修改完成后请不要忘了点击这里保存>></span>
+                  <a-button type="primary" :loading="submitLoading" @click="saveForm">保存评估表</a-button>
+                </template>
+              </a-card>
+            </div>
           </div>
         </a-spin>
       </div>
@@ -217,8 +242,8 @@
 import { computed, h, onMounted, ref, watch } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import { message, Modal } from 'ant-design-vue';
-import { RequestApiError } from '@imengyu/imengyu-utils';
-import { ArrowLeftOutlined, UpOutlined, DownOutlined, FileTextOutlined } from '@ant-design/icons-vue';
+import { RequestApiError, waitTimeOut } from '@imengyu/imengyu-utils';
+import { ArrowLeftOutlined, UpOutlined, DownOutlined, FileTextOutlined, EditOutlined, CheckOutlined } from '@ant-design/icons-vue';
 import AssessmentContentApi, {
   type CheckItemInfo,
   getRejectTypeText,
@@ -233,6 +258,7 @@ import { GROUP_TO_REVIEW_PROGRESS, GROUP_DISTRICT_ST, GROUP_DISTRICT_ND, GROUP_D
 import { isInMiniProgram } from '@/composeables/MiniProgramIng.ts';
 import { useReview } from './composeables/Review.ts';
 import { LEVEL_NATIONAL, LEVEL_PROVINCE, LEVEL_DISTRICT } from '@/api/collect/AssessmentConsts.ts';
+import { getFormErrorFieldsMessage } from '@/common/Form.ts';
 
 function formatErr(e: unknown): string {
   if (e instanceof RequestApiError)
@@ -266,6 +292,8 @@ const submitLoading = ref(false);
 const rejectLoading = ref(false);
 const rejectReason = ref<string | null>(null);
 
+const isEditMode = ref(false);
+
 interface ReviewFieldState {
   opinion: number | null;
   points: number | null;
@@ -297,7 +325,9 @@ const opinionSelectOptions = [
 ];
 
 const currentProgress = computed(() => currentForm.value?.progress ?? 0);
-const { reviewProgressInfo, canSubmitReview, reviewLevelLabel, progressHint, isNoProgressChange } = useReview(currentProgress);
+const { reviewProgressInfo, canSubmitReview, reviewLevelLabel, progressHint, isProtectUnit, isDistrict, isNoProgressChange } = useReview(currentProgress);
+
+const canEdit = computed(() => isProtectUnit.value || isDistrict.value);
 
 const currentUserGroupId = computed(() => {
   const groups = [...currentUserGroups.value].sort((a, b) => b.id - a.id);
@@ -369,6 +399,7 @@ const loader = useSimpleDataLoader(async () => {
   }
   const detail = await AssessmentContentApi.getSelfAssessmentDetail(id, uid);
   currentForm.value = detail;
+  isEditMode.value = false;
   loadEditorContent(detail);
   await loadCheckItems(detail);
   applyPrefillFromDetail(detail);
@@ -398,6 +429,8 @@ onMounted(() => {
   }, 800);
 });
 
+const blockRef = ref<InstanceType<typeof SelfAssessmentFormDisplay> | null>(null);
+
 async function goToAssessmentProtocol() {
   const list = await AssessmentContentApi.getUserAgreementList({
     year: new Date().getFullYear(),
@@ -420,7 +453,50 @@ async function goToAssessmentProtocol() {
   });
   window.open(path.href, '_blank');
 }
-
+async function saveForm() {
+  const cf = currentForm.value;
+  submitLoading.value = true;
+  if (!cf) {
+    submitLoading.value = false;
+    return;
+  }
+  if (cf.progress > 0) {
+    try {
+      await blockRef.value?.validate();
+    } catch (e: unknown) {
+      message.warning('请填写完整信息: ' + getFormErrorFieldsMessage(e));
+      submitLoading.value = false;
+      return;
+    }
+  }
+  /* if (cf.progress > 0) {
+    const confirmed = await new Promise<boolean>((resolve) => {
+      Modal.confirm({
+        title: '提示',
+        content: '您之前已提交审核,修改将导致审核撤回并需要重新审核,是否继续修改?',
+        okText: '继续修改',
+        cancelText: '取消',
+        onOk: () => resolve(true),
+        onCancel: () => resolve(false),
+      });
+    });
+    if (!confirmed)
+      return;
+  } */
+  cf.checkItems = currentFormCheckItems.value;
+  try {
+    await AssessmentContentApi.saveSelfAssessment(cf as SelfAssessmentDetail/* , 0 */);
+    message.success('保存评估表成功');
+    await waitTimeOut(500);
+    await loader.load();
+  } catch (error) {
+    Modal.error({
+      title: '保存评估表失败',
+      content: formatErr(error),
+    });
+  }
+  submitLoading.value = false;
+}
 async function saveReasions() {
   if (!isMulitRole.value) {
     message.warning('非多角色账号');
@@ -563,14 +639,20 @@ async function submitReview() {
   position: sticky;
   bottom: 0;
   z-index: 10;
-  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
-
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+
+  :deep(.ant-card) {
+    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
+    
+    &.collapsed .ant-card-body {
+      display: none;
+    }
+  }
   :deep(.ant-form-item) {
     margin-bottom: 0!important;
   }
 
-  &.collapsed :deep(.ant-card-body) {
-    display: none;
-  }
 }
 </style>