在企事业单位日常运营中,固定资产管理一直是后勤部门的重要工作痛点。传统的手工台账管理方式效率低下,容易出现资产流失、重复采购、维护不及时等问题。我们团队基于ThinkPHP和Laravel双框架开发的这套系统,正是为了解决这些实际业务场景中的管理难题。
这个系统最核心的业务价值在于实现了固定资产全生命周期的数字化管理。从资产入库、借用申请、维修记录到租赁管理,所有环节都通过线上流程完成,不仅大幅提升了管理效率,还通过数据驱动的方式为决策提供了支持。比如系统可以自动生成资产折旧报表、维修成本分析、使用率统计等关键业务数据。
技术选型心得:选择ThinkPHP和Laravel双框架并非偶然。ThinkPHP以其简洁的MVC架构和丰富的企业级功能,非常适合处理固定资产管理这类结构化数据业务;而Laravel优雅的ORM和队列系统,则完美支撑了审批流程、消息通知等需要高灵活性的功能模块。
系统采用前后端分离架构,后端提供RESTful API接口,前端使用Vue.js构建管理界面。这种架构的最大优势在于:
在API设计上,我们遵循了以下规范:
php复制// 资产列表API示例
Route::group(['prefix' => 'api/v1'], function() {
Route::get('assets', 'AssetController@index'); // 资产列表
Route::post('assets', 'AssetController@store'); // 新增资产
Route::put('assets/{id}', 'AssetController@update'); // 更新资产
Route::delete('assets/{id}', 'AssetController@destroy'); // 删除资产
});
固定资产管理系统的数据模型相对复杂,我们设计了以下核心表结构:
| 表名 | 主要字段 | 说明 |
|---|---|---|
| assets | id, name, category_id, status, purchase_date, price | 资产基本信息表 |
| asset_categories | id, name, depreciation_rate | 资产分类表 |
| borrow_records | id, asset_id, user_id, borrow_date, expected_return | 借用记录表 |
| maintenance_records | id, asset_id, fault_desc, cost, status | 维修记录表 |
| rental_contracts | id, asset_id, lessee, start_date, end_date, rent | 租赁合同表 |
为了提高查询性能,我们采取了以下优化措施:
资产借用是系统中最常用的功能之一,其业务流程如下:
在代码实现上,我们使用Laravel的Eloquent ORM处理业务逻辑:
php复制class BorrowController extends Controller
{
public function store(Request $request)
{
$validated = $request->validate([
'asset_id' => 'required|exists:assets,id',
'borrow_date' => 'required|date',
'expected_return' => 'required|date|after:borrow_date'
]);
$borrow = BorrowRecord::create([
'asset_id' => $validated['asset_id'],
'user_id' => auth()->id(),
'borrow_date' => $validated['borrow_date'],
'expected_return' => $validated['expected_return'],
'status' => 'pending'
]);
// 触发审批流程
event(new BorrowRequestCreated($borrow));
return response()->json($borrow, 201);
}
}
维修管理模块实现了故障报修、维修派工、维修验收的完整闭环。关键技术点包括:
我们在ThinkPHP中实现了维修状态机:
php复制class MaintenanceService
{
const STATUS_PENDING = 'pending';
const STATUS_ASSIGNED = 'assigned';
const STATUS_PROCESSING = 'processing';
const STATUS_COMPLETED = 'completed';
const STATUS_REJECTED = 'rejected';
private $stateMachine = [
self::STATUS_PENDING => [self::STATUS_ASSIGNED, self::STATUS_REJECTED],
self::STATUS_ASSIGNED => [self::STATUS_PROCESSING],
self::STATUS_PROCESSING => [self::STATUS_COMPLETED],
];
public function changeStatus($record, $newStatus)
{
if (!in_array($newStatus, $this->stateMachine[$record->status])) {
throw new \Exception('非法状态变更');
}
$record->status = $newStatus;
$record->save();
// 记录状态变更日志
MaintenanceLog::create([
'record_id' => $record->id,
'from_status' => $record->getOriginal('status'),
'to_status' => $newStatus,
'operator' => auth()->id()
]);
}
}
系统内置了多种预警规则,可以主动发现管理中的异常情况:
预警功能的实现依赖于Laravel的任务调度系统:
php复制// 在App\Console\Kernel中定义定时任务
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
// 检查超期借用
$overdue = BorrowRecord::where('expected_return', '<', now())
->where('status', '!=', 'returned')
->get();
foreach ($overdue as $record) {
event(new BorrowOverdue($record));
}
})->daily();
}
系统提供了丰富的数据分析功能,帮助管理者掌握资产状况:
前端使用ECharts实现可视化展示,后端提供聚合数据接口:
php复制class AssetReportController extends Controller
{
public function valueDistribution()
{
$data = AssetCategory::withSum('assets', 'price')
->get()
->map(function ($category) {
return [
'name' => $category->name,
'value' => $category->assets_sum_price
];
});
return response()->json($data);
}
}
我们推荐以下部署架构:
典型的Nginx配置示例:
nginx复制server {
listen 80;
server_name asset.example.com;
root /var/www/asset/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
在高并发场景下,我们采取了以下优化措施:
针对常见的N+1查询问题,我们使用Laravel的预加载功能:
php复制// 不好的写法(会产生N+1查询)
$assets = Asset::all();
foreach ($assets as $asset) {
echo $asset->category->name;
}
// 优化后的写法
$assets = Asset::with('category')->get();
foreach ($assets as $asset) {
echo $asset->category->name;
}
在系统需要支持多个独立组织使用时,我们实现了多租户架构。关键技术点包括:
我们在中间件中识别租户信息:
php复制class IdentifyTenant
{
public function handle($request, $next)
{
$tenant = Tenant::where('domain', $request->getHost())->first();
if (!$tenant) {
abort(404, '租户不存在');
}
Config::set('tenant', $tenant);
// 设置数据库连接
config([
'database.connections.tenant' => [
'driver' => 'mysql',
'host' => $tenant->db_host,
'database' => $tenant->db_name,
'username' => $tenant->db_user,
'password' => $tenant->db_pass,
]
]);
DB::setDefaultConnection('tenant');
return $next($request);
}
}
固定资产管理涉及大量附件上传,如:
我们使用Laravel的Filesystem抽象层,支持本地存储和云存储切换:
php复制// 配置示例
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
],
// 控制器中使用
public function uploadPhoto(Request $request)
{
$path = $request->file('photo')->store('asset-photos', 'public');
$asset = Asset::find($request->asset_id);
$asset->photo_url = Storage::url($path);
$asset->save();
return response()->json(['url' => $asset->photo_url]);
}
文件上传安全提示:一定要验证文件类型、大小,并对上传文件进行病毒扫描。我们遇到过攻击者上传恶意脚本的情况,后来增加了严格的验证规则。
系统提供了完善的API文档和SDK,方便与其他系统集成。开发新API时需要注意:
我们使用Swagger生成API文档,示例注解:
php复制/**
* @OA\Get(
* path="/api/v1/assets",
* tags={"Assets"},
* summary="获取资产列表",
* @OA\Parameter(
* name="category",
* in="query",
* description="资产分类ID",
* required=false,
* @OA\Schema(type="integer")
* ),
* @OA\Response(
* response=200,
* description="成功返回",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref="#/components/schemas/Asset")
* )
* )
* )
*/
public function index(Request $request)
{
// 控制器实现
}
对于复杂的审批流程,我们集成了工作流引擎,实现了:
工作流定义示例(BPMN格式):
xml复制<process id="borrow_approval" name="资产借用审批流程">
<startEvent id="start" />
<userTask id="dept_approve" name="部门审批" />
<sequenceFlow sourceRef="start" targetRef="dept_approve" />
<exclusiveGateway id="gateway1" />
<sequenceFlow sourceRef="dept_approve" targetRef="gateway1" />
<sequenceFlow sourceRef="gateway1" targetRef="admin_confirm">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${amount < 10000}]]>
</conditionExpression>
</sequenceFlow>
<userTask id="admin_confirm" name="管理员确认" />
<sequenceFlow sourceRef="admin_confirm" targetRef="end" />
<sequenceFlow sourceRef="gateway1" targetRef="director_approve">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[${amount >= 10000}]]>
</conditionExpression>
</sequenceFlow>
<userTask id="director_approve" name="分管领导审批" />
<sequenceFlow sourceRef="director_approve" targetRef="admin_confirm" />
<endEvent id="end" />
</process>
我们建立了多层次的测试体系:
典型的单元测试示例:
php复制class AssetServiceTest extends TestCase
{
public function test_asset_depreciation_calculation()
{
$category = AssetCategory::factory()->create([
'depreciation_rate' => 0.2 // 20%年折旧率
]);
$asset = Asset::factory()->create([
'category_id' => $category->id,
'price' => 10000,
'purchase_date' => now()->subYears(2)
]);
$service = new AssetService();
$value = $service->calculateDepreciatedValue($asset);
$this->assertEquals(6400, $value); // 10000*(1-0.2)^2
}
}
我们使用GitLab CI实现自动化构建和部署:
yaml复制stages:
- test
- build
- deploy
unit_test:
stage: test
script:
- php artisan test
dusk_test:
stage: test
script:
- php artisan dusk
only:
- master
build_frontend:
stage: build
script:
- npm install
- npm run production
artifacts:
paths:
- public/css
- public/js
deploy_production:
stage: deploy
script:
- rsync -avz --delete . deploy@production:/var/www/asset
only:
- master
我们实施了全面的安全措施:
安全中间件示例:
php复制class SecurityHeaders
{
public function handle($request, $next)
{
$response = $next($request);
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
$response->headers->set('Content-Security-Policy', "default-src 'self'");
return $response;
}
}
系统采用RBAC权限模型,实现了:
权限检查中间件:
php复制class CheckPermission
{
public function handle($request, $next, $permission)
{
if (!auth()->user()->can($permission)) {
abort(403, '无权访问');
}
return $next($request);
}
}
// 路由中使用
Route::get('assets/export', 'AssetController@export')
->middleware('permission:export_assets');
经过半年多的开发和迭代,系统已经在多个客户现场成功部署,平均提升了固定资产管理效率60%以上,减少了约30%的资产闲置浪费。从技术角度看,ThinkPHP和Laravel双框架的组合展现了良好的互补性,既保证了开发效率,又满足了复杂业务场景的需求。
在实际部署中,有几个经验值得分享:
系统未来的演进方向包括:
对于考虑开发类似系统的团队,我的建议是: