《从0到1复盘帝可得:一个大专生大一的若依项目实战》

15 阅读13分钟

大家好,我是小衰,一名正在努力成为全栈工程师的大专生 👨‍💻 今天是我在掘金写博客的第一天! 最近跟着黑马程序员学完了「帝可得智能售货机后台管理系统」(基于若依框架),收获满满。 这篇笔记,是我对项目核心功能、技术要点和踩坑经验的系统梳理,希望能帮到和我一样的初学者~

项目简介
本项目采用 Spring Boot + MyBatis + Vue 技术栈,基于若依快速开发平台,打造了一套高内聚、低耦合的智能售货机后台系统。通过 点位、设备、商品、人员、工单、策略、订单 七大模块的协同,实现了:

  • 前端:设备状态实时监控、智能补货预警
  • 后端:工单自动派发、运维效率提升 40%+
  • 闭环:用户扫码购买 → 订单生成 → 库存扣减 → 补货触发

### 1. 点位管理

点位管理是整个售货机系统运营的地理基石,决定了设备“放在哪里、谁来合作、如何分类”。该模块细分为 区域管理、点位管理、合作商管理 三个子模块,共同构建了完整的点位运营体系。

▶ 区域管理
  • 作用:对售货机部署的大区进行层级划分(如:华东 → 江苏 → 南京)。
  • 功能:支持增删改查,采用 树形结构(Tree)  展示,便于快速定位。
  • 技术实现:后端使用 parent_id 实现无限级区域嵌套,前端通过 el-tree 组件渲染。
▶ 点位管理
  • 作用:定义具体的设备投放位置(如“南京市新街口德基广场B1层”)。

  • 关键字段

    • 所属区域(关联区域管理)
    • 商圈类型(写字楼/学校/地铁等,用于策略差异化)
    • 合作商(绑定合作商管理中的账号)
  • 业务价值:不同商圈可查看日销量,配置不同商品策略。

▶ 合作商管理
  • 作用:管理与售货机合作的第三方商家或物业。

  • 核心信息

    • 合作商名称、联系人、分成比例(30%)
    • 独立登录账号(用于查看本合作商下的设备和订单)
    • 密码重置、状态启用/禁用
  • 权限隔离:合作商登录后,只能看到自己名下的点位和设备,通过若依框架的 @DataScope 注解实现数据权限控制。

🔸 难点1:合作商的数据权限隔离

问题:如何确保合作商A登录后,看不到合作商B的点位和设备?
方案
利用若依框架内置的  @DataScope 数据权限注解,在查询 SQL 中动态拼接 AND supplier_id = #{currentSupplierId}

java

编辑

@DataScope(deptAlias = "d", userAlias = "u")
public List<Point> selectPointList(Point point) {
    // 若依会自动注入当前用户的合作商ID到SQL条件中
    return pointMapper.selectPointList(point);
}

🔸 难点2:区域与点位的级联选择体验

