feat: 数据格式改为按钮组选择

- 移除 Select 下拉框
- 改为 JSON/CSV 按钮组
- 选中状态与生成数量按钮样式统一

feat: 优化空值率设置

- 增加 75% 预设选项
- 设置 100% 时自动设为必填
- 限制输入范围 0-100

fix: 空值率预设改为纯数字显示

- 5%/20%/50%/75% 统一样式

fix: 移除空值率低/中/高 i18n 翻译键

fix: 精简生成数量预设选项

- 移除 10、500
- 保留 50、100、1000、5000、10000
This commit is contained in:
雨霖铃
2026-06-06 10:47:01 +08:00
parent ea10b27c14
commit a374bf456d
3 changed files with 39 additions and 34 deletions
-12
View File
@@ -971,18 +971,6 @@
"message": "空值率", "message": "空值率",
"description": "Translation key: testDataGenerator_nullRate" "description": "Translation key: testDataGenerator_nullRate"
}, },
"testDataGenerator_nullRateLow": {
"message": "低 (5%)",
"description": "Translation key: testDataGenerator_nullRateLow"
},
"testDataGenerator_nullRateMedium": {
"message": "中 (20%)",
"description": "Translation key: testDataGenerator_nullRateMedium"
},
"testDataGenerator_nullRateHigh": {
"message": "高 (50%)",
"description": "Translation key: testDataGenerator_nullRateHigh"
},
"testDataGenerator_uniqueConstraint": { "testDataGenerator_uniqueConstraint": {
"message": "唯一性约束", "message": "唯一性约束",
"description": "Translation key: testDataGenerator_uniqueConstraint" "description": "Translation key: testDataGenerator_uniqueConstraint"
@@ -38,7 +38,14 @@ export default function FieldEditor({ field, onChange }: FieldEditorProps) {
}; };
const handleNullRateChange = (nullRate: number) => { const handleNullRateChange = (nullRate: number) => {
onChange({ ...field, nullRate }); // 限制范围 0-100
const clampedRate = Math.max(0, Math.min(100, nullRate));
// 设置为 100% 时自动设为必填
if (clampedRate === 100) {
onChange({ ...field, nullRate: clampedRate, required: true });
} else {
onChange({ ...field, nullRate: clampedRate });
}
}; };
const handleUniqueChange = (unique: boolean) => { const handleUniqueChange = (unique: boolean) => {
@@ -63,9 +70,10 @@ export default function FieldEditor({ field, onChange }: FieldEditorProps) {
}; };
const nullRatePresets = [ const nullRatePresets = [
{ label: t('testDataGenerator_nullRateLow'), value: 5 }, { label: '5%', value: 5 },
{ label: t('testDataGenerator_nullRateMedium'), value: 20 }, { label: '20%', value: 20 },
{ label: t('testDataGenerator_nullRateHigh'), value: 50 }, { label: '50%', value: 50 },
{ label: '75%', value: 75 },
]; ];
return ( return (
@@ -129,7 +137,12 @@ export default function FieldEditor({ field, onChange }: FieldEditorProps) {
<Input <Input
type="number" type="number"
value={field.nullRate} value={field.nullRate}
onChange={(e) => handleNullRateChange(Number(e.target.value))} onChange={(e) => {
const value = Number(e.target.value);
if (value >= 0 && value <= 100) {
handleNullRateChange(value);
}
}}
min={0} min={0}
max={100} max={100}
step={5} step={5}
@@ -5,13 +5,6 @@
import { useI18n } from '@/utils/chromeI18n'; import { useI18n } from '@/utils/chromeI18n';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
interface GenerateOptionsProps { interface GenerateOptionsProps {
count: number; count: number;
@@ -22,7 +15,12 @@ interface GenerateOptionsProps {
onDefaultNullRateChange: (rate: number) => void; onDefaultNullRateChange: (rate: number) => void;
} }
const COUNT_PRESETS = [10, 50, 100, 500, 1000, 5000, 10000]; const COUNT_PRESETS = [50, 100, 1000, 5000, 10000];
const FORMAT_OPTIONS = [
{ value: 'json' as const, label: 'JSON' },
{ value: 'csv' as const, label: 'CSV' },
];
export default function GenerateOptions({ export default function GenerateOptions({
count, count,
@@ -76,15 +74,21 @@ export default function GenerateOptions({
<label className="text-sm font-medium text-foreground"> <label className="text-sm font-medium text-foreground">
{t('testDataGenerator_format')} {t('testDataGenerator_format')}
</label> </label>
<Select value={format} onValueChange={(v) => onFormatChange(v as 'json' | 'csv')}> <div className="flex gap-2">
<SelectTrigger className="h-9"> {FORMAT_OPTIONS.map((option) => (
<SelectValue /> <button
</SelectTrigger> key={option.value}
<SelectContent> onClick={() => onFormatChange(option.value)}
<SelectItem value="json">JSON</SelectItem> className={`flex-1 px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
<SelectItem value="csv">CSV</SelectItem> format === option.value
</SelectContent> ? 'bg-primary text-primary-foreground'
</Select> : 'bg-muted text-muted-foreground hover:bg-muted/80'
}`}
>
{option.label}
</button>
))}
</div>
</div> </div>
{/* 默认空值率 */} {/* 默认空值率 */}