docs: update LLM guides for models and layout rules
Document new GUIDE.md expectations for src-layer edits and add index entries for models and shared types. Clarify layout usage, composable placement, error page conventions, and model/type ownership so future changes follow the intended layer boundaries.docs: update LLM guides for models and layout rules Document new GUIDE.md expectations for src-layer edits and add index entries for models and shared types. Clarify layout usage, composable placement, error page conventions, and model/type ownership so future changes follow the intended layer boundaries.
This commit is contained in:
@@ -4,8 +4,9 @@
|
||||
- Follow the existing code style and patterns.
|
||||
- Use pnpm for running project commands.
|
||||
- Keep code in TypeScript unless migration is required.
|
||||
- Before modifying or adding files in a `src/` subdirectory, read the corresponding `src/**/GUIDE.md` to understand the layer's constraints and conventions. Use `docs/llm-development-guide.md` as the index to find which GUIDE applies.
|
||||
- When the change introduces a new pattern, directory, or convention that affects layer boundaries, create or update the relevant `src/**/GUIDE.md` and ensure `docs/llm-development-guide.md` indexes it.
|
||||
- When refactoring or creating new components, review `docs/architecture-strategy.md` first and follow its layering and responsibility guidelines.
|
||||
- When a change affects LLM editing boundaries, page creation flow, layout usage, login-page boundaries, or frontend layering rules, update `docs/llm-development-guide.md` in the same change.
|
||||
- For UI debugging that spans implementation, state flow, and live browser behavior, use subagents deliberately: one for component contracts and event flow, one for data sources / routing / integration, and one for live browser verification. Do not edit files until the evidence from those threads converges on a root cause.
|
||||
- Treat subagent output as scoped evidence, not as a final answer. Use subagents to narrow the search space, confirm or eliminate hypotheses, and reduce local context load before making edits.
|
||||
- When a problem is directly tied to Vuetify component behavior, props, slots, accessibility output, or generated DOM, consult Vuetify MCP and official Vuetify API documentation before changing the implementation. Prefer supported Vuetify props, slots, and documented extension points over custom replacements unless the documented API is insufficient.
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
| 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` |
|
||||
|
||||
## 預設修改策略
|
||||
@@ -57,6 +59,9 @@
|
||||
- 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`。
|
||||
|
||||
## 修改前檢查
|
||||
@@ -67,6 +72,7 @@
|
||||
- 是否應拆成 page / section / item。
|
||||
- 是否應新增 page driver 或 command composable。
|
||||
- 是否需要 store,或只需要頁面內 state。
|
||||
- 是否應定義新的 model 型別(`src/models/`)。
|
||||
- 是否需要更新語系、menu、breadcrumb、favorites。
|
||||
|
||||
## 完成前驗證
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
`components/layouts` 是 app shell layout。一般功能需求不應修改這裡。
|
||||
|
||||
## 可用 Layout
|
||||
|
||||
- **MainLayout**(`layout: 'default'`):完整 app shell,包含 drawer、app bar、breadcrumb、favorites、toolbar actions 與主內容 slot。
|
||||
- **PlainLayout**(`layout: 'none'`):極簡空白佈局,只提供 `<v-app>` / `<v-main>` 外殼與一個 slot。登入頁、錯誤頁、維護中頁使用此 layout。
|
||||
|
||||
一般功能頁面統一使用 `layout: 'default'`。
|
||||
|
||||
## MainLayout 責任
|
||||
|
||||
- drawer
|
||||
@@ -20,3 +27,13 @@
|
||||
- domain-specific 狀態
|
||||
|
||||
如果頁面要影響 breadcrumb、favorites、menu 或 toolbar,優先使用 route meta、store 或 `shell/AppShell.vue` 已提供的 props/events。
|
||||
|
||||
## `main-layout/` 子目錄
|
||||
|
||||
`src/components/layouts/main-layout/` 收納 MainLayout 拆解出的子組件與共用的型別定義:
|
||||
|
||||
- `types.ts`:`AdminLayoutMenuItem`、`AdminLayoutBreadcrumbItem`、`AdminLayoutFeatures` 等型別,供 layout composable 與 shell 使用。
|
||||
- `DrawerDesktopMenu.vue` / `DrawerMobileMenuPanel.vue` / `DrawerMobileFavoritesPanel.vue`:桌面與行動版 drawer 內容。
|
||||
- `AppBarTopCol.vue` / `AppBarBreadcrumbCol.vue` / `AppBarFavoritesCol.vue`:app bar 不同列的組件。
|
||||
|
||||
一般功能需求不應修改這裡的檔案。
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
- `layout/`:AppShell / layout 狀態與事件協調。
|
||||
- `maint/`:maintenance demo 的表單、CRUD、editable grid 狀態。
|
||||
|
||||
頂層也可放通用 composable,例如 `useApiCall.ts`:封裝 loading / data / error / execute 模式、自動 snackbar 錯誤提示與取消請求過濾。適合為單一 API 呼叫提供輕量狀態管理,但不替代 page driver 或 command composable。
|
||||
|
||||
## 新增規則
|
||||
|
||||
- 用 `useXxx.ts` 命名。
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Models Guide
|
||||
|
||||
`models` 放 domain model 與 page model 型別定義。model 只定義形狀(interface/type),不含業務邏輯、API 呼叫或 UI 狀態。
|
||||
|
||||
## 種類
|
||||
|
||||
- **Domain Model**:特定領域的資料型別,例如 `StudentRecord`。檔名用 domain 命名(`student.ts`),型別使用 domain 前綴。
|
||||
- **Page Model**:`page.ts` 定義頁面驅動資料的 union type,供 page driver 組裝後傳給 page component。例如 `BasePageModel`、`MaintenancePageModel`。
|
||||
|
||||
## 規則
|
||||
|
||||
- 用 interface 或 type,不加 class。
|
||||
- domain model 應與 service response / store state 共用型別來源。
|
||||
- page model 僅定義畫面需要的欄位,不鏡像整個 service response。
|
||||
- 不 import component、view、store、composable。
|
||||
- 型別 export 時明確命名,避免與其他層混淆。
|
||||
|
||||
## Page Model 慣例
|
||||
|
||||
`src/models/page.ts` 定義基礎型別與 union:
|
||||
|
||||
- `BasePageModel`:所有頁面共用欄位(`title`、`loading`、`error`)。
|
||||
- 各頁面的 specific model 擴展 `BasePageModel`(例如 `MaintenancePageModel` 加 `type`、`records`)。
|
||||
- `PageModel` union 供 page component props 型別使用。
|
||||
|
||||
新增頁面類型時,先擴充 `PageModel` union 再新增對應的 page driver。
|
||||
+26
-3
@@ -23,9 +23,32 @@ meta: { layout: 'default' }
|
||||
meta: { layout: 'none' }
|
||||
```
|
||||
|
||||
## Auth Meta
|
||||
|
||||
| Meta | 效果 |
|
||||
|------|------|
|
||||
| `requiresAuth: true` | 未登入時導向 login,附 `redirect` query |
|
||||
| `guestOnly: true` | 已登入時導向 home(含 `VITE_SKIP_LOGIN` 啟用時) |
|
||||
| `roles: string[]` | RBAC,缺任一角色時導向 `/403` |
|
||||
|
||||
以上 meta 只在 `registerGuards` 中消費,不要在 component 裡重複檢查。
|
||||
|
||||
## 錯誤頁路由慣例
|
||||
|
||||
錯誤頁(403/500/503/network/maintenance/not-found)統一使用:
|
||||
|
||||
```ts
|
||||
meta: { title: 'Forbidden', layout: 'none' }
|
||||
```
|
||||
|
||||
- `layout: 'none'` 使頁面不被 `MainLayout` 包住,自己獨立渲染。
|
||||
- catch-all `/:pathMatch(.*)*` 放在路由陣列最後。
|
||||
- 錯誤頁 view 通常使用 `ErrorShell.vue` 共用組件,只傳入 props,不用重複寫佈局。
|
||||
|
||||
## Guards
|
||||
|
||||
- 登入需求使用既有 `requiresAuth` meta。
|
||||
- 訪客專用頁使用既有 `guestOnly` meta。
|
||||
- guard 流程放在 `guards.ts`,不要散落在 view/component。
|
||||
- catch-all route 保持在最後。
|
||||
- `beforeEach`:登入檢查、RBAC、`VITE_SKIP_LOGIN` 跳過。
|
||||
- `beforeResolve`:輕量前置工作(例如進度條)。
|
||||
- `afterEach`:document title、追蹤。
|
||||
- `onError`:chunk load 失敗等。
|
||||
|
||||
@@ -17,6 +17,14 @@ component/view -> store/composable -> service module -> httpClient -> hooks
|
||||
- request option 可接收 `signal`。
|
||||
- 錯誤正規化交給既有 error/http hooks 流程。
|
||||
|
||||
## 錯誤處理體系
|
||||
|
||||
- `error.ts`:定義 `ApiRequestError`(正規化後的錯誤類別)、`CanceledRequestError`(取消請求)、`normalizeError()`(將 ky HTTPError / TimeoutError / DOMException 統一轉為 `ApiRequestError`)。
|
||||
- `http-error.ts`:ky `beforeError` hook,將 response body 的錯誤訊息注入 error 物件。
|
||||
- `http-toast.ts`:全域 HTTP error toast,依 status code 顯示對應 snackbar。
|
||||
|
||||
service module 不需要自行 catch 並處理錯誤,交由 interceptors/hooks 與上層 composable(如 `useApiCall`)處理。
|
||||
|
||||
## ky 注意事項
|
||||
|
||||
- 本專案使用 ky,不使用 axios。
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Types Guide
|
||||
|
||||
`types` 放跨模組共用的 TypeScript 型別定義,例如 API 回應格式(`ApiError`)、認證相關型別(`User`、`LoginPayload`、`CaptchaResponse`)。
|
||||
|
||||
## 規則
|
||||
|
||||
- 只放純型別(interface / type),不放邏輯、class、常數或 runtime code。
|
||||
- 型別應小而聚焦,避免一個大雜燴檔。
|
||||
- 與 `models/` 的區別:`types/` 偏向 API 協定層(request/response、錯誤格式),`models/` 偏向領域實體與 page model。
|
||||
- 不 import component、view、store、composable。
|
||||
+1
-1
@@ -29,4 +29,4 @@ const page = useReportsPage()
|
||||
## 子目錄
|
||||
|
||||
- `views/maint` 是 maintenance demo route entry。詳見 `src/views/maint/GUIDE.md`。
|
||||
- `views/errors` 是錯誤頁入口,通常使用 `meta.layout = 'none'`。
|
||||
- `views/errors` 是錯誤頁入口,通常使用 `meta.layout = 'none'`。每個錯誤頁(`Forbidden.vue`、`ServerError.vue`、`NotFound.vue` 等)只傳入 props 給共用的 `ErrorShell.vue`,不再各自重複佈局邏輯。`ErrorShell.vue` 提供標題、圖示、顏色、描述、後端訊息、操作按鈕(返回上頁 / 回首頁 / 前往登入)等 slots。
|
||||
|
||||
Reference in New Issue
Block a user