This commit is contained in:
Your Name
2026-05-25 18:32:17 +08:00
parent 5430fe0417
commit 58c224a081
5 changed files with 376 additions and 3 deletions
@@ -14,10 +14,12 @@ use app\common\lists\ListsExtendInterface;
use app\common\lists\ListsSearchInterface;
use app\common\lists\Traits\HasDataScopeFilter;
use app\common\model\Order;
use app\common\model\tcm\Diagnosis;
use app\common\model\auth\Admin;
use app\common\model\auth\AdminDept;
use app\common\model\tcm\Diagnosis;
use app\common\model\tcm\Prescription;
use app\common\model\tcm\PrescriptionOrder;
use app\common\model\tcm\PrescriptionOrderLog;
use app\common\model\tcm\PrescriptionOrderPayOrder;
use app\common\model\ExpressTracking;
use app\common\service\gancao\GancaoScmRecipelService;
@@ -106,6 +108,7 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
$this->applyExpressKeywordFilter($query);
$this->applyServiceChannelFilter($query);
$this->applySupplyModeFilter($query);
$this->applyAuditAdminFilter($query);
if (!$this->shouldBypassListVisibilityForDiagnosisEdit()) {
// 业绩看板按部门点「合计业绩」/复诊下钻:部门或数据域内医助筛选已收口,勿再叠「仅本人订单」
if (!$this->shouldSkipCreatorOnlyForYejiDrawer()) {
@@ -121,6 +124,105 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
YejiStatsLogic::applyYejiDrawerChannelFilterToPrescriptionOrderQuery($query, $this->params);
}
/**
* 按下单人筛选:关联操作日志中该用户执行的处方/支付单审核记录
*/
private function applyAuditAdminFilter($query): void
{
$auditAdminId = (int) ($this->params['audit_admin_id'] ?? 0);
$keyword = trim((string) ($this->params['audit_admin_keyword'] ?? ''));
if ($auditAdminId <= 0 && $keyword === '') {
return;
}
$restricted = PrescriptionOrderLogic::isOrderPlacerAuditFilterRestricted($this->adminInfo);
if ($restricted) {
$selfId = (int) $this->adminId;
if ($auditAdminId > 0 && $auditAdminId !== $selfId) {
$query->whereRaw('0 = 1');
return;
}
if ($keyword !== '') {
$selfName = trim((string) ($this->adminInfo['name'] ?? ''));
if ($selfName === ''
|| (mb_stripos($selfName, $keyword) === false && mb_stripos($keyword, $selfName) === false)) {
$query->whereRaw('0 = 1');
return;
}
}
$auditAdminId = $selfId;
} elseif ($auditAdminId <= 0 && $keyword !== '') {
$roleIds = Config::get('project.prescription_order_placer_role_ids', [6]);
$roleIds = array_values(array_unique(array_filter(array_map(
'intval',
is_array($roleIds) ? $roleIds : []
), static fn(int $id): bool => $id > 0)));
if ($roleIds === []) {
$roleIds = [6];
}
$adminIds = Admin::alias('a')
->join('admin_role ar', 'a.id = ar.admin_id')
->whereLike('a.name', '%' . $keyword . '%')
->whereIn('ar.role_id', $roleIds)
->where('a.disable', 0)
->whereNull('a.delete_time')
->column('a.id');
$adminIds = array_values(array_filter(array_map('intval', $adminIds), static function (int $id): bool {
return $id > 0;
}));
if ($adminIds === []) {
$query->whereRaw('0 = 1');
return;
}
$this->applyAuditedByAdminIdsFilter($query, $adminIds);
return;
}
if ($auditAdminId <= 0) {
return;
}
if (!PrescriptionOrderLogic::adminHasPlacerRole($auditAdminId)) {
$query->whereRaw('0 = 1');
return;
}
$this->applyAuditedByAdminIdsFilter($query, [$auditAdminId]);
}
/**
* @param int[] $adminIds
*/
private function applyAuditedByAdminIdsFilter($query, array $adminIds): void
{
$adminIds = array_values(array_unique(array_filter(array_map('intval', $adminIds), static function (int $id): bool {
return $id > 0;
})));
if ($adminIds === []) {
$query->whereRaw('0 = 1');
return;
}
$logTbl = (new PrescriptionOrderLog())->getTable();
$poTbl = (new PrescriptionOrder())->getTable();
$actions = PrescriptionOrderLogic::prescriptionOrderAuditLogActions();
$actionIn = implode(',', array_map(static function (string $a): string {
return "'" . addslashes($a) . "'";
}, $actions));
$idIn = implode(',', $adminIds);
$query->whereExists(
"SELECT 1 FROM `{$logTbl}` l WHERE l.`prescription_order_id` = `{$poTbl}`.`id`"
. " AND l.`admin_id` IN ({$idIn}) AND l.`action` IN ({$actionIn})"
);
}
/**
* 业绩看板:仅列出二中心复诊口径下的业务订单(须同时传 assistant_id、start_time、end_timerevisit_slot=0 为全部复诊分项合计)。
* admin 维度按订单创建人 o.creator_id(与部门表复诊列、排行榜复诊列同口径)。
@@ -388,6 +490,7 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
$query = PrescriptionOrder::where($this->searchWhereWithoutCreateTimeRange())->whereNull('delete_time');
$this->applyDoctorAssistantFilters($query);
$this->applyPatientKeywordFilter($query);
$this->applyAuditAdminFilter($query);
if ($this->shouldSkipCreatorOnlyForYejiDrawer()) {
$this->applyDataScopeForPrescriptionOrder($query);
} elseif (PrescriptionOrderLogic::canViewOrderListStatsAllScope($this->adminInfo)) {
@@ -634,6 +737,10 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
'focus_pending_pay_count' => $focus['pending_pay'],
'focus_pending_ship_count' => $focus['pending_ship'],
'focus_risk_count' => $focus['risk'],
/** 1=「下单」角色审核人筛选仅本人 */
'list_placer_audit_filter_restricted' => PrescriptionOrderLogic::isOrderPlacerAuditFilterRestricted($this->adminInfo) ? 1 : 0,
/** 下单人下拉(下单角色用户) */
'audit_admin_options' => PrescriptionOrderLogic::listAuditAdminOptions($this->adminId, $this->adminInfo),
];
$yejiConsult = $this->computeYejiDrawerConsultCountIfRequested();
if ($yejiConsult !== null) {
@@ -115,6 +115,123 @@ class PrescriptionOrderLogic
return self::roleIntersect($adminInfo, is_array($roles) ? $roles : []);
}
/**
* 「下单」角色:列表「审核人」筛选仅允许查本人审核过的订单(经理/管理员等豁免)
*/
public static function isOrderPlacerAuditFilterRestricted(array $adminInfo): bool
{
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
return false;
}
$placer = Config::get('project.prescription_order_placer_role_ids', [6]);
if (!self::roleIntersect($adminInfo, is_array($placer) ? $placer : [])) {
return false;
}
$exempt = Config::get('project.prescription_order_placer_exempt_role_ids', [3, 8]);
return !self::roleIntersect($adminInfo, is_array($exempt) ? $exempt : []);
}
/** @return string[] */
public static function prescriptionOrderAuditLogActions(): array
{
return ['audit_rx_approve', 'audit_rx_reject', 'audit_pay_approve', 'audit_pay_reject'];
}
/** 是否展示「下单人」筛选(下单 / 经理 / 管理员 / 超管) */
public static function shouldShowAuditAdminFilter(array $adminInfo): bool
{
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
return true;
}
if (self::isOrderPlacerAuditFilterRestricted($adminInfo)) {
return true;
}
$exempt = Config::get('project.prescription_order_placer_exempt_role_ids', [3, 8]);
return self::roleIntersect($adminInfo, is_array($exempt) ? $exempt : []);
}
/**
* 下单人下拉:直接取「下单」角色下的后台用户(project.prescription_order_placer_role_ids
*
* @return array<int, array{id: int, name: string}>
*/
public static function listAuditAdminOptions(int $adminId, array $adminInfo): array
{
if ($adminId <= 0 || !self::shouldShowAuditAdminFilter($adminInfo)) {
return [];
}
$roleIds = Config::get('project.prescription_order_placer_role_ids', [6]);
$roleIds = array_values(array_unique(array_filter(array_map(
'intval',
is_array($roleIds) ? $roleIds : []
), static fn(int $id): bool => $id > 0)));
if ($roleIds === []) {
$roleIds = [6];
}
if (self::isOrderPlacerAuditFilterRestricted($adminInfo)) {
$name = trim((string) ($adminInfo['name'] ?? ''));
return [
[
'id' => $adminId,
'name' => $name !== '' ? $name : ('管理员#' . $adminId),
],
];
}
$rows = Db::name('admin')
->alias('a')
->join('admin_role ar', 'a.id = ar.admin_id')
->whereIn('ar.role_id', $roleIds)
->where('a.disable', 0)
->whereNull('a.delete_time')
->field(['a.id', 'a.name'])
->distinct(true)
->order('a.name', 'asc')
->select()
->toArray();
$out = [];
foreach ($rows as $r) {
$id = (int) ($r['id'] ?? 0);
if ($id <= 0) {
continue;
}
$name = trim((string) ($r['name'] ?? ''));
if ($name === '') {
$name = '管理员#' . $id;
}
$out[] = ['id' => $id, 'name' => $name];
}
return $out;
}
/** 指定后台账号是否拥有「下单」角色 */
public static function adminHasPlacerRole(int $adminId): bool
{
if ($adminId <= 0) {
return false;
}
$roleIds = Config::get('project.prescription_order_placer_role_ids', [6]);
$roleIds = array_values(array_unique(array_filter(array_map(
'intval',
is_array($roleIds) ? $roleIds : []
), static fn(int $id): bool => $id > 0)));
if ($roleIds === []) {
$roleIds = [6];
}
return Db::name('admin_role')
->where('admin_id', $adminId)
->whereIn('role_id', $roleIds)
->count() > 0;
}
/**
* 菜单权限:非全量角色可额外查看「关联处方开方人为本账号」的业务订单(医助代建单)
*