, * total_rows:int, * assigned_rows:int, * unassigned_rows:int, * invalid_rows:list * } */ public function rows(string $path): array { if (! is_file($path)) { throw new RuntimeException('客服公司映射文件不存在:' . $path); } $result = [ 'rows' => [], 'total_rows' => 0, 'assigned_rows' => 0, 'unassigned_rows' => 0, 'invalid_rows' => [], ]; foreach ($this->reader->rows( $path, ['公司名称', '结算比例', '对应客服公司'], sheetName: '公司盘点', ) as $row) { $result['total_rows']++; $sourceRow = $result['total_rows'] + 1; $storeName = trim((string) ($row['公司名称'] ?? '')); $serviceName = trim((string) ($row['对应客服公司'] ?? '')); if ($storeName === '') { continue; } if ($serviceName === '') { $result['unassigned_rows']++; continue; } $feeRate = $this->feeRate((string) ($row['结算比例'] ?? '')); if ($feeRate === null) { $result['invalid_rows'][] = "第 {$sourceRow} 行结算比例无效。"; continue; } $result['rows'][] = [ 'service_company_name' => $serviceName, 'store_company_name' => $storeName, 'fee_rate' => $feeRate, 'source_row' => $sourceRow, ]; $result['assigned_rows']++; } return $result; } private function feeRate(string $value): ?float { $normalized = trim(str_replace(['%', ',', ','], ['', '', ''], $value)); if ($normalized === '' || ! is_numeric($normalized)) { return null; } $rate = (float) $normalized; if ($rate > 1) { $rate /= 100; } return $rate > 0 && $rate <= 1 ? round($rate, 6) : null; } }