volunteer.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <template>
  2. <CommonRoot class="main">
  3. <LoadingPage v-if="loading" />
  4. <FlexCol :padding="30">
  5. <DynamicForm
  6. ref="formRef"
  7. :model="formModel"
  8. :options="formDefine"
  9. :formGlobalParams="querys"
  10. />
  11. <Height :height="20" />
  12. <Button type="primary" @click="submit">提交</Button>
  13. </FlexCol>
  14. </CommonRoot>
  15. </template>
  16. <script setup lang="ts">
  17. import { computed, nextTick, ref } from 'vue';
  18. import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
  19. import { useAliOssUploadCo } from '@/common/components/upload/AliOssUploadCo';
  20. import { showError } from '@/common/composeabe/ErrorDisplay';
  21. import { alert, toast } from '@/components/dialog/CommonRoot';
  22. import { backAndCallOnPageBack } from '@/components/utils/PageAction';
  23. import { RequestApiError } from '@imengyu/imengyu-utils';
  24. import DynamicForm from '@/components/dynamic/DynamicForm.vue';
  25. import LoadingPage from '@/components/display/loading/LoadingPage.vue';
  26. import Button from '@/components/basic/Button.vue';
  27. import CommonRoot from '@/components/dialog/CommonRoot.vue';
  28. import FlexCol from '@/components/layout/FlexCol.vue';
  29. import Height from '@/components/layout/space/Height.vue';
  30. import VillageApi, { VolunteerInfo } from '@/api/inhert/VillageApi';
  31. import CommonContent from '@/api/CommonContent';
  32. import type { RuleItem } from 'async-validator';
  33. import type { IDynamicFormOptions, IDynamicFormRef, IDynamicFormItemCallbackAdditionalProps } from '@/components/dynamic';
  34. import type { UploaderFieldProps } from '@/components/form/UploaderField.vue';
  35. import type { FieldProps } from '@/components/form/Field.vue';
  36. import type { PickerIdFieldProps } from '@/components/dynamic/wrappers/PickerIdField';
  37. import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
  38. import type { FormProps } from '@/components/form/Form.vue';
  39. import type { CheckBoxTreeListProps } from '@/components/dynamic/wrappers/CheckBoxTreeList.vue';
  40. const loading = ref(false);
  41. const formRef = ref<IDynamicFormRef>();
  42. const formModel = ref<VolunteerInfo>();
  43. const formDefine : IDynamicFormOptions = {
  44. formItems: [
  45. {
  46. name: 'groupBase',
  47. type: 'flat-simple',
  48. children: [
  49. {
  50. label: '用户名', name: 'username', type: 'text',
  51. additionalProps: {
  52. placeholder: '请输入用户名',
  53. },
  54. rules: [{ required: true, message: '请输入用户名' }],
  55. show: { callback: () => isNew.value },
  56. },
  57. {
  58. label: '密码',
  59. name: 'password',
  60. type: 'text',
  61. additionalProps: {
  62. placeholder: '请输入密码',
  63. type: 'password',
  64. } as FieldProps,
  65. rules: [{ required: true, message: '请输入密码' }],
  66. show: { callback: () => isNew.value || querys.value.onlyPassword },
  67. },
  68. {
  69. label: '确认密码',
  70. name: 'passwordRepeat',
  71. type: 'text',
  72. additionalProps: {
  73. placeholder: '请再输入一次密码',
  74. type: 'password',
  75. } as FieldProps,
  76. rules: [
  77. { required: true, message: '请再输入一次密码' },
  78. {
  79. async validator(rule, value) {
  80. if (value != formRef.value?.getValueByPath('password'))
  81. throw '两次输入密码不一致,请检查';
  82. },
  83. }
  84. ] as RuleItem[],
  85. show: { callback: () => isNew.value || querys.value.onlyPassword },
  86. },
  87. ]
  88. },
  89. {
  90. name: 'groupExtra',
  91. type: 'flat-simple',
  92. show: { callback: () => querys.value.onlyPassword == false },
  93. childrenColProps: {
  94. span: 24,
  95. },
  96. children: [
  97. {
  98. label: '真实名称', name: 'name', type: 'text',
  99. additionalProps: { placeholder: '请输入真实名称' },
  100. rules: [{ required: true, message: '请输入真实名称' }],
  101. },
  102. {
  103. label: '手机号', name: 'mobile', type: 'text',
  104. additionalProps: { placeholder: '请输入手机号' },
  105. rules: [{ required: true, message: '请输入手机号' }],
  106. },
  107. {
  108. label: '区域', name: 'regionId', type: 'select-id',
  109. additionalProps: {
  110. placeholder: '请选择区域',
  111. disabled: { callback: () => !isNew.value },
  112. loadData: async () => (await CommonContent.getCategoryList(1)).map(p => ({ text: p.title, value: p.id, raw: p }))
  113. } as IDynamicFormItemCallbackAdditionalProps<PickerIdFieldProps>,
  114. rules: [{ required: true, message: '请选择区域' }],
  115. },
  116. {
  117. label: '性别', name: 'sex', type: 'radio-value',
  118. additionalProps: {
  119. options: [
  120. { text: '男', value: 1 },
  121. { text: '女', value: 2 }
  122. ]
  123. } as RadioValueProps,
  124. },
  125. {
  126. label: '头像', name: 'image', type: 'uploader',
  127. additionalProps: {
  128. single: true,
  129. maxFileSize: 1024 * 1024 * 10,
  130. upload: useAliOssUploadCo('xiangyuan/volunteer/images')
  131. } as UploaderFieldProps,
  132. },
  133. { label: '地址', name: 'address', type: 'text', additionalProps: { placeholder: '请输入地址' } },
  134. {
  135. label: '介绍',
  136. name: 'intro',
  137. type: 'textarea',
  138. additionalProps: {
  139. placeholder: '请输入介绍',
  140. showWordLimit: true,
  141. maxLength: 200,
  142. } as FieldProps,
  143. },
  144. {
  145. label: '采集版块', name: 'catalogIds', type: 'check-box-tree',
  146. additionalProps: {
  147. placeholder: '请选择采集版块',
  148. vertical: true,
  149. multiple: true,
  150. loadData: async (pid) => (await VillageApi.getCatalogList(querys.value.villageId, pid)).map((p) => ({
  151. text: p.title,
  152. value: p.id,
  153. hasChildren: p.haschild,
  154. })),
  155. } as CheckBoxTreeListProps,
  156. },
  157. {
  158. label: '村落认领说明', name: 'claimReason', type: 'text',
  159. additionalProps: { placeholder: '请输入村落认领说明' } ,
  160. show: { callback: () => isNew.value },
  161. },
  162. ]
  163. },
  164. ],
  165. formAdditionaProps: {
  166. labelWidth: '160rpx',
  167. labelAlign: 'right',
  168. innerStyle: {
  169. radius: '10rpx',
  170. },
  171. } as Omit<FormProps, 'model'>,
  172. }
  173. async function submit() {
  174. if (!formRef.value || !formModel.value)
  175. return;
  176. try {
  177. await formRef.value.validate();
  178. } catch (e) {
  179. toast({ content: '有必填项未填写,请检查' });
  180. return;
  181. }
  182. try {
  183. loading.value = true;
  184. formModel.value!.villageId = querys.value.villageId;
  185. console.log('formModel.value', formModel.value);
  186. if (querys.value.id >= 0) {
  187. await VillageApi.updateVolunteer(formModel.value!);
  188. } else {
  189. await VillageApi.addVolunteer(formModel.value!);
  190. };
  191. alert({
  192. title: '操作成功',
  193. icon: 'success-filling',
  194. iconColor: 'success',
  195. content: isNew.value ? '新增志愿者信息成功' : '更新志愿者信息成功',
  196. onConfirm() {
  197. backPrev(true);
  198. },
  199. });
  200. } catch (e) {
  201. showError(e);
  202. } finally {
  203. loading.value = false;
  204. }
  205. }
  206. function backPrev(needRefresh: boolean) {
  207. backAndCallOnPageBack('list', {
  208. needRefresh,
  209. });
  210. }
  211. const { querys } = useLoadQuerys({
  212. villageId: 0,
  213. villageVolunteerId: 0,
  214. onlyPassword: false,
  215. id: 0,
  216. }, async (querys) => {
  217. loading.value = true;
  218. if (!formRef.value)
  219. return;
  220. let formData = undefined;
  221. try {
  222. formModel.value = new VolunteerInfo();
  223. if (querys.id >= 0)
  224. formData = await VillageApi.getVolunteerInfoByIdAdmin(querys.id);
  225. } catch (e) {
  226. if (!(e instanceof RequestApiError && e.errorMessage.startsWith('请完成')))
  227. showError(e, undefined, () => backPrev(false));
  228. } finally {
  229. loading.value = false;
  230. }
  231. if (formData) {
  232. formModel.value = formData;
  233. }
  234. await nextTick();
  235. formRef.value.initDefaultValuesToModel();
  236. console.log('formModel.value', formModel.value);
  237. });
  238. const isNew = computed(() => querys.value.id < 0);
  239. </script>