78 lines
2.5 KiB
TypeScript
78 lines
2.5 KiB
TypeScript
|
import React, { useState, useEffect } from 'react';
|
||
|
import { Button, Input, Space, Tag } from 'antd';
|
||
|
import { DeleteOutlined } from '@ant-design/icons';
|
||
|
|
||
|
type OptionCreatorProps = {
|
||
|
options: { [key: string]: string } | { label: string; value: string }[] | undefined;
|
||
|
onChange: (newOptions: { label: string; value: string }[]) => void;
|
||
|
};
|
||
|
|
||
|
const OptionCreator: React.FC<OptionCreatorProps> = ({ options, onChange }) => {
|
||
|
const [localOptions, setLocalOptions] = useState<{ label: string; value: string }[]>([]);
|
||
|
const [inputValue, setInputValue] = useState('');
|
||
|
|
||
|
// 监听传入的 options 变化,更新本地状态
|
||
|
useEffect(() => {
|
||
|
let validOptions: { label: string; value: string }[] = [];
|
||
|
if (Array.isArray(options)) {
|
||
|
validOptions = options;
|
||
|
} else if (typeof options === 'object' && options !== null) {
|
||
|
validOptions = Object.entries(options).map(([value, label]) => ({ label, value }));
|
||
|
}
|
||
|
setLocalOptions(validOptions);
|
||
|
}, [options]);
|
||
|
|
||
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||
|
setInputValue(e.target.value);
|
||
|
};
|
||
|
|
||
|
const handleAddOption = () => {
|
||
|
if (inputValue.trim()) {
|
||
|
const newOption = { label: inputValue, value: inputValue };
|
||
|
// 检查新选项是否已存在,避免重复添加
|
||
|
const isDuplicate = localOptions.some(option => option.value === newOption.value);
|
||
|
if (!isDuplicate) {
|
||
|
const newOptions = [...localOptions, newOption];
|
||
|
setLocalOptions(newOptions);
|
||
|
// 即时调用 onChange 通知父组件更新表单值
|
||
|
onChange(newOptions);
|
||
|
}
|
||
|
setInputValue('');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const handleDeleteOption = (value: string) => {
|
||
|
const newOptions = localOptions.filter(option => option.value !== value);
|
||
|
setLocalOptions(newOptions);
|
||
|
// 即时调用 onChange 通知父组件更新表单值
|
||
|
onChange(newOptions);
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div>
|
||
|
<Space>
|
||
|
<Input
|
||
|
value={inputValue}
|
||
|
onChange={handleInputChange}
|
||
|
placeholder="输入新选项"
|
||
|
/>
|
||
|
<Button onClick={handleAddOption}>添加选项</Button>
|
||
|
</Space>
|
||
|
<div style={{ marginTop: 16 }}>
|
||
|
{localOptions.map(option => (
|
||
|
<Tag
|
||
|
key={option.value}
|
||
|
closable
|
||
|
onClose={() => handleDeleteOption(option.value)}
|
||
|
icon={<DeleteOutlined />}
|
||
|
>
|
||
|
{option.label}
|
||
|
</Tag>
|
||
|
))}
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export default OptionCreator;
|