feat: establish enterprise-grade UI design master plan and clean up legacy assets

## Major Changes
-  Add comprehensive Enterprise Design Master Plan v4.0
- 🏗️ Establish 12-week execution roadmap for 95+ UI screens
- 🎨 Define enterprise-grade quality standards and design system
- 📋 Map all designs to function specifications with explicit references
- 🧹 Archive legacy prototype files to maintain clean repository structure

## Key Features
- Complete UI/UX guidelines enhancement plan
- Mobile-first design system with Web optimization
- WCAG 2.1 AA compliance framework
- Cross-platform design consistency standards
- Quality assurance and usability testing protocols

## Architecture
- Based on v3.0 shared module architecture
- 100% function specification compliance
- Modular design system approach
- Comprehensive documentation strategy

This establishes the foundation for creating world-class UI designs that meet Fortune 500 enterprise standards while ensuring perfect alignment with Drama Ling's functional requirements.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
鄭沛軒 2025-09-12 04:28:41 +08:00
parent f55007d2d8
commit ad22c7f4fd
100 changed files with 12406 additions and 8417 deletions

View File

@ -0,0 +1,389 @@
# 🚀 Drama Ling 企業級UI設計總體計劃
**建立日期**: 2025-01-15
**計劃版本**: v4.0 - 企業級重構
**架構基礎**: 共用模組架構 v3.0
**設計標準**: 企業級UI/UX規範
**執行目標**: 95+ UI畫面完整重設計
## 📋 計劃概述
### 🎯 核心目標
基於 Drama Ling v3.0 共用模組架構創建企業級標準的完整UI設計系統確保
- **100%符合功能規格**: 嚴格按照 `/docs/02_design/function-specs/` 規格執行
- **統一設計語言**: 完全遵循 `/docs/02_design/ui-ux/ui-ux-guidelines.md` 規範
- **企業級品質**: 達到Fortune 500企業內部系統標準
- **零設計債務**: 徹底重構,消除所有設計不一致問題
### 🏗️ 設計架構原則
1. **規格優先**: 所有設計必須100%符合功能規格文件
2. **模組化設計**: 基於v3.0共用模組架構的設計組件系統
3. **一致性保證**: 跨平台設計語言統一
4. **可擴展性**: 支援未來功能快速擴展的設計框架
5. **無障礙標準**: 符合WCAG 2.1 AA級無障礙要求
## 🔍 階段一:設計規範完善與標準化 (第1-2週)
### 1.1 UI/UX規範補全與更新 ⭐ **CRITICAL**
**目標**: 建立企業級完整設計規範系統
**工作內容**:
- [ ] **色彩系統完善**
- 引用文件: `/docs/02_design/ui-ux/ui-ux-guidelines.md` (第35-103行)
- 補全遺失的色彩定義:狀態色彩、反饋色彩、學習進度色彩
- 建立暗色/亮色主題完整色彩對照表
- 定義色彩使用場景和層次規範
- [ ] **字體系統標準化**
- 引用文件: `/docs/02_design/ui-ux/ui-ux-guidelines.md` (第105-136行)
- 補全遺失字體規格:多語言字體、特殊用途字體
- 建立響應式字體大小系統 (mobile/tablet/desktop)
- 定義字體層次和使用場景指南
- [ ] **間距與佈局系統**
- 引用文件: `/docs/02_design/ui-ux/ui-ux-guidelines.md` (第139-163行)
- 建立8px grid系統標準
- 定義響應式佈局斷點和規則
- 創建元件間距和頁面佈局標準模板
- [ ] **組件設計規範**
- 引用文件: `/docs/02_design/ui-ux/ui-ux-guidelines.md` (第188-200行)
- 補全缺失的組件規範:表單元件、遊戲化元件、學習專用元件
- 建立組件狀態系統 (default/hover/active/disabled/loading)
- 定義組件變體和使用場景
**輸出物**:
- `ui-ux-guidelines.md` 完整更新版本 (企業級標準)
- `design-system-components.md` 完整組件庫文檔
- `responsive-design-standards.md` 響應式設計標準
- `accessibility-guidelines.md` 無障礙設計指南
### 1.2 企業級設計系統建立
**目標**: 創建可重用的設計系統和組件庫
**工作內容**:
- [ ] **原子設計系統**: Atoms → Molecules → Organisms → Templates → Pages
- [ ] **Design Tokens**: 設計變數化管理系統
- [ ] **組件庫標準化**: 可重用UI組件集合
- [ ] **圖標系統**: 學習情境專用圖標設計
- [ ] **動畫設計語言**: 統一的動畫效果和互動反饋
**輸出物**:
- `design-system-tokens.css` - 完整設計變數系統
- `component-library.html` - 互動式組件展示
- `animation-guidelines.md` - 動畫設計標準
- `icon-system.svg` - 完整圖標庫
## 📱 階段二Mobile端企業級重設計 (第3-6週)
### 2.1 核心學習功能頁面群組 (第3-4週)
#### 2.1.1 情境對話系統 🎯 (優先級: P0)
**規格參考**:
- 主規格: `/docs/02_design/function-specs/mobile/01_situational-dialogue-mobile.md`
- 共用模組: `/docs/02_design/function-specs/common/ai-algorithm-specs.md`
- 共用模組: `/docs/02_design/function-specs/common/speaking-evaluation-specs.md`
- 共用模組: `/docs/02_design/function-specs/common/pragmatic-analysis-specs.md`
**需設計的頁面**:
- [ ] **UI_Dialogue_Practice_Main** - 情境對話練習主界面
- 設計要求: 語音輸入界面 (參考: ai-algorithm-specs.md 語音處理)
- 設計要求: 即時AI反饋顯示 (參考: ai-algorithm-specs.md AI評估系統)
- 設計要求: 劇情任務和詞彙任務雙重可視化
- 設計要求: 300秒限時挑戰計時器
- UI規範: 語音優先設計、即時語法反饋 (ui-ux-guidelines.md 第27-28行)
- [ ] **UI_Dialogue_Character_Selection** - 角色選擇頁面
- 設計要求: 角色卡片設計,突出角色特色和學習情境
- 設計要求: 角色能力和適合程度顯示
- [ ] **UI_Dialogue_Scene_Setting** - 場景設定頁面
- 設計要求: 沉浸式場景展示
- UI規範: 沉浸式學習環境設計 (ui-ux-guidelines.md 第9行)
- [ ] **UI_AI_Assistance_Panel** - AI輔助功能面板
- 設計要求: 回覆提示道具使用界面
- 設計要求: 語法即時檢測顯示
- UI規範: 智慧輔助、漸進引導 (ui-ux-guidelines.md 第21-22行)
- [ ] **UI_Dialogue_Results** - 對話練習結果頁面
- 設計要求: 口說評分五維雷達圖 (參考: speaking-evaluation-specs.md)
- 設計要求: 語用分析六維評估 (參考: pragmatic-analysis-specs.md)
- UI規範: 即時成就反饋 (ui-ux-guidelines.md 第25行)
#### 2.1.2 詞彙學習系統 📝 (優先級: P0)
**規格參考**:
- 主規格: `/docs/02_design/function-specs/mobile/02_vocabulary-learning-mobile.md`
- 共用模組: `/docs/02_design/function-specs/common/progressive-stage-system.md`
**需設計的頁面**:
- [ ] **UI_Vocab_Learning_Enhanced** - 多媒體詞彙學習主界面
- 設計要求: 詞彙展示 (音標、定義、例句)
- 設計要求: 雙語音頻系統 (標準速度/慢速)
- 設計要求: 智慧詞彙標註 (Source + Example)
- 設計要求: 視覺輔助學習 (例句配圖)
- UI規範: 詞彙學習流程 (ui-ux-guidelines.md 第29行)
- [ ] **UI_Vocab_Choice_Practice** - 詞彙選擇練習頁面
- 設計要求: 選擇題界面,支援多選和單選模式
- 設計要求: 即時正確性反饋
- [ ] **UI_Vocab_Fluency_Results** - 流暢度練習綜合結果
- 設計要求: 學習成效可視化展示
- 設計要求: 進度追蹤和建議系統
- [ ] **UI_Vocab_Review_System** - 間隔複習系統界面
- 設計要求: 複習提醒和排程界面
- UI規範: 間隔複習提醒 (ui-ux-guidelines.md 第31行)
#### 2.1.3 學習地圖系統 🗺️ (優先級: P0)
**規格參考**:
- 主規格: `/docs/02_design/function-specs/mobile/03_learning-map-mobile.md`
- 共用模組: `/docs/02_design/function-specs/common/progressive-stage-system.md`
**需設計的頁面**:
- [ ] **UI_Level_Map** - 學習地圖主畫面 (線性闖關版)
- 設計要求: 13階段×20劇本的地圖視覺化
- 設計要求: 四關進度指示器 (詞彙學習→詞彙熟悉→口說練習→情境對話)
- 設計要求: 關卡狀態管理 (🔒鎖定/⏳可進行/🔄進行中/✅已完成)
- 引用規格: progressive-stage-system.md 完整關卡系統
- [ ] **UI_Current_Level_Info** - 當前可進行關卡資訊面板
- 設計要求: 關卡詳細資訊展示
- 設計要求: 開始學習入口和準備指南
- [ ] **UI_Level_Progress_Detail** - 關卡進度詳情頁面
- 設計要求: 詳細進度追蹤和統計
- 設計要求: 個人表現分析
- [ ] **UI_Stage_Overview** - 階段總覽和劇本選擇
- 設計要求: 階段性學習目標展示
- 設計要求: 劇本選擇和預覽功能
- [ ] **UI_Level_Locked_Modal** - 關卡鎖定提示彈窗
- 設計要求: 解鎖條件清晰提示
- 設計要求: 引導用戶完成前置任務
### 2.2 商業功能頁面群組 (第4-5週)
#### 2.2.1 道具商店系統 🛒 (優先級: P1)
**規格參考**:
- 主規格: `/docs/02_design/function-specs/mobile/04_item-shop-mobile.md`
- 共用模組: `/docs/02_design/function-specs/common/business-rules.md`
**需設計的頁面**:
- [ ] **UI_Shop_Categories** - 道具商店分類主頁面
- 設計要求: 鑽石購買區 (5個價格套餐)
- 設計要求: 學習輔助道具區 (回覆提示、補命、加時)
- 設計要求: 限時挑戰道具區 (時間暫停、時間加成)
- 引用規格: business-rules.md 命條系統和經濟系統
- [ ] **UI_Diamond_Purchase** - 鑽石購買頁面
- 設計要求: 價格套餐展示和優惠信息
- 設計要求: 支付流程整合
- [ ] **UI_Item_Details** - 單一道具詳情頁面
- 設計要求: 道具功能詳細說明
- 設計要求: 使用場景和效果展示
- [ ] **UI_Shop_Item_Confirm** - 道具購買確認彈窗
- 設計要求: 購買資訊確認和風險提示
- UI規範: 高風險按鈕文字標注 (ui-ux-guidelines.md 第194行)
- [ ] **UI_Cost_Confirm_Popup** - 成本確認彈窗 (口說練習特別關卡)
- 設計要求: 特殊關卡成本說明
- 設計要求: 用戶決策支援資訊
#### 2.2.2 用戶認證系統 🔐 (優先級: P1)
**規格參考**:
- 主規格: `/docs/02_design/function-specs/mobile/05_user-authentication-mobile.md`
- 共用模組: `/docs/02_design/function-specs/common/business-rules.md`
**需設計的頁面**:
- [ ] **UI_Login_Main** - 主要登入頁面
- 設計要求: 多平台登入選項 (Google, Facebook, Apple)
- 設計要求: 記住登入和安全驗證
- 設計要求: 錯誤處理和安全提示
- [ ] **UI_SignUp_Main** - 用戶註冊頁面
- 設計要求: 分步驟註冊流程
- 設計要求: 即時驗證和錯誤提示
- 設計要求: 學習目標和程度設定
- [ ] **UI_PasswordReset_Form** - 密碼重置表單
- 設計要求: 多步驟驗證流程
- 設計要求: 安全性說明和引導
- [ ] **UI_PasswordReset_Popup** - 密碼重置確認彈窗
- 設計要求: 重置成功確認和後續指引
- [ ] **UI_Account_List** - 帳戶列表管理頁面
- 設計要求: 多帳戶管理和切換
- 設計要求: 帳戶安全狀態顯示
- [ ] **UI_Account_Option** - 帳戶選項設定頁面
- 設計要求: 帳戶設定和隱私控制
- 設計要求: 帳戶關聯和解綁功能
### 2.3 支援功能頁面群組 (第5-6週)
#### 2.3.1 系統介面和狀態頁面 📊 (優先級: P2)
**需設計的頁面**:
- [ ] **UI_Insufficient_Resources** - 資源不足提示頁面
- 設計要求: 清晰的資源不足說明
- 設計要求: 獲取資源的引導路徑
- [ ] **UI_LifePoints_Display** - 生命點數顯示組件
- 設計要求: 直觀的生命值視覺化
- UI規範: 命條生命系統 (ui-ux-guidelines.md 第30行)
- [ ] **UI_Subscription_Success** - 訂閱成功頁面
- 設計要求: 訂閱確認和權益說明
- 設計要求: 後續使用指引
- [ ] **UI_TimeWarp_Cards** - 時光卷使用介面
- 設計要求: 時光卷功能說明和使用確認
- 設計要求: 使用後效果展示
- [ ] **UI_LevelResult_SuccessResult** - 關卡成功結果頁面
- 設計要求: 成就慶祝動畫和統計展示
- UI規範: 即時成就反饋 (ui-ux-guidelines.md 第25行)
## 💻 階段三Web端企業級重設計 (第7-9週)
### 3.1 Web端專屬功能設計 (第7-8週)
**規格參考**: `/docs/02_design/function-specs/web/` 全部Web端規格
**設計重點**:
- [ ] **桌面優化界面**: 大螢幕佈局和多視窗支援
- [ ] **鍵盤導航**: 完整的鍵盤操作支援
- [ ] **批量操作**: 企業級批量管理功能
- [ ] **高級分析**: 詳細的學習分析和報告功能
**需設計的主要頁面**:
- [ ] **詞彙學習Web版**: 桌面優化的詞彙學習界面
- [ ] **情境對話Web版**: 大螢幕對話練習界面
- [ ] **學習地圖Web版**: 多層級地圖導航界面
- [ ] **道具商店Web版**: 企業級商店管理界面
- [ ] **用戶認證Web版**: SSO和企業登入支援
### 3.2 響應式設計和跨平台整合 (第8-9週)
**工作內容**:
- [ ] **響應式佈局**: Mobile → Tablet → Desktop 完整適配
- [ ] **跨瀏覽器相容性**: Chrome, Firefox, Safari, Edge 完整支援
- [ ] **效能優化**: 載入時間和互動回應最佳化
- [ ] **PWA功能**: 漸進式Web應用功能整合
## 🔧 階段四:設計系統完善和品質保證 (第10-12週)
### 4.1 設計系統文檔化和工具化 (第10-11週)
**工作內容**:
- [ ] **設計規範手冊**: 完整的設計規範使用指南
- [ ] **組件使用指南**: 每個組件的使用場景和最佳實踐
- [ ] **設計審查清單**: 品質控制清單和審查標準
- [ ] **維護指南**: 設計系統維護和更新流程
### 4.2 品質保證和使用性測試 (第11-12週)
**工作內容**:
- [ ] **設計一致性審查**: 跨平台設計一致性檢查
- [ ] **無障礙性測試**: WCAG 2.1 AA級合規驗證
- [ ] **使用性測試**: 用戶測試和回饋收集
- [ ] **效能評估**: 設計對系統效能的影響評估
## 📊 成功標準和驗收條件
### 🎯 品質標準
1. **功能規格符合度**: 100%符合所有功能規格要求
2. **設計一致性**: 跨平台設計語言100%統一
3. **無障礙標準**: WCAG 2.1 AA級100%合規
4. **效能標準**: 頁面載入時間<3秒互動回應時間<200ms
5. **瀏覽器支援**: 主流瀏覽器100%相容
### 📋 驗收清單
- [ ] 所有UI畫面符合對應功能規格文件要求
- [ ] 所有設計符合UI/UX規範標準
- [ ] 跨平台視覺一致性通過審查
- [ ] 無障礙功能測試全部通過
- [ ] 使用性測試滿意度≥90%
## 📁 交付物清單
### 🎨 設計文檔
- [ ] `ui-ux-guidelines.md` - 完善的UI/UX設計規範
- [ ] `design-system-documentation.md` - 設計系統完整文檔
- [ ] `component-library-guide.md` - 組件庫使用指南
- [ ] `responsive-design-standards.md` - 響應式設計標準
### 💻 設計資產
- [ ] `design-system.css` - 完整CSS設計系統
- [ ] 95+ HTML原型頁面 (Mobile + Web)
- [ ] 完整SVG圖標庫
- [ ] 設計系統展示網站
### 📋 支援文檔
- [ ] `design-review-checklist.md` - 設計審查清單
- [ ] `accessibility-compliance-report.md` - 無障礙合規報告
- [ ] `usability-test-results.md` - 使用性測試報告
- [ ] `maintenance-guidelines.md` - 維護指南
## 🚨 風險管控和品質保證
### ⚠️ 關鍵風險點
1. **規格理解偏差**: 設計不符合功能規格要求
- **控制措施**: 每個設計階段都進行規格文件交叉檢查
- **責任人**: 設計師必須深度閱讀相關規格文件
2. **設計一致性風險**: 跨頁面設計語言不統一
- **控制措施**: 建立設計審查機制,每週進行一致性檢查
- **工具支援**: 建立設計系統檢查清單
3. **無障礙合規風險**: 無障礙功能不完整
- **控制措施**: 每個組件設計完成都進行無障礙測試
- **標準遵循**: 嚴格遵循WCAG 2.1 AA級標準
### 🔍 品質控制機制
1. **階段性審查**: 每個階段結束進行全面審查
2. **同行評議**: 設計師之間相互審查和回饋
3. **用戶測試**: 關鍵頁面進行真實用戶測試
4. **技術可行性評估**: 設計與開發團隊聯合評估
## 📞 執行支援和溝通機制
### 🤝 團隊協作
- **設計團隊**: 負責設計執行和品質控制
- **產品團隊**: 提供功能需求解釋和使用者回饋
- **開發團隊**: 提供技術可行性建議和實現支援
- **測試團隊**: 提供品質測試和驗收支援
### 📋 進度追蹤
- **每週進度會議**: 檢討進度和解決阻礙
- **里程碑審查**: 階段性成果展示和評估
- **問題升級機制**: 重大問題快速上報和解決
- **文檔同步更新**: 確保所有團隊資訊同步
---
**📝 重要聲明**:
本計劃基於Drama Ling v3.0共用模組架構制定確保所有設計完全符合功能規格要求達到企業級應用標準。所有設計師在執行前必須深入理解相關功能規格文件和UI/UX規範確保設計品質和一致性。
**🎯 最終目標**:
創建Drama Ling史上最高品質的UI設計系統為用戶提供世界級的沉浸式英語學習體驗。
---
**最後更新**: 2025-01-15
**計劃版本**: v4.0 - 企業級重構
**執行週期**: 12週
**預期成果**: 95+ 企業級UI畫面

View File

@ -21,15 +21,15 @@ docs/
### 🚀 `/00_starter` - 專案基礎
**用途**: 包含專案初始化和AI輔助開發所使用的基礎模板和提示詞。
| 檔案名稱 | 用途 |
|------|---------|
| `CLAUDE_TEMPLATE.md` | Claude AI 互動模板和專案設置 |
| `READ.md` | 使用入門模板的說明指引 |
| `business_function_design_prompt.md` | 生成業務功能設計的 AI 提示詞 |
| `generate_requirements_prompt.md` | 創建專案需求的 AI 提示詞 |
| `generate_system_structure_prompt.md` | 系統架構生成的 AI 提示詞 |
| `system_detail_prompt.md` | 詳細系統規格的 AI 提示詞 |
| `system_structured_schema.json` | 結構化系統設計輸出的 JSON 架構 |
| 檔案名稱 | 用途 |
| ------------------------------------- | ------------------------------ |
| `CLAUDE_TEMPLATE.md` | Claude AI 互動模板和專案設置 |
| `READ.md` | 使用入門模板的說明指引 |
| `business_function_design_prompt.md` | 生成業務功能設計的 AI 提示詞 |
| `generate_requirements_prompt.md` | 創建專案需求的 AI 提示詞 |
| `generate_system_structure_prompt.md` | 系統架構生成的 AI 提示詞 |
| `system_detail_prompt.md` | 詳細系統規格的 AI 提示詞 |
| `system_structured_schema.json` | 結構化系統設計輸出的 JSON 架構 |
**使用時機**: 這些檔案主要在專案初始化時使用,以及與 AI 助手協作生成文檔和程式碼結構時使用。
@ -38,13 +38,13 @@ docs/
### 📋 `/01_requirement` - 需求文檔
**用途**: 包含核心專案需求、規格說明和系統設計文檔。**專注於知識管理和規格定義**。
| 檔案名稱 | 用途 |
|------|---------|
| `founding_pitch.md` | 初始專案提案和商業案例 |
| `requirements.md` | **產品功能需求總覽** - 詳細的產品規格和功能概述 |
| `user-stories.md` | **用戶故事和使用場景** - 用戶需求和互動情境 |
| `business-rules.md` | **業務邏輯和規則定義** - 核心商業規則和流程 |
| `acceptance-criteria.md` | **驗收標準和測試條件** - 功能驗收和品質標準 |
| 檔案名稱 | 用途 |
| ------------------------------ | ----------------------------------------------------------------- |
| `founding_pitch.md` | 初始專案提案和商業案例 |
| `requirements.md` | **產品功能需求總覽** - 詳細的產品規格和功能概述 |
| `user-stories.md` | **用戶故事和使用場景** - 用戶需求和互動情境 |
| `business-rules.md` | **業務邏輯和規則定義** - 核心商業規則和流程 |
| `acceptance-criteria.md` | **驗收標準和測試條件** - 功能驗收和品質標準 |
| `system_structure_design.json` | **結構化系統設計** - 從需求生成包含模組、功能和UI視圖的JSON格式 |
**關鍵文檔**: `requirements.md` 是產品應該做什麼以及如何運作的唯一真實來源。
@ -54,20 +54,20 @@ docs/
### 🎨 `/02_design` - 設計規格 (更新 2025-09-09)
**用途**: 涵蓋使用者體驗、視覺設計和互動模式的文檔。**專注於知識管理和規格定義**。
| 檔案名稱 | 用途 |
|------|---------|
| `ui-specifications.md` | **UI設計規範和標準** - 視覺設計標準和介面規範 |
| `ux-guidelines.md` | **用戶體驗設計指南** - 互動模式和使用者流程 |
| `component-library.md` | **UI組件庫文檔** - 可重用組件和設計系統 |
| `design-tokens.md` | **設計令牌和主題系統** - 顏色、字體、間距等設計變量 |
| `ai-algorithm-specs.md` | AI 分析演算法和語言處理規格 |
| `business-logic-rules.md` | 核心商業規則和邏輯流程定義 |
| `content-management-specs.md` | 內容創建、策劃和管理工作流程 |
| `gamification-mechanics.md` | 遊戲元素、成就和獎勵系統設計 |
| `ui-ux-guidelines.md` | 視覺設計標準、組件庫和使用者介面指南 |
| `function-specs/` | 平台別功能規格mobile/web/common|
| `html-prototypes/` | HTML原型和頁面範例 |
| `views/` | UI視圖設計檔案 |
| 檔案名稱 | 用途 |
| ---------------------------- | --------------------------------------------------- |
| `prototype-design-plan.md` | **原型設計製作計劃** - 雛形畫面開發的完整規劃 |
| `function-specs/` | **平台別功能規格** - mobile/web/common功能詳細規格 |
| `prototypes/` | **HTML原型系統** - 可互動的功能演示界面 |
| `ui-ux/` | **UI/UX設計系統** - 視覺規範、組件庫、樣式指南 |
| `views/` | **UI視圖設計檔案** - 介面設計的視覺化參考 |
**實際子目錄結構**:
- `function-specs/common/` - 跨平台共用規格API、資料模型、業務規則等
- `function-specs/mobile/` - 行動端專用功能規格
- `function-specs/web/` - 網頁端專用功能規格
- `ui-ux/ui-ux-guidelines.md` - 統一的UI/UX設計規範
- `ui-ux/dramaling-ui.css` - Drama Ling設計系統樣式表
**目標讀者**: 設計師、前端開發人員和產品經理。
@ -76,14 +76,14 @@ docs/
### 👨‍💻 `/03_development` - 開發文檔 (更新 2025-09-09)
**用途**: 為開發人員提供編碼標準、工作流程和專案路線圖的指南。**專注於知識管理和規格定義**。
| 檔案名稱 | 用途 |
|------|---------|
| `coding-standards.md` | **程式碼規範** - Flutter/Dart 和 .NET/C# 的程式碼風格指南、命名慣例和最佳實踐 |
| `architecture-overview.md` | **系統架構概述** - 整體系統架構和設計決策說明 |
| `deployment-guide.md` | **部署流程文檔** - 部署步驟、環境配置和發布流程 |
| `troubleshooting.md` | **常見問題排除** - 開發過程中常見問題的解決方案 |
| `development-workflow.md` | Git 工作流程、分支策略、程式碼審查流程和開發生命週期 |
| `project-roadmap.md` | **開發時程表** - 階段、里程碑和功能交付時程 |
| 檔案名稱 | 用途 |
| -------------------------- | ----------------------------------------------------------------------------- |
| `coding-standards.md` | **程式碼規範** - Flutter/Dart 和 .NET/C# 的程式碼風格指南、命名慣例和最佳實踐 |
| `architecture-overview.md` | **系統架構概述** - 整體系統架構和設計決策說明 |
| `deployment-guide.md` | **部署流程文檔** - 部署步驟、環境配置和發布流程 |
| `troubleshooting.md` | **常見問題排除** - 開發過程中常見問題的解決方案 |
| `development-workflow.md` | Git 工作流程、分支策略、程式碼審查流程和開發生命週期 |
| `project-roadmap.md` | **開發時程表** - 階段、里程碑和功能交付時程 |
**目標讀者**: 所有參與專案的開發人員。
@ -92,19 +92,19 @@ docs/
### ⚙️ `/04_technical` - 技術規格 (更新 2025-09-09)
**用途**: 技術實作細節、系統架構和整合規格說明。**專注於知識管理和規格定義**。
| 子目錄/檔案 | 用途 |
|------|---------|
| `api-specifications.md` | **API接口文檔** - 完整API規格、端點定義和資料格式 |
| `database-schema.md` | **資料庫設計文檔** - 資料表結構、關聯和索引設計 |
| `security-requirements.md` | **安全性需求** - 安全標準、認證機制和資料保護 |
| `performance-standards.md` | **效能標準定義** - 效能指標、基準測試和優化準則 |
| `01_architecture/` | 系統架構設計和決策文檔 |
| `02_api/` | **REST API 文檔** - 完整API規格、端點文檔、Swagger UI |
| `03_frontend/` | 前端技術規格和實作指南 |
| `04_mobile/` | 移動端開發技術規格 |
| `05_deployment/` | 部署流程和環境配置 |
| `06_development/` | **開發過程管理** - 問題追蹤、環境設定和開發工具配置 |
| `07_planning/` | 技術規劃和決策記錄 |
| 子目錄/檔案 | 用途 |
| -------------------------- | ----------------------------------------------------- |
| `api-specifications.md` | **API接口文檔** - 完整API規格、端點定義和資料格式 |
| `database-schema.md` | **資料庫設計文檔** - 資料表結構、關聯和索引設計 |
| `security-requirements.md` | **安全性需求** - 安全標準、認證機制和資料保護 |
| `performance-standards.md` | **效能標準定義** - 效能指標、基準測試和優化準則 |
| `01_architecture/` | 系統架構設計和決策文檔 |
| `02_api/` | **REST API 文檔** - 完整API規格、端點文檔、Swagger UI |
| `03_frontend/` | 前端技術規格和實作指南 |
| `04_mobile/` | 移動端開發技術規格 |
| `05_deployment/` | 部署流程和環境配置 |
| `06_development/` | **開發過程管理** - 問題追蹤、環境設定和開發工具配置 |
| `07_planning/` | 技術規劃和決策記錄 |
**關鍵文檔**: `02_api/` 目錄中的API文檔作為前端和後端團隊之間的契約。
@ -135,15 +135,15 @@ docs/
### ✅ 正確的內容分層
| 內容類型 | 正確位置 |
|---------|----------|
| 產品規格和需求 | `docs/01_requirement/` |
| 設計標準和指南 | `docs/02_design/` |
| 技術架構和 API 規格 | `docs/04_technical/` |
| 編碼規範和流程 | `docs/03_development/` |
| 具體任務和待辦事項 | `TASKS.md` |
| 專案執行計畫 | `projects/[專案名].md` |
| 進度追蹤和狀態更新 | 專案管理工具 |
| 內容類型 | 正確位置 |
| ------------------- | ---------------------- |
| 產品規格和需求 | `docs/01_requirement/` |
| 設計標準和指南 | `docs/02_design/` |
| 技術架構和 API 規格 | `docs/04_technical/` |
| 編碼規範和流程 | `docs/03_development/` |
| 具體任務和待辦事項 | `TASKS.md` |
| 專案執行計畫 | `projects/[專案名].md` |
| 進度追蹤和狀態更新 | 專案管理工具 |
---
@ -176,7 +176,7 @@ docs/
- 主要文檔: `/02_design/ui-ux-guidelines.md`, `/02_design/gamification-mechanics.md`
- 內容策略: `/02_design/content-management-specs.md`
- 功能規格: `/02_design/function-specs/`
- 原型參考: `/02_design/html-prototypes/`
- 原型參考: `/02_design/prototypes/`
---
@ -198,16 +198,16 @@ docs/
## 🔍 快速參考
| 尋找... | 前往... |
|----------------|----------|
| 要建構什麼功能 | `/01_requirement/requirements.md` |
| API 端點和資料格式 | `/04_technical/02_api/` |
| 系統架構 | `/04_technical/01_architecture/` |
| UI 設計標準 | `/02_design/ui-ux-guidelines.md` |
| 如何貢獻程式碼 | `/03_development/development-workflow.md` |
| 開發時程表 | `/03_development/project-roadmap.md` |
| 功能規格 | `/02_design/function-specs/` |
| 部署流程 | `/04_technical/05_deployment/` |
| 尋找... | 前往... |
| ------------------ | ----------------------------------------- |
| 要建構什麼功能 | `/01_requirement/requirements.md` |
| API 端點和資料格式 | `/04_technical/02_api/` |
| 系統架構 | `/04_technical/01_architecture/` |
| UI 設計標準 | `/02_design/ui-ux-guidelines.md` |
| 如何貢獻程式碼 | `/03_development/development-workflow.md` |
| 開發時程表 | `/03_development/project-roadmap.md` |
| 功能規格 | `/02_design/function-specs/` |
| 部署流程 | `/04_technical/05_deployment/` |
---

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -18,19 +18,18 @@
- 訂閱用戶: 30個
- 進階用戶: 50個
- **恢復機制**:
- 免費用戶: 每5小時自動恢復1個命條
- 訂閱用戶: 每小時自動恢復3個命條
- 進階用戶: 每小時自動恢復5個命條
- **命條消耗**: 1、2、3關啟動時消耗命條(第2+關不消耗)
### 消耗場景 (四關闖關系統)
| 場景 | 命條消耗 | 說明 |
| -------------- | -------- | ---------------------------- |
| 第1關詞彙學習 | 1個 | 啟動關卡時消耗,學習過程免費 |
| 第2關詞彙熟悉 | 1個 | 啟動關卡時消耗,無論答對答錯 |
| 場景 | 命條消耗 | 說明 |
| ------------------------ | -------- | ----------------------------- |
| 第1關詞彙學習 | 1個 | 啟動關卡時消耗,學習過程免費 |
| 第2關詞彙熟悉 | 1個 | 啟動關卡時消耗,無論答對答錯 |
| 第2+關:口說練習特別關卡 | 0個 | 付費關卡5鑽石不消耗命條 |
| 第3關情境對話 | 1個 | 啟動關卡時消耗,無論成功失敗 |
| 對話有辱罵情形 | 3個 | 額外扣除懲罰 |
| 第3關情境對話 | 1個 | 啟動關卡時消耗,無論成功失敗 |
| 對話有辱罵情形 | 3個 | 額外扣除懲罰 |
### 獲得命條方式
- **自動恢復**: 依用戶等級不同恢復速度(見上方基本規則)
@ -286,12 +285,12 @@
- **學習階層**: 第x階段 > 第x劇本 > 第x關卡
#### 關卡類型與規則
| 關卡類型 | 收費模式 | 命條消耗 | 星級獲得 | 解鎖條件 | 通關條件 |
|---------|---------|----------|----------|----------|----------|
| 詞彙學習 | 免費 | 啟動扣1條 | 自動3星 | 無 | 全部答對 |
| 詞彙熟悉 | 免費 | 啟動扣1條 | 自動3星 | 完成第1關 | 全部答對 |
| 口說練習特別關卡 | 5鑽石 | 不扣命條 | 1-3星 | 完成第2關 | 平均70分+ |
| 情境對話 | 免費 | 啟動扣1條 | 1-3星 | 完成第2+關或跳過 | 雙重通關條件 |
| 關卡類型 | 收費模式 | 命條消耗 | 星級獲得 | 解鎖條件 | 通關條件 |
| ---------------- | -------- | --------- | -------- | ---------------- | ------------ |
| 詞彙學習 | 免費 | 啟動扣1條 | 自動3星 | 無 | 全部答對 |
| 詞彙熟悉 | 免費 | 啟動扣1條 | 自動3星 | 完成第1關 | 全部答對 |
| 口說練習特別關卡 | 5鑽石 | 不扣命條 | 1-3星 | 完成第2關 | 平均70分+ |
| 情境對話 | 免費 | 啟動扣1條 | 1-3星 | 完成第2+關或跳過 | 雙重通關條件 |
### 舊版關卡結構系統
#### BR-LEARN-01: 階段化學習架構

View File

@ -1,16 +0,0 @@
詞彙
- Vocab: optimal
- Level: B2
- Definition:
The best or most effective possible in a particular situation.
- Original Sentence:
For the optimal coding experience, enable the recommended settings
- Example Sentence:
The optimal time to plant these seeds is in early spring.
- Example Image url:
- 例句音檔
- 詞彙正常速度音檔
- 詞彙慢速速度音檔
劇本

View File

@ -6,7 +6,7 @@
**建立日期**: 2025-09-08
**最後更新**: 2025-09-12
**負責團隊**: 產品/設計/開發
**原型參考**: `/prototypes/screens/phase2/05-vocabulary-learning-enhanced.html`
**原型參考**: `/docs/02_design/prototypes/screens/phase2/05-vocabulary-learning-enhanced.html`
### 主要功能
- **沉浸式詞彙展示**: 詞彙、音標、定義、多媒體整合展示
@ -346,7 +346,7 @@
## 📚 參考資源
- **原型畫面**: `/prototypes/screens/phase2/05-vocabulary-learning-enhanced.html`
- **原型畫面**: `/docs/02_design/prototypes/screens/phase2/05-vocabulary-learning-enhanced.html`
- **線性闖關系統**: `docs/02_design/function-specs/common/progressive-stage-system.md`
- **UI/UX設計規範**: `docs/02_design/ui-ux/ui-ux-guidelines.md` - 按鈕文字標注原則
- **命條系統規則**: `docs/02_design/function-specs/common/business-rules.md`

File diff suppressed because it is too large Load Diff

View File

@ -1,279 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 登入</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Login_Screen - 用戶登入界面 */
.login-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--primary-teal) 0%, var(--secondary-purple) 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--space-6);
}
.app-logo {
margin-bottom: var(--space-12);
text-align: center;
}
.app-logo h1 {
font-size: var(--text-4xl);
color: var(--text-primary);
margin-bottom: var(--space-2);
font-weight: bold;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.app-logo p {
font-size: var(--text-lg);
color: var(--text-secondary);
opacity: 0.9;
}
.login-card {
background: var(--card-background);
border-radius: var(--radius-lg);
padding: var(--space-8);
width: 100%;
max-width: 400px;
box-shadow: var(--shadow-xl);
border: 3px solid rgba(255,255,255,0.1);
}
.form-group {
margin-bottom: var(--space-6);
}
.form-label {
display: block;
font-size: var(--text-base);
color: var(--text-primary);
margin-bottom: var(--space-2);
font-weight: 500;
}
.form-input {
width: 100%;
padding: var(--space-4);
border: 2px solid var(--divider);
border-radius: var(--radius-md);
background: var(--background-secondary);
color: var(--text-primary);
font-size: var(--text-base);
transition: border-color var(--duration-normal);
}
.form-input:focus {
outline: none;
border-color: var(--primary-teal);
box-shadow: 0 0 0 3px rgba(0, 229, 204, 0.2);
}
.btn-login {
width: 100%;
padding: var(--space-4);
background: var(--primary-teal);
color: var(--background-dark);
border: 3px solid var(--primary-teal-dark);
border-radius: var(--radius-md);
font-size: var(--text-lg);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
margin-bottom: var(--space-4);
box-shadow: 0 4px 0 var(--primary-teal-dark);
transform: translateY(0);
}
.btn-login:hover {
background: var(--primary-teal-light);
transform: translateY(-1px);
box-shadow: 0 5px 0 var(--primary-teal-dark);
}
.btn-login:active {
transform: translateY(2px);
box-shadow: 0 2px 0 var(--primary-teal-dark);
}
.divider {
text-align: center;
margin: var(--space-6) 0;
position: relative;
color: var(--text-tertiary);
}
.divider::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: var(--divider);
}
.divider span {
background: var(--card-background);
padding: 0 var(--space-4);
}
.btn-google {
width: 100%;
padding: var(--space-4);
background: var(--text-primary);
color: var(--background-dark);
border: 3px solid #e0e0e0;
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: 500;
cursor: pointer;
transition: all var(--duration-normal);
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-3);
margin-bottom: var(--space-6);
box-shadow: 0 4px 0 #d0d0d0;
transform: translateY(0);
}
.btn-google:hover {
background: #f5f5f5;
transform: translateY(-1px);
box-shadow: 0 5px 0 #d0d0d0;
}
.btn-google:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #d0d0d0;
}
.google-icon {
width: 20px;
height: 20px;
}
.signup-link {
text-align: center;
color: var(--text-secondary);
font-size: var(--text-sm);
}
.signup-link a {
color: var(--primary-teal);
text-decoration: none;
font-weight: bold;
}
.signup-link a:hover {
text-decoration: underline;
}
@media (max-width: 480px) {
.login-container {
padding: var(--space-4);
}
.login-card {
padding: var(--space-6);
}
.app-logo h1 {
font-size: var(--text-3xl);
}
}
</style>
</head>
<body>
<div class="login-container">
<!-- UI_App_Logo - 應用程式標識 -->
<div class="app-logo">
<h1>Drama Ling</h1>
<p>用英語演出你的故事</p>
</div>
<!-- UI_Login_Form - 登入表單 -->
<div class="login-card">
<form id="loginForm">
<div class="form-group">
<label for="email" class="form-label">電子信箱</label>
<input type="email" id="email" class="form-input" placeholder="輸入您的電子信箱" required>
</div>
<div class="form-group">
<label for="password" class="form-label">密碼</label>
<input type="password" id="password" class="form-input" placeholder="輸入您的密碼" required>
</div>
<!-- UI_Login_Button - 登入按鈕 -->
<button type="submit" class="btn-login">
登入
</button>
</form>
<!-- UI_Divider - 分隔線 -->
<div class="divider">
<span>或者</span>
</div>
<!-- UI_Google_Login_Button - Google登入按鈕 -->
<button class="btn-google" id="googleLogin">
<svg class="google-icon" viewBox="0 0 24 24">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
使用 Google 登入
</button>
<!-- UI_Signup_Link - 註冊連結 -->
<div class="signup-link">
還沒有帳號?<a href="02-signup.html">立即註冊</a>
</div>
</div>
</div>
<script>
// 登入表單處理
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
// 模擬登入處理
if (email && password) {
// 顯示載入狀態
const loginBtn = document.querySelector('.btn-login');
loginBtn.textContent = '登入中...';
loginBtn.disabled = true;
// 模擬API請求延遲
setTimeout(() => {
// 成功登入後跳轉到儀表板
window.location.href = '03-onboarding.html';
}, 1500);
}
});
// Google登入處理
document.getElementById('googleLogin').addEventListener('click', function() {
// 模擬Google OAuth流程
this.textContent = '連接中...';
this.disabled = true;
setTimeout(() => {
window.location.href = '03-onboarding.html';
}, 2000);
});
</script>
</body>
</html>

View File

@ -1,491 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 註冊</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Signup_Screen - 用戶註冊界面 */
.signup-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--secondary-purple) 0%, var(--accent-violet) 100%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: var(--space-6);
}
.app-logo {
margin-bottom: var(--space-8);
text-align: center;
}
.app-logo h1 {
font-size: var(--text-4xl);
color: var(--text-primary);
margin-bottom: var(--space-2);
font-weight: bold;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.app-logo p {
font-size: var(--text-lg);
color: var(--text-secondary);
opacity: 0.9;
}
.signup-card {
background: var(--card-background);
border-radius: var(--radius-lg);
padding: var(--space-8);
width: 100%;
max-width: 450px;
box-shadow: var(--shadow-xl);
border: 3px solid rgba(255,255,255,0.1);
}
.form-group {
margin-bottom: var(--space-5);
}
.form-label {
display: block;
font-size: var(--text-base);
color: var(--text-primary);
margin-bottom: var(--space-2);
font-weight: 500;
}
.form-input {
width: 100%;
padding: var(--space-4);
border: 2px solid var(--divider);
border-radius: var(--radius-md);
background: var(--background-secondary);
color: var(--text-primary);
font-size: var(--text-base);
transition: border-color var(--duration-normal);
}
.form-input:focus {
outline: none;
border-color: var(--accent-violet);
box-shadow: 0 0 0 3px rgba(155, 89, 182, 0.2);
}
.form-row {
display: flex;
gap: var(--space-4);
}
.form-row .form-group {
flex: 1;
}
/* UI_Age_Selection - 年齡選擇 */
.age-selection {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-3);
margin-top: var(--space-2);
}
.age-option {
padding: var(--space-3);
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-md);
text-align: center;
cursor: pointer;
transition: all var(--duration-normal);
color: var(--text-secondary);
font-size: var(--text-sm);
}
.age-option:hover {
border-color: var(--accent-violet);
background: var(--background-primary);
}
.age-option.selected {
background: var(--accent-violet);
border-color: var(--accent-violet-dark);
color: var(--text-primary);
font-weight: bold;
transform: scale(1.05);
}
/* UI_Terms_Checkbox - 服務條款勾選 */
.terms-group {
display: flex;
align-items: flex-start;
gap: var(--space-3);
margin-bottom: var(--space-6);
font-size: var(--text-sm);
color: var(--text-secondary);
}
.custom-checkbox {
position: relative;
width: 20px;
height: 20px;
margin-top: 2px;
}
.custom-checkbox input {
opacity: 0;
position: absolute;
}
.checkmark {
position: absolute;
top: 0;
left: 0;
height: 20px;
width: 20px;
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-sm);
transition: all var(--duration-normal);
}
.custom-checkbox input:checked + .checkmark {
background: var(--accent-violet);
border-color: var(--accent-violet-dark);
}
.checkmark::after {
content: "";
position: absolute;
display: none;
left: 5px;
top: 2px;
width: 6px;
height: 10px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.custom-checkbox input:checked + .checkmark::after {
display: block;
}
.terms-text a {
color: var(--primary-teal);
text-decoration: none;
}
.terms-text a:hover {
text-decoration: underline;
}
.btn-signup {
width: 100%;
padding: var(--space-4);
background: var(--accent-violet);
color: var(--text-primary);
border: 3px solid var(--accent-violet-dark);
border-radius: var(--radius-md);
font-size: var(--text-lg);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
margin-bottom: var(--space-4);
box-shadow: 0 4px 0 var(--accent-violet-dark);
transform: translateY(0);
}
.btn-signup:hover {
background: var(--accent-violet-light);
transform: translateY(-1px);
box-shadow: 0 5px 0 var(--accent-violet-dark);
}
.btn-signup:active {
transform: translateY(2px);
box-shadow: 0 2px 0 var(--accent-violet-dark);
}
.btn-signup:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: 0 4px 0 var(--accent-violet-dark);
}
.divider {
text-align: center;
margin: var(--space-6) 0;
position: relative;
color: var(--text-tertiary);
}
.divider::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: var(--divider);
}
.divider span {
background: var(--card-background);
padding: 0 var(--space-4);
}
.btn-google {
width: 100%;
padding: var(--space-4);
background: var(--text-primary);
color: var(--background-dark);
border: 3px solid #e0e0e0;
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: 500;
cursor: pointer;
transition: all var(--duration-normal);
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-3);
margin-bottom: var(--space-6);
box-shadow: 0 4px 0 #d0d0d0;
transform: translateY(0);
}
.btn-google:hover {
background: #f5f5f5;
transform: translateY(-1px);
box-shadow: 0 5px 0 #d0d0d0;
}
.btn-google:active {
transform: translateY(2px);
box-shadow: 0 2px 0 #d0d0d0;
}
.google-icon {
width: 20px;
height: 20px;
}
.login-link {
text-align: center;
color: var(--text-secondary);
font-size: var(--text-sm);
}
.login-link a {
color: var(--primary-teal);
text-decoration: none;
font-weight: bold;
}
.login-link a:hover {
text-decoration: underline;
}
@media (max-width: 480px) {
.signup-container {
padding: var(--space-4);
}
.signup-card {
padding: var(--space-6);
}
.app-logo h1 {
font-size: var(--text-3xl);
}
.form-row {
flex-direction: column;
gap: 0;
}
.age-selection {
grid-template-columns: repeat(2, 1fr);
}
}
</style>
</head>
<body>
<div class="signup-container">
<!-- UI_App_Logo - 應用程式標識 -->
<div class="app-logo">
<h1>Drama Ling</h1>
<p>開始你的英語學習之旅</p>
</div>
<!-- UI_Signup_Form - 註冊表單 -->
<div class="signup-card">
<form id="signupForm">
<div class="form-row">
<div class="form-group">
<label for="firstName" class="form-label">名字</label>
<input type="text" id="firstName" class="form-input" placeholder="輸入您的名字" required>
</div>
<div class="form-group">
<label for="lastName" class="form-label">姓氏</label>
<input type="text" id="lastName" class="form-input" placeholder="輸入您的姓氏" required>
</div>
</div>
<div class="form-group">
<label for="email" class="form-label">電子信箱</label>
<input type="email" id="email" class="form-input" placeholder="輸入您的電子信箱" required>
</div>
<div class="form-group">
<label for="password" class="form-label">密碼</label>
<input type="password" id="password" class="form-input" placeholder="至少8個字符" required minlength="8">
</div>
<div class="form-group">
<label for="confirmPassword" class="form-label">確認密碼</label>
<input type="password" id="confirmPassword" class="form-input" placeholder="再次輸入密碼" required>
</div>
<!-- UI_Age_Selection - 年齡選擇 -->
<div class="form-group">
<label class="form-label">年齡範圍</label>
<div class="age-selection">
<div class="age-option" data-age="13-17">13-17歲</div>
<div class="age-option" data-age="18-24">18-24歲</div>
<div class="age-option" data-age="25-34">25-34歲</div>
<div class="age-option" data-age="35-44">35-44歲</div>
<div class="age-option" data-age="45-54">45-54歲</div>
<div class="age-option" data-age="55+">55歲以上</div>
</div>
</div>
<!-- UI_Terms_Checkbox - 服務條款勾選 -->
<div class="terms-group">
<label class="custom-checkbox">
<input type="checkbox" id="agreeTerms" required>
<span class="checkmark"></span>
</label>
<div class="terms-text">
我同意 <a href="#" target="_blank">服務條款</a><a href="#" target="_blank">隱私政策</a>
</div>
</div>
<!-- UI_Signup_Button - 註冊按鈕 -->
<button type="submit" class="btn-signup" id="signupBtn">
創建帳戶
</button>
</form>
<!-- UI_Divider - 分隔線 -->
<div class="divider">
<span>或者</span>
</div>
<!-- UI_Google_Signup_Button - Google註冊按鈕 -->
<button class="btn-google" id="googleSignup">
<svg class="google-icon" viewBox="0 0 24 24">
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
</svg>
使用 Google 註冊
</button>
<!-- UI_Login_Link - 登入連結 -->
<div class="login-link">
已經有帳號?<a href="01-login.html">立即登入</a>
</div>
</div>
</div>
<script>
// 年齡選擇處理
const ageOptions = document.querySelectorAll('.age-option');
let selectedAge = null;
ageOptions.forEach(option => {
option.addEventListener('click', function() {
// 移除其他選項的選中狀態
ageOptions.forEach(opt => opt.classList.remove('selected'));
// 設置當前選項為選中狀態
this.classList.add('selected');
selectedAge = this.dataset.age;
});
});
// 註冊表單處理
document.getElementById('signupForm').addEventListener('submit', function(e) {
e.preventDefault();
const firstName = document.getElementById('firstName').value;
const lastName = document.getElementById('lastName').value;
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirmPassword').value;
const agreeTerms = document.getElementById('agreeTerms').checked;
// 驗證密碼匹配
if (password !== confirmPassword) {
alert('密碼不匹配,請重新輸入');
return;
}
// 驗證年齡選擇
if (!selectedAge) {
alert('請選擇您的年齡範圍');
return;
}
// 驗證服務條款
if (!agreeTerms) {
alert('請同意服務條款和隱私政策');
return;
}
if (firstName && lastName && email && password) {
// 顯示載入狀態
const signupBtn = document.getElementById('signupBtn');
signupBtn.textContent = '創建中...';
signupBtn.disabled = true;
// 模擬API請求延遲
setTimeout(() => {
// 成功註冊後跳轉到引導流程
window.location.href = '03-onboarding.html';
}, 2000);
}
});
// Google註冊處理
document.getElementById('googleSignup').addEventListener('click', function() {
// 模擬Google OAuth流程
this.textContent = '連接中...';
this.disabled = true;
setTimeout(() => {
window.location.href = '03-onboarding.html';
}, 2000);
});
// 密碼確認即時驗證
document.getElementById('confirmPassword').addEventListener('input', function() {
const password = document.getElementById('password').value;
const confirmPassword = this.value;
if (confirmPassword && password !== confirmPassword) {
this.style.borderColor = 'var(--error-red)';
} else {
this.style.borderColor = 'var(--divider)';
}
});
</script>
</body>
</html>

