init
This commit is contained in:
+56
-180
@@ -5,10 +5,10 @@ namespace plugin\admin\app\model;
|
||||
use app\utils\Logger;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use plugin\admin\app\common\DataPermissionService;
|
||||
use support\Db;
|
||||
use support\Model;
|
||||
|
||||
|
||||
/**
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|static withDataPermission()
|
||||
*/
|
||||
@@ -20,194 +20,70 @@ class Base extends Model
|
||||
protected $connection = 'plugin.admin.mysql';
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
*
|
||||
* @param DateTimeInterface $date
|
||||
* @return string
|
||||
* --------------------------
|
||||
* 【核心配置】权限规则配置
|
||||
* 新增规则只需在这里加一项,无需改下面的逻辑
|
||||
* --------------------------
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date)
|
||||
protected function getPermissionRules(): array
|
||||
{
|
||||
return [
|
||||
// 规则1:医院权限
|
||||
'hospital' => [
|
||||
'table' => 'opm_mw_hospital', // 表名
|
||||
'admin_attr' => 'hospitals', // 用户属性里的键($admin['hospitals'])
|
||||
'permission_field'=> 'id', // 表中用于权限过滤的字段
|
||||
'related_field' => null, // 关联上级权限的字段(如科室关联医院的organ_id)
|
||||
'related_rule' => null, // 关联的上级规则key(对应上面的'hospital')
|
||||
],
|
||||
// 规则2:科室权限
|
||||
'department' => [
|
||||
'table' => 'opm_mw_department',
|
||||
'admin_attr' => 'departments',
|
||||
'permission_field'=> 'id',
|
||||
'related_field' => 'organ_id', // 科室通过organ_id关联医院
|
||||
'related_rule' => 'hospital', // 关联上级规则:医院
|
||||
],
|
||||
// 规则3:数据权限
|
||||
// 这个需要绑定 医院的.id
|
||||
// 这个需要绑定 科室的.id
|
||||
'data' => [
|
||||
'table' => 'opm_mw_info_data',
|
||||
'admin_attr' => 'data',
|
||||
'permission_field'=> 'id',
|
||||
'related_field' => null,
|
||||
'related_rule' => null,
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date): string
|
||||
{
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
public function scopeWithDataPermission(Builder $query): Builder
|
||||
|
||||
public function scopeWithDataPermission(Builder $query): Builder
|
||||
{
|
||||
$admin = runCatching(fn() => admin(),"无法获取登录状态")->getOrDefault([]);
|
||||
$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');
|
||||
// 超管判断(可选,也可以在规则里配置*)
|
||||
$isSuper = true;
|
||||
foreach (['hospitals', 'departments'] as $attr) {
|
||||
if (($admin[$attr] ?? '') !== '*') {
|
||||
$isSuper = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return $query->whereIn("{$hospitalAlias}.id", $hospitalIds);
|
||||
}
|
||||
if ($isSuper) return $query;
|
||||
|
||||
// 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');
|
||||
}
|
||||
});
|
||||
// 使用服务类应用权限
|
||||
$service = new DataPermissionService($admin);
|
||||
return $service->apply($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 "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)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user