|
@@ -22,46 +22,36 @@
|
|
|
</a-result>
|
|
</a-result>
|
|
|
<div v-else>
|
|
<div v-else>
|
|
|
<a-alert type="info" message="请仔细阅读传承协议,确保您已理解内容,并签署传承协议。" class="mb-4" show-icon />
|
|
<a-alert type="info" message="请仔细阅读传承协议,确保您已理解内容,并签署传承协议。" class="mb-4" show-icon />
|
|
|
- <a-form
|
|
|
|
|
- v-if="currentAgreement"
|
|
|
|
|
- ref="formRef"
|
|
|
|
|
- :model="currentAgreement"
|
|
|
|
|
- :rules="formRules"
|
|
|
|
|
- layout="vertical"
|
|
|
|
|
- >
|
|
|
|
|
- <a-typography-title class="mt-5!" :level="4">{{ agreementTitle }}</a-typography-title>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <AgreementFormDisplay
|
|
|
|
|
+ ref="agreementFormRef"
|
|
|
|
|
+ :currentAgreement="(currentAgreement as AgreementDetail)"
|
|
|
|
|
+ />
|
|
|
|
|
|
|
|
- <AgreementBodyNational
|
|
|
|
|
- v-if="currentAgreement?.level === 23"
|
|
|
|
|
- :detail="(currentAgreement as AgreementDetail)"
|
|
|
|
|
- :agreement-year="agreementYear"
|
|
|
|
|
- :party-a-stamp-date="partyAStampDate"
|
|
|
|
|
- :party-b-sign-date="partyBSignDate"
|
|
|
|
|
- @update:party-a-stamp-date="partyAStampDate = $event"
|
|
|
|
|
- @update:party-b-sign-date="partyBSignDate = $event"
|
|
|
|
|
- />
|
|
|
|
|
- <AgreementBodyProvincial
|
|
|
|
|
- v-else-if="currentAgreement?.level === 24"
|
|
|
|
|
- :detail="(currentAgreement as AgreementDetail)"
|
|
|
|
|
- :agreement-year="agreementYear"
|
|
|
|
|
- :party-a-stamp-date="partyAStampDate"
|
|
|
|
|
- :party-b-sign-date="partyBSignDate"
|
|
|
|
|
- @update:party-a-stamp-date="partyAStampDate = $event"
|
|
|
|
|
- @update:party-b-sign-date="partyBSignDate = $event"
|
|
|
|
|
- />
|
|
|
|
|
- <AgreementBodyMunicipal
|
|
|
|
|
- v-else-if="currentAgreement?.level === 25"
|
|
|
|
|
- :detail="(currentAgreement as AgreementDetail)"
|
|
|
|
|
- :agreement-year="agreementYear"
|
|
|
|
|
- :party-a-stamp-date="partyAStampDate"
|
|
|
|
|
- :party-b-sign-date="partyBSignDate"
|
|
|
|
|
- @update:party-a-stamp-date="partyAStampDate = $event"
|
|
|
|
|
- @update:party-b-sign-date="partyBSignDate = $event"
|
|
|
|
|
- />
|
|
|
|
|
- </a-form>
|
|
|
|
|
|
|
+ <a-alert
|
|
|
|
|
+ v-if="currentAgreement.rejectType > 0"
|
|
|
|
|
+ type="error"
|
|
|
|
|
+ show-icon
|
|
|
|
|
+ class="mt-4"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #message>
|
|
|
|
|
+ 审核回退:{{ rejectTypeLabel }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template v-if="currentAgreement.rejectReason" #description>
|
|
|
|
|
+ 回退原因:{{ currentAgreement.rejectReason }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </a-alert>
|
|
|
|
|
+ <a-alert
|
|
|
|
|
+ v-else-if="currentAgreement.progress >= 1"
|
|
|
|
|
+ type="success"
|
|
|
|
|
+ show-icon
|
|
|
|
|
+ class="mt-4"
|
|
|
|
|
+ :message="progressLabel"
|
|
|
|
|
+ />
|
|
|
|
|
|
|
|
<a-space direction="vertical" class="w-full mt-4" size="middle">
|
|
<a-space direction="vertical" class="w-full mt-4" size="middle">
|
|
|
<a-button type="primary" block :loading="submitLoading" @click="saveAgreement">保存传承协议</a-button>
|
|
<a-button type="primary" block :loading="submitLoading" @click="saveAgreement">保存传承协议</a-button>
|
|
|
|
|
+ <a-button v-if="!authStore.isAdmin && currentAgreement?.progress === 0" type="primary" block :loading="submitLoading" @click="submitForm">提交审核</a-button>
|
|
|
<a-button block :loading="submitLoading" @click="downloadAgreement">下载协议 PDF</a-button>
|
|
<a-button block :loading="submitLoading" @click="downloadAgreement">下载协议 PDF</a-button>
|
|
|
</a-space>
|
|
</a-space>
|
|
|
</div>
|
|
</div>
|
|
@@ -76,18 +66,13 @@
|
|
|
import { computed, h, onMounted, ref, watch } from 'vue';
|
|
import { computed, h, onMounted, ref, watch } from 'vue';
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
import { message, Modal } from 'ant-design-vue';
|
|
import { message, Modal } from 'ant-design-vue';
|
|
|
-import type { FormInstance } from 'ant-design-vue';
|
|
|
|
|
-import type { Rules } from 'async-validator';
|
|
|
|
|
-import { RequestApiError } from '@imengyu/imengyu-utils';
|
|
|
|
|
|
|
+import { RequestApiError, waitTimeOut } from '@imengyu/imengyu-utils';
|
|
|
import { useAuthStore } from '@/stores/auth';
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
import AssessmentContentApi, { AgreementDetail } from '@/api/collect/AssessmentContent';
|
|
import AssessmentContentApi, { AgreementDetail } from '@/api/collect/AssessmentContent';
|
|
|
-import AgreementBodyNational from './components/AgreementBodyNational.vue';
|
|
|
|
|
-import AgreementBodyProvincial from './components/AgreementBodyProvincial.vue';
|
|
|
|
|
-import AgreementBodyMunicipal from './components/AgreementBodyMunicipal.vue';
|
|
|
|
|
-import type { AgreementYmdParts } from './components/AgreementDateWriteBlock.vue';
|
|
|
|
|
import { useSimpleDataLoader } from '@/composeables/useSimpleDataLoader';
|
|
import { useSimpleDataLoader } from '@/composeables/useSimpleDataLoader';
|
|
|
import { ArrowLeftOutlined } from '@ant-design/icons-vue';
|
|
import { ArrowLeftOutlined } from '@ant-design/icons-vue';
|
|
|
import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
|
|
import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
|
|
|
|
|
+import AgreementFormDisplay from './components/AgreementFormDisplay.vue';
|
|
|
|
|
|
|
|
function formatErr(e: unknown): string {
|
|
function formatErr(e: unknown): string {
|
|
|
if (e instanceof RequestApiError)
|
|
if (e instanceof RequestApiError)
|
|
@@ -105,60 +90,7 @@ const queryId = computed(() => Number(route.query.id) || 0);
|
|
|
const queryUserId = computed(() => Number(route.query.userId) || 0);
|
|
const queryUserId = computed(() => Number(route.query.userId) || 0);
|
|
|
|
|
|
|
|
const currentAgreement = ref<AgreementDetail | null>(null);
|
|
const currentAgreement = ref<AgreementDetail | null>(null);
|
|
|
-const partyAStampDate = ref<AgreementYmdParts>({ year: '', month: '', day: '' });
|
|
|
|
|
-const partyBSignDate = ref<AgreementYmdParts>({ year: '', month: '', day: '' });
|
|
|
|
|
-const formRef = ref<FormInstance | null>(null);
|
|
|
|
|
-
|
|
|
|
|
-const CN_MOBILE_RE = /^1\d{10}$/;
|
|
|
|
|
-const CN_ID_RE = /^(?:\d{15}|\d{17}[\dXx])$/;
|
|
|
|
|
-
|
|
|
|
|
-const formRules = computed<Rules>(() => {
|
|
|
|
|
- const rules: Rules = {
|
|
|
|
|
- partyB: [{ required: true, message: '请填写乙方(传承人)姓名' }],
|
|
|
|
|
- apprentice: [
|
|
|
|
|
- { required: true, message: '请填写本年度带徒人数' },
|
|
|
|
|
- { type: 'integer', min: 0, message: '须为不小于 0 的整数' },
|
|
|
|
|
- ],
|
|
|
|
|
- activity: [
|
|
|
|
|
- { required: true, message: '请填写本年度宣传活动场次' },
|
|
|
|
|
- { type: 'integer', min: 0, message: '须为不小于 0 的整数' },
|
|
|
|
|
- ],
|
|
|
|
|
- partyBSign: [
|
|
|
|
|
- {
|
|
|
|
|
- validator(_rule, value, callback) {
|
|
|
|
|
- const s = typeof value === 'string' ? value.trim() : '';
|
|
|
|
|
- if (!s)
|
|
|
|
|
- callback(new Error('请完成乙方签名'));
|
|
|
|
|
- else
|
|
|
|
|
- callback();
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- ],
|
|
|
|
|
- idCard: [
|
|
|
|
|
- { required: true, message: '请填写身份证号' },
|
|
|
|
|
- ],
|
|
|
|
|
- ich: [{ required: true, message: '请填写非遗项目名称' }],
|
|
|
|
|
- health: [{ required: true, message: '请填写身体状况' }],
|
|
|
|
|
- mobile: [
|
|
|
|
|
- { required: true, message: '请填写乙方联系电话' },
|
|
|
|
|
- {
|
|
|
|
|
- validator(_rule, value, callback) {
|
|
|
|
|
- const s = value != null ? String(value).trim() : '';
|
|
|
|
|
- if (!CN_MOBILE_RE.test(s))
|
|
|
|
|
- callback(new Error('请输入正确的手机号'));
|
|
|
|
|
- else
|
|
|
|
|
- callback();
|
|
|
|
|
- },
|
|
|
|
|
- },
|
|
|
|
|
- ],
|
|
|
|
|
- };
|
|
|
|
|
- if (currentAgreement.value?.level !== 25)
|
|
|
|
|
- rules.course = [
|
|
|
|
|
- { required: true, message: '请填写本年度研修班场次' },
|
|
|
|
|
- { type: 'integer', min: 0, message: '须为不小于 0 的整数' },
|
|
|
|
|
- ];
|
|
|
|
|
- return rules;
|
|
|
|
|
-});
|
|
|
|
|
|
|
+const agreementFormRef = ref<InstanceType<typeof AgreementFormDisplay> | null>(null);
|
|
|
|
|
|
|
|
async function loadBasicInfo() {
|
|
async function loadBasicInfo() {
|
|
|
const uid = authStore.userInfo?.id ?? authStore.userId;
|
|
const uid = authStore.userInfo?.id ?? authStore.userId;
|
|
@@ -173,22 +105,11 @@ async function loadBasicInfo() {
|
|
|
d.level = basicInfo.level;
|
|
d.level = basicInfo.level;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const agreementYear = computed(() => currentAgreement.value?.year ?? 2027);
|
|
|
|
|
-const agreementTitle = computed(
|
|
|
|
|
- () => `${agreementYear.value} 年度${levelTitle.value}非物质文化遗产代表性传承人传承协议`,
|
|
|
|
|
-);
|
|
|
|
|
-const levelTitle = computed(() => {
|
|
|
|
|
- if (currentAgreement.value?.level === 23) return '国家级';
|
|
|
|
|
- if (currentAgreement.value?.level === 24) return '省级';
|
|
|
|
|
- return '市级';
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
const loader = useSimpleDataLoader(async () => {
|
|
const loader = useSimpleDataLoader(async () => {
|
|
|
if (queryId.value > 0) {
|
|
if (queryId.value > 0) {
|
|
|
|
|
+ const now = new Date();
|
|
|
const detail = await AssessmentContentApi.getAgreementDetail(queryId.value, queryUserId.value || undefined);
|
|
const detail = await AssessmentContentApi.getAgreementDetail(queryId.value, queryUserId.value || undefined);
|
|
|
currentAgreement.value = detail;
|
|
currentAgreement.value = detail;
|
|
|
- partyAStampDate.value = { year: '', month: '', day: '' };
|
|
|
|
|
- partyBSignDate.value = { year: '', month: '', day: '' };
|
|
|
|
|
return currentAgreement.value;
|
|
return currentAgreement.value;
|
|
|
}
|
|
}
|
|
|
const uid = authStore.userInfo?.id ?? authStore.userId;
|
|
const uid = authStore.userInfo?.id ?? authStore.userId;
|
|
@@ -199,12 +120,6 @@ const loader = useSimpleDataLoader(async () => {
|
|
|
uid,
|
|
uid,
|
|
|
);
|
|
);
|
|
|
currentAgreement.value = detail;
|
|
currentAgreement.value = detail;
|
|
|
- partyAStampDate.value = { year: '', month: '', day: '' };
|
|
|
|
|
- partyBSignDate.value = {
|
|
|
|
|
- year: detail.updatetime.getFullYear().toString(),
|
|
|
|
|
- month: (detail.updatetime.getMonth() + 1).toString(),
|
|
|
|
|
- day: detail.updatetime.getDate().toString(),
|
|
|
|
|
- };
|
|
|
|
|
} else {
|
|
} else {
|
|
|
currentAgreement.value = null;
|
|
currentAgreement.value = null;
|
|
|
}
|
|
}
|
|
@@ -227,6 +142,28 @@ watch(
|
|
|
const submitLoading = ref(false);
|
|
const submitLoading = ref(false);
|
|
|
const appConfiguration = injectAppConfiguration();
|
|
const appConfiguration = injectAppConfiguration();
|
|
|
|
|
|
|
|
|
|
+const rejectTypeLabel = computed(() => {
|
|
|
|
|
+ switch (currentAgreement.value?.rejectType) {
|
|
|
|
|
+ case 1: return '自评阶段退回';
|
|
|
|
|
+ case 2: return '项目保护单位退回';
|
|
|
|
|
+ case 3: return '县(区)文旅部门退回';
|
|
|
|
|
+ case 4: return '设区市文旅部门、省非遗中心退回';
|
|
|
|
|
+ case 5: return '省文化和旅游厅退回';
|
|
|
|
|
+ default: return '';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const progressLabel = computed(() => {
|
|
|
|
|
+ switch (currentAgreement.value?.progress) {
|
|
|
|
|
+ case 1: return '已提交,等待审核';
|
|
|
|
|
+ case 2: return '项目保护单位审核通过';
|
|
|
|
|
+ case 3: return '县(区)文旅部门审核通过';
|
|
|
|
|
+ case 4: return '设区市文旅部门、省非遗中心审核通过';
|
|
|
|
|
+ case 5: return '省文化和旅游厅审核通过';
|
|
|
|
|
+ default: return '';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
async function createAgreement() {
|
|
async function createAgreement() {
|
|
|
const now = new Date();
|
|
const now = new Date();
|
|
|
const u = authStore.userInfo;
|
|
const u = authStore.userInfo;
|
|
@@ -245,23 +182,13 @@ async function createAgreement() {
|
|
|
detail.partyA = '福建省文化和旅游厅';
|
|
detail.partyA = '福建省文化和旅游厅';
|
|
|
}
|
|
}
|
|
|
detail.partyB = nick;
|
|
detail.partyB = nick;
|
|
|
- partyAStampDate.value = {
|
|
|
|
|
- year: now.getFullYear().toString(),
|
|
|
|
|
- month: (now.getMonth() + 1).toString(),
|
|
|
|
|
- day: now.getDate().toString(),
|
|
|
|
|
- };
|
|
|
|
|
- partyBSignDate.value = {
|
|
|
|
|
- year: now.getFullYear().toString(),
|
|
|
|
|
- month: (now.getMonth() + 1).toString(),
|
|
|
|
|
- day: now.getDate().toString(),
|
|
|
|
|
- };
|
|
|
|
|
currentAgreement.value = detail;
|
|
currentAgreement.value = detail;
|
|
|
await loadBasicInfo();
|
|
await loadBasicInfo();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async function saveAgreement() {
|
|
async function saveAgreement() {
|
|
|
try {
|
|
try {
|
|
|
- await formRef.value?.validate();
|
|
|
|
|
|
|
+ await agreementFormRef.value?.validate();
|
|
|
} catch {
|
|
} catch {
|
|
|
message.warning('请填写完整信息');
|
|
message.warning('请填写完整信息');
|
|
|
return;
|
|
return;
|
|
@@ -284,6 +211,52 @@ async function saveAgreement() {
|
|
|
submitLoading.value = false;
|
|
submitLoading.value = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+async function submitForm() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await agreementFormRef.value?.validate();
|
|
|
|
|
+ } catch (e: unknown) {
|
|
|
|
|
+ if (e && typeof e === 'object' && 'errorFields' in (e as object))
|
|
|
|
|
+ message.warning('请填写完整信息');
|
|
|
|
|
+ else if (e instanceof Error)
|
|
|
|
|
+ message.warning(e.message);
|
|
|
|
|
+ else
|
|
|
|
|
+ message.warning('请填写完整信息');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const confirmed = await new Promise<boolean>((resolve) => {
|
|
|
|
|
+ Modal.confirm({
|
|
|
|
|
+ title: '提示',
|
|
|
|
|
+ content: '您确认要提交审核吗?请确认各项信息填写无误。',
|
|
|
|
|
+ okText: '确认提交',
|
|
|
|
|
+ cancelText: '取消',
|
|
|
|
|
+ onOk: () => resolve(true),
|
|
|
|
|
+ onCancel: () => resolve(false),
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ if (!confirmed)
|
|
|
|
|
+ return;
|
|
|
|
|
+ submitLoading.value = true;
|
|
|
|
|
+ const d = currentAgreement.value;
|
|
|
|
|
+ if (!d) {
|
|
|
|
|
+ submitLoading.value = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ d.progress = 1;
|
|
|
|
|
+ await AssessmentContentApi.saveAgreement(d as AgreementDetail);
|
|
|
|
|
+ message.success('提交审核成功');
|
|
|
|
|
+ await waitTimeOut(500);
|
|
|
|
|
+ await loader.load();
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Modal.error({
|
|
|
|
|
+ title: '提交审核失败',
|
|
|
|
|
+ content: formatErr(error),
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ submitLoading.value = false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
async function downloadAgreement() {
|
|
async function downloadAgreement() {
|
|
|
if (!currentAgreement.value?.id) {
|
|
if (!currentAgreement.value?.id) {
|
|
|
message.warning('请先保存传承协议后再下载 PDF');
|
|
message.warning('请先保存传承协议后再下载 PDF');
|