chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -23,5 +23,5 @@ export enum FileItemStatus {
|
||||
Wait = 'wait',
|
||||
}
|
||||
|
||||
// 支持预览的图片类型
|
||||
// Image types that support preview
|
||||
export const PREVIEW_IMAGE_TYPE = ['jpg', 'jpeg', 'png', 'webp', 'svg'];
|
||||
|
||||
@@ -119,7 +119,7 @@ export const getIconByExtension = (extension: string) => {
|
||||
return fileIcon;
|
||||
};
|
||||
|
||||
/** 获取文件名后缀 */
|
||||
/** Get filename suffix */
|
||||
export function getFileExtension(name?: string) {
|
||||
if (!name) {
|
||||
return '';
|
||||
|
||||
@@ -155,13 +155,13 @@ export const FileUpload: React.FC<FileUploadProps> = props => {
|
||||
|
||||
const handleChange = useMemoizedFn(val => onChange?.(val));
|
||||
|
||||
// 当fileList更新时,触发onChange
|
||||
// When the fileList is updated, onChange is triggered.
|
||||
useUpdateEffect(() => {
|
||||
const newVal = getSubmitValue();
|
||||
handleChange?.(newVal);
|
||||
}, [fileList]);
|
||||
|
||||
// 当表单值更新时,同步到fileList
|
||||
// When the form value is updated, sync to fileList
|
||||
useEffect(() => {
|
||||
const val = getSubmitValue();
|
||||
if (val !== value) {
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
import type { FileItemStatus } from '../file-icon';
|
||||
|
||||
export interface FileItem extends File {
|
||||
// 唯一标识
|
||||
// unique identifier
|
||||
uid?: string;
|
||||
// 文件地址
|
||||
// File address
|
||||
url?: string;
|
||||
// 上传进度
|
||||
// upload progress
|
||||
percent?: number;
|
||||
// 校验信息
|
||||
// verification information
|
||||
validateMessage?: string;
|
||||
status?: FileItemStatus;
|
||||
[key: string]: any;
|
||||
|
||||
@@ -99,10 +99,10 @@ export const useUpload = (props?: UploadConfig) => {
|
||||
throw new CustomError('normal_error', 'no uri');
|
||||
}
|
||||
|
||||
// 上传完成,清空超时计时器
|
||||
// Upload complete, clear timeout timer
|
||||
clearTimeout(progressTimer);
|
||||
|
||||
// 加签uri,获得url
|
||||
// Add uri and get the url.
|
||||
const { url } = await workflowApi.SignImageURL(
|
||||
{
|
||||
uri,
|
||||
|
||||
@@ -30,9 +30,9 @@ interface UploadValidateRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
* @param bytes 文件大小
|
||||
* @param decimals 小数位数, 默认 2 位
|
||||
* Format file size
|
||||
* @param bytes file size
|
||||
* @Param decimals, default 2 digits
|
||||
* @example
|
||||
* formatBytes(1024); // 1KB
|
||||
* formatBytes('1024'); // 1KB
|
||||
@@ -50,7 +50,7 @@ export function formatBytes(bytes: number, decimals = 2) {
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}${sizes[i]}`;
|
||||
}
|
||||
|
||||
/** 文件大小校验 */
|
||||
/** file size verification */
|
||||
export const sizeValidate = (
|
||||
size: number,
|
||||
maxSize: number = MAX_FILE_SIZE,
|
||||
@@ -71,7 +71,7 @@ export interface ImageSizeRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片的宽高
|
||||
* Get the width and height of the image
|
||||
*/
|
||||
export async function getImageSize(
|
||||
file: FileItem,
|
||||
@@ -93,7 +93,7 @@ export async function getImageSize(
|
||||
});
|
||||
}
|
||||
|
||||
/** 图像宽高校验 */
|
||||
/** image width check */
|
||||
// eslint-disable-next-line complexity
|
||||
export const imageSizeValidate = async (
|
||||
file: FileItem,
|
||||
@@ -101,7 +101,7 @@ export const imageSizeValidate = async (
|
||||
): Promise<string | undefined> => {
|
||||
const { maxWidth, minWidth, maxHeight, minHeight, aspectRatio } = rule || {};
|
||||
|
||||
// 未定义时不校验
|
||||
// No validation when undefined
|
||||
if (isNil(maxWidth || minWidth || maxHeight || minHeight || aspectRatio)) {
|
||||
return;
|
||||
}
|
||||
@@ -145,7 +145,7 @@ export const acceptValidate = (fileName: string, accept?: string) => {
|
||||
const fileExtension = getFileExtension(fileName);
|
||||
const mimeType = mime.lookup(fileExtension);
|
||||
|
||||
// image/* 匹配所有的图片类型
|
||||
// Image/* matches all image types
|
||||
if (acceptList.includes('image/*') && mimeType?.startsWith?.('image/')) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* test run test form 布局的 FormItem
|
||||
* Test run test form layout FormItem
|
||||
*/
|
||||
import React, { type FC, type ReactNode, type PropsWithChildren } from 'react';
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import css from './full-input.module.less';
|
||||
export interface InnerFullInputProps {
|
||||
value?: string;
|
||||
disabled?: boolean;
|
||||
/** 是否可以展开,默认 true */
|
||||
/** Whether it can be expanded, the default is true. */
|
||||
expand?: boolean;
|
||||
className?: string;
|
||||
onChange: (v?: string) => void;
|
||||
@@ -66,7 +66,7 @@ const InnerFullInputAdapter: React.FC<FullInputProps> = ({
|
||||
const content = editorRef.current.getContent();
|
||||
const { markdown } = delta2md(content.deltas[0], content.deltas);
|
||||
/**
|
||||
* change 可能来自用户输入或者初始化,做一下 diff 来保证性能
|
||||
* Changes may come from user input or initialization, do a diff to ensure performance
|
||||
*/
|
||||
if (markdown !== innerValueRef.current) {
|
||||
innerValueRef.current = markdown;
|
||||
|
||||
@@ -36,11 +36,11 @@ export interface InputNumberV2Props {
|
||||
onChange?: (v?: string) => void;
|
||||
onBlur?: () => void;
|
||||
onFocus?: () => void;
|
||||
/** 整型 */
|
||||
/** integer */
|
||||
int?: boolean;
|
||||
}
|
||||
|
||||
/** 是否是合法的数字字符串 */
|
||||
/** Is it a legal numeric string? */
|
||||
function isValidNumber(str: string) {
|
||||
try {
|
||||
const value = new BigNumber(str);
|
||||
@@ -73,18 +73,18 @@ export const InputNumberV2Adapter: React.FC<InputNumberV2Props> = ({
|
||||
|
||||
const handleBlur = () => {
|
||||
if (props.value === '' || props.value === undefined) {
|
||||
/** 失焦时若值为空,则同时清空验证值 */
|
||||
/** If the value is empty when out of focus, the verification value is also cleared */
|
||||
verifiedRef.current = undefined;
|
||||
if (props.value === '') {
|
||||
// 如果是空字符串需要主动转换为 undefined
|
||||
// If it is an empty string, it needs to be actively converted to undefined.
|
||||
onChange?.(undefined);
|
||||
}
|
||||
} else {
|
||||
/** 失焦时若值不为空,则需要验证值的合法性 */
|
||||
/** If the value is not empty when out of focus, you need to verify the legitimacy of the value */
|
||||
/**
|
||||
* 1. 若值本身合法,则对值做格式化
|
||||
* 2. 若值不合法,则采纳最近一次的合法值
|
||||
* 3. 若都没有,则返回 undefined
|
||||
* 1. If the value itself is legal, format the value
|
||||
* 2. If the value is not legal, the most recent legal value is adopted
|
||||
* 3. If none, return undefined
|
||||
*/
|
||||
let next: undefined | string;
|
||||
const nextBig = normalizeNumber(props.value) || verifiedRef.current;
|
||||
@@ -116,7 +116,7 @@ export const InputNumberV2Adapter: React.FC<InputNumberV2Props> = ({
|
||||
onChange?.(next);
|
||||
};
|
||||
|
||||
/** 当值发生变化,需要把值同步到合法数字 */
|
||||
/** When the value changes, you need to synchronize the value to a legal number */
|
||||
useEffect(() => {
|
||||
if (props.value === '' || props.value === undefined) {
|
||||
verifiedRef.current = undefined;
|
||||
|
||||
@@ -22,7 +22,7 @@ export { FormPanelLayout } from './form-panel';
|
||||
export { TraceIconButton, BaseTestButton } from './test-button';
|
||||
export { ResizablePanel } from './resizable-panel';
|
||||
export { BasePanel } from './resizable-panel/base-panel';
|
||||
// 禁止直接导出 form-engine 避免 formily 包被打到首屏
|
||||
// Prohibit direct export of form-engine to avoid formily packages being hit to the first screen
|
||||
// export { FormCore } from './form-engine';
|
||||
export { NodeEventInfo } from './node-event-info';
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function useGetCurrentResult({
|
||||
const isNodeLogNeedAsync = true;
|
||||
const { batch, isBatch } = result || {};
|
||||
|
||||
// 反序列化获取所有遍历数组
|
||||
// Deserialize to get all iterated arrays
|
||||
const batchData: NodeResult[] = useMemo(() => {
|
||||
if (!isBatch) {
|
||||
return [];
|
||||
@@ -49,13 +49,13 @@ export default function useGetCurrentResult({
|
||||
}
|
||||
return {
|
||||
...i,
|
||||
/** batch 数据里面不包含该标记,手动增加 */
|
||||
/** The tag is not included in the batch data, and it is added manually. */
|
||||
isBatch: true,
|
||||
};
|
||||
});
|
||||
}, [isBatch, batch]);
|
||||
|
||||
// 当前执行日志(同步获取完整日志)
|
||||
// Current execution log (get full log synchronously)
|
||||
const current: NodeResult | undefined = useMemo(() => {
|
||||
if (!isBatch) {
|
||||
return result;
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 解析运行结果的组件
|
||||
* Components that parse run results
|
||||
*/
|
||||
export { LogDetail } from './log-detail';
|
||||
|
||||
@@ -52,9 +52,9 @@ export const LogDetail: React.FC<LogDetailProps> = ({
|
||||
onOpenWorkflowLink,
|
||||
}) => {
|
||||
const { isBatch, nodeId } = result;
|
||||
/** 从 0 开始 */
|
||||
/** Start from 0 */
|
||||
const [paging, setPaging] = useState(0);
|
||||
/** 只看错误 */
|
||||
/** Just look at the error. */
|
||||
const [onlyShowError, setOnlyShowError] = useState(false);
|
||||
|
||||
const { current, batchData } = useGetCurrentResult({
|
||||
@@ -73,14 +73,14 @@ export const LogDetail: React.FC<LogDetailProps> = ({
|
||||
|
||||
const { modal, open } = useMarkdownModal();
|
||||
|
||||
// 当分页数据发生变化,重新选中第一项
|
||||
// When the paging data changes, re-select the first item
|
||||
useLayoutEffect(() => {
|
||||
setPaging(0);
|
||||
}, [batchData]);
|
||||
|
||||
return (
|
||||
<div className={css['log-detail']}>
|
||||
{/* 分页 */}
|
||||
{/* paging */}
|
||||
{isBatch ? (
|
||||
<LogDetailPagination
|
||||
paging={paging}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { type NodeResult } from '@coze-workflow/base';
|
||||
|
||||
/**
|
||||
* log images 业务逻辑太重了,本期暂不抽
|
||||
* Log images business logic is too heavy, this period will not draw
|
||||
*/
|
||||
export type LogImages = React.FC<{
|
||||
testRunResult: NodeResult;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 批处理的分页器
|
||||
* Batch pager
|
||||
*/
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
|
||||
@@ -37,17 +37,17 @@ import s from './more-selector.module.less';
|
||||
|
||||
interface MoreSelectorProps {
|
||||
/**
|
||||
* 运行结果数组
|
||||
* Run result array
|
||||
*/
|
||||
data: (NodeResult | null)[];
|
||||
/** 当前选择索引 */
|
||||
/** current selection index */
|
||||
paging: number;
|
||||
fixedCount: number;
|
||||
|
||||
/** placeholder */
|
||||
placeholder: string;
|
||||
|
||||
/** 选择索引变更事件 */
|
||||
/** Select index change event */
|
||||
onChange: (p: number) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@ export const PageSelector: React.FC<PageSelectorProps> = ({
|
||||
data,
|
||||
onChange,
|
||||
}) => {
|
||||
// 固定展示的条目,最大为 10 条,不到 10 条按实际展示
|
||||
// Fixed display items, the maximum is 10, less than 10 items are displayed according to the actual display
|
||||
const fixedItems = useMemo(
|
||||
() => data.slice(0, fixedCount),
|
||||
[fixedCount, data],
|
||||
);
|
||||
const moreItems = useMemo(() => data.slice(fixedCount), [data]);
|
||||
|
||||
// 是否需要通过下拉框展示更多
|
||||
// Do you need to show more through the drop-down box?
|
||||
const hasMore = useMemo(() => data.length > fixedCount, [data, fixedCount]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,19 +28,19 @@ import styles from './base-panel.module.less';
|
||||
interface BasePanelProps {
|
||||
className?: string;
|
||||
/**
|
||||
* 面板头,不传不渲染
|
||||
* Panel header, no pass and no render
|
||||
*/
|
||||
header?: React.ReactNode;
|
||||
/**
|
||||
* 面板脚,不传不渲染
|
||||
* Panel foot, do not pass and do not render
|
||||
*/
|
||||
footer?: React.ReactNode;
|
||||
/**
|
||||
* 默认初始高度,不支持响应式
|
||||
* Default initial height, does not support responsive
|
||||
*/
|
||||
height?: number;
|
||||
/**
|
||||
* 是否可拖拽改变高度
|
||||
* Can you drag and drop to change the height?
|
||||
*/
|
||||
resizable?:
|
||||
| boolean
|
||||
@@ -49,7 +49,7 @@ interface BasePanelProps {
|
||||
max?: number;
|
||||
};
|
||||
/**
|
||||
* 点击关闭事件,仅当渲染面板头时可能触发
|
||||
* Click to close the event, which may only be triggered when rendering the panel header
|
||||
*/
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export interface ResizablePanelRef {
|
||||
const MIN_HEIGHT = 156;
|
||||
|
||||
/**
|
||||
* TODO: 这里的核心伸缩能力后面想换成 semi 的 Resizable,这里先临时写一些逻辑适配
|
||||
* TODO: The core telescopic ability here wants to be replaced by semi Resizable later. Here are some temporary logical adaptations.
|
||||
*/
|
||||
export const ResizablePanel = forwardRef<
|
||||
ResizablePanelRef,
|
||||
@@ -95,7 +95,7 @@ export const ResizablePanel = forwardRef<
|
||||
const handleMouseMove = useCallback(
|
||||
e => {
|
||||
if (isResizing.current) {
|
||||
const newHeight = startHeight.current - (e.clientY - startY.current); // 计算新的高度
|
||||
const newHeight = startHeight.current - (e.clientY - startY.current); // Calculate the new height
|
||||
setHeight(newHeight > MIN_HEIGHT ? newHeight : MIN_HEIGHT);
|
||||
}
|
||||
},
|
||||
@@ -103,17 +103,17 @@ export const ResizablePanel = forwardRef<
|
||||
);
|
||||
const handleMouseUp = useCallback(() => {
|
||||
isResizing.current = false;
|
||||
document.removeEventListener('mousemove', handleMouseMove); // 取消监听
|
||||
document.removeEventListener('mouseup', handleMouseUp); // 取消监听
|
||||
document.removeEventListener('mousemove', handleMouseMove); // Cancel listening
|
||||
document.removeEventListener('mouseup', handleMouseUp); // Cancel listening
|
||||
}, [handleMouseMove]);
|
||||
|
||||
const handleMouseDown = useCallback(
|
||||
e => {
|
||||
isResizing.current = true;
|
||||
startY.current = e.clientY; // 记录鼠标开始拖拽时的 Y 轴坐标
|
||||
startY.current = e.clientY; // Record the Y-axis coordinates when the mouse starts dragging
|
||||
startHeight.current = innerRef.current?.offsetHeight || 0;
|
||||
document.addEventListener('mousemove', handleMouseMove); // 监听鼠标移动事件
|
||||
document.addEventListener('mouseup', handleMouseUp); // 监听鼠标抬起事件
|
||||
document.addEventListener('mousemove', handleMouseMove); // Monitor mouse movement events
|
||||
document.addEventListener('mouseup', handleMouseUp); // Monitor mouse lift events
|
||||
},
|
||||
[handleMouseMove, handleMouseUp],
|
||||
);
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
.resizable-panel-slide {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: -100%; /* 初始位置在容器的右外侧 */
|
||||
right: -100%; /* The initial position is on the right outside of the container */
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
@@ -25,26 +25,26 @@ interface Config {
|
||||
}
|
||||
|
||||
/**
|
||||
* 目前仅支持高度可变
|
||||
* Currently only highly variable is supported
|
||||
*/
|
||||
export const useResize = (config: Config) => {
|
||||
const [dragging, setDragging] = useState(false);
|
||||
const [height, setHeight] = useState(config.default);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
/**
|
||||
* 拖拽过程中
|
||||
* Dragging process
|
||||
*/
|
||||
const resizing = useRef(false);
|
||||
/**
|
||||
* y 轴变化
|
||||
* Y-axis variation
|
||||
*/
|
||||
const startY = useRef(0);
|
||||
/** 开始位置 */
|
||||
/** starting position */
|
||||
const start = useRef(0);
|
||||
|
||||
const handleMouseMove = useMemoizedFn(e => {
|
||||
if (resizing.current) {
|
||||
const newHeight = start.current - (e.clientY - startY.current); // 计算新的高度
|
||||
const newHeight = start.current - (e.clientY - startY.current); // Calculate the new height
|
||||
if (config.max && newHeight > config.max) {
|
||||
setHeight(config.max);
|
||||
} else if (config.min && newHeight < config.min) {
|
||||
@@ -57,17 +57,17 @@ export const useResize = (config: Config) => {
|
||||
const handleMouseUp = useCallback(() => {
|
||||
resizing.current = false;
|
||||
setDragging(false);
|
||||
document.removeEventListener('mousemove', handleMouseMove); // 取消监听
|
||||
document.removeEventListener('mouseup', handleMouseUp); // 取消监听
|
||||
document.removeEventListener('mousemove', handleMouseMove); // Cancel listening
|
||||
document.removeEventListener('mouseup', handleMouseUp); // Cancel listening
|
||||
}, [handleMouseMove]);
|
||||
|
||||
const handleMouseDown = useMemoizedFn(e => {
|
||||
resizing.current = true;
|
||||
setDragging(true);
|
||||
startY.current = e.clientY; // 记录鼠标开始拖拽时的 Y 轴坐标
|
||||
startY.current = e.clientY; // Record the Y-axis coordinates when the mouse starts dragging
|
||||
start.current = ref.current?.offsetHeight || 0;
|
||||
document.addEventListener('mousemove', handleMouseMove); // 监听鼠标移动事件
|
||||
document.addEventListener('mouseup', handleMouseUp); // 监听鼠标抬起事件
|
||||
document.addEventListener('mousemove', handleMouseMove); // Monitor mouse movement events
|
||||
document.addEventListener('mouseup', handleMouseUp); // Monitor mouse lift events
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -132,7 +132,7 @@ export const ChatFlowTestsetEditForm: React.FC<TestsetEditFormProps> = ({
|
||||
ipt.value = val;
|
||||
}
|
||||
|
||||
// 清除 object/array的空值,包括空字符串
|
||||
// Clears null values of objects/arrays, including empty strings
|
||||
if (
|
||||
!val &&
|
||||
(ipt.type === FormItemSchemaType.LIST ||
|
||||
@@ -141,7 +141,7 @@ export const ChatFlowTestsetEditForm: React.FC<TestsetEditFormProps> = ({
|
||||
ipt.value = undefined;
|
||||
}
|
||||
|
||||
// bool 类型 需要将枚举转为布尔值
|
||||
// Bool type, you need to convert the enumeration to a boolean
|
||||
if (ipt.type === FormItemSchemaType.BOOLEAN) {
|
||||
ipt.value = transTestsetBoolSelect2Bool(
|
||||
ipt.value as TestsetFormValuesForBoolSelect,
|
||||
@@ -184,7 +184,7 @@ export const ChatFlowTestsetEditForm: React.FC<TestsetEditFormProps> = ({
|
||||
// });
|
||||
|
||||
// formRef.current?.setValues(formValues);
|
||||
// // 设置值之后再校验一次
|
||||
// //Check again after setting the value
|
||||
// formRef.current?.validate(validateFields);
|
||||
// },
|
||||
// [formRef],
|
||||
|
||||
@@ -48,10 +48,10 @@ import {
|
||||
|
||||
import styles from './edit-form-section.module.less';
|
||||
|
||||
/** 整数类型表单精度 */
|
||||
/** integer type form precision */
|
||||
const INTEGER_PRECISION = 0.1;
|
||||
|
||||
/** bot field name 固定值 */
|
||||
/** Bot field name fixed value */
|
||||
const BOT_FIELD_NAME = `${TESTSET_BOT_NAME}_${ComponentType.CozeVariableBot}`;
|
||||
|
||||
interface EditFormSectionTitleProps {
|
||||
@@ -62,7 +62,7 @@ const EditFormSectionTitle: React.FC<EditFormSectionTitleProps> = ({
|
||||
schema,
|
||||
}) => {
|
||||
const title = useMemo(() => {
|
||||
// 目前只有start和variable两种节点
|
||||
// Currently only two nodes are start and variable
|
||||
switch (schema.component_type) {
|
||||
case ComponentType.CozeStartNode:
|
||||
return I18n.t('workflow_testset_start_node');
|
||||
@@ -255,8 +255,8 @@ export const EditFormSection: React.FC<EditFormSectionProps> = ({
|
||||
|
||||
const botFieldValue = useFieldState(BOT_FIELD_NAME);
|
||||
|
||||
// 判断是否选择到了应用,只有选中应用才会回显对话组件。
|
||||
// 应用内直接默认选中应用,可以回显对话组件。
|
||||
// Determine whether the application is selected, and only the selected application will echo the dialog component.
|
||||
// The application is directly selected by default in the application, and the dialog component can be echoed.
|
||||
const isBotSelectProject =
|
||||
(botFieldValue?.value?.id &&
|
||||
botFieldValue?.value?.type === IntelligenceType.Project) ||
|
||||
@@ -272,7 +272,7 @@ export const EditFormSection: React.FC<EditFormSectionProps> = ({
|
||||
if (projectId && i.type === FormItemSchemaType.BOT) {
|
||||
return false;
|
||||
}
|
||||
// 对话组件只会在应用内存在
|
||||
// The dialog component will only exist within the app
|
||||
if (!isBotSelectProject && i.type === FormItemSchemaType.CHAT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ export const TestsetEditForm: React.FC<TestsetEditFormProps> = ({ data }) => {
|
||||
ipt.value = val;
|
||||
}
|
||||
|
||||
// 清除 object/array的空值,包括空字符串
|
||||
// Clears null values of objects/arrays, including empty strings
|
||||
if (
|
||||
!val &&
|
||||
(ipt.type === FormItemSchemaType.LIST ||
|
||||
@@ -158,7 +158,7 @@ export const TestsetEditForm: React.FC<TestsetEditFormProps> = ({ data }) => {
|
||||
ipt.value = undefined;
|
||||
}
|
||||
|
||||
// bool 类型 需要将枚举转为布尔值
|
||||
// Bool type, you need to convert the enumeration to a boolean
|
||||
if (ipt.type === FormItemSchemaType.BOOLEAN) {
|
||||
ipt.value = transTestsetBoolSelect2Bool(
|
||||
ipt.value as TestsetFormValuesForBoolSelect,
|
||||
@@ -201,7 +201,7 @@ export const TestsetEditForm: React.FC<TestsetEditFormProps> = ({ data }) => {
|
||||
});
|
||||
|
||||
formRef.current?.setValues(formValues);
|
||||
// 设置值之后再校验一次
|
||||
// Check again after setting the value
|
||||
formRef.current?.validate(validateFields);
|
||||
},
|
||||
[formRef],
|
||||
|
||||
@@ -31,7 +31,7 @@ function count(val: unknown) {
|
||||
return val ? `${val}`.length : 0;
|
||||
}
|
||||
|
||||
/** 需要后缀 & blur trim,扩展下原始的input */
|
||||
/** The suffix & blur trim is required to expand the original input */
|
||||
function InnerInput(props: InputProps) {
|
||||
const onBlur = (evt: FocusEvent<HTMLInputElement>) => {
|
||||
props.onChange?.(
|
||||
|
||||
@@ -46,7 +46,7 @@ export const useEditFormSchemas = (testset?: CaseDataDetail | null) => {
|
||||
[]) as NodeFormSchema[];
|
||||
|
||||
if (localSchemas.length) {
|
||||
// 编辑模式:比对本地和远程schema并尝试赋值
|
||||
// Edit schema: compare local and remote schemas and try to assign values
|
||||
const localSchemaMap: Record<string, FormItemSchema | undefined> = {};
|
||||
traverseTestsetNodeFormSchemas(
|
||||
localSchemas,
|
||||
@@ -66,7 +66,7 @@ export const useEditFormSchemas = (testset?: CaseDataDetail | null) => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 创建模式:赋默认值
|
||||
// Creation mode: assigns default values
|
||||
traverseTestsetNodeFormSchemas(remoteSchemas, (schema, ipt) => {
|
||||
assignTestsetFormDefaultValue(ipt);
|
||||
});
|
||||
|
||||
@@ -39,12 +39,12 @@ export interface TestsetManageState {
|
||||
projectId?: string;
|
||||
|
||||
/**
|
||||
* 校验缓存
|
||||
* check cache
|
||||
*/
|
||||
validateCache: ValidateSchemaResult;
|
||||
|
||||
/**
|
||||
* 编辑面板状态
|
||||
* Edit Panel Status
|
||||
*/
|
||||
editPanelVisible: boolean;
|
||||
editData: CaseDataDetail | null;
|
||||
@@ -52,28 +52,28 @@ export interface TestsetManageState {
|
||||
editPanelCloseState: boolean;
|
||||
|
||||
/**
|
||||
* 自动填充状态
|
||||
* autofill status
|
||||
*/
|
||||
generating: boolean;
|
||||
/**
|
||||
* 自定义渲染组件,暂时从外部传入,后续不要了
|
||||
* Custom rendering component, temporarily passed in from the outside, no more in the future
|
||||
*/
|
||||
formRenders: Partial<Record<FormItemSchemaType, NodeFormItem>>;
|
||||
}
|
||||
|
||||
export interface TestsetManageAction {
|
||||
/** 更新状态 */
|
||||
/** update status */
|
||||
patch: (s: Partial<TestsetManageState>) => void;
|
||||
/**
|
||||
* 校验 schema
|
||||
* Validation schema
|
||||
*/
|
||||
validateSchema: () => Promise<ValidateSchemaResult>;
|
||||
/**
|
||||
* 打开编辑面板
|
||||
* Open the editing panel
|
||||
*/
|
||||
openEditPanel: (data?: CaseDataDetail) => void;
|
||||
/**
|
||||
* 关闭编辑面板
|
||||
* Close the edit panel
|
||||
*/
|
||||
closeEditPanel: () => void;
|
||||
|
||||
@@ -164,7 +164,7 @@ export const TestsetManageProvider: React.FC<
|
||||
formRenders,
|
||||
children,
|
||||
}) => {
|
||||
// 只初始化一次
|
||||
// Initialize only once
|
||||
const storeRef = useRef<TestsetManageStore>(
|
||||
createTestsetManageState({
|
||||
bizCtx: {
|
||||
|
||||
@@ -68,7 +68,7 @@ export interface TestsetSelectAPI {
|
||||
|
||||
const DEBOUNCE_DELAY = 200;
|
||||
|
||||
/** option key, 更新 name、incompatible、input时都要重新渲染 */
|
||||
/** Option key, re-render when updating name, incompatible, input */
|
||||
function getOptionKey({ caseBase, schemaIncompatible }: CaseDataDetail) {
|
||||
return `${caseBase?.caseID}_${caseBase?.name}_${caseBase?.input}_${
|
||||
schemaIncompatible ? 0 : 1
|
||||
@@ -139,7 +139,7 @@ export const TestsetSelect = forwardRef<TestsetSelectAPI, TestsetSelectProps>(
|
||||
}
|
||||
|
||||
const selectedTestset = optionsCacheRef.current.get(val);
|
||||
// 不兼容的不可选中
|
||||
// Incompatible unselectable
|
||||
if (!selectedTestset || selectedTestset.schemaIncompatible) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ export function useTestsetOptions() {
|
||||
const [loadingMore, setLoadingMore] = useState(false);
|
||||
const [optionsData, setOptionsData] = useState<OptionsData>({ list: [] });
|
||||
|
||||
// options 实时
|
||||
// Options in real time
|
||||
const optionsDataRef = useRef(optionsData);
|
||||
// options 缓存
|
||||
// Options cache
|
||||
const optionsCacheRef = useRef(new Map<Int64, CaseDataDetail>());
|
||||
|
||||
const setOptionsDataWithCache = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user