📖 前言

在前两篇教程中,我们完成了 HMRouter 的类型封装工具类封装编译插件配置测试页面搭建。本篇我们将深入探讨 HMRouter Interceptor 拦截器的封装和使用。

拦截器是 HMRouter 框架的核心功能之一,它允许你在路由跳转过程中进行拦截、验证、权限检查等操作,实现灵活的路由控制。通过拦截器,我们可以实现:

  • 权限验证:检查用户是否有权限访问目标页面
  • 登录检查:未登录用户自动跳转到登录页
  • 参数验证:验证路由参数的有效性
  • 日志记录:记录路由跳转日志
  • 性能监控:统计路由跳转耗时

🎯 拦截器封装目标

  • 类型统一:封装拦截器相关类型,保持项目代码风格一致
  • 简化使用:提供清晰的拦截器定义和使用示例
  • 功能完整:支持同步和异步两种拦截器实现方式
  • 易于维护:统一管理拦截器,便于后续扩展


📁 拦截器封装结构

entry/src/main/ets/hmRouter/
├── interceptor/                          # 拦截器相关封装目录
│   ├── Index.ets                          # 统一导出入口
│   ├── HMRouterUtilInterceptor.ets      # 拦截器接口类型别名
│   ├── HMRouterUtilInterceptorAction.ets # 拦截器动作枚举
│   ├── HMRouterUtilInterceptorInfo.ets   # 拦截器信息类型别名
│   ├── HMRouterUtilInterceptorChain.ets # 拦截器链类型别名
│   ├── HMRouterUtilInterceptorContext.ets # 拦截器上下文类型别名
│   └── HMRouterUtilInterceptorParam.ets  # 拦截器参数类型别名
└── interceptorInstance/                  # 拦截器实例目录
    ├── Index.ets                          # 统一导出入口
    └── HMRouterUtilTestInterceptor.ets  # 拦截器示例实现

🚀 拦截器封装步骤

步骤 1:封装拦截器类型定义

1.1 封装拦截器接口

文件: interceptor/HMRouterUtilInterceptor.ets

import { IHMInterceptor } from '@hadss/hmrouter';

/**
 * HMRouter 拦截器类型别名
 * 用于项目内部统一使用,定义路由拦截器接口
 *
 * 支持两种实现方式:
 * - 同步拦截器:实现 handle 方法
 * - 异步拦截器:实现 intercept 方法
 *
 * 注意:至少需要实现 handle 或 intercept 方法中的一个
 */
export type HMRouterUtilInterceptor = IHMInterceptor;

