register.js 7.7 KB

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