mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-14 03:30:19 +00:00
♻️ refactor: 重构ArgsInput组件 (#8765)
* ♻️ refactor(utils): extract args parsing logic from ArgsInput component - Extract parseArgs and argsToString functions to src/utils/args.ts - Add comprehensive test suite with 19 test cases covering edge cases - Fix escaped quote handling in parseArgs function - Replace String.replace() with String.replaceAll() for better readability - Improve code reusability and maintainability following project best practices * 📝 docs(utils): improve JSDoc comments and clean up redundant comments - Add comprehensive JSDoc with @param and @returns for args functions - Translate inline comments to English for consistency - Remove redundant comments in ArgsInput component - Keep only essential comments and improve code clarity - Improve code documentation quality and IDE support * ♻️ refactor(ArgsInput): completely redesign as array editor - Replace single input with individual argument inputs - Add visual array structure with add/remove buttons - Support keyboard shortcuts (Enter to add, Backspace to delete) - Improve UX with proper array operations and indexing - Remove dependency on args parsing utils for better performance * 🌐 i18n: add ArgsInput internationalization support - Add ArgsInput translations for en-US and zh-CN - Add TypeScript type definitions for new translation keys - Support dynamic placeholder with argument index - Fix TypeScript error for missing translation keys
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"ArgsInput": {
|
||||
"addArgument": "Add Argument",
|
||||
"argumentPlaceholder": "Argument {{index}}",
|
||||
"enterFirstArgument": "Enter first argument..."
|
||||
},
|
||||
"DragUpload": {
|
||||
"dragDesc": "Drag and drop files here to upload multiple images.",
|
||||
"dragFileDesc": "Drag and drop images and files here to upload multiple images and files.",
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"ArgsInput": {
|
||||
"addArgument": "添加参数",
|
||||
"argumentPlaceholder": "参数 {{index}}",
|
||||
"enterFirstArgument": "输入第一个参数..."
|
||||
},
|
||||
"DragUpload": {
|
||||
"dragDesc": "拖拽文件到这里,支持上传多个图片。",
|
||||
"dragFileDesc": "拖拽图片和文件到这里,支持上传多个图片和文件。",
|
||||
|
||||
@@ -1,20 +1,102 @@
|
||||
import { Input, type InputProps } from '@lobehub/ui';
|
||||
import { memo } from 'react';
|
||||
import { ActionIcon, Button, Input, type InputProps } from '@lobehub/ui';
|
||||
import { Plus, X } from 'lucide-react';
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Flexbox } from 'react-layout-kit';
|
||||
|
||||
interface ArgsInputProps extends Omit<InputProps, 'value' | 'onChange'> {
|
||||
onChange?: (value: string[]) => void;
|
||||
value?: string[];
|
||||
}
|
||||
|
||||
const ArgsInput = memo<ArgsInputProps>(({ value, onChange, ...res }) => {
|
||||
const ArgsInput = memo<ArgsInputProps>(({ value = [], onChange, ...res }) => {
|
||||
const { t } = useTranslation('components');
|
||||
|
||||
const handleAddArg = useCallback(() => {
|
||||
onChange?.([...value, '']);
|
||||
}, [value, onChange]);
|
||||
|
||||
const handleRemoveArg = useCallback(
|
||||
(index: number) => {
|
||||
const newValue = value.filter((_, i) => i !== index);
|
||||
onChange?.(newValue);
|
||||
},
|
||||
[value, onChange],
|
||||
);
|
||||
|
||||
const handleArgChange = useCallback(
|
||||
(index: number, newArg: string) => {
|
||||
const newValue = [...value];
|
||||
newValue[index] = newArg;
|
||||
onChange?.(newValue);
|
||||
},
|
||||
[value, onChange],
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: React.KeyboardEvent<HTMLInputElement>, index: number) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
if (index === value.length - 1) {
|
||||
handleAddArg();
|
||||
}
|
||||
} else if (e.key === 'Backspace' && e.currentTarget.value === '' && value.length > 1) {
|
||||
e.preventDefault();
|
||||
handleRemoveArg(index);
|
||||
}
|
||||
},
|
||||
[value.length, handleAddArg, handleRemoveArg],
|
||||
);
|
||||
|
||||
return (
|
||||
<Input
|
||||
onChange={(e) => {
|
||||
onChange?.([e.target.value]);
|
||||
}}
|
||||
value={value?.join(' ')}
|
||||
{...res}
|
||||
/>
|
||||
<Flexbox gap={8} style={{ width: '100%' }}>
|
||||
{value.length === 0 ? (
|
||||
<Flexbox align="center" gap={8} horizontal>
|
||||
<Input
|
||||
{...res}
|
||||
onBlur={(e) => {
|
||||
if (e.target.value.trim()) {
|
||||
onChange?.([e.target.value.trim()]);
|
||||
}
|
||||
res.onBlur?.(e);
|
||||
}}
|
||||
placeholder={t('ArgsInput.enterFirstArgument')}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<Button icon={Plus} onClick={handleAddArg} size="small" type="primary" />
|
||||
</Flexbox>
|
||||
) : (
|
||||
<>
|
||||
{value.map((arg, index) => (
|
||||
<Flexbox align="center" gap={8} horizontal key={index}>
|
||||
<Input
|
||||
onChange={(e) => handleArgChange(index, e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, index)}
|
||||
placeholder={t('ArgsInput.argumentPlaceholder', { index: index + 1 })}
|
||||
style={{ flex: 1 }}
|
||||
value={arg}
|
||||
/>
|
||||
<ActionIcon
|
||||
icon={X}
|
||||
onClick={() => handleRemoveArg(index)}
|
||||
size="small"
|
||||
style={{ flexShrink: 0 }}
|
||||
/>
|
||||
</Flexbox>
|
||||
))}
|
||||
<Button
|
||||
icon={Plus}
|
||||
onClick={handleAddArg}
|
||||
size="small"
|
||||
style={{ alignSelf: 'flex-start' }}
|
||||
type="dashed"
|
||||
>
|
||||
{t('ArgsInput.addArgument')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Flexbox>
|
||||
);
|
||||
});
|
||||
|
||||
export default ArgsInput;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
export default {
|
||||
ArgsInput: {
|
||||
addArgument: '添加参数',
|
||||
argumentPlaceholder: '参数 {{index}}',
|
||||
enterFirstArgument: '输入第一个参数...',
|
||||
},
|
||||
DragUpload: {
|
||||
dragDesc: '拖拽文件到这里,支持上传多个图片。',
|
||||
dragFileDesc: '拖拽图片和文件到这里,支持上传多个图片和文件。',
|
||||
|
||||
Reference in New Issue
Block a user