const api = require('../../utils/api') const finalStatuses = ['CONFIRMED', 'CANCELLED', 'FAILED', 'EXPIRED', 'CONSUMED'] Page({ data: { ticket: '', sessionId: '', preview: null, loading: true, confirming: false, cancelling: false, status: 'LOADING', message: '正在读取登录信息', canConfirm: false, canCancel: false, }, onLoad(options) { const scene = this.decodeRepeated(options.scene || '') const fallback = scene || this.buildFallbackScene(options) const ticket = this.extractTicket(fallback) const sessionId = this.extractSessionId(fallback) this.setData({ ticket, sessionId }) this.loadPreview() }, buildFallbackScene(options) { const ticket = options.ticket || '' const sessionId = options.session_id || options.sessionId || '' return `ticket=${ticket}&session_id=${sessionId}` }, decodeRepeated(value) { let text = String(value || '').trim() for (let index = 0; index < 3; index += 1) { try { const decoded = decodeURIComponent(text) if (decoded === text) { break } text = decoded } catch (error) { break } } return text }, extractTicket(value) { return this.extractSceneValue(value, ['ticket', 't']) }, extractSessionId(value) { return this.extractSceneValue(value, ['session_id', 'sessionId', 's']) }, extractSceneValue(value, names) { const raw = this.decodeRepeated(value) for (let index = 0; index < names.length; index += 1) { const name = names[index] const matched = raw.match(new RegExp(`(?:^|[?&])${name}=([^&]+)`)) if (matched && matched[1]) { return this.decodeRepeated(matched[1]) } } return '' }, async loadPreview() { if (!this.data.ticket || !this.data.sessionId) { this.updateStatus('FAILED', '登录二维码无效') return } try { const preview = await api.getErpLoginPreview(this.data.ticket, this.data.sessionId) this.setData({ preview, loading: false }) this.updateStatus('PENDING', '请确认是否登录 ERP') } catch (error) { this.updateStatus('FAILED', error.message || '登录信息读取失败') } }, async confirmLogin(e) { const phoneCode = e.detail && e.detail.code if (!phoneCode) { wx.showToast({ title: '未获得手机号授权', icon: 'none' }) return } this.setData({ confirming: true, message: '正在确认登录' }) try { const result = await api.confirmErpLogin(this.data.ticket, this.data.sessionId, phoneCode) const status = String(result.status || '').toUpperCase() this.updateStatus( status, status === 'CONFIRMED' ? '已确认,请回到电脑端' : (result.failureReason || '确认失败'), ) } catch (error) { this.updateStatus('FAILED', error.message || '确认失败') } finally { this.setData({ confirming: false }) } }, async cancelLogin() { this.setData({ cancelling: true, message: '正在取消登录' }) try { const result = await api.cancelErpLogin(this.data.ticket, this.data.sessionId) this.updateStatus(result.status || 'CANCELLED', '已取消本次登录') } catch (error) { wx.showToast({ title: error.message || '取消失败', icon: 'none' }) this.updateStatus(this.data.status || 'PENDING', this.data.message || '请确认是否登录 ERP') } finally { this.setData({ cancelling: false }) } }, updateStatus(status, message) { const normalized = String(status || '').toUpperCase() const actionable = normalized === 'PENDING' || normalized === 'SCANNED' this.setData({ loading: false, status: normalized, message, canConfirm: actionable && !finalStatuses.includes(normalized), canCancel: actionable && !finalStatuses.includes(normalized), }) }, })