d1-database.canvas 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. {
  2. "nodes": [
  3. {
  4. "id": "title",
  5. "type": "text",
  6. "text": "# D1 数据库设计\n\n**数据库名**: tg_live_game\n**引擎**: Cloudflare D1 (SQLite)\n**状态**: 📋 设计中\n\n设计原则:\n- Cloudflare Stream 为主数据源\n- D1 存储业务扩展元数据\n- 支持离线查询和统计",
  7. "x": -100,
  8. "y": -600,
  9. "width": 380,
  10. "height": 180,
  11. "color": "6"
  12. },
  13. {
  14. "id": "table_cameras",
  15. "type": "text",
  16. "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",
  17. "x": -500,
  18. "y": -340,
  19. "width": 300,
  20. "height": 280,
  21. "color": "4"
  22. },
  23. {
  24. "id": "table_live_sessions",
  25. "type": "text",
  26. "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",
  27. "x": -130,
  28. "y": -340,
  29. "width": 320,
  30. "height": 280,
  31. "color": "2"
  32. },
  33. {
  34. "id": "table_videos",
  35. "type": "text",
  36. "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",
  37. "x": 260,
  38. "y": -340,
  39. "width": 320,
  40. "height": 340,
  41. "color": "3"
  42. },
  43. {
  44. "id": "table_users",
  45. "type": "text",
  46. "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",
  47. "x": -500,
  48. "y": 0,
  49. "width": 300,
  50. "height": 240,
  51. "color": "5"
  52. },
  53. {
  54. "id": "table_permissions",
  55. "type": "text",
  56. "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",
  57. "x": -130,
  58. "y": 0,
  59. "width": 320,
  60. "height": 200,
  61. "color": "5"
  62. },
  63. {
  64. "id": "table_view_stats",
  65. "type": "text",
  66. "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",
  67. "x": 260,
  68. "y": 60,
  69. "width": 320,
  70. "height": 260,
  71. "color": "1"
  72. },
  73. {
  74. "id": "table_audit_logs",
  75. "type": "text",
  76. "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",
  77. "x": -500,
  78. "y": 300,
  79. "width": 300,
  80. "height": 220,
  81. "color": "1"
  82. },
  83. {
  84. "id": "er_diagram",
  85. "type": "text",
  86. "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- 用户 → 摄像头权限",
  87. "x": -130,
  88. "y": 260,
  89. "width": 320,
  90. "height": 260,
  91. "color": "6"
  92. },
  93. {
  94. "id": "wrangler_config",
  95. "type": "text",
  96. "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```",
  97. "x": 260,
  98. "y": 380,
  99. "width": 320,
  100. "height": 240,
  101. "color": "4"
  102. }
  103. ],
  104. "edges": [
  105. {
  106. "id": "edge_camera_session",
  107. "fromNode": "table_cameras",
  108. "fromSide": "right",
  109. "toNode": "table_live_sessions",
  110. "toSide": "left",
  111. "label": "1:N"
  112. },
  113. {
  114. "id": "edge_session_video",
  115. "fromNode": "table_live_sessions",
  116. "fromSide": "right",
  117. "toNode": "table_videos",
  118. "toSide": "left",
  119. "label": "1:1"
  120. },
  121. {
  122. "id": "edge_user_perm",
  123. "fromNode": "table_users",
  124. "fromSide": "right",
  125. "toNode": "table_permissions",
  126. "toSide": "left",
  127. "label": "1:N"
  128. },
  129. {
  130. "id": "edge_perm_camera",
  131. "fromNode": "table_permissions",
  132. "fromSide": "top",
  133. "toNode": "table_cameras",
  134. "toSide": "bottom",
  135. "label": "N:1"
  136. },
  137. {
  138. "id": "edge_video_stats",
  139. "fromNode": "table_videos",
  140. "fromSide": "bottom",
  141. "toNode": "table_view_stats",
  142. "toSide": "top",
  143. "label": "1:N"
  144. },
  145. {
  146. "id": "edge_user_audit",
  147. "fromNode": "table_users",
  148. "fromSide": "bottom",
  149. "toNode": "table_audit_logs",
  150. "toSide": "top",
  151. "label": "1:N"
  152. }
  153. ]
  154. }