说明:

  • 拦截器必须实现 IHMInterceptor 接口
  • 可以只实现 handle 方法(同步拦截器)
  • 可以只实现 intercept 方法(异步拦截器)
  • 也可以同时实现两个方法(异步路由优先调用 intercept
1.2 封装拦截器动作枚举

文件: interceptor/HMRouterUtilInterceptorAction.ets

import { HMInterceptorAction } from '@hadss/hmrouter';

/**
 * HMRouter 拦截器动作枚举
 * 用于同步拦截器控制路由流程
 */
export { HMInterceptorAction as HMRouterUtilInterceptorAction };

拦截器动作说明:

动作

说明

DO_NEXT

继续执行下一个拦截器

DO_REJECT

拦截当前路由操作,不执行后续拦截器和路由操作

DO_INTERCEPT

拦截当前路由操作,但继续执行后续拦截器

1.3 封装拦截器信息类型

文件: interceptor/HMRouterUtilInterceptorInfo.ets

import { HMInterceptorInfo } from '@hadss/hmrouter';

/**
 * HMRouter 拦截器信息类型别名
 * 包含路由跳转的完整信息,用于拦截器判断和处理
 */
export type HMRouterUtilInterceptorInfo = HMInterceptorInfo;

HMInterceptorInfo 包含的信息:

  • sourceName:跳转发起页面名称
  • targetName:目标页面名称
  • param:路由参数
  • navigationId:导航容器ID
1.4 封装拦截器链类型

文件: interceptor/HMRouterUtilInterceptorChain.ets

import { IHMInterceptorChain } from '@hadss/hmrouter';

/**
 * HMRouter 拦截器链类型别名
 * 用于异步拦截器控制路由流程
 */
export type HMRouterUtilInterceptorChain = IHMInterceptorChain;

拦截器链方法:

  • onContinue():继续执行下一个拦截器
  • onReject():拦截当前路由操作
  • getContext():获取拦截器上下文,用于共享数据
1.5 封装拦截器上下文类型

文件: interceptor/HMRouterUtilInterceptorContext.ets

import { InterceptorContext } from '@hadss/hmrouter';

/**
 * HMRouter 拦截器上下文类型别名
 * 用于拦截器之间共享数据
 */
export type HMRouterUtilInterceptorContext = InterceptorContext;
1.6 封装拦截器参数类型

文件: interceptor/HMRouterUtilInterceptorParam.ets

import { HMInterceptorParam } from '@hadss/hmrouter/src/main/ets/annotation/HMInterceptor';

/**
 * HMRouter 拦截器参数类型别名
 * 用于项目内部统一使用,定义拦截器配置参数
 *
 * 属性包括:
 * - interceptorName: 拦截器的唯一名称 (string, 必填)
 * - priority: 拦截器的优先级 (number, 数值越大优先级越高,默认为 9)
 * - global: 是否为全局拦截器 (boolean, 默认为 false)
 */
export type HMRouterUtilInterceptorParam = HMInterceptorParam;
1.7 统一导出

文件: interceptor/Index.ets

/**
 * HMRouter 拦截器相关类型统一导出
 */

export type { HMRouterUtilInterceptor } from './HMRouterUtilInterceptor';

export { HMRouterUtilInterceptorAction } from './HMRouterUtilInterceptorAction';

export type { HMRouterUtilInterceptorInfo } from './HMRouterUtilInterceptorInfo';

export type { HMRouterUtilInterceptorChain } from './HMRouterUtilInterceptorChain';

export type { HMRouterUtilInterceptorContext } from './HMRouterUtilInterceptorContext';

export type { HMRouterUtilInterceptorParam } from './HMRouterUtilInterceptorParam';

步骤 2:实现同步拦截器

同步拦截器通过实现 handle 方法,返回 HMInterceptorAction 枚举值来控制路由流程。

2.1 基本同步拦截器示例

文件: interceptorInstance/HMRouterUtilTestInterceptor.ets

import { HMInterceptor } from '@hadss/hmrouter';
import { HMRouterUtilInterceptor } from '../interceptor/HMRouterUtilInterceptor';
import {
  HMRouterUtilInterceptorAction,
  HMRouterUtilInterceptorInfo
} from '../interceptor/Index';

/**
 * 拦截器名称常量
 */
const HM_ROUTER_UTIL_INTERCEPTOR: string = 'HMRouterUtilTestInterceptor';

/**
 * HMRouter 测试拦截器
 *
 * 用于测试拦截器功能,同时实现了同步和异步两种拦截方式
 * - 同步拦截器:直接放行,不做任何拦截
 * - 异步拦截器:直接放行,不做任何拦截
 *
 * 注意:这是一个全局拦截器,会对所有路由跳转生效
 */
@HMInterceptor({
  interceptorName: HM_ROUTER_UTIL_INTERCEPTOR,
  global: true
})
export class HMRouterUtilTestInterceptor implements HMRouterUtilInterceptor {
  /**
   * 同步拦截器方法
   * @param info 拦截器信息
   * @returns 拦截器动作,返回 DO_NEXT 表示继续执行下一个拦截器
   */
  handle(info: HMRouterUtilInterceptorInfo): HMRouterUtilInterceptorAction {
    console.log('同步拦截器执行:', info.targetName);
    return HMRouterUtilInterceptorAction.DO_NEXT;
  }
}
2.2 登录拦截器示例
import { HMInterceptor } from '@hadss/hmrouter';
import { HMRouterUtil } from '../util/HMRouterUtil';
import {
  HMRouterUtilInterceptor,
  HMRouterUtilInterceptorAction,
  HMRouterUtilInterceptorInfo
} from '../interceptor/Index';

/**
 * 登录拦截器
 * 检查用户是否已登录,未登录则跳转到登录页
 */
@HMInterceptor({
  interceptorName: 'LoginInterceptor',
  priority: 10,
  global: false  // 非全局拦截器,需要在 @HMRouter 中指定
})
export class LoginInterceptor implements HMRouterUtilInterceptor {
  handle(info: HMRouterUtilInterceptorInfo): HMRouterUtilInterceptorAction {
    // 检查用户是否已登录
    const isLoggedIn = this.checkLoginStatus();
    
    if (isLoggedIn) {
      // 已登录,继续下一个拦截器
      return HMRouterUtilInterceptorAction.DO_NEXT;
    } else {
      // 未登录,跳转到登录页面
      HMRouterUtil.push(
        'pages/LoginPage',
        { targetUrl: info.targetName },
        { skipAllInterceptor: true }  // 避免循环拦截
      );
      
      // 拦截当前路由操作
      return HMRouterUtilInterceptorAction.DO_REJECT;
    }
  }

  private checkLoginStatus(): boolean {
    // 实现登录状态检查逻辑
    return false;  // 示例:返回 false 表示未登录
  }
}
2.3 权限拦截器示例
import { HMInterceptor } from '@hadss/hmrouter';
import {
  HMRouterUtilInterceptor,
  HMRouterUtilInterceptorAction,
  HMRouterUtilInterceptorInfo
} from '../interceptor/Index';

/**
 * 权限拦截器
 * 检查用户是否有权限访问目标页面
 */
@HMInterceptor({
  interceptorName: 'PermissionInterceptor',
  priority: 9,
  global: false
})
export class PermissionInterceptor implements HMRouterUtilInterceptor {
  handle(info: HMRouterUtilInterceptorInfo): HMRouterUtilInterceptorAction {
    // 检查用户权限
    const hasPermission = this.checkPermission(info.targetName);
    
    if (hasPermission) {
      return HMRouterUtilInterceptorAction.DO_NEXT;
    } else {
      console.warn('权限不足,无法访问:', info.targetName);
      return HMRouterUtilInterceptorAction.DO_REJECT;
    }
  }

  private checkPermission(pageUrl: string): boolean {
    // 实现权限检查逻辑
    // 例如:检查用户角色、页面访问权限等
    return true;  // 示例:返回 true 表示有权限
  }
}

步骤 3:实现异步拦截器

异步拦截器通过实现 intercept 方法,接收 IHMInterceptorChain 参数,支持异步操作和洋葱模型。

3.1 基本异步拦截器示例
import { HMInterceptor } from '@hadss/hmrouter';
import { HMRouterUtilInterceptor } from '../interceptor/HMRouterUtilInterceptor';
import {
  HMRouterUtilInterceptorChain
} from '../interceptor/Index';

/**
 * 异步拦截器示例
 * 支持异步操作,如网络请求、数据获取等
 */
@HMInterceptor({
  interceptorName: 'AsyncInterceptor',
  priority: 10,
  global: false
})
export class AsyncInterceptor implements HMRouterUtilInterceptor {
  /**
   * 异步拦截器方法
   * @param chain 拦截器链
   */
  async intercept(chain: HMRouterUtilInterceptorChain): Promise<void> {
    const context = chain.getContext();
    
    console.log('异步拦截器开始执行');
    context?.setData('startTime', Date.now());

    // 模拟异步操作,如网络请求
    await new Promise<void>((resolve) => {
      setTimeout(() => {
        console.log('异步操作完成');
        context?.setData('asyncCompleted', true);
        resolve();
      }, 1000);
    });

    // 继续执行下一个拦截器
    await chain.onContinue();

    // 洋葱模型:拦截器链返回后的处理
    console.log('异步拦截器执行完成');
    const endTime = Date.now();
    const startTime = context?.getData<number>('startTime') || 0;
    console.log(`总耗时: ${endTime - startTime}ms`);
  }
}
3.2 异步登录拦截器示例
import { HMInterceptor } from '@hadss/hmrouter';
import { HMRouterUtil } from '../util/HMRouterUtil';
import {
  HMRouterUtilInterceptor,
  HMRouterUtilInterceptorChain
} from '../interceptor/Index';

/**
 * 异步登录拦截器
 * 通过异步方式检查登录状态
 */
@HMInterceptor({
  interceptorName: 'AsyncLoginInterceptor',
  priority: 10,
  global: false
})
export class AsyncLoginInterceptor implements HMRouterUtilInterceptor {
  async intercept(chain: HMRouterUtilInterceptorChain): Promise<void> {
    // 异步检查登录状态
    const isLoggedIn = await this.checkLoginStatusAsync();
    
    if (isLoggedIn) {
      // 已登录,继续下一个拦截器
      await chain.onContinue();
    } else {
      // 未登录,跳转到登录页
      HMRouterUtil.push(
        'pages/LoginPage',
        { targetUrl: chain.getContext()?.getData<string>('targetUrl') },
        { skipAllInterceptor: true }
      );
      
      // 拦截当前路由操作
      await chain.onReject();
    }
  }

  private async checkLoginStatusAsync(): Promise<boolean> {
    // 实现异步登录状态检查
    // 例如:调用网络接口验证 token
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(false);  // 示例:返回 false 表示未登录
      }, 500);
    });
  }
}

