186 lines
8.9 KiB
Markdown
186 lines
8.9 KiB
Markdown
# LLM 開發操作指南
|
||
|
||
## 文件目的
|
||
|
||
本專案是給其他 Vue/Vuetify 專案使用的 template。LLM 協助修改時,預設應在 `src` 底下依分層規則新增或修改頁面、元件、store、service 與 composable。
|
||
|
||
本文件只保留全域操作順序與導覽。各層細節規範放在 `src/**/GUIDE.md`,避免重複維護。
|
||
|
||
## 建議閱讀順序
|
||
|
||
1. `src/GUIDE.md`
|
||
2. `docs/architecture-strategy.md`
|
||
3. 依 `maintenanceContract.pageKind` 閱讀對應的 demo 與 `src/**/GUIDE.md`(查 `docs/architecture-strategy.md` 的分層說明)
|
||
4. `docs/add-page-example.md`(需要新增頁面時)
|
||
|
||
`frontend-layering.md` 是歷史參考,後續以 `docs/architecture-strategy.md` 與 `src/**/GUIDE.md` 為準。
|
||
|
||
## GUIDE 索引
|
||
|
||
| 範圍 | 指南 |
|
||
|------|------|
|
||
| `src` 總覽、資料流、template core、demo 邊界 | `src/GUIDE.md` |
|
||
| route view 與薄 view 規則 | `src/views/GUIDE.md` |
|
||
| maintenance demo view | `src/views/maint/GUIDE.md` |
|
||
| Vue component 分層 | `src/components/GUIDE.md` |
|
||
| base 元件 | `src/components/base/GUIDE.md` |
|
||
| section 元件 | `src/components/sections/GUIDE.md` |
|
||
| layout 邊界 | `src/components/layouts/GUIDE.md` |
|
||
| page driver、command、layout composable | `src/composables/GUIDE.md` |
|
||
| route 與 guard | `src/router/GUIDE.md` |
|
||
| AppShell、tabs、global overlays | `src/shell/GUIDE.md` |
|
||
| Pinia store | `src/stores/GUIDE.md` |
|
||
| HTTP service / ky / API module | `src/services/GUIDE.md` |
|
||
| domain model 與 page model 型別 | `src/models/GUIDE.md` |
|
||
| 跨模組共用 API 型別 | `src/types/GUIDE.md` |
|
||
| i18n 文案 | `src/language/GUIDE.md` |
|
||
|
||
## 預設修改策略
|
||
|
||
一般功能需求優先修改:
|
||
|
||
- `src/views/*`
|
||
- `src/components/sections/*`
|
||
- `src/components/items/*`
|
||
- `src/composables/page-drivers/*`
|
||
- `src/composables/useCrudCommands.ts`
|
||
- `src/stores/*`
|
||
- `src/services/modules/*`
|
||
- `src/router/routes.ts`
|
||
- `src/language/*.json`
|
||
|
||
除非使用者明確要求,避免先修改 template core。template core 清單與 demo/example 邊界見 `src/GUIDE.md`。
|
||
|
||
## 常用判斷
|
||
|
||
- 新 route:讀 `src/router/GUIDE.md`。
|
||
- 一般頁面:讀 `src/views/GUIDE.md`、`src/components/GUIDE.md`、`src/composables/GUIDE.md`。
|
||
- 維護頁:讀 `src/views/maint/GUIDE.md`。
|
||
- 查詢/列表頁(篩選 + 表格):讀 `src/components/sections/GUIDE.md`(`SectionQueryPage`)。
|
||
- 申請/填寫頁(送出按鈕):讀 `src/components/sections/GUIDE.md`(`SectionFormPage`)。
|
||
- layout / AppShell / tabs / global overlay:讀 `src/shell/GUIDE.md` 與 `src/components/layouts/GUIDE.md`。
|
||
- API 串接:讀 `src/services/GUIDE.md`。
|
||
- 跨頁共享狀態:讀 `src/stores/GUIDE.md`。
|
||
- 定義 page model 或 domain model 型別:讀 `src/models/GUIDE.md`。
|
||
- 共用 API 型別定義:讀 `src/types/GUIDE.md`。
|
||
- 錯誤頁:讀 `src/views/GUIDE.md`(ErrorShell 模式)與 `src/router/GUIDE.md`(錯誤頁路由慣例)。
|
||
- 語系文案:讀 `src/language/GUIDE.md`。
|
||
|
||
## 修改前檢查
|
||
|
||
- 是否碰到 template core。
|
||
- 是否已有同類型範例可沿用。
|
||
- 是否需要新增 route。
|
||
- 是否應拆成 section / item。
|
||
- 是否應新增 page driver 或 command composable。
|
||
- 是否需要 store,或只需要頁面內 state。
|
||
- 是否應定義新的 model 型別(`src/models/`)。
|
||
- 是否需要更新語系、menu、breadcrumb、favorites。
|
||
|
||
## 從視覺特徵選擇 section 元件
|
||
|
||
當收到 prototype 截圖或設計稿時,依畫面特徵選擇 section 外殼:
|
||
|
||
| 特徵 | 選擇 |
|
||
|------|------|
|
||
| 有「送出/存檔」按鈕,且畫面為填寫表單(欄位 + 配合事項 + 動作按鈕) | `SectionFormPage` |
|
||
| 有「查詢」按鈕,且畫面為篩選條件 + 結果表格/列表 | `SectionQueryPage` |
|
||
| 純粹表格列表(無送出/查詢按鈕,只有 CRUD 操作) | 不用 section 外殼,直接組合 `v-data-table` |
|
||
| 混合結構(有查詢也有表單填寫) | 評估是否拆成兩頁;若必須同頁,不用通用外殼 |
|
||
|
||
判斷順序:先看有無「送出/存檔」→ 再看有無「查詢」→ 其餘視為一般列表頁。
|
||
|
||
## `.spec.json` 對照指南
|
||
|
||
當 LLM 依照 `GEN-FE-PROMPT` 讀取 `.ht/spec/{page}.spec.json` 後,依 `maintenanceContract.pageKind` 決定對應的 demo 與 composable 界面,再將 `.spec.json` 的 evidence 欄位對應到 composable 的 reactive state、computed 與 API calls。
|
||
|
||
### query(查詢頁)→ `SectionQueryPage`
|
||
|
||
參考:`src/views/demos/SectionQueryPageDemo.vue`、`src/composables/page-drivers/useSectionsDemoPage.ts`
|
||
|
||
架構:
|
||
```
|
||
View(自含 page model + UI) → SectionQueryPage
|
||
↓
|
||
composable (page driver)
|
||
```
|
||
|
||
**composable 必須回傳:**
|
||
|
||
| 名稱 | 型別 | 對應 `.spec.json` 來源 |
|
||
|------|------|------------------------|
|
||
| `queryFilters` | `Ref<{ 每個欄位 }>` | `pageContract.forms[0].fields` — 每個 field 建一個 key,型別依 `field.type`(text→string, select→string \| null,選項取自 `field.options`) |
|
||
| `pageModel` | `ComputedRef<{ title, ... }>` | `title` 來自 `pageContract.title`;`backLabel` 固定為 `'返回'` |
|
||
| `handleQuerySearch()` | 函式 | 觸發 `apiContract.endpoints` 中 `usage=search` 的 API call;呼叫時機對應 `bddContract.scenarios` 中 `type=query` 的 When |
|
||
| `handleQueryBack()` | 函式 | 對應 `pageContract.actions` 中 `actionType=back` |
|
||
| 表格資料 | 在 `pageModel` 中 | `tables[].headers` 對應表格欄;`sampleRows` 對應欄位格式 |
|
||
|
||
**page component props:**
|
||
- `v-model:query-filters` — 雙向綁定 `queryFilters`
|
||
- `:page` — 傳入 `pageModel`
|
||
|
||
**page component emits:**
|
||
- `@search` → 呼叫 `handleQuerySearch`
|
||
- `@back` → 呼叫 `handleQueryBack`
|
||
|
||
### application(申請/表單頁)→ `SectionFormPage`
|
||
|
||
參考:`src/views/demos/SectionFormPageDemo.vue`
|
||
|
||
架構:
|
||
```
|
||
View(自含 page model + UI) → SectionFormPage
|
||
↓
|
||
composable (page driver)
|
||
```
|
||
|
||
**composable 必須回傳:**
|
||
|
||
| 名稱 | 型別 | 對應 `.spec.json` 來源 |
|
||
|------|------|------------------------|
|
||
| `demoForm`(應改名為 `formState`) | `Ref<{ 每個欄位 }>` | `pageContract.forms[0].fields` — text/select 建 key;不可編輯的 `readonly` 欄位不放進 formState,改從 `pageModel` 單向顯示 |
|
||
| `pageModel` | `ComputedRef` | `title` 來自 `pageContract.title` |
|
||
| `handleFormSubmit()` | 函式 | 觸發 `apiContract.endpoints` 中 `usage=create` 的 POST endpoint;呼叫前驗證 `apiCatalog.fieldRules`;呼叫時機對應 `bddContract.scenarios` 中 `type=application-submit` 的 When/Then |
|
||
| `resetDemoForm()`(改為 `resetForm`) | 函式 | 對應 `pageContract.actions` 中 `actionType=reset` |
|
||
| `handleFormBack()` | 函式 | 對應 `actionType=back` |
|
||
|
||
**提交 payload 規則:**
|
||
- `apiCatalog.fieldRules` 中的 `field` 與 `rule` 決定必填、長度、格式驗證
|
||
- 型別轉換依 `field.type`:number 欄位不可包成 string 送出
|
||
|
||
### maintenance(維護/CRUD 頁)→ `maint/*`
|
||
|
||
參考:`src/views/maint/README.md` — 依資料結構選擇最接近的範本(EditableGrid / SingleRecord / MasterDetail A/B/C)
|
||
|
||
**composable 必須回傳:**
|
||
|
||
| 名稱 | 對應 `.spec.json` 來源 |
|
||
|------|------------------------|
|
||
| `search filters` | `pageContract.forms[0].fields` |
|
||
| `table data / headers` | `pageContract.tables[].headers` + search API response |
|
||
| `row action handlers` | `maintenanceContract.rowActions` — 每個 action 對應一個 handler;`enabledWhen` 決定啟用條件(如 `aprvYn === 'Z'` 時才能修改) |
|
||
| `create/update/delete calls` | `apiContract.endpoints` 中對應的 POST/PUT/DELETE |
|
||
|
||
**row action 狀態規則:**
|
||
- `enabledWhen` 直接轉為 template 中的 `:disabled` 或 `v-if` 條件
|
||
- `maintenanceContract.businessRules` 中的額外限制一併套用
|
||
|
||
### 通用規則
|
||
|
||
**entity 命名:** 所有 composable、component、store 的名稱以 `maintenanceContract.dataModel.primaryEntity` 為 entity 名,例如 primaryEntity=`FacilityApply` → `useFacilityApplyPage.ts` → `PageFacilityApply.vue`。
|
||
|
||
**API 串接:** 在 `src/services/modules/` 新增對應 entity 的 API module,method 名稱對齊 `apiContract.endpoints[].usage`(search/create/update/delete/print),path 對齊 `endpoint.path`。
|
||
|
||
**錯誤處理:** 檢查 `apiContract.errorHandling.format` — 若為 `ProblemDetailsWithValidationErrors`,須處理 `errors` 物件中的逐欄錯誤訊息;若為 `ProblemDetails`,只顯示 `detail`。
|
||
|
||
**語系文案:** 欄位 label 與按鈕文字取自 `pageContract.forms[].fields[].label` 和 `pageContract.actions[].label`,放入 `src/language/` 對應語系 key。
|
||
|
||
## 完成前驗證
|
||
|
||
- Vue / TypeScript 結構有變更:`pnpm -s type-check`
|
||
- 需要確認產物可建置:`pnpm -s build`
|
||
- Markdown 或大量搬移:`git diff --check`
|
||
- route、layout 或主要畫面流程有變更:啟動 dev server 並用瀏覽器確認,除非使用者明確不需要。
|
||
|
||
如果無法執行驗證,回報原因,不要宣稱已驗證。
|