| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- <template>
- <CommonRoot>
- <FlexCol padding="space.lg">
- <SimplePageContentLoader :loader="loader">
- <template v-if="loader.isFinished.value">
- <Result
- v-if="!currentAgreement"
- status="info"
- title="您还未签署传承协议"
- description="请先签署传承协议"
- >
- <Height :height="30" />
- <Button type="primary" @click="createAgreement">去签署传承协议</Button>
- </Result>
- <FlexCol v-else gap="gap.md">
- <Alert type="info" message="请仔细阅读传承协议,确保您已理解内容,并签署传承协议。" />
- <FlexCol gap="gap.md">
- <Form ref="formRef" :model="currentAgreement" :rules="formRules">
- <H3>{{ agreementTitle }}</H3>
- <AgreementBodyNational
- v-if="currentAgreement?.level === 23"
- :detail="(currentAgreement as AgreementDetail)"
- :agreement-year="agreementYear"
- :party-a-stamp-date="partyAStampDate"
- :party-b-sign-date="partyBSignDate"
- :upload-agreement-sign="uploadAgreementSign"
- @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"
- :upload-agreement-sign="uploadAgreementSign"
- @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"
- :upload-agreement-sign="uploadAgreementSign"
- @update:party-a-stamp-date="partyAStampDate = $event"
- @update:party-b-sign-date="partyBSignDate = $event"
- />
- </Form>
- </FlexCol>
- <Button type="primary" block :loading="submitLoading" @click="saveAgreement">保存传承协议</Button>
- <Button :loading="submitLoading" @click="downloadAgreement">下载协议PDF</Button>
- </FlexCol>
- </template>
- </SimplePageContentLoader>
- </FlexCol>
- </CommonRoot>
- </template>
- <script setup lang="ts">
- import { computed, ref } from 'vue';
- import { useAuthStore } from '@/store/auth';
- import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
- import { assertNotNull, formatError } from '@imengyu/imengyu-utils';
- import { toast, alert } from '@/components/dialog/CommonRoot';
- import AssessmentContentApi, { AgreementDetail } from '@/api/collect/AssessmentContent';
- import FlexCol from '@/components/layout/FlexCol.vue';
- import Result from '@/components/feedback/Result.vue';
- import SimplePageContentLoader from '@/components/loader/SimplePageContentLoader.vue';
- import Button from '@/components/basic/Button.vue';
- import Height from '@/components/layout/space/Height.vue';
- import H3 from '@/components/typography/H3.vue';
- import Alert from '@/components/feedback/Alert.vue';
- import Form, { type FormInstance } from '@/components/form/Form.vue';
- 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 type { Rules } from 'async-validator';
- import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
- import CommonRoot from '@/components/dialog/CommonRoot.vue';
- import { useImageSimpleUploadCo } from '@/common/components/upload/ImageUploadCo';
- import { injectAppConfiguration } from '@/api/system/useAppConfiguration';
- const { querys } = useLoadQuerys({
- id: 0,
- userId: 0,
- }, () => {
- loader.load();
- });
- const authStore = useAuthStore();
- const appConfig = injectAppConfiguration();
- 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, type: 'number', message: '请填写本年度带徒人数' },
- { type: 'number', min: 0, max: 100, message: '须为不小于 0 的整数' },
- ],
- activity: [
- { required: true, type: 'number', message: '请填写本年度宣传活动场次' },
- { type: 'number', min: 0, max: 100, 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: '请填写身份证号' },
- {
- validator(_rule, value, callback) {
- const s = value != null ? String(value).trim() : '';
- if (!CN_ID_RE.test(s))
- callback(new Error('请输入正确的身份证号'));
- else
- callback();
- },
- },
- ],
- 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, type: 'number', message: '请填写本年度研修班场次' },
- { type: 'number', min: 0, max: 100, message: '须为不小于 0 的整数' },
- ];
- return rules;
- });
- async function loadBasicInfo() {
- const basicInfo = await AssessmentContentApi.getInheritorBasic(authStore.userInfo?.id);
- assertNotNull(currentAgreement.value, 'currentAgreement is null');
- currentAgreement.value.partyB = basicInfo.name;
- currentAgreement.value.mobile = basicInfo.mobile;
- currentAgreement.value.idCard = basicInfo.idCard;
- currentAgreement.value.ich = basicInfo.ichName;
- currentAgreement.value.level = basicInfo.level;
- }
- const uploadAgreementSign = useImageSimpleUploadCo();
- 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 () => {
- if (querys.value.id > 0) {
- const detail = await AssessmentContentApi.getAgreementDetail(querys.value.id, querys.value.userId);
- currentAgreement.value = detail;
- partyAStampDate.value = { year: '', month: '', day: '' };
- partyBSignDate.value = { year: '', month: '', day: '' };
- return currentAgreement.value;
- }
- const basicInfo = await AssessmentContentApi.getInheritorBasic(authStore.userInfo?.id);
- if (basicInfo.agreementId > 0) {
- const detail = await AssessmentContentApi.getAgreementDetail(
- basicInfo.agreementId,
- authStore.userInfo?.id
- );
- 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 {
- currentAgreement.value = null;
- }
- return currentAgreement.value;
- });
- const submitLoading = ref(false);
- async function createAgreement() {
- const now = new Date();
- const u = authStore.userInfo;
- const nick = u?.nickname || u?.diyname;
- const uid = authStore.userInfo?.id ?? authStore.userId;
- const basicInfo = await AssessmentContentApi.getInheritorBasic(uid);
- const detail = new AgreementDetail();
- detail.userId = authStore.userInfo!.id;
- detail.year = appConfig.value?.collectSignYear || now.getFullYear() + 1;;
- if (basicInfo.level === 24) {
- detail.partyA = '厦门市文化和旅游局';
- } else if (basicInfo.level === 25) {
- detail.partyA = '厦门市文化和旅游局';
- } else {
- detail.partyA = '福建省文化和旅游厅';
- }
- detail.partyB = nick ?? '';
- console.log(authStore.userInfo, u, 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;
- loadBasicInfo();
- }
- async function saveAgreement() {
- const detail = currentAgreement.value;
- console.log(detail);
-
- try {
- await formRef.value?.validate();
- } catch (error) {
- toast('请填写完整信息');
- return;
- }
- submitLoading.value = true;
- try {
- assertNotNull(detail, 'currentAgreement is null');
- await AssessmentContentApi.saveAgreement(detail as AgreementDetail);
- toast('保存传承协议成功');
- } catch (error) {
- alert({
- title: '保存传承协议失败',
- content: formatError(error),
- });
- }
- submitLoading.value = false;
- }
- async function downloadAgreement() {
- if (!currentAgreement.value?.id) {
- toast('请先保存评估表后再下载PDF');
- return;
- }
- try {
- assertNotNull(currentAgreement.value, 'currentForm is null');
- const pdfPath = await AssessmentContentApi.downloadAgreementPdf(currentAgreement.value.id);
- uni.openDocument({
- filePath: pdfPath,
- fileType: 'pdf',
- showMenu: true,
- });
- } catch (error) {
- alert({
- title: '下载评估表失败',
- content: formatError(error),
- });
- }
- }
- </script>
|