步骤 4:注册和使用拦截器

4.1 全局拦截器注册

全局拦截器会对所有路由跳转生效,有两种注册方式:

方式1:使用 global: true 属性

@HMInterceptor({
  interceptorName: 'GlobalInterceptor',
  global: true,  // 全局拦截器
  priority: 10
})
export class GlobalInterceptor implements HMRouterUtilInterceptor {
  handle(info: HMRouterUtilInterceptorInfo): HMRouterUtilInterceptorAction {
    console.log('全局拦截器执行');
    return HMRouterUtilInterceptorAction.DO_NEXT;
  }
}

方式2:通过 API 动态注册

import { HMRouterUtil } from '../hmRouter/util/HMRouterUtil';
import { HMInterceptorInstance } from '@hadss/hmrouter/src/main/ets/store/ComponentInstance';

// 创建拦截器实例
const interceptorInstance: HMInterceptorInstance = {
  interceptorName: 'DynamicInterceptor',
  interceptor: new MyInterceptor(),
  priority: 10
};

// 注册全局拦截器
HMRouterUtil.registerGlobalInterceptor(interceptorInstance);

// 注销全局拦截器
HMRouterUtil.unRegisterGlobalInterceptor('DynamicInterceptor');
4.2 页面级拦截器注册

页面级拦截器只对特定页面的路由跳转生效,需要在 @HMRouter 注解中指定:

