{ "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 = \"\"\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"} ] }