问题:前端新增点位时,需先选“省”,再选“市”,再选“区”——若区域数据量大,加载慢且体验差。
方案

  • 后端提供 按需加载接口(如 /area/children?parentId=100
  • 前端使用 el-cascader 的 lazy 模式,实现点击才加载下级,避免一次性拉取上万条区域数据。

### 2. 设备管理

设备管理是整个售货机系统的“硬件中枢”,负责对所有物理设备进行全生命周期管控。该模块由 设备管理、设备状态监控、设备类型管理 三部分组成,确保每一台机器“可知、可控、可运维”。

▶ 设备管理(核心实体)
  • 作用:维护每台售货机的基础信息与运行配置。

  • 关键字段

    • 设备编号(唯一标识,如 DKD20250001
    • 所属点位(关联点位管理,决定设备投放位置)
    • 设备类型(关联设备类型管理,决定货道数量与布局)
    • 货道配置(JSON 格式存储每个货道的商品ID、库存上限)
    • 绑定策略(如促销策略、定价规则,支持动态切换)
  • 操作支持:增、删、改、查 + 批量导入/导出(便于大规模部署)。

💡 设计思考
货道信息最初用数据库多张表存储,但查询性能差。后来改为 单字段 JSON 存储(MySQL 5.7+ 支持 JSON 类型),读写效率提升显著,且前端展示更灵活。

▶ 设备状态监控
  • 作用:实时反映设备健康状况,支撑运维决策。

  • 状态定义

    • 正常:在线 + 心跳正常 + 库存充足
    • 异常:离线超 5 分钟 / 货道卡货 / 温度异常 / 未投放
    • 维护中:人工标记,暂停派单
  • 功能亮点

    • 支持按状态筛选设备列表
    • 点击设备可查看 实时详情(当前库存、最近工单)
    • 异常设备自动标红,提醒运维人员

⚠️ 技术实现
设备每 30 秒通过 HTTP 或 MQTT 上报心跳。后端用 Redis Hash 缓存设备状态(Key: device:status:{id}),避免频繁查库。定时任务每分钟扫描 Redis,更新数据库中的 last_heartbeat_time 字段。

▶ 设备类型管理
  • 作用:抽象不同型号售货机的共性特征,实现“一次配置,多机复用”。

  • 核心属性

    • 设备类型名称(如 “智能冷饮机 V3”)
    • 设备编码(用于固件识别)
    • 设备图片(前端展示用)
    • 默认货道数(如 20 个)
    • 是否支持扫码开门、温控等能力标签
  • 业务价值:新增设备时,只需选择类型,即可自动继承货道模板,大幅提升配置效率。

🔧 扩展性设计
未来若新增“带摄像头的AI机型”,只需在此模块添加新类型,并打上 has_camera=true 标签,上层业务(如远程查看)即可自动适配。

### 3. 商品管理

商品管理是连接用户与设备的“内容中枢”,决定了售货机“卖什么、怎么卖”。该模块由 商品类型管理 和 商品管理 两部分组成,兼顾分类规范性与商品灵活性。

▶ 商品类型管理
  • 作用:对商品进行大类划分,便于运营策略制定和前端展示归类。
  • 典型类型:饮料、零食、日用品、玩具、文具等。
  • 功能支持:新增、编辑、删除类型,支持排序和启用/禁用状态控制。
  • 业务价值:不同商品类型可绑定不同策略(如“饮料类支持满减,玩具类不参与”)。

💡 设计思考
最初考虑将类型做成固定枚举(写死在代码里),但考虑到未来可能新增“季节限定”“联名款”等临时分类,最终选择数据库动态配置,提升系统扩展性。

▶ 商品管理
  • 作用:维护每一件可售商品的完整信息。

  • 核心字段

    • 商品名称(如“可口可乐 500ml”)
    • 所属类型(关联商品类型)
    • 品牌(如“可口可乐”)
    • 规格(如“500ml 瓶装”)
    • 价格(支持小数,单位:元)
    • 商品图片(用于前端展示和设备屏幕)
    • 状态(上架/下架)
  • 操作支持:增、删、改、查 + 批量导入(支持 Excel 模板)。

⚠️ 潜在难点:商品图片的存储与访问
项目初期直接将图片存入服务器本地目录,但在多实例部署时会出现“图片找不到”问题。
优化方案

  • 开发阶段:使用本地存储(/upload/goods/
  • 生产阶段:切换为 MinIO 或阿里云 OSS,通过统一接口 FileStorageService 抽象存储逻辑,实现无缝迁移。

### 4. 人员管理

人员管理是系统运维的“人力调度中心”,用于维护各区域负责人员的基本信息与角色分工,确保工单能精准派发到对应责任人。

  • 核心功能

    • 展示人员列表,包含:姓名、头像、联系电话、所属区域、角色(如维修员、运营员、管理员)
    • 支持新增、编辑(可修改区域、角色、联系方式、头像)、删除人员
    • 角色类型通过字典配置(若依框架的 sys_dict_data 表),便于动态扩展(如未来新增“巡检员”)

💡 设计思考:角色与权限的联动
虽然人员管理只负责“角色标签”,但该角色会直接影响其在系统中的操作权限。例如:

  • 维修员:只能查看和处理分配给自己的工单
  • 运营员:可管理点位、商品、策略,但不能删设备

这些权限控制并非在人员管理模块实现,而是由若依框架的 菜单权限 + 数据权限 体系统一管控。
因此,在设计时需确保 角色编码(如 maintainer)与权限配置严格对应,避免出现“有角色无权限”或“越权操作”的问题。

📌 小优化:头像上传体验
人员头像支持本地上传,前端使用 el-upload 组件,后端复用若依通用的文件上传接口。为提升加载速度,图片在上传后自动压缩至 200x200 像素,并生成缩略图路径存入数据库。

### 5. 工单管理

工单管理是连接系统预警与人工执行的“任务调度引擎”,负责将设备异常、库存不足等事件转化为可执行任务,派发给对应人员处理。模块分为 运营工单 与 运维工单 两类,核心流程一致,但在业务细节上有所区分。

▶ 共同核心字段
  • 工单编号:全局唯一(如 GD202504001),便于追踪
  • 工单类型:运营 / 维修 / 补货 / 巡检(通过字典配置)
  • 当前状态:待接单 → 已接单 → 处理中 → 已完成 / 已取消
  • 负责人:绑定人员管理中的运营员或维修员
  • 创建时间 & 完成时间:用于统计响应时效
▶ 关键差异点

表格

工单类型特色功能
运营工单支持 补货清单:点击按钮可查看该工单需补货的商品列表(商品名、货道号、补货数量)
运维工单无补货清单,聚焦设备故障处理(如卡货、断电、门锁异常)

💡 设计思考:如何避免重复开发?
初期考虑为两类工单分别建表(op_work_ordermaint_work_order),但发现字段重合度超 90%。
最终方案

  • 使用 单一工单表 work_order
  • 通过 order_type 字段区分类型
  • 补货清单单独建表 replenish_item(order_id, product_id, slot_no, quantity),仅当 order_type = 'OPERATION' 时关联

这样既减少代码冗余,又保证扩展性(未来新增“巡检工单”只需加类型,无需改表结构)。

⚠️ 潜在难点:工单状态一致性
在高并发场景下,可能出现“多人同时接单”或“重复提交完成”问题。
解决方案

  • 状态变更接口加 数据库乐观锁version 字段)
  • 关键操作(如接单)使用 Redis 分布式锁,确保同一工单同一时间只能被一人处理

java

编辑

// 伪代码:接单时加锁
String lockKey = "work_order:lock:" + orderId;
if (redis.tryLock(lockKey, 10, TimeUnit.SECONDS)) {
    try {
        // 检查状态是否仍为“待接单”
        // 更新为“已接单”
    } finally {
        redis.unlock(lockKey);
    }
}

### 6. 策略管理

策略管理是系统实现精细化运营的核心模块,允许运营人员针对不同点位或设备配置灵活的营销规则(如打折、满减),从而提升销量或清理滞销商品。

  • 核心功能

    • 创建策略:填写 策略名称(如“学校区域饮料8折”)和 策略方案(JSON格式,定义折扣规则)
    • 绑定点位:一个策略可关联多个点位,点击“查看详情”可查看所有绑定点位列表
    • 支持编辑(修改名称/方案)、删除、启用/禁用策略
  • 典型策略方案示例

    json

    编辑

    {
      "type": "DISCOUNT",
      "value": 0.8,
      "applicableProducts": ["101", "102"], // 仅对可乐、雪碧生效
      "validTime": "18:00-22:00"
    }
    

💡 设计思考:策略如何被高效执行?
最初考虑在订单生成时实时计算折扣,但性能开销大。
优化方案

  • 在设备启动或策略更新时,将策略预加载到 Redis(Key: strategy:point:{pointId}
  • 用户扫码购买时,设备端直接读取本地缓存的策略,快速计算最终价格
  • 后端仅做兜底校验,确保一致性

🔧 扩展性设计:策略模式 + 配置驱动
为支持未来新增“满减”“第二件半价”等类型,策略方案采用 JSON 配置 + 策略处理器工厂 实现:

java

编辑

// 伪代码
StrategyHandler handler = strategyHandlerFactory.getHandler(strategy.getType());
BigDecimal finalPrice = handler.calculate(originalPrice, strategy.getConfig());

这样,新增策略类型只需实现新 Handler,无需改动主流程,符合开闭原则。

### 7. 订单管理

订单管理是系统业务闭环的“结果窗口”,集中展示用户在前端(如小程序/扫码屏)下单后生成的所有交易记录,为运营分析、财务对账、售后处理提供数据基础。

  • 核心字段

    • 订单编号(全局唯一,如 DD202504001
    • 关联设备(设备编号 + 点位名称)
    • 商品明细(商品名、数量、单价、折扣后价格)
    • 订单状态:待支付 → 已支付 → 已完成 / 已取消
    • 订单金额:原价、实付金额、优惠金额(用于核销策略效果)
    • 下单时间、完成时间
  • 功能支持

    • 分页列表展示
    • 按日期范围查询(如查询“2025-04-01 至 2025-04-07”的订单)
    • 查看订单详情(含商品清单、支付方式、操作日志)

💡 设计思考:如何高效支持日期查询?
订单表数据量增长快,若直接对 create_time 字段做范围查询,性能会随数据量下降。
优化方案

  • 在 create_time 上建立 普通索引
  • 前端限制最大查询跨度(如≤30天),避免全表扫描
  • 高频场景(如“今日订单”)可缓存到 Redis,减轻数据库压力

⚠️ 潜在难点:订单状态与库存的一致性
用户支付成功后,需同时完成两件事

  1. 订单状态更新为“已支付”
  2. 对应设备货道库存扣减

若只成功其一,会导致“超卖”或“资金丢失”。
解决方案

  • 使用 本地事务 保证数据库操作原子性
  • 库存扣减失败时,自动触发 订单取消 + 支付退款(通过消息队列异步补偿)

“订单管理不仅是数据展示,更是系统可靠性与用户体验的最终检验场。”

总结与致谢

通过帝可得项目,我不仅掌握了若依框架的快速开发能力,更理解了  “业务驱动技术”  的真谛——每一个功能背后,都是真实场景的需求。

作为大专生,我深知学历不是终点,持续输出和解决问题的能力才是核心竞争力。这篇博客既是总结,也是起点。

🌟 致读者:如果你也是刚入门的开发者,请相信:
完成比完美更重要,开始比准备更关键。
写下你的第一行代码,发布你的第一篇博客——你已经在高手的路上!