import { HMRouter } from '@hadss/hmrouter';

@HMRouter({
  pageUrl: 'pages/DetailPage',
  interceptors: ['LoginInterceptor', 'PermissionInterceptor']  // 指定拦截器
})
@Component
export struct DetailPage {
  // ...
}
4.3 拦截器执行顺序

拦截器的执行顺序遵循以下规则:

  1. 按优先级排序:优先级高的先执行(priority 值越大优先级越高)
  2. 优先级相同时:先执行页面级拦截器,再执行全局拦截器
  3. 同一优先级页面级拦截器:先执行发起页面的拦截器,再执行目标页面的拦截器

执行顺序示例:

优先级 15: 发起页面拦截器A
优先级 15: 目标页面拦截器B
优先级 15: 全局拦截器C
优先级 10: 发起页面拦截器D
优先级 10: 全局拦截器E
优先级 9: 全局拦截器F

步骤 5:拦截器上下文使用

拦截器上下文(InterceptorContext)用于在拦截器之间共享数据,特别适用于异步拦截器。

5.1 设置和获取上下文数据
async intercept(chain: HMRouterUtilInterceptorChain): Promise<void> {
  const context = chain.getContext();
  
  // 设置数据
  context?.setData('userId', '12345');
  context?.setData('startTime', Date.now());
  
  // 继续执行下一个拦截器
  await chain.onContinue();
  
  // 获取数据
  const userId = context?.getData<string>('userId');
  const startTime = context?.getData<number>('startTime');
  
  console.log('用户ID:', userId);
  console.log('开始时间:', startTime);
}
5.2 上下文数据传递示例
// 拦截器1:设置用户信息
async intercept(chain: HMRouterUtilInterceptorChain): Promise<void> {
  const context = chain.getContext();
  context?.setData('user', { id: '123', name: '张三' });
  await chain.onContinue();
}

// 拦截器2:使用用户信息
async intercept(chain: HMRouterUtilInterceptorChain): Promise<void> {
  const context = chain.getContext();
  const user = context?.getData<{ id: string; name: string }>('user');
  
  if (user) {
    console.log('当前用户:', user.name);
  }
  
  await chain.onContinue();
}

💡 实际应用示例

示例 1:完整的登录拦截器

