Yuruicamp

專案地圖(先看這裡)

接 Spring Boot 前已將前端整包收進 frontend/,根目錄邊界如下:

路徑 放什麼 你要改…時來這裡
frontend/ 主站、booking、admin、mock data/、Vite/npm 網頁、樣式、假資料、前端腳本
backend/ Spring Boot Java API(線 A 骨架:Firebase ID Token;見 backend/README.md
docs/ Schema、前端規格、資料表說明 DB/規格文件
plans/ 規劃與遷移規格 例如 plans/frontend-folder-migration-spec.md
docker-compose.yml + .env.example 本機 PostgreSQL 資料庫基礎設施

後端實作狀態

後端程式使用簡短中文註解;流程文件集中在 docs/backend-specs/,只保留用途、主要流程與驗證結果。

用 npm 開啟前端(推薦/日常開發請用這個)

前端的 npm/Vite 根目錄是 frontend/,必須先進入該資料夾再啟動。
頁面使用網站根絕對路徑(/storefront/.../data/.../assets/...),因此伺服器根必須是 frontend/,用 Vite 最穩。

# 在 repo 根 Yuruicamp/ 執行:
cd frontend
npm install          # 第一次或依賴有變時
npm run dev          # 啟動 Vite 開發伺服器

終端機出現類似 http://127.0.0.1:5173 後,用瀏覽器開啟:

要看什麼 網址
品牌入口(會導向首頁) http://127.0.0.1:5173/
主站首頁 http://127.0.0.1:5173/storefront/pages/home.html
商品列表 http://127.0.0.1:5173/storefront/pages/products.html
營地預約 http://127.0.0.1:5173/booking/pages/camp-search.html
賣家後台 http://127.0.0.1:5173/admin/login.html

停止伺服器:在該終端機按 Ctrl + C

常見錯誤(會導致沒有 CSS/JS、後台抓不到假資料):

假資料: 檔案在 frontend/data/;瀏覽器執行期路徑是 /data/**(由 Vite 以 frontend/ 為 root 提供)。

開發者改檔對照請看 userguide.md。更完整的啟動說明見下方「啟動方式」。


本機資料庫(Docker + PostgreSQL)

後端開發使用 PostgreSQL 16。為了讓大家環境一致,資料庫用 Docker 啟動;
Spring Boot 仍建議在本機 IDE 執行(除錯比較方便)。

相關檔案:

檔案 說明
docker-compose.yml 只啟動 Postgres(不包前端/後端)
.env.example 環境變數範本(可進 Git)
.env 每人本機密碼(不要 commit;已在 .gitignore

你需要先安裝

第一次設定(每人做一次)

  1. 在專案根目錄複製環境變數檔:

    Copy-Item .env.example .env
    
  2. 用編輯器打開 .env,把 POSTGRES_PASSWORD 改成你自己的本機密碼。
    不要把 .env commit / push 到 GitHub。

  3. 啟動資料庫:

    docker compose up -d
    
  4. 確認容器有在跑:

    docker ps
    

    應看得到 yuruicamp-db,且 PORTS 類似 0.0.0.0:5433->5432/tcp

連線資訊(給 Spring Boot / DBeaver / pgAdmin)

項目
Host localhost
Port 5433(不是 5432)
Database yuruicamp
Username .env 裡的 POSTGRES_USER(預設 postgres
Password .env 裡的 POSTGRES_PASSWORD

Spring Boot 範例(之後放在本機設定,勿把真密碼推進 Git):

spring.datasource.url=jdbc:postgresql://localhost:5433/yuruicamp
spring.datasource.username=postgres
spring.datasource.password=你的密碼

常用指令

# 啟動
docker compose up -d

# 看 log(排查連線問題很有用)
docker compose logs -f yuruicamp-db

# 停止(資料還在)
docker compose down

# 停止並清空資料卷(會刪光 DB 資料,慎用)
docker compose down -v

建表(schema)

compose 在資料卷第一次建立時,會自動執行:

說明文件:

若 volume 已存在、只改了 SQL,需重建(會清資料):docker compose down -v 後再 up -d
也可對空庫手動用 DBeaver / pgAdmin / psql 執行 docs/latest_schema.sql

常見問題

Q: port is already allocated / 5433 被占用?
A: 改 .envPOSTGRES_PORT(例如 5434),並同步改 Spring Boot 的連線 port。

Q: 我改了 .env 密碼或需要重建最新資料庫結構,連線還是舊資料? A: Postgres 的帳密與 docs/latest_schema.sql 都只在「資料卷第一次建立」時套用。若要重建(會清資料):

docker compose down -v
docker compose up -d

Q: 為什麼不用本機 5432?
A: 很多人電腦已裝過 PostgreSQL,5432 容易衝突,所以預設用 5433

Q: 可以把密碼寫在 docker-compose.yml 再推 GitHub 嗎?
A: 不行。請用 .env(已在 .gitignore),範本用 .env.example


Schema / 假資料

文件 說明
docs/latest_schema.sql PostgreSQL 現行 DDL(建庫真相來源)
docs/database-schema-guide.md ER 圖、函式/Trigger、資料字典
docs/schema-enums.md status / category 等 ENUM 允許值
docs/database-documents/ 各業務表領域說明
docs/seed/README.md PostgreSQL 開發 Seed:SQL 結構、載入順序、執行方式與維護規則
plans/data-integration-spec.md 前端 Mock JSON:資料語意、關聯、衍生資料與維護規則
plans/schema-migration-checklist.md Schema 整合任務清單(歷史勾選;DDL 以 latest_schema 為準)
cd frontend
npm run validate:data
npm run sync:listings
npm run normalize:data

v1.3.76 - 2026/07/06

v1.3.75 - 2026/07/06

v1.3.74 - 2026/07/06

v1.3.73 - 2026/07/06

v1.3.72 - 2026/07/06

v1.3.71 - 2026/07/06

v1.3.70 - 2026/07/06

v1.3.69 - 2026/07/06

v1.3.68 - 2026/07/06

v1.3.67 - 2026/07/06

v1.3.66 - 2026/07/06

v1.3.65 - 2026/07/06

v1.3.64 - 2026/07/06

v1.3.63 - 2026/07/06

v1.3.62 - 2026/07/06

v1.3.61 - 2026/07/06

v1.3.60 - 2026/07/06

v1.3.59 - 2026/07/04

v1.3.58 - 2026/07/04

v1.3.57 - 2026/07/04

v1.3.56 - 2026/07/04

v1.3.55 - 2026/07/03

v1.3.54 - 2026/07/03

v1.3.53 - 2026/07/03

v1.3.52 - 2026/07/03

v1.3.51 - 2026/07/03

v1.3.50 - 2026/07/03

v1.3.49 - 2026/07/03

v1.3.48 - 2026/07/03

v1.3.47 - 2026/07/03

v1.3.46 - 2026/07/03

v1.3.45 - 2026/07/03

v1.3.44 - 2026/07/03

v1.3.43 - 2026/07/03

v1.3.42 - 2026/07/03

v1.3.41 - 2026/07/03

v1.3.40 - 2026/07/02

v1.3.39 - 2026/07/02

v1.3.31 - 2026/06/30

v1.3.27 - 2026/06/30

Yuruicamp 露營選物品牌網站

探索戶外,從這裡開始 🏕️

Schema / 假資料

假資料已整合至 /data/**(多在 frontend/data/**);PostgreSQL 以 docs/latest_schema.sql 為準(給 Java bootcamp 銜接用,前端仍可走 Mock):

文件 說明
docs/latest_schema.sql PostgreSQL 現行 DDL(ENUM + 主表 PK/FK + View/Trigger)
docs/database-schema-guide.md ER 圖與資料字典導覽
docs/schema-enums.md 狀態/分類枚舉允許值
docs/database-documents/ 各業務表領域說明(含快照欄位語意)
docs/seed/README.md PostgreSQL 開發 Seed:SQL 結構、載入順序、執行方式與維護規則
plans/data-integration-spec.md 前端 Mock JSON:資料語意、關聯、衍生資料與維護規則
plans/schema-migration-checklist.md Schema 整合任務勾選清單(歷史)

📋 專案概述

Yuruicamp 是一個完整的露營選物電商網站前端實現,包含 storefront/pages/11 個買家功能頁面、Mock API 層、完整 RWD 響應式設計,以及一套獨立的賣家管理後台(含員工 ID 登入、九大管理模組、逐頁 view/edit 權限、圖表儀表板)。

開發目標:能跑 → 看懂 → 好改 → 效能,按此優先順序逐步實現。

技術棧

技術 用途
HTML5 語義化頁面結構
SCSS / CSS3 買家前台樣式系統、約 4900 行完整 CSS
Vanilla JavaScript 買家前台頁面互動邏輯(無框架依賴)
Vite + Sass SCSS 編譯、多頁面建置、資產壓縮
ESLint + Prettier + Stylelint JS / HTML / CSS / SCSS 基礎品質檢查
Bootstrap 5 + jQuery 3 + Chart.js 賣家後台 UI 框架、圖表視覺化
Mock API(localStorage / sessionStorage + JSON) 模擬前後台資料,預留真實 API 接入點
Git 版本控制

建置狀態:✅ 買家前台 14 階段完成 + 賣家後台 9 模組完成(2026/06/15,含租借多營地庫存與異動員工 ID)+ 預約子系統 6 頁面完成(2026/06/12)


📁 目錄結構

詳細改檔對照見 userguide.md。前端路徑皆在 frontend/ 底下。

Yuruicamp/
├── frontend/                     # ⭐ npm / Vite 根(三前端 + mock)
│   ├── package.json              # Vite、lint、format、stylelint、smoke
│   ├── vite.config.js
│   ├── index.html                # 品牌入口(重定向至 storefront/pages/home)
│   ├── storefront/               # 主站(裝備商城:pages/ + js/ + css/)
│   ├── components/               # 共用 HTML partial(暫放 frontend 根)
│   ├── booking/                  # 營地預約子站(pages/ + js/ + css/)
│   ├── admin/                    # 賣家後台(login / dashboard / partials / js)
│   ├── data/                     # ⭐ 全站唯一 Mock JSON(執行期 /data/**)
│   ├── assets/                   # 圖片、icon、影片
│   ├── src/styles.js             # Vite SCSS 入口(匯入 storefront/css)
│   ├── tests/                    # smoke 等
│   └── color/                    # 色票文件
│
├── backend/                      # Spring Boot(本階段架構不動)
├── docs/                         # Schema、frontend-specs、database-documents
├── plans/                        # 規劃與遷移規格(含 frontend-folder-migration-spec)
├── thoughts/                     # 開發思考筆記
├── docker-compose.yml            # 本機 PostgreSQL
├── README.md
├── userguide.md                  # 開發者工作手冊(路徑相對 frontend/)
├── changelog.md
└── .gitignore

🚀 快速開始

環境要求

啟動方式

方式 1:npm + Vite(強烈推薦,日常請用這個)

  1. 開啟終端機,進入前端目錄(不要停在 repo 根):

    cd frontend
    
  2. 安裝依賴(第一次或 package.json 有變時):

    npm install
    
  3. 啟動開發伺服器:

    npm run dev
    
  4. 看終端機印出的位址(預設 http://127.0.0.1:5173),用瀏覽器開啟例如:

    • 主站:http://127.0.0.1:5173/storefront/pages/home.html
    • 預約:http://127.0.0.1:5173/booking/pages/camp-search.html
    • 後台:http://127.0.0.1:5173/admin/login.html

為何一定要用 npm/Vite:HTML 已改成根絕對路徑(/storefront/js/.../data/.../assets/...),Vite 以 frontend/ 當網站根,這些路徑才會對上。用錯根目錄時會出現「沒有 CSS/JS、後台沒有假資料」。

常用品質檢查(皆在 frontend/ 執行)

cd frontend
npm run smoke      # 基礎結構與共用 runtime 檢查
npm run lint       # ESLint 檢查 JS
npm run format     # Prettier 檢查格式
npm run stylelint  # Stylelint 檢查 CSS / SCSS
npm run build      # Vite 多頁面建置與資產壓縮

Vite 透過 frontend/src/styles.js 匯入 storefront/css/main.scss;既有 storefront/css/main.css 保留作為非 Vite 靜態伺服器 fallback。

路徑契約(2026-07): 靜態資源與腳本一律用網站根絕對路徑(/assets/storefront/js/data)。Mock 路徑表在 storefront/js/api-mock.jsMockDataPaths;接 Spring 時改 AppConfig.USE_MOCK_API = falseAPI_BASE_URL,不必再改各頁路徑。詳見 plans/frontend-root-absolute-path-and-api-contract-spec.md

方式 2:VS Code Live Server(備援,不建議當日常主路徑)

安裝 Live Server 擴充套件,必須在 frontend/ 目錄右鍵 → Open with Live Server。
不要從 repo 根 Yuruicamp/,否則 /storefront/data 會 404(沒樣式、沒腳本、後台抓不到資料)。日常開發請優先用上方的 npm run dev

共用 Header / Footer 片段使用 .partial 副檔名,而不是 .html。這是為了避免 Live Server 對 HTML fragment 注入 live reload script,造成像 components/header 這類被 fetch() 載入的片段 response 截斷。

方式 3:Python 3(備援)

cd frontend
python -m http.server 8000
# 瀏覽器開啟 http://localhost:8000

方式 4:Node.js 靜態伺服器(備援)

cd frontend
npx http-server -p 8000
# 瀏覽器開啟 http://localhost:8000

首次使用建議路徑

路徑皆相對 frontend/(dev server root)。

買家前台(購物流程)

入口頁 → index.html
首頁   → storefront/pages/home.html
商品   → storefront/pages/products.html → storefront/pages/product-detail.html
購物   → 任一主站頁右上角購物車 Drawer → storefront/pages/checkout.html → storefront/pages/checkout-success.html
會員   → storefront/pages/member-center.html
內容   → storefront/pages/blog.html → storefront/pages/blog-detail.html
分店   → storefront/pages/branches.html
服務   → storefront/pages/faq.html

賣家後台(管理流程) — 詳見 userguide.md 第 13 節

登入   → admin/login.html(Demo 員工 ID:01 老闆 / 02 員工,密碼任意非空)
後台   → admin/dashboard.html(預設載入第一個有 view 權限的模組)
         ├── 分析報表      ← Sidebar「分析報表」
         ├── 訂單管理      ← Sidebar「訂單管理」
         ├── 庫存異動紀錄  ← Sidebar「庫存異動紀錄」
         ├── 商品與庫存    ← Sidebar「商品與庫存」
         ├── 客戶管理      ← Sidebar「客戶管理」
         ├── 折扣管理      ← Sidebar「折扣管理」
         ├── 評論管理      ← Sidebar「評論管理」
         ├── 預約/租借管理 ← Sidebar「預約/租借管理」
         └── 權限管理      ← Sidebar「權限管理」
登出   → Sidebar 底部或 Topbar 頭像 → 登出(清除 5 個 sessionStorage key,返回登入頁)

💡 後台登入狀態用 sessionStorage(5 個 key);員工主檔用 localStorage.adminEmployees。關閉分頁後 session 自動清除,不影響買家前台的 localStorage

預約系統(預約流程)

搜尋   → booking/pages/camp-search.html(篩選地區、環境、設施)
詳情   → booking/pages/camp-detail.html(選日期、選營位類型,寫入 localStorage.bookingCart)
租借   → booking/pages/camp-rental.html(加選裝備,更新 bookingCart)
結帳   → booking/pages/booking-cart.html(確認明細、填聯絡資訊、送出預約)
說明   → booking/pages/rental-guide.html(租借流程圖文說明)
FAQ    → booking/pages/booking-faq.html(預約與退款常見問題)

💡 預約系統使用獨立的 localStorage.bookingCart 儲存跨頁資料,與電商購物車的 localStorage.cart 完全分離,互不干擾。


🎨 設計系統

色彩規範

用途 色碼 預覽
主色 Primary #244d4d 深青綠(品牌主軸)
副色 Secondary #779999 淺青灰綠
成功 Success #4caf50 綠色
危險 Danger #d32f2f 紅色
輕背景 #f6fbf6 淺綠底
深 Hover #316868 按鈕懸停

所有色彩定義於 css/variables.scss,並由 main.css 的 CSS Custom Properties 引入。

💡 預約子系統色彩差異:預約端 Header 背景使用 booking token,並由 booking/css/settings/_tokens.scss 管理 --yc-* source of truth 與 --bk-* 相容 alias;公開頁載入編譯後的 booking/css/booking-main.css

響應式斷點(RWD)

斷點 寬度 目標裝置
xs < 576px iPhone SE、小型 Android
sm 576–767px 大型手機
md 768–991px iPad 直式
lg 992–1199px iPad 橫式、筆電
xl 1200–1399px 桌上型電腦
xxl ≥ 1400px 大型螢幕

手機版特別處理


🔧 全局 API 速查

應用狀態(js/state.js

// 讀取
window.AppState.isLoggedIn; // Boolean - 是否已登入
window.AppState.currentUser; // Object  - 當前用戶資料
window.AppState.cart; // Array   - 購物車商品列表
window.AppState.preferences; // Object  - 個人化喜好

// 持久化(寫入 localStorage)
window.saveAppState();

// 重置(只清除 Yuruicamp 已知狀態 key,不清空同網域其他資料)
window.resetAppState();

Mock API(window.API

// 商品
await window.API.products.getAll(filters); // 取得商品列表(支援篩選)
await window.API.products.getById(productId); // 取得單一商品詳情

// 用戶
await window.API.users.login(email, password); // 模擬登入
await window.API.users.getProfile(userId); // 取得用戶資料

// 訂單
await window.API.orders.getAll(userId); // 取得用戶訂單列表
await window.API.orders.create(orderData); // 建立訂單(模擬)

// 文章
await window.API.articles.getAll(); // 取得文章列表
await window.API.articles.getById(articleId); // 取得文章詳情

// 分店
await window.API.branches.getAll(); // 取得分店列表

💡 日後接入真實後端只需修改 js/api-mock.js 的實作,頁面邏輯無需改動。

UI 元件函數

// Toast 提示
window.showToast(message, type);
// type: 'success' | 'error' | 'warning' | 'info'
// 範例:window.showToast('已加入購物車', 'success')

// Modal 對話框
window.openModal(modalId); // 開啟 Modal
window.closeModal(modalId); // 關閉 Modal
// 範例:window.openModal('loginModal')

// 購物車操作
window.addToCart(product, quantity); // 加入購物車
window.removeFromCart(productId); // 移除商品
window.updateCartQuantity(productId, qty); // 更新數量
window.clearCart(); // 清空購物車
window.openCartDrawer(); // 開啟右側購物車視窗
window.closeCartDrawer(); // 關閉右側購物車視窗
window.renderCartDrawer(); // 依 AppState.cart 重繪 Drawer

工具函數(formatters.js / validators.js / cart-service.js

window.formatCurrency(3500); // → 'NT$3,500'
window.formatDate("2026-06-03"); // → '2026/06/03'
window.generateId(); // → 'id-1748922345-abc123xyz'
window.isValidEmail("a@b.com"); // → true / false
window.isValidPhone("0912345678"); // → true / false
window.calculateCartTotal(); // → Number(購物車總金額)
window.calculateShippingFee(total); // → 0 或 60(依免運門檻)
window.debounce(fn, 300); // 防抖(搜尋框使用)
window.throttle(fn, 100); // 節流(滾動事件使用)

🗄️ localStorage 結構

型別 說明
isLoggedIn Boolean 登入狀態
currentUser Object / null 當前用戶資料
cart Array 電商購物車商品([{id, name, price, quantity, ...}]
preferences Object 個人化問卷結果(風格偏好、裝備需求)
theme String 主題(預留,目前固定 'light'
memberProfile Object 會員中心儲存的個人資料
bookingCart Object 預約購物車({booking_info, selected_zones, selected_rentals, summary}
mockCheckoutSessions Array 契約化 Checkout Mock Session 與內部冪等資料
adminEmployees Array 後台員工清單與逐頁權限(permissions.js 種子初始化)

⚠️ cart(電商)與 bookingCart(預約)是兩個完全獨立的 localStorage key,互不干擾。

resetAppState() 只移除 Yuruicamp 已知狀態,包含 mockOrdersmockCheckoutSessions;不使用 localStorage.clear(),避免誤刪同網域其他專案資料。

sessionStorage 結構

商城 Checkout:

型別 說明
checkoutIdempotencyKey String 建立 Checkout 使用的 UUID
checkoutCartFingerprint String 購物車規格與數量指紋
checkoutCompletedOrderId String 建立成功的後端訂單 ID

後台:

型別 說明
adminLoggedIn String "true" 表示已登入
adminId String 員工 ID(例:"01"
adminName String 顯示名稱
isSuperAdmin String "true" / "false"
adminPermissions String JSON 字串,各 section 的 { view, edit }

⚡ 效能優化(第 14 階段)

所有頁面已套用以下最佳化措施:


🌐 瀏覽器相容性(第 14 階段)

瀏覽器 最低版本 說明
Chrome / Edge 90+ 完整支援
Firefox 88+ 完整支援
Safari 14+ 已加入 -webkit- 前綴、iOS 縮放修正、Safe Area 支援
Samsung Internet 14+ 基於 Chromium,完整支援

已處理的相容性問題


🔐 後端接入指南

Mock API 採用適配器模式。切換真後端時,頁面仍呼叫 window.APIBookingAPIAdminAPI,Token 與 REST 細節統一交給 api-client.js

目前(Mock)

// js/api-mock.js 內部從 JSON 檔讀取
window.API.products.getAll = async (filters) => {
  const data = await fetch("../data/products.json").then((r) => r.json());
  return data.filter(/* ... */);
};

