ソースを参照

按要求修改和优化

快乐的梦鱼 2 ヶ月 前
コミット
d525c64f96

+ 8 - 6
src/api/inhert/VillageInfoApi.ts

@@ -69,7 +69,7 @@ export class CommonInfoModel extends DataModel<CommonInfoModel> {
   villageVolunteerName = '';
   contentId = 0;
   name = '';
-  type = 0;
+  type = 1;
   audio = '';
   video = '';
   archives = '';
@@ -275,19 +275,21 @@ export class VillageInfoApi extends AppServerRequestModule<DataModel> {
   ) {
     if (subType === 'overview') {
       return (await this.post(`/village/${subType}/save`, {
+        ...data.toServerSide(),
         subType,
         village_id: villageId,
         village_volunteer_id: villageVolunteerId,
-        ...data.toServerSide(),
       }, '更新信息详情'));
     } else {
-      return (await this.post(`/village/collect/save`, {
+      const res : Record<string, any> = {
+        ...data.toServerSide(),
         collect_module_id: collectModuleId,
-        [subKey||'type']: subId,
         village_id: villageId,
         village_volunteer_id: villageVolunteerId,
-        ...data.toServerSide(),
-      }, '通用更新信息详情'));
+      };
+      if (subKey)
+        res[subKey] = subId;
+      return (await this.post(`/village/collect/save`, res, '通用更新信息详情'));
     }
   }
 }

+ 2 - 1
src/components/form/Uploader.vue

@@ -59,7 +59,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue';
+import { ref, watch } from 'vue';
 import { propGetThemeVar, useTheme, type TextStyle, type ViewStyle } from '../theme/ThemeDefine';
 import type { ToastInstance } from '../feedback/Toast.vue';
 import Toast from '../feedback/Toast.vue';
