快乐的梦鱼 před 2 měsíci
rodič
revize
5f183f0bb6

+ 132 - 58
src/pages/dig/forms/common.vue

@@ -3,10 +3,15 @@
     <CommonRoot>
       <LoadingPage v-if="loading" /> 
       <FlexCol :padding="30">
+        <Alert
+          v-if="localSavedState"
+          type="info"
+          message="您的修改已经暂存,可以放心离开,下次接着编辑"
+        />
         <DynamicForm
           ref="formRef"
           :options="formDefine"
-          :model="formModel"formModel
+          :model="formModel"
           :globalParams="querys"
         />
         <Height :height="20" />
@@ -18,24 +23,25 @@
 </template>
 
 <script setup lang="ts">
-import { nextTick, ref, type Ref } from 'vue';
-import { showError } from '@/common/composeabe/ErrorDisplay';
+import { nextTick, ref, watch, type Ref } from 'vue';
+import { useCollectStore } from '@/store/collect';
 import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
-import { getVillageInfoForm } from './forms';
-import { RequestApiError, waitTimeOut } from '@imengyu/imengyu-utils';
+import { getVillageInfoForm, getVillageInfoFormIds, type SingleForm } from './forms';
+import { showError } from '@/common/composeabe/ErrorDisplay';
+import { backAndCallOnPageBack } from '@/components/utils/PageAction';
+import { toast } from '@/components/utils/DialogAction';
+import { confirm } from '@/components/dialog/CommonRoot';
+import { Debounce, RequestApiError, waitTimeOut } from '@imengyu/imengyu-utils';
 import VillageInfoApi, { CommonInfoModel } from '@/api/inhert/VillageInfoApi';
 import DynamicForm from '@/components/dynamic/DynamicForm.vue';
 import LoadingPage from '@/components/display/loading/LoadingPage.vue';
 import Button from '@/components/basic/Button.vue';
 import CommonRoot from '@/components/dialog/CommonRoot.vue';
 import FlexCol from '@/components/layout/FlexCol.vue';
-import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
 import Height from '@/components/layout/space/Height.vue';
-import { backAndCallOnPageBack } from '@/components/utils/PageAction';
 import XBarSpace from '@/components/layout/space/XBarSpace.vue';
-import { toast } from '@/components/utils/DialogAction';
-import { confirm } from '@/components/dialog/CommonRoot';
-import { useCollectStore } from '@/store/collect';
+import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
+import Alert from '@/components/feedback/Alert.vue';
 
 const loading = ref(false);
 const subTitle = ref('');
@@ -54,47 +60,7 @@ const formDefine = ref<IDynamicFormOptions>({
     },
   },
 });
