| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- Page({
- data: {
- formData: {
- occupation: '',
- name: '',
- gender: '女',
- phone: '',
- code: ''
- },
- imgCodeInput: '',
- imgCodeImage: '',
- showImgCodePanel: false,
- isCodeSent: false,
- isSendingCode: false,
- isLoadingImgCode: false,
- isVerifyingImgCode: false,
- isSubmitting: false,
- showSubmitTip: false,
- submitTipText: '',
- countdown: 0,
- submitApi: 'https://kt.colexiu.com/edu-app/open/student/requestTrial',
- getImgCodeApi: 'https://kt.colexiu.com/edu-app/open/sendImgCode',
- sendSmsApi: 'https://kt.colexiu.com/edu-app/open/sendSmsVerify'
- },
- handleInputChange: function (e) {
- const field = e.currentTarget.dataset.field
- const value = e.detail.value
- const next = Object.assign({}, this.data.formData, { [field]: value })
- this.setData({ formData: next })
- },
- handleImgCodeInput: function (e) {
- const value = (e.detail.value || '').trim()
- this.setData({
- imgCodeInput: value
- })
- // 输入满足长度后自动校验,校验通过后自动发送短信
- if (value.length >= 4) {
- this.verifyImgCodeAndSendSms()
- }
- },
- handleSelectOption: function (e) {
- const field = e.currentTarget.dataset.field
- const value = e.currentTarget.dataset.value
- const next = Object.assign({}, this.data.formData, { [field]: value })
- this.setData({ formData: next })
- },
- handleSendCode: function () {
- const phone = (this.data.formData.phone || '').replace(/\s+/g, '')
- if (!/^1[3-9]\d{9}$/.test(phone)) {
- tt.showToast({
- title: '请先输入正确手机号',
- icon: 'none',
- duration: 3000
- })
- return
- }
- if (this.data.isSendingCode || this.data.isLoadingImgCode || this.data.countdown > 0) {
- return
- }
- // 先展示图形验证码区域,再拉取图片
- this.setData({
- showImgCodePanel: true,
- imgCodeInput: '',
- imgCodeImage: '',
- isLoadingImgCode: true
- })
- this.requestImgCode()
- },
- requestImgCode: function () {
- const phone = (this.data.formData.phone || '').replace(/\s+/g, '')
- tt.request({
- url: this.data.getImgCodeApi,
- method: 'GET',
- data: {
- phone: phone
- },
- success: (res) => {
- if (res.statusCode !== 200) {
- tt.showToast({
- title: this.getResponseMessage(res, '获取图形验证码失败'),
- icon: 'none',
- duration: 3000
- })
- return
- }
- const base64 = this.getImgCodeBase64(res)
- if (!base64) {
- tt.showToast({
- title: '图形验证码加载失败,请点击图片重试',
- icon: 'none',
- duration: 3000
- })
- return
- }
- this.setData({
- showImgCodePanel: true,
- imgCodeImage: base64.startsWith('data:image') ? base64 : `data:image/png;base64,${base64}`,
- imgCodeInput: ''
- })
- },
- fail: (_err) => {
- tt.showToast({
- title: '获取图形验证码失败',
- icon: 'none',
- duration: 3000
- })
- },
- complete: () => {
- this.setData({ isLoadingImgCode: false })
- }
- })
- },
- handleRefreshImgCode: function () {
- if (this.data.isLoadingImgCode || this.data.isVerifyingImgCode) {
- return
- }
- this.setData({
- imgCodeInput: '',
- isLoadingImgCode: true
- })
- this.requestImgCode()
- },
- handleCloseImgCodeModal: function () {
- this.setData({
- showImgCodePanel: false,
- imgCodeInput: '',
- imgCodeImage: ''
- })
- },
- verifyImgCodeAndSendSms: function () {
- const phone = (this.data.formData.phone || '').replace(/\s+/g, '')
- const imgCode = (this.data.imgCodeInput || '').trim()
- if (!/^1[3-9]\d{9}$/.test(phone)) {
- tt.showToast({
- title: '请先输入正确手机号',
- icon: 'none',
- duration: 3000
- })
- return
- }
- if (imgCode.length < 4) {
- return
- }
- if (this.data.isSendingCode || this.data.isVerifyingImgCode) {
- return
- }
- this.setData({ isVerifyingImgCode: true })
- tt.request({
- url: this.data.sendSmsApi,
- method: 'POST',
- header: {
- 'Content-Type': 'application/x-www-form-urlencoded'
- },
- data: {
- mobile: phone,
- type: 'REGISTER',
- clientId: 'BACKEND',
- code: imgCode
- },
- success: (res) => {
- const bizSuccess = !!(res && res.data && Number(res.data.code) === 200)
- if (!bizSuccess) {
- tt.showToast({
- title: this.getResponseMessage(res, '图形验证码错误'),
- icon: 'none',
- duration: 3000
- })
- this.refreshImgCodeAfterVerifyFail()
- return
- }
- this.setData({
- isCodeSent: true,
- showImgCodePanel: false,
- imgCodeInput: ''
- })
- this.startCountdown(60)
- tt.showToast({
- title: '验证码已发送',
- icon: 'none',
- duration: 3000
- })
- },
- fail: (_err) => {
- tt.showToast({
- title: '发送失败,请稍后重试',
- icon: 'none',
- duration: 3000
- })
- this.refreshImgCodeAfterVerifyFail()
- },
- complete: () => {
- this.setData({ isVerifyingImgCode: false })
- }
- })
- },
- startCountdown: function (seconds) {
- if (this._countdownTimer) {
- clearInterval(this._countdownTimer)
- }
- this.setData({ countdown: seconds })
- this._countdownTimer = setInterval(() => {
- const next = this.data.countdown - 1
- if (next <= 0) {
- clearInterval(this._countdownTimer)
- this._countdownTimer = null
- this.setData({ countdown: 0 })
- return
- }
- this.setData({ countdown: next })
- }, 1000)
- },
- handleSubmit: function () {
- if (this.data.isSubmitting) {
- return
- }
- const data = this.data.formData
- const occupation = (data.occupation || '').trim()
- const name = (data.name || '').trim()
- const gender = (data.gender || '').trim()
- const phone = (data.phone || '').replace(/\s+/g, '')
- const code = (data.code || '').trim()
- console.log('[TRIAL_FLOW] SUBMIT_CLICK', { occupation: occupation, gender: gender })
- if (!occupation) {
- this.showSubmitTip('请选择职业')
- return
- }
- if (!name) {
- this.showSubmitTip('请输入姓名')
- return
- }
- if (!gender) {
- this.showSubmitTip('请选择性别')
- return
- }
- if (!/^1[3-9]\d{9}$/.test(phone)) {
- this.showSubmitTip('请输入正确的11位手机号')
- return
- }
- if (!code) {
- this.showSubmitTip('请输入短信验证码')
- return
- }
- this.setData({ isSubmitting: true })
- this.submitTrial({
- occupation: occupation,
- name: name,
- gender: gender,
- phone: phone,
- code: code
- })
- },
- submitTrial: function (params) {
- tt.request({
- url: this.data.submitApi,
- method: 'POST',
- header: {
- 'Content-Type': 'application/x-www-form-urlencoded'
- },
- data: {
- occupation: params.occupation,
- name: params.name,
- gender: params.gender,
- phone: params.phone,
- code: params.code
- },
- success: (res) => {
- const bizSuccess = this.isApiSuccess(res)
- if (!bizSuccess) {
- this.showSubmitTip(this.getResponseMessage(res, '提交失败,请稍后重试'))
- return
- }
- this.showSubmitTip(this.getResponseMessage(res, '提交成功'))
- this.setData({
- formData: {
- occupation: '',
- name: '',
- gender: '女',
- phone: '',
- code: ''
- },
- imgCodeInput: '',
- imgCodeImage: '',
- showImgCodePanel: false,
- isCodeSent: false
- })
- },
- fail: (_err) => {
- this.showSubmitTip('提交失败,请稍后重试')
- },
- complete: () => {
- this.setData({ isSubmitting: false })
- }
- })
- },
- getResponseMessage: function (res, fallback) {
- if (!res || !res.data) {
- return fallback
- }
- if (typeof res.data === 'string') {
- return res.data || fallback
- }
- return res.data.message || res.data.msg || fallback
- },
- isApiSuccess: function (res) {
- if (!res || res.statusCode !== 200) {
- return false
- }
- const data = res.data
- if (data === undefined || data === null || data === '') {
- return true
- }
- const failPattern = /(错误|失败|无效|过期|不存在|required|invalid|unauthorized|forbidden|denied|error|fail)/i
- if (typeof data === 'string') {
- return !failPattern.test(data)
- }
- if (typeof data !== 'object') {
- return true
- }
- if (typeof data.success === 'boolean') {
- return data.success
- }
- if (data.code !== undefined && data.code !== null && data.code !== '') {
- const code = String(data.code)
- if (code !== '0' && code !== '200') {
- return false
- }
- }
- if (data.status !== undefined && data.status !== null && data.status !== '') {
- const status = String(data.status)
- if (status !== '0' && status !== '200' && status.toLowerCase() !== 'success') {
- return false
- }
- }
- const msg = (data.message || data.msg || data.error || '').toString()
- if (msg && failPattern.test(msg)) {
- return false
- }
- return true
- },
- getImgCodeBase64: function (res) {
- if (!res || !res.data) {
- return ''
- }
- // 按接口约定:图片 base64 在 res.data.data
- if (typeof res.data.data === 'string') {
- return res.data.data.trim()
- }
- // 仅保留一个最小兜底:res.data 本身是字符串
- if (typeof res.data === 'string') {
- return res.data.trim()
- }
- return ''
- },
- refreshImgCodeAfterVerifyFail: function () {
- // 图形码失败后只刷新图片并等待用户再次输入,不触发短信发送
- this.setData({
- imgCodeInput: '',
- isLoadingImgCode: true
- })
- this.requestImgCode()
- },
- showSubmitTip: function (text) {
- if (this._submitTipTimer) {
- clearTimeout(this._submitTipTimer)
- }
- this.setData({
- showSubmitTip: true,
- submitTipText: text || ''
- })
- this._submitTipTimer = setTimeout(() => {
- this.setData({
- showSubmitTip: false,
- submitTipText: ''
- })
- this._submitTipTimer = null
- }, 3000)
- },
- handleGoProduct: function () {
- tt.redirectTo({
- url: '/pages/product/index'
- })
- },
- handleGoTrial: function () {
- },
- onUnload: function () {
- if (this._submitTipTimer) {
- clearTimeout(this._submitTipTimer)
- this._submitTipTimer = null
- }
- if (this._countdownTimer) {
- clearInterval(this._countdownTimer)
- this._countdownTimer = null
- }
- }
- })
|