feat: 支持患者列表按最近挂号筛选
- tcm.diagnosis/lists 新增最近有效挂号时间区间与渠道筛选,lists/count 共用过滤逻辑 - 诊单患者列表更多筛选增加最近挂号时间和渠道,并与顶部挂号快捷筛选互斥 - 明确 daterange-picker change 事件转发,列表补充最近挂号渠道摘要展示
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
:end-placeholder="endPlaceholder"
|
||||
:value-format="valueFormat"
|
||||
clearable
|
||||
@change="emit('change', $event)"
|
||||
></el-date-picker>
|
||||
</template>
|
||||
|
||||
@@ -29,7 +30,7 @@ const props = withDefaults(
|
||||
endPlaceholder: '结束时间'
|
||||
}
|
||||
)
|
||||
const emit = defineEmits(['update:startTime', 'update:endTime'])
|
||||
const emit = defineEmits(['update:startTime', 'update:endTime', 'change'])
|
||||
|
||||
const content = computed<any>({
|
||||
get: () => {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
formData.pending_assign !== '1' &&
|
||||
formData.pending_booking !== '1' &&
|
||||
formData.completed_appointment !== '1' &&
|
||||
!hasLatestAppointmentFilter() &&
|
||||
formData.appointment_date === tab.value
|
||||
}
|
||||
]"
|
||||
@@ -110,6 +111,32 @@
|
||||
<el-select v-model="formData.assistant_id" placeholder="医助" clearable filterable size="small" @change="doSearch">
|
||||
<el-option v-for="item in assistantOptions" :key="item.id" :label="item.name" :value="Number(item.id)" />
|
||||
</el-select>
|
||||
<daterange-picker
|
||||
class="latest-appointment-range"
|
||||
v-model:startTime="formData.latest_appointment_start_date"
|
||||
v-model:endTime="formData.latest_appointment_end_date"
|
||||
picker-type="daterange"
|
||||
value-format="YYYY-MM-DD"
|
||||
start-placeholder="最近挂号开始"
|
||||
end-placeholder="最近挂号结束"
|
||||
@change="handleLatestAppointmentFilterChange"
|
||||
/>
|
||||
<el-select
|
||||
v-model="formData.latest_appointment_channel_source"
|
||||
placeholder="最近挂号渠道"
|
||||
clearable
|
||||
filterable
|
||||
size="small"
|
||||
class="latest-appointment-channel"
|
||||
@change="handleLatestAppointmentFilterChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in channelOptions"
|
||||
:key="String(item.value)"
|
||||
:label="item.name"
|
||||
:value="String(item.value)"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button size="small" @click="handleReset">重置</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -213,6 +240,9 @@
|
||||
<div class="apt-doctor">{{ row.appointment_doctor_name || '-' }}</div>
|
||||
<div class="apt-time">{{ row.appointment_time_text || '-' }}</div>
|
||||
</template>
|
||||
<div v-if="latestAppointmentChannelText(row)" class="apt-latest-channel">
|
||||
最近渠道:{{ latestAppointmentChannelText(row) }}
|
||||
</div>
|
||||
</template>
|
||||
<span v-else class="apt-none">未挂号</span>
|
||||
</div>
|
||||
@@ -689,6 +719,7 @@ import useUserStore from '@/stores/modules/user'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { computed, defineAsyncComponent, onMounted, onUnmounted, watch } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import DaterangePicker from '@/components/daterange-picker/index.vue'
|
||||
|
||||
const EditPopup = defineAsyncComponent(() => import('./edit.vue'))
|
||||
const DetailPopup = defineAsyncComponent(() => import('./detail.vue'))
|
||||
@@ -728,6 +759,9 @@ const formData = reactive({
|
||||
assistant_id: '',
|
||||
start_time: '',
|
||||
end_time: '',
|
||||
latest_appointment_start_date: '' as string,
|
||||
latest_appointment_end_date: '' as string,
|
||||
latest_appointment_channel_source: '' as string,
|
||||
diagnosis_confirmed: '' as '' | '0' | '1',
|
||||
appointment_date: '' as string,
|
||||
has_appointment: '' as '' | '0' | '1',
|
||||
@@ -760,6 +794,9 @@ const setHasAppointment = (v: string) => {
|
||||
formData.has_appointment = v as '' | '0' | '1'
|
||||
formData.pending_booking = ''
|
||||
formData.completed_appointment = ''
|
||||
if (v === '0') {
|
||||
clearLatestAppointmentFilters()
|
||||
}
|
||||
pager.page = 1
|
||||
getLists()
|
||||
fetchDateCounts()
|
||||
@@ -823,6 +860,9 @@ function buildPendingAssignCountPayload(): Record<string, unknown> {
|
||||
has_appointment: '',
|
||||
pending_booking: '',
|
||||
completed_appointment: '',
|
||||
latest_appointment_start_date: '',
|
||||
latest_appointment_end_date: '',
|
||||
latest_appointment_channel_source: '',
|
||||
pending_assign_order_month: resolvePendingAssignOrderMonthForRequest()
|
||||
} as Record<string, unknown>) as Record<string, unknown>
|
||||
}
|
||||
@@ -850,6 +890,9 @@ function clearSecondaryFiltersWhenPendingAssignWideSearch() {
|
||||
formData.assistant_id = ''
|
||||
formData.start_time = ''
|
||||
formData.end_time = ''
|
||||
formData.latest_appointment_start_date = ''
|
||||
formData.latest_appointment_end_date = ''
|
||||
formData.latest_appointment_channel_source = ''
|
||||
formData.pending_assign_order_month = ''
|
||||
activeTab.value = 'all'
|
||||
if (kw1 !== '') {
|
||||
@@ -886,6 +929,7 @@ const handleDateTabClick = async (value: string) => {
|
||||
formData.pending_booking = ''
|
||||
formData.completed_appointment = ''
|
||||
formData.has_appointment = ''
|
||||
clearLatestAppointmentFilters()
|
||||
formData.appointment_date = value
|
||||
pager.page = 1
|
||||
await getLists()
|
||||
@@ -901,6 +945,7 @@ const handlePendingBookingTabClick = async () => {
|
||||
formData.completed_appointment = ''
|
||||
formData.appointment_date = ''
|
||||
formData.has_appointment = '0'
|
||||
clearLatestAppointmentFilters()
|
||||
pager.page = 1
|
||||
await getLists()
|
||||
fetchDateCounts()
|
||||
@@ -915,6 +960,7 @@ const handleCompletedVisitTabClick = async () => {
|
||||
formData.completed_appointment = '1'
|
||||
formData.has_appointment = ''
|
||||
formData.appointment_date = ''
|
||||
clearLatestAppointmentFilters()
|
||||
pager.page = 1
|
||||
await getLists()
|
||||
fetchDateCounts()
|
||||
@@ -926,6 +972,7 @@ const handlePendingAssignTabClick = async () => {
|
||||
formData.completed_appointment = ''
|
||||
formData.has_appointment = ''
|
||||
formData.appointment_date = ''
|
||||
clearLatestAppointmentFilters()
|
||||
if (!formData.pending_assign_order_month) {
|
||||
formData.pending_assign_order_month = dayjs().format('YYYY-MM')
|
||||
}
|
||||
@@ -1047,16 +1094,29 @@ const handleMoreCommand = (cmd: string) => {
|
||||
const diagnosisTypeOptions = ref<any[]>([])
|
||||
const syndromeTypeOptions = ref<any[]>([])
|
||||
const assistantOptions = ref<any[]>([])
|
||||
const channelOptions = ref<Array<{ name: string; value: string }>>([])
|
||||
|
||||
const getDictOptions = async () => {
|
||||
try {
|
||||
const [diagnosisType, syndromeType, assistants] = await Promise.all([
|
||||
const [diagnosisType, syndromeType, channels, assistants] = await Promise.all([
|
||||
getDictData({ type: 'diagnosis_type' }),
|
||||
getDictData({ type: 'syndrome_type' }),
|
||||
getDictData({ type: 'channels' }),
|
||||
getAssistants()
|
||||
])
|
||||
diagnosisTypeOptions.value = diagnosisType?.diagnosis_type || []
|
||||
syndromeTypeOptions.value = syndromeType?.syndrome_type || []
|
||||
channelOptions.value = (channels?.channels || [])
|
||||
.filter((row: any) => row.status !== 0)
|
||||
.sort((a: any, b: any) => {
|
||||
const ds = Number(b?.sort ?? 0) - Number(a?.sort ?? 0)
|
||||
if (ds !== 0) return ds
|
||||
return Number(b?.id ?? 0) - Number(a?.id ?? 0)
|
||||
})
|
||||
.map((row: any) => ({
|
||||
name: String(row?.name ?? row?.value ?? ''),
|
||||
value: row?.value != null && row.value !== '' ? String(row.value) : ''
|
||||
}))
|
||||
assistantOptions.value = assistants || []
|
||||
} catch (error) {
|
||||
console.error('获取字典数据失败:', error)
|
||||
@@ -1069,6 +1129,40 @@ const getDictLabel = (options: any[], value: string) => {
|
||||
return item ? item.name : value || '-'
|
||||
}
|
||||
|
||||
const clearLatestAppointmentFilters = () => {
|
||||
formData.latest_appointment_start_date = ''
|
||||
formData.latest_appointment_end_date = ''
|
||||
formData.latest_appointment_channel_source = ''
|
||||
}
|
||||
|
||||
const hasLatestAppointmentFilter = () =>
|
||||
!!(
|
||||
formData.latest_appointment_start_date ||
|
||||
formData.latest_appointment_end_date ||
|
||||
formData.latest_appointment_channel_source
|
||||
)
|
||||
|
||||
const handleLatestAppointmentFilterChange = () => {
|
||||
if (hasLatestAppointmentFilter()) {
|
||||
formData.appointment_date = ''
|
||||
formData.pending_booking = ''
|
||||
formData.completed_appointment = ''
|
||||
if (formData.has_appointment === '0') {
|
||||
formData.has_appointment = ''
|
||||
}
|
||||
}
|
||||
doSearch()
|
||||
}
|
||||
|
||||
const latestAppointmentChannelText = (row: any) => {
|
||||
const desc = String(row?.latest_appointment_channel_source_desc || '').trim()
|
||||
const raw = String(row?.latest_appointment_channel_source || '').trim()
|
||||
const detail = String(row?.latest_appointment_channel_source_detail || '').trim()
|
||||
const base = desc || raw
|
||||
if (!base) return ''
|
||||
return detail ? `${base}(${detail})` : base
|
||||
}
|
||||
|
||||
// 获取医助名称
|
||||
const getAssistantName = (assistantId: number | string) => {
|
||||
// 如果没有assistant_id,返回"-"
|
||||
@@ -1103,6 +1197,9 @@ const handleReset = () => {
|
||||
formData.diagnosis_type = ''
|
||||
formData.syndrome_type = ''
|
||||
formData.assistant_id = ''
|
||||
formData.latest_appointment_start_date = ''
|
||||
formData.latest_appointment_end_date = ''
|
||||
formData.latest_appointment_channel_source = ''
|
||||
formData.diagnosis_confirmed = ''
|
||||
formData.appointment_date = ''
|
||||
formData.has_appointment = ''
|
||||
@@ -2190,10 +2287,20 @@ onUnmounted(() => {
|
||||
.filter-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px dashed var(--el-border-color-lighter);
|
||||
|
||||
.latest-appointment-range {
|
||||
width: 260px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.latest-appointment-channel {
|
||||
width: 170px;
|
||||
}
|
||||
}
|
||||
|
||||
.list-card {
|
||||
@@ -2363,6 +2470,13 @@ onUnmounted(() => {
|
||||
font-size: 13px;
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
|
||||
.apt-latest-channel {
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
line-height: 1.35;
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.status-confirmed {
|
||||
|
||||
@@ -28,8 +28,10 @@ use app\common\model\tcm\CallRecord;
|
||||
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\lists\ListsSearchInterface;
|
||||
use app\common\lists\Traits\HasDataScopeFilter;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 中医辨房病因诊单列表
|
||||
@@ -39,6 +41,10 @@ use app\common\lists\Traits\HasDataScopeFilter;
|
||||
class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
{
|
||||
use HasDataScopeFilter;
|
||||
|
||||
/** 最近挂号筛选只统计这些有效状态:已预约、已完成、已过号 */
|
||||
private const EFFECTIVE_APPOINTMENT_STATUSES = [1, 3, 4];
|
||||
|
||||
/**
|
||||
* @notes 设置搜索条件
|
||||
* @return array
|
||||
@@ -133,6 +139,8 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
$query->whereExists("SELECT 1 FROM {$aptTbl} apt WHERE apt.patient_id = {$diagTbl}.id AND apt.status = 3");
|
||||
}
|
||||
|
||||
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
||||
|
||||
$this->applyPendingAssignBusinessOrderMonthFilter($query);
|
||||
|
||||
// 仅已开方(待分配+关键词检索时不限制)
|
||||
@@ -210,6 +218,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
->order('appointment_time', 'asc')
|
||||
->order('id', 'asc');
|
||||
$appointments = $subQuery->select()->toArray();
|
||||
$latestAppointmentMap = $this->buildLatestAppointmentMap($diagnosisIds);
|
||||
|
||||
foreach ($appointments as $apt) {
|
||||
$did = (int) ($apt['patient_id'] ?? 0);
|
||||
@@ -240,6 +249,8 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
}
|
||||
// 合并到诊单列表
|
||||
foreach ($lists as &$item) {
|
||||
$latestAppointment = $latestAppointmentMap[(int) $item['id']] ?? null;
|
||||
$this->appendLatestAppointmentSummary($item, $latestAppointment);
|
||||
$aptList = $appointmentMap[(int) $item['id']] ?? [];
|
||||
if (!empty($aptList)) {
|
||||
$apt = $aptList[0];
|
||||
@@ -280,6 +291,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
}
|
||||
} else {
|
||||
foreach ($lists as &$item) {
|
||||
$this->appendLatestAppointmentSummary($item, null);
|
||||
$item['has_appointment'] = 0;
|
||||
$item['appointment_id'] = null;
|
||||
$item['appointment_status'] = 0;
|
||||
@@ -558,6 +570,8 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
$query->whereExists("SELECT 1 FROM {$aptTbl} apt WHERE apt.patient_id = {$diagTbl}.id AND apt.status = 3");
|
||||
}
|
||||
|
||||
$this->applyLatestAppointmentFilters($query, $pendingWideSearch);
|
||||
|
||||
// 仅已开方(待分配+关键词检索时不限制)
|
||||
if (!$pendingWideSearch && isset($this->params['only_has_prescription']) && (string) $this->params['only_has_prescription'] === '1') {
|
||||
$rxTbl = (new Prescription())->getTable();
|
||||
@@ -587,6 +601,204 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
return $query->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 最近一次有效挂号过滤:按 appointment_date DESC, appointment_time DESC, id DESC 取一条。
|
||||
*
|
||||
* @param mixed $query
|
||||
*/
|
||||
private function applyLatestAppointmentFilters($query, bool $pendingWideSearch): void
|
||||
{
|
||||
if ($pendingWideSearch) {
|
||||
return;
|
||||
}
|
||||
|
||||
$startDate = $this->normalizeYmd($this->params['latest_appointment_start_date'] ?? '');
|
||||
$endDate = $this->normalizeYmd($this->params['latest_appointment_end_date'] ?? '');
|
||||
$channelSource = trim((string) ($this->params['latest_appointment_channel_source'] ?? ''));
|
||||
|
||||
if ($startDate === '' && $endDate === '' && $channelSource === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$aptTbl = (new Appointment())->getTable();
|
||||
$diagTbl = (new Diagnosis())->getTable();
|
||||
$latestIdSql = $this->latestAppointmentIdSubSql($aptTbl, $diagTbl);
|
||||
$conditions = ["latest_apt.id = ({$latestIdSql})"];
|
||||
|
||||
if ($startDate !== '') {
|
||||
$conditions[] = "latest_apt.appointment_date >= '" . addslashes($startDate) . "'";
|
||||
}
|
||||
if ($endDate !== '') {
|
||||
$conditions[] = "latest_apt.appointment_date <= '" . addslashes($endDate) . "'";
|
||||
}
|
||||
if ($channelSource !== '') {
|
||||
$channelCond = $this->appointmentChannelConditionSql('latest_apt', $channelSource);
|
||||
if ($channelCond === '') {
|
||||
$query->whereRaw('0 = 1');
|
||||
|
||||
return;
|
||||
}
|
||||
$conditions[] = $channelCond;
|
||||
}
|
||||
|
||||
$query->whereExists("SELECT 1 FROM {$aptTbl} latest_apt WHERE " . implode(' AND ', $conditions));
|
||||
}
|
||||
|
||||
private function latestAppointmentIdSubSql(string $aptTbl, string $diagTbl): string
|
||||
{
|
||||
$statuses = implode(',', self::EFFECTIVE_APPOINTMENT_STATUSES);
|
||||
|
||||
return "SELECT apt_latest.id FROM {$aptTbl} apt_latest "
|
||||
. "WHERE apt_latest.patient_id = {$diagTbl}.id "
|
||||
. "AND apt_latest.status IN ({$statuses}) "
|
||||
. "ORDER BY apt_latest.appointment_date DESC, "
|
||||
. "IFNULL(NULLIF(TRIM(apt_latest.appointment_time), ''), '00:00:00') DESC, "
|
||||
. "apt_latest.id DESC LIMIT 1";
|
||||
}
|
||||
|
||||
private function appointmentChannelConditionSql(string $alias, string $channelSource): string
|
||||
{
|
||||
$cols = $this->appointmentTableFields();
|
||||
$hasChannelSource = in_array('channel_source', $cols, true);
|
||||
$hasChannels = in_array('channels', $cols, true);
|
||||
if (!$hasChannelSource && !$hasChannels) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$quoted = "'" . addslashes($channelSource) . "'";
|
||||
$parts = [];
|
||||
if ($hasChannelSource) {
|
||||
$parts[] = "{$alias}.channel_source = {$quoted}";
|
||||
}
|
||||
if ($hasChannels) {
|
||||
$parts[] = "{$alias}.channels = {$quoted}";
|
||||
if (is_numeric($channelSource)) {
|
||||
$parts[] = "{$alias}.channels = " . (int) $channelSource;
|
||||
}
|
||||
}
|
||||
|
||||
$parts = array_values(array_unique($parts));
|
||||
|
||||
return $parts === [] ? '' : '(' . implode(' OR ', $parts) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, mixed> $diagnosisIds
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function buildLatestAppointmentMap(array $diagnosisIds): array
|
||||
{
|
||||
$diagnosisIds = array_values(array_filter(array_unique(array_map('intval', $diagnosisIds)), static function (int $id): bool {
|
||||
return $id > 0;
|
||||
}));
|
||||
if ($diagnosisIds === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$cols = $this->appointmentTableFields();
|
||||
$fields = ['id', 'patient_id', 'appointment_date', 'appointment_time', 'status'];
|
||||
foreach (['channel_source', 'channel_source_detail', 'channels'] as $col) {
|
||||
if (in_array($col, $cols, true)) {
|
||||
$fields[] = $col;
|
||||
}
|
||||
}
|
||||
|
||||
$appointments = Appointment::whereIn('patient_id', $diagnosisIds)
|
||||
->whereIn('status', self::EFFECTIVE_APPOINTMENT_STATUSES)
|
||||
->field($fields)
|
||||
->order('patient_id', 'asc')
|
||||
->order('appointment_date', 'desc')
|
||||
->orderRaw("IFNULL(NULLIF(TRIM(appointment_time), ''), '00:00:00') DESC")
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$map = [];
|
||||
$channelNameByValue = DictData::where('type_value', 'channels')->column('name', 'value');
|
||||
foreach ($appointments as $appointment) {
|
||||
$diagnosisId = (int) ($appointment['patient_id'] ?? 0);
|
||||
if ($diagnosisId <= 0 || isset($map[$diagnosisId])) {
|
||||
continue;
|
||||
}
|
||||
$appointment['channel_source_desc'] = $this->appointmentChannelDesc($appointment, $channelNameByValue ?: []);
|
||||
$map[$diagnosisId] = $appointment;
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $item
|
||||
* @param array<string, mixed>|null $appointment
|
||||
*/
|
||||
private function appendLatestAppointmentSummary(array &$item, ?array $appointment): void
|
||||
{
|
||||
$item['latest_appointment_id'] = null;
|
||||
$item['latest_appointment_time_text'] = '';
|
||||
$item['latest_appointment_channel_source'] = '';
|
||||
$item['latest_appointment_channel_source_desc'] = '';
|
||||
$item['latest_appointment_channel_source_detail'] = '';
|
||||
|
||||
if ($appointment === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$timePart = (string) ($appointment['appointment_time'] ?? '');
|
||||
if (strlen($timePart) > 5) {
|
||||
$timePart = substr($timePart, 0, 5);
|
||||
}
|
||||
$rawChannel = trim((string) ($appointment['channel_source'] ?? ''));
|
||||
if ($rawChannel === '' && isset($appointment['channels']) && $appointment['channels'] !== '' && $appointment['channels'] !== null) {
|
||||
$rawChannel = trim((string) $appointment['channels']);
|
||||
}
|
||||
|
||||
$item['latest_appointment_id'] = (int) ($appointment['id'] ?? 0);
|
||||
$item['latest_appointment_time_text'] = trim((string) ($appointment['appointment_date'] ?? '') . ' ' . $timePart);
|
||||
$item['latest_appointment_channel_source'] = $rawChannel;
|
||||
$item['latest_appointment_channel_source_desc'] = (string) ($appointment['channel_source_desc'] ?? '');
|
||||
$item['latest_appointment_channel_source_detail'] = trim((string) ($appointment['channel_source_detail'] ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $appointment
|
||||
* @param array<string, string> $channelNameByValue
|
||||
*/
|
||||
private function appointmentChannelDesc(array $appointment, array $channelNameByValue): string
|
||||
{
|
||||
$srcKey = trim((string) ($appointment['channel_source'] ?? ''));
|
||||
if ($srcKey === '' && isset($appointment['channels']) && $appointment['channels'] !== '' && $appointment['channels'] !== null) {
|
||||
$srcKey = trim((string) $appointment['channels']);
|
||||
}
|
||||
if ($srcKey === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) ($channelNameByValue[$srcKey] ?? $channelNameByValue[(string) (int) $srcKey] ?? $srcKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function appointmentTableFields(): array
|
||||
{
|
||||
static $fields = null;
|
||||
if ($fields !== null) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$tblFields = Db::name('doctor_appointment')->getTableFields();
|
||||
$fields = is_array($tblFields) ? array_values(array_map('strval', $tblFields)) : [];
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
private function normalizeYmd($value): string
|
||||
{
|
||||
$date = trim((string) $value);
|
||||
|
||||
return preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) ? $date : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 待分配 Tab 且有关键词时:放宽列表条件(与 `applyDiagnosisListKeywordFilter` 判定一致)。
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user