diff --git a/AGENTS.md b/AGENTS.md index 9c7b827..e163350 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,7 +75,7 @@ **最後更新:** 2026-08-02 **進行中:** -- 水晶熱舞社重啟:30TH 應援報名已接上資料庫與後臺,下一階段可再做活動/練習影片內容管理 +- 水晶熱舞社重啟:30TH 報名與水晶練習室練舞清單已接上後臺;播放器本身仍待加入合法影片來源 **待確認:** - developer-rules 健檢尚未執行 @@ -90,6 +90,8 @@ - 水晶熱舞社 30TH 募集表單已接上 PHP/PDO/MySQL,可儲存報名、參與內容與參考檔案 - 後臺新增「30TH 應援報名」清單、搜尋、狀態處理、內部備註與受登入保護的檔案下載 - 架構決定:水晶熱舞社暫時共用推廣部後臺;偶像培訓維持獨立資料邊界,之後另拆專案與登入系統 +- 水晶練習室的「練舞清單」已改為讀取 `dance_practice_items`,後臺可管理歌曲、分類、練習重點、影片網址、難度、進度、優先順序與公開狀態 +- 練舞清單初始資料沿用原頁面的 Couple、Com' Back、Road Fighter;偶像培訓的練習生/課程/紀錄未接入此資料表 --- diff --git a/admin/bootstrap.php b/admin/bootstrap.php index e873e4a..0fd7bfc 100644 --- a/admin/bootstrap.php +++ b/admin/bootstrap.php @@ -165,6 +165,22 @@ function modules(): array ], 'list' => ['display_name', 'media_type', 'category', 'file_path', 'status', 'updated_at'], ], + 'dance_practices' => [ + 'label' => '練舞清單', 'item_label' => '練舞項目', 'list_title' => '練舞清單', 'icon' => 'list-check', 'table' => 'dance_practice_items', 'order' => 'sort_order, id', 'group' => 'dance', + 'fields' => [ + 'title' => ['label' => '歌曲名稱', 'type' => 'text', 'required' => true], + 'tags' => ['label' => '練習分類', 'type' => 'text'], + 'practice_focus' => ['label' => '練習重點', 'type' => 'textarea', 'required' => true], + 'video_url' => ['label' => '參考影片網址', 'type' => 'url'], + 'difficulty' => ['label' => '難度', 'type' => 'select', 'default' => 'medium', 'required' => true, 'options' => ['easy' => '入門', 'medium' => '中等', 'hard' => '挑戰']], + 'progress_status' => ['label' => '練習進度', 'type' => 'select', 'default' => 'not_started', 'required' => true, 'options' => ['not_started' => '未開始', 'practicing' => '練習中', 'review' => '待複習', 'completed' => '已完成']], + 'note_text' => ['label' => '補充說明', 'type' => 'text'], + 'is_featured' => ['label' => '優先練習', 'type' => 'checkbox'], + 'sort_order' => ['label' => '排序', 'type' => 'number', 'default' => '0'], + 'status' => ['label' => '公開狀態', 'type' => 'status', 'required' => true], + ], + 'list' => ['title', 'difficulty', 'progress_status', 'is_featured', 'sort_order', 'status', 'updated_at'], + ], ]; } @@ -263,9 +279,14 @@ function render_header(string $title, string $active = ''): void 控制台
內容資料
$mod): ?> + = h($mod['label']) ?>水晶熱舞社
+ $mod): ?> + + = h($mod['label']) ?> + 30TH 應援報名系統
公開狀態 diff --git a/admin/database/schema.sql b/admin/database/schema.sql index 954a573..59a25af 100644 --- a/admin/database/schema.sql +++ b/admin/database/schema.sql @@ -1,5 +1,6 @@ CREATE DATABASE IF NOT EXISTS sechskies_cms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE sechskies_cms; +SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS admin_users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, @@ -138,6 +139,39 @@ CREATE TABLE IF NOT EXISTS dance_applications ( INDEX idx_dance_applications_email (email) ) ENGINE=InnoDB; +CREATE TABLE IF NOT EXISTS dance_practice_items ( + id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, + title VARCHAR(160) NOT NULL, + tags VARCHAR(255) NULL, + practice_focus TEXT NOT NULL, + video_url VARCHAR(500) NULL, + difficulty ENUM('easy','medium','hard') NOT NULL DEFAULT 'medium', + progress_status ENUM('not_started','practicing','review','completed') NOT NULL DEFAULT 'not_started', + note_text VARCHAR(255) NULL, + is_featured TINYINT(1) NOT NULL DEFAULT 0, + sort_order INT NOT NULL DEFAULT 0, + status ENUM('draft','coming_soon','published','archived') NOT NULL DEFAULT 'draft', + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX idx_dance_practice_order (status, sort_order, id), + INDEX idx_dance_practice_title (title) +) ENGINE=InnoDB; + +INSERT INTO dance_practice_items + (title, tags, practice_focus, difficulty, progress_status, note_text, is_featured, sort_order, status) +SELECT 'Couple', 'Dance,Vocal', '副歌動作、隊形感、甜感表情', 'easy', 'not_started', '可作為第一首示範歌', 1, 10, 'published' +WHERE NOT EXISTS (SELECT 1 FROM dance_practice_items WHERE title = 'Couple'); + +INSERT INTO dance_practice_items + (title, tags, practice_focus, difficulty, progress_status, note_text, is_featured, sort_order, status) +SELECT 'Com'' Back', 'Dance,Rap', '強拍、Rap 段落、舞台氣勢', 'medium', 'not_started', '未來擴充', 0, 20, 'coming_soon' +WHERE NOT EXISTS (SELECT 1 FROM dance_practice_items WHERE title = 'Com'' Back'); + +INSERT INTO dance_practice_items + (title, tags, practice_focus, difficulty, progress_status, note_text, is_featured, sort_order, status) +SELECT 'Road Fighter', 'Dance,Rap,Performance', '節奏、力量、舞台感', 'hard', 'not_started', '未來擴充', 0, 30, 'coming_soon' +WHERE NOT EXISTS (SELECT 1 FROM dance_practice_items WHERE title = 'Road Fighter'); + CREATE TABLE IF NOT EXISTS audit_logs ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, admin_user_id INT UNSIGNED NULL, diff --git a/admin/record-form.php b/admin/record-form.php index 19b82f0..f6305a2 100644 --- a/admin/record-form.php +++ b/admin/record-form.php @@ -66,7 +66,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } $record = array_merge($record, $data); } -render_header(($id ? '編輯' : '新增') . $module['label'], $key); +render_header(($id ? '編輯' : '新增') . ($module['item_label'] ?? $module['label']), $key); ?>