register.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. import { enroll,smsSend } from '../../api/other';
  2. import { FETCH_AND_FORMAT_USER_INFO } from '../../utils/util.js'
  3. import { uploadImage } from '../../utils/upload.js';
  4. import {BASE_URL} from '../../utils/request';
  5. const app = getApp();
  6. Page({
  7. data: {
  8. formData: {
  9. phone: '',
  10. captcha: '',
  11. nickname: '',
  12. gender: '', // '女' 或 '男'
  13. race_number: '', // 身份证号
  14. // competition_no: '', // 比赛ID
  15. competition_image: '' // 上传的图片路径
  16. },
  17. phoneError: '',
  18. raceNumberError:'',
  19. genders: ['女', '男'],
  20. showPicker: false,
  21. fileList: [],
  22. checked: false,
  23. showRegistrationSuccess: false,
  24. canSubmit: false, // 按钮是否可点击
  25. showAgreementModal:false,
  26. agreementContent:'',
  27. agreementTitle:'',
  28. codeText: '获取验证码',
  29. codeDisabled: false,
  30. timer: null,
  31. countdown: 60,
  32. couponInfo:{},
  33. filePath: '', // 上传成功的文件路径
  34. fileType: '', // image / pdf
  35. baseUrl:BASE_URL
  36. },
  37. onShowPicker() {
  38. this.setData({ showPicker: true });
  39. },
  40. onCancel() {
  41. this.setData({ showPicker: false });
  42. },
  43. // 性别确定
  44. onConfirm(event) {
  45. const { value } = event.detail;
  46. this.setData({
  47. formData: {
  48. ...this.data.formData,
  49. gender: value
  50. },
  51. showPicker: false
  52. }, () => this.checkFormValid());
  53. },
  54. // 点击上传区域
  55. chooseFile() {
  56. wx.showActionSheet({
  57. itemList: ['图片', 'PDF'],
  58. success: res => {
  59. if (res.tapIndex === 0) {
  60. this.chooseImage();
  61. } else {
  62. this.choosePdf();
  63. }
  64. }
  65. });
  66. },
  67. // 选择图片
  68. chooseImage() {
  69. wx.chooseImage({
  70. count: 1,
  71. sizeType: ['original', 'compressed'],
  72. sourceType: ['album', 'camera'],
  73. success: res => {
  74. const path = res.tempFilePaths[0];
  75. this.uploadFile(path, 'image');
  76. }
  77. });
  78. },
  79. // 选择 PDF
  80. choosePdf() {
  81. wx.chooseMessageFile({
  82. count: 1,
  83. type: 'file',
  84. success: res => {
  85. const file = res.tempFiles[0];
  86. if (file.name.endsWith('.pdf')) {
  87. this.uploadFile(file.path, 'pdf');
  88. } else {
  89. wx.showToast({ title: '请选择 PDF 文件', icon: 'none' });
  90. }
  91. }
  92. });
  93. },
  94. // 上传文件
  95. async uploadFile(path, type) {
  96. if (!path) {
  97. wx.showToast({ title: '文件路径错误', icon: 'none' });
  98. return;
  99. }
  100. try {
  101. const res = await uploadImage(path);
  102. console.log('上传成功:', res);
  103. this.setData({
  104. filePath: res.url,
  105. fileType: type,
  106. "formData.competition_image": res.path
  107. });
  108. } catch (err) {
  109. console.error('上传失败:', err);
  110. }
  111. },
  112. // 删除文件
  113. removeFile() {
  114. this.setData({
  115. filePath: '',
  116. fileType: '',
  117. "formData.competition_image": ''
  118. });
  119. },
  120. // 输入框数据绑定
  121. onInput(e) {
  122. console.log(e)
  123. const field = e.currentTarget.dataset.field;
  124. const value = e.detail;
  125. // 手机号单独做校验
  126. if (field === 'phone') {
  127. const regPhone = /^1[3-9]\d{9}$/;
  128. if (value && !regPhone.test(value)) {
  129. this.setData({ phoneError: '手机号格式不正确' });
  130. }else{
  131. this.setData({ phoneError: '' });
  132. }
  133. }
  134. if (field === 'race_number') {
  135. const regIdCard = /^\d{18}$/;
  136. if (value && !regIdCard.test(value)) {
  137. this.setData({ raceNumberError: '身份证号格式不正确' });
  138. }else{
  139. this.setData({ raceNumberError: '' });
  140. }
  141. }
  142. this.setData({
  143. formData: { ...this.data.formData, [field]: value }
  144. }, () => this.checkFormValid());
  145. },
  146. // 勾选协议
  147. onCheckbox(event) {
  148. this.setData({ checked: event.detail }, () => this.checkFormValid());
  149. },
  150. // 校验表单是否可提交
  151. checkFormValid() {
  152. const { phone, captcha, nickname, gender, race_number } = this.data.formData;
  153. const valid = phone && captcha && nickname && gender && race_number && this.data.checked;
  154. this.setData({ canSubmit: valid });
  155. },
  156. // 获取验证码
  157. async getCode() {
  158. if(this.data.codeDisabled) return;
  159. const phone = this.data.formData.phone;
  160. if (!phone) {
  161. wx.showToast({
  162. title: '请输入手机号',
  163. icon: 'none'
  164. });
  165. return;
  166. }
  167. if (!/^1[3-9]\d{9}$/.test(phone)) {
  168. wx.showToast({
  169. title: '手机号格式不正确',
  170. icon: 'none'
  171. });
  172. return;
  173. }
  174. // 禁用按钮
  175. this.setData({ codeDisabled: true });
  176. const res = await smsSend({phone:this.data.formData.phone});
  177. if (res.code == 200) {
  178. wx.showToast({ title: '验证码已发送', icon: 'none' });
  179. this.startCountdown();
  180. } else {
  181. wx.showToast({ title: res.message || '发送失败', icon: 'none' });
  182. this.setData({ codeDisabled: false });
  183. }
  184. },
  185. // 提交报名
  186. async onSubmit() {
  187. if (!this.data.canSubmit) return;
  188. const payload = {
  189. ...this.data.formData,
  190. gender: this.data.formData.gender === '女' ? 0 : 1
  191. };
  192. const res = await enroll(payload);
  193. if (res.code === 200) {
  194. // 优惠券信息
  195. this.setData({
  196. couponInfo:res.data[0]
  197. })
  198. this.setData({ showRegistrationSuccess: true });
  199. app.globalData.userInfo = await FETCH_AND_FORMAT_USER_INFO();
  200. } else {
  201. wx.showToast({ title: res.message || '报名失败', icon: 'none', duration: 2000 });
  202. }
  203. },
  204. // 点击协议文字显示弹窗
  205. showAgreement(e) {
  206. const type = e.currentTarget.dataset.type;
  207. const dataInfo = app.globalData.programConfig;
  208. this.setData({
  209. showAgreementModal: true,
  210. agreementContent: type == 'rules'?dataInfo.rules : type == 'liability'?dataInfo.disclaimer : dataInfo.privacy_policy,
  211. agreementTitle:type == 'rules'?'活动规则': type == 'liability'?'免责协议' : '隐私政策'
  212. });
  213. },
  214. closeAgreementModal() {
  215. this.setData({ showAgreementModal: false });
  216. },
  217. onReceive() {
  218. this.setData({ showRegistrationSuccess: false });
  219. wx.navigateBack({ delta: 1 });
  220. },
  221. //预览图片
  222. previewImage(e){
  223. const current = e.currentTarget.dataset.src;
  224. wx.previewImage({
  225. current,
  226. urls: [current]
  227. });
  228. },
  229. startCountdown() {
  230. let countdown = this.data.countdown;
  231. this.setData({ codeText: `${countdown}s` });
  232. if (this.data.timer) clearInterval(this.data.timer);
  233. this.data.timer = setInterval(() => {
  234. countdown -= 1;
  235. if (countdown <= 0) {
  236. clearInterval(this.data.timer);
  237. this.setData({ codeText: '获取验证码', codeDisabled: false, countdown: 60 });
  238. } else {
  239. this.setData({ codeText: `${countdown}s`, countdown });
  240. }
  241. }, 1000);
  242. },
  243. onUnload() {
  244. if (this.data.timer) clearInterval(this.data.timer);
  245. }
  246. });