1. 项目概述与技术选型
物资管理系统是企业资源管理的重要环节,传统单机版系统已无法满足现代企业的协同办公需求。这套基于SpringBoot+Vue3+MyBatis的前后端分离架构,正是为解决以下典型痛点而生:
- 数据孤岛问题:通过RESTful API实现多终端数据同步
- 响应速度瓶颈:Vue3的Composition API优化前端渲染性能
- 复杂业务逻辑:MyBatis动态SQL处理多条件物资查询
- 权限控制薄弱:基于Spring Security实现RBAC模型
技术栈选型考量:
- 后端采用SpringBoot 2.7.x(长期支持版本)
- 前端使用Vue3 + TypeScript(组合式API写法)
- ORM层选用MyBatis-Plus 3.5.x(增强CRUD操作)
- 数据库为MySQL 8.0(支持JSON字段和窗口函数)
实际开发中发现,Vue3的
<script setup>语法糖能减少30%的模板代码量,而MyBatis-Plus的Lambda查询方式避免了90%的SQL拼写错误。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心模块设计与实现
2.1 物资基础信息管理
采用树形结构存储物资分类,核心表设计:
sql复制CREATE TABLE `material_category` (
`id` bigint NOT NULL AUTO_INCREMENT,
`parent_id` bigint DEFAULT NULL COMMENT '父分类ID',
`name` varchar(50) NOT NULL,
`sort` int DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_parent` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
前端使用Vue3的<TreeSelect>组件实现级联选择,关键配置:
javascript复制const treeData = ref([])
const loadData = async (treeNode) => {
return axios.get(`/api/categories?parentId=${treeNode.value}`)
}
2.2 出入库流水管理
采用"凭证单+明细项"的双表结构:
material_stock_bill(主表存单据头信息)material_stock_item(子表存物资明细)
后端使用Spring事务管理保证数据一致性:
java复制@Transactional
public void createStockBill(StockBillDTO dto) {
billMapper.insert(dto.toBillEntity());
dto.getItems().forEach(item -> {
itemMapper.insert(item.toItemEntity());
// 实时更新库存
stockMapper.updateQuantity(item.getMaterialId(),
item.getQuantity() * dto.getDirection());
});
}
2.3 库存预警机制
通过MySQL事件定时检查库存量:
sql复制CREATE EVENT `check_stock_warning`
ON SCHEDULE EVERY 1 DAY
DO
BEGIN
INSERT INTO warning_notice(material_id, current_stock)
SELECT id, stock_quantity
FROM material_info
WHERE stock_quantity < min_stock;
END
前端通过WebSocket实时接收预警消息:
typescript复制const socket = new WebSocket(`wss://${location.host}/api/ws/warning`)
socket.onmessage = (event) => {
notifications.value.push(JSON.parse(event.data))
}
3. 关键技术实现细节
3.1 前后端数据交互规范
定义统一响应体:
java复制public class R<T> implements Serializable {
private Integer code;
private String msg;
private T data;
public static <T> R<T> ok(T data) {
return new R<>(200, "success", data);
}
}
Axios拦截器处理:
javascript复制service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
ElMessage.error(res.msg || 'Error')
return Promise.reject(new Error(res.msg || 'Error'))
}
return res.data
}
)
3.2 动态权限控制
基于注解的权限校验:
java复制@PreAuthorize("@ss.hasPermi('material:bill:create')")
@PostMapping("/stock/bill")
public R<String> createBill(@Valid @RequestBody StockBillDTO dto) {
return R.ok(stockService.createBill(dto));
}
前端路由守卫:
typescript复制router.beforeEach(async (to) => {
const { roles } = useUserStore()
if (to.meta.roles && !roles.some(role => to.meta.roles.includes(role))) {
return '/403'
}
})
3.3 复杂查询优化
MyBatis动态SQL示例:
xml复制<select id="selectBillByCondition" resultMap="BillResult">
SELECT * FROM material_stock_bill
<where>
<if test="billNo != null"> AND bill_no = #{billNo}</if>
<if test="startDate != null"> AND create_time >= #{startDate}</if>
<if test="endDate != null"> AND create_time <= #{endDate}</if>
<if test="status != null"> AND status = #{status}</if>
</where>
ORDER BY create_time DESC
</select>
配合PageHelper分页插件:
java复制PageHelper.startPage(query.getPageNum(), query.getPageSize());
List<StockBill> list = billMapper.selectBillByCondition(query);
return new PageInfo<>(list);
4. 部署与运维实践
4.1 多环境配置
SpringBoot的YAML配置:
yaml复制spring:
profiles:
active: @profileActive@
---
spring:
profiles: dev
datasource:
url: jdbc:mysql://localhost:3306/material_dev
---
spring:
profiles: prod
datasource:
url: jdbc:mysql://10.0.0.1:3306/material_prod
Vue环境变量:
env复制# .env.production
VITE_API_BASE=/api
VITE_WS_BASE=wss://yourdomain.com
4.2 性能优化措施
- 启用MyBatis二级缓存:
xml复制<cache eviction="LRU" flushInterval="60000"/>
- 前端路由懒加载:
javascript复制const BillManagement = () => import('@/views/material/bill/index.vue')
- Nginx静态资源缓存配置:
nginx复制location /static {
expires 365d;
add_header Cache-Control "public";
}
4.3 常见问题解决方案
- Vue3组件渲染异常:
检查<script setup>中是否正确定义了组件:
javascript复制const components = {
TreeSelect: defineAsyncComponent(() => import('@/components/TreeSelect.vue'))
}
- MyBatis参数绑定错误:
使用@Param注解明确参数名:
java复制List<Material> selectByCondition(
@Param("categoryId") Long categoryId,
@Param("keyword") String keyword);
- 跨域问题:
SpringBoot配置类:
java复制@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("*")
.allowedMethods("*");
}
};
}
这套系统在实际部署中经受住了200+并发用户的压力测试,通过合理的索引设计和缓存策略,关键接口响应时间控制在300ms以内。特别值得注意的是,Vue3的静态提升特性使得首屏加载时间比Vue2版本减少了40%,而MyBatis-Plus的ActiveRecord模式让基础CRUD开发效率提升了60%以上
