my.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. "use strict";
  2. const common_vendor = require("../../common/vendor.js");
  3. const api_user = require("../../api/user.js");
  4. const common_assets = require("../../common/assets.js");
  5. new Proxy({}, {
  6. get(_, key) {
  7. throw new Error(`Module "util" has been externalized for browser compatibility. Cannot access "util.${key}" in client code. See https://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.`);
  8. }
  9. });
  10. const _sfc_main = {
  11. data() {
  12. return {
  13. isLogin: false,
  14. userInfo: {
  15. username: "",
  16. userId: "",
  17. avatar: ""
  18. },
  19. menuItems: [
  20. { title: "个人资料", icon: "icon-user", action: "profile" },
  21. // { title: '我的订单', icon: 'icon-order', action: 'orders' },
  22. // { title: '我的收藏', icon: 'icon-star', action: 'favorites' },
  23. { title: "设置", icon: "icon-settings", action: "settings" },
  24. { title: "帮助中心", icon: "icon-help", action: "help" }
  25. ],
  26. showAuthModal: false,
  27. wxLoginCode: ""
  28. // 存储微信登录code
  29. };
  30. },
  31. onLoad() {
  32. this.checkLogin();
  33. },
  34. onShow() {
  35. this.checkLoginStatus();
  36. },
  37. methods: {
  38. checkLogin() {
  39. const userInfo = common_vendor.index.getStorageSync("userInfo");
  40. if (!userInfo) {
  41. common_vendor.index.reLaunch({
  42. url: "/pages/login/login",
  43. success: () => {
  44. console.log("跳转到身份验证登录页面成功");
  45. },
  46. fail: (err) => {
  47. console.error("跳转到身份验证登录页面失败:", err);
  48. common_vendor.index.showToast({
  49. title: "跳转失败,请重试",
  50. icon: "none"
  51. });
  52. }
  53. });
  54. return false;
  55. }
  56. try {
  57. const parsedUserInfo = JSON.parse(userInfo);
  58. if (!parsedUserInfo.openid) {
  59. common_vendor.index.navigateTo({
  60. url: "/pages/login/login"
  61. });
  62. return false;
  63. }
  64. return true;
  65. } catch (e) {
  66. console.error("解析用户信息失败:", e);
  67. common_vendor.index.removeStorageSync("userInfo");
  68. common_vendor.index.navigateTo({
  69. url: "/pages/login/login"
  70. });
  71. return false;
  72. }
  73. },
  74. // 检查登录状态
  75. checkLoginStatus() {
  76. try {
  77. const token = common_vendor.index.getStorageSync("token");
  78. const userInfoStr = common_vendor.index.getStorageSync("userInfo");
  79. if (token && userInfoStr) {
  80. const userInfo = JSON.parse(userInfoStr);
  81. const loginTime = userInfo.loginTime || 0;
  82. const currentTime = (/* @__PURE__ */ new Date()).getTime();
  83. const loginExpireTime = 7 * 24 * 60 * 60 * 1e3;
  84. if (currentTime - loginTime > loginExpireTime) {
  85. console.log("登录已过期,需要重新登录");
  86. this.handleLogout(false);
  87. return;
  88. }
  89. this.isLogin = true;
  90. this.userInfo = userInfo;
  91. this.fetchUserDetail();
  92. } else {
  93. this.isLogin = false;
  94. this.userInfo = {
  95. username: "",
  96. userId: "",
  97. avatar: "",
  98. phone: ""
  99. };
  100. }
  101. } catch (e) {
  102. console.error("获取登录状态失败", e);
  103. this.isLogin = false;
  104. }
  105. },
  106. // 前往登录页
  107. goLogin() {
  108. common_vendor.index.navigateTo({
  109. url: "/pages/login/login"
  110. });
  111. },
  112. // 微信登录
  113. wxLogin() {
  114. this.getWxLoginCode();
  115. },
  116. // 获取微信登录 code
  117. getWxLoginCode() {
  118. common_vendor.index.showLoading({ title: "登录中..." });
  119. common_vendor.index.login({
  120. provider: "weixin",
  121. success: (loginRes) => {
  122. console.log("获取微信登录code成功:", loginRes.code);
  123. this.wxLoginCode = loginRes.code;
  124. common_vendor.index.hideLoading();
  125. this.showAuthModal = true;
  126. },
  127. fail: (err) => {
  128. common_vendor.index.hideLoading();
  129. console.error("获取微信登录code失败:", err);
  130. common_vendor.index.showToast({
  131. title: "微信登录失败",
  132. icon: "none"
  133. });
  134. }
  135. });
  136. },
  137. // 用户点击授权按钮时调用
  138. getUserProfile() {
  139. common_vendor.wx$1.getUserProfile({
  140. desc: "用于完善用户资料",
  141. success: (profileRes) => {
  142. console.log("获取用户信息成功:", profileRes);
  143. const loginParams = {
  144. code: this.wxLoginCode,
  145. userInfo: profileRes.userInfo,
  146. signature: profileRes.signature,
  147. rawData: profileRes.rawData,
  148. encryptedData: profileRes.encryptedData,
  149. iv: profileRes.iv
  150. };
  151. this.showAuthModal = false;
  152. this.wxLoginRequest(loginParams);
  153. },
  154. fail: (err) => {
  155. console.error("获取用户信息失败:", err);
  156. this.showAuthModal = false;
  157. this.wxLoginRequest({
  158. code: this.wxLoginCode,
  159. userInfo: {
  160. nickName: "微信用户",
  161. avatarUrl: "",
  162. gender: 0,
  163. province: "",
  164. city: "",
  165. country: ""
  166. }
  167. });
  168. }
  169. });
  170. },
  171. // 取消授权
  172. cancelAuth() {
  173. this.showAuthModal = false;
  174. this.wxLoginRequest({
  175. code: this.wxLoginCode,
  176. userInfo: {
  177. nickName: "微信用户",
  178. avatarUrl: "",
  179. gender: 0,
  180. province: "",
  181. city: "",
  182. country: ""
  183. }
  184. });
  185. },
  186. // 头像选择回调
  187. onChooseAvatar(e) {
  188. const { avatarUrl } = e.detail;
  189. console.log("用户选择的头像:", avatarUrl);
  190. },
  191. // 发送微信登录请求并处理结果
  192. async wxLoginRequest(loginParams) {
  193. try {
  194. common_vendor.index.showLoading({ title: "登录中..." });
  195. console.log("发送登录请求,参数:", loginParams);
  196. const data = await api_user.wxLogin(loginParams);
  197. console.log("登录成功,返回数据:", data);
  198. const userData = this.buildUserData(data, loginParams);
  199. this.saveLoginState(data, userData);
  200. if (userData.userId) {
  201. this.fetchUserDetail();
  202. } else {
  203. console.log("无法获取用户ID,跳过获取详细信息");
  204. }
  205. if (!userData.phone) {
  206. console.log("用户未绑定手机号,可以提示用户绑定");
  207. }
  208. } catch (error) {
  209. this.handleLoginError(error, loginParams);
  210. }
  211. },
  212. /**
  213. * 构建用户数据对象
  214. * @param {Object} data - 后端返回的数据
  215. * @param {Object} loginParams - 登录参数
  216. * @returns {Object} - 构建的用户数据
  217. */
  218. buildUserData(data, loginParams) {
  219. console.log("构建用户数据,服务器返回:", data);
  220. let userData = {
  221. // 用户基本信息 - 优先使用服务器返回的数据
  222. username: data.username || data.nickName || (loginParams.userInfo ? loginParams.userInfo.nickName : "微信用户"),
  223. // 用户ID可能在不同字段
  224. userId: data.userId || data.user_id || data.id || data.openid || "",
  225. // 头像可能在不同字段
  226. avatar: data.avatar || data.avatarUrl || (loginParams.userInfo ? loginParams.userInfo.avatarUrl : "/static/avatar.png"),
  227. // 用户详细信息
  228. phone: data.phone || data.mobile || "",
  229. gender: data.gender || (loginParams.userInfo ? loginParams.userInfo.gender : 0),
  230. // 微信相关信息
  231. openid: data.openid || "",
  232. unionid: data.unionid || "",
  233. session_key: data.session_key || "",
  234. // 是否新用户
  235. is_new_user: data.is_new_user || false,
  236. // 登录时间
  237. loginTime: (/* @__PURE__ */ new Date()).getTime()
  238. };
  239. console.log("构建的用户数据:", userData);
  240. return userData;
  241. },
  242. /**
  243. * 保存登录状态和用户信息
  244. * @param {Object} data - 后端返回的数据
  245. * @param {Object} userData - 构建的用户数据
  246. */
  247. saveLoginState(data, userData) {
  248. const token = data.token || data.session_key || "";
  249. if (token) {
  250. common_vendor.index.setStorageSync("token", token);
  251. console.log("Token已保存:", token);
  252. }
  253. common_vendor.index.setStorageSync("userInfo", JSON.stringify(userData));
  254. console.log("用户信息已保存");
  255. this.isLogin = true;
  256. this.userInfo = userData;
  257. common_vendor.index.hideLoading();
  258. common_vendor.index.showToast({
  259. title: "登录成功",
  260. icon: "success"
  261. });
  262. },
  263. /**
  264. * 处理登录错误
  265. * @param {Error} error - 错误对象
  266. * @param {Object} loginParams - 登录参数
  267. */
  268. handleLoginError(error, loginParams) {
  269. common_vendor.index.hideLoading();
  270. if (error.message && (error.message.includes("code无效") || error.message.includes("已过期") || error.message.includes("已被使用") || error.status === 999)) {
  271. console.error("微信登录code无效,重新获取:", error);
  272. common_vendor.index.showToast({
  273. title: "code已过期,请重试",
  274. icon: "none",
  275. duration: 2e3
  276. });
  277. setTimeout(() => {
  278. this.getWxLoginCode();
  279. }, 1e3);
  280. return;
  281. }
  282. if (error.code === 10001) {
  283. common_vendor.index.navigateTo({
  284. url: "/pages/bind/bind?code=" + (loginParams.code || "")
  285. });
  286. } else if (error.message && error.message.includes("CSRF")) {
  287. console.error("CSRF验证失败:", error);
  288. common_vendor.index.showToast({
  289. title: "CSRF验证失败,请刷新页面重试",
  290. icon: "none",
  291. duration: 2e3
  292. });
  293. setTimeout(() => this.refreshCSRFToken(), 2e3);
  294. } else {
  295. console.error("微信登录失败:", error);
  296. common_vendor.index.showToast({
  297. title: error.message || "登录失败",
  298. icon: "none"
  299. });
  300. }
  301. },
  302. /**
  303. * 获取用户详细信息
  304. * 步骤6: 获取并更新用户详细信息
  305. */
  306. async fetchUserDetail() {
  307. try {
  308. if (!this.isLogin)
  309. return;
  310. const userId = this.userInfo.userId;
  311. const userDetail = await api_user.getUserInfo(userId);
  312. console.log("获取用户详细信息成功:", userDetail);
  313. if (userDetail) {
  314. this.updateUserInfo(userDetail);
  315. }
  316. } catch (error) {
  317. console.error("获取用户详细信息失败:", error);
  318. }
  319. },
  320. /**
  321. * 更新用户信息
  322. * @param {Object} userDetail - 用户详细信息
  323. */
  324. updateUserInfo(userDetail) {
  325. const updatedUserInfo = {
  326. ...this.userInfo,
  327. // 更新基本信息
  328. username: userDetail.username || userDetail.nickName || this.userInfo.username,
  329. avatar: userDetail.avatar || userDetail.avatarUrl || this.userInfo.avatar,
  330. phone: userDetail.phone || userDetail.mobile || this.userInfo.phone,
  331. // 更新详细信息
  332. email: userDetail.email || "",
  333. address: userDetail.address || "",
  334. birthday: userDetail.birthday || "",
  335. // 其他字段
  336. ...userDetail
  337. };
  338. this.userInfo = updatedUserInfo;
  339. common_vendor.index.setStorageSync("userInfo", JSON.stringify(updatedUserInfo));
  340. console.log("用户详细信息已更新");
  341. },
  342. /**
  343. * 获取用户手机号
  344. * @param {Object} e - 事件对象
  345. */
  346. getPhoneNumber(e) {
  347. if (e.detail.code) {
  348. common_vendor.wx$1.request({
  349. url: "http:192.168.66.187:8083/wechat/getUserPhoneNumber",
  350. method: "POST",
  351. data: {
  352. code: e.detail.code,
  353. // 刚获取的新code
  354. openid: this.data.openid
  355. }
  356. });
  357. }
  358. },
  359. /* async getPhoneNumber(e) {
  360. console.log('获取手机号事件:', e);
  361. // 检查是否成功获取
  362. if (e.detail.errMsg !== 'getPhoneNumber:ok') {
  363. console.error('用户拒绝授权手机号');
  364. uni.showToast({
  365. title: '获取手机号失败',
  366. icon: 'none'
  367. });
  368. return;
  369. }
  370. try {
  371. uni.showLoading({ title: '获取手机号中...' });
  372. // 每次都重新获取最新的登录code
  373. const loginResult = await new Promise((resolve, reject) => {
  374. uni.login({
  375. provider: 'weixin',
  376. success: (res) => resolve(res),
  377. fail: (err) => reject(err)
  378. });
  379. });
  380. if (!loginResult || !loginResult.code) {
  381. throw new Error('获取微信登录凭证失败');
  382. }
  383. console.log('成功获取新的登录code:', loginResult.code);
  384. // 获取存储的用户信息
  385. const userInfoStr = uni.getStorageSync('userInfo');
  386. if (!userInfoStr) {
  387. throw new Error('用户信息不存在,请重新登录');
  388. }
  389. const userInfo = JSON.parse(userInfoStr);
  390. // 准备请求参数
  391. const params = {
  392. code: loginResult.code,
  393. encryptedData: e.detail.encryptedData,
  394. iv: e.detail.iv,
  395. openid: userInfo.openid
  396. };
  397. console.log('获取手机号请求参数:', params);
  398. // 调用获取手机号API
  399. const phoneData = await getUserPhoneNumber(params);
  400. console.log('获取手机号成功:', phoneData);
  401. // 更新用户信息
  402. if (phoneData && phoneData.phoneNumber) {
  403. const updatedUserInfo = {
  404. ...this.userInfo,
  405. phone: phoneData.phoneNumber
  406. };
  407. // 更新状态和存储
  408. this.userInfo = updatedUserInfo;
  409. uni.setStorageSync('userInfo', JSON.stringify(updatedUserInfo));
  410. uni.showToast({
  411. title: '手机号绑定成功',
  412. icon: 'success'
  413. });
  414. } else {
  415. throw new Error('未能获取到手机号');
  416. }
  417. } catch (error) {
  418. console.error('获取手机号失败:', error);
  419. uni.showToast({
  420. title: error.message || '获取手机号失败',
  421. icon: 'none'
  422. });
  423. } finally {
  424. uni.hideLoading();
  425. }
  426. }, */
  427. // 添加刷新 CSRF token 的方法
  428. refreshCSRFToken() {
  429. common_vendor.index.request({
  430. url: "your-api-endpoint/csrf-token",
  431. // 替换为获取 CSRF token 的 API
  432. method: "GET",
  433. success: (res) => {
  434. if (res.data && res.data.csrfToken) {
  435. common_vendor.index.setStorageSync("csrfToken", res.data.csrfToken);
  436. console.log("CSRF token 已刷新");
  437. }
  438. },
  439. fail: (err) => {
  440. console.error("获取 CSRF token 失败", err);
  441. }
  442. });
  443. },
  444. handleMenuClick(item) {
  445. const needLogin = ["profile", "orders", "favorites"];
  446. if (needLogin.includes(item.action) && !this.isLogin) {
  447. common_vendor.index.showToast({
  448. title: "请先登录",
  449. icon: "none"
  450. });
  451. setTimeout(() => {
  452. this.goLogin();
  453. }, 1500);
  454. return;
  455. }
  456. switch (item.action) {
  457. case "profile":
  458. common_vendor.index.navigateTo({ url: "/pages/profile/profile" });
  459. break;
  460. case "orders":
  461. common_vendor.index.navigateTo({ url: "/pages/orders/orders" });
  462. break;
  463. case "favorites":
  464. common_vendor.index.navigateTo({ url: "/pages/favorites/favorites" });
  465. break;
  466. case "settings":
  467. common_vendor.index.navigateTo({ url: "/pages/settings/settings" });
  468. break;
  469. case "help":
  470. common_vendor.index.navigateTo({ url: "/pages/help/help" });
  471. break;
  472. default:
  473. common_vendor.index.showToast({
  474. title: `点击了${item.title}`,
  475. icon: "none"
  476. });
  477. }
  478. },
  479. // 处理退出登录 - 增强版
  480. handleLogout(showConfirm = true) {
  481. const doLogout = () => {
  482. api_user.logout().then(() => {
  483. try {
  484. common_vendor.index.removeStorageSync("token");
  485. common_vendor.index.removeStorageSync("userInfo");
  486. this.isLogin = false;
  487. this.userInfo = {
  488. username: "",
  489. userId: "",
  490. avatar: "",
  491. phone: ""
  492. };
  493. if (showConfirm) {
  494. common_vendor.index.showToast({
  495. title: "已退出登录",
  496. icon: "success"
  497. });
  498. }
  499. } catch (e) {
  500. console.error("退出登录失败", e);
  501. if (showConfirm) {
  502. common_vendor.index.showToast({
  503. title: "退出登录失败",
  504. icon: "none"
  505. });
  506. }
  507. }
  508. }).catch((err) => {
  509. console.error("退出登录请求失败", err);
  510. common_vendor.index.removeStorageSync("token");
  511. common_vendor.index.removeStorageSync("userInfo");
  512. this.isLogin = false;
  513. if (showConfirm) {
  514. common_vendor.index.showToast({
  515. title: err.message || "退出登录失败",
  516. icon: "none"
  517. });
  518. }
  519. });
  520. };
  521. if (showConfirm) {
  522. common_vendor.index.showModal({
  523. title: "提示",
  524. content: "确定要退出登录吗?",
  525. success: (res) => {
  526. if (res.confirm) {
  527. doLogout();
  528. }
  529. }
  530. });
  531. } else {
  532. doLogout();
  533. }
  534. },
  535. // 格式化手机号,例如:188****8888
  536. formatPhone(phone) {
  537. if (!phone || phone.length < 11)
  538. return phone;
  539. return phone.substring(0, 3) + "****" + phone.substring(7);
  540. }
  541. }
  542. };
  543. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  544. return common_vendor.e({
  545. a: $data.isLogin
  546. }, $data.isLogin ? common_vendor.e({
  547. b: $data.userInfo.avatar || "/static/avatar.png",
  548. c: common_vendor.t($data.userInfo.username),
  549. d: $data.userInfo.phone
  550. }, $data.userInfo.phone ? {
  551. e: common_vendor.t($options.formatPhone($data.userInfo.phone))
  552. } : {}) : {
  553. f: common_assets._imports_0$1,
  554. g: common_vendor.o((...args) => $options.goLogin && $options.goLogin(...args))
  555. }, {
  556. h: common_vendor.f($data.menuItems, (item, index, i0) => {
  557. return {
  558. a: common_vendor.n(item.icon),
  559. b: common_vendor.t(item.title),
  560. c: index,
  561. d: common_vendor.o(($event) => $options.handleMenuClick(item), index)
  562. };
  563. }),
  564. i: $data.isLogin
  565. }, $data.isLogin ? {
  566. j: common_vendor.o((...args) => $options.handleLogout && $options.handleLogout(...args))
  567. } : {}, {
  568. k: $data.showAuthModal
  569. }, $data.showAuthModal ? {
  570. l: common_vendor.o((...args) => $options.getUserProfile && $options.getUserProfile(...args)),
  571. m: common_vendor.o((...args) => $options.cancelAuth && $options.cancelAuth(...args))
  572. } : {});
  573. }
  574. const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
  575. wx.createPage(MiniProgramPage);