Skip to content

导出中心插件

导出中心是 MineShop 的通用数据导出解决方案,支持大数据量异步导出、多种格式、进度追踪等功能。

🎯 系统架构

┌─────────────────────────────────────────────────────────────┐
│                      ExportService                           │
│                      导出服务层                               │
├─────────────────────────────────────────────────────────────┤
│   ExportJob        │   ExportWriter    │   DtoHydrator      │
│   异步任务          │   文件写入器       │   DTO 解析器        │
├─────────────────────────────────────────────────────────────┤
│                      Redis Queue                             │
│                      异步队列                                 │
└─────────────────────────────────────────────────────────────┘

✨ 核心特性

1. 注解驱动

使用 @ExportColumn 注解定义导出列:

php
// OrderExportDto.php
#[ExportColumn(name: '订单编号', index: 1)]
public string $orderNo;

#[ExportColumn(name: '下单时间', index: 2)]
public string $createdAt;

#[ExportColumn(name: '订单金额', index: 3)]
public float $totalAmount;

#[ExportColumn(name: '订单状态', index: 4)]
public string $statusText;

2. 多种写入器

写入器说明适用场景
PhpSpreadsheetWriter基于 PhpSpreadsheet小数据量、复杂格式
XlsWriterWriter基于 xlswriter 扩展大数据量、高性能

3. 异步队列

通过 ConfigProvider 自动注册队列配置:

php
// ConfigProvider.php
'async_queue' => [
    'export' => [
        'driver' => RedisDriver::class,
        'channel' => '{export-queue}',
        'handle_timeout' => 600,  // 10分钟超时
        'processes' => 1,
        'concurrent' => ['limit' => 5],
    ],
],

4. 进度追踪

php
// AbstractExportWriter.php
protected function updateProgress(int $current, int $total): void
{
    $progress = $total > 0 ? round($current / $total * 100, 2) : 0;
    
    // 每处理 100 条或进度变化超过 1% 时更新
    if ($current % 100 === 0 || $progress - $this->lastProgress >= 1) {
        $this->task->update(['progress' => $progress]);
        $this->lastProgress = $progress;
    }
}

🔄 导出流程

┌──────────┐    创建任务    ┌──────────┐    推送队列    ┌──────────┐
│  发起导出 │ ───────────→ │  任务记录 │ ───────────→ │  异步处理 │
└──────────┘              └──────────┘              └──────────┘

                               ┌─────────────────────────┤
                               │                         │
                               ↓                         ↓
                         ┌──────────┐             ┌──────────┐
                         │  导出完成 │             │  导出失败 │
                         └──────────┘             └──────────┘

📦 使用示例

1. 定义导出 DTO

php
namespace App\Application\Admin\Trade\Dto;

use Plugin\ExportCenter\Annotation\ExportColumn;

class OrderExportDto
{
    #[ExportColumn(name: '订单编号', index: 1)]
    public string $orderNo;

    #[ExportColumn(name: '收货人', index: 2)]
    public string $receiverName;

    #[ExportColumn(name: '订单金额', index: 3)]
    public float $totalAmount;
}

2. Repository 实现导出方法

php
// OrderRepository.php
public function export(array $params): Generator
{
    $query = $this->buildExportQuery($params);
    
    foreach ($query->cursor() as $order) {
        yield $this->toExportDto($order);
    }
}

3. 控制器调用

php
// OrderController.php
public function export(ExportRequest $request): ResponseInterface
{
    return $this->exportService->create(
        name: '订单导出',
        dtoClass: OrderExportDto::class,
        generator: fn() => $this->repository->export($request->all()),
    );
}

💻 API 接口

接口方法说明
/export/taskGET任务列表
/export/task/{id}GET任务详情
/export/task/{id}/downloadGET下载文件
/export/task/{id}DELETE删除任务

⚠️ 注意事项

  1. 内存控制: 使用 Generator 避免内存溢出
  2. 超时设置: 大数据量导出需调整 handle_timeout
  3. 文件清理: 定期清理过期导出文件
  4. 并发限制: 通过 concurrent.limit 控制并发数

📚 相关文档

基于 Apache-2.0 许可发布 | 感谢 MineAdmin 提供的优秀基础框架