Files
skt-vuetify-templates/src/services/README.md
T
skytek_xinliang 71683482e1 refactor: ky
2026-05-07 11:17:30 +08:00

3.9 KiB
Raw Blame History

Services

src/services 是資料存取與 HTTP 邊界,負責封裝 ky client、hooks、token/session、錯誤處理與 API 模組。

目前資料流

component/view -> store/composable -> service module -> httpClient -> hooks

原則:

  • component 不直接處理底層 HTTP client、token、hooks 或錯誤正規化。
  • store 或 composable 負責協調 UI 狀態與呼叫 service。
  • service 回傳資料,不持有 UI 狀態。
  • service 不 import component、view 或 store。

目前檔案

  • client.ts:建立單一 ky instance,設定 prefix、timeout、credentials 與 hooks。
  • interceptors.ts:集中提供 ky hooks,處理 request token 注入與 response 錯誤。
  • error.ts:提供 normalizeError() 與統一錯誤型別。
  • http-error.ts:提供全域 HTTP 錯誤事件。
  • http-toast.ts:提供 HTTP 錯誤提示相關流程。
  • token.ts:提供 token 單一來源,並同步 localStorage。
  • session.ts:提供 session 相關流程。
  • modules/auth.ts:封裝登入與驗證碼 API。
  • modules/menu.ts:封裝選單與收藏選單 API。

API 模組規則

新增 API 時,優先放在 src/services/modules/<domain>.ts

API module 應:

  • 使用 httpClient 發 request。
  • 匯出清楚命名的 API 物件,例如 authApimenuApi
  • 定義與該 module 相關的 request/response 型別。
  • 接收 AbortSignal 等 request option,但不管理頁面 loading 或 controller 狀態。

ky 使用注意事項

本專案使用 ky,不使用 axios。新增或調整 API module 時注意:

  • ky 不回傳 axios 的 { data, status, headers } 物件。需要 JSON 時使用 .json<T>()
  • 若呼叫端已經依賴 { data } 形狀,請在 API module 內包回 { data: await ... },不要讓 store 或 component 混用多種 response 形狀。
  • ky 的錯誤型別是 HTTPErrorTimeoutError 等,不是 AxiosError。錯誤一律交給 normalizeError(),呼叫端不要直接判斷 ky error。
  • ky 基於 Fetch API,取消請求使用原生 AbortControllersignal
  • token 注入、401 force logout、HTTP 錯誤導頁與 toast 都集中在 ky hooks。不要在單一 service module 裡重複實作。
  • FormData 請用 body: formDataJSON payload 請用 json: payload
  • 如果需求需要 upload progress、request/response transform、或其他 axios 專屬行為,先確認 ky/fetch 是否有等價做法,再決定是否擴充 service layer。

HTTP Client 設定

client.tsbaseURL 優先使用 VITE_API_BASE_URL,否則使用 /service/api。開發模式下,Vite proxy 會將 /service/* 轉送到後端。

template 提供 .env.example 作為環境變數範本。建立新專案時,複製成 .env 或對應 mode 的 env 檔,再填入實際 API 設定。

cp .env.example .env

目前 vite.config.mts 的 dev proxy 會將 /service/ 轉送到範例後端。正式專案若後端不同,優先調整 env 或 Vite proxy 設定,不要逐一修改 service module 裡的 endpoint。

production 不應沿用 template 內的示範後端位址,應由使用專案自己的部署環境提供 VITE_API_BASE_URL

目前 API 呼叫範例:

  • authApi.getCaptcha() -> /Auth/get-captcha
  • authApi.login() -> /Auth/login
  • menuApi.getMenu() -> /Menu/GetMenu
  • menuApi.getFavorite() -> /Menu/GetFavorite

Token 與錯誤處理

token 由 tokenService 作為單一來源:

  • store 負責登入成功後寫入 token,以及登出時清除 token。
  • hooks 只讀取 token 並附加到 request。
  • 401 或 HTTP 錯誤由 hooks 與錯誤事件流程集中處理。

錯誤透過 normalizeError() 轉成 UI 可理解的格式。UI 或 store 不需要直接理解 ky 的 HTTPError。

請求取消

需要取消請求時,由 store 或 composable 建立 AbortControllerservice module 只接收 signal。不要讓 service module 持有 controller 或 UI 狀態。