1. 项目背景与核心价值
去年帮朋友改造他的家电零售门店管理系统时,发现传统ERP系统存在三个致命痛点:后台操作复杂让店员望而生畏、销售数据滞后影响决策时效、线上线下库存不同步导致超卖。这正是我们开发这套系统的初衷——用SpringBoot+Vue打造一个"会呼吸"的智能家电销售管理平台。
这个系统最核心的竞争力在于:用Vue构建的极简操作界面让50岁店员也能快速上手,基于WebSocket的实时看板让库存变动和销售数据秒级刷新,配合智能预警机制自动拦截超卖订单。上个月在本地家电卖场实测期间,店员培训时间从2周缩短到3天,库存准确率提升到99.8%,老板最爱的"爆款追踪"功能让促销资源投放精准度提高了35%。
2. 技术架构解析
2.1 前后端分离设计
采用经典的SpringBoot+Vue前后端分离架构,这不是简单的技术堆砌。我们刻意保持后端API的纯净性——所有业务逻辑都在SpringBoot层处理,Vue只负责数据展示和交互。这样设计有两个实际好处:
- 当需要开发微信小程序时,可以直接复用现有API
- 夜间批量处理等后台任务不会影响前端响应速度
具体技术栈选型:
- 后端:SpringBoot 2.7 + MyBatis-Plus 3.5
- 前端:Vue 3 + Element Plus + ECharts
- 数据库:MySQL 8.0(必须用8.0版本才能使用窗口函数做销售排行分析)
2.2 智能库存管理模块
这是系统最复杂的部分,采用多级缓存策略:
- 第一层:Redis缓存热门商品库存(设置5秒自动过期)
- 第二层:MySQL行级锁保证强一致性
- 第三层:JVM内存队列做请求合并
// 库存扣减核心逻辑示例 @Transactional public boolean deductStock(Long productId, int num) { // 先查Redis Integer cacheStock = redisTemplate.opsForValue().get("stock:"+productId); if(cacheStock != null && cacheStock < num) { return false; } // 再查数据库 Product product = productMapper.selectByIdForUpdate(productId); if(product.getStock() < num) { return false; } // 双写 productMapper.deductStock(productId, num); redisTemplate.opsForValue().set("stock:"+productId, product.getStock()-num, 5, TimeUnit.SECONDS); return true; }重要提示:必须用@Transactional注解保证原子性,但要注意锁粒度问题。我们曾因锁住整个方法导致性能瓶颈,后来改为selectByIdForUpdate只锁单行记录。
3. 核心功能实现细节
3.1 销售看板实时更新
采用WebSocket+ETL管道方案:
- 订单数据变更时触发Binlog监听
- Flink实时计算销售额/销量指标
- 通过WebSocket推送至前端
// 前端接收实时数据示例 <script setup> import { onMounted } from 'vue' const socket = new WebSocket('wss://yourdomain.com/realtime') onMounted(() => { socket.onmessage = (event) => { const data = JSON.parse(event.data) // 更新ECharts图表 updateDashboard(data) } }) </script>3.2 智能促销引擎
基于规则引擎Drools实现促销策略:
rule "夏季空调促销" when $p: Product(category=="空调", season=="夏季") then $p.setDiscount(0.8); insert(new PromotionEvent($p.getId(),"夏季特惠")); end配套的MySQL表设计特别注意了JSON字段的使用:
CREATE TABLE `promotion_rules` ( `id` bigint NOT NULL AUTO_INCREMENT, `rule_name` varchar(50) DEFAULT NULL, `condition_json` json DEFAULT NULL, -- 存储规则条件 `action_json` json DEFAULT NULL, -- 存储执行动作 PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;4. 部署与调优实战
4.1 高性能部署方案
推荐使用Docker Compose编排:
version: '3' services: backend: image: openjdk:17-jdk ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=prod deploy: resources: limits: cpus: '2' memory: 2G frontend: image: nginx:alpine ports: - "80:80" volumes: - ./dist:/usr/share/nginx/html关键调优参数:
- SpringBoot连接池配置:
spring: datasource: hikari: maximum-pool-size: 20 connection-timeout: 30000 idle-timeout: 600000- Vue生产环境优化:
// vite.config.js export default defineConfig({ build: { chunkSizeWarningLimit: 1500, rollupOptions: { output: { manualChunks(id) { if (id.includes('node_modules')) { return 'vendor' } } } } } })5. 典型问题排查指南
5.1 库存超卖问题
现象:促销期间出现库存负数 排查步骤:
- 检查Redis与MySQL数据是否同步
- 用Arthas监控deductStock方法执行情况
- 压力测试时使用Jmeter模拟并发
最终解决方案:
// 增加库存版本号校验 @Update("update product set stock=stock-#{num}, version=version+1 where id=#{id} and version=#{version}") int deductStockWithVersion(@Param("id") Long id, @Param("num") int num, @Param("version") int version);5.2 图表加载卡顿
优化方案:
- 前端启用数据分页加载
- 后端添加@Cacheable注解
- 数据库建立分析专用视图
CREATE VIEW sales_stats AS SELECT product_id, SUM(quantity) as total_sales, DATE_FORMAT(create_time,'%Y-%m-%d') as day FROM order_detail GROUP BY product_id, day;6. 二次开发建议
- 扩展接口时遵循RESTful规范:
GET /api/products - 获取商品列表 POST /api/products - 创建商品 GET /api/products/{id} - 获取商品详情 PUT /api/products/{id} - 更新商品 DELETE /api/products/{id} - 删除商品- 前端组件复用技巧:
<!-- 通用表单组件示例 --> <template> <el-form :model="formData" :rules="rules"> <slot name="fields"></slot> <el-button @click="submit">提交</el-button> </el-form> </template> <script> export default { props: ['submitFn'], methods: { submit() { this.$refs.form.validate(valid => { if(valid) this.submitFn(this.formData) }) } } } </script>这套系统经过三个版本的迭代,目前已经形成完整的开发文档和API规范。最近新增的"智能补货预测"模块采用时间序列分析算法,能根据历史销售数据自动生成采购建议,这个功能特别适合有多家连锁门店的客户。