-
-async function submit() {
-  if (!formRef.value)
-    return;
-  try {
-    await formRef.value.validate();
-  } catch {
-    toast('有必填项未填写,请检查');
-    return;
-  }
-  try {
-    loading.value = true;
-    formModel.value.type = querys.value.subId;
-    await waitTimeOut(800);
-    await VillageInfoApi.updateInfo(
-      collectStore.getCollectModuleId(querys.value.subType),
-      querys.value.subType,
-      querys.value.subKey,
-      querys.value.subId,
-      querys.value.villageId,
-      querys.value.villageVolunteerId,
-      formModel.value as CommonInfoModel,
-    );
-    confirm({
-      content: '您的提交已成功,感谢您的参与!',
-      cancelText: '继续编辑',
-      confirmText: '返回列表',
-      icon: 'success',
-      onConfirm: () => backPrev(true),
-    })
-  } catch (e) {
-    showError(e);
-  } finally {
-    loading.value = false;
-  }
-}
-function backPrev(needRefresh: boolean) {
-  backAndCallOnPageBack('list', {
-    needRefresh,
-  });
-}
+let currentFormInfo : SingleForm|null = null;
 
 const { querys } = useLoadQuerys({ 
   villageId: 0,  
@@ -114,17 +80,17 @@ const { querys } = useLoadQuerys({
     return;
 
   let formData = undefined;
-
   await waitTimeOut(200);
 
   try {
-    const [model, forms] = getVillageInfoForm(querys.subType, querys.subId);
+    currentFormInfo = getVillageInfoForm(querys.subType, querys.subId);
+    const [model, forms] = currentFormInfo;
     formModel.value = new model() as any;
     formDefine.value = {
       ...formDefine.value,
       ...forms(formRef as any)
     };
-    if (querys.id >= 0)
+    if (querys.id >= 0) {
       formData = await VillageInfoApi.getInfo(
         collectStore.getCollectModuleId(querys.subType),
         querys.subType, 
@@ -135,19 +101,127 @@ const { querys } = useLoadQuerys({
         querys.id,
         model,
       );
+    }
   } catch (e) {
+    console.log(e);
     if (!(e instanceof RequestApiError && e.errorMessage.startsWith('请完成')))
       showError(e, undefined, () => backPrev(false));
   } finally {
     loading.value = false;
   }
-
-  if (formData) {
+    
+  formData = await loadLocalSave(formData as CommonInfoModel);
+  if (formData)
     formModel.value = formData as any;
-  }
 
   await nextTick();
-
   formRef.value.initDefaultValuesToModel();
+
+  await waitTimeOut(1000);
+  canSaveNow = true;
 });
+
+async function submit() {
+  if (!formRef.value)
+    return;
+  try {
+    await formRef.value.validate();
+  } catch {
+    toast('有必填项未填写,请检查');
+    return;
+  }
+  try {
+    loading.value = true;
+    formModel.value.type = querys.value.subId;
+    await waitTimeOut(800);
+    if (currentFormInfo?.[2].typeName && querys.value.subId == -1) {
+      const ids = getVillageInfoFormIds(querys.value.subType);
+      for (const id of ids) {
+        await VillageInfoApi.updateInfo(
+          collectStore.getCollectModuleId(querys.value.subType),
+          querys.value.subType,
+          querys.value.subKey,
+          id,
+          querys.value.villageId,
+          querys.value.villageVolunteerId,
+          formModel.value as CommonInfoModel,
+        );
+      }
+    } else {
+      await VillageInfoApi.updateInfo(
+        collectStore.getCollectModuleId(querys.value.subType),
+        querys.value.subType,
+        querys.value.subKey,
+        querys.value.subId,
+        querys.value.villageId,
+        querys.value.villageVolunteerId,
+        formModel.value as CommonInfoModel,
+      );
+    }
+    confirm({
+      content: '您的提交已成功,感谢您的参与!',
+      cancelText: '继续编辑',
+      confirmText: '返回列表',
+      icon: 'success',
+      onConfirm: () => backPrev(true),
+    })
+  } catch (e) {
+    showError(e);
+  } finally {
+    loading.value = false;
+  }
+}
+function backPrev(needRefresh: boolean) {
+  backAndCallOnPageBack('list', {
+    needRefresh,
+  });
+}
+
+const localSavedState = ref(false);
+const saveLocalSaveDebounce = new Debounce(1000, saveLocalSave);
+let canSaveNow = false;
+
+function getSaveName() {
+  return `FormLocalSave-${querys.value.id}-${querys.value.subType}-${querys.value.subId}-${querys.value.villageId}-${querys.value.villageVolunteerId}`;
+}
+async function loadLocalSave(formData: CommonInfoModel|undefined) {
+  if (!currentFormInfo)
+    return formData;
+  console.log('加载暂存数据');
+  const saveName = getSaveName();
+  const saveData = uni.getStorageSync(saveName);
+  if (saveData) {
+    const res = await confirm({
+      content: '您有上次编辑未完成的内容,是否要从上次的编辑数据继续?',
+      cancelText: '取消',
+      confirmText: '继续',
+      icon: 'prompt',
+    })
+    if (res) {
+      const d = JSON.parse(saveData);
+      d.id = 0;
+      formData = new currentFormInfo[0]().fromServerSide(d) as CommonInfoModel;  
+      console.log('有暂存数据', formData);
+    } else
+      deleteLocalSave();
+  }
+  return formData;
+}
+function deleteLocalSave() {
+  const saveName = getSaveName();
+  uni.removeStorageSync(saveName);
+  localSavedState.value = false;
+}
+function saveLocalSave() {
+  const saveName = getSaveName();
+  uni.setStorageSync(saveName, JSON.stringify(formModel.value.toServerSide()));
+  localSavedState.value = true;
+  console.log('保存暂存数据');
+}
+
+watch(formModel, () => {
+  if (!canSaveNow)
+    return;
+  saveLocalSaveDebounce.executeWithDelay();
+}, { deep: true })
 </script>

+ 2 - 2
src/pages/dig/forms/data/building.ts

@@ -507,7 +507,7 @@ export function villageInfoBuildingForm(title: string) : SingleForm  {
         ]
       },
     ] 
-  })]
+  }), { title: title, typeName: 'nature' }]
 }
 
 export const villageInfoDistributionForm : SingleForm = [CommonInfoModel, (r) => ({
@@ -562,4 +562,4 @@ export const villageInfoDistributionForm : SingleForm = [CommonInfoModel, (r) =>
       showTitle: false,
     }).formItems
   ] 
-})];
+}), { title: '建筑分布', typeName: '', }]

+ 5 - 5
src/pages/dig/forms/data/cultural.ts

@@ -57,18 +57,18 @@ export function villageInfoFolkCultureForm(title: string) : SingleForm {
         contentKey: 'details'
       }).formItems
     ]