真實 API facade

// facade 呼叫共用 REST 層,pages/*.js 不自行 fetch
window.API.products.getAll = async (filters) => {
  return window.ApiClient._restRequest("/products", {
    auth: "optional",
  });
};

Firebase 初始化後注入 Auth:

window.AppAuth.configure({ auth: firebaseAuth });

本機 dev: Token 只能透過開發認證設定或 AppAuth.configure() 提供,不可寫死在 Checkout 頁面。API Base URL 設定在 storefront/js/config.js

window.AppConfig.API_BASE_URL = "http://localhost:8080/api";

詳細規則與驗證步驟見 docs/frontend-specs/api/auth-rest-client.md


📦 關鍵數字

項目 買家前台 賣家後台 預約系統 合計
HTML 頁面 11 個 2 個(login + dashboard)+ 9 個 partials 6 個 28 個
JavaScript 模組 19 個(6 元件 + 10 頁面 + 3 核心) 10 個(permissions + core + 8 功能) 5 個 34 個
CSS 檔案 1 個(main.css) 1 個(admin.css) 1 個(booking-main.css) 3 個
Mock 資料 JSON 全站共用 /data/**(13 檔,見 data-paths.js 13 個
RWD 斷點 6 個(xs / sm / md / lg / xl / xxl) Bootstrap 5 斷點(同套) 768px 主要斷點
儲存機制 localStorage(8 個鍵,含 bookingCart、adminEmployees) sessionStorage(5 個 key) localStorage.bookingCart

✅ 品質工具與 Smoke Test

以下指令請先 cd frontend 再執行(package.json 已不在 repo 根)。

指令 目的
npm run dev 啟動 Vite 開發伺服器,支援多頁面與 SCSS entry
npm run build 使用 Vite 建置 HTML、JS、SCSS 與資產壓縮輸出
npm run lint 以 ESLint 檢查主站與 booking JS 語法與基礎維護風險
npm run format 以 Prettier 檢查 HTML / CSS / SCSS / JS / JSON / Markdown 格式
npm run stylelint 以 Stylelint 檢查 SCSS 與 booking CSS
npm run smoke 檢查共用 header/cart drawer、拆分 runtime 載入順序、Vite/tooling 檔案是否齊全

🗺️ 未來擴展方向

方向 說明
接入真實後端(前台) 修改 js/api-mock.js 的各函數實作,頁面邏輯零改動
接入真實後端(後台) 修改 admin/js/*.js 中各 fetch('../data/xxx.json')permissions.js 的 localStorage 邏輯改為真實 API
後台密碼驗證 / 操作日誌 逐頁 view/edit 權限已完成;待辦:密碼後端驗證、審計紀錄(見 plans/adminPermissions.md
升級至 SPA 以 Vue 3 或 React 重構,可直接複用現有 CSS 設計系統與 JSON 資料
加入數據分析 main.jsinitGlobalListeners() 接入 GA4 / GTM 事件追蹤
自動化測試 以 Playwright 或 Cypress 撰寫自動化測試腳本
深色模式 main.css 已預留 @media (prefers-color-scheme: dark) 區塊
PWA 加入 manifest.json 與 Service Worker 支援離線瀏覽

📞 品牌聯絡資訊



版本:1.3.76
最後更新:2026/07/06

完整更新紀錄請見 changelog.md