View File

@ -1,562 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 新手引導</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Onboarding_Screen - 新手引導界面 */
.onboarding-container {
min-height: 100vh;
background: linear-gradient(45deg, var(--primary-teal) 0%, var(--secondary-purple) 50%, var(--accent-violet) 100%);
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
.onboarding-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.1) 0%, transparent 50%),
radial-gradient(circle at 70% 80%, rgba(255,255,255,0.05) 0%, transparent 50%);
}
.onboarding-header {
padding: var(--space-6) var(--space-6) 0;
text-align: center;
position: relative;
z-index: 1;
}
.welcome-title {
font-size: var(--text-3xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-2);
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.welcome-subtitle {
font-size: var(--text-lg);
color: var(--text-secondary);
opacity: 0.9;
margin-bottom: var(--space-8);
}
.onboarding-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 var(--space-6);
position: relative;
z-index: 1;
}
/* UI_Onboarding_Steps - 引導步驟 */
.onboarding-steps {
background: var(--card-background);
border-radius: var(--radius-xl);
padding: var(--space-8);
margin-bottom: var(--space-8);
box-shadow: var(--shadow-xl);
border: 3px solid rgba(255,255,255,0.1);
}
.step-indicators {
display: flex;
justify-content: center;
margin-bottom: var(--space-8);
gap: var(--space-3);
}
.step-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--divider);
transition: all var(--duration-normal);
}
.step-dot.active {
background: var(--primary-teal);
transform: scale(1.2);
box-shadow: 0 0 10px rgba(0, 229, 204, 0.5);
}
.step-dot.completed {
background: var(--success-green);
}
.step-content {
text-align: center;
min-height: 300px;
display: flex;
flex-direction: column;
justify-content: center;
}
.step-icon {
font-size: 80px;
margin-bottom: var(--space-6);
}
.step-title {
font-size: var(--text-2xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-4);
}
.step-description {
font-size: var(--text-base);
color: var(--text-secondary);
line-height: 1.6;
max-width: 400px;
margin: 0 auto var(--space-6);
}
/* UI_Learning_Goals_Selection - 學習目標選擇 */
.goals-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-4);
margin-bottom: var(--space-6);
}
.goal-option {
padding: var(--space-5);
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-lg);
text-align: center;
cursor: pointer;
transition: all var(--duration-normal);
}
.goal-option:hover {
border-color: var(--primary-teal);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.goal-option.selected {
background: var(--primary-teal);
border-color: var(--primary-teal-dark);
color: var(--background-dark);
font-weight: bold;
box-shadow: 0 4px 0 var(--primary-teal-dark);
}
.goal-icon {
font-size: 40px;
margin-bottom: var(--space-2);
display: block;
}
.goal-title {
font-size: var(--text-base);
font-weight: 500;
}
/* UI_English_Level_Assessment - 英語程度評估 */
.level-options {
display: flex;
flex-direction: column;
gap: var(--space-3);
margin-bottom: var(--space-6);
}
.level-option {
padding: var(--space-4);
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-lg);
cursor: pointer;
transition: all var(--duration-normal);
display: flex;
align-items: center;
gap: var(--space-4);
}
.level-option:hover {
border-color: var(--secondary-purple);
background: var(--background-primary);
}
.level-option.selected {
background: var(--secondary-purple);
border-color: var(--secondary-purple-dark);
color: var(--text-primary);
font-weight: bold;
box-shadow: 0 4px 0 var(--secondary-purple-dark);
}
.level-badge {
background: var(--divider);
color: var(--text-primary);
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-md);
font-size: var(--text-sm);
font-weight: bold;
min-width: 60px;
text-align: center;
}
.level-option.selected .level-badge {
background: var(--secondary-purple-dark);
}
.level-details {
flex: 1;
}
.level-title {
font-size: var(--text-base);
font-weight: 500;
margin-bottom: var(--space-1);
}
.level-desc {
font-size: var(--text-sm);
color: var(--text-tertiary);
}
.level-option.selected .level-desc {
color: var(--text-secondary);
}
/* 導航按鈕 */
.onboarding-navigation {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-6);
position: relative;
z-index: 1;
}
.btn-skip {
background: transparent;
color: var(--text-secondary);
border: none;
font-size: var(--text-base);
cursor: pointer;
padding: var(--space-3) var(--space-4);
border-radius: var(--radius-md);
transition: all var(--duration-normal);
}
.btn-skip:hover {
color: var(--text-primary);
background: rgba(255,255,255,0.1);
}
.btn-next {
padding: var(--space-4) var(--space-8);
background: var(--primary-teal);
color: var(--background-dark);
border: 3px solid var(--primary-teal-dark);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 4px 0 var(--primary-teal-dark);
transform: translateY(0);
}
.btn-next:hover {
background: var(--primary-teal-light);
transform: translateY(-1px);
box-shadow: 0 5px 0 var(--primary-teal-dark);
}
.btn-next:active {
transform: translateY(2px);
box-shadow: 0 2px 0 var(--primary-teal-dark);
}
.btn-next:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: 0 4px 0 var(--primary-teal-dark);
}
@media (max-width: 480px) {
.onboarding-container {
padding: 0;
}
.onboarding-header, .onboarding-content, .onboarding-navigation {
padding-left: var(--space-4);
padding-right: var(--space-4);
}
.onboarding-steps {
padding: var(--space-6);
}
.welcome-title {
font-size: var(--text-2xl);
}
.goals-grid {
grid-template-columns: 1fr;
}
.step-icon {
font-size: 60px;
}
.onboarding-navigation {
flex-direction: column;
gap: var(--space-4);
}
.btn-next {
width: 100%;
}
}
</style>
</head>
<body>
<div class="onboarding-container">
<!-- UI_Welcome_Header - 歡迎標題 -->
<div class="onboarding-header">
<h1 class="welcome-title">歡迎來到 Drama Ling</h1>
<p class="welcome-subtitle">讓我們了解您的學習需求</p>
</div>
<div class="onboarding-content">
<div class="onboarding-steps">
<!-- UI_Step_Indicators - 步驟指示器 -->
<div class="step-indicators">
<div class="step-dot active" data-step="1"></div>
<div class="step-dot" data-step="2"></div>
<div class="step-dot" data-step="3"></div>
</div>
<!-- 步驟1歡迎介紹 -->
<div class="step-content" id="step1">
<div class="step-icon">🎭</div>
<h2 class="step-title">用英語演出你的故事</h2>
<p class="step-description">
Drama Ling 結合情境對話和AI智能分析讓您在真實場景中練習英語提升溝通能力。我們將根據您的學習目標和程度為您量身打造個人化的學習路徑。
</p>
</div>
<!-- 步驟2學習目標選擇 -->
<div class="step-content" id="step2" style="display: none;">
<div class="step-icon">🎯</div>
<h2 class="step-title">您的學習目標是什麼?</h2>
<p class="step-description">選擇最符合您需求的學習目標(可選擇多個)</p>
<!-- UI_Learning_Goals_Selection - 學習目標選擇 -->
<div class="goals-grid">
<div class="goal-option" data-goal="daily">
<span class="goal-icon">💬</span>
<div class="goal-title">日常對話</div>
</div>
<div class="goal-option" data-goal="business">
<span class="goal-icon">💼</span>
<div class="goal-title">商務英語</div>
</div>
<div class="goal-option" data-goal="travel">
<span class="goal-icon">✈️</span>
<div class="goal-title">旅遊英語</div>
</div>
<div class="goal-option" data-goal="exam">
<span class="goal-icon">📚</span>
<div class="goal-title">考試準備</div>
</div>
</div>
</div>
<!-- 步驟3英語程度評估 -->
<div class="step-content" id="step3" style="display: none;">
<div class="step-icon">📊</div>
<h2 class="step-title">您的英語程度如何?</h2>
<p class="step-description">選擇最符合您目前程度的選項</p>
<!-- UI_English_Level_Assessment - 英語程度評估 -->
<div class="level-options">
<div class="level-option" data-level="beginner">
<div class="level-badge">A1-A2</div>
<div class="level-details">
<div class="level-title">初學者</div>
<div class="level-desc">基礎詞彙和簡單句型</div>
</div>
</div>
<div class="level-option" data-level="intermediate">
<div class="level-badge">B1-B2</div>
<div class="level-details">
<div class="level-title">中級</div>
<div class="level-desc">能進行日常對話,但需要更多練習</div>
</div>
</div>
<div class="level-option" data-level="advanced">
<div class="level-badge">C1-C2</div>
<div class="level-details">
<div class="level-title">高級</div>
<div class="level-desc">流利對話,想要精進表達能力</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- UI_Navigation_Buttons - 導航按鈕 -->
<div class="onboarding-navigation">
<button class="btn-skip" id="skipBtn">跳過</button>
<button class="btn-next" id="nextBtn">下一步</button>
</div>
</div>
<script>
let currentStep = 1;
const totalSteps = 3;
let selectedGoals = [];
let selectedLevel = null;
// 更新步驟指示器
function updateStepIndicators() {
const dots = document.querySelectorAll('.step-dot');
dots.forEach((dot, index) => {
const stepNumber = index + 1;
dot.classList.remove('active', 'completed');
if (stepNumber < currentStep) {
dot.classList.add('completed');
} else if (stepNumber === currentStep) {
dot.classList.add('active');
}
});
}
// 顯示當前步驟
function showStep(stepNumber) {
// 隱藏所有步驟內容
document.querySelectorAll('.step-content').forEach(step => {
step.style.display = 'none';
});
// 顯示當前步驟
document.getElementById(`step${stepNumber}`).style.display = 'block';
// 更新步驟指示器
updateStepIndicators();
// 更新按鈕狀態
updateButtonState();
}
// 更新按鈕狀態
function updateButtonState() {
const nextBtn = document.getElementById('nextBtn');
const skipBtn = document.getElementById('skipBtn');
// 檢查當前步驟是否已完成
let canProceed = true;
if (currentStep === 2 && selectedGoals.length === 0) {
canProceed = false;
}
if (currentStep === 3 && !selectedLevel) {
canProceed = false;
}
nextBtn.disabled = !canProceed;
// 更新按鈕文字
if (currentStep === totalSteps) {
nextBtn.textContent = '開始學習';
skipBtn.style.display = 'none';
} else {
nextBtn.textContent = '下一步';
skipBtn.style.display = 'block';
}
}
// 學習目標選擇處理
document.querySelectorAll('.goal-option').forEach(option => {
option.addEventListener('click', function() {
const goal = this.dataset.goal;
if (this.classList.contains('selected')) {
// 取消選擇
this.classList.remove('selected');
selectedGoals = selectedGoals.filter(g => g !== goal);
} else {
// 選擇
this.classList.add('selected');
selectedGoals.push(goal);
}
updateButtonState();
});
});
// 英語程度選擇處理
document.querySelectorAll('.level-option').forEach(option => {
option.addEventListener('click', function() {
// 移除其他選項的選中狀態
document.querySelectorAll('.level-option').forEach(opt => {
opt.classList.remove('selected');
});
// 設置當前選項為選中狀態
this.classList.add('selected');
selectedLevel = this.dataset.level;
updateButtonState();
});
});
// 下一步按鈕處理
document.getElementById('nextBtn').addEventListener('click', function() {
if (currentStep < totalSteps) {
currentStep++;
showStep(currentStep);
} else {
// 完成引導,跳轉到學習路徑選擇
completeOnboarding();
}
});
// 跳過按鈕處理
document.getElementById('skipBtn').addEventListener('click', function() {
completeOnboarding();
});
// 完成引導流程
function completeOnboarding() {
// 儲存用戶選擇
const userData = {
goals: selectedGoals,
level: selectedLevel,
completedOnboarding: true
};
localStorage.setItem('dramatLingUserData', JSON.stringify(userData));
// 跳轉到學習路徑選擇
window.location.href = '04-learning-path-selection.html';
}
// 初始化
showStep(currentStep);
</script>
</body>
</html>

View File

@ -1,571 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 選擇學習路徑</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Learning_Path_Selection - 學習路徑選擇 */
.path-selection-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--background-primary) 0%, var(--background-secondary) 100%);
padding: var(--space-6);
}
.header-section {
text-align: center;
margin-bottom: var(--space-8);
}
.page-title {
font-size: var(--text-3xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-3);
}
.page-subtitle {
font-size: var(--text-lg);
color: var(--text-secondary);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.paths-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: var(--space-8);
max-width: 1200px;
margin: 0 auto var(--space-8);
}
/* UI_Learning_Path_Card - 學習路徑卡片 */
.path-card {
background: var(--card-background);
border-radius: var(--radius-xl);
padding: var(--space-8);
border: 3px solid var(--divider);
transition: all var(--duration-normal);
cursor: pointer;
position: relative;
overflow: hidden;
}
.path-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--divider);
transition: all var(--duration-normal);
}
.path-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-xl);
border-color: var(--primary-teal);
}
.path-card:hover::before {
background: var(--primary-teal);
}
.path-card.selected {
border-color: var(--primary-teal);
background: linear-gradient(135deg, var(--card-background) 0%, rgba(0, 229, 204, 0.05) 100%);
transform: translateY(-4px);
box-shadow: var(--shadow-xl), 0 0 0 2px var(--primary-teal);
}
.path-card.selected::before {
background: var(--primary-teal);
}
.path-icon {
width: 80px;
height: 80px;
border-radius: 50%;
margin: 0 auto var(--space-6);
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
background: var(--background-secondary);
border: 3px solid var(--divider);
}
.path-card.selected .path-icon {
background: var(--primary-teal);
border-color: var(--primary-teal-dark);
color: var(--background-dark);
}
.path-title {
font-size: var(--text-xl);
color: var(--text-primary);
font-weight: bold;
text-align: center;
margin-bottom: var(--space-4);
}
.path-description {
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: var(--space-6);
text-align: center;
}
/* UI_Learning_Features - 學習特色 */
.path-features {
list-style: none;
padding: 0;
margin: 0 0 var(--space-6);
}
.path-features li {
display: flex;
align-items: center;
margin-bottom: var(--space-3);
font-size: var(--text-sm);
color: var(--text-secondary);
}
.path-features li::before {
content: '✓';
color: var(--success-green);
font-weight: bold;
margin-right: var(--space-3);
width: 16px;
text-align: center;
}
.path-card.selected .path-features li::before {
color: var(--primary-teal);
}
/* UI_Difficulty_Badge - 難度標識 */
.difficulty-badge {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-md);
font-size: var(--text-sm);
font-weight: 500;
margin-bottom: var(--space-4);
}
.difficulty-beginner {
background: var(--success-green);
color: var(--text-primary);
}
.difficulty-intermediate {
background: var(--warning-yellow);
color: var(--background-dark);
}
.difficulty-advanced {
background: var(--error-red);
color: var(--text-primary);
}
.stars {
display: flex;
gap: 2px;
}
.star {
width: 12px;
height: 12px;
background: var(--star-active);
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.star.inactive {
background: var(--star-inactive);
}
/* UI_Time_Estimate - 時間估計 */
.time-estimate {
display: flex;
align-items: center;
justify-content: center;
gap: var(--space-2);
font-size: var(--text-sm);
color: var(--text-tertiary);
padding: var(--space-3);
background: var(--background-secondary);
border-radius: var(--radius-md);
}
.path-card.selected .time-estimate {
background: rgba(0, 229, 204, 0.1);
color: var(--primary-teal);
}
/* 開始學習按鈕 */
.start-learning-section {
text-align: center;
max-width: 500px;
margin: 0 auto;
}
.btn-start-learning {
padding: var(--space-5) var(--space-12);
background: var(--primary-teal);
color: var(--background-dark);
border: 3px solid var(--primary-teal-dark);
border-radius: var(--radius-lg);
font-size: var(--text-xl);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 6px 0 var(--primary-teal-dark);
transform: translateY(0);
width: 100%;
margin-bottom: var(--space-4);
}
.btn-start-learning:hover {
background: var(--primary-teal-light);
transform: translateY(-2px);
box-shadow: 0 8px 0 var(--primary-teal-dark);
}
.btn-start-learning:active {
transform: translateY(3px);
box-shadow: 0 3px 0 var(--primary-teal-dark);
}
.btn-start-learning:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: 0 6px 0 var(--primary-teal-dark);
}
.selection-hint {
font-size: var(--text-sm);
color: var(--text-tertiary);
margin-top: var(--space-3);
}
@media (max-width: 768px) {
.paths-grid {
grid-template-columns: 1fr;
gap: var(--space-6);
}
.path-selection-container {
padding: var(--space-4);
}
.page-title {
font-size: var(--text-2xl);
}
.path-card {
padding: var(--space-6);
}
.btn-start-learning {
padding: var(--space-4) var(--space-8);
font-size: var(--text-lg);
}
}
</style>
</head>
<body>
<div class="path-selection-container">
<!-- UI_Page_Header - 頁面標題 -->
<div class="header-section">
<h1 class="page-title">選擇您的學習路徑</h1>
<p class="page-subtitle">
根據您的英語程度和學習目標,我們為您推薦了以下學習路徑。每個路徑都經過精心設計,幫助您循序漸進地提升英語能力。
</p>
</div>
<!-- UI_Learning_Paths_Grid - 學習路徑網格 -->
<div class="paths-grid">
<!-- 日常對話路徑 -->
<div class="path-card" data-path="daily-conversation">
<div class="path-icon">💬</div>
<h2 class="path-title">日常對話精通</h2>
<div class="difficulty-badge difficulty-beginner">
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star inactive"></div>
<div class="star inactive"></div>
<div class="star inactive"></div>
</div>
<span>適合初學者</span>
</div>
<p class="path-description">
從基礎問候開始,逐步掌握購物、用餐、問路等日常情境對話,建立英語溝通的信心基礎。
</p>
<ul class="path-features">
<li>13個階段循序學習</li>
<li>20+真實場景劇本</li>
<li>AI即時發音糾正</li>
<li>詞彙量從300增至1500</li>
<li>三維對話能力評估</li>
</ul>
<div class="time-estimate">
<span>⏱️</span>
<span>預估完成時間8-12週</span>
</div>
</div>
<!-- 商務英語路徑 -->
<div class="path-card" data-path="business-english">
<div class="path-icon">💼</div>
<h2 class="path-title">商務英語專精</h2>
<div class="difficulty-badge difficulty-intermediate">
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star inactive"></div>
</div>
<span>中高級</span>
</div>
<p class="path-description">
專為職場人士設計,涵蓋會議討論、簡報演示、商務談判等專業場景,提升職場競爭力。
</p>
<ul class="path-features">
<li>職場核心情境訓練</li>
<li>商務詞彙2000+</li>
<li>簡報技巧專項練習</li>
<li>談判對話深度分析</li>
<li>專業表達能力評估</li>
</ul>
<div class="time-estimate">
<span>⏱️</span>
<span>預估完成時間12-16週</span>
</div>
</div>
<!-- 旅遊英語路徑 -->
<div class="path-card" data-path="travel-english">
<div class="path-icon">✈️</div>
<h2 class="path-title">旅遊英語達人</h2>
<div class="difficulty-badge difficulty-beginner">
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star inactive"></div>
<div class="star inactive"></div>
</div>
<span>初中級</span>
</div>
<p class="path-description">
為愛好旅遊的您量身打造,掌握機場、飯店、餐廳、景點等旅遊必備對話技能。
</p>
<ul class="path-features">
<li>旅遊場景全覆蓋</li>
<li>緊急狀況應對訓練</li>
<li>文化交流對話練習</li>
<li>實用短語快速記憶</li>
<li>口音適應性訓練</li>
</ul>
<div class="time-estimate">
<span>⏱️</span>
<span>預估完成時間6-10週</span>
</div>
</div>
<!-- 考試準備路徑 -->
<div class="path-card" data-path="exam-prep">
<div class="path-icon">📚</div>
<h2 class="path-title">考試準備強化</h2>
<div class="difficulty-badge difficulty-advanced">
<div class="stars">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
<span>高級</span>
</div>
<p class="path-description">
針對TOEIC、IELTS、TOEFL等英語檢定考試重點強化口說測驗的應答技巧和流暢度。
</p>
<ul class="path-features">
<li>考試題型專項練習</li>
<li>高頻詞彙密集訓練</li>
<li>答題策略深度解析</li>
<li>時間管理技巧培養</li>
<li>模擬考試實戰演練</li>
</ul>
<div class="time-estimate">
<span>⏱️</span>
<span>預估完成時間10-14週</span>
</div>
</div>
</div>
<!-- UI_Start_Learning_Button - 開始學習按鈕 -->
<div class="start-learning-section">
<button class="btn-start-learning" id="startLearningBtn" disabled>
開始我的學習之旅
</button>
<p class="selection-hint">請先選擇一個學習路徑</p>
</div>
</div>
<script>
let selectedPath = null;
// 學習路徑選擇處理
document.querySelectorAll('.path-card').forEach(card => {
card.addEventListener('click', function() {
// 移除其他卡片的選中狀態
document.querySelectorAll('.path-card').forEach(c => {
c.classList.remove('selected');
});
// 設置當前卡片為選中狀態
this.classList.add('selected');
selectedPath = this.dataset.path;
// 更新按鈕狀態
updateStartButton();
});
});
// 更新開始學習按鈕狀態
function updateStartButton() {
const startBtn = document.getElementById('startLearningBtn');
const hint = document.querySelector('.selection-hint');
if (selectedPath) {
startBtn.disabled = false;
hint.textContent = `已選擇:${getPathDisplayName(selectedPath)}`;
hint.style.color = 'var(--primary-teal)';
} else {
startBtn.disabled = true;
hint.textContent = '請先選擇一個學習路徑';
hint.style.color = 'var(--text-tertiary)';
}
}
// 獲取路徑顯示名稱
function getPathDisplayName(pathId) {
const names = {
'daily-conversation': '日常對話精通',
'business-english': '商務英語專精',
'travel-english': '旅遊英語達人',
'exam-prep': '考試準備強化'
};
return names[pathId] || pathId;
}
// 開始學習按鈕處理
document.getElementById('startLearningBtn').addEventListener('click', function() {
if (!selectedPath) return;
// 顯示載入狀態
this.textContent = '準備中...';
this.disabled = true;
// 儲存用戶選擇的學習路徑
const existingData = JSON.parse(localStorage.getItem('dramatLingUserData') || '{}');
const userData = {
...existingData,
selectedPath: selectedPath,
startDate: new Date().toISOString(),
currentStage: 1,
unlockedStages: [1],
completedStages: [],
totalProgress: 0
};
localStorage.setItem('dramatLingUserData', JSON.stringify(userData));
// 模擬準備過程
setTimeout(() => {
// 跳轉到四關學習系統主畫面
window.location.href = '05-four-stage-learning.html';
}, 2000);
});
// 初始化 - 檢查是否有推薦路徑
document.addEventListener('DOMContentLoaded', function() {
const userData = JSON.parse(localStorage.getItem('dramatLingUserData') || '{}');
// 根據用戶的學習目標和程度推薦路徑
if (userData.goals && userData.level) {
let recommendedPath = null;
if (userData.goals.includes('business')) {
recommendedPath = 'business-english';
} else if (userData.goals.includes('travel')) {
recommendedPath = 'travel-english';
} else if (userData.goals.includes('exam')) {
recommendedPath = 'exam-prep';
} else if (userData.goals.includes('daily')) {
recommendedPath = 'daily-conversation';
} else {
// 根據程度推薦
if (userData.level === 'beginner') {
recommendedPath = 'daily-conversation';
} else if (userData.level === 'intermediate') {
recommendedPath = 'travel-english';
} else if (userData.level === 'advanced') {
recommendedPath = 'business-english';
}
}
// 高亮推薦路徑
if (recommendedPath) {
const recommendedCard = document.querySelector(`[data-path="${recommendedPath}"]`);
if (recommendedCard) {
const recommendedBadge = document.createElement('div');
recommendedBadge.style.cssText = `
position: absolute;
top: -10px;
right: -10px;
background: var(--warning-yellow);
color: var(--background-dark);
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-md);
font-size: var(--text-xs);
font-weight: bold;
transform: rotate(15deg);
box-shadow: var(--shadow-md);
`;
recommendedBadge.textContent = '推薦';
recommendedCard.appendChild(recommendedBadge);
recommendedCard.style.position = 'relative';
}
}
}
});
</script>
</body>
</html>

View File