-  })];
+  }), { title: title, typeName: 'folk_culture_type', }];
 }
 
 export const villageInfoCulture : GroupForm = {
   [1]: [CommonInfoModel, (m) => villageCommonContent(m, {
     title: '建村历史',
     showTitle: true
-  })],
+  }), { title: '建村历史', typeName: 'cultural_type', }],
   [2]: [CommonInfoModel, (m) => villageCommonContent(m, {
     title: '历史事件',
     showTitle: true
-  })],  
+  }), { title: '历史事件', typeName: 'cultural_type', }],  
   [3]: [CommonInfoModel, (m) => ({
     formItems: [
       ...(villageCommonContent(m, {
@@ -91,7 +91,7 @@ export const villageInfoCulture : GroupForm = {
         }]
       },
     ],
-  })],
+  }), { title: '历史文献', typeName: 'cultural_type', }],
   [4]: [CommonInfoModel, (m) => ({
     formItems: [
       ...villageCommonContent(m, {
@@ -189,5 +189,5 @@ export const villageInfoCulture : GroupForm = {
         },
       },
     ],
-  })],
+  }), { title: '口述历史', typeName: 'cultural_type', }],
 }

+ 1 - 1
src/pages/dig/forms/data/element.ts

@@ -256,4 +256,4 @@ export const vilElementForm : SingleForm = [CommonInfoModel, (r) => ({
       ]
     },
   ] 
-})]
+}), { title: '环境要素', typeName: '', }]

+ 1 - 1
src/pages/dig/forms/data/environment.ts

@@ -98,4 +98,4 @@ export const villageInfoEnvironmentForm : SingleForm= [CommonInfoModel, (r) => (
       showTitle: false,
     }).formItems
   ] 
-})]
+}), { title: '环境格局', typeName: '', }]

+ 1 - 1
src/pages/dig/forms/data/food.ts

@@ -39,5 +39,5 @@ export function villageInfoFoodProductsForm(title: string) : SingleForm {
         showTitle: false,
       })).formItems
     ]
-  })];
+  }), { title: title, typeName: 'product_type', }];
 }

+ 2 - 2
src/pages/dig/forms/data/history.ts

@@ -36,7 +36,7 @@ export const villageInfoStoryFormItems: SingleForm = [CommonInfoModel, (r) => ({
       showTitle: false,
     }).formItems
   ]
-})]
+}), { title: '掌故轶事', typeName: '', }]
 
 export const villageInfoFigureFormItems: SingleForm = [CommonInfoModel, (r) => ({
   formItems: [
@@ -73,4 +73,4 @@ export const villageInfoFigureFormItems: SingleForm = [CommonInfoModel, (r) => (
       showTitle: false,
     }).formItems
   ]
-})]
+}), { title: '历史人物', typeName: '', }]

+ 5 - 5
src/pages/dig/forms/data/overview.ts

@@ -86,7 +86,7 @@ export const villageInfoOverviewForm : GroupForm = {
         }],
       },
     ]
-  })],
+  }), { title: '行政区划', typeName: '', }],
   [2]: [VillageEnvInfo, () => ({
     formItems: [
       { 
@@ -192,7 +192,7 @@ export const villageInfoOverviewForm : GroupForm = {
         }],
       },
     ]
-  })],
+  }), { title: '村落综述', typeName: '', }],
   [3]: [CommonInfoModel, () => ({
     formItems: [
       { 
@@ -290,7 +290,7 @@ export const villageInfoOverviewForm : GroupForm = {
         rules:  [] 
       }, 
     ]
-  })],
+  }), { title: '地理信息', typeName: '', }],
   [4]: [CommonInfoModel, () => ({ 
     formItems: [
       {
@@ -481,7 +481,7 @@ export const villageInfoOverviewForm : GroupForm = {
         ]
       },
     ] 
-  })],
+  }), { title: '建设与保护', typeName: '', }],
   [5]: [CommonInfoModel, () => ({
     formItems: [
       {
@@ -541,5 +541,5 @@ export const villageInfoOverviewForm : GroupForm = {
         ]
       },
     ] 
-  })],
+  }), { title: '人口与经济', typeName: '', }],
 }

+ 1 - 1
src/pages/dig/forms/data/specker.ts

@@ -124,4 +124,4 @@ export const villageInfoSpeakerForm : SingleForm = [CommonInfoModel, (r) => ({
       ]
     },
   ]
-})]
+}), { title: '口述人', typeName: '', }]

+ 257 - 236
src/pages/dig/forms/data/travel.ts

@@ -460,243 +460,264 @@ export const villageInfoTravelGuideForm : SingleForm = [CommonInfoModel, () => (
       ]
     }
   ] 
-})]
+}), { title: '旅游导览', typeName: '', }]
 
