docs: expand LLM guide with spec-to-page mapping
Update the LLM development guide to prioritize src/GUIDE.md and add detailed `.spec.json` mapping rules for query, application, and maintenance pages. Clarify how page contracts, API contracts, actions, validation, naming, error handling, and i18n should drive generated composables and page components.docs: expand LLM guide with spec-to-page mapping Update the LLM development guide to prioritize src/GUIDE.md and add detailed `.spec.json` mapping rules for query, application, and maintenance pages. Clarify how page contracts, API contracts, actions, validation, naming, error handling, and i18n should drive generated composables and page components.
This commit is contained in:
@@ -8,13 +8,12 @@
|
||||
|
||||
## 建議閱讀順序
|
||||
|
||||
1. `README.md`
|
||||
1. `src/GUIDE.md`
|
||||
2. `docs/architecture-strategy.md`
|
||||
3. `src/GUIDE.md`
|
||||
4. 依變更範圍閱讀對應的 `src/**/GUIDE.md`
|
||||
5. `docs/add-page-example.md`(需要新增頁面時)
|
||||
3. 依 `maintenanceContract.pageKind` 閱讀對應的 `src/**/GUIDE.md`(查 `src/GUIDE.md` 中的「依 pageKind 選擇起點」表格)
|
||||
4. `docs/add-page-example.md`(需要新增頁面時)
|
||||
|
||||
`docs/frontend-layering.md` 是歷史參考,後續以 `docs/architecture-strategy.md` 與 `src/**/GUIDE.md` 為準。
|
||||
`frontend-layering.md` 是歷史參考,後續以 `docs/architecture-strategy.md` 與 `src/**/GUIDE.md` 為準。
|
||||
|
||||
## GUIDE 索引
|
||||
|
||||
@@ -92,6 +91,92 @@
|
||||
|
||||
判斷順序:先看有無「送出/存檔」→ 再看有無「查詢」→ 其餘視為一般列表頁。
|
||||
|
||||
## `.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/components/pages/PageSectionQueryPageDemo.vue`、`src/composables/page-drivers/useSectionsDemoPage.ts`
|
||||
|
||||
架構:
|
||||
```
|
||||
View (薄層) → composable (page driver) → PageSectionQueryPageDemo → SectionQueryPage
|
||||
```
|
||||
|
||||
**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`、`src/components/pages/PageSectionFormPageDemo.vue`
|
||||
|
||||
架構:
|
||||
```
|
||||
View (薄層) → composable (page driver) → PageSectionFormPageDemo → SectionFormPage
|
||||
```
|
||||
|
||||
**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 送出
|
||||
|
||||
**page component emits:**
|
||||
- `@submit` → 呼叫 `handleFormSubmit`
|
||||
- `@reset` → 呼叫 `resetForm`
|
||||
- `@back` → 呼叫 `handleFormBack`
|
||||
|
||||
### 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`
|
||||
|
||||
+53
-32
@@ -1,37 +1,58 @@
|
||||
# Components Guide
|
||||
# Src Guide
|
||||
|
||||
`src/components` 放 Vue UI 元件,包含 layout、page component、feature/domain component 與少量跨頁共用元件。
|
||||
`src` 是 template 使用者主要修改的區域。新增功能時,先從 route view、page component 與 page driver 開始,除非需求明確牽涉 app shell、登入、router guard 或 HTTP core,否則不要先改 template core。
|
||||
|
||||
## 分層
|
||||
|
||||
| 目錄 | 說明 | 指南 |
|
||||
|------|------|------|
|
||||
| `pages/` | 完整頁面組裝,檔名使用 `Page` 前綴 | — |
|
||||
| `sections/` | 頁面區塊容器,例如搜尋區、表格、dialog shell、panel | `sections/GUIDE.md` |
|
||||
| `items/` | 單筆資料、欄位群組或原子級呈現 | `items/GUIDE.md` |
|
||||
| `layouts/` | App shell layout | `layouts/GUIDE.md` |
|
||||
| `base/` | 真正跨頁共用且不屬於特定 domain 的基礎元件 | `base/GUIDE.md` |
|
||||
| `login/` | 登入頁專用 UI | — |
|
||||
| `maint/` | maintenance demo 舊有或領域型 UI 元件 | — |
|
||||
|
||||
## 規則
|
||||
|
||||
- 不要假設 `src/components` 會自動全域註冊元件;需要使用元件時,依照目前 Vue SFC 慣例明確 import。
|
||||
- 直接被 route 載入的檔案放在 `src/views`,不要放在 `src/components`。
|
||||
- 負責完整頁面主畫面組裝的元件使用 `Page` 前綴。
|
||||
- 只服務單一功能或 domain 的元件,放在對應資料夾,不要放進 `base`。
|
||||
- layout 元件只處理 app shell 與框架 UI,不放頁面專屬業務流程。
|
||||
- `pages` 可組合 sections/items,但不直接處理 API。
|
||||
- `sections` 決定布局與區塊互動,不知道 route。
|
||||
- `items` 不知道自己在表格、grid 或 dialog 中。
|
||||
|
||||
## 命名
|
||||
|
||||
- Page component:`PageXxx.vue`
|
||||
- Section component:`SectionXxx.vue`
|
||||
- Item component:`ItemXxx.vue`
|
||||
- Layout component:依 shell/區塊命名,例如 `MainLayout.vue`
|
||||
Template Core 與 Demo/Example 的完整清單見 `src/README.md`。
|
||||
|
||||
## 資料流
|
||||
|
||||
component 以 props 接收資料,以 emit 回報使用者事件。需要跨頁共享的狀態交給 `src/stores`;可重用流程或較複雜 UI state 放到 `src/composables`。
|
||||
```txt
|
||||
router -> AppShell -> layout -> view(Page Driver) -> Page Component -> Section -> Item
|
||||
↓
|
||||
page driver / command composable -> store -> service
|
||||
```
|
||||
|
||||
## 主要目錄
|
||||
|
||||
- `views/`:route entry,維持薄層,只做 route wiring 與 page driver 掛載。詳見 `src/views/GUIDE.md`。
|
||||
- `components/`:Vue UI 元件,依 pages / sections / items / layouts / base 分層。詳見 `src/components/GUIDE.md`。
|
||||
- `composables/`:page driver、command flow、layout flow 與可重用狀態流程。詳見 `src/composables/GUIDE.md`。
|
||||
- `router/`:route、layout meta、auth meta 與 guard。詳見 `src/router/GUIDE.md`。
|
||||
- `shell/`:AppShell、tabs、global overlays。詳見 `src/shell/GUIDE.md`。
|
||||
- `stores/`:跨頁共享狀態與快取。詳見 `src/stores/GUIDE.md`。
|
||||
- `services/`:HTTP client、API module、token/session、錯誤處理。詳見 `src/services/GUIDE.md`。
|
||||
- `language/`:Vue I18n 文案。詳見 `src/language/GUIDE.md`。
|
||||
|
||||
## 依 pageKind 選擇起點
|
||||
|
||||
`.spec.json` 中 `maintenanceContract.pageKind` 決定使用哪一種 demo 架構。完整欄位對照見 `docs/llm-development-guide.md` 的「`.spec.json` 對照指南」。
|
||||
|
||||
| pageKind | 參考 Demo | 讀取 GUIDE |
|
||||
| ------------- | ------------------------------------------ | -------------------------------------------------------- |
|
||||
| `query` | `src/views/demos/SectionQueryPageDemo.vue` | `src/components/sections/GUIDE.md`(SectionQueryPage) |
|
||||
| `application` | `src/views/demos/SectionFormPageDemo.vue` | `src/components/sections/GUIDE.md`(SectionFormPage) |
|
||||
| `maintenance` | `src/views/maint/*` | `src/views/maint/README.md` + `src/views/maint/GUIDE.md` |
|
||||
| `auth` | `src/views/Login.vue` | `src/views/GUIDE.md` |
|
||||
| `print` | query 或 application demo | 同 query / application |
|
||||
| `chooser` | 不適用 demo | 轉為 route group 或 tab |
|
||||
|
||||
## 新功能流程
|
||||
|
||||
1. 依 `pageKind` 選擇最接近的 demo。
|
||||
2. 在 `src/views/<domain>/` 新增 route view(薄層,只掛 page driver)。
|
||||
3. 在 `src/composables/page-drivers/` 新增 page driver composable。
|
||||
4. 在 `src/components/pages/` 新增 page component。
|
||||
5. 若畫面有獨立區塊,拆到 `src/components/sections/*`。
|
||||
6. 若區塊內有欄位群組,拆到 `src/components/items/*`。
|
||||
7. 在 `src/services/modules/` 新增 API module。
|
||||
8. 在 `src/models/` 定義 page model 與 domain model 型別。
|
||||
9. 在 `src/router/routes.ts` 新增 route。
|
||||
10. 在 `src/language/` 新增語系文案。
|
||||
|
||||
跨頁共享狀態才新增或修改 `src/stores/*`。
|
||||
|
||||
## 驗證
|
||||
|
||||
- Vue / TypeScript 結構變更:`pnpm -s type-check`
|
||||
- 需要確認產物:`pnpm -s build`
|
||||
- route、layout 或主要畫面流程變更:啟動 dev server 並做瀏覽器檢查,除非使用者明確不需要。
|
||||
|
||||
Reference in New Issue
Block a user