Commit 0a2b74f9 authored by 李维's avatar 李维

feat: 移除路由配置

parent 00f41aa5
{ {"ver":"1.1.2","uuid":"c35bb2f6-f24a-4850-ae44-643f2fdc7541","isBundle":false,"bundleName":"","priority":1,"compressionType":{},"optimizeHotUpdate":{},"inlineSpriteFrames":{},"isRemoteBundle":{"ios":false,"android":false},"subMetas":{}}
"ver": "1.1.2", \ No newline at end of file
"uuid": "c35bb2f6-f24a-4850-ae44-643f2fdc7541",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {
"ios": false,
"android": false
},
"subMetas": {}
}
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html // - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
const {ccclass, property} = cc._decorator; const {ccclass, property} = cc._decorator;
import Router from '../../script/router';
@ccclass @ccclass
export default class NewClass extends cc.Component { export default class NewClass extends cc.Component {
...@@ -21,12 +21,7 @@ export default class NewClass extends cc.Component { ...@@ -21,12 +21,7 @@ export default class NewClass extends cc.Component {
} }
onRunGameCenter() { onRunGameCenter() {
// 使用路由管理器运行主场景 cc.director.loadScene('middleLayer_for_jxw_demo');
const router = Router.getInstance();
router.navigateTo('/index', {
action: 'start',
timestamp: Date.now()
});
} }
// update (dt) {} // update (dt) {}
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html // - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
const {ccclass, property} = cc._decorator; const {ccclass, property} = cc._decorator;
import Router from '../../script/router';
@ccclass @ccclass
export default class NewClass extends cc.Component { export default class NewClass extends cc.Component {
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
"_groupIndex": 0, "_groupIndex": 0,
"groupIndex": 0, "groupIndex": 0,
"autoReleaseAssets": true, "autoReleaseAssets": true,
"_id": "0737ce42-24f0-45c6-8e1a-8bdab4f74ba3" "_id": "f0dfe8f4-e6c5-43c7-a94e-70cbf68bf300"
}, },
{ {
"__type__": "cc.Node", "__type__": "cc.Node",
......
{ {
"ver": "1.2.9", "ver": "1.2.9",
"uuid": "0737ce42-24f0-45c6-8e1a-8bdab4f74ba3", "uuid": "f0dfe8f4-e6c5-43c7-a94e-70cbf68bf300",
"asyncLoadAssets": false, "asyncLoadAssets": false,
"autoReleaseAssets": true, "autoReleaseAssets": true,
"subMetas": {} "subMetas": {}
......
const { ccclass, property } = cc._decorator; const { ccclass, property } = cc._decorator;
import { initAir } from './air'; import { initAir } from './air';
import Router from './router';
import { initializeDefaultRoutes } from './router/config/defaultRoutes';
@ccclass @ccclass
export default class middleLayer extends cc.Component { export default class middleLayer extends cc.Component {
...@@ -161,8 +160,7 @@ export default class middleLayer extends cc.Component { ...@@ -161,8 +160,7 @@ export default class middleLayer extends cc.Component {
// 生命当前节点为常驻节点 // 生命当前节点为常驻节点
cc.game.addPersistRootNode(this.node); cc.game.addPersistRootNode(this.node);
// 初始化路由系统
this.initRouterSystem();
// 添加事件监听 // 添加事件监听
// this.initListener(); // this.initListener();
...@@ -232,132 +230,26 @@ export default class middleLayer extends cc.Component { ...@@ -232,132 +230,26 @@ export default class middleLayer extends cc.Component {
// token.string = this.token; // token.string = this.token;
} }
/**
* 初始化路由系统
*/
initRouterSystem() {
console.log('开始初始化路由系统...');
try {
let routerNode = cc.find('RouterNode');
if (!routerNode) {
console.log('创建路由节点...');
routerNode = new cc.Node('RouterNode');
const routerComponent = routerNode.addComponent(Router);
console.log('路由组件添加成功:', routerComponent);
cc.game.addPersistRootNode(routerNode);
console.log('路由节点设置为常驻节点');
// 手动加载默认路由
this.scheduleOnce(() => {
console.log('手动加载默认路由...');
initializeDefaultRoutes(routerComponent);
}, 0.1);
} else {
console.log('路由节点已存在:', routerNode);
if (routerNode.isValid) {
console.log('现有路由节点有效,跳过创建');
// 检查是否需要加载默认路由
const routerComponent = routerNode.getComponent(Router);
if (routerComponent && routerComponent['routes'].size === 0) {
console.log('路由表为空,加载默认路由...');
initializeDefaultRoutes(routerComponent);
}
} else {
console.log('现有路由节点无效,重新创建...');
if (routerNode.parent) {
routerNode.removeFromParent();
}
cc.game.removePersistRootNode(routerNode);
routerNode = new cc.Node('RouterNode');
const routerComponent = routerNode.addComponent(Router);
cc.game.addPersistRootNode(routerNode);
console.log('路由节点重新创建完成');
// 立即加载默认路由
console.log('立即加载默认路由...');
initializeDefaultRoutes(routerComponent);
}
}
this.scheduleOnce(() => {
console.log('路由系统初始化完成');
}, 0.1);
} catch (error) {
console.error('初始化路由系统失败:', error);
}
}
/** /**
* 运行子场景 * 运行子场景
*/ */
runMainScene() { runMainScene() {
console.log('延迟执行路由导航...'); console.log('加载游戏中心场景...');
cc.director.loadScene('gamecenter');
// 确保路由系统已经初始化并加载了默认路由
this.scheduleOnce(() => {
const router = Router.getInstance();
// 检查路由是否存在
if (!router.hasRoute('/gamecenter')) {
console.log('游戏中心路由不存在,正在初始化默认路由...');
initializeDefaultRoutes(router);
// 再次延迟执行导航
this.scheduleOnce(() => {
this.performGameCenterNavigation(router);
}, 0.1);
} else {
this.performGameCenterNavigation(router);
}
}, 0.2);
} }
/**
* 执行游戏中心导航
*/
private performGameCenterNavigation(router: any) {
router.debugRoutes(); // 显示当前路由状态
router.navigateTo('/gamecenter', {
params: {
source: 'middleLayer',
timestamp: Date.now()
}
}).then(success => {
if (success) {
console.log('成功导航到游戏中心');
} else {
console.error('导航到游戏中心失败');
}
});
}
/** /**
* 关闭游戏中心 * 关闭游戏中心
*/ */
closeGameCenter() { closeGameCenter() {
const router = Router.getInstance(); console.log('关闭游戏中心,加载空页面...');
cc.director.loadScene("empty", () => {
// 确保空页面路由存在
if (!router.hasRoute('/empty')) {
console.log('空页面路由不存在,正在初始化默认路由...');
initializeDefaultRoutes(router);
}
router.navigateTo('/empty', {
params: {
source: 'gamecenter',
timestamp: Date.now()
}
}).then(success => {
cc.game.removePersistRootNode(this.node); cc.game.removePersistRootNode(this.node);
this.callNativeFunction({ name: 'exit', value: '' }); this.callNativeFunction({ name: 'exit', value: '' });
if (success) {
console.log('成功导航到空页面');
} else {
console.error('导航到空页面失败');
}
}); });
} }
......
{
"ver": "1.1.2",
"uuid": "2bf53579-cc34-4abe-b8fb-32b7ed0aa07e",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
# 🛣️ 路由系统
一个为 Cocos Creator 设计的前端风格路由管理系统,支持路径导航、场景切换和路由守卫。
## ✨ 特性
- 🚀 **前端风格路由** - 使用 `/index`, `/gamecenter` 等路径
- 🎯 **场景分离** - 路径与场景名分离,支持灵活配置
- 🛡️ **简化守卫** - 轻量级的认证和权限检查
- 🔄 **冲突处理** - 智能的路由冲突解决策略
- 📱 **Cocos Creator 集成** - 完全兼容 Cocos Creator 场景系统
- 🧹 **无冗余** - 精简的代码结构,易于维护
## 🏗️ 架构
```
router/
├── index.ts # 🚪 统一入口
├── core/ # ⚙️ 核心功能
│ ├── router.ts # 🎮 路由管理器
│ └── types.ts # 📝 类型定义
├── guards/ # 🛡️ 路由守卫
│ ├── index.ts # 🚪 守卫入口
│ ├── factory.ts # 🏭 守卫工厂
│ └── gameCenterGuard.ts # 🎮 游戏中心守卫
├── config/ # ⚙️ 配置相关
│ └── defaultRoutes.ts # 🎯 默认路由配置
└── testNoBuiltin.ts # 🧪 测试文件
```
## 🚀 快速开始
### 1. 初始化路由系统
```typescript
import Router from './router/core/router';
// 获取路由实例
const router = Router.getInstance();
// 添加路由
router.addRoute({
path: '/index',
name: 'index',
sceneName: 'middleLayer_for_jxw_demo',
title: '主场景',
meta: {
requiresAuth: false,
requiresPermission: false
}
});
```
### 2. 导航到路由
```typescript
// 使用路径导航
await router.navigateTo('/index');
// 使用名称导航
await router.navigateTo('index');
// 使用场景名导航(向后兼容)
await router.navigateTo('middleLayer_for_jxw_demo');
```
### 3. 添加路由守卫
```typescript
import { SimpleGuard } from './router/guards/factory';
const guard = new SimpleGuard();
guard.setAuthStatus(true, ['admin_access']);
router.addGlobalGuard(guard);
```
## 🛡️ 路由守卫
### 简化守卫系统
系统使用简化的守卫,只保留必要的功能:
-**认证检查** - 检查用户是否已登录
-**权限检查** - 检查用户是否有访问权限
-**复杂日志** - 移除了复杂的日志记录
-**加载状态** - 移除了复杂的加载状态管理
### 守卫配置
```typescript
{
path: '/gamecenter',
name: 'gamecenter',
sceneName: 'gamecenter',
title: '游戏中心',
meta: {
requiresAuth: true, // 需要认证
permissions: ['game_access'] // 需要特定权限
}
}
```
## ⚙️ 配置选项
### 路由冲突处理
```typescript
router.addRoute(route, {
source: 'custom_config', // 来源标识
conflictStrategy: 'merge', // 冲突策略
allowOverride: true // 允许覆盖
});
```
**冲突策略选项:**
- `skip` - 跳过冲突的路由
- `override` - 覆盖现有路由
- `merge` - 合并路由配置
- `error` - 抛出错误(默认)
## 🧪 测试
### 运行测试
```typescript
// 在浏览器控制台中运行
window.testNoBuiltin.runAllTests();
// 或者运行单个测试
window.testNoBuiltin.testRouterStatus();
window.testNoBuiltin.testSimpleGuardSystem();
```
### 可用测试函数
- `testRouterStatus()` - 测试路由系统状态
- `testManualRouteAddition()` - 测试手动添加路由
- `testBatchRouteAddition()` - 测试批量添加路由
- `testSimpleGuardSystem()` - 测试简化守卫系统
## 🔧 高级功能
### 批量操作
```typescript
// 批量添加路由
const routes = [route1, route2, route3];
const result = router.addRoutes(routes, {
source: 'batch_import',
conflictStrategy: 'merge'
});
console.log(`成功: ${result.added}, 跳过: ${result.skipped}, 失败: ${result.failed}`);
```
### 路由管理
```typescript
// 检查路由是否存在
if (router.hasRoute('/gamecenter')) {
console.log('游戏中心路由已存在');
}
// 获取路由来源
const source = router.getRouteSource('/gamecenter');
console.log('路由来源:', source);
// 移除路由
router.removeRoute('/test');
```
## 📝 类型定义
### RouteConfig
```typescript
interface RouteConfig {
path: string; // 前端路径(如 /index)
name: string; // 路由名称
sceneName: string; // Cocos Creator 场景名
title: string; // 路由标题
meta?: RouteMeta; // 元数据
beforeEnter?: RouteGuardFunction; // 进入前守卫
afterEnter?: RouteGuardFunction; // 进入后守卫
beforeLeave?: RouteGuardFunction; // 离开前守卫
afterLeave?: RouteGuardFunction; // 离开后守卫
}
```
### RouteMeta
```typescript
interface RouteMeta {
requiresAuth?: boolean; // 是否需要认证
requiresPermission?: boolean; // 是否需要权限
permissions?: string[]; // 所需权限列表
keepAlive?: boolean; // 是否保持活跃
source?: string; // 路由来源
}
```
## 🚫 限制说明
- **内置路由已禁用** - 系统不会自动加载任何内置路由
- **需要手动配置** - 所有路由必须手动添加
- **简化守卫** - 移除了复杂的日志和加载状态管理
- **无自动导入** - 不支持从外部文件自动导入路由配置
## 🐛 故障排除
### 常见问题
#### 1. "路由不存在" 错误
```
router.ts:355 路由不存在: /gamecenter
```
**解决方案:**
```typescript
// 检查路由是否存在
const router = Router.getInstance();
if (!router.hasRoute('/gamecenter')) {
// 初始化默认路由
import { initializeDefaultRoutes } from './router/config/defaultRoutes';
initializeDefaultRoutes(router);
}
```
#### 2. "Cannot find module" 错误
```
load script [./authGuard] failed : Error: Cannot find module './authGuard'
```
**解决方案:**
这通常是因为旧的导入路径。确保使用正确的导入:
```typescript
// ❌ 错误的导入
import { AuthGuard } from './guards/authGuard';
// ✅ 正确的导入
import { SimpleGuard } from './guards/factory';
```
#### 3. 路由系统初始化时序问题
**解决方案:**
确保在导航之前路由系统已完全初始化:
```typescript
// 在 middleLayer.ts 中
runSubScene() {
this.scheduleOnce(() => {
const router = Router.getInstance();
// 检查路由是否存在
if (!router.hasRoute('/gamecenter')) {
initializeDefaultRoutes(router);
}
router.navigateTo('/gamecenter');
}, 0.2); // 适当的延迟
}
```
### 调试技巧
#### 1. 检查路由状态
```typescript
const router = Router.getInstance();
router.debugRoutes(); // 显示所有路由信息
```
#### 2. 运行修复测试
```typescript
// 在浏览器控制台中
window.testRouterFix.runAllFixTests();
```
#### 3. 手动初始化路由
```typescript
import { initializeDefaultRoutes } from './router/config/defaultRoutes';
const router = Router.getInstance();
initializeDefaultRoutes(router);
router.debugRoutes();
```
## 🔄 迁移指南
### 从旧版本迁移
1. **更新导入路径**
```typescript
// 旧版本
import Router from './router';
// 新版本
import Router from './router/core/router';
```
2. **简化守卫使用**
```typescript
// 旧版本
import { AuthGuard, PermissionGuard } from './router/guards';
// 新版本
import { SimpleGuard } from './router/guards/factory';
```
3. **手动添加路由**
```typescript
// 旧版本:自动加载内置路由
// 新版本:手动添加所需路由
router.addRoute({
path: '/index',
name: 'index',
sceneName: 'middleLayer_for_jxw_demo',
title: '主场景'
});
```
## 📚 示例
### 完整示例
```typescript
import Router from './router/core/router';
class GameManager {
private router: Router;
constructor() {
this.router = Router.getInstance();
this.initRoutes();
}
private initRoutes() {
// 添加主场景路由
this.router.addRoute({
path: '/index',
name: 'index',
sceneName: 'middleLayer_for_jxw_demo',
title: '主场景',
meta: { requiresAuth: false }
});
// 添加游戏中心路由
this.router.addRoute({
path: '/gamecenter',
name: 'gamecenter',
sceneName: 'gamecenter',
title: '游戏中心',
meta: {
requiresAuth: true,
permissions: ['game_access']
}
});
}
public async goToGameCenter() {
return await this.router.navigateTo('/gamecenter');
}
public async goToMain() {
return await this.router.navigateTo('/index');
}
}
```
## 🤝 贡献
欢迎提交 Issue 和 Pull Request!
## �� 许可证
MIT License
\ No newline at end of file
{
"ver": "2.0.0",
"uuid": "07ba58a3-8d89-461b-902e-b47d97277b6b",
"subMetas": {}
}
\ No newline at end of file
{
"ver": "1.1.2",
"uuid": "ea3819fe-453f-43a6-ace2-73c12855187c",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
import { RouteConfig } from '../core/types';
/**
* 默认路由配置
* 替代原来的内置路由
*/
export const DEFAULT_ROUTES: RouteConfig[] = [
{
path: '/',
name: 'home',
sceneName: 'middleLayer_for_jxw_demo',
title: '首页',
meta: {
requiresAuth: false,
requiresPermission: false,
keepAlive: true,
source: 'default_config'
}
},
{
path: '/index',
name: 'index',
sceneName: 'middleLayer_for_jxw_demo',
title: '主场景',
meta: {
requiresAuth: false,
requiresPermission: false,
keepAlive: true,
source: 'default_config'
}
},
{
path: '/gamecenter',
name: 'gamecenter',
sceneName: 'gamecenter',
title: '游戏中心',
meta: {
requiresAuth: false,
requiresPermission: false,
keepAlive: false,
source: 'default_config'
}
},
{
path: '/empty',
name: 'empty',
sceneName: 'empty',
title: '空页面',
meta: {
requiresAuth: false,
requiresPermission: false,
keepAlive: false,
source: 'default_config'
}
}
];
/**
* 初始化默认路由
* 在路由系统启动后调用此函数来加载默认路由
*/
export function initializeDefaultRoutes(router: any): void {
console.log('🚀 初始化默认路由...');
const result = router.addRoutes(DEFAULT_ROUTES, {
source: 'default_config',
conflictStrategy: 'error'
});
console.log(`✅ 默认路由初始化完成:`, result);
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "a07d8f55-e252-49fa-a882-422b49ce0576",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "1.1.2",
"uuid": "e4ee8d89-1adb-43a2-a5bf-59d37ef106e1",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
import { RouteConfig, RouteGuard, RouteHistory, NavigateOptions } from './types';
import { createDefaultGuards } from '../guards/factory';
const { ccclass, property } = cc._decorator;
/**
* 路由管理器
* 提供前端风格的路由功能,支持路径导航和场景切换
*/
@ccclass
export default class Router extends cc.Component {
private static instance: Router | null = null;
private routes: Map<string, RouteConfig> = new Map();
private currentRoute: RouteConfig | null = null;
private globalGuards: RouteGuard[] = [];
private routeHistory: RouteHistory[] = [];
/**
* 获取单例实例
*/
public static getInstance(): Router {
if (!Router.instance) {
const node = new cc.Node('RouterNode');
Router.instance = node.addComponent(Router);
cc.game.addPersistRootNode(node);
}
return Router.instance;
}
onLoad() {
console.log('Router 组件加载');
console.log('🚫 内置路由已禁用,需要手动添加路由');
// 初始化简化的全局守卫
this.initSimpleGuards();
console.log('✅ 路由系统初始化完成');
}
/**
* 初始化简化的全局守卫
*/
private initSimpleGuards(): void {
try {
const guards = createDefaultGuards();
guards.forEach(guard => this.addGlobalGuard(guard));
console.log('✅ 简化守卫初始化完成');
} catch (error) {
console.error('❌ 初始化简化守卫失败:', error);
}
}
/**
* 添加路由
* @param route 路由配置
* @param options 添加选项
*/
public addRoute(route: RouteConfig, options: {
allowOverride?: boolean;
conflictStrategy?: 'skip' | 'override' | 'merge' | 'error';
source?: string;
} = {}): boolean {
const {
allowOverride = false,
conflictStrategy = 'error',
source = 'unknown'
} = options;
const existingRoute = this.routes.get(route.path);
if (existingRoute) {
// 检测到冲突
console.warn(`⚠️ 路由冲突检测: ${route.path}`);
console.warn(` 现有路由: ${existingRoute.name} (${existingRoute.sceneName}) - 来源: ${existingRoute.meta?.source || 'unknown'}`);
console.warn(` 新路由: ${route.name} (${route.sceneName}) - 来源: ${source}`);
switch (conflictStrategy) {
case 'skip':
console.log(` 策略: skip - 跳过新路由,保持现有路由`);
return false;
case 'override':
if (!allowOverride) {
console.error(` 策略: override - 但未允许覆盖,拒绝添加`);
return false;
}
console.log(` 策略: override - 覆盖现有路由`);
this.routes.set(route.path, {
...route,
meta: {
...route.meta,
source: source,
overriddenFrom: existingRoute.meta?.source || 'unknown',
overriddenAt: Date.now()
}
});
console.log(`✅ 路由已覆盖: ${route.path} -> ${route.sceneName}`);
return true;
case 'merge':
console.log(` 策略: merge - 合并路由配置`);
const mergedRoute = this.mergeRoutes(existingRoute, route, source);
this.routes.set(route.path, mergedRoute);
console.log(`✅ 路由已合并: ${route.path} -> ${route.sceneName}`);
return true;
case 'error':
default:
console.error(` 策略: error - 路由冲突,拒绝添加`);
console.error(` 请检查路由配置或使用不同的冲突策略`);
return false;
}
} else {
// 没有冲突,正常添加
this.routes.set(route.path, {
...route,
meta: {
...route.meta,
source: source
}
});
console.log(`✅ 路由已添加: ${route.path} -> ${route.sceneName} (来源: ${source})`);
return true;
}
}
/**
* 合并路由配置
*/
private mergeRoutes(existing: RouteConfig, newRoute: RouteConfig, source: string): RouteConfig {
console.log(`🔄 合并路由配置: ${existing.path}`);
return {
...existing, // 保留现有配置
...newRoute, // 应用新配置
meta: {
...existing.meta, // 保留现有元数据
...newRoute.meta, // 应用新元数据
source: source, // 标记来源
mergedFrom: [ // 记录合并来源
existing.meta?.source || 'unknown',
source
],
mergedAt: Date.now() // 记录合并时间
},
// 合并守卫函数(新守卫优先)
beforeEnter: newRoute.beforeEnter || existing.beforeEnter,
afterEnter: newRoute.afterEnter || existing.afterEnter,
beforeLeave: newRoute.beforeLeave || existing.beforeLeave,
afterLeave: newRoute.afterLeave || existing.afterLeave
};
}
/**
* 移除路由
*/
public removeRoute(path: string): boolean {
const existingRoute = this.routes.get(path);
if (existingRoute) {
this.routes.delete(path);
console.log(`🗑️ 路由已移除: ${path} (${existingRoute.name})`);
return true;
}
console.warn(`⚠️ 路由不存在,无法移除: ${path}`);
return false;
}
/**
* 检查路由是否存在
*/
public hasRoute(path: string): boolean {
return this.routes.has(path);
}
/**
* 获取路由来源信息
*/
public getRouteSource(path: string): string | undefined {
const route = this.routes.get(path);
return route?.meta?.source;
}
/**
* 列出所有路由冲突
*/
public listRouteConflicts(): Array<{
path: string;
existing: RouteConfig;
conflicts: RouteConfig[];
}> {
const conflicts: Array<{
path: string;
existing: RouteConfig;
conflicts: RouteConfig[];
}> = [];
// 这里可以添加冲突检测逻辑
// 目前返回空数组,因为冲突在添加时就被处理了
return conflicts;
}
/**
* 批量添加路由
*/
public addRoutes(routes: RouteConfig[], options: {
source?: string;
conflictStrategy?: 'skip' | 'override' | 'merge' | 'error';
allowOverride?: boolean;
} = {}): {
total: number;
added: number;
skipped: number;
failed: number;
} {
const { source = 'batch', conflictStrategy = 'error', allowOverride = false } = options;
console.log(`🚀 开始批量添加路由,共 ${routes.length} 个...`);
let added = 0;
let skipped = 0;
let failed = 0;
routes.forEach((route, index) => {
try {
const success = this.addRoute(route, {
source: source,
conflictStrategy: conflictStrategy,
allowOverride: allowOverride
});
if (success) {
added++;
} else {
skipped++;
}
} catch (error) {
console.error(`❌ 添加路由失败 [${index}]: ${route.path}`, error);
failed++;
}
});
console.log(`✅ 批量添加完成: 成功 ${added} 个,跳过 ${skipped} 个,失败 ${failed} 个`);
return { total: routes.length, added, skipped, failed };
}
/**
* 从配置文件加载路由
*/
public async loadRoutesFromConfig(configPath: string): Promise<boolean> {
try {
console.log(`📁 从配置文件加载路由: ${configPath}`);
// 这里可以实现从外部文件加载路由配置的逻辑
// 例如:从 JSON 文件、远程 API、数据库等
// 示例:模拟加载配置
const mockRoutes: RouteConfig[] = [
{
path: '/custom',
name: 'custom',
sceneName: 'custom',
title: '自定义页面',
meta: {
requiresAuth: false,
requiresPermission: false,
source: 'config_file'
}
}
];
const result = this.addRoutes(mockRoutes, {
source: 'config_file',
conflictStrategy: 'merge'
});
console.log(`✅ 配置文件路由加载完成:`, result);
return result.failed === 0;
} catch (error) {
console.error(`❌ 从配置文件加载路由失败: ${configPath}`, error);
return false;
}
}
/**
* 清空所有路由
*/
public clearAllRoutes(): void {
const count = this.routes.size;
this.routes.clear();
console.log(`🗑️ 已清空所有路由,共 ${count} 个`);
}
/**
* 重置路由系统
*/
public reset(): void {
console.log('🔄 重置路由系统...');
// 清空所有路由
this.clearAllRoutes();
// 清空守卫
this.globalGuards = [];
// 清空历史
this.routeHistory = [];
// 重置当前路由
this.currentRoute = null;
console.log('✅ 路由系统重置完成');
}
/**
* 添加全局守卫
*/
public addGlobalGuard(guard: RouteGuard): void {
this.globalGuards.push(guard);
console.log(`全局守卫已添加: ${guard.constructor.name}`);
}
/**
* 导航到指定路由
*/
public async navigateTo(target: string, options: NavigateOptions = {}): Promise<boolean> {
try {
console.log(`准备导航到: ${target}`);
// 查找目标路由
let targetRoute: RouteConfig | undefined;
// 1. 先尝试按路径查找(支持 /index, /gamecenter 等)
if (target.startsWith('/')) {
targetRoute = this.findRouteByPath(target);
console.log(`按路径查找路由: ${target}`, targetRoute);
}
// 2. 如果没找到,尝试按名称查找
if (!targetRoute) {
targetRoute = this.findRouteByName(target);
console.log(`按名称查找路由: ${target}`, targetRoute);
}
// 3. 如果还没找到,尝试按场景名查找(向后兼容)
if (!targetRoute) {
targetRoute = this.findRouteBySceneName(target);
console.log(`按场景名查找路由: ${target}`, targetRoute);
}
if (!targetRoute) {
console.error(`路由不存在: ${target}`);
return false;
}
// 获取当前路由
const currentRoute = this.currentRoute;
// 执行守卫检查
if (!await this.executeGuards(targetRoute, currentRoute, 'before')) {
return false;
}
// 记录导航历史
if (currentRoute) {
this.addToHistory(currentRoute);
}
// 强制执行垃圾回收
this.forceGarbageCollection();
// 加载场景
const sceneName = targetRoute.sceneName;
console.log(`加载场景: ${sceneName}`);
return new Promise((resolve) => {
cc.director.loadScene(sceneName, (error: any) => {
if (error) {
console.error(`场景加载失败: ${sceneName}`, error);
resolve(false);
return;
}
// 更新当前路由
this.currentRoute = targetRoute;
// 执行进入后守卫
this.executeGuards(targetRoute, currentRoute, 'after');
// 场景加载完成后再次执行垃圾回收
this.scheduleOnce(() => {
this.forceGarbageCollection();
}, 0.1);
console.log(`成功导航到路由: ${targetRoute.path}`);
resolve(true);
});
});
} catch (error) {
console.error('导航失败:', error);
return false;
}
}
/**
* 执行守卫
*/
private async executeGuards(targetRoute: RouteConfig, currentRoute: RouteConfig | null, type: 'before' | 'after'): Promise<boolean> {
if (type === 'before') {
// 执行离开守卫
if (currentRoute && currentRoute.beforeLeave) {
const canLeave = await currentRoute.beforeLeave(currentRoute, targetRoute);
if (canLeave === false) {
console.log('离开守卫阻止导航');
return false;
}
}
// 执行进入守卫
if (targetRoute.beforeEnter) {
const canEnter = await targetRoute.beforeEnter(targetRoute, currentRoute);
if (canEnter === false) {
console.log('进入守卫阻止导航');
return false;
}
}
// 执行全局守卫
for (const guard of this.globalGuards) {
if (guard.beforeEnter) {
const canEnter = await guard.beforeEnter(targetRoute, currentRoute);
if (canEnter === false) {
console.log(`全局守卫 ${guard.constructor.name} 阻止导航`);
return false;
}
}
}
} else {
// 执行进入后守卫
if (targetRoute.afterEnter) {
targetRoute.afterEnter(targetRoute, currentRoute);
}
// 执行全局守卫
this.globalGuards.forEach(guard => {
if (guard.afterEnter) {
guard.afterEnter(targetRoute, currentRoute);
}
});
// 执行离开后守卫
if (currentRoute && currentRoute.afterLeave) {
currentRoute.afterLeave(currentRoute, targetRoute);
}
}
return true;
}
/**
* 根据路径查找路由
*/
public findRouteByPath(path: string): RouteConfig | undefined {
return this.routes.get(path);
}
/**
* 根据名称查找路由
*/
public findRouteByName(name: string): RouteConfig | undefined {
const routesArray = Array.from(this.routes.values());
for (let i = 0; i < routesArray.length; i++) {
const route = routesArray[i];
if (route.name === name) {
return route;
}
}
return undefined;
}
/**
* 根据场景名查找路由
*/
public findRouteBySceneName(sceneName: string): RouteConfig | undefined {
const routesArray = Array.from(this.routes.values());
for (let i = 0; i < routesArray.length; i++) {
const route = routesArray[i];
if (route.sceneName === sceneName) {
return route;
}
}
return undefined;
}
/**
* 强制执行垃圾回收
*/
private forceGarbageCollection(): void {
try {
console.log('🗑️ 强制执行垃圾回收...');
// 方法1: 尝试调用浏览器的垃圾回收(如果支持)
if (typeof window !== 'undefined' && (window as any).gc) {
(window as any).gc();
console.log('✅ 浏览器垃圾回收已执行');
}
// 方法2: 清理 Cocos Creator 的资源缓存
if (cc.assetManager) {
// 清理未使用的资源
try {
// 尝试清理纹理缓存
if ((cc.assetManager as any).releaseUnusedAssets) {
(cc.assetManager as any).releaseUnusedAssets();
console.log('✅ Cocos Creator 资源缓存已清理');
}
} catch (e) {
console.log('ℹ️ 资源缓存清理方法不可用');
}
}
console.log('✅ 垃圾回收完成');
} catch (error) {
console.error('❌ 垃圾回收失败:', error);
}
}
/**
* 添加路由到历史记录
*/
private addToHistory(route: RouteConfig): void {
if (this.routeHistory.length >= 50) {
this.routeHistory.shift();
}
this.routeHistory.push({
path: route.path,
name: route.name,
timestamp: Date.now(),
params: {}
});
}
/**
* 获取当前路由
*/
public getCurrentRoute(): RouteConfig | null {
return this.currentRoute;
}
/**
* 获取路由历史
*/
public getRouteHistory(): RouteHistory[] {
return [...this.routeHistory];
}
/**
* 调试路由信息
*/
public debugRoutes(): void {
console.log('=== 路由调试信息 ===');
console.log(`已注册路由数量: ${this.routes.size}`);
console.log(`当前路由: ${this.currentRoute ? this.currentRoute.path : 'null'}`);
console.log(`路由历史长度: ${this.routeHistory.length}`);
console.log(`全局守卫数量: ${this.globalGuards.length}`);
console.log('所有路由:');
this.routes.forEach((route, path) => {
console.log(` - ${path}: ${route.name} (${route.title}) -> ${route.sceneName}`);
});
console.log('==================');
}
onDestroy() {
console.log('Router 组件销毁');
Router.instance = null;
}
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "36ba85e9-cb5d-4356-b8d6-4666eae046a8",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
/**
* 路由系统类型定义
*/
/**
* 路由元数据
*/
export interface RouteMeta {
title?: string;
requiresAuth?: boolean;
requiresPermission?: boolean;
permissions?: string[];
keepAlive?: boolean;
description?: string;
[key: string]: any;
}
/**
* 路由配置
*/
export interface RouteConfig {
path: string; // 前端风格的路径,如 /index, /gamecenter
name: string; // 路由名称
sceneName: string; // Cocos Creator 场景名
title?: string; // 页面标题
meta?: RouteMeta; // 路由元数据
beforeEnter?: RouteGuardFunction; // 进入前守卫
afterEnter?: RouteGuardFunction; // 进入后守卫
beforeLeave?: RouteGuardFunction; // 离开前守卫
afterLeave?: RouteGuardFunction; // 离开后守卫
}
/**
* 路由守卫函数类型
*/
export type RouteGuardFunction = (to: RouteConfig, from: RouteConfig) => boolean | Promise<boolean> | void;
/**
* 路由守卫接口
*/
export interface RouteGuard {
beforeEnter?: RouteGuardFunction; // 进入前守卫
afterEnter?: RouteGuardFunction; // 进入后守卫
beforeLeave?: RouteGuardFunction; // 离开前守卫
afterLeave?: RouteGuardFunction; // 离开后守卫
}
// 路由历史记录
export interface RouteHistory {
path: string;
name: string;
timestamp: number;
params?: any;
}
// 路由参数
export interface RouteParams {
[key: string]: any;
}
/**
* 导航选项
*/
export interface NavigateOptions {
params?: Record<string, any>;
replace?: boolean;
[key: string]: any;
}
// 路由错误
export interface RouteError {
code: string;
message: string;
details?: any;
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "34293000-086f-4fdf-8555-90d2adadc048",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
{
"ver": "1.1.2",
"uuid": "ff0b0596-4c74-472e-864d-6bb6f94b17ff",
"isBundle": false,
"bundleName": "",
"priority": 1,
"compressionType": {},
"optimizeHotUpdate": {},
"inlineSpriteFrames": {},
"isRemoteBundle": {},
"subMetas": {}
}
\ No newline at end of file
import { RouteGuard, RouteConfig } from '../../core/types';
/**
* 简化的路由守卫
* 只保留必要的认证和权限检查功能
*/
export class SimpleGuard implements RouteGuard {
private isAuthenticated: boolean = false;
private userPermissions: string[] = [];
constructor() {
this.checkAuthStatus();
}
/**
* 检查认证状态
*/
private checkAuthStatus(): void {
try {
const token = cc.sys.localStorage.getItem('userToken');
this.isAuthenticated = !!token;
if (this.isAuthenticated) {
const userInfoStr = cc.sys.localStorage.getItem('userInfo');
if (userInfoStr) {
const userInfo = JSON.parse(userInfoStr);
this.userPermissions = userInfo.permissions || [];
}
}
} catch (error) {
console.error('检查认证状态失败:', error);
}
}
/**
* 设置认证状态
*/
public setAuthStatus(authenticated: boolean, permissions: string[] = []): void {
this.isAuthenticated = authenticated;
this.userPermissions = permissions;
console.log(`认证状态已更新: ${authenticated}, 权限:`, permissions);
}
/**
* 路由进入前检查
*/
public beforeEnter(to: RouteConfig, from: RouteConfig): boolean {
// 检查是否需要认证
if (to.meta?.requiresAuth && !this.isAuthenticated) {
console.log(`路由 ${to.path} 需要认证,但用户未登录`);
this.showLoginPrompt();
return false;
}
// 检查权限
if (to.meta?.permissions && to.meta.permissions.length > 0) {
const hasPermission = to.meta.permissions.some(permission =>
this.userPermissions.includes(permission)
);
if (!hasPermission) {
console.log(`用户没有访问路由 ${to.path} 的权限`);
this.showPermissionDenied();
return false;
}
}
return true;
}
/**
* 显示登录提示
*/
private showLoginPrompt(): void {
console.log('请先登录');
cc.systemEvent.emit('showLoginPrompt');
}
/**
* 显示权限不足提示
*/
private showPermissionDenied(): void {
console.log('权限不足,无法访问该页面');
cc.systemEvent.emit('showPermissionDenied');
}
}
/**
* 创建简化的全局守卫
*/
export function createDefaultGuards(): RouteGuard[] {
return [new SimpleGuard()];
}
/**
* 创建认证守卫
*/
export function createAuthGuard(): SimpleGuard {
return new SimpleGuard();
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "c61b15a5-f8c2-454c-a256-988d24f84554",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
/**
* 游戏中心路由守卫辅助函数
* 简化的版本,只保留必要的检查功能
*/
/**
* 检查用户是否已登录
*/
export function isUserLoggedIn(): boolean {
try {
const token = cc.sys.localStorage.getItem('userToken');
return !!token;
} catch (error) {
console.error('检查登录状态失败:', error);
return false;
}
}
/**
* 检查用户是否有游戏访问权限
*/
export function hasGamePermission(): boolean {
try {
const userInfoStr = cc.sys.localStorage.getItem('userInfo');
if (!userInfoStr) return false;
const userInfo = JSON.parse(userInfoStr);
const permissions = userInfo.permissions || [];
return permissions.includes('game_access') || permissions.includes('admin_access');
} catch (error) {
console.error('检查游戏权限失败:', error);
return false;
}
}
/**
* 检查游戏中心是否可用
*/
export function isGameCenterAvailable(): boolean {
// 简化的检查:总是返回true
// 可以根据实际需求添加网络状态、服务器状态等检查
return true;
}
/**
* 初始化游戏中心
*/
export function initializeGameCenter(): void {
console.log('🎮 游戏中心初始化完成');
}
/**
* 记录游戏中心访问日志
*/
export function logGameCenterAccess(): void {
console.log('📝 记录游戏中心访问日志');
}
/**
* 显示欢迎信息
*/
export function showWelcomeMessage(): void {
console.log('👋 欢迎来到游戏中心!');
}
/**
* 检查是否有未保存的游戏进度
*/
export function hasUnsavedProgress(): boolean {
// 简化的检查:总是返回false
// 可以根据实际需求添加进度检查逻辑
return false;
}
/**
* 检查是否有活跃的游戏
*/
export function hasActiveGame(): boolean {
// 简化的检查:总是返回false
// 可以根据实际需求添加游戏状态检查逻辑
return false;
}
/**
* 确认未保存进度
*/
export function confirmUnsavedProgress(): boolean {
// 简化的确认:总是返回true
// 可以根据实际需求添加用户确认逻辑
return true;
}
/**
* 确认活跃游戏
*/
export function confirmActiveGame(): boolean {
// 简化的确认:总是返回true
// 可以根据实际需求添加用户确认逻辑
return true;
}
/**
* 清理游戏中心
*/
export function cleanupGameCenter(): void {
console.log('🧹 游戏中心清理完成');
}
/**
* 保存用户设置
*/
export function saveUserSettings(): void {
console.log('💾 用户设置已保存');
}
/**
* 记录游戏中心退出日志
*/
export function logGameCenterExit(): void {
console.log('📝 记录游戏中心退出日志');
}
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "75a2db79-206f-4fa3-a469-ddb0677bf369",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
/**
* 路由守卫入口文件
* 导出简化的守卫类型和工厂函数
*/
// 导出守卫接口
export * from '../../core/types';
// 导出守卫工厂函数
export { createDefaultGuards, createAuthGuard } from './factory';
// 导出简化守卫实现
export { SimpleGuard } from './factory';
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "eab4cbb4-241f-41a0-9d77-b4ef4f7a0390",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
/**
* 路由系统入口文件
* 统一导出所有路由相关功能
*/
// 核心路由管理器
export { default as Router } from './core/router';
// 类型定义
export * from './core/types';
// 路由守卫
export * from './guards';
// 路由配置
export { initializeDefaultRoutes } from './config/defaultRoutes';
// 默认导出路由管理器
import Router from './core/router';
export default Router;
\ No newline at end of file
{
"ver": "1.0.8",
"uuid": "4c46bcff-c8b4-47b5-840d-cb8adcb07ccf",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}
\ No newline at end of file
{ {
"title": "play", "title": "play",
"packageName": "org.cocos2d.demo", "packageName": "org.cocos2d.demo",
"startScene": "0737ce42-24f0-45c6-8e1a-8bdab4f74ba3", "startScene": "f0dfe8f4-e6c5-43c7-a94e-70cbf68bf300",
"excludeScenes": [], "excludeScenes": [],
"includeSDKBox": false, "includeSDKBox": false,
"orientation": { "orientation": {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment