You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Laravel Vite优化资源打包并改进献血系统代码?

问题1:如何使用Laravel Vite对HTML、CSS和JS进行资源打包优化?

Laravel Vite是Laravel官方推荐的前端构建工具,以下是具体的优化步骤:

1. 基础配置确认

确保你的Laravel版本在9.x及以上(默认集成Vite),旧版本可通过以下命令升级并安装Vite:

composer require laravel/vite-plugin
npm install

2. 规范资源目录结构

将前端资源按类型组织在resources/js和resources/css目录下:

  • 入口文件:resources/js/app.js(统一导入JS模块和CSS)
  • 样式文件:resources/css/app.css(或使用Sass/Tailwind等预处理器)

3. CSS打包优化

  • 提取公共样式:将复用样式抽离为单独文件(如resources/css/components/button.css),在app.css中导入
  • 预处理器支持:安装Sass依赖后直接使用,Vite自动编译:
    npm install sass
    
    将样式文件改为.scss后缀,在app.js中导入:
    import '../css/app.scss';
    
  • 生产环境压缩:执行npm run build时,Vite会自动压缩CSS代码

4. JS打包优化

  • 模块化开发:将JS代码拆分为多个模块(如resources/js/utils/validation.js),通过ES6 import导入,Vite自动执行Tree Shaking移除未使用代码
  • 代码分割:使用动态导入实现按需加载,比如路由组件:
    const Dashboard = () => import('./pages/Dashboard.vue');
    
  • 生产环境混淆:npm run build会自动混淆压缩JS代码,减小体积

5. 资源引用与缓存优化

  • 在Blade模板中使用@vite指令加载资源,自动处理版本哈希(避免浏览器缓存旧资源):
    @vite(['resources/js/app.js', 'resources/css/app.css'])
    
  • 自定义Vite配置(vite.config.js),修改资源输出目录或添加CDN前缀:
    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    
    export default defineConfig({
      plugins: [
        laravel({
          input: ['resources/js/app.js', 'resources/css/app.css'],
          buildDirectory: 'build', // 自定义构建目录
        }),
      ],
    });
    

6. 额外优化

  • 图片处理:使用vite-plugin-imagetools压缩图片、支持WebP格式:
    npm install vite-plugin-imagetools
    
    配置后在代码中导入图片:
    import logo from '../images/logo.png?w=200&format=webp';
    
  • 字体优化:将本地字体放在resources/fonts目录,在CSS中引用,Vite自动处理打包和缓存
问题2:献血管理系统代码改进方案

以下是针对这套代码的具体改进点,覆盖数据库、模型、控制器、视图等核心层面:

一、数据库层优化

1. 增加字段约束与索引

修改迁移文件,为blood_type和status添加枚举约束,同时添加索引提升查询性能:

public function up(): void
{
    Schema::create('blood_donations', function (Blueprint $table) {
        $table->id();
        $table->string('donor_name', 255);
        // 血型枚举约束
        $table->enum('blood_type', ['A+','A-','B+','B-','AB+','AB-','O+','O-']);
        $table->integer('bags')->default(1)->unsigned(); // 袋数禁止为负
        // 状态枚举约束,默认可用
        $table->enum('status', ['available', 'used', 'expired'])->default('available');
        $table->date('donation_date');
        $table->date('expiry_date')->nullable();
        $table->timestamps();
        $table->softDeletes(); // 新增软删除字段

        // 添加索引加速查询
        $table->index('blood_type');
        $table->index('status');
        $table->index('donation_date');
    });
}

2. 自动计算过期日期

献血血液有效期通常为6个月,可在迁移后通过模型观察者自动设置,避免手动输入。

二、模型层优化

1. 使用枚举常量替代硬编码

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class BloodDonation extends Model
{
    use SoftDeletes;

    // 血型枚举常量
    const BLOOD_TYPES = ['A+','A-','B+','B-','AB+','AB-','O+','O-'];
    // 状态枚举常量
    const STATUS_AVAILABLE = 'available';
    const STATUS_USED = 'used';
    const STATUS_EXPIRED = 'expired';

    protected $fillable = [
        'donor_name', 'blood_type', 'bags',
        'status', 'donation_date', 'expiry_date'
    ];

    protected $dates = ['deleted_at'];

    // 自动设置过期日期
    protected static function booted()
    {
        static::creating(function ($donation) {
            if (!$donation->expiry_date) {
                $donation->expiry_date = $donation->donation_date->addMonths(6);
            }
        });
    }

    // 作用域:查询可用血液
    public function scopeAvailable($query)
    {
        return $query->where('status', self::STATUS_AVAILABLE);
    }

    // 访问器:格式化状态为中文
    public function getStatusLabelAttribute()
    {
        return match($this->status) {
            self::STATUS_AVAILABLE => '可用',
            self::STATUS_USED => '已使用',
            self::STATUS_EXPIRED => '已过期',
            default => '未知'
        };
    }
}

三、控制器层优化

1. 用表单请求类分离验证逻辑

创建StoreBloodDonationRequest和UpdateBloodDonationRequest类,替代控制器内的验证代码:

php artisan make:request StoreBloodDonationRequest

请求类示例:

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use App\Models\BloodDonation;

class StoreBloodDonationRequest extends FormRequest
{
    public function authorize()
    {
        return auth()->check(); // 仅登录用户可提交
    }

    public function rules()
    {
        return [
            'donor_name'    => 'required|string|max:255',
            'blood_type'    => 'required|in:'.implode(',', BloodDonation::BLOOD_TYPES),
            'bags'          => 'required|integer|min:1|max:10', // 限制袋数范围
            'status'        => 'required|in:'.implode(',', [BloodDonation::STATUS_AVAILABLE, BloodDonation::STATUS_USED, BloodDonation::STATUS_EXPIRED]),
            'donation_date' => 'required|date|before_or_equal:today',
        ];
    }

    // 自定义中文错误消息
    public function messages()
    {
        return [
            'blood_type.in' => '血型必须选择指定的有效类型',
            'status.in' => '状态只能是可用、已使用或已过期',
        ];
    }
}

控制器中使用:

public function store(StoreBloodDonationRequest $request)
{
    BloodDonation::create($request->validated());
    return redirect()->route('blood-donations.index')->with('success', '记录已添加!');
}

2. 优化报表查询性能

将集合过滤改为数据库原生查询,减少内存占用:

private function getData()
{
    $query = BloodDonation::query();

    // 统计总数据
    $total = $query->count();
    $available = $query->where('status', BloodDonation::STATUS_AVAILABLE)->sum('bags');
    $used = $query->where('status', BloodDonation::STATUS_USED)->sum('bags');
    $expired = $query->where('status', BloodDonation::STATUS_EXPIRED)->sum('bags');

    // 按血型分组统计
    $summary = $query->selectRaw('blood_type, SUM(bags) as total')
        ->selectRaw('SUM(CASE WHEN status = ? THEN bags ELSE 0 END) as available', [BloodDonation::STATUS_AVAILABLE])
        ->selectRaw('SUM(CASE WHEN status = ? THEN bags ELSE 0 END) as used', [BloodDonation::STATUS_USED])
        ->selectRaw('SUM(CASE WHEN status = ? THEN bags ELSE 0 END) as expired', [BloodDonation::STATUS_EXPIRED])
        ->groupBy('blood_type')
        ->get()
        ->keyBy('blood_type');

    // 补全所有血型,避免缺失
    $fullSummary = [];
    foreach (BloodDonation::BLOOD_TYPES as $type) {
        $fullSummary[] = $summary->get($type, [
            'type' => $type,
            'total' => 0,
            'available' => 0,
            'used' => 0,
            'expired' => 0,
        ]);
    }

    return [
        'total'     => $total,
        'available' => $available,
        'used'      => $used,
        'expired'   => $expired,
        'summary'   => $fullSummary,
        'donations' => $query->latest()->get(),
    ];
}

四、路由优化

1. 增加权限控制

使用Laravel Gate或权限包(如spatie/laravel-permission)添加权限验证:

