diff --git a/cool/ctx/index.ts b/cool/ctx/index.ts index d5b57c9..07dd61e 100644 --- a/cool/ctx/index.ts +++ b/cool/ctx/index.ts @@ -64,7 +64,7 @@ if (isArray(ctx.subPackages)) { PAGES.push({ path: a.root + "/" + b.path, // 拼接子包根路径和页面路径 style: b.style, - meta: b.meta ?? {}, + meta: b.meta }); }); }); diff --git a/cool/router/index.ts b/cool/router/index.ts index b398e17..5105c82 100644 --- a/cool/router/index.ts +++ b/cool/router/index.ts @@ -1,11 +1,24 @@ import { PAGES, TABS } from "../ctx"; import type { BackOptions, PageInstance, PushOptions } from "../types"; -import { storage, last, isNull, isEmpty, get, isFunction, toArray, map, debounce } from "../utils"; +import { + storage, + last, + isNull, + isEmpty, + get, + isFunction, + toArray, + map, + debounce, + nth +} from "../utils"; // 路由信息类型 type RouteInfo = { path: string; - meta?: UTSJSONObject; + query: UTSJSONObject; + meta: UTSJSONObject; + isAuth?: boolean; }; // 跳转前钩子类型 @@ -21,15 +34,11 @@ type Events = { // 路由核心类 export class Router { - private _events = {} as Events; // 事件存储 + private eventsMap = {} as Events; // 事件存储 // 获取缓存的路由参数 params() { - const data = storage.get("router-params") as UTSJSONObject; - if (isNull(data)) { - return {} as UTSJSONObject; - } - return data; + return (storage.get("router-params") ?? {}) as UTSJSONObject; } // 获取默认路径,支持 home 和 login @@ -38,6 +47,7 @@ export class Router { home: PAGES[0].path, // 首页为第一个页面 login: "/pages/user/login" }; + return get(paths, name) as string; } @@ -45,31 +55,38 @@ export class Router { getPages(): PageInstance[] { return map(getCurrentPages(), (e) => { let path = e.route!; + // 根路径自动转为首页 if (path == "/") { path = this.defaultPath("home"); } + // 补全路径前缀 if (!path.startsWith("/")) { path = "/" + path; } + // 获取页面样式 const page = PAGES.find((e) => e.path == path); const style = page?.style; const meta = page?.meta; + // 获取页面暴露的方法 // @ts-ignore - let exposed = e.vm as any; + const vm = e.vm as any; + + let exposed = vm; + // #ifdef H5 exposed = get(e, "vm.$.exposed"); // #endif + // 获取页面 query 参数 const query = (get(e, "options") ?? {}) as UTSJSONObject; + return { path, - // @ts-ignore - vm: e.vm!, - // @ts-ignore + vm, exposed, style, meta, @@ -113,7 +130,8 @@ export class Router { complete, animationType, animationDuration, - events + events, + isAuth } = options; // 拼接 query 参数到 url @@ -176,15 +194,15 @@ export class Router { }; // 跳转前钩子处理 - if (isFunction(this._events["beforeEach"])) { - const meta = PAGES.find((e) => e.path == path)?.meta; - const from = this.getPages().slice(-1)[0]; - const to: RouteInfo = { path, meta: meta ?? {} }; - (this._events["beforeEach"] as BeforeEach)( - to, - from, - next - ); + if (this.eventsMap.beforeEach != null) { + // 当前页 + const from = last(this.getPages()); + + // 跳转页 + const to = { path, meta: this.getMeta(path), query, isAuth } as RouteInfo; + + // 调用跳转前钩子 + this.eventsMap.beforeEach(to, from!, next); } else { next(); } @@ -197,31 +215,49 @@ export class Router { }); } - // 返回上一页,若为首页则回首页 + // 返回上一页 back(options: BackOptions | null = null) { - let path = '' - const next = ()=>{ - if (this.isFirstPage()) { - this.home(); - path = this.defaultPath("home") - } else { - path = this.getPages().slice(-2)[0].path; + if (this.isFirstPage()) { + this.home(); + } else { + const delta = options?.delta ?? 1; + + // 执行跳转函数 + const next = () => { uni.navigateBack({ ...(options ?? {}) }); + }; + + // 跳转前钩子处理 + if (this.eventsMap.beforeEach != null) { + // 当前页 + const from = last(this.getPages()); + + // 上一页 + const to = nth(this.getPages(), -delta - 1); + + if (to != null) { + // 调用跳转前钩子 + this.eventsMap.beforeEach( + { + path: to.path, + query: to.query, + meta: to.meta ?? ({} as UTSJSONObject) + }, + from!, + next + ); + } else { + console.error("[router] found to page is null"); + } + } else { + next(); } } - // 跳转前钩子处理 - if (isFunction(this._events["beforeEach"])) { - const meta = PAGES.find((e) => e.path == path)?.meta; - const from = this.getPages().slice(-1)[0]; - const to: RouteInfo = { path, meta: meta ?? {} }; - (this._events["beforeEach"] as BeforeEach)( - to, - from, - next - ); - } else { - next(); - } + } + + // 获取页面元数据 + getMeta(path: string) { + return PAGES.find((e) => e.path.includes(path))?.meta ?? ({} as UTSJSONObject); } // 执行当前页面暴露的方法 @@ -296,21 +332,21 @@ export class Router { }); } // 登录后回调 - if (isFunction(this._events["afterLogin"])) { - (this._events["afterLogin"] as AfterLogin)(); + if (this.eventsMap.afterLogin != null) { + this.eventsMap.afterLogin!(); } // 触发全局 afterLogin 事件 uni.$emit("afterLogin"); } // 注册跳转前钩子 - beforeEach(callback: BeforeEach) { - this._events["beforeEach"] = callback; + beforeEach(cb: BeforeEach) { + this.eventsMap.beforeEach = cb; } // 注册登录后回调 - afterLogin(callback: AfterLogin) { - this._events["afterLogin"] = callback; + afterLogin(cb: AfterLogin) { + this.eventsMap.afterLogin = cb; } } diff --git a/cool/types/index.ts b/cool/types/index.ts index 99ee80d..1146799 100644 --- a/cool/types/index.ts +++ b/cool/types/index.ts @@ -37,8 +37,9 @@ export type PushOptions = { path: string; mode?: PushMode; events?: any; - query?: any; - params?: any; + query?: UTSJSONObject; + isAuth?: boolean; + params?: UTSJSONObject; animationType?: PushAnimationType; animationDuration?: number; success?: (result: any) => void; diff --git a/manifest.json b/manifest.json index beaa1aa..6a19bed 100644 --- a/manifest.json +++ b/manifest.json @@ -1,13 +1,11 @@ { "name": "cool-unix", - "appid": "__UNI__EC807C1", + "appid": "__UNI__651711F", "description": "完全开源、永久免费、上手容易、效率极高的开发脚手架", "versionName": "1.0.0", "versionCode": "100", "uni-app-x": {}, - /* 快应用特有相关 */ "quickapp": {}, - /* 小程序特有相关 */ "mp-weixin": { "darkmode": true, "appid": "wxdebc4de0b5584ca4", @@ -93,4 +91,4 @@ "splashScreens": {} } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index f880e09..bc17082 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cool-unix", - "version": "8.0.25", + "version": "8.0.26", "license": "MIT", "scripts": { "build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js", diff --git a/pages.json b/pages.json index 294c696..966d3c3 100644 --- a/pages.json +++ b/pages.json @@ -28,7 +28,7 @@ "style": { "navigationBarTitleText": "设置" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -37,7 +37,7 @@ "style": { "navigationBarTitleText": "通用设置" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -46,7 +46,7 @@ "style": { "navigationBarTitleText": "通知设置" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -55,7 +55,7 @@ "style": { "navigationBarTitleText": "" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -64,7 +64,7 @@ "style": { "navigationBarTitleText": "联系客服" }, - "meta":{ + "meta": { "isAuth": true } } @@ -78,7 +78,7 @@ "style": { "navigationBarTitleText": "编辑资料" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -87,7 +87,7 @@ "style": { "navigationStyle": "custom" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -96,7 +96,7 @@ "style": { "navigationStyle": "custom" }, - "meta":{ + "meta": { "isAuth": true } }, @@ -489,6 +489,15 @@ "style": { "navigationBarTitleText": "Animation 动画" } + }, + { + "path": "other/router/index", + "style": { + "navigationBarTitleText": "Router 路由" + } + }, + { + "path": "other/router/query" } ] }, @@ -512,6 +521,9 @@ "style": { "navigationBarTitleText": "收货地址", "enablePullDownRefresh": true + }, + "meta": { + "isAuth": true } }, { diff --git a/pages/demo/other/router/index.uvue b/pages/demo/other/router/index.uvue new file mode 100644 index 0000000..296823e --- /dev/null +++ b/pages/demo/other/router/index.uvue @@ -0,0 +1,41 @@ + + + + + diff --git a/pages/demo/other/router/query.uvue b/pages/demo/other/router/query.uvue new file mode 100644 index 0000000..de14587 --- /dev/null +++ b/pages/demo/other/router/query.uvue @@ -0,0 +1,29 @@ + + + + + diff --git a/pages/index/home.uvue b/pages/index/home.uvue index b55c4b0..7d49472 100644 --- a/pages/index/home.uvue +++ b/pages/index/home.uvue @@ -46,9 +46,9 @@ - {{ - item.label - }}({{ item.children?.length ?? 0 }}) + {{ item.label }}({{ item.children?.length ?? 0 }}) @@ -461,6 +461,11 @@ const data = computed(() => { label: "Animation", icon: "instance-line", path: "/pages/demo/other/animation" + }, + { + label: "Router", + icon: "compass-discover-line", + path: "/pages/demo/other/router/index" } ] } diff --git a/router/index.ts b/router/index.ts index c5a4624..9fca840 100644 --- a/router/index.ts +++ b/router/index.ts @@ -1,8 +1,17 @@ import { router, useStore } from "@/cool"; -router.beforeEach((to, _, next) => { +/** + * 路由跳转前的全局钩子(如修改 pages.json 后需重新编译项目以确保路由信息生效) + * @param to 跳转页 + * @param from 当前页 + * @param next 跳转函数 + */ +router.beforeEach((to, from, next) => { const { user } = useStore(); - if (to.meta?.isAuth == true) { + + // 判断是否需要登录 + if (to.isAuth == true || to.meta?.isAuth == true) { + // 如果用户信息为空,则跳转到登录页 if (!user.isNull()) { next(); } else { @@ -11,4 +20,4 @@ router.beforeEach((to, _, next) => { } else { next(); } -}); \ No newline at end of file +});