Переглянути джерело

📦 对接各级审核意见修改功能

快乐的梦鱼 4 тижнів тому
батько
коміт
0205224c07

+ 1 - 1
src/api/collect/AssessmentContent.ts

@@ -721,7 +721,7 @@ export interface SelfAssessmentReviewOnlyPayload {
   /** 自查表 ID */
   checkId: number;
   /** 审核角色组 ID */
-  groupId: string;
+  groupId: number;
   /** 退回状态:0=无,1=自评阶段退回,2=项目保护单位退回,3=县(区)文旅部门退回,4=设区市文旅部门、省非遗中心退回,5=省文化和旅游厅退回 */
   rejectType: number;
   /** 审核退回意见 */

+ 1 - 1
src/assets/scss/fix.scss

@@ -78,7 +78,7 @@
   max-height: 60px;
   overflow: hidden;
   overflow-y: scroll!important;
-  font-size: 12px;
+  font-size: 1rem;
 }
 
 @media screen and (max-width: 768px) {

+ 13 - 0
src/pages/collect/assessment/composeables/GroupData.ts

@@ -34,24 +34,28 @@ export const GROUP_TO_REVIEW_PROGRESS = {
   [GROUP_PROTECT_UNIT]: {
     target: 2,
     rejectTarget: 2,
+    rejectType: 2,
     minSource: 1,
     canReject: true,
   }, // 项目保护单位
   [GROUP_DISTRICT]: {
     target: 3,
     rejectTarget: 3,
+    rejectType: 3,
     minSource: 2,
     canReject: true,
   }, // 县(区)文旅部门
   [GROUP_DISTRICT_CENTER]: {
     target: 4,
     rejectTarget: 4,
+    rejectType: 4,
     minSource: 3,
     canReject: true,
   },// 设区市文旅部门、省非遗中心
   [GROUP_DISTRICT_ST]: {
     target: 0,
     rejectTarget: 0,
+    rejectType: 4,
     minSource: 3,
     noProgressChange: true,
     canReject: true,
@@ -60,6 +64,7 @@ export const GROUP_TO_REVIEW_PROGRESS = {
   [GROUP_DISTRICT_ND]: {
     target: 0,
     rejectTarget: 0,
+    rejectType: 4,
     minSource: 3,
     noProgressChange: true,
     canReject: true,
@@ -68,6 +73,7 @@ export const GROUP_TO_REVIEW_PROGRESS = {
   [GROUP_DISTRICT_RD]: {
     target: 0,
     rejectTarget: 4,
+    rejectType: 4,
     minSource: 3,
     noProgressChange: true,
     canReject: true,
@@ -76,6 +82,7 @@ export const GROUP_TO_REVIEW_PROGRESS = {
   [GROUP_DISTRICT_TH]: {
     target: 4,
     rejectTarget: 4,
+    rejectType: 4,
     minSource: 3,
     canReject: true,
     displayGroup: [GROUP_DISTRICT_TH, GROUP_DISTRICT_FI],
@@ -83,6 +90,7 @@ export const GROUP_TO_REVIEW_PROGRESS = {
   [GROUP_DISTRICT_FI]: {
     target: 0,
     rejectTarget: 0,
+    rejectType: 4,
     minSource: 3,
     noProgressChange: true,
     canReject: true,
@@ -91,6 +99,7 @@ export const GROUP_TO_REVIEW_PROGRESS = {
   [GROUP_PROVINCE]: {
     target: 5,
     rejectTarget: 5,
+    rejectType: 5,
     minSource: 4,
     canReject: true,
   },// 省文化和旅游厅
@@ -108,6 +117,10 @@ export const GROUP_TO_REVIEW_PROGRESS = {
    */
   rejectTarget: number,
   /**
+   * 当前级别回退类型
+   */
+  rejectType: number,
+  /**
    * 是否不修改进度(子角色审核,等待终审)
    */
   noProgressChange?: boolean,

+ 15 - 0
src/pages/collect/assessment/composeables/Review.ts

@@ -21,6 +21,19 @@ export function useReview(sourceProgress?: ComputedRef<number>) {
     return currentUserGroup.value?.id === GROUP_PROVINCE;
   });
   /**
+   * 是否是区级审核级别
+   */
+  const isDistrict = computed(() => {
+    return (
+      currentUserGroup.value?.id === GROUP_DISTRICT_FI
+      || currentUserGroup.value?.id === GROUP_DISTRICT_FI
+      || currentUserGroup.value?.id === GROUP_DISTRICT_ND
+      || currentUserGroup.value?.id === GROUP_DISTRICT_RD
+      || currentUserGroup.value?.id === GROUP_DISTRICT_TH
+      || currentUserGroup.value?.id === GROUP_DISTRICT_FI
+    );
+  });
+  /**
    * 是否是项目保护单位
    */
   const isProtectUnit = computed(() => {
@@ -108,12 +121,14 @@ export function useReview(sourceProgress?: ComputedRef<number>) {
 
   return {
     reviewProgressInfo,
+    currentUserGroup,
     canReview,
     canReviewButPrevNotCompleted,
     isCurrentLevelReviewed,
     canSubmitReview,
     reviewLevelLabel,
     progressHint,
+    isDistrict,
     isEndLevel,
     isProtectUnit,
     isNoProgressChange,

+ 113 - 0
src/pages/collect/assessment/evaluation-form.vue

@@ -36,6 +36,10 @@
               :current-form-check-items="(currentFormCheckItems as SelfAssessmentCheckItemAnswer[])"
               :readonly="false"
             />
+            <template v-if="isReviewer">
+              <a-divider />
+              <a-button type="primary" block :loading="submitLoading" @click="reviewModalVisible = true">编辑审核意见</a-button>
+            </template>
             <a-divider />
             <a-space direction="vertical" class="w-full" size="middle">
               <a-button type="primary" block :loading="submitLoading" @click="saveForm">保存评估表</a-button>
@@ -57,6 +61,42 @@
     >
       <iframe :src="previewUrl" class="w-full h-full" style="min-height: 60vh"></iframe>
     </a-modal>
+    <a-modal
+      title="编辑审核意见"
+      v-model:visible="reviewModalVisible"
+      :confirm-loading="reviewSubmitting"
+      ok-text="提交审核"
+      cancel-text="取消"
+      @ok="handleReviewSubmit"
+    >
+      <a-form :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
+        <a-form-item label="审核角色" required>
+          <a-select v-model:value="reviewForm.groupId" placeholder="请选择审核角色">
+            <a-select-option v-for="opt in groupOptions" :key="opt.value" :value="Number(opt.value)">{{ opt.label }}</a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item label="审核操作" required>
+          <a-radio-group v-model:value="reviewForm.rejectType">
+            <a-radio :value="0">通过</a-radio>
+            <a-radio :value="rejectTypeForGroup">退回</a-radio>
+          </a-radio-group>
+        </a-form-item>
+        <a-form-item v-if="reviewForm.rejectType === 0" label="评估级别">
+          <a-select v-model:value="reviewForm.opinion" placeholder="请选择评估级别">
+            <a-select-option v-for="opt in opinionOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item v-if="reviewForm.rejectType === 0" label="评分">
+          <a-input-number v-model:value="reviewForm.points" :min="0" :max="100" class="w-full" placeholder="请输入评分" />
+        </a-form-item>
+        <a-form-item v-if="reviewForm.rejectType > 0" label="退回意见">
+          <a-textarea v-model:value="reviewForm.rejectReason" :rows="3" :maxlength="500" show-count placeholder="请输入退回意见" />
+        </a-form-item>
+        <a-form-item label="发送短信">
+          <a-switch v-model:checked="reviewSendMsg" />
+        </a-form-item>
+      </a-form>
+    </a-modal>
   </div>
 </template>
 
@@ -72,12 +112,15 @@ import AssessmentContentApi, {
   SelfAssessmentDetail,
   CheckItemInfo,
   SelfAssessmentCheckItemAnswer,
+  type SelfAssessmentReviewOnlyPayload,
 } from '@/api/collect/AssessmentContent';
 import SelfAssessmentFormDisplay from './components/SelfAssessmentFormDisplay.vue';
 import { useSimpleDataLoader } from '@/composeables/useSimpleDataLoader';
 import { injectAppConfiguration } from '@/api/system/useAppConfiguration.ts';
 import { getFormErrorFieldsMessage } from '@/common/Form.ts';
 import { LEVEL_NATIONAL, LEVEL_PROVINCE, LEVEL_DISTRICT } from '@/api/collect/AssessmentConsts.ts';
+import { useReview } from './composeables/Review.ts';
+import { GROUP_LABELS, GROUP_TO_REVIEW_PROGRESS } from './composeables/GroupData.ts';
 
 
 function formatErr(e: unknown): string {
@@ -100,6 +143,10 @@ const currentForm = ref<SelfAssessmentDetail | null>(null);
 const currentFormCheckItems = ref([] as SelfAssessmentCheckItemAnswer[]);
 const checkItemList = ref([] as CheckItemInfo[]);
 
+const currentProgress = computed(() => currentForm.value?.progress ?? 0);
+const { currentUserGroup, isDistrict, isEndLevel, isProtectUnit } = useReview(currentProgress);
+const isReviewer = computed(() => isDistrict.value || isEndLevel.value || isProtectUnit.value);
+
 const blockRef = ref<InstanceType<typeof SelfAssessmentFormDisplay> | null>(null);
 const submitLoading = ref(false);
 
@@ -305,6 +352,72 @@ function reviewerView() {
   });
 }
 
+const reviewModalVisible = ref(false);
+const reviewSubmitting = ref(false);
+const reviewSendMsg = ref(false);
+const reviewForm = ref({
+  groupId: Number(currentUserGroup.value?.id ?? 0),
+  rejectType: 0,
+  opinion: undefined as number | undefined,
+  points: undefined as number | undefined,
+  rejectReason: '',
+});
+
+const groupOptions = computed(() => {
+  return Object.entries(GROUP_LABELS)
+    .filter(([key]) => Number(key) > 0)
+    .map(([key, label]) => ({ value: key, label }));
+});
+
+const opinionOptions = [
+  { label: '优秀', value: 1 },
+  { label: '合格', value: 2 },
+  { label: '不合格', value: 3 },
+  { label: '丧失传承能力', value: 4 },
+  { label: '取消资格', value: 5 },
+];
+
+const rejectTypeForGroup = computed(() => {
+  const gid = Number(reviewForm.value.groupId);
+  return GROUP_TO_REVIEW_PROGRESS[gid]?.rejectTarget || 0;
+});
+
+async function handleReviewSubmit() {
+  const cf = currentForm.value;
+  if (!cf?.id) {
+    message.warning('请先保存评估表');
+    return;
+  }
+  if (!reviewForm.value.groupId) {
+    message.warning('请选择审核角色');
+    return;
+  }
+  reviewSubmitting.value = true;
+  try {
+    const payload: SelfAssessmentReviewOnlyPayload = {
+      checkId: cf.id,
+      groupId: reviewForm.value.groupId,
+      rejectType: reviewForm.value.rejectType,
+      rejectReason: reviewForm.value.rejectType > 0 ? reviewForm.value.rejectReason : undefined,
+      opinion: reviewForm.value.rejectType === 0 ? reviewForm.value.opinion : undefined,
+      points: reviewForm.value.rejectType === 0 ? reviewForm.value.points : undefined,
+      sendMsg: reviewSendMsg.value ? 1 : 0,
+    };
+    await AssessmentContentApi.reviewOnly(payload);
+    message.success('审核提交成功');
+    reviewModalVisible.value = false;
+    reviewForm.value = { groupId: currentUserGroup.value?.id ?? 0, rejectType: 0, opinion: undefined, points: undefined, rejectReason: '' };
+    reviewSendMsg.value = false;
+    await loader.load();
+  } catch (error) {
+    Modal.error({
+      title: '审核提交失败',
+      content: formatErr(error),
+    });
+  }
+  reviewSubmitting.value = false;
+}
+
 const loader = useSimpleDataLoader(async () => {
   if (queryId.value > 0) {
     const detail = await AssessmentContentApi.getSelfAssessmentDetail(queryId.value, queryUserId.value || undefined);