-export const villageInfoRouteForm : GroupForm = {
-  [1]: [CommonInfoModel, (r) => ({
-    formItems: [
-      {
-        label: '游览路线', 
-        name: 'route', 
-        type: 'text', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入游览路线',
-        },
-        rules:  [{
-          required: true,
-          message: '请输入游览路线',
-        }] 
-      },
-      {
-        label: '路线名称', 
-        name: 'name', 
-        type: 'text', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入路线名称',
-        },
-        rules:  [{
-          required: true,
-          message: '请输入路线名称',
-        }] 
-      },
-      {
-        label: '描述', 
-        name: 'desc', 
-        type: 'richtext', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入描述',
-          maxLength: 200,
-          showWordLimit: true, 
-        },
-        rules:  [{
-          required: true,
-          message: '请输入描述',
-        }] 
-      },
-      {
-        label: '起始点', 
-        name: 'startPoint', 
-        type: 'text', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入起始点',
-        },
-        rules:  [{
-          required: true,
-          message: '请输入起始点',
-        }] 
-      },
-      {
-        label: '终止点', 
-        name: 'endPoint', 
-        type: 'text', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入终止点',
-        },
-        rules:  [{
-          required: true,
-          message: '请输入终止点',
-        }] 
-      },
-      {
-        label: '预计时长', 
-        name: 'estimate', 
-        type: 'number', 
-        defaultValue: 1,
-        additionalProps: {
-          min: 1,
-          addonAfter: '小时',
-        },
-        rules:  [{
-          required: true,
-          message: '请输入预计时长',
-        }] 
-      },
-      ...villageCommonContent(r, {
-        title: '游览路线',
-        showContent: false,
-        showTitle: false,
-      }).formItems
-    ] 
-  })],
-  [2]: [CommonInfoModel, (r) => ({
-    formItems: [
-      {
-        label: '活动标题', 
-        name: 'activity', 
-        type: 'text', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入活动标题',
-        },
-        rules:  [{
-          required: true,
-          message: '请输入活动标题',
-        }] 
-      },
-      {
-        label: '活动开始时间', 
-        name: 'startTime',
-        type: 'datetime', 
-        defaultValue: '',
-        additionalProps: {
-          type: 'datetime',
-        },
-        rules: [{
-          required: true,
-          message: '请选择活动开始时间',
-        }],
-      },
-      {
-        label: '活动结束时间', 
-        name: 'endTime',
-        type: 'datetime', 
-        defaultValue: '',
-        additionalProps: {
-          type: 'datetime',
-        },
-        rules: [{
-          required: true,
-          message: '请选择活动结束时间',
-        }],
-      },
-      {
-        label: '活动时长', 
-        name: 'duration',
-        type: 'number', 
-        defaultValue: 0,
-        additionalProps: {
-          min: 0,
-          addonAfter: '分钟',
-        },
-        rules: [{
-          required: true,
-          message: '请选择活动时长',
-        }],
-      },
-      ...villageCommonContent(r, {
-        title: '活动时间',
-        showContent: false,
-        showTitle: false,
-      }).formItems
-    ] 
-  })],
-  [3]: [CommonInfoModel, (r) => ({
-    formItems: [
-      {
-        label: '特色', 
-        name: 'advant', 
-        type: 'richtext', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入特色',
-          maxLength: 300,
-          showWordLimit: true, 
-        } as FieldProps,
-        rules:  [{
-          required: true,
-          message: '请输入特色',
-        }] 
-      },
-      {
-        label: '文化背景', 
-        name: 'intro', 
-        type: 'richtext', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入文化背景',
-          maxLength: 300,
-          showWordLimit: true, 
-        } as FieldProps,
-        rules:  [{
-          required: true,
-          message: '请输入文化背景',
-        }] 
-      },
-      {
-        label: '精彩推荐', 
-        name: 'recommend', 
-        type: 'richtext', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入精彩推荐',
-          maxLength: 300,
-          showWordLimit: true, 
-        } as FieldProps,
-        rules:  [{
-          required: true,
-          message: '请输入精彩推荐',
-        }] 
+export const villageInfoRouteForm : SingleForm = [CommonInfoModel, (r) => ({
+  formItems: [
+    {
+      label: '游览路线', 
+      name: 'serviceFacilities', 
+      type: 'flat-group', 
+      childrenColProps: {
+        span: 24,
       },
-      {
-        label: '推荐描述', 
-        name: 'reason', 
-        type: 'richtext', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入推荐描述',
-          maxLength: 300,
-          showWordLimit: true, 
-        } as FieldProps,
-        rules:  [{
-          required: true,
-          message: '请输入推荐描述',
-        }] 
+      children: [
+        {
+          label: '游览路线', 
+          name: 'route', 
+          type: 'text', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入游览路线',
+          },
+          rules:  [{
+            required: true,
+            message: '请输入游览路线',
+          }] 
+        },
+        {
+          label: '路线名称', 
+          name: 'name', 
+          type: 'text', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入路线名称',
+          },
+          rules:  [{
+            required: true,
+            message: '请输入路线名称',
+          }] 
+        },
+        {
+          label: '描述', 
+          name: 'desc', 
+          type: 'richtext', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入描述',
+            maxLength: 200,
+            showWordLimit: true, 
+          },
+          rules:  [{
+            required: true,
+            message: '请输入描述',
+          }] 
+        },
+        {
+          label: '起始点', 
+          name: 'startPoint', 
+          type: 'text', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入起始点',
+          },
+          rules:  [{
+            required: true,
+            message: '请输入起始点',
+          }] 
+        },
+        {
+          label: '终止点', 
+          name: 'endPoint', 
+          type: 'text', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入终止点',
+          },
+          rules:  [{
+            required: true,
+            message: '请输入终止点',
+          }] 
+        },
+        {
+          label: '预计时长', 
+          name: 'estimate', 
+          type: 'number', 
+          defaultValue: 1,
+          additionalProps: {
+            min: 1,
+            addonAfter: '小时',
+          },
+          rules:  [{
+            required: true,
+            message: '请输入预计时长',
+          }] 
+        },
+        ...villageCommonContent(r, {
+          title: '游览路线',
+          showContent: false,
+          showTitle: false,
+        }).formItems
+      ]
+    },
+    
+    {
+      label: '活动时间', 
+      name: 'serviceFacilities', 
+      type: 'flat-group', 
+      childrenColProps: {
+        span: 24,
       },
-      {
-        label: '活动亮点', 
-        name: 'highlight', 
-        type: 'richtext', 
-        defaultValue: '',
-        additionalProps: {
-          placeholder: '请输入活动亮点',
-          maxLength: 300,
-          showWordLimit: true, 
-        } as FieldProps,
-        rules:  [{
-          required: true,
-          message: '请输入活动亮点',
-        }] 
+      children: [
+        {
+          label: '活动标题', 
+          name: 'activity', 
+          type: 'text', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入活动标题',
+          },
+          rules:  [{
+            required: true,
+            message: '请输入活动标题',
+          }] 
+        },
+        {
+          label: '活动开始时间', 
+          name: 'startTime',
+          type: 'datetime', 
+          defaultValue: '',
+          additionalProps: {
+            type: 'datetime',
+          },
+          rules: [{
+            required: true,
+            message: '请选择活动开始时间',
+          }],
+        },
+        {
+          label: '活动结束时间', 
+          name: 'endTime',
+          type: 'datetime', 
+          defaultValue: '',
+          additionalProps: {
+            type: 'datetime',
+          },
+          rules: [{
+            required: true,
+            message: '请选择活动结束时间',
+          }],
+        },
+        {
+          label: '活动时长', 
+          name: 'duration',
+          type: 'number', 
+          defaultValue: 0,
+          additionalProps: {
+            min: 0,
+            addonAfter: '分钟',
+          },
+          rules: [{
+            required: true,
+            message: '请选择活动时长',
+          }],
+        },
+        ...villageCommonContent(r, {
+          title: '活动时间',
+          showContent: false,
+          showTitle: false,
+        }).formItems
+      ] 
+    },
+    {
+      label: '路线特色', 
+      name: 'serviceFacilities', 
+      type: 'flat-group', 
+      childrenColProps: {
+        span: 24,
       },
-      ...villageCommonContent(r, {
-        title: '路线特色',
-        showContent: false,
-        showTitle: false,
-      }).formItems
-    ] 
-  })]
-}
+      children: [
+        {
+          label: '特色', 
+          name: 'advant', 
+          type: 'richtext', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入特色',
+            maxLength: 300,
+            showWordLimit: true, 
+          } as FieldProps,
+          rules:  [{
+            required: true,
+            message: '请输入特色',
+          }] 
+        },
+        {
+          label: '文化背景', 
+          name: 'intro', 
+          type: 'richtext', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入文化背景',
+            maxLength: 300,
+            showWordLimit: true, 
+          } as FieldProps,
+          rules:  [{
+            required: true,
+            message: '请输入文化背景',
+          }] 
+        },
+        {
+          label: '精彩推荐', 
+          name: 'recommend', 
+          type: 'richtext', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入精彩推荐',
+            maxLength: 300,
+            showWordLimit: true, 
+          } as FieldProps,
+          rules:  [{
+            required: true,
+            message: '请输入精彩推荐',
+          }] 
+        },
+        {
+          label: '推荐描述', 
+          name: 'reason', 
+          type: 'richtext', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入推荐描述',
+            maxLength: 300,
+            showWordLimit: true, 
+          } as FieldProps,
+          rules:  [{
+            required: true,
+            message: '请输入推荐描述',
+          }] 
+        },
+        {
+          label: '活动亮点', 
+          name: 'highlight', 
+          type: 'richtext', 
+          defaultValue: '',
+          additionalProps: {
+            placeholder: '请输入活动亮点',
+            maxLength: 300,
+            showWordLimit: true, 
+          } as FieldProps,
+          rules:  [{
+            required: true,
+            message: '请输入活动亮点',
+          }] 
+        },
+        ...villageCommonContent(r, {
+          title: '路线特色',
+          showContent: false,
+          showTitle: false,
+        }).formItems
+      ]
+    },
+  ] 
+}), { title: '旅游路线', typeName: '', }];

