基于若依框架的固定资产管理系统:源码解析与二次开发实践

发布时间:2026/10/15 12:16:10
基于若依框架的固定资产管理系统:源码解析与二次开发实践 简介这是一份基于Java若依框架与layui实现的固定资产管理系统源码适合需要快速搭建企业资产台账、掌握前后端分离开发的Java工程师或毕业设计人员。源码覆盖资产登记、领用/借用/归还、维修、调拨、转移、报废、统计及组织权限等完整闭环后台采用Spring Boot若依脚手架前端基于layui构建表格与表单交互可直接学习RBAC权限分配与业务模块扩展方式。压缩包共1883个文件大小8.88MB其中包含317个Java文件、180个HTML页面、90个JS脚本、40个CSS样式及SQL脚本、XML配置等代码结构完整并带有版本历史记录。目前已有559人学习下载。借助这套源码可快速理解固定资产全生命周期管理的数据流转、审批状态更新与统计报表实现思路同时参照若依框架的代码生成、权限拦截和日志处理机制用于二次开发或项目实战练习。1. 固定资产管理不只是“记个数”一个基于若依框架的Java项目能解决什么如果你手头有一个 java 固定资产管理源码很多人的第一反应是“无非就是一套增删改查把资产列表存进数据库而已”。但真到用的时候就会发现资产这个东西一旦开始流转——今天领用、明天归还、后天维修、年底折旧——账就乱了。这套基于若依框架搭建的固定资产管理系统正是把“台账”和“流转单据”串起来让每一条资产从入库、领用、归还、报修到报废都能追溯到人。适合谁一类是做行政后勤信息化的开发者拿来改改就能交付另一类是刚接触若依框架的人用这套业务代码理解权限、数据隔离和代码生成器的配合方式。2. 技术选型与项目边界为什么选若依资产台账这摊事覆盖到哪里2.1 技术底座若依到底给了哪些开箱即用的能力选若依作为底座最直接的理由是它把企业后台系统的“公共工程”都做完了。用户管理、角色权限、菜单路由、操作日志、数据字典这些如果从头写一套下来最少两三周而且很容易在各种权限交接点翻车。若依的前后端分离版本是用 Spring Boot 2.x 加 Spring Security 做后端Vue 2 加 Element UI 做前端MyBatis 管数据库访问Redis 承担验证码和部分缓存。固定资产管理源码基于这套骨架等于一开始就站在一个能登录、能分配角色、能记录操作痕迹的系统上业务代码只需要专注资产本身。权限这块尤其值得重视。固定资产有个天然属性数据按部门隔离。行政部门不应该看到研发部的打印机资产财务部又需要看全局。若依提供的数据权限注解 DataScope 可以按“本人、本部门、本部门及以下、全部”四个档位切分查询范围固定资产模块直接复用这一套比自己在 SQL 里拼 where 条件要可靠得多。还有一个容易被忽略的点是代码生成器。若依内置的生成器可以根据数据库表反向生成 Java 实体、Mapper、Service、Controller 以及前端列表页和表单页。这套固定资产源码里的基础台账部分完全可以用生成器先铺底再手工加业务逻辑。2.2 模块边界资产台账、领用归还与折旧的核心表设计这套源码覆盖的功能范围从表设计就能看出来。核心表大致是五张资产分类表、资产主表、领用/归还记录表、维修记录表、折旧记录表。资产主表存静态信息比如资产编号、名称、分类、原值、购置日期、使用部门和使用人领用记录表存动态信息谁在什么时间从谁手里领走了什么资产维修表和折旧表则记录资产在使用过程中的状态变化。常见做法是把资产主表和流转记录表拆开不要把所有历史都塞到主表里。假设一台笔记本电脑被三个人前后使用过如果只在一行里改“使用人”那历史就丢了。这套模块的做法是主表只管“当前状态”每次领用、归还都在记录表里追加一条同时反向更新主表的当前使用人和状态字段。这样的设计在盘点时特别有用拉出记录表就能看到这台设备从入库到现在经过了哪些人。字段设计上有一个容易踩坑的地方是金额类型。资产原值、净值、累计折旧这几列不要用 double要用 decimal。原因放到后面避坑章节细说这里只要记住凡是涉及钱的字段在设计表结构时就给 decimal(12,2) 起步。2.3 环境准备JDK、MySQL、Redis 与 Maven 的版本清单跑这套源码之前环境最好和项目保持一致否则会遇到一堆玄学问题。JDK 用 1.8这是若依框架常年适配的版本用 11 或 17 不是不行但某些反射相关的旧依赖可能会报错。Maven 用 3.6 以上即可。数据库方面MySQL 5.7 和 8.0 都能用但 8.0 需要注意时区参数这个也有专门坑位。组件推荐版本用途JDK1.8编译与运行后端Maven3.6依赖管理、打包MySQL5.7 / 8.0业务数据存储Redis5.x 以上验证码、会话缓存Node.js12.x 14.x前端依赖安装与构建Redis 在这套架构里不是可选项。若依登录时验证码存的就是 Redis如果本地没装或没启动后端能启动但验证码会一直失效登录界面像卡住一样。所以环境准备时先把 Redis 跑起来再启动后端。Node 版本也留意一下太新的 Node 和旧版 Vue 项目配合时node-sass 经常编译失败这是前端工程的老毛病。3. 核心模块拆解一个“资产入库”请求从页面到数据库的完整链路3.1 后端分层Controller、Service、Mapper 各管一段若依的后端包结构非常固定固定资产模块在src/main/java/com/xxx/asset下面通常会长这样asset/ ├── controller/ │ └── FixedAssetController.java ├── domain/ │ └── FixedAsset.java ├── mapper/ │ ├── FixedAssetMapper.java │ └── xml/FixedAssetMapper.xml ├── service/ │ ├── IFixedAssetService.java │ └── impl/FixedAssetServiceImpl.java └── common/ └── CodeGenerator.java一套标准的请求链路是前端页面点击“新增资产” → 表单数据通过 axios 提交到 Controller → Controller 调用 Service → Service 组装业务校验逻辑后调用 Mapper → Mapper 通过 XML 里的 SQL 语句写入数据库。权限注解和操作日志注解挂在 Controller 的方法上保证每一次写操作都能落到日志表里。用户新增资产时Controller 要做的动作如下PostMapping(/fixedAsset) PreAuthorize(ss.hasPermi(asset:fixedAsset:add)) Log(title 固定资产, businessType BusinessType.INSERT) public AjaxResult add(RequestBody FixedAsset fixedAsset) { // 1. 生成资产编号 String assetNo codeGenerator.generate(fixedAsset.getCategoryId()); fixedAsset.setAssetNo(assetNo); // 2. 初始净值等于原值 fixedAsset.setNetValue(fixedAsset.getOriginalValue()); // 3. 初始状态为在库 fixedAsset.setStatus(0); return toAjax(fixedAssetService.insertFixedAsset(fixedAsset)); }这个方法的逻辑很清楚先给资产编一个唯一编号再设置初始净值和状态。注意PreAuthorize里的权限标识它和前端菜单按钮的权限字符串一一对应如果没有分配权限后端会直接返回 403前端连请求都发不出去。Log注解负责把这次新增操作写进操作日志表。3.2 数据实体与表映射从 BaseEntity 到 FixedAsset若依体系里的实体类一般继承一个 BaseEntity里面预置了 createBy、createTime、updateBy、updateTime、remark 这些通用字段避免每张表都重复定义。FixedAsset 实体则进一步加上资产特有的字段public class FixedAsset extends BaseEntity { private Long assetId; // 资产ID private String assetNo; // 资产编号唯一 private String assetName; // 资产名称 private Long categoryId; // 资产分类ID private BigDecimal originalValue; // 原值 private BigDecimal netValue; // 净值 private String useDept; // 使用部门 private String useBy; // 使用人 private String status; // 状态0在库 1领用 2维修 3报废 // 非表字段用于列表查询条件 private String categoryName; // 分类名称连表查询用 }原值、净值都用 BigDecimal是因为金额计算经不起浮点误差。而categoryName标注为“非表字段”在 MyBatis 的 resultMap 里通过连表查询填充前端表格可以直接展示分类名称不用自己再发一次查询。3.3 Mapper 与 SQL条件分页和数据权限如何拼进一条查询列表页最常用的查询是分页加条件筛选。若依的分页是通过 PageHelper 插件实现的Controller 里接收前端传来的 pageNum 和 pageSizeService 层直接调用 Mapper 方法分页插件自动拦截 SQL 做 limit 操作。条件的拼装在 XML 里完成select idselectFixedAssetList parameterTypeFixedAsset resultMapFixedAssetResult select fa.asset_id, fa.asset_no, fa.asset_name, fa.original_value, fa.net_value, fa.use_dept, fa.use_by, fa.status, ac.category_name from fixed_asset fa left join asset_category ac on fa.category_id ac.category_id where${params.dataScope}/where if testassetName ! null and assetName ! and fa.asset_name like concat(%, #{assetName}, %) /if if teststatus ! null and fa.status #{status} /if if testcategoryId ! null and fa.category_id #{categoryId} /if order by fa.create_time desc /select这里最需要注意的是${params.dataScope}它用的是$符号而非#因为数据权限拼接进来的是“and fa.use_dept in (...)”这样的 SQL 片段不能用预编译参数替代。这一行就是若依数据权限的核心Service 层方法上标注DataScope(deptAlias fa)注解后框架会自动把当前用户可见的部门范围拼进这条 SQL。如果你在二次开发时发现某些列表不过滤数据八成是注解没加或者 XML 里漏了params.dataScope。like concat(%, #{assetName}, %)的写法避免了自己拼接百分号造成的 SQL 注入风险这也是项目里的默认习惯。3.4 前端交互Vue Element UI 如何完成一次新增前端列表页在src/views/asset/fixedAsset/index.vue页面本身不复杂上方是搜索条件中间是表格右侧是新增编辑按钮。资产分类用的是下拉树组件因为分类表通常是两级或三级结构。handleAdd() { this.reset(); this.open true; this.title 添加资产; this.form.categoryId undefined; this.assetOptions.forEach(item { if (item.children item.children.length 0) { this.form.categoryId item.children[0].id; } }); }, submitForm() { this.$refs[assetForm].validate(valid { if (valid) { if (this.form.assetId ! null) { updateFixedAsset(this.form).then(response { this.msgSuccess(修改成功); this.open false; this.getList(); }); } else { addFixedAsset(this.form).then(response { this.msgSuccess(新增成功); this.open false; this.getList(); }); } } }); }新增和编辑共用同一个表单弹窗靠assetId是否存在来区分调哪个接口。assetForm 里的校验规则集中在资产名称必填、原值必须大于 0、资产分类必选这几项Element UI 的表单校验会在 submit 之前拦截错误不用等后端返回 500。这个模式下最常出问题的是“编辑时分类树回显”和“数字输入框返回字符串”两个点后面排查章节会提到。3.5 权限控制部门与数据范围在业务中的实际落地固定资产列表的权限最终体现在“谁能看到哪些资产”上。若依角色的数据权限有五个档位全部数据、本部门及以下、本部门、仅本人、自定义部门。固定资产模块在 Service 层给查询方法加上了DataScope注解Override Service public ListFixedAsset selectFixedAssetList(FixedAsset fixedAsset) { // 启动数据权限过滤deptAlias对应SQL里的fa别名 return fixedAssetMapper.selectFixedAssetList(fixedAsset); }调用这个查询前框架会分析当前登录用户的角色配置把允许看到的部门编码拼成一个 IN 条件塞进 SQL。这比自己在业务代码里判断“用户是什么角色”要干净得多。实测中容易出现的问题是资产主表里存的是部门名称而非部门 ID导致数据权限 SQL 里的 dept 条件匹配不上。所以我一般建议表设计时使用部门 ID 作为外键部门名称只做展示不要混用。4. 让源码跑起来从初始化数据库到录入第一笔资产的完整步骤4.1 初始化数据库从 SQL 脚本到菜单权限数据拿到源码后第一步不是急着启动而是先把数据库建好。项目里一般会带一个 sql 目录里面包含初始化脚本和业务表脚本。执行顺序很重要# 先创建业务库 mysql -uroot -p -e CREATE DATABASE asset_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 导入框架基础表和业务表 mysql -uroot -p asset_db sql/init_schema.sql mysql -uroot -p asset_db sql/fixed_asset.sql先执行框架脚本再执行业务表脚本因为业务表里外键引用了框架的数据字典表。菜单数据也存在这张表里导入之后登录后台就能在菜单管理里看到“固定资产”这个目录。一个常见的翻车点直接用 Navicat 的“运行 SQL 文件”导入脚本里如果包含多条语句且没设置分隔符会出现语法报错。建议命令行导入能看到完整的错误信息。导入完成后检查一下 sys_menu 表里是否已经有固定资产相关的菜单记录如果没有在菜单管理页面手动添加一级菜单和按钮权限否则前端登录后看不到这个模块也别谈调接口。4.2 启动前后端Maven 构建与 npm install 的核心步骤后端用 IDEA 打开项目等 Maven 把依赖拉完改掉application.yml里的数据库连接和 Redis 配置然后运行 RuoYiApplication 主类。以下是一份最常见的本地配置spring: datasource: url: jdbc:mysql://localhost:3306/asset_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password redis: host: localhost port: 6379 database: 0serverTimezoneAsia/Shanghai在 MySQL 8.0 下必须显式声明否则连接会报时区错误。Redis 的密码如果没设置就留空若依默认配置会尝试用空密码连接。后端启动的标志是控制台打印出“Application run successfully”或者 Tomcat 端口监听 8080 的日志。前端在单独的目录比如ruoyi-ui执行:npm install npm run dev等看到编译完成、DONE Compiled successfully字样浏览器访问http://localhost:80或http://localhost:8080用项目自带的 admin 账号登录。若依默认会把前端端口配成 80而且已经配好了代理前端发出的/dev-api请求会被转发到后端 8080所以本地开发时几乎不需要改跨域。提示如果 npm install 时间特别长或者卡住优先检查 Node 版本旧项目的依赖对 Node 新版本兼容性很差常见的翻车点是 node-sass 编译失败。4.3 验收路径从登录到完整走通一次资产领用环境跑通之后不要只看列表页面就认为成功了。建议按业务主线完整走一遍先维护资产分类然后新增一台资产确认列表出现且编号自动生成再把这条资产领用给某个部门去记录表里查一下变动明细最后做一次还库操作确认资产状态从“领用”变回“在库”。这样等于把模块的所有状态流转都验证了一遍。每走一步都注意两个细节第一新增资产后刷新列表看编号是否按规则生成、原值是否回显正确第二查看操作日志确认新增、领用、归还三步都有日志记录。这两点验证完基本说明后端逻辑和前端联调都没问题。如果领用后状态没变大概率是 Service 里更新主表状态和插入记录表的顺序写反了。4.4 容易被忽略的验收项编号唯一性和 Redis 缓存还要专门验证一下资产编号唯一性。连续新增两台资产如果编号规则用“日期 序号”确认两台编号没有重复再尝试在列表查询里按编号搜索看接口能否精确返回。很多项目上线后才暴露一个问题资产编号在写库时没有唯一索引导致并发新增时生成重复编号Excel 导入时更是重灾区。建议在数据库层面直接给 asset_no 加唯一索引双保险。Redis 在这套系统里的角色也值得验收一下。登录后刷新页面验证码不会频繁失效说明 Redis 读写正常。如果登录时验证码老是提示过期检查本机 Redis 是否启动以及 application.yml 里的端口和实际端口是否一致。这些虽然不算业务功能的 bug但排查起来最耗时间属于典型的“环境问题先于代码问题”。5. 避坑实录固定资产模块在真实环境里的五个翻车点5.1 资产编号重复导入 Excel 时第 17 行意外中断现象在导出已有资产数据、修改后再导入时提示“资产编号已存在”导入流程中断人都不知道是哪一行出了问题。原因导出的 Excel 里本来就包含现有资产的编号再导回数据库时数据库中的 asset_no 字段有唯一索引第一条重复记录就把整批导入干掉了。解决导入功能里先读取 Excel 全部数据在内存里做一次重复检查遇到重复编号时把行号和具体资产名拼进提示信息同时保留唯一索引作为兜底。从那以后我每做一个导入功能都会加一条“先校验后入库”的规矩批量操作最怕的就是中断后不知从何查起。5.2 MySQL 8.0 时区报错与 Redis 没启动的假象现象后端启动时控制台抛The server time zone value Öйú±ê׼ʱ¼ä is unrecognized后面跟着一大串乱码甚至有人误以为是编码问题在改 pom 文件。原因安装 MySQL 8.0 时系统时区没有正确识别JDBC 连接串里又缺少 serverTimezone 参数。解决在数据库连接 URL 末尾加上serverTimezoneAsia/Shanghai同时把useSSLfalse加上避免本地环境证书校验带来的其他异常。至于 Redis 未启动这个问题现象是先访问登录页验证码图片加载不出来或者登录提交后一直转圈控制台看不到任何明显的报错这是典型的“后端正常但依赖服务没起”。解决启动项目前把 Redis 端到端验证一遍redis-cli ping返回 PONG 再启动后端。5.3 折旧计算出现 0.009999金额精度丢失现象资产每月折旧后净值字段出现 0.009999 这类尾巴比如原值 5000 元折旧后净值变成 4123.009999。原因实体类或数据库表把金额字段定义成了 double浮点数在二进制下无法精确表示十分位数值累加误差就出来了。解决数据库金额字段统一改成 decimal(12,2)Java 实体用 BigDecimalService 层的折旧计算必须显式指定保留两位小数。BigDecimal monthDepreciation originalValue .subtract(netValueNow) .divide(new BigDecimal(36), 2, RoundingMode.HALF_UP); newNetValue netValueNow.subtract(monthDepreciation).setScale(2, RoundingMode.HALF_UP);这里divide方法如果不传精度和舍入模式会抛 ArithmeticException所以折旧计算里把它写全是血泪经验换来的习惯。另一个容易被忽略的地方是 BigDecimal 构造不要用 new BigDecimal(0.1)要用 new BigDecimal(0.1)字符串构造才不会有浮点残留。5.4 前端日期查询漏掉当天数据现象资产列表按“购置日期”查询某一天查出来的数据比当天实际录入的少如果那天刚好只有 23:59 录的一笔列表甚至直接空白。原因Element UI 的 date-picker 默认返回的时间是当天 00:00:00后端 SQL 用create_time #{endTime}判断把当天最后几秒的数据全排除了。解决前端给日期组件加上value-formatyyyy-MM-dd后端参数接收后用 startDate 和 endDate 两个变量SQL 写成create_time #{startDate} and create_time DATE_ADD(#{endDate}, INTERVAL 1 DAY)把结束时间当成开区间处理。这种问题在前后端联调时很容易被当成“系统丢了数据”实际是边界条件没闭合。5.5 数据权限失效普通用户能看到全部部门资产现象新建一个只读用户只分配了资产列表的权限登录后却能看到全公司资产数据。原因排查下来有两种可能。一是角色配置页面里“数据权限”还是默认的“全部数据”没有改成“本部门”二是 Service 的查询方法没有标注 DataScope 注解或者 XML 的 where 条件里没有拼${params.dataScope}这个动态段。解决先确认角色的数据权限档位再检查后端查询方法。避免下次再犯我给项目加了一个规则所有查询方法里 where 子句第一个条件必须是数据权限段SQL 审查时先查这一行。6. 二次开发实战给资产编号加一套可配置的编码规则6.1 设计编码规则表源码里自带的编号规则通常是“资产分类前缀 当天日期 三位序号”比如 ZC-20250106-001。但不同企业有自己的习惯有的要加部门编码有的要按年份重置序号。硬编码显然不行我一般会加一张编码规则配置表让管理员在页面上自己改规则。create table asset_code_rule ( rule_id int primary key auto_increment, category_id bigint not null, prefix varchar(20), split_char varchar(5) default -, date_pattern varchar(10) default yyyyMMdd, serial_length int default 3, reset_mode varchar(10) default year, update_time datetime );表结构里reset_mode决定序列号怎么重置year表示每年从 001 重新计数day表示每天重置none表示一直累加。这个配置项是二次开发时被问得最多的点很多企业是要“资产编号全局唯一、格式好看、能看出归属”配置表比改代码灵活得多。6.2 编写一个独立的编号生成器生成器类放在 common 包里核心逻辑是读规则、拼前缀、取序列号。序列号的生成方式有两种选择并发量小用数据库查当天最大编号再加一并发大就改用 Redis 的 INCR。public String generate(Long categoryId) { CodeRule rule codeRuleMapper.selectByCategoryId(categoryId); String prefix rule.getPrefix(); String datePart LocalDate.now().format(DateTimeFormatter .ofPattern(rule.getDatePattern())); int serial serialNumService.nextSerial( rule.getResetMode(), rule.getDatePattern()); String serialStr String.format(%0 serialLength d, serial); return prefix rule.getSplitChar() datePart rule.getSplitChar() serialStr; }每次调用生成器都要先查规则再取序列号最后把三段拼接。serialLength 动态参与格式化比如规则改成 4 位序号生成的编号自动变成 ZC-20250106-0001不用改 Java 代码。需要保证唯一性时建议在 fixed_asset 表上继续保留 asset_no 的唯一索引数据库层永远做最后一道防线。6.3 接入 Service 并验证把原来 Controller 里生成编号的逻辑下沉到 Service 层同时判断当前资产是“新增”才生成编号“编辑”时保持不变。调整完成后照例走一遍验收路径新建一条资产确认编号按新规则生成把规则里的 prefix 改成 ZC再新增一条确认新旧编号能同时存在。如果项目里同时存在“按分类不同规则”的需求给 code_rule 表按分类多配几条规则即可。从那以后我每次改完这类公共逻辑都强制走一遍“新增、编辑、导入导出、权限复核”四步回归宁可多花十分钟也不愿意交付后收到“编号怎么变成这样了”的反馈。希望这篇拆解能帮你把项目跑起来也能让你在改造时有明确的下手点。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询