214 lines
6.2 KiB
PHP
214 lines
6.2 KiB
PHP
<?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" / "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)));
|
||
}
|
||
|
||
|
||
}
|