更新
This commit is contained in:
@@ -71,6 +71,11 @@ export function appointmentAdminEdit(params: any) {
|
|||||||
return request.post({ url: '/doctor.appointment/edit', params })
|
return request.post({ url: '/doctor.appointment/edit', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量修改挂号渠道来源(与 edit 共用 doctor.appointment/edit 权限) */
|
||||||
|
export function appointmentBatchEditChannel(params: any) {
|
||||||
|
return request.post({ url: '/doctor.appointment/batchEditChannel', params })
|
||||||
|
}
|
||||||
|
|
||||||
// 获取挂号详情
|
// 获取挂号详情
|
||||||
export function appointmentDetail(params: any) {
|
export function appointmentDetail(params: any) {
|
||||||
return request.get({ url: '/doctor.appointment/detail', params })
|
return request.get({ url: '/doctor.appointment/detail', params })
|
||||||
|
|||||||
@@ -50,6 +50,22 @@
|
|||||||
<el-option label="已过号" :value="4" />
|
<el-option label="已过号" :value="4" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="渠道">
|
||||||
|
<el-select
|
||||||
|
v-model="queryParams.channel_source"
|
||||||
|
placeholder="全部"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
class="!w-[200px]"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in channelOptions"
|
||||||
|
:key="String(item.value)"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||||
<el-button @click="resetFilter">重置</el-button>
|
<el-button @click="resetFilter">重置</el-button>
|
||||||
@@ -58,7 +74,29 @@
|
|||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-card class="!border-none mt-4" shadow="never">
|
<el-card class="!border-none mt-4" shadow="never">
|
||||||
<el-table v-loading="pager.loading" :data="pager.lists" size="large" stripe>
|
<div class="flex flex-wrap items-center gap-3 mb-4">
|
||||||
|
<el-button
|
||||||
|
v-perms="['doctor.appointment/edit']"
|
||||||
|
type="primary"
|
||||||
|
:disabled="selectedRows.length === 0"
|
||||||
|
@click="openBatchChannelDialog"
|
||||||
|
>
|
||||||
|
批量修改渠道
|
||||||
|
</el-button>
|
||||||
|
<span v-if="selectedRows.length > 0" class="text-sm text-gray-500">
|
||||||
|
已选 {{ selectedRows.length }} 条
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
v-loading="pager.loading"
|
||||||
|
row-key="id"
|
||||||
|
:data="pager.lists"
|
||||||
|
size="large"
|
||||||
|
stripe
|
||||||
|
@selection-change="onSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="48" align="center" reserve-selection />
|
||||||
<el-table-column label="ID" prop="id" width="72" align="center" />
|
<el-table-column label="ID" prop="id" width="72" align="center" />
|
||||||
<el-table-column label="诊单/患者" min-width="140">
|
<el-table-column label="诊单/患者" min-width="140">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
@@ -206,13 +244,55 @@
|
|||||||
<el-button type="primary" :loading="editSaving" @click="submitEdit">保存</el-button>
|
<el-button type="primary" :loading="editSaving" @click="submitEdit">保存</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="batchChannelVisible"
|
||||||
|
title="批量修改渠道"
|
||||||
|
width="520px"
|
||||||
|
destroy-on-close
|
||||||
|
@closed="resetBatchChannelForm"
|
||||||
|
>
|
||||||
|
<p class="text-sm text-gray-600 mb-4">将对已选 {{ selectedRows.length }} 条挂号写入同一渠道来源(仅改渠道,不改其它字段)。</p>
|
||||||
|
<el-form :model="batchChannelForm" label-width="96px">
|
||||||
|
<el-form-item label="渠道来源" required>
|
||||||
|
<el-select
|
||||||
|
v-model="batchChannelForm.channel_source"
|
||||||
|
placeholder="请选择渠道来源"
|
||||||
|
filterable
|
||||||
|
class="!w-full"
|
||||||
|
@change="onBatchChannelSourceChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in channelOptions"
|
||||||
|
:key="String(item.value)"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="needsBatchChannelSourceDetail" label="自媒体补充" required>
|
||||||
|
<el-input
|
||||||
|
v-model="batchChannelForm.channel_source_detail"
|
||||||
|
maxlength="128"
|
||||||
|
show-word-limit
|
||||||
|
placeholder="请输入自媒体相关补充内容"
|
||||||
|
clearable
|
||||||
|
class="!w-full"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="batchChannelVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="batchChannelSaving" @click="submitBatchChannel">确定</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="consumerPrescriptionGuahao">
|
<script lang="ts" setup name="consumerPrescriptionGuahao">
|
||||||
import DaterangePicker from '@/components/daterange-picker/index.vue'
|
import DaterangePicker from '@/components/daterange-picker/index.vue'
|
||||||
import { getDictData } from '@/api/app'
|
import { getDictData } from '@/api/app'
|
||||||
import { appointmentAdminEdit, appointmentLists } from '@/api/doctor'
|
import { appointmentAdminEdit, appointmentBatchEditChannel, appointmentLists } from '@/api/doctor'
|
||||||
import { getAssistants } from '@/api/tcm'
|
import { getAssistants } from '@/api/tcm'
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import feedback from '@/utils/feedback'
|
import feedback from '@/utils/feedback'
|
||||||
@@ -223,7 +303,8 @@ const queryParams = reactive({
|
|||||||
patient_name: '',
|
patient_name: '',
|
||||||
doctor_name: '',
|
doctor_name: '',
|
||||||
assistant_id: undefined as number | undefined,
|
assistant_id: undefined as number | undefined,
|
||||||
status: '' as number | ''
|
status: '' as number | '',
|
||||||
|
channel_source: '' as string
|
||||||
})
|
})
|
||||||
|
|
||||||
const queryInit = {
|
const queryInit = {
|
||||||
@@ -232,7 +313,8 @@ const queryInit = {
|
|||||||
patient_name: '',
|
patient_name: '',
|
||||||
doctor_name: '',
|
doctor_name: '',
|
||||||
assistant_id: undefined as number | undefined,
|
assistant_id: undefined as number | undefined,
|
||||||
status: '' as number | ''
|
status: '' as number | '',
|
||||||
|
channel_source: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const { pager, getLists, resetPage } = usePaging({
|
const { pager, getLists, resetPage } = usePaging({
|
||||||
@@ -242,6 +324,13 @@ const { pager, getLists, resetPage } = usePaging({
|
|||||||
|
|
||||||
const assistantOptions = ref<Array<{ id: number; name: string; account?: string }>>([])
|
const assistantOptions = ref<Array<{ id: number; name: string; account?: string }>>([])
|
||||||
|
|
||||||
|
const tableRef = ref<{ clearSelection?: () => void } | null>(null)
|
||||||
|
const selectedRows = ref<Record<string, unknown>[]>([])
|
||||||
|
|
||||||
|
function onSelectionChange(rows: Record<string, unknown>[]) {
|
||||||
|
selectedRows.value = rows
|
||||||
|
}
|
||||||
|
|
||||||
/** 与诊单预约弹窗一致:这些字典 name 需填「自媒体补充」 */
|
/** 与诊单预约弹窗一致:这些字典 name 需填「自媒体补充」 */
|
||||||
const CHANNEL_NAMES_REQUIRING_SELF_MEDIA_DETAIL = new Set([
|
const CHANNEL_NAMES_REQUIRING_SELF_MEDIA_DETAIL = new Set([
|
||||||
'自媒体4H',
|
'自媒体4H',
|
||||||
@@ -266,6 +355,78 @@ const selectedChannelDictName = computed(() => {
|
|||||||
|
|
||||||
const needsChannelSourceDetail = computed(() => channelNameRequiresSelfMediaDetail(selectedChannelDictName.value))
|
const needsChannelSourceDetail = computed(() => channelNameRequiresSelfMediaDetail(selectedChannelDictName.value))
|
||||||
|
|
||||||
|
const batchSelectedChannelDictName = computed(() => {
|
||||||
|
const v = batchChannelForm.channel_source
|
||||||
|
if (v === '' || v == null) return ''
|
||||||
|
const row = channelOptions.value.find((item: { value: string }) => String(item.value) === String(v))
|
||||||
|
return row ? String(row.name ?? '').trim() : ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const needsBatchChannelSourceDetail = computed(() =>
|
||||||
|
channelNameRequiresSelfMediaDetail(batchSelectedChannelDictName.value)
|
||||||
|
)
|
||||||
|
|
||||||
|
function onBatchChannelSourceChange(val: string) {
|
||||||
|
const row = channelOptions.value.find((item: { value: string }) => String(item.value) === String(val))
|
||||||
|
const name = row ? String(row.name ?? '').trim() : ''
|
||||||
|
if (!channelNameRequiresSelfMediaDetail(name)) {
|
||||||
|
batchChannelForm.channel_source_detail = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const batchChannelVisible = ref(false)
|
||||||
|
const batchChannelSaving = ref(false)
|
||||||
|
const batchChannelForm = reactive({
|
||||||
|
channel_source: '' as string,
|
||||||
|
channel_source_detail: '' as string
|
||||||
|
})
|
||||||
|
|
||||||
|
function openBatchChannelDialog() {
|
||||||
|
if (selectedRows.value.length === 0) {
|
||||||
|
feedback.msgWarning('请先勾选挂号记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
batchChannelForm.channel_source = ''
|
||||||
|
batchChannelForm.channel_source_detail = ''
|
||||||
|
batchChannelVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetBatchChannelForm() {
|
||||||
|
batchChannelForm.channel_source = ''
|
||||||
|
batchChannelForm.channel_source_detail = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitBatchChannel() {
|
||||||
|
if (selectedRows.value.length === 0) {
|
||||||
|
feedback.msgWarning('请先勾选挂号记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!batchChannelForm.channel_source) {
|
||||||
|
feedback.msgError('请选择渠道来源')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (needsBatchChannelSourceDetail.value && !batchChannelForm.channel_source_detail.trim()) {
|
||||||
|
feedback.msgError('请填写自媒体补充说明')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
batchChannelSaving.value = true
|
||||||
|
try {
|
||||||
|
const ids = selectedRows.value.map((r) => Number(r.id))
|
||||||
|
await appointmentBatchEditChannel({
|
||||||
|
ids,
|
||||||
|
channel_source: batchChannelForm.channel_source,
|
||||||
|
channel_source_detail: batchChannelForm.channel_source_detail.trim()
|
||||||
|
})
|
||||||
|
feedback.msgSuccess('批量修改成功')
|
||||||
|
batchChannelVisible.value = false
|
||||||
|
tableRef.value?.clearSelection?.()
|
||||||
|
selectedRows.value = []
|
||||||
|
getLists()
|
||||||
|
} finally {
|
||||||
|
batchChannelSaving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onChannelSourceChange(val: string) {
|
function onChannelSourceChange(val: string) {
|
||||||
const row = channelOptions.value.find((item: { value: string }) => String(item.value) === String(val))
|
const row = channelOptions.value.find((item: { value: string }) => String(item.value) === String(val))
|
||||||
const name = row ? String(row.name ?? '').trim() : ''
|
const name = row ? String(row.name ?? '').trim() : ''
|
||||||
|
|||||||
@@ -263,6 +263,11 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item class="w-[160px]" label="服务渠道">
|
||||||
|
<el-select v-model="queryParams.service_channel" clearable placeholder="全部" class="!w-full">
|
||||||
|
<el-option label="未指派" value="0" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||||
<el-button @click="handleReset">重置</el-button>
|
<el-button @click="handleReset">重置</el-button>
|
||||||
@@ -1599,7 +1604,17 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="服务渠道">
|
<el-form-item label="服务渠道">
|
||||||
<el-input v-model="editForm.service_channel" placeholder="可选" maxlength="100" />
|
<el-select
|
||||||
|
v-model="editForm.service_channel"
|
||||||
|
class="w-full"
|
||||||
|
filterable
|
||||||
|
allow-create
|
||||||
|
default-first-option
|
||||||
|
clearable
|
||||||
|
placeholder="可选或自定义输入"
|
||||||
|
>
|
||||||
|
<el-option label="未指派" value="0" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@@ -2834,6 +2849,8 @@ const queryParams = reactive({
|
|||||||
payment_slip_audit_status: '' as number | '',
|
payment_slip_audit_status: '' as number | '',
|
||||||
/** 供货方式:甘草(已传甘草药方单号)/ 自营(无甘草单号) */
|
/** 供货方式:甘草(已传甘草药方单号)/ 自营(无甘草单号) */
|
||||||
supply_mode: '' as '' | 'gancao' | 'self',
|
supply_mode: '' as '' | 'gancao' | 'self',
|
||||||
|
/** 服务渠道:'' 不限;'0' 未指派(库内 '' 或 '0') */
|
||||||
|
service_channel: '' as '' | '0',
|
||||||
/** 列表排除履约已取消(4):重点看板「待处方审核」等用 */
|
/** 列表排除履约已取消(4):重点看板「待处方审核」等用 */
|
||||||
exclude_fulfillment_cancelled: 0 as number
|
exclude_fulfillment_cancelled: 0 as number
|
||||||
})
|
})
|
||||||
@@ -2950,6 +2967,12 @@ function normalizePrescriptionOrderListQuery(params: Record<string, unknown>): R
|
|||||||
if (!String(p.patient_keyword || '').trim()) delete p.patient_keyword
|
if (!String(p.patient_keyword || '').trim()) delete p.patient_keyword
|
||||||
if (!String(p.express_keyword || '').trim()) delete p.express_keyword
|
if (!String(p.express_keyword || '').trim()) delete p.express_keyword
|
||||||
if (!p.express_company || p.express_company === '') delete p.express_company
|
if (!p.express_company || p.express_company === '') delete p.express_company
|
||||||
|
if (p.service_channel === '' || p.service_channel === undefined || p.service_channel === null) {
|
||||||
|
delete p.service_channel
|
||||||
|
} else {
|
||||||
|
p.service_channel = String(p.service_channel).trim()
|
||||||
|
if (p.service_channel === '') delete p.service_channel
|
||||||
|
}
|
||||||
if (Number(p.exclude_fulfillment_cancelled) !== 1) delete p.exclude_fulfillment_cancelled
|
if (Number(p.exclude_fulfillment_cancelled) !== 1) delete p.exclude_fulfillment_cancelled
|
||||||
if (!String(p.start_time || '').trim() || !String(p.end_time || '').trim()) {
|
if (!String(p.start_time || '').trim() || !String(p.end_time || '').trim()) {
|
||||||
delete p.start_time
|
delete p.start_time
|
||||||
@@ -3167,6 +3190,7 @@ function handleReset() {
|
|||||||
queryParams.prescription_audit_status = ''
|
queryParams.prescription_audit_status = ''
|
||||||
queryParams.payment_slip_audit_status = ''
|
queryParams.payment_slip_audit_status = ''
|
||||||
queryParams.supply_mode = ''
|
queryParams.supply_mode = ''
|
||||||
|
queryParams.service_channel = ''
|
||||||
queryParams.exclude_fulfillment_cancelled = 0
|
queryParams.exclude_fulfillment_cancelled = 0
|
||||||
resetParams()
|
resetParams()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,22 @@ class AppointmentController extends BaseAdminController
|
|||||||
return $this->success('保存成功');
|
return $this->success('保存成功');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量修改挂号渠道来源(消费者处方-挂号列表) */
|
||||||
|
public function batchEditChannel()
|
||||||
|
{
|
||||||
|
$params = (new AppointmentValidate())->post()->goCheck('batchEditChannel');
|
||||||
|
$post = $this->request->post();
|
||||||
|
if (\array_key_exists('channel_source_detail', $post)) {
|
||||||
|
$params['channel_source_detail'] = $post['channel_source_detail'];
|
||||||
|
}
|
||||||
|
$result = AppointmentLogic::adminBatchEditChannel($params, $this->adminId, $this->adminInfo);
|
||||||
|
if ($result === false) {
|
||||||
|
return $this->fail(AppointmentLogic::getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success((string) ($result['msg'] ?? '操作成功'), $result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notes 预约详情
|
* @notes 预约详情
|
||||||
* @return \think\response\Json
|
* @return \think\response\Json
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ class AuthMiddleware
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 挂号列表批量改渠道:与单条编辑同一数据域,复用 doctor.appointment/edit
|
||||||
|
if ($accessUri === 'doctor.appointment/batcheditchannel'
|
||||||
|
&& in_array('doctor.appointment/edit', $adminUris, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use app\common\model\dict\DictData;
|
|||||||
use app\common\lists\ListsExtendInterface;
|
use app\common\lists\ListsExtendInterface;
|
||||||
use app\common\lists\ListsSearchInterface;
|
use app\common\lists\ListsSearchInterface;
|
||||||
use app\common\lists\Traits\HasDataScopeFilter;
|
use app\common\lists\Traits\HasDataScopeFilter;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 医生预约列表
|
* 医生预约列表
|
||||||
@@ -74,6 +75,46 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道筛选:与 AppointmentLogic 一致,兼容仅有 channel_source、仅有 channels、或两者皆有的表结构
|
||||||
|
*
|
||||||
|
* @param mixed $query
|
||||||
|
*/
|
||||||
|
private function applyChannelSourceFilter($query, string $chFilter): void
|
||||||
|
{
|
||||||
|
if ($chFilter === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$tblFields = Db::name('doctor_appointment')->getTableFields();
|
||||||
|
$cols = \is_array($tblFields) ? $tblFields : [];
|
||||||
|
$hasChannelSource = \in_array('channel_source', $cols, true);
|
||||||
|
$hasChannels = \in_array('channels', $cols, true);
|
||||||
|
if (!$hasChannelSource && !$hasChannels) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->where(function ($q) use ($chFilter, $hasChannelSource, $hasChannels): void {
|
||||||
|
if ($hasChannelSource && $hasChannels) {
|
||||||
|
$q->where('a.channel_source', '=', $chFilter)
|
||||||
|
->whereOr('a.channels', '=', $chFilter);
|
||||||
|
if (is_numeric($chFilter)) {
|
||||||
|
$q->whereOr('a.channels', '=', (int) $chFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($hasChannelSource) {
|
||||||
|
$q->where('a.channel_source', '=', $chFilter);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$q->where('a.channels', '=', $chFilter);
|
||||||
|
if (is_numeric($chFilter)) {
|
||||||
|
$q->whereOr('a.channels', '=', (int) $chFilter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notes 设置搜索条件
|
* @notes 设置搜索条件
|
||||||
* @return array
|
* @return array
|
||||||
@@ -107,6 +148,9 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
$this->searchWhere[] = ['a.status', '=', $this->params['status']];
|
$this->searchWhere[] = ['a.status', '=', $this->params['status']];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 渠道字典 value(命中 channel_source 或 legacy channels)
|
||||||
|
$chFilter = isset($this->params['channel_source']) ? trim((string) $this->params['channel_source']) : '';
|
||||||
|
|
||||||
// 处理日期范围搜索
|
// 处理日期范围搜索
|
||||||
if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) {
|
if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) {
|
||||||
$this->searchWhere[] = ['a.appointment_date', 'between', [$this->params['start_date'], $this->params['end_date']]];
|
$this->searchWhere[] = ['a.appointment_date', 'between', [$this->params['start_date'], $this->params['end_date']]];
|
||||||
@@ -147,6 +191,8 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
|
|
||||||
$this->applyAssistantIdFilter($query);
|
$this->applyAssistantIdFilter($query);
|
||||||
|
|
||||||
|
$this->applyChannelSourceFilter($query, $chFilter);
|
||||||
|
|
||||||
// 是否确认诊单:1=已确认 0=未确认
|
// 是否确认诊单:1=已确认 0=未确认
|
||||||
if (isset($this->params['diagnosis_confirmed']) && $this->params['diagnosis_confirmed'] !== '') {
|
if (isset($this->params['diagnosis_confirmed']) && $this->params['diagnosis_confirmed'] !== '') {
|
||||||
$confirmed = (int)$this->params['diagnosis_confirmed'];
|
$confirmed = (int)$this->params['diagnosis_confirmed'];
|
||||||
@@ -308,6 +354,7 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
if ($applyStatusFilter && isset($this->params['status']) && $this->params['status'] !== '') {
|
if ($applyStatusFilter && isset($this->params['status']) && $this->params['status'] !== '') {
|
||||||
$query->where('a.status', '=', $this->params['status']);
|
$query->where('a.status', '=', $this->params['status']);
|
||||||
}
|
}
|
||||||
|
$chFilter = isset($this->params['channel_source']) ? trim((string) $this->params['channel_source']) : '';
|
||||||
if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) {
|
if (!empty($this->params['start_date']) && !empty($this->params['end_date'])) {
|
||||||
$query->whereBetween('a.appointment_date', [$this->params['start_date'], $this->params['end_date']]);
|
$query->whereBetween('a.appointment_date', [$this->params['start_date'], $this->params['end_date']]);
|
||||||
} elseif (!empty($this->params['start_date'])) {
|
} elseif (!empty($this->params['start_date'])) {
|
||||||
@@ -326,6 +373,8 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
|
|
||||||
$this->applyAssistantIdFilter($query);
|
$this->applyAssistantIdFilter($query);
|
||||||
|
|
||||||
|
$this->applyChannelSourceFilter($query, $chFilter);
|
||||||
|
|
||||||
if ((int) ($this->params['exclude_cancelled'] ?? 0) === 1) {
|
if ((int) ($this->params['exclude_cancelled'] ?? 0) === 1) {
|
||||||
$sf = $this->params['status'] ?? '';
|
$sf = $this->params['status'] ?? '';
|
||||||
if ($sf === '' || (int) $sf !== 2) {
|
if ($sf === '' || (int) $sf !== 2) {
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
$this->applyPatientIdFilter($query);
|
$this->applyPatientIdFilter($query);
|
||||||
$this->applyExpressCompanyFilter($query);
|
$this->applyExpressCompanyFilter($query);
|
||||||
$this->applyExpressKeywordFilter($query);
|
$this->applyExpressKeywordFilter($query);
|
||||||
|
$this->applyServiceChannelFilter($query);
|
||||||
$this->applySupplyModeFilter($query);
|
$this->applySupplyModeFilter($query);
|
||||||
if (!$this->shouldBypassListVisibilityForDiagnosisEdit()) {
|
if (!$this->shouldBypassListVisibilityForDiagnosisEdit()) {
|
||||||
$this->applyCreatorOrOwnPrescriptionVisibility($query);
|
$this->applyCreatorOrOwnPrescriptionVisibility($query);
|
||||||
@@ -200,6 +201,24 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
$query->whereRaw("(($po) OR ($et))");
|
$query->whereRaw("(($po) OR ($et))");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务渠道:未指派传 service_channel=0 时命中「空串」或「0」(varchar)
|
||||||
|
*/
|
||||||
|
private function applyServiceChannelFilter(Query $query): void
|
||||||
|
{
|
||||||
|
$raw = $this->params['service_channel'] ?? '';
|
||||||
|
if ($raw === '' || $raw === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$v = trim((string) $raw);
|
||||||
|
if ($v === '0') {
|
||||||
|
$query->whereRaw("(TRIM(IFNULL(`service_channel`,'')) = '' OR `service_channel` = '0')");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$query->where('service_channel', '=', $v);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 供货方式:甘草(已上传甘草药方单号)/ 自营(无甘草单号,走药房直发等)
|
* 供货方式:甘草(已上传甘草药方单号)/ 自营(无甘草单号,走药房直发等)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1106,6 +1106,130 @@ class AppointmentLogic extends BaseLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台批量修改挂号渠道(仅渠道号与可选补充)
|
||||||
|
*
|
||||||
|
* @param array<string, mixed> $params
|
||||||
|
* @return array{updated:int}|false
|
||||||
|
*/
|
||||||
|
public static function adminBatchEditChannel(array $params, int $adminId, array $adminInfo)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$idsRaw = $params['ids'] ?? [];
|
||||||
|
if (!\is_array($idsRaw) || $idsRaw === []) {
|
||||||
|
self::setError('请选择要修改的挂号记录');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = [];
|
||||||
|
foreach ($idsRaw as $raw) {
|
||||||
|
$id = (int) $raw;
|
||||||
|
if ($id > 0) {
|
||||||
|
$ids[$id] = $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ids = array_values($ids);
|
||||||
|
$maxBatch = 300;
|
||||||
|
if (\count($ids) === 0) {
|
||||||
|
self::setError('预约ID无效');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (\count($ids) > $maxBatch) {
|
||||||
|
self::setError('单次最多修改 ' . $maxBatch . ' 条挂号');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$chSrc = trim((string) ($params['channel_source'] ?? ''));
|
||||||
|
if ($chSrc === '') {
|
||||||
|
self::setError('请选择渠道来源');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$chDetail = isset($params['channel_source_detail']) ? trim((string) $params['channel_source_detail']) : '';
|
||||||
|
$channelDictName = trim((string) (DictData::where('type_value', 'channels')
|
||||||
|
->where('value', $chSrc)
|
||||||
|
->value('name') ?? ''));
|
||||||
|
if ($channelDictName !== '' && self::channelDictNameRequiresSourceDetail($channelDictName)) {
|
||||||
|
if ($chDetail === '') {
|
||||||
|
self::setError('请填写自媒体渠道补充信息');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mb_strlen($chDetail) > 128) {
|
||||||
|
self::setError('渠道补充说明过长');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tblFields = Db::name('doctor_appointment')->getTableFields();
|
||||||
|
$cols = \is_array($tblFields) ? $tblFields : [];
|
||||||
|
$channelErr = self::assertAppointmentChannelWritable($cols, $chSrc);
|
||||||
|
if ($channelErr !== null) {
|
||||||
|
self::setError($channelErr);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Db::startTrans();
|
||||||
|
|
||||||
|
$updated = 0;
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$appointment = Appointment::findOrEmpty((int) $id);
|
||||||
|
if ($appointment->isEmpty()) {
|
||||||
|
Db::rollback();
|
||||||
|
self::setError('预约记录不存在(ID ' . $id . ')');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$diag = Diagnosis::where('id', (int) $appointment->patient_id)->whereNull('delete_time')->find();
|
||||||
|
|
||||||
|
if (!self::appointmentRowManageableByAdmin($appointment, $diag ?: null, $adminId, $adminInfo)) {
|
||||||
|
Db::rollback();
|
||||||
|
self::setError('无权限修改挂号 #' . $id);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$saveData = [
|
||||||
|
'update_time' => time(),
|
||||||
|
];
|
||||||
|
self::mergeAppointmentChannelIntoRow($saveData, $cols, $chSrc, $chDetail);
|
||||||
|
|
||||||
|
$saveData = self::filterAppointmentRowByExistingColumns($saveData, $cols);
|
||||||
|
|
||||||
|
Db::name('doctor_appointment')->where('id', $id)->update($saveData);
|
||||||
|
|
||||||
|
$patientId = (int) $appointment->patient_id;
|
||||||
|
self::appendDiagnosisGuahaoLog(
|
||||||
|
$patientId,
|
||||||
|
(int) $id,
|
||||||
|
$adminId,
|
||||||
|
$adminInfo,
|
||||||
|
'admin_batch_channel',
|
||||||
|
sprintf('批量修改挂号 #%d:渠道设为 %s', $id, $chSrc !== '' ? $chSrc : '—')
|
||||||
|
);
|
||||||
|
++$updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
Db::commit();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'updated' => $updated,
|
||||||
|
'msg' => sprintf('已更新 %d 条挂号渠道', $updated),
|
||||||
|
];
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Db::rollback();
|
||||||
|
self::setError($e->getMessage());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 诊单列表维度:记录谁在后台发起挂号 / 取消挂号(写入失败不影响主流程)
|
* 诊单列表维度:记录谁在后台发起挂号 / 取消挂号(写入失败不影响主流程)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class AppointmentValidate extends BaseValidate
|
|||||||
'remark' => 'max:500',
|
'remark' => 'max:500',
|
||||||
'channel_source' => 'require',
|
'channel_source' => 'require',
|
||||||
'channel_source_detail' => 'max:128',
|
'channel_source_detail' => 'max:128',
|
||||||
|
'ids' => 'require|array',
|
||||||
'note_id' => 'require|integer',
|
'note_id' => 'require|integer',
|
||||||
'image_type' => 'require|in:tongue_images,report_files',
|
'image_type' => 'require|in:tongue_images,report_files',
|
||||||
'image_path' => 'require',
|
'image_path' => 'require',
|
||||||
@@ -51,6 +52,7 @@ class AppointmentValidate extends BaseValidate
|
|||||||
'assistant_id' => '医助',
|
'assistant_id' => '医助',
|
||||||
'channel_source' => '渠道来源',
|
'channel_source' => '渠道来源',
|
||||||
'channel_source_detail' => '渠道补充说明',
|
'channel_source_detail' => '渠道补充说明',
|
||||||
|
'ids' => '预约ID列表',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,4 +150,10 @@ class AppointmentValidate extends BaseValidate
|
|||||||
'channel_source_detail',
|
'channel_source_detail',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 批量修改挂号渠道(权限同 doctor.appointment/edit) */
|
||||||
|
public function sceneBatchEditChannel()
|
||||||
|
{
|
||||||
|
return $this->only(['ids', 'channel_source', 'channel_source_detail']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user