From 96b96bcaaa15ea7269ae7bbcf6b5727154507f7b Mon Sep 17 00:00:00 2001 From: skytek_xinliang Date: Tue, 19 May 2026 14:13:10 +0800 Subject: [PATCH] docs: reorganize architecture strategy documentation Split current project diagnostics into a dedicated analysis document and trim the main architecture strategy to focus on core guidance. This makes the documentation easier to navigate and separates observed issues from recommended architectural principles.docs: reorganize architecture strategy documentation Split current project diagnostics into a dedicated analysis document and trim the main architecture strategy to focus on core guidance. This makes the documentation easier to navigate and separates observed issues from recommended architectural principles. --- docs/analyse-now.md | 47 + docs/architecture-strategy.md | 218 ++-- docs/llm-development-guide.md | 45 +- docs/what-apple-do.md | 81 ++ src/components/items/ItemFormFieldGroup.vue | 172 ++++ src/components/sections/SectionDataTable.vue | 169 ++++ src/components/sections/SectionFormPanel.vue | 282 ++++++ .../sections/SectionSearchPanel.vue | 102 ++ src/composables/commands/useCrudCommands.ts | 125 +++ .../maint/useMaintenanceCrudFlow.ts | 2 +- .../useSingleRecordMaintenancePage.ts | 258 +++++ src/views/maint/SingleRecord.vue | 949 +----------------- 12 files changed, 1373 insertions(+), 1077 deletions(-) create mode 100644 docs/analyse-now.md create mode 100644 docs/what-apple-do.md create mode 100644 src/components/items/ItemFormFieldGroup.vue create mode 100644 src/components/sections/SectionDataTable.vue create mode 100644 src/components/sections/SectionFormPanel.vue create mode 100644 src/components/sections/SectionSearchPanel.vue create mode 100644 src/composables/commands/useCrudCommands.ts create mode 100644 src/composables/page-drivers/useSingleRecordMaintenancePage.ts diff --git a/docs/analyse-now.md b/docs/analyse-now.md new file mode 100644 index 0000000..879c923 --- /dev/null +++ b/docs/analyse-now.md @@ -0,0 +1,47 @@ +## 二、我們專案的現況診斷 + +### 2.1 App.vue 過度臃腫(~590 行) + +| 職責 | 行數 | 應屬層級 | +|------|------|----------| +| Layout 切換 | ~20 | App Shell | +| Tabs 管理 | ~80 | Page Driver | +| Breadcrumb 組裝 | ~40 | Layout | +| Favorites 管理 | ~60 | Store | +| Search Dialog | ~80 | App Shell / Widget | +| Message Dialog | ~60 | App Shell / Widget | +| Snackbar | ~10 | Global Overlay | +| Logout / Force logout | ~30 | Auth Flow | +| HTTP Toast | ~20 | Service Layer | + +- **問題**:App.vue 同時承擔 App Shell、Page Driver、Global Widget、Auth Flow 四種責任。 +- **對比**:App Store 的 `App.svelte` 只有 161 行,只負責 `Navigation + PageResolver + Footer`。 + +### 2.2 Views 過厚(SingleRecord.vue ~830 行) + +- 混雜:表格呈現、搜尋表單、dialog 模板、表單狀態、CRUD 流程、驗證邏輯、分頁、snackbar。 +- **對比**:App Store 的 `ProductPage.svelte` 只有 77 行,只負責「把 page 轉成 DefaultPageRequirements + 一個 slot override」。 + +### 2.3 缺乏統一的頁面資料門面 + +``` +現況: + view → store → service(直接鏈式呼叫) + view 自己管理 loading / error / dialog visible + +App Store: + UI → jet.dispatch(intent) → runtime → controller → page model + UI 只接收 page model,不管理載入狀態 +``` + +### 2.4 Dialog 狀態與模板內嵌於 View + +- `SingleRecord.vue` 內含 5 個 `ConfirmDialog` 實例 + 1 個大 form overlay。 +- 任何 dialog 更動都需要修改 view 檔案。 + +### 2.5 沒有容器/內容分離的 Section 層 + +- 表格、表單、搜尋區塊都是直接寫在 view 或 page component 中。 +- 缺乏類似 `ShelfItemLayout` 的通用佈局抽象:「這一區是水平捲軸還是網格」應該由容器決定,裡面的內容元件不應該知道。 + +--- diff --git a/docs/architecture-strategy.md b/docs/architecture-strategy.md index d2ab4c7..667e03a 100644 --- a/docs/architecture-strategy.md +++ b/docs/architecture-strategy.md @@ -1,139 +1,19 @@ # 資料流與元件分層優化策略 -> 分析標的:`~/code/apps.apple.com-main`(Apple App Store Web — Svelte + Jet 架構) -> 適用目標:`/home/carl/git/skt-vuetify-templates`(Vue 3 + Vuetify + Pinia) -> 原則:不強制遷移既有程式碼,但所有新增功能與重構以本文件為最高準則。 - ---- - ## 一、Apple App Store 專案的核心架構特徵 -### 1.1 單一業務邏輯門面(Jet Facade) +1 單一業務邏輯門面 +2 Intent / Action 分離(查詢與命令) +3 Page Model 驅動 UI(資料驅動) +4 Shelf / Item 分層(容器與內容分離) +5 Svelte Context 作為跨層依賴注入 +6 命令式外殼 + 聲明式 UI -``` -browser.ts → bootstrap → Jet.load → runtime + objectGraph - ↓ - UI 層僅透過 jet.dispatch(intent) / jet.perform(action) 溝通 -``` - -- **Jet** 封裝所有業務邏輯:路由、資料取得、動作分發、metrics。 -- UI 層**不直接**呼叫 API、不直接操作 storage、不直接操作 history。 -- 所有外部依賴(fetch、storage、locale、user)統一注入 `Dependencies`,再組裝成 `ObjectGraph`。 - -### 1.2 Intent / Action 分離(查詢與命令) - -| 類型 | 職責 | 回傳值 | 例子 | -|------|------|--------|------| -| **Intent** | 取得頁面資料(Query) | `Promise` | `RouteUrlIntent` → 回傳 `ProductPage` | -| **Action** | 執行副作用(Command) | `'performed' \| 'unsupported'` | `FlowAction` → 導航到新頁面 | - -- `FlowAction` 是主要導航機制:內含 `destination Intent` + `pageUrl` + `presentationContext`。 -- Action handler 註冊採用**型別註冊制**:`jet.onAction('flowAction', handler)`。 - -### 1.3 Page Model 驅動 UI(資料驅動) - -```ts -// App.svelte 的介面極簡 -export let page: Promise | Page -``` - -- 整個應用由單一 `page` prop 驅動。 -- `PageResolver` 處理 `Promise` 的 loading / error 狀態。 -- `Page.svelte` 用 type guard 分發到對應的 page component:`isProductPage(page)` → ``。 -- **Page 是 union type**,不是 route-based 的硬編碼映射。 - -### 1.4 Shelf / Item 分層(容器與內容分離) - -``` -Page (TodayPage / ProductPage / ...) - └── Shelf[] (水平捲軸 / 網格) - └── ShelfItemLayout (佈局抽象:HorizontalShelf or Grid) - └── Item (BrickItem / LargeLockupItem / ...) -``` - -- **Shelf** = 容器邏輯:決定是水平捲軸還是網格、rowsPerColumn、邊框。 -- **ShelfItemLayout** = 佈局中介:根據 `isHorizontal` 選擇 `HorizontalShelf` 或 `Grid`。 -- **Item** = 純粹內容渲染:只關心單一資料單位的呈現,不知道自己是水平還是網格。 -- **FallbackShelf** = 優雅的降級策略:遇到未實作的 shelf 類型顯示 placeholder,不 crash。 - -### 1.5 Svelte Context 作為跨層依賴注入 - -```ts -// bootstrap.ts -context.set('jet', jet) -context.set('i18n', i18nStore) - -// 深層元件 -const jet = getJet() // 從 Svelte Context 取得 -const i18n = getI18n() // 從 Svelte Context 取得 -``` - -- 避免 props drilling:Jet、i18n、accessibility layout、today-card layout 都透過 context 傳遞。 -- Context 在啟動時注入,生命周期與應用一致,不是用來傳遞 UI 狀態的。 - -### 1.6 命令式外殼 + 聲明式 UI - -```ts -// browser.ts(命令式啟動層) -const app = new App({ target: container, context, hydrate: true }) -registerActionHandlers({ - jet, - updateApp: (props) => app.$set(props), // 橋接命令式 → 聲明式 -}) -``` - -- 導航、歷史管理、scroll 復原由命令式的 action handler 處理。 -- UI 渲染完全聲明式,只接收 `page` 與 `isFirstPage` 兩個 prop。 - ---- +Read only when needed: [what apple do](./what-apple-do.md) ## 二、我們專案的現況診斷 -### 2.1 App.vue 過度臃腫(~590 行) - -| 職責 | 行數 | 應屬層級 | -|------|------|----------| -| Layout 切換 | ~20 | App Shell | -| Tabs 管理 | ~80 | Page Driver | -| Breadcrumb 組裝 | ~40 | Layout | -| Favorites 管理 | ~60 | Store | -| Search Dialog | ~80 | App Shell / Widget | -| Message Dialog | ~60 | App Shell / Widget | -| Snackbar | ~10 | Global Overlay | -| Logout / Force logout | ~30 | Auth Flow | -| HTTP Toast | ~20 | Service Layer | - -- **問題**:App.vue 同時承擔 App Shell、Page Driver、Global Widget、Auth Flow 四種責任。 -- **對比**:App Store 的 `App.svelte` 只有 161 行,只負責 `Navigation + PageResolver + Footer`。 - -### 2.2 Views 過厚(SingleRecord.vue ~830 行) - -- 混雜:表格呈現、搜尋表單、dialog 模板、表單狀態、CRUD 流程、驗證邏輯、分頁、snackbar。 -- **對比**:App Store 的 `ProductPage.svelte` 只有 77 行,只負責「把 page 轉成 DefaultPageRequirements + 一個 slot override」。 - -### 2.3 缺乏統一的頁面資料門面 - -``` -現況: - view → store → service(直接鏈式呼叫) - view 自己管理 loading / error / dialog visible - -App Store: - UI → jet.dispatch(intent) → runtime → controller → page model - UI 只接收 page model,不管理載入狀態 -``` - -### 2.4 Dialog 狀態與模板內嵌於 View - -- `SingleRecord.vue` 內含 5 個 `ConfirmDialog` 實例 + 1 個大 form overlay。 -- 任何 dialog 更動都需要修改 view 檔案。 - -### 2.5 沒有容器/內容分離的 Section 層 - -- 表格、表單、搜尋區塊都是直接寫在 view 或 page component 中。 -- 缺乏類似 `ShelfItemLayout` 的通用佈局抽象:「這一區是水平捲軸還是網格」應該由容器決定,裡面的內容元件不應該知道。 - ---- +Read only when needed: [analyse now](./analyse-now.md) ## 三、優化後的資料流策略 @@ -188,7 +68,7 @@ App Store: ```ts // src/composables/usePageDriver.ts -export function useStudentMaintenancePage() { +export function useMaintenancePage() { const studentStore = useStudentStore() const { records, loading, error, load } = useCrudDriver({ store: studentStore, @@ -264,7 +144,7 @@ src/ │ ├── components/ │ ├── pages/ ← 新增:Page Component 層 -│ │ ├── PageStudentMaintenance.vue +│ │ ├── PageMaintenance.vue │ │ └── PageReport.vue │ │ │ ├── sections/ ← 新增:Section / Shelf 層 @@ -273,7 +153,7 @@ src/ │ │ └── SectionFormPanel.vue │ │ │ ├── items/ ← 新增:Item / Atom 層(領域獨立) -│ │ ├── ItemStudentRow.vue +│ │ ├── ItemDataRow.vue │ │ └── ItemFormField.vue │ │ │ ├── layouts/ ← 維持:App Shell Layout @@ -285,11 +165,11 @@ src/ │ ├── composables/ │ ├── page-drivers/ ← 新增:頁面資料協調 -│ │ └── useStudentMaintenancePage.ts +│ │ └── useMaintenancePage.ts │ ├── commands/ ← 新增:命令流程(對齊 Jet Action) -│ │ └── useStudentCrudCommands.ts +│ │ └── useCrudCommands.ts │ ├── forms/ ← 維持/重組:表單狀態機 -│ │ └── useStudentForm.ts +│ │ └── useForm.ts │ └── layout/ ← 維持 │ ├── models/ ← 新增:領域模型與 Page Union @@ -321,15 +201,18 @@ src/ ```vue ``` @@ -340,7 +223,7 @@ load() - **對齊**:App Store 的 `ProductPage.svelte`、`TodayPage.svelte`、`DefaultPage.svelte`。 ```vue - +