快乐的梦鱼 недель назад: 4
Родитель
Сommit
0be01c0c75

+ 2 - 0
src/api/collect/AssessmentContent.ts

@@ -210,6 +210,7 @@ export class SelfAssessmentDetail extends DataModel<SelfAssessmentDetail> {
       province: { clientSide: 'number', serverSide: 'number' },
       provincePoints: { clientSide: 'number', serverSide: 'number' },
       level: { clientSide: 'number', serverSide: 'string' },
+      awardTime: { clientSide: 'date', serverSide: 'string' },
       checkItems: {
         clientSide: 'array',
         clientSideChildDataModel: SelfAssessmentCheckItemAnswer,
@@ -255,6 +256,7 @@ export class SelfAssessmentDetail extends DataModel<SelfAssessmentDetail> {
   address = '' as string|null;
   content = '' as string|null;
   weigh = 0 as number;
+  awardTime = new Date();
   deductContent = '' as string|null;
   deductPoints = 0 as number;
   points = 0 as number;

+ 1 - 1
src/components/dynamic/DynamicForm.vue

@@ -21,7 +21,7 @@
       :description="`At form ${name || 'unnamed'} Root`"
     />
     <template v-else>
-      <template v-for="(item, index) in options.formItems" :key="index">
+      <template v-for="(item, index) in options.formItems" :key="item.name">
         <template v-if="item.type === 'insertion'">
           <slot name="insertion" :data="item" />
         </template>

+ 16 - 16
src/components/dynamic/nest/DynamicFormItemContainer.vue

@@ -38,9 +38,9 @@
         </template>
       </DynamicFormItemNormal>
       <!--循环子条目-->
-      <DynamicFormItemContainerFuckMp 
+      <DynamicFormItemContainer 
         v-for="(child, k) in item.children"
-        :key="k"
+        :key="child.name"
         :item="child"
         :name="name+'.'+child.name"
         :rawModel="rawModel"
@@ -56,7 +56,7 @@
         <template #formCeil="values">
           <slot name="formCeil" :data="values.data" />
         </template>
-      </DynamicFormItemContainerFuckMp>
+      </DynamicFormItemContainer>
     </DynamicFormCheckEmpty>
     <!--对象组-->
     <DynamicFormCheckEmpty 
@@ -70,9 +70,9 @@
       <FormGroup :title="evaluateCallback(item.label)" v-bind="(item.additionalProps as object)">
         <Row v-bind="item.rowProps">
           <!--循环子条目-->
-          <DynamicFormItemContainerFuckMp 
+          <DynamicFormItemContainer 
             v-for="(child, k) in item.children" 
-            :key="k"
+            :key="child.name"
             :item="child"
             :colProps="{ ...item.childrenColProps, ...child.colProps }"
             :name="name+'.'+child.name"
@@ -89,7 +89,7 @@
             <template #formCeil="values">
               <slot name="formCeil" :data="values.data" />
             </template>
-          </DynamicFormItemContainerFuckMp>
+          </DynamicFormItemContainer>
         </Row>
       </FormGroup>
     </DynamicFormCheckEmpty>
@@ -97,10 +97,10 @@
     <FormGroup v-else-if="item.type === 'flat-group'" :title="evaluateCallback(item.label)" v-bind="(item.additionalProps as object)">
       <Row v-bind="item.rowProps">
         <!--循环子条目-->
-        <DynamicFormItemContainerFuckMp 
+        <DynamicFormItemContainer 
           v-for="(child, k) in item.children" 
           :colProps="{ ...item.childrenColProps, ...child.colProps }"
-          :key="k"
+          :key="child.name"
           :item="child"
           :name="parentName ? `${parentName}.${child.name}` : child.name"
           :rawModel="rawModel"
@@ -116,7 +116,7 @@
           <template #formCeil="values">
             <slot name="formCeil" :data="values.data" />
           </template>
-        </DynamicFormItemContainerFuckMp>
+        </DynamicFormItemContainer>
       </Row>
     </FormGroup>
     <!--扁平普通-->
@@ -133,9 +133,9 @@
       <template #insertion>
         <Row v-bind="item.rowProps">
           <!--循环子条目-->
-          <DynamicFormItemContainerFuckMp 
+          <DynamicFormItemContainer 
             v-for="(child, k) in item.children" 
-            :key="k"
+            :key="child.name"
             :item="child"
             :colProps="{ ...item.childrenColProps, ...child.colProps }"
             :name="parentName ? `${parentName}.${child.name}` : child.name"
@@ -152,7 +152,7 @@
             <template #formCeil="values">
               <slot name="formCeil" :data="values.data" />
             </template>
-          </DynamicFormItemContainerFuckMp>
+          </DynamicFormItemContainer>
         </Row>
       </template>
     </DynamicFormItemNormal>
@@ -198,7 +198,7 @@
               />
             </template>
             <template #child="{ item, pitem, kname, model: child, onUpdateValue, isFirst, isLast }">
-              <DynamicFormItemContainerFuckMp
+              <DynamicFormItemContainer
                 :item="item"
                 :name="kname"
                 :rawModel="rawModel"
@@ -260,7 +260,7 @@
               />
             </template>
             <template #child="{ item, pitem, kname, model: child, onUpdateValue, isFirst, isLast }">
-              <DynamicFormItemContainerFuckMp
+              <DynamicFormItemContainer
                 :item="item"
                 :name="kname"
                 :rawModel="rawModel"
@@ -276,7 +276,7 @@
                 <template #formCeil="values">
                   <slot name="formCeil" :data="values.data" />
                 </template>
-              </DynamicFormItemContainerFuckMp>
+              </DynamicFormItemContainer>
             </template>
           </FormArrayGroup>
         </template>
@@ -313,7 +313,7 @@ import FormArrayGroup from '../group/FormArrayGroup.vue';;
 import Col, { type ColProps } from '@/components/layout/grid/Col.vue';
 import Row from '@/components/layout/grid/Row.vue';
 import DynamicFormCheckEmpty from './DynamicFormCheckEmpty.vue';
-import DynamicFormItemContainerFuckMp from './DynamicFormItemContainerFuckMp.vue';
+import DynamicFormItemContainer from './DynamicFormItemContainer.vue';
 
 /**
  * 动态表单条目包装组件,处理基础类型分支、数据传入、回调处理、事件传递。

+ 0 - 19
src/components/dynamic/nest/DynamicFormItemContainerFuckMp.vue

@@ -1,19 +0,0 @@
-<script setup lang="ts">
-import DynamicFormItemContainer, { type DynamicFormItemContainerProps } from './DynamicFormItemContainer.vue';
-
-defineProps<DynamicFormItemContainerProps>()
-defineEmits(['update:model'])
-defineOptions({
-  options: {
-    virtualHost: true,
-  }
-})
-</script>
-
-<template>
-  <DynamicFormItemContainer v-bind="($props as any)" @update:model="(val) => $emit('update:model', val)">
-    <template #formCeil="values">
-      <slot name="formCeil" :data="values.data" />
-    </template>
-  </DynamicFormItemContainer>
-</template>

+ 1 - 1
src/components/dynamic/wrappers/CheckBoxList.vue

@@ -93,7 +93,7 @@ export interface CheckBoxListProps {
   vertical?: boolean,
   className?: string,
   innerStyle?: Record<string, any>,
-  loadData: () => Promise<CheckBoxListItem[]>;
+  loadData?: () => Promise<CheckBoxListItem[]>;
 }
 
 const props = withDefaults(defineProps<CheckBoxListProps>(), {

+ 2 - 2
src/pages/article/editor/editor.vue

@@ -12,8 +12,8 @@
     ></sp-editor>
     
     <view class="d-flex flex-row align-center gap-s p-3">
-      <Button @click="cancel">取消</Button>
-      <Button type="primary" @click="save">保存</Button>
+      <Button :innerStyle="{ flex: '1' }" @click="cancel">取消</Button>
+      <Button :innerStyle="{ flex: '1' }" type="primary" @click="save">保存</Button>
     </view>
     <XBarSpace />
   </view>

+ 116 - 244
src/pages/collect/assessment/argeement-sign.vue

@@ -22,165 +22,36 @@
               <Form ref="formRef" :model="currentAgreement" :rules="formRules">
                 <H3>{{ agreementTitle }}</H3>
 
-                <FlexCol :gap="'sm'">
-                  <P>甲方:福建省文化和旅游厅</P>
-                  <FlexRow align="center" wrap :gap="'sm'">
-                    <Text font-config="p" color="text.content">乙方:</Text>
-                    <AgreementPrefillInline
-                      v-model="currentAgreement.partyB"
-                      name="partyB"
-                      placeholder="请填写乙方(传承人)姓名"
-                    />
-                  </FlexRow>
-                </FlexCol>
-
-                <Height :height="8" />
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  为传承弘扬中华优秀传统文化,有效保护和传承非物质文化遗产,鼓励和支持国家级非物质文化遗产代表性传承人开展传承活动,根据《中华人民共和国非物质文化遗产法》《国家级非物质文化遗产代表性传承人认定与管理办法》等有关法律法规,制定协议,并按照下列各项条款签署,甲、乙双方共同遵守。
-                </Text>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  一、甲乙双方应当以习近平新时代中国特色社会主义思想为指导,坚持以人民为中心,弘扬社会主义核心价值观,共同保护传承非物质文化遗产,推动中华优秀传统文化创造性转化、创新性发展。
-                </Text>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  二、甲方按照《国家级非物质文化遗产代表性传承人认定与管理办法》的要求,支持国家级非物质文化遗产代表性传承人开展传承、传播活动。
-                </Text>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  三、甲方按照《国家级非物质文化遗产保护专项资金管理办法》的要求,落实国家给予的代表性传承人的传承补助。
-                </Text>
-
-                <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
-                  <Text font-config="p" color="text.content">四、乙方应积极开展传承活动,培养后继人才,制定传承计划,{{ agreementYear }} 年度带徒</Text>
-                  <AgreementPrefillInline
-                    v-model="currentAgreement.apprentice"
-                    name="apprentice"
-                    number-mode
-                    placeholder="人数"
-                    suffix="人。"
-                  />
-                </FlexRow>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  五、乙方应妥善保存相关实物、资料情况。主动保存、提供与该项非遗项目有关的原始资料、实物,配合记录工作。
-                </Text>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  六、乙方应主动、及时配合非遗调查,主动向文化和旅游主管部门、非遗保护中心反映非遗项目保护、传承情况和总结材料,并完成文化和旅游主管部门临时交办的非遗工作任务,提出保护的意见、建议。
-                </Text>
-
-                <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
-                  <Text font-config="p" color="text.content">七、乙方应积极、主动参加各级政府组织的非物质文化遗产公益性宣传活动,{{ agreementYear }} 年度完成</Text>
-                  <AgreementPrefillInline
-                    v-model="currentAgreement.activity"
-                    name="activity"
-                    number-mode
-                    placeholder="场次"
-                    suffix="场。"
-                  />
-                </FlexRow>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  八、乙方应合理使用国家级非物质文化遗产代表性传承人补助经费,用于开展非遗项目的传习活动,做好传承补助经费使用记录、支出范围和绩效评价等,不得用于生活补助。
-                </Text>
-
-                <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
-                  <Text font-config="p" color="text.content">九、乙方应积极、主动参加文化和旅游部组织的非物质文化遗产代表性传承人研修班,{{ agreementYear }} 年度完成</Text>
-                  <AgreementPrefillInline
-                    v-model="currentAgreement.course"
-                    name="course"
-                    number-mode
-                    placeholder="场次"
-                    suffix="场。"
-                  />
-                </FlexRow>
-
-                <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
-                  十、乙方应积极参与非物质文化遗产相关理论和实践研究、发表(出版)论文、专著等研究。
-                </Text>
-
-                <Height :height="16" />
-
-                <FlexCol :gap="'md'" :inner-style="signBlockStyle">
-                  <FlexRow padding="space.sm">
-                    <Text font-config="p" color="text.content" bold>甲方:福建省文化和旅游厅</Text>
-                  </FlexRow>
-                  <Field
-                    label="负责人(代表人)"
-                    label-position="top"
-                    v-model="currentAgreement.partyASign"
-                    placeholder="选填"
-                    :show-bottom-border="true"
-                  />
-                  <Field
-                    label="甲方电话"
-                    label-position="top"
-                    name="partyAMobile"
-                    type="tel"
-                    v-model="currentAgreement.partyAMobile"
-                    placeholder="请填写甲方联系电话"
-                  />
-                  <AgreementDateWriteBlock
-                    v-model="partyAStampDate"
-                    hint="(以实际盖章日期为准)"
-                  />
-
-                  <Height :height="24" />
-
-                  <FlexRow padding="space.sm">
-                    <Text font-config="p" color="text.content" bold>乙方:{{ currentAgreement.partyB }}(签名)</Text>
-                  </FlexRow>
-                  <Field
-                    label="乙方签名 / 说明"
-                    label-position="top"
-                    name="partyBSign"
-                    showRightArrow
-                  >
-                    <Text>点击签名</Text>
-                    <template #extra>
-                      <SignatureField
-                        v-model="currentAgreement.partyBSign"
-                        placeholder=""
-                        :upload="uploadAgreementSign"
-                      />
-                    </template>
-                  </Field>
-                  <Field
-                    label="身份证号"
-                    label-position="top"
-                    name="idCard"
-                    v-model="currentAgreement.idCard"
-                    placeholder="请填写身份证号"
-                  />
-                  <Field
-                    label="项目名称"
-                    label-position="top"
-                    name="ich"
-                    v-model="currentAgreement.ich"
-                    placeholder="非遗项目名称"
-                  />
-                  <Field
-                    label="身体状况"
-                    label-position="top"
-                    name="health"
-                    v-model="currentAgreement.health"
-                    placeholder="请简要填写"
-                  />
-                  <Field
-                    label="乙方电话"
-                    label-position="top"
-                    name="mobile"
-                    type="tel"
-                    v-model="currentAgreement.mobile"
-                    placeholder="请填写联系电话"
-                  />
-                  <AgreementDateWriteBlock
-                    v-model="partyBSignDate"
-                    hint="(以实际签署日期为准)"
-                  />
-                </FlexCol>
+                <AgreementBodyNational
+                  v-if="agreementLevel === 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="agreementLevel === 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
+                  :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>
 
@@ -207,14 +78,11 @@ 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 FlexRow from '@/components/layout/FlexRow.vue';
-import P from '@/components/typography/P.vue';
-import Field from '@/components/form/Field.vue';
-import Text from '@/components/basic/Text.vue';
-import AgreementPrefillInline from './components/AgreementPrefillInline.vue';
-import AgreementDateWriteBlock, { type AgreementYmdParts } from './components/AgreementDateWriteBlock.vue';
-import SignatureField from '@/components/form/SignatureField.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';
@@ -238,73 +106,87 @@ const formRef = ref<FormInstance | null>(null);
 const CN_MOBILE_RE = /^1\d{10}$/;
 const CN_ID_RE = /^(?:\d{15}|\d{17}[\dXx])$/;
 
-const formRules: 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 的整数' },
-  ],
-  course: [
-    { required: true, message: '请填写本年度研修班场次' },
-    { type: 'integer', min: 0, message: '须为不小于 0 的整数' },
-  ],
-  partyAMobile: [
-    {
-      validator(_rule, value, callback) {
-        const s = value != null && value !== undefined ? String(value).trim() : '';
-        if (!s) {
-          callback();
-          return;
-        }
-        if (!CN_MOBILE_RE.test(s))
-          callback(new Error('请输入正确的甲方联系电话'));
-        else
-          callback();
+/** 23=国家级 24=省级 25=市级;缺省按国家级展示 */
+const agreementLevel = computed(() => {
+  const v = currentAgreement.value?.level;
+  if (v === 24) return 24;
+  if (v === 25) return 25;
+  return 23;
+});
+
+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 的整数' },
+    ],
+    partyAMobile: [
+      {
+        validator(_rule, value, callback) {
+          const s = value != null && value !== undefined ? String(value).trim() : '';
+          if (!s) {
+            callback();
+            return;
+          }
+          if (!CN_MOBILE_RE.test(s))
+            callback(new Error('请输入正确的甲方联系电话'));
+          else
+            callback();
+        },
       },
-    },
-  ],
-  partyBSign: [
-    {
-      validator(_rule, value, callback) {
-        const s = typeof value === 'string' ? value.trim() : '';
-        if (!s)
-          callback(new Error('请完成乙方签名'));
-        else
-          callback();
+    ],
+    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();
+    ],
+    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();
+    ],
+    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 (agreementLevel.value === 25)
+    rules.partyA = [{ required: true, message: '请填写甲方单位全称' }];
+  else
+    rules.course = [
+      { required: true, message: '请填写本年度研修班场次' },
+      { type: 'integer', min: 0, message: '须为不小于 0 的整数' },
+    ];
+  return rules;
+});
 
 const articleWrapStyle = {
   padding: '24rpx 28rpx',
@@ -314,13 +196,6 @@ const articleWrapStyle = {
   borderStyle: 'solid',
   borderColor: '#eeeeee',
 };
-const paragraphStyle = {
-  lineHeight: '1.75',
-  marginBottom: '12rpx',
-};
-const signBlockStyle = {
-  paddingTop: '8rpx',
-};
 
 async function loadBasicInfo() {
   const basicInfo = await AssessmentContentApi.getInheritorBasic(authStore.userInfo?.id);
@@ -334,17 +209,14 @@ async function loadBasicInfo() {
 const uploadAgreementSign = useImageSimpleUploadCo();
 
 const agreementYear = computed(() => currentAgreement.value?.year ?? new Date().getFullYear());
-
-const levelTitle = computed(() => {
-  const v = currentAgreement.value?.level;
-  if (v === 23) return '国家级';
-  if (v === 24) return '省级';
-  if (v === 25) return '市级';
-  return '国家级';
-});
 const agreementTitle = computed(
   () => `${agreementYear.value} 年度${levelTitle.value}非物质文化遗产代表性传承人传承协议`,
 );
+const levelTitle = computed(() => {
+  if (agreementLevel.value === 23) return '国家级';
+  if (agreementLevel.value === 24) return '省级';
+  return '市级';
+});
 const loader = useSimpleDataLoader(async () => {
   if (querys.value.id > 0) {
     const detail = await AssessmentContentApi.getAgreementDetail(querys.value.id);

+ 192 - 0
src/pages/collect/assessment/components/AgreementBodyMunicipal.vue

@@ -0,0 +1,192 @@
+<template>
+  <FlexCol :gap="'sm'">
+    <P>甲方:(设文化和旅游局)</P>
+    <FlexRow align="center" wrap :gap="'sm'">
+      <Text font-config="p" color="text.content">乙方:</Text>
+      <AgreementPrefillInline
+        v-model="detail.partyB"
+        name="partyB"
+        placeholder="请填写乙方(传承人)姓名"
+      />
+    </FlexRow>
+  </FlexCol>
+
+  <Height :height="8" />
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    为传承弘扬中华优秀传统文化,有效保护和传承非物质文化遗产,鼓励和支持市级非物质文化遗产代表性传承人开展传承活动,根据《福建省非物质文化遗产条例》《厦门市市级非物质文化遗产代表性传承人认定与管理办法》等有关法律法规,制定协议,并按照下列各项条款签署,甲、乙双方共同遵守。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    九、甲乙双方应当以习近平新时代中国特色社会主义思想为指导,坚持以人民为中心,弘扬社会主义核心价值观,共同保护传承非物质文化遗产,推动中华优秀传统文化创造性转化、创新性发展。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十、甲方按照《厦门市市级非物质文化遗产代表性传承人认定与管理办法》的要求,支持市级非物质文化遗产代表性传承人开展传承、传播活动。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十一、甲方按照《福建省非物质文化遗产保护与传承专项资金管理办法》的要求,落实市文化和旅游局给予的代表性传承人的传承补助。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">十二、乙方应积极开展传承活动,培养后继人才,制定传承计划,{{ agreementYear }} 年度带徒</Text>
+    <AgreementPrefillInline
+      v-model="detail.apprentice"
+      name="apprentice"
+      number-mode
+      placeholder="人数"
+      suffix="人。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十三、乙方应妥善保存相关实物、资料情况。主动保存、提供与该项非遗项目有关的原始资料、实物,配合记录工作。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十四、乙方应主动、及时配合非遗调查,主动向文化和旅游主管部门、非遗保护中心反映非遗项目保护、传承情况和总结材料,并完成文化和旅游主管部门临时交办的非遗工作任务,提出保护的意见、建议。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">十五、乙方应积极、主动参加各级政府组织的非物质文化遗产公益性宣传活动,{{ agreementYear }} 年度完成</Text>
+    <AgreementPrefillInline
+      v-model="detail.activity"
+      name="activity"
+      number-mode
+      placeholder="场次"
+      suffix="场。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十六、乙方应合理使用市级非物质文化遗产代表性传承人补助经费,用于开展非遗项目的传习活动,做好传承补助经费使用记录、支出范围和绩效评价等,不得用于生活补助。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十七、乙方应积极参与非物质文化遗产相关理论和实践研究、发表(出版)论文、专著等研究。
+  </Text>
+
+  <Height :height="16" />
+
+  <FlexCol :gap="'md'" :inner-style="signBlockStyle">
+    <Field
+      label="甲方"
+      label-position="top"
+      name="partyA"
+      v-model="detail.partyA"
+      placeholder="请填写设区市文化和旅游局全称"
+      :show-bottom-border="true"
+    />
+    <Field
+      label="负责人(代表人)"
+      label-position="top"
+      v-model="detail.partyASign"
+      placeholder="选填"
+      :show-bottom-border="true"
+    />
+    <Field
+      label="甲方电话"
+      label-position="top"
+      name="partyAMobile"
+      type="tel"
+      v-model="detail.partyAMobile"
+      placeholder="请填写甲方联系电话"
+    />
+    <AgreementDateWriteBlock
+      :model-value="partyAStampDate"
+      hint="(以实际盖章日期为准)"
+      @update:model-value="emit('update:partyAStampDate', $event)"
+    />
+
+    <Height :height="24" />
+
+    <FlexRow padding="space.sm">
+      <Text font-config="p" color="text.content" bold>乙方:{{ detail.partyB }}(签名)</Text>
+    </FlexRow>
+    <Field
+      label="乙方签名 / 说明"
+      label-position="top"
+      name="partyBSign"
+      showRightArrow
+    >
+      <Text>点击签名</Text>
+      <template #extra>
+        <SignatureField
+          v-model="detail.partyBSign"
+          placeholder=""
+          :upload="uploadAgreementSign"
+        />
+      </template>
+    </Field>
+    <Field
+      label="身份证号"
+      label-position="top"
+      name="idCard"
+      v-model="detail.idCard"
+      placeholder="请填写身份证号"
+    />
+    <Field
+      label="项目名称"
+      label-position="top"
+      name="ich"
+      v-model="detail.ich"
+      placeholder="非遗项目名称"
+    />
+    <Field
+      label="身体状况"
+      label-position="top"
+      name="health"
+      v-model="detail.health"
+      placeholder="请简要填写"
+    />
+    <Field
+      label="乙方电话"
+      label-position="top"
+      name="mobile"
+      type="tel"
+      v-model="detail.mobile"
+      placeholder="请填写联系电话"
+    />
+    <AgreementDateWriteBlock
+      :model-value="partyBSignDate"
+      hint="(以实际签署日期为准)"
+      @update:model-value="emit('update:partyBSignDate', $event)"
+    />
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import type { AgreementDetail } from '@/api/collect/AssessmentContent';
+import type { UploaderAction } from '@/components/form/Uploader';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import Height from '@/components/layout/space/Height.vue';
+import Text from '@/components/basic/Text.vue';
+import P from '@/components/typography/P.vue';
+import Field from '@/components/form/Field.vue';
+import SignatureField from '@/components/form/SignatureField.vue';
+import AgreementPrefillInline from './AgreementPrefillInline.vue';
+import AgreementDateWriteBlock, { type AgreementYmdParts } from './AgreementDateWriteBlock.vue';
+
+defineProps<{
+  detail: AgreementDetail;
+  agreementYear: number;
+  partyAStampDate: AgreementYmdParts;
+  partyBSignDate: AgreementYmdParts;
+  uploadAgreementSign: (item: UploaderAction) => () => void;
+}>();
+
+const emit = defineEmits<{
+  (e: 'update:partyAStampDate', v: AgreementYmdParts): void;
+  (e: 'update:partyBSignDate', v: AgreementYmdParts): void;
+}>();
+
+const paragraphStyle = {
+  lineHeight: '1.75',
+  marginBottom: '12rpx',
+};
+const signBlockStyle = {
+  paddingTop: '8rpx',
+};
+</script>

+ 198 - 0
src/pages/collect/assessment/components/AgreementBodyNational.vue

@@ -0,0 +1,198 @@
+<template>
+  <FlexCol :gap="'sm'">
+    <P>甲方:福建省文化和旅游厅</P>
+    <FlexRow align="center" wrap :gap="'sm'">
+      <Text font-config="p" color="text.content">乙方:</Text>
+      <AgreementPrefillInline
+        v-model="detail.partyB"
+        name="partyB"
+        placeholder="请填写乙方(传承人)姓名"
+      />
+    </FlexRow>
+  </FlexCol>
+
+  <Height :height="8" />
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    为传承弘扬中华优秀传统文化,有效保护和传承非物质文化遗产,鼓励和支持国家级非物质文化遗产代表性传承人开展传承活动,根据《中华人民共和国非物质文化遗产法》《国家级非物质文化遗产代表性传承人认定与管理办法》等有关法律法规,制定协议,并按照下列各项条款签署,甲、乙双方共同遵守。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    一、甲乙双方应当以习近平新时代中国特色社会主义思想为指导,坚持以人民为中心,弘扬社会主义核心价值观,共同保护传承非物质文化遗产,推动中华优秀传统文化创造性转化、创新性发展。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    二、甲方按照《国家级非物质文化遗产代表性传承人认定与管理办法》的要求,支持国家级非物质文化遗产代表性传承人开展传承、传播活动。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    三、甲方按照《国家级非物质文化遗产保护专项资金管理办法》的要求,落实国家给予的代表性传承人的传承补助。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">四、乙方应积极开展传承活动,培养后继人才,制定传承计划,{{ agreementYear }} 年度带徒</Text>
+    <AgreementPrefillInline
+      v-model="detail.apprentice"
+      name="apprentice"
+      number-mode
+      placeholder="人数"
+      suffix="人。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    五、乙方应妥善保存相关实物、资料情况。主动保存、提供与该项非遗项目有关的原始资料、实物,配合记录工作。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    六、乙方应主动、及时配合非遗调查,主动向文化和旅游主管部门、非遗保护中心反映非遗项目保护、传承情况和总结材料,并完成文化和旅游主管部门临时交办的非遗工作任务,提出保护的意见、建议。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">七、乙方应积极、主动参加各级政府组织的非物质文化遗产公益性宣传活动,{{ agreementYear }} 年度完成</Text>
+    <AgreementPrefillInline
+      v-model="detail.activity"
+      name="activity"
+      number-mode
+      placeholder="场次"
+      suffix="场。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    八、乙方应合理使用国家级非物质文化遗产代表性传承人补助经费,用于开展非遗项目的传习活动,做好传承补助经费使用记录、支出范围和绩效评价等,不得用于生活补助。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">九、乙方应积极、主动参加文化和旅游部组织的非物质文化遗产代表性传承人研修班,{{ agreementYear }} 年度完成</Text>
+    <AgreementPrefillInline
+      v-model="detail.course"
+      name="course"
+      number-mode
+      placeholder="场次"
+      suffix="场。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十、乙方应积极参与非物质文化遗产相关理论和实践研究、发表(出版)论文、专著等研究。
+  </Text>
+
+  <Height :height="16" />
+
+  <FlexCol :gap="'md'" :inner-style="signBlockStyle">
+    <FlexRow padding="space.sm">
+      <Text font-config="p" color="text.content" bold>甲方:福建省文化和旅游厅</Text>
+    </FlexRow>
+    <Field
+      label="负责人(代表人)"
+      label-position="top"
+      v-model="detail.partyASign"
+      placeholder="选填"
+      :show-bottom-border="true"
+    />
+    <Field
+      label="甲方电话"
+      label-position="top"
+      name="partyAMobile"
+      type="tel"
+      v-model="detail.partyAMobile"
+      placeholder="请填写甲方联系电话"
+    />
+    <AgreementDateWriteBlock
+      :model-value="partyAStampDate"
+      hint="(以实际盖章日期为准)"
+      @update:model-value="emit('update:partyAStampDate', $event)"
+    />
+
+    <Height :height="24" />
+
+    <FlexRow padding="space.sm">
+      <Text font-config="p" color="text.content" bold>乙方:{{ detail.partyB }}(签名)</Text>
+    </FlexRow>
+    <Field
+      label="乙方签名 / 说明"
+      label-position="top"
+      name="partyBSign"
+      showRightArrow
+    >
+      <Text>点击签名</Text>
+      <template #extra>
+        <SignatureField
+          v-model="detail.partyBSign"
+          placeholder=""
+          :upload="uploadAgreementSign"
+        />
+      </template>
+    </Field>
+    <Field
+      label="身份证号"
+      label-position="top"
+      name="idCard"
+      v-model="detail.idCard"
+      placeholder="请填写身份证号"
+    />
+    <Field
+      label="项目名称"
+      label-position="top"
+      name="ich"
+      v-model="detail.ich"
+      placeholder="非遗项目名称"
+    />
+    <Field
+      label="身体状况"
+      label-position="top"
+      name="health"
+      v-model="detail.health"
+      placeholder="请简要填写"
+    />
+    <Field
+      label="乙方电话"
+      label-position="top"
+      name="mobile"
+      type="tel"
+      v-model="detail.mobile"
+      placeholder="请填写联系电话"
+    />
+    <AgreementDateWriteBlock
+      :model-value="partyBSignDate"
+      hint="(以实际签署日期为准)"
+      @update:model-value="emit('update:partyBSignDate', $event)"
+    />
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import type { AgreementDetail } from '@/api/collect/AssessmentContent';
+import type { UploaderAction } from '@/components/form/Uploader';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import Height from '@/components/layout/space/Height.vue';
+import Text from '@/components/basic/Text.vue';
+import P from '@/components/typography/P.vue';
+import Field from '@/components/form/Field.vue';
+import SignatureField from '@/components/form/SignatureField.vue';
+import AgreementPrefillInline from './AgreementPrefillInline.vue';
+import AgreementDateWriteBlock, { type AgreementYmdParts } from './AgreementDateWriteBlock.vue';
+
+defineProps<{
+  detail: AgreementDetail;
+  agreementYear: number;
+  partyAStampDate: AgreementYmdParts;
+  partyBSignDate: AgreementYmdParts;
+  uploadAgreementSign: (item: UploaderAction) => () => void;
+}>();
+
+const emit = defineEmits<{
+  (e: 'update:partyAStampDate', v: AgreementYmdParts): void;
+  (e: 'update:partyBSignDate', v: AgreementYmdParts): void;
+}>();
+
+const paragraphStyle = {
+  lineHeight: '1.75',
+  marginBottom: '12rpx',
+};
+const signBlockStyle = {
+  paddingTop: '8rpx',
+};
+</script>

+ 198 - 0
src/pages/collect/assessment/components/AgreementBodyProvincial.vue

@@ -0,0 +1,198 @@
+<template>
+  <FlexCol :gap="'sm'">
+    <P>甲方:厦门市文化和旅游局</P>
+    <FlexRow align="center" wrap :gap="'sm'">
+      <Text font-config="p" color="text.content">乙方:</Text>
+      <AgreementPrefillInline
+        v-model="detail.partyB"
+        name="partyB"
+        placeholder="请填写乙方(传承人)姓名"
+      />
+    </FlexRow>
+  </FlexCol>
+
+  <Height :height="8" />
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    为传承弘扬中华优秀传统文化,有效保护和传承非物质文化遗产,鼓励和支持省级非物质文化遗产代表性传承人开展传承活动,根据《福建省非物质文化遗产条例》《福建省非物质文化遗产代表性传承人认定与管理办法》等有关法律法规,制定协议,并按照下列各项条款签署,甲、乙双方共同遵守。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    一、甲乙双方应当以习近平新时代中国特色社会主义思想为指导,坚持以人民为中心,弘扬社会主义核心价值观,共同保护传承非物质文化遗产,推动中华优秀传统文化创造性转化、创新性发展。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    二、甲方按照《福建省非物质文化遗产代表性传承人认定与管理办法》的要求,支持省级非物质文化遗产代表性传承人开展传承、传播活动。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    三、甲方按照《福建省非物质文化遗产保护与传承专项资金管理办法》的要求,落实省文化和旅游厅给予的代表性传承人的传承补助。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">四、乙方应积极开展传承活动,培养后继人才,制定传承计划,{{ agreementYear }} 年度带徒</Text>
+    <AgreementPrefillInline
+      v-model="detail.apprentice"
+      name="apprentice"
+      number-mode
+      placeholder="人数"
+      suffix="人。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    五、乙方应妥善保存相关实物、资料情况。主动保存、提供与该项非遗项目有关的原始资料、实物,配合记录工作。
+  </Text>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    六、乙方应主动、及时配合非遗调查,主动向文化和旅游主管部门、非遗保护中心反映非遗项目保护、传承情况和总结材料,并完成文化和旅游主管部门临时交办的非遗工作任务,提出保护的意见、建议。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">七、乙方应积极、主动参加各级政府组织的非物质文化遗产公益性宣传活动,{{ agreementYear }} 年度完成</Text>
+    <AgreementPrefillInline
+      v-model="detail.activity"
+      name="activity"
+      number-mode
+      placeholder="场次"
+      suffix="场。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    八、乙方应合理使用省级非物质文化遗产代表性传承人补助经费,用于开展非遗项目的传习活动,做好传承补助经费使用记录、支出范围和绩效评价等,不得用于生活补助。
+  </Text>
+
+  <FlexRow align="center" wrap :gap="'sm'" :inner-style="paragraphStyle">
+    <Text font-config="p" color="text.content">九、乙方应积极、主动参加文化和旅游部组织的非物质文化遗产代表性传承人研修班,{{ agreementYear }} 年度完成</Text>
+    <AgreementPrefillInline
+      v-model="detail.course"
+      name="course"
+      number-mode
+      placeholder="场次"
+      suffix="场。"
+    />
+  </FlexRow>
+
+  <Text font-config="p" color="text.content" :inner-style="paragraphStyle">
+    十、乙方应积极参与非物质文化遗产相关理论和实践研究、发表(出版)论文、专著等研究。
+  </Text>
+
+  <Height :height="16" />
+
+  <FlexCol :gap="'md'" :inner-style="signBlockStyle">
+    <FlexRow padding="space.sm">
+      <Text font-config="p" color="text.content" bold>甲方:厦门市文化和旅游局</Text>
+    </FlexRow>
+    <Field
+      label="负责人(代表人)"
+      label-position="top"
+      v-model="detail.partyASign"
+      placeholder="选填"
+      :show-bottom-border="true"
+    />
+    <Field
+      label="甲方电话"
+      label-position="top"
+      name="partyAMobile"
+      type="tel"
+      v-model="detail.partyAMobile"
+      placeholder="请填写甲方联系电话"
+    />
+    <AgreementDateWriteBlock
+      :model-value="partyAStampDate"
+      hint="(以实际盖章日期为准)"
+      @update:model-value="emit('update:partyAStampDate', $event)"
+    />
+
+    <Height :height="24" />
+
+    <FlexRow padding="space.sm">
+      <Text font-config="p" color="text.content" bold>乙方:{{ detail.partyB }}(签名)</Text>
+    </FlexRow>
+    <Field
+      label="乙方签名 / 说明"
+      label-position="top"
+      name="partyBSign"
+      showRightArrow
+    >
+      <Text>点击签名</Text>
+      <template #extra>
+        <SignatureField
+          v-model="detail.partyBSign"
+          placeholder=""
+          :upload="uploadAgreementSign"
+        />
+      </template>
+    </Field>
+    <Field
+      label="身份证号"
+      label-position="top"
+      name="idCard"
+      v-model="detail.idCard"
+      placeholder="请填写身份证号"
+    />
+    <Field
+      label="项目名称"
+      label-position="top"
+      name="ich"
+      v-model="detail.ich"
+      placeholder="非遗项目名称"
+    />
+    <Field
+      label="身体状况"
+      label-position="top"
+      name="health"
+      v-model="detail.health"
+      placeholder="请简要填写"
+    />
+    <Field
+      label="乙方电话"
+      label-position="top"
+      name="mobile"
+      type="tel"
+      v-model="detail.mobile"
+      placeholder="请填写联系电话"
+    />
+    <AgreementDateWriteBlock
+      :model-value="partyBSignDate"
+      hint="(以实际签署日期为准)"
+      @update:model-value="emit('update:partyBSignDate', $event)"
+    />
+  </FlexCol>
+</template>
+
+<script setup lang="ts">
+import type { AgreementDetail } from '@/api/collect/AssessmentContent';
+import type { UploaderAction } from '@/components/form/Uploader';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import Height from '@/components/layout/space/Height.vue';
+import Text from '@/components/basic/Text.vue';
+import P from '@/components/typography/P.vue';
+import Field from '@/components/form/Field.vue';
+import SignatureField from '@/components/form/SignatureField.vue';
+import AgreementPrefillInline from './AgreementPrefillInline.vue';
+import AgreementDateWriteBlock, { type AgreementYmdParts } from './AgreementDateWriteBlock.vue';
+
+defineProps<{
+  detail: AgreementDetail;
+  agreementYear: number;
+  partyAStampDate: AgreementYmdParts;
+  partyBSignDate: AgreementYmdParts;
+  uploadAgreementSign: (item: UploaderAction) => () => void;
+}>();
+
+const emit = defineEmits<{
+  (e: 'update:partyAStampDate', v: AgreementYmdParts): void;
+  (e: 'update:partyBSignDate', v: AgreementYmdParts): void;
+}>();
+
+const paragraphStyle = {
+  lineHeight: '1.75',
+  marginBottom: '12rpx',
+};
+const signBlockStyle = {
+  paddingTop: '8rpx',
+};
+</script>

+ 10 - 2
src/pages/collect/assessment/evaluation-form.vue

@@ -140,6 +140,12 @@ const formOptions : IDynamicFormOptions = {
           additionalProps: { placeholder: '请输入家庭住址' },
         },
         {
+          label: '获评时间',
+          name: 'awardTime',
+          type: 'date',
+          additionalProps: { placeholder: '请选择获评时间' },
+        },
+        {
           label: '自评报告',
           name: 'content',
           type: 'richtext',
@@ -154,7 +160,7 @@ const formOptions : IDynamicFormOptions = {
     {
       type: 'flat-group',
       label: '传承人自查评估',
-      name: 'selfAssessmentGroup',
+      name: 'selfAssessmentGroup2',
       childrenColProps: { span: 24 },
       children: [
         {
@@ -217,6 +223,7 @@ const formOptions : IDynamicFormOptions = {
     content: [{ required: true, message: '请填写自评报告' }],
     self: [{ required: true, message: '请选择自我评估' }],
     sign: [{ required: true, message: '请传承人签名' }],
+    awardTime: [{ required: true, message: '请选择获评时间' }],
   },
 };
 
@@ -242,7 +249,8 @@ async function loadBasicInfo() {
 }
 async function loadCheckItems() {
   assertNotNull(currentForm.value, 'currentForm is null');
-  checkItemList.value = await AssessmentContentApi.getCheckItems(Number(currentForm.value.level));
+  checkItemList.value = await AssessmentContentApi.getCheckItems(0);
+  checkItemList.value.concat(await AssessmentContentApi.getCheckItems(Number(currentForm.value.level)));
   currentFormCheckItems.value = currentForm.value.checkItems.concat();
 }