form2.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <!-- 工作人员 -->
  2. <template>
  3. <div>
  4. <van-nav-bar fixed :border="false">
  5. <template #left>
  6. <van-icon name="arrow-left" color="#3D3D3D" @click="onClickLeft" />
  7. </template>
  8. <template #title>
  9. <p style="padding-left: 3em;font-size: 1.2rem;" v-text="lang[langType].signUpWK"></p>
  10. </template>
  11. </van-nav-bar>
  12. <div class="form">
  13. <van-form ref="form" @submit="onSubmit" label-width="8em">
  14. <!-- 姓名 -->
  15. <van-field size="large" input-align="right"
  16. :rules="[{ required: true, trigger: 'onBlur', message: lang[langType].nameContent }]" required
  17. v-model="formData.name" :placeholder="lang[langType].nameContent">
  18. <template #label>
  19. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].name"></span>
  20. </template>
  21. </van-field>
  22. <!-- 手机号 -->
  23. <van-field size="large" input-align="right"
  24. :rules="[{ required: true, trigger: 'onBlur', message: lang[langType].contactContent }]"
  25. v-model="formData.contact" type="number" required :placeholder="lang[langType].contactContent">
  26. <template #label>
  27. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].contact"></span>
  28. </template>
  29. </van-field>
  30. <!-- 照片 -->
  31. <van-field size="large" input-align="right" :placeholder="lang[langType].photoContent" required
  32. :rules="[{ required: true, trigger: 'onChange', message: lang[langType].photoContent }]"
  33. v-model="formData.photoUrl">
  34. <template #label>
  35. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].photo"></span>
  36. </template>
  37. <template #input>
  38. <van-uploader :preview-full-image="false" accept="image/*" v-model="photo"
  39. :before-delete="beforeDelete" :max-count="1" :max-size="524288000" @oversize="filesize"
  40. :after-read="beforeRead" result-type="file">
  41. </van-uploader>
  42. <p class="upFileSubtitle" v-text="lang[langType].photoSubContent"> </p>
  43. </template>
  44. </van-field>
  45. <!-- 证件 -->
  46. <van-field size="large" input-align="right"
  47. :rules="[{ required: true, trigger: 'onBlur', message: lang[langType].IDcardNumberContent }]"
  48. v-model="formData.passport" required :placeholder="lang[langType].IDcardNumberContent">
  49. <template #label>
  50. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].IDcardNumber"></span>
  51. </template>
  52. </van-field>
  53. <!-- 身份类别 -->
  54. <van-field size="large" v-model="formData.identityType" required label-align="top"
  55. :rules="[{ required: true, trigger: 'onBlur', message: lang[langType].identityTypeContent }]"
  56. :placeholder="lang[langType].identityTypeContent">
  57. <template #label>
  58. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].identityType"></span>
  59. </template>
  60. <template #input>
  61. <van-radio-group checked-color="#3F5AC8" style="justify-content: flex-end;width: 100%;"
  62. v-model="formData.identityType" :direction="langType === 'zh' ? 'horizontal' : 'vertical'">
  63. <van-radio style="flex: 1;margin-top: 10px; margin-bottom: 5px; " name="媒体">{{
  64. lang[langType].media }}</van-radio>
  65. <van-radio style="flex: 1;margin-top: 10px; margin-bottom: 5px; " name="工作人员">{{
  66. lang[langType].staff }}</van-radio>
  67. <van-radio style="flex: 1;margin-top: 10px; margin-bottom: 5px; " name="志愿者">{{
  68. lang[langType].volunteer }}</van-radio>
  69. </van-radio-group>
  70. </template>
  71. </van-field>
  72. <!-- 单位类型 -->
  73. <van-field size="large " input-align="right" v-model="formData.unitTypeName" clickable
  74. :rules="[{ required: true, trigger: 'onChange', message: lang[langType].workGroupTextContent }]"
  75. right-icon="calendar-o" readonly :placeholder="lang[langType].workGroupTextContent"
  76. @click="showUnitType = true" required>
  77. <template #label>
  78. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].workGroupText"></span>
  79. </template>
  80. </van-field>
  81. <van-popup v-model:show="showUnitType" destroy-on-close round position="bottom">
  82. <van-picker :confirm-button-text="lang[langType].confirm"
  83. :cancel-button-text="lang[langType].cancel" :columns="unitTypeList"
  84. @cancel="showUnitType = false" @confirm="onUnitTypeConfirm" />
  85. </van-popup>
  86. <!-- 工作单位 -->
  87. <van-field size="large" input-align="right" v-model="formData.workUnit"
  88. :rules="[{ required: true, trigger: 'onBlur', message: lang[langType].companyContent }]" required
  89. :placeholder="lang[langType].companyBContent">
  90. <template #label>
  91. <span :class="langType === 'zh' ? 'label' : ''" v-html="lang[langType].companyB"></span>
  92. </template>
  93. </van-field>
  94. <br />
  95. <van-button
  96. style="background: linear-gradient(270deg, #1D19BC 0%, #1C4CD5 100%);margin: 0 auto;width: calc(100% - 40px);"
  97. block type="primary" native-type="submit">
  98. {{ lang[langType].submit }}
  99. </van-button>
  100. </van-form>
  101. </div>
  102. </div>
  103. </template>
  104. <script setup>
  105. import { defineProps, defineEmits, defineExpose, reactive, ref, computed } from 'vue';
  106. import { showToast, showDialog } from 'vant';
  107. import { saveData, uploadImage } from '@/api/2025.js';
  108. import lang from './lang.js';
  109. const props = defineProps(['langType', 'verificationCode', 'subData']);
  110. const emits = defineEmits(['closeComponent']);
  111. const formData = reactive({})
  112. const unitTypeList = computed(() => lang[props.langType].workGroup)
  113. const showUnitType = ref(false)
  114. const form = ref(null); // 引入子组件的实例,用于调用子组件的方法
  115. const photo = ref([]);
  116. const reset = () => {
  117. form.value.resetValidation();
  118. }
  119. const onClickLeft = () => {
  120. emits('closeComponent');
  121. };
  122. const onUnitTypeConfirm = (values) => {
  123. showUnitType.value = false;
  124. formData.unitType = values.selectedOptions[0].value;
  125. formData.unitTypeName = values.selectedOptions[0].text;
  126. }
  127. // 上传
  128. const beforeDelete = (index) => {
  129. photo.value.splice(index, 1);
  130. formData.photoUrl = '';
  131. return false;
  132. }
  133. const filesize = () => showToast(lang[props.langType].fileSize);
  134. const beforeRead = (file) => {
  135. if (!file) showToast(lang[props.langType].photoContent);
  136. uploadImage(file).then(res => {
  137. showToast(lang[props.langType].upFileSusscess);
  138. formData.photoUrl = res
  139. photo.value = [
  140. {
  141. url: res,
  142. file: file.file,
  143. }
  144. ]
  145. }).catch((res) => {
  146. showToast(res.msg || lang[props.langType].upFileError);
  147. })
  148. return false;
  149. };
  150. let loading = false
  151. const onSubmit = () => {
  152. if (loading) return
  153. loading = true
  154. saveData({
  155. name: formData.name, // 姓名
  156. code: props.verificationCode, // 邀请码
  157. photo: formData.photoUrl, // 照片
  158. phone: formData.contact, // 手机号
  159. idCard: formData.passport, // 证件号
  160. workUnit: formData.workUnit, // 工作单位
  161. workGroup: formData.unitType, // 单位类型
  162. identityType: formData.identityType, // 身份类别
  163. userType: '工作人员'
  164. }).then((res) => {
  165. if (!isNaN(res.code) && res.code !== 0) {
  166. showToast(res.msg || lang[props.langType].networkError);
  167. return;
  168. }
  169. // 清空表单内容 from
  170. // Object.keys(from).forEach((key) => {
  171. // from[key] = '';
  172. // });
  173. loading = false
  174. showDialog({
  175. message: lang[props.langType].registration,
  176. })
  177. }).catch((res) => {
  178. loading = false
  179. showToast(res.msg || lang[props.langType].networkError);
  180. });
  181. }
  182. defineExpose({ reset })
  183. </script>
  184. <style lang="scss"></style>