Files
skt-vuetify-templates/src/components/layouts/MAIN_LAYOUT_SPEC.md
T
skytek_xinliang a45563685f docs: refresh template documentation and examples
Update README and frontend layering docs to reflect the current template core structure, use relative repository links, and remove outdated demo guidance.

Add expanded API response examples for common features and ignore local Codex configuration.docs: refresh template documentation and examples

Update README and frontend layering docs to reflect the current template core structure, use relative repository links, and remove outdated demo guidance.

Add expanded API response examples for common features and ignore local Codex configuration.
2026-05-11 15:45:31 +08:00

17 KiB
Raw Blame History

MainLayout 規格表

來源元件:src/components/layouts/MainLayout.vue

MainLayout 是預設後台版型的 app shell,負責組合側邊選單、頂部工具列、常用功能列、breadcrumb、內容區與輔助視窗。元件本身不直接呼叫後端 API;所有資料都透過 props 傳入,互動則透過 emit 交給外層處理。

功能總覽

功能區塊 功能說明 主要輸入 主要輸出事件 需要後端 API
系統品牌區 顯示系統標題、副標題,或由 title slot 覆蓋。 systemTitle, systemSubtitle, title slot 否,目前為 props/default。
使用者資訊 顯示使用者頭像文字、姓名、角色。可用 feature toggle 關閉。 userProfile, features.showUserInfo 否,目前為 props/default。
側邊選單 桌面版顯示多層 drawer menu;支援展開群組、收合 rail、選單項目導頁。 menuItems, isRail, drawerConfig select, toggle-sidebar, update:isRail 是,menuItems 目前由 GetMenu 取得後轉換。
行動版選單 行動版 drawer 使用階層式選單面板,點擊有子層項目會進入下一層,點擊葉節點會選取並關閉 drawer。 menuItems, Vuetify display 狀態 select, toggle-sidebar 是,資料同 menuItems,目前由 GetMenu 取得後轉換。
行動版階層導覽 在 drawer 上方顯示「主選單」與目前進入的選單層級,可返回任一層。 menuItems 衍生出的 mobileMenuLevels 是,層級內容間接來自 GetMenu
常用功能列 桌面版顯示常用功能 chip,可選取、移除,也可顯示新增按鈕。 favoriteItems, favoritesConfig, favoritesBarVisible, features.showFavorites select, add-favorite, remove-favorite, update:favoritesBarVisible 否,目前不是由後端提供;GetFavorite 已有 service/store 方法但登入流程中未啟用。
行動版常用功能 行動版 drawer 可切換到常用功能面板並選取項目。 favoriteItems, features.showFavorites select 否,目前不是由後端提供。
搜尋列 輸入關鍵字後,按 Enter 或按鈕才觸發搜尋;觸發後清空輸入。 searchConfig, features.showSearch search 否,MainLayout 只送出關鍵字;目前外層用已載入的選單做前端比對。
工具列通知 顯示通知按鈕與 badge 數量。 toolbarActions.notificationsLabel, toolbarCounts.notifications action('notifications') 否,目前只是按鈕與 props 數字。
工具列訊息 顯示訊息按鈕與 badge 數量。 toolbarActions.messagesLabel, toolbarCounts.messages action('messages') 否,目前外層開啟示意訊息 dialog,沒有 API。
工具列設定 顯示設定 menu,可切換常用功能列與 breadcrumb 顯示狀態。 showFavoritesBar, breadcrumbBarVisible update:favoritesBarVisible, update:breadcrumbBarVisible 否,屬本機 UI 狀態。
登出 顯示登出按鈕,點擊後交由外層處理。 logoutLabel logout 否,layout 本身不呼叫 API。
主題切換 feature 開啟時顯示主題切換按鈕,透過 useThemeToggle 切換 Vuetify theme。 features.showThemeToggle, themeToggleLabel toggle-theme 否,本機 theme 狀態。
Breadcrumb 桌面版顯示目前頁面路徑;未傳入項目時顯示預設首頁。可插入 breadcrumb-actions slot。 breadcrumbItems, breadcrumbConfig, breadcrumbBarVisible, features.showBreadcrumb update:breadcrumbBarVisible, update:favoritesBarVisible 否,目前由外層依路由與已載入選單推導。
內容區 slot 承載各頁面內容,並依 app bar 高度動態設定 v-main padding。 default slot 否。
操作說明浮窗 收到 help action 時顯示暫時說明內容,可關閉。 toolbarActions.helpLabel action('help') 否,目前內容為靜態文字,且 help 按鈕在子元件中未顯示。

