form2.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 class="navTitle" 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. :loading="loading"
  97. style="background: linear-gradient(270deg, #1D19BC 0%, #1C4CD5 100%);margin: 0 auto;width: calc(100% - 40px);"
  98. block type="primary" native-type="submit">
  99. {{ lang[langType].submit }}
  100. </van-button>
  101. </van-form>
  102. </div>
  103. </div>
  104. </template>
  105. <script setup>
  106. import { defineProps, defineEmits, defineExpose, reactive, ref, computed } from 'vue';
  107. import { showToast, showDialog } from 'vant';
  108. import { saveData, uploadImage } from '@/api/2025.js';
  109. import lang from './lang.js';
  110. const props = defineProps(['langType', 'verificationCode', 'subData']);
  111. const emits = defineEmits(['closeComponent']);
  112. const loading = ref(false);
  113. const formData = reactive({})
  114. const unitTypeList = computed(() => lang[props.langType].workGroup)
  115. const showUnitType = ref(false)
  116. const form = ref(null); // 引入子组件的实例,用于调用子组件的方法
  117. const photo = ref([]);
  118. const reset = () => {
  119. form.value.resetValidation();
  120. }
  121. const onClickLeft = () => {
  122. emits('closeComponent');
  123. };
  124. const onUnitTypeConfirm = (values) => {
  125. showUnitType.value = false;
  126. formData.unitType = values.selectedOptions[0].value;
  127. formData.unitTypeName = values.selectedOptions[0].text;
  128. }
  129. // 上传
  130. const beforeDelete = (index) => {
  131. photo.value.splice(index, 1);
  132. formData.photoUrl = '';
  133. return false;
  134. }
  135. const filesize = () => showToast(lang[props.langType].fileSize);
  136. const beforeRead = (file) => {
  137. if (!file) showToast(lang[props.langType].photoContent);
  138. uploadImage(file).then(res => {
  139. showToast(lang[props.langType].upFileSusscess);
  140. formData.photoUrl = res
  141. photo.value = [
  142. {
  143. url: res,
  144. file: file.file,
  145. }
  146. ]
  147. }).catch((res) => {
  148. showToast(res.msg || lang[props.langType].upFileError);
  149. })
  150. return false;
  151. };
  152. const onSubmit = () => {
  153. if (loading.value) return
  154. loading.value = true
  155. saveData({
  156. name: formData.name, // 姓名
  157. code: props.verificationCode, // 邀请码
  158. photo: formData.photoUrl, // 照片
  159. phone: formData.contact, // 手机号
  160. idCard: formData.passport, // 证件号
  161. workUnit: formData.workUnit, // 工作单位
  162. workGroup: formData.unitType, // 单位类型
  163. identityType: formData.identityType, // 身份类别
  164. userType: '工作人员'
  165. }).then((res) => {
  166. if (!isNaN(res.code) && res.code !== 0) {
  167. showToast(res.msg || lang[props.langType].networkError);
  168. return;
  169. }
  170. // 清空表单内容 from
  171. // Object.keys(from).forEach((key) => {
  172. // from[key] = '';
  173. // });
  174. loading.value = false
  175. showDialog({
  176. message: lang[props.langType].registration,
  177. })
  178. }).catch((res) => {
  179. loading.value = false
  180. showToast(res.msg || lang[props.langType].networkError);
  181. });
  182. }
  183. defineExpose({ reset })
  184. </script>
  185. <style lang="scss"></style>