From d747f043c3089dd81c65ca0f53cc08ed3d781256 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Mon, 31 Mar 2025 10:49:34 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/package.json | 2 +- react-ui/src/hooks/useCacheState.ts | 7 +- react-ui/src/hooks/useCheck.ts | 12 +-- react-ui/src/hooks/useComputingResource.ts | 6 +- react-ui/src/hooks/useDraggable.ts | 4 +- react-ui/src/pages/Points/index.tsx | 8 +- react-ui/src/utils/constant.ts | 14 +++- react-ui/src/utils/date.ts | 2 +- react-ui/src/utils/format.ts | 85 ++++++++++++++++++---- react-ui/src/utils/localStorage.ts | 14 ++++ react-ui/src/utils/promise.ts | 5 +- react-ui/src/utils/sessionStorage.ts | 22 +++++- react-ui/src/utils/statusTableCell.tsx | 4 + react-ui/src/utils/table.tsx | 42 ++++++++--- react-ui/src/utils/ui.tsx | 31 +++++--- react-ui/typedoc.json | 11 ++- 16 files changed, 205 insertions(+), 64 deletions(-) diff --git a/react-ui/package.json b/react-ui/package.json index e4d95504..2c7b13a1 100644 --- a/react-ui/package.json +++ b/react-ui/package.json @@ -16,7 +16,7 @@ "docker:dev": "docker-compose -f ./docker/docker-compose.dev.yml up", "docker:push": "npm run docker-hub:build && npm run docker:tag && docker push antdesign/ant-design-pro", "docker:tag": "docker tag ant-design-pro antdesign/ant-design-pro", - "docs": "typedoc --entryPointStrategy expand --entryPoints 'src/utils' --skipErrorChecking --out docs", + "docs": "typedoc", "gh-pages": "gh-pages -d dist", "i18n-remove": "pro i18n-remove --locale=zh-CN --write", "postinstall": "max setup", diff --git a/react-ui/src/hooks/useCacheState.ts b/react-ui/src/hooks/useCacheState.ts index e320b0a6..78b16fa7 100644 --- a/react-ui/src/hooks/useCacheState.ts +++ b/react-ui/src/hooks/useCacheState.ts @@ -29,13 +29,18 @@ const removeCacheState = (key: string) => { } }; -// 移除所有页面 state 缓存 +/** + * 移除所有页面 state 缓存 + */ export const removeAllPageCacheState = () => { pageKeys.forEach((key) => { sessionStorage.removeItem(key); }); }; +/** + * 缓存页面数据 + */ export const useCacheState = () => { const { pathname } = window.location; const key = 'pagecache:' + pathname; diff --git a/react-ui/src/hooks/useCheck.ts b/react-ui/src/hooks/useCheck.ts index 1b965549..3c9c985b 100644 --- a/react-ui/src/hooks/useCheck.ts +++ b/react-ui/src/hooks/useCheck.ts @@ -1,15 +1,9 @@ import { useCallback, useMemo, useState } from 'react'; /** - * @description 选择、全选操作 - * @param list 需要进行选择的列表 - * @returns selected 选中的项 - * setSelected 设置 selected 的方法 - * checked 是否全选 - * indeterminate 是否部分选中 - * checkAll 全选 - * isSingleChecked 是否单个选中 - * checkSingle 单个选中 + * 选择、全选操作 + * @param list - 需要进行选择的列表 + * @return [选中的项, 设置选中的方法, 是否全选, 是否部分选中, 全选方法,是否单个选中,选中单个方法] */ export const useCheck = (list: T[]) => { const [selected, setSelected] = useState([]); diff --git a/react-ui/src/hooks/useComputingResource.ts b/react-ui/src/hooks/useComputingResource.ts index e1e27506..b2239247 100644 --- a/react-ui/src/hooks/useComputingResource.ts +++ b/react-ui/src/hooks/useComputingResource.ts @@ -12,7 +12,7 @@ import { useCallback, useEffect, useState } from 'react'; const computingResource: ComputingResource[] = []; -// 过滤资源规格 +/** 过滤资源规格 */ export const filterResourceStandard: SelectProps['filterOption'] = ( input: string, option?: ComputingResource, @@ -22,13 +22,13 @@ export const filterResourceStandard: SelectProps['fil ); }; -// 资源规格字段 +/** 资源规格字段 */ export const resourceFieldNames = { label: 'description', value: 'id', }; -// 获取资源规格 +/** 获取资源规格 */ export function useComputingResource() { const [resourceStandardList, setResourceStandardList] = useState([]); diff --git a/react-ui/src/hooks/useDraggable.ts b/react-ui/src/hooks/useDraggable.ts index b093ea6f..121aaafa 100644 --- a/react-ui/src/hooks/useDraggable.ts +++ b/react-ui/src/hooks/useDraggable.ts @@ -1,6 +1,8 @@ -// 处理 react-draggable 组件拖动结束时,响应了点击事件的 import { useState } from 'react'; +/** + * 处理 react-draggable 组件拖动结束时,响应了点击事件的 + */ export const useDraggable = (onClick: () => void) => { const [isDragging, setIsDragging] = useState(false); diff --git a/react-ui/src/pages/Points/index.tsx b/react-ui/src/pages/Points/index.tsx index 0fa3a1d8..19baa315 100644 --- a/react-ui/src/pages/Points/index.tsx +++ b/react-ui/src/pages/Points/index.tsx @@ -25,19 +25,19 @@ enum TaskType { const taskTypeOptions = [ { - value: 'dev_environment', + value: TaskType.DevEnvironment, label: '开发环境', }, { - value: 'workflow', + value: TaskType.Workflow, label: '实验', }, { - value: 'ray', + value: TaskType.Ray, label: '超参数自动寻优', }, { - value: 'service', + value: TaskType.Service, label: '服务', }, ]; diff --git a/react-ui/src/utils/constant.ts b/react-ui/src/utils/constant.ts index 4fe1ea9b..0ca0c423 100644 --- a/react-ui/src/utils/constant.ts +++ b/react-ui/src/utils/constant.ts @@ -1,3 +1,13 @@ -export const xlCols = { span: 12 }; -export const xllCols = { span: 10 }; +/* + * @Author: 赵伟 + * @Date: 2025-02-21 09:52:50 + * @Description: 通用表单项输入控件宽度 + */ + +const xlCols = { span: 12 }; +const xllCols = { span: 10 }; + +/** + * 输入控件宽度,xl: 12, xll: 10 + */ export const formCols = { xl: xlCols, xxl: xllCols }; diff --git a/react-ui/src/utils/date.ts b/react-ui/src/utils/date.ts index 33c8dda8..02734886 100644 --- a/react-ui/src/utils/date.ts +++ b/react-ui/src/utils/date.ts @@ -1,7 +1,7 @@ import dayjs from 'dayjs'; /** - * Calculates the elapsed time between two dates and returns a formatted string representing the duration. + * 计算两个日期之间经过的时间,如 "3分12秒" * * @param {string | null | undefined} begin - The starting date. * @param {string | null | undefined} end - The ending date. diff --git a/react-ui/src/utils/format.ts b/react-ui/src/utils/format.ts index 9c1d327d..32e7d7d4 100644 --- a/react-ui/src/utils/format.ts +++ b/react-ui/src/utils/format.ts @@ -1,3 +1,4 @@ +import { BasicInfoLink } from '@/components/BasicInfo/types'; import { ResourceSelectorResponse } from '@/components/ResourceSelectorModal'; import { ResourceInfoTabKeys } from '@/pages/Dataset/components/ResourceInfo'; import { @@ -18,8 +19,13 @@ type SelectedCodeConfig = { show_value?: string; // 后端使用的 }; -// 格式化数据集数组 -export const formatDatasets = (datasets?: DatasetData[]) => { +/** + * 格式化数据集数组 + * + * @param datasets - 数据集数组 + * @return 基本信息链接对象数组 + */ +export const formatDatasets = (datasets?: DatasetData[]): BasicInfoLink[] | undefined => { if (!datasets || datasets.length === 0) { return undefined; } @@ -29,8 +35,13 @@ export const formatDatasets = (datasets?: DatasetData[]) => { })); }; -// 格式化数据集 -export const formatDataset = (dataset?: DatasetData) => { +/** + * 格式化数据集 + * + * @param dataset - 数据集 + * @return 基本信息链接对象 + */ +export const formatDataset = (dataset?: DatasetData): BasicInfoLink | undefined => { if (!dataset) { return undefined; } @@ -40,8 +51,13 @@ export const formatDataset = (dataset?: DatasetData) => { }; }; -// 格式化模型 -export const formatModel = (model: ModelData) => { +/** + * 格式化模型 + * + * @param model - 模型 + * @return 基本信息链接对象 + */ +export const formatModel = (model: ModelData): BasicInfoLink | undefined => { if (!model) { return undefined; } @@ -51,16 +67,28 @@ export const formatModel = (model: ModelData) => { }; }; -// 格式化镜像 -export const formatMirror = (mirror: ResourceSelectorResponse) => { +/** + * 格式化镜像 + * + * @param mirror - 选择的镜像 + * @return 镜像地址 + */ +export const formatMirror = (mirror: ResourceSelectorResponse): string | undefined => { if (!mirror) { return undefined; } return mirror.path; }; -// 格式化代码配置 -export const formatCodeConfig = (project?: ProjectDependency | SelectedCodeConfig) => { +/** + * 格式化代码配置 + * + * @param project - 代码配置或者选择的代码配置 + * @return 基本信息链接对象 + */ +export const formatCodeConfig = ( + project?: ProjectDependency | SelectedCodeConfig, +): BasicInfoLink | undefined => { if (!project) { return undefined; } @@ -81,7 +109,12 @@ export const formatCodeConfig = (project?: ProjectDependency | SelectedCodeConfi } }; -// 格式化训练任务(实验实例) +/** + * 格式化训练任务(实验实例) + * + * @param task - 训练任务 + * @return 基本信息链接对象 + */ export const formatTrainTask = (task?: TrainTask) => { if (!task) { return undefined; @@ -92,8 +125,13 @@ export const formatTrainTask = (task?: TrainTask) => { }; }; -// 格式化数据来源 -export const formatSource = (source?: string) => { +/** + * 格式化数据来源 + * + * @param source - 数据来源枚举值 + * @return 数据来源中文名称 + */ +export const formatSource = (source?: string): string | undefined => { if (source === DataSource.Create) { return '用户上传'; } else if (source === DataSource.HandExport) { @@ -106,7 +144,12 @@ export const formatSource = (source?: string) => { return source; }; -// 格式化字符串数组,以逗号分隔 +/** + * 格式化字符串数组,以逗号分隔 + * + * @param value - 字符串数组 + * @return 字符串,以逗号分隔 + */ export const formatList = (value: string[] | null | undefined): string => { if ( value === undefined || @@ -119,14 +162,24 @@ export const formatList = (value: string[] | null | undefined): string => { return value.join(','); }; -// 格式化布尔值 +/** + * 格式化布尔值 + * + * @param value - 布尔值 + * @return true 为 "是",false 为 "否" + */ export const formatBoolean = (value: boolean): string => { return value ? '是' : '否'; }; type FormatEnumFunc = (value: string | number) => React.ReactNode; -// 格式化枚举 +/** + * 格式化枚举 + * + * @param options - 枚举选项数组 + * @return 一个函数,参数是枚举值,从选项数组中找到对应的项,然后返回该项的 label + */ export const formatEnum = ( options: { value?: string | number | null; label?: React.ReactNode }[], ): FormatEnumFunc => { diff --git a/react-ui/src/utils/localStorage.ts b/react-ui/src/utils/localStorage.ts index 4d224465..4c28251e 100644 --- a/react-ui/src/utils/localStorage.ts +++ b/react-ui/src/utils/localStorage.ts @@ -6,6 +6,11 @@ export default class LocalStorage { // 记住密码 static readonly rememberPasswordKey = 'login-remember-password'; + /** + * 获取 LocalStorage 值 + * @param key - LocalStorage key + * @param isObject - 是不是对象 + */ static getItem(key: string, isObject: boolean = false) { const jsonStr = localStorage.getItem(key); if (!isObject) { @@ -17,12 +22,21 @@ export default class LocalStorage { return null; } + /** + * 设置 LocalStorage 值 + * @param key - LocalStorage key + * @param isObject - 是不是对象 + */ static setItem(key: string, state?: any, isObject: boolean = false) { if (state) { localStorage.setItem(key, isObject ? JSON.stringify(state) : state); } } + /** + * 移除 LocalStorage 值 + * @param key - LocalStorage key + */ static removeItem(key: string) { localStorage.removeItem(key); } diff --git a/react-ui/src/utils/promise.ts b/react-ui/src/utils/promise.ts index 1919ecd1..7340e3bf 100644 --- a/react-ui/src/utils/promise.ts +++ b/react-ui/src/utils/promise.ts @@ -1,6 +1,7 @@ /** - * @param { Promise } promise - * @return { Promise } + * 封装 Promise,不会抛异常,resolve 的时候返回 [data, null], reject 的时候返回 [null, error] + * @param promise + * @return resolve 的时候返回 [data, null], reject 的时候返回 [null, error] */ export async function to(promise: Promise): Promise<[T, null] | [null, U]> { try { diff --git a/react-ui/src/utils/sessionStorage.ts b/react-ui/src/utils/sessionStorage.ts index 4a41e214..423d03a5 100644 --- a/react-ui/src/utils/sessionStorage.ts +++ b/react-ui/src/utils/sessionStorage.ts @@ -1,15 +1,20 @@ import { parseJsonText } from './index'; export default class SessionStorage { - // 用于新建镜像 + /** 用于新建镜像 */ static readonly mirrorNameKey = 'mirror-name'; - // 模型部署服务版本 + /** 模型部署服务版本 */ static readonly serviceVersionInfoKey = 'service-version-info'; - // 编辑器 url + /** 编辑器 url */ static readonly editorUrlKey = 'editor-url'; - // 客户端信息 + /** 客户端信息 */ static readonly clientInfoKey = 'client-info'; + /** + * 获取 SessionStorage 值 + * @param key - SessionStorage key + * @param isObject - 是不是对象 + */ static getItem(key: string, isObject: boolean = false) { const jsonStr = sessionStorage.getItem(key); if (!isObject) { @@ -21,12 +26,21 @@ export default class SessionStorage { return null; } + /** + * 设置 SessionStorage 值 + * @param key - SessionStorage key + * @param isObject - 是不是对象 + */ static setItem(key: string, state?: any, isObject: boolean = false) { if (state) { sessionStorage.setItem(key, isObject ? JSON.stringify(state) : state); } } + /** + * 移除 SessionStorage 值 + * @param key - SessionStorage key + */ static removeItem(key: string) { sessionStorage.removeItem(key); } diff --git a/react-ui/src/utils/statusTableCell.tsx b/react-ui/src/utils/statusTableCell.tsx index 8efa5803..265aa9c4 100644 --- a/react-ui/src/utils/statusTableCell.tsx +++ b/react-ui/src/utils/statusTableCell.tsx @@ -10,6 +10,10 @@ export type StatusInfo = { color?: string; }; +/** + * 通用的 Table 状态单元格 + * @param infos - 选项数组 + */ function statusTableCell(infos: StatusInfo[]) { return function (status?: string | number | null) { const info = infos.find((item) => item.value === status); diff --git a/react-ui/src/utils/table.tsx b/react-ui/src/utils/table.tsx index a26b719f..ac66967f 100644 --- a/react-ui/src/utils/table.tsx +++ b/react-ui/src/utils/table.tsx @@ -10,27 +10,44 @@ import { Tooltip, TooltipProps, Typography } from 'antd'; import dayjs from 'dayjs'; export enum TableCellValueType { + /** 序号 */ Index = 'Index', + /** 文本 */ Text = 'Text', + /** 日期 */ Date = 'Date', + /** 数组 */ Array = 'Array', + /** 链接 */ Link = 'Link', + /** 自定义 */ Custom = 'Custom', } export type TableCellValueOptions = { - page?: number; // 类型为 Index 时有效 - pageSize?: number; // 类型为 Index 时有效 - property?: string; // 类型为 Array 时有效 - dateFormat?: string; // 类型为 Date 时有效 - onClick?: (record: T, e: React.MouseEvent) => void; // 类型为 Link 时有效 - format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null; // 类型为 Custom 时有效 - copyable?: boolean; // 省略时是否可以复制 + /** 页数,类型为 Index 时有效 */ + page?: number; + /** 分页大小,类型为 Index 时有效 */ + pageSize?: number; + /** 取数组对象的哪个属性值,类型为 Array 时有效 */ + property?: string; + /** 日期格式,类型为 Date 时有效*/ + dateFormat?: string; + /** 链接点击回调,类型为 Link 时有效 */ + onClick?: (record: T, e: React.MouseEvent) => void; + /** 自定义函数,类型为 Custom 时有效*/ + format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null; + /** 省略时是否可以复制 */ + copyable?: boolean; }; type TableCellFormatter = (value: any | undefined | null) => string | undefined | null; -// 日期转换函数 +/** + * 日期转换函数 + * @param {string | undefined} dateFormat - 日期格式 + * @returns {TableCellFormatter} Table cell 渲染函数 + */ function formatDateText(dateFormat?: string): TableCellFormatter { return (value: any | undefined | null): ReturnType => { if (value === undefined || value === null || value === '') { @@ -45,7 +62,7 @@ function formatDateText(dateFormat?: string): TableCellFormatter { /** * 数组转换函数,将数组元素转换为字符串,用逗号分隔 - * @param {string} property 如果数组元素是对象,那么取数组元素的某个属性 + * @param {string} property - 如果数组元素是对象,那么取数组元素的某个属性 * @returns {TableCellFormatter} Table cell 渲染函数 */ function formatArray(property?: string): TableCellFormatter { @@ -65,6 +82,13 @@ function formatArray(property?: string): TableCellFormatter { }; } +/** + * Table cell render 函数 + * @param ellipsis - 是否省略 + * @param type - 类型 + * @param options - 选项 + * @returns React 节点 + */ function tableCellRender( ellipsis: boolean | TooltipProps | 'auto' = false, type: TableCellValueType = TableCellValueType.Text, diff --git a/react-ui/src/utils/ui.tsx b/react-ui/src/utils/ui.tsx index a5472bd5..f40fd576 100644 --- a/react-ui/src/utils/ui.tsx +++ b/react-ui/src/utils/ui.tsx @@ -25,7 +25,9 @@ type ModalConfirmProps = ModalFuncProps & { isDelete?: boolean; }; -// 自定义删除 Confirm 弹框 +/** + * 自定义 Confirm 弹框 + */ export function modalConfirm({ title, content, @@ -63,7 +65,7 @@ export function modalConfirm({ /** * 跳转到登录页 - * @param toHome 是否跳转到首页 + * @param toHome - 是否跳转到首页 */ export const gotoLoginPage = (toHome: boolean = true) => { const { pathname, search } = location; @@ -80,6 +82,9 @@ export const gotoLoginPage = (toHome: boolean = true) => { } }; +/** + * 跳转到 OAuth2 登录页 + */ export const gotoOAuth2 = () => { const clientInfo = SessionStorage.getItem(SessionStorage.clientInfoKey, true) as ClientInfo; if (clientInfo) { @@ -89,7 +94,10 @@ export const gotoOAuth2 = () => { } }; -// 从事件中获取上传文件列表,用于 Upload + Form 中 +/** + * 从事件中获取上传文件列表,用于 Upload + Form 中 + * @param e - 事件,包含文件列表 fileList + */ export const getFileListFromEvent = (e: any) => { const fileList: UploadFile[] = (Array.isArray(e) ? e : e?.fileList) || []; return fileList.map((item) => { @@ -137,7 +145,10 @@ export const validateUploadFiles = (files: UploadFile[], required: boolean = tru return !hasError; }; -// 限制上传文件类型 +/** + * 限制上传文件类型 + * @param type - 只允许上次的的文件类型 + */ export const limitUploadFileType = (type: string) => { return (file: UploadFile): boolean | string => { const acceptTypes = type.split(',').map((item) => item.trim()); @@ -153,12 +164,12 @@ export const limitUploadFileType = (type: string) => { /** * 删除 FormList 表单项,如果表单项没有值,则直接删除,否则弹出确认框 - * @param form From实例 - * @param listName FormList 的 name - * @param name FormList 的其中一项 - * @param remove FormList 的删除方法 - * @param fieldNames FormList 的子项名称数组 - * @param confirmTitle 弹出确认框的标题 + * @param form - From实例 + * @param listName - FormList 的 name + * @param name - FormList 的其中一项 + * @param remove - FormList 的删除方法 + * @param fieldNames - FormList 的子项名称数组 + * @param confirmTitle - 弹出确认框的标题 */ export const removeFormListItem = ( form: FormInstance, diff --git a/react-ui/typedoc.json b/react-ui/typedoc.json index 33384478..f9868f57 100644 --- a/react-ui/typedoc.json +++ b/react-ui/typedoc.json @@ -1,5 +1,5 @@ { - "entryPoints": ["./src/utils"], + "entryPoints": ["./src/utils", "./src/hooks"], "entryPointStrategy": "expand", "out": "docs", "excludePrivate": true, @@ -7,5 +7,14 @@ "excludeExternals": true, "includeVersion": true, "categorizeByGroup": true, + "skipErrorChecking": true, + "exclude": [ + "src/utils/formRules.ts", + "src/utils/loading.tsx", + "src/utils/menuRender.tsx", + "src/utils/IconUtil.ts", + "src/utils/permission.ts", + "src/utils/tree.ts" + ], "name": "工具类文档" }