後端 API 需求

API 目前狀態 呼叫位置 提供給 MainLayout 的資料 Request Response 對應
Menu/GetMenu 已啟用 src/views/Login.vue 登入成功後呼叫 menuStore.getMenu(authStore.user?.id ?? '') menuItems { userID: string } res.data.data 存入 menuStore.menu,再由 toLayoutMenuItems() 轉成 layout 選單。
Menu/GetFavorite 未啟用 service/store 已存在,但登入流程呼叫被註解 { userID: string } 若未來啟用,可轉成 favoriteItems;目前不列為後端需求。

一般建議補齊的 API 配合清單

這份清單是以一般後台系統實作來看,列出 MainLayout 常見會需要後端配合的資料。現況仍只有 Menu/GetMenu 已接上;其餘項目可依產品需求決定是否實作。

類別 建議 API 對應 layout 功能 必要性 說明
選單與權限 Menu/GetMenu 側邊選單、行動版選單、前端選單搜尋、breadcrumb 推導 必要,已啟用 依使用者、角色、權限回傳可用功能。
使用者資訊 User/GetCurrentUserUser/GetProfile 使用者資訊區 userProfile 建議 回傳姓名、角色、單位、頭像文字或頭像 URL。現況使用 default props。
常用功能查詢 Menu/GetFavoriteFavorite/GetFavorites 常用功能列、行動版常用功能 建議 若常用功能要跨裝置保存,就應由後端提供。現況 service/store 已有 Menu/GetFavorite,但登入流程未啟用。
常用功能維護 Favorite/AddFavorite, Favorite/RemoveFavorite, Favorite/UpdateFavoriteOrder 新增常用、移除常用、常用排序 建議 現況常用功能主要由前端本機 store 處理;若要保存到帳號需補 API。
未讀數量 Notification/GetUnreadCounts 通知 badge、訊息 badge toolbarCounts 建議 可一次回傳 { notifications, messages },避免 layout 分別打多支 API。現況預設皆為 0
通知清單 Notification/GetNotifications 通知按鈕點擊後的通知列表 視需求 目前 layout 只 emit action('notifications'),外層尚未實作通知 UI。
通知已讀 Notification/MarkAsRead, Notification/MarkAllAsRead 通知清單互動、badge 歸零 視需求 若有通知列表,通常需要搭配已讀狀態更新。
訊息清單 Message/GetMessages 訊息按鈕點擊後的訊息 dialog 建議 現況 App.vue 使用示意資料,不含 API。
訊息已讀 Message/MarkAsRead, Message/MarkAllAsRead 訊息清單互動、badge 歸零 視需求 若訊息中心要顯示未讀數,通常需要已讀 API。
搜尋 Search/SearchMenuSearch/GlobalSearch 搜尋列 視需求 只搜尋目前已載入選單可維持前端搜尋;若要搜尋公告、頁面、業務資料或權限內功能,應補後端搜尋 API。
登出 Auth/LogoutAuth/RevokeToken 登出按鈕 視認證架構 若後端有 session、refresh token 或 token revoke 機制,需要呼叫後端;若只是清 local token,可維持前端處理。
使用者偏好 UserPreference/GetLayoutSettings, UserPreference/SaveLayoutSettings 側欄收合、常用列顯示、breadcrumb 顯示、主題 可選 目前可用 localStorage/store 處理;只有需要跨裝置同步時才需要 API。
操作說明 Help/GetPageHelp 或 CMS API 操作說明浮窗 可選 現況為靜態暫時文字,且 help 按鈕未顯示;若說明內容需依頁面、角色或版本管理才需要 API。

API 優先順序建議

優先順序 API / 功能 建議理由
1 Menu/GetMenu layout 最核心資料,決定使用者可見功能與導頁入口。
2 User/GetCurrentUser 使用者資訊區不應長期使用假資料,且常被其他功能共用。
3 Favorite/GetFavorites 與常用功能維護 API 常用功能若要符合使用者帳號體驗,需要後端保存。
4 Notification/GetUnreadCounts / Message/GetMessages toolbar badge 與訊息中心目前是 demo 狀態,若要上線需補。
5 Search/GlobalSearch 只有當搜尋範圍超過目前選單時才需要。
6 UserPreference 類 API 屬體驗同步,不影響核心操作,可最後處理。

建議 API 回傳格式

以下格式是給後端製作 API 時的建議契約。若沿用現有 service 包裝,前端實際讀取位置可能是 res.data.data;欄位命名可配合既有後端規範調整,但資料語意應保持一致。