+ 29 - 33
src/pages/dig/forms/forms.ts

@@ -1,16 +1,6 @@
-import VillageInfoApi, { CommonInfoModel, VillageBulidingInfo, VillageEnvInfo } from "@/api/inhert/VillageInfoApi";
-import { useAliOssUploadCo } from "@/common/components/upload/AliOssUploadCo";
-import type { IDynamicFormOptions, IDynamicFormItem, IDynamicFormRef, IDynamicFormItemCallbackAdditionalProps } from "@/components/dynamic";
-import type { CheckBoxListProps } from "@/components/dynamic/wrappers/CheckBoxList.vue";
-import type { CheckBoxToIntProps } from "@/components/dynamic/wrappers/CheckBoxToInt";
-import type { PickerIdFieldProps } from "@/components/dynamic/wrappers/PickerIdField";
-import type { RadioIdFieldProps } from "@/components/dynamic/wrappers/RadioIdField";
+import { CommonInfoModel } from "@/api/inhert/VillageInfoApi";
+import type { IDynamicFormOptions, IDynamicFormRef } from "@/components/dynamic";
 import type { FieldProps } from "@/components/form/Field.vue";
-import type { PickerFieldProps } from "@/components/form/PickerField.vue";
-import type { StepperProps } from "@/components/form/Stepper.vue";
-import type { UploaderInstance } from "@/components/form/Uploader.vue";
-import type { UploaderFieldInstance, UploaderFieldProps } from "@/components/form/UploaderField.vue";
-import type { RowProps } from "@/components/layout/grid/Row.vue";
 import type { NewDataModel } from "@imengyu/js-request-transform";
 import type { Ref } from "vue";
 import { villageCommonContent } from "./data/common";
