index.js 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. let Parse = getApp().Parse;
  2. let company = getApp().globalData.company
  3. const request = require("../../utils/request");
  4. const qiniuUploader = require("../../utils/qiniuUploader");
  5. //获取应用实例
  6. const app = getApp()
  7. const real = require('../../utils/real')
  8. var timer
  9. /**
  10. * @class NovaAppAuth
  11. * @memberof module:components
  12. * @tutorial userauth
  13. * @desc 通用登录组件
  14. * # 登录组件相关数据表
  15. * - _User
  16. */
  17. Page({
  18. data: {
  19. phoneModal: false, //短信验证码登录弹窗
  20. logo: "https://file-cloud.fmode.cn/MldI5PBNt7/20210928/g0k1jb034826.png",
  21. name: "未来商城",
  22. desc: "江西脑控科技有限公司是国内领先的IT技术企业。专注于互联网+服务,面向政府提供区块链、大数据、物联网、人工智能解决方案",
  23. wxModel: false,
  24. avatarUrl: '',
  25. avatar: '',
  26. nickname: '',
  27. check: false,
  28. mobile: '', //手机号
  29. verilyCode: '', //验证码
  30. s: 0, //获取验证码倒计时 秒/s
  31. countDown: false,
  32. avatarKey: Date.now(), // 用于强制刷新头像显示
  33. isProcessingAuth: false, // 标记是否正在处理授权流程
  34. },
  35. onLoad: async function (options) {
  36. let Company = new Parse.Query('Company')
  37. Company.equalTo("objectId", company)
  38. let currentCompany = await Company.first()
  39. if (currentCompany && currentCompany.id) {
  40. this.setData({
  41. logo: currentCompany.get('logo'),
  42. name: currentCompany.get('name'),
  43. desc: currentCompany.get('desc')
  44. })
  45. }
  46. this.getUptoken()
  47. this.getAgreement() //用户协议
  48. },
  49. async getUptoken() {
  50. let res = await Parse.Cloud.run('qiniu_uptoken', {
  51. company: company
  52. })
  53. this.setData({
  54. uptokenURL: res.uptoken,
  55. domain: res.domain,
  56. uploadURL: res.zoneUrl
  57. })
  58. },
  59. async getAgreement() {
  60. let query = new Parse.Query('ContractAgreement')
  61. query.equalTo('type', 'wxapp')
  62. query.equalTo('company', company)
  63. query.select('title', 'content')
  64. let res = await query.first()
  65. if (res?.id) {
  66. this.setData({
  67. agreement: res.toJSON()
  68. })
  69. }
  70. },
  71. /* 是否同意授权协议 */
  72. getAgreementAuth() {
  73. if (!this.data.check && this.data.agreement) {
  74. wx.showModal({
  75. title: '提示',
  76. content: `请您仔细阅读并充分理解相关条款,点击同意即代表已阅读并同意《${this.data.agreement.title || '用户隐私协议'}》`,
  77. showCancel: true,
  78. cancelText: '取消',
  79. cancelColor: '#000000',
  80. confirmText: '同意',
  81. confirmColor: '#3CC51F',
  82. success: (result) => {
  83. if (result.confirm) {
  84. this.setData({
  85. check: true,
  86. })
  87. // this.getUserProfile()
  88. }
  89. },
  90. fail: () => { },
  91. complete: () => { }
  92. });
  93. return
  94. }
  95. // this.getUserProfile()
  96. return true
  97. },
  98. /* 判断是否绑定手机号 */
  99. async getUserProfile() {
  100. // 检查用户是否已登录
  101. let currentUser = Parse.User.current();
  102. if (!currentUser?.id) {
  103. console.log('⚠️ 用户未登录,需要先登录');
  104. // 不要在这里调用 checkAuth(true),因为它会触发微信官方的强制授权弹窗
  105. // 应该在外层(index.js)处理登录逻辑
  106. return false;
  107. }
  108. /* 如果手机号存在,已注册过判断是否上传过头像昵称信息 */
  109. if (currentUser?.get('mobile')) {
  110. wx.setStorageSync("userLogin", currentUser.id);
  111. // 检查是否需要完善信息(可选)
  112. // 如果用户没有昵称或昵称是默认的,提示完善信息
  113. const needProfile = !currentUser.get('nickname') ||
  114. currentUser.get('nickname') === '微信用户' ||
  115. currentUser.get('nickname') === '';
  116. if (needProfile) {
  117. // 显示自定义的完善信息弹窗(允许跳过)
  118. console.log('ℹ️ 显示自定义头像昵称弹窗');
  119. this.setData({
  120. wxModel: true
  121. });
  122. return false;
  123. }
  124. // 用户信息完整,返回上一页
  125. this.backLoad();
  126. return false;
  127. }
  128. // 用户已登录但没有手机号,允许继续
  129. return true;
  130. },
  131. /* 短信验证码登录弹窗 */
  132. async showDialogBtn() {
  133. let auth = this.getAgreementAuth()
  134. if (!auth) return
  135. let userProfile = await this.getUserProfile()
  136. if (!userProfile) return
  137. // 标记正在处理授权
  138. this.setData({
  139. isProcessingAuth: true,
  140. phoneModal: true
  141. })
  142. },
  143. async getPhoneNumber(e) {
  144. let auth = this.getAgreementAuth()
  145. if (!auth) return
  146. let userProfile = await this.getUserProfile()
  147. if (!userProfile) return
  148. // 标记正在处理授权
  149. this.setData({
  150. isProcessingAuth: true
  151. })
  152. let {
  153. code
  154. } = e.detail
  155. console.log(code);
  156. let phoneNumber = await request.getPhone(code)
  157. if(phoneNumber) this.authMobileUser(phoneNumber)
  158. },
  159. //合并User与绑定手机号逻辑
  160. async authMobileUser(mobile) {
  161. let currentUser = Parse.User.current()
  162. let queryMobUser = new Parse.Query('_User')
  163. queryMobUser.equalTo('mobile', mobile)
  164. queryMobUser.equalTo('company', company)
  165. queryMobUser.notEqualTo('type', 'admin')
  166. queryMobUser.notEqualTo('isDeleted', true)
  167. // queryMobUser.exists(`wxapp.${getApp().globalData.appid}`)
  168. let resMobUser = await queryMobUser.first()
  169. if (resMobUser?.id) {
  170. //请求User合并API,获取token重新登录,再更新昵称头像信息等
  171. let token = await this.getUpdateUserToken(currentUser.id, resMobUser.id)
  172. console.log(token);
  173. if (token) {
  174. Parse.User.become(token).then(async user => {
  175. // let user = Parse.User.current();
  176. wx.setStorageSync("userLogin", user.id);
  177. if (!user.get('avatar') || user.get('nickname') == '微信用户' || !user.get('nickname')) {
  178. this.setData({
  179. phoneModal: false,
  180. wxModel: true
  181. })
  182. return
  183. }
  184. this.backLoad()
  185. return
  186. })
  187. .catch(async err => {
  188. console.log('❌ Parse.User.become 失败:', err);
  189. // 不要直接退出,而是尝试重新登录
  190. wx.showModal({
  191. title: '提示',
  192. content: '登录状态异常,是否重新登录?',
  193. showCancel: true,
  194. cancelText: '取消',
  195. confirmText: '重新登录',
  196. success: async (result) => {
  197. if (result.confirm) {
  198. // 清除登录状态
  199. wx.removeStorageSync("sessionToken");
  200. wx.removeStorageSync("userLogin");
  201. try {
  202. // 尝试重新登录
  203. await Parse.User.logOut();
  204. await getApp().checkAuth(true);
  205. // 重新获取用户信息
  206. const currentUser = Parse.User.current();
  207. if (currentUser && currentUser.get('mobile')) {
  208. wx.setStorageSync("userLogin", currentUser.id);
  209. this.backLoad();
  210. }
  211. } catch (reloginErr) {
  212. console.error('❌ 重新登录失败:', reloginErr);
  213. wx.showToast({
  214. title: '登录失败,请稍后重试',
  215. icon: 'none'
  216. });
  217. }
  218. } else {
  219. // 用户取消,返回上一页
  220. wx.navigateBack();
  221. }
  222. },
  223. });
  224. return
  225. })
  226. return
  227. }
  228. return
  229. }
  230. currentUser.set('mobile', mobile)
  231. await currentUser.save()
  232. if (!currentUser.get('avatar') || currentUser.get('nickname') == '微信用户' || !currentUser.get('nickname')) {
  233. this.setData({
  234. phoneModal: false,
  235. wxModel: true
  236. })
  237. return
  238. }
  239. this.backLoad()
  240. return
  241. },
  242. async getUpdateUserToken(oldUser, newUserId) {
  243. return new Promise((resolve, reject) => {
  244. wx.login({
  245. success: function (res) {
  246. let parms = {
  247. oldUserId: oldUser,
  248. newUserId: newUserId,
  249. appId: getApp().globalData.appid,
  250. code: res.code,
  251. companyId: company,
  252. appType: getApp().globalData.appType || ''
  253. }
  254. if (res.code) {
  255. let url = 'https://server.fmode.cn/api/wxapp/combine/user'
  256. wx.request({
  257. url: url,
  258. data: parms,
  259. header: { 'content-type': 'application/json' },
  260. method: 'POST',
  261. async success(res) {
  262. console.log(res);
  263. let data = res.data
  264. if (data.code == 200) {
  265. wx.setStorageSync("sessionToken", data.data.token);
  266. // 用户合并成功后,更新 ScanRecord 表中的 user 字段
  267. console.log('🔄 [用户合并] 开始更新 ScanRecord 中的用户关联');
  268. console.log(' - 旧用户ID:', oldUser);
  269. console.log(' - 新用户ID:', newUserId);
  270. try {
  271. // 使用 Parse.User.become 切换到新用户
  272. await Parse.User.become(data.data.token);
  273. // 查询所有旧用户的扫码记录
  274. const ScanRecord = Parse.Object.extend('ScanRecord');
  275. const scanQuery = new Parse.Query(ScanRecord);
  276. scanQuery.equalTo('user', {
  277. __type: 'Pointer',
  278. className: '_User',
  279. objectId: oldUser
  280. });
  281. scanQuery.limit(1000); // 设置查询上限
  282. const oldRecords = await scanQuery.find();
  283. console.log(`📋 [查询结果] 找到 ${oldRecords.length} 条旧用户的扫码记录`);
  284. if (oldRecords.length > 0) {
  285. // 批量更新所有记录,将 user 指向新用户
  286. const updatePromises = oldRecords.map(record => {
  287. record.set('user', {
  288. __type: 'Pointer',
  289. className: '_User',
  290. objectId: newUserId
  291. });
  292. return record.save();
  293. });
  294. await Promise.all(updatePromises);
  295. console.log(`✅ [更新成功] 已将 ${oldRecords.length} 条扫码记录的用户更新为新用户`);
  296. } else {
  297. console.log('ℹ️ [无需更新] 旧用户没有扫码记录');
  298. }
  299. } catch (updateError) {
  300. console.error('❌ [更新失败] 更新 ScanRecord 失败:', updateError);
  301. console.error(' - 错误信息:', updateError.message);
  302. // 不影响主流程,继续返回 token
  303. }
  304. resolve(data.data.token)
  305. } else {
  306. console.log(data?.mess);
  307. wx.showModal({
  308. title: '提示',
  309. content: data?.mess,
  310. showCancel: false,
  311. cancelText: '取消',
  312. cancelColor: '#000000',
  313. confirmText: '确定',
  314. confirmColor: '#3CC51F',
  315. success: (result) => {
  316. if (result.confirm) {
  317. }
  318. },
  319. fail: () => { },
  320. complete: () => { }
  321. });
  322. resolve()
  323. }
  324. },
  325. });
  326. }
  327. },
  328. fail: function (err) {
  329. wx.showModal({
  330. title: '提示',
  331. content: '登录超时,请稍后重试',
  332. showCancel: false,
  333. cancelText: '取消',
  334. cancelColor: '#000000',
  335. confirmText: '确定',
  336. confirmColor: '#3CC51F',
  337. success: (result) => {
  338. if (result.confirm) {
  339. }
  340. },
  341. fail: () => { },
  342. complete: () => { }
  343. });
  344. console.warn('小程序wx.login失败');
  345. resolve()
  346. }
  347. });
  348. })
  349. },
  350. //获取验证码
  351. async getPhoneCode() {
  352. let { mobile, s, countDown } = this.data
  353. if (!real.isPoneAvailable(mobile)) {
  354. wx.showToast({
  355. title: '手机号格式有误',
  356. icon: 'error',
  357. duration: 1500,
  358. mask: false,
  359. });
  360. return
  361. }
  362. if(countDown || s > 0) return
  363. this.setData({
  364. countDown:true
  365. })
  366. let parsm = {
  367. company: company,
  368. mobile: mobile
  369. }
  370. let code = await this.getRequest(parsm, 'message')
  371. if(code?.code == 1){
  372. this.setData({
  373. s:60
  374. })
  375. this.decrementTime()
  376. }else{
  377. wx.showToast({
  378. title: '验证码获取失败',
  379. icon: 'error',
  380. image: '',
  381. duration: 1500,
  382. mask: false,
  383. });
  384. this.setData({
  385. countDown:false
  386. })
  387. }
  388. },
  389. //接口请求
  390. getRequest(parsm, apig) {
  391. return new Promise((resolve, rej) => {
  392. let url = 'https://server.fmode.cn/api/apig/'
  393. wx.request({
  394. url: url + apig,
  395. data: parsm,
  396. header: { 'content-type': 'application/json' },
  397. method: 'POST',
  398. dataType: 'json',
  399. responseType: 'text',
  400. success: (result) => {
  401. console.log(result);
  402. resolve(result.data)
  403. },
  404. fail: () => {
  405. resolve(false)
  406. },
  407. complete: () => { }
  408. });
  409. })
  410. },
  411. // 倒计时
  412. decrementTime(){
  413. timer = setTimeout(() => {
  414. let { s } = this.data
  415. if(s == 0){
  416. this.setData({ countDown:false })
  417. timer && clearTimeout(timer)
  418. return
  419. }
  420. s--
  421. this.setData({
  422. s:s
  423. })
  424. this.decrementTime()
  425. }, 1000);
  426. },
  427. //验证码绑定手机号登录
  428. async completePhone() {
  429. let { mobile, verilyCode } = this.data
  430. if(!real.isPoneAvailable(mobile) || !verilyCode.toString().trim()){
  431. wx.showToast({
  432. title: '手机号或验证码不正确',
  433. icon: 'none',
  434. image: '',
  435. duration: 1500,
  436. mask: false,
  437. });
  438. return
  439. }
  440. // 标记正在处理授权
  441. this.setData({
  442. isProcessingAuth: true
  443. })
  444. let parsm = {
  445. mobile: mobile,
  446. code:verilyCode
  447. }
  448. let isVerify = await this.getRequest(parsm, 'verifyCode')
  449. console.log(isVerify);
  450. if(isVerify.code == 200){
  451. this.authMobileUser(mobile.toString())
  452. }else{
  453. // 验证失败,重置标记
  454. this.setData({
  455. isProcessingAuth: false
  456. })
  457. wx.showToast({
  458. title:isVerify?.msg || '验证码错误',
  459. icon: 'none',
  460. image: '',
  461. duration: 1500,
  462. mask: false,
  463. });
  464. return
  465. }
  466. },
  467. //关闭手机号授权弹窗
  468. hideModal: function () {
  469. this.setData({
  470. phoneModal: false,
  471. isProcessingAuth: false // 重置标记
  472. })
  473. },
  474. backLoad() {
  475. console.log('===========================================');
  476. console.log('======= backLoad 方法调用 =======');
  477. let pages = getCurrentPages();
  478. console.log('当前页面栈层数:', pages.length);
  479. console.log('当前页面路由:', pages[pages.length - 1]?.route);
  480. // 检查是否有 returnUrl 参数(从 H5 页面传递过来)
  481. const currentPage = pages[pages.length - 1];
  482. const returnUrl = currentPage?.options?.returnUrl;
  483. if (returnUrl) {
  484. console.log('📍 检测到 returnUrl 参数:', returnUrl);
  485. // 如果是 web-view 页面,跳转回去
  486. const decodedUrl = decodeURIComponent(returnUrl);
  487. console.log('🔙 准备跳转回 H5 页面:', decodedUrl);
  488. wx.navigateTo({
  489. url: `/common-page/pages/web-view/index?path=${encodeURIComponent(decodedUrl)}`,
  490. success: () => {
  491. console.log('✅ 跳转回 H5 页面成功');
  492. console.log('===========================================');
  493. },
  494. fail: (err) => {
  495. console.error('❌ 跳转回 H5 页面失败:', err);
  496. // 降级:正常返回上一页
  497. this.normalBackLoad();
  498. }
  499. });
  500. return;
  501. }
  502. // 没有 returnUrl,执行正常的返回逻辑
  503. this.normalBackLoad();
  504. },
  505. normalBackLoad() {
  506. let pages = getCurrentPages();
  507. // 如果页面栈只有1层或没有上一页,直接跳转到首页
  508. if (pages.length <= 1) {
  509. console.log('⚠️ 没有上一个页面,直接跳转到首页');
  510. this.goToHome();
  511. return;
  512. }
  513. // 有上一个页面
  514. let beforePage = pages[pages.length - 2];
  515. console.log('上一个页面路由:', beforePage.route);
  516. // 尝试调用上一个页面的 onLoad 方法(如果存在)
  517. if (beforePage && typeof beforePage.onLoad === 'function') {
  518. try {
  519. let options = beforePage.options || { isInit: true };
  520. beforePage.onLoad(options);
  521. console.log('✅ 已调用上一个页面的 onLoad');
  522. } catch (err) {
  523. console.warn('⚠️ 调用上一个页面 onLoad 失败:', err);
  524. }
  525. }
  526. // 返回上一页
  527. console.log('🔙 执行 navigateBack...');
  528. wx.navigateBack({
  529. delta: 1,
  530. success: () => {
  531. console.log('✅ navigateBack 成功');
  532. console.log('===========================================');
  533. },
  534. fail: (err) => {
  535. console.error('❌ navigateBack 失败:', err);
  536. console.log('⚠️ 尝试使用 reLaunch 跳转到首页');
  537. this.goToHome();
  538. }
  539. });
  540. },
  541. // 跳转到首页
  542. goToHome() {
  543. console.log('===========================================');
  544. console.log('======= goToHome 方法调用 =======');
  545. const app = getApp();
  546. console.log('globalData.rootPage:', app.globalData.rootPage);
  547. console.log('globalData.defaultTabBar:', app.globalData.defaultTabBar);
  548. // 尝试多个可能的首页路径
  549. let rootPage = app.globalData.rootPage
  550. || app.globalData.defaultTabBar?.list?.[0]?.pagePath
  551. || '/pages/index/index'
  552. || '/index/index';
  553. // 确保路径以 / 开头
  554. if (!rootPage.startsWith('/')) {
  555. rootPage = '/' + rootPage;
  556. }
  557. console.log('准备跳转到:', rootPage);
  558. wx.reLaunch({
  559. url: rootPage,
  560. success: () => {
  561. console.log('✅ reLaunch 成功');
  562. console.log('===========================================');
  563. },
  564. fail: (err) => {
  565. console.error('❌ reLaunch 失败:', err);
  566. console.log('⚠️ 尝试使用 switchTab');
  567. // 如果是 tabBar 页面,尝试使用 switchTab
  568. wx.switchTab({
  569. url: rootPage,
  570. success: () => {
  571. console.log('✅ switchTab 成功');
  572. console.log('===========================================');
  573. },
  574. fail: (err2) => {
  575. console.error('❌ switchTab 也失败:', err2);
  576. console.log('⚠️ 最后尝试:直接 navigateBack');
  577. // 最后的兜底:直接返回
  578. wx.navigateBack({
  579. delta: 1,
  580. fail: (err3) => {
  581. console.error('❌ 所有跳转方式都失败了:', err3);
  582. console.log('===========================================');
  583. // 显示错误提示
  584. wx.showModal({
  585. title: '提示',
  586. content: '页面跳转失败,请手动返回',
  587. showCancel: false
  588. });
  589. }
  590. });
  591. }
  592. });
  593. }
  594. });
  595. },
  596. goBack: function () {
  597. wx.navigateBack({
  598. delta: 1,
  599. })
  600. },
  601. //手动获取微信头像
  602. onChooseAvatar(e) {
  603. console.log('=== onChooseAvatar 触发 ===');
  604. console.log('事件对象:', e);
  605. const { avatarUrl } = e.detail;
  606. console.log('获取到的头像URL:', avatarUrl);
  607. console.log('头像URL类型:', typeof avatarUrl);
  608. console.log('头像URL长度:', avatarUrl ? avatarUrl.length : 0);
  609. if (avatarUrl) {
  610. // 微信头像URL可能是临时路径,需要先下载
  611. // 临时路径格式:http://tmp/xxx.jpg
  612. // 相机拍照路径格式:wxfile://tmp_xxx.jpg
  613. this.setData({
  614. avatarUrl: avatarUrl,
  615. avatarKey: Date.now() // 更新key强制刷新
  616. }, () => {
  617. console.log('✅ 头像URL已更新到data:', this.data.avatarUrl);
  618. console.log('✅ avatarKey已更新:', this.data.avatarKey);
  619. });
  620. } else {
  621. console.error('❌ 未获取到头像URL');
  622. // 在开发环境下,如果获取失败,提示用户可以跳过
  623. wx.showToast({
  624. title: '开发工具不支持,请真机测试或跳过',
  625. icon: 'none',
  626. duration: 2000
  627. });
  628. }
  629. },
  630. //获取昵称
  631. onChangeName(e) {
  632. console.log('=== 昵称输入事件 ===');
  633. console.log('事件对象:', e);
  634. // 注意:type="nickname" 的 input 会在用户输入时自动更新 model:value
  635. // 这里只是记录日志,实际的值更新由 model:value 自动处理
  636. if (e.detail && e.detail.value !== undefined) {
  637. console.log('昵称值:', e.detail.value);
  638. }
  639. },
  640. //确定头像昵称
  641. async onComplete() {
  642. console.log('=== onComplete 方法被调用 ===');
  643. let {
  644. nickname,
  645. avatarUrl
  646. } = this.data
  647. console.log('昵称:', nickname);
  648. console.log('头像URL:', avatarUrl);
  649. let user = Parse.User.current();
  650. if (!user) {
  651. console.error('❌ 用户未登录,无法保存信息');
  652. wx.showToast({
  653. title: '用户未登录',
  654. icon: 'none'
  655. });
  656. return;
  657. }
  658. console.log('当前用户ID:', user.id);
  659. // 显示加载提示
  660. wx.showLoading({
  661. title: '保存中...',
  662. mask: true
  663. });
  664. try {
  665. // 如果用户填写了信息,则更新
  666. if (nickname || avatarUrl) {
  667. console.log('ℹ️ 用户填写了信息,开始更新');
  668. // 如果有头像,上传头像
  669. if (avatarUrl) {
  670. console.log('📤 开始上传头像...');
  671. let avatar = await this.updataAvatar(avatarUrl);
  672. if (avatar) {
  673. user.set("avatar", avatar);
  674. console.log('✅ 头像上传成功:', avatar);
  675. } else {
  676. console.warn('⚠️ 头像上传失败');
  677. }
  678. }
  679. // 如果有昵称,更新昵称
  680. if (nickname) {
  681. user.set("nickname", nickname);
  682. console.log('✅ 昵称已设置:', nickname);
  683. }
  684. await user.save();
  685. console.log('✅ 用户信息保存成功');
  686. } else {
  687. // 用户没有填写任何信息,使用默认值
  688. console.log('ℹ️ 用户跳过头像昵称设置,使用默认值');
  689. // 如果用户没有昵称,设置默认昵称
  690. if (!user.get('nickname') || user.get('nickname') === '微信用户') {
  691. const defaultNickname = '用户' + user.id.substring(0, 6);
  692. user.set('nickname', defaultNickname);
  693. await user.save();
  694. console.log('✅ 已设置默认昵称:', defaultNickname);
  695. }
  696. }
  697. wx.hideLoading();
  698. // 关闭弹窗
  699. this.onClose();
  700. // 延迟一下再跳转,确保弹窗关闭动画完成
  701. setTimeout(() => {
  702. console.log('🚀 准备跳转...');
  703. this.backLoad();
  704. }, 300);
  705. } catch (err) {
  706. wx.hideLoading();
  707. console.error('❌ 保存用户信息失败:', err);
  708. wx.showModal({
  709. title: '提示',
  710. content: '保存失败,是否继续?',
  711. showCancel: true,
  712. cancelText: '重试',
  713. confirmText: '继续',
  714. success: (result) => {
  715. if (result.confirm) {
  716. // 用户选择继续,直接跳转
  717. this.onClose();
  718. setTimeout(() => {
  719. this.backLoad();
  720. }, 300);
  721. }
  722. // 用户选择重试,留在当前页面
  723. }
  724. });
  725. }
  726. },
  727. //跳过头像昵称设置
  728. async onSkip() {
  729. console.log('=== onSkip 方法被调用 ===');
  730. let user = Parse.User.current();
  731. if (!user) {
  732. console.error('❌ 用户未登录');
  733. wx.showToast({
  734. title: '用户未登录',
  735. icon: 'none'
  736. });
  737. return;
  738. }
  739. console.log('当前用户ID:', user.id);
  740. wx.showLoading({
  741. title: '处理中...',
  742. mask: true
  743. });
  744. try {
  745. // 设置默认昵称(如果没有)
  746. if (!user.get('nickname') || user.get('nickname') === '微信用户') {
  747. const defaultNickname = '用户' + user.id.substring(0, 6);
  748. user.set('nickname', defaultNickname);
  749. await user.save();
  750. console.log('✅ 已设置默认昵称:', defaultNickname);
  751. } else {
  752. console.log('ℹ️ 用户已有昵称:', user.get('nickname'));
  753. }
  754. wx.hideLoading();
  755. // 关闭弹窗
  756. this.onClose();
  757. // 延迟一下再跳转
  758. setTimeout(() => {
  759. console.log('🚀 准备跳转...');
  760. this.backLoad();
  761. }, 300);
  762. } catch (err) {
  763. wx.hideLoading();
  764. console.error('❌ 设置默认昵称失败:', err);
  765. // 即使失败也允许继续
  766. this.onClose();
  767. setTimeout(() => {
  768. this.backLoad();
  769. }, 300);
  770. }
  771. },
  772. //关闭头像昵称填写弹窗
  773. onClose() {
  774. this.setData({
  775. wxModel: false,
  776. isProcessingAuth: false // 重置标记
  777. })
  778. },
  779. //上传头像
  780. updataAvatar(url) {
  781. let that = this;
  782. return new Promise((resolve, rejcet) => {
  783. qiniuUploader.upload(
  784. url,
  785. async (res) => {
  786. let img = res.imageURL;
  787. resolve(img)
  788. },
  789. (error) => {
  790. console.log("error: " + error);
  791. resolve(false)
  792. }, {
  793. region: "SCN",
  794. uploadURL: that.data.uploadURL,
  795. domain: that.data.domain,
  796. uptoken: that.data.uptokenURL,
  797. }
  798. );
  799. })
  800. },
  801. //选择勾选用户协议
  802. onCheckAgreement() {
  803. this.setData({
  804. check: !this.data.check
  805. })
  806. },
  807. //附件下载
  808. openFile() {
  809. let {
  810. agreement
  811. } = this.data
  812. let url = agreement.content,
  813. name = agreement.title
  814. const _this = this;
  815. let rep = this.getFileType(url)
  816. console.log(url, name);
  817. wx.showLoading({
  818. title: '加载中',
  819. })
  820. wx.downloadFile({
  821. url: url, //要预览的PDF的地址
  822. filePath: wx.env.USER_DATA_PATH + `/${name}.${rep}`,
  823. success: function (res) {
  824. console.log(res);
  825. if (res.statusCode === 200) { //成功
  826. var Path = res.filePath //返回的文件临时地址,用于后面打开本地预览所用
  827. console.log(Path)
  828. wx.openDocument({
  829. filePath: Path, //要打开的文件路径
  830. showMenu: true,
  831. success: function (res) {
  832. wx.hideLoading()
  833. console.log(res, '打开PDF成功');
  834. },
  835. fail: function (res) {
  836. console.log(res)
  837. wx.hideLoading()
  838. }
  839. })
  840. }
  841. },
  842. fail: function (res) {
  843. wx.hideLoading()
  844. console.log(res); //失败
  845. },
  846. })
  847. },
  848. //解析文件类型
  849. getFileType(url) {
  850. let pdfReg = /^.+(\.pdf)$/
  851. let txtReg = /^.+(\.txt)$/
  852. let wordReg = /^.+(\.doc|\.docx)$/
  853. let excelReg = /^.+(\.xls|\.xlsx)$/
  854. let jpgPng = /^.+(\.png)$/
  855. let jpgJpg = /^.+(\.jpg)$/
  856. let jpgJpeg = /^.+(\.jpeg)$/
  857. if (pdfReg.test(url)) {
  858. return 'pdf'
  859. }
  860. if (txtReg.test(url)) {
  861. return 'txt'
  862. }
  863. if (wordReg.test(url)) {
  864. return 'docx'
  865. }
  866. if (excelReg.test(url)) {
  867. return 'xls'
  868. }
  869. if (jpgPng.test(url)) {
  870. return 'png'
  871. }
  872. if (jpgJpg.test(url)) {
  873. return 'jpg'
  874. }
  875. if (jpgJpeg.test(url)) {
  876. return 'jpeg'
  877. }
  878. },
  879. onShow: function () {
  880. console.log('=== onShow 方法被调用 ===');
  881. // 如果正在处理授权流程,不要自动返回
  882. if (this.data.isProcessingAuth) {
  883. console.log('ℹ️ 正在处理授权流程,不自动返回');
  884. return;
  885. }
  886. // 如果有弹窗显示(手机号弹窗或头像昵称弹窗),不要自动返回
  887. if (this.data.phoneModal || this.data.wxModel) {
  888. console.log('ℹ️ 有弹窗显示,不自动返回');
  889. return;
  890. }
  891. let userLogin = wx.getStorageSync('userLogin');
  892. let currentUser = Parse.User.current();
  893. console.log('userLogin 存储:', userLogin);
  894. console.log('当前用户:', currentUser ? currentUser.id : '无');
  895. console.log('手机号:', currentUser?.get('mobile') || '无');
  896. // 检查是否是从其他页面跳转过来的(有 returnUrl 参数)
  897. const pages = getCurrentPages();
  898. const currentPage = pages[pages.length - 1];
  899. const hasReturnUrl = currentPage?.options?.returnUrl;
  900. if (hasReturnUrl) {
  901. console.log('ℹ️ 检测到 returnUrl 参数,用户需要完成登录流程');
  902. // 不要自动返回,让用户完成登录
  903. return;
  904. }
  905. // 只有当用户已登录且有手机号,并且不是从其他页面跳转过来时才返回
  906. if (userLogin && currentUser && currentUser.get('mobile')) {
  907. console.log('✅ 用户已完整登录,返回上一页');
  908. wx.navigateBack({
  909. fail: () => {
  910. console.log('⚠️ 返回失败,可能是首页');
  911. }
  912. });
  913. } else {
  914. console.log('ℹ️ 用户未完整登录,显示授权页面');
  915. }
  916. },
  917. onReady: function () {
  918. },
  919. })