format('Y-m-d H:i:s'); } public function scopeWithDataPermission(Builder $query): Builder { $admin = runCatching(fn() => admin(),"无法获取登录状态")->getOrDefault([]); $hospitalRaw = trim((string)($admin['hospitals'] ?? '')); $departmentRaw = trim((string)($admin['departments'] ?? '')); if ($hospitalRaw === '*' && $departmentRaw === '*') { return $query; } $hospitalIds = $this->parseVisibleIds($hospitalRaw); $departmentIds = $this->parseVisibleIds($departmentRaw); if (empty($hospitalIds) && empty($departmentIds)) { return $query->whereRaw('1 = 0'); } $baseQuery = $query->getQuery(); // 主表 [$fromTable, $fromAlias] = $this->parseTableAlias((string)($baseQuery->from ?? '')); // 识别 join 里的医院/科室表别名 $hospitalAlias = $this->findTableAlias($baseQuery, 'opm_mw_hospital'); $departmentAlias = $this->findTableAlias($baseQuery, 'opm_mw_department'); Logger::debug('scopeWithDataPermission fromTable:{} fromAlias:{} hospitalAlias:{} departmentAlias:{} hospitalIds:{} departmentIds:{}', [ $fromTable, $fromAlias, $hospitalAlias, $departmentAlias, $hospitalIds, $departmentIds, ]); // 1) 主表就是医院表:只加医院权限 if ($fromTable === 'opm_mw_hospital' && $hospitalAlias) { if (empty($hospitalIds)) { return $query->whereRaw('1 = 0'); } return $query->whereIn("{$hospitalAlias}.id", $hospitalIds); } // 2) 主表就是科室表:只加科室权限 if ($fromTable === 'opm_mw_department' && $departmentAlias) { return $query->where(function (Builder $q) use ($departmentAlias, $hospitalIds, $departmentIds) { $has = false; // 科室权限:department.id if (!empty($departmentIds)) { $q->whereIn("{$departmentAlias}.id", $departmentIds); $has = true; } // 医院权限:department.organ_id if (!empty($hospitalIds)) { if ($has) { $q->whereIn("{$departmentAlias}.organ_id", $hospitalIds); } else { $q->orWhereIn("{$departmentAlias}.organ_id", $hospitalIds); } $has = true; } if (!$has) { $q->whereRaw('1 = 0'); } }); } // 3) 主表不是这两个,但 join 里有它们:按别名补条件 return $query->where(function (Builder $q) use ( $hospitalAlias, $departmentAlias, $hospitalIds, $departmentIds ) { $hasAny = false; if ($hospitalAlias && !empty($hospitalIds)) { $q->whereIn("{$hospitalAlias}.id", $hospitalIds); $hasAny = true; } if ($departmentAlias) { $q->where(function (Builder $dq) use ($departmentAlias, $hospitalIds, $departmentIds) { $has = false; if (!empty($departmentIds)) { $dq->whereIn("{$departmentAlias}.id", $departmentIds); $has = true; } if (!empty($hospitalIds)) { if ($has) { $dq->orWhereIn("{$departmentAlias}.organ_id", $hospitalIds); } else { $dq->whereIn("{$departmentAlias}.organ_id", $hospitalIds); } $has = true; } if (!$has) { $dq->whereRaw('1 = 0'); } }); $hasAny = true; } if (!$hasAny) { $q->whereRaw('1 = 0'); } }); } /** * 解析 "table as t" / "table t" */ protected function parseTableAlias(string $table): array { $table = trim(str_replace('`', '', $table)); if ($table === '') { return ['', '']; } if (stripos($table, ' as ') !== false) { [$name, $alias] = preg_split('/\s+as\s+/i', $table, 2); return [trim($name), trim($alias)]; } $parts = preg_split('/\s+/', $table); if (count($parts) >= 2) { return [trim($parts[0]), trim($parts[1])]; } return [$table, $table]; } /** * 在 from / joins 中找指定表的别名 */ protected function findTableAlias($baseQuery, string $tableName): ?string { [$fromTable, $fromAlias] = $this->parseTableAlias((string)($baseQuery->from ?? '')); if ($fromTable === $tableName) { return $fromAlias; } foreach (($baseQuery->joins ?? []) as $join) { [$joinTable, $joinAlias] = $this->parseTableAlias((string)($join->table ?? '')); if ($joinTable === $tableName) { return $joinAlias; } } return null; } /** * 把 "1,2,3" / "1,2,3" / " 1 , 2 " 转成数组 */ protected function parseVisibleIds(string $raw): array { $raw = trim($raw); if ($raw === '' || $raw === '*') { return []; } $parts = preg_split('/[,\s,]+/u', $raw) ?: []; $parts = array_filter($parts, static fn($v) => $v !== ''); return array_values(array_unique(array_map('intval', $parts))); } }