import { HMInterceptor } from '@hadss/hmrouter';
import { HMRouterUtil } from '../util/HMRouterUtil';
import {
  HMRouterUtilInterceptor,
  HMRouterUtilInterceptorAction,
  HMRouterUtilInterceptorInfo
} from '../interceptor/Index';

/**
 * 登录拦截器
 * 检查用户登录状态,未登录则跳转到登录页
 */
@HMInterceptor({
  interceptorName: 'LoginInterceptor',
  priority: 10,
  global: true  // 全局拦截器
})
export class LoginInterceptor implements HMRouterUtilInterceptor {
  // 需要登录的页面列表
  private readonly loginRequiredPages: string[] = [
    'pages/ProfilePage',
    'pages/OrderPage',
    'pages/SettingPage'
  ];

  handle(info: HMRouterUtilInterceptorInfo): HMRouterUtilInterceptorAction {
    // 检查目标页面是否需要登录
    const needLogin = this.loginRequiredPages.includes(info.targetName);
    
    if (!needLogin) {
      // 不需要登录,直接放行
      return HMRouterUtilInterceptorAction.DO_NEXT;
    }

    // 检查登录状态
    const isLoggedIn = this.checkLoginStatus();
    
    if (isLoggedIn) {
      return HMRouterUtilInterceptorAction.DO_NEXT;
    } else {
      // 未登录,跳转到登录页
      HMRouterUtil.push(
        'pages/LoginPage',
        { 
          targetUrl: info.targetName,
          sourceUrl: info.sourceName
        },
        { skipAllInterceptor: true }  // 跳过所有拦截器,避免循环
      );
      
      return HMRouterUtilInterceptorAction.DO_REJECT;
    }
  }

  private checkLoginStatus(): boolean {
    // 实现登录状态检查
    // 例如:从本地存储或状态管理中读取
    return false;
  }
}

示例 2:日志记录拦截器

import { HMInterceptor } from '@hadss/hmrouter';
import {
  HMRouterUtilInterceptor,
  HMRouterUtilInterceptorAction,
  HMRouterUtilInterceptorInfo
} from '../interceptor/Index';

/**
 * 日志记录拦截器
 * 记录所有路由跳转日志
 */
@HMInterceptor({
  interceptorName: 'LogInterceptor',
  priority: 1,  // 低优先级,最后执行
  global: true
})
export class LogInterceptor implements HMRouterUtilInterceptor {
  handle(info: HMRouterUtilInterceptorInfo): HMRouterUtilInterceptorAction {
    // 记录路由跳转日志
    console.log('路由跳转:', {
      from: info.sourceName,
      to: info.targetName,
      param: info.param,
      timestamp: new Date().toISOString()
    });

    // 可以发送到日志服务器
    this.sendLogToServer({
      from: info.sourceName,
      to: info.targetName,
      param: info.param
    });

    return HMRouterUtilInterceptorAction.DO_NEXT;
  }

  private sendLogToServer(log: any): void {
    // 实现日志发送逻辑
  }
}

示例 3:性能监控拦截器

import { HMInterceptor } from '@hadss/hmrouter';
import {
  HMRouterUtilInterceptor,
  HMRouterUtilInterceptorChain
} from '../interceptor/Index';

/**
 * 性能监控拦截器
 * 统计路由跳转耗时
 */
@HMInterceptor({
  interceptorName: 'PerformanceInterceptor',
  priority: 1,
  global: true
})
export class PerformanceInterceptor implements HMRouterUtilInterceptor {
  async intercept(chain: HMRouterUtilInterceptorChain): Promise<void> {
    const context = chain.getContext();
    const startTime = Date.now();
    
    context?.setData('routeStartTime', startTime);

    // 继续执行下一个拦截器
    await chain.onContinue();

    // 计算耗时
    const endTime = Date.now();
    const duration = endTime - startTime;

    console.log(`路由跳转耗时: ${duration}ms`);

    // 如果耗时过长,记录警告
    if (duration > 1000) {
      console.warn('路由跳转耗时过长:', duration, 'ms');
    }
  }
}

⚠️ 注意事项

1. 装饰器必须使用原始名称

HMRouter 编译插件只识别原始的装饰器名称:

// ✅ 正确:使用原始装饰器
@HMInterceptor({ interceptorName: 'MyInterceptor' })
export class MyInterceptor { }

