更新
This commit is contained in:
@@ -121,6 +121,16 @@
|
|||||||
end-placeholder="最近挂号结束"
|
end-placeholder="最近挂号结束"
|
||||||
@change="handleLatestAppointmentFilterChange"
|
@change="handleLatestAppointmentFilterChange"
|
||||||
/>
|
/>
|
||||||
|
<daterange-picker
|
||||||
|
class="latest-assign-range"
|
||||||
|
v-model:startTime="formData.latest_assign_start_date"
|
||||||
|
v-model:endTime="formData.latest_assign_end_date"
|
||||||
|
picker-type="daterange"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
start-placeholder="最近指派开始"
|
||||||
|
end-placeholder="最近指派结束"
|
||||||
|
@change="handleLatestAssignFilterChange"
|
||||||
|
/>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="formData.latest_appointment_channel_source"
|
v-model="formData.latest_appointment_channel_source"
|
||||||
placeholder="最近挂号渠道"
|
placeholder="最近挂号渠道"
|
||||||
@@ -173,6 +183,7 @@
|
|||||||
v-loading="pager.loading"
|
v-loading="pager.loading"
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
@row-dblclick="goReadonly"
|
@row-dblclick="goReadonly"
|
||||||
|
@sort-change="handleTableSortChange"
|
||||||
:row-class-name="getRowClassName"
|
:row-class-name="getRowClassName"
|
||||||
class="diagnosis-table"
|
class="diagnosis-table"
|
||||||
stripe
|
stripe
|
||||||
@@ -283,7 +294,14 @@
|
|||||||
<span v-else class="status-unprescribed">未开方</span>
|
<span v-else class="status-unprescribed">未开方</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="未服务天数" width="110" align="center">
|
<el-table-column
|
||||||
|
label="未服务天数"
|
||||||
|
prop="unserved_days"
|
||||||
|
width="110"
|
||||||
|
align="center"
|
||||||
|
sortable="custom"
|
||||||
|
:sort-orders="['descending', 'ascending']"
|
||||||
|
>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
v-if="row.last_blood_record_at"
|
v-if="row.last_blood_record_at"
|
||||||
@@ -762,6 +780,10 @@ const formData = reactive({
|
|||||||
latest_appointment_start_date: '' as string,
|
latest_appointment_start_date: '' as string,
|
||||||
latest_appointment_end_date: '' as string,
|
latest_appointment_end_date: '' as string,
|
||||||
latest_appointment_channel_source: '' as string,
|
latest_appointment_channel_source: '' as string,
|
||||||
|
latest_assign_start_date: '' as string,
|
||||||
|
latest_assign_end_date: '' as string,
|
||||||
|
/** 未服务天数排序:desc=天数多到少 asc=少到多 */
|
||||||
|
sort_unserved_days: '' as '' | 'asc' | 'desc',
|
||||||
diagnosis_confirmed: '' as '' | '0' | '1',
|
diagnosis_confirmed: '' as '' | '0' | '1',
|
||||||
appointment_date: '' as string,
|
appointment_date: '' as string,
|
||||||
has_appointment: '' as '' | '0' | '1',
|
has_appointment: '' as '' | '0' | '1',
|
||||||
@@ -849,22 +871,50 @@ function resolvePendingAssignOrderMonthForRequest(): string {
|
|||||||
return dayjs().format('YYYY-MM')
|
return dayjs().format('YYYY-MM')
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 待分配角标 count 请求:与列表同条件,且去掉其它顶部 Tab 残留(如默认「当天挂号」) */
|
/** 除顶部 Tab 专属条件外,与主列表共用的「更多筛选」参数(角标 count 需同步) */
|
||||||
function buildPendingAssignCountPayload(): Record<string, unknown> {
|
function buildSharedDiagnosisFilterPayload(): Record<string, unknown> {
|
||||||
return buildTcmDiagnosisListRequestPayload({
|
return {
|
||||||
...formData,
|
keyword: formData.keyword,
|
||||||
|
diagnosis_type: formData.diagnosis_type,
|
||||||
|
syndrome_type: formData.syndrome_type,
|
||||||
|
assistant_id: formData.assistant_id,
|
||||||
|
diagnosis_confirmed: formData.diagnosis_confirmed,
|
||||||
|
has_appointment: formData.has_appointment,
|
||||||
|
latest_appointment_start_date: formData.latest_appointment_start_date,
|
||||||
|
latest_appointment_end_date: formData.latest_appointment_end_date,
|
||||||
|
latest_appointment_channel_source: formData.latest_appointment_channel_source,
|
||||||
|
latest_assign_start_date: formData.latest_assign_start_date,
|
||||||
|
latest_assign_end_date: formData.latest_assign_end_date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 顶部 Tab 角标 count 请求:带上共用筛选,再叠加各 Tab 专属条件 */
|
||||||
|
function buildDateCountRequestPayload(overrides: Record<string, unknown> = {}): Record<string, unknown> {
|
||||||
|
return {
|
||||||
page_no: 1,
|
page_no: 1,
|
||||||
page_size: 1,
|
page_size: 1,
|
||||||
pending_assign: 1,
|
...buildSharedDiagnosisFilterPayload(),
|
||||||
appointment_date: '',
|
appointment_date: '',
|
||||||
has_appointment: '',
|
|
||||||
pending_booking: '',
|
pending_booking: '',
|
||||||
completed_appointment: '',
|
completed_appointment: '',
|
||||||
latest_appointment_start_date: '',
|
pending_assign: '',
|
||||||
latest_appointment_end_date: '',
|
pending_assign_order_month: '',
|
||||||
latest_appointment_channel_source: '',
|
pending_assign_keyword: '',
|
||||||
pending_assign_order_month: resolvePendingAssignOrderMonthForRequest()
|
sort_unserved_days: '',
|
||||||
} as Record<string, unknown>) as Record<string, unknown>
|
...overrides
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 待分配角标 count 请求:与列表同条件,且去掉其它顶部 Tab 残留(如默认「当天挂号」) */
|
||||||
|
function buildPendingAssignCountPayload(): Record<string, unknown> {
|
||||||
|
return buildTcmDiagnosisListRequestPayload(
|
||||||
|
buildDateCountRequestPayload({
|
||||||
|
pending_assign: 1,
|
||||||
|
has_appointment: '',
|
||||||
|
pending_assign_order_month: resolvePendingAssignOrderMonthForRequest(),
|
||||||
|
pending_assign_keyword: formData.pending_assign_keyword
|
||||||
|
}) as Record<string, unknown>
|
||||||
|
) as Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchTcmDiagnosisListsForPaging = (req: Record<string, unknown>) =>
|
const fetchTcmDiagnosisListsForPaging = (req: Record<string, unknown>) =>
|
||||||
@@ -893,6 +943,9 @@ function clearSecondaryFiltersWhenPendingAssignWideSearch() {
|
|||||||
formData.latest_appointment_start_date = ''
|
formData.latest_appointment_start_date = ''
|
||||||
formData.latest_appointment_end_date = ''
|
formData.latest_appointment_end_date = ''
|
||||||
formData.latest_appointment_channel_source = ''
|
formData.latest_appointment_channel_source = ''
|
||||||
|
formData.latest_assign_start_date = ''
|
||||||
|
formData.latest_assign_end_date = ''
|
||||||
|
formData.sort_unserved_days = ''
|
||||||
formData.pending_assign_order_month = ''
|
formData.pending_assign_order_month = ''
|
||||||
activeTab.value = 'all'
|
activeTab.value = 'all'
|
||||||
if (kw1 !== '') {
|
if (kw1 !== '') {
|
||||||
@@ -994,14 +1047,26 @@ const onPendingAssignOrderMonthChange = async (val: string | null) => {
|
|||||||
const fetchDateCounts = async () => {
|
const fetchDateCounts = async () => {
|
||||||
try {
|
try {
|
||||||
const [yesterday, dayBefore, today, tomorrow, dayAfter, all, noApt, doneVisit, pending] = await Promise.all([
|
const [yesterday, dayBefore, today, tomorrow, dayAfter, all, noApt, doneVisit, pending] = await Promise.all([
|
||||||
tcmDiagnosisLists({ appointment_date: yesterdayStr.value, page_no: 1, page_size: 1 }),
|
tcmDiagnosisLists(
|
||||||
tcmDiagnosisLists({ appointment_date: dayBeforeStr.value, page_no: 1, page_size: 1 }),
|
buildDateCountRequestPayload({ appointment_date: yesterdayStr.value, has_appointment: '' }) as any
|
||||||
tcmDiagnosisLists({ appointment_date: todayStr.value, page_no: 1, page_size: 1 }),
|
),
|
||||||
tcmDiagnosisLists({ appointment_date: tomorrowStr.value, page_no: 1, page_size: 1 }),
|
tcmDiagnosisLists(
|
||||||
tcmDiagnosisLists({ appointment_date: dayAfterStr.value, page_no: 1, page_size: 1 }),
|
buildDateCountRequestPayload({ appointment_date: dayBeforeStr.value, has_appointment: '' }) as any
|
||||||
tcmDiagnosisLists({ page_no: 1, page_size: 1 }),
|
),
|
||||||
tcmDiagnosisLists({ has_appointment: 0, page_no: 1, page_size: 1 }),
|
tcmDiagnosisLists(
|
||||||
tcmDiagnosisLists({ completed_appointment: 1, page_no: 1, page_size: 1 }),
|
buildDateCountRequestPayload({ appointment_date: todayStr.value, has_appointment: '' }) as any
|
||||||
|
),
|
||||||
|
tcmDiagnosisLists(
|
||||||
|
buildDateCountRequestPayload({ appointment_date: tomorrowStr.value, has_appointment: '' }) as any
|
||||||
|
),
|
||||||
|
tcmDiagnosisLists(
|
||||||
|
buildDateCountRequestPayload({ appointment_date: dayAfterStr.value, has_appointment: '' }) as any
|
||||||
|
),
|
||||||
|
tcmDiagnosisLists(buildDateCountRequestPayload() as any),
|
||||||
|
tcmDiagnosisLists(buildDateCountRequestPayload({ has_appointment: 0 }) as any),
|
||||||
|
tcmDiagnosisLists(
|
||||||
|
buildDateCountRequestPayload({ completed_appointment: 1, has_appointment: '' }) as any
|
||||||
|
),
|
||||||
tcmDiagnosisLists(buildPendingAssignCountPayload() as any)
|
tcmDiagnosisLists(buildPendingAssignCountPayload() as any)
|
||||||
])
|
])
|
||||||
dateCounts.value = {
|
dateCounts.value = {
|
||||||
@@ -1135,6 +1200,11 @@ const clearLatestAppointmentFilters = () => {
|
|||||||
formData.latest_appointment_channel_source = ''
|
formData.latest_appointment_channel_source = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clearLatestAssignFilters = () => {
|
||||||
|
formData.latest_assign_start_date = ''
|
||||||
|
formData.latest_assign_end_date = ''
|
||||||
|
}
|
||||||
|
|
||||||
const hasLatestAppointmentFilter = () =>
|
const hasLatestAppointmentFilter = () =>
|
||||||
!!(
|
!!(
|
||||||
formData.latest_appointment_start_date ||
|
formData.latest_appointment_start_date ||
|
||||||
@@ -1142,6 +1212,9 @@ const hasLatestAppointmentFilter = () =>
|
|||||||
formData.latest_appointment_channel_source
|
formData.latest_appointment_channel_source
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const hasLatestAssignFilter = () =>
|
||||||
|
!!(formData.latest_assign_start_date || formData.latest_assign_end_date)
|
||||||
|
|
||||||
const handleLatestAppointmentFilterChange = () => {
|
const handleLatestAppointmentFilterChange = () => {
|
||||||
if (hasLatestAppointmentFilter()) {
|
if (hasLatestAppointmentFilter()) {
|
||||||
formData.appointment_date = ''
|
formData.appointment_date = ''
|
||||||
@@ -1154,6 +1227,27 @@ const handleLatestAppointmentFilterChange = () => {
|
|||||||
doSearch()
|
doSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleLatestAssignFilterChange = () => {
|
||||||
|
doSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleTableSortChange = ({
|
||||||
|
prop,
|
||||||
|
order
|
||||||
|
}: {
|
||||||
|
prop: string
|
||||||
|
order: 'ascending' | 'descending' | null
|
||||||
|
}) => {
|
||||||
|
if (prop === 'unserved_days') {
|
||||||
|
formData.sort_unserved_days =
|
||||||
|
order === 'ascending' ? 'asc' : order === 'descending' ? 'desc' : ''
|
||||||
|
} else {
|
||||||
|
formData.sort_unserved_days = ''
|
||||||
|
}
|
||||||
|
pager.page = 1
|
||||||
|
getLists()
|
||||||
|
}
|
||||||
|
|
||||||
const latestAppointmentChannelText = (row: any) => {
|
const latestAppointmentChannelText = (row: any) => {
|
||||||
const desc = String(row?.latest_appointment_channel_source_desc || '').trim()
|
const desc = String(row?.latest_appointment_channel_source_desc || '').trim()
|
||||||
const raw = String(row?.latest_appointment_channel_source || '').trim()
|
const raw = String(row?.latest_appointment_channel_source || '').trim()
|
||||||
@@ -1200,6 +1294,9 @@ const handleReset = () => {
|
|||||||
formData.latest_appointment_start_date = ''
|
formData.latest_appointment_start_date = ''
|
||||||
formData.latest_appointment_end_date = ''
|
formData.latest_appointment_end_date = ''
|
||||||
formData.latest_appointment_channel_source = ''
|
formData.latest_appointment_channel_source = ''
|
||||||
|
formData.latest_assign_start_date = ''
|
||||||
|
formData.latest_assign_end_date = ''
|
||||||
|
formData.sort_unserved_days = ''
|
||||||
formData.diagnosis_confirmed = ''
|
formData.diagnosis_confirmed = ''
|
||||||
formData.appointment_date = ''
|
formData.appointment_date = ''
|
||||||
formData.has_appointment = ''
|
formData.has_appointment = ''
|
||||||
@@ -2298,6 +2395,11 @@ onUnmounted(() => {
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.latest-assign-range {
|
||||||
|
width: 260px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.latest-appointment-channel {
|
.latest-appointment-channel {
|
||||||
width: 170px;
|
width: 170px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
||||||
|
$this->applyLatestAssignFilters($query, $pendingWideSearch);
|
||||||
|
|
||||||
$this->applyPendingAssignBusinessOrderMonthFilter($query);
|
$this->applyPendingAssignBusinessOrderMonthFilter($query);
|
||||||
|
|
||||||
@@ -167,30 +168,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按挂号状态优先级排序:已过号(4) > 已预约(1) > 已完成(3),然后按挂号日期+时间升序
|
$orderRaw = $this->resolveListOrderRaw($pendingWideSearch);
|
||||||
// 若传了 appointment_date(当天/明天等筛选),只按「该日」的挂号排序与展示
|
|
||||||
$diagTbl = (new Diagnosis())->getTable();
|
|
||||||
$aptTbl = (new Appointment())->getTable();
|
|
||||||
$minAptDateCond = '';
|
|
||||||
if (!$pendingWideSearch && !empty($this->params['appointment_date'])) {
|
|
||||||
$sortAptDate = addslashes((string) $this->params['appointment_date']);
|
|
||||||
$minAptDateCond = " AND apt.appointment_date = '{$sortAptDate}'";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取最早的挂号状态(用于排序优先级)
|
|
||||||
$minAptStatusExpr = '(SELECT apt.status FROM ' . $aptTbl . ' apt WHERE apt.patient_id = ' . $diagTbl . '.id AND apt.status IN (1,3,4)' . $minAptDateCond . ' ORDER BY CASE apt.status WHEN 4 THEN 1 WHEN 1 THEN 2 WHEN 3 THEN 3 ELSE 4 END, apt.appointment_date ASC, apt.appointment_time ASC LIMIT 1)';
|
|
||||||
|
|
||||||
// 获取最早的挂号时间(用于同状态内排序)
|
|
||||||
$minAptExpr = '(SELECT MIN(CONCAT(apt.appointment_date, \' \', IFNULL(NULLIF(TRIM(apt.appointment_time), \'\'), \'00:00:00\'))) FROM ' . $aptTbl . ' apt WHERE apt.patient_id = ' . $diagTbl . '.id AND apt.status IN (1,3,4)' . $minAptDateCond . ')';
|
|
||||||
|
|
||||||
// 「已完成」Tab:按最近一条「已完成」(status=3) 挂号日期+时间降序…
|
|
||||||
$isCompletedTab = !$pendingWideSearch && isset($this->params['completed_appointment']) && (string) $this->params['completed_appointment'] === '1';
|
|
||||||
if ($isCompletedTab) {
|
|
||||||
$maxCompletedAptExpr = '(SELECT MAX(CONCAT(apt.appointment_date, \' \', IFNULL(NULLIF(TRIM(apt.appointment_time), \'\'), \'00:00:00\'))) FROM ' . $aptTbl . ' apt WHERE apt.patient_id = ' . $diagTbl . '.id AND apt.status = 3' . $minAptDateCond . ')';
|
|
||||||
$orderRaw = $diagTbl . '.assign_read_at IS NULL DESC, IFNULL(' . $maxCompletedAptExpr . ", '1970-01-01 00:00:00') DESC, {$diagTbl}.id DESC";
|
|
||||||
} else {
|
|
||||||
$orderRaw = $diagTbl . '.assign_read_at IS NULL DESC, CASE IFNULL(' . $minAptStatusExpr . ', 999) WHEN 4 THEN 1 WHEN 1 THEN 2 WHEN 3 THEN 3 ELSE 4 END ASC, IFNULL(' . $minAptExpr . ", '9999-12-31 23:59:59') ASC, {$diagTbl}.id DESC";
|
|
||||||
}
|
|
||||||
|
|
||||||
$lists = $query
|
$lists = $query
|
||||||
->with(['DiagnosisViewRecord'])
|
->with(['DiagnosisViewRecord'])
|
||||||
@@ -571,6 +549,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
||||||
|
$this->applyLatestAssignFilters($query, $pendingWideSearch);
|
||||||
|
|
||||||
// 仅已开方(待分配+关键词检索时不限制)
|
// 仅已开方(待分配+关键词检索时不限制)
|
||||||
if (!$pendingWideSearch && isset($this->params['only_has_prescription']) && (string) $this->params['only_has_prescription'] === '1') {
|
if (!$pendingWideSearch && isset($this->params['only_has_prescription']) && (string) $this->params['only_has_prescription'] === '1') {
|
||||||
@@ -644,6 +623,99 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
|||||||
$query->whereExists("SELECT 1 FROM {$aptTbl} latest_apt WHERE " . implode(' AND ', $conditions));
|
$query->whereExists("SELECT 1 FROM {$aptTbl} latest_apt WHERE " . implode(' AND ', $conditions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近一次成功指派过滤:按 create_time DESC, id DESC 取 to_assistant_id>0 的一条。
|
||||||
|
*
|
||||||
|
* @param mixed $query
|
||||||
|
*/
|
||||||
|
private function applyLatestAssignFilters($query, bool $pendingWideSearch): void
|
||||||
|
{
|
||||||
|
if ($pendingWideSearch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$startDate = $this->normalizeYmd($this->params['latest_assign_start_date'] ?? '');
|
||||||
|
$endDate = $this->normalizeYmd($this->params['latest_assign_end_date'] ?? '');
|
||||||
|
if ($startDate === '' && $endDate === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$logTbl = Db::name('tcm_diagnosis_assign_log')->getTable();
|
||||||
|
$diagTbl = (new Diagnosis())->getTable();
|
||||||
|
$latestIdSql = $this->latestAssignLogIdSubSql($logTbl, $diagTbl);
|
||||||
|
$conditions = ["latest_lg.id = ({$latestIdSql})"];
|
||||||
|
|
||||||
|
if ($startDate !== '') {
|
||||||
|
$startTs = (int) strtotime($startDate . ' 00:00:00');
|
||||||
|
$conditions[] = "latest_lg.create_time >= {$startTs}";
|
||||||
|
}
|
||||||
|
if ($endDate !== '') {
|
||||||
|
$endTs = (int) strtotime($endDate . ' 23:59:59');
|
||||||
|
$conditions[] = "latest_lg.create_time <= {$endTs}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->whereExists("SELECT 1 FROM {$logTbl} latest_lg WHERE " . implode(' AND ', $conditions));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function latestAssignLogIdSubSql(string $logTbl, string $diagTbl): string
|
||||||
|
{
|
||||||
|
return "SELECT lg_latest.id FROM {$logTbl} lg_latest "
|
||||||
|
. "WHERE lg_latest.diagnosis_id = {$diagTbl}.id "
|
||||||
|
. 'AND lg_latest.to_assistant_id > 0 '
|
||||||
|
. 'ORDER BY lg_latest.create_time DESC, lg_latest.id DESC LIMIT 1';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列表默认排序;支持 sort_unserved_days=asc|desc 按未服务天数排序。
|
||||||
|
*/
|
||||||
|
private function resolveListOrderRaw(bool $pendingWideSearch): string
|
||||||
|
{
|
||||||
|
$diagTbl = (new Diagnosis())->getTable();
|
||||||
|
$sortUnserved = strtolower(trim((string) ($this->params['sort_unserved_days'] ?? '')));
|
||||||
|
if (in_array($sortUnserved, ['asc', 'desc'], true)) {
|
||||||
|
$anchorExpr = $this->unservedAnchorExpr($diagTbl);
|
||||||
|
$nullLast = "CASE WHEN IFNULL({$anchorExpr}, 0) = 0 THEN 1 ELSE 0 END ASC";
|
||||||
|
if ($sortUnserved === 'desc') {
|
||||||
|
return "{$nullLast}, IFNULL({$anchorExpr}, 0) ASC, {$diagTbl}.id DESC";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "{$nullLast}, IFNULL({$anchorExpr}, 0) DESC, {$diagTbl}.id DESC";
|
||||||
|
}
|
||||||
|
|
||||||
|
$aptTbl = (new Appointment())->getTable();
|
||||||
|
$minAptDateCond = '';
|
||||||
|
if (!$pendingWideSearch && !empty($this->params['appointment_date'])) {
|
||||||
|
$sortAptDate = addslashes((string) $this->params['appointment_date']);
|
||||||
|
$minAptDateCond = " AND apt.appointment_date = '{$sortAptDate}'";
|
||||||
|
}
|
||||||
|
|
||||||
|
$minAptStatusExpr = '(SELECT apt.status FROM ' . $aptTbl . ' apt WHERE apt.patient_id = ' . $diagTbl . '.id AND apt.status IN (1,3,4)' . $minAptDateCond . ' ORDER BY CASE apt.status WHEN 4 THEN 1 WHEN 1 THEN 2 WHEN 3 THEN 3 ELSE 4 END, apt.appointment_date ASC, apt.appointment_time ASC LIMIT 1)';
|
||||||
|
$minAptExpr = '(SELECT MIN(CONCAT(apt.appointment_date, \' \', IFNULL(NULLIF(TRIM(apt.appointment_time), \'\'), \'00:00:00\'))) FROM ' . $aptTbl . ' apt WHERE apt.patient_id = ' . $diagTbl . '.id AND apt.status IN (1,3,4)' . $minAptDateCond . ')';
|
||||||
|
|
||||||
|
$isCompletedTab = !$pendingWideSearch && isset($this->params['completed_appointment']) && (string) $this->params['completed_appointment'] === '1';
|
||||||
|
if ($isCompletedTab) {
|
||||||
|
$maxCompletedAptExpr = '(SELECT MAX(CONCAT(apt.appointment_date, \' \', IFNULL(NULLIF(TRIM(apt.appointment_time), \'\'), \'00:00:00\'))) FROM ' . $aptTbl . ' apt WHERE apt.patient_id = ' . $diagTbl . '.id AND apt.status = 3' . $minAptDateCond . ')';
|
||||||
|
|
||||||
|
return $diagTbl . '.assign_read_at IS NULL DESC, IFNULL(' . $maxCompletedAptExpr . ", '1970-01-01 00:00:00') DESC, {$diagTbl}.id DESC";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $diagTbl . '.assign_read_at IS NULL DESC, CASE IFNULL(' . $minAptStatusExpr . ', 999) WHEN 4 THEN 1 WHEN 1 THEN 2 WHEN 3 THEN 3 ELSE 4 END ASC, IFNULL(' . $minAptExpr . ", '9999-12-31 23:59:59') ASC, {$diagTbl}.id DESC";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 未服务天数锚点:血糖/饮食/运动记录最近 record_date 的最大值 */
|
||||||
|
private function unservedAnchorExpr(string $diagTbl): string
|
||||||
|
{
|
||||||
|
$bloodTbl = (new BloodRecord())->getTable();
|
||||||
|
$dietTbl = (new DietRecord())->getTable();
|
||||||
|
$exerciseTbl = (new ExerciseRecord())->getTable();
|
||||||
|
|
||||||
|
return 'GREATEST('
|
||||||
|
. "COALESCE((SELECT MAX(br.record_date) FROM {$bloodTbl} br WHERE br.diagnosis_id = {$diagTbl}.id AND br.delete_time IS NULL), 0), "
|
||||||
|
. "COALESCE((SELECT MAX(dr.record_date) FROM {$dietTbl} dr WHERE dr.diagnosis_id = {$diagTbl}.id AND dr.delete_time IS NULL), 0), "
|
||||||
|
. "COALESCE((SELECT MAX(er.record_date) FROM {$exerciseTbl} er WHERE er.diagnosis_id = {$diagTbl}.id AND er.delete_time IS NULL), 0)"
|
||||||
|
. ')';
|
||||||
|
}
|
||||||
|
|
||||||
private function latestAppointmentIdSubSql(string $aptTbl, string $diagTbl): string
|
private function latestAppointmentIdSubSql(string $aptTbl, string $diagTbl): string
|
||||||
{
|
{
|
||||||
$statuses = implode(',', self::EFFECTIVE_APPOINTMENT_STATUSES);
|
$statuses = implode(',', self::EFFECTIVE_APPOINTMENT_STATUSES);
|
||||||
|
|||||||
Reference in New Issue
Block a user