@ -1,971 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 四關學習系統</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Four_Stage_Learning_Main - 四關學習主畫面 */
.learning-main-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--background-primary) 0%, var(--background-secondary) 100%);
}
/* UI_Top_Status_Bar - 頂部狀態列 */
.top-status-bar {
background: var(--card-background);
padding: var(--space-4) var(--space-6);
border-bottom: 2px solid var(--divider);
display: flex;
justify-content: space-between;
align-items: center;
}
.user-info {
display: flex;
align-items: center;
gap: var(--space-3);
}
.user-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--primary-teal);
display: flex;
align-items: center;
justify-content: center;
color: var(--background-dark);
font-weight: bold;
font-size: var(--text-lg);
}
.user-details {
display: flex;
flex-direction: column;
}
.user-name {
font-size: var(--text-base);
color: var(--text-primary);
font-weight: 500;
}
.user-level {
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* UI_Life_Points_Display - 生命點數顯示 */
.status-indicators {
display: flex;
align-items: center;
gap: var(--space-6);
}
.life-points {
display: flex;
align-items: center;
gap: var(--space-2);
}
.hearts {
display: flex;
gap: var(--space-1);
}
.heart {
width: 24px;
height: 24px;
background: var(--error-red);
clip-path: path('M12,21.35l-1.45-1.32C5.4,15.36,2,12.28,2,8.5 C2,5.42,4.42,3,7.5,3c1.74,0,3.41,0.81,4.5,2.09C13.09,3.81,14.76,3,16.5,3 C19.58,3,22,5.42,22,8.5c0,3.78-3.4,6.86-8.55,11.54L12,21.35z');
position: relative;
}
.heart.empty {
background: var(--divider);
}
.heart.infinite {
background: var(--gold);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.diamonds {
display: flex;
align-items: center;
gap: var(--space-2);
color: var(--diamond);
}
.diamond-icon {
width: 20px;
height: 20px;
background: var(--diamond);
clip-path: polygon(50% 0%, 0% 50%, 50% 100%, 100% 50%);
}
.diamond-count {
font-weight: bold;
color: var(--text-primary);
}
/* UI_Current_Stage_Header - 當前階段標題 */
.stage-header {
padding: var(--space-8) var(--space-6) var(--space-6);
text-align: center;
background: linear-gradient(135deg, rgba(0, 229, 204, 0.1) 0%, rgba(142, 68, 173, 0.1) 100%);
}
.stage-title {
font-size: var(--text-3xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-2);
}
.stage-subtitle {
font-size: var(--text-lg);
color: var(--text-secondary);
margin-bottom: var(--space-4);
}
/* UI_Progress_Overview - 進度總覽 */
.progress-overview {
display: flex;
justify-content: center;
gap: var(--space-8);
margin-bottom: var(--space-6);
}
.progress-item {
text-align: center;
}
.progress-value {
font-size: var(--text-2xl);
font-weight: bold;
color: var(--primary-teal);
margin-bottom: var(--space-1);
}
.progress-label {
font-size: var(--text-sm);
color: var(--text-tertiary);
}
/* UI_Script_Selection_Grid - 劇本選擇網格 */
.scripts-section {
padding: 0 var(--space-6) var(--space-8);
}
.section-title {
font-size: var(--text-xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-6);
text-align: center;
}
.scripts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: var(--space-6);
max-width: 1000px;
margin: 0 auto;
}
/* UI_Script_Card - 劇本卡片 */
.script-card {
background: var(--card-background);
border-radius: var(--radius-lg);
padding: var(--space-6);
border: 3px solid var(--divider);
transition: all var(--duration-normal);
cursor: pointer;
position: relative;
overflow: hidden;
}
.script-card.available {
border-color: var(--primary-teal);
background: linear-gradient(135deg, var(--card-background) 0%, rgba(0, 229, 204, 0.05) 100%);
}
.script-card.available:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
border-color: var(--primary-teal-light);
}
.script-card.locked {
opacity: 0.6;
cursor: not-allowed;
}
.script-card.completed {
border-color: var(--success-green);
background: linear-gradient(135deg, var(--card-background) 0%, rgba(39, 174, 96, 0.05) 100%);
}
.script-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--divider);
}
.script-card.available::before {
background: var(--primary-teal);
}
.script-card.completed::before {
background: var(--success-green);
}
.script-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--space-4);
}
.script-title {
font-size: var(--text-lg);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-1);
}
.script-scenario {
font-size: var(--text-sm);
color: var(--text-secondary);
}
/* UI_Script_Status_Badge - 劇本狀態標識 */
.status-badge {
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-md);
font-size: var(--text-xs);
font-weight: bold;
text-align: center;
}
.status-available {
background: var(--primary-teal);
color: var(--background-dark);
}
.status-locked {
background: var(--divider);
color: var(--text-tertiary);
}
.status-completed {
background: var(--success-green);
color: var(--text-primary);
}
/* UI_Four_Stage_Progress - 四關進度顯示 */
.stages-progress {
margin: var(--space-4) 0;
}
.stages-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-3);
}
.stage-step {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-md);
font-size: var(--text-sm);
position: relative;
}
.stage-step.completed {
background: var(--success-green);
color: var(--text-primary);
}
.stage-step.current {
background: var(--primary-teal);
color: var(--background-dark);
font-weight: bold;
animation: glow 2s infinite alternate;
}
@keyframes glow {
from { box-shadow: 0 0 5px rgba(0, 229, 204, 0.5); }
to { box-shadow: 0 0 10px rgba(0, 229, 204, 0.8); }
}
.stage-step.locked {
background: var(--background-secondary);
color: var(--text-tertiary);
}
.stage-step.bonus {
background: var(--gold);
color: var(--background-dark);
border: 2px solid var(--warning-yellow);
}
.stage-connector {
flex: 1;
height: 2px;
background: var(--divider);
margin: 0 var(--space-2);
}
.stage-connector.completed {
background: var(--success-green);
}
.stage-connector.current {
background: linear-gradient(90deg, var(--success-green) 0%, var(--primary-teal) 100%);
}
/* UI_Stars_Rating - 星級評價 */
.script-rating {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: var(--space-4);
}
.stars-display {
display: flex;
gap: var(--space-1);
}
.star-rating {
width: 16px;
height: 16px;
background: var(--star-active);
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}
.star-rating.empty {
background: var(--star-inactive);
}
.script-card.locked .star-rating {
background: var(--divider);
}
.play-button {
padding: var(--space-2) var(--space-4);
background: var(--primary-teal);
color: var(--background-dark);
border: none;
border-radius: var(--radius-md);
font-size: var(--text-sm);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
}
.play-button:hover {
background: var(--primary-teal-light);
transform: scale(1.05);
}
.script-card.locked .play-button {
background: var(--divider);
cursor: not-allowed;
transform: none;
}
.script-card.completed .play-button {
background: var(--success-green);
}
@media (max-width: 768px) {
.top-status-bar {
padding: var(--space-3) var(--space-4);
flex-wrap: wrap;
gap: var(--space-3);
}
.status-indicators {
gap: var(--space-4);
}
.stage-header {
padding: var(--space-6) var(--space-4) var(--space-4);
}
.stage-title {
font-size: var(--text-2xl);
}
.progress-overview {
flex-wrap: wrap;
gap: var(--space-4);
}
.scripts-section {
padding: 0 var(--space-4) var(--space-6);
}
.scripts-grid {
grid-template-columns: 1fr;
gap: var(--space-4);
}
.stages-row {
flex-direction: column;
gap: var(--space-2);
align-items: stretch;
}
.stage-connector {
display: none;
}
}
</style>
</head>
<body>
<div class="learning-main-container">
<!-- UI_Top_Status_Bar - 頂部狀態列 -->
<div class="top-status-bar">
<div class="user-info">
<div class="user-avatar" id="userAvatar">J</div>
<div class="user-details">
<div class="user-name" id="userName">John Doe</div>
<div class="user-level" id="userLevel">初學者 - 階段1</div>
</div>
</div>
<div class="status-indicators">
<!-- UI_Life_Points_Display - 生命點數顯示 -->
<div class="life-points">
<div class="hearts" id="heartsContainer">
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart"></div>
<div class="heart empty"></div>
</div>
</div>
<div class="diamonds">
<div class="diamond-icon"></div>
<span class="diamond-count" id="diamondCount">150</span>
</div>
</div>
</div>
<!-- UI_Current_Stage_Header - 當前階段標題 -->
<div class="stage-header">
<h1 class="stage-title">階段1基礎對話入門</h1>
<p class="stage-subtitle">掌握日常生活中最常用的基礎對話技巧</p>
<!-- UI_Progress_Overview - 進度總覽 -->
<div class="progress-overview">
<div class="progress-item">
<div class="progress-value" id="completedScripts">3</div>
<div class="progress-label">已完成劇本</div>
</div>
<div class="progress-item">
<div class="progress-value" id="totalStars">9</div>
<div class="progress-label">獲得星數</div>
</div>
<div class="progress-item">
<div class="progress-value" id="totalWords">45</div>
<div class="progress-label">學會詞彙</div>
</div>
</div>
</div>
<!-- UI_Script_Selection_Grid - 劇本選擇網格 -->
<div class="scripts-section">
<h2 class="section-title">選擇劇本開始學習</h2>
<div class="scripts-grid">
<!-- 劇本1問候與自我介紹 -->
<div class="script-card completed" data-script="greeting">
<div class="script-header">
<div>
<div class="script-title">問候與自我介紹</div>
<div class="script-scenario">咖啡廳初次見面</div>
</div>
<div class="status-badge status-completed">已完成</div>
</div>
<!-- UI_Four_Stage_Progress - 四關進度顯示 -->
<div class="stages-progress">
<div class="stages-row">
<div class="stage-step completed">
<span></span>
<span>詞彙學習</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed">
<span></span>
<span>詞彙熟悉</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed bonus">
<span>💎</span>
<span>口說練習</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed">
<span></span>
<span>情境對話</span>
</div>
</div>
</div>
<div class="script-rating">
<div class="stars-display">
<div class="star-rating"></div>
<div class="star-rating"></div>
<div class="star-rating"></div>
</div>
<button class="play-button">重新練習</button>
</div>
</div>
<!-- 劇本2購物與詢價 -->
<div class="script-card completed" data-script="shopping">
<div class="script-header">
<div>
<div class="script-title">購物與詢價</div>
<div class="script-scenario">服飾店購買衣物</div>
</div>
<div class="status-badge status-completed">已完成</div>
</div>
<div class="stages-progress">
<div class="stages-row">
<div class="stage-step completed">
<span></span>
<span>詞彙學習</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed">
<span></span>
<span>詞彙熟悉</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked bonus">
<span>🔒</span>
<span>口說練習</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed">
<span></span>
<span>情境對話</span>
</div>
</div>
</div>
<div class="script-rating">
<div class="stars-display">
<div class="star-rating"></div>
<div class="star-rating"></div>
<div class="star-rating empty"></div>
</div>
<button class="play-button">重新練習</button>
</div>
</div>
<!-- 劇本3餐廳點餐 -->
<div class="script-card completed" data-script="restaurant">
<div class="script-header">
<div>
<div class="script-title">餐廳點餐</div>
<div class="script-scenario">西餐廳用餐體驗</div>
</div>
<div class="status-badge status-completed">已完成</div>
</div>
<div class="stages-progress">
<div class="stages-row">
<div class="stage-step completed">
<span></span>
<span>詞彙學習</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed">
<span></span>
<span>詞彙熟悉</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed bonus">
<span>💎</span>
<span>口說練習</span>
</div>
<div class="stage-connector completed"></div>
<div class="stage-step completed">
<span></span>
<span>情境對話</span>
</div>
</div>
</div>
<div class="script-rating">
<div class="stars-display">
<div class="star-rating"></div>
<div class="star-rating"></div>
<div class="star-rating"></div>
</div>
<button class="play-button">重新練習</button>
</div>
</div>
<!-- 劇本4問路指南 - 當前可玩 -->
<div class="script-card available" data-script="directions">
<div class="script-header">
<div>
<div class="script-title">問路指南</div>
<div class="script-scenario">街頭問路與指路</div>
</div>
<div class="status-badge status-available">可開始</div>
</div>
<div class="stages-progress">
<div class="stages-row">
<div class="stage-step current">
<span>1</span>
<span>詞彙學習</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked">
<span>🔒</span>
<span>詞彙熟悉</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked bonus">
<span>💎</span>
<span>口說練習</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked">
<span>🔒</span>
<span>情境對話</span>
</div>
</div>
</div>
<div class="script-rating">
<div class="stars-display">
<div class="star-rating empty"></div>
<div class="star-rating empty"></div>
<div class="star-rating empty"></div>
</div>
<button class="play-button">開始學習</button>
</div>
</div>
<!-- 劇本5天氣聊天 - 鎖定 -->
<div class="script-card locked" data-script="weather">
<div class="script-header">
<div>
<div class="script-title">天氣聊天</div>
<div class="script-scenario">日常天氣話題</div>
</div>
<div class="status-badge status-locked">🔒 鎖定</div>
</div>
<div class="stages-progress">
<div class="stages-row">
<div class="stage-step locked">
<span>🔒</span>
<span>詞彙學習</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked">
<span>🔒</span>
<span>詞彙熟悉</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked bonus">
<span>💎</span>
<span>口說練習</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked">
<span>🔒</span>
<span>情境對話</span>
</div>
</div>
</div>
<div class="script-rating">
<div class="stars-display">
<div class="star-rating"></div>
<div class="star-rating"></div>
<div class="star-rating"></div>
</div>
<button class="play-button">需完成前面劇本</button>
</div>
</div>
<!-- 劇本6醫院看診 - 鎖定 -->
<div class="script-card locked" data-script="hospital">
<div class="script-header">
<div>
<div class="script-title">醫院看診</div>
<div class="script-scenario">醫院掛號就診</div>
</div>
<div class="status-badge status-locked">🔒 鎖定</div>
</div>
<div class="stages-progress">
<div class="stages-row">
<div class="stage-step locked">
<span>🔒</span>
<span>詞彙學習</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked">
<span>🔒</span>
<span>詞彙熟悉</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked bonus">
<span>💎</span>
<span>口說練習</span>
</div>
<div class="stage-connector"></div>
<div class="stage-step locked">
<span>🔒</span>
<span>情境對話</span>
</div>
</div>
</div>
<div class="script-rating">
<div class="stars-display">
<div class="star-rating"></div>
<div class="star-rating"></div>
<div class="star-rating"></div>
</div>
<button class="play-button">需完成前面劇本</button>
</div>
</div>
</div>
</div>
</div>
<script>
// 初始化用戶數據
document.addEventListener('DOMContentLoaded', function() {
loadUserData();
updateUserInterface();
});
// 載入用戶數據
function loadUserData() {
const userData = JSON.parse(localStorage.getItem('dramatLingUserData') || '{}');
// 模擬用戶數據
const defaultData = {
name: 'John Doe',
level: 'beginner',
currentStage: 1,
lifePoints: 4,
maxLifePoints: 5,
diamonds: 150,
completedScripts: 3,
totalStars: 9,
totalWords: 45,
userTier: 'free' // free, premium, unlimited
};
// 合併數據
window.userData = { ...defaultData, ...userData };
}
// 更新用戶界面
function updateUserInterface() {
const data = window.userData;
// 更新用戶信息
document.getElementById('userName').textContent = data.name;
document.getElementById('userLevel').textContent = `${getLevelDisplayName(data.level)} - 階段${data.currentStage}`;
document.getElementById('userAvatar').textContent = data.name.charAt(0).toUpperCase();
// 更新生命點數
updateLifePoints(data.lifePoints, data.maxLifePoints, data.userTier);
// 更新鑽石數量
document.getElementById('diamondCount').textContent = data.diamonds;
// 更新進度統計
document.getElementById('completedScripts').textContent = data.completedScripts;
document.getElementById('totalStars').textContent = data.totalStars;
document.getElementById('totalWords').textContent = data.totalWords;
}
// 更新生命點數顯示
function updateLifePoints(current, max, userTier) {
const heartsContainer = document.getElementById('heartsContainer');
heartsContainer.innerHTML = '';
if (userTier === 'unlimited') {
// 無限生命
const infiniteHeart = document.createElement('div');
infiniteHeart.className = 'heart infinite';
infiniteHeart.title = '無限生命';
heartsContainer.appendChild(infiniteHeart);
const infiniteText = document.createElement('span');
infiniteText.textContent = '∞';
infiniteText.style.cssText = 'color: var(--gold); font-weight: bold; margin-left: var(--space-2);';
heartsContainer.appendChild(infiniteText);
} else {
// 一般生命點數
for (let i = 0; i < max; i++) {
const heart = document.createElement('div');
heart.className = i < current ? 'heart' : 'heart empty';
heartsContainer.appendChild(heart);
}
}
}
// 獲取等級顯示名稱
function getLevelDisplayName(level) {
const levelNames = {
'beginner': '初學者',
'intermediate': '中級',
'advanced': '高級'
};
return levelNames[level] || level;
}
// 劇本卡片點擊處理
document.querySelectorAll('.script-card').forEach(card => {
card.addEventListener('click', function() {
const scriptId = this.dataset.script;
const isLocked = this.classList.contains('locked');
const isCompleted = this.classList.contains('completed');
const isAvailable = this.classList.contains('available');
if (isLocked) {
// 顯示解鎖提示
showLockedMessage();
return;
}
if (isAvailable) {
// 進入學習模式
startScript(scriptId);
} else if (isCompleted) {
// 重新練習或查看詳情
reviewScript(scriptId);
}
});
});
// 開始劇本學習
function startScript(scriptId) {
// 儲存當前劇本ID
localStorage.setItem('currentScript', scriptId);
// 根據劇本進度決定進入哪個關卡
// 這裡模擬進入第1關詞彙學習
window.location.href = `../phase2/vocabulary-learning.html?script=${scriptId}`;
}
// 重新練習劇本
function reviewScript(scriptId) {
// 顯示劇本選項彈窗
showScriptOptionsModal(scriptId);
}
// 顯示鎖定訊息
function showLockedMessage() {
// 簡單的提示訊息
alert('請先完成前面的劇本才能解鎖此內容!');
}
// 顯示劇本選項彈窗
function showScriptOptionsModal(scriptId) {
// 簡化處理,直接重新開始
if (confirm('要重新練習這個劇本嗎?')) {
startScript(scriptId);
}
}
// 模擬學習進度更新
function simulateProgress() {
// 這個函數會在實際學習過程中被調用
const data = window.userData;
data.totalWords += 5; // 學會新詞彙
data.totalStars += 1; // 獲得星級
if (Math.random() > 0.7) {
data.completedScripts += 1; // 完成劇本
}
// 儲存數據
localStorage.setItem('dramatLingUserData', JSON.stringify(data));
// 更新界面
updateUserInterface();
}
// 生命點數消耗處理
function consumeLifePoint() {
const data = window.userData;
if (data.userTier === 'unlimited') {
return true; // 無限生命不消耗
}
if (data.lifePoints > 0) {
data.lifePoints--;
localStorage.setItem('dramatLingUserData', JSON.stringify(data));
updateUserInterface();
return true;
} else {
// 生命點數不足,顯示補充選項
showLifePointsModal();
return false;
}
}
// 顯示生命點數補充彈窗
function showLifePointsModal() {
alert('生命點數不足!請等待恢復或購買無限生命。');
}
</script>
</body>
</html>

View File

@ -1,454 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 第1階段核心流程原型展示</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* Prototype Index Showcase Styles */
.showcase-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--background-primary) 0%, var(--background-secondary) 100%);
padding: var(--space-8) var(--space-6);
}
.showcase-header {
text-align: center;
margin-bottom: var(--space-12);
}
.showcase-title {
font-size: var(--text-4xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-4);
background: linear-gradient(135deg, var(--primary-teal) 0%, var(--secondary-purple) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.showcase-subtitle {
font-size: var(--text-xl);
color: var(--text-secondary);
margin-bottom: var(--space-6);
max-width: 800px;
margin-left: auto;
margin-right: auto;
line-height: 1.6;
}
.showcase-description {
font-size: var(--text-base);
color: var(--text-tertiary);
max-width: 1000px;
margin: 0 auto var(--space-8);
line-height: 1.7;
}
.screens-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: var(--space-8);
max-width: 1400px;
margin: 0 auto;
}
.screen-card {
background: var(--card-background);
border-radius: var(--radius-xl);
padding: var(--space-8);
border: 3px solid var(--divider);
transition: all var(--duration-normal);
cursor: pointer;
position: relative;
overflow: hidden;
}
.screen-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--primary-teal) 0%, var(--secondary-purple) 100%);
transform: translateX(-100%);
transition: transform var(--duration-normal);
}
.screen-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-xl);
border-color: var(--primary-teal);
}
.screen-card:hover::before {
transform: translateX(0);
}
.screen-icon {
width: 80px;
height: 80px;
border-radius: 50%;
margin: 0 auto var(--space-6);
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
background: linear-gradient(135deg, var(--primary-teal) 0%, var(--secondary-purple) 100%);
color: var(--text-primary);
}
.screen-title {
font-size: var(--text-xl);
color: var(--text-primary);
font-weight: bold;
text-align: center;
margin-bottom: var(--space-4);
}
.screen-description {
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: var(--space-6);
text-align: center;
}
.screen-features {
list-style: none;
padding: 0;
margin: 0 0 var(--space-6);
}
.screen-features li {
display: flex;
align-items: center;
margin-bottom: var(--space-3);
font-size: var(--text-sm);
color: var(--text-secondary);
}
.screen-features li::before {
content: '✓';
color: var(--primary-teal);
font-weight: bold;
margin-right: var(--space-3);
width: 16px;
text-align: center;
}
.screen-status {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-md);
font-size: var(--text-sm);
font-weight: 500;
margin-bottom: var(--space-4);
background: var(--success-green);
color: var(--text-primary);
}
.btn-view-screen {
width: 100%;
padding: var(--space-4) var(--space-6);
background: var(--primary-teal);
color: var(--background-dark);
border: 3px solid var(--primary-teal-dark);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 4px 0 var(--primary-teal-dark);
transform: translateY(0);
text-decoration: none;
display: block;
text-align: center;
}
.btn-view-screen:hover {
background: var(--primary-teal-light);
transform: translateY(-1px);
box-shadow: 0 5px 0 var(--primary-teal-dark);
}
.btn-view-screen:active {
transform: translateY(2px);
box-shadow: 0 2px 0 var(--primary-teal-dark);
}
.flow-navigation {
text-align: center;
margin-top: var(--space-12);
padding: var(--space-8);
background: var(--card-background);
border-radius: var(--radius-lg);
border: 2px solid var(--divider);
}
.flow-title {
font-size: var(--text-2xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-4);
}
.flow-description {
color: var(--text-secondary);
margin-bottom: var(--space-6);
line-height: 1.6;
}
.flow-steps {
display: flex;
justify-content: center;
align-items: center;
gap: var(--space-4);
flex-wrap: wrap;
margin-bottom: var(--space-6);
}
.flow-step {
padding: var(--space-3) var(--space-4);
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-md);
font-size: var(--text-sm);
color: var(--text-secondary);
white-space: nowrap;
}
.flow-arrow {
color: var(--primary-teal);
font-size: var(--text-lg);
}
.btn-start-flow {
padding: var(--space-5) var(--space-12);
background: var(--secondary-purple);
color: var(--text-primary);
border: 3px solid var(--secondary-purple-dark);
border-radius: var(--radius-lg);
font-size: var(--text-lg);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 6px 0 var(--secondary-purple-dark);
transform: translateY(0);
text-decoration: none;
display: inline-block;
}
.btn-start-flow:hover {
background: var(--secondary-purple-light);
transform: translateY(-2px);
box-shadow: 0 8px 0 var(--secondary-purple-dark);
}
.btn-start-flow:active {
transform: translateY(3px);
box-shadow: 0 3px 0 var(--secondary-purple-dark);
}
@media (max-width: 768px) {
.showcase-container {
padding: var(--space-6) var(--space-4);
}
.showcase-title {
font-size: var(--text-3xl);
}
.showcase-subtitle {
font-size: var(--text-lg);
}
.screens-grid {
grid-template-columns: 1fr;
gap: var(--space-6);
}
.screen-card {
padding: var(--space-6);
}
.flow-steps {
flex-direction: column;
gap: var(--space-2);
}
.flow-arrow {
transform: rotate(90deg);
}
}
</style>
</head>
<body>
<div class="showcase-container">
<!-- Showcase Header -->
<div class="showcase-header">
<h1 class="showcase-title">Drama Ling 原型展示</h1>
<h2 class="showcase-subtitle">第1階段核心學習流程畫面</h2>
<p class="showcase-description">
本展示包含 Drama Ling 核心學習流程的完整用戶體驗,從用戶註冊到四關學習系統的主要界面。
每個畫面都基於完整的 UI/UX 設計系統,整合了 102 個 UI 元件,並實現了 Duolingo 風格的遊戲化學習體驗。
所有畫面均採用響應式設計,支援桌面和行動裝置。
</p>
</div>
<!-- Screens Grid -->
<div class="screens-grid">
<!-- Login Screen -->
<div class="screen-card">
<div class="screen-icon">🔐</div>
<h3 class="screen-title">用戶登入</h3>
<div class="screen-status">
<span></span>
<span>已完成</span>
</div>
<p class="screen-description">
完整的用戶認證界面,支援電子郵件登入和 Google OAuth包含表單驗證和載入狀態處理。
</p>
<ul class="screen-features">
<li>UI_Login_Screen - 用戶登入界面</li>
<li>UI_Login_Form - 登入表單</li>
<li>UI_Google_Login_Button - Google登入</li>
<li>響應式設計與動畫效果</li>
<li>表單驗證與錯誤處理</li>
</ul>
<a href="01-login.html" class="btn-view-screen">查看登入畫面</a>
</div>
<!-- Signup Screen -->
<div class="screen-card">
<div class="screen-icon">📝</div>
<h3 class="screen-title">用戶註冊</h3>
<div class="screen-status">
<span></span>
<span>已完成</span>
</div>
<p class="screen-description">
詳細的註冊流程,包含個人資料填寫、年齡選擇、服務條款確認等完整用戶資料收集。
</p>
<ul class="screen-features">
<li>UI_Signup_Form - 註冊表單</li>
<li>UI_Age_Selection - 年齡範圍選擇</li>
<li>UI_Terms_Checkbox - 服務條款勾選</li>
<li>密碼強度驗證</li>
<li>即時表單驗證</li>
</ul>
<a href="02-signup.html" class="btn-view-screen">查看註冊畫面</a>
</div>
<!-- Onboarding Screen -->
<div class="screen-card">
<div class="screen-icon">🎯</div>
<h3 class="screen-title">新手引導</h3>
<div class="screen-status">
<span></span>
<span>已完成</span>
</div>
<p class="screen-description">
三步驟引導流程,收集用戶學習目標和英語程度,為後續學習路徑推薦提供數據基礎。
</p>
<ul class="screen-features">
<li>UI_Onboarding_Steps - 三步驟引導</li>
<li>UI_Learning_Goals_Selection - 學習目標選擇</li>
<li>UI_English_Level_Assessment - 程度評估</li>
<li>步驟指示器與進度追蹤</li>
<li>數據收集與儲存</li>
</ul>
<a href="03-onboarding.html" class="btn-view-screen">查看引導畫面</a>
</div>
<!-- Learning Path Selection -->
<div class="screen-card">
<div class="screen-icon">🛤️</div>
<h3 class="screen-title">學習路徑選擇</h3>
<div class="screen-status">
<span></span>
<span>已完成</span>
</div>
<p class="screen-description">
四種專業學習路徑選擇,包含日常對話、商務英語、旅遊英語、考試準備等不同學習方向。
</p>
<ul class="screen-features">
<li>UI_Learning_Path_Card - 學習路徑卡片</li>
<li>UI_Difficulty_Badge - 難度等級標識</li>
<li>UI_Time_Estimate - 完成時間預估</li>
<li>智能推薦系統</li>
<li>路徑特色說明</li>
</ul>
<a href="04-learning-path-selection.html" class="btn-view-screen">查看路徑選擇</a>
</div>
<!-- Four Stage Learning System -->
<div class="screen-card">
<div class="screen-icon">🎮</div>
<h3 class="screen-title">四關學習系統</h3>
<div class="screen-status">
<span></span>
<span>已完成</span>
</div>
<p class="screen-description">
Drama Ling 的核心學習界面展示13個階段的線性闖關系統每個劇本包含4個循序漸進的學習關卡。
</p>
<ul class="screen-features">
<li>UI_Four_Stage_Learning_Main - 主學習界面</li>
<li>UI_Life_Points_Display - 生命點數系統</li>
<li>UI_Script_Card - 劇本卡片設計</li>
<li>UI_Four_Stage_Progress - 四關進度顯示</li>
<li>UI_Stars_Rating - 星級評價系統</li>
</ul>
<a href="05-four-stage-learning.html" class="btn-view-screen">查看學習系統</a>
</div>
</div>
<!-- Flow Navigation -->
<div class="flow-navigation">
<h3 class="flow-title">完整用戶流程體驗</h3>
<p class="flow-description">
體驗從註冊到開始學習的完整流程,所有畫面間的導航和數據傳遞都已實現
</p>
<div class="flow-steps">
<div class="flow-step">用戶登入</div>
<div class="flow-arrow"></div>
<div class="flow-step">新手引導</div>
<div class="flow-arrow"></div>
<div class="flow-step">路徑選擇</div>
<div class="flow-arrow"></div>
<div class="flow-step">開始學習</div>
</div>
<a href="01-login.html" class="btn-start-flow">開始完整流程體驗</a>
</div>
</div>
<script>
// 統計功能
document.addEventListener('DOMContentLoaded', function() {
console.log('Drama Ling Phase 1 Prototypes Loaded');
console.log('包含畫面數量:', document.querySelectorAll('.screen-card').length);
console.log('設計基於docs/02_design/prototype-design-plan.md');
console.log('UI 系統docs/02_design/ui-ux/dramaling-ui.css');
console.log('元件參考docs/02_design/function-specs/common/system_structure_design.json');
});
// 卡片hover效果增強
document.querySelectorAll('.screen-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-8px) scale(1.02)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(-4px) scale(1)';
});
});
</script>
</body>
</html>

