where('rollback_time', '>=', $startTs) ->where('rollback_time', '<=', $endTs) ->where('diagnosis_id', '>', 0) ->field(['diagnosis_id', 'rollback_time', 'rollback_admin_id']) ->select() ->toArray(); $out = []; foreach ($rows as $r) { $out[RevisitRateCalculator::rollbackKey( (int) ($r['diagnosis_id'] ?? 0), (int) ($r['rollback_time'] ?? 0), (int) ($r['rollback_admin_id'] ?? 0) )] = true; } return $out; } private static function iterateOrderSeqRows(array $diagIds, array $fields): \Generator { foreach (array_chunk($diagIds, 2000) as $chunk) { foreach (self::fetchOrderSeqRows($chunk, $fields) as $r) { yield $r; } } } private static function buildAssistantDeptIndex(array $adminIds): array { if ($adminIds === []) { return [[], []]; } // admin_dept 为 (admin_id, dept_id) 联合主键、无自增 id;取最小 dept_id 作为归属部门保证确定性 $relRows = Db::name('admin_dept') ->whereIn('admin_id', $adminIds) ->order(['admin_id' => 'asc', 'dept_id' => 'asc']) ->field(['admin_id', 'dept_id']) ->select() ->toArray(); $deptNames = Db::name('dept') ->whereNull('delete_time') ->column('name', 'id'); $canonical = []; foreach ($relRows as $r) { $aid = (int) ($r['admin_id'] ?? 0); $deptId = (int) ($r['dept_id'] ?? 0); if ($aid <= 0 || $deptId <= 0 || isset($canonical[$aid])) { continue; } if (!isset($deptNames[$deptId])) { continue; } $canonical[$aid] = $deptId; } $names = []; foreach ($deptNames as $id => $name) { $names[(int) $id] = (string) $name; } return [$canonical, $names]; } private static function resolveDeptFilterSet(mixed $raw): array { $erSet = DeptLogic::getErCenterSubtreeDeptIdSet(); if ($erSet === []) { return []; } $deptFilterIds = self::parseDeptIds($raw); if ($deptFilterIds === []) { return $erSet; } $allowedRoots = []; foreach ($deptFilterIds as $id) { if (isset($erSet[$id])) { $allowedRoots[] = $id; } } if ($allowedRoots === []) { return []; } $expanded = self::expandDeptSubtreeSet($allowedRoots); $out = []; foreach ($expanded as $id => $_) { if (isset($erSet[$id])) { $out[$id] = true; } } return $out; } private static function parseDeptIds(mixed $raw): array { if ($raw === null || $raw === '' || $raw === []) { return []; } $list = \is_array($raw) ? $raw : explode(',', (string) $raw); return array_values(array_unique(array_filter( array_map('intval', $list), static fn (int $v): bool => $v > 0 ))); } private static function expandDeptSubtreeSet(array $deptIds): array { $rows = Db::name('dept') ->whereNull('delete_time') ->field(['id', 'pid']) ->select() ->toArray(); $childrenByPid = []; foreach ($rows as $r) { $childrenByPid[(int) $r['pid']][] = (int) $r['id']; } $set = []; $queue = $deptIds; while ($queue !== []) { $id = (int) array_shift($queue); if ($id <= 0 || isset($set[$id])) { continue; } $set[$id] = true; foreach ($childrenByPid[$id] ?? [] as $childId) { $queue[] = $childId; } } return $set; } private static function fetchRefundOrRejectDiagnosisSet(array $diagIds): array { if ($diagIds === []) { return []; } $out = []; foreach (array_chunk($diagIds, 2000) as $chunk) { $ids = Db::name('tcm_prescription_order') ->whereIn('diagnosis_id', $chunk) ->whereNull('delete_time') ->whereIn('fulfillment_status', [9, 10]) ->group('diagnosis_id') ->column('diagnosis_id'); foreach ($ids as $id) { $out[(int) $id] = true; } } return $out; } private static function fetchOrderSeqRows(array $diagIds, array $fields): array { // 实现已搬至 RevisitVisitSlotService(诊次口径单点维护),此处保留委托以减少 diff return RevisitVisitSlotService::fetchOrderSeqRows($diagIds, $fields); } private static function fetchRevisitSlotStartOffsetMap(array $diagIds): array { // 实现已搬至 RevisitVisitSlotService(诊次口径单点维护),此处保留委托以减少 diff return RevisitVisitSlotService::fetchRevisitSlotStartOffsetMap($diagIds); } private static function fetchDiagnosisInfo(array $diagIds): array { if ($diagIds === []) { return []; } $rows = Db::name('tcm_diagnosis') ->whereIn('id', $diagIds) ->field(['id', 'patient_name', 'phone']) ->select() ->toArray(); $out = []; foreach ($rows as $r) { $out[(int) $r['id']] = [ 'patient_name' => trim((string) ($r['patient_name'] ?? '')), 'phone' => trim((string) ($r['phone'] ?? '')), ]; } return $out; } private static function cohortDeptOptions(): array { $erSet = DeptLogic::getErCenterSubtreeDeptIdSet(); if ($erSet === []) { return ['rows' => []]; } $rows = Db::name('dept') ->whereNull('delete_time') ->whereIn('id', array_keys($erSet)) ->field(['id', 'pid', 'name']) ->order('sort', 'desc') ->order('id', 'asc') ->select() ->toArray(); return [ 'rows' => array_map(static fn (array $r): array => [ 'id' => (int) $r['id'], 'pid' => (int) $r['pid'], 'name' => (string) $r['name'], ], $rows), ]; } }