export default { methods: { // 清除登录态(token / 会员信息 / 购物车 / 本地存储) clearLoginState() { this.$store.commit('setToken', ''); this.$store.commit('setMemberInfo', ''); this.$store.dispatch('emptyCart'); uni.removeStorageSync('authInfo'); uni.removeStorageSync('privacyAgreed'); }, // 跨平台登录入口:小程序下用 ns-login 原生授权弹窗 (走 wx.login / getPhoneNumber), // H5 / 快应用 / APP 下用原生登录页 /pages_tool/login/login (手机号+动态码表单). // // 修复背景: 之前所有跳转统一用 LOGIN_PAGE_URL (/pages_tool/login/login), // 这个原生登录页在微信小程序下是 form 提交 (像 H5), 没有走 wx.login 授权。 // 期望行为: // - 微信小程序 / 鸿蒙元服务 / 其他小程序: 跳到首页 /pages/index/index, // 首页挂载了 , 用户后续操作触发 _requireHomeAuth // 时会自动弹 ns-login 弹窗, 走原生 wx.login / getPhoneNumber 授权. // - H5 / 快应用 / APP: 保持跳 LOGIN_PAGE_URL (原生登录页), 表单流程正常. getLoginEntryUrl() { // #ifdef MP-WEIXIN || MP-HARMONY || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ || MP-KUAISHOU || MP-JD || MP-360 || MP-XHS return this.$util.INDEX_PAGE_URL; // #endif // #ifndef MP-WEIXIN || MP-HARMONY || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ || MP-KUAISHOU || MP-JD || MP-360 || MP-XHS return this.$util.LOGIN_PAGE_URL; // #endif }, // 统一的"跳登录入口"封装, 包含组件级防抖锁 + 清登录态 + reLaunch // // 为什么需要防抖: 微信小程序下, 短时间内连发 reLaunch 会触发 // "appLaunch with non-empty page stack" native 错误 (页面销毁未完成, 新 launch 时栈非空). // 注销/退出流程中常见并发场景: // - cancelsuccess.vue onLoad 调 getStatus 异步回调 + 用户点 "完成" 按钮 // - 多个 submitCancelApply 同时被触发 // 防抖策略: 同一组件实例 800ms 内只能跳一次, 之后忽略 // (util.js reLaunch 分支还有 300ms 全局锁作为第二道防线) redirectToLoginOnce() { // 组件级防抖: 800ms 内重复调用直接忽略 const now = Date.now(); if (this._lastLoginRedirectAt && now - this._lastLoginRedirectAt < 800) { console.warn('[member-public] redirectToLoginOnce 防抖: 800ms 内重复调用已忽略'); return; } this._lastLoginRedirectAt = now; this.clearLoginState(); // 小程序下 getLoginEntryUrl() 返回首页 (走 ns-login 原生授权弹窗), // H5 / APP 下返回原生登录页 (form 提交) this.$util.redirectTo(this.getLoginEntryUrl(), {}, 'reLaunch'); }, // 退出登录 logout() { uni.showModal({ title: this.$lang('logoutTitle'), content: this.$lang('logoutContent'), success: (res) => { if (res.confirm) { // 统一的跳登录入口: 内部带防抖锁, 避免连发 reLaunch this.redirectToLoginOnce(); } } }); }, // 账号注销入口:先查状态,根据状态分流 cancellation() { this.getCancelStatus(); }, // 查询注销状态并跳转对应页面 // status: undefined/null → 未申请 → 协议页 cancellation.vue // status: 0 → 审核中 → 状态页 cancelstatus.vue // status: 1 → 通过 → 成功页 cancelsuccess.vue // status: -1 → 拒绝 → 拒绝页 cancelrefuse.vue getCancelStatus() { this.$api.sendRequest({ url: '/membercancel/api/membercancel/info', success: res => { if (res.code >= 0) { if (res.data) { if (res.data.status == 0) { this.$util.redirectTo('/pages_tool/member/cancelstatus'); } else if (res.data.status == 1) { this.$util.redirectTo('/pages_tool/member/cancelsuccess'); } else { this.$util.redirectTo('/pages_tool/member/cancelrefuse'); } } else { this.$util.redirectTo('/pages_tool/member/cancellation'); } } else if (res.code == -1) { // 统一的跳登录入口: 内部带防抖锁, 避免连发 reLaunch this.redirectToLoginOnce(); } } }); }, // 提交注销申请并清理登录态(供 assets.vue 等页面调用) submitCancelApply(options = {}) { uni.showModal({ title: options.title || this.$lang('member.public.riskWarningTitle'), content: options.content || this.$lang('member.public.cancelAccountConfirm'), confirmColor: '#000000', success: res => { if (res.confirm) { this.$api.sendRequest({ url: '/membercancel/api/membercancel/apply', success: rres => { if (rres.code >= 0) { // 注销申请提交成功后立刻清空登录态, // 避免用户通过标题栏/导航栏返回到会员中心等页面时仍能看到账号信息 if (options.clearStateAndRedirect) { // 跳登录入口: 内部带防抖锁, 避免连发 reLaunch this.redirectToLoginOnce(); } else { // 跳 cancelstatus (审核中), 也走 reLaunch 清栈 this.clearLoginState(); this.$util.redirectTo('/pages_tool/member/cancelstatus', {}, 'reLaunch'); } } else { this.$util.showToast({ title: rres.message }); } } }); } } }); } } };