Browse Source

feat: add TG Live Game project structure and documentation

- Created new project files for TG Live Game, including _project.md, workflow.md, and architecture.canvas.
- Updated workspace.json to reflect new project structure and current tab settings.
- Added detailed documentation for backend API services and development workflow.
- Removed outdated architecture and database design files to streamline project organization.
yb 3 weeks ago
parent
commit
545cc29651

+ 40 - 15
.obsidian/workspace.json

@@ -13,18 +13,36 @@
             "state": {
               "type": "canvas",
               "state": {
-                "file": "pwtk-admin-web/architecture-v1.canvas",
+                "file": "tg-live-game/tg-live-game-hono/architecture.canvas",
                 "viewState": {
-                  "x": 305,
-                  "y": -3874.5750890511144,
-                  "zoom": -3.7170646889186036
+                  "x": 40,
+                  "y": 517.7096725377177,
+                  "zoom": -0.5584719462465597
+                }
+              },
+              "icon": "lucide-layout-dashboard",
+              "title": "architecture"
+            }
+          },
+          {
+            "id": "b9f073ad4bf12d8c",
+            "type": "leaf",
+            "state": {
+              "type": "canvas",
+              "state": {
+                "file": "tg-live-game/architecture-v1.canvas",
+                "viewState": {
+                  "x": -211.3297830171836,
+                  "y": -407.01853093057,
+                  "zoom": -1.4445660879730733
                 }
               },
               "icon": "lucide-layout-dashboard",
               "title": "architecture-v1"
             }
           }
-        ]
+        ],
+        "currentTab": 1
       }
     ],
     "direction": "vertical"
@@ -81,7 +99,7 @@
       }
     ],
     "direction": "horizontal",
-    "width": 305.5
+    "width": 254.5
   },
   "right": {
     "id": "93884d0cec98b8d0",
@@ -177,6 +195,7 @@
   },
   "left-ribbon": {
     "hiddenItems": {
+      "bases:Create new base": false,
       "switcher:Open quick switcher": false,
       "graph:Open graph view": false,
       "canvas:Create new canvas": false,
@@ -185,20 +204,26 @@
       "command-palette:Open command palette": false
     }
   },
