资讯动态

企业EAM系统开发实战:Vue+Spring Boot全栈架构解析

发布时间:2026/10/15 15:30:30 来源:尧图企业网站定制
1. 项目背景与核心价值企业资产管理EAM系统是现代企业数字化转型的基础设施之一。传统资产管理依赖人工台账和Excel表格存在数据孤岛、流程割裂、追溯困难等痛点。我们团队最近为一家中型制造企业实施的这套系统通过前后端分离架构实现了资产全生命周期管理上线后使设备利用率提升27%盘点效率提高近10倍。这个系统的核心价值在于三个维度一是通过标准化编码体系解决资产标识混乱问题二是借助工作流引擎实现从采购到报废的闭环管理三是利用数据分析看板辅助决策。特别在制造行业设备停机成本每小时可能高达数万元预防性维护功能直接关系到企业效益。2. 技术架构设计解析2.1 前端技术选型采用Vue 3组合式API开发管理后台主要基于以下考量相比React更温和的学习曲线适合企业IT团队后续维护Element Plus组件库提供丰富的业务组件如资产树形选择器ECharts对设备状态可视化支持更友好关键配置示例// vite.config.js 生产环境优化 build: { rollupOptions: { output: { manualChunks(id) { if (id.includes(element-plus) || id.includes(echarts)) { return vendor } } } } }2.2 后端架构设计Spring Boot采用分层架构com.asset ├── config # 安全/持久化配置 ├── controller # RESTful API ├── service # 业务逻辑 │ ├── impl # 实现类 ├── repository # JPA接口 └── model # 实体类特别设计了双数据源主库MySQL 8.0InnoDB集群从库Redis缓存热点数据如部门资产统计2.3 数据库关键设计资产主表结构优化要点CREATE TABLE asset ( id BIGINT NOT NULL AUTO_INCREMENT, asset_code VARCHAR(20) NOT NULL COMMENT 资产编码规则: DEPTYYYYMM5位序列, name VARCHAR(100) NOT NULL, category_id INT NOT NULL COMMENT 关联资产分类表, status TINYINT NOT NULL DEFAULT 1 COMMENT 1-在用 2-闲置 3-维修, purchase_date DATE NOT NULL, net_value DECIMAL(12,2) COMMENT 净值计算原值-累计折旧, location_id INT COMMENT GIS坐标编码, qr_code VARCHAR(255) COMMENT 二维码存储路径, PRIMARY KEY (id), UNIQUE INDEX udx_code (asset_code), INDEX idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3. 核心功能实现细节3.1 资产全生命周期工作流采用Activiti引擎驱动状态变更graph TD A[采购申请] --|审批| B[入库登记] B -- C[领用分配] C -- D[日常使用] D --|故障| E[维修流程] D --|闲置| F[调拨流程] D --|报废| G[处置流程]关键状态机实现Transactional public void changeAssetStatus(Long assetId, AssetStatus newStatus) { Asset asset repository.findById(assetId) .orElseThrow(() - new BusinessException(资产不存在)); // 状态校验逻辑 if (asset.getStatus() AssetStatus.SCRAPPED) { throw new BusinessException(已报废资产不可操作); } // 记录变更日志 AssetLog log new AssetLog(); log.setAssetId(assetId); log.setOldStatus(asset.getStatus()); log.setNewStatus(newStatus); logRepository.save(log); asset.setStatus(newStatus); repository.save(asset); }3.2 移动端盘点方案混合开发方案选型对比方案优点缺点适用场景纯Web跨平台扫码性能差简单盘点UniApp开发快功能受限原型验证React Native性能好学习成本高大型项目Flutter体验优生态较弱重UI需求最终采用CordovaWebView方案使用ZXing插件实现毫秒级扫码本地SQLite存储离线盘点数据通过WebSocket实现实时进度同步3.3 折旧计算模块财务部门特别要求的双余额递减法public BigDecimal calculateDepreciation(Asset asset) { BigDecimal cost asset.getOriginalValue(); BigDecimal salvage asset.getSalvageValue(); int years asset.getUsefulLife(); // 双倍余额递减法公式 BigDecimal rate BigDecimal.valueOf(2.0) .divide(BigDecimal.valueOf(years), 10, RoundingMode.HALF_UP); BigDecimal bookValue cost.subtract(asset.getAccumulatedDepreciation()); BigDecimal depreciation bookValue.multiply(rate); // 最后两年转为直线法 if (asset.getUsedYears() years - 2) { depreciation bookValue.subtract(salvage) .divide(BigDecimal.valueOf(2), 2, RoundingMode.HALF_UP); } return depreciation.compareTo(BigDecimal.ZERO) 0 ? depreciation : BigDecimal.ZERO; }4. 性能优化实战记录4.1 千万级数据查询优化资产历史表分库方案按年度水平分片2023_asset_history建立时间维度索引冷数据归档到ClickHouse查询优化前后对比优化措施查询耗时(ms)内存占用(MB)原始查询4200850添加索引1200320分页优化800150结果缓存50804.2 高并发领用控制分布式锁实现方案对比// Redisson分布式锁实现 public boolean acquireAsset(Long assetId, Long userId) { RLock lock redissonClient.getLock(asset: assetId); try { if (lock.tryLock(3, 10, TimeUnit.SECONDS)) { Asset asset repository.findById(assetId); if (asset.getStatus() AssetStatus.AVAILABLE) { asset.setUserId(userId); repository.save(asset); return true; } } } finally { lock.unlock(); } return false; }4.3 文件导入性能提升Excel导入优化策略使用EasyExcel替代POI内存降低60%采用批量插入batchSize1000异步处理机制Async public void importAssets(MultipartFile file) { EasyExcel.read(file.getInputStream()) .head(AssetImportDTO.class) .registerReadListener(new AssetImportListener()) .sheet() .doRead(); } // 自定义监听器实现分批入库 class AssetImportListener implements ReadListenerAssetImportDTO { private ListAsset cache new ArrayList(1000); Override public void invoke(AssetImportDTO data, AnalysisContext context) { Asset asset convertToEntity(data); cache.add(asset); if (cache.size() 1000) { batchInsert(); } } private void batchInsert() { repository.saveAll(cache); cache.clear(); } }5. 部署与运维方案5.1 容器化部署Docker Compose编排示例version: 3 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - ./mysql/data:/var/lib/mysql - ./mysql/conf:/etc/mysql/conf.d redis: image: redis:6 ports: - 6379:6379 backend: build: ./backend ports: - 8080:8080 depends_on: - mysql - redis frontend: build: ./frontend ports: - 80:805.2 监控体系搭建Prometheus监控指标示例资产API成功率折旧计算耗时并发领用等待数盘点任务队列深度Grafana看板配置关键点设置资产状态分布饼图折旧计提进度时序图接口响应时间热力图6. 典型问题排查实录6.1 扫码枪兼容性问题现象部分工业扫码枪无法触发Web页面事件 排查过程抓取键盘事件发现部分设备发送KeyCode异常使用input事件替代keydown事件添加300ms防抖处理最终解决方案// 扫码枪专用输入组件 template input v-modelscanValue inputhandleScan refscannerInput classscanner-input / /template script setup const scanValue ref() let timer null const handleScan () { clearTimeout(timer) timer setTimeout(() { if (scanValue.value.length 8) { submitScan(scanValue.value) scanValue.value } }, 300) } /script6.2 折旧计算精度问题故障现象年末资产净值出现0.01元差异 根本原因BigDecimal除法未统一精度 修复方案// 统一配置计算精度 Bean public ArithmeticUtils arithmeticUtils() { return new ArithmeticUtils(6, RoundingMode.HALF_UP); } // 所有计算使用工具类 public BigDecimal calculate(Asset asset) { return arithmeticUtils.divide( asset.getOriginalValue(), BigDecimal.valueOf(asset.getUsefulLife()) ); }6.3 并发领用超发问题复现步骤用户A和B同时申请同一资产系统检查时都显示可用最终两人都获得使用权解决方案对比方案实现复杂度性能影响可靠性数据库乐观锁低小中等SELECT FOR UPDATE中较大高分布式锁高中等最高最终采用组合方案前端限制重复提交后端加Redis分布式锁数据库最终校验7. 扩展方向建议物联网集成通过MQTT协议接入设备实时数据预测性维护基于设备历史数据训练LSTM模型数字孪生Three.js实现资产3D可视化区块链存证关键操作上链存证实际项目中我们接入了PLC设备数据采集通过以下指标预测故障电机振动频率轴承温度变化率电流波动系数# 简化的预测模型示例 from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense model Sequential([ LSTM(64, input_shape(30, 5)), # 30个时间步,5个特征 Dense(1, activationsigmoid) ]) model.compile(lossbinary_crossentropy, optimizeradam)

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