| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- <template>
- <div class="about main-background main-background-type0">
- <div class="nav-placeholder" />
- <section class="main-section large">
- <div class="content">
- <div class="title left-right">
- <a-button :icon="h(ArrowLeftOutlined)" @click="router.back()">返回</a-button>
- <h2>自查评估表审核</h2>
- <div class="w-20" />
- </div>
- <a-spin :spinning="loader.loading.value">
- <a-result
- v-if="!currentForm"
- status="warning"
- title="无法加载评估表"
- sub-title="请从管理员列表进入,并确认自查表 ID 与传承人用户 ID 正确。"
- />
- <div v-else>
- <a-alert
- type="info"
- show-icon
- class="mb-4"
- :message="progressHint"
- />
- <SelfAssessmentFormDisplay
- :current-form="(currentForm as SelfAssessmentDetail)"
- :check-item-list="(checkItemList as CheckItemInfo[])"
- :current-form-check-items="(currentFormCheckItems as SelfAssessmentCheckItemAnswer[])"
- :readonly="true"
- />
- <a-divider />
- <a-card title="审核提交" size="small">
- <a-alert
- v-if="!canSubmitReview"
- type="warning"
- show-icon
- class="mb-4"
- message="当前账号用户组无权在此环节审核"
- :description="`仅项目保护单位(9)、县(区)文旅部门(5)、设区市文旅部门/省非遗中心(10)、省文化和旅游厅(11) 可提交。`"
- />
- <a-form layout="vertical" class="max-w-xl">
- <a-form-item :label="`审核环节:${reviewLevelLabel}`">
- <a-select
- v-model:value="reviewOpinion"
- allow-clear
- placeholder="请选择审核意见"
- :options="opinionSelectOptions"
- />
- </a-form-item>
- <a-form-item label="评分">
- <a-input-number
- v-model:value="reviewPoints"
- :min="0"
- :max="100"
- class="w-full"
- placeholder="可选"
- />
- </a-form-item>
- <a-form-item label="提交后进度">
- <a-input :value="progressSubmitLabel" readonly />
- </a-form-item>
- <a-form-item>
- <a-space>
- <a-button
- type="primary"
- :loading="submitLoading"
- :disabled="!canSubmitReview"
- @click="submitReview"
- >
- 提交审核
- </a-button>
- <a-button
- danger
- :loading="rejectLoading"
- :disabled="!canSubmitReview"
- @click="submitReject"
- >
- 回退
- </a-button>
- </a-space>
- </a-form-item>
- </a-form>
- </a-card>
- </div>
- </a-spin>
- </div>
- </section>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, h, onMounted, ref, watch } from 'vue';
- import { useRoute, useRouter } from 'vue-router';
- import { Input, message, Modal } from 'ant-design-vue';
- import { RequestApiError } from '@imengyu/imengyu-utils';
- import { ArrowLeftOutlined } from '@ant-design/icons-vue';
- import AssessmentContentApi, {
- type CheckItemInfo,
- type SelfAssessmentCheckItemAnswer,
- SelfAssessmentDetail,
- } from '@/api/collect/AssessmentContent';
- import SelfAssessmentFormDisplay from './components/SelfAssessmentFormDisplay.vue';
- import { useSimpleDataLoader } from '@/composeables/useSimpleDataLoader';
- import { useAuthStore } from '@/stores/auth';
- function formatErr(e: unknown): string {
- if (e instanceof RequestApiError)
- return e.errorMessage;
- if (e instanceof Error)
- return e.message;
- return String(e);
- }
- const router = useRouter();
- const route = useRoute();
- const authStore = useAuthStore();
- const currentUserGroups = computed(() => authStore.userInfo?.adminGroup || []);
- const queryFormId = computed(() => Number(route.query.id) || 0);
- const queryUserId = computed(() => Number(route.query.userId) || 0);
- /** 列表当前进度(与管理员列表一致) */
- const listProgress = computed(() => {
- const p = Number(route.query.progress);
- return Number.isFinite(p) ? p : NaN;
- });
- const currentForm = ref<SelfAssessmentDetail | null>(null);
- const currentFormCheckItems = ref([] as SelfAssessmentCheckItemAnswer[]);
- const checkItemList = ref([] as CheckItemInfo[]);
- const submitLoading = ref(false);
- const rejectLoading = ref(false);
- const reviewOpinion = ref<number | null>(null);
- const reviewPoints = ref<number | null>(null);
- /** 用户组 → 本环节提交后的 progress */
- const GROUP_TO_REVIEW_PROGRESS: Record<number, number> = {
- 9: 2, // 项目保护单位
- 5: 3, // 县(区)文旅部门
- 10: 4, // 设区市文旅部门、省非遗中心
- 11: 5, // 省文化和旅游厅
- };
- const PROGRESS_SUBMIT_LABELS: Record<number, string> = {
- 2: '2 — 项目保护单位审核完成',
- 3: '3 — 县(区)文旅部门审核完成',
- 4: '4 — 设区市文旅部门、省非遗中心审核完成',
- 5: '5 — 省文化和旅游厅审核完成',
- };
- const opinionSelectOptions = [
- { label: '优秀', value: 1 },
- { label: '合格', value: 2 },
- { label: '不合格', value: 3 },
- { label: '丧失传承能力', value: 4 },
- { label: '取消资格', value: 5 },
- ];
- const reviewProgress = computed(
- () => {
- const currentUserGroup = currentUserGroups.value.find((group) => GROUP_TO_REVIEW_PROGRESS[group.id]);
- return GROUP_TO_REVIEW_PROGRESS[currentUserGroup?.id ?? 0] ?? 0;
- },
- );
- const canSubmitReview = computed(
- () => reviewProgress.value >= 2 && reviewProgress.value <= 5,
- );
- const progressSubmitLabel = computed(
- () => PROGRESS_SUBMIT_LABELS[reviewProgress.value] ?? '—',
- );
- const reviewLevelLabel = computed(() => {
- switch (reviewProgress.value) {
- case 2:
- return '项目保护单位';
- case 3:
- return '县(区)文旅部门';
- case 4:
- return '设区市文旅部门、省非遗中心';
- case 5:
- return '省文化和旅游厅';
- default:
- return '';
- }
- });
- const progressHint = computed(() => {
- const lp = listProgress.value;
- const lpText = Number.isFinite(lp) ? `列表进度:${lp}` : '未传列表进度参数';
- const roleText = canSubmitReview.value
- ? `当前账号审核环节:${reviewLevelLabel.value}(提交后 progress=${reviewProgress.value})`
- : `当前用户组 ${currentUserGroups.value.map((group) => group.name).join(',')} 无对应审核环节`;
- return `${lpText}。${roleText}。`;
- });
- const currentYear = new Date().getFullYear();
- function levelTitleFromForm(f: SelfAssessmentDetail) {
- if (f.level === 23) return '国家级';
- if (f.level === 24) return '省级';
- if (f.level === 25) return '市级';
- return '国家级';
- }
- function loadEditorContent(f: SelfAssessmentDetail) {
- if (typeof f.content !== 'object' || f.content === null)
- f.content = {};
- f.content.title = `传承人填写${currentYear}年1月1日至${currentYear}年12月31日${levelTitleFromForm(f)}非遗传承人义务履行和传承补助经费使用情况等,不超过1000字,如未履行职责请进行说明。参考提纲如下:`;
- for (let i = 0; i < 8; i++) {
- if (typeof f.content[`item${i}`] !== 'string')
- f.content[`item${i}`] = '';
- }
- }
- async function loadCheckItems(f: SelfAssessmentDetail) {
- const { top } = await AssessmentContentApi.getCheckItems(Number(f.level));
- checkItemList.value = top as CheckItemInfo[];
- currentFormCheckItems.value = [...f.checkItems] as SelfAssessmentCheckItemAnswer[];
- }
- function applyPrefillFromDetail(f: SelfAssessmentDetail) {
- const t = reviewProgress.value;
- if (!canSubmitReview.value)
- return;
- if (t === 2) {
- reviewOpinion.value = f.ichUnit ?? null;
- reviewPoints.value = f.unitPoints || null;
- } else if (t === 3) {
- reviewOpinion.value = f.county ?? null;
- reviewPoints.value = f.countyPoints || null;
- } else if (t === 4) {
- reviewOpinion.value = f.district ?? null;
- reviewPoints.value = f.districtPoints || null;
- } else if (t === 5) {
- reviewOpinion.value = f.province ?? null;
- reviewPoints.value = f.provincePoints || null;
- }
- }
- const loader = useSimpleDataLoader(async () => {
- const id = queryFormId.value;
- const uid = queryUserId.value;
- if (!id || !uid) {
- currentForm.value = null;
- return null;
- }
- const detail = await AssessmentContentApi.getSelfAssessmentDetail(id, uid);
- currentForm.value = detail;
- loadEditorContent(detail);
- await loadCheckItems(detail);
- applyPrefillFromDetail(detail);
- return detail;
- }, { immediate: false });
- watch(reviewProgress, () => {
- const f = currentForm.value;
- if (f)
- applyPrefillFromDetail(f as SelfAssessmentDetail);
- });
- watch(
- () => [queryFormId.value, queryUserId.value, listProgress.value] as const,
- () => {
- loader.load();
- },
- );
- onMounted(() => {
- loader.load();
- });
- /** 回退后 progress:退回至上一环节 */
- const rejectTargetProgress = computed(() => Math.max(1, reviewProgress.value - 1));
- function promptRejectReason() {
- const draft = ref('');
- return new Promise<string | null>((resolve) => {
- Modal.confirm({
- title: '回退自查评估表',
- okText: '确认回退',
- cancelText: '取消',
- okType: 'danger',
- width: 800,
- content: () => h(Input.TextArea, {
- value: draft.value,
- rows: 4,
- maxlength: 500,
- showCount: true,
- placeholder: '请输入回退原因(必填)',
- 'onUpdate:value': (v: string) => {
- draft.value = v ?? '';
- },
- }),
- onOk: () => {
- const reason = draft.value.trim();
- if (!reason) {
- message.warning('请输入回退原因');
- return Promise.reject();
- }
- resolve(reason);
- },
- onCancel: () => {
- resolve(null);
- },
- });
- });
- }
- async function submitReject() {
- const f = currentForm.value;
- if (!f?.id) {
- message.warning('缺少自查表 ID');
- return;
- }
- if (!canSubmitReview.value) {
- message.warning('当前账号用户组无权回退');
- return;
- }
- const rejectReason = await promptRejectReason();
- if (rejectReason === null)
- return;
- const t = reviewProgress.value;
- try {
- rejectLoading.value = true;
- await AssessmentContentApi.reviewSelfAssessment({
- id: f.id,
- progress: rejectTargetProgress.value,
- rejectType: t,
- rejectReason,
- });
- message.success('已回退');
- router.back();
- } catch (e) {
- Modal.error({ title: '回退失败', content: formatErr(e) });
- } finally {
- rejectLoading.value = false;
- }
- }
- async function submitReview() {
- const f = currentForm.value;
- if (!f?.id) {
- message.warning('缺少自查表 ID');
- return;
- }
- if (!canSubmitReview.value) {
- message.warning('当前账号用户组无权提交审核');
- return;
- }
- if (reviewOpinion.value == null) {
- message.warning('请选择审核意见');
- return;
- }
- const t = reviewProgress.value;
- const base = { id: f.id, progress: t };
- const points = reviewPoints.value != null && reviewPoints.value >= 0 ? reviewPoints.value : undefined;
- const op = reviewOpinion.value;
- try {
- submitLoading.value = true;
- if (t === 2)
- await AssessmentContentApi.reviewSelfAssessment({ ...base, ichUnit: op, unitPoints: points });
- else if (t === 3)
- await AssessmentContentApi.reviewSelfAssessment({ ...base, county: op, countyPoints: points });
- else if (t === 4)
- await AssessmentContentApi.reviewSelfAssessment({ ...base, district: op, districtPoints: points });
- else
- await AssessmentContentApi.reviewSelfAssessment({ ...base, province: op, provincePoints: points });
- message.success('审核提交成功');
- router.back();
- } catch (e) {
- Modal.error({ title: '审核提交失败', content: formatErr(e) });
- } finally {
- submitLoading.value = false;
- }
- }
- </script>
|