Pārlūkot izejas kodu

管理员志愿者管理页面

快乐的梦鱼 1 nedēļu atpakaļ
vecāks
revīzija
f89b5a5a8a

+ 40 - 0
src/api/inhert/VillageApi.ts

@@ -84,6 +84,8 @@ export class VolunteerInfo extends DataModel<VolunteerInfo> {
       id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
       points: [{ clientSide: 'number', serverSide: 'number' }, { clientSide: CONVERTER_ADD_DEFAULT, clientSideParam: { defaultValue: 0 } }],
       level: [{ clientSide: 'number', serverSide: 'number' }, { clientSide: CONVERTER_ADD_DEFAULT, clientSideParam: { defaultValue: 0 } }],
+      collectModule: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
+      birthday: { clientSide: 'date', serverSide: 'undefined' },
     }
   }
 
@@ -106,6 +108,8 @@ export class VolunteerInfo extends DataModel<VolunteerInfo> {
   typeText = '';
   sexText = '';
   statusText = '';
+  collectModule = [];
+  collectModuleText = '';
 }
 
 export class VillageMenuListItem extends DataModel<VillageMenuListItem> {
@@ -175,6 +179,42 @@ export class VillageApi extends AppServerRequestModule<DataModel> {
       .catch(e => { throw e });
   }
   
+  async addVolunteer(data: VolunteerInfo) {
+    return (this.post('/village/volunteer/add', data.toServerSide(), '添加志愿者')) ;
+  }
+  async updateVolunteer(data: VolunteerInfo) {
+    return (this.post('/village/volunteer/update', data.toServerSide(), '更新志愿者')) ;
+  }
+  async getVolunteerInfoById(id: number) {
+    return (await this.post('/village/volunteer/getInfo', {
+    }, '获取志愿者信息', undefined, VolunteerInfo)).data as VolunteerInfo
+  }
+  async getVillageVolunteerList(villageId?: number) {
+    return (this.post('/village/volunteer/getList', {
+      village_id: villageId,
+    }, '获取志愿者列表')) 
+      .then(res => transformArrayDataModel<VolunteerInfo>(VolunteerInfo, res.data2 || [], ``, true))
+      .catch(e => { throw e });
+  }
+  async getCollectModuleList() {
+    return (this.get('/village/volunteer/getCollectModuleList', '获取采集版块列表', {
+    })) 
+      .then(res => {
+        const result = [] as {
+          value: string,
+          label: string,
+        }[];
+        for (const key in res.data2) {
+          result.push({
+            value: key,
+            label: res.data2[key],
+          })
+        }
+        return result;
+      })
+      .catch(e => { throw e });
+  }
+
   async getVillageMenuList(id: number) {
     return (this.get('/village/menu/getList', '村落菜单列表', {
       village_id: id,

+ 2 - 0
src/components/dynamic/DynamicForm.vue

@@ -139,6 +139,8 @@ onMounted(() => {
 });
 
 defineExpose<FormExport>({
+  getFormRef: () => formRef.value,
+  getFormData: () => formModel.value,
   initFormData,
   loadFormData,
   submitForm,

+ 6 - 4
src/components/dynamic/DynamicFormControl.vue

@@ -12,6 +12,7 @@
       ref="formItemRef"
       v-else-if="formDefineItem.type === 'text'"
       :label="label"
+      :name="formDefineItem.fullName"
       :modelValue="modelValue"
       @update:modelValue="onValueChanged"
       :maxlength="260"
@@ -23,6 +24,7 @@
       v-else-if="formDefineItem.type === 'textarea'"
       multiline
       :label="label"
+      :name="formDefineItem.fullName"
       :modelValue="modelValue"
       :required="Boolean(formDefineItem.rules?.length)"
       @update:modelValue="onValueChanged"
@@ -58,7 +60,7 @@
           ref="itemRef"
           :modelValue="modelValue"
           @update:modelValue="onValueChanged"
-          v-bind="(params as any as IDynamicFormItemRadioValueFormItemProps)"
+          v-bind="(params as any as RadioValueProps)"
         />
       </template>
       <template v-else-if="formDefineItem.type === 'select'">
@@ -84,7 +86,7 @@
           ref="itemRef"
           :modelValue="modelValue"
           @update:modelValue="onValueChanged"
-          v-bind="(params as any as IDynamicFormItemSelectIdFormItemProps)"
+          v-bind="(params as any as PickerIdFieldProps)"
         />
       </template>
       <template v-else-if="formDefineItem.type === 'select-city'">
@@ -194,8 +196,8 @@ import RadioValue from './wrappers/RadioValue.vue';
 import PickerIdField from './wrappers/PickerIdField.vue';
 import CheckBoxList from './wrappers/CheckBoxList.vue';
 import CheckBoxToInt from './wrappers/CheckBoxToInt.vue';
-import type { IDynamicFormItemRadioValueFormItemProps } from './wrappers/RadioValue';
-import type { IDynamicFormItemSelectIdFormItemProps } from './wrappers/PickerIdField';
+import type { RadioValueProps } from './wrappers/RadioValue';
+import type { PickerIdFieldProps } from './wrappers/PickerIdField';
 import PickerCityField from './wrappers/PickerCityField.vue';
 import PickerLonlat from './wrappers/PickerLonlat.vue';
 import DateTimePickerField from '../form/DateTimePickerField.vue';

+ 11 - 0
src/components/dynamic/index.ts

@@ -1,4 +1,5 @@
 import type { RuleItem } from "async-validator";
+import type { FormInstance } from "../form/Form.vue";
 
 export interface FormDefine {
   /**
@@ -104,6 +105,16 @@ export interface FormExport {
    */
   initFormData(data: () => any): void;
   /**
+   * 获取表单实例
+   * @returns 表单实例
+   */
+  getFormRef(): FormInstance;
+  /**
+   * 获取表单数据
+   * @returns 表单数据
+   */
+  getFormData(): Record<string, any>;
+  /**
    * 加载表单数据
    * @param value 表单数据
    */

+ 9 - 4
src/components/dynamic/wrappers/CheckBoxList.vue

@@ -1,5 +1,5 @@
 <template>
-  <FlexRow align="center" wrap>
+  <FlexView :direction="vertical ? 'column' : 'row'" align="center" :gap="10" wrap>
     <ActivityIndicator v-if="loadStatus === 'loading'" />
     <Alert
       v-else-if="loadStatus === 'error'" 
@@ -23,7 +23,7 @@
         :disabled="value.disable"
       />
     </CheckBoxGroup>
-  </FlexRow>
+  </FlexView>
 </template>
 
 <script setup lang="ts">
@@ -31,7 +31,7 @@ import ActivityIndicator from '@/components/basic/ActivityIndicator.vue';
 import Alert from '@/components/feedback/Alert.vue';
 import CheckBox from '@/components/form/CheckBox.vue';
 import CheckBoxGroup from '@/components/form/CheckBoxGroup.vue';
-import FlexRow from '@/components/layout/FlexRow.vue';
+import FlexView from '@/components/layout/FlexView.vue';
 import { onMounted, ref, type PropType } from 'vue';
 
 export interface CheckBoxListItem {
@@ -42,6 +42,7 @@ export interface CheckBoxListItem {
 export interface CheckBoxListProps {
   multiple?: boolean,
   disabled?: boolean,
+  vertical?: boolean,
   className?: string,
   loadData: () => Promise<CheckBoxListItem[]>;
 }
@@ -66,7 +67,11 @@ const props = defineProps({
   className: {
     type: String,
     default: ''
-  }
+  },
+  vertical: {
+    type: Boolean,
+    default: false
+  },
 })
 const emit = defineEmits(['update:modelValue', 'change'])
 

+ 4 - 8
src/components/dynamic/wrappers/PickerIdField.ts

@@ -1,22 +1,18 @@
 import type { PickerFieldProps } from "@/components/form/PickerField.vue";
 
-export interface IDynamicFormItemSelectIdOption {
+export interface PickerIdFieldOption {
   text: string,
   value: string|number,
 }
 
-export interface IDynamicFormItemSelectIdFormItemProps extends PickerFieldProps {
+export interface PickerIdFieldProps extends Omit<PickerFieldProps, 'columns'> {
   /**
    * 是否禁用
    */
-  disabled: boolean;
+  disabled?: boolean;
   /**
    * 加载选项数据
    * @returns 
    */
-  loadData: () => Promise<IDynamicFormItemSelectIdOption[]>;
-  /**
-   * 选择值
-   */
-  value: unknown;
+  loadData: () => Promise<PickerIdFieldOption[]>;
 }

+ 9 - 3
src/components/dynamic/wrappers/PickerIdField.vue

@@ -7,11 +7,17 @@
 
 <script setup lang="ts">
 import PickerField from '@/components/form/PickerField.vue';
-import type { IDynamicFormItemSelectIdFormItemProps, IDynamicFormItemSelectIdOption } from './PickerIdField';
+import type { PickerIdFieldProps, PickerIdFieldOption } from './PickerIdField';
 import { useDataLoader } from '@/components/composeabe/DataLoader';
 
-const props = defineProps<IDynamicFormItemSelectIdFormItemProps>();
-const loader = useDataLoader<IDynamicFormItemSelectIdOption[]>(props.loadData, {
+const props = defineProps<PickerIdFieldProps>();
+const loader = useDataLoader<PickerIdFieldOption[]>(async () => {
+  const res = await props.loadData();
+  return ([{
+    text: '请选择',
+    value: '',
+  }] as PickerIdFieldOption[]).concat(res);
+}, {
   immediate: true,
 });
 </script>

+ 4 - 8
src/components/dynamic/wrappers/RadioValue.ts

@@ -1,19 +1,15 @@
-export interface IDynamicFormItemRadioValueOption {
+export interface RadioValueOption {
   text: string,
   value: unknown,
 }
 
-export interface IDynamicFormItemRadioValueFormItemProps {
+export interface RadioValueProps {
   /**
    * 是否禁用
    */
-  disabled: boolean;
+  disabled?: boolean;
   /**
    * 选项数据
    */
-  options: IDynamicFormItemRadioValueOption[];
-  /**
-   * 选择值
-   */
-  value: unknown;
+  options: RadioValueOption[];
 }

+ 25 - 15
src/components/dynamic/wrappers/RadioValue.vue

@@ -1,24 +1,27 @@
 <template>
-  <RadioGroup
-    :value="selectValue"
-    @update:value="onUpdateValue"
-    :disabled="disabled"
-    v-bind="$attrs"
-  >
-    <Radio
-      v-for="it in options"
-      :key="(it.value as string)"
-      :name="(it.value as string)"
-      :label="it.text"
-    />
-  </RadioGroup>
+  <FlexView :direction="vertical ? 'column' : 'row'" align="center" :gap="10" wrap>
+    <RadioGroup
+      :value="selectValue"
+      @update:value="onUpdateValue"
+      :disabled="disabled"
+      v-bind="$attrs"
+    >
+      <Radio
+        v-for="it in options"
+        :key="(it.value as string)"
+        :name="(it.value as string)"
+        :text="it.text"
+      />
+    </RadioGroup>
+  </FlexView>
 </template>
 
 <script lang="ts" setup>
 import { type PropType, ref, watch, onMounted } from 'vue';
 import RadioGroup from '@/components/form/RadioGroup.vue';
 import Radio from '@/components/form/Radio.vue';
-import type { IDynamicFormItemRadioValueOption } from './RadioValue';
+import type { RadioValueOption } from './RadioValue';
+import FlexView from '@/components/layout/FlexView.vue';
 
 const props = defineProps({
   /**
@@ -29,10 +32,17 @@ const props = defineProps({
     default: false
   },
   /**
+   * 是否垂直方向
+   */
+  vertical: {
+    type: Boolean,
+    default: false
+  },
+  /**
    * 选项数据
    */
   options: {
-    type: Object as PropType<IDynamicFormItemRadioValueOption[]>,
+    type: Object as PropType<RadioValueOption[]>,
     default: null,
   },
   modelValue: {

+ 9 - 3
src/components/form/Field.vue

@@ -18,16 +18,22 @@
       v-if="showLabel !== false && label" 
       align="center" 
       :flex="labelFlex"
+      :innerStyle="{
+        width: labelWidth,
+      }"
+      :justify="selectStyleType(labelAlign, 'left', {
+        left: 'flex-start',
+        center: 'center',
+        right: 'flex-end',
+      })"
     >
       <text v-if="requiredShow && showRequiredBadge" :style="themeStyles.requiredMark.value">*</text>
       <slot name="leftIcon" />
       <view v-if="!label" :style="labelStyle" />
       <text v-else :style="{
         ...themeStyles.labelText.value,
-        width: labelWidth,
-        textAlign: labelAlign,
-        color: themeContext.resolveThemeColor(disabled ? labelDisableColor : labelColor),
         ...labelStyle,
+        color: themeContext.resolveThemeColor(disabled ? labelDisableColor : labelColor),
       }">
         {{ label + (colon ? ': ' : '') }}
       </text>

+ 5 - 3
src/components/form/Form.vue

@@ -1,6 +1,8 @@
 <template>
-  <form class="nana-form" :name="name" :style="innerStyle">
-    <slot />
+  <form class="nana-form" :name="name">
+    <view :style="innerStyle">
+      <slot />
+    </view>
   </form>
 </template>
 
@@ -281,7 +283,7 @@ function validate(name?: string|string[]) {
         filteredRules[key] = rule;
     }
   });
-
+  
   //获取当前参数
   const nowValues = model.value;
 

+ 7 - 0
src/pages.json

@@ -55,6 +55,13 @@
       }
     },
     {
+      "path": "pages/dig/admin/volunteer",
+      "style": {
+        "navigationBarTitleText": "乡源·乡村文化资源挖掘平台-志愿者管理",
+        "enablePullDownRefresh": false
+      }
+    },
+    {
       "path": "pages/dig/task/environment",
       "style": {
         "navigationBarTitleText": "乡源·乡村文化资源挖掘平台-环境格局",

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

@@ -1,11 +1,56 @@
 <template>
-  <web-view :src="src" />
+  <FlexCol :padding="30">
+    <FlexRow justify="space-between">
+      <SearchBar
+        v-model="searchText"
+        placeholder="搜一搜" 
+        :innerStyle="{ width: '460rpx' }"
+        @confirm="search"
+      />
+      <Button type="primary" @click="newData">+ 新增</Button>
+    </FlexRow>
+    <FlexCol :gap="20" :margin="[20,0,0,0]">
+      <FlexRow 
+        v-for="item in listLoader.list.value"
+        :key="item.id" 
+        backgroundColor="white" 
+        radius="20"
+        :padding="20"
+        @click="goDetail(item.id)"
+      >
+        <Image :src="item.image" width="170rpx" height="170rpx" />
+        <FlexCol>
+          <Text :fontSize="36" bold :text="`${item.name} ${item.sex === 0 ? '男' : '女'}`" />
+          <Text :fontSize="26" :text="`手机:${item.mobile}`" />
+          <Text :fontSize="26" :text="`地址:${item.address || ''}`" />
+          <Text :fontSize="26" :text="`可采编:${item.collectModuleText || '暂无'}`" />
+        </FlexCol>
+      </FlexRow>
+    </FlexCol>
+    <SimplePageListLoader :loader="listLoader" :noEmpty="true">
+      <template #empty>
+        <Empty image="search" text="暂无数据,点击按钮新增数据">
+          <Button type="primary" @click="newData">+ 新增数据</Button>
+        </Empty>
+      </template>
+    </SimplePageListLoader>
+  </FlexCol>
 </template>
 
 <script setup lang="ts">
+import VillageApi from '@/api/inhert/VillageApi';
+import SimplePageListLoader from '@/common/components/SimplePageListLoader.vue';
 import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
-import { useAuthStore } from '@/store/auth';
-import { computed } from 'vue';
+import { useSimplePageListLoader } from '@/common/composeabe/SimplePageListLoader';
+import Button from '@/components/basic/Button.vue';
+import Image from '@/components/basic/Image.vue';
+import Text from '@/components/basic/Text.vue';
+import Empty from '@/components/feedback/Empty.vue';
+import SearchBar from '@/components/form/SearchBar.vue';
+import FlexCol from '@/components/layout/FlexCol.vue';
+import FlexRow from '@/components/layout/FlexRow.vue';
+import { navTo } from '@/components/utils/PageAction';
+import { ref } from 'vue';
 
 const { querys } = useLoadQuerys({ 
   id: 0,  
@@ -13,11 +58,43 @@ const { querys } = useLoadQuerys({
   points: 0,
   level: 0,
   villageVolunteerId: 0,
+}, () => {
+  listLoader.loadData(undefined, true);
 });
-const authStore = useAuthStore();
-const src = computed(() => {
-  const url = `https://mn.wenlvti.net/test8/#/admin?id=${querys.value.id}&internalAuth=${encodeURIComponent(JSON.stringify(authStore.getInternalAuth()))}&t=${Date.now()}`
-  console.log(url);
-  return url;
+
+const searchText = ref('');
+const listLoader = useSimplePageListLoader(8, async (page, pageSize, params) => {
+  if (page === 1) {
+    let res = await VillageApi.getVillageVolunteerList(querys.value.id);
+    if (searchText.value)
+      res = res.filter((p) => p.name.includes(searchText.value));
+    return {
+      page,
+      total: res.length,
+      list: res.map((item) => ({
+        ...item,
+        title: `${item.name} ${item.sex === 0 ? '男' : '女'} 手机号:${item.mobile} 地址:${item.address || ''}`,
+        desc: `可采编:${item.collectModuleText || '暂无'}`,
+      })),
+    }
+  }
+  return {
+    page,
+    total: 0,
+    list: [],
+  }
 });
+
+function newData() {
+  navTo('./admin/volunteer', { 
+    id: -1,
+    villageId: querys.value.id,  
+    villageVolunteerId: querys.value.villageVolunteerId,  
+  });
+}
+function goDetail(id: number) {
+}
+function search() {
+  listLoader.loadData(undefined, true);
+}
 </script>

+ 217 - 0
src/pages/dig/admin/volunteer.vue

@@ -0,0 +1,217 @@
+<template>
+  <CommonRoot class="main">
+    <LoadingPage v-if="loading" /> 
+    <FlexCol :padding="30">
+      <DynamicForm
+        ref="formRef"
+        :formDefine="formDefine"
+        :formProps="({
+          labelWidth: '160rpx',
+          labelAlign: 'right',
+          innerStyle: {
+            radius: '10rpx',
+          },
+        })"
+        :formGlobalParams="querys"
+      />
+      <Height :height="20" />
+      <Button type="primary" @click="submit">提交</Button>
+    </FlexCol>
+  </CommonRoot>
+</template>
+
+<script setup lang="ts">
+import { computed, ref } from 'vue';
+import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
+import { useAliOssUploadCo } from '@/common/components/upload/AliOssUploadCo';
+import { showError } from '@/common/composeabe/ErrorDisplay';
+import { alert } from '@/components/dialog/CommonRoot';
+import { backAndCallOnPageBack } from '@/components/utils/PageAction';
+import { RequestApiError } from '@imengyu/imengyu-utils';
+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 Height from '@/components/layout/space/Height.vue';
+import VillageApi, { VolunteerInfo } from '@/api/inhert/VillageApi';
+import CommonContent from '@/api/CommonContent';
+import type { RuleItem } from 'async-validator';
+import type { FormDefine, FormExport, IFormItemCallbackAdditionalProps } from '@/components/dynamic';
+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';
+
+const loading = ref(false);
+
+const formRef = ref<FormExport>();
+const formDefine : FormDefine = {
+  items: [
+    { 
+      label: '用户名', name: 'username', type: 'text',
+      params: { 
+        placeholder: '请输入用户名',
+        disabled: { callback: () => !isNew.value },
+      },
+      rules: [{ required: true, message: '请输入用户名' }],
+    },
+    {
+      label: '密码',
+      name: 'password',
+      type: 'text',
+      params: { 
+        placeholder: '请输入密码',
+        type: 'password',
+      } as FieldProps,
+      rules: [{ required: true, message: '请输入密码' }],
+    },
+    {
+      label: '确认密码',
+      name: 'passwordRepeat',
+      type: 'text',
+      params: { 
+        placeholder: '请再输入一次密码',
+        type: 'password',
+      } as FieldProps,
+      rules: [
+        { required: true, message: '请再输入一次密码' },
+        {
+          async validator(rule, value) {
+            if (value !== formRef.value?.getFormData().password)
+              throw '两次输入密码不一致,请检查';
+          },
+        }
+      ] as RuleItem[],
+    },
+    {
+      label: '真实名称', name: 'name', type: 'text',
+      params: { placeholder: '请输入真实名称' },
+      rules: [{ required: true, message: '请输入真实名称' }],
+    },
+    {
+      label: '手机号', name: 'mobile', type: 'text',
+      params: { placeholder: '请输入手机号' },
+      rules: [{ required: true, message: '请输入手机号' }],
+    },
+    { 
+      label: '区域', name: 'regionId', type: 'select-id',
+      params: {
+        placeholder: '请选择区域',
+        disabled: { callback: () => !isNew.value },
+        loadData: async () => (await CommonContent.getCategoryList(1)).map(p => ({ text: p.title, value: p.id, raw: p }))
+      } as IFormItemCallbackAdditionalProps<PickerIdFieldProps>,
+      rules: [{ required: true, message: '请选择区域' }],
+    },
+    { 
+      label: '所属村庄', name: 'villageId', type: 'select-id',
+      params: {
+        placeholder: '请选择所属村庄',
+        disabled: { callback: () => !isNew.value },
+        loadData: async () => (await VillageApi.getClaimedVallageList()).map(p => ({ text: p.title, value: p.id, raw: p })),
+      } as IFormItemCallbackAdditionalProps<PickerIdFieldProps>,
+      rules: [{ required: true, message: '请选择所属村庄' }],
+    },
+    {
+      label: '性别', name: 'sex', type: 'radio-value',
+      params: {
+        options: [
+          { text: '男', value: 1 },
+          { text: '女', value: 2 }
+        ]
+      } as RadioValueProps,
+    },
+    { 
+      label: '头像', name: 'image', type: 'uploader',
+      params: {
+        single: true,
+        maxFileSize: 1024 * 1024 * 10,
+        upload: useAliOssUploadCo('xiangyuan/volunteer/images')
+      } as UploaderFieldProps,
+    },
+    { label: '地址', name: 'address', type: 'text', params: { placeholder: '请输入地址' } },
+    { label: '介绍', name: 'intro', type: 'textarea', params: { placeholder: '请输入介绍' } },
+    { 
+      label: '采集版块', name: 'collectModule', type: 'check-box-list', 
+      params: { 
+        placeholder: '请选择采集版块',
+        vertical: true,
+        multiple: true,
+        loadData: async () => 
+          (await VillageApi.getCollectModuleList())
+            .map((p) => ({
+              text: p.label,
+              value: p.value,
+              raw: p
+            }))
+          ,
+      } as CheckBoxListProps,
+    },
+    { label: '村落认领说明', name: 'claimReason', type: 'text', params: { placeholder: '请输入村落认领说明' } },
+  ],
+}
+
+async function submit() {
+  if (!formRef.value)
+    return;
+  try {
+    const data = await formRef.value.submitForm<VolunteerInfo>();
+    if (!data)
+      return;
+    loading.value = true;
+    if (querys.value.id >= 0) {
+      await VillageApi.updateVolunteer(data);
+    } else {
+      await VillageApi.addVolunteer(data);
+    };
+    alert({
+      title: '操作成功',
+      icon: 'success-filling',
+      iconColor: 'success',
+      content: isNew.value ? '新增志愿者信息成功' : '更新志愿者信息成功',
+      onConfirm() {
+        backPrev(true);
+      },
+    });
+  } catch (e) {
+    showError(e);
+  } finally {
+    loading.value = false;
+  }
+}
+function backPrev(needRefresh: boolean) {
+  backAndCallOnPageBack('list', {
+    needRefresh,
+  });
+}
+
+const { querys } = useLoadQuerys({ 
+  villageId: 0,  
+  villageVolunteerId: 0,
+  id: 0,
+}, async (querys) => {
+  loading.value = true;
+  if (!formRef.value)
+    return;
+
+  let formData = undefined;
+
+  try {
+    formRef.value.initFormData(() => new VolunteerInfo());
+    if (querys.id >= 0)
+      formData = await VillageApi.getVolunteerInfoById(querys.id);
+  } catch (e) {
+    if (!(e instanceof RequestApiError && e.errorMessage.startsWith('请完成')))
+      showError(e, undefined, () => backPrev(false));
+  } finally {
+    loading.value = false;
+  }
+
+  if (formData) {
+    formRef.value.loadFormData(formData);
+  }
+});
+const isNew = computed(() => querys.value.id < 0);
+
+</script>

+ 4 - 2
src/pages/dig/forms/common.vue

@@ -8,6 +8,10 @@
         :formProps="({
           labelWidth: '160rpx',
           labelAlign: 'left',
+          innerStyle: {
+            borderRadius: '20rpx',
+            overflow: 'hidden',
+          },
         })"
         :formGlobalParams="querys"
       />
@@ -33,7 +37,6 @@ import type { FormDefine, FormExport } from '@/components/dynamic';
 import Height from '@/components/layout/space/Height.vue';
 import { backAndCallOnPageBack } from '@/components/utils/PageAction';
 
-const popupRef = ref();
 const loading = ref(false);
 
 const formRef = ref<FormExport>();
@@ -54,7 +57,6 @@ async function submit() {
       querys.value.villageVolunteerId,
       data,
     );
-    popupRef.value.open();
   } catch (e) {
     showError(e);
   } finally {

+ 23 - 23
src/pages/dig/forms/forms.ts

@@ -4,7 +4,7 @@ import type { FormDefine, FormDefineItem, IFormItemCallbackAdditionalProps } fro
 import type { FormGroupProps } from "@/components/dynamic/DynamicFormCate.vue";
 import type { CheckBoxListProps } from "@/components/dynamic/wrappers/CheckBoxList.vue";
 import type { CheckBoxToIntProps } from "@/components/dynamic/wrappers/CheckBoxToInt";
-import type { IDynamicFormItemSelectIdFormItemProps } from "@/components/dynamic/wrappers/PickerIdField";
+import type { PickerIdFieldProps } from "@/components/dynamic/wrappers/PickerIdField";
 import type { FieldProps } from "@/components/form/Field.vue";
 import type { PickerFieldProps } from "@/components/form/PickerField.vue";
 import type { StepperProps } from "@/components/form/Stepper.vue";
@@ -53,7 +53,7 @@ const villageInfoBuildingForm : SingleForm = [VillageBulidingInfo, {
             text: p.title,
           }))
         ,
-      } as IDynamicFormItemSelectIdFormItemProps,
+      } as PickerIdFieldProps,
       itemParams: { showRightArrow: true } as FieldProps,
       rules: [{
         required: true,
@@ -85,7 +85,7 @@ const villageInfoBuildingForm : SingleForm = [VillageBulidingInfo, {
             text: p.title,
           }))
         ,
-      } as IDynamicFormItemSelectIdFormItemProps,
+      } as PickerIdFieldProps,
       itemParams: { showRightArrow: true } as FieldProps,
       rules: [{
         required: true,
@@ -117,7 +117,7 @@ const villageInfoBuildingForm : SingleForm = [VillageBulidingInfo, {
             text: p.title,
           }))
         ,
-      } as IDynamicFormItemSelectIdFormItemProps,
+      } as PickerIdFieldProps,
       itemParams: { showRightArrow: true } as FieldProps,
       rules: [{
         required: true,
@@ -460,7 +460,7 @@ const villageInfoFolkCultureForm : SingleForm = [VillageBulidingInfo, {
               text: p.title,
             }))
         },
-      } as IFormItemCallbackAdditionalProps<IDynamicFormItemSelectIdFormItemProps>,
+      } as IFormItemCallbackAdditionalProps<PickerIdFieldProps>,
       itemParams: { showRightArrow: true } as FieldProps,
       rules: [],
     },
@@ -579,7 +579,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -682,7 +682,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -706,7 +706,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -740,7 +740,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -759,7 +759,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -958,7 +958,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                       text: p.title,
                     }))
                   ,
-                } as IDynamicFormItemSelectIdFormItemProps,
+                } as PickerIdFieldProps,
                 itemParams: { showRightArrow: true } as FieldProps,
                 rules: [],
               })),
@@ -1256,7 +1256,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1275,7 +1275,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1515,7 +1515,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1556,7 +1556,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1575,7 +1575,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1754,7 +1754,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1773,7 +1773,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1818,7 +1818,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1837,7 +1837,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1856,7 +1856,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -1875,7 +1875,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,
@@ -2160,7 +2160,7 @@ const villageInfoForm : Record<string, Record<number, SingleForm>> = {
                 text: p.title,
               }))
             ,
-          } as IDynamicFormItemSelectIdFormItemProps,
+          } as PickerIdFieldProps,
           itemParams: { showRightArrow: true } as FieldProps,
           rules: [{
             required: true,