Menu/GetMenu

{
  "success": true,
  "message": "",
  "data": [
    {
      "mdl_id": "student",
      "mdl_name": "學生資訊",
      "children": [
        {
          "unt_id": "course",
          "unt_name": "選課作業",
          "children": [
            {
              "fnc_id": "course-add",
              "fnc_name": "線上加選"
            }
          ]
        }
      ]
    }
  ]
}

User/GetCurrentUserUser/GetProfile

{
  "success": true,
  "message": "",
  "data": {
    "id": "A123456789",
    "name": "王小明",
    "role": "資訊工程系 - 學生",
    "avatarText": "王",
    "departmentId": "CS",
    "departmentName": "資訊工程系"
  }
}

Menu/GetFavoriteFavorite/GetFavorites

{
  "success": true,
  "message": "",
  "data": [
    {
      "id": "fav-1",
      "title": "線上加選",
      "path": "/course-add",
      "icon": "mdiPlus",
      "sort": 1
    }
  ]
}

Favorite/AddFavorite

{
  "success": true,
  "message": "新增成功",
  "data": {
    "id": "fav-1",
    "title": "線上加選",
    "path": "/course-add",
    "icon": "mdiPlus",
    "sort": 1
  }
}

Favorite/RemoveFavorite

{
  "success": true,
  "message": "移除成功",
  "data": {
    "id": "fav-1",
    "path": "/course-add"
  }
}

Favorite/UpdateFavoriteOrder

{
  "success": true,
  "message": "排序已更新",
  "data": [
    {
      "id": "fav-1",
      "path": "/course-add",
      "sort": 1
    },
    {
      "id": "fav-2",
      "path": "/score-query",
      "sort": 2
    }
  ]
}

Notification/GetUnreadCounts

{
  "success": true,
  "message": "",
  "data": {
    "notifications": 3,
    "messages": 12
  }
}

Notification/GetNotifications

{
  "success": true,
  "message": "",
  "data": {
    "items": [
      {
        "id": "notice-1",
        "title": "系統維護提醒",
        "content": "系統將於週六凌晨維護。",
        "source": "資訊中心",
        "publishedAt": "2026-05-07T09:00:00+08:00",
        "isRead": false,
        "link": "/announcements/notice-1"
      }
    ],
    "total": 1,
    "unreadCount": 1
  }
}

Notification/MarkAsRead

{
  "success": true,
  "message": "已標記為已讀",
  "data": {
    "id": "notice-1",
    "isRead": true,
    "unreadCount": 0
  }
}

Notification/MarkAllAsRead

{
  "success": true,
  "message": "已全部標記為已讀",
  "data": {
    "unreadCount": 0
  }
}

Message/GetMessages

{
  "success": true,
  "message": "",
  "data": {
    "items": [
      {
        "id": "msg-1",
        "title": "教務處公告",
        "summary": "加退選時間即將開始。",
        "sender": "教務處",
        "sentAt": "2026-05-07T10:30:00+08:00",
        "isRead": false,
        "link": "/messages/msg-1"
      }
    ],
    "total": 1,
    "unreadCount": 1
  }
}

Message/MarkAsRead

{
  "success": true,
  "message": "已標記為已讀",
  "data": {
    "id": "msg-1",
    "isRead": true,
    "unreadCount": 0
  }
}

Message/MarkAllAsRead

{
  "success": true,
  "message": "已全部標記為已讀",
  "data": {
    "unreadCount": 0
  }
}

Search/SearchMenuSearch/GlobalSearch

{
  "success": true,
  "message": "",
  "data": {
    "items": [
      {
        "id": "course-add",
        "type": "menu",
        "title": "線上加選",
        "path": "/course-add",
        "parents": ["學生資訊", "選課作業"],
        "icon": "mdiPlus"
      }
    ],
    "total": 1
  }
}

Auth/LogoutAuth/RevokeToken

{
  "success": true,
  "message": "登出成功",
  "data": {
    "revoked": true
  }
}

UserPreference/GetLayoutSettings

{
  "success": true,
  "message": "",
  "data": {
    "isRail": false,
    "favoritesBarVisible": true,
    "breadcrumbBarVisible": true,
    "themeName": "light"
  }
}

UserPreference/SaveLayoutSettings

{
  "success": true,
  "message": "設定已儲存",
  "data": {
    "isRail": false,
    "favoritesBarVisible": true,
    "breadcrumbBarVisible": true,
    "themeName": "light",
    "updatedAt": "2026-05-07T10:30:00+08:00"
  }
}

