feat: 增强select字段的选项管理(任务10)

- 添加选项列表输入框
  * 支持每行一个选项的简单格式
  * 支持JSON数组格式
  * 使用等宽字体便于编辑

- 自动处理选项值
  * 保存时自动清洗和规范化(已在后端实现)
  * 自动去重选项(已在field-pool.ts实现)
  * 展开嵌套数组格式(已在field-pool.ts实现)
  * 转换为JSON字符串存储(已在TemplateManager实现)

- 优化用户体验
  * 仅在select和radio类型时显示选项输入框
  * 提供清晰的格式说明和示例
  * 添加提示信息说明自动处理功能
This commit is contained in:
WuYongJie 2025-12-13 15:23:26 +08:00
parent ad888185ec
commit b065ecdce6
2 changed files with 32 additions and 2 deletions

View File

@ -87,7 +87,7 @@
- _需求: 16.1, 16.2, 16.3, 16.4, 16.5, 16.6, 16.7_
- _测试报告: docs/reports/TEMPLATE_FIELDS_VALIDATION_TEST_REPORT.md_
- [ ] 10. 增强select字段的选项管理
- [x] 10. 增强select字段的选项管理
- 支持逐行输入和JSON数组两种格式
- 自动清洗和规范化选项值
- 自动去重选项

View File

@ -470,7 +470,37 @@ export default function TemplateFieldsEditor({
</div>
</div>
{/* 下拉选项已移除,选项在分类管理中管理 */}
{/* 选项管理 - 仅在select或radio类型时显示 */}
{(isSelectType || field.type === 'radio') && (
<div className="mt-3">
<label className="block text-xs font-medium text-slate-700 dark:text-slate-300 mb-1.5">
选项列表
<span className="ml-2 text-[10px] text-slate-500 dark:text-slate-400">
(每行一个选项,或使用JSON数组格式)
</span>
</label>
<textarea
value={field.optionsStatic || ''}
onChange={(e) => {
e.stopPropagation()
onUpdateField(index, { optionsStatic: e.target.value })
}}
onClick={(e) => e.stopPropagation()}
className="w-full px-3 py-2 text-sm border border-slate-300 dark:border-slate-600 dark:bg-slate-900 dark:text-white rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all duration-200 font-mono"
placeholder={'示例1(每行一个):\n选项1\n选项2\n选项3\n\n示例2(JSON数组):\n["选项1", "选项2", "选项3"]'}
rows={4}
autoComplete="off"
/>
<div className="mt-1.5 flex items-start gap-2 text-[10px] text-slate-500 dark:text-slate-400">
<svg className="w-3 h-3 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>
保存时会自动清洗、去重和规范化选项值。支持嵌套数组格式(如 [["A", "B"], "C"])会自动展开。
</span>
</div>
</div>
)}
<div className="flex flex-wrap gap-3 mt-3 pt-3 border-t border-slate-200/60 dark:border-slate-700/60">
<label className="flex items-center gap-1.5 text-xs text-slate-700 dark:text-slate-300 cursor-pointer">