Route::middleware(['auth', 'can:manage-blood-donations'])->group(function () {
    Route::resource('blood-donations', BloodDonationController::class);
    Route::get('/blood-reports', [BloodReportController::class, 'index'])->name('blood-reports.index');
    Route::get('/blood-reports/pdf', [BloodReportController::class, 'exportPdf'])->name('blood-reports.pdf');
    Route::get('/blood-reports/excel', [BloodReportController::class, 'exportExcel'])->name('blood-reports.excel');
});

2. 简化资源路由

仅保留需要的资源控制器方法:

Route::resource('blood-donations', BloodDonationController::class)->only(['index', 'create', 'store', 'edit', 'update', 'destroy']);

五、视图层优化

1. 完善表单与错误提示

在创建/编辑表单中添加所有字段,并显示验证错误:

{{-- 创建页表单 --}}
<form method="POST" action="{{ route('blood-donations.store') }}">
    @csrf
    <div>
        <label for="donor_name">献血者姓名</label>
        <input type="text" name="donor_name" id="donor_name" value="{{ old('donor_name') }}" required>
        @error('donor_name')
            <span class="text-red-500">{{ $message }}</span>
        @enderror
    </div>

    <div>
        <label for="blood_type">血型</label>
        <select name="blood_type" id="blood_type" required>
            @foreach(App\Models\BloodDonation::BLOOD_TYPES as $type)
                <option value="{{ $type }}" {{ old('blood_type') == $type ? 'selected' : '' }}>{{ $type }}</option>
            @endforeach
        </select>
        @error('blood_type')
            <span class="text-red-500">{{ $message }}</span>
        @enderror
    </div>

    <!-- 袋数、状态、献血日期字段省略 -->

    <button type="submit">保存</button>
</form>

2. 分页与操作按钮优化

{{-- 列表页 --}}
@forelse($donations as $d)
    <div>
        <p>{{ $d->donor_name }} | {{ $d->blood_type }} | {{ $d->status_label }}</p>
        <a href="{{ route('blood-donations.edit', $d) }}">编辑</a>
        <form action="{{ route('blood-donations.destroy',$d) }}" method="POST" class="inline">
            @csrf @method('DELETE')
            <button type="submit" onclick="return confirm('确定要删除吗?')">删除</button>
        </form>
    </div>
@empty
    <p>暂无记录。</p>
@endforelse

{{-- 分页链接 --}}
{{ $donations->links() }}

六、报表导出优化

1. 支持日期范围筛选

避免导出全部数据,添加日期筛选:

public function exportExcel(Request $request)
{
    $query = BloodDonation::query();
    if ($request->start_date) {
        $query->where('donation_date', '>=', $request->start_date);
    }
    if ($request->end_date) {
        $query->where('donation_date', '<=', $request->end_date);
    }

    return Excel::download(new BloodReportExport($query), 'blood-report.xlsx');
}

修改导出类接收查询参数:

class BloodReportExport implements FromCollection, WithHeadings
{
    private $query;

    public function __construct($query)
    {
        $this->query = $query;
    }

    public function collection()
    {
        return $this->query->select(
            'donor_name','blood_type','bags','status','donation_date'
        )->get();
    }

    public function headings(): array
    {
        return ['献血者姓名','血型','袋数','状态','献血日期'];
    }
}

2. 异步处理大文件导出

使用Laravel队列避免请求超时:

public function exportPdf(Request $request)
{
    dispatch(new ExportBloodReportPdfJob($request->all()));
    return redirect()->route('blood-reports.index')->with('success', '报表正在生成,稍后将通知您!');
}

七、安全与性能优化

1. 缓存统计数据

缓存报表统计数据,减少数据库查询:

private function getData()
{
    return Cache::remember('blood-report-data', 3600, function () {
        // 原查询逻辑
    });
}

2. 防止批量赋值漏洞

严格控制$fillable字段,避免意外赋值;或使用$guarded = []明确允许所有字段赋值(需确保字段安全)。

内容的提问来源于stack exchange,提问作者Chingchongg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 01:22:28