@@ -264,6 +264,7 @@ const props = withDefaults(defineProps<UploaderProps>(), {
   showDelete: true,
   showUpload: true,
   uploadWhenAdded: true,
+  autoUpdateUploadList: true,
   uploadQueueMode: 'all',
   listType: 'grid',
   chooseType: 'image',

+ 24 - 7
src/components/form/UploaderField.vue

@@ -2,13 +2,14 @@
   <Uploader
     ref="uploaderRef"
     v-bind="props"
+    :modelValue="[]"
     :maxUploadCount="single ? 1 : maxUploadCount"
     @updateList="handleListChange"
   />
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref, toRef } from 'vue';
+import { onMounted, ref, toRef, watch } from 'vue';
 import { useFieldChildValueInjector } from './FormContext';
 import type { UploaderInstance, UploaderProps } from './Uploader.vue';
 import { stringUrlToUploaderItem, type UploaderItem } from './Uploader';
@@ -16,7 +17,16 @@ import Uploader from './Uploader.vue';
 
 export interface UploaderFieldProps extends Omit<UploaderProps, 'value'> {
   modelValue?: string[]|string;
+  /**
+   * 是否为单文件上传
+   * @default false
+   */
   single?: boolean;
+  /**
+   * 是否根据modelValue自动更新已上传列表,当modelValue变化时,会自动更新已上传列表。
+   * @default true
+   */
+  autoUpdateUploadList?: boolean;
 }
 
 const uploaderRef = ref<UploaderInstance>();
@@ -26,6 +36,7 @@ const props = withDefaults(defineProps<UploaderFieldProps>(), {
   showDelete: true,
   showUpload: true,
   uploadWhenAdded: true,
+  autoUpdateUploadList: true,
 });
 
 const {
@@ -38,17 +49,23 @@ const {
   //() => { /*uploaderRef.value?.pick()*/ },
 );
 
+watch(() => props.modelValue, (newVal) => {
+  if (props.autoUpdateUploadList)
+    setUploaderList();
+})
+
 function handleListChange(list: UploaderItem[]) {
   updateValue(list.map((item) => item.uploadedPath).filter((item) => item) as string[]);
 }
+function setUploaderList() {
+  uploaderRef.value?.setList(props.single || typeof value.value === 'string' 
+    ? (value.value ? [ stringUrlToUploaderItem(value.value as any as string) ] : [])
+    : value.value?.map((item) => stringUrlToUploaderItem(item)) ?? []
+  );
+}
 
 onMounted(() => {
-  setTimeout(() => {
-    uploaderRef.value?.setList(props.single || typeof value.value === 'string' 
-      ? (value.value ? [ stringUrlToUploaderItem(value.value as any as string) ] : [])
-      : value.value?.map((item) => stringUrlToUploaderItem(item)) ?? []
-    )
-  }, 200);
+  setTimeout(() => setUploaderList(), 200);
 });
 
 defineExpose({

+ 3 - 1
src/components/form/UploaderListItem.vue

@@ -52,7 +52,9 @@
       :innerStyle="{ 
         ...(isListStyle ? themeStyles.itemListStyleImage.value : themeStyles.itemImage.value), 
         ...imageStyle,
-      }" />
+      }" 
+      mode="aspectFill" 
+    />
     <Icon v-else :icon="fileIcon" :color="itemMaskTextColor" :size="itemListStyleImageSize" />
 
     <FlexRow v-if="isListStyle" :flex="1" align="center">

+ 1 - 1
src/pages.json

@@ -75,7 +75,7 @@
       "path": "pages/dig/forms/list",
       "style": {
         "navigationBarTitleText": "信息列表",
-        "enablePullDownRefresh": false
+        "enablePullDownRefresh": true
       }
     },
     {

+ 1 - 1
src/pages/article/list.vue

@@ -11,8 +11,8 @@
 
 <script setup lang="ts">
 import CommonContent, { GetContentListParams } from '@/api/CommonContent';
-import { DataDateUtils } from '@imengyu/js-request-transform';
 import CommonListPage from './common/CommonListPage.vue';
+import { DataDateUtils } from '@imengyu/js-request-transform';
 
 async function loadData(
   page: number, 

+ 8 - 2
src/pages/dig/admin.vue

@@ -32,13 +32,14 @@
         </Touchable>
       </button>
 
-      <FlexRow 
+      <Touchable 
         v-for="item in listLoader.list.value"
         :key="item.id" 
         backgroundColor="white" 
         radius="20"
         :padding="20"
         :gap="20"
+        direction="row"
         @click="goDetail(item.id)"
       >
         <Image :src="item.image" width="150rpx" height="150rpx" round radius="30" />
@@ -48,7 +49,7 @@
           <Text :fontSize="26" :text="`地址:${item.address || ''}`" />
           <Text :fontSize="26" :text="`可采编:${item.collectModuleText || '暂无'}`" />
         </FlexCol>
-      </FlexRow>
+      </Touchable>
     </FlexCol>
     <SimplePageListLoader :loader="listLoader" :noEmpty="true">
       <template #empty>
@@ -120,6 +121,11 @@ function newData() {
   });
 }
 function goDetail(id: number) {
+  navTo('./admin/volunteer', { 
+    id,
+    villageId: querys.value.id,  
+    villageVolunteerId: querys.value.villageVolunteerId,  
+  });
 }
 function search() {
   listLoader.loadData(undefined, true);

+ 23 - 12
src/pages/dig/admin/volunteer.vue

@@ -36,7 +36,7 @@ import type { UploaderFieldProps } from '@/components/form/UploaderField.vue';
 import type { FieldProps } from '@/components/form/Field.vue';
 import type { PickerIdFieldProps } from '@/components/dynamic/wrappers/PickerIdField';
 import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
-import type { CheckBoxListProps } from '@/components/dynamic/wrappers/CheckBoxList.vue';
+import type { CheckBoxListItem, CheckBoxListProps } from '@/components/dynamic/wrappers/CheckBoxList.vue';
 import type { FormProps } from '@/components/form/Form.vue';
 
 const loading = ref(false);
@@ -49,9 +49,9 @@ const formDefine : IDynamicFormOptions = {
       label: '用户名', name: 'username', type: 'text',
       additionalProps: { 
         placeholder: '请输入用户名',
-        disabled: { callback: () => !isNew.value },
       },
       rules: [{ required: true, message: '请输入用户名' }],
+      show: { callback: () => isNew.value },
     },
     {
       label: '密码',
@@ -138,22 +138,33 @@ const formDefine : IDynamicFormOptions = {
       } as FieldProps,
     },
     { 
-      label: '采集版块', name: 'collectModule', type: 'check-box-list', 
+      label: '采集版块', name: 'catalogIds', type: 'check-box-list', 
       additionalProps: { 
         placeholder: '请选择采集版块',
         vertical: true,
         multiple: true,
-        loadData: async () => 
-          (await VillageApi.getCollectModuleList())
-            .map((p) => ({
-              text: p.label,
-              value: p.value,
-              raw: p
-            }))
-          ,
+        loadData: async () => {
+          async function getCatalogChildren(pid?: number, prefix?: string) {
+            const catalog = (await VillageApi.getCatalogList(querys.value.villageId, pid));
+            const res = [] as CheckBoxListItem[];
+            for (let p of catalog) {
+              res.push({
+                text: (prefix || '') + p.title,
+                value: p.id,
+              });
+              res.push(...(await getCatalogChildren(p.id, (prefix || '') + ' - ')));
+            }
+            return res;
+          }
+          return getCatalogChildren();
+        },
       } as CheckBoxListProps,
     },
-    { label: '村落认领说明', name: 'claimReason', type: 'text', additionalProps: { placeholder: '请输入村落认领说明' } },
+    { 
+      label: '村落认领说明', name: 'claimReason', type: 'text', 
+      additionalProps: { placeholder: '请输入村落认领说明' } ,
+      show: { callback: () => isNew.value },
+    },
   ],
   formAdditionaProps: {
     labelWidth: '160rpx',

+ 45 - 18
src/pages/dig/forms/common.vue

@@ -16,7 +16,7 @@
           :globalParams="querys"
         />
         <Height :height="20" />
-        <Button type="primary" @click="submit">提交</Button>
+        <Button type="primary" :loading="loading" @click="submit">提交</Button>
       </FlexCol>
       <XBarSpace />
     </CommonRoot>
@@ -32,7 +32,7 @@ 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 { Debounce, ObjectUtils, 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';
@@ -81,7 +81,7 @@ const { querys } = useLoadQuerys({
     return;
 
   let formData = undefined;
-  await waitTimeOut(200);
+  await waitTimeOut(800);
 
   try {
     currentFormInfo = getVillageInfoForm(querys.subType, querys.subId);
@@ -92,16 +92,38 @@ const { querys } = useLoadQuerys({
       ...forms(formRef as any)
     };
     if (querys.id >= 0) {
-      formData = await VillageInfoApi.getInfo(
-        collectStore.getCollectModuleId(querys.subType),
-        querys.subType, 
-        querys.subId,
-        querys.subKey,
-        querys.villageId, 
-        querys.villageVolunteerId,
-        querys.id,
-        model,
-      );
+      if (currentFormInfo?.[2].typeName && querys.subId == -1) {
+        const ids = getVillageInfoFormIds(querys.subType);
+        
+        for (const id of ids) {
+          try {
+            const data = await VillageInfoApi.getInfo(
+              collectStore.getCollectModuleId(querys.subType),
+              querys.subType, 
+              id,
+              querys.subKey,
+              querys.villageId, 
+              querys.villageVolunteerId,
+              querys.id,
+              model,
+            );
+            ObjectUtils.cloneValuesToObject(data, formModel.value);
+          } catch {
+            //ignore
+          }
+        }
+      } else {
+        formData = await VillageInfoApi.getInfo(
+          collectStore.getCollectModuleId(querys.subType),
+          querys.subType, 
+          querys.subId,
+          querys.subKey,
+          querys.villageId, 
+          querys.villageVolunteerId,
+          querys.id,
+          model,
+        );
+      }
     }
   } catch (e) {
     console.log(e);
@@ -111,12 +133,17 @@ const { querys } = useLoadQuerys({
     loading.value = false;
   }
     
-  formData = await loadLocalSave(formData as CommonInfoModel);
-  if (formData)
-    formModel.value = formData as any;
+  try {
+    formData = await loadLocalSave(formData as CommonInfoModel);
+    if (formData)
+      formModel.value = formData as any;
+  } catch (e) {
+    console.log(e);
+    showError(e, '加载本地保存数据失败');
+  }
 
   await nextTick();
-  await waitTimeOut(100);
+  await waitTimeOut(400);
   formRef.value.initDefaultValuesToModel();
 
   console.log(formModel.value);
@@ -135,7 +162,6 @@ async function submit() {
   }
   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);
@@ -161,6 +187,7 @@ async function submit() {
         formModel.value as CommonInfoModel,
       );
     }
+    deleteLocalSave();
     confirm({
       content: '您的提交已成功,感谢您的参与!',
       cancelText: '继续编辑',

+ 4 - 3
src/pages/dig/forms/data/common.ts

@@ -9,7 +9,7 @@ export function villageCommonContent (ref: Ref<IDynamicFormRef>, options: {
   title: string,
   showTitle?: boolean,
   showContent?: boolean,
-  showType?: boolean,
+  noType?: boolean,
   contentKey?: string,
 } = {
   title: '文章',
@@ -50,7 +50,7 @@ export function villageCommonContent (ref: Ref<IDynamicFormRef>, options: {
               message: '请输入介绍内容',
             }]
           },
-          {
+          ...(options.noType !== true ? [{
             label: `${options.title}类型`,
             name: 'type',
             type: 'select-id',
@@ -78,7 +78,8 @@ export function villageCommonContent (ref: Ref<IDynamicFormRef>, options: {
             additionalProps: {
               placeholder: '如果是转载文章可以输入来源',
             },
-          }]: []),
+          }] : []),
+          ]: []),
         ],
       },
       {

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

@@ -74,7 +74,7 @@ export const villageInfoOverviewForm : GroupForm = {
         } as RadioIdFieldProps,
       },
     ]
-  }), { title: '行政区划', typeName: '', order: 1 }],
+  }), { title: '行政区划', typeName: 'type', order: 1 }],
   [5]: [CommonInfoModel, () => ({
     formItems: [
       {
@@ -126,7 +126,7 @@ export const villageInfoOverviewForm : GroupForm = {
         ]
       },
     ] 
-  }), { title: '综述', typeName: '', order: 2 }],
+  }), { title: '综述', typeName: 'type', order: 2 }],
   [2]: [VillageEnvInfo, () => ({
     formItems: [
       { 
@@ -208,7 +208,7 @@ export const villageInfoOverviewForm : GroupForm = {
         formProps: { showRightArrow: true } as FieldProps,
       },
     ]
-  }), { title: '地理信息', typeName: '', order: 3 }],
+  }), { title: '地理信息', typeName: 'type', order: 3 }],
   [3]: [CommonInfoModel, () => ({
     formItems: [
       { 
@@ -286,7 +286,7 @@ export const villageInfoOverviewForm : GroupForm = {
         rules:  [] 
       }, 
     ]
-  }), { title: '建设与保护', typeName: '', order: 4 }],
+  }), { title: '建设与保护', typeName: 'type', order: 4 }],
   [4]: [CommonInfoModel, () => ({ 
     formItems: [
       {
@@ -475,5 +475,5 @@ export const villageInfoOverviewForm : GroupForm = {
         ]
       },
     ] 
-  }), { title: '人口与经济', typeName: '', order: 5 }],
+  }), { title: '人口与经济', typeName: 'type', order: 5 }],
 }

