Files
dsserver/plugin/admin/app/model/Base.php
T
zimoyin 1a84e92384 init
2026-04-03 11:32:19 +08:00

214 lines
6.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace plugin\admin\app\model;
use app\utils\Logger;
use DateTimeInterface;
use Illuminate\Database\Eloquent\Builder;
use support\Db;
use support\Model;
/**
* @method static \Illuminate\Database\Eloquent\Builder|static withDataPermission()
*/
class Base extends Model
{
/**
* @var string
*/
protected $connection = 'plugin.admin.mysql';
/**
* 格式化日期
*
* @param DateTimeInterface $date
* @return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return $date->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" / "123" / " 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)));
}
}