register.js 6.4 KB

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