+ 6 - 5
src/pages/dig/forms/data/specker.ts

@@ -30,6 +30,12 @@ export const villageInfoSpeakerForm : SingleForm = [CommonInfoModel, (r) => ({
             message: '请输入姓名',
           }]
         },
+        ...villageCommonContent(r, {
+          title: '口述人',
+          showTitle: false,
+          showContent: true,
+          noType: true,
+        }).formItems,
         {
           label: '性别',
           name: 'sex',
@@ -112,11 +118,6 @@ export const villageInfoSpeakerForm : SingleForm = [CommonInfoModel, (r) => ({
           } as UploaderFieldProps,
           rules: []
         },
-        ...villageCommonContent(r, {
-          title: '口述人',
-          showTitle: false,
-          showContent: false,
-        }).formItems,
       ]
     },
   ]

+ 0 - 1
src/pages/dig/forms/forms.ts

@@ -123,7 +123,6 @@ const villageInfoForm : Record<string, GroupForm> = {
         ...villageCommonContent(r, {
           title: '记录',
           showTitle: false,
-          showType: true,
         }).formItems
       ]
     }), { title: '随手记', typeName: '', }]

+ 7 - 1
src/pages/dig/forms/list.vue

@@ -31,6 +31,7 @@
           :width="100"
           :height="100"
           :radius="10"
+          mode="aspectFill"
           round
         />
         <FlexCol>
@@ -70,6 +71,7 @@ import H4 from '@/components/typography/H4.vue';
 import Touchable from '@/components/feedback/Touchable.vue';
 import XBarSpace from '@/components/layout/space/XBarSpace.vue';
 import { useCollectStore } from '@/store/collect';
+import { onPullDownRefresh } from '@dcloudio/uni-app';
 
 const subTitle = ref('');
 const searchText = ref('');
@@ -97,7 +99,7 @@ const listLoader = useSimplePageListLoader<{
   let res = (page == 1 ? await VillageInfoApi.getList(
     collectStore.getCollectModuleId(params.subType),
     params.subType,
-    params.subId,
+    params.subKey ? params.subId : undefined,
     params.subKey,
     params.villageId,
     params.villageVolunteerId,
@@ -157,6 +159,10 @@ const { querys } = useLoadQuerys({
   listLoader.loadData(querys)
 });
 
+onPullDownRefresh(() => {
+  listLoader.loadData(undefined, true);
+});
+
 defineExpose({
   onPageBack(name: string, param: any) {
     if (param && param.needRefresh)