当前位置: 首页 > news >正文

怎么把管屏幕三个字拆成9张数据库表

前两篇聊了为什么要做、跟别人的区别在哪。这篇是动手前最重要的一步:拆需求。

你接到的需求是"做一个数字标牌管理系统"。八个字。但系统长什么样?一个字都没说。

这就是独立开发者和外包的区别——外包会去反复确认需求,独立开发者要学会自己拆。


从一句话到一张图

"管屏幕"这三个字,听起来简单,仔细想其实有四层:

第一层:屏幕本身。有几块屏幕?什么型号?分辨率多少?横着还是竖着?在线还是离线?——这是设备管理。

第二层:屏幕上放什么。图片、视频、轮播图、文档。这些东西从哪来?怎么分类?——这是素材管理。

第三层:什么时候放什么。工作日放促销广告,周末放品牌宣传。早上 9 点员工上班放欢迎页,晚上打烊放"明日营业时间"。——这是节目编排。

第四层:放了之后呢。播了没有?播了几次?有没有报错?——这是播放统计。

还有一个横切面:谁来操作?老板能删素材,店员只能看。——这是用户权限。

五块东西,在纸上画就是一张图:

┌─ 用户权限 (横切) │ 设备管理 ──┤ 素材管理 ──┼── 节目编排 ──→ 播放统计 │

从图到数据库

画完图,下一步是把每个模块变成表。

这一步没什么高深的——就是问自己:这个东西有什么属性?

设备有什么属性?编号、名称、型号、分辨率、布局模板、IP 地址、在线状态、上次心跳时间、属于哪个分组。

翻译成 SQL:

CREATETABLEt_device(idBIGINTPRIMARYKEY,device_noVARCHAR(50)NOTNULL,-- 设备编号nameVARCHAR(100)NOTNULL,-- 设备名称modelVARCHAR(50),-- double_side/stand/wallresolutionVARCHAR(20),-- 1920x1080layout_templateVARCHAR(50),-- single/split_h/split_vstatusVARCHAR(20)DEFAULT'offline',-- online/offline/errorgroup_idBIGINT,-- 属于哪个分组last_heartbeatDATETIME,-- 最后心跳时间...);

素材有什么属性?名称、类型(图片/视频/轮播/文档)、属于哪个分类、文件地址、缩略图、文件大小、播放时长。

节目有什么属性?名称、开始时间、结束时间、排期类型(单次/每天/每周/自定义)、状态(草稿/已发布/已过期)。

中间还有个关键表:节目和素材的关联。一个节目里有多个素材,每个素材有一个播放顺序(sort_order)。多分区屏幕的话,每个素材还有一个区域编号(zone_index)。

这就多了一张关联表:

CREATETABLEt_program_material(program_idBIGINT,material_idBIGINT,zone_indexINTDEFAULT0,-- 在屏幕哪个区域sort_orderINTDEFAULT0,-- 播放顺序durationINT-- 这个素材播几秒);

最终,9 张表:

干什么的
t_user登录用户
t_device_group设备分组
t_device设备信息 + 心跳
t_material_category素材分类(树形)
t_material素材文件
t_program节目单
t_program_material节目里有哪些素材
t_device_command设备远程指令
t_play_log播放记录

拆需求的两个原则

做了几个项目之后,我拆需求有两个原则。

第一,一张表只干一件事。

素材分类和素材是两张表。设备分组和设备是两张表。不要因为"可以用一个字段代替"就合并——分开之后,你改分类名称,素材表一行都不用动。

第二,先想"查什么",再定"怎么存"。

设计t_play_log的时候,我先想的不是字段,是查询场景:“查这台设备昨天的播放记录”“查这个素材总共被播了多少次”“哪个设备报错最多”。

然后才加索引:(device_id, created_at)(program_id)


下篇开始动手写代码。第一件事:搭开发环境。JDK 装不上、Maven 配不对、MySQL 密码忘了——这些我都踩过。



关于作者:无羡,独立开发者,全栈工程师,专注 AI 应用与微服务架构。

📌 分类:技术复盘

🔗 个人博客 — 更多技术文章
✨ 开发者福利整理 — 云服务资源汇总
📂 软件工坊 — 我的技术分享
🌐 个人门户 — 独立开发作品全集

http://www.jsqmd.com/news/1272712/

相关文章:

  • C++高性能序列化与数据传输:大数据架构师的底层优化指南
  • Python自动化时间盲注脚本实战:从原理到高效渗透工具开发
  • Kimi LeetCode 3739. 统计主要元素子数组数目 II C语言实现
  • Linux网络排查利器:ss命令原理、实战与netstat替代指南
  • C++二进制文件操作:深入解析std::string序列化原理与避坑指南
  • 光伏发电系统仿真与变步长MPPT算法实践
  • 推动技术成果转化 让创新落地服务实际需求
  • Dify安装与Ollama模型接入
  • 基于Matlab的移动机器人路径规划与PID控制仿真
  • 得物App sign签名逆向:MD5加密常见错误与排查方案详解
  • 国产SPC工具在离散制造中的动态控制与边缘计算应用
  • C 语言循环与自增运算符组合对比分析
  • LangChain Memory机制详解与应用实践
  • LLM结构化输出对回答多样性的影响与平衡策略
  • 羽毛球剪辑算法集锦
  • C++异常处理终极防线:std::terminate触发机制与二次异常规避
  • 大模型技术全解析:从理论到工程实践
  • 使用JPEXS FFDec逆向分析SWF文件中的自定义加密算法与密钥生成
  • AI大模型应用开发工程师:技术落地与商业价值
  • 微信防撤回补丁失效?逆向工程实战:从内存修改到开源方案
  • Python历史事件爬虫系统:架构设计与实战技巧
  • 平衡二叉树、相交链表与随机指针链表的LeetCode经典题解析
  • AI治理中的技术尊严:易经三原则与动态伦理评估
  • 千笔AI如何解决MBA论文写作五大痛点
  • 上海做宴会厅隔断的厂家哪个好 2026年正规厂家实力与用户口碑 - 工业品牌热点
  • AIGC检测与抄袭检测的技术差异与应用实践
  • TMS320C30同步串口实现异步RS-232通信的软硬件协同设计
  • 你的 self.name = value 为何“绕道”了?——Python 数据描述符的优先级霸权与实例属性消失之谜
  • TI多核SoC处理器追踪实战:从Cortex-A15到EVE的调试与性能优化
  • 智能体技术提升个人效率的实践与优化