更新
This commit is contained in:
@@ -31,8 +31,10 @@ use app\common\model\auth\Admin;
|
||||
use app\common\model\auth\AdminDept;
|
||||
use app\common\model\auth\AdminRole;
|
||||
use app\common\model\dict\DictData;
|
||||
use app\common\model\tcm\DiagnosisRevisitDue;
|
||||
use app\common\lists\ListsSearchInterface;
|
||||
use app\common\lists\Traits\HasDataScopeFilter;
|
||||
use app\common\service\tcm\RevisitDueService;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
@@ -143,6 +145,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
|
||||
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
||||
$this->applyLatestAssignFilters($query, $pendingWideSearch);
|
||||
$this->applyRevisitDueFilters($query, $pendingWideSearch);
|
||||
|
||||
$this->applyPendingAssignBusinessOrderMonthFilter($query);
|
||||
|
||||
@@ -460,6 +463,19 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
}
|
||||
unset($item);
|
||||
|
||||
// 复诊到期(契约 C):按快照表批量读取,缺行/不一致时由服务内部自愈(仅小页前 50 行);读取异常由服务降级为 none 占位
|
||||
$revisitDueMap = [];
|
||||
if (!empty($diagIdsForUnserved)) {
|
||||
$revisitDueMap = RevisitDueService::buildListPayload($diagIdsForUnserved, [
|
||||
'self_heal' => true,
|
||||
'page_size' => (int) $this->limitLength,
|
||||
]);
|
||||
}
|
||||
foreach ($lists as &$item) {
|
||||
$item['revisit_due'] = $revisitDueMap[(int) $item['id']] ?? RevisitDueService::emptyPayload();
|
||||
}
|
||||
unset($item);
|
||||
|
||||
return $lists;
|
||||
}
|
||||
|
||||
@@ -598,6 +614,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
|
||||
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
||||
$this->applyLatestAssignFilters($query, $pendingWideSearch);
|
||||
$this->applyRevisitDueFilters($query, $pendingWideSearch);
|
||||
|
||||
// 仅已开方(待分配+关键词检索时不限制)
|
||||
if (!$pendingWideSearch && isset($this->params['only_has_prescription']) && (string) $this->params['only_has_prescription'] === '1') {
|
||||
@@ -714,11 +731,120 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表默认排序;支持 sort_unserved_days=asc|desc 按未服务天数排序。
|
||||
* 复诊到期筛选(方案 §3.2 ②):以快照表 tcm_diagnosis_revisit_due 的 EXISTS 子查询实现。
|
||||
*
|
||||
* revisit_state:due(超期 ∪ 过号,排除已承诺未到期)| warning(到期前 warn_days 内)| booked(已约且日期未过)
|
||||
* | visited(已面诊)| contacted(已承诺复诊日未过)| no_days(有有效订单但缺开药天数)| pending(到期日在预警窗之外)
|
||||
* revisit_days_bucket:14|21|28|30 精确命中档位;other = 未命中档位且有开药天数
|
||||
* 待分配宽搜不套此过滤;lists() 与 count() 各调用一次保证分页总数一致。
|
||||
*
|
||||
* @param mixed $query
|
||||
*/
|
||||
private function applyRevisitDueFilters($query, bool $pendingWideSearch): void
|
||||
{
|
||||
if ($pendingWideSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
$state = strtolower(trim((string) ($this->params['revisit_state'] ?? '')));
|
||||
$bucket = strtolower(trim((string) ($this->params['revisit_days_bucket'] ?? '')));
|
||||
if ($state === '' && $bucket === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$rdTbl = (new DiagnosisRevisitDue())->getTable();
|
||||
$diagTbl = (new Diagnosis())->getTable();
|
||||
$conditions = ["rd.diagnosis_id = {$diagTbl}.id"];
|
||||
|
||||
if ($state !== '') {
|
||||
$warnDays = (int) (RevisitDueService::config()['warn_days'] ?? 3);
|
||||
if ($warnDays < 0) {
|
||||
$warnDays = 0;
|
||||
}
|
||||
$warnEdge = "DATE_ADD(CURDATE(), INTERVAL {$warnDays} DAY)";
|
||||
switch ($state) {
|
||||
case 'due':
|
||||
$conditions[] = 'rd.closed_state = 0';
|
||||
$conditions[] = '(rd.appointment_state = 4 OR (rd.due_date IS NOT NULL AND rd.due_date <= CURDATE()))';
|
||||
$conditions[] = '(rd.promised_date IS NULL OR rd.promised_date < CURDATE())';
|
||||
break;
|
||||
case 'warning':
|
||||
// 与读取侧 deriveState 对齐:过号(4)/已约已过期/已联系(承诺日未到) 的行优先级更高,不落入预警
|
||||
$conditions[] = 'rd.closed_state = 0';
|
||||
$conditions[] = 'rd.due_date IS NOT NULL';
|
||||
$conditions[] = 'rd.due_date > CURDATE()';
|
||||
$conditions[] = "rd.due_date <= {$warnEdge}";
|
||||
$conditions[] = 'rd.appointment_state <> 4';
|
||||
$conditions[] = 'NOT (rd.appointment_state = 1 AND rd.appointment_date < CURDATE())';
|
||||
$conditions[] = '(rd.promised_date IS NULL OR rd.promised_date < CURDATE())';
|
||||
break;
|
||||
case 'booked':
|
||||
$conditions[] = 'rd.appointment_state = 1';
|
||||
$conditions[] = 'rd.appointment_date IS NOT NULL';
|
||||
$conditions[] = 'rd.appointment_date >= CURDATE()';
|
||||
break;
|
||||
case 'visited':
|
||||
$conditions[] = '(rd.closed_state = 3 OR rd.appointment_state = 3)';
|
||||
break;
|
||||
case 'contacted':
|
||||
$conditions[] = 'rd.promised_date IS NOT NULL';
|
||||
$conditions[] = 'rd.promised_date >= CURDATE()';
|
||||
break;
|
||||
case 'no_days':
|
||||
// 与 deriveState 的 no_days 分支对齐:进行中、有有效订单但算不出预计复诊日(失效行不计)
|
||||
$conditions[] = 'rd.closed_state = 0';
|
||||
$conditions[] = 'rd.valid_order_count > 0';
|
||||
$conditions[] = 'rd.due_date IS NULL';
|
||||
break;
|
||||
case 'pending':
|
||||
$conditions[] = 'rd.closed_state = 0';
|
||||
$conditions[] = 'rd.due_date IS NOT NULL';
|
||||
$conditions[] = "rd.due_date > {$warnEdge}";
|
||||
$conditions[] = 'rd.appointment_state <> 4';
|
||||
$conditions[] = 'NOT (rd.appointment_state = 1 AND rd.appointment_date < CURDATE())';
|
||||
$conditions[] = '(rd.promised_date IS NULL OR rd.promised_date < CURDATE())';
|
||||
break;
|
||||
default:
|
||||
// 未知状态值:不做任何收窄(与其它未知筛选参数一致,避免误清空列表)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bucket !== '') {
|
||||
if ($bucket === 'other') {
|
||||
$conditions[] = 'rd.rule_days = 0';
|
||||
$conditions[] = 'rd.medication_days > 0';
|
||||
} elseif (ctype_digit($bucket) && (int) $bucket > 0) {
|
||||
$conditions[] = 'rd.rule_days = ' . (int) $bucket;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($conditions) <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query->whereExists("SELECT 1 FROM {$rdTbl} rd WHERE " . implode(' AND ', $conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表默认排序;支持 sort_revisit_due=asc|desc 按复诊到期日排序(优先),
|
||||
* 或 sort_unserved_days=asc|desc 按未服务天数排序;两者互斥,前者存在时忽略后者。
|
||||
*/
|
||||
private function resolveListOrderRaw(bool $pendingWideSearch): string
|
||||
{
|
||||
$diagTbl = (new Diagnosis())->getTable();
|
||||
|
||||
// 复诊到期日排序(方案 §3.2 ③):单行子查询取进行中快照的 due_date,无快照 / 无到期日的行置后
|
||||
$sortRevisitDue = strtolower(trim((string) ($this->params['sort_revisit_due'] ?? '')));
|
||||
if (in_array($sortRevisitDue, ['asc', 'desc'], true)) {
|
||||
$rdTbl = (new DiagnosisRevisitDue())->getTable();
|
||||
$dueExpr = "(SELECT rd.due_date FROM {$rdTbl} rd WHERE rd.diagnosis_id = {$diagTbl}.id AND rd.closed_state = 0 LIMIT 1)";
|
||||
$nullLast = "CASE WHEN {$dueExpr} IS NULL THEN 1 ELSE 0 END ASC";
|
||||
$dir = $sortRevisitDue === 'desc' ? 'DESC' : 'ASC';
|
||||
|
||||
return "{$nullLast}, {$dueExpr} {$dir}, {$diagTbl}.id DESC";
|
||||
}
|
||||
|
||||
$sortUnserved = strtolower(trim((string) ($this->params['sort_unserved_days'] ?? '')));
|
||||
if (in_array($sortUnserved, ['asc', 'desc'], true)) {
|
||||
$anchorExpr = $this->unservedAnchorExpr($diagTbl);
|
||||
|
||||
Reference in New Issue
Block a user