Bladeren bron

修改任务页支持动态覆盖

快乐的梦鱼 2 maanden geleden
bovenliggende
commit
5ab6990308
5 gewijzigde bestanden met toevoegingen van 137 en 26 verwijderingen
  1. 55 14
      src/api/inhert/VillageApi.ts
  2. 34 5
      src/pages/dig/details.vue
  3. 26 4
      src/pages/dig/forms/task.vue
  4. 14 3
      src/pages/dig/forms/tasks.ts
  5. 8 0
      src/store/collect.ts

+ 55 - 14
src/api/inhert/VillageApi.ts

@@ -134,6 +134,38 @@ export class VillageMenuListItem extends DataModel<VillageMenuListItem> {
   name = '';
   logo = '';
 }
+export class VillageCatalogListItem extends DataModel<VillageCatalogListItem> {
+  constructor() {
+    super(VillageCatalogListItem, "村落目录列表");
+    this.setNameMapperCase('Camel', 'Snake');
+    this._convertTable = {
+      id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
+      collectModuleId: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
+      haschild: { clientSide: 'boolean', serverSide: 'number' },
+    }
+    this._nameMapperServer = {
+    };
+    this._convertKeyType = (key, direction) => {
+      if (key.endsWith('At'))
+        return {
+          clientSide: 'date',
+          serverSide: 'string',
+        };
+      return undefined;
+    };
+
+  }
+  id !: number;
+  name = '';
+  title = '';
+  pid = 0;
+  desc = '';
+  collectModuleId = 0;
+  collectModuleName = '';
+  villageName = '';
+  spacer = '';
+  haschild = false;
+}
 
 export class VillageApi extends AppServerRequestModule<DataModel> {
 
@@ -171,20 +203,6 @@ export class VillageApi extends AppServerRequestModule<DataModel> {
     return (await this.post('/village/volunteer/getInfo', {
     }, '获取志愿者信息', undefined, VolunteerInfo)).data as VolunteerInfo
   }
-  async getCollectModuleMap() {
-    const res = (await this.post('/village/volunteer/getCollectModuleList', {}, '采集板块列表'))
-    const map = new Map<string, number>();
-    if (!res.data2 || typeof res.data2 !== 'object') 
-      return map;
-    for (const key in res.data2) {
-      if (typeof res.data2[key] !== 'string')
-        throw new Error(`采集板块列表键值对值不是字符串: ${key} -> ${res.data2[key]}`);
-      if (isNaN(Number(key)))
-        throw new Error(`采集板块列表键值对键不是数字: ${key}`);
-      map.set(res.data2[key], Number(key));
-    }
-    return map;
-  }
   async getVolunteerRanklist(category?: number) {
     return (this.post('/village/volunteer/getRanklist', {
       category,
@@ -229,6 +247,29 @@ export class VillageApi extends AppServerRequestModule<DataModel> {
       .catch(e => { throw e });
   }
 
+  async getCollectModuleMap() {
+    const res = (await this.post('/village/volunteer/getCollectModuleList', {}, '采集板块列表'))
+    const map = new Map<string, number>();
+    if (!res.data2 || typeof res.data2 !== 'object') 
+      return map;
+    for (const key in res.data2) {
+      if (typeof res.data2[key] !== 'string')
+        throw new Error(`采集板块列表键值对值不是字符串: ${key} -> ${res.data2[key]}`);
+      if (isNaN(Number(key)))
+        throw new Error(`采集板块列表键值对键不是数字: ${key}`);
+      map.set(res.data2[key], Number(key));
+    }
+    return map;
+  }
+
+  async getCatalogList(villageId?: number, pid?: number) {
+    return (this.get('/village/village/getCatalogList', '村落目录列表', {
+      village_id: villageId,
+      pid: pid,
+    })) 
+      .then(res => transformArrayDataModel<VillageCatalogListItem>(VillageCatalogListItem, res.data2, `村落目录列表`, true))
+      .catch(e => { throw e });
+  }
   async getVillageMenuList(id: number) {
     return (this.get('/village/menu/getList', '村落菜单列表', {
       village_id: id,

+ 34 - 5
src/pages/dig/details.vue

@@ -11,7 +11,7 @@
       <FlexRow flexBasis="50%">
         <Text :fontSize="30" text="已认领:" />
         <Width :width="20" />
-        <Text :fontSize="30" color="primary" :text="querys.name" />
+        <Text :fontSize="30" color="primary" :text="decodeURIComponent(querys.name)" />
       </FlexRow>
       <FlexRow flexBasis="50%" align="center">
         <Text :fontSize="30" color="text.content" :text="`文化积分: `" />
@@ -45,7 +45,7 @@
         description="请联系管理员认领可采编栏目"
       />
       <TaskList
-        v-for="(item,key) in TaskRootDef"
+        v-for="(item,key) in taskList.content.value"
         :key="key"
         :icon="item.icon"
         :title="item.title"
@@ -75,8 +75,10 @@ import TaskList from './components/TaskList.vue';
 import XBarSpace from '@/components/layout/space/XBarSpace.vue';
 import Width from '@/components/layout/space/Width.vue';
 import Alert from '@/components/feedback/Alert.vue';
-import { TaskRootDef } from './forms/tasks';
+import { TaskRootDef, type TaskRootMenuDefItem } from './forms/tasks';
 import { useTaskEntryForm } from './forms/composeable/TaskEntryForm';
+import { useSimpleDataLoader } from '@/common/composeabe/SimpleDataLoader';
+import VillageApi, { VillageCatalogListItem } from '@/api/inhert/VillageApi';
 
 const { querys } = useLoadQuerys({ 
   name: '',
@@ -87,13 +89,37 @@ const { querys } = useLoadQuerys({
 });
 
 const authStore = useAuthStore();
-const { canCollect, isEmpty } = useCollectStore();
+const { canCollect, getCollectModuleInternalNameById, isEmpty } = useCollectStore();
 const { goForm } = useTaskEntryForm();
 
 const nextPageData = computed(() => ({
   villageId: querys.value.villageId,  
   villageVolunteerId: querys.value.villageVolunteerId,
 }));
+const taskList = useSimpleDataLoader<(TaskRootMenuDefItem & {
+  catalogItem?: VillageCatalogListItem,
+})[]>(async () => {
+  const res = (await VillageApi.getCatalogList(querys.value.villageId))
+    .filter(item => item.pid == 0)
+    .map(item => ({
+      ...item,
+      collectModuleName: getCollectModuleInternalNameById(item.collectModuleId),
+    }));
+
+  if (res.length === 0)
+    return TaskRootDef;
+
+  return TaskRootDef
+    .map(item => ({
+      ...item,
+      catalogItem: res.find(t => t.collectModuleName == item.name || t.title == item.title)
+    }))
+    .filter(item => item.catalogItem)
+    .map(item => ({
+      ...item,
+      title: item.catalogItem?.title || item.title,
+    }));
+});
 
 function goCollect() {
   if (!canCollect('collect')) {
@@ -107,7 +133,9 @@ function goCollect() {
   goForm('collect', 1, '随手记')
 }
 
-function goTask(item: typeof TaskRootDef[0]) {
+function goTask(item: TaskRootMenuDefItem & {
+  catalogItem?: VillageCatalogListItem,
+}) {
   if (!item.enable) {
     uni.showToast({
       title: '您当前没有可完成此任务的权限',
@@ -121,6 +149,7 @@ function goTask(item: typeof TaskRootDef[0]) {
   } else {
     navTo('forms/task', {
       ...nextPageData.value,
+      taskPid: item.catalogItem?.id || 0,
       taskName: item.goForm.name,
     })
   }

+ 26 - 4
src/pages/dig/forms/task.vue

@@ -30,14 +30,36 @@ import { TaskMenuDef, type TaskMenuDefItem } from './tasks';
 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';
 
 const { goForm } = useTaskEntryForm();
-const { canCollect } = useCollectStore();
+const { canCollect, getCollectModuleInternalNameById } = useCollectStore();
 
-const { querys } = useLoadQuerys({ 
+useLoadQuerys({ 
+  villageId: 0,
   taskName: '',
-}, ({ taskName }) => {
-  currentTaskDefItem.value = TaskMenuDef[taskName];
+  taskPid: 0,
+}, async ({ villageId, taskName, taskPid  }) => {
+  currentTaskDefItem.value = { ...TaskMenuDef[taskName] };
+  if (taskPid) {
+    const res = (await VillageApi.getCatalogList(villageId, taskPid))
+      .map(item => ({
+        ...item,
+        collectModuleName: getCollectModuleInternalNameById(item.collectModuleId),
+      }));
+    if (res.length === 0)
+      return;
+    currentTaskDefItem.value.list = currentTaskDefItem.value.list
+      .map(item => ({
+        ...item,
+        catalogItem: res.find(t => t.name == item.title),
+      }))
+      .filter(item => item.catalogItem)
+      .map(item => ({
+        ...item,
+        title: item.catalogItem?.title || item.title,
+      }));
+  }
 });
 const currentTaskDefItem = ref<TaskMenuDefItem|null>(null);
 

+ 14 - 3
src/pages/dig/forms/tasks.ts

@@ -9,22 +9,25 @@ export type TaskMenuDefItem = {
   }[];
 }
 export type TaskMenuDefGoForm = [string, number, string|undefined, string|undefined, string|undefined];
-
-export const TaskRootDef : {
+export type TaskRootMenuDefItem = {
   title: string;
   desc: string;
   icon: string;
   enable: string|boolean;
+  name: string;
   goForm: {
     title: string;
     name: string;
   }|TaskMenuDefGoForm
-}[] = [
+}
+
+export const TaskRootDef : TaskRootMenuDefItem[] = [
   {
     title: '村落概况',
     desc: '探索村落的历史渊源与发生轨迹',
     icon: 'icon-task-summary',
     enable: 'overview',
+    name: 'overview',
     goForm: {
       title: '村落概况',
       name: 'overview',
@@ -35,6 +38,7 @@ export const TaskRootDef : {
     desc: '传承百年文化遗产和精神财富',
     icon: 'icon-task-history',
     enable: true,
+    name: 'history',
     goForm: {
       title: '历史文化',
       name: 'history',
@@ -45,6 +49,7 @@ export const TaskRootDef : {
     desc: '维护文化多样性',
     icon: 'icon-task-custom-1',
     enable: 'ich',
+    name: 'ich',
     goForm: [ 'ich', 0, undefined, undefined, '非物质文化遗产项目' ],
   },
   {
@@ -52,6 +57,7 @@ export const TaskRootDef : {
     desc: '感受自然人文环境之美',
     icon: 'icon-task-environment',
     enable: 'environment',
+    name: 'environment',
     goForm: {
       title: '环境格局',
       name: 'environment',
@@ -62,6 +68,7 @@ export const TaskRootDef : {
     desc: '领略古建筑的独特魅力',
     icon: 'icon-task-building',
     enable: true,
+    name: 'building',
     goForm: {
       title: '传统建筑',
       name: 'building',
@@ -72,6 +79,7 @@ export const TaskRootDef : {
     desc: '体验民间传统习俗与节庆',
     icon: 'icon-task-custom',
     enable: 'folk_culture',
+    name: 'folk_culture',
     goForm: {
       title: '民俗文化',
       name: 'custom',
@@ -82,6 +90,7 @@ export const TaskRootDef : {
     desc: '正宗、传统地方特色美食',
     icon: 'icon-task-food',
     enable: 'food_product',
+    name: 'food',
     goForm: {
       title: '地道美食',
       name: 'food',
@@ -92,6 +101,7 @@ export const TaskRootDef : {
     desc: '特定地域的植物、矿物或工艺品',
     icon: 'icon-task-mine',
     enable: 'food_product',
+    name: 'product',
     goForm: {
       title: '物产资源',
       name: 'product',
@@ -102,6 +112,7 @@ export const TaskRootDef : {
     desc: '体验独特的文化魅力',
     icon: 'icon-task-trip',
     enable: true,
+    name: 'trip',
     goForm: {
       title: '旅游路线',
       name: 'trip',

+ 8 - 0
src/store/collect.ts

@@ -44,6 +44,13 @@ export const useCollectStore = defineStore('collect', () => {
       return collectableModules.value.get(CollectableModulesNameMapping[module]);
     return collectableModules.value.get(module);
   }
+  function getCollectModuleInternalNameById(id: number) {
+    for (const [key, value] of collectableModules.value) {
+      if (value == id)
+        return key;
+    }
+    return '';
+  }
   
   const isEmpty = computed(() => collectableModules.value.size === 0);
 
@@ -51,6 +58,7 @@ export const useCollectStore = defineStore('collect', () => {
     isEmpty,
     collectableModules,
     setCollectableModules,
+    getCollectModuleInternalNameById,
     getCollectModuleId,
     canCollect,
   }