View File

@ -1,935 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 道具商店</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Shop_Main - 道具商店主頁面 */
.shop-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--background-primary) 0%, var(--background-secondary) 100%);
}
/* UI_Shop_Header - 商店頂部區域 */
.shop-header {
background: var(--card-background);
padding: var(--space-6);
border-bottom: 2px solid var(--divider);
display: flex;
justify-content: space-between;
align-items: center;
}
.shop-title-section {
display: flex;
align-items: center;
gap: var(--space-4);
}
.shop-icon {
width: 60px;
height: 60px;
border-radius: 50%;
background: linear-gradient(135deg, var(--gold) 0%, var(--warning-yellow) 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
border: 3px solid var(--warning-yellow);
}
.shop-title {
font-size: var(--text-3xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-1);
}
.shop-subtitle {
font-size: var(--text-base);
color: var(--text-secondary);
}
/* UI_Diamond_Balance_Display - 鑽石餘額顯示 */
.balance-section {
display: flex;
align-items: center;
gap: var(--space-6);
}
.balance-display {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-4) var(--space-6);
background: var(--background-secondary);
border-radius: var(--radius-lg);
border: 2px solid var(--divider);
}
.diamond-icon {
width: 28px;
height: 28px;
background: var(--diamond);
clip-path: polygon(50% 0%, 0% 50%, 50% 100%, 100% 50%);
animation: sparkle 2s infinite;
}
@keyframes sparkle {
0%, 100% { transform: scale(1) rotate(0deg); }
50% { transform: scale(1.1) rotate(45deg); }
}
.balance-amount {
font-size: var(--text-xl);
font-weight: bold;
color: var(--text-primary);
}
.btn-buy-diamonds {
padding: var(--space-3) var(--space-6);
background: var(--primary-teal);
color: var(--background-dark);
border: 3px solid var(--primary-teal-dark);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 4px 0 var(--primary-teal-dark);
transform: translateY(0);
}
.btn-buy-diamonds:hover {
background: var(--primary-teal-light);
transform: translateY(-1px);
box-shadow: 0 5px 0 var(--primary-teal-dark);
}
.btn-buy-diamonds:active {
transform: translateY(2px);
box-shadow: 0 2px 0 var(--primary-teal-dark);
}
/* UI_Shop_Categories - 商店分類選項 */
.shop-nav {
background: var(--card-background);
padding: 0 var(--space-6);
border-bottom: 1px solid var(--divider);
}
.category-tabs {
display: flex;
gap: var(--space-2);
}
.category-tab {
padding: var(--space-4) var(--space-6);
background: transparent;
border: none;
color: var(--text-secondary);
font-size: var(--text-base);
font-weight: 500;
cursor: pointer;
transition: all var(--duration-normal);
border-bottom: 3px solid transparent;
position: relative;
}
.category-tab:hover {
color: var(--text-primary);
background: var(--background-secondary);
}
.category-tab.active {
color: var(--primary-teal);
border-bottom-color: var(--primary-teal);
background: var(--background-secondary);
}
.category-tab .badge {
position: absolute;
top: var(--space-2);
right: var(--space-2);
background: var(--error-red);
color: var(--text-primary);
font-size: var(--text-xs);
padding: 2px 6px;
border-radius: 10px;
font-weight: bold;
}
/* Shop Content Area */
.shop-content {
padding: var(--space-8) var(--space-6);
}
.category-section {
display: none;
}
.category-section.active {
display: block;
}
.section-title {
font-size: var(--text-xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-2);
display: flex;
align-items: center;
gap: var(--space-3);
}
.section-description {
color: var(--text-secondary);
margin-bottom: var(--space-8);
line-height: 1.6;
}
/* UI_Item_Grid - 道具網格佈局 */
.items-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--space-6);
margin-bottom: var(--space-8);
}
/* UI_Shop_Item_Card - 道具卡片 */
.item-card {
background: var(--card-background);
border-radius: var(--radius-lg);
padding: var(--space-6);
border: 2px solid var(--divider);
transition: all var(--duration-normal);
cursor: pointer;
position: relative;
overflow: hidden;
}
.item-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--divider);
transition: all var(--duration-normal);
}
.item-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
border-color: var(--primary-teal);
}
.item-card:hover::before {
background: var(--primary-teal);
}
.item-card.popular {
border-color: var(--warning-yellow);
background: linear-gradient(135deg, var(--card-background) 0%, rgba(243, 156, 18, 0.05) 100%);
}
.item-card.popular::before {
background: var(--warning-yellow);
}
.item-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--space-4);
}
.item-icon {
width: 50px;
height: 50px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
margin-bottom: var(--space-3);
}
.item-helper { background: var(--info-cyan); }
.item-life { background: var(--error-red); }
.item-time { background: var(--warning-yellow); }
.item-premium { background: var(--secondary-purple); }
/* UI_Popular_Badge - 熱門標籤 */
.popular-badge {
background: var(--warning-yellow);
color: var(--background-dark);
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-md);
font-size: var(--text-xs);
font-weight: bold;
position: absolute;
top: var(--space-3);
right: var(--space-3);
transform: rotate(15deg);
}
.item-title {
font-size: var(--text-lg);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-2);
}
.item-description {
color: var(--text-secondary);
font-size: var(--text-sm);
line-height: 1.5;
margin-bottom: var(--space-4);
}
/* UI_Item_Price_Display - 價格顯示 */
.item-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.price-section {
display: flex;
align-items: center;
gap: var(--space-2);
}
.price-amount {
display: flex;
align-items: center;
gap: var(--space-2);
font-weight: bold;
color: var(--text-primary);
}
.price-diamond {
width: 16px;
height: 16px;
background: var(--diamond);
clip-path: polygon(50% 0%, 0% 50%, 50% 100%, 100% 50%);
}
.original-price {
text-decoration: line-through;
color: var(--text-tertiary);
font-size: var(--text-sm);
}
.discount-badge {
background: var(--error-red);
color: var(--text-primary);
padding: 2px 6px;
border-radius: var(--radius-sm);
font-size: var(--text-xs);
font-weight: bold;
}
/* UI_Buy_Button - 購買按鈕 */
.btn-buy-item {
padding: var(--space-3) var(--space-5);
background: var(--primary-teal);
color: var(--background-dark);
border: 2px solid var(--primary-teal-dark);
border-radius: var(--radius-md);
font-size: var(--text-sm);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 3px 0 var(--primary-teal-dark);
transform: translateY(0);
}
.btn-buy-item:hover {
background: var(--primary-teal-light);
transform: translateY(-1px);
box-shadow: 0 4px 0 var(--primary-teal-dark);
}
.btn-buy-item:active {
transform: translateY(1px);
box-shadow: 0 2px 0 var(--primary-teal-dark);
}
.btn-buy-item:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: 0 3px 0 var(--primary-teal-dark);
}
/* UI_Diamond_Purchase_Section - 鑽石購買專區 */
.diamond-packages {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--space-4);
}
.diamond-package {
background: var(--card-background);
border: 2px solid var(--divider);
border-radius: var(--radius-lg);
padding: var(--space-6);
text-align: center;
transition: all var(--duration-normal);
cursor: pointer;
position: relative;
}
.diamond-package:hover {
transform: scale(1.02);
border-color: var(--diamond);
box-shadow: var(--shadow-lg);
}
.diamond-package.recommended {
border-color: var(--warning-yellow);
background: linear-gradient(135deg, var(--card-background) 0%, rgba(243, 156, 18, 0.1) 100%);
transform: scale(1.05);
}
.diamond-package.recommended::before {
content: '最超值';
position: absolute;
top: -10px;
left: 50%;
transform: translateX(-50%);
background: var(--warning-yellow);
color: var(--background-dark);
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-md);
font-size: var(--text-xs);
font-weight: bold;
}
.package-amount {
font-size: var(--text-2xl);
font-weight: bold;
color: var(--diamond);
margin-bottom: var(--space-2);
}
.package-price {
font-size: var(--text-lg);
font-weight: bold;
color: var(--text-primary);
margin-bottom: var(--space-4);
}
.package-bonus {
color: var(--success-green);
font-size: var(--text-sm);
font-weight: 500;
margin-bottom: var(--space-4);
}
@media (max-width: 768px) {
.shop-header {
flex-direction: column;
gap: var(--space-4);
padding: var(--space-4);
}
.balance-section {
width: 100%;
justify-content: center;
}
.shop-content {
padding: var(--space-6) var(--space-4);
}
.category-tabs {
flex-wrap: wrap;
justify-content: center;
}
.category-tab {
padding: var(--space-3) var(--space-4);
font-size: var(--text-sm);
}
.items-grid {
grid-template-columns: 1fr;
gap: var(--space-4);
}
.diamond-packages {
grid-template-columns: repeat(2, 1fr);
gap: var(--space-3);
}
}
</style>
</head>
<body>
<div class="shop-container">
<!-- UI_Shop_Header - 商店頂部區域 -->
<div class="shop-header">
<div class="shop-title-section">
<div class="shop-icon">🛒</div>
<div>
<h1 class="shop-title">道具商店</h1>
<p class="shop-subtitle">提升學習效率,解鎖更多可能</p>
</div>
</div>
<!-- UI_Diamond_Balance_Display - 鑽石餘額顯示 -->
<div class="balance-section">
<div class="balance-display">
<div class="diamond-icon"></div>
<span class="balance-amount" id="diamondBalance">1,250</span>
</div>
<button class="btn-buy-diamonds" id="buyDiamondsBtn">購買鑽石</button>
</div>
</div>
<!-- UI_Shop_Categories - 商店分類選項 -->
<div class="shop-nav">
<div class="category-tabs">
<button class="category-tab active" data-category="learning">
學習輔助
<span class="badge">HOT</span>
</button>
<button class="category-tab" data-category="life">
生命補充
</button>
<button class="category-tab" data-category="challenge">
挑戰道具
</button>
<button class="category-tab" data-category="premium">
會員專區
</button>
<button class="category-tab" data-category="diamonds">
鑽石購買
</button>
</div>
</div>
<div class="shop-content">
<!-- 學習輔助道具 -->
<div class="category-section active" id="learning">
<h2 class="section-title">
<span>📚</span>
學習輔助道具
</h2>
<p class="section-description">
提升學習效果,讓英語學習更輕鬆有趣。這些道具能在四關闖關過程中提供即時幫助。
</p>
<div class="items-grid">
<!-- 回覆提示道具 -->
<div class="item-card popular">
<div class="popular-badge">熱門</div>
<div class="item-icon item-helper">💡</div>
<h3 class="item-title">智能回覆提示</h3>
<p class="item-description">
在情境對話中獲得AI智能回覆建議幫助您選擇最恰當的回應。每次使用提供3個優質回覆選項。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>50</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 翻譯輔助 -->
<div class="item-card">
<div class="item-icon item-helper">🌐</div>
<h3 class="item-title">即時翻譯輔助</h3>
<p class="item-description">
遇到不熟悉的詞彙或句子時,一鍵查看中文翻譯和詳細解釋。包含文化背景說明。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>30</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 語法檢查 -->
<div class="item-card">
<div class="item-icon item-helper">✏️</div>
<h3 class="item-title">語法檢查器</h3>
<p class="item-description">
AI語法檢查工具即時分析您的句子結構提供語法改善建議和正確用法示例。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>40</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 發音練習加強 -->
<div class="item-card">
<div class="item-icon item-helper">🎤</div>
<h3 class="item-title">發音練習加強</h3>
<p class="item-description">
額外的發音練習機會包含音標指導和發音技巧提示。AI評分系統提供詳細改善建議。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>60</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
</div>
</div>
<!-- 生命補充道具 -->
<div class="category-section" id="life">
<h2 class="section-title">
<span>❤️</span>
生命補充道具
</h2>
<p class="section-description">
快速恢復生命點數,持續您的學習進度。不同套餐適合不同學習強度的需求。
</p>
<div class="items-grid">
<!-- 單次補命 -->
<div class="item-card">
<div class="item-icon item-life">💖</div>
<h3 class="item-title">立即補命</h3>
<p class="item-description">
立即恢復1個生命點數繼續您的學習之旅。適合偶爾使用的學習者。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>20</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 完全恢復 -->
<div class="item-card popular">
<div class="popular-badge">推薦</div>
<div class="item-icon item-life">💕</div>
<h3 class="item-title">完全恢復</h3>
<p class="item-description">
將生命點數恢復至滿格狀態,適合密集學習時使用。比單次購買更划算。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>80</span>
</div>
<span class="original-price">100💎</span>
<span class="discount-badge">-20%</span>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 生命守護 -->
<div class="item-card">
<div class="item-icon item-life">🛡️</div>
<h3 class="item-title">生命守護</h3>
<p class="item-description">
24小時內失敗不消耗生命點數安心挑戰困難關卡。適合想要突破瓶頸的學習者。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>150</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
</div>
</div>
<!-- 挑戰道具 -->
<div class="category-section" id="challenge">
<h2 class="section-title">
<span></span>
挑戰道具
</h2>
<p class="section-description">
在限時挑戰和競技模式中獲得優勢,提升排行榜名次和獎勵獲得。
</p>
<div class="items-grid">
<!-- 時間暫停 -->
<div class="item-card">
<div class="item-icon item-time">⏸️</div>
<h3 class="item-title">時間暫停</h3>
<p class="item-description">
在300秒限時挑戰中暫停計時5秒爭取更多思考時間。每次挑戰可使用1次。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>35</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 額外時間 -->
<div class="item-card">
<div class="item-icon item-time"></div>
<h3 class="item-title">時間加成</h3>
<p class="item-description">
為限時挑戰增加30秒額外時間完成更多題目獲得更高分數。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>45</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- 雙倍經驗 -->
<div class="item-card popular">
<div class="popular-badge">熱門</div>
<div class="item-icon item-time"></div>
<h3 class="item-title">經驗雙倍</h3>
<p class="item-description">
接下來的3次學習獲得雙倍經驗值快速提升等級和解鎖新內容。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>70</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
</div>
</div>
<!-- 會員專區 -->
<div class="category-section" id="premium">
<h2 class="section-title">
<span>👑</span>
會員專區
</h2>
<p class="section-description">
專為付費會員準備的超值道具包,享受更優惠的價格和獨家內容。
</p>
<div class="items-grid">
<!-- 會員專享包 -->
<div class="item-card">
<div class="item-icon item-premium">🎁</div>
<h3 class="item-title">會員專享包</h3>
<p class="item-description">
包含5次智能回覆提示、3次完全恢復、2次時間暫停。只有會員才能享受的超值組合。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>200</span>
</div>
<span class="original-price">350💎</span>
<span class="discount-badge">-43%</span>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
<!-- VIP學習加速器 -->
<div class="item-card">
<div class="item-icon item-premium">🚀</div>
<h3 class="item-title">VIP學習加速器</h3>
<p class="item-description">
7天內所有學習獲得3倍經驗值生命恢復速度加倍專屬徽章顯示。
</p>
<div class="item-footer">
<div class="price-section">
<div class="price-amount">
<div class="price-diamond"></div>
<span>500</span>
</div>
</div>
<button class="btn-buy-item">購買</button>
</div>
</div>
</div>
</div>
<!-- UI_Diamond_Purchase_Section - 鑽石購買專區 -->
<div class="category-section" id="diamonds">
<h2 class="section-title">
<span>💎</span>
鑽石購買專區
</h2>
<p class="section-description">
選擇最適合您的鑽石套餐,享受更豐富的學習體驗。首次購買享有新手優惠。
</p>
<div class="diamond-packages">
<!-- 新手包 -->
<div class="diamond-package">
<div class="package-amount">💎 500</div>
<div class="package-price">NT$ 30</div>
<div class="package-bonus">首次購買專享</div>
<button class="btn-buy-item">立即購買</button>
</div>
<!-- 基礎包 -->
<div class="diamond-package">
<div class="package-amount">💎 1,200</div>
<div class="package-price">NT$ 60</div>
<div class="package-bonus">贈送200鑽石</div>
<button class="btn-buy-item">立即購買</button>
</div>
<!-- 價值包 - 推薦 -->
<div class="diamond-package recommended">
<div class="package-amount">💎 2,500</div>
<div class="package-price">NT$ 99</div>
<div class="package-bonus">贈送500鑽石</div>
<button class="btn-buy-item">立即購買</button>
</div>
<!-- 豪華包 -->
<div class="diamond-package">
<div class="package-amount">💎 5,000</div>
<div class="package-price">NT$ 190</div>
<div class="package-bonus">贈送1000鑽石</div>
<button class="btn-buy-item">立即購買</button>
</div>
<!-- 至尊包 -->
<div class="diamond-package">
<div class="package-amount">💎 12,000</div>
<div class="package-price">NT$ 390</div>
<div class="package-bonus">贈送3000鑽石</div>
<button class="btn-buy-item">立即購買</button>
</div>
</div>
</div>
</div>
</div>
<script>
// 分類切換功能
document.querySelectorAll('.category-tab').forEach(tab => {
tab.addEventListener('click', function() {
// 移除所有active狀態
document.querySelectorAll('.category-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.category-section').forEach(s => s.classList.remove('active'));
// 設置當前active狀態
this.classList.add('active');
const category = this.dataset.category;
document.getElementById(category).classList.add('active');
});
});
// 購買道具功能
document.querySelectorAll('.btn-buy-item').forEach(button => {
button.addEventListener('click', function(e) {
e.stopPropagation();
const itemCard = this.closest('.item-card') || this.closest('.diamond-package');
const itemName = itemCard.querySelector('.item-title')?.textContent ||
itemCard.querySelector('.package-amount')?.textContent || '道具';
const price = itemCard.querySelector('.price-amount span')?.textContent ||
itemCard.querySelector('.package-price')?.textContent || '未知價格';
if (confirm(`確定要購買 ${itemName} 嗎?\n價格${price.includes('NT$') ? price : price + '💎'}`)) {
// 模擬購買過程
this.textContent = '購買中...';
this.disabled = true;
setTimeout(() => {
// 更新鑽石餘額(如果是鑽石道具)
if (!price.includes('NT$')) {
const currentBalance = parseInt(document.getElementById('diamondBalance').textContent);
const itemPrice = parseInt(price);
if (currentBalance >= itemPrice) {
document.getElementById('diamondBalance').textContent = currentBalance - itemPrice;
alert(`成功購買 ${itemName}\n剩餘鑽石${currentBalance - itemPrice}`);
} else {
alert('鑽石不足,請先購買鑽石!');
// 自動切換到鑽石購買頁面
document.querySelector('[data-category="diamonds"]').click();
}
} else {
// 模擬金錢購買流程
window.location.href = '../phase2/02-payment-flow.html';
return;
}
this.textContent = '購買';
this.disabled = false;
}, 1500);
}
});
});
// 購買鑽石按鈕
document.getElementById('buyDiamondsBtn').addEventListener('click', function() {
document.querySelector('[data-category="diamonds"]').click();
});
// 道具卡片hover效果
document.querySelectorAll('.item-card, .diamond-package').forEach(card => {
card.addEventListener('click', function() {
// 顯示詳細信息(可擴展)
const title = this.querySelector('.item-title')?.textContent ||
this.querySelector('.package-amount')?.textContent;
const description = this.querySelector('.item-description')?.textContent ||
this.querySelector('.package-bonus')?.textContent;
console.log(`查看道具詳情:${title}`);
// 這裡可以添加詳細信息彈窗
});
});
// 初始化用戶數據
document.addEventListener('DOMContentLoaded', function() {
// 模擬從localStorage讀取用戶數據
const userData = JSON.parse(localStorage.getItem('dramatLingUserData') || '{}');
const defaultDiamonds = 1250;
document.getElementById('diamondBalance').textContent = userData.diamonds || defaultDiamonds;
});
</script>
</body>
</html>

View File