// ❌ 错误:封装后的装饰器不会被识别
@HMRouterInterceptorDecorator({ interceptorName: 'MyInterceptor' })
export class MyInterceptor { }

2. 同步拦截器 vs 异步拦截器

特性

同步拦截器

异步拦截器

实现方法

handle

intercept

返回值

HMInterceptorAction

Promise<void>

支持异步操作

支持洋葱模型

调用方式

同步/异步路由均可

仅异步路由方法

重要提示: 异步拦截器只能通过异步路由方法(如 pushAsyncreplaceAsync)触发。

3. 拦截器执行时机

拦截器在以下时机执行:

  • 路由栈发生变化前
  • 转场动画发生前
  • 页面生命周期回调前

特殊情况:

  • pageUrl 为空时,拦截器不会执行
  • 当目标页面不存在时,执行全局和发起页面拦截器,然后执行 onLost 回调
  • 当目标页面存在时,执行全局、发起页面和目标页面的拦截器

4. 避免循环拦截

在拦截器中跳转到其他页面时,应使用 skipAllInterceptor: true 避免循环拦截:

HMRouterUtil.push(
  'pages/LoginPage',
  { targetUrl: info.targetName },
  { skipAllInterceptor: true }  // 跳过所有拦截器
);

5. 拦截器优先级

  • 优先级数值越大,执行越早
  • 默认优先级为 9
  • 建议将关键拦截器(如登录检查)设置为较高优先级(如 10)
  • 将辅助拦截器(如日志记录)设置为较低优先级(如 1)

📊 拦截器使用场景对比

场景 1:登录检查

直接在每个页面检查:

// ❌ 代码重复,难以维护
aboutToAppear() {
  if (!isLoggedIn()) {
    HMRouterUtil.push('pages/LoginPage');
    return;
  }
  // 页面逻辑
}

使用拦截器:

// ✅ 统一管理,易于维护
@HMInterceptor({ interceptorName: 'LoginInterceptor', global: true })
export class LoginInterceptor {
  handle(info: HMInterceptorInfo): HMInterceptorAction {
    if (!isLoggedIn()) {
      HMRouterUtil.push('pages/LoginPage', { targetUrl: info.targetName });
      return HMInterceptorAction.DO_REJECT;
    }
    return HMInterceptorAction.DO_NEXT;
  }
}

场景 2:参数验证

直接在每个页面验证:

// ❌ 代码分散
aboutToAppear() {
  const param = HMRouterUtil.getCurrentParam();
  if (!param || !param.id) {
    console.error('参数错误');
    HMRouterUtil.pop();
    return;
  }
}

使用拦截器:

// ✅ 统一验证
@HMInterceptor({ interceptorName: 'ParamValidator', global: false })
export class ParamValidator {
  handle(info: HMInterceptorInfo): HMInterceptorAction {
    if (!info.param || !info.param.id) {
      console.error('参数错误');
      return HMInterceptorAction.DO_REJECT;
    }
    return HMInterceptorAction.DO_NEXT;
  }
}

🎯 设计原则

原则

说明

单一职责

每个拦截器专注于特定功能(登录、权限、日志等)

优先级合理

关键拦截器设置高优先级,辅助拦截器设置低优先级

避免循环

在拦截器中跳转时使用 skipAllInterceptor: true

类型安全

使用封装的类型别名,保证类型安全

易于测试

拦截器可以独立测试,不依赖页面


📝 总结

本文介绍了 HMRouter Interceptor 拦截器的封装和使用,包括:

  1. 类型封装:封装了 6 个拦截器相关类型
  2. 同步拦截器:通过 handle 方法实现同步拦截
  3. 异步拦截器:通过 intercept 方法实现异步拦截,支持洋葱模型
  4. 全局拦截器:使用 global: true 或 API 注册全局拦截器
  5. 页面级拦截器:在 @HMRouter 中指定页面级拦截器
  6. 拦截器上下文:使用上下文在拦截器之间共享数据
  7. 实际应用:提供了登录、日志、性能监控等实际应用示例

通过拦截器封装,我们可以:

  • 实现统一的路由控制逻辑
  • 减少代码重复,提高可维护性
  • 支持复杂的路由验证和权限控制
  • 实现路由跳转的日志记录和性能监控

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