active_pharmacies)) { $list = Pharmacy::where('status', 1)->get(); foreach ($list as $p) { $this->active_pharmacies[$p->pharmacy_code] = $p; } } return $this->active_pharmacies[$code] ?? null; } public function __construct(protected ContainerInterface $container) { parent::__construct('getProduct:command'); } public function configure() { parent::configure(); $this->setDescription('获取处方平台商品数据'); } protected function logInfo(string $message): void { $this->line(date('Y-m-d H:i:s') . ' [INFO] ' . $message); Log::getInstance('getProductCommand')->info($message); } protected function logWarn(string $message): void { $this->warn(date('Y-m-d H:i:s') . ' [WARN] ' . $message); Log::getInstance('getProductCommand')->warning($message); } protected function logError(string $message): void { $this->error(date('Y-m-d H:i:s') . ' [ERROR] ' . $message); Log::getInstance('getProductCommand')->error($message); } // 主逻辑处理 public function handle() { $startTime = microtime(true); $this->logInfo("================== [getProductCommand] 处方平台商品目录同步开始 =================="); $stats = [ 'total_received' => 0, 'created' => 0, 'updated' => 0, 'unchanged' => 0, 'skipped_invalid' => 0, 'skipped_pharmacy' => 0, 'failed' => 0, ]; try { // 预加载已启用的药房列表 if (empty($this->active_pharmacies)) { $list = Pharmacy::where('status', 1)->get(); foreach ($list as $p) { $this->active_pharmacies[$p->pharmacy_code] = $p; } } if (empty($this->active_pharmacies)) { $this->logError("未找到任何已启用的药房配置,请先在药房管理中添加并启用药房后再执行同步"); return; } $pharmacyListStr = implode(', ', array_map(function ($p) { return "{$p->pharmacy_name}({$p->pharmacy_code})"; }, array_values($this->active_pharmacies))); $this->logInfo("当前系统已启用药房 (" . count($this->active_pharmacies) . " 个): [{$pharmacyListStr}]"); $prescription = new Prescription(); $page = 1; $page_size = 100; $this->logInfo("正在请求第 1 页商品目录数据 (pageSize={$page_size})..."); $result = $prescription->getProd(1, $page_size); if (empty($result) || !isset($result['rows'])) { $this->logWarn("处方平台未返回有效的商品目录数据,任务结束"); return; } $totalCount = (int)($result['count'] ?? count($result['rows'])); $totalPages = (int)ceil($totalCount / $page_size); $this->logInfo("处方平台商品目录查询成功: 平台总数据量={$totalCount} 条,总页数={$totalPages} 页"); // 处理第 1 页 $this->logInfo(">>> 正在处理第 1/{$totalPages} 页数据 (当前页 " . count($result['rows']) . " 条)..."); foreach ($result['rows'] as $item) { $stats['total_received']++; $this->handleData($item, $stats); } // 处理后续页 if ($totalPages > 1) { for ($i = 2; $i <= $totalPages; $i++) { $this->logInfo(">>> 正在请求并处理第 {$i}/{$totalPages} 页数据..."); try { $pageResult = $prescription->getProd($i, $page_size); if (!isset($pageResult['rows']) || empty($pageResult['rows'])) { $this->logWarn("第 {$i} 页返回空数据,跳过"); continue; } foreach ($pageResult['rows'] as $item) { $stats['total_received']++; $this->handleData($item, $stats); } } catch (\Throwable $e) { $this->logError("第 {$i} 页商品同步失败: " . $e->getMessage()); } } } } catch (\Throwable $e) { $this->logError("商品同步全局异常: " . $e->getMessage()); } $duration = round(microtime(true) - $startTime, 2); $this->logInfo("================== [getProductCommand] 处方平台商品目录同步完成 =================="); $this->logInfo("总耗时: {$duration}s | 平台接收: {$stats['total_received']} 条 | 新增入库: {$stats['created']} 条 | 变更更新: {$stats['updated']} 条 | 资料无变动: {$stats['unchanged']} 条 | 非本院药房忽略: {$stats['skipped_pharmacy']} 条 | 字段缺失跳过: {$stats['skipped_invalid']} 条 | 处理失败: {$stats['failed']} 条"); } /** * 参数设置 * @return array[] */ protected function getArguments(): array { return [ // ['sign', InputArgument::REQUIRED, '签名数据'] ]; } /** * 入库 * @param array $item * @param array $stats * @return bool */ protected function handleData(array $item, array &$stats): bool { if (empty($item['drugCode']) || empty($item['drugPrice']) || empty($item['thirdCode']) || empty($item['thirdDrugCode']) || empty($item['approvalNumber'])) { $drugName = $item['tradeName'] ?? '未知名'; $this->logWarn("【跳过-字段缺失】药品 [{$drugName}] 缺少必要字段(drugCode/drugPrice/thirdCode/thirdDrugCode/approvalNumber)"); $stats['skipped_invalid']++; return false; } try { Db::beginTransaction(); $pharmacy = $this->getPharmacy($item['thirdCode']); if (empty($pharmacy)) { Db::rollBack(); $stats['skipped_pharmacy']++; return false; } // 查询是否存在 $params = array(); $params['product_platform_code'] = $item['drugCode']; $params['product_pharmacy_code'] = $item['thirdDrugCode']; $params['license_number'] = $item['approvalNumber']; $params['pharmacy_code'] = $item['thirdCode']; $product_platform = ProductPlatform::getOne($params); if (!empty($product_platform)) { // 已存在,更新 $product_platform_data = array(); $product_data = array(); // 商品名称 if (isset($item['tradeName'])) { if ($product_platform['product_name'] != $item['tradeName']) { $product_platform_data['product_name'] = $item['tradeName']; $product_data['product_name'] = $item['tradeName']; } } // 商品价格 if ($product_platform['product_price'] != $item['drugPrice']) { $product_platform_data['product_price'] = $item['drugPrice']; $product_data['product_price'] = $item['drugPrice']; } // 药品类型 if (isset($item['drugClassCode'])) { if ($item['drugClassCode'] == 1) { $product_type = 1; } elseif ($item['drugClassCode'] == 2) { $product_type = 2; } else { $product_type = 0; } if ($product_platform['product_type'] != $product_type) { $product_platform_data['product_type'] = $product_type; $product_data['product_type'] = $product_type; } } // 商品规格 if (isset($item['specifications'])) { if ($product_platform['product_spec'] != $item['specifications']) { $product_platform_data['product_spec'] = $item['specifications']; $product_data['product_spec'] = $item['specifications']; } } // 生产厂家 if (isset($item['manufacturer'])) { if ($product_platform['manufacturer'] != $item['manufacturer']) { $product_platform_data['manufacturer'] = $item['manufacturer']; $product_data['manufacturer'] = $item['manufacturer']; } } // 零售包装单位 if (isset($item['packingUnit'])) { if ($product_platform['retail_unit'] != $item['packingUnit']) { $product_platform_data['retail_unit'] = $item['packingUnit']; $product_data['packaging_unit'] = $item['packingUnit']; } } // 基本包装数量 if (isset($item['basicPackingCount'])) { if ($product_platform['packaging_count'] != $item['basicPackingCount']) { $product_platform_data['packaging_count'] = $item['basicPackingCount']; } } // 基本包装单位 if (isset($item['basicPackingUnit'])) { if ($product_platform['packaging_unit'] != $item['basicPackingUnit']) { $product_platform_data['packaging_unit'] = $item['basicPackingUnit']; } } // 单次剂量单位 if (isset($item['defaultSingleDosageUnit'])) { if ($product_platform['single_unit'] != $item['defaultSingleDosageUnit']) { $product_platform_data['single_unit'] = $item['defaultSingleDosageUnit']; } } $product_platform_data['pharmacy_code'] = $item['thirdCode']; $product_data['pharmacy_code'] = $item['thirdCode']; $product_data['pharmacy_id'] = (string)$pharmacy->pharmacy_id; if (!empty($product_platform_data)) { // 更新商品表-处方平台 $params = array(); $params['product_platform_id'] = $product_platform['product_platform_id']; ProductPlatform::edit($params, $product_platform_data); if (!empty($product_data)) { // 获取商品表数据 $params = array(); $params['product_platform_id'] = $product_platform['product_platform_id']; $product = Product::getOne($params); if (!empty($product)) { // 更新商品表 $params = array(); $params['product_platform_id'] = $product_platform['product_platform_id']; Product::edit($params, $product_data); } } $this->logInfo("【更新药品】药房 [{$pharmacy->pharmacy_name}({$item['thirdCode']})] 药品 [{$item['tradeName']}] (ID: {$product_platform['product_platform_id']}, 价格: {$item['drugPrice']})"); $stats['updated']++; } else { $stats['unchanged']++; } } else { // 不存在,创建 $data = array(); $data['pharmacy_code'] = $item['thirdCode']; if (isset($item['tradeName'])) { $data['product_name'] = $item['tradeName']; } $data['product_price'] = $item['drugPrice']; if (isset($item['drugClassCode'])) { if ($item['drugClassCode'] == 1) { $data['product_type'] = 1; } elseif ($item['drugClassCode'] == 2) { $data['product_type'] = 2; } else { $data['product_type'] = 0; } } $data['product_platform_code'] = $item['drugCode']; $data['product_pharmacy_code'] = $item['thirdDrugCode']; if (isset($item['specifications'])) { $data['product_spec'] = $item['specifications']; } $data['license_number'] = $item['approvalNumber']; if (isset($item['manufacturer'])) { $data['manufacturer'] = $item['manufacturer']; } if (isset($item['defaultSingleDosageUnit'])) { $data['single_unit'] = $item['defaultSingleDosageUnit']; } if (isset($item['basicPackingUnit'])) { $data['packaging_unit'] = $item['basicPackingUnit']; } if (isset($item['basicPackingCount'])) { $data['packaging_count'] = $item['basicPackingCount']; } if (isset($item['packingUnit'])) { $data['retail_unit'] = $item['packingUnit']; } $product_platform = ProductPlatform::addProductPlatform($data); if (empty($product_platform)) { Db::rollBack(); $this->logError("【新增失败】药房 [{$pharmacy->pharmacy_name}({$item['thirdCode']})] 药品 [{$item['tradeName']}] 写入数据库失败"); $stats['failed']++; return false; } $this->logInfo("【新增入库】药房 [{$pharmacy->pharmacy_name}({$item['thirdCode']})] 药品 [{$item['tradeName']}] (平台编码: {$item['drugCode']}, 批准文号: {$item['approvalNumber']}, 价格: {$item['drugPrice']})"); $stats['created']++; } Db::commit(); } catch (\Throwable $e) { Db::rollBack(); $drugName = $item['tradeName'] ?? '未知名'; $this->logError("【更新异常】药品 [{$drugName}] (thirdDrugCode: {$item['thirdDrugCode']}) 异常: " . $e->getMessage()); $stats['failed']++; return false; } return true; } }