当前位置: 首页 > news >正文

Coze源码分析-API授权-获取令牌列表-前端源码

概述

本文深入分析Coze Studio中用户API授权获取令牌列表功能的前端实现。该功能是PAT(Personal Access Token)管理系统的核心组件,负责展示用户创建的所有个人访问令牌信息,包括令牌名称、创建时间、最后使用时间、过期时间和状态等关键信息。通过对源码的详细解析,我们将了解其数据获取机制、列表展示逻辑、状态管理和用户体验优化等核心技术要点。

功能特性

核心功能

  • 令牌列表获取:从后端API获取完整的PAT令牌列表数据
  • 实时状态展示:动态显示令牌状态(活跃/已过期)
  • 多维度信息展示:包含令牌名称、创建时间、最后使用时间、过期时间
  • 加载状态管理:提供友好的加载状态和错误处理
  • 空状态处理:当无令牌时提供引导用户创建的空状态页面

用户体验特性

  • 即时加载:页面初始化时自动获取令牌列表
  • 状态感知:通过颜色和标签直观显示令牌状态
  • 时间格式化:友好的时间显示格式
  • 国际化支持:多语言界面适配
  • 响应式设计:适配不同屏幕尺寸

技术架构

整体架构设计

┌─────────────────────────────────────────────────────────────┐
│                      PAT列表获取模块                        │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │   PatBody   │  │  DataTable  │  │    TableColumn      │  │
│  │  (主组件)    │  │  (数据表格)  │  │   (列配置组件)       │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │                 useGetPATList                           │  │
│  │               (数据获取Hook)                             │  │
│  └─────────────────────────────────────────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│                      状态管理层                             │
│  ┌─────────────────┐  ┌─────────────────────────────────┐  │
│  │ usePatOperation │  │         API Hooks               │  │
│  │   (操作逻辑)     │  │     useRequest                  │  │
│  └─────────────────┘  └─────────────────────────────────┘  │
├─────────────────────────────────────────────────────────────┤
│                       API服务层                            │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │              PAT Permission API                         │  │
│  │          ListPersonalAccessTokens                       │  │
│  └─────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

核心模块结构

frontend/packages/studio/open-platform/open-auth/
├── src/
│   ├── components/
│   │   └── pat/                    # PAT管理核心组件模块
│   │       ├── index.tsx          # 主组件(PatBody)- 整合所有子组件
│   │       └── data-table/        # 令牌列表展示模块
│   │           ├── index.tsx      # 数据表格主组件
│   │           └── table-column/  # 表格列配置模块
│   │               ├── index.tsx           # 列配置主文件
│   │               ├── column-name.tsx     # 令牌名称列
│   │               ├── column-create-at.tsx # 创建时间列
│   │               ├── column-last-use-at.tsx # 最后使用时间列
│   │               ├── column-expire-at.tsx # 过期时间列
│   │               ├── column-status.tsx   # 状态列
│   │               └── column-op.tsx       # 操作列(编辑/删除)
│   ├── hooks/
│   │   └── pat/                   # PAT状态管理模块
│   │       ├── use-token.ts       # API调用Hooks
│   │       │                      # - useGetPATList(获取列表)
│   │       └── action/
│   │           └── use-pat-operation.ts # 操作状态管理Hook
│   │                              # - 列表数据管理
│   │                              # - 加载状态控制
│   └── utils/
│       └── time.ts                # 时间处理工具模块
│                                  # - 令牌状态判断
│                                  # - 时间格式化显示
└── API服务层/└── pat_permission_api/        # PAT权限API接口模块└── ListPersonalAccessTokens  # 获取令牌列表接口

用户获取令牌列表流程概述

用户访问API授权页面↓PatBody组件初始化↓useEffect() 触发↓fetchData() 调用↓useGetPATList Hook执行↓patPermissionApi.ListPersonalAccessTokens()↓后端返回令牌列表数据↓onSuccess() 处理成功响应↓setDataSource() 更新状态↓DataTable 组件渲染列表↓TableColumn 展示格式化数据

该流程包含完整的数据获取和展示链路:

  1. 组件初始化:PatBody组件挂载时自动触发数据获取
  2. API调用:使用ListPersonalAccessTokens API获取令牌列表
  3. 数据处理:对返回的令牌数据进行状态管理和格式化
  4. 列表渲染:通过DataTable和TableColumn组件展示格式化的令牌信息

整个流程确保了令牌列表的实时性和用户体验的流畅性。

核心组件实现

1. 主组件初始化(PatBody)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/index.tsx

负责整体PAT管理功能的初始化和数据获取:

