Quellcode durchsuchen

📦 增加基础页面

快乐的梦鱼 vor 2 Wochen
Ursprung
Commit
8d15a66cc6

+ 44 - 49
src/api/inheritor/InheritorContent.ts

@@ -1,17 +1,46 @@
 import { DataModel } from '@imengyu/js-request-transform';
 import { AppServerRequestModule } from '../RequestModules';
 
-export class IchInfo extends DataModel<IchInfo> {
-  constructor() {
-    super(IchInfo, "非遗项目信息");
+export class CommonInfo<T extends DataModel> extends DataModel<T> {
+
+  constructor(classCreator?: (new () => T) | undefined, name: string = '基础信息') {
+    super(classCreator, name);
     this.setNameMapperCase('Camel', 'Snake');
     this._convertTable = {
       id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
-      lonlat: { serverSide: 'undefined' },
       flag: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
-      batch: { clientSide: 'number', serverSide: 'string' },
       type: { clientSide: 'number', serverSide: 'number' },
       keywords: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
+      images: { clientSide: 'array', serverSide: 'string' },
+      expandInfo: { serverSide: 'undefined' },
+    };
+  }
+
+  contentId = null as number|null;
+  collectId = null as number|null;
+  
+  title = '' as string;
+  region = null as number|null;
+  image = '' as string|null;
+  imageDesc = '' as string|null;
+  images = [] as string[];
+  audio = '' as string|null;
+  video = '' as string|null;
+  flag = '' as string;
+  keywords = '' as string|null;
+  tags = '' as string;
+  associationId = 0 as number;
+  pid = 0 as number;
+  content = '' as string|null;
+}
+
+export class IchInfo extends CommonInfo<IchInfo> {
+  constructor() {
+    super(IchInfo, "非遗项目信息");
+    this._convertTable = {
+      ...this._convertTable,
+      lonlat: { serverSide: 'undefined' },
+      batch: { clientSide: 'number', serverSide: 'string' },
       typicalImages: [
         { 
           clientSide: 'object', 
@@ -27,7 +56,6 @@ export class IchInfo extends DataModel<IchInfo> {
           }
         },
       ],
-      expandInfo: { serverSide: 'undefined' },
     };
     this._convertKeyType = (key, direction) => {
       if (key.endsWith('Text') || key.endsWith('_text')) {
@@ -61,20 +89,6 @@ export class IchInfo extends DataModel<IchInfo> {
   id = 0 as number;
   modelId = 2;
   mainBodyColumnId = 0 as number;
-  contentId = null as number|null;
-  collectId = null as number|null;
-  title = '' as string;
-  region = null as number|null;
-  image = '' as string;
-  imageDesc = '' as string|null;
-  images = [] as string[];
-  audio = '' as string|null;
-  video = '' as string;
-  flag = '' as string;
-  keywords = '' as string|null;
-  tags = '' as string;
-  associationId = '' as string|null;
-  pid = 0 as number;
   ztImage = '' as string|null;
   intro = '' as string;
   description = '' as string;
@@ -173,29 +187,19 @@ export class IchExpandInfo extends DataModel<IchExpandInfo> {
   protectLevelText = '' as string;
   progressText = '' as string;
 }
-export class InheritorInfo extends DataModel<InheritorInfo> {
+export class InheritorInfo extends CommonInfo<InheritorInfo> {
   constructor() {
     super(InheritorInfo, "传承人信息");
-    this.setNameMapperCase('Camel', 'Snake');
     this._convertTable = {
-      id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
+      ...this._convertTable,
     }
   }
+
+  expandInfo = new InheritorExpandInfo();
+
   id = 0 as number;
   modelId = 7;
   mainBodyColumnId = 0 as number;
-  title = '' as string;
-  region = null as number|null;
-  image = '' as string;
-  imageDesc = '' as string|null;
-  images = [] as string[];
-  audio = '' as string|null;
-  video = '' as string|null;
-  flag = '' as string;
-  keywords = '' as string|null;
-  tags = '' as string;
-  associationId = null as number|null;
-  pid = 0 as number;
   alsoName = '' as string|null;
   nation = '' as string;
   dateBirth = '' as string;
@@ -247,29 +251,20 @@ export class InheritorExpandInfo extends DataModel<InheritorExpandInfo> {
   }
   modelId = 7;
 }
-export class SeminarInfo extends DataModel<SeminarInfo> {
+export class SeminarInfo extends CommonInfo<SeminarInfo> {
   constructor() {
     super(SeminarInfo, "传习所信息");
     this.setNameMapperCase('Camel', 'Snake');
     this._convertTable = {
-      id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
+      ...this._convertTable,
     }
   }
+
+  expandInfo = new SeminarExpandInfo();
+
   id = 0 as number;
   modelId = 17;
   mainBodyColumnId = 0 as number;
-  title = '' as string;
-  region = null as number|null;
-  image = '' as string|null;
-  imageDesc = '' as string|null;
-  images = [] as string[];
-  audio = '' as string|null;
-  video = '' as string|null;
-  flag = '' as string;
-  keywords = '' as string|null;
-  tags = '' as string;
-  associationId = 0 as number;
-  pid = 0 as number;
   content = '' as string|null;
   mapX = '' as string|null;
   mapY = '' as string|null;

+ 1 - 1
src/common/ConvertRgeistry.ts

@@ -42,7 +42,7 @@ export function registryConvert() {
       if (typeof source === 'string') 
         return {
           success: true,
-          result: source?.split(',') || [],
+          result: source ? source.split(',') : [],
         }
       return {
         success: false,

+ 14 - 0
src/composeable/WindowOnUnLoad.ts

@@ -0,0 +1,14 @@
+import { onBeforeUnmount, onMounted } from "vue";
+
+export function useWindowOnUnLoadConfirm() {
+  function callback(e: BeforeUnloadEvent) {
+    e.preventDefault();
+    return '确定要离开吗?';
+  }
+  onMounted(() => {
+    window.addEventListener('beforeunload', callback);
+  })
+  onBeforeUnmount(() => {
+    window.removeEventListener('beforeunload', callback);
+  });
+}

+ 8 - 5
src/pages/forms/form.vue

@@ -30,12 +30,13 @@
 </template>
 
 <script setup lang="ts" generic="T extends DataModel">
-import InheritorContent from '@/api/inheritor/InheritorContent';
-import type { DataModel } from '@imengyu/js-request-transform';
-import { DynamicForm, type IDynamicFormOptions, type IDynamicFormRef } from '@imengyu/vue-dynamic-form';
-import { message, Modal, type FormInstance } from 'ant-design-vue';
 import { onMounted, ref, toRefs, type PropType } from 'vue';
 import { useRouter } from 'vue-router';
+import { useWindowOnUnLoadConfirm } from '@/composeable/WindowOnUnLoad';
+import { DynamicForm, type IDynamicFormOptions, type IDynamicFormRef } from '@imengyu/vue-dynamic-form';
+import { message, Modal, type FormInstance } from 'ant-design-vue';
+import InheritorContent from '@/api/inheritor/InheritorContent';
+import type { DataModel } from '@imengyu/js-request-transform';
 
 const props = defineProps({
   title: {
@@ -67,6 +68,8 @@ const router = useRouter();
 const loading = ref(false);
 const loadingData = ref(false);
 
+useWindowOnUnLoadConfirm();
+
 async function handleSubmit() {
   loading.value = true;
 
@@ -87,7 +90,7 @@ async function handleSubmit() {
       title: '提交成功',
       content: result.message,
       onOk() {
-        router.push({ path: '/' })
+        router.back();
       },
     });
   } catch (error) {

+ 1 - 1
src/pages/forms/ich.vue

@@ -299,4 +299,4 @@ async function saveData(model: IchInfo) {
   await InheritorContent.saveExpandInfo(model.expandInfo);
 }
 
-</script>
+</script>

+ 183 - 0
src/pages/forms/inheritor.vue

@@ -0,0 +1,183 @@
+<template>
+  <!-- 传承人基础表单 -->
+  <Form 
+    :formModel="formModel"
+    :formOptions="formOptions"
+    :load="loadData"
+    :save="saveData"
+  />
+</template>
+
+<script setup lang="ts">
+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 CommonContent from '@/api/CommonContent';
+import type { IDynamicFormOptions } from '@imengyu/vue-dynamic-form';
+import type { SelectProps } from 'ant-design-vue';
+import type { UploadImageFormItemProps } from '@/components/dynamicf/UploadImageFormItem';
+
+const formModel = ref(new InheritorInfo()) as Ref<InheritorInfo>;
+const formOptions = ref<IDynamicFormOptions>({
+  formLabelCol: { span: 6 },
+  formWrapperCol: { span: 24 },
+  formAdditionaProps: {
+    layout: 'vertical',
+    scrollToFirstError: true,
+  },
+  formNestNameGenerateType: 'array',
+  formItems: [
+    {
+      type: 'group-flat', label: '传承人信息', name: 'ichInfo',
+      childrenColProps: { span: 24 },
+      children: [
+        { 
+          label: '标题', name: 'title', type: 'text',
+          additionalProps: { placeholder: '请输入标题' },
+        },
+        //请在这里添加表单项
+      ]
+    },
+    {
+      type: 'group-flat', label: '通用信息', name: 'commonInfo',
+      childrenColProps: { span: 24 },
+      children: [
+        { 
+          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: 'type', type: 'select',
+          additionalProps: {
+            placeholder: '请选择类型',
+            options: [
+              { text: '文章', value: 1 },
+              { text: '音频', value: 2 },
+              { text: '视频', value: 3 },
+              { text: '相册', value: 4 },
+              { text: '数字档案', value: 5 }]
+            },  
+        },
+        { 
+          label: '图片', name: 'image', type: 'single-image',
+          additionalProps: {
+            placeholder: '请上传图片',
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '图片说明', name: 'imageDesc', type: 'text',
+          additionalProps: { placeholder: '请输入图片说明' }
+        },
+        { 
+          label: '转自', name: 'from', type: 'text',
+          additionalProps: { placeholder: '请输入来源' },
+        },
+        { 
+          label: '组图', name: 'images', type: 'mulit-image',
+          hidden: { callback: (_, model) => (model as InheritorInfo).type !== 4 },
+          additionalProps: {
+            placeholder: '请上传图片',
+            maxCount: 20,
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo(),
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '音频', name: 'audio', type: 'single-image',
+          hidden: { callback: (_, model) => (model as InheritorInfo).type !== 2 },
+          additionalProps: {
+            placeholder: '请上传音频',
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '视频', name: 'video', type: 'single-video',
+          hidden: { callback: (_, model) => (model as InheritorInfo).type !== 3 },
+          additionalProps: {
+            placeholder: '请上传视频',
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,  
+        },
+        { 
+          label: '数字档案', name: 'archives', type: 'mulit-image',
+          hidden: { callback: (_, model) => (model as InheritorInfo).type !== 5 },
+          additionalProps: {
+            placeholder: '请上传数字档案',
+            maxCount: 20,
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '标志', name: 'flag', type: 'select',
+          additionalProps: {
+            mode: 'tags',
+            options: [  
+              { text: '热门', value: 'hot' },
+              { text: '推荐', value: 'recommend' },
+              { text: '置顶', value: 'top' },
+            ],
+            placeholder: '请输入标志' 
+          } as SelectProps,
+        },
+        { 
+          label: '关键字', name: 'keywords', type: 'select',
+          additionalProps: {
+            mode: 'tags',
+            options: [],
+            placeholder: '请输入关键字,回车添加' 
+          } as SelectProps,
+        },
+        { 
+          label: '描述', name: 'desc', type: 'text-area',
+          additionalProps: { placeholder: '请输入描述' },
+        },
+        { 
+          label: 'TAG', name: 'tags', type: 'text',
+          additionalProps: { placeholder: '请输入TAG' },
+        },
+        { 
+          label: '备注', name: 'memo', type: 'text-area',
+          additionalProps: { placeholder: '请输入备注' },
+        },
+      ]
+    },
+    {
+      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: '请选择类型' }],
+    image: [{ required: true, message: '请上传图片' }],
+    level: [{ required: true, message: '请选择级别' }],
+    ichType: [{ required: true, message: '请选择非遗类型' }],
+    batch: [{ 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);
+}
+
+</script>

+ 183 - 0
src/pages/forms/seminar.vue

@@ -0,0 +1,183 @@
+<template>
+  <!-- 传习所基础表单 -->
+  <Form 
+    :formModel="formModel"
+    :formOptions="formOptions"
+    :load="loadData"
+    :save="saveData"
+  />
+</template>
+
+<script setup lang="ts">
+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 CommonContent from '@/api/CommonContent';
+import type { IDynamicFormOptions } from '@imengyu/vue-dynamic-form';
+import type { SelectProps } from 'ant-design-vue';
+import type { UploadImageFormItemProps } from '@/components/dynamicf/UploadImageFormItem';
+
+const formModel = ref(new SeminarInfo()) as Ref<SeminarInfo>;
+const formOptions = ref<IDynamicFormOptions>({
+  formLabelCol: { span: 6 },
+  formWrapperCol: { span: 24 },
+  formAdditionaProps: {
+    layout: 'vertical',
+    scrollToFirstError: true,
+  },
+  formNestNameGenerateType: 'array',
+  formItems: [
+    {
+      type: 'group-flat', label: '传习所信息', name: 'seminarInfo',
+      childrenColProps: { span: 24 },
+      children: [
+        { 
+          label: '标题', name: 'title', type: 'text',
+          additionalProps: { placeholder: '请输入标题' },
+        },
+        
+      ]
+    },
+    {
+      type: 'group-flat', label: '通用信息', name: 'commonInfo',
+      childrenColProps: { span: 24 },
+      children: [
+        { 
+          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: 'type', type: 'select',
+          additionalProps: {
+            placeholder: '请选择类型',
+            options: [
+              { text: '文章', value: 1 },
+              { text: '音频', value: 2 },
+              { text: '视频', value: 3 },
+              { text: '相册', value: 4 },
+              { text: '数字档案', value: 5 }]
+            },  
+        },
+        { 
+          label: '图片', name: 'image', type: 'single-image',
+          additionalProps: {
+            placeholder: '请上传图片',
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '图片说明', name: 'imageDesc', type: 'text',
+          additionalProps: { placeholder: '请输入图片说明' }
+        },
+        { 
+          label: '转自', name: 'from', type: 'text',
+          additionalProps: { placeholder: '请输入来源' },
+        },
+        { 
+          label: '组图', name: 'images', type: 'mulit-image',
+          hidden: { callback: (_, model) => (model as SeminarInfo).type !== 4 },
+          additionalProps: {
+            placeholder: '请上传图片',
+            maxCount: 20,
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo(),
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '音频', name: 'audio', type: 'single-image',
+          hidden: { callback: (_, model) => (model as SeminarInfo).type !== 2 },
+          additionalProps: {
+            placeholder: '请上传音频',
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '视频', name: 'video', type: 'single-video',
+          hidden: { callback: (_, model) => (model as SeminarInfo).type !== 3 },
+          additionalProps: {
+            placeholder: '请上传视频',
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,  
+        },
+        { 
+          label: '数字档案', name: 'archives', type: 'mulit-image',
+          hidden: { callback: (_, model) => (model as SeminarInfo).type !== 5 },
+          additionalProps: {
+            placeholder: '请上传数字档案',
+            maxCount: 20,
+            name: 'file',
+            uploadCo: useImageSimpleUploadCo()
+          } as UploadImageFormItemProps,
+        },
+        { 
+          label: '标志', name: 'flag', type: 'select',
+          additionalProps: {
+            mode: 'tags',
+            options: [  
+              { text: '热门', value: 'hot' },
+              { text: '推荐', value: 'recommend' },
+              { text: '置顶', value: 'top' },
+            ],
+            placeholder: '请输入标志' 
+          } as SelectProps,
+        },
+        { 
+          label: '关键字', name: 'keywords', type: 'select',
+          additionalProps: {
+            mode: 'tags',
+            options: [],
+            placeholder: '请输入关键字,回车添加' 
+          } as SelectProps,
+        },
+        { 
+          label: '描述', name: 'desc', type: 'text-area',
+          additionalProps: { placeholder: '请输入描述' },
+        },
+        { 
+          label: 'TAG', name: 'tags', type: 'text',
+          additionalProps: { placeholder: '请输入TAG' },
+        },
+        { 
+          label: '备注', name: 'memo', type: 'text-area',
+          additionalProps: { placeholder: '请输入备注' },
+        },
+      ]
+    },
+    {
+      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: '请选择类型' }],
+    image: [{ required: true, message: '请上传图片' }],
+    level: [{ required: true, message: '请选择级别' }],
+    ichType: [{ required: true, message: '请选择非遗类型' }],
+    batch: [{ 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);
+}
+
+</script>

+ 2 - 2
src/pages/inheritor.vue

@@ -40,7 +40,7 @@
             </EmptyToRecord>
           </a-tab-pane>
           <a-tab-pane key="2" tab="传承人">
-            <EmptyToRecord title="传承人" :model="inheritorData">
+            <EmptyToRecord title="传承人" :model="inheritorData" @edit="router.push({ name: 'FormInheritor' })">
               <a-descriptions class="mt-3" title="传承人信息" v-if="inheritorData" bordered :column="{ xs: 1, sm: 1, md: 1, lg: 2 }">
                 <a-descriptions-item label="名字"><ShowValueOrNull :value="inheritorData.title" /></a-descriptions-item>
                 <a-descriptions-item v-if="inheritorData.image" label="头像">
@@ -73,7 +73,7 @@
               </a-descriptions>
             </EmptyToRecord>
           </a-tab-pane>
-          <a-tab-pane key="3" tab="传习所">
+          <a-tab-pane key="3" tab="传习所" @edit="router.push({ name: 'FormSeminar' })">
             <EmptyToRecord title="传习所" :model="seminarData">
               <a-descriptions class="mt-3" title="传习所信息" v-if="seminarData" bordered :column="{ xs: 1, sm: 1, md: 1, lg: 2 }">
                 <a-descriptions-item label="标题"><ShowValueOrNull :value="seminarData.title" /></a-descriptions-item>

+ 10 - 0
src/router/index.ts

@@ -16,6 +16,16 @@ const router = createRouter({
       component: () => import('@/pages/forms/ich.vue'),
     }, 
     {
+      path: '/forms/inheritor',
+      name: 'FormInheritor',
+      component: () => import('@/pages/forms/inheritor.vue'),
+    }, 
+    {
+      path: '/forms/seminar',
+      name: 'FormSeminar',
+      component: () => import('@/pages/forms/seminar.vue'),
+    }, 
+    {
       path: '/login',
       name: 'Login',
       component: () => import('@/pages/login.vue'),