160 lines
5.7 KiB
PHP
160 lines
5.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\adminapi\logic\firstvisit;
|
|
|
|
use app\common\model\auth\AdminRole;
|
|
use app\common\model\doctor\Appointment;
|
|
use app\common\model\tcm\Diagnosis;
|
|
use app\common\service\DataScope\DataScopeService;
|
|
use think\db\Query;
|
|
use think\facade\Db;
|
|
|
|
/**
|
|
* “我的患者”统一数据范围。
|
|
*
|
|
* 角色语义:医生只看本人接诊患者,医助只看本人归属患者;经理、
|
|
* 诊室组长和管理员按系统 DataScope 查看团队患者;root 查看全部。
|
|
*/
|
|
class MyPatientLogic
|
|
{
|
|
private const DOCTOR_ROLE_ID = 1;
|
|
private const ASSISTANT_ROLE_ID = 2;
|
|
private const TEAM_ROLE_IDS = [3, 7, 8];
|
|
private const EFFECTIVE_APPOINTMENT_STATUSES = [1, 3, 4];
|
|
|
|
/**
|
|
* @param Query $query 以 d 作为 zyt_tcm_diagnosis 别名的查询
|
|
*/
|
|
public static function applyScope(Query $query, int $adminId, array $adminInfo): void
|
|
{
|
|
if ($adminId <= 0) {
|
|
$query->whereRaw('0 = 1');
|
|
|
|
return;
|
|
}
|
|
|
|
if ((int) ($adminInfo['root'] ?? 0) === 1) {
|
|
return;
|
|
}
|
|
|
|
$roleIds = self::roleIds($adminId);
|
|
$appointmentTable = (new Appointment())->getTable();
|
|
$statusList = implode(',', self::EFFECTIVE_APPOINTMENT_STATUSES);
|
|
|
|
// 管理角色按系统的数据范围查看“范围内医助归属或医生接诊”的患者。
|
|
if (array_intersect($roleIds, self::TEAM_ROLE_IDS) !== []) {
|
|
$visibleAdminIds = DataScopeService::getVisibleAdminIds($adminId, $adminInfo);
|
|
if ($visibleAdminIds === null) {
|
|
return;
|
|
}
|
|
$visibleAdminIds = self::normalizeIds($visibleAdminIds);
|
|
if ($visibleAdminIds === []) {
|
|
$query->whereRaw('0 = 1');
|
|
|
|
return;
|
|
}
|
|
$ids = implode(',', $visibleAdminIds);
|
|
$query->whereRaw(
|
|
"(CAST(d.assistant_id AS UNSIGNED) IN ({$ids})"
|
|
. " OR EXISTS (SELECT 1 FROM {$appointmentTable} scope_apt"
|
|
. ' WHERE scope_apt.patient_id = d.id'
|
|
. " AND scope_apt.status IN ({$statusList})"
|
|
. " AND scope_apt.doctor_id IN ({$ids})))"
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
// 一线角色始终只取“本人关系”,不受数据库中医生角色 ALL 配置影响。
|
|
$conditions = [];
|
|
if (in_array(self::ASSISTANT_ROLE_ID, $roleIds, true)) {
|
|
$conditions[] = 'CAST(d.assistant_id AS UNSIGNED) = ' . $adminId;
|
|
}
|
|
if (in_array(self::DOCTOR_ROLE_ID, $roleIds, true)) {
|
|
$conditions[] = "EXISTS (SELECT 1 FROM {$appointmentTable} scope_apt"
|
|
. ' WHERE scope_apt.patient_id = d.id'
|
|
. " AND scope_apt.status IN ({$statusList})"
|
|
. " AND scope_apt.doctor_id = {$adminId})";
|
|
}
|
|
|
|
// 未知/异常角色按本人医助或本人医生关系收窄,拒绝意外放大全库。
|
|
if ($conditions === []) {
|
|
$conditions[] = 'CAST(d.assistant_id AS UNSIGNED) = ' . $adminId;
|
|
$conditions[] = "EXISTS (SELECT 1 FROM {$appointmentTable} scope_apt"
|
|
. ' WHERE scope_apt.patient_id = d.id'
|
|
. " AND scope_apt.status IN ({$statusList})"
|
|
. " AND scope_apt.doctor_id = {$adminId})";
|
|
}
|
|
|
|
$query->whereRaw('(' . implode(' OR ', $conditions) . ')');
|
|
}
|
|
|
|
public static function canAccessDiagnosis(int $diagnosisId, int $adminId, array $adminInfo): bool
|
|
{
|
|
if ($diagnosisId <= 0 || $adminId <= 0) {
|
|
return false;
|
|
}
|
|
|
|
$diagnosisTable = (new Diagnosis())->getTable();
|
|
$query = Db::table($diagnosisTable)
|
|
->alias('d')
|
|
->where('d.id', $diagnosisId)
|
|
->whereNull('d.delete_time')
|
|
->where('d.status', 1);
|
|
self::applyScope($query, $adminId, $adminInfo);
|
|
|
|
return (int) $query->count() > 0;
|
|
}
|
|
|
|
/** @return array{mode:string,label:string} */
|
|
public static function scopeMeta(int $adminId, array $adminInfo): array
|
|
{
|
|
if ((int) ($adminInfo['root'] ?? 0) === 1) {
|
|
return ['mode' => 'all', 'label' => '全部数据'];
|
|
}
|
|
|
|
$roleIds = self::roleIds($adminId);
|
|
if (array_intersect($roleIds, self::TEAM_ROLE_IDS) !== []) {
|
|
$scope = DataScopeService::getEffectiveScope($adminInfo);
|
|
$labels = [
|
|
DataScopeService::SCOPE_ALL => '全部数据',
|
|
DataScopeService::SCOPE_DEPT_AND_CHILD => '本部门及下级',
|
|
DataScopeService::SCOPE_DEPT => '本部门',
|
|
DataScopeService::SCOPE_SELF => '仅本人',
|
|
];
|
|
|
|
return [
|
|
'mode' => $scope === DataScopeService::SCOPE_ALL ? 'all' : 'team',
|
|
'label' => $labels[$scope] ?? '仅本人',
|
|
];
|
|
}
|
|
|
|
$isDoctor = in_array(self::DOCTOR_ROLE_ID, $roleIds, true);
|
|
$isAssistant = in_array(self::ASSISTANT_ROLE_ID, $roleIds, true);
|
|
if ($isDoctor && $isAssistant) {
|
|
return ['mode' => 'self', 'label' => '本人归属及接诊'];
|
|
}
|
|
if ($isDoctor) {
|
|
return ['mode' => 'self', 'label' => '本人接诊'];
|
|
}
|
|
|
|
return ['mode' => 'self', 'label' => '本人归属'];
|
|
}
|
|
|
|
/** @return int[] */
|
|
private static function roleIds(int $adminId): array
|
|
{
|
|
return self::normalizeIds(AdminRole::where('admin_id', $adminId)->column('role_id'));
|
|
}
|
|
|
|
/** @param array<int|string, mixed> $ids @return int[] */
|
|
private static function normalizeIds(array $ids): array
|
|
{
|
|
return array_values(array_unique(array_filter(array_map('intval', $ids), static function (int $id): bool {
|
|
return $id > 0;
|
|
})));
|
|
}
|
|
}
|