@@ -18,15 +8,18 @@ import { villageInfoBuildingForm, villageInfoDistributionForm } from "./data/bui
 import { villageInfoCulture, villageInfoFolkCultureForm } from "./data/cultural";
 import { villageInfoFoodProductsForm } from "./data/food";
 import { villageInfoOverviewForm } from "./data/overview";
-import { ichFormItems } from "./data/ich";
 import { villageInfoEnvironmentForm } from "./data/environment";
 import { villageInfoRelicForm } from "./data/relic";
 import { vilElementForm } from "./data/element";
 import { villageInfoFigureFormItems, villageInfoStoryFormItems } from "./data/history";
 import { villageInfoRouteForm, villageInfoTravelGuideForm } from "./data/travel";
 import { villageInfoSpeakerForm } from "./data/specker";
+import { ichFormItems } from "./data/ich";
 
-export type SingleForm = [NewDataModel, (formRef: Ref<IDynamicFormRef>) => IDynamicFormOptions]
+export type SingleForm = [NewDataModel, (formRef: Ref<IDynamicFormRef>) => IDynamicFormOptions, {
+  title: string,
+  typeName: string,
+}]
 export type GroupForm = Record<number, SingleForm>
 
 const villageInfoForm : Record<string, GroupForm> = {
@@ -52,12 +45,8 @@ const villageInfoForm : Record<string, GroupForm> = {
     [2]: villageInfoBuildingForm('历史建筑'),
     [3]: villageInfoBuildingForm('重要传统建筑'),
   },
-  'distribution': {
-    [0]: villageInfoDistributionForm,
-  },
-  'relic': {
-    [0]: villageInfoRelicForm,
-  },
+  'distribution': { [0]: villageInfoDistributionForm },
+  'relic': { [0]: villageInfoRelicForm },
   'folk_culture': {
     [1]: villageInfoFolkCultureForm('节庆活动'),
     [2]: villageInfoFolkCultureForm('祭祀崇礼'),
@@ -65,13 +54,9 @@ const villageInfoForm : Record<string, GroupForm> = {
     [4]: villageInfoFolkCultureForm('地方方言'),
     [5]: villageInfoFolkCultureForm('特色文化'),
   },
-  'ich': {
-    [0]: ichFormItems,
-  },
-  'travel_guide': {
-    [0]: villageInfoTravelGuideForm, 
-  },
-  'route': villageInfoRouteForm,
+  'ich': { [0]: ichFormItems },
+  'travel_guide': { [0]: villageInfoTravelGuideForm },
+  'route': { [0]: villageInfoRouteForm },
   'food_product': {
     [1]: villageInfoFoodProductsForm('农副产品'),
     [2]: villageInfoFoodProductsForm('食品产品'),
@@ -113,7 +98,7 @@ const villageInfoForm : Record<string, GroupForm> = {
           showTitle: false,
         }).formItems
       ]
-    })]
+    }), { title: '随手记', typeName: '', }]
   },
 }
 
