基於 Vue 3 的 AIQuiz 單頁應用程式,提供工作分頁與儀表板介面,適合數據展示、工作流程與儀表板類專案。程式碼含中文註解,便於維護與擴充。
本專案已改為獨立 Git 儲存庫。若要推送到 GitHub 上的新 repository aiquiz_frontend:
- 在 GitHub 建立新 repository,名稱設為 aiquiz_frontend(不要勾選「Add a README」)。
- 在專案目錄執行:
git remote add origin https://github.com/kevin7261/aiquiz_frontend.git
git branch -M main
git push -u origin main若使用 SSH:git remote add origin git@github.com:kevin7261/aiquiz_frontend.git
AIQuiz 為一單頁應用程式(SPA),以 Vue 3 為核心,搭配 Vue Router、Pinia、Bootstrap 5 與 Font Awesome,實作「工作分頁」與「儀表板」兩大區塊,並可依需求擴充狀態與頁面。
| 項目 | 說明 |
|---|---|
| 技術棧 | Vue 3 Composition API、Vue Router 4、Pinia、Bootstrap 5、Font Awesome |
| 介面 | 標題列 + Tab 切換(工作分頁 / 儀表板)+ 內容區 + 頁腳 |
| 版面 | 固定版面,無 RWD 設定 |
| 狀態管理 | Pinia store 預留擴充,可集中管理全域狀態 |
| 程式風格 | 中文註解、ESLint、Prettier、Vue CLI 建置 |
- 內部工具或儀表板
- 數據與統計展示
- 學術或研究用介面
- 需快速擴充分頁與狀態的 Vue 3 專案
首頁由 HomeView 組成,包含:
-
標題列
顯示目前分頁名稱(「工作分頁」或「儀表板」)。 -
分頁導航
- 🔧 工作分頁:切換至工作分頁內容。
- 📊 儀表板:切換至儀表板內容。
-
內容區
依所選 Tab 顯示 WorkTab 或 DashboardTab。 -
頁腳
臺灣大學地理環境資源學系與年份。
- 當前工作狀態說明。
- 支援格式:GeoJSON, Shapefile, KML, CSV。
- 工作區功能:數據處理與分析、屬性查詢與篩選、地理計算工具。
- 快速操作按鈕:載入資料、執行分析、匯出結果。
(以上為靜態說明,實際邏輯可於 src/tabs/WorkTab.vue 擴充。)
- 系統統計:數據點總數、使用記憶體等(目前為佔位)。
- 分析摘要:空間參考(如 WGS84)、最後更新時間。
- 數據品質指標:完整性、準確性、時效性進度條。
- 快速操作:重新整理、匯出報告、設定警報。
(數值與行為可於 src/tabs/DashboardTab.vue 改為接 API 或 store。)
全螢幕載入遮罩組件,可由父組件控制顯示/隱藏、載入文字、進度與副標。目前首頁傳入 isVisible: false,預設不顯示;若未來有非同步載入需求,可改為綁定 store 或 props。
| 套件 | 版本 | 用途 |
|---|---|---|
| vue | ^3.2.13 | 前端框架,Composition API、響應式、組件化 |
| vue-router | ^4.5.1 | 單頁應用路由(History 模式、守衛、meta) |
| pinia | ^2.1.0 | 狀態管理,取代 Vuex,支援 DevTools、持久化 |
| bootstrap | ^5.3.0 | 網格、元件、工具類、JS 元件 |
| @fortawesome/fontawesome-free | ^6.7.2 | 圖示字體(solid / regular / brands) |
| core-js | ^3.8.3 | Babel 依賴,用於 polyfill(babel.config.js 之 corejs: 3) |
| 套件 | 版本 | 用途 |
|---|---|---|
| @vue/cli-service | ^5.0.8 | Vue CLI 建置與開發伺服器 |
| @vue/cli-plugin-babel | ^5.0.8 | Babel 轉譯與 polyfill(useBuiltIns: 'usage', corejs: 3) |
| @vue/cli-plugin-eslint | ^5.0.8 | ESLint 整合 |
| @babel/core | ^7.12.16 | Babel 核心 |
| @babel/eslint-parser | ^7.12.16 | ESLint 使用 Babel 解析器 |
| eslint | ^8.57.0 | 程式碼檢查 |
| eslint-plugin-vue | ^9.27.0 | Vue 專用規則 |
| eslint-config-prettier | ^10.1.5 | 關閉與 Prettier 衝突的規則 |
| eslint-plugin-prettier | ^5.4.1 | 以 Prettier 作為 ESLint 規則 |
| prettier | ^3.5.3 | 程式碼格式化 |
| gh-pages | ^5.0.0 | 部署至 GitHub Pages(npm run deploy) |
| html-webpack-plugin | ^4.5.2 | HTML 產物與 title 等設定(由 Vue CLI 使用) |
- 設定於
package.json的browserslist。 - 預設:
"> 1%", "last 2 versions", "not dead", "not ie 11"。 - 影響 Babel 與 Autoprefixer 的輸出,建置時會依此產生相容程式碼。
- Node.js:>= 14.0.0(建議 16.x 或 18.x LTS)。
- 套件管理:npm >= 6.0.0 或 yarn >= 1.22.0。
- 作業系統:Windows / macOS / Linux 皆可;開發伺服器設定
host: '0.0.0.0',區域網路可連線。
git clone https://github.com/kevin7261/aiquiz_frontend.git
cd aiquiz_frontend(若專案根目錄即為 frontend,則從 frontend 開始即可。)
npm install
# 或
yarn install會安裝 package.json 中所有 dependencies 與 devDependencies,並產生 node_modules 與 package-lock.json(或 yarn.lock)。
npm run serve
# 或
yarn serve- 使用 Vue CLI 啟動開發伺服器。
- 預設:**http://localhost:8080**(port 在
vue.config.js的devServer.port設定)。 - 支援熱重載(HMR),修改程式存檔後會自動更新瀏覽器。
host: '0.0.0.0'時,同一網路可透過本機 IP:8080 存取。
npm run build
# 或
yarn build- 產出目錄:dist/。
- 生產環境
publicPath為/aiquiz_frontend/(對應 GitHub Pages 子路徑)。 - 建置時會進行壓縮、Tree-shaking、chunk 分割等優化。
npm run deploy
# 或
yarn deploy- 會先執行
predeploy(即npm run build),再以 gh-pages 將dist目錄推送至gh-pages分支。 - 若倉庫為
https://github.com/kevin7261/autoq,則線上網址為:**https://kevin7261.github.io/aiquiz_frontend**。 vue.config.js中生產環境publicPath: '/aiquiz_frontend/'需與 GitHub 專案名稱一致,否則資源路徑會錯誤。
frontend/
├── public/ # 靜態資源(不經 webpack 處理,複製至 dist 根目錄)
│ ├── index.html # 入口 HTML,含 <div id="app">
│ ├── favicon.ico # 網站圖示
│ ├── 404.html # 可選:SPA 404 頁
│ └── data/ # 靜態數據(可放 JSON、壓縮檔等)
│ └── rag_db.zip
│
├── src/
│ ├── main.js # 應用程式入口:建立 Vue app、掛載 router/pinia、引入全域樣式
│ ├── App.vue # 根組件:僅含 <router-view>,作為路由出口
│ │
│ ├── router/
│ │ └── index.js # Vue Router 設定:routes、history、beforeEach(設定 document.title)
│ │
│ ├── stores/
│ │ └── dataStore.js # Pinia store(id: 'data'),目前為預留擴充用
│ │
│ ├── views/
│ │ └── HomeView.vue # 首頁:標題、Tab 導航、WorkTab/DashboardTab、頁腳
│ │
│ ├── tabs/
│ │ ├── WorkTab.vue # 工作分頁內容(靜態說明與按鈕)
│ │ └── DashboardTab.vue # 儀表板內容(統計、品質指標、按鈕)
│ │
│ ├── components/
│ │ └── LoadingOverlay.vue # 全螢幕載入遮罩(isVisible、loadingText、progress、subText)
│ │
│ ├── assets/
│ │ ├── css/
│ │ │ ├── variables.css # CSS 變數:顏色、字體、間距等
│ │ │ └── common.css # 全域樣式與工具類(引入 variables.css)
│ │ └── logo.png # 專案 logo(可選)
│ │
│ └── constants/ # 常數目錄(目前僅 .gitkeep,可放常數或列舉)
│ └── .gitkeep
│
├── babel.config.js # Babel:@vue/cli-plugin-babel/preset,corejs: 3,useBuiltIns: 'usage'
├── vue.config.js # Vue CLI:publicPath、devServer、chainWebpack(title)、transpileDependencies
├── vite.config.js # 若未來改用 Vite 建置可在此設定
├── jsconfig.json # JS 路徑別名等(可給編輯器與工具使用)
├── package.json # 依賴、腳本、browserslist、eslintConfig
├── package-lock.json # npm 依賴鎖檔
├── README.md # 本說明文件
│
└── scripts/ # 自訂腳本(可選,如建置前處理)
├── remove-console.js
└── remove-console-ast.js
| 目錄/檔案 | 職責 |
|---|---|
| src/main.js | 建立 app、註冊 router/pinia、引入 Bootstrap / Font Awesome / common.css、掛載 #app |
| src/App.vue | 根組件,僅提供 <router-view> |
| src/router/index.js | 定義 routes(/ → HomeView)、createWebHistory、beforeEach 設定 title |
| src/stores/dataStore.js | Pinia store,目前僅預留狀態,供日後擴充 |
| src/views/HomeView.vue | 首頁版面:標題、Tab、WorkTab/DashboardTab、頁腳 |
| src/tabs/*.vue | 各分頁的 UI 與邏輯(可再接 API 或 store) |
| src/components/*.vue | 可重用 UI(如 LoadingOverlay) |
| src/assets/css/ | 全域變數與樣式,供各組件與 main 使用 |
-
publicPath
- 開發:
/。 - 生產:
/aiquiz_frontend/,對應 GitHub Pages 專案路徑。
- 開發:
-
chainWebpack
- 設定
html-webpack-plugin的 title 為'AIQuiz'。
- 設定
-
transpileDependencies
true:轉譯node_modules內依賴,提高舊瀏覽器相容性。
-
devServer
port: 8080。host: '0.0.0.0':允許區域網路存取。
- preset:
@vue/cli-plugin-babel/preset。 - useBuiltIns: 'usage':依程式碼使用情況自動注入 polyfill。
- corejs: 3:使用 core-js 3。
- extends:
plugin:vue/vue3-essential、eslint:recommended。 - parser:
@babel/eslint-parser。 - rules:
no-console: warn、no-debugger: warn、vue/multi-word-component-names: off等。
| 指令 | 說明 |
|---|---|
| npm run serve | 啟動開發伺服器(預設 http://localhost:8080),支援 HMR |
| npm run build | 建置生產版本至 dist/,使用生產 publicPath |
| npm run lint | 執行 ESLint 檢查 |
| npm run lint:fix | 執行 ESLint 並自動修復可修復問題 |
| npm run prettier | 使用 Prettier 格式化專案內檔案 |
| npm run prettier:check | 僅檢查格式,不寫入 |
| npm run format | 先執行 prettier,再執行 lint:fix |
| npm run predeploy | 由 deploy 自動呼叫,實際執行 npm run build |
| npm run deploy | 先 build,再以 gh-pages 部署 dist 至 gh-pages 分支 |
-
main.js
createApp(App)→app.use(router)→app.use(pinia)→app.mount('#app')。- 載入 Bootstrap CSS/JS、Font Awesome、
common.css。
-
App.vue
- 僅渲染
<router-view />,由路由決定顯示哪個 view。
- 僅渲染
-
router
- 路徑
/對應 HomeView;其餘路徑可於router/index.js擴充。
- 路徑
-
HomeView
- 使用
ref('work')管理activeTab,以switchTab('work'|'dashboard')切換。 - 依
activeTab顯示 WorkTab 或 DashboardTab。 - 不依賴 dataStore 的圖層或複雜狀態;若未來有全域狀態,可改為從 dataStore 讀寫。
- 使用
- 路由:
router→ 決定顯示 HomeView。 - 分頁:HomeView 的
activeTab→ 決定顯示 WorkTab 或 DashboardTab。 - 全域狀態:Pinia
dataStore目前僅預留,未在畫面上使用;可於 dataStore 新增 state/getters/actions,再在任一組件中useDataStore()使用。
- 角色:根組件,僅作為路由出口。
- template:
<div id="app">內含<router-view />。 - 樣式:引入
./assets/css/common.css。
- 角色:首頁畫面,包含標題、Tab、內容、頁腳。
- 狀態:
activeTab('work' | 'dashboard')。 - 計算屬性:
currentTabTitle依activeTab回傳「工作分頁」或「儀表板」。 - 子組件:LoadingOverlay、WorkTab、DashboardTab。
- 注意:LoadingOverlay 目前
isVisible固定為false;若有非同步載入,可改為響應式變數或 store。
- 角色:工作分頁內容。
- 技術:
<script setup>,無 props/emit。 - 內容:工作狀態、支援格式、工作區功能、快速操作按鈕(UI only,可自行綁定事件與 API/store)。
- 角色:儀表板內容。
- 技術:
<script setup>。 - 內容:系統統計、分析摘要、數據品質進度條、快速操作按鈕;可改為從 store 或 API 取得數據。
- Props:
isVisible(必填)、loadingText、progress、showProgress、subText。 - 用途:全螢幕半透明遮罩 + 載入文字(與可選進度條)。
- 使用處:HomeView 內,目前僅作佔位,不顯示。
- Store id:
'data'。 - 選項:
persist: true(會使用 pinia 持久化插件若已註冊)。 - 目前內容:單一
_placeholderref,回傳於 store;可依需求擴充 state、getters、actions。
- 定義 CSS 自訂屬性:
- 顏色(如
--my-color-*、--my-bgcolor-*)。 - 字體(字型、大小、字重、字距)。
- 間距、陰影等。
- 顏色(如
- 供
common.css與各組件透過var(--...)使用。
- 引入 variables.css。
- 全域重置與基礎樣式(如
html/body、#app)。 - 工具類:如
.my-title-*、.my-content-*、.my-bgcolor-*、.my-color-*等,對應 variables 中的變數。
- 在 main.js 或 App.vue 中已引入
common.css;HomeView 也再次引入以確保樣式覆蓋順序。 - 組件內可直接使用 Bootstrap 類與自訂
.my-*類,或寫<style scoped>使用var(--my-*)。
npm run lint # 僅檢查
npm run lint:fix # 檢查並自動修復
npm run prettier # 格式化
npm run format # prettier + lint:fix建議提交前執行一次 npm run format,以符合專案 ESLint / Prettier 設定。
- 在
src/views/新增 Vue 組件(例如AboutView.vue)。 - 在
src/router/index.js的routes中新增一筆:path、name、component(可 lazy load:() => import('@/views/AboutView.vue'))。- 若有需要,在
meta設定title,以便在beforeEach中設定document.title。
- 在
src/tabs/新增組件(例如ReportTab.vue)。 - 在 HomeView.vue:
import新組件。- 在
components中註冊。 - 在
currentTabTitle的switch中加上新 case。 - 在 template 的 nav 中加一個按鈕(
@click="switchTab('report')"等)。 - 在內容區加一個
v-if="activeTab === 'report'"並渲染新組件。
在任一組件或組合式函式中:
import { useDataStore } from '@/stores/dataStore';
export default {
setup() {
const store = useDataStore();
// 讀寫 store._placeholder 或未來擴充的 state/actions
return { store };
},
};可於 dataStore.js 中新增 ref/computed/ 函式,並在 return 中暴露給組件使用。
- 重要模組與函式建議加上 JSDoc 或區塊註解(中文亦可)。
- 組件名建議多字(例如
HomeView、WorkTab),以利除錯與規範;本專案已關閉vue/multi-word-component-names,可依團隊習慣調整。
npm run build- 產出在 dist/。
- 生產環境
publicPath為/aiquiz_frontend/,所有資源路徑會以/aiquiz_frontend/為前綴。 - 若需部署到其他路徑,請修改
vue.config.js的publicPath。
建置完成後可用靜態檔案伺服器預覽,例如:
npx serve dist -s-s 會啟用 SPA fallback(所有路徑回傳 index.html)。注意預覽時網址需與 publicPath 一致(例如掛在 /aiquiz_frontend/ 下)。
-
倉庫設定中啟用 GitHub Pages,來源選 gh-pages 分支(或依你使用的設定)。
-
執行:
npm run deploy
-
確認倉庫名與
publicPath一致(例如倉庫username/aiquiz_frontend→publicPath: '/aiquiz_frontend/')。 -
線上網址一般為:
https://<username>.github.io/aiquiz_frontend/。
- 來源:
@/stores/dataStore。 - 回傳:Pinia store 實例。
- 目前對外:
_placeholder(ref,可讀寫)。 - 擴充方式:在
dataStore.js的defineStore回傳函式中新增 state / getters / actions,再於組件中呼叫。
- createWebHistory(process.env.BASE_URL):HTML5 History 模式。
- routes:目前僅
{ path: '/', name: 'Home', component: HomeView, meta: { title: 'AIQuiz', ... } }。 - beforeEach:若
to.meta.title存在,則設定document.title = to.meta.title + ' - AIQuiz'。
- 確認 Node 版本 >= 14,建議 16 或 18。
- 刪除
node_modules與package-lock.json後重新npm install。 - 檢查 8080 port 是否被佔用,必要時在
vue.config.js修改devServer.port。
- 檢查
vue.config.js的 publicPath 是否與實際部署路徑一致(例如 GitHub Pages 的/aiquiz_frontend/)。 - 若部署在子路徑,需確保
router的createWebHistory(base)的 base 與 publicPath 一致(Vue CLI 會透過process.env.BASE_URL處理)。
- 執行
npm run lint:fix與npm run prettier。 - 若仍不符合預期,檢查
.eslintrc*與package.json內eslintConfig,以及是否有本機.prettierrc覆寫設定。
- 若曾使用舊版 store(例如含圖層狀態),瀏覽器可能留有 localStorage。
- 在開發者工具 → Application → Local Storage 中刪除該網域下與 pinia 相關的 key,或清除網站資料後重新載入。
- Fork 本倉庫。
- 建立分支(例如
feature/xxx或fix/xxx)。 - 修改後執行
npm run format與npm run lint,通過後再提交。 - 提交訊息建議使用語義化前綴:
feat:、fix:、docs:、style:、refactor:、chore:等。 - 對本倉庫發起 Pull Request,並簡述變更內容。
- 授權:MIT License,詳見 LICENSE。
- 作者:Kevin Cheng
- Email:kevin7261@gmail.com
- GitHub:@kevin7261
- 專案首頁:https://kevin7261.github.io/aiquiz_frontend
若本專案對你有幫助,歡迎給一個 Star;若有問題或建議,可透過 GitHub Issues 或上述信箱聯絡。