-  "active": "d1c67f0d3fca314e",
+  "active": "b9f073ad4bf12d8c",
   "lastOpenFiles": [
+    "tg-live-game/tg-live-game-hono/auth-system.canvas",
+    "tg-live-game/tg-live-game-hono/architecture.canvas",
+    "tg-live-game/tg-live-game-hono/d1-database.canvas",
+    "tg-live-game/tg-live-game-hono/_project.md",
+    "tg-live-game/_project.md",
+    "tg-live-game/workflow.md",
+    "tg-live-game/tg-live-game-hono/workflow.md",
+    "tg-live-game/architecture-v1.canvas",
+    "tg-live-game/discuss-2024-12-31.md",
+    "tg-live-game/rtsp-cloudflare-stream.canvas",
+    "tg-live-game/tg-live-game-web",
+    "tg-live-game/tg-live-game-hono",
+    "tg-live-game/tg-live-game-hono/README.md",
     "pwtk-admin-web/architecture-v1.canvas",
     "pwtk-admin-web/discuss-2025-01-02.md",
-    "tg-live-game/architecture-v1.canvas",
-    "tg-live-game-hono/auth-system.canvas",
-    "tg-live-game-hono/README.md",
-    "tg-live-game-hono/d1-database.canvas",
-    "tg-live-game-hono/architecture.canvas",
     "tg-live-game-hono/README.md.tmp.4959.1767332108780",
-    "tg-live-game-hono",
-    "tg-live-game/discuss-2024-12-31.md",
+    "tg-live-game/tg-live-game-hono",
     "pwtk-admin-web/architecture-v1.canvas.tmp.2064.1767331486716",
-    "tg-live-game/rtsp-cloudflare-stream.canvas",
     "pwtk-admin-web/architecture-v1.canvas.tmp.2064.1767329530729",
     "未命名.md",
     "pwtk-admin-web",

+ 0 - 206
tg-live-game-hono/architecture.canvas

@@ -1,206 +0,0 @@
-{
-  "nodes": [
-    {
-      "id": "title",
-      "type": "text",
-      "text": "# tg-live-game-hono 架构\n\n**版本**: v1.1.0\n**技术栈**: Hono + Cloudflare Workers + D1\n**状态**: ✅ 已实现\n\n新增功能:\n- JWT 认证\n- 用户管理\n- RBAC 权限",
-      "x": -100,
-      "y": -600,
-      "width": 350,
-      "height": 160,
-      "color": "6"
-    },
-    {
-      "id": "entry",
-      "type": "text",
-      "text": "**入口文件**\n`src/index.ts`\n\n功能:\n- Hono 应用初始化\n- CORS/日志中间件\n- 路由挂载\n  - /api/auth (公开)\n  - /api/users (admin)\n  - /api/stream\n\n端口: localhost:8787",
-      "x": -550,
-      "y": -380,
-      "width": 280,
-      "height": 220,
-      "color": "4"
-    },
-    {
-      "id": "middleware",
-      "type": "text",
-      "text": "**中间件**\n`src/middleware/auth.ts`\n\n- authMiddleware()\n  验证 JWT Token\n- requireRole(roles)\n  角色权限检查\n- requirePermission()\n  资源权限检查\n- optionalAuth()\n  可选认证",
-      "x": -550,
-      "y": -100,
-      "width": 280,
-      "height": 200,
-      "color": "5"
-    },
-    {
-      "id": "routes_auth",
-      "type": "text",
-      "text": "**认证路由**\n`src/routes/auth.ts`\n\n公开接口:\n- POST /login\n- POST /register\n- POST /refresh\n\n需认证:\n- GET /me\n- POST /change-password\n- POST /logout",
-      "x": -200,
-      "y": -380,
-      "width": 260,
-      "height": 220,
-      "color": "2"
-    },
-    {
-      "id": "routes_user",
-      "type": "text",
-      "text": "**用户路由**\n`src/routes/user.ts`\n\n需 admin 角色:\n- GET /users\n- GET /users/:id\n- POST /users\n- PUT /users/:id\n- DELETE /users/:id\n\n权限管理:\n- GET /users/:id/permissions\n- POST /users/:id/permissions\n- DELETE /users/:id/permissions/:id",
-      "x": 120,
-      "y": -380,
-      "width": 280,
-      "height": 280,
-      "color": "2"
-    },
-    {
-      "id": "routes_stream",
-      "type": "text",
-      "text": "**Stream 路由**\n`src/routes/stream.ts`\n\n视频管理 (13个端点)\n直播管理\n\n需认证 ✅",
-      "x": 460,
-      "y": -380,
-      "width": 220,
-      "height": 140,
-      "color": "2"
-    },
-    {
-      "id": "services_auth",
-      "type": "text",
-      "text": "**认证服务**\n`src/services/auth.ts`\n\nAuthService:\n- login()\n- register()\n- refreshToken()\n- getCurrentUser()\n- changePassword()\n- logAudit()",
-      "x": -200,
-      "y": -100,
-      "width": 260,
-      "height": 180,
-      "color": "3"
-    },
-    {
-      "id": "services_cf",
-      "type": "text",
-      "text": "**Stream 服务**\n`src/services/cloudflare.ts`\n\nCloudflareStreamService:\n- 视频 CRUD\n- 直播 CRUD\n- 播放信息",
-      "x": 460,
-      "y": -180,
-      "width": 220,
-      "height": 140,
-      "color": "3"
-    },
-    {
-      "id": "utils",
-      "type": "text",
-      "text": "**工具函数**\n`src/utils/`\n\njwt.ts:\n- createToken()\n- verifyToken()\n- generateId()\n\npassword.ts:\n- hashPassword()\n- verifyPassword()\n\n算法: PBKDF2 + HMAC-SHA256",
-      "x": 120,
-      "y": -40,
-      "width": 280,
-      "height": 200,
-      "color": "4"
-    },
-    {
-      "id": "database",
-      "type": "text",
-      "text": "**D1 数据库**\n\n表:\n- users\n- user_permissions\n- cameras\n- live_sessions\n- videos\n- view_stats\n- audit_logs\n\n详见: d1-database.canvas",
-      "x": -550,
-      "y": 160,
-      "width": 280,
-      "height": 200,
-      "color": "1"
-    },
-    {
-      "id": "env_vars",
-      "type": "text",
-      "text": "**环境变量**\n\nCloudflare:\n- CF_ACCOUNT_ID\n- CF_API_TOKEN\n- CUSTOMER_SUBDOMAIN\n\nJWT:\n- JWT_SECRET\n- JWT_EXPIRES_IN\n- REFRESH_EXPIRES_IN\n\nD1:\n- DB binding",
-      "x": -200,
-      "y": 140,
-      "width": 260,
-      "height": 220,
-      "color": "4"
-    },
-    {
-      "id": "types",
-      "type": "text",
-      "text": "**类型定义**\n`src/types/index.ts`\n\n新增:\n- JwtPayload\n- LoginRequest\n- RegisterRequest\n- AuthResponse\n- User\n- UserPermission\n- Camera\n- LiveSession\n- ...",
-      "x": 460,
-      "y": 20,
-      "width": 220,
-      "height": 220,
-      "color": "5"
-    }
-  ],
-  "edges": [
-    {
-      "id": "edge_entry_mw",
-      "fromNode": "entry",
-      "fromSide": "bottom",
-      "toNode": "middleware",
-      "toSide": "top",
-      "label": "use()"
-    },
-    {
-      "id": "edge_entry_auth",
-      "fromNode": "entry",
-      "fromSide": "right",
-      "toNode": "routes_auth",
-      "toSide": "left",
-      "label": "/api/auth"
-    },
-    {
-      "id": "edge_entry_user",
-      "fromNode": "entry",
-      "fromSide": "right",
-      "toNode": "routes_user",
-      "toSide": "left",
-      "label": "/api/users"
-    },
-    {
-      "id": "edge_user_stream",
-      "fromNode": "routes_user",
-      "fromSide": "right",
-      "toNode": "routes_stream",
-      "toSide": "left",
-      "label": "/api/stream"
-    },
-    {
-      "id": "edge_auth_service",
-      "fromNode": "routes_auth",
-      "fromSide": "bottom",
-      "toNode": "services_auth",
-      "toSide": "top",
-      "label": "AuthService"
-    },
-    {
-      "id": "edge_service_utils",
-      "fromNode": "services_auth",
-      "fromSide": "right",
-      "toNode": "utils",
-      "toSide": "left",
-      "label": "jwt/password"
-    },
-    {
-      "id": "edge_stream_cf",
-      "fromNode": "routes_stream",
-      "fromSide": "bottom",
-      "toNode": "services_cf",
-      "toSide": "top",
-      "label": "StreamService"
-    },
-    {
-      "id": "edge_mw_db",
-      "fromNode": "middleware",
-      "fromSide": "bottom",
-      "toNode": "database",
-      "toSide": "top",
-      "label": "权限查询"
-    },
-    {
-      "id": "edge_service_db",
-      "fromNode": "services_auth",
-      "fromSide": "bottom",
-      "toNode": "database",
-      "toSide": "right",
-      "label": "用户查询"
-    },
-    {
-      "id": "edge_cf_types",
-      "fromNode": "services_cf",
-      "fromSide": "bottom",
-      "toNode": "types",
-      "toSide": "top",
-      "label": "import"
-    }
-  ]
-}

+ 0 - 146
tg-live-game-hono/auth-system.canvas

@@ -1,146 +0,0 @@
-{
-  "nodes": [
-    {
-      "id": "title",
-      "type": "text",
-      "text": "# 认证鉴权系统设计\n\n**方案**: JWT + D1\n**状态**: 📋 设计中\n\n特点:\n- 无状态 JWT 认证\n- 基于角色的访问控制 (RBAC)\n- 细粒度资源权限\n- 边缘计算友好",
-      "x": -100,
-      "y": -600,
-      "width": 380,
-      "height": 160,
-      "color": "6"
-    },
-    {
-      "id": "auth_flow",
-      "type": "text",
-      "text": "## 认证流程\n\n```\n1. 登录请求\n   POST /api/auth/login\n   { username, password }\n        ↓\n2. 验证密码\n   bcrypt.compare()\n        ↓\n3. 生成 JWT\n   { userId, role, exp }\n        ↓\n4. 返回 Token\n   { accessToken, refreshToken }\n        ↓\n5. 客户端存储\n   Authorization: Bearer <token>\n```",
-      "x": -500,
-      "y": -380,
-      "width": 300,
-      "height": 340,
-      "color": "2"
-    },
-    {
-      "id": "jwt_structure",
-      "type": "text",
-      "text": "## JWT 结构\n\n**Header**\n```json\n{ \"alg\": \"HS256\", \"typ\": \"JWT\" }\n```\n\n**Payload**\n```json\n{\n  \"sub\": \"user-id\",\n  \"username\": \"admin\",\n  \"role\": \"admin\",\n  \"iat\": 1704067200,\n  \"exp\": 1704153600\n}\n```\n\n**有效期**\n- accessToken: 24h\n- refreshToken: 7d",
-      "x": -130,
-      "y": -380,
-      "width": 300,
-      "height": 320,
-      "color": "4"
-    },
-    {
-      "id": "rbac",
-      "type": "text",
-      "text": "## RBAC 角色权限\n\n| 角色 | 权限 |\n|------|------|\n| admin | 全部操作 |\n| operator | 摄像头管理、直播控制 |\n| viewer | 仅查看 |\n\n**资源权限**\n```\nuser_permissions 表\n- view: 查看摄像头\n- control: 控制直播\n- manage: 管理配置\n```",
-      "x": 240,
-      "y": -380,
-      "width": 280,
-      "height": 280,
-      "color": "3"
-    },
-    {
-      "id": "middleware",
-      "type": "text",
-      "text": "## 中间件设计\n\n**authMiddleware**\n- 解析 Bearer Token\n- 验证 JWT 签名\n- 检查过期时间\n- 注入 c.set('user', payload)\n\n**requireRole(roles)**\n- 检查用户角色\n- 403 Forbidden\n\n**requirePermission(resource, action)**\n- 查询 user_permissions\n- 检查资源权限",
-      "x": -500,
-      "y": 20,
-      "width": 300,
-      "height": 260,
-      "color": "5"
-    },
-    {
-      "id": "api_endpoints",
-      "type": "text",
-      "text": "## API 端点\n\n**认证**\n- POST /api/auth/login\n- POST /api/auth/register\n- POST /api/auth/refresh\n- POST /api/auth/logout\n- GET  /api/auth/me\n\n**用户管理 (admin)**\n- GET  /api/users\n- GET  /api/users/:id\n- POST /api/users\n- PUT  /api/users/:id\n- DELETE /api/users/:id\n\n**权限管理 (admin)**\n- GET  /api/users/:id/permissions\n- POST /api/users/:id/permissions\n- DELETE /api/permissions/:id",
-      "x": -130,
-      "y": 0,
-      "width": 300,
-      "height": 340,
-      "color": "2"
-    },
-    {
-      "id": "file_structure",
-      "type": "text",
-      "text": "## 文件结构\n\n```\nsrc/\n├── middleware/\n│   └── auth.ts\n├── services/\n│   ├── auth.ts\n│   └── user.ts\n├── routes/\n│   ├── auth.ts\n│   └── user.ts\n├── utils/\n│   ├── jwt.ts\n│   └── password.ts\n└── types/\n    └── index.ts\n```",
-      "x": 240,
-      "y": -40,
-      "width": 280,
-      "height": 280,
-      "color": "4"
-    },
-    {
-      "id": "security",
-      "type": "text",
-      "text": "## 安全措施\n\n- 密码 bcrypt 哈希 (cost=12)\n- JWT 密钥环境变量\n- HTTPS 强制\n- Rate Limiting\n- 登录失败锁定\n- Audit Log 记录\n- CORS 白名单",
-      "x": -500,
-      "y": 340,
-      "width": 300,
-      "height": 180,
-      "color": "1"
-    },
-    {
-      "id": "env_config",
-      "type": "text",
-      "text": "## 环境配置\n\n**.dev.vars**\n```\nJWT_SECRET=your-secret-key\nJWT_EXPIRES_IN=86400\nREFRESH_EXPIRES_IN=604800\n```\n\n**wrangler secret**\n```bash\nwrangler secret put JWT_SECRET\n```",
-      "x": -130,
-      "y": 400,
-      "width": 300,
-      "height": 180,
-      "color": "4"
-    },
-    {
-      "id": "protected_routes",
-      "type": "text",
-      "text": "## 路由保护\n\n**公开路由**\n- /api/auth/login\n- /api/auth/register\n- / (健康检查)\n\n**需要认证**\n- /api/stream/*\n- /api/users/*\n- /api/auth/me\n\n**需要 admin**\n- POST/PUT/DELETE /api/users\n- /api/permissions/*",
-      "x": 240,
-      "y": 300,
-      "width": 280,
-      "height": 240,
-      "color": "3"
-    }
-  ],
-  "edges": [
-    {
-      "id": "edge_flow_jwt",
-      "fromNode": "auth_flow",
-      "fromSide": "right",
-      "toNode": "jwt_structure",
-      "toSide": "left",
-      "label": "生成"
-    },
-    {
-      "id": "edge_jwt_rbac",
-      "fromNode": "jwt_structure",
-      "fromSide": "right",
-      "toNode": "rbac",
-      "toSide": "left",
-      "label": "携带 role"
-    },
-    {
-      "id": "edge_mw_api",
-      "fromNode": "middleware",
-      "fromSide": "right",
-      "toNode": "api_endpoints",
-      "toSide": "left",
-      "label": "保护"
-    },
-    {
-      "id": "edge_api_files",
-      "fromNode": "api_endpoints",
-      "fromSide": "right",
-      "toNode": "file_structure",
-      "toSide": "left",
-      "label": "实现"
-    },
-    {
-      "id": "edge_mw_security",
-      "fromNode": "middleware",
-      "fromSide": "bottom",
-      "toNode": "security",
-      "toSide": "top",
-      "label": "安全策略"
-    }
-  ]
-}

+ 0 - 154
tg-live-game-hono/d1-database.canvas

@@ -1,154 +0,0 @@
-{
-  "nodes": [
-    {
-      "id": "title",
-      "type": "text",
-      "text": "# D1 数据库设计\n\n**数据库名**: tg_live_game\n**引擎**: Cloudflare D1 (SQLite)\n**状态**: 📋 设计中\n\n设计原则:\n- Cloudflare Stream 为主数据源\n- D1 存储业务扩展元数据\n- 支持离线查询和统计",
-      "x": -100,
-      "y": -600,
-      "width": 380,
-      "height": 180,
-      "color": "6"
-    },
-    {
-      "id": "table_cameras",
-      "type": "text",
-      "text": "**cameras** 摄像头管理\n\n```sql\nid          TEXT PRIMARY KEY\nname        TEXT NOT NULL\ntype        TEXT -- 'mac'|'ip'|'rtsp'\nprotocol    TEXT -- 'rtmps'|'srt'|'whip'\nrtsp_url    TEXT\nlocation    TEXT\nstatus      TEXT -- 'online'|'offline'\nlive_input_id TEXT -- CF Stream ID\ncreated_at  INTEGER\nupdated_at  INTEGER\n```\n\n索引: status, type",
-      "x": -500,
-      "y": -340,
-      "width": 300,
-      "height": 280,
-      "color": "4"
-    },
-    {
-      "id": "table_live_sessions",
-      "type": "text",
-      "text": "**live_sessions** 直播会话\n\n```sql\nid          TEXT PRIMARY KEY\ncamera_id   TEXT REFERENCES cameras\nlive_input_id TEXT -- CF Stream ID\nstarted_at  INTEGER NOT NULL\nended_at    INTEGER\nduration    INTEGER -- 秒\nstatus      TEXT -- 'live'|'ended'|'error'\nviewer_count INTEGER DEFAULT 0\nrecording_id TEXT -- 录像视频ID\ncreated_at  INTEGER\n```\n\n索引: camera_id, status, started_at",
-      "x": -130,
-      "y": -340,
-      "width": 320,
-      "height": 280,
-      "color": "2"
-    },
-    {
-      "id": "table_videos",
-      "type": "text",
-      "text": "**videos** 视频元数据\n\n```sql\nid          TEXT PRIMARY KEY\ncf_uid      TEXT UNIQUE -- CF Stream UID\ncamera_id   TEXT REFERENCES cameras\nsession_id  TEXT REFERENCES live_sessions\ntitle       TEXT\ndescription TEXT\ntags        TEXT -- JSON array\nthumbnail   TEXT\nduration    INTEGER\nsize        INTEGER\nstatus      TEXT -- 'ready'|'processing'\nis_public   INTEGER DEFAULT 0\nview_count  INTEGER DEFAULT 0\ncreated_at  INTEGER\nupdated_at  INTEGER\n```\n\n索引: cf_uid, camera_id, status",
-      "x": 260,
-      "y": -340,
-      "width": 320,
-      "height": 340,
-      "color": "3"
-    },
-    {
-      "id": "table_users",
-      "type": "text",
-      "text": "**users** 用户管理\n\n```sql\nid          TEXT PRIMARY KEY\nusername    TEXT UNIQUE\nemail       TEXT UNIQUE\npassword_hash TEXT\nrole        TEXT -- 'admin'|'operator'|'viewer'\nstatus      TEXT -- 'active'|'disabled'\nlast_login  INTEGER\ncreated_at  INTEGER\nupdated_at  INTEGER\n```\n\n索引: username, email, role",
-      "x": -500,
-      "y": 0,
-      "width": 300,
-      "height": 240,
-      "color": "5"
-    },
-    {
-      "id": "table_permissions",
-      "type": "text",
-      "text": "**user_permissions** 权限\n\n```sql\nid          TEXT PRIMARY KEY\nuser_id     TEXT REFERENCES users\ncamera_id   TEXT REFERENCES cameras\npermission  TEXT -- 'view'|'control'|'manage'\ngranted_at  INTEGER\ngranted_by  TEXT REFERENCES users\n```\n\n索引: user_id, camera_id",
-      "x": -130,
-      "y": 0,
-      "width": 320,
-      "height": 200,
-      "color": "5"
-    },
-    {
-      "id": "table_view_stats",
-      "type": "text",
-      "text": "**view_stats** 观看统计\n\n```sql\nid          TEXT PRIMARY KEY\nvideo_id    TEXT REFERENCES videos\nsession_id  TEXT REFERENCES live_sessions\nuser_id     TEXT -- 可为空(匿名)\nip_address  TEXT\nuser_agent  TEXT\nwatch_duration INTEGER -- 秒\nstarted_at  INTEGER\nended_at    INTEGER\ncountry     TEXT\ncity        TEXT\n```\n\n索引: video_id, session_id, started_at",
-      "x": 260,
-      "y": 60,
-      "width": 320,
-      "height": 260,
-      "color": "1"
-    },
-    {
-      "id": "table_audit_logs",
-      "type": "text",
-      "text": "**audit_logs** 操作日志\n\n```sql\nid          TEXT PRIMARY KEY\nuser_id     TEXT REFERENCES users\naction      TEXT -- 'create'|'update'|'delete'\nresource    TEXT -- 'camera'|'video'|'user'\nresource_id TEXT\ndetails     TEXT -- JSON\nip_address  TEXT\ncreated_at  INTEGER\n```\n\n索引: user_id, action, created_at",
-      "x": -500,
-      "y": 300,
-      "width": 300,
-      "height": 220,
-      "color": "1"
-    },
-    {
-      "id": "er_diagram",
-      "type": "text",
-      "text": "## ER 关系图\n\n```\nusers ──1:N──> user_permissions\n  │                  │\n  │                  v\n  │            cameras ──1:N──> live_sessions\n  │               │                   │\n  │               │                   v\n  └──1:N──> audit_logs         videos <──1:N── view_stats\n```\n\n核心关系:\n- 摄像头 → 多个直播会话\n- 直播会话 → 录像视频\n- 用户 → 摄像头权限",
-      "x": -130,
-      "y": 260,
-      "width": 320,
-      "height": 260,
-      "color": "6"
-    },
-    {
-      "id": "wrangler_config",
-      "type": "text",
-      "text": "## wrangler.toml 配置\n\n```toml\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"tg_live_game\"\ndatabase_id = \"<your-database-id>\"\n```\n\n## 创建命令\n\n```bash\nwrangler d1 create tg_live_game\nwrangler d1 execute tg_live_game \\\n  --file=./schema.sql\n```",
-      "x": 260,
-      "y": 380,
-      "width": 320,
-      "height": 240,
-      "color": "4"
-    }
-  ],
-  "edges": [
-    {
-      "id": "edge_camera_session",
-      "fromNode": "table_cameras",
-      "fromSide": "right",
-      "toNode": "table_live_sessions",
-      "toSide": "left",
-      "label": "1:N"
-    },
-    {
-      "id": "edge_session_video",
-      "fromNode": "table_live_sessions",
-      "fromSide": "right",
-      "toNode": "table_videos",
-      "toSide": "left",
-      "label": "1:1"
-    },
-    {
-      "id": "edge_user_perm",
-      "fromNode": "table_users",
-      "fromSide": "right",
-      "toNode": "table_permissions",
-      "toSide": "left",
-      "label": "1:N"
-    },
-    {
-      "id": "edge_perm_camera",
-      "fromNode": "table_permissions",
-      "fromSide": "top",
-      "toNode": "table_cameras",
-      "toSide": "bottom",
-      "label": "N:1"
-    },
-    {
-      "id": "edge_video_stats",
-      "fromNode": "table_videos",
-      "fromSide": "bottom",
-      "toNode": "table_view_stats",
-      "toSide": "top",
-      "label": "1:N"
-    },
-    {
-      "id": "edge_user_audit",
-      "fromNode": "table_users",
-      "fromSide": "bottom",
-      "toNode": "table_audit_logs",
-      "toSide": "top",
-      "label": "1:N"
-    }
-  ]
-}

+ 88 - 0
tg-live-game/_project.md

@@ -0,0 +1,88 @@
+---
+type: project-group
+name: TG Live Game
+status: active
+created: 2024-12-31
+updated: 2026-01-03
+children:
+  - tg-live-game-hono
+  - tg-live-game-web
+---
+
+# TG Live Game
+
+直播游戏平台项目组,包含后端 API 服务和前端应用。
+
+## 子项目
+
+| 子项目 | 类型 | 技术栈 | Kanban ID |
+|--------|------|--------|-----------|
+| [[tg-live-game-hono/_project\|tg-live-game-hono]] | 后端 | Hono + CF Workers | `7c6bb2ce-90a2-4e96-bc04-5facdcdb337f` |
+| [[tg-live-game-web/_project\|tg-live-game-web]] | 前端 | Vue 3 + TypeScript | `32214e97-f833-485f-8c7c-cf4d82327e0b` |
+
+## 系统架构
+
+详见 [[architecture-v1]]
+
+```
+Mac摄像头 → RTMPS → Cloudflare Stream → HLS → tg-live-game-web
+                         ↑
+                    tg-live-game-hono (API)
+```
+
+## 项目状态
+
+- **POC 阶段**: ✅ 已完成
+- **v1 目标**: Mac摄像头 → RTMPS → Cloudflare → Web播放
+
+### v2 目标
+- [ ] RTSP输入支持
+- [ ] WHIP输出支持
+- [ ] Java进程管理
+
+### v3 目标
+- [ ] 多路流管理
+- [ ] 自动重连
+- [ ] 监控告警
+
+## 代码仓库
+
+| 项目 | 路径 |
+|------|------|
+| 后端 | `/Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono` |
+| 前端 | `/Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-web` |
+
+## 开发工作流
+
+详见 [[workflow]] 文档。
+
+### Claude Code 启动方式
+
+```bash
+# 多项目协作开发(推荐)
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game
+claude
+```
+
+### 多项目协作
+
+同时涉及前后端的功能,使用依赖链串联任务:
+
+```
+任务01-hono (后端) → 任务01-web (前端) → 任务02-hono → 任务02-web → ...
+```
+
+### 任务字段
+
+| 字段 | 含义 |
+|------|------|
+| `project` | 目标 Kanban 项目 |
+| `related` | 关联任务编号 |
+| `depends` | 依赖任务(需先完成) |
+
+## 相关文档
+
+- [[workflow]] - 完整开发工作流
+- [[architecture-v1]] - 系统架构
+- [[tg-live-game-hono/_project]] - 后端项目
+- [[tg-live-game-web/_project]] - 前端项目

+ 0 - 0
tg-live-game-hono/README.md → tg-live-game/tg-live-game-hono/README.md


+ 65 - 0
tg-live-game/tg-live-game-hono/_project.md

@@ -0,0 +1,65 @@
+---
+type: sub-project
+name: TG Live Game Hono
+parent: tg-live-game
+kanban_id: 7c6bb2ce-90a2-4e96-bc04-5facdcdb337f
+code_path: /Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono
+tech_stack: Hono + Cloudflare Workers + D1
+status: active
+created: 2024-12-31
+updated: 2026-01-03
+---
+
+# TG Live Game Hono
+
+后端 API 服务,基于 Hono + Cloudflare Workers 构建。
+
+## 项目关联
+
+| 属性 | 值 |
+|------|-----|
+| Kanban Project | [tg-live-game-hono](vibe://kanban/7c6bb2ce-90a2-4e96-bc04-5facdcdb337f) |
+| 代码仓库 | `/Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono` |
+| 父项目 | [[tg-live-game]] |
+| 关联前端 | [[tg-live-game-web]] |
+
+## 架构文档
+
+- [[architecture]] - 整体架构设计 (v1.1.0)
+- [[auth-system]] - 认证鉴权系统设计
+- [[d1-database]] - D1 数据库设计
+- [[workflow]] - 开发工作流
+
+## 技术栈
+
+- **框架**: Hono v4
+- **运行时**: Cloudflare Workers
+- **数据库**: Cloudflare D1 (SQLite)
+- **认证**: JWT (HS256)
+- **语言**: TypeScript
+
+## 功能模块
+
+| 模块 | 描述 | 状态 |
+|------|------|------|
+| 视频管理 | CRUD、导入、上传 | ✅ 已实现 |
+| 直播管理 | CRUD、播放信息 | ✅ 已实现 |
+| Cloudflare API | Stream API 封装 | ✅ 已实现 |
+| JWT 认证 | 登录、注册、刷新 | ✅ 已实现 |
+| 用户管理 | CRUD、权限管理 | ✅ 已实现 |
+| RBAC 权限 | 角色权限控制 | ✅ 已实现 |
+
+## 开发命令
+
+```bash
+# 进入代码目录
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono
+
+# 启动 Claude Code
+claude
+
+# 开发命令
+npm install       # 安装依赖
+npm run dev       # 本地开发
+npm run deploy    # 部署
+```

+ 28 - 0
tg-live-game/tg-live-game-hono/architecture.canvas

@@ -0,0 +1,28 @@
+{
+	"nodes":[
+		{"id":"database","type":"text","text":"**D1 数据库**\n\n表:\n- users\n- user_permissions\n- cameras\n- live_sessions\n- videos\n- view_stats\n- audit_logs\n\n详见: d1-database.canvas","x":-760,"y":240,"width":280,"height":460,"color":"1"},
+		{"id":"env_vars","type":"text","text":"**环境变量**\n\nCloudflare:\n- CF_ACCOUNT_ID\n- CF_API_TOKEN\n- CUSTOMER_SUBDOMAIN\n\nJWT:\n- JWT_SECRET\n- JWT_EXPIRES_IN\n- REFRESH_EXPIRES_IN\n\nD1:\n- DB binding","x":-760,"y":960,"width":280,"height":480,"color":"4"},
+		{"id":"types","type":"text","text":"**类型定义**\n`src/types/index.ts`\n\n新增:\n- JwtPayload\n- LoginRequest\n- RegisterRequest\n- AuthResponse\n- User\n- UserPermission\n- Camera\n- LiveSession\n- ...","x":560,"y":608,"width":270,"height":435,"color":"5"},
+		{"id":"services_cf","type":"text","text":"**Stream 服务**\n`src/services/cloudflare.ts`\n\nCloudflareStreamService:\n- 视频 CRUD\n- 直播 CRUD\n- 播放信息","x":585,"y":60,"width":220,"height":310,"color":"3"},
+		{"id":"routes_stream","type":"text","text":"**Stream 路由**\n`src/routes/stream.ts`\n\n视频管理 (13个端点)\n直播管理\n\n需认证 ✅","x":585,"y":-360,"width":220,"height":240,"color":"2"},
+		{"id":"routes_user","type":"text","text":"**用户路由**\n`src/routes/user.ts`\n\n需 admin 角色:\n- GET /users\n- GET /users/:id\n- POST /users\n- PUT /users/:id\n- DELETE /users/:id\n\n权限管理:\n- GET /users/:id/permissions\n- POST /users/:id/permissions\n- DELETE /users/:id/permissions/:id","x":110,"y":-500,"width":280,"height":520,"color":"2"},
+		{"id":"title","type":"text","text":"# tg-live-game-hono 架构\n\n**版本**: v1.1.0\n**技术栈**: Hono + Cloudflare Workers + D1\n**状态**: ✅ 已实现\n\n新增功能:\n- JWT 认证\n- 用户管理\n- RBAC 权限","x":-300,"y":-1020,"width":630,"height":340,"color":"6"},
+		{"id":"services_auth","type":"text","text":"**认证服务**\n`src/services/auth.ts`\n\nAuthService:\n- login()\n- register()\n- refreshToken()\n- getCurrentUser()\n- changePassword()\n- logAudit()","x":-300,"y":280,"width":260,"height":380,"color":"3"},
+		{"id":"utils","type":"text","text":"**工具函数**\n`src/utils/`\n\njwt.ts:\n- createToken()\n- verifyToken()\n- generateId()\n\npassword.ts:\n- hashPassword()\n- verifyPassword()\n\n算法: PBKDF2 + HMAC-SHA256","x":200,"y":265,"width":280,"height":410,"color":"4"},
+		{"id":"entry","type":"text","text":"**入口文件**\n`src/index.ts`\n\n功能:\n- Hono 应用初始化\n- CORS/日志中间件\n- 路由挂载\n  - /api/auth (公开)\n  - /api/users (admin)\n  - /api/stream\n\n端口: localhost:8787","x":-760,"y":-760,"width":280,"height":370,"color":"4"},
+		{"id":"middleware","type":"text","text":"**中间件**\n`src/middleware/auth.ts`\n\n- authMiddleware()\n  验证 JWT Token\n- requireRole(roles)\n  角色权限检查\n- requirePermission()\n  资源权限检查\n- optionalAuth()\n  可选认证","x":-760,"y":-240,"width":280,"height":320,"color":"5"},
+		{"id":"routes_auth","type":"text","text":"**认证路由**\n`src/routes/auth.ts`\n\n公开接口:\n- POST /login\n- POST /register\n- POST /refresh\n\n需认证:\n- GET /me\n- POST /change-password\n- POST /logout","x":-300,"y":-240,"width":260,"height":405,"color":"2"}
+	],
+	"edges":[
+		{"id":"edge_entry_mw","fromNode":"entry","fromSide":"bottom","toNode":"middleware","toSide":"top","label":"use()"},
+		{"id":"edge_entry_auth","fromNode":"entry","fromSide":"right","toNode":"routes_auth","toSide":"left","label":"/api/auth"},
+		{"id":"edge_entry_user","fromNode":"entry","fromSide":"right","toNode":"routes_user","toSide":"left","label":"/api/users"},
+		{"id":"edge_user_stream","fromNode":"routes_user","fromSide":"right","toNode":"routes_stream","toSide":"left","label":"/api/stream"},
+		{"id":"edge_auth_service","fromNode":"routes_auth","fromSide":"bottom","toNode":"services_auth","toSide":"top","label":"AuthService"},
+		{"id":"edge_service_utils","fromNode":"services_auth","fromSide":"right","toNode":"utils","toSide":"left","label":"jwt/password"},
+		{"id":"edge_stream_cf","fromNode":"routes_stream","fromSide":"bottom","toNode":"services_cf","toSide":"top","label":"StreamService"},
+		{"id":"edge_mw_db","fromNode":"middleware","fromSide":"bottom","toNode":"database","toSide":"top","label":"权限查询"},
+		{"id":"edge_service_db","fromNode":"services_auth","fromSide":"left","toNode":"database","toSide":"right","label":"用户查询"},
+		{"id":"edge_cf_types","fromNode":"services_cf","fromSide":"bottom","toNode":"types","toSide":"top","label":"import"}
+	]
+}

+ 21 - 0
tg-live-game/tg-live-game-hono/auth-system.canvas

@@ -0,0 +1,21 @@
+{
+	"nodes":[
+		{"id":"title","type":"text","text":"# 认证鉴权系统设计\n\n**方案**: JWT + D1\n**状态**: 📋 设计中\n\n特点:\n- 无状态 JWT 认证\n- 基于角色的访问控制 (RBAC)\n- 细粒度资源权限\n- 边缘计算友好","x":-100,"y":-600,"width":380,"height":160,"color":"6"},
+		{"id":"auth_flow","type":"text","text":"## 认证流程\n\n```\n1. 登录请求\n   POST /api/auth/login\n   { username, password }\n        ↓\n2. 验证密码\n   bcrypt.compare()\n        ↓\n3. 生成 JWT\n   { userId, role, exp }\n        ↓\n4. 返回 Token\n   { accessToken, refreshToken }\n        ↓\n5. 客户端存储\n   Authorization: Bearer <token>\n```","x":-500,"y":-380,"width":300,"height":340,"color":"2"},
+		{"id":"jwt_structure","type":"text","text":"## JWT 结构\n\n**Header**\n```json\n{ \"alg\": \"HS256\", \"typ\": \"JWT\" }\n```\n\n**Payload**\n```json\n{\n  \"sub\": \"user-id\",\n  \"username\": \"admin\",\n  \"role\": \"admin\",\n  \"iat\": 1704067200,\n  \"exp\": 1704153600\n}\n```\n\n**有效期**\n- accessToken: 24h\n- refreshToken: 7d","x":-130,"y":-380,"width":300,"height":320,"color":"4"},
+		{"id":"rbac","type":"text","text":"## RBAC 角色权限\n\n| 角色 | 权限 |\n|------|------|\n| admin | 全部操作 |\n| operator | 摄像头管理、直播控制 |\n| viewer | 仅查看 |\n\n**资源权限**\n```\nuser_permissions 表\n- view: 查看摄像头\n- control: 控制直播\n- manage: 管理配置\n```","x":240,"y":-380,"width":280,"height":280,"color":"3"},
+		{"id":"middleware","type":"text","text":"## 中间件设计\n\n**authMiddleware**\n- 解析 Bearer Token\n- 验证 JWT 签名\n- 检查过期时间\n- 注入 c.set('user', payload)\n\n**requireRole(roles)**\n- 检查用户角色\n- 403 Forbidden\n\n**requirePermission(resource, action)**\n- 查询 user_permissions\n- 检查资源权限","x":-500,"y":20,"width":300,"height":260,"color":"5"},
+		{"id":"api_endpoints","type":"text","text":"## API 端点\n\n**认证**\n- POST /api/auth/login\n- POST /api/auth/register\n- POST /api/auth/refresh\n- POST /api/auth/logout\n- GET  /api/auth/me\n\n**用户管理 (admin)**\n- GET  /api/users\n- GET  /api/users/:id\n- POST /api/users\n- PUT  /api/users/:id\n- DELETE /api/users/:id\n\n**权限管理 (admin)**\n- GET  /api/users/:id/permissions\n- POST /api/users/:id/permissions\n- DELETE /api/permissions/:id","x":-130,"y":0,"width":300,"height":340,"color":"2"},
+		{"id":"file_structure","type":"text","text":"## 文件结构\n\n```\nsrc/\n├── middleware/\n│   └── auth.ts\n├── services/\n│   ├── auth.ts\n│   └── user.ts\n├── routes/\n│   ├── auth.ts\n│   └── user.ts\n├── utils/\n│   ├── jwt.ts\n│   └── password.ts\n└── types/\n    └── index.ts\n```","x":240,"y":-40,"width":280,"height":280,"color":"4"},
+		{"id":"security","type":"text","text":"## 安全措施\n\n- 密码 bcrypt 哈希 (cost=12)\n- JWT 密钥环境变量\n- HTTPS 强制\n- Rate Limiting\n- 登录失败锁定\n- Audit Log 记录\n- CORS 白名单","x":-500,"y":340,"width":300,"height":180,"color":"1"},
+		{"id":"env_config","type":"text","text":"## 环境配置\n\n**.dev.vars**\n```\nJWT_SECRET=your-secret-key\nJWT_EXPIRES_IN=86400\nREFRESH_EXPIRES_IN=604800\n```\n\n**wrangler secret**\n```bash\nwrangler secret put JWT_SECRET\n```","x":-130,"y":400,"width":300,"height":180,"color":"4"},
+		{"id":"protected_routes","type":"text","text":"## 路由保护\n\n**公开路由**\n- /api/auth/login\n- /api/auth/register\n- / (健康检查)\n\n**需要认证**\n- /api/stream/*\n- /api/users/*\n- /api/auth/me\n\n**需要 admin**\n- POST/PUT/DELETE /api/users\n- /api/permissions/*","x":240,"y":300,"width":280,"height":240,"color":"3"}
+	],
+	"edges":[
+		{"id":"edge_flow_jwt","fromNode":"auth_flow","fromSide":"right","toNode":"jwt_structure","toSide":"left","label":"生成"},
+		{"id":"edge_jwt_rbac","fromNode":"jwt_structure","fromSide":"right","toNode":"rbac","toSide":"left","label":"携带 role"},
+		{"id":"edge_mw_api","fromNode":"middleware","fromSide":"right","toNode":"api_endpoints","toSide":"left","label":"保护"},
+		{"id":"edge_api_files","fromNode":"api_endpoints","fromSide":"right","toNode":"file_structure","toSide":"left","label":"实现"},
+		{"id":"edge_mw_security","fromNode":"middleware","fromSide":"bottom","toNode":"security","toSide":"top","label":"安全策略"}
+	]
+}

+ 23 - 0
tg-live-game/tg-live-game-hono/d1-database.canvas

@@ -0,0 +1,23 @@
+{
+	"nodes":[
+		{"id":"title","type":"text","text":"# D1 数据库设计\n\n**数据库名**: tg_live_game\n**引擎**: Cloudflare D1 (SQLite)\n**状态**: 📋 设计中\n\n设计原则:\n- Cloudflare Stream 为主数据源\n- D1 存储业务扩展元数据\n- 支持离线查询和统计","x":-100,"y":-600,"width":380,"height":180,"color":"6"},
+		{"id":"table_cameras","type":"text","text":"**cameras** 摄像头管理\n\n```sql\nid          TEXT PRIMARY KEY\nname        TEXT NOT NULL\ntype        TEXT -- 'mac'|'ip'|'rtsp'\nprotocol    TEXT -- 'rtmps'|'srt'|'whip'\nrtsp_url    TEXT\nlocation    TEXT\nstatus      TEXT -- 'online'|'offline'\nlive_input_id TEXT -- CF Stream ID\ncreated_at  INTEGER\nupdated_at  INTEGER\n```\n\n索引: status, type","x":-500,"y":-340,"width":300,"height":280,"color":"4"},
+		{"id":"table_live_sessions","type":"text","text":"**live_sessions** 直播会话\n\n```sql\nid          TEXT PRIMARY KEY\ncamera_id   TEXT REFERENCES cameras\nlive_input_id TEXT -- CF Stream ID\nstarted_at  INTEGER NOT NULL\nended_at    INTEGER\nduration    INTEGER -- 秒\nstatus      TEXT -- 'live'|'ended'|'error'\nviewer_count INTEGER DEFAULT 0\nrecording_id TEXT -- 录像视频ID\ncreated_at  INTEGER\n```\n\n索引: camera_id, status, started_at","x":-130,"y":-340,"width":320,"height":280,"color":"2"},
+		{"id":"table_videos","type":"text","text":"**videos** 视频元数据\n\n```sql\nid          TEXT PRIMARY KEY\ncf_uid      TEXT UNIQUE -- CF Stream UID\ncamera_id   TEXT REFERENCES cameras\nsession_id  TEXT REFERENCES live_sessions\ntitle       TEXT\ndescription TEXT\ntags        TEXT -- JSON array\nthumbnail   TEXT\nduration    INTEGER\nsize        INTEGER\nstatus      TEXT -- 'ready'|'processing'\nis_public   INTEGER DEFAULT 0\nview_count  INTEGER DEFAULT 0\ncreated_at  INTEGER\nupdated_at  INTEGER\n```\n\n索引: cf_uid, camera_id, status","x":260,"y":-340,"width":320,"height":340,"color":"3"},
+		{"id":"table_users","type":"text","text":"**users** 用户管理\n\n```sql\nid          TEXT PRIMARY KEY\nusername    TEXT UNIQUE\nemail       TEXT UNIQUE\npassword_hash TEXT\nrole        TEXT -- 'admin'|'operator'|'viewer'\nstatus      TEXT -- 'active'|'disabled'\nlast_login  INTEGER\ncreated_at  INTEGER\nupdated_at  INTEGER\n```\n\n索引: username, email, role","x":-500,"y":0,"width":300,"height":240,"color":"5"},
+		{"id":"table_permissions","type":"text","text":"**user_permissions** 权限\n\n```sql\nid          TEXT PRIMARY KEY\nuser_id     TEXT REFERENCES users\ncamera_id   TEXT REFERENCES cameras\npermission  TEXT -- 'view'|'control'|'manage'\ngranted_at  INTEGER\ngranted_by  TEXT REFERENCES users\n```\n\n索引: user_id, camera_id","x":-130,"y":0,"width":320,"height":200,"color":"5"},
+		{"id":"table_view_stats","type":"text","text":"**view_stats** 观看统计\n\n```sql\nid          TEXT PRIMARY KEY\nvideo_id    TEXT REFERENCES videos\nsession_id  TEXT REFERENCES live_sessions\nuser_id     TEXT -- 可为空(匿名)\nip_address  TEXT\nuser_agent  TEXT\nwatch_duration INTEGER -- 秒\nstarted_at  INTEGER\nended_at    INTEGER\ncountry     TEXT\ncity        TEXT\n```\n\n索引: video_id, session_id, started_at","x":260,"y":60,"width":320,"height":260,"color":"1"},
+		{"id":"table_audit_logs","type":"text","text":"**audit_logs** 操作日志\n\n```sql\nid          TEXT PRIMARY KEY\nuser_id     TEXT REFERENCES users\naction      TEXT -- 'create'|'update'|'delete'\nresource    TEXT -- 'camera'|'video'|'user'\nresource_id TEXT\ndetails     TEXT -- JSON\nip_address  TEXT\ncreated_at  INTEGER\n```\n\n索引: user_id, action, created_at","x":-500,"y":300,"width":300,"height":220,"color":"1"},
+		{"id":"er_diagram","type":"text","text":"## ER 关系图\n\n```\nusers ──1:N──> user_permissions\n  │                  │\n  │                  v\n  │            cameras ──1:N──> live_sessions\n  │               │                   │\n  │               │                   v\n  └──1:N──> audit_logs         videos <──1:N── view_stats\n```\n\n核心关系:\n- 摄像头 → 多个直播会话\n- 直播会话 → 录像视频\n- 用户 → 摄像头权限","x":-130,"y":260,"width":320,"height":260,"color":"6"},
+		{"id":"wrangler_config","type":"text","text":"## wrangler.toml 配置\n\n```toml\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"tg_live_game\"\ndatabase_id = \"<your-database-id>\"\n```\n\n## 创建命令\n\n```bash\nwrangler d1 create tg_live_game\nwrangler d1 execute tg_live_game \\\n  --file=./schema.sql\n```","x":260,"y":380,"width":320,"height":240,"color":"4"},
+		{"id":"5aa4ab97e1a61931","x":-780,"y":-710,"width":500,"height":310,"type":"text","text":"任务20260101-01\n\n数据库备份\n\n1. 要求如下\n\n2. 每天备份一次,文件要按照日期命名\n"}
+	],
+	"edges":[
+		{"id":"edge_camera_session","fromNode":"table_cameras","fromSide":"right","toNode":"table_live_sessions","toSide":"left","label":"1:N"},
+		{"id":"edge_session_video","fromNode":"table_live_sessions","fromSide":"right","toNode":"table_videos","toSide":"left","label":"1:1"},
+		{"id":"edge_user_perm","fromNode":"table_users","fromSide":"right","toNode":"table_permissions","toSide":"left","label":"1:N"},
+		{"id":"edge_perm_camera","fromNode":"table_permissions","fromSide":"top","toNode":"table_cameras","toSide":"bottom","label":"N:1"},
+		{"id":"edge_video_stats","fromNode":"table_videos","fromSide":"bottom","toNode":"table_view_stats","toSide":"top","label":"1:N"},
+		{"id":"edge_user_audit","fromNode":"table_users","fromSide":"bottom","toNode":"table_audit_logs","toSide":"top","label":"1:N"}
+	]
+}

+ 152 - 0
tg-live-game/tg-live-game-hono/workflow.md

@@ -0,0 +1,152 @@
+# 开发工作流
+
+> 本文档描述 Obsidian + Vibe Kanban + Claude Code 三者协作的工作流程
+
+## 三者关系
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│  Obsidian (文档中心 - 单一数据源)                                  │
+│  路径: /Users/jamesw/dev_workspace/vibe-coding-cn                │
+│  ├── 架构设计 (*.canvas)                                         │
+│  ├── 需求文档                                                    │
+│  └── 任务卡片 → 同步到 Kanban                                     │
+└─────────────────────────────────────────────────────────────────┘
+                         ↓ 读取文档 / 同步任务
+┌─────────────────────────────────────────────────────────────────┐
+│  Vibe Kanban (任务管理)                                           │
+│  ├── Project: tg-live-game-hono                                  │
+│  ├── Project ID: 7c6bb2ce-90a2-4e96-bc04-5facdcdb337f            │
+│  └── 任务状态: todo → inprogress → inreview → done               │
+└─────────────────────────────────────────────────────────────────┘
+                         ↓ 领取任务 / 执行开发
+┌─────────────────────────────────────────────────────────────────┐
+│  Claude Code (代码开发)                                           │
+│  工作目录: /Users/jamesw/dev_workspace/frontend/tg-live-game/    │
+│           tg-live-game-hono                                      │
+│  ├── 读取 Obsidian 架构文档                                       │
+│  ├── 根据 Kanban 任务开发                                         │
+│  └── 完成后更新任务状态                                            │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+## 工作流程
+
+### 1. 需求设计阶段 (Obsidian)
+
+在 Obsidian 的 canvas 中设计架构和需求:
+
+1. 打开相关的 `.canvas` 文件
+2. 添加新的组件/功能卡片
+3. 使用任务卡片格式标记待开发内容:
+
+```
+任务YYYYMMDD-NN
+─────────────────
+任务标题
+
+1. 需求描述
+2. 具体要求
+3. ...
+```
+
+### 2. 任务同步阶段 (Obsidian → Kanban)
+
+当 canvas 有新的任务卡片时:
+
+1. Claude Code 读取 canvas 文件
+2. 解析新增的任务卡片
+3. 提取任务名称和描述
+4. 调用 Vibe Kanban API 创建任务
+
+**同步命令示例**:
+```
+"同步 d1-database.canvas 的新任务到 Kanban"
+```
+
+### 3. 开发阶段 (Claude Code)
+
+1. 从 Kanban 获取任务
+2. 读取 Obsidian 文档理解架构
+3. 在代码目录执行开发
+4. 完成后提交代码
+
+### 4. 任务完成阶段
+
+1. 代码提交到 git
+2. 更新 Kanban 任务状态为 `done`
+3. 如有需要,更新 Obsidian 文档
+
+## 文件路径映射
+
+| 位置 | 路径 | 用途 |
+|------|------|------|
+| Obsidian 文档 | `/Users/jamesw/dev_workspace/vibe-coding-cn/tg-live-game/tg-live-game-hono/` | 架构设计、需求文档 |
+| 代码仓库 | `/Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono/` | 代码实现 |
+| Claude 配置 | `{代码仓库}/CLAUDE.md` | 项目关联配置 |
+
+## 任务卡片规范
+
+### 格式
+```
+任务YYYYMMDD-NN
+
+任务标题
+
+1. 第一个要求
+2. 第二个要求
+...
+```
+
+### 示例
+```
+任务20260101-01
+
+数据库备份
+
+1. 要求如下
+2. 每天备份一次,文件要按照日期命名
+```
+
+### 解析规则
+- **任务编号**: `任务YYYYMMDD-NN` 格式,用于唯一标识
+- **任务标题**: 编号后的第一行非空文本
+- **任务描述**: 剩余所有内容
+
+## 多项目协作
+
+当任务涉及前后端同时开发时,参考父项目的工作流文档:[[../workflow]]
+
+### Claude Code 启动位置
+
+```bash
+# 仅后端开发
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono
+claude
+
+# 前后端协作(推荐)
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game
+claude
+```
+
+### 关联任务格式
+
+```
+任务YYYYMMDD-NN-hono
+─────────────────
+后端:功能名称
+
+project: tg-live-game-hono
+related: 任务YYYYMMDD-NN-web
+
+1. 需求描述
+```
+
+## 相关文件
+
+- [[architecture]] - 整体架构设计
+- [[auth-system]] - 认证鉴权系统
+- [[d1-database]] - 数据库设计
+- [[README]] - 项目概述
+- [[../workflow]] - 父项目工作流(多项目协作)
+- [[../_project]] - 父项目配置

+ 242 - 0
tg-live-game/workflow.md

@@ -0,0 +1,242 @@
+# 开发工作流
+
+> 本文档描述 Obsidian + Vibe Kanban + Claude Code 三者协作的工作流程
+
+## 三者角色定位
+
+| 角色 | 定位 | 特点 |
+|------|------|------|
+| **Obsidian** | 设计中心 | 批量规划、可视化设计、长期文档 |
+| **Vibe Kanban** | 任务中心 | 状态管理、进度追踪、快速创建 |
+| **Claude Code** | 执行中心 | 连接两者,执行开发 |
+
+## 任务创建的两种路径
+
+### 路径 A:从 Kanban 直接创建(快速任务)
+
+```
+用户在 Kanban 创建任务
+         ↓
+Claude Code 读取任务
+         ↓
+Claude Code 查阅 Obsidian 文档理解上下文
+         ↓
+执行开发
+         ↓
+更新 Kanban 状态
+```
+
+**适用场景**:bug 修复、小功能迭代、不需要详细设计的任务
+
+### 路径 B:从 Obsidian Canvas 批量创建(规划任务)
+
+```
+用户在 Obsidian Canvas 设计架构
+         ↓
+添加任务卡片(带 project/depends 字段)
+         ↓
+Claude Code 解析 Canvas
+         ↓
+同步到对应的 Kanban 项目
+         ↓
+按依赖顺序执行开发
+         ↓
+更新 Kanban 状态
+```
+
+**适用场景**:新功能规划、前后端联动开发、批量任务创建
+
+## 数据同步方向
+
+| 从 → 到 | 方式 | 说明 |
+|---------|------|------|
+| Obsidian → Kanban | 手动命令 | Canvas 任务卡片同步到看板 |
+| Kanban → Claude | 自动读取 | 开发时读取任务列表 |
+| Claude → Kanban | 自动更新 | 完成后更新任务状态 |
+| Obsidian → Claude | 只读查阅 | 读取架构文档理解需求 |
+
+## 三者关系
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│  Obsidian (文档中心 - 单一数据源)                                  │
+│  路径: /Users/jamesw/dev_workspace/vibe-coding-cn/tg-live-game   │
+│  ├── 架构设计 (*.canvas)                                         │
+│  ├── 需求文档                                                    │
+│  └── 任务卡片 → 同步到 Kanban                                     │
+└─────────────────────────────────────────────────────────────────┘
+                         ↓ 读取文档 / 同步任务
+┌─────────────────────────────────────────────────────────────────┐
+│  Vibe Kanban (任务管理)                                           │
+│  ├── tg-live-game-hono: 7c6bb2ce-90a2-4e96-bc04-5facdcdb337f    │
+│  ├── tg-live-game-web:  32214e97-f833-485f-8c7c-cf4d82327e0b    │
+│  └── 任务状态: todo → inprogress → inreview → done               │
+└─────────────────────────────────────────────────────────────────┘
+                         ↓ 领取任务 / 执行开发
+┌─────────────────────────────────────────────────────────────────┐
+│  Claude Code (代码开发)                                           │
+│  启动目录: /Users/jamesw/dev_workspace/frontend/tg-live-game/    │
+│  ├── tg-live-game-hono/  (后端)                                  │
+│  └── tg-live-game-web/   (前端)                                  │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+## 多项目协作工作流
+
+### 场景:同时设计前后端功能
+
+当一个功能需要前后端同时开发时(如"用户列表"功能):
+
+```
+1. Obsidian 设计阶段
+   ├── 在 canvas 画架构图
+   └── 创建两个关联的任务卡片
+       ├── 任务20260103-01-hono (后端 API)
+       └── 任务20260103-01-web  (前端页面)
+
+2. 任务同步阶段
+   ├── 解析任务卡片的 project 字段
+   ├── hono 任务 → tg-live-game-hono Kanban
+   └── web 任务 → tg-live-game-web Kanban
+
+3. Claude Code 开发阶段
+   ├── 在父目录 tg-live-game 启动
+   ├── 读取关联任务,理解依赖关系
+   ├── 先开发后端 (depends 优先)
+   └── 再开发前端
+
+4. 代码提交阶段
+   ├── cd tg-live-game-hono && git commit
+   └── cd tg-live-game-web && git commit
+```
+
+## 任务卡片格式
+
+### 单项目任务
+
+```
+任务YYYYMMDD-NN
+
+任务标题
+
+project: tg-live-game-hono
+
+1. 需求描述
+2. 具体要求
+```
+
+### 关联任务(前后端)
+
+**后端任务**:
+```
+任务YYYYMMDD-NN-hono
+─────────────────
+后端:用户列表 API
+
+project: tg-live-game-hono
+related: 任务YYYYMMDD-NN-web
+
+1. 实现 GET /api/users
+2. 返回分页数据
+```
+
+**前端任务**:
+```
+任务YYYYMMDD-NN-web
+─────────────────
+前端:用户列表页面
+
+project: tg-live-game-web
+related: 任务YYYYMMDD-NN-hono
+depends: 任务YYYYMMDD-NN-hono
+
+1. 调用用户列表 API
+2. 表格展示用户数据
+```
+
+### 字段说明
+
+| 字段 | 含义 | 用途 |
+|------|------|------|
+| `project` | 目标 Kanban 项目名 | 决定任务创建到哪个看板 |
+| `related` | 关联任务编号 | 表示任务之间的关系 |
+| `depends` | 依赖任务编号 | 表示需要先完成的任务 |
+
+## 文件路径映射
+
+| 位置 | 路径 | 用途 |
+|------|------|------|
+| Obsidian 项目文档 | `vibe-coding-cn/tg-live-game/` | 架构设计、需求文档 |
+| Obsidian 后端文档 | `vibe-coding-cn/tg-live-game/tg-live-game-hono/` | 后端架构 |
+| Obsidian 前端文档 | `vibe-coding-cn/tg-live-game/tg-live-game-web/` | 前端架构 |
+| 代码父目录 | `frontend/tg-live-game/` | Claude Code 启动位置 |
+| 后端代码 | `frontend/tg-live-game/tg-live-game-hono/` | Hono API |
+| 前端代码 | `frontend/tg-live-game/tg-live-game-web/` | Vue 应用 |
+
+## Claude Code 启动说明
+
+```bash
+# 多项目开发(推荐)
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game
+claude
+
+# 单项目开发(仅后端)
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-hono
+claude
+
+# 单项目开发(仅前端)
+cd /Users/jamesw/dev_workspace/frontend/tg-live-game/tg-live-game-web
+claude
+```
+
+## 交替式开发模式(批量任务)
+
+当 Obsidian 一次性创建多个前后端任务,需要交替开发和验证时:
+
+### 依赖链设计
+
+用 `depends` 字段串联任务,形成执行顺序:
+
+```
+任务01-hono (后端 API A)     ← 无依赖,最先执行
+    ↓
+任务01-web  (前端调用 A)     depends: 任务01-hono
+    ↓
+任务02-hono (后端 API B)     depends: 任务01-web
+    ↓
+任务02-web  (前端调用 B)     depends: 任务02-hono
+    ↓
+...
+```
+
+### Canvas 中的表示
+
+```
+┌──────────────────┐     ┌──────────────────┐
+│ 任务01-hono      │ ──→ │ 任务01-web       │
+│ 后端:用户列表   │     │ 前端:用户列表   │
+│ project: hono    │     │ depends: 01-hono │
+└──────────────────┘     └──────────────────┘
+                              │
+                              ↓ depends
+┌──────────────────┐     ┌──────────────────┐
+│ 任务02-hono      │ ──→ │ 任务02-web       │
+│ 后端:用户详情   │     │ 前端:用户详情   │
+│ depends: 01-web  │     │ depends: 02-hono │
+└──────────────────┘     └──────────────────┘
+```
+
+### 执行顺序
+
+Claude Code 按 `depends` 链自动排序执行:
+1. 任务01-hono → 开发后端 API A
+2. 任务01-web → 开发前端调用 A,验证
+3. 任务02-hono → 开发后端 API B
+4. 任务02-web → 开发前端调用 B,验证
+
+## 相关文档
+
+- [[architecture-v1]] - 整体系统架构
+- [[tg-live-game-hono/_project]] - 后端项目配置
+- [[tg-live-game-hono/workflow]] - 后端开发工作流
+- [[tg-live-game-web/_project]] - 前端项目配置