@@ -125,19 +110,30 @@ export function getVillageInfoForm(subType: string, subId: number) {
     return mergeFormItems(group);
   return group[subId];
 }
+export function getVillageInfoFormIds(subType: string) {
+  return Object.keys(villageInfoForm[subType]).map((k) => Number(k));
+}
 
-function mergeFormItems(set: Record<number, SingleForm>) {
+export function mergeFormItems(set: Record<number, SingleForm>) {
   const keys = Object.keys(set);
-  const result : SingleForm =  [set[keys[0] as any][0], (formRef: Ref<IDynamicFormRef>) => {
+  const result : SingleForm = [set[keys[0] as any][0], (formRef: Ref<IDynamicFormRef>) => {
     const options : IDynamicFormOptions = {
       formItems: [],
     };
     for (const key in set) {
-      const op = set[key][1](formRef);
-      options.formItems.push(...op.formItems);
+      const it = set[key];
+      const op = it[1](formRef);
+      const ex = it[2];
+      options.formItems.push({
+        label: ex.title, 
+        name: 'group' + key, 
+        type: 'flat-group', 
+        childrenColProps: { span: 24 },
+        children: op.formItems, 
+      });
     }
     return options;
-  }]
+  }, set[keys[0] as any]?.[2] ?? { title: '合并', typeName: '' }]
 
   return result;
 }

+ 54 - 12
src/pages/dig/forms/task.vue

@@ -15,7 +15,7 @@
         :title="item.title"
         :desc="item.desc"
         :enable="typeof item.enable === 'string' ? canCollect(item.enable) : item.enable"
-        @click="goForm(...item.goForm)"
+        @click="handleClick(item)"
       />
     </FlexCol>
   </FlexCol>
@@ -31,6 +31,9 @@ import FlexCol from '@/components/layout/FlexCol.vue';
 import Image from '@/components/basic/Image.vue';
 import TaskList from '../components/TaskList.vue';
 import VillageApi from '@/api/inhert/VillageApi';
+import { alert } from '@/components/utils/DialogAction';
+import { getVillageInfoForm } from './forms';
+import { navTo } from '@/components/utils/PageAction';
 
 const { goForm } = useTaskEntryForm();
 const { canCollect, getCollectModuleInternalNameById } = useCollectStore();
@@ -39,7 +42,8 @@ useLoadQuerys({
   villageId: 0,
   taskName: '',
   taskPid: 0,
-}, async ({ villageId, taskName, taskPid  }) => {
+}, async (querys) => {
+  const { villageId, taskName, taskPid } = querys;
   currentTaskDefItem.value = { ...TaskMenuDef[taskName] };
   if (taskPid) {
     const res = (await VillageApi.getCatalogList(villageId, taskPid));
@@ -47,21 +51,59 @@ useLoadQuerys({
       return;
     currentTaskDefItem.value.list = res
       .map(item => {
-        const collectModuleInternalName = getCollectModuleInternalNameById(item.collectModuleId);
-        console.log(collectModuleInternalName);
-        
-        return {
-          ...item,
-          enable: true,
-          catalogItem: item,
-          goForm: [ collectModuleInternalName, -1, undefined, 
-            collectModuleInternalName === 'overview' ? 'common' : undefined
-          , item.title ]
+        try {
+          const collectModuleInternalName = getCollectModuleInternalNameById(item.collectModuleId);
+          if (!collectModuleInternalName && item.collectModuleId)
+            throw new Error('不存在定义的表单数据');
+          const formDefine = collectModuleInternalName ? getVillageInfoForm(collectModuleInternalName, -1) : undefined;
+          return {
+            ...item,
+            enable: true,
+            catalogItem: item,
+            goForm: collectModuleInternalName ? [ 
+              collectModuleInternalName, 
+              -1, 
+              formDefine?.[2].typeName, 
+              collectModuleInternalName === 'overview' ? 'common' : undefined,
+              item.title 
+            ] : undefined,
+            onClick: () => {
+              if (item.haschild) {
+                navTo('./task', {
+                  ...querys,
+                  taskName: item.title,
+                  taskPid: item.id,
+                })
+              } else {
+                alert({
+                  title: item.title,
+                  content: '不存在定义的表单数据',
+                })
+              }
+            }
+          }
+        } catch (e) {
+          return {
+            ...item,
+            desc: '' + e,
+            enable: false,
+          }
         }
       });
   }
 });
+
 const currentTaskDefItem = ref<TaskMenuDefItem|null>(null);
+const handleClick = (item: TaskMenuDefItem['list'][0]) => {
+  if (item.goForm) {
+    goForm(...item.goForm);
+    return;
+  }
+  if (item.onClick) {
+    item.onClick();
+  }
+}
+
 
 
 </script>

+ 13 - 26
src/pages/dig/forms/tasks.ts

@@ -5,7 +5,8 @@ export type TaskMenuDefItem = {
     desc: string;
     icon: string;
     enable: string|boolean;
-    goForm: TaskMenuDefGoForm;
+    goForm?: TaskMenuDefGoForm;
+    onClick?: () => void;
   }[];
 }
 export type TaskMenuDefGoForm = [string, number, string|undefined, string|undefined, string|undefined];
@@ -228,14 +229,14 @@ export const TaskMenuDef : Record<string, TaskMenuDefItem> = {
         desc: '乡村繁荣的多元支柱',
         icon: 'icon-task-food-1',
         enable: 'food_product',
-        goForm: [ 'food_product', 1, undefined, undefined, '农副产品' ],
+        goForm: [ 'food_product', 1, 'product_type', undefined, '农副产品' ],
       },
       {
         title: '特色美食',
         desc: '给味蕾探索带来无限惊喜',
         icon: 'icon-task-food-2',
         enable: 'food_product',
-        goForm: [ 'food_product', 3, undefined, undefined, '特色美食' ],
+        goForm: [ 'food_product', 3, 'product_type', undefined, '特色美食' ],
       },
     ],
   },
@@ -247,7 +248,7 @@ export const TaskMenuDef : Record<string, TaskMenuDefItem> = {
         desc: '村落建立与发展历程',
         icon: 'icon-task-history-1',
         enable: 'cultural',
-        goForm: [ 'cultural', 1, undefined, undefined, '建村历史' ],
+        goForm: [ 'cultural', 1, 'cultural_type', undefined, '建村历史' ],
       },
       {
         title: '历史人物',
@@ -261,7 +262,7 @@ export const TaskMenuDef : Record<string, TaskMenuDefItem> = {
         desc: '重大历史事件记录',
         icon: 'icon-task-history-3',
         enable: 'cultural',
-        goForm: [ 'cultural', 2, undefined, undefined, '历史事件' ],
+        goForm: [ 'cultural', 2, 'cultural_type', undefined, '历史事件' ],
       },
       {
         title: '掌故轶事',
@@ -275,14 +276,14 @@ export const TaskMenuDef : Record<string, TaskMenuDefItem> = {
         desc: '重要历史文献资料',
         icon: 'icon-task-history-5',
         enable: 'cultural',
-        goForm: [ 'cultural', 3, undefined, undefined, '历史文献' ],
+        goForm: [ 'cultural', 3, 'cultural_type', undefined, '历史文献' ],
       },
       {
         title: '口述历史',
         desc: '村民口述历史记录',
         icon: 'icon-task-history-6',
         enable: 'cultural',
-        goForm: [ 'cultural', 4, undefined, undefined, '口述历史' ],
+        goForm: [ 'cultural', 4, 'cultural_type', undefined, '口述历史' ],
       },
     ],
   },
@@ -294,21 +295,21 @@ export const TaskMenuDef : Record<string, TaskMenuDefItem> = {
         desc: '文化交流的开放窗口',
         icon: 'icon-task-mine-1',
         enable: 'food_product',
-        goForm: [ 'food_product', 4, undefined, undefined, '商业集市' ],
+        goForm: [ 'food_product', 4, 'product_type', undefined, '商业集市' ],
       },
       {
         title: '服装服饰',
         desc: '艺术与功能交织的时尚篇章',
         icon: 'icon-task-mine-2',
         enable: 'food_product',
-        goForm: [ 'food_product', 5, undefined, undefined, '服装服饰' ],
+        goForm: [ 'food_product', 5, 'product_type', undefined, '服装服饰' ],
       },
       {
         title: '运输工具',
         desc: '历史的运输工具',
         icon: 'icon-task-mine-2',
         enable: 'food_product',
-        goForm: [ 'food_product', 6, undefined, undefined, '运输工具' ],
+        goForm: [ 'food_product', 6, 'product_type', undefined, '运输工具' ],
       },
     ],
   },
@@ -363,25 +364,11 @@ export const TaskMenuDef : Record<string, TaskMenuDefItem> = {
         goForm: [ 'travel_guide', 0, undefined, undefined, '旅游导览' ],
       },
       {
-        title: '游路线',
+        title: '游路线',
         desc: '',
         icon: 'icon-task-trip-1',
         enable: 'route',
-        goForm: [ 'route', 1, undefined, undefined, '游览路线' ],
-      },
-      {
-        title: '活动时间',
-        desc: '',
-        icon: 'icon-task-trip-2',
-        enable: 'route',
-        goForm: [ 'route', 2, undefined, undefined, '活动时间' ],
-      },
-      {
-        title: '路线特色',
-        desc: '',
-        icon: 'icon-task-trip-4',
-        enable: 'route',
-        goForm: [ 'route', 3, undefined, undefined, '路线特色' ],
+        goForm: [ 'route', 0, undefined, undefined, '旅游路线' ],
       },
     ],
   },