Help/GetPageHelp

{
  "success": true,
  "message": "",
  "data": {
    "pageKey": "home",
    "title": "操作說明",
    "content": "這裡顯示目前頁面的操作說明。",
    "updatedAt": "2026-05-07T10:30:00+08:00"
  }
}

可維持前端處理的功能

功能 原因
Breadcrumb 顯示與路徑推導 可由目前 route、menuItemsfavoriteItems 推導,不一定要後端提供。
側欄收合狀態 屬使用者介面偏好,localStorage 即可;除非要求跨裝置同步。
常用列顯示 / breadcrumb 顯示 屬畫面偏好,localStorage/store 即可。
主題切換 本機 theme 狀態即可;除非要求登入後跨裝置一致。
前端選單搜尋 若搜尋範圍只限已載入的 menuItems,不需要後端 API。

GetMenu 欄位轉換

後端節點層級 後端欄位 Layout 欄位 說明
模組層 mdl_name title 第一層選單標題。
模組層 children subItems 第二層單元清單。
單元層 unt_name title 第二層選單標題。
單元層 children subItems 第三層功能清單。
功能層 fnc_name title 葉節點功能名稱。
功能層 fnc_id path 有值時轉成 /${fnc_id},作為 router path。
模組層與單元層 navigable: false 群組節點預設不可導頁。

Props 與狀態來源

Prop / 狀態 用途 預設值或目前來源 後端需求
menuItems 桌面與行動版主選單。 App.vue 使用 menuStore.menuItems 加上固定選單合併後傳入。 是,來自 GetMenu
favoriteItems 常用功能列與行動版常用面板。 App.vue 合併 menuStore.favoriteItemsfavoritesStore.layoutItems;目前 GetFavorite 未啟用。 否。
breadcrumbItems Breadcrumb 顯示。 breadcrumbStore 依 route、menuItemsfavoriteItems 推導。 否。
userProfile 使用者資訊區。 MainLayout default props。 否。
toolbarCounts 通知、訊息 badge。 MainLayout default props,預設皆為 0 否。
searchConfig 搜尋 placeholder 與 label。 MainLayout default props。 否。
toolbarActions 通知、訊息、說明、設定 label。 MainLayout default props。 否。
favoritesConfig 常用列 label、新增按鈕 label、是否顯示新增。 MainLayout default props。 否。
breadcrumbConfig 首頁 breadcrumb label、disabled、icon。 MainLayout default props。 否。
features 控制主題切換、常用列、breadcrumb、搜尋、工具列、使用者資訊是否顯示。 MainLayout default props。 否。
drawerConfig drawer 寬度與 rail 寬度。 MainLayout default props。 否。
isRail 桌面側欄是否收合。 App.vuev-model:is-rail 綁定 menuStore.isRailstore 會寫入 localStorage。 否。
favoritesBarVisible 常用功能列是否顯示。 App.vuev-model:favorites-bar-visible 綁定 favoritesStore 否。
breadcrumbBarVisible Breadcrumb 是否顯示。 App.vuev-model:breadcrumb-bar-visible 綁定 favoritesStore 否。

事件契約

事件 觸發時機 外層目前處理
select(item) 選取側邊選單、常用功能或搜尋結果延伸選取時。 App.vue 呼叫 router.push(item.path)
search(keyword) 搜尋列按 Enter 或搜尋按鈕。 App.vue 以已載入的合併選單做前端搜尋並顯示 dialog。
action(type) 點擊通知、訊息、說明等工具列 action。 messages 會開啟訊息 dialog;其他目前無處理。
logout 點擊登出按鈕。 App.vue 清除 auth、tabs,導回 login。
toggle-sidebar(payload) 點擊 drawer 收合/展開按鈕。 目前外層未綁定。
toggle-theme(themeName) 切換主題成功。 目前外層未綁定。
add-favorite 點擊常用功能新增按鈕。 目前外層未綁定。
remove-favorite(item) 點擊常用 chip close。 App.vue 從本機常用清單切換移除。
update:isRail(value) 受控模式下更新側欄 rail 狀態。 v-model:is-rail 寫回 menuStore.isRail
update:favoritesBarVisible(value) 更新常用列顯示狀態。 v-model:favorites-bar-visible 寫回 favoritesStore
update:breadcrumbBarVisible(value) 更新 breadcrumb 顯示狀態。 v-model:breadcrumb-bar-visible 寫回 favoritesStore