index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. <template>
  2. <div class="mcSubmit">
  3. <div style="text-align: center; font-size: 20px">第十五届航展报名申请</div>
  4. <van-form @submit="onSubmit" ref="submits" style="background: #fff">
  5. <van-cell-group style="margin: none" inset>
  6. <div class="myTitle required"><span class="number">01</span>姓名</div>
  7. <van-field
  8. class="zdycell"
  9. v-model="formData.name"
  10. label-align="top"
  11. name="姓名"
  12. maxlength="15"
  13. label=""
  14. placeholder="请填写您的姓名"
  15. :rules="[{ required: true, message: '请填写您的姓名' }]"
  16. />
  17. <div class="myTitle required"><span class="number">02</span>证件类型</div>
  18. <van-field
  19. v-model="setObjId.type"
  20. class="zdycell"
  21. is-link
  22. readonly
  23. name="picker"
  24. label=""
  25. :placeholder="t('feedback.setselcet')"
  26. :rules="[{ required: true, message: '请选择证件类型' }]"
  27. @click="showPicker.type = true"
  28. />
  29. <van-popup v-model:show="showPicker.type" position="bottom">
  30. <van-picker
  31. :columns="columns.industryOptionId"
  32. @confirm="(val) => onConfirm(val, 'type')"
  33. @cancel="showPicker.type = false"
  34. />
  35. </van-popup>
  36. <div class="myTitle required"><span class="number">03</span>证件号码</div>
  37. <van-field
  38. class="zdycell"
  39. v-model="formData.num"
  40. label-align="top"
  41. name="姓名"
  42. maxlength="15"
  43. label=""
  44. placeholder="请输入证件号码"
  45. :rules="[{ required: true, message: '请输入证件号码' }]"
  46. />
  47. <div class="myTitle required"><span class="number">04</span>性别</div>
  48. <van-field name="radio" label="" :rules="[{ required: true, message: '请选择性别' }]">
  49. <template #input>
  50. <van-radio-group v-model="formData.gender" direction="horizontal">
  51. <van-radio name="男">男性</van-radio>
  52. <van-radio name="女">女性</van-radio>
  53. <!-- <van-radio name="3">其他</van-radio> -->
  54. </van-radio-group>
  55. </template>
  56. </van-field>
  57. <div class="myTitle required"><span class="number">05</span>国籍</div>
  58. <van-field
  59. class="zdycell"
  60. v-model="formData.nationality"
  61. label-align="top"
  62. name="国籍"
  63. maxlength="15"
  64. label=""
  65. placeholder="请填写您的国籍"
  66. :rules="[{ required: true, message: '请填写您的国籍' }]"
  67. />
  68. <!-- <van-field
  69. v-model="formData.nationality"
  70. is-link
  71. class="zdycell"
  72. readonly
  73. name="picker"
  74. label=""
  75. :placeholder="t('feedback.setselcet')"
  76. @click="showPicker.nationality = true"
  77. :rules="[{ required: true, message: '请选择您的国籍' }]"
  78. /> -->
  79. <div class="myTitle required"><span class="number">06</span>单位名称</div>
  80. <van-field
  81. class="zdycell"
  82. v-model="formData.unit"
  83. label-align="top"
  84. name="姓名"
  85. maxlength="15"
  86. label=""
  87. placeholder="请填写单位名称"
  88. :rules="[{ required: true, message: '请填写单位名称' }]"
  89. />
  90. <div class="myTitle required"><span class="number">07</span>职务</div>
  91. <van-field
  92. class="zdycell"
  93. v-model="formData.job"
  94. label-align="top"
  95. name="姓名"
  96. maxlength="15"
  97. label=""
  98. placeholder="请填写您的职位"
  99. :rules="[{ required: true, message: '请填写您的职位' }]"
  100. />
  101. <div class="myTitle required"><span class="number">08</span>手机号码</div>
  102. <van-field
  103. class="zdycell"
  104. v-model="formData.phone"
  105. label-align="top"
  106. name="手机号码"
  107. maxlength="11"
  108. label=""
  109. :rules="[{ required: true, message: '请填写您的手机号码' }]"
  110. placeholder="请填写您的手机号码"
  111. />
  112. <div class="myTitle required"><span class="number">09</span>出生日期</div>
  113. <van-field
  114. v-model="setObjId.birthday"
  115. class="zdycell"
  116. is-link
  117. readonly
  118. name="picker"
  119. label=""
  120. :placeholder="t('feedback.setselcet')"
  121. :rules="[{ required: true, message: '请选择出生日期' }]"
  122. @click="showPicker.birthday = true"
  123. />
  124. <van-popup v-model:show="showPicker.birthday" position="bottom">
  125. <van-date-picker
  126. :min-date="dataDay.minDate"
  127. :max-date="dataDay.maxDate"
  128. @confirm="(val) => onConfirmdate(val, 'birthday')"
  129. @cancel="showPicker.birthday = false"
  130. />
  131. </van-popup>
  132. <div class="myTitle required"><span class="number">10</span>计划参观日期</div>
  133. <van-field
  134. v-model="setObjId.joinDate"
  135. class="zdycell"
  136. is-link
  137. readonly
  138. name="picker"
  139. label=""
  140. :placeholder="t('feedback.setselcet')"
  141. :rules="[{ required: true, message: '请选择计划参观日期' }]"
  142. @click="showPicker.joinDate = true"
  143. />
  144. <van-popup v-model:show="showPicker.joinDate" position="bottom">
  145. <van-picker :columns="columns.data" @confirm="(val) => onConfirm(val, 'joinDate')" @cancel="showPicker.date = false" />
  146. </van-popup>
  147. <div class="myTitle required"><span class="number">11</span>头像</div>
  148. <van-field class="uploadercell" name="uploader" label-align="top">
  149. <template #input>
  150. <div>
  151. <div>
  152. <van-uploader
  153. upload-icon="plus"
  154. :multiple="true"
  155. :before-read="beforeRead"
  156. :after-read="clzpAfterRead"
  157. accept="image/*"
  158. :max-count="6"
  159. v-model="formData.thumb"
  160. />
  161. </div>
  162. <div class="tips" v-html="'请上传图片</br>支持jpg、png格式,不大于5MB;'"></div>
  163. </div>
  164. </template>
  165. </van-field>
  166. <van-popup v-model:show="showPicker.nationality" position="bottom">
  167. <van-picker
  168. :columns="columnsnationality"
  169. @confirm="(val) => onConfirm(val, 'nationality')"
  170. @cancel="showPicker.nationality = false"
  171. />
  172. </van-popup>
  173. <div style="margin: 54px 0 24px 0; background-color: #f5f5f5">
  174. <van-button style="height: 44px" block color="#00B3EC" type="primary" native-type="submit"> 提交 </van-button>
  175. </div>
  176. </van-cell-group>
  177. </van-form>
  178. </div>
  179. </template>
  180. <script setup>
  181. import { ref, watch } from 'vue';
  182. import nationalityList from './country.json';
  183. import { addRoster } from '/@/api/index';
  184. import { useRouter } from 'vue-router';
  185. import axios from 'axios';
  186. // const areaList = ref({});
  187. import { showToast } from 'vant';
  188. const router = useRouter();
  189. const dataDay = ref({
  190. minDate: new Date(1924, 1, 1),
  191. maxDate: new Date(2024, 12, 12),
  192. });
  193. const columns = ref({
  194. industryOptionId: [
  195. {
  196. text: '身份证',
  197. value: '身份证',
  198. value: '身份证',
  199. },
  200. {
  201. text: '港澳回乡证',
  202. value: '港澳回乡证',
  203. value: '港澳回乡证',
  204. },
  205. {
  206. text: '台胞证',
  207. value: '台胞证',
  208. value: '台胞证',
  209. },
  210. {
  211. text: '国外护照',
  212. value: '国外护照',
  213. value: '国外护照',
  214. },
  215. ],
  216. data: [
  217. {
  218. text: '11月13日(周三) ',
  219. value: '2024-11-13',
  220. },
  221. {
  222. text: '11月14日(周四)',
  223. value: '2024-11-14',
  224. },
  225. {
  226. text: '11月15日(周五)',
  227. value: '2024-11-15',
  228. },
  229. {
  230. text: '11月16日(周六)',
  231. value: '2024-11-16',
  232. },
  233. {
  234. text: '11月17日(周日)',
  235. value: '2024-11-17',
  236. },
  237. ],
  238. });
  239. const loading = ref(false);
  240. const submits = ref(null);
  241. const setObjId = ref({
  242. type: null,
  243. nationality: null,
  244. joinDate: null,
  245. });
  246. const showPicker = ref({
  247. type: false,
  248. nationality: false,
  249. softwareOptionId: false,
  250. joinDate: false,
  251. });
  252. const formData = ref({
  253. birthday: '',
  254. exhibitionName: '',
  255. gender: '男',
  256. job: '',
  257. joinDate: '',
  258. name: '',
  259. nationality: '中国',
  260. num: '',
  261. phone: '',
  262. thumb: [],
  263. type: '',
  264. unit: '',
  265. year: 2024,
  266. exhibitionName: '2024珠海航展',
  267. });
  268. import { useI18n } from 'vue-i18n';
  269. const { t, locale } = useI18n();
  270. const columnsnationality = nationalityList.map((ele) => {
  271. return {
  272. text: locale.value == 'en-us' ? ele.english : ele.chinese,
  273. value: locale.value == 'en-us' ? ele.english : ele.chinese,
  274. zhText: ele.chinese,
  275. };
  276. });
  277. const onConfirm = ({ selectedOptions, selectedValues }, b) => {
  278. console.log('onConfirm', selectedOptions, selectedValues);
  279. formData.value[b] = selectedValues.join(',');
  280. setObjId.value[b] = selectedOptions[0].zhText || selectedOptions[0].text;
  281. showPicker.value[b] = false;
  282. };
  283. const onConfirmdate = ({ selectedOptions, selectedValues }, b) => {
  284. console.log('onConfirm', selectedOptions, selectedValues);
  285. formData.value[b] = selectedValues.join('-');
  286. setObjId.value[b] = selectedValues.join('-');
  287. showPicker.value[b] = false;
  288. };
  289. const onSubmit = async () => {
  290. console.log('submit', formData.value, setObjId.value);
  291. let param = { ...formData.value };
  292. param.thumb = param.thumb[0]?.url;
  293. await addRoster(param);
  294. router.push('/airshowsuccess');
  295. };
  296. // const beforeUpload = (file) => {
  297. // console.log('beforeUpload', file);
  298. // const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
  299. // if (!isJpgOrPng) {
  300. // showToast('You can only upload JPG file!');
  301. // }
  302. // const isLt2M = file.size / 1024 / 1024 < 2;
  303. // if (!isLt2M) {
  304. // showToast('Image must smaller than 2MB!');
  305. // }
  306. // return isJpgOrPng && isLt2M;
  307. // }; //校验图片的格式
  308. function beforeRead(file) {
  309. const isJpgOrPng =
  310. file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'video/mp4' || file.type === 'video/quicktime';
  311. if (!isJpgOrPng) {
  312. showToast(t('feedback.fileTips'));
  313. return false;
  314. }
  315. const isLt2M = file.size / 1024 / 1024 < 5;
  316. const isLt50M = file.size / 1024 / 1024 < 50;
  317. if (!isLt2M && (file.type === 'image/jpeg' || file.type === 'image/png')) {
  318. showToast(t('feedback.fileTips'));
  319. return false;
  320. }
  321. if (!isLt50M && (file.type === 'video/mp4' || file.type === 'video/quicktime')) {
  322. showToast(t('feedback.fileTips'));
  323. return false;
  324. }
  325. // if (!/(jpg|jpeg|png|JPG|PNG|mp4|quicktime)/i.test(file.type)) {
  326. // showToast(t('feedback.fileTips'));
  327. // return false;
  328. // }
  329. return true;
  330. }
  331. function validator(value, rule) {
  332. let isOk = Boolean(formData.value[rule.name] || (formData.value[`${rule.name}Imgs`] && formData.value[`${rule.name}Imgs`].length > 0));
  333. return isOk;
  334. }
  335. //照片上传事件方法
  336. function clzpAfterRead(file) {
  337. // 上传状态提示开启
  338. file.status = 'uploading';
  339. file.message = '上传中...';
  340. loading.value = true;
  341. // 创建一个空对象实例
  342. let formData = new FormData();
  343. // 调用append()方法添加数据
  344. formData.append('file', file.file);
  345. axios({
  346. url: '/service/manage/common/upload/files',
  347. method: 'POST',
  348. data: formData,
  349. headers: {
  350. 'Content-Type': 'multipart/form-data',
  351. },
  352. })
  353. .then((res) => {
  354. loading.value = false;
  355. let { data } = res;
  356. if (data.code == 200 || data.code == 0) {
  357. // 上传状态提示关闭
  358. file.url = data.data;
  359. file.file = file.file;
  360. file.content = '';
  361. file.status = 'done';
  362. showToast('上传成功!');
  363. setTimeout(() => {
  364. console.log('problemDesc', submits.value);
  365. // submits.value.validate('problemDesc')();
  366. // submits.value.validate('solution');
  367. }, 1000);
  368. }
  369. console.log('formData.faultImg', formData, file);
  370. })
  371. .catch(() => {
  372. loading.value = false;
  373. });
  374. }
  375. </script>
  376. <style lang="scss" scoped>
  377. .mcSubmit {
  378. padding-top: 16px;
  379. .tips {
  380. font-size: 14px;
  381. font-family: Source Han Sans CN, Source Han Sans CN;
  382. font-weight: 400;
  383. color: #cccccc;
  384. line-height: 16px;
  385. margin-top: 15px;
  386. }
  387. .required {
  388. &::before {
  389. display: inline-block;
  390. margin-inline-end: 4px;
  391. color: #ff4d4f;
  392. font-size: 14px;
  393. font-family: SimSun, sans-serif;
  394. line-height: 1;
  395. content: '*';
  396. position: absolute;
  397. left: -11px;
  398. top: 4.5px;
  399. }
  400. }
  401. .myTitle {
  402. position: relative;
  403. margin: 48px 0 15px 0;
  404. font-size: 16px;
  405. // padding: 0 var(--van-cell-horizontal-padding);
  406. .number {
  407. font-size: 16px;
  408. font-family: Microsoft YaHei, Microsoft YaHei;
  409. font-weight: bold;
  410. color: #00b3ec;
  411. }
  412. span {
  413. font-size: 16px;
  414. font-family: Microsoft YaHei, Microsoft YaHei;
  415. font-weight: 400;
  416. color: #333333;
  417. line-height: 19px;
  418. margin-right: 7px;
  419. }
  420. }
  421. ::v-deep .uploadercell:after {
  422. display: none;
  423. }
  424. ::v-deep .ratecell:after {
  425. display: none;
  426. }
  427. ::v-deep .van-cell {
  428. padding: 4px 0px;
  429. }
  430. // ::v-deep .van-uploader__upload{
  431. // background-color: #fff;
  432. // border: 1px solid #e4e4e5;
  433. // border-radius: 5px;
  434. // }
  435. // .zdycell {
  436. // border: 1px solid #e4e4e5;
  437. // border-radius: 5px;
  438. // }
  439. .uploadercell {
  440. padding: 20px 0 0 0;
  441. }
  442. }
  443. </style>