db = DB::connection((string) config('jushuitan.connection', 'jushuitan_local')); } /** * @param array $filters * @return array{data:array,total:int} */ public function paginate(array $filters, int $page, int $perPage): array { $page = max($page, 1); $perPage = min(max($perPage, 1), 100); $q = $this->filteredQuery($filters); $total = (clone $q)->count(); $rows = (clone $q) ->orderByDesc('ship_time') ->orderByDesc('id') ->forPage($page, $perPage) ->get() ->map(fn ($r) => (array) $r) ->all(); return ['data' => $rows, 'total' => $total]; } /** * @param array $filters * @return \Generator> */ public function exportRows(array $filters, int $batchSize = 1000): \Generator { $batchSize = min(max($batchSize, 1), 5000); $lastId = null; while (true) { $query = $this->filteredQuery($filters); if ($lastId !== null) { $query->where('id', '>', $lastId); } $rows = $query->orderBy('id')->limit($batchSize)->get()->all(); if ($rows === []) { return; } foreach ($rows as $row) { yield (array) $row; } $lastId = (int) $rows[array_key_last($rows)]->id; if (count($rows) < $batchSize) { return; } } } /** @param array $filters */ private function filteredQuery(array $filters): Builder { $query = $this->db->table('jst_oms_shipping'); if (($filters['express_no'] ?? '') !== '') { $query->where('express_no', '=', trim((string) $filters['express_no'])); } if (($filters['sourceno'] ?? '') !== '') { $query->where('trade_no', '=', trim((string) $filters['sourceno'])); } foreach (['barcode', 'supplier_name', 'shop_name', 'warehouse_name'] as $column) { if (($filters[$column] ?? '') !== '') { $query->whereRaw($column . " LIKE ? ESCAPE '!'", [$this->contains((string) $filters[$column])]); } } if (($filters['express_company'] ?? '') !== '') { $value = $this->contains((string) $filters['express_company']); $query->where(static function (Builder $courier) use ($value): void { $courier->whereRaw("express_name1 LIKE ? ESCAPE '!'", [$value]) ->orWhereRaw("express_name2 LIKE ? ESCAPE '!'", [$value]); }); } if (($filters['ship_from'] ?? '') !== '') { $query->where('ship_time', '>=', $filters['ship_from'] . ' 00:00:00'); } if (($filters['ship_to'] ?? '') !== '') { $query->where('ship_time', '<', date('Y-m-d 00:00:00', strtotime($filters['ship_to'] . ' +1 day'))); } return $query; } private function contains(string $value): string { return '%' . str_replace(['!', '%', '_'], ['!!', '!%', '!_'], trim($value)) . '%'; } /** 同步状态(供页面显示同步中/最近完成)。 */ public function syncStatus(): array { try { $row = $this->db->table('jst_sync_state')->where('dataset_key', 'jst.sctrade')->first(); if (! $row) { return ['code' => 'unavailable', 'last_succeeded_at' => null]; } return [ 'code' => (string) ($row->status ?? 'unavailable'), 'last_succeeded_at' => $row->last_succeeded_at ?? null, ]; } catch (\Throwable) { return ['code' => 'unavailable', 'last_succeeded_at' => null]; } } }