chore: replace all cn comments of fe to en version by volc api (#320)

This commit is contained in:
tecvan
2025-07-31 10:32:15 +08:00
committed by GitHub
parent 716ec0cba8
commit 71f6245a01
2960 changed files with 15545 additions and 15545 deletions

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ContentType, useSendTextMessage } from '@coze-common/chat-area';
import { sendTeaEvent, EVENT_NAMES } from '@coze-arch/bot-tea';
import { type ShortCutCommand } from '@coze-agent-ide/tool-config';
@@ -188,7 +188,7 @@ describe('useSendUseToolMessage', () => {
work_flow_id: '',
};
const componentsFormValues = { news: '查询北京news' };
// @ts-expect-error --单测忽略
// @ts-expect-error -- single test ignored
sendUseToolMessage({ shortcut, componentsFormValues });
expect(sendMultimodalMessage).toHaveBeenCalled();
expect(sendTeaEvent).toHaveBeenCalledWith(EVENT_NAMES.shortcut_use, {
@@ -237,7 +237,7 @@ describe('getTemplateQuery', () => {
work_flow_id: '',
};
const componentsFormValues = { news: '北京新闻' };
// @ts-expect-error --单测忽略
// @ts-expect-error -- single test ignored
const result = getTemplateQuery(shortcut, componentsFormValues);
expect(result).toBe('查询北京新闻');
});
@@ -278,7 +278,7 @@ describe('getTemplateQuery', () => {
work_flow_id: '',
};
const componentsFormValues = { news: '北京新闻' };
// @ts-expect-error --单测忽略
// @ts-expect-error -- single test ignored
expect(() => getTemplateQuery(shortcut, componentsFormValues)).toThrowError(
'template_query is not defined',
);

View File

@@ -70,7 +70,7 @@ describe('initToolInfoByToolApi', () => {
const result = initToolInfoByToolApi(plugin);
expect(result?.tool_params_list.length).toBe(MAX_TOOL_PARAMS_COUNT + 2);
// 前10个是required=true的参数
// The first 10 parameters are required = true
expect(
result?.tool_params_list
.slice(0, MAX_TOOL_PARAMS_COUNT)

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
InputType,
// eslint-disable-next-line camelcase
@@ -136,7 +136,7 @@ describe('getSubmitFieldFromComponentTypeForm', () => {
});
it('returns TextInput type for unrecognized type', () => {
// @ts-expect-error -- 无视
// @ts-expect-error -- ignore
const values: ComponentTypeItem = { type: 'unknown' };
const result = getSubmitFieldFromComponentTypeForm(values);
expect(result).toEqual({ input_type: InputType.TextInput });

View File

@@ -138,7 +138,7 @@ export const LoadMoreList = <TData extends object>(
onSelect?.(item);
}}
onMouseEnter={() => {
// 鼠标位于滚动条中,会触发该事件,设置仅在移动鼠标过程中进行更新
// The mouse is in the scroll bar, which triggers the event, and the settings are only updated during mouse movement
if (mouseMovingRef.current) {
focusTo(item);
listRef.current?.focus();

View File

@@ -30,7 +30,7 @@ export const DSLForm: DSLComponent = ({
const formRef = useRef<FormApi>();
/**
* text类型组件交互 支持 placeholder 表示默认值
* Text type component interaction, support placeholder to represent default value
* @param formValues
*/
const onSubmitWrap = (formValues: FormValue) => {

View File

@@ -24,7 +24,7 @@ import { DSLPlaceholer } from './placeholder';
import { DSLColumnLayout } from './layout';
import { DSLForm } from './form';
// 组件参数是在运行时决定,无法具体做类型约束
// Component parameters are determined at run time and cannot be subject to specific type constraints
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const DSLWidgetsMap: Record<string, DSLComponent<any>> = {
'@flowpd/cici-components/Input': DSLFormInput,

View File

@@ -16,7 +16,7 @@
import type { FC, PropsWithChildren } from 'react';
// 本期不需要不支持复布局解析
// This issue does not need to support multiple layout analysis
export const DSLColumnLayout: FC<PropsWithChildren> = ({ children }) => (
<div className="flex items-center justify-between w-full mb-3 gap-2">
{children}

View File

@@ -25,7 +25,7 @@ const parseRules = (rules: RuleItem[]): RuleItem[] =>
if (rule.required) {
return {
...rule,
// required 情况下,禁止输入空格
// Do not enter spaces if required
validator: (r, v) => !!v?.trim(),
};
}

View File

@@ -40,9 +40,9 @@ export type TCustomUpload = (uploadParams: {
export interface DSLContext {
dsl: DSL;
uploadFile?: TCustomUpload;
onChange?: (value: Record<string, TValue>) => void; // 需要兼容 file
onChange?: (value: Record<string, TValue>) => void; // Compatible files required
onSubmit?: (value: Record<string, TValue>) => void;
readonly?: boolean; // 支持搭建时的预览模式
readonly?: boolean; // Support preview mode during build
}
export interface DSLFormFieldCommonProps {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type FC, useState, useRef, useEffect } from 'react';
import classnames from 'classnames';
@@ -72,7 +72,7 @@ const UploadContent: FC<{
},
)}
style={{
// @ts-expect-error ts 无法识别自定义变量
// @ts-expect-error ts cannot recognize custom variable
'--var-percent': `${file.percent}%`,
}}
>
@@ -152,7 +152,7 @@ const FileUpload: FC<
percent: 0,
status: 'uploading',
});
// 立即清理错误状态
// Immediately clean up the error state
fieldApi.setError(true);
uidRef.current = newFile?.uid;
uploadFile?.({
@@ -188,7 +188,7 @@ const FileUpload: FC<
if (uidRef.current !== newFile.uid) {
return;
}
// 上传失败,触发错误状态
// Upload failed, error status triggered
fieldApi.setError(false);
setFile({
...newFile,
@@ -221,13 +221,13 @@ const FileUpload: FC<
}
}}
customRequest={({ onSuccess }) => {
// 即使 action="" ,在不传 customRequest 仍然会触发一次向当前 URL 上传文件的请求
// 这里传一个 mock customRequest 来阻止 semi 默认的上传行为
// Even if action = ", a request to upload a file to the current URL will still be triggered without customRequest
// Here is a mock customRequest to prevent semi default upload behavior
onSuccess('');
}}
showUploadList={false}
onChange={({ currentFile }) => {
// semi 同一个文件会触发多次 onChange这里只响应首个
// Semi The same file will trigger multiple onChanges, only the first one is responded here
if (
uidRef.current !== currentFile.uid &&
(!props.maxSize ||
@@ -247,7 +247,7 @@ const FileUpload: FC<
setFile(undefined);
onChange?.('');
setTimeout(() => {
// 删除文件,清理错误状态避免立刻飘红
// Delete files, clean up error states to avoid immediate redness
fieldApi.setError(true);
});
}}
@@ -295,17 +295,17 @@ const FileInput: FC<
</>
);
// 为了方便控制向外传递的 value
// To facilitate control of the value passed outward
const UploadInner = withField((props: UploadProps) => {
const [showInput, setShowInput] = useState(false);
const hasError = props.validateStatus === 'error';
const fieldApi = useFieldApi(props.name);
// 避免清空输入导致的飘红
// Avoid flushing red caused by empty input
useEffect(() => {
setTimeout(() => {
props.onChange?.('');
// 避免 onchange 触发校验导致立刻飘红
// Avoid onchange triggering verification and causing immediate redness
setTimeout(() => {
fieldApi.setError(true);
});

View File

@@ -126,7 +126,7 @@ export const useSendUseToolMessage = () => {
shortcut,
componentsFormValues,
/**
* 无参数调用 store 场景下没有 componentList
* Calling store without parameters does not have a pixentList
*/
withoutComponentsList,
);
@@ -145,9 +145,9 @@ export const useSendUseToolMessage = () => {
mixList: [
{
type: ContentType.Text,
// TODO 需要看下是否能够优化
// TODO needs to see if it can be optimized.
/**
* 防止发送空消息(没有对话的气泡框) => 使用空格占位
* Prevent sending empty messages (no dialog bubble box) = > Use spaces to occupy space
*/
text: sendQuery || ' ',
},
@@ -219,7 +219,7 @@ const getPluginParams = (
}),
);
// key: components_list中的parameter属性 valuevalues中对应的值 | default_value
// The parameter attribute value in key: components_list: the corresponding value in values | default_value
const runPluginVariables = (tool_params_list ?? []).reduce<
Record<string, ToolParamValue>
>((acc, cur) => {
@@ -271,7 +271,7 @@ const getPluginDefaultParams = (shortcut: ShortCutCommand) => {
tool_info: { tool_params_list } = {},
} = shortcut;
// key: components_list中的parameter属性 valuevalues中对应的值 | default_value
// The parameter attribute value in key: components_list: the corresponding value in values | default_value
const runPluginVariables = (tool_params_list ?? []).reduce<
Record<string, ToolParamValue>
>((acc, cur) => {
@@ -309,7 +309,7 @@ export const getTemplateQuery = (
if (!template_query) {
throw new Error('template_query is not defined');
}
// 处理图片文件
// Processing image files
const componentListValue = getComponentListValue(
components_list,
componentsFormValues,
@@ -330,12 +330,12 @@ const filterComponentFormValues = (
Object.keys(componentsFormValues).reduce<Record<string, unknown>>(
(acc, cur) => {
const value = componentsFormValues[cur];
// 文件类型
// file type
if (typeof value === 'object' && value.fileInstance) {
acc[cur] = setImageAndFileValue(value);
return acc;
}
// 普通文本类型
// plain text type
acc[cur] = setTextValue(value as string);
return acc;
},
@@ -388,7 +388,7 @@ const isComponentImage = (
getFileInfo(value.fileInstance)?.fileType === 'image',
);
// 获取component_listvalue, 带上默认值
// Get component_list value with default value
export const getComponentListValue = (
componentsList: ShortCutCommand['components_list'],
componentsFormValues: Record<string, TValue>,
@@ -399,7 +399,7 @@ export const getComponentListValue = (
value => value,
);
// key: components_list中的parameter属性 valuevalues中对应的值 | default_value
// The parameter attribute value in key: components_list: the corresponding value in values | default_value
return (componentsList ?? []).reduce<Record<string, string>>((acc, cur) => {
const { default_value, name, hide } = cur;
if (!name) {

View File

@@ -32,7 +32,7 @@ export const useImperativeLayoutEffect = <Params extends unknown[]>(
if (!effectValue) {
return;
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- 体操不动, 凑活用吧
// eslint-disable-next-line @typescript-eslint/ban-ts-comment -- gymnastics don't move, let's make a living
// @ts-expect-error
const params = paramRef.current || ([] as Params);
return effectRef.current(...params);

View File

@@ -20,15 +20,15 @@ import {
} from '@coze-common/chat-core';
import { useGetRegisteredPlugin } from '@coze-common/chat-area';
// 延迟1.5s后开始模拟上传进度
// Start simulating upload progress after 1.5s delay
const FAKE_PROGRESS_START_DELAY = 1500;
// fake progress 初始进度
// Fake progress initial progress
const FAKE_PROGRESS_START = 50;
// 最大进度
// maximum progress
const FAKE_PROGRESS_MAX = 85;
// 每次步进值
// value per step
const FAKE_PROGRESS_STEP = 5;
// 循环间隔
// Cycle interval
const FAKE_PROGRESS_INTERVAL = 100;
export const useGetUploadPluginInstance = () => {
@@ -55,7 +55,7 @@ export const useGetUploadPluginInstance = () => {
file,
type: getFileInfo(file)?.fileType === 'image' ? 'image' : 'object',
});
// 如果1s内上传进度没有变化主动触发fake progress, 500ms内从50%上升到80%,忽略后续的真实进度
// If the upload progress does not change within 1s, actively trigger fake progress, increase from 50% to 80% within 500ms, ignoring the subsequent real progress
let isStartFakeProgress = false;
let fakeProgressTimer: number | undefined;
let fakeProgress = FAKE_PROGRESS_START;
@@ -82,7 +82,7 @@ export const useGetUploadPluginInstance = () => {
isStartFakeProgress = false;
}
uploader.on('progress', ({ percent }) => {
// 有假进度,忽略后续的真实进度
// There is a fake progress, ignore the subsequent real progress.
if (isStartFakeProgress) {
return;
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
// !Notice 禁止直接导出 shortcut-tool会导致下游依赖不需要的 knowledge-upload
// ! Notice prohibits direct export of shortcut-tool, causing downstream dependencies on unwanted knowledge-uploads
// export { ShortcutToolConfig } from './shortcut-tool';
export { ShortcutBar } from './shortcut-bar';

View File

@@ -13,8 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 快捷指令操作bar
// Quick command bar
import { type CSSProperties, type FC, useRef, useState } from 'react';
import cls from 'classnames';
@@ -48,7 +48,7 @@ interface ChatShortCutBarProps {
) => void;
className?: string;
wrapperClassName?: string;
uiMode?: UIMode; // 默认为白色,有背景的时候为模糊
uiMode?: UIMode; // The default is white, and it is blurred when there is a background.
defaultId?: string;
wrapperStyle?: CSSProperties;
toolTipFooterSlot?: React.ReactNode;
@@ -100,8 +100,8 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
const shortcutClick = (shortcut: ShortCutCommand) => {
/**
* send_type=SendTypePanel components_list hide均为true
* 直接发送
* send_type = SendTypePanel and components_list hide is true
* send directly
*/
const hideTemplate = enableSendTypePanelHideTemplate(shortcut);
@@ -174,7 +174,7 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
};
/**
* sendType=panel 支持不展示组件直接发送
* sendType = panel supports sending directly without displaying components
*/
const onShortcutTemplateNoParamsSubmit = (
componentsFormValues: Record<string, TValue>,
@@ -186,7 +186,7 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
const { agent_id, object_id, components_list, tool_info } = shortcut;
/**
* sendType=panel,useTool=true 无参数直接发送
* sendType = panel, useTool = true Send directly without parameters
*/
const withoutComponentsList =
!!tool_info?.tool_name && !components_list?.length;
@@ -270,7 +270,7 @@ export const ShortcutBar: FC<ChatShortCutBarProps> = props => {
}}
minVisibleItems={1}
items={shortcuts}
// @ts-expect-error visibleItemRenderer 有问题
// @ts-expect-error visibleItemRenderer has a problem
visibleItemRenderer={renderShortcut}
overflowRenderer={overflowItems => {
if (!overflowItems.length) {

View File

@@ -22,11 +22,11 @@ import {
} from '@coze-common/chat-core';
export interface ChatShortCutBarProps {
shortcuts: ShortCutCommand[]; // 目前支持两种快捷键
shortcuts: ShortCutCommand[]; // Currently supports two shortcuts
onClickShortCut: (shortcutInfo: ShortCutCommand) => void;
}
// 更新后 home white 调试区、商店为 grey
export type UIMode = 'grey' | 'white' | 'blur'; // 默认为白色,有背景的时候为模糊
// After the update, the home is white debugging area and the store is grey.
export type UIMode = 'grey' | 'white' | 'blur'; // The default is white, and it is blurred when there is a background.
export interface OnBeforeSendTemplateShortcutParams {
message: TextAndFileMixMessageProps;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
// 快捷指令换起的模板组件
// Template component for shortcut command replacement
import { type FC, useMemo, useRef } from 'react';
import { type ShortCutCommand } from '@coze-agent-ide/tool-config';

View File

@@ -14,5 +14,5 @@
* limitations under the License.
*/
// 快捷指令在IDE中的配置tool
// Quick instructions in the IDE configuration tool
export { ShortcutToolConfig } from './shortcut-config';

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
// 快捷指令在IDE中的配置tool
// Quick instructions in the IDE configuration tool
import React, { type FC, useState } from 'react';
import { useShallow } from 'zustand/react/shallow';
@@ -85,7 +85,7 @@ export const ShortcutToolConfig: FC<ShortcutToolConfigProps> = props => {
const getSpaceId = useSpaceStore(state => state.getSpaceId);
const setHasValidData = useToolValidData();
// single不展示指定agent的快捷指令
// Single command that does not show the specified agent
const singleShortcuts = initShortcuts?.filter(shortcut => !shortcut.agent_id);
const shortcuts =
botMode === BotMode.SingleMode ? singleShortcuts : initShortcuts;
@@ -174,7 +174,7 @@ export const ShortcutToolConfig: FC<ShortcutToolConfigProps> = props => {
},
{ __disableErrorToast: true },
);
// TODO: hzf 得加上
// TODO: hzf has to be added
// if (res && res.data?.check_not_pass) {
// Toast.error(I18n.t('shortcut_modal_illegal_keyword_detected_error'));
// onFail();
@@ -214,7 +214,7 @@ export const ShortcutToolConfig: FC<ShortcutToolConfigProps> = props => {
{ __disableErrorToast: true },
);
const strictShortcuts = newShortcut && getStrictShortcuts([newShortcut]);
// 一次只能添加一个快捷指令
// Only one shortcut can be added at a time
const strictShortcut = strictShortcuts?.[0];
if (!strictShortcut) {
Toast.error('Please fill in the required fields');

View File

@@ -54,7 +54,7 @@ export const ShortcutItem: FC<ShortcutItemProps> = ({
useEffect(() => {
connect(dropRef, dragRef);
}, [dragRef, dropRef]);
// 点击删除,弹出二次确认弹窗
// Click Delete to pop up the secondary confirmation pop-up window.
const openConfirmRemoveModal = () => {
UIModal.info({
title: I18n.t('bot_ide_shortcut_removal_confirm'),

View File

@@ -113,10 +113,10 @@ export const ActionSwitchArea = forwardRef<
tool_params_list = [],
} = toolInfo || {};
const newComponents = initComponentsByToolParams(tool_params_list);
// TODO: hzf, 有点复杂,看看可以initValue
// TODO: hzf, it's a bit complicated, let's see if it can initValue
formRef.current?.formApi.setValue('components_list', newComponents);
setComponents(newComponents);
// 只有这种情况需要手动更新数据
// Only in this case do you need to manually update the data
componentsRef.current?.formApi?.setValues(newComponents);
formRef.current?.formApi.setValue('tool_type', tool_type);

View File

@@ -39,7 +39,7 @@ export const initComponentsByToolParams = (
};
});
// 获取没有被使用的组件
// Get unused components
export const getUnusedComponents = (
shortcut: ShortcutEditFormValues,
): shortcut_command.Components[] => {

View File

@@ -14,16 +14,16 @@
* limitations under the License.
*/
// format选择的插件参数列表
// Format selected plugin parameter list
import { type WorkFlowItemType } from '@coze-studio/bot-detail-store';
import { type PluginApi, ToolType } from '@coze-arch/bot-api/playground_api';
import { type ToolInfo } from '../../../types';
// 最多勾选10个如果入参数量超过10个仅勾选其中10个优先勾选required参数勾满10个时其他checkbox置灰不可继续勾选。
// Check up to 10 parameters. If the number of input parameters exceeds 10, only 10 of them will be checked, and the required parameters will be selected first; when 10 parameters are checked, other checkboxes out grey cannot be checked.
export const MAX_TOOL_PARAMS_COUNT = 10;
// 初始化工具列表参数
// Initialization tool list parameters
export const initToolInfoByToolApi = (
toolApi?: WorkFlowItemType | PluginApi,
): ToolInfo | null => {
@@ -38,7 +38,7 @@ export const initToolInfoByToolApi = (
const { tool_params_list } = workflowPluginProcessedToolInfo;
// params进行排序,将required=true的字段排在前面
// Sort params to rank fields with required = true first
const sortedParams = tool_params_list?.sort(
(a, b) => (b.required ? 1 : -1) - (a.required ? 1 : -1),
);
@@ -60,7 +60,7 @@ export const initToolInfoByToolApi = (
};
};
// workflow参数转化为toolParams
// Convert workflow parameters to toolParams
export const initToolInfoByWorkFlow = (
workFlow: WorkFlowItemType,
): ToolInfo => {
@@ -86,7 +86,7 @@ export const initToolInfoByPlugin = (plugin: PluginApi): ToolInfo => {
};
};
// 获取skillModal开启的tab
// Get tabs opened by skillModal
export const getSkillModalTab = (): (
| 'plugin'
| 'workflow'

View File

@@ -53,7 +53,7 @@ export const ButtonName: FC<ButtonNameProps> = props => {
noLabel
fieldClassName="!pb-0"
onLoadList={list => {
// 如果是编辑状态不设置默认icon, 新增下默认选中列表第一个icon
// If it is an editing state, do not set the default icon, and add the first icon in the default selected list.
const isEdit = !!editedShortcut.command_id;
if (isEdit) {
return;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type FC, useState } from 'react';
import cls from 'classnames';
@@ -107,7 +107,7 @@ export const IconListField = () => (
<div className="flex justify-center items-center flex-col w-[420px] h-[148px]">
<IconCozWarningCircle className="mb-4 w-8 h-8 coz-fg-hglt-red" />
<div className="coz-fg-secondary text-xs">
{/*@ts-expect-error --替换*/}
{/* @ts-expect-error -- replace*/}
{I18n.t('Connection failed')}
</div>
</div>

View File

@@ -86,7 +86,7 @@ export const ComponentDefaultValue: FC<ComponentDefaultValueProps> = props => {
);
}
if (type === 'upload') {
// 先置灰,后续放开上传默认值
// Grey out first, then release the upload default value.
return <UploadField />;
// return (
// <UploadDefaultValue

View File

@@ -67,13 +67,13 @@ export const getInputTypeFromFile = (file: File): UploadItemType | '' => {
return getInputTypeFromFileType(fileType);
};
// 判断文件是否超过最大限制
// Determine whether the file exceeds the maximum limit
export const isOverMaxSizeByUploadItemConfig = (
file: File | undefined,
config: UploadItemConfig | undefined,
): {
isOverSize: boolean;
// 单位 MB
// Unit MB
maxSize?: number;
} => {
if (!file) {
@@ -104,7 +104,7 @@ export const isOverMaxSizeByUploadItemConfig = (
};
};
// 根据acceptUploadItemTypes获取accept
// Accept based on acceptUploadItemTypes
export const getAcceptByUploadItemTypes = (
acceptUploadItemTypes: UploadItemType[],
) => {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { DndProvider } from '@coze-studio/components/dnd-provider';
@@ -45,7 +45,7 @@ import { tableEmpty } from './empty';
import styles from './index.module.less';
export interface ComponentsTableProps {
components: shortcut_command.Components[]; // 变量列表
components: shortcut_command.Components[]; // Variable list
onChange?: (components: shortcut_command.Components[]) => void;
toolType?: shortcut_command.ToolType;
toolInfo: ToolInfo;
@@ -59,7 +59,7 @@ export interface ComponentsTableActions {
const MAX_COMPONENTS = 10;
// 半受控组件,使用初始值 + 暴露 API 的方式,方便内部维护本地 id 用于拖拽排序标识数据
// Semi-controlled component, using initial value + exposed API to facilitate internal maintenance of local ID for dragging and dropping sorting identification data
export const ComponentsTable = forwardRef<
{ formApi?: ComponentsTableActions },
ComponentsTableProps
@@ -80,7 +80,7 @@ export const ComponentsTable = forwardRef<
formApi: formRef.current
? {
validate: async (...props) => {
// 在这里统一处理,避免多个相同字段触发多次 toast
// It is handled uniformly here to avoid multiple identical fields triggering multiple toasts.
if (
values.some(
component =>
@@ -128,10 +128,10 @@ export const ComponentsTable = forwardRef<
(isBefore ? 0 : 1);
sourceItem && newValues.splice(targetIndex, 0, sourceItem);
errors.splice(targetIndex, 0, sourceError);
// 前后 index 相同的情况不触发 onChange 避免频繁 rerender
// Do not trigger onChange if the index is the same before and after to avoid frequent rerender
if (sourceIndex !== targetIndex) {
onChangeInner(newValues);
// 只在拖拽排序后,需要手动更新 form value
// Only after dragging sort, you need to manually update the form value
formRef.current?.setValues(
{
values: newValues,
@@ -190,7 +190,7 @@ export const ComponentsTable = forwardRef<
<DndProvider>
<Form<{ values: ComponentsWithId[] }>
initValues={{ values }}
// 手动触发校验,避免受增删和拖拽排序影响
// Manually trigger validation to avoid being affected by addition, deletion and drag-and-drop sorting
trigger="custom"
autoComplete="off"
disabled={disabled}
@@ -199,16 +199,16 @@ export const ComponentsTable = forwardRef<
const changedKeys = Object.keys(changedValues);
if (
changedKeys.length === 1 &&
// 只在表单修改场景下触发 onChange 避免无限循环
// Trigger onChange only in form modification scenarios to avoid infinite loops
changedKeys[0]?.startsWith('values.[')
) {
onChangeInner([...newValues.values]);
// 只在编辑表单场景下对具体字段触发校验,其它场景(整行的增删排序)不触发校验
// Validation is only triggered for specific fields in the edit form scenario, and verification is not triggered in other scenarios (addition and deletion sorting of entire lines)
setTimeout(() => {
if (formRef.current) {
checkDuplicateName(newValues.values, formRef.current);
}
// @ts-expect-error semi 的类型定义无法支持多段 path
// @ts-expect-error -- The type definition of semi cannot support multi-segment paths
formRef.current?.validate([changedKeys[0]]);
});
}

View File

@@ -58,7 +58,7 @@ export const checkDuplicateName = (
}
});
setTimeout(() => {
// 避免修改后立刻被 field 自己的校验状态覆盖
// Avoid being overwritten by the field's own check state immediately after modification
Object.entries(fieldMap).forEach(([name, indexArray]) => {
const isDuplicated = indexArray.length > 1;
indexArray.forEach(index => {
@@ -81,7 +81,7 @@ export const getComponentTypeSelectFormInitValues = (): ComponentTypeItem => ({
type: 'text',
});
// 定义一个映射对象,将ComponentTypeItemtype映射到对应的input_type和其他字段
// Define a mapping object that maps the ComponentTypeItem type to the corresponding input_type and other fields
const componentTypeHandlers = {
text: () => ({ input_type: InputType.TextInput }),
select: (value: ComponentTypeItem) => {
@@ -126,11 +126,11 @@ export const getSubmitFieldFromComponentTypeForm = (
return result;
}
// 如果没有找到处理函数,就返回默认值
// If no handler is found, the default value is returned
return { input_type: InputType.TextInput };
};
// 是否是上传类型
// Is it the upload type?
export const isUploadType = (
type: InputType,
): type is
@@ -157,7 +157,7 @@ export const isUploadType = (
InputType.MixUpload,
].includes(type);
// input_type映射到对应的处理函数
// Map input_type to the corresponding handler
const inputTypeHandlers = {
[InputType.TextInput]: () => ({ type: 'text' }),
[InputType.Select]: (options: string[] = []) => ({
@@ -194,7 +194,7 @@ export const getComponentTypeFormBySubmitField = (
};
/**
* 1. 修改components列表中对应组件的hidetrue
* 1. Modify the hide of the corresponding component in the components list: true
*/
export const modifyComponentWhenSwitchChange = ({
components,
@@ -215,7 +215,7 @@ export const modifyComponentWhenSwitchChange = ({
return item;
});
// components switch是否disable
// Components switching disabled
export const isSwitchDisabled = ({
components,
record,
@@ -233,17 +233,17 @@ export const isSwitchDisabled = ({
}
/**
* 使用工具&为必填参数
* Use tools & required parameters
*/
return !!toolInfo?.tool_params_list?.find(t => t.name === record.parameter)
?.required;
})();
// 组件超过最大数量, 不允许开启
// Components exceed the maximum number and are not allowed to be opened
const isMaxCount =
record.hide && components.filter(com => !com.hide).length >= MAX_COMPONENTS;
/** 必填且没有默认值不允许关闭 */
/** Required and no default value Closure is not allowed */
const isFinalRequired = isRequired && !isWithDefaultValue;
return isFinalRequired || isMaxCount;

View File

@@ -308,7 +308,7 @@ const DraggableBodyRow: FC<
onMove: OnMove<string>;
}>
> = ({ id, onMove, children, sortable }) => {
// 因为 name 可能为空,这里拿 shortid 做一个兜底
// Because the name may be empty, take shortid as a bottom line here.
const dropRef = useRef<HTMLElement>(null);
const { connect } = useDnDSortableItem<string>({
type,
@@ -317,7 +317,7 @@ const DraggableBodyRow: FC<
enabled: sortable,
});
useEffect(() => {
// 为了避免复杂的跨组件传值,这里稍微直接操作一下 DOM ,非常抱歉
// In order to avoid complicated cross-component value transfer, here is a little direct manipulation of the DOM, I'm very sorry.
const handleRef = {
current: (dropRef.current?.querySelector(`#${handleId}`) ??
null) as HTMLElement | null,
@@ -329,7 +329,7 @@ const DraggableBodyRow: FC<
export const tableComponents = {
body: {
// semi-ui 导出的类型定义非常不负责任
// The type definition exported by semi-ui is very irresponsible
row: DraggableBodyRow,
},
} as unknown as TableComponents;

View File

@@ -20,11 +20,11 @@ import { Form } from '@coze-arch/bot-semi';
import style from './index.module.less';
// TODO: hzf, 取名component有点奇怪
// TODO: hzf, the named component is a bit strange
export type FormInputWithMaxCountProps = {
maxCount: number;
} & React.ComponentProps<typeof Form.Input>;
// input后带上suffix表示能够输入的最大字数
// After input, put a suffix to indicate the maximum number of words that can be entered
export const FormInputWithMaxCount = (props: FormInputWithMaxCountProps) => {
const [count, setCount] = React.useState(0);
const handleChange = (v: string) => {

View File

@@ -32,7 +32,7 @@ export const getSubmitValue = (
const newValues = { ...values };
/**
* 最先执行 根据是否包含 components_list 设置 send_type
* Execute first, depending on whether components_list is included send_type
*/
mutableSendType(newValues);
@@ -50,7 +50,7 @@ export const getSubmitValue = (
if (!use_tool) {
mutableInitNotUseToolFormValues(newValues);
}
// TODO: hzf干掉不合理
// TODO: hzf killing is unreasonable
return newValues as ShortCutCommand;
};
@@ -63,7 +63,7 @@ const mutableSendType = (value: ShortcutEditFormValues) => {
};
/**
* 为了兼容,需要在修改components_list的default_value,hide的时候同步修改toolParams
* For compatibility, you need to modify the toolParams synchronously when modifying the default_value and hide of the components_list
* 1.components_list.hide => !toolParams.refer_component
* 2.components_list.default_value => refer_componentfalse && toolParams.default_value
*/
@@ -90,7 +90,7 @@ export const findToolParamsByComponent = (
component: Components,
) => params?.find(param => param.name === component.parameter);
// 初始化query类型的表单参数
// Initialize form parameters for query types
const mutableInitQueryFormValues = (values: ShortcutEditFormValues): void => {
values.tool_type = undefined;
values.plugin_id = '';
@@ -104,7 +104,7 @@ const mutableInitQueryFormValues = (values: ShortcutEditFormValues): void => {
values.card_schema = '';
};
// 初始化使用插件组件的时候表单参数
// Initialize form parameters when using plug-in components
const mutableInitNotUseToolFormValues = (
values: ShortcutEditFormValues,
): void => {
@@ -137,10 +137,10 @@ const mutableFormatCommandName = (values: ShortcutEditFormValues): void => {
};
/**
* 筛选toolParams存在,components中不存在的变量
* 并且refer_component=false,
* 转化为components_list
* 用于向前兼容,旧指令中tool的默认参数放在toolParams
* Filter toolParams exists, variables that do not exist in components
* And refer_component = false,
* Converted to components_list
* For forward compatibility, the default parameters of tool in the old directive are placed in toolParams
*/
export const initComponentsListFromToolParams = (
components: Components[],
@@ -167,10 +167,10 @@ export const initComponentsListFromToolParams = (
};
/**
* 兼容旧指令
* 如果InputType UploadImage, UploadDoc, UploadTable, UploadAudio,
* 判断upload_options是否为空
* 为空,加上对应的upload_options
* Compatible with outdated instructions
* If the InputType is UploadImage, UploadDoc, UploadTable, UploadAudio,
* Determine if upload_options is empty
* Is empty, plus the corresponding upload_options
*/
export const initComponentsUploadOptions = (
components: Components[],
@@ -198,14 +198,14 @@ export const initComponentsUploadOptions = (
export const getInitialValues = (
initShortcut?: ShortCutCommand,
): ShortcutEditFormValues => {
// 初始化
// initialization
if (!initShortcut) {
return {
send_type: SendType.SendTypeQuery,
use_tool: false,
};
}
// 回显
// echo
const {
shortcut_command,
tool_type,

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, {
type Dispatch,
type FC,
@@ -106,7 +106,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
getInitialValues(shortcut),
);
// 使用技能 & 未选择工具 => 禁止提交
// Use Skills & Unselected Tools = > Forbid Submissions
const disableSubmit =
editedShortcut?.use_tool && !editedShortcut?.tool_info?.tool_name;
@@ -127,7 +127,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
console.log('onConfirm', formattedValues);
if (mode === 'create') {
// TODO: hzf add的类型应该没有command_id
// TODO: hzf add type should have no command_id
onAdd?.(formattedValues, () => {
setConfirmLoading(false);
});
@@ -146,7 +146,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
await formRef.current?.formApi.validate();
return actionSwitchAreaRef.current?.validate();
// eslint-disable-next-line @coze-arch/use-error-in-catch -- 正常表单校验不需要处理e
// eslint-disable-next-line @coze-arch/use-error-in-catch -- normal form validation does not require processing e
} catch (e) {
return false;
}
@@ -166,7 +166,7 @@ export const ShortcutEditModal: FC<ShortcutEditModalProps> = props => {
const { data: pluginData } = useRequest(
async () => {
// 方便类型推断
// convenient type inference
if (shortcut?.plugin_id && spaceId) {
const res = await PluginDevelopApi.GetPlaygroundPluginList({
page: 1,

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { type RefObject, useMemo, useRef, useState } from 'react';
import cls from 'classnames';
@@ -61,7 +61,7 @@ export const SwitchAgent = (props: SwitchAgentProps) => {
if (!editedShortcut.agent_id) {
return {
defaultAgentId: '',
// @ts-expect-error --后面替换
// @ts-expect-error -- replace later
defaultName: I18n.t('Do not specify'),
};
}

View File

@@ -78,10 +78,10 @@ const ExpressionEditorContainer = forwardRef<
useEffect(() => model.setVariableTree(variableTree), [variableTree]);
useEffect(() => model.setFocus(focus), [focus]);
// 同步表单值变化
// Synchronize form value changes
useEffect(() => {
if (model.value === formValue) {
// 无需同步
// No synchronization required
return;
}
model.setValue(formValue);

View File

@@ -70,7 +70,7 @@ const VarQueryTextarea: FC<UsageWithVarTextAreaProps> = props => {
useEffect(() => editorRef.current?.model.setFocus(focus), [focus]);
// 设置防抖防止 onFocus / onBlur 在点击时出现抖动
// Set anti-shake to prevent onFocus/onBlur from shaking when clicked
const setFocus = useCallback(
debounce((newFocusValue: boolean) => {
_setFocus(newFocusValue);

View File

@@ -55,7 +55,7 @@ interface ExpressionEditorSuggestionProps {
}
/**
* 自动提示
* autoprompt
*/
export const VarExpressionEditorSuggestion: FC<
ExpressionEditorSuggestionProps

View File

@@ -23,7 +23,7 @@ import type { ShortCutCommand } from '@coze-agent-ide/tool-config';
export enum OpenModeType {
OnlyOnceAdd = 'only_once_add',
}
// TODO: hzf 两份定义?
// TODO: hzf two definitions?
export interface SkillsModalProps {
tabsConfig?: {
plugin?: {
@@ -44,9 +44,9 @@ export interface SkillsModalProps {
};
};
tabs: ('plugin' | 'workflow' | 'datasets' | 'imageFlow')[];
/** 打开弹窗模式:
* 默认不传
* only_once_add仅可添加一次后关闭并返回callback函数
/** Open pop-up mode:
* Do not pass by default
* only_once_add: close after adding only once and return the callback function
*/
openMode?: OpenModeType;
openModeCallback?: (val?: PluginApi | WorkFlowItemType) => void;

View File

@@ -83,7 +83,7 @@ export const QueryShortcut: FC<QueryShortcutProps> = props => {
return (
<div className={typeSafeShortcutCommandVariants({ color: props.uiMode })}>
{/*指令名称不超长,展示描述*/}
{/*Instruction name is not too long, display description*/}
<TooltipWithContent
shortcut={shortcut}
toolTipFooterSlot={toolTipFooterSlot}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { type shortcut_command } from '@coze-arch/bot-api/playground_api';
import { type DSL } from '../../types';
@@ -25,7 +25,7 @@ import {
getLayoutDSL,
} from './templates';
// 通过 Components 生成完整的 DSL
// Generating a complete DSL with Components
export const getDSLFromComponents = (
params: shortcut_command.Components[],
): DSL => {
@@ -36,7 +36,7 @@ export const getDSLFromComponents = (
[...formItemsDSL, ...layoutDSL].forEach(
item => (template.elements[item.id] = item),
);
// @ts-expect-error 支持直接传递 props
// @ts-expect-error supports direct delivery of props
template.elements.submitButton.props.formFields = formItemsDSL.map(
item => item.id,
);
@@ -45,7 +45,7 @@ export const getDSLFromComponents = (
type DSLElement = DSL['elements'][string];
// 通过 Components 创建 DSL 中对应的表单元素 Element
// Create the corresponding form element Element in the DSL through Components
export const getFormElementFromComponent = (
param: shortcut_command.Components,
): DSLElement => {
@@ -55,12 +55,12 @@ export const getFormElementFromComponent = (
return getFormItemPlaceholderDSL();
};
// 用于生成 DSL 语法中双列布局的容器元素
// Container elements for generating two-column layouts in DSL syntax
const ITEMS_PER_LINE = 2;
export const getElementsLayout = (elements: DSLElement[]): DSLElement[] => {
const res: DSLElement[] = [];
const elementsCopy = [...elements];
// 如出现奇数个,最后一行占满
// If an odd number appears, the last line is full
while (elementsCopy.length) {
res.push(getLayoutDSL(elementsCopy.splice(0, ITEMS_PER_LINE)));
}

View File

@@ -20,7 +20,7 @@ import { shortid } from '../uuid';
import { getAcceptByUploadItemTypes } from '../file-const';
import { type DSL, ElementDirectiveType, ElementPropsType } from '../../types';
// @fixme DSL 类型定义需要更新
// @Fixme DSL type definition needs to be updated
export const getDSLTemplate = (): DSL => ({
elements: {
root: {
@@ -32,7 +32,7 @@ export const getDSLTemplate = (): DSL => ({
},
form: {
id: 'form',
name: 'FlowpdCiciComponentsForm', // TODO 组件名 & type 最好也能事先就约定好
name: 'FlowpdCiciComponentsForm', // TODO component name & type can preferably be agreed in advance
type: '@flowpd/cici-components/Form',
props: {
value: {
@@ -47,15 +47,15 @@ export const getDSLTemplate = (): DSL => ({
// some rules value
},
},
children: ['submitButton'], // 根据 variables + layout 生成
children: ['submitButton'], // Generated from variables + layout
},
// 通过 getFormElementsFromcomponent 生成表单元素
// Generate form elements from getFormElementsFromcomponent
// ...inputElements,
// 通过 getElementsLayout 生成表单元素 layout
// Generate form element layout with getElementsLayout
// ...inputLayoutElements,
submitButton: {
id: 'submitButton',
name: 'FlowpdCiciComponentsButton', // TODO 组件名 & type 最好也能事先就约定好
name: 'FlowpdCiciComponentsButton', // TODO component name & type can preferably be agreed in advance
type: '@flowpd/cici-components/Button',
props: {
onClick: {
@@ -69,7 +69,7 @@ export const getDSLTemplate = (): DSL => ({
variables: {
formValue: {
id: 'formValue',
defaultValue: {}, // 不需要缺省值
defaultValue: {}, // No default is required
},
},
actions: {
@@ -96,7 +96,7 @@ export type GetFormItemTemplate = (
export const getInputElementDSL: GetFormItemTemplate = component => ({
id: component.name ?? shortid(),
name: 'FlowpdCiciComponentsInput', // TODO 组件名最好也能事先就约定好
name: 'FlowpdCiciComponentsInput', // The TODO component name should preferably be agreed in advance
type: '@flowpd/cici-components/Input',
props: {
name: component.name,
@@ -104,13 +104,13 @@ export const getInputElementDSL: GetFormItemTemplate = component => ({
defaultValue: component.default_value,
rules: [],
noErrorMessage: true,
// @FIXME DSL 解析逻辑实际支持传入任意值作为 props但是类型定义里没有兼容这种语法
// The @FIXME DSL parsing logic actually supports passing arbitrary values as props, but there is no compatible syntax in the type definition
} as unknown as DSLElement['props'],
});
export const getSelectElementDSL: GetFormItemTemplate = component => ({
id: component.name ?? shortid(),
name: 'FlowpdCiciComponentsSelect', // TODO 组件名最好也能事先就约定好
name: 'FlowpdCiciComponentsSelect', // The TODO component name should preferably be agreed in advance
type: '@flowpd/cici-components/Select',
props: {
name: component.name,
@@ -126,11 +126,11 @@ export const getSelectElementDSL: GetFormItemTemplate = component => ({
},
],
noErrorMessage: true,
// @FIXME DSL 解析逻辑实际支持传入任意值作为 props但是类型定义里没有兼容这种语法
// The @FIXME DSL parsing logic actually supports passing arbitrary values as props, but there is no compatible syntax in the type definition
} as unknown as DSLElement['props'],
});
// 单位 kb
// Unit kb
export const IMAGE_MAX_SIZE = 500 * 1024; // 500 mb
export const FILE_MAX_SIZE = 500 * 1024; // 500 mb
@@ -147,7 +147,7 @@ const getAcceptByComponent = (component: shortcut_command.Components) => {
export const getUploadElementDSL: GetFormItemTemplate = component => ({
id: component.name ?? shortid(),
name: 'FlowpdCiciComponentsUpload', // TODO 组件名最好也能事先就约定好
name: 'FlowpdCiciComponentsUpload', // The TODO component name should preferably be agreed in advance
type: '@flowpd/cici-components/Upload',
props: {
name: component.name,
@@ -164,11 +164,11 @@ export const getUploadElementDSL: GetFormItemTemplate = component => ({
},
],
noErrorMessage: true,
// @FIXME DSL 解析逻辑实际支持传入任意值作为 props但是类型定义里没有兼容这种语法
// The @FIXME DSL parsing logic actually supports passing arbitrary values as props, but there is no compatible syntax in the type definition
} as unknown as DSLElement['props'],
});
// 配置 & 预览模式占位符
// Configuration & Preview Mode Placeholders
export const getFormItemPlaceholderDSL = () => ({
id: shortid(),
name: 'FlowpdCiciComponentsFormItemPlaceholder',
@@ -180,7 +180,7 @@ export const getLayoutDSL = (items: DSLElement[]): DSLElement => ({
name: 'FlowpdCiciComponentsColumnLayout',
type: '@flowpd/cici-components/ColumnLayout',
props: {
// 如出现奇数个,最后一行占满
// If an odd number appears, the last line is full
Columns: items.map(item => ({
children: [item.id],
config: { vertical: 'top', weight: 1, width: 'weighted' },
@@ -189,7 +189,7 @@ export const getLayoutDSL = (items: DSLElement[]): DSLElement => ({
action: 'enableUrl',
backgroundColor: 'transparent',
enableClickEvent: false,
// @FIXME card-buidler Layout 现有的数据结构,但是实际上类型非法
// @FIXME card-buidler Layout an existing data structure, but the type is actually illegal
} as unknown as DSLElement['props'],
});
export const getFormItemDSLMap: Record<

View File

@@ -95,7 +95,7 @@ export const ACCEPT_UPLOAD_TYPES: {
},
];
// 和chat支持的文件格式做映射
// Map with file formats supported by chat
export const fileTypeToInputTypeMap = {
[FileTypeEnum.IMAGE]: shortcut_command.InputType.UploadImage,
[FileTypeEnum.AUDIO]: shortcut_command.InputType.UploadAudio,
@@ -126,7 +126,7 @@ export const acceptMap = FILE_TYPE_CONFIG.reduce<{
return acc;
}, {});
// 根据acceptUploadItemTypes获取accept
// Accept based on acceptUploadItemTypes
export const getAcceptByUploadItemTypes = (
acceptUploadItemTypes: shortcut_command.InputType[],
) => {
@@ -144,7 +144,7 @@ export const getAcceptByUploadItemTypes = (
return accept.join(',');
};
// 根据fileType获取对应的fileInfo
// Get the corresponding fileInfo according to fileType
export const getFileInfoByFileType = (fileType: FileTypeEnum) => {
const inputType = fileTypeToInputTypeMap[fileType];
if (!inputType) {
@@ -153,7 +153,7 @@ export const getFileInfoByFileType = (fileType: FileTypeEnum) => {
return ACCEPT_UPLOAD_TYPES.find(item => item.type === inputType);
};
// ACCEPT_UPLOAD_TYPES转化为map
// ACCEPT_UPLOAD_TYPES converted to map
export const getAcceptUploadItemTypesMap = () =>
ACCEPT_UPLOAD_TYPES.reduce<{
[key in shortcut_command.InputType]?: string;

View File

@@ -14,13 +14,13 @@
* limitations under the License.
*/
// 根据template_querycomponents拼接query
// Stitching queries based on template_query and components
export const getQueryFromTemplate = (
templateQuery: string,
values: Record<string, unknown>,
) => {
let query = templateQuery;
// 替换模板中的{{key}}为values中key对应的值
// Replace the {{key}} in the template with the value corresponding to the key in values
Object.keys(values).forEach(key => {
query = query.replace(
new RegExp(`\\{\\{${key}\\}\\}`, 'g'),

View File

@@ -21,7 +21,7 @@ import {
import { type ToolInfo } from '../shortcut-tool/types';
// 根据shortcut获取toolInfo
// Get toolInfo by shortcut
export const getToolInfoByShortcut = (
shortcut: shortcut_command.ShortcutCommand | undefined,
): ToolInfo => {
@@ -51,11 +51,11 @@ export const getToolInfoByShortcut = (
};
};
// 校验string数字 + 英文 + _ & 不能是纯数字
// Check string: number + English + _ & cannot be pure numbers
export const validateCmdString = (value: string) =>
/^[a-zA-Z0-9_]+$/.test(value) && !/^[0-9]+$/.test(value);
// 根据tool_type判断是否开启了tool
// According to tool_type determine whether the tool is turned on.
export const initToolEnabledByToolTYpe = (
toolType: shortcut_command.ToolType | undefined,
) =>
@@ -65,7 +65,7 @@ export const initToolEnabledByToolTYpe = (
shortcut_command.ToolType.ToolTypePlugin,
].includes(toolType);
// 校验pluginworkflow参数是否为string|integer类型,不支持复杂的对象类型
// Verify that the plugin and workflow parameters are of type string | integer, and do not support complex object types
export const validatePluginAndWorkflowParams = (
params: ToolParams[],
enableEmpty = false,
@@ -89,7 +89,7 @@ export const validatePluginAndWorkflowParams = (
};
};
// 校验shortcut_command是否重复
// Check if shortcut_command duplicate
export const validateCommandNameRepeat = (
checkShortcut: shortcut_command.ShortcutCommand,
shortcuts: shortcut_command.ShortcutCommand[],
@@ -101,7 +101,7 @@ export const validateCommandNameRepeat = (
shortcut.shortcut_command === shortcutCommand,
);
};
// 校验按钮名称command_name是否重复
// Check button name command_name duplicate
export const validateButtonNameRepeat = (
checkShortcut: shortcut_command.ShortcutCommand,
shortcuts: shortcut_command.ShortcutCommand[],

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
// 对齐 card-builder 生成 ID 的逻辑,暂时拷贝一份,未来计划直接使用 card-buidler 的底层能力
// Align the logic of card-builder generating ID, make a copy temporarily, and plan to use the underlying capabilities of card-buidler directly in the future
import { nanoid, customAlphabet } from 'nanoid';
/**
* @param prefix - id前缀
* @param options - alphabet: 字母表; length: 长度,默认10;
* @param prefix - id prefix
* @Param options - alphabet; length: length, default 10;
*/
export const shortid = (
prefix = '',