ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于LayuiMini与PHP的固定资产管理系统设计与实践

基于LayuiMini与PHP的固定资产管理系统设计与实践 做后台管理系统这些年我接到过不少类似的需求单位里固定资产上千件台账全靠一张Excel今天有人领了台笔记本没登记明天报废的显示器还在资产目录里挂着。去年我亲手落地了一套基于LayuiMini框架的PHP资产管理系统专门面向IT办公行业的固定资产与设备管理场景从需求梳理到部署上线前后花了一周多。这套源码在很多开源站上已经能搜到但搜到源码只是开始真正让它跑起来并在团队里用顺才是大部分人的坎。这篇文章我会把系统设计思路、数据库结构、核心功能实现、部署步骤和二次开发方向一次讲透顺便把我踩过的坑原原本本列出来。适合三类人看一是公司IT部门想搭一套内部资产平台的二是PHP开发者想找个能直接改的后台管理项目练手三是做外包的朋友需要快速交付资产管理类需求。1. 项目定位这套资产管理系统到底在解决什么问题1.1 IT办公行业的资产管理痛点IT办公行业的固定资产和其他行业不太一样设备品类多、变更频率高、责任归属复杂。一台笔记本从采购入库到分配给员工中间可能经历领用、归还、再分配、维修、调拨最后报废整个过程如果全靠人来记基本一定会乱。我见过的典型场面行政部门有一份资产总表财务部门有一份折旧表IT部门自己又维护一份设备维修记录表三份表的数据永远对不上。问起一台显示器的去向相关负责人只能说好像在小张那。这套系统的核心价值就是把资产从入库到报废的所有状态变更收拢到一个平台上每一件资产都有唯一编码每一次状态变化都有记录谁在什么时间领走了什么设备、设备当前在哪个部门哪个人手里打开系统随时能查。这本质上解决的是账实一致和责任可追溯两个问题。1.2 功能边界与角色模型设计项目立项时我没有急着写代码先把角色和流程定死了。系统里规划了三种角色管理员、部门负责人、普通员工。管理员负责资产的录入、处置、盘点、数据维护和系统配置部门负责人只能看到本部门的数据负责审批下属的领用和借用申请普通员工可以提交申请查看自己名下领用了哪些资产。这种角色模型没有做得特别复杂因为资产管理系统不是OA系统过度设计权限只会增加维护成本但对中小型IT办公团队来说足够清晰。核心业务流程我梳理为七个环节登记入库、领用申请、审批发放、归还入库、调拨转移、维修登记、盘点处置。系统里所有功能都围绕这七个环节展开每个环节都会产生一条操作记录形成完整的生命周期闭环。1.3 为什么是LayuiMiniPHP而不是前后端分离很多朋友会问现在新项目不都上VueSpring Boot了吗为什么还要用LayuiMini这种老牌框架我的答案很简单内部管理系统最看重的是部署简单、维护成本低、改起来快。PHPMySQL这对组合在中小型应用里依然是最省事的方案虚拟主机能跑云服务器能跑Windows服务器装个PHPStudy也能跑。LayuiMini是经典Layui框架的增强封装自带一套清爽的后台管理布局——左侧菜单、顶部栏、右侧内容区正好是后台管理系统的标准形态不需要自己从零搭布局。LayuiMini保留了Layui的模块化加载机制每个页面按需引入模块比如form、table、laydate这些组件。对PHP开发者来说Layui的交互组件和jQuery时代的思维模式很接近不用重新学一套响应式框架的工程化体系。在这个项目里前端负责页面渲染和交互后端PHP只做数据校验和接口输出两者通过AJAX交换JSON数据分工简单直接。2. 架构设计与数据库核心表2.1 整体技术栈与环境依赖这套源码的技术栈很常规但正因为常规才稳定。后端要求PHP 7.4以上实测PHP 8.0和8.1都能跑得比较顺畅如果使用PHP 8.2需要留意一些第三方库的兼容性声明数据库用MySQL 5.7或8.0Web服务器推荐NginxApache也可以本地开发直接用PHPStudy或宝塔面板即可。开发调试工具我用的PHPStorm配合Xdebug做断点调试。很多做PHP的同学习惯在代码里到处写var_dump和die但在这个项目里接口都是返回JSON用调试工具看请求的请求头和返回内容反而更清晰。遇到AJAX请求不出数据的情况打开浏览器开发者工具看Network标签页基本能定位八成的接口问题。2.2 八张核心表的结构设计思路数据库一共规划了八张核心表我把它们列出来表名用途说明asset资产主表存储资产的基本信息和当前状态category资产分类表如笔记本、显示器、服务器、网络设备等department部门表维护组织架构user用户表包含登录账号、密码哈希、角色关联asset_record资产操作流水表记录所有状态变更历史maintenance维修记录表登记故障与维修情况check_record盘点记录表存储盘点任务与结果depreciation折旧计算表用于保存每期的折旧数据其中最关键的是asset表和asset_record表。asset表里常见的核心字段包括资产编号、资产名称、分类ID、品牌型号、序列号、供应商、购买价格、购买日期、保修截止日期、当前状态、使用部门ID、使用人ID、存放位置、备注。asset_record表的设计思路是只追加、不修改、不删除。每条记录包含资产ID、操作类型、操作前状态、操作后状态、操作人ID、操作时间、备注信息。这样设计的好处非常直接——任何时候都能回放某件资产的完整历史审计的时候不需要翻Excel和纸质单据。2.3 资产编码与状态机的规则设计资产编码是整个系统的骨架我强烈建议不要直接用数据库自增ID当作资产编码对外展示。一则容易泄露业务数量二则后期导入历史数据时会产生冲突。这套系统采用的编码规则是固定资产大类简称年月四位流水号比如电脑类资产在2025年6月登记的第7台设备编码就是DN-202506-0007。资产状态我用一个整数类型字段存储枚举定义为1表示在库2表示已领用3表示维修中4表示已调拨调拨完成后会回到在库或已领用5表示已报废。状态流转必须走统一的接口不允许直接改数据库字段否则流程记录就是断的。3. 核心功能模块从登记到报废的全生命周期实现3.1 入库登记与资产编码生成入库是整个系统的起点。资产到货后管理员在后台进入资产入库页面选择资产分类、填写品牌型号、序列号、供应商、购买价格、购买日期等信息。系统自动生成资产编码并用一个二维码插件生成对应的资产二维码可以打印出来贴到设备上。在PHP后端资产编码的生成逻辑不复杂但必须保证并发下不重复public function generateAssetCode($categoryPrefix ZC) { $datePart date(Ym); // 从数据库里查出当前月份已使用的最大流水号 $maxSeq $this-db-query( SELECT MAX(SUBSTRING(asset_code, 8)) AS max_seq FROM asset WHERE asset_code LIKE {$categoryPrefix}-{$datePart}-% )-fetchColumn(); $newSeq str_pad((int)$maxSeq 1, 4, 0, STR_PAD_LEFT); return {$categoryPrefix}-{$datePart}-{$newSeq}; }注意这里用了SUBSTRING(asset_code, 8)来取流水号因为前缀加年月固定占7位比如DN-202506是8位如果前缀是ZCZC-202506也是8位要注意统一编码长度。如果分类前缀长度不统一建议用正则表达式或者单独维护一张编码序列号表来控制避免并发插入时拿到同一个流水号。表单提交时后端需要先做一次唯一性校验查询序列号是否已经在库里存在。IT设备的序列号是由厂商出厂时确定的绝不会重复这是判断资产是否重复入库最重要的依据。3.2 领用申请、审批与归还的实现细节员工登录系统后在资产列表页浏览当前在库的资产点击申请领用按钮发起申请。申请表单里需要选择资产、填写使用原因、预计使用时长系统默认领用周期为长期借用周期为短期。审批流程是典型的单级审批提交后状态变为待审批部门负责人在工作台看到待办列表点击同意后系统自动执行两件事——修改资产状态为已领用写入一条asset_record流水记录使用人、部门、审批人、审批时间和申请表单编号。归还流程我建议在代码里加上一个归还状态检查这一步很容易被忽略。归还登记时管理员应该对设备外观和基本功能做检查确认完好才允许入库。我在系统里做了一个归还备注字段如果设备有损坏可以在归还时直接勾选送修系统会自动把资产状态置为维修中然后跳转到维修登记表单减少一次人工操作。3.3 调拨、维修与盘点调拨场景在IT办公行业很常见员工调岗、部门重组资产要跟着人走。调拨流程在前端表现为一个表单选择目标部门和目标使用人提交后资产的使用部门和使用人字段被更新同时system记录一条调拨流水保留原部门和新部门信息。维修模块是一个独立的功能入口任何状态下的资产都可以发起维修申请。维修记录表里至少要包含这几个字段故障描述、维修商、维修费用、送修时间、预计归还时间、维修结果。维修完成后由管理员操作维修完毕资产从维修中回到在库或已领用状态。盘点模块我设计为创建盘点任务→逐项核对→生成差异报告三步。管理员创建盘点任务时可以选择盘点的范围比如只盘某个部门或某个分类的资产。盘点时系统按列表逐项展示管理员需要勾选正常或异常。盘点结束后系统自动列出账实不符的资产清单差异项可以一键生成报损或调账单据并写入盘点记录表。3.4 折旧计算与报表统计财务视角的折旧是这个系统的另一个重头戏。系统内置了最常用的直线折旧法原则是当月新增资产当月不计提折旧次月开始计提。public function calcDepreciation($asset) { $originalValue floatval($asset[purchase_price]); $residualRate 0.05; // 残值率5% $usefulMonths $asset[category_useful_months]; // 例如60个月 $monthlyDepreciation round( ($originalValue - $originalValue * $residualRate) / $usefulMonths, 2 ); $purchaseMonth date(Ym, strtotime($asset[purchase_date])); $currentMonth date(Ym); // 从购入次月起算已提月数 $elapsedMonths max(0, (int)$currentMonth - (int)$purchaseMonth - 1 ); $totalDepreciation min($monthlyDepreciation * $elapsedMonths, $originalValue - $originalValue * $residualRate); return [ monthly $monthlyDepreciation, total round($totalDepreciation, 2), net_value round($originalValue - $totalDepreciation, 2), ]; }报表统计方面前端我用了一个折线图和两个饼图来展示一个折线图展示近12个月的新增资产数量和报废数量趋势一个饼图按资产分类统计数量占比一个饼图按资产当前状态统计在库、已领用、维修中的比例。数据接口在PHP后端做聚合查询基本用一个GROUP BY就能搞定。-- 按状态统计资产数量 SELECT status, COUNT(*) AS total FROM asset GROUP BY status;4. 项目管理与部署落地从源码到能跑起来4.1 部署前的环境配置源码拿到手之后不要急着上传服务器先把运行环境整理好。我在服务器上用的是NginxPHP 8.0MySQL 8.0的组合宝塔面板管理。如果你用Apache大部分设置是类似的但要注意伪静态规则需要额外配置。Nginx配置的核心配置块大概是这样server { listen 80; server_name asset.example.com; root /www/wwwroot/asset/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/tmp/php-cgi-80.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 7d; access_log off; } }这里比较容易踩坑的是root指向的目录如果源码结构是public目录作为Web根目录那root必须指向public否则访问路由会全部404。4.2 初始化步骤与上线配置环境准备好之后初始化项目我总结了几个固定步骤创建数据库并导入根目录下的asset.sql文件SQL文件里包含了表结构和初始管理员账号数据。修改config/database.php配置文件把数据库主机、库名、用户名、密码改成自己环境里的实际值。确认runtime目录可写基于ThinkPHP的项目如果没有写权限运行时会产生大量报错。登录后台浏览器访问/admin进入登录页初始账号admin初始密码需要看SQL文件里的说明登录成功后第一时间在个人中心修改密码。到系统设置页面把网站名称、公司名称这些基本配置改掉避免页面底部出现示例站信息。我之前帮朋友部署这套系统时第一步就改了数据库密码然后在配置文件里填错了库名结果登录页一直提示数据库连接失败。排查了半天才发现是配置文件里有两处环境变量需要同步修改一处是数据库配置另一处是缓存配置里的数据库选择。4.3 权限、安全与备份权限控制这块我建议不要只在代码里判断角色而是把角色和权限规则放进数据库做一个简单的RBAC模型。LayuiMini前端配合后端接口做菜单权限控制不同角色登录后看到的菜单项不同接口层再做一次权限校验做到双重判断。安全方面有几件很小但很重要的事必须做第一数据库密码不要用弱密码第二所有SQL必须用预处理参数绑定的方式执行我见过不少PHP资产管理项目里字符串拼接SQL导致SQL注入的这类系统里装的全是公司内部资产信息泄露后果很严重第三登录密码一律用password_hash()存储不要存明文。备份策略我是用Linux的crontab每天凌晨执行一次MySQL全量备份0 2 * * * mysqldump -u root -p你的密码 asset /backup/asset_$(date \%Y\%m\%d).sql find /backup -name asset_*.sql -mtime 30 -delete这条脚本会保留最近30天的备份超过30天自动清理磁盘压力很小但能救命。5. 常见问题与避坑经验5.1 高频问题排查速查表在实际使用过程中我整理了下面这个速查表很多问题都出在这些地方故障现象可能原因解决办法登录页打不开或样式错乱LayuiMini静态资源路径不对检查base配置和静态资源引用路径确认public目录是否作为Web根目录登录后提示数据库查询失败配置文件的库名或密码错误核对config/database.php和.env文件中的数据库配置AJAX接口返回500错误PHP版本兼容性或代码语法问题打开PHP错误日志在入口文件临时开启display_errors定位资产列表加载很慢数据量大了之后缺少索引给asset表的asset_code、status、department_id字段加索引上传资产图片失败PHP的upload_max_filesize太小修改php.ini中upload_max_filesize和post_max_size改完重启PHP排查这类问题我有个习惯先在浏览器F12控制台看前端报的什么错再看Network标签页里的接口请求返回把错误消息复制下来去搜索比盲目改代码高效得多。5.2 我踩过的几个坑第一个坑是PHP 8.x环境下某几个扩展库不支持。这套系统在PHP 7.4上跑得好好的升到PHP 8.0后偶尔会出现类方法签名不兼容的警告。处理方式是先看PHP错误日志把有问题的第三方库替换成兼容版本或者改用官方API。建议生产环境固定PHP版本号不要随手升级。第二个坑是盘点功能上线后财务反馈Excel导出超时。我一开始用PHPExcel封装一次性导出全量数据资产到三千条以上时脚本直接内存溢出。后来改成CSV流式导出在文件指针里逐行写入内存占用控制在几MB以内问题立刻解决。第三个坑是资产编码重复。系统运行了半年后有同事反馈某台设备无法入库查了一遍是因为之前有人在数据库中手动INSERT了一条记录手工填了一个已经存在的资产编码又没有走系统的编码生成逻辑。从此以后我规定所有资产入库必须通过系统的入库表单操作运维人员在后台直接改数据的行为一律禁止。5.3 二次开发时最容易被忽略的设计很多接手这套源码开发的同事最容易忽略的一点是修改资产状态时必须同步写流水。如果只改了asset表的status字段而没有写asset_record表表面看资产状态变了但历史记录里查不到这条变更后续盘点对账时数据就会出现逻辑漏洞。我的建议是把状态变更统一封装成一个方法public function changeAssetStatus($assetId, $newStatus, $operatorId, $remark ) { $asset $this-getAssetById($assetId); $oldStatus $asset[status]; // 更新资产主表状态 $this-db-update(asset, [status $newStatus], [id $assetId]); // 写入操作流水 $this-db-insert(asset_record, [ asset_id $assetId, old_status $oldStatus, new_status $newStatus, operator_id $operatorId, remark $remark, created_at date(Y-m-d H:i:s), ]); }以后不管哪个模块要改变资产状态都调用这个公共方法流水一致性自然就保证了。6. 二次开发与扩展方向6.1 可以快速落地的三个增强功能这套系统跑顺后有几个增强功能很容易做而且对日常使用体验提升非常明显。第一个是资产二维码标签打印。系统里已经生成了每个资产的二维码只需做一个标签打印页面把资产名称、编码、二维码放到一个适合标签纸尺寸的模板里用浏览器打印功能批量输出。IT部门用一台热敏标签打印机就可以自己打印资产标签不需要外购。第二个是接入企业微信或钉钉审批。企业内部系统最大的痛点不是功能少而是用户不愿意每天登录一个独立的后台去处理待办。可以在这个系统里加一个简单的Webhook当有新的领用申请提交时通过Webhook推送到企业微信群机器人或钉钉群审批人在群里看到消息再去后台操作。实现成本很低但从无人使用到每天有人处理的转变非常明显。第三个是盘点扫码。普通的盘点流程是打印盘点单拿着纸去现场逐台核对然后再回电脑上录入结果效率很低。手持PDA或带扫码功能的手机进入H5盘点页面直接扫设备上的二维码系统自动标记该资产已盘点没被扫到的就是账实差异项。我在这个系统上实现了简单的扫码盘点接口一条URL/scan?code资产编码就能完成核对动作。6.2 扩展时控制规模和边界这套源码的定位是轻量级内部管理系统我不建议为了追求架构的先进性把它重构成微服务或者全面容器化。对大多数几十人到几百人的团队来说单体PHP应用配合MySQL足够扛住日常负载。如果后续并发量上来优先做的事情是加一层Redis缓存把资产列表的查询结果缓存起来然后做读写分离把统计类SQL放到从库。这些改造都不需要推翻重来在原框架基础上就能逐步完成。技术上还值得关注的是如果业务范围扩大到多公司或多账套数据库层面要增加一个公司ID字段做数据隔离前端再增加一个切换公司的下拉框即可。这是多数资产管理系统的终态需求在一开始设计asset主表时就可以预留这个字段省得以后数据迁移。我在这套系统的落地上最大的体会是资产管理系统的难点不在代码而在流程梳理。编码规则怎么定、状态机怎么转、审批链走几级这些业务规则定死了代码只是把它们翻译成功能而已。如果给我的同行一个建议我会说动手写代码之前先用一张纸画出资产从入库到报废的完整流程图把所有可能的状态和动作写出来再打开编辑器——这个习惯至少能帮你少返工一半的活儿。
返回列表