share-reg-page.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <template>
  2. <CommonRoot>
  3. <FlexCol :gap="20" :padding="30">
  4. <!--完成-->
  5. <Result
  6. v-if="step === 'already'"
  7. status="success"
  8. title="您已经是志愿者"
  9. desc="赶快去采编村社文化资源信息吧"
  10. >
  11. <Height :size="20" />
  12. <Button type="primary" @click="navTo('/pages/index')">返回首页</Button>
  13. </Result>
  14. <!--注册-->
  15. <FlexCol v-else-if="step === 'register'" center>
  16. <FlexCol :padding="30">
  17. <DynamicForm
  18. ref="registerFormRef"
  19. :model="registerFormModel"
  20. :options="registerFormDefine"
  21. :formGlobalParams="querys"
  22. />
  23. <Height :height="20" />
  24. <Button type="primary" @click="registerSubmit" :loading="registerFormLoading">提交</Button>
  25. </FlexCol>
  26. </FlexCol>
  27. <!--注册完成-->
  28. <Result
  29. v-if="step === 'finished'"
  30. status="success"
  31. title="注册志愿者成功"
  32. desc="请等待管理员审核,在此期间,可以在社区中先逛逛,学习如何采编村社文化资源信息吧"
  33. >
  34. <Height :size="20" />
  35. <Button type="primary" @click="navTo('/pages/index')">进入首页</Button>
  36. </Result>
  37. <!--登录-->
  38. <FlexCol v-else center :height="400">
  39. <Icon icon="smile-filling" color="primary" :size="156" />
  40. <Height :height="20" />
  41. <Text :fontSize="26" color="primary" text="欢迎注册,加入志愿者队伍" />
  42. <Height :size="40" />
  43. <!-- #ifdef MP-WEIXIN -->
  44. <Button type="primary" block text="微信登录" @click="loginWechat" />
  45. <Height :size="20" />
  46. <!-- #endif -->
  47. <!-- #ifndef MP-WEIXIN -->
  48. <Result status="warning" title="提示" desc="当前环境不支持微信登录" />
  49. <!-- #endif -->
  50. </FlexCol>
  51. </FlexCol>
  52. </CommonRoot>
  53. </template>
  54. <script setup lang="ts">
  55. import Button from '@/components/basic/Button.vue';
  56. import Result from '@/components/feedback/Result.vue';
  57. import FlexCol from '@/components/layout/FlexCol.vue';
  58. import Height from '@/components/layout/space/Height.vue';
  59. import Icon from '@/components/basic/Icon.vue';
  60. import Text from '@/components/basic/Text.vue';
  61. import CommonRoot from '@/components/dialog/CommonRoot.vue';
  62. import DynamicForm from '@/components/dynamic/DynamicForm.vue';
  63. import { navTo } from '@/components/utils/PageAction';
  64. import { useAuthStore } from '@/store/auth';
  65. import { useAliOssUploadCo } from '@/common/components/upload/AliOssUploadCo';
  66. import { closeToast, toast } from '@/components/dialog/CommonRoot';
  67. import { showError } from '@/common/composeabe/ErrorDisplay';
  68. import { useLoadQuerys } from '@/common/composeabe/LoadQuerys';
  69. import { onMounted, ref } from 'vue';
  70. import VillageApi, { type VolunteerInfo } from '@/api/inhert/VillageApi';
  71. import CommonContent from '@/api/CommonContent';
  72. import type { IDynamicFormItemCallbackAdditionalProps, IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
  73. import type { FieldProps } from '@/components/form/Field.vue';
  74. import type { RuleItem } from 'async-validator';
  75. import type { PickerIdFieldProps } from '@/components/dynamic/wrappers/PickerIdField';
  76. import type { RadioValueProps } from '@/components/dynamic/wrappers/RadioValue';
  77. import type { UploaderFieldProps } from '@/components/form/UploaderField.vue';
  78. import type { FormProps } from '@/components/form/Form.vue';
  79. import { useAppInit } from '@/common/composeabe/AppInit';
  80. import { UserApi } from '@/api/auth/UserApi';
  81. /**
  82. * 分享注册页面
  83. *
  84. * 用户从管理员分享链接进入,需要注册为志愿者
  85. * 0. 如果已经登录,且有志愿者信息,直接跳转已经注册页, 否则进入注册流程
  86. * 1. 登录微信, 登录成功后, 如果有志愿者信息, 直接跳转成功页, 否则进入注册流程
  87. * 2. 注册流程中, 提交成功后, 跳转成功页
  88. */
  89. const authStore = useAuthStore();
  90. const { init } = useAppInit();
  91. const { querys } = useLoadQuerys({
  92. villageId: 0,
  93. });
  94. const step = ref<''|'register'|'finished'|'already'>('');
  95. onMounted(() => {
  96. if (authStore.isLogged) {
  97. if (authStore.userInfo?.villageVolunteer)
  98. step.value = 'already';
  99. else
  100. step.value = 'register';
  101. }
  102. });
  103. function loginWechat() {
  104. toast({
  105. type: 'loading',
  106. content: '登录中...',
  107. })
  108. Promise.all([
  109. uni.login({ provider: 'weixin' }),
  110. uni.getUserProfile({ desc: '用于完善会员资料' }),
  111. ])
  112. .then((res) => {
  113. authStore.loginWechart(res[0].code, res[1]).then((res) => {
  114. toast({
  115. type: 'success',
  116. content: '登录成功',
  117. });
  118. if (res.villageVolunteer) {
  119. //有志愿者信息,表示是志愿者,直接跳转
  120. step.value = 'already';
  121. return;
  122. }
  123. step.value = 'register';
  124. }).catch(showError);
  125. })
  126. .catch(showError)
  127. .finally(() => closeToast());
  128. }
  129. const registerFormLoading = ref(false);
  130. const registerFormRef = ref<IDynamicFormRef>();
  131. const registerFormModel = ref<VolunteerInfo>();
  132. const registerFormDefine : IDynamicFormOptions = {
  133. formItems: [
  134. {
  135. name: 'groupBase',
  136. type: 'flat-simple',
  137. children: [
  138. {
  139. label: '登录账号', name: 'username', type: 'text',
  140. additionalProps: {
  141. placeholder: '请输入用户名',
  142. },
  143. rules: [{ required: true, message: '请输入用户名' }],
  144. },
  145. {
  146. label: '密码',
  147. name: 'password',
  148. type: 'text',
  149. additionalProps: {
  150. placeholder: '请输入密码',
  151. type: 'password',
  152. } as FieldProps,
  153. rules: [{ required: true, message: '请输入密码' }],
  154. },
  155. {
  156. label: '确认密码',
  157. name: 'passwordRepeat',
  158. type: 'text',
  159. additionalProps: {
  160. placeholder: '请再输入一次密码',
  161. type: 'password',
  162. } as FieldProps,
  163. rules: [
  164. { required: true, message: '请再输入一次密码' },
  165. {
  166. async validator(rule, value) {
  167. if (value != registerFormRef.value?.getValueByPath('password'))
  168. throw '两次输入密码不一致,请检查';
  169. },
  170. }
  171. ] as RuleItem[],
  172. },
  173. ]
  174. },
  175. {
  176. name: 'groupExtra',
  177. type: 'flat-simple',
  178. childrenColProps: {
  179. span: 24,
  180. },
  181. children: [
  182. {
  183. label: '真实名称', name: 'name', type: 'text',
  184. additionalProps: { placeholder: '请输入真实名称' },
  185. rules: [{ required: true, message: '请输入真实名称' }],
  186. },
  187. {
  188. label: '手机号', name: 'mobile', type: 'text',
  189. additionalProps: { placeholder: '请输入手机号' },
  190. rules: [{ required: true, message: '请输入手机号' }],
  191. },
  192. {
  193. label: '区域', name: 'regionId', type: 'select-id',
  194. additionalProps: {
  195. placeholder: '请选择区域',
  196. loadData: async () => (await CommonContent.getCategoryList(1)).map(p => ({ text: p.title, value: p.id, raw: p }))
  197. } as IDynamicFormItemCallbackAdditionalProps<PickerIdFieldProps>,
  198. rules: [{ required: true, message: '请选择区域' }],
  199. },
  200. {
  201. label: '性别', name: 'sex', type: 'radio-value',
  202. additionalProps: {
  203. options: [
  204. { text: '男', value: 1 },
  205. { text: '女', value: 2 }
  206. ]
  207. } as RadioValueProps,
  208. },
  209. {
  210. label: '头像', name: 'image', type: 'uploader',
  211. additionalProps: {
  212. single: true,
  213. maxFileSize: 1024 * 1024 * 10,
  214. upload: useAliOssUploadCo('xiangyuan/volunteer/images')
  215. } as UploaderFieldProps,
  216. },
  217. { label: '地址', name: 'address', type: 'text', additionalProps: { placeholder: '请输入地址' } },
  218. {
  219. label: '介绍',
  220. name: 'intro',
  221. type: 'textarea',
  222. additionalProps: {
  223. placeholder: '请输入介绍',
  224. showWordLimit: true,
  225. maxLength: 200,
  226. } as FieldProps,
  227. },
  228. {
  229. label: '村落认领说明', name: 'claimReason', type: 'text',
  230. additionalProps: { placeholder: '请输入村落认领说明' } ,
  231. },
  232. ]
  233. },
  234. ],
  235. formAdditionaProps: {
  236. labelWidth: '160rpx',
  237. labelAlign: 'right',
  238. innerStyle: {
  239. radius: '10rpx',
  240. },
  241. } as Omit<FormProps, 'model'>,
  242. }
  243. async function registerSubmit() {
  244. if (!registerFormRef.value || !registerFormModel.value)
  245. return;
  246. try {
  247. await registerFormRef.value.validate();
  248. } catch (e) {
  249. toast({ content: '有必填项未填写,请检查' });
  250. return;
  251. }
  252. try {
  253. registerFormLoading.value = true;
  254. registerFormModel.value!.villageId = querys.value.villageId;
  255. const loginRes = await VillageApi.shareAddVolunteer(registerFormModel.value!);
  256. await authStore.loginResultHandle(loginRes, UserApi.LOGIN_TYPE_USER);
  257. await init();
  258. toast({ content: '注册成功' });
  259. step.value = 'finished';
  260. } catch (e) {
  261. showError(e);
  262. } finally {
  263. registerFormLoading.value = false;
  264. }
  265. }
  266. </script>