1. 项目背景与核心价值
这套基于Layui的PHP资产管理系统,是我在IT部门工作五年间逐步打磨出来的实战工具。最初源于公司固定资产管理的混乱现状——设备台账不全、领用记录缺失、维修状态不明,每次审计都要耗费大量人力整理Excel表格。市面上成熟的商业系统要么功能过剩,要么价格昂贵,于是决定用最熟悉的PHP技术栈自建解决方案。
选择Layui作为前端框架有几个关键考量:首先,它的组件开箱即用,表格、表单、弹窗等元素能快速搭建管理界面;其次,轻量级特性(核心文件仅100KB左右)特别适合内网部署环境;最重要的是,其经典的iframe多标签页模式,对习惯了传统ERP界面的行政人员非常友好。后端采用原生PHP开发,确保在老旧服务器上也能流畅运行,避免框架依赖带来的兼容性问题。
系统核心解决了这些痛点:
- 资产全生命周期追踪(采购入库→领用登记→维修记录→报废处置)
- 自动生成符合财务规范的折旧报表
- 基于部门/人员的多维统计视图
- 低门槛操作界面(支持扫码枪快速录入)
2. 技术架构与关键实现
2.1 前端层设计要点
Layui的模块化设计是本系统的骨架。通过以下代码结构组织功能模块:
javascript复制layui.config({
base: '/static/modules/'
}).extend({
assetTable: 'asset/table',
assetForm: 'asset/form'
});
表格渲染是核心交互,这里优化了三个细节:
- 动态列配置:根据不同资产类型(电脑/办公家具等)自动显示对应字段
- 单元格批注:鼠标悬停显示完整采购信息或维修历史
- 行内编辑:双击单元格直接修改状态,避免频繁跳转页面
javascript复制layui.use(['assetTable'], function(){
var table = layui.assetTable;
table.render({
elem: '#assetTable',
url: '/api/asset/list',
cols: [[
{type: 'checkbox'},
{field: 'sn', title: '资产编号', sort: true},
{field: 'type_name', title: '类型', templet: '#typeTpl'},
{field: 'status', title: '状态', edit: 'text'} // 允许直接编辑状态
]]
});
});
2.2 后端数据处理逻辑
PHP端采用经典的三层架构:
code复制/application
/controller // 路由控制
/service // 业务逻辑
/dao // 数据操作
资产入库的典型处理流程:
php复制class AssetService {
public function addAsset($data) {
// 校验必填字段
if (empty($data['sn']) || empty($data['price'])) {
throw new Exception('资产编号和价格不能为空');
}
// 生成财务凭证号
$data['finance_code'] = 'AST-' . date('Ymd') . str_pad(mt_rand(1,999), 3, '0', STR_PAD_LEFT);
// 写入主表
$assetId = AssetDao::save($data);
// 记录操作日志
OperationLogDao::log('asset_add', $assetId);
return $assetId;
}
}
2.3 数据库关键设计
资产主表结构示例:
sql复制CREATE TABLE `asset` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sn` varchar(32) NOT NULL COMMENT '资产编号',
`type_id` smallint(6) NOT NULL COMMENT '类型',
`name` varchar(100) NOT NULL COMMENT '资产名称',
`spec` varchar(255) DEFAULT NULL COMMENT '规格型号',
`price` decimal(10,2) NOT NULL COMMENT '采购价格',
`finance_code` varchar(32) DEFAULT NULL COMMENT '财务凭证号',
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1-在库 2-在用 3-维修 4-报废',
`location` varchar(255) DEFAULT NULL COMMENT '存放位置',
`user_id` int(11) DEFAULT NULL COMMENT '使用人',
`purchase_date` date DEFAULT NULL COMMENT '采购日期',
`scrap_date` date DEFAULT NULL COMMENT '报废日期',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_sn` (`sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
关联表设计技巧:
- 使用type_id关联类型字典表,便于扩展新资产类别
- 状态字段采用位运算存储复合状态(如"待报废"状态可表示为
status & 8) - 操作日志表记录完整变更历史,包含修改前后的JSON快照
3. 部署实践与性能优化
3.1 环境搭建避坑指南
在CentOS 7上的典型安装步骤:
bash复制# 安装基础环境
yum install -y httpd php php-mysql php-gd php-mbstring
# 配置PHP(重点调整以下参数)
memory_limit = 256M
post_max_size = 50M
upload_max_filesize = 50M
session.save_handler = files
session.save_path = "/var/lib/php/session"
# 目录权限设置
chown -R apache:apache /var/www/html/assets/uploads
chmod -R 755 /var/www/html/application/runtime
常见部署问题解决方案:
- 中文乱码:确保数据库连接字符集为utf8mb4
php复制$db = new PDO('mysql:host=localhost;dbname=asset;charset=utf8mb4', 'user', 'pass'); - 文件上传失败:检查selinux状态
bash复制
setsebool -P httpd_unified 1 - 会话无法保持:确认session.save_path可写
3.2 高并发场景优化
通过以下措施提升响应速度:
- 静态资源CDN分发:将Layui的JS/CSS上传至内网文件服务器
- 数据库查询优化:
php复制// 原始查询 $assets = $db->query("SELECT * FROM asset WHERE status=1"); // 优化后 $assets = $db->prepare("SELECT id,sn,name FROM asset WHERE status=?"); $assets->execute([1]); - 缓存热点数据:使用APCu缓存部门树等高频访问数据
php复制if (!apcu_exists('department_tree')) { $tree = DepartmentService::buildTree(); apcu_store('department_tree', $tree, 3600); }
3.3 安全加固方案
必须实施的五项安全措施:
- 输入过滤:所有用户输入强制类型转换
php复制$id = (int)$_GET['id']; // 防止SQL注入 - 目录保护:禁止直接访问runtime目录
apache复制<Directory "/var/www/html/application/runtime"> Deny from all </Directory> - 防CSRF:关键操作需验证token
html复制<input type="hidden" name="__token__" value="<?=session_id()?>"> - 操作审计:记录管理员所有敏感操作
- 定期备份:设置mysqldump定时任务
4. 扩展开发与二次定制
4.1 常见业务扩展场景
- 对接企业微信审批流:
php复制// 资产报废审批回调示例
public function wechatCallback() {
$data = json_decode(file_get_contents('php://input'), true);
if ($data['Event'] == 'sys_approval_change') {
$result = ApprovalService::handle($data['ApprovalId']);
echo json_encode(['errcode' => 0]);
}
}
- 批量导入优化方案:
- 使用PHPExcel处理复杂Excel模板
- 内存优化技巧:
php复制$reader = PHPExcel_IOFactory::createReader('Excel2007'); $reader->setReadDataOnly(true); // 只读数据不加载样式 $spreadsheet = $reader->load($filePath);
- 移动端适配改造:
- 基于Layui的响应式布局调整
- 扫码功能集成:
javascript复制layui.use(['jquery', 'assetMobile'], function(){ $('#scanBtn').click(function(){ assetMobile.scanCode(function(sn){ location.href = '/mobile/detail?sn=' + sn; }); }); });
4.2 报表开发实战
固定资产折旧计算逻辑:
php复制public function calculateDepreciation($asset, $month) {
// 直线法计算月折旧
$months = ($asset['service_life'] ?? 60) * 12;
$residualRate = 0.05; // 残值率5%
$depreciation = round(
$asset['price'] * (1 - $residualRate) / $months,
2
);
// 生成月度折旧记录
DepreciationDao::save([
'asset_id' => $asset['id'],
'month' => $month,
'amount' => $depreciation,
'balance' => $asset['price'] - $depreciation * $this->getPassedMonths($asset, $month)
]);
return $depreciation;
}
4.3 系统集成方案
与现有OA系统对接的三种方式:
- 数据库级同步:通过定时任务双向同步用户表
- API接口对接:提供RESTful接口供调用
php复制$router->get('/api/external/asset/{sn}', 'AssetController@getBySn'); - 单点登录集成:基于SAML协议实现
5. 运维监控与故障处理
5.1 日常维护清单
必须定期检查的五个指标:
- 数据库表空间使用率(特别是操作日志表)
- 上传目录文件数量(避免堆积扫描件)
- 定时任务执行日志
- 最近一周的异常登录记录
- 备份文件完整性验证
5.2 典型故障排查
- 页面加载缓慢:
- 检查Nginx+PHP-FPM配置
nginx复制location ~ \.php$ { fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; } - 分析慢查询日志
sql复制SELECT * FROM mysql.slow_log WHERE start_time > NOW() - INTERVAL 1 DAY ORDER BY query_time DESC LIMIT 10;
- 报表数据异常:
- 验证折旧计算基准日是否正确
- 检查资产状态变更日志是否有误操作
- 对比财务系统的凭证记录
5.3 升级迁移策略
跨版本升级注意事项:
- 数据库变更必须通过迁移脚本执行
php复制// 20230501_add_asset_insurance.php class Migration_20230501 { public function up() { DB::query("ALTER TABLE asset ADD COLUMN insurance varchar(100)"); } } - 保留旧版本代码的兼容层
- 灰度发布方案:先在内网测试环境验证所有报表
这套系统经过三年迭代,目前稳定管理着2000+固定资产项。最大的体会是:资产管理系统成功的关键不在于技术复杂度,而在于业务流程的标准化程度。建议实施前先花时间梳理清楚企业的资产管理规范,特别是跨部门协作流程,否则再好的系统也只会成为另一个信息孤岛。
