Quellcode durchsuchen

📦 基础页面完成

快乐的梦鱼 vor 2 Wochen
Ursprung
Commit
1f22c13f08

+ 2 - 0
src/api/CommonContent.ts

@@ -321,6 +321,8 @@ export class CommonContentApi extends AppServerRequestModule<DataModel> {
     type?: number,
     withself?: boolean,
   ) {
+    if (type === 1)
+      withself = true;
     return (this.get('/content/category/getCategoryList', '获取分类列表', {
       type,
       is_tree: false,

+ 24 - 2
src/api/inheritor/InheritorContent.ts

@@ -13,6 +13,7 @@ export class CommonInfo<T extends DataModel> extends DataModel<T> {
       keywords: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
       images: { clientSide: 'array', serverSide: 'string' },
       expandInfo: { serverSide: 'undefined' },
+      region: { clientSide: 'number', serverSide: 'number' },
     };
   }
 
@@ -260,7 +261,24 @@ export class InheritorExpandInfo extends DataModel<InheritorExpandInfo> {
     super(InheritorExpandInfo, "非遗项目信息");
     this.setNameMapperCase('Camel', 'Snake');
     this._convertTable = {
-      
+      gender: { clientSide: 'number', serverSide: 'string' },
+      level: { clientSide: 'number', serverSide: 'string' },
+      batch: { clientSide: 'number', serverSide: 'string' },
+      photosJson: [
+        { 
+          clientSide: 'object', 
+          clientSideChildDataModel: {
+            convertTable: {},
+          }, 
+          serverSide: 'string' 
+        },
+        {
+          clientSide: 'addDefaultValue',
+          clientSideParam: {
+            defaultValue: [],
+          }
+        },
+      ],
     };
     this._convertKeyType = (key, direction) => {
       if (key.endsWith('Text') || key.endsWith('_text')) {
@@ -336,7 +354,7 @@ export class SeminarExpandInfo extends DataModel<SeminarExpandInfo> {
     super(SeminarExpandInfo, "非遗项目信息");
     this.setNameMapperCase('Camel', 'Snake');
     this._convertTable = {
-      
+      lonlat: { serverSide: 'undefined' },
     };
     this._convertKeyType = (key, direction) => {
       if (key.endsWith('Text') || key.endsWith('_text')) {
@@ -347,11 +365,15 @@ export class SeminarExpandInfo extends DataModel<SeminarExpandInfo> {
       }
     };
     this._afterSolveServer = (self) => {
+      self.lonlat = [ self.longitude, self.latitude ];
     };
     this._afterSolveClient = (data) => {
+      data.longitude = this.lonlat[0];
+      data.latitude = this.lonlat[1];
     };
   }
   modelId = 17;
+  lonlat = [] as (number|string)[];
 }
 
 export class InheritorContentApi extends AppServerRequestModule<DataModel> {

+ 1 - 2
src/components/parts/EmptyToRecord.vue

@@ -25,8 +25,7 @@ defineProps({
   </a-result>
   <div v-else>
     <a-alert
-      :message="`${title}信息`"
-      :description="`您已提交${title}信息,点击这里可以修改信息`"
+      :message="`点击这里可以修改 ${title} 信息`"
       type="info"
       show-icon
     >

+ 86 - 20
src/pages/forms/form.vue

@@ -10,26 +10,46 @@
         </div>
         <a-spin v-if="loadingData" />
         <template v-else>
-          <DynamicForm
-            ref="form"
-            :model="(formModel as any)" 
-            :options="formOptions"
-          />
-          <a-button 
-            type="primary"
-            block 
-            :loading="loading" class="mt-3" 
-            @click="handleSubmit"
-          >
-            提交
-          </a-button>
+          
+          <a-tabs centered>
+            <a-tab-pane key="1" tab="基础信息">
+              <DynamicForm
+                ref="form"
+                :model="(formModel as any)" 
+                :options="formOptions"
+              />
+              <a-button 
+                type="primary"
+                block 
+                :loading="loading" class="mt-3" 
+                @click="handleSubmitBase"
+              >
+                提交
+              </a-button>
+            </a-tab-pane>
+            <a-tab-pane key="2" tab="扩展信息">
+              <DynamicForm
+                ref="formExtend"
+                :model="(extendFormModel as any)" 
+                :options="extendFormOptions"
+              />
+              <a-button 
+                type="primary"
+                block 
+                :loading="loading" class="mt-3" 
+                @click="handleSubmitExtend"
+              >
+                提交
+              </a-button>
+            </a-tab-pane>
+          </a-tabs>
         </template>
       </div>
     </section>
   </div>
 </template>
 
-<script setup lang="ts" generic="T extends DataModel">
+<script setup lang="ts" generic="T extends DataModel, U extends DataModel">
 import { onMounted, ref, toRefs, type PropType } from 'vue';
 import { useRouter } from 'vue-router';
 import { useWindowOnUnLoadConfirm } from '@/composeable/WindowOnUnLoad';
@@ -41,7 +61,7 @@ import type { DataModel } from '@imengyu/js-request-transform';
 const props = defineProps({
   title: {
     type: String,
-    default: '项目申报'
+    default: '非遗数字化资源采集'
   },
   formModel: {
     type: Object as PropType<T>,
@@ -51,18 +71,31 @@ const props = defineProps({
     type: Object as PropType<IDynamicFormOptions>,
     required: true
   },
+  extendFormModel: {
+    type: Object as PropType<U>,
+    required: true
+  },
+  extendFormOptions: {
+    type: Object as PropType<IDynamicFormOptions>,
+    required: true
+  },
   load: {
-    type: Function as PropType<() => Promise<T|undefined|void>>,
+    type: Function as PropType<() => Promise<void>>,
     default: () => Promise.resolve()
   },
   save: {
     type: Function as PropType<(model: T) => Promise<void>>,
     default: () => Promise.resolve()
-  }
+  },
+  saveExtend: {
+    type: Function as PropType<(model: U) => Promise<void>>,
+    default: () => Promise.resolve()
+  },
 })
 
 const { formModel, formOptions, load } = toRefs(props);
-const form = ref<IDynamicFormRef>();
+const formBase = ref<IDynamicFormRef>();
+const formExtend = ref<IDynamicFormRef>();
 
 const router = useRouter();
 const loading = ref(false);
@@ -70,10 +103,10 @@ const loadingData = ref(false);
 
 useWindowOnUnLoadConfirm();
 
-async function handleSubmit() {
+async function handleSubmitBase() {
   loading.value = true;
 
-  const ref = (form.value?.getFormRef() as FormInstance);
+  const ref = (formBase.value?.getFormRef() as FormInstance);
   try {
     await ref.validate();
   } catch (e) {
@@ -102,6 +135,39 @@ async function handleSubmit() {
     loading.value = false;
   }
 }
+async function handleSubmitExtend() {
+  loading.value = true;
+
+  const ref = (formExtend.value?.getFormRef() as FormInstance);
+  try {
+    await ref.validate();
+  } catch (e) {
+    message.warn('请填写完整信息');
+    loading.value = false;
+    if ((e as any).errorFields)
+      ref.scrollToField((e as any).errorFields[0].name, { block: 'center' })
+    return;
+  }
+  try {
+    const result = await InheritorContent.saveExpandInfo(formModel.value);
+    await props.save(formModel.value);
+    Modal.success({
+      title: '提交成功',
+      content: result.message,
+      onOk() {
+        router.back();
+      },
+    });
+  } catch (error) {
+    Modal.error({
+      title: '提交失败',
+      content: '' + error,
+    });
+  } finally {
+    loading.value = false;
+  }
+}
+
 async function loadData() {
   loadingData.value = true;
   try {

+ 64 - 58
src/pages/forms/ich.vue

@@ -3,8 +3,9 @@
   <Form 
     :formModel="formModel"
     :formOptions="formOptions"
+    :extendFormModel="formExtendModel"
+    :extendFormOptions="formExtendOptions"
     :load="loadData"
-    :save="saveData"
   />
 </template>
 
@@ -12,7 +13,7 @@
 import { ref, type Ref } from 'vue';
 import { useImageSimpleUploadCo } from '@/common/upload/ImageUploadCo';
 import Form from './form.vue';
-import InheritorContent, { IchInfo } from '@/api/inheritor/InheritorContent';
+import InheritorContent, { IchExpandInfo, IchInfo } from '@/api/inheritor/InheritorContent';
 import CommonContent from '@/api/CommonContent';
 import type { IDynamicFormOptions } from '@imengyu/vue-dynamic-form';
 import type { SelectProps } from 'ant-design-vue';
@@ -226,61 +227,8 @@ const formOptions = ref<IDynamicFormOptions>({
         },
       ]
     },
-    {
-      type: 'group-object', label: '扩展信息', name: 'expandInfo',
-      childrenColProps: { span: 24 },
-      children: [
-        { 
-          type: 'select-id', label: '保护级别', name: 'protectLevel', 
-          additionalProps: { 
-            placeholder: '请选择保护级别', 
-            loadData: async () => (await CommonContent.getCategoryList(171)).map(p => ({ label: p.title, value: p.id, raw: p })) 
-          } 
-        },
-        { type: 'text', label: '其他名称', name: 'otherNames', additionalProps: { placeholder: '请输入其他名称' } },
-        { type: 'text', label: '实践方式', name: 'practice', additionalProps: { placeholder: '请输入实践方式' } },
-        { type: 'text', label: '表现形式', name: 'expression', additionalProps: { placeholder: '请输入表现形式' } },
-        { type: 'text', label: '遗产持有者', name: 'holders', additionalProps: { placeholder: '请输入遗产持有者' } },
-        { type: 'text', label: '列入名录时间', name: 'joinday', additionalProps: { placeholder: '请选择列入名录时间' } },
-        { type: 'text', label: '形成时间', name: 'formation', additionalProps: { placeholder: '请选择形成时间' } },
-        { type: 'text', label: '分布区域', name: 'area', additionalProps: { placeholder: '请输入分布区域' } },
-        { type: 'text', label: '源流', name: 'origin', additionalProps: { placeholder: '请输入源流' } },
-        { type: 'text', label: '主要特点', name: 'feature', additionalProps: { placeholder: '请输入主要特点' } },
-        { type: 'text', label: '重要功能', name: 'functions', additionalProps: { placeholder: '请输入重要功能' } },
-        { type: 'text', label: '代表作品', name: 'works', additionalProps: { placeholder: '请输入代表作品' } },
-        { type: 'text', label: '保护单位', name: 'unit', additionalProps: { placeholder: '请输入保护单位' } },
-        { type: 'text', label: '保护情况', name: 'protect', additionalProps: { placeholder: '请输入保护情况' } },
-        { type: 'text-area', label: '综合概述', name: 'overview', additionalProps: { placeholder: '请输入综合概述' } },
-        { type: 'text', label: '代表人物', name: 'figures', additionalProps: { placeholder: '请输入代表人物' } },
-        { type: 'text', label: '传承群体', name: 'group', additionalProps: { placeholder: '请输入传承群体' } },
-        { type: 'text', label: '传承方式', name: 'inherit', additionalProps: { placeholder: '请输入传承方式' } },
-        { type: 'text', label: '发展现状', name: 'develop', additionalProps: { placeholder: '请输入发展现状' } },
-        { type: 'text', label: '相关民俗', name: 'customs', additionalProps: { placeholder: '请输入相关民俗' } },
-        { type: 'text', label: '相关信仰', name: 'religion', additionalProps: { placeholder: '请输入相关信仰' } },
-        { type: 'text', label: '文化空间', name: 'space', additionalProps: { placeholder: '请输入文化空间' } },
-        { type: 'text', label: '自然环境', name: 'natural', additionalProps: { placeholder: '请输入自然环境' } },
-        { type: 'text', label: '社会环境', name: 'social', additionalProps: { placeholder: '请输入社会环境' } },
-        { type: 'text', label: '历史沿革', name: 'history', additionalProps: { placeholder: '请输入历史沿革' } },
-        { type: 'text', label: '续存状态', name: 'existence', additionalProps: { placeholder: '请输入续存状态' } },
-        { type: 'text', label: '价值', name: 'meaning', additionalProps: { placeholder: '请输入价值' } },
-        { type: 'text', label: '相关实物', name: 'prop', additionalProps: { placeholder: '请输入相关实物' } },
-        { type: 'text', label: '其他基本情况', name: 'other', additionalProps: { placeholder: '请输入其他基本情况' } },
-        { type: 'mulit-image', label: '相关图片', name: 'images', additionalProps: { placeholder: '请上传相关图片', uploadCo: useImageSimpleUploadCo() } },
-        { type: 'text', label: '相关习俗', name: 'folkCulture', additionalProps: { placeholder: '请输入相关习俗' } },
-        { type: 'text', label: '文物古迹', name: 'culturalRelic', additionalProps: { placeholder: '请输入文物古迹' } },
-        { type: 'text', label: '文献资料', name: 'literature', additionalProps: { placeholder: '请输入文献资料' } },
-        { type: 'text', label: '组织机构', name: 'organization', additionalProps: { placeholder: '请输入组织机构' } },
-        { type: 'text-area', label: '项目描述', name: 'description', additionalProps: { placeholder: '请输入项目描述' } },
-        { type: 'text-area', label: '简介', name: 'desc', additionalProps: { placeholder: '请输入简介' } },
-        { type: 'text', label: '申报地区', name: 'declarationRegion', additionalProps: { placeholder: '请输入申报地区' } },
-        { type: 'text', label: '流行地区', name: 'popularRegion', additionalProps: { placeholder: '请输入流行地区' } },
-      ]
-    },
   ],
   formRules: {
-    expandInfo: {
-      protectLevel: [{ required: true, message: '请选择保护级别' }],
-    },
     title: [{ required: true, message: '请输入标题' }],
     region: [{ required: true, message: '请选择地区' }],
     type: [{ required: true, message: '请选择类型' }],
@@ -291,12 +239,70 @@ const formOptions = ref<IDynamicFormOptions>({
   }
 });
 
+const formExtendModel = ref(new IchExpandInfo()) as Ref<IchExpandInfo>;
+const formExtendOptions = ref<IDynamicFormOptions>({
+  formLabelCol: { span: 6 },
+  formWrapperCol: { span: 24 },
+  formAdditionaProps: {
+    layout: 'vertical',
+    scrollToFirstError: true,
+  },
+  formNestNameGenerateType: 'array',
+  formItems: [
+    { 
+      type: 'select-id', label: '保护级别', name: 'protectLevel', 
+      additionalProps: { 
+        placeholder: '请选择保护级别', 
+        loadData: async () => (await CommonContent.getCategoryList(171)).map(p => ({ label: p.title, value: p.id, raw: p })) 
+      } 
+    },
+    { type: 'text', label: '其他名称', name: 'otherNames', additionalProps: { placeholder: '请输入其他名称' } },
+    { type: 'text', label: '实践方式', name: 'practice', additionalProps: { placeholder: '请输入实践方式' } },
+    { type: 'text', label: '表现形式', name: 'expression', additionalProps: { placeholder: '请输入表现形式' } },
+    { type: 'text', label: '遗产持有者', name: 'holders', additionalProps: { placeholder: '请输入遗产持有者' } },
+    { type: 'text', label: '列入名录时间', name: 'joinday', additionalProps: { placeholder: '请选择列入名录时间' } },
+    { type: 'text', label: '形成时间', name: 'formation', additionalProps: { placeholder: '请选择形成时间' } },
+    { type: 'text', label: '分布区域', name: 'area', additionalProps: { placeholder: '请输入分布区域' } },
+    { type: 'text', label: '源流', name: 'origin', additionalProps: { placeholder: '请输入源流' } },
+    { type: 'text', label: '主要特点', name: 'feature', additionalProps: { placeholder: '请输入主要特点' } },
+    { type: 'text', label: '重要功能', name: 'functions', additionalProps: { placeholder: '请输入重要功能' } },
+    { type: 'text', label: '代表作品', name: 'works', additionalProps: { placeholder: '请输入代表作品' } },
+    { type: 'text', label: '保护单位', name: 'unit', additionalProps: { placeholder: '请输入保护单位' } },
+    { type: 'text', label: '保护情况', name: 'protect', additionalProps: { placeholder: '请输入保护情况' } },
+    { type: 'text-area', label: '综合概述', name: 'overview', additionalProps: { placeholder: '请输入综合概述' } },
+    { type: 'text', label: '代表人物', name: 'figures', additionalProps: { placeholder: '请输入代表人物' } },
+    { type: 'text', label: '传承群体', name: 'group', additionalProps: { placeholder: '请输入传承群体' } },
+    { type: 'text', label: '传承方式', name: 'inherit', additionalProps: { placeholder: '请输入传承方式' } },
+    { type: 'text', label: '发展现状', name: 'develop', additionalProps: { placeholder: '请输入发展现状' } },
+    { type: 'text', label: '相关民俗', name: 'customs', additionalProps: { placeholder: '请输入相关民俗' } },
+    { type: 'text', label: '相关信仰', name: 'religion', additionalProps: { placeholder: '请输入相关信仰' } },
+    { type: 'text', label: '文化空间', name: 'space', additionalProps: { placeholder: '请输入文化空间' } },
+    { type: 'text', label: '自然环境', name: 'natural', additionalProps: { placeholder: '请输入自然环境' } },
+    { type: 'text', label: '社会环境', name: 'social', additionalProps: { placeholder: '请输入社会环境' } },
+    { type: 'text', label: '历史沿革', name: 'history', additionalProps: { placeholder: '请输入历史沿革' } },
+    { type: 'text', label: '续存状态', name: 'existence', additionalProps: { placeholder: '请输入续存状态' } },
+    { type: 'text', label: '价值', name: 'meaning', additionalProps: { placeholder: '请输入价值' } },
+    { type: 'text', label: '相关实物', name: 'prop', additionalProps: { placeholder: '请输入相关实物' } },
+    { type: 'text', label: '其他基本情况', name: 'other', additionalProps: { placeholder: '请输入其他基本情况' } },
+    { type: 'mulit-image', label: '相关图片', name: 'images', additionalProps: { placeholder: '请上传相关图片', uploadCo: useImageSimpleUploadCo() } },
+    { type: 'text', label: '相关习俗', name: 'folkCulture', additionalProps: { placeholder: '请输入相关习俗' } },
+    { type: 'text', label: '文物古迹', name: 'culturalRelic', additionalProps: { placeholder: '请输入文物古迹' } },
+    { type: 'text', label: '文献资料', name: 'literature', additionalProps: { placeholder: '请输入文献资料' } },
+    { type: 'text', label: '组织机构', name: 'organization', additionalProps: { placeholder: '请输入组织机构' } },
+    { type: 'text-area', label: '项目描述', name: 'description', additionalProps: { placeholder: '请输入项目描述' } },
+    { type: 'text-area', label: '简介', name: 'desc', additionalProps: { placeholder: '请输入简介' } },
+    { type: 'text', label: '申报地区', name: 'declarationRegion', additionalProps: { placeholder: '请输入申报地区' } },
+    { type: 'text', label: '流行地区', name: 'popularRegion', additionalProps: { placeholder: '请输入流行地区' } },
+  ],
+  formRules: { 
+    protectLevel: [{ required: true, message: '请选择保护级别' }],
+  }
+});
+
 async function loadData() {
   formModel.value = await InheritorContent.getIchInfo();
   formModel.value.expandInfo = await InheritorContent.getIchExpandInfo();
-}
-async function saveData(model: IchInfo) {
-  await InheritorContent.saveExpandInfo(model.expandInfo);
+  formExtendModel.value = formModel.value.expandInfo;
 }
 
 </script>

+ 369 - 15
src/pages/forms/inheritor.vue

@@ -3,8 +3,9 @@
   <Form 
     :formModel="formModel"
     :formOptions="formOptions"
+    :extendFormModel="formExtendModel"
+    :extendFormOptions="formExtendOptions"
     :load="loadData"
-    :save="saveData"
   />
 </template>
 
@@ -12,7 +13,7 @@
 import { ref, type Ref } from 'vue';
 import { useImageSimpleUploadCo } from '@/common/upload/ImageUploadCo';
 import Form from './form.vue';
-import InheritorContent, { InheritorInfo } from '@/api/inheritor/InheritorContent';
+import InheritorContent, { InheritorExpandInfo, InheritorInfo } from '@/api/inheritor/InheritorContent';
 import CommonContent from '@/api/CommonContent';
 import type { IDynamicFormOptions } from '@imengyu/vue-dynamic-form';
 import type { SelectProps } from 'ant-design-vue';
@@ -212,18 +213,8 @@ const formOptions = ref<IDynamicFormOptions>({
         },
       ]
     },
-    {
-      type: 'group-object', label: '扩展信息', name: 'expandInfo',
-      childrenColProps: { span: 24 },
-      children: [
-        //在这里添加表单项目
-      ]
-    },
   ],
   formRules: {
-    expandInfo: {
-      protectLevel: [{ required: true, message: '请选择保护级别' }],
-    },
     title: [{ required: true, message: '请输入标题' }],
     region: [{ required: true, message: '请选 择地区' }],
     type: [{ required: true, message: '请选择类型' }],
@@ -235,12 +226,375 @@ const formOptions = ref<IDynamicFormOptions>({
   }
 });
 
+const formExtendModel = ref(new InheritorExpandInfo()) as Ref<InheritorExpandInfo>;
+const formExtendOptions = ref<IDynamicFormOptions>({
+  formLabelCol: { span: 6 },
+  formWrapperCol: { span: 24 },
+  formAdditionaProps: {
+    layout: 'vertical',
+    scrollToFirstError: true,
+  },
+  formNestNameGenerateType: 'array',
+  formItems: [
+    {
+      label: '传承人',
+      name: 'name',
+      type: 'text',
+      additionalProps: { placeholder: '请输入传承人姓名' }
+    },
+    {
+      label: '性别',
+      name: 'gender',
+      type: 'select',
+      additionalProps: {
+        placeholder: '请选择性别',
+        options: [
+          { text: '女', value: 0 },
+          { text: '男', value: 1 },
+          { text: '未知', value: 2 }
+        ]
+      }
+    },
+    {
+      label: '证件照',
+      name: 'idPhoto',
+      type: 'single-image',
+      additionalProps: {
+        placeholder: '请上传证件照',
+        uploadCo: useImageSimpleUploadCo()
+      } as UploadImageFormItemProps
+    },
+    {
+      label: '民族',
+      name: 'nation',
+      type: 'text',
+      additionalProps: { placeholder: '请输入民族' }
+    },
+    {
+      label: '籍贯',
+      name: 'nativePlace',
+      type: 'text',
+      additionalProps: { placeholder: '请输入籍贯' }
+    },
+    {
+      label: '通信地址',
+      name: 'address',
+      type: 'text',
+      additionalProps: { placeholder: '请输入通信地址' }
+    },
+    {
+      label: '联系方式',
+      name: 'mobile',
+      type: 'text',
+      additionalProps: { placeholder: '请输入联系方式' }
+    },
+    {
+      label: '身份证号',
+      name: 'idCard',
+      type: 'text',
+      additionalProps: { placeholder: '请输入身份证号' }
+    },
+    {
+      label: '文化程度',
+      name: 'education',
+      type: 'select-id',
+      additionalProps: {
+        placeholder: '请选择文化程度',
+        loadData: async () => (await CommonContent.getCategoryList(10)).map(p => ({ label: p.title, value: p.id, raw: p }))
+      }
+    },
+    {
+      label: '代表性传承人级别',
+      name: 'level',
+      type: 'select-id',
+      additionalProps: {
+        placeholder: '请选择传承人级别',
+        loadData: async () => (await CommonContent.getCategoryList(2)).map(p => ({ label: p.title, value: p.id, raw: p }))
+      }
+    },
+    {
+      label: '类型',
+      name: 'type',
+      type: 'select-id',
+      additionalProps: {
+        placeholder: '请选择类型',
+        loadData: async () => (await CommonContent.getCategoryList(4)).map(p => ({ label: p.title, value: p.id, raw: p }))
+      }
+    },
+    {
+      label: '批次',
+      name: 'batch',
+      type: 'select-id',
+      additionalProps: {
+        placeholder: '请选择批次',
+        loadData: async () => (await CommonContent.getCategoryList(289)).map(p => ({ label: p.title, value: p.id, raw: p }))
+      }
+    },
+    {
+      label: '地区',
+      name: 'region',
+      type: 'select-id',
+      additionalProps: {
+        placeholder: '请选择地区',
+        loadData: async () => (await CommonContent.getCategoryList(1)).map(p => ({ label: p.title, value: p.id, raw: p }))
+      }
+    },
+    {
+      label: '项目名称',
+      name: 'ichName',
+      type: 'text',
+      additionalProps: { placeholder: '请输入项目名称' }
+    },
+    {
+      label: '别名',
+      name: 'aliasName',
+      type: 'text',
+      additionalProps: { placeholder: '请输入别名' }
+    },
+    {
+      label: '艺名',
+      name: 'stageName',
+      type: 'text',
+      additionalProps: { placeholder: '请输入艺名' }
+    },
+    {
+      label: '出生',
+      name: 'birth',
+      type: 'date',
+      additionalProps: { placeholder: '请选择出生日期' }
+    },
+    {
+      label: '逝世',
+      name: 'death',
+      type: 'date',
+      additionalProps: { placeholder: '请选择逝世日期' }
+    },
+    {
+      label: '出生地',
+      name: 'birthplace',
+      type: 'text',
+      additionalProps: { placeholder: '请输入出生地' }
+    },
+    {
+      label: '供职单位',
+      name: 'unit',
+      type: 'text',
+      additionalProps: { placeholder: '请输入供职单位' }
+    },
+    {
+      label: '职业',
+      name: 'job',
+      type: 'text',
+      additionalProps: { placeholder: '请输入职业' }
+    },
+    {
+      label: '职务职称',
+      name: 'jobTitle',
+      type: 'text',
+      additionalProps: { placeholder: '请输入职务职称' }
+    },
+    {
+      label: '非遗年收入',
+      name: 'ichAnnualIncome',
+      type: 'text',
+      additionalProps: { placeholder: '请输入非遗年收入' }
+    },
+    {
+      label: '从艺时间',
+      name: 'artisticYears',
+      type: 'number',
+      additionalProps: { placeholder: '请输入从艺时间' }
+    },
+    {
+      label: '学习与实践经历',
+      name: 'experience',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入学习与实践经历' }
+    },
+    {
+      label: '技艺特点',
+      name: 'feature',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入技艺特点' }
+    },
+    {
+      label: '代表作品及介绍',
+      name: 'workDesc',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入代表作品及介绍' }
+    },
+    {
+      label: '所属流派',
+      name: 'sect',
+      type: 'text',
+      additionalProps: { placeholder: '请输入所属流派' }
+    },
+    {
+      label: '成就和影响',
+      name: 'achievement',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入成就和影响' }
+    },
+    {
+      label: '重要影响人物和事件',
+      name: 'influence',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入重要影响人物和事件' }
+    },
+    {
+      label: '传承方式',
+      name: 'method',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入传承方式' }
+    },
+    {
+      label: '传承谱系',
+      name: 'pedigree',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入传承谱系' }
+    },
+    {
+      label: '授徒传艺情况',
+      name: 'teach',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入授徒传艺情况' }
+    },
+    {
+      label: '对项目的认识、评价和建议',
+      name: 'recognize',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入对项目的认识、评价和建议' }
+    },
+    {
+      label: '其他需说明的情况',
+      name: 'other',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入其他需说明的情况' }
+    },
+    {
+      label: '图片资源',
+      name: 'images',
+      type: 'mulit-image',
+      additionalProps: {
+        placeholder: '请上传图片资源',
+        uploadCo: useImageSimpleUploadCo()
+      }
+    },
+    {
+      label: '荣誉称号',
+      name: 'honoraryTitle',
+      type: 'text',
+      additionalProps: { placeholder: '请输入荣誉称号' }
+    },
+    {
+      label: '当前级别通过时间',
+      name: 'cityInheritorDay',
+      type: 'date',
+      additionalProps: { placeholder: '请选择当前级别通过时间' }
+    },
+    {
+      label: '工作单位',
+      name: 'jobUnit',
+      type: 'text',
+      additionalProps: { placeholder: '请输入工作单位' }
+    },
+    {
+      label: '邮编',
+      name: 'postcode',
+      type: 'text',
+      additionalProps: { placeholder: '请输入邮编' }
+    },
+    {
+      label: '电子信箱',
+      name: 'email',
+      type: 'text',
+      additionalProps: { placeholder: '请输入电子信箱' }
+    },
+    {
+      label: '个人简历',
+      name: 'personalCv',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入个人简历' }
+    },
+    {
+      label: '参与社会公益活动情况',
+      name: 'activity',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入参与社会公益活动情况(展演,宣传,讲座等)' }
+    },
+    {
+      label: '持有该项目的相关实物、资料情况',
+      name: 'information',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入持有该项目的相关实物、资料情况' }
+    },
+    {
+      label: '为该项目保护传承所做的其他贡献',
+      name: 'contribute',
+      type: 'text-area',
+      additionalProps: { placeholder: '请输入为该项目保护传承所做的其他贡献' }
+    },
+    { 
+      type: 'array-object', label: '照片、著作权人及手机号、照片说明', name: 'photosJson',
+      formProps: {
+        center: false,
+      },
+      additionalProps: {
+        direction: 'horizontal'
+      },
+      newChildrenObject: (arrayNow) => ({
+        desc: `代表性图片${arrayNow.length+1}`,
+        url: '',
+        from: '',
+        mobile: '',
+      }),
+      children: [
+        { type: 'text', label: '著作权人', name: 'author', additionalProps: { placeholder: '请输入著作权人' } },
+        { type: 'text', label: '手机号', name: 'mobile', additionalProps: { placeholder: '请输入手机号' } },
+        { type: 'text', label: '照片说明', name: 'desc', additionalProps: { placeholder: '请输入照片说明' } },
+        { 
+          label: '照片', name: 'url', type: 'single-image',
+          additionalProps: {
+            name: 'file',
+            placeholder: '请上传图片',
+            uploadCo: useImageSimpleUploadCo(),
+          } as UploadImageFormItemProps,
+        },
+      ]
+    },
+    {
+      label: '被推荐人身份证复印件',
+      name: 'idCardImages',
+      type: 'single-image',
+      additionalProps: {
+        placeholder: '请上传被推荐人身份证复印件',
+        uploadCo: useImageSimpleUploadCo()
+      } as UploadImageFormItemProps
+    },
+    
+  ],
+  formRules: {
+    name: [{ required: true, message: '请输入姓名' }],
+    level: [{ required: true, message: '请选择级别' }],
+    gender: [{ required: true, message: '请选择性别' }],
+    idPhoto: [{ required: true, message: '请上传身份证照片' }],
+    nation: [{ required: true, message: '请选择民族' }],
+    nativePlace: [{ required: true, message: '请输入籍贯' }],
+    address: [{ required: true, message: '请输入地址' }],
+    mobile: [{ required: true, message: '请输入手机号' }],
+    idCard: [{ required: true, message: '请输入身份证号' }],
+    education: [{ required: true, message: '请选择学历' }],
+    type: [{ required: true, message: '请选择类型' }],
+    batch: [{ required: true, message: '请选择批次' }],
+    region: [{ required: true, message: '请选择区域' }],
+    ichName: [{ required: true, message: '请输入项目名称' }],
+  }
+});
+
 async function loadData() {
   formModel.value = await InheritorContent.getInheritorInfo();
   formModel.value.expandInfo = await InheritorContent.getInheritorExpandInfo();
-}
-async function saveData(model: InheritorInfo) {
-  await InheritorContent.saveExpandInfo(model.expandInfo);
+  formExtendModel.value = formModel.value.expandInfo;
 }
 
 </script>

+ 38 - 13
src/pages/forms/seminar.vue

@@ -3,8 +3,9 @@
   <Form 
     :formModel="formModel"
     :formOptions="formOptions"
+    :extendFormModel="formExtendModel"
+    :extendFormOptions="formExtendOptions"
     :load="loadData"
-    :save="saveData"
   />
 </template>
 
@@ -12,7 +13,7 @@
 import { ref, type Ref } from 'vue';
 import { useImageSimpleUploadCo } from '@/common/upload/ImageUploadCo';
 import Form from './form.vue';
-import InheritorContent, { SeminarInfo } from '@/api/inheritor/InheritorContent';
+import InheritorContent, { SeminarExpandInfo, SeminarInfo } from '@/api/inheritor/InheritorContent';
 import CommonContent from '@/api/CommonContent';
 import type { IDynamicFormOptions } from '@imengyu/vue-dynamic-form';
 import type { SelectProps } from 'ant-design-vue';
@@ -189,13 +190,6 @@ const formOptions = ref<IDynamicFormOptions>({
         },
       ]
     },
-    {
-      type: 'group-object', label: '扩展信息', name: 'expandInfo',
-      childrenColProps: { span: 24 },
-      children: [
-        
-      ]
-    },
   ],
   formRules: {
     expandInfo: {
@@ -211,12 +205,43 @@ const formOptions = ref<IDynamicFormOptions>({
   }
 });
 
+const formExtendModel = ref(new SeminarExpandInfo()) as Ref<SeminarExpandInfo>;
+const formExtendOptions = ref<IDynamicFormOptions>({
+  formLabelCol: { span: 6 },
+  formWrapperCol: { span: 24 },
+  formAdditionaProps: {
+    layout: 'vertical',
+    scrollToFirstError: true,
+  },
+  formNestNameGenerateType: 'array',
+  formItems: [
+    { label: '持有者', name: 'holders', type: 'text', additionalProps: { placeholder: '请输入持有者' } },
+    { label: '地区', name: 'region', type: 'select-id', additionalProps: { placeholder: '请选择地区', loadData: async () => (await CommonContent.getCategoryList(1)).map(p => ({ label: p.title, value: p.id, raw: p })) } },
+    { label: '地图坐标', name: 'lonlat', type: 'map-pick-point' },
+    {
+      type: 'simple-flat', label: '', name: 'map',
+      childrenColProps: { span: 12 },
+      children: [
+        { label: '平面坐标X', name: 'mapX', type: 'number', additionalProps: { placeholder: '请输入平面坐标X' } },
+        { label: '平面坐标Y', name: 'mapY', type: 'number', additionalProps: { placeholder: '请输入平面坐标Y' } },
+      ]
+    },
+    { label: '成立时间', name: 'openTime', type: 'date-time', additionalProps: { placeholder: '请选择成立时间' } },
+    { label: '图片', name: 'image', type: 'single-image', additionalProps: { placeholder: '请上传图片', uploadCo: useImageSimpleUploadCo() } },
+    { label: '相关图片', name: 'images', type: 'mulit-image', additionalProps: { placeholder: '请上传相关图片', uploadCo: useImageSimpleUploadCo() } },
+    { label: '地址', name: 'address', type: 'text', additionalProps: { placeholder: '请输入地址' } },
+    { label: '描述', name: 'intro', type: 'text-area', additionalProps: { placeholder: '请输入描述' } },
+    { label: '简介', name: 'desc', type: 'text-area', additionalProps: { placeholder: '请输入简介' } }
+  ],
+  formRules: {
+    region: [{ required: true, message: '请选择地区' }]
+  }
+});
+
 async function loadData() {
   formModel.value = await InheritorContent.getSeminarInfo();
-  formModel.value.expandInfo = await InheritorContent.getInheritorExpandInfo();
-}
-async function saveData(model: SeminarInfo) {
-  await InheritorContent.saveExpandInfo(model.expandInfo);
+  formModel.value.expandInfo = await InheritorContent.getSeminarExpandInfo();
+  formExtendModel.value = formModel.value.expandInfo;
 }
 
 </script>