diff --git a/AGENTS.md b/AGENTS.md index 72c94ab..01bd88f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,12 @@ - ❌ `useStudentCrudCommands.ts` → ✅ `useCrudCommands.ts` - ✅ `models/student.ts`, `stores/students.ts` — domain layer, specific names are correct +## GUIDE.md 寫作規則 + +- `src/**/GUIDE.md` 只保留該層/目錄的**約束、慣例與索引**,不要塞入詳細 API 文件。 +- 當新增 pattern、目錄或慣例影響層邊界時,建立或更新對應的 `src/**/GUIDE.md`,並確保 `docs/llm-development-guide.md` 將其列入索引。 +- 元件的 Props/Slots/Emits 詳細說明放在各子目錄的 `GUIDE.md`(如 `src/components/base/GUIDE.md`、`src/components/sections/GUIDE.md`),不要放在上層 `src/components/GUIDE.md`。 + ## Stack - Framework: Vue 3 + Vite - UI Library: Vuetify diff --git a/docs/architecture-strategy.md b/docs/architecture-strategy.md index dd33a7e..9159571 100644 --- a/docs/architecture-strategy.md +++ b/docs/architecture-strategy.md @@ -443,4 +443,4 @@ views/xxx.vue --- -*本文件取代 `docs/frontend-layering.md` 與 `src/components/README.md` 成為新增功能與重構的最高準則。既有檔案可保留作為歷史參考,但後續開發以本文為準。* +*本文件取代 `docs/frontend-layering.md` 與 `src/components/GUIDE.md` 成為新增功能與重構的最高準則。既有檔案可保留作為歷史參考,但後續開發以本文為準。* diff --git a/docs/llm-development-guide.md b/docs/llm-development-guide.md index c54a4f3..2ca33fc 100644 --- a/docs/llm-development-guide.md +++ b/docs/llm-development-guide.md @@ -24,6 +24,8 @@ | 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` | @@ -64,43 +66,6 @@ - 錯誤頁:讀 `src/views/GUIDE.md`(ErrorShell 模式)與 `src/router/GUIDE.md`(錯誤頁路由慣例)。 - 語系文案:讀 `src/language/GUIDE.md`。 -## 環境變數(.env 檔案) - -Vite 會依 mode 自動載入對應層級的 `.env` 檔案,優先順序由高到低: - -``` -.env.[mode].local ← 本機覆蓋,不提交(最高優先) -.env.[mode] ← mode 專用 -.env.local ← 本機覆蓋,不提交 -.env ← 所有 mode 通用 -``` - -專案實際使用與版本控制規則: - -| 檔案 | 用途 | Git | -|------|------|-----| -| `.env.example` | 範本檔,列出所有可用變數與說明 | 提交 | -| `.env` | 所有 Vite 指令皆載入(serve / build) | 忽略 | -| `.env.development` | `vite serve`(mode=development)載入 | 忽略 | -| `.env.development.local` | 本機開發機密值(帳號密碼等) | 忽略 | -| `.env.production` | `vite build`(mode=production)載入 | 忽略 | - -**新增環境變數時應遵守的順序:** - -1. 在 `.env` 或 `.env.development` 中新增變數並給定預設值 -2. 在 `.env.example` 中加入該變數的說明與格式,供其他開發者參考 -3. 若變數包含機密資訊(帳號、密碼、token),僅放在 `.env.development.local`,不要寫入 `.env.example` 的預設值 - -**現有變數說明:** - -| 變數 | 適用檔案 | 說明 | -|------|----------|------| -| `VITE_PROXY_TARGET` | `.env`, `.env.development`, `.env.development.local` | dev server proxy 目標後端 URL | -| `VITE_API_BASE_URL` | `.env`, `.env.development`, `.env.production` | API 請求 base URL,dev 用相對路徑走 proxy,prod 用完整 URL | -| `VITE_SKIP_LOGIN` | `.env.development` | 登入示範開關,`true` 時略過登入流程 | -| `VITE_DEV_DEFAULT_USER_ID` | `.env.development.local` | 本機開發示範帳號 | -| `VITE_DEV_DEFAULT_PASSWORD` | `.env.development.local` | 本機開發示範密碼 | - ## 修改前檢查 - 是否碰到 template core。 diff --git a/src/components/GUIDE.md b/src/components/GUIDE.md index 59e02d0..3b2514b 100644 --- a/src/components/GUIDE.md +++ b/src/components/GUIDE.md @@ -1,25 +1,29 @@ # Components Guide -`components` 放 Vue UI 元件。元件以 props 接收資料,以 emits 回報事件;不要直接處理 route、HTTP client、token/session 或全域流程。 +`src/components` 放 Vue UI 元件,包含 layout、page component、feature/domain component 與少量跨頁共用元件。 ## 分層 -- `pages/`:完整頁面組裝,檔名使用 `Page` 前綴。 -- `sections/`:頁面區塊容器,例如搜尋區、表格、dialog shell、panel。 -- `items/`:單筆資料、欄位群組或原子級呈現。 -- `layouts/`:app shell layout。詳見 `src/components/layouts/GUIDE.md`。 -- `base/`:真正跨頁共用且不屬於特定 domain 的基礎元件。 -- `login/`:登入頁專用 UI。 -- `maint/`:maintenance demo 舊有或領域型 UI 元件。 +| 目錄 | 說明 | 指南 | +|------|------|------| +| `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 元件 | — | ## 規則 -- 不假設元件全域註冊;使用時明確 import。 -- route component 放在 `views`,不要放在 `components`。 +- 不要假設 `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 中。 -- 只服務單一 domain 的元件放在 domain/feature 目錄,不放進 `base`。 ## 命名 @@ -27,3 +31,7 @@ - Section component:`SectionXxx.vue` - Item component:`ItemXxx.vue` - Layout component:依 shell/區塊命名,例如 `MainLayout.vue` + +## 資料流 + +component 以 props 接收資料,以 emit 回報使用者事件。需要跨頁共享的狀態交給 `src/stores`;可重用流程或較複雜 UI state 放到 `src/composables`。 diff --git a/src/components/README.md b/src/components/README.md deleted file mode 100644 index fd44950..0000000 --- a/src/components/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Components - -`src/components` 放 Vue 元件,包含 layout、page component、feature/domain component 與少量跨頁共用元件。 - -## 目前結構 - -- `PageLogin.vue`、`PageIndex.vue`、`PageMaint.vue`:頁面型元件,接收 view 組好的資料與事件,負責完整頁面主畫面組裝。 -- `layouts/*`:app shell 與 layout 子元件。`MainLayout.vue` 負責主框架,`PlainLayout.vue` 負責不套主框架的頁面。 -- `layouts/main-layout/*`:`MainLayout.vue` 拆出的 drawer、app bar、breadcrumb、favorites 等骨架子元件。 -- `login/*`:登入頁專用 UI 區塊,服務 `PageLogin.vue`。 -- `maint/*`:maintenance 領域元件,服務 `views/maint/*`。 -- `maint/master-detail/*`:master-detail 維護頁專用子元件。 -- `base/*`:真正跨頁重用且不屬於特定 domain 的基礎元件。 - -## 使用規則 - -- 不要假設 `src/components` 會自動全域註冊元件;需要使用元件時,依照目前 Vue SFC 慣例明確 import。 -- 直接被 route 載入的檔案放在 `src/views`,不要放在 `src/components`。 -- 負責完整頁面主畫面組裝的元件使用 `Page` 前綴。 -- 只服務單一功能或 domain 的元件,放在對應資料夾,不要放進 `base`。 -- layout 元件只處理 app shell 與框架 UI,不放頁面專屬業務流程。 - -## 資料流 - -component 以 props 接收資料,以 emit 回報使用者事件。需要跨頁共享的狀態交給 `src/stores`;可重用流程或較複雜 UI state 放到 `src/composables`。 diff --git a/src/components/base/BaseFormSelect.vue b/src/components/base/BaseFormSelect.vue new file mode 100644 index 0000000..c4fa7fd --- /dev/null +++ b/src/components/base/BaseFormSelect.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/components/base/BaseFormTextField.vue b/src/components/base/BaseFormTextField.vue new file mode 100644 index 0000000..e3b654d --- /dev/null +++ b/src/components/base/BaseFormTextField.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/components/base/GUIDE.md b/src/components/base/GUIDE.md new file mode 100644 index 0000000..9299bd1 --- /dev/null +++ b/src/components/base/GUIDE.md @@ -0,0 +1,46 @@ +# Base Components Guide + +`src/components/base` 放真正跨頁共用且不屬於特定 domain 的基礎元件。 + +## 規則 + +- 只服務單一 domain 的元件不要放進 `base`。 +- 命名不使用 `Page`/`Section`/`Item` 前綴,直接以功能命名。 + +## BaseFormTextField + +前置 label + `v-text-field`,預設 `variant="outlined"`、`density="compact"`、`hide-details`。 + +| Prop | 型別 | 預設 | 說明 | +|------|------|------|------| +| `modelValue` | `string` | — | 雙向綁定字串值 | +| `label` | `string` | `undefined` | `#prepend` 內 `` 的文字 | +| `labelCharCount` | `number` | `undefined` | 字數,用於計算 `min-width: 字數 × 0.785rem` | +| `prependMarginEnd` | `number` | `8` | `#prepend` 的 `margin-inline-end`(px) | +| `readonly` | `boolean` | `undefined` | 是否唯讀 | + +```vue + +``` + +## BaseFormSelect + +前置 label + `v-select`,預設 `variant="outlined"`、`density="compact"`、`hide-details`。 + +| Prop | 型別 | 預設 | 說明 | +|------|------|------|------| +| `modelValue` | `any` | — | 雙向綁定值 | +| `items` | `any[]` | — | `v-select` 的 `items` | +| `label` | `string` | `undefined` | `#prepend` 內 `` 的文字 | +| `labelCharCount` | `number` | `undefined` | 字數,用於計算 `min-width` | +| `prependMarginEnd` | `number` | `8` | `#prepend` 的 `margin-inline-end`(px) | + +```vue + +``` diff --git a/src/components/sections/GUIDE.md b/src/components/sections/GUIDE.md new file mode 100644 index 0000000..290f6e2 --- /dev/null +++ b/src/components/sections/GUIDE.md @@ -0,0 +1,84 @@ +# Section Components Guide + +`src/components/sections` 放頁面區塊容器,例如搜尋區、表格、dialog shell、panel。 + +## 規則 + +- 決定布局與區塊互動,不知道 route。 +- 檔名使用 `Section` 前綴。 + +## SectionFormPage + +表單申請/填寫頁面通用外殼。最外層為 `v-form`,內含標題卡片、表單欄位區、子區段插槽、配合事項與動作按鈕列。 + +### 使用時機 + +- 頁面包含**送出/存檔按鈕**(`type="submit"`) +- 需要**表單驗證**與整體 `v-form` 包覆 +- 具有**標題卡片**、**配合事項/注意事項區**、**動作按鈕列**的固定結構 +- 例如:申請單、借用單、報名表、維護單等填寫頁面 + +不適用情境:純粹列表/查詢頁面(無送出按鈕)、結構差異過大的頁面。 + +### Props + +| Prop | 型別 | 預設 | 說明 | +|------|------|------|------| +| `title` | `string` | — | 頁面標題 | +| `loading` | `boolean` | `undefined` | 是否顯示 loading | +| `error` | `string` | `undefined` | 錯誤訊息 | +| `message` | `string` | `undefined` | 成功訊息 | +| `submitLabel` | `string` | `'存檔'` | 送出按鈕文字 | +| `resetLabel` | `string` | `'清除'` | 清除按鈕文字 | +| `backLabel` | `string` | `'返回'` | 返回按鈕文字 | + +### Slots + +| Slot | 用途 | +|------|------| +| `#fields` | 表單欄位區,用 `v-row`/`v-col` 配置 | +| `#sections` | 額外子區段卡片(明細、表格等) | +| `#notices` | 配合事項/注意事項清單 | + +### Emits + +| Emit | 說明 | +|------|------| +| `@submit` | 點擊存檔時觸發 | +| `@reset` | 點擊清除時觸發 | +| `@back` | 點擊返回時觸發 | + +### 範例 + +```vue + + + + + + + +``` diff --git a/src/components/sections/SectionFormPage.vue b/src/components/sections/SectionFormPage.vue new file mode 100644 index 0000000..fa26773 --- /dev/null +++ b/src/components/sections/SectionFormPage.vue @@ -0,0 +1,58 @@ + + +