diff --git a/codes/README.md b/codes/README.md new file mode 100644 index 0000000..38a29c3 --- /dev/null +++ b/codes/README.md @@ -0,0 +1,3 @@ +# 参考代码 + +部分代码片段,供参考。 \ No newline at end of file diff --git a/codes/router.txt b/codes/router.txt new file mode 100644 index 0000000..e9e28d5 --- /dev/null +++ b/codes/router.txt @@ -0,0 +1,222 @@ +import { getCurrentInstance, type App } from 'vue' +import { useUserLoginStore } from '@/store/login' +import { Pages } from './pages' +import { LoginPopupViewer } from './loginPopupServices' +import Loading from './Loading' + +/** 实时判断用户是否已登录(避免 computed 缓存) */ +function isUserLoggedIn(): boolean { + return useUserLoginStore().isLoggedIn +} + +// 路由相关配置 +// 这里可以根据实际情况调整 +// 例如:需要登录验证的页面等 +// 以及登录页面、会员中心页面等 + +// 需要登录验证的页面 +const authPages = [ + Pages.USER_INFO_EDIT, + Pages.VIP_CENTER, + //Pages.PRODUCT_LIST, + //Pages.PRODUCT_DETAILS, + Pages.USER_ACCOUNT_SECURITY, + Pages.USER_EDIT_NICKNAME, + Pages.USER_ORDER_LIST, + Pages.USER_ORDER_DETAILS, + Pages.USER_MOBILE, + Pages.DISTRIBUTION_CENTER, + Pages.DISTRIBUTION_CENTER_DETAILS, + Pages.USER_MOBILE_CHANGE, + Pages.USER_PERSONAL_INFO, + Pages.USER_REMARK, + Pages.PRODUCT_ORDER_CONFIRM, + Pages.PRODUCT_PAY_MODE, + Pages.COUPON_CENTER, + Pages.COUPON_LIST, + Pages.CUSTOMER_SERVICE, + Pages.SHIPPING_ADDRESS_ADDED_OR_EDIT, + Pages.SHIPPING_ADDRESS_LIST, + Pages.USER_PASSWORD_CONFIG, + Pages.WITHDRAWAL, + Pages.WITHDRAWAL_RECORD_LIST, +] + +/** 判断是否需要登录 */ +function getBasePath(url: string): string { + const index = url.indexOf('?') + return index !== -1 ? url.substring(0, index) : url +} + +function isAuthRequired(url: string): boolean { + const cleanUrl = getBasePath(url) + console.log(`URL数据源:${authPages}`) + console.log(`URL原始值: ${url}`) + console.log(`URL过滤值: ${cleanUrl}`) + return authPages.some((item) => item === cleanUrl) +} + +/** 缓存跳转路径 */ +function cacheRedirect(url: string) { + uni.setStorageSync('pending_redirect', url) +} + +/** 读取并清除缓存跳转路径 */ +function consumeRedirect(): string | null { + const url = uni.getStorageSync('pending_redirect') + uni.removeStorageSync('pending_redirect') + return url || null +} + +/** 路由核心跳转方法 */ +async function internalNavigate( + type: 'navigateTo' | 'redirectTo' | 'switchTab' | 'reLaunch', + url: string, + options: Record = {}, +) { + const originUrl: string = url.startsWith('/') ? url : `/${url}` + const isAuthPage = isAuthRequired(originUrl) + console.log(`[Router][${type}] 跳转到:`, originUrl, '需要登录:', isAuthPage) + console.log(`[Router][${type}] 是否登录:`, isUserLoggedIn) + + // 如果需要登录但未登录,则弹出登录框 + if (isAuthPage && !isUserLoggedIn()) { + cacheRedirect(originUrl) + const loginResult = await LoginPopupViewer.open() + console.log(`[Router][${type}] 登录弹窗结果:`, loginResult) + + // 如果登录失败(或用户取消),中断跳转 + if (!loginResult) { + console.log(`[Router][${type}] 已终止跳转,原因:用户未登录或取消登录`) + Loading.showError({ msg: '已取消登录' }) + return + } + } + + // 登录状态已满足,可以安全跳转 + try { + switch (type) { + case 'navigateTo': + return await uniNavigateTo(originUrl, options) + case 'redirectTo': + return await uniRedirectTo(originUrl, options) + case 'switchTab': + return await uniSwitchTab(originUrl) + case 'reLaunch': + return await uniReLaunch(originUrl) + } + } catch (error) { + console.error(`[Router][${type}] 跳转失败:`, error) + } +} + +/** ✅ Promise 封装 uni API **/ +function uniNavigateTo(url: string, options: any) { + return new Promise((resolve, reject) => { + uni.navigateTo({ + url, + ...options, + success: resolve, + fail: reject, + }) + }) +} +function uniRedirectTo(url: string, options: any) { + return new Promise((resolve, reject) => { + uni.redirectTo({ + url, + ...options, + success: resolve, + fail: reject, + }) + }) +} +function uniSwitchTab(url: string) { + return new Promise((resolve, reject) => { + uni.switchTab({ + url, + success: resolve, + fail: reject, + }) + }) +} +function uniReLaunch(url: string) { + return new Promise((resolve, reject) => { + uni.reLaunch({ + url, + success: resolve, + fail: reject, + }) + }) +} + +// ✅ Router API 对象 +// ✅ Router API 对象 +export const Router = { + // 页面跳转,支持登录鉴权 + async navigateTo(opt: { url: string; requiresAuth?: boolean } & Record) { + return await internalNavigate('navigateTo', opt.url, opt) + }, + + // 页面重定向,支持登录鉴权 + async redirectTo(opt: { url: string; requiresAuth?: boolean } & Record) { + return await internalNavigate('redirectTo', opt.url, opt) + }, + + // tab 页面切换 + async switchTab(opt: { url: string }) { + return await internalNavigate('switchTab', opt.url, opt) + }, + + // 重新启动应用跳转 + async reLaunch(opt: { url: string }) { + return await internalNavigate('reLaunch', opt.url, opt) + }, + + // 重定向别名 + async replace(opt: { url: string; requiresAuth?: boolean } & Record) { + return await internalNavigate('redirectTo', opt.url, opt) + }, + + // 返回上一级 + async back(delta = 1) { + return await new Promise((resolve, reject) => { + uni.navigateBack({ + delta, + success: resolve, + fail: reject, + }) + }) + }, + + consumeRedirect, +} + +let cachedRouter: typeof Router | null = null + +/** + * ✅ 全局安全获取 $Router 实例(推荐使用) + */ +export function useRouter(): typeof Router { + if (cachedRouter) return cachedRouter + + const instance = getCurrentInstance() + if (!instance) { + throw new Error('useRouter() 必须在 setup() 或生命周期中调用') + } + + const router = instance.appContext.config.globalProperties.$Router + if (!router) { + throw new Error('$Router 尚未注入,请在 main.ts 中使用 app.use(RouterPlugin)') + } + + cachedRouter = router + return router +} + +/** ✅ 注册为全局插件 */ +export default { + install(app: App) { + app.config.globalProperties.$Router = Router + }, +}