@ -1,864 +0,0 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 付費流程</title>
<link rel="stylesheet" href="../../../docs/02_design/ui-ux/dramaling-ui.css">
<style>
/* UI_Payment_Flow - 付費流程主容器 */
.payment-container {
min-height: 100vh;
background: linear-gradient(135deg, var(--background-primary) 0%, var(--background-secondary) 100%);
padding: var(--space-6);
display: flex;
align-items: center;
justify-content: center;
}
.payment-wrapper {
width: 100%;
max-width: 600px;
background: var(--card-background);
border-radius: var(--radius-xl);
padding: var(--space-8);
border: 3px solid var(--divider);
box-shadow: var(--shadow-xl);
position: relative;
overflow: hidden;
}
.payment-wrapper::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--primary-teal) 0%, var(--secondary-purple) 100%);
}
/* UI_Payment_Header - 付費標題區域 */
.payment-header {
text-align: center;
margin-bottom: var(--space-8);
}
.payment-icon {
width: 80px;
height: 80px;
border-radius: 50%;
background: linear-gradient(135deg, var(--gold) 0%, var(--warning-yellow) 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
margin: 0 auto var(--space-4);
border: 3px solid var(--warning-yellow);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); box-shadow: 0 0 20px rgba(243, 156, 18, 0.5); }
}
.payment-title {
font-size: var(--text-3xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-2);
}
.payment-subtitle {
font-size: var(--text-base);
color: var(--text-secondary);
line-height: 1.6;
}
/* UI_Payment_Progress - 付費進度指示器 */
.payment-progress {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: var(--space-8);
gap: var(--space-2);
}
.progress-step {
display: flex;
align-items: center;
gap: var(--space-3);
}
.step-circle {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--background-secondary);
border: 2px solid var(--divider);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--text-sm);
font-weight: bold;
color: var(--text-tertiary);
transition: all var(--duration-normal);
}
.step-circle.active {
background: var(--primary-teal);
border-color: var(--primary-teal-dark);
color: var(--background-dark);
}
.step-circle.completed {
background: var(--success-green);
border-color: var(--success-green);
color: var(--text-primary);
}
.step-connector {
width: 40px;
height: 2px;
background: var(--divider);
transition: all var(--duration-normal);
}
.step-connector.active {
background: var(--primary-teal);
}
/* Payment Step Sections */
.payment-step {
display: none;
}
.payment-step.active {
display: block;
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* UI_Package_Selection - 套餐選擇 */
.package-selection {
margin-bottom: var(--space-8);
}
.section-title {
font-size: var(--text-xl);
color: var(--text-primary);
font-weight: bold;
margin-bottom: var(--space-4);
display: flex;
align-items: center;
gap: var(--space-3);
}
.packages-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--space-4);
margin-bottom: var(--space-6);
}
.package-option {
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-lg);
padding: var(--space-4);
text-align: center;
cursor: pointer;
transition: all var(--duration-normal);
position: relative;
}
.package-option:hover {
transform: translateY(-2px);
border-color: var(--primary-teal);
box-shadow: var(--shadow-md);
}
.package-option.selected {
background: var(--primary-teal);
border-color: var(--primary-teal-dark);
color: var(--background-dark);
transform: scale(1.05);
box-shadow: 0 4px 0 var(--primary-teal-dark);
}
.package-option.recommended {
border-color: var(--warning-yellow);
background: linear-gradient(135deg, var(--background-secondary) 0%, rgba(243, 156, 18, 0.1) 100%);
}
.package-option.recommended::before {
content: '最划算';
position: absolute;
top: -8px;
left: 50%;
transform: translateX(-50%);
background: var(--warning-yellow);
color: var(--background-dark);
padding: 2px 8px;
border-radius: var(--radius-sm);
font-size: var(--text-xs);
font-weight: bold;
}
.package-diamonds {
font-size: var(--text-xl);
font-weight: bold;
color: var(--diamond);
margin-bottom: var(--space-2);
}
.package-option.selected .package-diamonds {
color: var(--background-dark);
}
.package-price {
font-size: var(--text-lg);
font-weight: bold;
color: var(--text-primary);
margin-bottom: var(--space-2);
}
.package-option.selected .package-price {
color: var(--background-dark);
}
.package-bonus {
font-size: var(--text-sm);
color: var(--success-green);
}
.package-option.selected .package-bonus {
color: var(--background-dark);
}
/* UI_Payment_Methods - 支付方式選擇 */
.payment-methods {
margin-bottom: var(--space-8);
}
.methods-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--space-4);
}
.payment-method {
background: var(--background-secondary);
border: 2px solid var(--divider);
border-radius: var(--radius-lg);
padding: var(--space-4);
cursor: pointer;
transition: all var(--duration-normal);
display: flex;
align-items: center;
gap: var(--space-3);
}
.payment-method:hover {
border-color: var(--primary-teal);
background: var(--background-primary);
}
.payment-method.selected {
background: var(--primary-teal);
border-color: var(--primary-teal-dark);
color: var(--background-dark);
box-shadow: 0 4px 0 var(--primary-teal-dark);
}
.method-icon {
width: 40px;
height: 40px;
border-radius: var(--radius-md);
background: var(--text-primary);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
.payment-method.selected .method-icon {
background: var(--background-dark);
color: var(--primary-teal);
}
.method-info {
flex: 1;
}
.method-name {
font-size: var(--text-base);
font-weight: bold;
color: var(--text-primary);
margin-bottom: var(--space-1);
}
.payment-method.selected .method-name {
color: var(--background-dark);
}
.method-description {
font-size: var(--text-sm);
color: var(--text-secondary);
}
.payment-method.selected .method-description {
color: var(--background-dark);
}
/* UI_Purchase_Confirmation - 購買確認 */
.purchase-summary {
background: var(--background-secondary);
border-radius: var(--radius-lg);
padding: var(--space-6);
border: 2px solid var(--divider);
margin-bottom: var(--space-6);
}
.summary-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-3);
}
.summary-row:last-child {
margin-bottom: 0;
padding-top: var(--space-3);
border-top: 1px solid var(--divider);
font-weight: bold;
font-size: var(--text-lg);
}
.summary-label {
color: var(--text-secondary);
}
.summary-value {
color: var(--text-primary);
font-weight: 500;
}
.total-label {
color: var(--text-primary);
}
.total-value {
color: var(--primary-teal);
}
/* UI_Loading_Animation - 載入動畫 */
.payment-loading {
text-align: center;
padding: var(--space-8) 0;
}
.loading-spinner {
width: 60px;
height: 60px;
border: 4px solid var(--divider);
border-top: 4px solid var(--primary-teal);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto var(--space-4);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
font-size: var(--text-lg);
color: var(--text-secondary);
margin-bottom: var(--space-2);
}
.loading-details {
font-size: var(--text-sm);
color: var(--text-tertiary);
}
/* UI_Success_Confirmation - 成功確認 */
.payment-success {
text-align: center;
padding: var(--space-8) 0;
}
.success-icon {
width: 100px;
height: 100px;
border-radius: 50%;
background: var(--success-green);
display: flex;
align-items: center;
justify-content: center;
font-size: 60px;
margin: 0 auto var(--space-6);
animation: successPulse 0.6s ease-out;
}
@keyframes successPulse {
0% { transform: scale(0) rotate(0deg); }
50% { transform: scale(1.2) rotate(180deg); }
100% { transform: scale(1) rotate(360deg); }
}
.success-title {
font-size: var(--text-2xl);
color: var(--success-green);
font-weight: bold;
margin-bottom: var(--space-4);
}
.success-message {
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: var(--space-6);
}
.success-details {
background: var(--background-secondary);
border-radius: var(--radius-lg);
padding: var(--space-4);
margin-bottom: var(--space-6);
}
/* Navigation Buttons */
.payment-navigation {
display: flex;
justify-content: space-between;
gap: var(--space-4);
}
.btn-secondary {
padding: var(--space-4) var(--space-6);
background: var(--background-secondary);
color: var(--text-primary);
border: 2px solid var(--divider);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: 500;
cursor: pointer;
transition: all var(--duration-normal);
}
.btn-secondary:hover {
background: var(--background-primary);
border-color: var(--primary-teal);
}
.btn-primary {
padding: var(--space-4) var(--space-8);
background: var(--primary-teal);
color: var(--background-dark);
border: 3px solid var(--primary-teal-dark);
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: bold;
cursor: pointer;
transition: all var(--duration-normal);
box-shadow: 0 4px 0 var(--primary-teal-dark);
transform: translateY(0);
}
.btn-primary:hover {
background: var(--primary-teal-light);
transform: translateY(-1px);
box-shadow: 0 5px 0 var(--primary-teal-dark);
}
.btn-primary:active {
transform: translateY(2px);
box-shadow: 0 2px 0 var(--primary-teal-dark);
}
.btn-primary:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
box-shadow: 0 4px 0 var(--primary-teal-dark);
}
@media (max-width: 768px) {
.payment-container {
padding: var(--space-4);
}
.payment-wrapper {
padding: var(--space-6);
}
.payment-progress {
flex-direction: column;
gap: var(--space-1);
}
.step-connector {
width: 2px;
height: 20px;
transform: rotate(90deg);
}
.packages-grid {
grid-template-columns: 1fr;
}
.methods-grid {
grid-template-columns: 1fr;
}
.payment-navigation {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="payment-container">
<div class="payment-wrapper">
<!-- UI_Payment_Header - 付費標題區域 -->
<div class="payment-header">
<div class="payment-icon">💰</div>
<h1 class="payment-title">購買鑽石</h1>
<p class="payment-subtitle">選擇最適合您的套餐,立即開始豐富的學習體驗</p>
</div>
<!-- UI_Payment_Progress - 付費進度指示器 -->
<div class="payment-progress">
<div class="progress-step">
<div class="step-circle active" id="step1">1</div>
<div class="step-connector active"></div>
</div>
<div class="progress-step">
<div class="step-circle" id="step2">2</div>
<div class="step-connector"></div>
</div>
<div class="progress-step">
<div class="step-circle" id="step3">3</div>
</div>
</div>
<!-- Step 1: Package Selection -->
<div class="payment-step active" id="packageStep">
<!-- UI_Package_Selection - 套餐選擇 -->
<div class="package-selection">
<h2 class="section-title">
<span>💎</span>
選擇鑽石套餐
</h2>
<div class="packages-grid">
<div class="package-option" data-package="starter">
<div class="package-diamonds">💎 500</div>
<div class="package-price">NT$ 30</div>
<div class="package-bonus">新手專享</div>
</div>
<div class="package-option" data-package="basic">
<div class="package-diamonds">💎 1,200</div>
<div class="package-price">NT$ 60</div>
<div class="package-bonus">+200贈送</div>
</div>
<div class="package-option recommended" data-package="value">
<div class="package-diamonds">💎 2,500</div>
<div class="package-price">NT$ 99</div>
<div class="package-bonus">+500贈送</div>
</div>
<div class="package-option" data-package="premium">
<div class="package-diamonds">💎 5,000</div>
<div class="package-price">NT$ 190</div>
<div class="package-bonus">+1000贈送</div>
</div>
<div class="package-option" data-package="ultimate">
<div class="package-diamonds">💎 12,000</div>
<div class="package-price">NT$ 390</div>
<div class="package-bonus">+3000贈送</div>
</div>
</div>
</div>
<div class="payment-navigation">
<button class="btn-secondary" onclick="goBack()">返回商店</button>
<button class="btn-primary" id="nextToPayment" disabled>下一步</button>
</div>
</div>
<!-- Step 2: Payment Method Selection -->
<div class="payment-step" id="paymentStep">
<!-- UI_Payment_Methods - 支付方式選擇 -->
<div class="payment-methods">
<h2 class="section-title">
<span>💳</span>
選擇支付方式
</h2>
<div class="methods-grid">
<div class="payment-method" data-method="applepay">
<div class="method-icon">🍎</div>
<div class="method-info">
<div class="method-name">Apple Pay</div>
<div class="method-description">安全快速的一鍵支付</div>
</div>
</div>
<div class="payment-method" data-method="googlepay">
<div class="method-icon">📱</div>
<div class="method-info">
<div class="method-name">Google Pay</div>
<div class="method-description">Google 官方支付服務</div>
</div>
</div>
<div class="payment-method" data-method="creditcard">
<div class="method-icon">💳</div>
<div class="method-info">
<div class="method-name">信用卡</div>
<div class="method-description">Visa / MasterCard</div>
</div>
</div>
<div class="payment-method" data-method="paypal">
<div class="method-icon">🔵</div>
<div class="method-info">
<div class="method-name">PayPal</div>
<div class="method-description">國際通用支付平台</div>
</div>
</div>
</div>
</div>
<!-- UI_Purchase_Confirmation - 購買確認 -->
<div class="purchase-summary">
<div class="summary-row">
<span class="summary-label">套餐內容:</span>
<span class="summary-value" id="summaryPackage">請選擇套餐</span>
</div>
<div class="summary-row">
<span class="summary-label">基礎鑽石:</span>
<span class="summary-value" id="summaryDiamonds">0</span>
</div>
<div class="summary-row">
<span class="summary-label">贈送鑽石:</span>
<span class="summary-value" id="summaryBonus">0</span>
</div>
<div class="summary-row">
<span class="total-label">總計:</span>
<span class="total-value" id="summaryTotal">NT$ 0</span>
</div>
</div>
<div class="payment-navigation">
<button class="btn-secondary" id="backToPackage">上一步</button>
<button class="btn-primary" id="confirmPayment" disabled>確認付款</button>
</div>
</div>
<!-- Step 3: Processing -->
<div class="payment-step" id="processingStep">
<!-- UI_Loading_Animation - 載入動畫 -->
<div class="payment-loading">
<div class="loading-spinner"></div>
<div class="loading-text">正在處理您的付款...</div>
<div class="loading-details">請勿關閉此頁面,我們正在與支付服務商確認您的交易</div>
</div>
</div>
<!-- Success Step -->
<div class="payment-step" id="successStep">
<!-- UI_Success_Confirmation - 成功確認 -->
<div class="payment-success">
<div class="success-icon"></div>
<h2 class="success-title">付款成功!</h2>
<p class="success-message">
恭喜您!鑽石已經成功充值到您的帳戶中。現在您可以盡情享受 Drama Ling 的完整學習體驗了!
</p>
<div class="success-details">
<div class="summary-row">
<span class="summary-label">購買項目:</span>
<span class="summary-value" id="successPackage">-</span>
</div>
<div class="summary-row">
<span class="summary-label">獲得鑽石:</span>
<span class="summary-value" id="successDiamonds">-</span>
</div>
<div class="summary-row">
<span class="summary-label">交易時間:</span>
<span class="summary-value" id="successTime">-</span>
</div>
</div>
<div class="payment-navigation">
<button class="btn-secondary" onclick="goToShop()">返回商店</button>
<button class="btn-primary" onclick="goToLearning()">開始學習</button>
</div>
</div>
</div>
</div>
</div>
<script>
let currentStep = 1;
let selectedPackage = null;
let selectedPaymentMethod = null;
const packageData = {
starter: { diamonds: 500, price: 30, bonus: 0, name: '新手包' },
basic: { diamonds: 1000, price: 60, bonus: 200, name: '基礎包' },
value: { diamonds: 2000, price: 99, bonus: 500, name: '價值包' },
premium: { diamonds: 4000, price: 190, bonus: 1000, name: '豪華包' },
ultimate: { diamonds: 9000, price: 390, bonus: 3000, name: '至尊包' }
};
// 套餐選擇處理
document.querySelectorAll('.package-option').forEach(option => {
option.addEventListener('click', function() {
document.querySelectorAll('.package-option').forEach(opt => opt.classList.remove('selected'));
this.classList.add('selected');
selectedPackage = this.dataset.package;
document.getElementById('nextToPayment').disabled = false;
updateSummary();
});
});
// 支付方式選擇處理
document.querySelectorAll('.payment-method').forEach(method => {
method.addEventListener('click', function() {
document.querySelectorAll('.payment-method').forEach(met => met.classList.remove('selected'));
this.classList.add('selected');
selectedPaymentMethod = this.dataset.method;
document.getElementById('confirmPayment').disabled = false;
});
});
// 更新購買摘要
function updateSummary() {
if (!selectedPackage) return;
const package = packageData[selectedPackage];
document.getElementById('summaryPackage').textContent = package.name;
document.getElementById('summaryDiamonds').textContent = `💎 ${package.diamonds}`;
document.getElementById('summaryBonus').textContent = package.bonus > 0 ? `💎 ${package.bonus}` : '無';
document.getElementById('summaryTotal').textContent = `NT$ ${package.price}`;
}
// 步驟導航
function goToStep(step) {
// 隱藏所有步驟
document.querySelectorAll('.payment-step').forEach(s => s.classList.remove('active'));
// 更新進度指示器
document.querySelectorAll('.step-circle').forEach((circle, index) => {
circle.classList.remove('active', 'completed');
if (index + 1 < step) {
circle.classList.add('completed');
circle.textContent = '✓';
} else if (index + 1 === step) {
circle.classList.add('active');
circle.textContent = index + 1;
} else {
circle.textContent = index + 1;
}
});
// 更新連接器
document.querySelectorAll('.step-connector').forEach((connector, index) => {
connector.classList.remove('active');
if (index + 1 < step) {
connector.classList.add('active');
}
});
// 顯示目標步驟
const steps = ['packageStep', 'paymentStep', 'processingStep', 'successStep'];
document.getElementById(steps[step - 1]).classList.add('active');
currentStep = step;
}
// 按鈕事件處理
document.getElementById('nextToPayment').addEventListener('click', function() {
if (selectedPackage) {
goToStep(2);
}
});
document.getElementById('backToPackage').addEventListener('click', function() {
goToStep(1);
});
document.getElementById('confirmPayment').addEventListener('click', function() {
if (selectedPackage && selectedPaymentMethod) {
goToStep(3);
// 模擬支付處理
setTimeout(() => {
processPaymentSuccess();
}, 3000);
}
});
// 處理支付成功
function processPaymentSuccess() {
const package = packageData[selectedPackage];
const totalDiamonds = package.diamonds + package.bonus;
// 更新成功頁面信息
document.getElementById('successPackage').textContent = package.name;
document.getElementById('successDiamonds').textContent = `💎 ${totalDiamonds}`;
document.getElementById('successTime').textContent = new Date().toLocaleString('zh-TW');
// 更新本地存儲的鑽石數量
const userData = JSON.parse(localStorage.getItem('dramatLingUserData') || '{}');
const currentDiamonds = userData.diamonds || 1250;
userData.diamonds = currentDiamonds + totalDiamonds;
localStorage.setItem('dramatLingUserData', JSON.stringify(userData));
goToStep(4);
}
// 導航函數
function goBack() {
window.location.href = '01-item-shop.html';
}
function goToShop() {
window.location.href = '01-item-shop.html';
}
function goToLearning() {
window.location.href = '../phase1/05-four-stage-learning.html';
}
// 初始化
document.addEventListener('DOMContentLoaded', function() {
// 檢查URL參數是否有預選套餐
const urlParams = new URLSearchParams(window.location.search);
const preselectedPackage = urlParams.get('package');
if (preselectedPackage && packageData[preselectedPackage]) {
const packageElement = document.querySelector(`[data-package="${preselectedPackage}"]`);
if (packageElement) {
packageElement.click();
}
}
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,253 @@
# Common Function Specs 文件分析報告
## 📋 執行摘要
**分析日期**: 2025-09-12
**分析範圍**: `/docs/02_design/function-specs/common/` 資料夾
**文件總數**: 10個文件
**總體評估**: 🟡 **中等品質** - 有明確架構但存在重疊和缺失
---
## 📁 現有文件清單與用途分析
### 🎯 **核心系統規格** (4個文件)
| 文件名 | 用途 | 品質評估 | 大小 |
|--------|------|----------|------|
| **progressive-stage-system.md** | 線性闖關學習系統的完整架構定義 | ✅ 優秀 | 9.9KB |
| **business-rules.md** | 跨平台業務邏輯和規則(命條、付費、鑽石系統) | ✅ 優秀 | 29.7KB |
| **data-models.md** | 所有核心數據實體結構和關係 | ✅ 優秀 | 37.4KB |
| **api-specifications.md** | 完整API接口文檔和端點定義 | ✅ 優秀 | 22.8KB |
### 🤖 **AI系統規格** (3個文件)
| 文件名 | 用途 | 品質評估 | 大小 |
|--------|------|----------|------|
| **ai-algorithm-specs.md** | AI對話分析算法整合規格 | 🟡 中等 | 18.6KB |
| **speaking-evaluation-specs.md** | 五維度口說評分系統詳細規格 | ✅ 優秀 | 3.0KB |
| **pragmatic-analysis-specs.md** | 六維語用分析標準和建議系統 | ✅ 優秀 | 8.8KB |
### 📚 **內容管理** (1個文件)
| 文件名 | 用途 | 品質評估 | 大小 |
|--------|------|----------|------|
| **content-management-specs.md** | 學習內容管理和劇本架構 | 🟡 中等 | 14.0KB |
### 🔧 **系統架構** (1個文件)
| 文件名 | 用途 | 品質評估 | 大小 |
|--------|------|----------|------|
| **system_structure_design.json** | 結構化系統設計和模組定義 | ✅ 優秀 | 111KB |
---
## 🔍 **重複性分析**
### ✅ **無重複問題的文件組合**
- **progressive-stage-system.md****business-rules.md**: 前者定義學習架構,後者定義業務規則,職責清晰
- **speaking-evaluation-specs.md****pragmatic-analysis-specs.md**: 前者評分,後者建議,功能互補
- **data-models.md****api-specifications.md**: 前者定義數據結構,後者定義接口契約,標準分層
### 🟡 **輕微重疊但可接受**
- **ai-algorithm-specs.md** 與其他AI文件: 作為整合規格引用其他模組,角色清晰
- **content-management-specs.md****data-models.md**: 前者專注內容架構,後者涵蓋所有數據模型
### 🚨 **需要注意的潛在重複**
- **system_structure_design.json** 包含所有系統模組定義,與其他文件可能存在信息重複,但作為系統總覽是必要的
---
## 📊 **行業標準對比分析**
### 🏆 **符合行業最佳實踐**
#### ✅ **架構分層清晰**
```
Business Rules → Data Models → API Specs
↓ ↓ ↓
業務邏輯 → 數據結構 → 接口定義
```
#### ✅ **模組化設計**
- 每個文件職責單一且明確
- 支援跨文件引用和依賴管理
- 遵循"關注點分離"原則
#### ✅ **完整性覆蓋**
- **業務層**: business-rules.md
- **應用層**: progressive-stage-system.md, ai-algorithm-specs.md
- **數據層**: data-models.md
- **接口層**: api-specifications.md
- **內容層**: content-management-specs.md
### 🎯 **行業標準參考**
| 標準實踐 | Drama Ling 現狀 | 評估 |
|----------|-----------------|------|
| **業務規則文檔** | ✅ 完整的 business-rules.md | 符合 |
| **數據模型規範** | ✅ 詳細的 data-models.md | 符合 |
| **API契約文檔** | ✅ 完整的 api-specifications.md | 符合 |
| **系統架構圖** | ✅ system_structure_design.json | 符合 |
| **測試規格** | ❌ 缺失 | 需要 |
| **安全規格** | ❌ 缺失 | 需要 |
| **性能規格** | ❌ 缺失 | 需要 |
---
## ⚠️ **缺失分析**
### 🚨 **高優先級缺失**
#### 1. **測試規格文檔** (`testing-specifications.md`)
```yaml
缺失內容:
- 單元測試標準
- 整合測試策略
- E2E測試場景
- 性能測試基準
重要性: 🔴 高
影響: 開發品質保證
```
#### 2. **安全規格文檔** (`security-requirements.md`)
```yaml
缺失內容:
- 數據加密標準
- 用戶隱私保護
- API安全規範
- 漏洞防護策略
重要性: 🔴 高
影響: 系統安全風險
```
#### 3. **錯誤處理規格** (`error-handling-specs.md`)
```yaml
缺失內容:
- 統一錯誤碼定義
- 錯誤回復策略
- 用戶友好錯誤訊息
- 日誌記錄標準
重要性: 🟡 中
影響: 用戶體驗和維護性
```
### 🟡 **中優先級缺失**
#### 4. **性能規格文檔** (`performance-standards.md`)
```yaml
缺失內容:
- 響應時間標準
- 併發處理能力
- 資源使用限制
- 擴展性要求
重要性: 🟡 中
影響: 系統性能表現
```
#### 5. **國際化規格** (`internationalization-specs.md`)
```yaml
缺失內容:
- 多語言支援策略
- 本地化內容管理
- 時區和貨幣處理
- 文化適應性設計
重要性: 🟡 中
影響: 全球化擴展
```
### 🟢 **低優先級缺失**
#### 6. **監控與日誌規格** (`monitoring-logging-specs.md`)
#### 7. **備份與恢復規格** (`backup-recovery-specs.md`)
#### 8. **第三方整合規格** (`third-party-integration-specs.md`)
---
## 🏗️ **結構優化建議**
### 📁 **建議的資料夾重組結構**
```
docs/02_design/function-specs/common/
├── 01_core-system/ # 核心系統規格
│ ├── progressive-stage-system.md
│ ├── business-rules.md
│ ├── data-models.md
│ └── system_structure_design.json
├── 02_api-interfaces/ # 接口規格
│ ├── api-specifications.md
│ ├── error-handling-specs.md # 新增
│ └── security-requirements.md # 新增
├── 03_ai-systems/ # AI系統規格
│ ├── ai-algorithm-specs.md
│ ├── speaking-evaluation-specs.md
│ └── pragmatic-analysis-specs.md
├── 04_content-management/ # 內容管理
│ └── content-management-specs.md
├── 05_quality-assurance/ # 品質保證
│ ├── testing-specifications.md # 新增
│ ├── performance-standards.md # 新增
│ └── monitoring-logging-specs.md # 新增
└── 06_localization/ # 本地化
└── internationalization-specs.md # 新增
```
### 🔄 **遷移優先順序**
1. **Phase 1 (立即)**: 創建缺失的高優先級文檔
2. **Phase 2 (短期)**: 重組資料夾結構,保持向後兼容
3. **Phase 3 (長期)**: 添加中低優先級規格文檔
---
## 📈 **品質評估總結**
### 🎯 **強項**
- ✅ **核心業務邏輯完整**: business-rules.md 和 progressive-stage-system.md 提供完整的系統規則
- ✅ **數據架構清晰**: data-models.md 定義完整的數據關係
- ✅ **API設計規範**: api-specifications.md 提供完整的接口契約
- ✅ **AI系統專業**: 口說評分和語用分析規格詳細且專業
### ⚠️ **需要改善**
- 🔶 **缺乏品質保證規格**: 測試、安全、性能規格缺失
- 🔶 **錯誤處理不統一**: 缺乏統一的錯誤處理策略
- 🔶 **監控機制不足**: 缺乏運營監控和日誌管理規格
### 📊 **總體分數**
```
內容完整性: ⭐⭐⭐⭐⚪ (4/5)
結構組織性: ⭐⭐⭐⚪⚪ (3/5)
專業標準性: ⭐⭐⭐⭐⚪ (4/5)
維護便利性: ⭐⭐⭐⚪⚪ (3/5)
總體評分: 70/100 (🟡 中等品質)
```
---
## 🚀 **行動建議**
### 🔴 **立即行動 (本週)**
1. **創建 `security-requirements.md`** - 定義基本安全標準
2. **創建 `testing-specifications.md`** - 建立測試框架和標準
3. **創建 `error-handling-specs.md`** - 統一錯誤處理策略
### 🟡 **短期計劃 (本月)**
1. **重組資料夾結構** - 按照建議的6大分類重組
2. **更新文檔間引用** - 確保所有交叉引用正確
3. **建立文檔維護流程** - 定期更新和審查機制
### 🟢 **長期規劃 (三個月)**
1. **完善品質保證體系** - 添加性能、監控等規格
2. **國際化準備** - 創建本地化和國際化規格
3. **建立文檔自動化** - 使用工具自動檢查文檔一致性
---
**報告結論**: Drama Ling 的 Common Function Specs 具有良好的核心基礎,業務邏輯和數據架構清晰完整。主要改善方向是補強品質保證相關規格,並優化文檔組織結構以提升維護效率。
---
**分析者**: Claude AI
**審查建議**: 建議產品團隊基於此報告制定文檔改善計劃,優先處理安全和測試規格的缺失問題。

View File

@ -0,0 +1,483 @@
# Drama Ling UI/UX 設計完整計劃
**制定日期**: 2025-09-12
**計劃版本**: v1.0
**基於架構**: function-specs v3.0 共用模組架構
**設計規範**: ui-ux-guidelines.md v2.0
## 🎯 計劃概述
基於 `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs` 的完整規格文件設計所有頁面的UI/UX原型。所有設計將嚴格遵循 `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/ui-ux-guidelines.md` 的設計規範,並在規範不足時先補充規範再進行設計。
## 📋 第一階段UI/UX規範完善
### 1.1 現有規範分析與補充
**目標**: 確保UI/UX規範涵蓋所有功能設計需求
**參考文件**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/ui-ux-guidelines.md` (主要規範)
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/business-rules.md` (業務規則)
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/progressive-stage-system.md` (系統架構)
**需補充的設計規範**:
#### 1.1.1 組件規範補充 ✅ (待驗證)
- [ ] **學習地圖組件**: 13階段×20劇本的地圖視覺化設計
- 引用: `progressive-stage-system.md` - 線性闖關架構
- 設計要素: 六角形關卡節點、連接線、狀態顏色、進度動畫
- [ ] **命條系統組件**: 生命點數的視覺表現
- 引用: `business-rules.md` - 命條系統規則
- 設計要素: 心形圖標、數量顯示、恢復計時器、不足警告
- [ ] **道具商店組件**: 鑽石和道具的購買界面
- 引用: `business-rules.md` - 道具商店系統
- 設計要素: 商品卡片、價格標籤、購買確認、餘額顯示
#### 1.1.2 互動設計規範補充
- [ ] **語音輸入設計**: 語音優先的交互模式
- 引用: `ai-algorithm-specs.md` - 語音處理規格
- 設計要素: 語音波形、錄音狀態、即時轉換反饋
- [ ] **AI輔助界面**: 智能提示和建議的展示方式
- 引用: `ai-algorithm-specs.md` - AI算法規格
- 設計要素: 對話氣泡、建議卡片、漸進式引導
- [ ] **評分反饋系統**: 即時評分和建議的視覺化
- 引用: `speaking-evaluation-specs.md` - 口說評分系統
- 設計要素: 分數動畫、雷達圖、改進建議
#### 1.1.3 平台適配規範補充
- [ ] **響應式設計規則**: Mobile和Web端的適配標準
- 引用: `platform-feature-mapping.md` - 平台對應關係
- 設計要素: 斷點設定、組件縮放、交互差異
- [ ] **Web端專屬組件**: 桌面環境的特殊組件
- 引用: `web/README.md` - Web端特色功能
- 設計要素: 鍵盤快捷鍵、多視窗、批量操作
**輸出物**:
- `ui-ux-guidelines.md` 的完整更新版本
- 新增組件設計規範文檔
- 設計系統組件庫更新
### 1.2 設計系統建立
**目標**: 建立可重用的設計系統和組件庫
**工作項目**:
- [ ] **色彩系統**: 完整的色彩變數定義
- [ ] **字體系統**: 響應式字體和行高規範
- [ ] **間距系統**: 統一的空間和佈局規則
- [ ] **組件庫**: 可重用的UI組件集合
- [ ] **圖標系統**: 學習情境專用的圖標設計
**參考文件**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/dramaling-ui.css`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/ui-showcase.html`
## 📱 第二階段Mobile端頁面設計
### 2.1 核心學習功能頁面
#### 2.1.1 情境對話系統 (優先級: P0)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/01_situational-dialogue-mobile.md`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/ai-algorithm-specs.md`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/speaking-evaluation-specs.md`
**需設計的頁面**:
- [ ] `UI_Dialogue_Practice_Main` - 情境對話練習主界面
- 語音輸入界面 (參考: ai-algorithm-specs.md 語音處理)
- 即時AI反饋顯示 (參考: ai-algorithm-specs.md AI評估系統)
- 劇情任務和詞彙任務雙重可視化
- 300秒限時挑戰計時器
- [ ] `UI_Dialogue_Character_Selection` - 角色選擇頁面
- [ ] `UI_Dialogue_Scene_Setting` - 場景設定頁面
- [ ] `UI_AI_Assistance_Panel` - AI輔助功能面板
- 回覆提示道具使用界面
- 語法即時檢測顯示
- [ ] `UI_Dialogue_Results` - 對話練習結果頁面
- 口說評分五維雷達圖 (參考: speaking-evaluation-specs.md)
- 語用分析六維評估 (參考: pragmatic-analysis-specs.md)
#### 2.1.2 詞彙學習系統 (優先級: P0)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/02_vocabulary-learning-mobile.md`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/progressive-stage-system.md`
**需設計的頁面**:
- [ ] `UI_Vocab_Learning_Enhanced` - 多媒體詞彙學習主界面
- 詞彙展示 (音標、定義、例句)
- 雙語音頻系統 (標準速度/慢速)
- 智慧詞彙標註 (Source + Example)
- 視覺輔助學習 (例句配圖)
- [ ] `UI_Vocab_Choice_Practice` - 詞彙選擇練習頁面
- [ ] `UI_Vocab_Fluency_Results` - 流暢度練習綜合結果
- [ ] `UI_Vocab_Review_System` - 間隔複習系統界面
#### 2.1.3 學習地圖系統 (優先級: P0)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/03_learning-map-mobile.md`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/progressive-stage-system.md`
**需設計的頁面**:
- [ ] `UI_Level_Map` - 學習地圖主畫面 (線性闖關版)
- 13階段×20劇本的地圖視覺化
- 四關進度指示器 (詞彙學習→詞彙熟悉→口說練習→情境對話)
- 關卡狀態管理 (🔒鎖定/⏳可進行/🔄進行中/✅已完成)
- [ ] `UI_Current_Level_Info` - 當前可進行關卡資訊面板
- [ ] `UI_Level_Progress_Detail` - 關卡進度詳情頁面
- [ ] `UI_Stage_Overview` - 階段總覽和劇本選擇
- [ ] `UI_Level_Locked_Modal` - 關卡鎖定提示彈窗
### 2.2 商業功能頁面
#### 2.2.1 道具商店系統 (優先級: P1)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/04_item-shop-mobile.md`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/business-rules.md`
**需設計的頁面**:
- [ ] `UI_Shop_Categories` - 道具商店分類主頁面
- 鑽石購買區 (5個價格套餐)
- 學習輔助道具區 (回覆提示、補命、加時)
- 限時挑戰道具區 (時間暫停、時間加成)
- [ ] `UI_Diamond_Purchase` - 鑽石購買頁面
- [ ] `UI_Item_Details` - 單一道具詳情頁面
- [ ] `UI_Shop_Item_Confirm` - 道具購買確認彈窗
- [ ] `UI_Cost_Confirm_Popup` - 成本確認彈窗 (口說練習特別關卡)
- [ ] `UI_Insufficient_Resources` - 資源不足提示頁面
- [ ] `UI_Purchase_Success` - 購買成功頁面
#### 2.2.2 用戶認證系統 (優先級: P1)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/05_user-authentication-mobile.md`
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/business-rules.md`
**需設計的頁面**:
- [ ] `UI_Login_Main` - 登入主頁面
- Email + 密碼登入
- 第三方登入 (Google、Apple)
- 記住登入功能
- [ ] `UI_SignUp_Main` - 註冊主頁面
- [ ] `UI_PasswordReset_Form` - 密碼重設頁面
- [ ] `UI_Profile_Settings` - 用戶資料設定頁面
- [ ] `UI_Subscription_Plans` - 訂閱方案頁面
- 7天免費體驗
- 月費/年費訂閱選項
- [ ] `UI_Account_Security` - 帳戶安全設定頁面
### 2.3 支援功能頁面
#### 2.3.1 系統通知和反饋 (優先級: P2)
**需設計的頁面**:
- [ ] `UI_Achievement_Notification` - 成就通知彈窗
- [ ] `UI_Level_Complete_Celebration` - 關卡完成慶祝頁面
- [ ] `UI_Daily_Streak_Reward` - 每日連續學習獎勵
- [ ] `UI_System_Maintenance` - 系統維護提示頁面
- [ ] `UI_Network_Error` - 網路錯誤處理頁面
#### 2.3.2 學習分析和報告 (優先級: P2)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/data-models.md`
**需設計的頁面**:
- [ ] `UI_Learning_Analytics` - 學習分析報告頁面
- [ ] `UI_Progress_Statistics` - 進度統計頁面
- [ ] `UI_Vocabulary_Review_Schedule` - 詞彙複習排程
- [ ] `UI_Speaking_Improvement_Report` - 口說能力改善報告
## 💻 第三階段Web端頁面設計
### 3.1 核心功能Web端適配
#### 3.1.1 詞彙學習系統 (Web版)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/vocabulary-learning-web.md`
**需設計的頁面**:
- [ ] `Page_Vocab_Learning_W` - Web版詞彙學習主頁面
- 大螢幕多詞彙並列展示
- 鍵盤快捷鍵支援
- 批量學習進度管理
- [ ] `Page_Vocab_Batch_Practice_W` - 批量詞彙練習頁面
- [ ] `Page_Vocab_Analytics_W` - 詞彙學習分析頁面
#### 3.1.2 情境對話系統 (Web版)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/situational-dialogue-web.md`
**需設計的頁面**:
- [ ] `Page_Dialogue_Practice_W` - Web版情境對話練習頁面
- 桌面端語音輸入優化
- 多螢幕支援
- 詳細的即時分析面板
- [ ] `Page_Dialogue_History_W` - 對話練習歷史記錄
- [ ] `Page_Advanced_Analytics_W` - 進階對話分析頁面
#### 3.1.3 學習地圖系統 (Web版)
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/learning-map-web.md`
**需設計的頁面**:
- [ ] `Page_Learning_Map_W` - Web版學習地圖主頁面
- 完整的13階段×20劇本視覺化
- 滑鼠懸停詳細資訊
- 鍵盤導航支援
- [ ] `Page_Stage_Management_W` - 階段管理頁面
- [ ] `Page_Batch_Progress_W` - 批量進度管理頁面
### 3.2 Web端專屬功能
#### 3.2.1 企業級功能
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/user-authentication-web.md`
**需設計的頁面**:
- [ ] `Page_SSO_Login_W` - 企業單點登入頁面
- [ ] `Page_Two_Factor_Auth_W` - 雙因素認證設定頁面
- [ ] `Page_Session_Management_W` - 會話管理頁面
- [ ] `Page_Admin_Dashboard_W` - 管理員儀表板
#### 3.2.2 高級商店功能
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/item-shop-web.md`
**需設計的頁面**:
- [ ] `Page_Shop_Main_W` - Web版道具商店主頁面
- 大螢幕完整商店展示
- 批量購買支援
- 價格比較工具
- [ ] `Page_Diamond_Purchase_W` - Web版鑽石購買頁面
- [ ] `Page_Price_Comparison_W` - 價格比較分析頁面
- [ ] `Page_Bulk_Purchase_W` - 批量購買頁面
- [ ] `Page_Payment_Methods_W` - 支付方式管理頁面
- [ ] `Page_Purchase_History_W` - 購買歷史頁面
## 🧩 第四階段:共用組件設計
### 4.1 核心功能組件
**規格參考**:
- `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/business-rules.md`
**需設計的組件**:
- [ ] `Component_LifePoints_Display` - 命條顯示組件
- 心形生命值圖標
- 數量和恢復時間顯示
- 不足時的警告狀態
- [ ] `Component_Diamond_Balance` - 鑽石餘額顯示組件
- [ ] `Component_Progress_Indicator` - 學習進度指示器
- [ ] `Component_Achievement_Badge` - 成就徽章組件
- [ ] `Component_Star_Rating` - 星級評分組件
### 4.2 互動功能組件
**需設計的組件**:
- [ ] `Component_Voice_Input` - 語音輸入組件
- 錄音狀態指示
- 語音波形顯示
- 即時轉換反饋
- [ ] `Component_AI_Suggestion` - AI建議組件
- [ ] `Component_Timer_Display` - 計時器組件
- [ ] `Component_Score_Animation` - 分數動畫組件
- [ ] `Component_Celebration_Effect` - 慶祝動畫效果
### 4.3 購買流程組件
**需設計的組件**:
- [ ] `Modal_Purchase_Confirm` - 購買確認模態視窗
- 商品資訊展示
- 支付方式選擇
- 安全驗證流程
- [ ] `Modal_Payment_Processing` - 支付處理模態視窗
- [ ] `Component_Price_Tag` - 價格標籤組件
- [ ] `Component_Discount_Badge` - 折扣標籤組件
## 🎨 第五階段:視覺設計精修
### 5.1 品牌視覺一致性
**工作項目**:
- [ ] **圖標系統設計**: 學習情境專用圖標集合
- [ ] **插圖系統設計**: 學習場景插圖和角色設計
- [ ] **動畫效果設計**: 學習回饋和成就慶祝動畫
- [ ] **色彩應用指南**: 各功能區域的色彩使用規範
### 5.2 用戶體驗優化
**工作項目**:
- [ ] **微互動設計**: 按鈕點擊、狀態切換的細微動畫
- [ ] **載入狀態設計**: 各種載入和等待狀態的友善提示
- [ ] **錯誤處理設計**: 友善的錯誤提示和解決方案引導
- [ ] **無障礙設計**: 色彩對比、鍵盤導航、螢幕閱讀器支援
## 📊 第六階段:原型開發與驗證
### 6.1 高保真原型開發
**工作項目**:
- [ ] **Mobile端原型**: 完整的移動端交互原型
- [ ] **Web端原型**: 桌面端功能完整原型
- [ ] **響應式驗證**: 各種螢幕尺寸的適配測試
- [ ] **交互流程驗證**: 完整用戶旅程的原型測試
### 6.2 設計系統文檔
**工作項目**:
- [ ] **組件庫文檔**: 完整的組件使用說明
- [ ] **設計規範手冊**: 設計師和開發者使用指南
- [ ] **品牌指南**: 視覺識別和品牌應用規範
- [ ] **無障礙設計指南**: WCAG 2.1 AA合規指南
## 🔧 執行方法與工具
### 工具選擇
- **設計工具**: Figma (主要), Adobe XD (輔助)
- **原型工具**: Figma Prototype, Principle
- **協作工具**: Figma Team, Abstract (版本控制)
- **開發交接**: Figma Dev Mode, Zeplin
### 版本控制
- **設計檔案**: 統一命名規範和版本控制
- **組件庫**: 版本化管理,向下相容性考量
- **規範文檔**: Git版本控制變更記錄追蹤
## ⏰ 時程規劃
### 第一階段UI/UX規範完善 (1週)
- 天數 1-2: 現有規範分析
- 天數 3-5: 補充設計規範
- 天數 6-7: 設計系統建立
### 第二階段Mobile端設計 (3週)
- 週1: 核心學習功能頁面設計
- 週2: 商業功能頁面設計
- 週3: 支援功能頁面設計
### 第三階段Web端設計 (2週)
- 週1: 核心功能Web端適配
- 週2: Web端專屬功能設計
### 第四階段:組件設計 (1週)
- 天數 1-3: 核心功能組件
- 天數 4-5: 互動功能組件
- 天數 6-7: 購買流程組件
### 第五階段:視覺精修 (1週)
- 天數 1-4: 品牌視覺一致性
- 天數 5-7: 用戶體驗優化
### 第六階段:原型驗證 (1週)
- 天數 1-4: 高保真原型開發
- 天數 5-7: 設計系統文檔
**總計**: 9週 (約2個月)
## 🎯 成功指標
### 設計品質指標
- [ ] **規範完整度**: UI/UX規範涵蓋所有功能設計需求
- [ ] **設計一致性**: 跨平台設計元素一致性達95%以上
- [ ] **無障礙合規**: WCAG 2.1 AA標準100%合規
- [ ] **響應式覆蓋**: 支援5種以上主要螢幕尺寸
### 用戶體驗指標
- [ ] **學習效率**: 用戶完成學習任務的時間減少20%
- [ ] **互動滿意度**: 用戶界面滿意度評分8分以上(10分制)
- [ ] **轉換效率**: 付費轉換漏斗各環節流失率低於15%
- [ ] **錯誤發生率**: 用戶操作錯誤率低於5%
### 開發支援指標
- [ ] **設計交接效率**: 設計到開發的交接時間減少50%
- [ ] **組件重用率**: 設計組件重用率達80%以上
- [ ] **開發一致性**: 開發實現與設計稿一致性達95%以上
- [ ] **維護效率**: 設計變更的維護時間減少60%
## 📋 風險管控
### 設計風險
- **風險**: 規範更新導致已完成設計需要大幅修改
- **應對**: 分階段驗證,及早發現問題
- **風險**: 跨平台設計一致性難以維持
- **應對**: 建立嚴格的設計系統和組件庫
### 時程風險
- **風險**: 設計複雜度超出預期時程
- **應對**: 設定優先級,核心功能優先完成
- **風險**: 規格文件理解偏差導致返工
- **應對**: 定期與產品團隊對齊確認
### 品質風險
- **風險**: 用戶體驗測試反饋需要重大修改
- **應對**: 早期進行用戶研究和可用性測試
- **風險**: 無障礙設計要求影響視覺效果
- **應對**: 從設計初期就考慮無障礙需求
## 📚 關鍵參考文件清單
### 核心規格文件 (必讀)
1. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/README.md` - 總覽和架構說明
2. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/business-rules.md` - 共同業務規則
3. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/progressive-stage-system.md` - 線性闖關學習系統
4. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/platform-feature-mapping.md` - 平台功能對應表
### Mobile端規格文件
1. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/01_situational-dialogue-mobile.md`
2. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/02_vocabulary-learning-mobile.md`
3. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/03_learning-map-mobile.md`
4. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/04_item-shop-mobile.md`
5. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/mobile/05_user-authentication-mobile.md`
### Web端規格文件
1. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/vocabulary-learning-web.md`
2. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/situational-dialogue-web.md`
3. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/learning-map-web.md`
4. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/item-shop-web.md`
5. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/web/user-authentication-web.md`
### 共用模組規格文件
1. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/ai-algorithm-specs.md` - AI算法規格
2. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/speaking-evaluation-specs.md` - 口說評分系統
3. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/pragmatic-analysis-specs.md` - 語用分析系統
4. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/content-management-specs.md` - 內容管理規格
5. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/data-models.md` - 數據模型
6. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/function-specs/common/api-specifications.md` - API規格
### UI/UX設計規範文件
1. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/ui-ux-guidelines.md` - 主要設計規範
2. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/dramaling-ui.css` - CSS設計系統
3. `/Users/jettcheng1018/code/dramaling-app/docs/02_design/ui-ux/ui-showcase.html` - 組件展示
## 📞 溝通與協作
### 定期檢查點
- **每週設計評審**: 與產品經理和開發團隊的設計進度檢視
- **雙週用戶測試**: 關鍵功能的用戶可用性測試
- **月度設計總結**: 設計成果和問題總結報告
### 協作方式
- **設計協作**: Figma團隊協作即時同步設計進展
- **跨團隊溝通**: Slack頻道重要決策留存記錄
- **文檔協作**: 設計規範和說明的協作編輯
---
**計劃制定者**: Claude AI
**審核狀態**: 待產品團隊確認
**下次更新**: 根據第一階段執行結果調整
**重要提醒**:
1. 所有設計必須嚴格遵循引用的規格文件內容
2. UI/UX規範不足時必須先補充規範再進行設計
3. 跨平台一致性是設計成功的關鍵指標
4. 用戶學習效果始終是設計決策的第一優先考量

View File

@ -4,7 +4,8 @@
**文檔名稱**: Drama Ling 設計雛形畫面制作計劃
**建立日期**: 2025-09-11
**版本**: v1.0
**最後更新**: 2025-09-12
**版本**: v1.1 - 更新詞彙學習系統和文件路徑
**目標**: 基於完整功能規格創建可視化雛形畫面,讓用戶能直觀體驗系統功能和流程
## 🎯 計劃目標與範圍
@ -42,7 +43,7 @@
- **訂閱服務**: 免費試用、付費方案、特權功能
### 🎨 設計系統規範
**出處**: `/docs/02_design/ui-ux/dramaling-ui.css` & `/docs/02_design/function-specs/common/ui-ux-guidelines.md`
**出處**: `/docs/02_design/ui-ux/dramaling-ui.css` & `/docs/02_design/ui-ux/ui-ux-guidelines.md`
- **設計語言**: 色彩系統、字體規範、組件樣式
- **Duolingo風格**: 厚實3D按鈕、12px圓角、下壓動畫效果
- **響應式佈局**: 桌面和移動端的適配方案
@ -89,9 +90,10 @@
**基於**: `UI_Vocab_Level1_Learning`, `UI_Vocab_Level2_Mastery`, `UI_Vocab_Level2Plus_Speaking`, `UI_Dialogue_Practice_Main`
##### 第1關詞彙學習畫面
- **詞彙介紹界面** - 詞彙卡片設計、發音按鈕、示意圖展示
- **選擇題測驗** - 4選1界面、即時反饋、錯誤重測機制
- **進度指示** - 5個詞彙的學習進度條
- **沉浸式詞彙瀏覽** - 多媒體詞彙展示,包含音標、定義、音檔
- **雙語境展示** - Source句子(真實語境) + Example句子(教學例句)
- **自由導航** - 用戶可自由前後瀏覽,無測試壓力的純學習體驗
- **直接詞彙標註** - 使用originalHighlight/exampleHighlight進行精確標註
##### 第2關詞彙熟悉畫面
- **句子重組界面** - 拖拽操作、元素排列、提示系統
@ -166,25 +168,16 @@
### 文件組織結構
```
prototype-screens/
├── assets/ # 資源文件
│ ├── css/
│ │ ├── dramaling-ui.css # 現有設計系統
│ │ └── prototype-theme.css # 雛形專用樣式
│ ├── js/
│ │ ├── prototype-core.js # 核心交互邏輯
│ │ └── mock-data.js # 模擬數據
docs/02_design/prototypes/
├── assets/ # 資源文件
│ ├── css/ # 樣式表
│ ├── js/ # JavaScript文件
│ └── images/ # 圖片資源
├── components/ # 可重用組件庫
├── screens/ # 雛形畫面
│ ├── 01_authentication/ # 認證相關畫面
│ ├── 02_learning_core/ # 核心學習畫面
│ ├── 03_business/ # 商業功能畫面
│ ├── 04_social/ # 社交功能畫面
│ └── 05_system/ # 系統功能畫面
├── flows/ # 流程演示
│ ├── onboarding-flow.html # 新手引導流程
│ ├── learning-flow.html # 學習流程演示
│ └── purchase-flow.html # 購買流程演示
│ ├── phase1/ # 第一階段:核心學習流程
│ ├── phase2/ # 第二階段:商業功能與輔助系統
│ └── phase3/ # 第三階段:社交與分析功能
└── index.html # 主導覽頁面
```
@ -270,11 +263,22 @@ prototype-screens/
## 📊 預期成果與交付物
### 主要交付物
1. **完整雛形系統** - 涵蓋所有主要功能的可互動原型
1. **完整雛形系統** - 涵蓋所有主要功能的可互動原型 (`/docs/02_design/prototypes/`)
2. **流程演示文檔** - 主要用戶旅程的視覺演示
3. **設計規範文檔** - 雛形制作中確立的設計標準
4. **技術實現文檔** - 前端實現的技術方案和代碼結構
### 原型檔案結構
```
docs/02_design/prototypes/
├── screens/ # 具體功能畫面
│ ├── phase1/ # 第一階段:核心學習流程
│ ├── phase2/ # 第二階段:商業功能與輔助系統
│ └── phase3/ # 第三階段:社交與分析功能
├── components/ # 可重用組件庫
└── assets/ # 共用資源文件
```
### 驗證目標
1. **業務邏輯驗證** - 功能規格的視覺化確認
2. **用戶體驗驗證** - 設計決策的可用性測試
@ -295,11 +299,69 @@ prototype-screens/
3. **第一個畫面** - 從登入頁面開始制作第一個雛形
4. **迭代優化** - 基於實際效果調整設計和技術方案
## 📋 完整頁面設計清單 (基於function-specs)
### 🎯 **Mobile端功能頁面** (基於 `/mobile/` 規格)
1. **用戶認證系統** - 登入、註冊、社交登入 (`05_user-authentication-mobile.md`)
2. **情境對話功能** - AI對話、評分反饋 (`01_situational-dialogue-mobile.md`)
3. **詞彙學習系統** - 沉浸式學習體驗 (`02_vocabulary-learning-mobile.md`) ✅
4. **學習地圖** - 關卡選擇、進度追蹤 (`03_learning-map-mobile.md`)
5. **道具商店** - 商品購買、付費流程 (`04_item-shop-mobile.md`) ✅
### 🖥️ **Web端功能頁面** (基於 `/web/` 規格)
1. **用戶認證系統** - 桌面端登入體驗 (`user-authentication-web.md`)
2. **情境對話功能** - 大螢幕對話界面 (`situational-dialogue-web.md`)
3. **詞彙學習系統** - 桌面端學習體驗 (`vocabulary-learning-web.md`)
4. **學習地圖** - 桌面端地圖導覽 (`learning-map-web.md`)
5. **道具商店** - 桌面端購買體驗 (`item-shop-web.md`)
### 🔧 **Common功能系統** (基於 `/common/` 規格)
1. **AI算法展示** - 三維評分系統視覺化 (`ai-algorithm-specs.md`)
2. **口說評分界面** - 五維度評分展示 (`speaking-evaluation-specs.md`)
3. **語用分析界面** - 六維語用建議系統 (`pragmatic-analysis-specs.md`)
4. **進度追蹤系統** - 線性闖關進度管理 (`progressive-stage-system.md`)
5. **內容管理界面** - 劇本、詞彙管理 (`content-management-specs.md`)
### 🔄 **整合功能頁面** (基於綜合規格)
1. **完整用戶流程** - 端到端學習旅程 (`comprehensive-user-flows-with-ui.md`)
2. **平台功能映射** - 跨平台功能展示 (`platform-feature-mapping.md`)
## 🎨 **設計執行策略**
### Phase 1: UI/UX規範完善 ⭐ **當前重點**
- **檢查現有規範** - 分析 `/ui-ux/ui-ux-guidelines.md` 完整性
- **補充缺失規範** - 為缺少的組件添加設計規範
- **統一設計語言** - 確保所有頁面遵循一致標準
### Phase 2: 核心學習系統頁面
- **詞彙學習系統** - 沉浸式多媒體體驗 ✅
- **情境對話系統** - AI互動與評分展示
- **進度管理系統** - 四關闖關視覺化
- **學習地圖** - 13階段×20劇本導覽
### Phase 3: 商業與輔助系統
- **用戶認證流程** - 登入註冊完整體驗
- **道具商店系統** - 完整購買生態 ✅
- **命條與獎勵** - 遊戲化機制展示 ✅
- **廣告與挑戰** - 額外收益機制 ✅
### Phase 4: AI智能系統
- **口說評分界面** - 五維度專業評估
- **語用分析展示** - 六維語用建議
- **AI算法可視化** - 三維評估系統
- **即時反饋系統** - 智能學習輔助
### Phase 5: 社交與分析
- **社交排行榜** - 好友競爭系統
- **學習分析** - 個人進度儀表板
- **成就系統** - 徽章收集展示
- **數據同步** - 跨平台進度管理
### 協作機制
1. **每日進度更新** - 每天匯報制作進度和遇到的問題
2. **週度檢查** - 每週進行設計品質和技術實現檢查
3. **用戶反饋收集** - 定期收集用戶對雛形效果的反饋
4. **迭代改進** - 根據反饋持續優化雛形質量
1. **規範優先** - 每個頁面設計前先完善UI/UX規範
2. **迭代設計** - 快速原型→測試→優化的循環
3. **跨平台一致** - 確保mobile/web體驗的一致性
4. **功能完整** - 每個頁面都要體現完整的用戶流程
---

View File

@ -0,0 +1,959 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling - 登入</title>
<style>
:root {
/* Premium Design System V3.0 */
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
--success-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
--warning-gradient: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
--error-gradient: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
--bg-primary: #0f0f23;
--bg-secondary: #1a1a2e;
--bg-card: rgba(255, 255, 255, 0.1);
--bg-input: rgba(255, 255, 255, 0.08);
--text-primary: #ffffff;
--text-secondary: #b8b8d4;
--text-muted: #8a8aa8;
--border-radius: 16px;
--border-radius-lg: 24px;
--shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.4);
--shadow-xl: 0 25px 80px rgba(0, 0, 0, 0.6);
--font-family: 'SF Pro Display', system-ui, -apple-system, sans-serif;
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--font-size-xl: 1.25rem;
--font-size-2xl: 1.5rem;
--font-size-3xl: 1.875rem;
--transition-all: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-family);
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
overflow-x: hidden;
}
.login-container {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 2rem 1rem;
position: relative;
}
.background-animation {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background: var(--primary-gradient);
opacity: 0.1;
}
.background-animation::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at 20% 20%, rgba(102, 126, 234, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 80%, rgba(118, 75, 162, 0.3) 0%, transparent 50%),
radial-gradient(circle at 40% 60%, rgba(240, 147, 251, 0.2) 0%, transparent 50%);
animation: backgroundPulse 6s ease-in-out infinite alternate;
}
@keyframes backgroundPulse {
from { opacity: 0.3; transform: scale(1); }
to { opacity: 0.6; transform: scale(1.1); }
}
.login-card {
background: var(--bg-card);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--border-radius-lg);
padding: 2.5rem;
width: 100%;
max-width: 400px;
box-shadow: var(--shadow-xl);
animation: cardSlideIn 0.6s ease-out;
position: relative;
overflow: hidden;
}
.login-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 2px;
background: var(--primary-gradient);
}
@keyframes cardSlideIn {
from {
opacity: 0;
transform: translateY(40px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.app-logo {
text-align: center;
margin-bottom: 2rem;
}
.logo-icon {
width: 80px;
height: 80px;
background: var(--primary-gradient);
border-radius: 50%;
margin: 0 auto 1rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
font-weight: bold;
box-shadow: var(--shadow-lg);
animation: logoFloat 3s ease-in-out infinite;
}
@keyframes logoFloat {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
.app-title {
font-size: var(--font-size-2xl);
font-weight: 700;
background: var(--primary-gradient);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 0.5rem;
}
.app-subtitle {
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.login-form {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.form-group {
position: relative;
}
.form-label {
display: block;
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--text-secondary);
margin-bottom: 0.5rem;
}
.form-input {
width: 100%;
padding: 1rem 1.25rem;
background: var(--bg-input);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--border-radius);
color: var(--text-primary);
font-size: var(--font-size-base);
transition: var(--transition-all);
backdrop-filter: blur(10px);
}
.form-input:focus {
outline: none;
border-color: rgba(102, 126, 234, 0.5);
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
background: rgba(255, 255, 255, 0.12);
}
.form-input::placeholder {
color: var(--text-muted);
}
.password-toggle {
position: absolute;
right: 1rem;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 1.2rem;
transition: var(--transition-all);
}
.password-toggle:hover {
color: var(--text-primary);
}
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
font-size: var(--font-size-sm);
}
.remember-me {
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--text-secondary);
}
.custom-checkbox {
width: 18px;
height: 18px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
background: transparent;
cursor: pointer;
transition: var(--transition-all);
position: relative;
}
.custom-checkbox.checked {
background: var(--primary-gradient);
border-color: transparent;
}
.custom-checkbox.checked::after {
content: '✓';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 12px;
font-weight: bold;
}
.forgot-password {
color: var(--text-secondary);
text-decoration: none;
transition: var(--transition-all);
}
.forgot-password:hover {
color: var(--text-primary);
text-decoration: underline;
}
.login-button {
background: var(--primary-gradient);
border: none;
border-radius: var(--border-radius);
padding: 1rem 2rem;
color: white;
font-size: var(--font-size-base);
font-weight: 600;
cursor: pointer;
transition: var(--transition-all);
box-shadow: var(--shadow-lg);
position: relative;
overflow: hidden;
}
.login-button:hover {
transform: translateY(-2px);
box-shadow: 0 25px 80px rgba(102, 126, 234, 0.4);
}
.login-button:active {
transform: translateY(0);
}
.login-button.loading {
pointer-events: none;
}
.login-button .spinner {
display: none;
width: 20px;
height: 20px;
border: 2px solid transparent;
border-top: 2px solid white;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 0.5rem;
}
.login-button.loading .spinner {
display: inline-block;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.divider {
text-align: center;
margin: 1.5rem 0;
position: relative;
}
.divider::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: rgba(255, 255, 255, 0.1);
}
.divider span {
background: var(--bg-secondary);
padding: 0 1rem;
color: var(--text-muted);
font-size: var(--font-size-sm);
}
.social-login {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.social-button {
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
padding: 0.875rem 1rem;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: var(--border-radius);
background: var(--bg-input);
color: var(--text-primary);
text-decoration: none;
font-weight: 500;
transition: var(--transition-all);
backdrop-filter: blur(10px);
}
.social-button:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
}
.social-icon {
width: 20px;
height: 20px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
.google-icon { background: #4285f4; color: white; }
.facebook-icon { background: #1877f2; color: white; }
.apple-icon { background: #000; color: white; }
.register-link {
text-align: center;
margin-top: 1.5rem;
color: var(--text-secondary);
font-size: var(--font-size-sm);
}
.register-link a {
color: var(--text-primary);
text-decoration: none;
font-weight: 600;
background: var(--primary-gradient);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.register-link a:hover {
text-decoration: underline;
}
.guest-mode {
text-align: center;
margin-top: 1rem;
}
.guest-button {
color: var(--text-muted);
text-decoration: none;
font-size: var(--font-size-sm);
padding: 0.5rem 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: var(--border-radius);
transition: var(--transition-all);
}
.guest-button:hover {
color: var(--text-secondary);
border-color: rgba(255, 255, 255, 0.2);
}
.error-message {
color: #fa709a;
font-size: var(--font-size-sm);
margin-top: 0.5rem;
padding: 0.5rem;
background: rgba(250, 112, 154, 0.1);
border-radius: var(--border-radius);
border-left: 3px solid #fa709a;
animation: errorShake 0.5s ease-in-out;
}
@keyframes errorShake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.security-notice {
text-align: center;
margin-top: 1rem;
padding: 0.75rem;
background: rgba(67, 233, 123, 0.1);
border-radius: var(--border-radius);
border-left: 3px solid #43e97b;
font-size: var(--font-size-xs);
color: var(--text-secondary);
}
@media (max-width: 480px) {
.login-card {
padding: 2rem 1.5rem;
margin: 1rem;
}
.app-title {
font-size: var(--font-size-xl);
}
.logo-icon {
width: 60px;
height: 60px;
font-size: 1.5rem;
}
}
</style>
</head>
<body>
<div class="background-animation"></div>
<div class="login-container">
<div class="login-card">
<div class="app-logo">
<div class="logo-icon">DL</div>
<h1 class="app-title">Drama Ling</h1>
<p class="app-subtitle">沉浸式英語學習體驗</p>
</div>
<form class="login-form" id="loginForm">
<div class="form-group">
<label class="form-label" for="username">電子郵件或用戶名</label>
<input
type="text"
id="username"
class="form-input"
placeholder="輸入您的電子郵件或用戶名"
required
>
</div>
<div class="form-group" style="position: relative;">
<label class="form-label" for="password">密碼</label>
<input
type="password"
id="password"
class="form-input"
placeholder="輸入您的密碼"
required
>
<button type="button" class="password-toggle" id="passwordToggle">👁</button>
</div>
<div class="form-options">
<label class="remember-me">
<div class="custom-checkbox" id="rememberCheckbox"></div>
<span>記住我</span>
</label>
<a href="#" class="forgot-password" id="forgotPassword">忘記密碼?</a>
</div>
<button type="submit" class="login-button" id="loginButton">
<div class="spinner"></div>
<span>登入</span>
</button>
<div id="errorMessage" class="error-message" style="display: none;"></div>
</form>
<div class="divider">
<span>或者使用</span>
</div>
<div class="social-login">
<a href="#" class="social-button" id="googleLogin">
<div class="social-icon google-icon">G</div>
<span>使用 Google 登入</span>
</a>
<a href="#" class="social-button" id="facebookLogin">
<div class="social-icon facebook-icon">f</div>
<span>使用 Facebook 登入</span>
</a>
<a href="#" class="social-button" id="appleLogin">
<div class="social-icon apple-icon">🍎</div>
<span>使用 Apple 登入</span>
</a>
</div>
<div class="register-link">
還沒有帳戶? <a href="#" id="registerLink">立即註冊</a>
</div>
<div class="guest-mode">
<a href="#" class="guest-button" id="guestMode">遊客模式體驗</a>
</div>
<div class="security-notice">
🔒 您的資料受到 AES-256 加密保護
</div>
</div>
</div>
<script>
class LoginSystem {
constructor() {
this.initializeElements();
this.bindEvents();
this.initializeState();
}
initializeElements() {
this.loginForm = document.getElementById('loginForm');
this.usernameInput = document.getElementById('username');
this.passwordInput = document.getElementById('password');
this.passwordToggle = document.getElementById('passwordToggle');
this.rememberCheckbox = document.getElementById('rememberCheckbox');
this.loginButton = document.getElementById('loginButton');
this.errorMessage = document.getElementById('errorMessage');
this.forgotPassword = document.getElementById('forgotPassword');
this.registerLink = document.getElementById('registerLink');
this.guestMode = document.getElementById('guestMode');
this.googleLogin = document.getElementById('googleLogin');
this.facebookLogin = document.getElementById('facebookLogin');
this.appleLogin = document.getElementById('appleLogin');
}
initializeState() {
this.isRememberChecked = false;
this.isPasswordVisible = false;
this.loginAttempts = 0;
this.maxLoginAttempts = 5;
this.lockoutTime = 3600000; // 1 hour in milliseconds
// Load saved preferences
this.loadSavedCredentials();
this.checkLockoutStatus();
}
bindEvents() {
this.loginForm.addEventListener('submit', (e) => this.handleLogin(e));
this.passwordToggle.addEventListener('click', () => this.togglePasswordVisibility());
this.rememberCheckbox.addEventListener('click', () => this.toggleRememberMe());
this.forgotPassword.addEventListener('click', (e) => this.handleForgotPassword(e));
this.registerLink.addEventListener('click', (e) => this.handleRegister(e));
this.guestMode.addEventListener('click', (e) => this.handleGuestMode(e));
this.googleLogin.addEventListener('click', (e) => this.handleSocialLogin(e, 'google'));
this.facebookLogin.addEventListener('click', (e) => this.handleSocialLogin(e, 'facebook'));
this.appleLogin.addEventListener('click', (e) => this.handleSocialLogin(e, 'apple'));
// Real-time validation
this.usernameInput.addEventListener('input', () => this.validateInput('username'));
this.passwordInput.addEventListener('input', () => this.validateInput('password'));
// Keyboard shortcuts
document.addEventListener('keydown', (e) => this.handleKeyboardShortcuts(e));
}
togglePasswordVisibility() {
this.isPasswordVisible = !this.isPasswordVisible;
this.passwordInput.type = this.isPasswordVisible ? 'text' : 'password';
this.passwordToggle.textContent = this.isPasswordVisible ? '🙈' : '👁';
// Add animation effect
this.passwordToggle.style.transform = 'scale(0.9)';
setTimeout(() => {
this.passwordToggle.style.transform = 'scale(1)';
}, 150);
}
toggleRememberMe() {
this.isRememberChecked = !this.isRememberChecked;
this.rememberCheckbox.classList.toggle('checked', this.isRememberChecked);
// Save preference
localStorage.setItem('rememberMe', this.isRememberChecked);
}
validateInput(inputType) {
const input = inputType === 'username' ? this.usernameInput : this.passwordInput;
const value = input.value.trim();
// Remove previous validation states
input.style.borderColor = '';
input.style.boxShadow = '';
if (inputType === 'username') {
const isEmail = this.isValidEmail(value);
const isUsername = this.isValidUsername(value);
if (value && !isEmail && !isUsername) {
this.setInputError(input, '請輸入有效的電子郵件或用戶名');
return false;
}
} else if (inputType === 'password') {
if (value && value.length < 8) {
this.setInputError(input, '密碼至少需要8個字符');
return false;
}
}
if (value) {
this.setInputSuccess(input);
}
return true;
}
setInputError(input, message) {
input.style.borderColor = '#fa709a';
input.style.boxShadow = '0 0 0 3px rgba(250, 112, 154, 0.2)';
}
setInputSuccess(input) {
input.style.borderColor = '#43e97b';
input.style.boxShadow = '0 0 0 3px rgba(67, 233, 123, 0.2)';
}
isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
isValidUsername(username) {
const usernameRegex = /^[a-zA-Z0-9_]{3,20}$/;
return usernameRegex.test(username);
}
async handleLogin(e) {
e.preventDefault();
if (this.isAccountLocked()) {
this.showError('帳戶已被鎖定,請稍後再試');
return;
}
const username = this.usernameInput.value.trim();
const password = this.passwordInput.value;
// Validate inputs
if (!this.validateInput('username') || !this.validateInput('password')) {
return;
}
if (!username || !password) {
this.showError('請填寫所有必填欄位');
return;
}
// Show loading state
this.setLoadingState(true);
this.hideError();
try {
// Simulate API call
await this.simulateLoginAPI(username, password);
// Success handling
this.handleLoginSuccess(username);
} catch (error) {
this.handleLoginError(error);
} finally {
this.setLoadingState(false);
}
}
async simulateLoginAPI(username, password) {
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 1500));
// Simulate different response scenarios
const scenarios = {
'demo@dramaling.com': { success: true, user: { name: 'Demo User', level: 'Advanced' } },
'test@example.com': { success: true, user: { name: 'Test User', level: 'Beginner' } },
'wrong@email.com': { success: false, error: '帳號或密碼錯誤' },
'locked@account.com': { success: false, error: '帳戶已被鎖定' }
};
const result = scenarios[username.toLowerCase()] || { success: false, error: '帳號或密碼錯誤' };
if (!result.success) {
throw new Error(result.error);
}
return result;
}
handleLoginSuccess(username) {
// Reset login attempts
this.loginAttempts = 0;
localStorage.removeItem('loginAttempts');
localStorage.removeItem('lockoutTime');
// Save credentials if remember me is checked
if (this.isRememberChecked) {
this.saveCredentials(username);
}
// Show success animation
this.showSuccessAnimation();
// Simulate navigation to main app
setTimeout(() => {
alert('登入成功!即將進入 Drama Ling 主應用...');
// In real app: window.location.href = '/dashboard';
}, 1000);
}
handleLoginError(error) {
this.loginAttempts++;
localStorage.setItem('loginAttempts', this.loginAttempts);
if (this.loginAttempts >= this.maxLoginAttempts) {
const lockoutTime = Date.now() + this.lockoutTime;
localStorage.setItem('lockoutTime', lockoutTime);
this.showError(`登入失敗次數過多,帳戶已被鎖定 1 小時`);
} else {
const remainingAttempts = this.maxLoginAttempts - this.loginAttempts;
this.showError(`${error.message} (剩餘嘗試次數: ${remainingAttempts})`);
}
// Shake animation for error
this.loginButton.style.animation = 'errorShake 0.5s ease-in-out';
setTimeout(() => {
this.loginButton.style.animation = '';
}, 500);
}
setLoadingState(isLoading) {
this.loginButton.classList.toggle('loading', isLoading);
this.loginButton.disabled = isLoading;
const span = this.loginButton.querySelector('span');
span.textContent = isLoading ? '登入中...' : '登入';
}
showError(message) {
this.errorMessage.textContent = message;
this.errorMessage.style.display = 'block';
this.errorMessage.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
hideError() {
this.errorMessage.style.display = 'none';
}
showSuccessAnimation() {
// Create success overlay
const overlay = document.createElement('div');
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 2rem;
font-weight: bold;
opacity: 0;
transition: opacity 0.3s ease;
`;
overlay.innerHTML = '✓ 登入成功!';
document.body.appendChild(overlay);
// Animate in
setTimeout(() => overlay.style.opacity = '1', 100);
// Remove after animation
setTimeout(() => {
overlay.style.opacity = '0';
setTimeout(() => document.body.removeChild(overlay), 300);
}, 2000);
}
handleSocialLogin(e, provider) {
e.preventDefault();
this.showSocialLoginAnimation(provider);
// Simulate OAuth flow
setTimeout(() => {
alert(`正在使用 ${provider.toUpperCase()} 進行登入...`);
// In real app: initiate OAuth flow
}, 1000);
}
showSocialLoginAnimation(provider) {
const button = e.currentTarget;
const originalText = button.innerHTML;
button.innerHTML = `
<div class="spinner" style="display: inline-block;"></div>
<span>連接中...</span>
`;
setTimeout(() => {
button.innerHTML = originalText;
}, 2000);
}
handleForgotPassword(e) {
e.preventDefault();
alert('即將跳轉到密碼重置頁面...');
// In real app: navigate to password reset page
}
handleRegister(e) {
e.preventDefault();
alert('即將跳轉到註冊頁面...');
// In real app: navigate to registration page
}
handleGuestMode(e) {
e.preventDefault();
const confirmGuest = confirm('以遊客模式進入將限制部分功能,確定要繼續嗎?');
if (confirmGuest) {
alert('正在以遊客模式進入 Drama Ling...');
// In real app: navigate to guest mode
}
}
loadSavedCredentials() {
const savedUsername = localStorage.getItem('savedUsername');
const rememberMe = localStorage.getItem('rememberMe') === 'true';
if (savedUsername && rememberMe) {
this.usernameInput.value = savedUsername;
this.isRememberChecked = true;
this.rememberCheckbox.classList.add('checked');
}
}
saveCredentials(username) {
localStorage.setItem('savedUsername', username);
}
checkLockoutStatus() {
const lockoutTime = localStorage.getItem('lockoutTime');
const attempts = localStorage.getItem('loginAttempts');
if (lockoutTime && Date.now() < parseInt(lockoutTime)) {
const remainingTime = Math.ceil((parseInt(lockoutTime) - Date.now()) / 60000);
this.showError(`帳戶已被鎖定,請在 ${remainingTime} 分鐘後再試`);
this.loginButton.disabled = true;
} else {
// Clear expired lockout
localStorage.removeItem('lockoutTime');
localStorage.removeItem('loginAttempts');
this.loginAttempts = 0;
}
if (attempts) {
this.loginAttempts = parseInt(attempts);
}
}
isAccountLocked() {
const lockoutTime = localStorage.getItem('lockoutTime');
return lockoutTime && Date.now() < parseInt(lockoutTime);
}
handleKeyboardShortcuts(e) {
// Enter key to submit
if (e.key === 'Enter' && (this.usernameInput.focused || this.passwordInput.focused)) {
this.handleLogin(e);
}
// Escape key to clear form
if (e.key === 'Escape') {
this.clearForm();
}
}
clearForm() {
this.usernameInput.value = '';
this.passwordInput.value = '';
this.hideError();
this.usernameInput.focus();
}
}
// Initialize login system when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new LoginSystem();
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff