message_data = $message_data; } /** * Execute the job. * * @return void */ public function handle() { try { $this->export_excel($this->message_data); } catch (\Exception $e) { Log::info('job_error', '违规数据-导出低价挂网数据处理队列失败', ['data' => $this->message_data, 'error' => $e->getMessage()]); //失败后清除缓存 Cache::forget('ExportLowPriceGoodsJobs_'. $this->company_id); } } /** * 列表导出 * @author 唐远望 * @version 1.0 * @date 2025-06-17 */ public function export_excel($message_data) { $LowPriceGoodsModel = new LowPriceGoodsModel(); $LowPriceGoodsMemberModel = new LowPriceGoodsMemberModel(); $admin_company_id = $message_data['admin_company_id'] ?? '0'; $company_id = $message_data['access_token']['company_id'] ?? '0'; $is_admin = $message_data['access_token']['is_admin'] ?? '0'; //是否管理员操作 0=是1=否 $user_id = $message_data['access_token']['uid'] ?? 0; $file_id = $message_data['file_id']; // 查询条件 $map = []; $job_page = isset($message_data['job_page']) ? $message_data['job_page'] : 1; $limit = 1000; //每次处理1000条 $status = $message_data['status'] ?? ''; $start_time = $message_data['start_time'] ?? ''; $end_time = $message_data['end_time'] ?? ''; $product_name = $message_data['product_name'] ?? ''; $product_names = $message_data['product_names'] ?? ''; $first_responsible_person = $message_data['first_responsible_person'] ?? ''; $responsible_person = $message_data['responsible_person'] ?? ''; $platform = $message_data['platform'] ?? ''; $company_name = $message_data['company_name'] ?? ''; $store_name = $message_data['store_name'] ?? ''; $store_names = $message_data['store_names'] ?? ''; $source_responsible_person = $message_data['source_responsible_person'] ?? ''; $processing_status = $message_data['processing_status'] ?? ''; $product_specs = $message_data['product_specs'] ?? ''; $online_posting_count = $message_data['online_posting_count'] ?? ''; $category_name = $message_data['category_name'] ?? ''; $province_ids = $message_data['province_ids'] ?? ''; $city_ids = $message_data['city_ids'] ?? ''; $shipment_province_ids = $message_data['shipment_province_ids'] ?? ''; $shipment_city_ids = $message_data['shipment_city_ids'] ?? ''; // 时间条件 if ($start_time) $map[] = ['insert_time', '>=', strtotime($start_time)]; if ($end_time) $map[] = ['insert_time', '<=', strtotime($end_time)]; // 其他条件 if ($product_name) $map[] = ['product_name', 'like', "%$product_name%"]; if ($store_name) $map[] = ['store_name', 'like', "%$store_name%"]; if ($category_name) $map[] = ['category_name', 'like', "%$category_name%"]; $low_price_goods_where = []; // 权限判断 if ($is_admin != 1 && $company_id != 0) { $low_price_goods_where['company_id'] = $company_id; } else { $low_price_goods_where['company_id'] = $admin_company_id; } $LowPriceGoodsModel = $LowPriceGoodsModel->where($low_price_goods_where); //多选平台查询 if ($platform && is_string($platform)) { $platform = explode(',', $platform); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('platform', $platform); } //多选处理状态查询 if ($processing_status && is_string($processing_status)) { $processing_status = explode(',', $processing_status); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('processing_status', $processing_status); } //多选状态查询 if ($status && is_string($status)) { $status = explode(',', $status); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('status', $status); } //多选店铺名称查询 if ($store_names && is_string($store_names)) { $store_names = explode(',', $store_names); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('store_name', $store_names); } //多选违规挂网次数查询 if ($online_posting_count && is_string($online_posting_count)) { $online_posting_count = explode(',', $online_posting_count); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('online_posting_count', $online_posting_count); } //多选规格查询 if ($product_specs && is_string($product_specs)) { $product_specs = explode(',', $product_specs); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_specs', $product_specs); } //多选商品查询 if ($product_names && is_string($product_names)) { $product_names = explode(',', $product_names); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('product_name', $product_names); } //多选公司查询 if ($company_name && is_string($company_name)) { $company_name = explode(',', $company_name); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('company_name', $company_name); } //多选第一责任人 if ($first_responsible_person && is_string($first_responsible_person)) { $first_responsible_person = explode(',', $first_responsible_person); $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $first_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid'); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) { $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1'); }); } //多选责任人 if ($responsible_person && is_string($responsible_person)) { $responsible_person = explode(',', $responsible_person); $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid'); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) { $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1'); }); } //多选溯源责任人 if ($source_responsible_person && is_string($source_responsible_person)) { $source_responsible_person = explode(',', $source_responsible_person); $subQuery = $LowPriceGoodsMemberModel->whereIn('employee_id', $source_responsible_person)->distinct('lowprice_product_logid')->select('lowprice_product_logid'); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('id', function ($query1) use ($subQuery) { $query1->select('lowprice_product_logid')->fromSub($subQuery, 'sub1'); }); } //多选省份 if ($province_ids && is_string($province_ids)) { $province_ids = explode(',', $province_ids); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('province_id', $province_ids); } //多选城市 if ($city_ids && is_string($city_ids)) { $city_ids = explode(',', $city_ids); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('city_id', $city_ids); } //多选发货省份 if ($shipment_province_ids && is_string($shipment_province_ids)) { $shipment_province_ids = explode(',', $shipment_province_ids); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('shipment_province_id', $shipment_province_ids); } //多选发货城市 if ($shipment_city_ids && is_string($shipment_city_ids)) { $shipment_city_ids = explode(',', $shipment_city_ids); $LowPriceGoodsModel = $LowPriceGoodsModel->whereIn('shipment_city_id', $shipment_city_ids); } $key_name = 'ExportLowPriceGoodsJobs_' . $low_price_goods_where['company_id']; //创建缓存 Cache::put($key_name, [], 60 * 60 * 24); $query = $LowPriceGoodsModel->where($map); if ($is_admin != 1 && $company_id != 0) { $query = $query->where(function ($q) use ($user_id) { $q->where('first_responsible_person', 'like', "%,{$user_id},%") ->orWhere('responsible_person', 'like', "%,{$user_id},%") ->orWhere('source_responsible_person', 'like', "%,{$user_id},%"); }); } $query->orderByDesc('id') ->chunkById($limit, function ($rows) use ($key_name) { $result_data = $rows->toArray(); if (empty($result_data)) { return true; } $list_data = $this->processing_responsible_person($result_data); $list_data_info = Cache::get($key_name) ?: []; $list_new_data = !empty($list_data_info) ? array_merge($list_data_info, $list_data) : $list_data; Cache::put($key_name, $list_new_data, 60 * 60 * 24); // 每处理完一个块,释放内存 unset($result_data); gc_collect_cycles(); return true; }); $export_data_info = Cache::get($key_name) ?: []; $this->export_download($export_data_info, $low_price_goods_where['company_id'], $file_id); return; } /** * 处理责任人展示信息 * @author 唐远望 * @version 1.0 * @date 2025-12-17 */ public function processing_responsible_person($result) { $EmployeeModel = new EmployeeModel(); //获取所有员工 $employeee_data = $EmployeeModel->select(['id', 'name'])->get()->toarray(); $employeee_list = []; if (!empty($employeee_data)) { foreach ($employeee_data as $key => $value) { $employeee_list[$value['id']] = $value['name']; } } if (isset($result) && count($result) > 0) { foreach ($result as $key => $value) { //查询第一责任人名称 $first_responsible_person = $value['first_responsible_person'] != '' ? explode(',', $value['first_responsible_person']) : []; $first_responsible_person_name = []; if (!empty($first_responsible_person)) { foreach ($first_responsible_person as $k => $v) { if (isset($employeee_list[$v])) { $first_responsible_person_name[] = $employeee_list[$v]; } } } $result[$key]['first_responsible_person_name'] = $first_responsible_person_name; //查询责任人名称 $responsible_person = $value['responsible_person'] != '' ? explode(',', $value['responsible_person']) : []; $responsible_person_name = []; if (!empty($responsible_person)) { foreach ($responsible_person as $k => $v) { if (isset($employeee_list[$v])) { $responsible_person_name[] = $employeee_list[$v]; } } } $result[$key]['responsible_person_name'] = $responsible_person_name; //查询来源责任人名称 $source_responsible_person = $value['source_responsible_person'] != '' ? explode(',', $value['source_responsible_person']) : []; $source_responsible_person_name = []; if (!empty($source_responsible_person)) { foreach ($source_responsible_person as $k => $v) { if (isset($employeee_list[$v])) { $source_responsible_person_name[] = $employeee_list[$v]; } } } $result[$key]['source_responsible_person_name'] = $source_responsible_person_name; } } return $result; } /** * 导出下载 * @author 唐远望 * @version 1.0 * @date 2025-06-17 */ public function export_download($data, $company_id, $file_id) { // 创建一个新的 Spreadsheet 对象 $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); //合并单元格 $sheet->mergeCells('A1:U1'); $sheet->setCellValue('A1', '低价挂网商品导出(导出时间:' . date('Y-m-d H:i:s', time()) . ')'); // 设置合并后的单元格内容 // 获取合并后的单元格样式对象 $style = $sheet->getStyle('A1'); // 设置水平居中和垂直居中 $style->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)->setVertical(Alignment::VERTICAL_CENTER); // 然后设置行高以适应两行文本 $sheet->getRowDimension(1)->setRowHeight(40); // 设置行高,单位是磅(point) // 设置表头 $sheet->setCellValue('A2', '第一责任人'); $sheet->setCellValue('B2', '责任人'); $sheet->setCellValue('C2', '平台'); $sheet->setCellValue('D2', '商品分类'); $sheet->setCellValue('E2', '商品名称'); $sheet->setCellValue('F2', '库存'); $sheet->setCellValue('G2', '销量'); $sheet->setCellValue('H2', '快照URL'); $sheet->setCellValue('I2', '商品规格'); $sheet->setCellValue('J2', '监控价格'); $sheet->setCellValue('K2', '挂网价格'); $sheet->setCellValue('L2', '累计挂网次数'); $sheet->setCellValue('M2', '连续挂网次数'); $sheet->setCellValue('N2', '链接地址'); $sheet->setCellValue('O2', '店铺名称'); $sheet->setCellValue('P2', '公司名称'); $sheet->setCellValue('Q2', '公司分类'); $sheet->setCellValue('R2', '信用代码'); $sheet->setCellValue('S2', '省份'); $sheet->setCellValue('T2', '城市'); $sheet->setCellValue('U2', '溯源责任人'); $sheet->setCellValue('V2', '处理状态'); $sheet->setCellValue('W2', '任务状态'); $sheet->setCellValue('X2', '记录时间'); $sheet->setCellValue('Y2', '发货省份'); $sheet->setCellValue('Z2', '发货城市'); $platform_data = [ '0' => '全部', '1' => '淘宝', '2' => '京东', '3' => '拼多多', '4' => '美团', '5' => '药师帮', '6' => '1药城', '7' => '药久久', ]; $processing_status_text = [ '1' => '待处理', ]; $status_text = [ '0' => '有效', '1' => '无效', ]; // 填充数据 $row = 3; // 从第2行开始 foreach ($data as $item) { $first_responsible_person_name = !empty($item['first_responsible_person_name']) ? implode(',', $item['first_responsible_person_name']) : ''; $responsible_person_name = !empty($item['responsible_person_name']) ? implode(',', $item['responsible_person_name']) : ''; $source_responsible_person_name = !empty($item['source_responsible_person_name']) ? implode(',', $item['source_responsible_person_name']) : ''; $sheet->setCellValue('A' . $row, $first_responsible_person_name); $sheet->setCellValue('B' . $row, $responsible_person_name); $sheet->setCellValue('C' . $row, isset($platform_data[$item['platform']]) ? $platform_data[$item['platform']] : ''); $sheet->setCellValue('D' . $row, $item['category_name']); $sheet->setCellValue('E' . $row, $item['product_name']); $sheet->setCellValue('F' . $row, $item['inventory']); $sheet->setCellValue('G' . $row, $item['sales']); $sheet->setCellValue('H' . $row, $item['snapshot_url']); $sheet->setCellValue('I' . $row, $item['product_specs']); $sheet->setCellValue('J' . $row, $item['suggested_price']); $sheet->setCellValue('K' . $row, $item['online_posting_price']); $sheet->setCellValue('L' . $row, $item['online_posting_count']); $sheet->setCellValue('M' . $row, $item['continuous_listing_count']); $sheet->setCellValue('N' . $row, $item['link_url']); $sheet->setCellValue('O' . $row, $item['store_name']); $sheet->setCellValue('P' . $row, $item['company_name']); $sheet->setCellValue('Q' . $row, $item['company_category_name']); $sheet->setCellValue('R' . $row, $item['social_credit_code']); $sheet->setCellValue('S' . $row, $item['province_name']); $sheet->setCellValue('T' . $row, $item['city_name']); $sheet->setCellValue('U' . $row, $source_responsible_person_name); $sheet->setCellValue('V' . $row, isset($processing_status_text[$item['processing_status']]) ? $processing_status_text[$item['processing_status']] : ''); $sheet->setCellValue('W' . $row, isset($status_text[$item['status']]) ? $status_text[$item['status']] : ''); $sheet->setCellValue('X' . $row, date('Y-m-d H:i:s', $item['insert_time'])); $sheet->setCellValue('Y' . $row, $item['shipment_city_name']); $sheet->setCellValue('Z' . $row, $item['shipment_city_name']); $row++; } // 创建Excel文件 $filename = '低价挂网商品数据' . $file_id . '.xlsx'; $path = public_path('uploads/exports/'); $fullPath = $path . $filename; if (!is_dir($path)) mkdir($path, 0777, true); // 生成 Excel 文件 $writer = new Xlsx($spreadsheet); $writer->save($fullPath); // 清理 $spreadsheet->disconnectWorksheets(); unset($spreadsheet, $writer); //释放redis缓存 Cache::forget('ExportLowPriceGoodsJobs_' . $company_id); $Oss = new Oss(); $oss_url = $Oss->uploadFile($filename, $fullPath); if ($oss_url) @unlink($fullPath); // 记录下载任务 $downloadTask = DownloadTaskModel::where(['file_id' => $file_id, 'company_id' => $company_id])->first(); if ($downloadTask) { $downloadTask->url = $oss_url; $downloadTask->file_dir_name = $filename; $downloadTask->update_time = time(); $downloadTask->status = 1; $downloadTask->save(); } return $oss_url; } public function failed(\Throwable $exception) { Log::info('job_error', '违规数据-导出低价挂网数据队列完全失败', ['data' => $this->message_data, 'error' => $exception]); if($this->company_id) { //失败后清除缓存 Cache::forget('ExportLowPriceGoodsJobs_'. $this->company_id); } } }