export const PatBody: React.FC<PATProps> = ({size,type,renderTopBodySlot,renderDataEmptySlot,getCustomDataConfig,fetchCustomPatList,renderPermissionModal,afterCancelPermissionModal,
}) => {const {onAddClick,loading,dataSource,       // 令牌列表数据editHandle,runDelete,refreshHandle,showDataForm,isCreate,createSuccessHandle,onCancel,successData,showResult,setShowResult,editInfo,fetchData,        // 数据获取函数} = usePatOperation({ fetchCustomPatList, afterCancelPermissionModal });// 组件挂载时自动获取令牌列表useEffect(() => {fetchData();}, []);return (<div className="w-full h-full flex flex-col">{renderTopBodySlot?.({ openAddModal: onAddClick }) || (<TopBody openAddModal={onAddClick} />)}<DataTablesize={size}type={type}loading={loading}          // 加载状态dataSource={dataSource}   // 令牌列表数据onEdit={editHandle}onDelete={runDelete}onAddClick={onAddClick}renderDataEmptySlot={renderDataEmptySlot}getCustomDataConfig={getCustomDataConfig}/>{/* 其他模态框组件 */}</div>);
};

设计亮点

  • 自动初始化:组件挂载时自动获取令牌列表,无需用户手动触发
  • 状态传递:将加载状态和数据源传递给子组件
  • 灵活配置:支持自定义数据获取函数和渲染配置
  • 响应式布局:使用flex布局适配不同屏幕尺寸

2. 数据表格组件(DataTable)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/index.tsx

负责渲染令牌列表的表格展示:

export const DataTable = ({loading,dataSource,        // 令牌列表数据onEdit,onDelete,onAddClick,renderDataEmptySlot,getCustomDataConfig = getTableColumnConf,size,type,
}: DataTableProps) => {const tableRef = useRef<HTMLDivElement>(null);const tableHeight = useTableHeight(tableRef);// 获取表格列配置const columns: ColumnProps<PersonalAccessToken>[] = getCustomDataConfig?.({onEdit,onDelete,}).filter(item => !item.hidden);return (<div className={cls('flex-1', styles['table-container'])} ref={tableRef}><AuthTableuseHoverStyle={false}size={size}type={type}tableProps={{rowKey: 'id',loading,           // 显示加载状态dataSource,        // 令牌列表数据源columns,           // 表格列配置scroll: { y: tableHeight },}}empty={renderDataEmptySlot?.() || (<UIEmptyempty={{title: I18n.t('no_api_token_1'),description: I18n.t('add_api_token_1'),btnText: I18n.t('add_new_token_button_1'),btnOnClick: onAddClick,}}/>)}/></div>);
};

设计亮点

  • 动态高度:使用useTableHeight自动计算表格高度
  • 空状态处理:提供友好的空数据展示和引导操作
  • 加载状态:集成loading状态显示
  • 可配置列:支持自定义列配置和隐藏特定列
  • 响应式设计:表格支持滚动和自适应布局

3. 表格列配置(getTableColumnConf)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/table-column/index.tsx

定义令牌列表的表格列结构:

export const getTableColumnConf = ({onEdit,onDelete,
}: {onEdit: (v: PersonalAccessToken) => void;onDelete: (id: string) => void;
}): ColumnProps<PersonalAccessToken>[] => [columnNameConf(),        // 令牌名称列columnCreateAtConf(),    // 创建时间列columnLastUseAtConf(),   // 最后使用时间列columnExpireAtConf(),    // 过期时间列columnStatusConf(),      // 状态列{...columnOpConf(),     // 操作列render: (_, record) => (<ColumnOpBody {...{ record, isCurrentUser: true, onEdit, onDelete }} />),},
];

设计亮点

  • 模块化设计:每个列都有独立的配置函数,便于维护
  • 功能完整:涵盖令牌的所有关键信息展示
  • 操作集成:在操作列中集成编辑和删除功能

4.表格列详细实现

1. 令牌名称列(columnNameConf)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/table-column/column-name.tsx

export const columnNameConf: () => ColumnProps<PersonalAccessToken> = () => ({title: I18n.t('coze_api_list1'),    // 列标题:令牌名称dataIndex: 'name',                   // 数据字段width: 120,                          // 列宽度render: (name: string) => <p>{name}</p>,  // 渲染函数
});
2. 创建时间列(columnCreateAtConf)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/table-column/column-create-at.tsx

export const columnCreateAtConf: () => ColumnProps<PersonalAccessToken> =() => ({title: I18n.t('coze_api_list3'),         // 列标题:创建时间dataIndex: 'created_at',                 // 数据字段render: (createTime: number) => getDetailTime(createTime),  // 时间格式化});
3. 最后使用时间列(columnLastUseAtConf)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/table-column/column-last-use-at.tsx

export const columnLastUseAtConf: () => ColumnProps<PersonalAccessToken> =() => ({title: I18n.t('coze_api_list4'),         // 列标题:最后使用时间dataIndex: 'last_used_at',               // 数据字段render: (lastUseTime: number) => getDetailTime(lastUseTime),  // 时间格式化});
4. 过期时间列(columnExpireAtConf)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/table-column/column-expire-at.tsx

export const columnExpireAtConf: () => ColumnProps<PersonalAccessToken> =() => ({title: I18n.t('expire_time_1'),          // 列标题:过期时间dataIndex: 'expire_at',                  // 数据字段render: (expireTime: number) => getExpirationTime(expireTime),  // 过期时间格式化});
5. 状态列(columnStatusConf)

文件位置:frontend/packages/studio/open-platform/open-auth/src/components/pat/data-table/table-column/column-status.tsx

export const columnStatusConf: () => ColumnProps<PersonalAccessToken> = () => ({title: I18n.t('api_status_1'),           // 列标题:状态dataIndex: 'id',                         // 使用id字段但实际基于expire_at判断width: 80,render: (_: string, record: PersonalAccessToken) => {const isActive = getStatus(record?.expire_at as number);  // 判断令牌是否活跃return (<Tag size="small" color={isActive ? 'primary' : 'grey'}>{I18n.t(isActive ? 'api_status_active_1' : 'api_status_expired_1')}</Tag>);},
});

设计亮点

  • 动态状态:基于过期时间实时计算令牌状态
  • 视觉区分:使用不同颜色的Tag组件区分活跃和过期状态
  • 国际化标签:状态文本支持多语言

业务逻辑

数据获取Hook(useGetPATList)

文件位置:frontend/packages/studio/open-platform/open-auth/src/hooks/pat/use-token.ts

封装令牌列表获取的核心逻辑:

export const useGetPATList = ({fetchCustomPatList,
}: {fetchCustomPatList?: FetchCustomPatList;
}) => {const [dataSource, setDataSource] = useState<PersonalAccessToken[]>([]);// 获取PAT列表的函数const fetchPatList = useMemoizedFn(() => {if (fetchCustomPatList) {return fetchCustomPatList();  // 自定义获取函数}return patPermissionApi.ListPersonalAccessTokens({});  // 默认API调用});// 使用useRequest管理API调用状态const { loading, run: fetchData } = useRequest(fetchPatList, {manual: true,onSuccess: dataSourceData => {// 成功获取数据后更新状态setDataSource(dataSourceData?.data?.personal_access_tokens);// 埋点上报成功事件reporter.event({eventName: REPORT_EVENTS.openGetPatList,meta: {level: 'success',action: 'ListPersonalAccessTokens',},});},onError: error => {// 错误处理和埋点上报reporter.errorEvent({eventName: REPORT_EVENTS.openGetPatList,error,meta: {action: 'ListPersonalAccessTokens',},});},});return {dataSource,    // 令牌列表数据loading,       // 加载状态fetchData,     // 获取数据函数};
};

设计亮点

  • 灵活性:支持自定义数据获取函数,便于测试和扩展
  • 错误处理:完整的错误处理机制和埋点上报
  • 状态管理:使用useRequest统一管理加载状态和数据状态
  • 手动控制:manual: true允许精确控制API调用时机
  • 数据提取:从API响应中正确提取personal_access_tokens数组
bot-api/package.json

文件位置:frontend/packages/arch/bot-api/package.json
核心代码:

{"name": "@coze-arch/bot-api","version": "0.0.1","description": "RPC wrapper for bot studio application","author": "fanwenjie.fe@bytedance.com","exports": {".": "./src/index.ts",},
}

代码作用:

  • 1.包定义 :定义了一个名为 @coze-arch/bot-api 的 npm 包,版本为 0.0.1,这是一个用于 bot studio 应用的 RPC 包装器。
  • 2.通过主入口文件 :
    frontend\packages\arch\bot-api\src\index.ts 中, patPermissionApi 被导出:
export { patPermissionApi } from './pat-permission-api';

这允许通过 @coze-arch/bot-api 直接导入 patPermissionApi 。

  • 3.patPermissionApi 实现 :在 src/pat-permission-api.ts 中, patPermissionApi 是一个配置好的服务实例,它使用了 PATPermissionService 和 axios 请求配置。
src/pat-permission-api.ts

文件位置:frontend\packages\arch\bot-api\src\pat-permission-api.ts

核心代码:

import PATPermissionService from './idl/pat_permission_api';
import { axiosInstance, type BotAPIRequestConfig } from './axios';export const patPermissionApi = new PATPermissionService<BotAPIRequestConfig>({request: (params, config = {}) =>axiosInstance.request({ ...params, ...config }),
});
代码含义详解

这段代码是创建一个 PATPermissionService 实例的构造函数调用,具体含义如下:

PATPermissionService<BotAPIRequestConfig>({request: (params, config = {}) => axiosInstance.request({ ...params, ...config }),
})
  1. 泛型参数
  • PATPermissionService<BotAPIRequestConfig>:这是一个泛型类,BotAPIRequestConfig 是类型参数
  • BotAPIRequestConfig 定义了业务层的自定义 axios 配置类型,包含 __disableErrorToast 等业务特定字段
  1. 构造函数参数

传入一个配置对象,包含 request 函数:

{request: (params, config = {}) => axiosInstance.request({ ...params, ...config })
}
  1. request 函数解析

这是一个依赖注入的设计模式:

  • 参数说明

    • params:包含 HTTP 请求的基本参数(url、method、data、headers 等)
    • config:可选的额外配置,默认为空对象
  • 函数体

    • { ...params, ...config }:使用展开运算符合并参数
    • axiosInstance.request():调用 axios 实例的 request 方法发送 HTTP 请求
  1. 依赖注入模式
// IDL 生成的服务类不直接依赖具体的 HTTP 库
class PATPermissionService<T> {private request: any;constructor(options?: { request?: Function }) {this.request = options?.request || this.request;}
}
  1. 适配器模式
// 将 axiosInstance.request 适配为 IDL 服务所需的接口
request: (params, config) => axiosInstance.request({ ...params, ...config })
  1. 数据流转过程

  2. 业务调用patPermissionApi.ListPersonalAccessTokens(params)

  3. 参数组装:IDL 生成的方法将业务参数转换为标准 HTTP 参数

  4. 请求发送:调用注入的 request 函数

  5. HTTP 请求:最终通过 axiosInstance.request 发送请求

  6. 优势

  • 解耦:IDL 生成的代码不直接依赖 axios,便于测试和替换
  • 类型安全:通过泛型确保配置类型的一致性
  • 可扩展:可以在 request 函数中添加业务逻辑(如错误处理、认证等)
  • 统一性:所有 API 调用都通过相同的 request 函数,便于统一管理
  1. 实际效果

当调用 ListPersonalAccessTokens 时:

// 1. IDL 生成的方法
ListPersonalAccessTokens(req, options) {const params = { url: '/api/...', method: 'POST', data: {...} };return this.request(params, options); // 调用注入的 request 函数
}// 2. 注入的 request 函数
(params, config) => {// params = { url: '/api/...', method: 'POST', data: {...} }// config = options (可能包含 __disableErrorToast 等)return axiosInstance.request({ ...params, ...config });
}

这种设计确保了代码的模块化、可测试性和可维护性。

axiosInstance说明

1.axiosInstance 在整个项目中是全局共享的
2.bot-api 包中的导入 ( frontend/packages/arch/bot-api/src/axios.ts )
是直接从 @coze-arch/bot-http 包导入了 axiosInstance 。

import {axiosInstance,isApiError,type AxiosRequestConfig,
} from '@coze-arch/bot-http';

3.bot-http 包中的定义 ( frontend/packages/arch/bot-http/src/axios.ts ):

export const axiosInstance = axios.create();

这里创建了一个全局的 axios 实例,与用户名修改保存请求的 axios 实例是同一个。

PATPermissionService说明

1.bot-api包中的导入路径:
import PATPermissionService from ‘./idl/pat_permission_api’;
实际指向
frontend/packages/arch/bot-api/src/idl/pat_permission_api.ts
文件内容重新导出了 @coze-arch/idl/pat_permission_api 包的所有内容,包括默认导出

export * from '@coze-arch/idl/pat_permission_api';
export { default as default } from '@coze-arch/idl/pat_permission_api';

2.idl包的模块映射
文件位置:frontend/packages/arch/idl/package.json
核心代码:

"name": "@coze-arch/idl","version": "0.0.1","description": "IDL files for bot studio application","author": "fanwenjie.fe@bytedance.com","exports": {"./pat_permission_api": "./src/auto-generated/pat_permission_api/index.ts",

代码作用:将 @coze-arch/idl/pat_permission_api 映射到实际文件路径frontend/packages/arch/idl/src/auto-generated/pat_permission_api/index.ts
这个文件说明后续见 PAT权限获取令牌列表-API接口实现 这个章节。

API层设计与实现

IDL基础类型定义(base.thrift)

文件位置:idl/base.thrift
核心代码:

namespace py base
namespace go base
namespace java com.bytedance.thrift.basestruct TrafficEnv {1: bool   Open = false,2: string Env  = ""   ,
}struct Base {1:          string             LogID      = "",2:          string             Caller     = "",3:          string             Addr       = "",4:          string             Client     = "",5: optional TrafficEnv         TrafficEnv     ,6: optional map<string,string> Extra          ,
}struct BaseResp {1:          string             StatusMessage = "",2:          i32                StatusCode    = 0 ,3: optional map<string,string> Extra             ,
}struct EmptyReq {
}struct EmptyData {}struct EmptyResp {1: i64       code,2: string    msg ,3: EmptyData data,
}struct EmptyRpcReq {255: optional Base Base,
}struct EmptyRpcResp {255: optional BaseResp BaseResp,
}

文件作用:
定义了项目中所有接口的基础数据结构,作为其他IDL文件的依赖基础。

IDL接口定义(openapiauth.thrift)

文件位置:idl/permission/openapiauth.thrift

定义获取令牌列表的数据结构:

include "../base.thrift"namespace go permission.openapiauth// 获取令牌列表请求
struct ListPersonalAccessTokensRequest {1: optional string organization_id (api.query="organization_id") // 组织ID2: optional i64 page (api.query="page") // 页码(从0开始)3: optional i64 size (api.query="size") // 页面大小4: optional PatSearchOption search_option (api.query="search_option") // 搜索选项
}// 包含创建者信息的令牌数据结构
struct PersonalAccessTokenWithCreatorInfo {1: required i64 id (api.js_conv="true")2: required string name3: required i64 created_at4: required i64 updated_at5: required i64 last_used_at // -1 表示未使用6: required i64 expire_at // -1 表示永久有效7: string creator_name8: string creator_unique_name9: string creator_avatar_url10: string creator_icon_url11: bool locked12: UserStatus creator_status
}// 获取令牌列表响应数据
struct ListPersonalAccessTokensResponseData {1: required list<PersonalAccessTokenWithCreatorInfo> personal_access_tokens // PAT列表2: bool has_more // 是否还有更多数据
}// 获取令牌列表响应
struct ListPersonalAccessTokensResponse {1: required ListPersonalAccessTokensResponseData data2: required i32 code3: required string msg
}

设计亮点

  • 分页支持:请求结构支持分页查询,便于处理大量数据
  • 搜索选项:支持不同的搜索模式(all、others、owned)
  • 完整信息:响应包含令牌的完整信息和创建者信息
  • 扩展性:has_more字段支持无限滚动加载

IDL服务定义(openapiauth_service.thrift)

文件位置:idl/permission/openapiauth_service.thrift

定义获取令牌列表的服务接口:

include "../base.thrift"
include "./openapiauth.thrift"namespace go permission.openapiauthservice OpenAPIAuthService {openapiauth.ListPersonalAccessTokensResponse ListPersonalAccessTokens (1: openapiauth.ListPersonalAccessTokensRequest req) (api.get="/api/permission_api/pat/list_personal_access_tokens")
}

设计亮点

  • RESTful设计:使用GET方法获取资源列表
  • 语义化路径:API路径清晰表达获取令牌列表的功能
  • 标准化:与其他PAT相关接口保持一致的命名规范

PAT权限获取令牌列表-TypeScript接口生成

通过IDL代码生成工具,自动生成对应的TypeScript接口:

文件位置:frontend/packages/arch/idl/src/auto-generated/pat_permission_api/namespaces/openapi.ts

// 获取令牌列表请求接口
export interface ListPersonalAccessTokensRequest {/** organization id */organization_id?: string;/** zero-indexed */page?: Int64;/** page size */size?: Int64;/** search option */search_option?: PatSearchOption;
}// 获取令牌列表响应接口
export interface ListPersonalAccessTokensResponse {data: ListPersonalAccessTokensResponseData;
}export interface ListPersonalAccessTokensResponse2 {code: number;msg: string;data: ListPersonalAccessTokensResponseData;
}// 获取令牌列表响应数据接口
export interface ListPersonalAccessTokensResponseData {/** PAT 列表 */personal_access_tokens: Array<PersonalAccessTokenWithCreatorInfo>;/** 是否还有更多数据 */has_more?: boolean;
}// 包含创建者信息的令牌数据结构
export interface PersonalAccessTokenWithCreatorInfo {id: string;name: string;created_at: Int64;updated_at: Int64;/** -1 表示未使用 */last_used_at: Int64;/** -1 表示无限期 */expire_at: Int64;creator_name?: string;creator_unique_name?: string;creator_avatar_url?: string;creator_icon_url?: string;locked?: boolean;creator_status?: UserStatus;
}// 基础令牌数据结构
export interface PersonalAccessToken {id: string;name: string;created_at: Int64;updated_at: Int64;/** -1 表示未使用 */last_used_at: Int64;/** -1 表示无限期 */expire_at: Int64;
}

设计亮点

  • 分页支持:请求接口支持分页参数,便于处理大量令牌数据
  • 搜索选项:支持不同的搜索模式(all、others、owned)
  • 完整信息:响应包含令牌的完整信息和创建者信息
  • 类型安全:使用Int64类型确保时间戳的正确处理
  • 可选字段:创建者信息和扩展字段都是可选的,增强了接口的灵活性
  • 标准响应:统一的响应格式便于错误处理和状态管理

PAT权限获取令牌列表-服务类生成

文件位置:frontend/packages/arch/idl/src/auto-generated/pat_permission_api/index.ts

自动生成的API服务类实现:

export default class PatPermissionApiService<T> {private request: any = () => {throw new Error('PatPermissionApiService.request is undefined');};private baseURL: string | ((path: string) => string) = '';constructor(options?: {baseURL?: string | ((path: string) => string);request?<R>(params: {url: string;method: 'GET' | 'DELETE' | 'POST' | 'PUT' | 'PATCH';data?: any;params?: any;headers?: any;},options?: T,): Promise<R>;}) {this.request = options?.request || this.request;this.baseURL = options?.baseURL || '';}private genBaseURL(path: string) {return typeof this.baseURL === 'string'? this.baseURL + path: this.baseURL(path);}/*** GET /api/permission_api/pat/list_personal_access_tokens** list pats** list pats in account*/ListPersonalAccessTokens(req?: ListPersonalAccessTokensRequest,options?: T,): Promise<ListPersonalAccessTokensResponse2> {const _req = req || {};const url = this.genBaseURL('/api/permission_api/pat/list_personal_access_tokens',);const method = 'GET';const params = {organization_id: _req['organization_id'],page: _req['page'],size: _req['size'],search_option: _req['search_option'],};return this.request({ url, method, params }, options);}// ... 其他方法
}

代码作用

  • PatPermissionApiService 类的 ListPersonalAccessTokens 方法用于获取PAT令牌列表
  • 该方法使用GET请求,从后端获取令牌列表数据
  • 支持可选的分页参数和搜索选项
  • 所有请求参数都作为URL查询参数传递
  • 此文件是基于 openapiauth.thrift 自动生成的,开发者无需手动修改

时间处理工具

时间工具函数

文件位置:frontend/packages/studio/open-platform/open-auth/src/utils/time.ts

提供完整的时间处理和状态判断功能:

// 服务端时间值枚举
enum ServerTimeValue {PERMANENT = -1,    // 永久有效NOT_USE = -1,      // 未使用
}// 获取详细时间格式(用于创建时间和最后使用时间)
export const getDetailTime = (d: number) => {if (d === ServerTimeValue.NOT_USE) {return '-';  // 未使用时显示"-"}const showDate = dayjs.unix(d).format('YYYY-MM-DD HH:mm:ss');return showDate;
};// 获取过期时间格式
export const getExpirationTime = (d: number) => {if (d === ServerTimeValue.PERMANENT) {return I18n.t('api_status_permanent_1');  // 永久有效}const showDate = dayjs.unix(d).format('YYYY-MM-DD');return showDate;
};// 判断令牌状态
export const getStatus = (d: number) => {if (d === ServerTimeValue.PERMANENT) {return true;  // 永久有效为活跃状态}const current = dayjs().unix();return d >= current;  // 过期时间大于等于当前时间为活跃状态
};

设计亮点

  • 特殊值处理:正确处理-1表示的永久有效和未使用状态
  • 格式统一:创建时间和最后使用时间使用完整的日期时间格式
  • 过期时间简化:过期时间只显示日期,更加简洁
  • 状态准确性:基于Unix时间戳精确判断令牌是否过期

文件依赖关系

以下是获取令牌列表功能相关文件的依赖关系图:

┌─────────────────────────────────────────────────────────────────────────────┐
│                              文件依赖关系图                                 │
└─────────────────────────────────────────────────────────────────────────────┘IDL定义层                    代码生成工具                  生成的TypeScript代码┌─────────────┐                ┌─────────────┐              ┌─────────────────────┐│             │                │             │              │                     ││ openapiauth │────────────────→│   cli.js    │──────────────→│     openapi.ts      ││   .thrift   │                │             │              │   (类型定义文件)    ││             │                │ IDL转换工具 │              │                     │└─────────────┘                │             │              └─────────────────────┘│                        └─────────────┘                        ││                                                               │▼                                                               ▼┌─────────────┐                                                ┌─────────────────────┐│             │                                                │                     ││openapiauth_ │                                                │     index.ts        ││service.thrift│────────────────────────────────────────────────→│  (服务实现文件)     ││             │                                                │                     ││(服务接口定义)│                                                │                     │└─────────────┘                                                └─────────────────────┘┌─────────────────────────────────────────────────────────────────────────────┐
│                                文件内容说明                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│ 1. openapiauth.thrift                                                       │
│    ├─ ListPersonalAccessTokensRequest                                       │
│    ├─ ListPersonalAccessTokensResponse                                      │
│    ├─ ListPersonalAccessTokensResponseData                                  │
│    └─ PersonalAccessTokenWithCreatorInfo                                    │
│                                                                             │
│ 2. openapiauth_service.thrift                                               │
│    └─ ListPersonalAccessTokens 服务方法定义                                │
│                                                                             │
│ 3. cli.js (IDL转换工具)                                                     │
│    └─ @coze-arch/idl2ts-cli 工具入口                                       │
│                                                                             │
│ 4. openapi.ts (类型定义)                                                    │
│    ├─ ListPersonalAccessTokensRequest                                       │
│    ├─ ListPersonalAccessTokensResponse                                      │
│    ├─ ListPersonalAccessTokensResponse2                                     │
│    ├─ ListPersonalAccessTokensResponseData                                  │
│    ├─ PersonalAccessTokenWithCreatorInfo                                    │
│    └─ PersonalAccessToken                                                   │
│                                                                             │
│ 5. index.ts (服务实现)                                                      │
│    ├─ PatPermissionApiService 类                                            │
│    └─ ListPersonalAccessTokens 方法实现                                     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

数据流转关系

获取令牌列表功能的完整数据流转过程:

┌─────────────────────────────────────────────────────────────────────────────┐
│                              数据流转图                                     │
└─────────────────────────────────────────────────────────────────────────────┘前端组件层                    Hook状态层                     API服务层┌─────────────┐              ┌─────────────┐               ┌─────────────┐│             │              │             │               │             ││  PatBody    │──fetchData──→│useGetPATList│──API调用────→│patPermission││  (主组件)   │              │   Hook      │               │    Api      ││             │              │             │               │             │└─────────────┘              └─────────────┘               └─────────────┘│                            │                             ││                            │                             │▼                            ▼                             ▼┌─────────────┐              ┌─────────────┐               ┌─────────────┐│             │              │             │               │             ││  DataTable  │◄─dataSource─│   状态管理  │◄─响应数据───│ListPersonal ││  (数据表格) │              │   loading   │               │AccessTokens ││             │              │             │               │   Method    │└─────────────┘              └─────────────┘               └─────────────┘│                                                          ││                                                          │▼                                                          ▼┌─────────────┐                                            ┌─────────────┐│             │                                            │             ││TableColumn  │                                            │ IDL生成的   ││ (列配置)    │                                            │ TypeScript  ││             │                                            │   接口      │└─────────────┘                                            └─────────────┘

关键文件作用说明

  1. IDL定义文件

    • openapiauth.thrift:定义数据结构(ListPersonalAccessTokensRequest、ListPersonalAccessTokensResponse等)
    • openapiauth_service.thrift:定义服务接口(ListPersonalAccessTokens方法)
  2. 代码生成

    • @coze-arch/idl2ts-cli:将IDL文件转换为TypeScript代码
    • 生成类型定义和服务实现
  3. 前端组件

    • PatBody:主组件,负责整体布局和数据获取触发
    • DataTable:数据表格组件,负责渲染令牌列表
    • TableColumn:列配置组件,定义每列的显示逻辑
  4. 状态管理

    • useGetPATList:数据获取Hook,封装API调用逻辑
    • usePatOperation:操作状态管理Hook,统一管理所有PAT操作
  5. API服务

    • patPermissionApi:API服务实例,提供ListPersonalAccessTokens方法
    • PatPermissionApiService:生成的服务类,包含具体的HTTP请求实现

这种分层架构确保了代码的可维护性和可扩展性,同时通过IDL工具链保证了前后端接口的一致性。

IDL文件解析器分析结论

通过深入分析Coze Studio项目的IDL架构,我可以确认**openapiauth_service.thriftpassport.thrift使用相同的Thrift Parser**。

关键发现
  1. 统一的IDL工具链:项目使用@coze-arch/idl2ts-cli作为统一的IDL到TypeScript转换工具,该工具支持处理所有Thrift文件。

  2. 共享基础结构

    • 两个文件都位于统一的coze-studio\idl目录下
    • 两个文件都引用了共享的base.thrift文件
    • 使用相同的namespace和结构体定义规范
  3. 统一的代码生成流程

    • frontend\packages\arch\api-schema\api.config.js配置了passport.thrift的生成
    • frontend\packages\arch\idl\package.json包含了openapiauth_service.thrift的自动生成代码
    • 两者都使用相同的idl2ts工具链进行代码生成
  4. 相同的输出格式:生成的TypeScript代码都遵循相同的结构和命名约定,包含相同的注释头和类型定义格式。

结论

openapiauth_service.thriftpassport.thrift确实使用相同的Thrift Parser(@coze-arch/idl2ts-cli),它们共享相同的解析规则、代码生成逻辑和输出格式。这确保了整个项目中IDL文件处理的一致性和兼容性。

@coze-arch/idl2ts-cli 工具详细信息

工具名称

@coze-arch/idl2ts-cli

详细地址

项目路径frontend/infra/idl/idl2ts-cli/

工具详细信息

版本:0.1.7

描述:IDL(Interface Definition Language)到TypeScript的转换工具

主要功能

  1. gen命令:从Thrift或Protocol Buffer文件生成API代码
  2. filter命令:生成过滤后的API类型定义

可执行文件idl2ts(位于 ./src/cli.js
最终调用的是frontend/infra/idl/idl2ts-cli/src/cli.ts 这个文件

核心依赖

  • @coze-arch/idl2ts-generator:代码生成器
  • @coze-arch/idl2ts-helper:辅助工具
  • @coze-arch/idl2ts-plugin:插件系统
  • commander:命令行界面
  • prettier:代码格式化

使用方式

# 生成API代码
idl2ts gen <projectRoot> [-f --format-config <formatConfig>]# 生成过滤类型
idl2ts filter <projectRoot> [-f --format-config <formatConfig>]

许可证:Apache-2.0

作者:fanwenjie.fe@bytedance.com

这个工具是Coze Studio项目中统一处理所有IDL文件(包括openapiauth_service.thrift和其他相关文件)的核心工具,确保了整个项目中API代码生成的一致性。

状态管理集成

操作状态管理(usePatOperation)

文件位置:frontend/packages/studio/open-platform/open-auth/src/hooks/pat/action/use-pat-operation.ts

将获取令牌列表功能集成到整体操作状态管理中:

export const usePatOperation = ({fetchCustomPatList,afterCancelPermissionModal,
}: {fetchCustomPatList?: FetchCustomPatList;afterCancelPermissionModal?: (isCreate: boolean) => void;
}) => {// 集成获取PAT列表功能const { loading, dataSource, fetchData } = useGetPATList({fetchCustomPatList,});// 其他状态管理const [showDataForm, setShowDataForm] = useState(false);const [showResult, setShowResult] = useState(false);const [isCreate, setIsCreate] = useState(true);const [editInfo, setEditInfo] = useState<PersonalAccessToken>();// 返回统一的状态和操作函数return {dataSource,    // 令牌列表数据loading,       // 加载状态fetchData,     // 数据获取函数// ... 其他操作函数};
};

设计亮点

  • 状态集成:将获取列表功能集成到整体状态管理中
  • 统一接口:提供统一的数据源和加载状态
  • 功能解耦:各个功能模块保持独立,通过Hook进行组合

技术要点总结

1. 数据流管理

  • 自动获取:组件挂载时自动获取令牌列表,确保数据实时性
  • 状态同步:使用useRequest统一管理API调用状态和数据状态
  • 错误处理:完整的错误处理机制和用户反馈

2. 用户体验优化

  • 加载状态:友好的加载状态展示
  • 空状态处理:当无数据时提供引导操作
  • 状态感知:通过颜色和标签直观显示令牌状态
  • 时间格式化:用户友好的时间显示格式

3. 架构设计

  • 组件解耦:各组件职责明确,通过props进行通信
  • Hook复用:数据获取逻辑封装为可复用的Hook
  • 配置灵活:支持自定义数据获取和列配置

4. 技术特色

  • TypeScript支持:完整的类型定义确保代码安全
  • 国际化:所有文本支持多语言
  • 埋点上报:集成完整的事件上报机制
  • 响应式设计:适配不同屏幕尺寸

5. 性能优化

  • 按需渲染:表格支持虚拟滚动和动态高度
  • 状态缓存:合理使用useMemoizedFn避免不必要的重渲染
  • 懒加载:手动控制API调用时机

技术对比分析

与传统列表获取方案的对比

1. 传统方案 vs Coze Studio方案
对比维度传统方案Coze Studio方案优势分析
数据获取直接在组件中调用APIuseGetPATList Hook封装逻辑解耦,可复用性强
状态管理useState + useEffectuseRequest + 统一状态管理更好的加载状态控制
类型安全手写接口类型IDL自动生成TypeScript类型一致性,减少错误
错误处理组件内部处理Hook统一错误处理 + 埋点错误处理标准化
时间处理组件内格式化独立time工具函数逻辑复用,维护性好
2. 技术选型优势

IDL驱动开发 vs 手写API

  • 一致性保障:IDL确保前后端接口定义完全一致
  • 自动化程度:减少80%的手写接口代码
  • 维护成本:接口变更时自动同步,避免人工维护错误

Hook模式 vs 传统Class组件

  • 代码复用率:提升60%以上的逻辑复用能力
  • 测试友好性:Hook更容易进行单元测试
  • 性能优化:更精细的重渲染控制

架构设计对比

1. 分层架构优势
传统MVC架构                    Coze Studio分层架构
┌─────────────┐               ┌─────────────────────┐
│   View      │               │   组件层(展示)      │
├─────────────┤               ├─────────────────────┤
│ Controller  │   ========>   │   Hook层(逻辑)      │
├─────────────┤               ├─────────────────────┤
│   Model     │               │   API层(数据)       │
└─────────────┘               └─────────────────────┘

优势分析

  • 职责清晰:每层专注特定功能,便于维护和测试
  • 可扩展性:新增功能时只需修改对应层级
  • 团队协作:不同层级可由不同开发者并行开发

安全性设计分析

数据安全保护

1. 令牌数据脱敏
// 前端永不展示完整令牌值
interface PersonalAccessTokenWithCreatorInfo {id: string;           // 仅展示令牌IDname: string;         // 展示令牌名称(用户自定义)// ❌ 不包含token值,避免泄露created_at: Int64;last_used_at: Int64;expire_at: Int64;
}

安全措施

  • 敏感信息隔离:列表接口永不返回实际令牌值
  • 最小权限原则:仅获取展示所需的基本信息
  • 前端零存储:令牌值不在前端任何地方持久化
2. 时间安全处理
// 状态判断基于服务端时间
export const getStatus = (d: number) => {if (d === ServerTimeValue.PERMANENT) {return true;}const current = dayjs().unix();  // 使用当前时间判断return d >= current;
};

安全考虑

  • 时间同步:基于Unix时间戳确保时间判断准确性
  • 过期检测:前端实时检测令牌过期状态
  • 视觉提示:通过颜色区分有效和过期令牌

网络安全措施

1. API请求安全
// 统一的axios实例配置
export const patPermissionApi = new PATPermissionService<BotAPIRequestConfig>({request: (params, config = {}) =>axiosInstance.request({ ...params, ...config }),
});

安全特性

  • 统一认证:所有API请求通过统一的axios实例
  • 错误处理:标准化错误处理防止信息泄露
  • 请求拦截:支持请求和响应拦截器进行安全检查
2. 用户权限控制
// 基于用户身份的数据获取
struct ListPersonalAccessTokensRequest {1: optional string organization_id  // 组织级权限控制2: optional PatSearchOption search_option  // 搜索权限控制
}

权限设计

  • 组织隔离:基于organization_id实现多租户数据隔离
  • 搜索权限:支持不同搜索模式(owned/others/all)的权限控制
  • 数据过滤:后端根据用户权限过滤返回数据

前端安全最佳实践

1. 输入验证和XSS防护
// 令牌名称安全渲染
render: (name: string) => <p>{name}</p>  // React自动转义
2. 错误信息安全处理
// 错误信息脱敏处理
onError: error => {reporter.errorEvent({eventName: REPORT_EVENTS.openGetPatList,error,  // 错误详情仅用于内部分析// 用户界面不展示敏感错误信息});
}

性能优化设计

渲染性能优化

1. 虚拟化表格
// 动态高度计算
const tableHeight = useTableHeight(tableRef);// 滚动优化
scroll: { y: tableHeight }

优化效果

  • 大数据支持:支持渲染1000+令牌记录
  • 内存控制:仅渲染可视区域内容
  • 滚动流畅:60FPS滚动体验
2. 状态更新优化
// 使用useMemoizedFn避免不必要重渲染
const fetchPatList = useMemoizedFn(() => {// API调用逻辑
});

性能收益

  • 减少重渲染:避免因函数引用变化导致的子组件重渲染
  • 内存优化:复用函数实例,减少GC压力

网络性能优化

1. 分页加载策略
struct ListPersonalAccessTokensRequest {2: optional i64 page    // 分页支持3: optional i64 size    // 页面大小控制
}

优化策略

  • 按需加载:支持分页或无限滚动加载
  • 数据缓存:合理缓存已加载数据
  • 预加载机制:可扩展支持预加载下一页数据
2. 请求去重和缓存
// useRequest内置请求去重
const { loading, run: fetchData } = useRequest(fetchPatList, {manual: true,  // 手动控制,避免重复请求// 内置防抖和缓存机制
});

扩展性设计分析

组件扩展性

1. 插槽化设计
interface PATProps {renderTopBodySlot?: (props: { openAddModal: () => void }) => ReactNode;renderDataEmptySlot?: () => ReactNode;getCustomDataConfig?: (...) => ColumnProps<PersonalAccessToken>[];
}

扩展能力

  • UI定制:支持顶部区域和空状态的自定义渲染
  • 列配置:支持自定义表格列配置
  • 操作扩展:预留操作按钮的扩展接口
2. Hook抽象设计
// 可复用的数据获取Hook
export const useGetPATList = ({fetchCustomPatList,  // 支持自定义数据源
}) => {// Hook实现
};

扩展价值

  • 数据源灵活:支持不同环境下的数据获取方式
  • 逻辑复用:Hook可在不同组件中复用
  • 测试友好:便于Mock数据源进行测试

API扩展性

1. IDL扩展机制
// 向后兼容的字段扩展
struct PersonalAccessTokenWithCreatorInfo {// 现有字段...11: bool locked            // 新增字段(可选)12: UserStatus creator_status  // 新增字段(可选)// 未来可继续添加字段
}

扩展优势

  • 向后兼容:新增字段不影响现有功能
  • 渐进式更新:前端可选择性支持新字段
  • 版本管理:IDL版本控制确保接口稳定性
2. 搜索功能扩展
// 可扩展的搜索选项
enum PatSearchOption {ALL = 'all',OWNED = 'owned', OTHERS = 'others',// 未来可扩展:SHARED, EXPIRED等
}

监控与调试支持

埋点监控体系

// 成功事件埋点
reporter.event({eventName: REPORT_EVENTS.openGetPatList,meta: {level: 'success',action: 'ListPersonalAccessTokens',},
});// 错误事件埋点
reporter.errorEvent({eventName: REPORT_EVENTS.openGetPatList,error,meta: {action: 'ListPersonalAccessTokens',},
});

监控价值

  • 成功率监控:实时监控API调用成功率
  • 错误分析:收集错误信息便于问题排查
  • 用户行为:分析用户使用模式优化体验

开发调试支持

1. TypeScript类型检查
// 完整的类型定义确保编译时错误检查
interface ListPersonalAccessTokensResponse2 {code: number;msg: string;data: ListPersonalAccessTokensResponseData;
}
2. 错误边界处理
// 组件级错误处理
const { loading, run: fetchData } = useRequest(fetchPatList, {onError: error => {// 统一错误处理逻辑},
});

技术总结与最佳实践

整体架构优势

通过对Coze Studio PAT令牌列表获取功能的深入分析,我们发现其在多个技术维度上都体现了企业级应用的最佳实践:

1. 架构设计优势
  • 分层解耦:组件层、Hook层、API层职责清晰,易于维护和扩展
  • IDL驱动:基于Thrift IDL的前后端接口一致性保证,减少80%的手写接口代码
  • 类型安全:完整的TypeScript类型体系确保编译时错误检查
  • 插槽化设计:预留多个扩展点,支持UI定制和功能扩展
2. 安全性保障
  • 数据脱敏:前端永不展示完整令牌值,确保敏感信息安全
  • 权限控制:基于组织ID和搜索选项的多层级权限管理
  • 时间安全:基于Unix时间戳的精确过期状态判断
  • 错误处理:统一的错误处理机制和埋点监控体系
3. 性能优化特色
  • 虚拟化渲染:支持1000+令牌记录的流畅展示
  • 状态优化:使用useMemoizedFn避免不必要的重渲染
  • 分页加载:支持按需加载和数据缓存策略
  • 网络优化:内置请求去重和防抖机制
4. 开发效率提升
  • Hook复用:数据获取逻辑60%以上的复用率
  • 自动化生成:IDL工具链自动生成API代码和类型定义
  • 调试友好:完整的错误边界和监控埋点支持
  • 测试便利:Hook抽象便于Mock和单元测试

技术价值与创新点

1. IDL驱动开发模式

相比传统手写API方式,IDL驱动开发模式带来了显著的技术价值:

  • 接口一致性:前后端接口定义完全一致,避免协作中的理解偏差
  • 维护成本:接口变更时自动同步,减少人工维护错误
  • 开发效率:代码生成工具提升80%的接口开发效率
  • 版本管理:IDL版本控制确保接口向后兼容
2. React Hook架构模式

Hook模式相比传统Class组件带来的架构优势:

  • 逻辑复用:Hook可在多个组件间共享,提升60%以上代码复用率
  • 状态管理:更精细的状态更新控制,减少不必要的重渲染
  • 测试友好:Hook更容易进行单元测试和Mock
  • 代码组织:按功能维度组织代码,提升可维护性
3. 安全设计最佳实践

在企业级应用中,安全性设计的关键实践:

  • 最小权限原则:前端仅获取展示所需的最小信息集
  • 数据分离:敏感数据(令牌值)与展示数据完全分离
  • 时间精确性:基于服务端时间的精确状态判断
  • 错误脱敏:用户界面不暴露系统内部错误信息

行业对比与竞争优势

1. 相比传统企业应用
  • 开发效率:IDL工具链提升3-5倍的接口开发效率
  • 代码质量:TypeScript + Hook模式显著降低运行时错误
  • 用户体验:虚拟化表格和状态管理提供更流畅的交互体验
  • 维护成本:分层架构和组件化设计降低长期维护成本
2. 相比同类产品
  • 技术先进性:IDL驱动 + React Hook的技术栈更加现代化
  • 安全保障:多层级的安全设计更符合企业安全要求
  • 扩展能力:插槽化设计和Hook抽象提供更强的扩展性
  • 监控完善:完整的埋点和错误监控体系

学习价值与应用场景

1. 技术学习价值

本案例为前端开发者提供了以下学习价值:

  • 现代React开发:Hook模式的最佳实践和状态管理
  • 企业级架构:分层设计和组件化开发的实际应用
  • API设计:IDL驱动开发的完整实践流程
  • 安全开发:前端安全设计的具体实现方法
2. 适用场景分析

该架构模式特别适用于以下场景:

  • 企业级管理系统:需要严格权限控制和数据安全的系统
  • API管理平台:需要展示和管理大量API相关数据的平台
  • 配置管理工具:需要处理复杂配置数据的管理工具
  • 大数据展示:需要高性能列表展示的应用场景

未来开发建议

1. 短期优化建议
  • 缓存优化:实现本地缓存机制,减少重复请求
  • 无限滚动:将分页加载改为无限滚动加载
  • 筛选功能:增加更多筛选条件(状态、创建时间等)
  • 批量操作:支持批量删除和状态更新
2. 中长期扩展方向
  • 智能推荐:基于使用模式的令牌管理推荐
  • 实时监控:令牌使用情况实时监控和告警
  • 权限分析:令牌权限使用分析和优化建议
  • 自动化管理:令牌生命周期的自动化管理

总的来说,Coze Studio的PAT令牌列表获取功能不仅在技本实现上达到了行业领先水平,更在安全性、性能和可扩展性方面设立了企业级应用开发的标杆。这种综合性的技术实践为前端开发领域提供了宝贵的参考案例,对于推动整个行业的技术进步具有重要的示范意义。

http://www.dtcms.com/a/358575.html

相关文章:

  • Spring注解演进与自动装配原理深度解析:从历史发展到自定义Starter实践
  • 逆向思维下,如何把基金投资做亏?
  • 佛山B2B企业GEO搜索优化科普指南
  • 模拟实现STL中的list容器
  • vue中的与,或,非
  • C++:list容器--模拟实现(下篇)
  • 粒子群优化算法(PSO)
  • vscode terminal远程连接linux服务器GUI图形界面
  • Linux/UNIX系统编程手册笔记:文件I/O、进程和内存分配
  • Ferris Wheel (贪心 | 双指针)
  • 【MogDB】在刚发布的银河麒麟v11上安装MogDB
  • 微电网调度(风、光、储能、电网交互)(MatlabPython代码实现)
  • open webui源码分析13-模型管理
  • Python生成免安装exe
  • 承上启下的JDK13安装步骤及下载(附小白详细教程)
  • Transformer朴素采样时,生成 T 个 token 需要的 FLOPs 计算推导过程
  • sunset: 1渗透测试
  • 《HM-RAG: Hierarchical Multi-Agent Multimodal Retrieval Augmented Generation》
  • Java中使用正则表达式的正确打开方式
  • 《微服务架构从故障频发到自愈可控的实战突围方案》
  • C++抽象类
  • Photoshop - Ps 编辑图像
  • 在PowerPoint和WPS演示让蝴蝶一直跳8字舞
  • 干掉抽取壳!FART 自动化脱壳框架与 Execute 脱壳点解析
  • 迷你电脑用到什么型号的RJ45网口
  • 【系列08】端侧AI:构建与部署高效的本地化AI模型 第7章:架构设计与高效算子
  • 文件夹和文件一键加密,保护你的隐私
  • 计算机算术8-浮点加法
  • EVidenceModeler v2.1 安装与使用--生信工具58
  • 开发者效率白皮书:工具选型与使用方法论