UserExport.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. namespace App\Jobs\OpenWork\External;
  3. use Illuminate\Bus\Queueable;
  4. use Illuminate\Contracts\Queue\ShouldQueue;
  5. use Illuminate\Foundation\Bus\Dispatchable;
  6. use Illuminate\Queue\InteractsWithQueue;
  7. use Illuminate\Queue\SerializesModels;
  8. use Illuminate\Support\Facades\Cache;
  9. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  10. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  11. use App\Servers\DB\DbService;
  12. use App\Models\OpenWork\DownloadTask as DownloadTaskModel;
  13. use App\Servers\Aliyun\Oss;
  14. /**
  15. * 导出客户数据-下载
  16. * @author 唐远望
  17. * @version 2.0
  18. * @date 2025-09-09
  19. */
  20. class UserExport implements ShouldQueue
  21. {
  22. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  23. protected $message_data;
  24. protected $Records;
  25. protected $file_id;
  26. /**
  27. * Create a new job instance.
  28. *
  29. * @return void
  30. */
  31. public function __construct(array $message_data)
  32. {
  33. $this->message_data = $message_data;
  34. $this->file_id = $message_data['file_id'];
  35. }
  36. public function getCorpId()
  37. {
  38. return $this->message_data['corpid'] ?? null;
  39. }
  40. public function handle()
  41. {
  42. $chunkSize = 1000;
  43. $file_id = $this->file_id;
  44. $corpid = $this->message_data['corpid'];
  45. (new DbService())->getConnectionNameByCorpId($corpid);
  46. // 标记为处理中
  47. Cache::put('export_status_' . $file_id, 'processing', 86400);
  48. // 获取导出参数
  49. $exportParams = Cache::get('export_params_' . $file_id);
  50. if (!$exportParams) {
  51. $this->fail(new \Exception('导出参数不存在'));
  52. return;
  53. }
  54. // 获取模型
  55. $modelClass = $exportParams['model'];
  56. $Model = new $modelClass;
  57. // 构建查询
  58. $query = $Model->query()
  59. ->join('openwork_external_follow', 'openwork_external_follow.external_userid', '=', 'openwork_external.external_userid')
  60. ->where($exportParams['map'])
  61. ->select(['openwork_external.*', 'openwork_external_follow.status', 'openwork_external_follow.follow_userid', 'openwork_external_follow.add_way', 'openwork_external_follow.remark', 'openwork_external_follow.remark_corp_name', 'openwork_external_follow.remark_mobiles', 'openwork_external_follow.createtime'])
  62. ->orderByDesc('openwork_external_follow.createtime')
  63. ->with(['external_tags']);
  64. // 标签筛选
  65. if (!empty($exportParams['external_userid'])) {
  66. $query->whereIn('openwork_external_follow.external_userid', $exportParams['external_userid']);
  67. }
  68. // 创建Excel文件
  69. $filename = '企业客户信息_' . $file_id . '.xlsx';
  70. $fullPath = public_path('uploads/exports/' . $filename);
  71. // 确保目录存在
  72. if (!file_exists(dirname($fullPath))) {
  73. mkdir(dirname($fullPath), 0755, true);
  74. }
  75. // 创建一个新的 Spreadsheet 对象
  76. $spreadsheet = new Spreadsheet();
  77. $sheet = $spreadsheet->getActiveSheet();
  78. // 设置表头
  79. $headers = [
  80. 'A' => '授权方企微ID',
  81. 'B' => '企业客户ID',
  82. 'C' => '客户名称',
  83. 'D' => '所属企业',
  84. 'E' => '所属客服',
  85. 'F' => '客户状态',
  86. 'G' => '客户备注',
  87. 'H' => '添加时间',
  88. 'I' => '用户标签'
  89. ];
  90. foreach ($headers as $col => $value) {
  91. $sheet->setCellValue($col . '1', $value);
  92. }
  93. // 分块处理数据
  94. $row = 2;
  95. $query->chunk($chunkSize, function ($chunk) use (&$row, $sheet) {
  96. foreach ($chunk as $item) {
  97. $item = $item->toArray();
  98. // 加载标签关系
  99. $tag_id_name_array = !empty($item['external_tags']) ? array_column($item['external_tags'], 'tag_name') : [];
  100. if (!empty($tag_id_name_array)) {
  101. $tag_id_name_array = array_filter($tag_id_name_array);
  102. }
  103. $tag_id_name = count($tag_id_name_array) > 0 ? implode(',', $tag_id_name_array) : '';
  104. $sheet->setCellValueExplicit('A' . $row, $item['corpid'], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  105. $sheet->setCellValueExplicit('B' . $row, $item['external_userid'], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  106. $sheet->setCellValueExplicit('C' . $row, $item['name'], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  107. $sheet->setCellValueExplicit('D' . $row, $item['corp_name'], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  108. $sheet->setCellValueExplicit('E' . $row, $item['follow_userid'], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  109. $sheet->setCellValueExplicit('F' . $row, $item['status'] == 0 ? '正常' : '流失', \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  110. $sheet->setCellValueExplicit('G' . $row, $item['remark'], \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  111. $sheet->setCellValueExplicit('H' . $row, date('Y-m-d H:i:s', $item['insert_time']), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  112. $sheet->setCellValueExplicit('I' . $row, $tag_id_name, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
  113. $row++;
  114. }
  115. // 每处理完一个块,释放内存
  116. unset($chunk);
  117. gc_collect_cycles();
  118. });
  119. // 保存文件
  120. $writer = new Xlsx($spreadsheet);
  121. $writer->save($fullPath);
  122. // 清理
  123. $spreadsheet->disconnectWorksheets();
  124. unset($spreadsheet, $writer);
  125. // 更新状态和文件路径
  126. Cache::put('export_status_' . $file_id, 'completed', 86400);
  127. Cache::put('export_file_path_' . $file_id, $filename, 86400);
  128. // 清理参数缓存
  129. Cache::forget('export_params_' . $file_id);
  130. $Oss = new Oss();
  131. $oss_url = $Oss->uploadFile($filename,$fullPath);
  132. if ($oss_url) @unlink($fullPath);
  133. //查询下载任务
  134. $downloadTask = DownloadTaskModel::where(['file_id' => $file_id, 'corpid' => $corpid])->first();
  135. if ($downloadTask) {
  136. $downloadTask->url =$oss_url;
  137. $downloadTask->file_dir_name =$filename;
  138. $downloadTask->update_time = time();
  139. $downloadTask->status = 1;
  140. $downloadTask->save();
  141. }
  142. }
  143. public function failed(\Exception $exception)
  144. {
  145. // 处理失败情况
  146. Cache::put('export_status_' . $this->file_id, 'failed', 86400);
  147. Cache::put('export_error_' . $this->file_id, $exception->getMessage(), 86400);
  148. }
  149. }