Phase 10: field editor (FR-14)
เพิ่ม editor ต่อ template field — ผู้ดูแลเลือกรูปแบบช่องกรอกในฟอร์มสร้างเอกสารได้: text → textbox/textarea, number/date → control ตาม type (presentation metadata ล้วน — validation ยังยึด Type, ค่า field เป็น string ทั้ง flow, ไม่แตะ generate/sync/add-in) - Backend: TemplateField.Editor (nullable, null = default ของ type) + migration AddTemplateFieldEditor + validate ตาม type ใน PUT templates (ค่าไม่รู้จัก/ไม่เข้ากับ type → 400, normalize-on-write, API คืน resolved เสมอ) - Web: util fieldEditor.ts + editor select หน้าแก้ template (desktop+mobile, ซ่อนเมื่อ type มีทางเดียว) + ฟอร์มสร้างเอกสาร render ตาม editor + แก้ prefill re-generate ของ field date จาก ISO timestamp เต็ม (input[type=date] รับเฉพาะ yyyy-MM-dd เดิมแสดงว่าง) - Docs: spec v6 (FR-14/AC-17) + plan Phase 10 + sub-plan field-editor.md + acceptance-review AC-17 + README/CLAUDE.md - Tests: backend 60/60 (FieldEditorTests ใหม่ 8 กรณี) · web 46/46 + build ผ่าน Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7b20f12ede
commit
9bb4a48c00
23 changed files with 865 additions and 45 deletions
|
|
@ -54,7 +54,11 @@ async function load() {
|
|||
fromDoc.value = { id: src.id, fileName: src.fileName }
|
||||
// prefill เฉพาะ key ที่มีใน defs ปัจจุบัน — key ที่หายไปหลัง replace ไฟล์โชว์ไม่ได้ (generate ก็ ignore)
|
||||
prefill.value = Object.fromEntries(
|
||||
detail.value.fields.map((f) => [f.key, src.fields.find((s) => s.key === f.key)?.value ?? '']),
|
||||
detail.value.fields.map((f) => {
|
||||
const value = src.fields.find((s) => s.key === f.key)?.value ?? ''
|
||||
// field วันที่: input[type=date] รับเฉพาะ yyyy-MM-dd — ค่าจาก sync ของ Word อาจเป็น ISO timestamp เต็ม (FR-14)
|
||||
return [f.key, resolveEditor(f) === 'date' ? dateInputValue(value) : value]
|
||||
}),
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
|
|
@ -212,11 +216,37 @@ onMounted(load)
|
|||
<span class="ml-1 font-mono text-xs font-normal text-muted">{{ f.key }}</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
<!-- render ตาม editor ของ field (FR-14): textarea สำหรับข้อความยาว · number/date ตาม type -->
|
||||
<textarea
|
||||
v-if="resolveEditor(f) === 'textarea'"
|
||||
:id="`field-${f.key}`"
|
||||
v-model="values[f.key]"
|
||||
:type="f.type === 'number' ? 'number' : f.type === 'date' ? 'date' : 'text'"
|
||||
:step="f.type === 'number' ? 'any' : undefined"
|
||||
class="input"
|
||||
:class="issues[f.key] ? 'border-error' : ''"
|
||||
rows="4"
|
||||
/>
|
||||
<input
|
||||
v-else-if="resolveEditor(f) === 'number'"
|
||||
:id="`field-${f.key}`"
|
||||
v-model="values[f.key]"
|
||||
type="number"
|
||||
step="any"
|
||||
class="input"
|
||||
:class="issues[f.key] ? 'border-error' : ''"
|
||||
/>
|
||||
<input
|
||||
v-else-if="resolveEditor(f) === 'date'"
|
||||
:id="`field-${f.key}`"
|
||||
v-model="values[f.key]"
|
||||
type="date"
|
||||
class="input"
|
||||
:class="issues[f.key] ? 'border-error' : ''"
|
||||
/>
|
||||
<input
|
||||
v-else
|
||||
:id="`field-${f.key}`"
|
||||
v-model="values[f.key]"
|
||||
type="text"
|
||||
class="input"
|
||||
:class="issues[f.key] ? 'border-error' : ''"
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue