register.js 6.3 KB

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