1. 项目概述
煤炭销售管理系统是基于SSM(Spring+SpringMVC+MyBatis)和Vue.js技术栈开发的企业级应用,主要面向煤炭贸易企业实现销售全流程数字化管理。这个毕业设计项目完整实现了从采购入库、库存管理、销售开单到财务结算的业务闭环,采用前后端分离架构,后端提供RESTful API接口,前端通过Vue组件化开发实现交互。
我在实际开发过程中发现,煤炭行业销售管理有几个特殊需求:需要处理大宗商品的批次管理、支持多种计量单位换算、具备复杂的价格计算公式(如热值计价)。这些业务特性使得系统设计比普通商品销售系统更具挑战性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 后端SSM框架整合
SSM框架组合是JavaEE领域的经典方案,本系统采用以下版本:
- Spring 5.3.18(IoC容器和事务管理)
- SpringMVC 5.3.18(RESTful接口开发)
- MyBatis 3.5.9(ORM映射)
数据库选用MySQL 8.0,主要考虑到:
- 事务完整性要求高(资金流水记录必须ACID)
- 需要处理复杂的多表关联查询(如销售单-客户-煤种关系)
- 未来可能面临大数据量存储(历史交易记录积累)
关键配置技巧:在Spring事务管理中,对updateInventory这类库存操作方法需要设置@Transactional(isolation=READ_COMMITTED, propagation=REQUIRED)确保数据一致性
2.2 前端Vue技术栈
前端采用Vue 2.6 + Element UI 2.15的组合,主要功能模块包括:
- 路由管理:vue-router实现多级路由嵌套
- 状态管理:Vuex集中管理用户权限、全局配置
- 可视化:ECharts实现销售数据看板
- 表单验证:async-validator处理复杂业务规则
实测中发现Element UI的表格组件在处理万级数据时存在性能瓶颈,最终采用虚拟滚动方案优化:
javascript复制<el-table
:data="tableData"
style="width: 100%"
height="500"
v-loading="loading"
row-key="id"
:tree-props="{children: 'children'}"
>
3. 核心业务模块实现
3.1 煤炭批次管理
煤炭作为大宗商品,批次管理是核心难点。系统设计了三级关联体系:
- 采购批次(关联供应商、矿点)
- 库存批次(关联煤仓、质检报告)
- 销售批次(关联客户合同)
数据库表关系设计:
sql复制CREATE TABLE `coal_batch` (
`batch_id` varchar(32) NOT NULL COMMENT '批次ID',
`coal_type` varchar(20) NOT NULL COMMENT '煤种',
`purchase_id` varchar(32) DEFAULT NULL COMMENT '采购单号',
`storage_location` varchar(50) NOT NULL COMMENT '存放位置',
`net_weight` decimal(12,2) NOT NULL COMMENT '净重(吨)',
`calorific_value` int DEFAULT NULL COMMENT '发热量(kcal/kg)',
`sulfur_content` decimal(5,2) DEFAULT NULL COMMENT '硫分(%)',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '状态(0:在库 1:已出库)',
PRIMARY KEY (`batch_id`),
KEY `idx_purchase` (`purchase_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 动态价格计算引擎
煤炭价格计算涉及多个变量参数,系统设计了规则引擎:
java复制public interface PriceCalculator {
BigDecimal calculate(PriceContext context);
}
@Service
public class CalorificPricing implements PriceCalculator {
@Override
public BigDecimal calculate(PriceContext ctx) {
// 基准价 + (实际热值-基准热值)*热值系数
return ctx.getBasePrice()
.add(ctx.getActualCalorific()
.subtract(ctx.getStandardCalorific())
.multiply(ctx.getCalorificFactor()));
}
}
前端通过动态表单配置价格公式:
vue复制<el-form-item label="计价公式" prop="formula">
<el-select v-model="form.formula" @change="updateFormula">
<el-option label="热值计价" value="CALORIFIC"></el-option>
<el-option label="固定单价" value="FIXED"></el-option>
<el-option label="阶梯计价" value="STEPPED"></el-option>
</el-select>
<div v-if="form.formula === 'CALORIFIC'" class="formula-params">
<el-input-number v-model="form.baseCalorific" :min="4000" :max="8000"></el-input-number>
<span>kcal/kg基准 + </span>
<el-input-number v-model="form.calorificFactor" :min="0" :step="0.01"></el-input-number>
<span>元/100kcal浮动</span>
</div>
</el-form-item>
4. 系统安全设计
4.1 权限控制模型
采用RBAC(基于角色的访问控制)模型,特点包括:
- 角色继承(销售经理继承销售员权限)
- 数据权限过滤(分公司只能查看本机构数据)
- 操作日志审计(关键操作留痕)
Spring Security配置示例:
java复制@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/sales/**").hasAnyRole("SALES_MANAGER","SALES_CLERK")
.antMatchers(HttpMethod.POST, "/api/contract").hasRole("SALES_MANAGER")
.antMatchers("/api/report/**").access("@dataSecurity.checkDepartment(authentication)")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
4.2 交易数据校验
针对煤炭销售中的重量差异问题,实现双重校验机制:
- 地磅系统对接(通过串口通信获取实时称重数据)
- 运单照片OCR识别(使用Tesseract识别车牌号和载重)
校验逻辑伪代码:
python复制def verify_weight(order):
scale_weight = get_scale_data(order.truck_no)
ocr_weight = ocr_recognize(order.photo_url)
if abs(scale_weight - ocr_weight) > 0.5: # 允许0.5吨误差
raise ValidationError("称重数据不一致")
if abs(order.declared_weight - scale_weight) > order.allowance:
trigger_alert("实际重量超出申报范围")
5. 部署与性能优化
5.1 生产环境部署方案
推荐部署架构:
code复制前端服务器(Nginx)
├── 静态资源部署
└── 反向代理 → 后端集群(Spring Boot)
├── 主库(MySQL Master)
└── 从库(MySQL Slave)
关键Nginx配置:
nginx复制location /api {
proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 75s;
proxy_read_timeout 300s; # 长报表导出需要超时延长
}
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
5.2 大数据量优化策略
针对煤炭销售系统常见的大数据量场景:
- 分库分表:按年份拆分交易记录表
- 冷热分离:将3年前数据迁移到归档库
- 查询优化:为常用报表创建物化视图
MyBatis批量插入优化示例:
xml复制<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO sales_detail
(order_id, coal_type, weight, unit_price)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.orderId}, #{item.coalType},
#{item.weight}, #{item.unitPrice})
</foreach>
</insert>
6. 开发经验总结
在完成这个毕业设计项目过程中,有几个值得分享的实践心得:
-
复杂表单处理:对于煤炭销售合同这种多字段表单,建议拆分为多个子组件,通过Vuex管理状态。实测将200+字段的表单拆分为"客户信息"、"煤质要求"、"运输条款"等6个组件后,维护效率提升40%
-
报表性能优化:销售汇总报表涉及多表join时,采用以下方案:
- 后台使用Spring Batch进行夜间预计算
- 前端实现"滚动加载+列虚拟化"
- 测试数据量达到50万条时,页面响应时间仍能保持在2秒内
-
移动端适配:使用vw/vh单位配合媒体查询,主要界面在手机端可正常操作。特别要注意Element UI组件在移动端的点击区域问题,需要通过自定义CSS调整:
css复制@media screen and (max-width: 768px) {
.el-button {
padding: 12px;
min-width: 80px;
}
.el-form-item__label {
float: none;
width: 100%;
}
}
- 调试技巧:在开发价格计算模块时,建议:
- 使用Vue DevTools的Time Travel功能回溯状态变化
- 为MyBatis配置SQL日志输出,检查N+1查询问题
- 对复杂业务规则编写单元测试(如JUnit测试价格引擎)
