let Parse = getApp().Parse; let company = getApp().globalData.company const request = require("../../utils/request"); const qiniuUploader = require("../../utils/qiniuUploader"); //获取应用实例 const app = getApp() const real = require('../../utils/real') var timer function normalizeCnMobile(value) { if (value === null || value === undefined) return ''; const digits = String(value).replace(/\D/g, ''); if (!digits) return ''; const last11 = digits.length >= 11 ? digits.slice(-11) : digits; if (/^1\d{10}$/.test(last11)) return last11; if (/^1\d{10}$/.test(digits)) return digits; return ''; } function addCnMobileToSet(set, value) { const m = normalizeCnMobile(value); if (m) set.add(m); } async function localRejudgeIfNeeded() { try { const pending = wx.getStorageSync('traffic_deduct_pending'); if (!pending) return; const storeId = pending && pending.storeId ? pending.storeId : null; const currentUser = Parse.User.current(); const numsSet = new Set(); addCnMobileToSet(numsSet, currentUser && currentUser.get('mobile')); addCnMobileToSet(numsSet, currentUser && currentUser.get('phone')); try { addCnMobileToSet(numsSet, wx.getStorageSync('user_mobile')); } catch (e) {} const uniqUserNumbers = Array.from(numsSet); console.log('🚦 [traffic] 授权页本地复判开始:', { storeId, userId: currentUser?.id, userNumbers: uniqUserNumbers }); if (!storeId || !uniqUserNumbers.length) { console.log('🚦 [traffic] 本地复判条件不足,退出'); return; } const phones = new Set(); const mobiles = new Set(); const tryPartnerQueries = [ { key: 'storeId', value: storeId }, { key: 'store', value: { __type: 'Pointer', className: 'ShopStore', objectId: storeId } }, { key: 'shopStore', value: { __type: 'Pointer', className: 'ShopStore', objectId: storeId } } ]; for (const item of tryPartnerQueries) { try { const q = new Parse.Query('Partner'); q.equalTo(item.key, item.value); q.limit(200); q.select('phone', 'mobile', 'name'); const list = await q.find(); if (list && list.length) { list.forEach((p) => { addCnMobileToSet(phones, p.get('phone')); addCnMobileToSet(mobiles, p.get('mobile')); }); } } catch (e) {} } console.log('🚦 [traffic] 授权页本地复判 Partner 集合:', { phoneCount: phones.size, mobileCount: mobiles.size }); const phoneHit = uniqUserNumbers.some((n) => phones.has(n)); const mobileHit = uniqUserNumbers.some((n) => mobiles.has(n)); if (phoneHit || mobileHit) { console.log('🚦 [traffic] 授权页本地复判命中:', { reason: phoneHit ? 'partner_phone_match' : 'partner_mobile_match', matches: uniqUserNumbers.filter((n) => phoneHit ? phones.has(n) : mobiles.has(n)) }); try { currentUser.set('trafficExempt', true); currentUser.set('trafficExemptAt', new Date()); currentUser.set('trafficExemptStoreId', storeId); await currentUser.save(); } catch (e) {} wx.removeStorageSync('traffic_deduct_pending'); } else { console.log('🚦 [traffic] 授权页本地复判未命中,等待首页复判继续'); } } catch (e) { console.warn('🚦 [traffic] 授权页本地复判失败:', e?.message || e); } } async function flushPendingScanRecord(mobileHint) { try { const pending = wx.getStorageSync('pending_scan_record'); if (!pending) { console.log('ℹ️ [ScanRecord] 授权页未发现 pending_scan_record'); return false; } const now = Date.now(); const scanTime = pending.timestamp || 0; const hoursPassed = scanTime ? (now - scanTime) / (1000 * 60 * 60) : 0; if (hoursPassed > 24) { console.log('⚠️ [ScanRecord] pending_scan_record 已超过24小时,清除'); wx.removeStorageSync('pending_scan_record'); return false; } const currentUser = Parse.User.current(); if (!currentUser || !currentUser.id) { console.log('⚠️ [ScanRecord] 授权页补记失败:无登录用户'); return false; } let storageMobile = ''; try { storageMobile = wx.getStorageSync('user_mobile') || ''; } catch (e) {} const normalized = normalizeCnMobile( currentUser.get('mobile') || currentUser.get('phone') || storageMobile || mobileHint ); console.log('📌 [ScanRecord] 授权页补记前置:', { userId: currentUser.id, mobile: normalizeCnMobile(currentUser.get('mobile')) || '无', phone: normalizeCnMobile(currentUser.get('phone')) || '无', storage: normalizeCnMobile(storageMobile) || '无', hint: normalizeCnMobile(mobileHint) || '无', normalized: normalized || '无', storeId: pending.storeId || '无', partnerId: pending.partnerId || '无' }); if (!normalized) { console.log('⏳ [ScanRecord] 授权页补记失败:仍未获取到手机号'); return false; } const ScanRecord = Parse.Object.extend('ScanRecord'); const record = new ScanRecord(); record.set('company', { __type: 'Pointer', className: 'Company', objectId: company }); record.set('storeId', pending.storeId); record.set('sourceType', pending.sourceType || 'unknown'); record.set('scanCount', parseInt(pending.scanCount) || 0); record.set('scanTime', new Date()); if (pending.employeeId) record.set('employeeId', pending.employeeId); if (pending.partnerId) record.set('partnerId', pending.partnerId); if (pending.userId) record.set('userId', pending.userId); if (pending.productId) record.set('productId', pending.productId); record.set('user', { __type: 'Pointer', className: '_User', objectId: currentUser.id }); record.set('userid', currentUser.id); await record.save(); console.log('✅ [ScanRecord] 授权页补记保存成功', { recordId: record.id }); wx.removeStorageSync('pending_scan_record'); return true; } catch (e) { console.error('❌ [ScanRecord] 授权页补记保存失败:', e?.message || e); try { console.error(' - code:', e.code); console.error(' - details:', e.details); } catch (e2) {} return false; } } /** * @class NovaAppAuth * @memberof module:components * @tutorial userauth * @desc 通用登录组件 * # 登录组件相关数据表 * - _User */ Page({ data: { phoneModal: false, //短信验证码登录弹窗 logo: "https://file-cloud.fmode.cn/MldI5PBNt7/20210928/g0k1jb034826.png", name: "未来商城", desc: "江西脑控科技有限公司是国内领先的IT技术企业。专注于互联网+服务,面向政府提供区块链、大数据、物联网、人工智能解决方案", wxModel: false, avatarUrl: '', avatar: '', nickname: '', check: false, mobile: '', //手机号 verilyCode: '', //验证码 s: 0, //获取验证码倒计时 秒/s countDown: false, avatarKey: Date.now(), // 用于强制刷新头像显示 isProcessingAuth: false, // 标记是否正在处理授权流程 }, onLoad: async function (options) { let Company = new Parse.Query('Company') Company.equalTo("objectId", company) let currentCompany = await Company.first() if (currentCompany && currentCompany.id) { this.setData({ logo: currentCompany.get('logo'), name: currentCompany.get('name'), desc: currentCompany.get('desc') }) } this.getUptoken() this.getAgreement() //用户协议 }, async getUptoken() { let res = await Parse.Cloud.run('qiniu_uptoken', { company: company }) this.setData({ uptokenURL: res.uptoken, domain: res.domain, uploadURL: res.zoneUrl }) }, async getAgreement() { let query = new Parse.Query('ContractAgreement') query.equalTo('type', 'wxapp') query.equalTo('company', company) query.select('title', 'content') let res = await query.first() if (res?.id) { this.setData({ agreement: res.toJSON() }) } }, /* 是否同意授权协议 */ getAgreementAuth() { if (!this.data.check && this.data.agreement) { wx.showModal({ title: '提示', content: `请您仔细阅读并充分理解相关条款,点击同意即代表已阅读并同意《${this.data.agreement.title || '用户隐私协议'}》`, showCancel: true, cancelText: '取消', cancelColor: '#000000', confirmText: '同意', confirmColor: '#3CC51F', success: (result) => { if (result.confirm) { this.setData({ check: true, }) // this.getUserProfile() } }, fail: () => { }, complete: () => { } }); return } // this.getUserProfile() return true }, /* 判断是否绑定手机号 */ async getUserProfile() { // 检查用户是否已登录 let currentUser = Parse.User.current(); if (!currentUser?.id) { console.log('⚠️ 用户未登录,需要先登录'); // 不要在这里调用 checkAuth(true),因为它会触发微信官方的强制授权弹窗 // 应该在外层(index.js)处理登录逻辑 return false; } /* 如果手机号存在,已注册过判断是否上传过头像昵称信息 */ if (currentUser?.get('mobile')) { wx.setStorageSync("userLogin", currentUser.id); // 检查是否需要完善信息(可选) // 如果用户没有昵称或昵称是默认的,提示完善信息 const needProfile = !currentUser.get('nickname') || currentUser.get('nickname') === '微信用户' || currentUser.get('nickname') === ''; if (needProfile) { // 显示自定义的完善信息弹窗(允许跳过) console.log('ℹ️ 显示自定义头像昵称弹窗'); this.setData({ wxModel: true }); return false; } // 用户信息完整,返回上一页 this.backLoad(); return false; } // 用户已登录但没有手机号,允许继续 return true; }, /* 短信验证码登录弹窗 */ async showDialogBtn() { let auth = this.getAgreementAuth() if (!auth) return let userProfile = await this.getUserProfile() if (!userProfile) return // 标记正在处理授权 this.setData({ isProcessingAuth: true, phoneModal: true }) }, async getPhoneNumber(e) { let auth = this.getAgreementAuth() if (!auth) return let userProfile = await this.getUserProfile() if (!userProfile) return // 标记正在处理授权 this.setData({ isProcessingAuth: true }) let { code } = e.detail console.log('📱 [mobile] getPhoneNumber code:', code || '无'); if (!code) { console.error('❌ [mobile] getPhoneNumber 缺少 code,无法换取手机号'); return } let phoneNumber = await request.getPhone(code) console.log('📱 [mobile] request.getPhone 返回:', phoneNumber || '无'); if(phoneNumber) { await this.authMobileUser(phoneNumber) } else { console.error('❌ [mobile] 未获取到手机号(request.getPhone 返回空)'); } }, //合并User与绑定手机号逻辑 async authMobileUser(mobile) { let pendingScan = null try { pendingScan = wx.getStorageSync('pending_scan_record'); } catch (e) {} let currentUser = Parse.User.current() console.log('📱 [mobile] 开始处理手机号绑定/合并:', { userId: currentUser?.id || '无', mobile: mobile || '无', hasPendingScan: !!pendingScan }) let queryMobUser = new Parse.Query('_User') queryMobUser.equalTo('mobile', mobile) queryMobUser.equalTo('company', company) queryMobUser.notEqualTo('type', 'admin') queryMobUser.notEqualTo('isDeleted', true) // queryMobUser.exists(`wxapp.${getApp().globalData.appid}`) let resMobUser = await queryMobUser.first() if (resMobUser?.id) { //请求User合并API,获取token重新登录,再更新昵称头像信息等 let token = await this.getUpdateUserToken(currentUser.id, resMobUser.id) console.log(token); if (token) { Parse.User.become(token).then(async user => { // let user = Parse.User.current(); wx.setStorageSync("userLogin", user.id); try { const hasMobile = !!normalizeCnMobile(user.get('mobile') || user.get('phone') || mobile); if (hasMobile && !normalizeCnMobile(user.get('mobile'))) { user.set('mobile', mobile); } if (hasMobile && !normalizeCnMobile(user.get('phone'))) { user.set('phone', mobile); } if (hasMobile) { await user.save(); } console.log('✅ [mobile] merge-become 后用户手机号状态:', { userId: user?.id || '无', mobile: user.get('mobile') || '无', phone: user.get('phone') || '无' }) } catch (e) { console.error('❌ [mobile] merge-become 后写入手机号失败:', e?.message || e); } try { wx.setStorageSync('user_mobile', (user.get('mobile') || mobile) || ''); } catch (e) {} try { await flushPendingScanRecord(mobile); } catch (e) {} try { if (typeof getApp().checkAndRecordPendingScan === 'function') { const ok = await getApp().checkAndRecordPendingScan(); console.log('📌 [ScanRecord] merge-become 补记结果:', ok ? 'success' : 'not_written'); setTimeout(() => { try { getApp().checkAndRecordPendingScan(); } catch (e) {} }, 500); setTimeout(() => { try { getApp().checkAndRecordPendingScan(); } catch (e) {} }, 1500); } else { console.warn('⚠️ [ScanRecord] getApp().checkAndRecordPendingScan 不存在,无法触发补记'); } } catch (e) { console.warn('⚠️ [ScanRecord] merge-become 触发补记失败:', e?.message || e); } try { if (typeof getApp().checkTrafficDeductPending === 'function') { console.log('🚦 [traffic] 触发暂缓扣减复判(merge-become 成功后)'); await getApp().checkTrafficDeductPending(); } else { await localRejudgeIfNeeded(); } } catch (e) {} if (!user.get('avatar') || user.get('nickname') == '微信用户' || !user.get('nickname')) { this.setData({ phoneModal: false, wxModel: true }) return } this.backLoad() return }) .catch(async err => { console.log('❌ Parse.User.become 失败:', err); // 不要直接退出,而是尝试重新登录 wx.showModal({ title: '提示', content: '登录状态异常,是否重新登录?', showCancel: true, cancelText: '取消', confirmText: '重新登录', success: async (result) => { if (result.confirm) { // 清除登录状态 wx.removeStorageSync("sessionToken"); wx.removeStorageSync("userLogin"); try { // 尝试重新登录 await Parse.User.logOut(); await getApp().checkAuth(true); // 重新获取用户信息 const currentUser = Parse.User.current(); if (currentUser && currentUser.get('mobile')) { wx.setStorageSync("userLogin", currentUser.id); this.backLoad(); } } catch (reloginErr) { console.error('❌ 重新登录失败:', reloginErr); wx.showToast({ title: '登录失败,请稍后重试', icon: 'none' }); } } else { // 用户取消,返回上一页 wx.navigateBack(); } }, }); return }) return } return } try { currentUser.set('mobile', mobile) currentUser.set('phone', mobile) await currentUser.save() console.log('✅ [mobile] 已写入手机号:', { userId: currentUser?.id || '无', mobile: currentUser.get('mobile') || '无', phone: currentUser.get('phone') || '无' }) } catch (e) { console.error('❌ [mobile] 写入手机号失败:', e?.message || e); return } try { wx.setStorageSync('user_mobile', mobile || ''); try { await flushPendingScanRecord(mobile); } catch (e) {} if (typeof getApp().checkAndRecordPendingScan === 'function') { const ok = await getApp().checkAndRecordPendingScan(); console.log('📌 [ScanRecord] 绑定手机号后补记结果:', ok ? 'success' : 'not_written'); setTimeout(() => { try { getApp().checkAndRecordPendingScan(); } catch (e) {} }, 500); setTimeout(() => { try { getApp().checkAndRecordPendingScan(); } catch (e) {} }, 1500); } else { console.warn('⚠️ [ScanRecord] getApp().checkAndRecordPendingScan 不存在,无法触发补记'); } } catch (e) { console.warn('⚠️ [ScanRecord] 绑定手机号后触发补记失败:', e?.message || e); } try { if (typeof getApp().checkTrafficDeductPending === 'function') { console.log('🚦 [traffic] 触发暂缓扣减复判(绑定手机号后)'); await getApp().checkTrafficDeductPending(); } else { await localRejudgeIfNeeded(); } } catch (e) {} if (!currentUser.get('avatar') || currentUser.get('nickname') == '微信用户' || !currentUser.get('nickname')) { this.setData({ phoneModal: false, wxModel: true }) return } this.backLoad() return }, async getUpdateUserToken(oldUser, newUserId) { return new Promise((resolve, reject) => { wx.login({ success: function (res) { let parms = { oldUserId: oldUser, newUserId: newUserId, appId: getApp().globalData.appid, code: res.code, companyId: company, appType: getApp().globalData.appType || '' } if (res.code) { let url = 'https://server.fmode.cn/api/wxapp/combine/user' wx.request({ url: url, data: parms, header: { 'content-type': 'application/json' }, method: 'POST', async success(res) { console.log(res); let data = res.data if (data.code == 200) { wx.setStorageSync("sessionToken", data.data.token); // 用户合并成功后,更新 ScanRecord 表中的 user 字段 console.log('🔄 [用户合并] 开始更新 ScanRecord 中的用户关联'); console.log(' - 旧用户ID:', oldUser); console.log(' - 新用户ID:', newUserId); try { // 使用 Parse.User.become 切换到新用户 await Parse.User.become(data.data.token); // 查询所有旧用户的扫码记录 const ScanRecord = Parse.Object.extend('ScanRecord'); const scanQuery = new Parse.Query(ScanRecord); scanQuery.equalTo('user', { __type: 'Pointer', className: '_User', objectId: oldUser }); scanQuery.limit(1000); // 设置查询上限 const oldRecords = await scanQuery.find(); console.log(`📋 [查询结果] 找到 ${oldRecords.length} 条旧用户的扫码记录`); if (oldRecords.length > 0) { // 批量更新所有记录,将 user 指向新用户 const updatePromises = oldRecords.map(record => { record.set('user', { __type: 'Pointer', className: '_User', objectId: newUserId }); return record.save(); }); await Promise.all(updatePromises); console.log(`✅ [更新成功] 已将 ${oldRecords.length} 条扫码记录的用户更新为新用户`); } else { console.log('ℹ️ [无需更新] 旧用户没有扫码记录'); } } catch (updateError) { console.error('❌ [更新失败] 更新 ScanRecord 失败:', updateError); console.error(' - 错误信息:', updateError.message); // 不影响主流程,继续返回 token } resolve(data.data.token) } else { console.log(data?.mess); wx.showModal({ title: '提示', content: data?.mess, showCancel: false, cancelText: '取消', cancelColor: '#000000', confirmText: '确定', confirmColor: '#3CC51F', success: (result) => { if (result.confirm) { } }, fail: () => { }, complete: () => { } }); resolve() } }, }); } }, fail: function (err) { wx.showModal({ title: '提示', content: '登录超时,请稍后重试', showCancel: false, cancelText: '取消', cancelColor: '#000000', confirmText: '确定', confirmColor: '#3CC51F', success: (result) => { if (result.confirm) { } }, fail: () => { }, complete: () => { } }); console.warn('小程序wx.login失败'); resolve() } }); }) }, //获取验证码 async getPhoneCode() { let { mobile, s, countDown } = this.data if (!real.isPoneAvailable(mobile)) { wx.showToast({ title: '手机号格式有误', icon: 'error', duration: 1500, mask: false, }); return } if(countDown || s > 0) return this.setData({ countDown:true }) let parsm = { company: company, mobile: mobile } let code = await this.getRequest(parsm, 'message') if(code?.code == 1){ this.setData({ s:60 }) this.decrementTime() }else{ wx.showToast({ title: '验证码获取失败', icon: 'error', image: '', duration: 1500, mask: false, }); this.setData({ countDown:false }) } }, //接口请求 getRequest(parsm, apig) { return new Promise((resolve, rej) => { let url = 'https://server.fmode.cn/api/apig/' wx.request({ url: url + apig, data: parsm, header: { 'content-type': 'application/json' }, method: 'POST', dataType: 'json', responseType: 'text', success: (result) => { console.log(result); resolve(result.data) }, fail: () => { resolve(false) }, complete: () => { } }); }) }, // 倒计时 decrementTime(){ timer = setTimeout(() => { let { s } = this.data if(s == 0){ this.setData({ countDown:false }) timer && clearTimeout(timer) return } s-- this.setData({ s:s }) this.decrementTime() }, 1000); }, //验证码绑定手机号登录 async completePhone() { let { mobile, verilyCode } = this.data if(!real.isPoneAvailable(mobile) || !verilyCode.toString().trim()){ wx.showToast({ title: '手机号或验证码不正确', icon: 'none', image: '', duration: 1500, mask: false, }); return } // 标记正在处理授权 this.setData({ isProcessingAuth: true }) let parsm = { mobile: mobile, code:verilyCode } let isVerify = await this.getRequest(parsm, 'verifyCode') console.log(isVerify); if(isVerify.code == 200){ this.authMobileUser(mobile.toString()) }else{ // 验证失败,重置标记 this.setData({ isProcessingAuth: false }) wx.showToast({ title:isVerify?.msg || '验证码错误', icon: 'none', image: '', duration: 1500, mask: false, }); return } }, //关闭手机号授权弹窗 hideModal: function () { this.setData({ phoneModal: false, isProcessingAuth: false // 重置标记 }) }, backLoad() { console.log('==========================================='); console.log('======= backLoad 方法调用 ======='); let pages = getCurrentPages(); console.log('当前页面栈层数:', pages.length); console.log('当前页面路由:', pages[pages.length - 1]?.route); // 检查是否有 returnUrl 参数(从 H5 页面传递过来) const currentPage = pages[pages.length - 1]; const returnUrl = currentPage?.options?.returnUrl; if (returnUrl) { console.log('📍 检测到 returnUrl 参数:', returnUrl); // 如果是 web-view 页面,跳转回去 const decodedUrl = decodeURIComponent(returnUrl); console.log('🔙 准备跳转回 H5 页面:', decodedUrl); let nextUrl = `/common-page/pages/web-view/index?path=${encodeURIComponent(decodedUrl)}`; const storeId = currentPage?.options?.storeId; const storeName = currentPage?.options?.storeName; if (storeId) { nextUrl += `&storeId=${storeId}`; } if (storeName) { nextUrl += `&storeName=${storeName}`; } wx.redirectTo({ url: nextUrl, success: () => { console.log('✅ 跳转回 H5 页面成功'); console.log('==========================================='); }, fail: (err) => { console.error('❌ 跳转回 H5 页面失败:', err); wx.reLaunch({ url: nextUrl, success: () => { console.log('✅ reLaunch 跳转回 H5 页面成功'); console.log('==========================================='); }, fail: () => { this.normalBackLoad(); } }); } }); return; } // 没有 returnUrl,执行正常的返回逻辑 this.normalBackLoad(); }, normalBackLoad() { let pages = getCurrentPages(); // 如果页面栈只有1层或没有上一页,直接跳转到首页 if (pages.length <= 1) { console.log('⚠️ 没有上一个页面,直接跳转到首页'); this.goToHome(); return; } // 有上一个页面 let beforePage = pages[pages.length - 2]; console.log('上一个页面路由:', beforePage.route); // 尝试调用上一个页面的 onLoad 方法(如果存在) if (beforePage && typeof beforePage.onLoad === 'function') { try { let options = beforePage.options || { isInit: true }; beforePage.onLoad(options); console.log('✅ 已调用上一个页面的 onLoad'); } catch (err) { console.warn('⚠️ 调用上一个页面 onLoad 失败:', err); } } // 返回上一页 console.log('🔙 执行 navigateBack...'); wx.navigateBack({ delta: 1, success: () => { console.log('✅ navigateBack 成功'); console.log('==========================================='); }, fail: (err) => { console.error('❌ navigateBack 失败:', err); console.log('⚠️ 尝试使用 reLaunch 跳转到首页'); this.goToHome(); } }); }, // 跳转到首页 goToHome() { console.log('==========================================='); console.log('======= goToHome 方法调用 ======='); const app = getApp(); console.log('globalData.rootPage:', app.globalData.rootPage); console.log('globalData.defaultTabBar:', app.globalData.defaultTabBar); // 尝试多个可能的首页路径 let rootPage = app.globalData.rootPage || app.globalData.defaultTabBar?.list?.[0]?.pagePath || '/pages/index/index' || '/index/index'; // 确保路径以 / 开头 if (!rootPage.startsWith('/')) { rootPage = '/' + rootPage; } console.log('准备跳转到:', rootPage); wx.reLaunch({ url: rootPage, success: () => { console.log('✅ reLaunch 成功'); console.log('==========================================='); }, fail: (err) => { console.error('❌ reLaunch 失败:', err); console.log('⚠️ 尝试使用 switchTab'); // 如果是 tabBar 页面,尝试使用 switchTab wx.switchTab({ url: rootPage, success: () => { console.log('✅ switchTab 成功'); console.log('==========================================='); }, fail: (err2) => { console.error('❌ switchTab 也失败:', err2); console.log('⚠️ 最后尝试:直接 navigateBack'); // 最后的兜底:直接返回 wx.navigateBack({ delta: 1, fail: (err3) => { console.error('❌ 所有跳转方式都失败了:', err3); console.log('==========================================='); // 显示错误提示 wx.showModal({ title: '提示', content: '页面跳转失败,请手动返回', showCancel: false }); } }); } }); } }); }, goBack: function () { wx.navigateBack({ delta: 1, }) }, //手动获取微信头像 onChooseAvatar(e) { console.log('=== onChooseAvatar 触发 ==='); console.log('事件对象:', e); const { avatarUrl } = e.detail; console.log('获取到的头像URL:', avatarUrl); console.log('头像URL类型:', typeof avatarUrl); console.log('头像URL长度:', avatarUrl ? avatarUrl.length : 0); if (avatarUrl) { // 微信头像URL可能是临时路径,需要先下载 // 临时路径格式:http://tmp/xxx.jpg // 相机拍照路径格式:wxfile://tmp_xxx.jpg this.setData({ avatarUrl: avatarUrl, avatarKey: Date.now() // 更新key强制刷新 }, () => { console.log('✅ 头像URL已更新到data:', this.data.avatarUrl); console.log('✅ avatarKey已更新:', this.data.avatarKey); }); } else { console.error('❌ 未获取到头像URL'); wx.showToast({ title: '开发工具不支持,请真机测试', icon: 'none', duration: 2000 }); } }, //获取昵称 onChangeName(e) { console.log('=== 昵称输入事件 ==='); console.log('事件对象:', e); // 注意:type="nickname" 的 input 会在用户输入时自动更新 model:value // 这里只是记录日志,实际的值更新由 model:value 自动处理 if (e.detail && e.detail.value !== undefined) { console.log('昵称值:', e.detail.value); } }, //确定头像昵称 async onComplete() { console.log('=== onComplete 方法被调用 ==='); if (this.data.isProcessingAuth) return; this.setData({ isProcessingAuth: true }) let { nickname, avatarUrl } = this.data const finalNickname = (nickname || '').toString().trim(); console.log('昵称:', nickname); console.log('头像URL:', avatarUrl); let user = Parse.User.current(); if (!user) { console.error('❌ 用户未登录,无法保存信息'); wx.showToast({ title: '用户未登录', icon: 'none' }); return; } console.log('当前用户ID:', user.id); if (!finalNickname) { this.setData({ isProcessingAuth: false }) wx.showToast({ title: '请输入微信昵称', icon: 'none' }); return; } const hasAvatar = !!user.get('avatar') if (!hasAvatar && !avatarUrl) { this.setData({ isProcessingAuth: false }) wx.showToast({ title: '请选择微信头像', icon: 'none' }); return; } // 显示加载提示 wx.showLoading({ title: '保存中...', mask: true }); try { if (avatarUrl) { console.log('📤 开始上传头像...'); let avatar = await this.updataAvatar(avatarUrl); if (avatar) { user.set("avatar", avatar); console.log('✅ 头像上传成功:', avatar); } else { console.warn('⚠️ 头像上传失败'); wx.hideLoading(); this.setData({ isProcessingAuth: false }) wx.showToast({ title: '头像上传失败,请重试', icon: 'none' }); return; } } user.set("nickname", finalNickname); console.log('✅ 昵称已设置:', finalNickname); await user.save(); try { await user.fetch(); } catch (e) {} if (!user.get('avatar')) { wx.hideLoading(); this.setData({ isProcessingAuth: false }) wx.showToast({ title: '头像保存失败,请重试', icon: 'none' }); return; } console.log('✅ 用户信息保存成功'); wx.hideLoading(); // 关闭弹窗 this.onClose(); // 延迟一下再跳转,确保弹窗关闭动画完成 setTimeout(() => { console.log('🚀 准备跳转...'); try { const u = Parse.User.current(); if (u && u.id) { wx.setStorageSync('userLogin', u.id); } } catch (e) {} this.backLoad(); }, 300); } catch (err) { wx.hideLoading(); this.setData({ isProcessingAuth: false }) console.error('❌ 保存用户信息失败:', err); wx.showModal({ title: '提示', content: '保存失败,请重试', showCancel: false, confirmText: '重试' }); } }, //关闭头像昵称填写弹窗 onClose() { this.setData({ wxModel: false, isProcessingAuth: false // 重置标记 }) }, //上传头像 async updataAvatar(url) { const normalizeUrl = (value) => { if (!value) return ''; let s = String(value).trim(); if (!s) return ''; if (s.startsWith('//')) return 'https:' + s; return s.replace(/^http:\/\//i, 'https://'); }; const normalizeDomain = (value) => { const d = normalizeUrl(value); if (!d) return ''; return d.endsWith('/') ? d.slice(0, -1) : d; }; const downloadIfNeeded = (src) => { return new Promise((resolve) => { if (!src) return resolve(''); const isRemote = /^https?:\/\//i.test(src) || src.startsWith('//'); if (!isRemote) return resolve(src); wx.downloadFile({ url: normalizeUrl(src), success: (res) => resolve(res?.tempFilePath || ''), fail: () => resolve('') }); }); }; try { if (!this.data.uptokenURL || !this.data.domain || !this.data.uploadURL) { await this.getUptoken(); } } catch (e) {} const filePath = await downloadIfNeeded(normalizeUrl(url)); if (!filePath) return false; return new Promise((resolve) => { qiniuUploader.upload( filePath, (res) => { const img = normalizeUrl(res?.imageURL || res?.fileUrl || ''); resolve(img || false); }, (error) => { console.log("error: " + error); resolve(false); }, { region: "SCN", uploadURL: this.data.uploadURL, domain: normalizeDomain(this.data.domain), uptoken: this.data.uptokenURL, } ); }); }, //选择勾选用户协议 onCheckAgreement() { this.setData({ check: !this.data.check }) }, //附件下载 openFile() { let { agreement } = this.data let url = agreement.content, name = agreement.title const _this = this; let rep = this.getFileType(url) console.log(url, name); wx.showLoading({ title: '加载中', }) wx.downloadFile({ url: url, //要预览的PDF的地址 filePath: wx.env.USER_DATA_PATH + `/${name}.${rep}`, success: function (res) { console.log(res); if (res.statusCode === 200) { //成功 var Path = res.filePath //返回的文件临时地址,用于后面打开本地预览所用 console.log(Path) wx.openDocument({ filePath: Path, //要打开的文件路径 showMenu: true, success: function (res) { wx.hideLoading() console.log(res, '打开PDF成功'); }, fail: function (res) { console.log(res) wx.hideLoading() } }) } }, fail: function (res) { wx.hideLoading() console.log(res); //失败 }, }) }, //解析文件类型 getFileType(url) { let pdfReg = /^.+(\.pdf)$/ let txtReg = /^.+(\.txt)$/ let wordReg = /^.+(\.doc|\.docx)$/ let excelReg = /^.+(\.xls|\.xlsx)$/ let jpgPng = /^.+(\.png)$/ let jpgJpg = /^.+(\.jpg)$/ let jpgJpeg = /^.+(\.jpeg)$/ if (pdfReg.test(url)) { return 'pdf' } if (txtReg.test(url)) { return 'txt' } if (wordReg.test(url)) { return 'docx' } if (excelReg.test(url)) { return 'xls' } if (jpgPng.test(url)) { return 'png' } if (jpgJpg.test(url)) { return 'jpg' } if (jpgJpeg.test(url)) { return 'jpeg' } }, onShow: function () { console.log('=== onShow 方法被调用 ==='); // 如果正在处理授权流程,不要自动返回 if (this.data.isProcessingAuth) { console.log('ℹ️ 正在处理授权流程,不自动返回'); return; } // 如果有弹窗显示(手机号弹窗或头像昵称弹窗),不要自动返回 if (this.data.phoneModal || this.data.wxModel) { console.log('ℹ️ 有弹窗显示,不自动返回'); return; } let userLogin = wx.getStorageSync('userLogin'); let currentUser = Parse.User.current(); console.log('userLogin 存储:', userLogin); console.log('当前用户:', currentUser ? currentUser.id : '无'); console.log('手机号:', currentUser?.get('mobile') || '无'); // 检查是否是从其他页面跳转过来的(有 returnUrl 参数) const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const hasReturnUrl = currentPage?.options?.returnUrl; if (hasReturnUrl) { console.log('ℹ️ 检测到 returnUrl 参数,用户需要完成登录流程'); // 不要自动返回,让用户完成登录 return; } // 只有当用户已登录且有手机号,并且不是从其他页面跳转过来时才返回 if (userLogin && currentUser && currentUser.get('mobile')) { console.log('✅ 用户已完整登录,返回上一页'); wx.navigateBack({ fail: () => { console.log('⚠️ 返回失败,可能是首页'); } }); } else { console.log('ℹ️ 用户未完整登录,显示授权页面'); } }, onReady: function () { }, })