docs: refresh project guidance and environment setup
Add env example defaults for Vite API and login settings, document template structure and page creation flow, and align agent guidance with current LLM development rules. Also allow committing the env example while keeping local env files ignored.docs: refresh project guidance and environment setup Add env example defaults for Vite API and login settings, document template structure and page creation flow, and align agent guidance with current LLM development rules. Also allow committing the env example while keeping local env files ignored.
This commit is contained in:
@@ -5,3 +5,12 @@ args = ["chrome-devtools-mcp@latest", "--browserUrl", "http://localhost:9222"]
|
||||
[mcp_servers.code-review-graph]
|
||||
command = "uvx"
|
||||
args = ["code-review-graph", "serve"]
|
||||
|
||||
[mcp_servers.code-review-graph.tools.get_minimal_context_tool]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.code-review-graph.tools.query_graph_tool]
|
||||
approval_mode = "approve"
|
||||
|
||||
[mcp_servers.code-review-graph.tools.build_or_update_graph_tool]
|
||||
approval_mode = "approve"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Vite API base URL。
|
||||
# 使用 Vite dev proxy 時,建議維持相對路徑。
|
||||
VITE_API_BASE_URL=/service/api
|
||||
|
||||
# 登入示範開關。只有專案明確支援略過登入時才設為 true。
|
||||
VITE_SKIP_LOGIN=false
|
||||
|
||||
# 本機開發示範帳號。
|
||||
# 有後端或 demo 帳號時,複製到 .env.development.local 後填入。
|
||||
VITE_DEV_DEFAULT_USER_ID=
|
||||
VITE_DEV_DEFAULT_PASSWORD=
|
||||
@@ -28,6 +28,7 @@ output/playwright/
|
||||
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Playwright
|
||||
/test-results/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- Use pnpm for running project commands.
|
||||
- Keep code in TypeScript unless migration is required.
|
||||
- When refactoring or creating new components, review `docs/frontend-layering.md` first and follow its layering and responsibility guidelines.
|
||||
- For bulk verification failures such as `pnpm run lint`, collect the full output first, then split the work into non-overlapping batches by file or concern and assign those batches to subagents in parallel. Keep the integration and final verification pass in the main agent.
|
||||
- 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.
|
||||
@@ -13,7 +13,7 @@
|
||||
## Stack
|
||||
- Framework: Vue 3 + Vite
|
||||
- UI Library: Vuetify
|
||||
- Enabled Features: ESLint, Vuetify MCP, Pinia, Vue I18n, Vue Router
|
||||
- Enabled Features: Vuetify MCP, Pinia, Vue I18n, Vue Router
|
||||
|
||||
## Icon Usage
|
||||
```js
|
||||
|
||||
@@ -1,115 +1,153 @@
|
||||
# skt-vuetify-templates
|
||||
|
||||
Scaffolded with Vuetify CLI.
|
||||
Vue 3 + Vite + Vuetify template,目標是讓新專案可以直接在 `src` 裡新增 views、components、stores、services 與 composables,並讓一般頁面自動被主框架 layout 包住。
|
||||
|
||||
## ❗️ Documentation
|
||||
## Stack
|
||||
|
||||
- Primary docs: https://vuetifyjs.com/
|
||||
- Getting started guide: https://vuetifyjs.com/en/getting-started/installation/
|
||||
- Community support: https://community.vuetifyjs.com/
|
||||
- Issue tracker: https://issues.vuetifyjs.com/
|
||||
|
||||
## 🧱 Stack
|
||||
|
||||
- Framework: Vue 3 + Vite
|
||||
- UI Library: Vuetify
|
||||
- Language: TypeScript
|
||||
- Package manager: pnpm
|
||||
|
||||
## 🧭 Start Here
|
||||
|
||||
- Main entry: `src/main.ts`
|
||||
- Main app component: `src/App.vue`
|
||||
- Main styles: `src/styles/`
|
||||
- Plugin setup: `src/plugins/`
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
- `src/main.ts` — application entry point
|
||||
- `src/App.vue` — root component
|
||||
- `src/components/` — reusable Vue components
|
||||
- `src/plugins/` — plugin registration and setup
|
||||
- `src/styles/` — global styles and theme settings
|
||||
- `public/` — static public files
|
||||
|
||||
## ✨ Enabled Features
|
||||
|
||||
- ESLint
|
||||
- Vuetify MCP
|
||||
- Vue 3 + Vite
|
||||
- Vuetify
|
||||
- TypeScript
|
||||
- Pinia
|
||||
- Vue I18n
|
||||
- Vue Router
|
||||
- Vue I18n
|
||||
- pnpm
|
||||
|
||||
## 💿 Install
|
||||
|
||||
Use your selected package manager (pnpm) to install dependencies:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## 🏗️ Build
|
||||
開發伺服器預設使用 `vite.config.mts` 的 port `3700`。
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
## Template 使用方式
|
||||
|
||||
一般功能開發從 `src` 開始:
|
||||
|
||||
1. 在 `src/views` 或 `src/views/<feature>` 新增頁面。
|
||||
2. 在 `src/router/routes.ts` 新增 route。
|
||||
3. 一般頁面使用 `meta: { layout: 'default' }`。
|
||||
4. 畫面區塊拆到 `src/components/<feature>`。
|
||||
5. 複雜流程放到 `src/composables/<feature>`。
|
||||
6. 跨頁共享狀態放到 `src/stores/*.ts`。
|
||||
7. API module 放到 `src/services/modules/<domain>.ts`。
|
||||
|
||||
更完整的入口說明見 [src/README.md](./src/README.md)。
|
||||
|
||||
## 新增頁面
|
||||
|
||||
最小 route 範例:
|
||||
|
||||
```ts
|
||||
{
|
||||
path: '/reports',
|
||||
name: 'reports',
|
||||
component: () => import('@/views/reports/Reports.vue'),
|
||||
meta: { layout: 'default', requiresAuth: true },
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 Available Scripts
|
||||
完整範例見 [docs/add-page-example.md](./docs/add-page-example.md)。
|
||||
|
||||
## Layout
|
||||
|
||||
`App.vue` 會根據 `route.meta.layout` 選擇 layout:
|
||||
|
||||
- `default`:使用 `src/components/layouts/MainLayout.vue`
|
||||
- `none`:使用 `src/components/layouts/PlainLayout.vue`
|
||||
|
||||
一般功能頁使用 `default`。登入頁、錯誤頁、維護中頁、明確要求獨立顯示的頁面才使用 `none`。
|
||||
|
||||
## API 與環境變數
|
||||
|
||||
複製 `.env.example` 作為本機設定起點:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
常用設定:
|
||||
|
||||
```env
|
||||
VITE_API_BASE_URL=/service/api
|
||||
VITE_SKIP_LOGIN=false
|
||||
VITE_DEV_DEFAULT_USER_ID=
|
||||
VITE_DEV_DEFAULT_PASSWORD=
|
||||
```
|
||||
|
||||
`client.ts` 會優先使用 `VITE_API_BASE_URL`,否則預設 `/service/api`。開發模式下,Vite proxy 會將 `/service/*` 轉送到後端。
|
||||
|
||||
實際 `.env` 與 `.env.*.local` 不應提交。production API URL 應由使用專案自己的部署環境提供。
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `src/main.ts`:app entry。
|
||||
- `src/App.vue`:app shell 組裝層,依 route meta 切換 layout。
|
||||
- `src/router`:routes、history、guards。
|
||||
- `src/views`:route views。
|
||||
- `src/components`:layout、page component、feature/domain components。
|
||||
- `src/composables`:可重用流程與 UI state。
|
||||
- `src/stores`:Pinia stores。
|
||||
- `src/services`:HTTP client、API modules、token/session/error。
|
||||
- `src/plugins`:Vuetify、Pinia、I18n、Router 註冊。
|
||||
- `src/styles`:Vuetify SASS settings 與 themes。
|
||||
- `src/language`:i18n JSON。
|
||||
|
||||
## Template Core 與 Demo
|
||||
|
||||
template core 是 app shell、router、layout、plugins、styles、services 基礎設施與全域 stores。一般專案會保留它們。
|
||||
|
||||
demo/example 主要是 maintenance 與學生資料範例:
|
||||
|
||||
- `src/views/Home.vue`
|
||||
- `src/components/PageIndex.vue`
|
||||
- `src/views/maint/*`
|
||||
- `src/components/maint/*`
|
||||
- `src/composables/maint/*`
|
||||
- `src/components/PageMaint.vue`
|
||||
- `src/stores/students.ts`
|
||||
- `src/stores/semesters.ts`
|
||||
- `src/views/FncPage.vue`
|
||||
- `src/views/Settings.vue`
|
||||
- `src/assets/*` 中的品牌或展示素材
|
||||
|
||||
建立正式專案時可依需求替換或刪除 demo/example。刪除時同步清理 routes、menu、language、assets 與引用。
|
||||
|
||||
## Documentation
|
||||
|
||||
- [src/README.md](./src/README.md):`src` 開發入口。
|
||||
- [docs/frontend-layering.md](./docs/frontend-layering.md):目前前端分層與責任邊界。
|
||||
- [docs/llm-development-guide.md](./docs/llm-development-guide.md):給 LLM 的操作規則。
|
||||
- [docs/add-page-example.md](./docs/add-page-example.md):新增頁面範例。
|
||||
- [src/components/README.md](./src/components/README.md)
|
||||
- [src/services/README.md](./src/services/README.md)
|
||||
- [src/plugins/README.md](./src/plugins/README.md)
|
||||
- [src/styles/README.md](./src/styles/README.md)
|
||||
|
||||
## Scripts
|
||||
|
||||
- `pnpm dev`
|
||||
- `pnpm build`
|
||||
- `pnpm preview`
|
||||
- `pnpm build-only`
|
||||
- `pnpm type-check`
|
||||
- `pnpm lint`
|
||||
- `pnpm lint:fix`
|
||||
- `pnpm format`
|
||||
- `pnpm mcp`
|
||||
- `pnpm mcp:revert`
|
||||
|
||||
## 💪 Support Vuetify Development
|
||||
## Verification
|
||||
|
||||
This project uses Vuetify - an MIT licensed Open Source project. We are glad to welcome contributors and any support for ongoing development:
|
||||
|
||||
- Contribute to Vuetify and ecosystem projects: https://github.com/vuetifyjs
|
||||
- Request enterprise support: https://support.vuetifyjs.com/
|
||||
- Sponsor on GitHub: https://github.com/sponsors/vuetifyjs
|
||||
- Support on Open Collective: https://opencollective.com/vuetify
|
||||
|
||||
## playwright
|
||||
完成修改後至少執行:
|
||||
|
||||
```bash
|
||||
pnpm exec playwright test
|
||||
# Runs the end-to-end tests.
|
||||
|
||||
pnpm exec playwright test --ui
|
||||
# Starts the interactive UI mode.
|
||||
|
||||
pnpm exec playwright test --project=chromium
|
||||
# Runs the tests only on Desktop Chrome.
|
||||
|
||||
pnpm exec playwright test example
|
||||
# Runs the tests in a specific file.
|
||||
|
||||
pnpm exec playwright test --debug
|
||||
# Runs the tests in debug mode.
|
||||
|
||||
pnpm exec playwright codegen
|
||||
# Auto generate tests with Codegen.
|
||||
pnpm type-check
|
||||
pnpm build
|
||||
```
|
||||
|
||||
We suggest that you begin by typing:
|
||||
若變更 route、layout 或主要 UI flow,再啟動 dev server 並用瀏覽器確認。
|
||||
|
||||
```bash
|
||||
pnpm exec playwright test
|
||||
```
|
||||
## Vuetify
|
||||
|
||||
And check out the following files:
|
||||
- ./tests/e2e/example.spec.ts - Example end-to-end test
|
||||
- ./playwright.config.ts - Playwright Test configuration
|
||||
- Vuetify docs: https://vuetifyjs.com/
|
||||
- Installation guide: https://vuetifyjs.com/en/getting-started/installation/
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
# 新增頁面範例
|
||||
|
||||
這份文件示範如何用目前 `src/` 慣例新增一個被 `MainLayout` 包住的一般功能頁。
|
||||
|
||||
範例功能:`reports`
|
||||
|
||||
## 1. 新增 route view
|
||||
|
||||
```vue
|
||||
<!-- src/views/reports/Reports.vue -->
|
||||
<script setup lang="ts">
|
||||
import ReportsTable from '@/components/reports/ReportsTable.vue'
|
||||
|
||||
const rows = [
|
||||
{ id: 1, title: '學生統計', owner: '教務處' },
|
||||
{ id: 2, title: '課程統計', owner: '課務組' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ReportsTable :rows="rows" />
|
||||
</template>
|
||||
```
|
||||
|
||||
view 的責任是頁面資料組裝與事件協調。畫面區塊交給 feature component。
|
||||
|
||||
## 2. 新增 feature component
|
||||
|
||||
```vue
|
||||
<!-- src/components/reports/ReportsTable.vue -->
|
||||
<script setup lang="ts">
|
||||
interface ReportRow {
|
||||
id: number
|
||||
title: string
|
||||
owner: string
|
||||
}
|
||||
|
||||
defineProps<{
|
||||
rows: ReportRow[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card flat>
|
||||
<v-card-title class="text-h6">報表清單</v-card-title>
|
||||
<v-table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名稱</th>
|
||||
<th>負責單位</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="row in rows" :key="row.id">
|
||||
<td>{{ row.title }}</td>
|
||||
<td>{{ row.owner }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</v-card>
|
||||
</template>
|
||||
```
|
||||
|
||||
component 以 props 接收資料,以 emit 回報事件。不要在 component 裡直接處理 route 或底層 HTTP。
|
||||
|
||||
## 3. 加入 route
|
||||
|
||||
route 加在 `src/router/routes.ts` 的 `routes` 陣列中,並放在 `/:pathMatch(.*)*` catch-all route 前面。
|
||||
|
||||
```ts
|
||||
// src/router/routes.ts
|
||||
{
|
||||
path: '/reports',
|
||||
name: 'reports',
|
||||
component: () => import('@/views/reports/Reports.vue'),
|
||||
meta: { layout: 'default', requiresAuth: true },
|
||||
}
|
||||
```
|
||||
|
||||
`layout: 'default'` 會讓頁面被 `MainLayout` 包住。登入頁、錯誤頁、維護中頁才使用 `layout: 'none'`。
|
||||
|
||||
若頁面需要出現在 drawer menu、favorites 或 breadcrumb:
|
||||
|
||||
- menu 來源目前由 `src/stores/menu.ts` 轉換後端選單資料。
|
||||
- breadcrumb 會依 route path、menu/favorite items 與 fallback title 產生。
|
||||
- 新功能若使用後端選單,優先調整後端選單資料或對應 API mock,不要把頁面專屬選單邏輯塞進 layout。
|
||||
- 若只是新增 route,通常不需要修改 `MainLayout.vue`。
|
||||
|
||||
## 4. 需要 API 時新增 service module
|
||||
|
||||
```ts
|
||||
// src/services/modules/reports.ts
|
||||
import { httpClient } from '../client'
|
||||
|
||||
export interface ReportSummary {
|
||||
id: number
|
||||
title: string
|
||||
owner: string
|
||||
}
|
||||
|
||||
export const reportsApi = {
|
||||
list: () => httpClient.get<ReportSummary[]>('/Reports'),
|
||||
}
|
||||
```
|
||||
|
||||
service 只封裝 HTTP 細節,不持有 UI 狀態。
|
||||
|
||||
`httpClient` 的 `baseURL` 來自 `VITE_API_BASE_URL`。template 預設值見 `.env.example`,通常使用 `/service/api` 搭配 Vite proxy。
|
||||
|
||||
## 5. 需要共享狀態時新增 store
|
||||
|
||||
```ts
|
||||
// src/stores/reports.ts
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { reportsApi, type ReportSummary } from '@/services/modules/reports'
|
||||
|
||||
export const useReportsStore = defineStore('reports', () => {
|
||||
const items = ref<ReportSummary[]>([])
|
||||
const loading = ref(false)
|
||||
|
||||
const load = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const { data } = await reportsApi.list()
|
||||
items.value = data
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
items,
|
||||
loading,
|
||||
load,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
只有跨頁共享、需要快取、或全域狀態才新增 store。單頁暫時狀態留在 view、component 或 composable。
|
||||
|
||||
## 6. 驗證
|
||||
|
||||
至少執行:
|
||||
|
||||
```bash
|
||||
pnpm type-check
|
||||
pnpm build
|
||||
```
|
||||
|
||||
若有 route、layout 或主要互動流程變更,再啟動 dev server 並用瀏覽器確認。
|
||||
@@ -239,10 +239,10 @@ layout 不應承擔:
|
||||
- 承接畫面快取與顯示狀態
|
||||
- 作為 view 與 services 之間的狀態收斂點
|
||||
|
||||
注意:
|
||||
規則:
|
||||
|
||||
- 目前仍存在 `src/stores/stores/*` 的重複目錄
|
||||
- 這不是分層設計的一部分,而是待整理的結構噪音
|
||||
- store 檔案直接放在 `src/stores/*.ts`
|
||||
- 不要建立 `src/stores/stores/*` 這類重複巢狀目錄
|
||||
|
||||
### `src/services`
|
||||
|
||||
@@ -272,6 +272,61 @@ layout 不應承擔:
|
||||
|
||||
## 目前已落地的分層模式
|
||||
|
||||
## Template Core 與 Demo 邊界
|
||||
|
||||
### Template Core
|
||||
|
||||
以下檔案屬於 template core,負責 app shell、layout、route、plugin、theme、HTTP 基礎設施與全域狀態:
|
||||
|
||||
- [main.ts](/home/carl/git/skt-vuetify-templates/src/main.ts)
|
||||
- [App.vue](/home/carl/git/skt-vuetify-templates/src/App.vue)
|
||||
- `src/router/index.ts`
|
||||
- `src/router/guards.ts`
|
||||
- `src/components/layouts/*`
|
||||
- `src/views/Login.vue`
|
||||
- `src/plugins/*`
|
||||
- `src/styles/*`
|
||||
- `src/services/client.ts`
|
||||
- `src/services/interceptors.ts`
|
||||
- `src/services/token.ts`
|
||||
- `src/services/session.ts`
|
||||
- `src/services/error.ts`
|
||||
- `src/services/http-error.ts`
|
||||
- `src/services/http-toast.ts`
|
||||
- `src/stores/auth.ts`
|
||||
- `src/stores/menu.ts`
|
||||
- `src/stores/breadcrumbs.ts`
|
||||
- `src/stores/favorites.ts`
|
||||
- `src/stores/messages.ts`
|
||||
- `src/stores/snackbar.ts`
|
||||
- `src/composables/layout/*`
|
||||
|
||||
一般功能開發優先不要修改 template core;只有需求明確要求改變框架行為時才調整。
|
||||
|
||||
`src/router/routes.ts` 是新增功能 route 的正式入口,可新增 route,但不要破壞既有 layout meta、auth meta 與 catch-all route 規則。
|
||||
|
||||
### Demo / Example
|
||||
|
||||
以下檔案偏向示範資料與範例頁,可在正式專案中替換或刪除:
|
||||
|
||||
- `src/views/Home.vue`
|
||||
- `src/components/PageIndex.vue`
|
||||
- `src/views/maint/*`
|
||||
- `src/components/maint/*`
|
||||
- `src/composables/maint/*`
|
||||
- `src/components/PageMaint.vue`
|
||||
- `src/stores/students.ts`
|
||||
- `src/stores/semesters.ts`
|
||||
- `src/views/FncPage.vue`
|
||||
- `src/views/Settings.vue`
|
||||
- `src/assets/logo.png`
|
||||
- `src/assets/logo.svg`
|
||||
- `src/assets/robot-svgrepo-com.svg`
|
||||
|
||||
`maint` 是可參考的 demo feature,不是所有新專案都必須保留的核心功能。
|
||||
|
||||
移除 demo/example 時,要同步清理 routes、menu、language、store import、component import 與 assets。
|
||||
|
||||
### 模式 1:`view -> page component -> page family components`
|
||||
|
||||
已落地頁面:
|
||||
@@ -358,7 +413,6 @@ layout 不應承擔:
|
||||
|
||||
### 中優先度
|
||||
|
||||
- 清理 `src/stores/stores/*` 重複結構
|
||||
- 檢查 `components/maint` 內是否仍有可再明確命名的舊名稱
|
||||
- 視 `PageMaint` 的後續演進,決定是否維持在 `components` 根目錄
|
||||
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
# LLM 開發操作指南
|
||||
|
||||
## 文件目的
|
||||
|
||||
本專案是給其他 Vue/Vuetify 專案使用的 template。LLM 在協助修改時,主要工作應集中在 `src` 底下新增或修改頁面、元件、store、service 與 composable,並讓一般頁面自然被 `MainLayout` 包住。
|
||||
|
||||
本文件描述的是後續 LLM 依照 template 修改專案時的預設操作規則,不是目前對話 session 的永久限制。若使用者明確要求修改 template shell 或登入頁入口,可依需求處理。
|
||||
|
||||
建議閱讀順序:
|
||||
|
||||
1. `README.md`
|
||||
2. `src/README.md`
|
||||
3. `docs/add-page-example.md`
|
||||
4. `docs/frontend-layering.md`
|
||||
|
||||
## 預設不可修改的檔案
|
||||
|
||||
以下檔案視為 template 核心邊界。LLM 依本文件處理一般功能需求時,不應修改:
|
||||
|
||||
- `src/components/layouts/MainLayout.vue`
|
||||
- `src/views/Login.vue`
|
||||
|
||||
如果一般功能需求看起來需要修改上述檔案,先停下來回報原因,並改從可修改檔案尋找解法。只有在使用者明確指定要調整 layout shell 或登入頁入口時,才可以修改。
|
||||
|
||||
## 優先修改的位置
|
||||
|
||||
一般功能需求應優先落在:
|
||||
|
||||
- `src/views/*`
|
||||
- `src/views/<feature>/*`
|
||||
- `src/components/<feature>/*`
|
||||
- `src/composables/<feature>/*`
|
||||
- `src/stores/*`
|
||||
- `src/services/*`
|
||||
- `src/router/routes.ts`
|
||||
- `src/language/*.json`
|
||||
|
||||
新增頁面時,通常只需要新增 view、必要的 feature components,並在 `src/router/routes.ts` 加入 route。
|
||||
|
||||
## 依循 `src/` 既有慣例
|
||||
|
||||
開始實作前,先檢查需求最接近的既有檔案,並沿用目前 `src/` 的責任分工、命名方式、資料流與 import 寫法。不要另起一套資料夾結構、狀態管理方式或 API 呼叫方式。
|
||||
|
||||
目前主要資料流是:
|
||||
|
||||
```txt
|
||||
router -> App.vue -> layout -> view -> component -> composable/store -> service
|
||||
```
|
||||
|
||||
判斷原則:
|
||||
|
||||
- `router` 決定 route、layout meta、auth meta 與錯誤頁入口
|
||||
- `App.vue` 組裝 layout props、全域 UI 與 layout event
|
||||
- `views` 承接路由入口、頁面資料協調與頁面事件協調
|
||||
- `components` 承接畫面呈現、props/emits 與可拆分 UI 區塊
|
||||
- `composables` 承接可重用流程、頁面狀態機或較複雜的 UI state
|
||||
- `stores` 承接跨頁共享狀態、快取與全域顯示狀態
|
||||
- `services` 承接 HTTP client、API 模組、token、session 與錯誤處理
|
||||
|
||||
新增功能時,優先找相同類型的現有範例再修改:
|
||||
|
||||
- 新 route:參考 `src/router/routes.ts`
|
||||
- 一般被主 layout 包住的頁面:參考 `src/views/Home.vue`、`src/views/maint/EditableGrid.vue`
|
||||
- 登入相關 UI:參考 `src/components/PageLogin.vue` 與 `src/components/login/*`
|
||||
- 維護頁:參考 `src/views/maint/*`、`src/components/maint/*`、`src/composables/maint/*`
|
||||
- API 呼叫:參考 `src/services/modules/*` 與使用它們的 store/composable
|
||||
- 全域提示:參考 `src/stores/snackbar.ts` 與 `src/composables/useApiCall.ts`
|
||||
|
||||
## Template Core 與 Demo 邊界
|
||||
|
||||
一般功能需求應避免先修改 template core。這些檔案支撐 app shell、route/layout、登入、全域狀態與 API 基礎設施:
|
||||
|
||||
- `src/main.ts`
|
||||
- `src/App.vue`
|
||||
- `src/router/index.ts`
|
||||
- `src/router/guards.ts`
|
||||
- `src/components/layouts/*`
|
||||
- `src/views/Login.vue`
|
||||
- `src/plugins/*`
|
||||
- `src/styles/*`
|
||||
- `src/services/client.ts`
|
||||
- `src/services/interceptors.ts`
|
||||
- `src/services/token.ts`
|
||||
- `src/services/session.ts`
|
||||
- `src/services/error.ts`
|
||||
- `src/services/http-error.ts`
|
||||
- `src/services/http-toast.ts`
|
||||
- `src/stores/auth.ts`
|
||||
- `src/stores/menu.ts`
|
||||
- `src/stores/breadcrumbs.ts`
|
||||
- `src/stores/favorites.ts`
|
||||
- `src/stores/messages.ts`
|
||||
- `src/stores/snackbar.ts`
|
||||
- `src/composables/layout/*`
|
||||
|
||||
以下內容偏向 demo/example,建立正式專案時可依需求替換或刪除:
|
||||
|
||||
- `src/views/Home.vue`
|
||||
- `src/components/PageIndex.vue`
|
||||
- `src/views/maint/*`
|
||||
- `src/components/maint/*`
|
||||
- `src/composables/maint/*`
|
||||
- `src/components/PageMaint.vue`
|
||||
- `src/stores/students.ts`
|
||||
- `src/stores/semesters.ts`
|
||||
- `src/views/FncPage.vue`
|
||||
- `src/views/Settings.vue`
|
||||
- `src/assets/logo.png`
|
||||
- `src/assets/logo.svg`
|
||||
- `src/assets/robot-svgrepo-com.svg`
|
||||
|
||||
`maint` 是可參考的 demo feature,不是所有新專案都必須保留的核心功能。
|
||||
|
||||
移除 demo/example 時,同步清理 `src/router/routes.ts`、相關 menu/favorites/breadcrumb 流程、語系文案、assets 與 import。
|
||||
|
||||
## 新增一般頁面的流程
|
||||
|
||||
1. 在 `src/views` 或 `src/views/<feature>` 新增頁面檔案。
|
||||
2. 若頁面超過單一簡單畫面,將主要 UI 拆到 `src/components/<feature>`。
|
||||
3. 若有可重用或狀態較多的流程,放到 `src/composables/<feature>`。
|
||||
4. 若資料需要跨頁共享,才新增或修改 `src/stores`。
|
||||
5. 在 `src/router/routes.ts` 新增 route。
|
||||
6. 一般頁面的 route 必須使用 `meta: { layout: 'default' }`。
|
||||
|
||||
範例:
|
||||
|
||||
```ts
|
||||
{
|
||||
path: '/reports',
|
||||
name: 'reports',
|
||||
component: () => import('@/views/reports/Reports.vue'),
|
||||
meta: { layout: 'default' },
|
||||
}
|
||||
```
|
||||
|
||||
使用 `layout: 'default'` 的頁面會由 `App.vue` 放進 `MainLayout` 的預設 slot,不需要也不可以直接 import 或包裝 `MainLayout.vue`。
|
||||
|
||||
完整範例見 `docs/add-page-example.md`。
|
||||
|
||||
## 何時使用 `layout: 'none'`
|
||||
|
||||
只有下列頁面應使用 `meta: { layout: 'none' }`:
|
||||
|
||||
- 登入頁
|
||||
- 錯誤頁
|
||||
- 維護中頁
|
||||
- 明確要求不要被主框架包住的獨立頁
|
||||
|
||||
不要為了一般功能頁使用 `layout: 'none'`。
|
||||
|
||||
## Layout 邊界
|
||||
|
||||
`MainLayout` 只負責 app shell:
|
||||
|
||||
- drawer
|
||||
- app bar
|
||||
- breadcrumb
|
||||
- favorites
|
||||
- toolbar actions
|
||||
- 主內容 slot
|
||||
|
||||
頁面專屬業務流程、資料規則、表單、列表、對話框、查詢條件與 CRUD 行為都不應放進 layout。
|
||||
|
||||
如果頁面需要在主內容區呈現特定畫面,請修改該 route 對應的 view 或 feature component。
|
||||
|
||||
如果頁面需要影響 breadcrumb、favorites、menu 或 toolbar,優先使用現有 store、route meta 或 `App.vue` 已經提供的 layout props/event 流程,不要修改 `MainLayout.vue`。
|
||||
|
||||
## Login 邊界
|
||||
|
||||
`src/views/Login.vue` 是登入頁入口。一般功能需求預設不修改這個檔案。
|
||||
|
||||
若需求是調整登入頁內部區塊,優先檢查並修改:
|
||||
|
||||
- `src/components/PageLogin.vue`
|
||||
- `src/components/login/*`
|
||||
- `src/stores/auth.ts`
|
||||
- `src/stores/loginAnnouncements.ts`
|
||||
- `src/services/modules/auth.ts`
|
||||
|
||||
若需求明確要求改變登入頁 route、guard 或登入後導向,優先檢查:
|
||||
|
||||
- `src/router/routes.ts`
|
||||
- `src/router/guards.ts`
|
||||
- `src/stores/auth.ts`
|
||||
|
||||
## View 與 Component 分工
|
||||
|
||||
`views` 是路由入口,負責:
|
||||
|
||||
- 接 route params/query
|
||||
- 組合頁面資料
|
||||
- 串接 store、service、composable
|
||||
- 管理頁面專屬事件
|
||||
- 組裝頁面主 component
|
||||
|
||||
`components/<feature>` 負責:
|
||||
|
||||
- 呈現頁面區塊
|
||||
- 接 props
|
||||
- emit 使用者事件
|
||||
- 拆分表單、列表、工具列、dialog 等 UI
|
||||
|
||||
不要把完整功能長期塞在單一 view。當畫面有多個區塊、表單、列表、dialog 或重複 UI 時,應拆到 feature components。
|
||||
|
||||
## Router 安排規則
|
||||
|
||||
route 集中放在 `src/router/routes.ts`。不要在 view 或 component 裡臨時建立 route 設定。
|
||||
|
||||
一般 route 應包含:
|
||||
|
||||
- `path`
|
||||
- `name`
|
||||
- `component`
|
||||
- `meta.layout`
|
||||
|
||||
需要登入才可進入的頁面使用既有 `requiresAuth` meta。訪客專用頁面使用既有 `guestOnly` meta。導航守衛流程放在 `src/router/guards.ts`,不要散落在頁面 component。
|
||||
|
||||
## Composable 使用規則
|
||||
|
||||
只有在邏輯有下列特性時才新增 composable:
|
||||
|
||||
- 會被多個元件使用
|
||||
- 狀態流程明顯
|
||||
- 有副作用或非簡單 UI 邏輯
|
||||
- 從 component 抽出後可讓 component 責任更清楚
|
||||
|
||||
目前既有 composable 的使用定位:
|
||||
|
||||
- `src/composables/useApiCall.ts`:包裝可重用 API 呼叫狀態與錯誤提示流程
|
||||
- `src/composables/layout/useAdminLayoutState.ts`:提供 layout shell 所需的狀態組裝
|
||||
- `src/composables/layout/useThemeToggle.ts`:提供主題切換流程
|
||||
- `src/composables/maint/useMaintenanceCrudFlow.ts`:提供維護頁 CRUD 流程狀態
|
||||
- `src/composables/maint/useStudentMaintenanceForm.ts`:提供學生維護表單狀態
|
||||
- `src/composables/maint/useEditableStudentGrid.ts`:提供 editable grid 狀態
|
||||
|
||||
新增 composable 時,用 `useXxx.ts` 命名。若只服務單一 feature,放在 `src/composables/<feature>`;若確定跨 feature 使用,才放在 `src/composables` 根目錄。
|
||||
|
||||
## Store 與 Service 資料流規則
|
||||
|
||||
只有在資料或狀態跨頁共享時才使用 store。單一頁面的暫時 UI 狀態應留在 view、feature component 或 composable。
|
||||
|
||||
store 檔案直接放在 `src/stores/*.ts`。不要建立 `src/stores/stores/*` 或其他重複巢狀 store 目錄。
|
||||
|
||||
service 放在 `src/services`,負責外部 API 與 HTTP 細節。component 不應直接處理底層 HTTP client、token、interceptor 或錯誤正規化。
|
||||
|
||||
資料流優先順序:
|
||||
|
||||
1. component 透過 props/emits 與 view 或 page component 溝通。
|
||||
2. view 或 composable 協調頁面流程。
|
||||
3. 跨頁共享狀態由 store 管理。
|
||||
4. store 或 composable 呼叫 service。
|
||||
5. service 回傳資料,不持有 UI 狀態。
|
||||
|
||||
不要讓 service import component、view 或 store。不要讓 component 直接繞過既有 store/composable 去操作 token、session 或 HTTP interceptor。
|
||||
|
||||
## 環境變數規則
|
||||
|
||||
template 提供 `.env.example` 作為範本。不要提交實際 `.env` 或 `.env.*.local`。
|
||||
|
||||
常用變數:
|
||||
|
||||
- `VITE_API_BASE_URL`:API base URL,預設使用 `/service/api` 搭配 Vite proxy。
|
||||
- `VITE_SKIP_LOGIN`:登入示範開關,只有專案明確支援時才使用。
|
||||
- `VITE_DEV_DEFAULT_USER_ID`、`VITE_DEV_DEFAULT_PASSWORD`:本機開發示範帳號,放在本機 env,不要寫進程式。
|
||||
|
||||
## Vuetify 使用規則
|
||||
|
||||
優先使用 Vuetify 原生元件、props、slots 與事件。當需求直接牽涉 Vuetify 元件行為、DOM、可及性輸出或 slot 結構時,先查官方 Vuetify API 文件,再修改實作。
|
||||
|
||||
icon 使用 `@mdi/js`:
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { mdiAccount } from '@mdi/js'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-icon :icon="mdiAccount" />
|
||||
</template>
|
||||
```
|
||||
|
||||
## 修改前檢查
|
||||
|
||||
開始改檔前先確認:
|
||||
|
||||
- 是否會碰到禁止修改檔案
|
||||
- 是否只需要新增或修改 view
|
||||
- 是否需要新增 route
|
||||
- 是否需要拆 feature component
|
||||
- 是否已閱讀 `docs/frontend-layering.md`
|
||||
- 是否已參考 `src/` 裡相同類型的既有範例
|
||||
- 是否符合 Vue 3、Composition API、`<script setup lang="ts">` 的既有寫法
|
||||
|
||||
## 完成前驗證
|
||||
|
||||
修改完成後,至少執行與變更範圍相符的檢查:
|
||||
|
||||
- TypeScript 或 Vue 結構有變更:`pnpm type-check`
|
||||
- 需要確認產物可建置:`pnpm build`
|
||||
- route、layout 或主要畫面流程有變更:啟動 dev server 並用瀏覽器確認頁面被正確包在主 layout 中
|
||||
|
||||
如果無法執行驗證,回報原因,不要宣稱已驗證。
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
# Src 開發入口
|
||||
|
||||
`src` 是 template 使用者主要修改的區域。新增功能時,先從 `views` 與 `router/routes.ts` 開始,除非需求明確牽涉 app shell,否則不要先改 layout。
|
||||
|
||||
## 常見開發流程
|
||||
|
||||
1. 在 `src/views` 或 `src/views/<feature>` 新增 route view。
|
||||
2. 在 `src/router/routes.ts` 加入 route。
|
||||
3. 一般頁面使用 `meta: { layout: 'default' }`,讓內容被 `MainLayout` 包住。
|
||||
4. 畫面超過單一簡單區塊時,拆到 `src/components/<feature>`。
|
||||
5. 可重用流程或較複雜 UI state 放到 `src/composables/<feature>`。
|
||||
6. 跨頁共享狀態放到 `src/stores/*.ts`。
|
||||
7. API 呼叫放到 `src/services/modules/<domain>.ts`。
|
||||
|
||||
## 主要資料流
|
||||
|
||||
```txt
|
||||
router -> App.vue -> layout -> view -> component -> composable/store -> service
|
||||
```
|
||||
|
||||
責任分工:
|
||||
|
||||
- `router`:route、layout meta、auth meta 與錯誤頁入口。
|
||||
- `App.vue`:根據 route meta 組裝 layout、全域 UI 與 layout event。
|
||||
- `views`:路由入口、頁面資料協調與頁面事件協調。
|
||||
- `components`:畫面呈現、props/emits 與可拆分 UI 區塊。
|
||||
- `composables`:可重用流程、頁面狀態機或較複雜 UI state。
|
||||
- `stores`:跨頁共享狀態、快取與全域顯示狀態。
|
||||
- `services`:HTTP client、API 模組、token、session 與錯誤處理。
|
||||
|
||||
## Template Core
|
||||
|
||||
一般功能開發時,優先視為 template core:
|
||||
|
||||
App shell:
|
||||
|
||||
- `src/main.ts`
|
||||
- `src/App.vue`
|
||||
|
||||
Layout:
|
||||
|
||||
- `src/components/layouts/MainLayout.vue`
|
||||
- `src/components/layouts/PlainLayout.vue`
|
||||
- `src/components/layouts/main-layout/*`
|
||||
|
||||
Login entry:
|
||||
|
||||
- `src/views/Login.vue`
|
||||
|
||||
Router core:
|
||||
|
||||
- `src/router/index.ts`
|
||||
- `src/router/guards.ts`
|
||||
|
||||
Plugin / theme core:
|
||||
|
||||
- `src/plugins/*`
|
||||
- `src/styles/*`
|
||||
|
||||
HTTP core:
|
||||
|
||||
- `src/services/client.ts`
|
||||
- `src/services/interceptors.ts`
|
||||
- `src/services/token.ts`
|
||||
- `src/services/session.ts`
|
||||
- `src/services/error.ts`
|
||||
- `src/services/http-error.ts`
|
||||
- `src/services/http-toast.ts`
|
||||
|
||||
Global stores:
|
||||
|
||||
- `src/stores/auth.ts`
|
||||
- `src/stores/menu.ts`
|
||||
- `src/stores/breadcrumbs.ts`
|
||||
- `src/stores/favorites.ts`
|
||||
- `src/stores/messages.ts`
|
||||
- `src/stores/snackbar.ts`
|
||||
|
||||
Layout composables:
|
||||
|
||||
- `src/composables/layout/*`
|
||||
|
||||
這些檔案支撐 app shell、登入、路由、全域狀態與 API 基礎設施。只有需求明確要求修改 template core 時才調整。
|
||||
|
||||
`src/router/routes.ts` 是功能開發時可新增 route 的入口,但不要改壞既有 layout meta、auth meta 與 catch-all route 規則。
|
||||
|
||||
登入 route 入口是 `src/views/Login.vue`。若只是調整登入畫面內容,優先修改 `src/components/PageLogin.vue` 與 `src/components/login/*`。
|
||||
|
||||
`src/services/modules/auth.ts` 與 `src/services/modules/menu.ts` 是預設後端契約的 API adapter。接新後端時常需要調整,但不要把 UI 狀態放進 service module。
|
||||
|
||||
## Demo / Example
|
||||
|
||||
以下內容偏向示範資料與範例頁,建立新專案時可依需求替換或刪除:
|
||||
|
||||
- `src/views/Home.vue`
|
||||
- `src/components/PageIndex.vue`
|
||||
- `src/views/maint/*`
|
||||
- `src/components/maint/*`
|
||||
- `src/composables/maint/*`
|
||||
- `src/components/PageMaint.vue`
|
||||
- `src/stores/students.ts`
|
||||
- `src/stores/semesters.ts`
|
||||
- `src/views/FncPage.vue`
|
||||
- `src/views/Settings.vue`
|
||||
- `src/language/*.json` 中與 starter home、maint、學生資料相關的文案
|
||||
- `src/assets/logo.png`
|
||||
- `src/assets/logo.svg`
|
||||
- `src/assets/robot-svgrepo-com.svg`
|
||||
|
||||
刪除 demo/example 時,也要同步清理:
|
||||
|
||||
- `src/router/routes.ts`
|
||||
- `src/stores/menu.ts` 中依賴的選單資料流程
|
||||
- 相關 `src/language/*.json` 文案
|
||||
- 不再被 import 的 demo components、composables、stores 與 assets
|
||||
|
||||
## 新頁面最小範例
|
||||
|
||||
```ts
|
||||
// src/router/routes.ts
|
||||
{
|
||||
path: '/reports',
|
||||
name: 'reports',
|
||||
component: () => import('@/views/reports/Reports.vue'),
|
||||
meta: { layout: 'default', requiresAuth: true },
|
||||
}
|
||||
```
|
||||
|
||||
```vue
|
||||
<!-- src/views/reports/Reports.vue -->
|
||||
<script setup lang="ts">
|
||||
import ReportsTable from '@/components/reports/ReportsTable.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ReportsTable />
|
||||
</template>
|
||||
```
|
||||
|
||||
更多範例見 `docs/add-page-example.md`。
|
||||
|
||||
## 文件導覽
|
||||
|
||||
- `docs/add-page-example.md`:新增頁面範例。
|
||||
- `docs/frontend-layering.md`:完整分層與責任邊界。
|
||||
- `docs/llm-development-guide.md`:LLM 操作邊界。
|
||||
|
||||
## 驗證
|
||||
|
||||
```bash
|
||||
pnpm type-check
|
||||
pnpm build
|
||||
```
|
||||
@@ -42,6 +42,16 @@ API module 應:
|
||||
|
||||
`client.ts` 的 `baseURL` 優先使用 `VITE_API_BASE_URL`,否則使用 `/service/api`。開發模式下,Vite proxy 會將 `/service/*` 轉送到後端。
|
||||
|
||||
template 提供 `.env.example` 作為環境變數範本。建立新專案時,複製成 `.env` 或對應 mode 的 env 檔,再填入實際 API 設定。
|
||||
|
||||
```bash
|
||||
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`
|
||||
|
||||
Reference in New Issue
Block a user