更新
This commit is contained in:
@@ -61,6 +61,14 @@ export function tcmDiagnosisDetail(params: any) {
|
|||||||
return request.get({ url: '/tcm.diagnosis/detail', params })
|
return request.get({ url: '/tcm.diagnosis/detail', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 设置复诊接诊率统计起始偏移(统计诊次=实单序号+偏移;1=二诊起,2=三诊起) */
|
||||||
|
export function tcmDiagnosisSetRevisitSlotStartOffset(params: {
|
||||||
|
id: number
|
||||||
|
revisit_slot_start_offset: number
|
||||||
|
}) {
|
||||||
|
return request.post({ url: '/tcm.diagnosis/setRevisitSlotStartOffset', params })
|
||||||
|
}
|
||||||
|
|
||||||
/** 诊单挂号 / 取消挂号 操作日志 */
|
/** 诊单挂号 / 取消挂号 操作日志 */
|
||||||
export function tcmDiagnosisGuahaoLogList(params: { id: number }) {
|
export function tcmDiagnosisGuahaoLogList(params: { id: number }) {
|
||||||
return request.get({ url: '/tcm.diagnosis/guahaoLogList', params })
|
return request.get({ url: '/tcm.diagnosis/guahaoLogList', params })
|
||||||
|
|||||||
@@ -1290,11 +1290,15 @@ const detailFullAddress = computed(() => {
|
|||||||
const servicePackageOptions = ref<ServicePackageOption[]>([])
|
const servicePackageOptions = ref<ServicePackageOption[]>([])
|
||||||
|
|
||||||
async function loadServicePackageOptions() {
|
async function loadServicePackageOptions() {
|
||||||
|
if (servicePackageOptions.value.length > 0) return
|
||||||
try {
|
try {
|
||||||
const data: any = await getDictData({ type: 'server_order' })
|
const data: any = await getDictData({ type: 'server_order' })
|
||||||
servicePackageOptions.value = normalizeServicePackageOptions(data?.server_order)
|
const opts = normalizeServicePackageOptions(data?.server_order)
|
||||||
|
if (opts.length > 0) {
|
||||||
|
servicePackageOptions.value = opts
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
servicePackageOptions.value = []
|
/* 请求被同参数请求取消或失败时保留现值,open() 时会重试 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1639,6 +1643,8 @@ async function updateJdLogistics() {
|
|||||||
|
|
||||||
// ─── 打开 / 刷新 ───
|
// ─── 打开 / 刷新 ───
|
||||||
async function open(id: number) {
|
async function open(id: number) {
|
||||||
|
// 页面级同参数字典请求会取消抽屉挂载时的那次(axios 去重取消),打开时兜底重试
|
||||||
|
void loadServicePackageOptions()
|
||||||
// 显式彻底清空缓存,防止前一次弹窗的数据残留
|
// 显式彻底清空缓存,防止前一次弹窗的数据残留
|
||||||
detailData.value = null
|
detailData.value = null
|
||||||
detailUnlinkedPayOrders.value = []
|
detailUnlinkedPayOrders.value = []
|
||||||
|
|||||||
@@ -298,7 +298,7 @@
|
|||||||
:fetch-fun="prescriptionOrderExport"
|
:fetch-fun="prescriptionOrderExport"
|
||||||
:params="prescriptionOrderExportParams"
|
:params="prescriptionOrderExportParams"
|
||||||
:page-size="pager.size"
|
:page-size="pager.size"
|
||||||
export-hint="导出范围与上方筛选一致(履约状态、创建时间及其他条件均会生效)。含「自媒体渠道(挂号渠道来源)」:优先取该单关联处方登记的挂号;无则诊单下同患者挂号取 id 最大的一条(与前台挂号选择的记录一致);业绩侧栏带渠道筛选导出时与同页列表高亮挂号同源。「服务套餐」按字典 server_order 解析展示。「处方」导出主方/辅方药材明细;「主方/辅方服用方式、天数」与详情侧栏、处方笺同口径(天数优先取订单 medication_days,缺省回退处方 usage_days / 辅方 aux_usage)。「关联收款记录」与详情侧栏同源(已支付/已退款/待审核),每笔两行展示(摘要行+明细行),多笔空行分隔,单元格自动换行。「签收日期」与详情/业绩看板同源,仅读物流库(轨迹/签收时间):导出不再实时查快递100,速度只取决于数据库;签收时间由 `tcm:backfill-sign-time` 命令与物流自动更新定时任务落库,刚发货尚未同步的单子会暂时为空,待下次回填/定时任务刷新后显示。"
|
export-hint="导出范围与上方筛选一致(履约状态、创建时间及其他条件均会生效)。含「自媒体渠道(挂号渠道来源)」:优先取该单关联处方登记的挂号;无则诊单下同患者挂号取 id 最大的一条(与前台挂号选择的记录一致);业绩侧栏带渠道筛选导出时与同页列表高亮挂号同源。「服务套餐」按字典 server_order 解析展示。「处方」导出主方/辅方药材明细;「主方/辅方服用方式、天数」与详情侧栏同口径(主方/辅方天数分别取处方 usage_days、辅方 aux_usage.usage_days;「天数」列为订单 medication_days)。「关联收款记录」与详情侧栏同源(已支付/已退款/待审核),每笔两行展示(摘要行+明细行),多笔空行分隔,单元格自动换行。「签收日期」与详情/业绩看板同源,仅读物流库(轨迹/签收时间):导出不再实时查快递100,速度只取决于数据库;签收时间由 `tcm:backfill-sign-time` 命令与物流自动更新定时任务落库,刚发货尚未同步的单子会暂时为空,待下次回填/定时任务刷新后显示。"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<b>当月被指派总数</b>:当月内诊单被指派给医助(按指派操作时间落月,<b>剔除勾选「继承」的指派</b>)的诊单数,按「医助 × 诊单」去重;部门行 / 合计行按诊单去重。
|
<b>当月被指派总数</b>:当月内诊单被指派给医助(按指派操作时间落月,<b>剔除勾选「继承」的指派</b>)的诊单数,按「医助 × 诊单」去重;部门行 / 合计行按诊单去重。
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<b>诊次(第 N 次下单)</b>:患者(诊单)名下计入业绩的业务订单(剔除已取消 / 拒收 / 退款)按下单时间升序的全局序号,<b>跨月累计不重置</b>——如 5 月指派后旗下成交 4 单为二诊~五诊,下月再成交即为六诊。
|
<b>诊次(第 N 次下单)</b>:患者(诊单)名下计入业绩的业务订单(剔除已取消 / 拒收 / 退款)按下单时间升序编号为「实单序号」,<b>统计诊次 = 实单序号 + 诊单偏移</b>(默认偏移 1 → 第 1 笔实单为二诊;偏移 2 → 第 1 笔实单为三诊,5 笔实单等价七诊)。诊次<b>跨月累计不重置</b>。诊单可在「业务订单」tab 配置偏移量。
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<b>当月 N 诊单数</b>:当月内下单且诊次为 N 的订单数,归属下单时点<b>持有该患者的医助</b>(指派可在往月;释放后不再归属;「继承」指派会转移持有人但不计被指派数)。
|
<b>当月 N 诊单数</b>:当月内下单且诊次为 N 的订单数,归属下单时点<b>持有该患者的医助</b>(指派可在往月;释放后不再归属;「继承」指派会转移持有人但不计被指派数)。
|
||||||
|
|||||||
@@ -83,6 +83,23 @@
|
|||||||
<el-radio-button value="0">未确认</el-radio-button>
|
<el-radio-button value="0">未确认</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="filter-group">
|
||||||
|
<span class="filter-label">部门</span>
|
||||||
|
<el-tree-select
|
||||||
|
v-model="formData.assistant_dept_id"
|
||||||
|
:data="departmentTreeRaw"
|
||||||
|
class="filter-dept-select"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
check-strictly
|
||||||
|
:default-expand-all="true"
|
||||||
|
node-key="id"
|
||||||
|
size="small"
|
||||||
|
:props="assistantDeptTreeProps"
|
||||||
|
placeholder="选父级含子级"
|
||||||
|
@change="handleAssistantDeptChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@@ -542,6 +559,7 @@
|
|||||||
import { usePaging } from '@/hooks/usePaging'
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import { defineAsyncComponent, onMounted, onUnmounted, watch } from 'vue'
|
import { defineAsyncComponent, onMounted, onUnmounted, watch } from 'vue'
|
||||||
import { appointmentLists, cancelAppointment, completeAppointment, appointmentDetail } from '@/api/doctor'
|
import { appointmentLists, cancelAppointment, completeAppointment, appointmentDetail } from '@/api/doctor'
|
||||||
|
import { deptAll } from '@/api/org/department'
|
||||||
import { getCallSignature, generateMiniProgramQrcode, tcmDiagnosisDetail, prescriptionGetByAppointment } from '@/api/tcm'
|
import { getCallSignature, generateMiniProgramQrcode, tcmDiagnosisDetail, prescriptionGetByAppointment } from '@/api/tcm'
|
||||||
import { getDictData } from '@/api/app'
|
import { getDictData } from '@/api/app'
|
||||||
import { addDoctorNote } from '@/api/patient'
|
import { addDoctorNote } from '@/api/patient'
|
||||||
@@ -603,10 +621,19 @@ const formData = reactive({
|
|||||||
end_date: '',
|
end_date: '',
|
||||||
date_preset: 'today' as '' | 'yesterday' | 'day_before' | 'today' | 'tomorrow' | 'day_after',
|
date_preset: 'today' as '' | 'yesterday' | 'day_before' | 'today' | 'tomorrow' | 'day_after',
|
||||||
diagnosis_confirmed: '' as '' | '0' | '1', // ''=全部 1=已确认 0=未确认
|
diagnosis_confirmed: '' as '' | '0' | '1', // ''=全部 1=已确认 0=未确认
|
||||||
|
/** 接诊医生 / 诊单医助 / 挂号医助所属部门(选父级含子级) */
|
||||||
|
assistant_dept_id: '' as number | '',
|
||||||
/** 为 1 时后端 extend 返回各状态数量,避免额外 4 次列表请求 */
|
/** 为 1 时后端 extend 返回各状态数量,避免额外 4 次列表请求 */
|
||||||
include_status_counts: 0 as 0 | 1
|
include_status_counts: 0 as 0 | 1
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const departmentTreeRaw = ref<unknown[]>([])
|
||||||
|
const assistantDeptTreeProps = {
|
||||||
|
value: 'id',
|
||||||
|
label: 'name',
|
||||||
|
children: 'children'
|
||||||
|
}
|
||||||
|
|
||||||
const activeTab = ref('1')
|
const activeTab = ref('1')
|
||||||
const dateCustomVisible = ref(false)
|
const dateCustomVisible = ref(false)
|
||||||
const statusCount = ref<Record<number, number>>({
|
const statusCount = ref<Record<number, number>>({
|
||||||
@@ -721,6 +748,12 @@ const handleDiagnosisConfirmedChange = () => {
|
|||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 部门筛选变更
|
||||||
|
const handleAssistantDeptChange = () => {
|
||||||
|
pager.page = 1
|
||||||
|
loadData()
|
||||||
|
}
|
||||||
|
|
||||||
// 快捷日期变更
|
// 快捷日期变更
|
||||||
const handleDatePresetChange = (val: string | number | boolean | undefined) => {
|
const handleDatePresetChange = (val: string | number | boolean | undefined) => {
|
||||||
const v = String(val || '')
|
const v = String(val || '')
|
||||||
@@ -770,6 +803,7 @@ const handleReset = () => {
|
|||||||
formData.doctor_name = ''
|
formData.doctor_name = ''
|
||||||
formData.date_preset = 'today'
|
formData.date_preset = 'today'
|
||||||
formData.diagnosis_confirmed = ''
|
formData.diagnosis_confirmed = ''
|
||||||
|
formData.assistant_dept_id = ''
|
||||||
const t = new Date()
|
const t = new Date()
|
||||||
const p = (n: number) => String(n).padStart(2, '0')
|
const p = (n: number) => String(n).padStart(2, '0')
|
||||||
formData.start_date = `${t.getFullYear()}-${p(t.getMonth() + 1)}-${p(t.getDate())}`
|
formData.start_date = `${t.getFullYear()}-${p(t.getMonth() + 1)}-${p(t.getDate())}`
|
||||||
@@ -1099,7 +1133,13 @@ formData.start_date = `${_today.getFullYear()}-${_pad(_today.getMonth() + 1)}-${
|
|||||||
formData.end_date = formData.start_date
|
formData.end_date = formData.start_date
|
||||||
formData.status = 1
|
formData.status = 1
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const deptTree = await deptAll()
|
||||||
|
departmentTreeRaw.value = Array.isArray(deptTree) ? deptTree : []
|
||||||
|
} catch {
|
||||||
|
departmentTreeRaw.value = []
|
||||||
|
}
|
||||||
loadData()
|
loadData()
|
||||||
listPollTimer = setInterval(() => {
|
listPollTimer = setInterval(() => {
|
||||||
loadData({ silent: true })
|
loadData({ silent: true })
|
||||||
@@ -1228,6 +1268,10 @@ onUnmounted(() => {
|
|||||||
padding: 6px 14px;
|
padding: 6px 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-dept-select {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,43 @@
|
|||||||
<el-empty description="当前诊单未携带患者ID,无法列出业务订单" />
|
<el-empty description="当前诊单未携带患者ID,无法列出业务订单" />
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<div v-if="diagnosisId > 0" class="po-revisit-offset-bar mb-3">
|
||||||
|
<div class="po-revisit-offset-bar__main">
|
||||||
|
<span class="text-sm text-gray-600">复诊统计起始偏移</span>
|
||||||
|
<el-tooltip placement="top">
|
||||||
|
<template #content>
|
||||||
|
<div class="max-w-xs leading-relaxed">
|
||||||
|
在实单诊次序号上叠加偏移量。设为 1(默认):第 1 笔实单计为二诊;设为 2:第 1 笔实单计为三诊——若有 5 笔实单,则统计上相当于计至七诊(5+2)。
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-icon class="text-gray-400 align-middle ml-1"><QuestionFilled /></el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-input-number
|
||||||
|
v-model="revisitSlotStartOffset"
|
||||||
|
v-perms="['tcm.diagnosis/setRevisitSlotStartOffset']"
|
||||||
|
:min="1"
|
||||||
|
:max="20"
|
||||||
|
:step="1"
|
||||||
|
controls-position="right"
|
||||||
|
class="w-[120px] ml-3"
|
||||||
|
:disabled="offsetSaving"
|
||||||
|
/>
|
||||||
|
<span class="text-xs text-gray-500 ml-2">
|
||||||
|
第 1 笔实单计为{{ visitSlotStartLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
v-perms="['tcm.diagnosis/setRevisitSlotStartOffset']"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
:loading="offsetSaving"
|
||||||
|
:disabled="!offsetDirty"
|
||||||
|
@click="saveRevisitSlotStartOffset"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="pager.loading"
|
v-loading="pager.loading"
|
||||||
:data="pager.lists"
|
:data="pager.lists"
|
||||||
@@ -12,6 +49,23 @@
|
|||||||
empty-text="暂无业务订单"
|
empty-text="暂无业务订单"
|
||||||
>
|
>
|
||||||
<el-table-column label="订单编号" prop="order_no" min-width="200" show-overflow-tooltip />
|
<el-table-column label="订单编号" prop="order_no" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column label="全局诊次" width="96" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.global_visit_seq">{{ row.global_visit_seq }}诊</span>
|
||||||
|
<span v-else class="text-gray-400">—</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="计入统计" width="96" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag
|
||||||
|
v-if="row.counts_for_revisit_rate"
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
effect="plain"
|
||||||
|
>是</el-tag>
|
||||||
|
<el-tag v-else type="info" size="small" effect="plain">否</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="金额" width="120" align="right">
|
<el-table-column label="金额" width="120" align="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span class="text-red-500 font-semibold">¥{{ formatAmount(row.amount) }}</span>
|
<span class="text-red-500 font-semibold">¥{{ formatAmount(row.amount) }}</span>
|
||||||
@@ -63,9 +117,11 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, reactive, ref, watch } from 'vue'
|
import { computed, reactive, ref, watch } from 'vue'
|
||||||
|
import { QuestionFilled } from '@element-plus/icons-vue'
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import { prescriptionOrderLists } from '@/api/tcm'
|
import { prescriptionOrderLists, tcmDiagnosisDetail, tcmDiagnosisSetRevisitSlotStartOffset } from '@/api/tcm'
|
||||||
import PrescriptionOrderDetailDrawer from '@/views/consumer/prescription/components/PrescriptionOrderDetailDrawer.vue'
|
import PrescriptionOrderDetailDrawer from '@/views/consumer/prescription/components/PrescriptionOrderDetailDrawer.vue'
|
||||||
|
import feedback from '@/utils/feedback'
|
||||||
import {
|
import {
|
||||||
formatTime,
|
formatTime,
|
||||||
fulfillmentText,
|
fulfillmentText,
|
||||||
@@ -91,6 +147,25 @@ const { pager, getLists, resetPage } = usePaging({
|
|||||||
size: 10
|
size: 10
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const revisitSlotStartOffset = ref(1)
|
||||||
|
const savedRevisitSlotStartOffset = ref(1)
|
||||||
|
const offsetSaving = ref(false)
|
||||||
|
const offsetLoading = ref(false)
|
||||||
|
|
||||||
|
const offsetDirty = computed(
|
||||||
|
() => Number(revisitSlotStartOffset.value) !== Number(savedRevisitSlotStartOffset.value)
|
||||||
|
)
|
||||||
|
|
||||||
|
const visitSlotStartLabel = computed(() => {
|
||||||
|
const offset = Number(revisitSlotStartOffset.value) || 1
|
||||||
|
const slot = offset + 1
|
||||||
|
const cn = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
|
||||||
|
if (slot >= 2 && slot <= 10) {
|
||||||
|
return cn[slot] + '诊'
|
||||||
|
}
|
||||||
|
return `第${slot}诊`
|
||||||
|
})
|
||||||
|
|
||||||
const buildParams = () => {
|
const buildParams = () => {
|
||||||
Object.keys(queryParams).forEach((k) => delete queryParams[k])
|
Object.keys(queryParams).forEach((k) => delete queryParams[k])
|
||||||
if (props.diagnosisId > 0) {
|
if (props.diagnosisId > 0) {
|
||||||
@@ -102,6 +177,47 @@ const buildParams = () => {
|
|||||||
queryParams.scene = 'diagnosis_edit'
|
queryParams.scene = 'diagnosis_edit'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadRevisitSlotStartOffset() {
|
||||||
|
if (props.diagnosisId <= 0) return
|
||||||
|
offsetLoading.value = true
|
||||||
|
try {
|
||||||
|
const res: any = await tcmDiagnosisDetail({ id: props.diagnosisId })
|
||||||
|
const d = res?.data ?? res ?? {}
|
||||||
|
const offset = Number(d.revisit_slot_start_offset)
|
||||||
|
const val = offset >= 1 && offset <= 20 ? offset : 1
|
||||||
|
revisitSlotStartOffset.value = val
|
||||||
|
savedRevisitSlotStartOffset.value = val
|
||||||
|
} catch {
|
||||||
|
revisitSlotStartOffset.value = 1
|
||||||
|
savedRevisitSlotStartOffset.value = 1
|
||||||
|
} finally {
|
||||||
|
offsetLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveRevisitSlotStartOffset() {
|
||||||
|
if (props.diagnosisId <= 0) return
|
||||||
|
const offset = Number(revisitSlotStartOffset.value)
|
||||||
|
if (!Number.isFinite(offset) || offset < 1 || offset > 20) {
|
||||||
|
feedback.msgWarning('起始偏移须在 1~20 之间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
offsetSaving.value = true
|
||||||
|
try {
|
||||||
|
await tcmDiagnosisSetRevisitSlotStartOffset({
|
||||||
|
id: props.diagnosisId,
|
||||||
|
revisit_slot_start_offset: offset
|
||||||
|
})
|
||||||
|
savedRevisitSlotStartOffset.value = offset
|
||||||
|
feedback.msgSuccess('保存成功')
|
||||||
|
getLists()
|
||||||
|
} catch {
|
||||||
|
/* 拦截器已提示 */
|
||||||
|
} finally {
|
||||||
|
offsetSaving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ─── 详情抽屉(共享组件,数据拉取/展示全部在组件内) ───
|
// ─── 详情抽屉(共享组件,数据拉取/展示全部在组件内) ───
|
||||||
const detailDrawerRef = ref<InstanceType<typeof PrescriptionOrderDetailDrawer>>()
|
const detailDrawerRef = ref<InstanceType<typeof PrescriptionOrderDetailDrawer>>()
|
||||||
|
|
||||||
@@ -117,8 +233,13 @@ const formatAmount = (value: unknown) => {
|
|||||||
watch(
|
watch(
|
||||||
() => [props.diagnosisId, patientIdNum.value] as const,
|
() => [props.diagnosisId, patientIdNum.value] as const,
|
||||||
() => {
|
() => {
|
||||||
if (!patientIdAvailable.value) { pager.lists = []; pager.count = 0; return }
|
if (!patientIdAvailable.value) {
|
||||||
|
pager.lists = []
|
||||||
|
pager.count = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
buildParams()
|
buildParams()
|
||||||
|
void loadRevisitSlotStartOffset()
|
||||||
resetPage()
|
resetPage()
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
@@ -134,4 +255,21 @@ defineExpose({ refresh: () => getLists() })
|
|||||||
.po-empty-tip {
|
.po-empty-tip {
|
||||||
padding: 24px 0;
|
padding: 24px 0;
|
||||||
}
|
}
|
||||||
|
.po-revisit-offset-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--el-fill-color-lighter);
|
||||||
|
}
|
||||||
|
.po-revisit-offset-bar__main {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -94,6 +94,24 @@ class DiagnosisController extends BaseAdminController
|
|||||||
return $this->fail(DiagnosisLogic::getError());
|
return $this->fail(DiagnosisLogic::getError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notes 设置复诊接诊率统计起始偏移(业务订单 tab)
|
||||||
|
*/
|
||||||
|
public function setRevisitSlotStartOffset()
|
||||||
|
{
|
||||||
|
$params = (new DiagnosisValidate())->post()->goCheck('setRevisitSlotStartOffset');
|
||||||
|
$ok = DiagnosisLogic::setRevisitSlotStartOffset(
|
||||||
|
(int) $params['id'],
|
||||||
|
(int) $params['revisit_slot_start_offset'],
|
||||||
|
$this->adminInfo
|
||||||
|
);
|
||||||
|
if (!$ok) {
|
||||||
|
return $this->fail(DiagnosisLogic::getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success('保存成功');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notes 删除诊单
|
* @notes 删除诊单
|
||||||
* @return \think\response\Json
|
* @return \think\response\Json
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
namespace app\adminapi\lists\doctor;
|
namespace app\adminapi\lists\doctor;
|
||||||
|
|
||||||
use app\adminapi\lists\BaseAdminDataLists;
|
use app\adminapi\lists\BaseAdminDataLists;
|
||||||
|
use app\adminapi\logic\dept\DeptLogic;
|
||||||
|
use app\common\model\auth\AdminDept;
|
||||||
use app\common\model\DiagnosisViewRecord;
|
use app\common\model\DiagnosisViewRecord;
|
||||||
use app\common\model\doctor\Appointment;
|
use app\common\model\doctor\Appointment;
|
||||||
use app\common\model\tcm\Prescription;
|
use app\common\model\tcm\Prescription;
|
||||||
@@ -75,6 +77,35 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按部门筛选:接诊医生、诊单医助或挂号医助所属部门命中子树即可(选父级含子级)
|
||||||
|
*
|
||||||
|
* @param mixed $query
|
||||||
|
*/
|
||||||
|
private function applyAssistantDeptIdFilter($query): void
|
||||||
|
{
|
||||||
|
if (!isset($this->params['assistant_dept_id']) || $this->params['assistant_dept_id'] === '' || (int) $this->params['assistant_dept_id'] <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$rootDeptId = (int) $this->params['assistant_dept_id'];
|
||||||
|
$deptIds = DeptLogic::getSelfAndDescendantIds($rootDeptId);
|
||||||
|
$deptIds = array_values(array_filter(array_map('intval', $deptIds), static function (int $id): bool {
|
||||||
|
return $id > 0;
|
||||||
|
}));
|
||||||
|
if ($deptIds === []) {
|
||||||
|
$query->whereRaw('0 = 1');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$inList = implode(',', $deptIds);
|
||||||
|
$adTbl = (new AdminDept())->getTable();
|
||||||
|
$query->whereRaw(
|
||||||
|
"(EXISTS (SELECT 1 FROM `{$adTbl}` ad WHERE ad.`admin_id` = a.`doctor_id` AND ad.`dept_id` IN ({$inList}))"
|
||||||
|
. " OR EXISTS (SELECT 1 FROM `{$adTbl}` ad WHERE ad.`admin_id` = u.`assistant_id` AND ad.`dept_id` IN ({$inList}))"
|
||||||
|
. " OR EXISTS (SELECT 1 FROM `{$adTbl}` ad WHERE ad.`admin_id` = a.`assistant_id` AND ad.`dept_id` IN ({$inList})))"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渠道筛选:与 AppointmentLogic 一致,兼容仅有 channel_source、仅有 channels、或两者皆有的表结构
|
* 渠道筛选:与 AppointmentLogic 一致,兼容仅有 channel_source、仅有 channels、或两者皆有的表结构
|
||||||
*
|
*
|
||||||
@@ -191,6 +222,8 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
|
|
||||||
$this->applyAssistantIdFilter($query);
|
$this->applyAssistantIdFilter($query);
|
||||||
|
|
||||||
|
$this->applyAssistantDeptIdFilter($query);
|
||||||
|
|
||||||
$this->applyChannelSourceFilter($query, $chFilter);
|
$this->applyChannelSourceFilter($query, $chFilter);
|
||||||
|
|
||||||
// 是否确认诊单:1=已确认 0=未确认
|
// 是否确认诊单:1=已确认 0=未确认
|
||||||
@@ -373,6 +406,8 @@ class AppointmentLists extends BaseAdminDataLists implements ListsSearchInterfac
|
|||||||
|
|
||||||
$this->applyAssistantIdFilter($query);
|
$this->applyAssistantIdFilter($query);
|
||||||
|
|
||||||
|
$this->applyAssistantDeptIdFilter($query);
|
||||||
|
|
||||||
$this->applyChannelSourceFilter($query, $chFilter);
|
$this->applyChannelSourceFilter($query, $chFilter);
|
||||||
|
|
||||||
if ((int) ($this->params['exclude_cancelled'] ?? 0) === 1) {
|
if ((int) ($this->params['exclude_cancelled'] ?? 0) === 1) {
|
||||||
|
|||||||
@@ -741,6 +741,10 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
}
|
}
|
||||||
unset($item);
|
unset($item);
|
||||||
|
|
||||||
|
if ($this->shouldBypassListVisibilityForDiagnosisEdit()) {
|
||||||
|
$this->appendDiagnosisEditVisitSeqFields($lists);
|
||||||
|
}
|
||||||
|
|
||||||
$this->appendPrescriptionOrderAssignSnapshotErCenterFlags($lists);
|
$this->appendPrescriptionOrderAssignSnapshotErCenterFlags($lists);
|
||||||
|
|
||||||
if ((int) ($this->params['yeji_order_drawer'] ?? 0) === 1) {
|
if ((int) ($this->params['yeji_order_drawer'] ?? 0) === 1) {
|
||||||
@@ -1417,6 +1421,69 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 诊单编辑-业务订单 tab:标注全局诊次及是否计入复诊接诊率(与 RevisitRateLogic 同口径)
|
||||||
|
*
|
||||||
|
* @param array<int, array<string, mixed>> $lists
|
||||||
|
*/
|
||||||
|
private function appendDiagnosisEditVisitSeqFields(array &$lists): void
|
||||||
|
{
|
||||||
|
if ($lists === []) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$diagIds = [];
|
||||||
|
foreach ($lists as $row) {
|
||||||
|
$d = (int) ($row['diagnosis_id'] ?? 0);
|
||||||
|
if ($d > 0) {
|
||||||
|
$diagIds[$d] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$contextDid = (int) ($this->params['context_diagnosis_id'] ?? 0);
|
||||||
|
if ($contextDid > 0) {
|
||||||
|
$diagIds[$contextDid] = true;
|
||||||
|
}
|
||||||
|
$diagIdList = array_keys($diagIds);
|
||||||
|
if ($diagIdList === []) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$offsetRows = Diagnosis::whereIn('id', $diagIdList)
|
||||||
|
->whereNull('delete_time')
|
||||||
|
->column('revisit_slot_start_offset', 'id');
|
||||||
|
$offsetMap = [];
|
||||||
|
foreach ($offsetRows as $id => $offset) {
|
||||||
|
$offsetMap[(int) $id] = max(1, min(20, (int) $offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var array<int, int> $seqByOrderId order_id => global seq within diagnosis */
|
||||||
|
$seqByOrderId = [];
|
||||||
|
foreach ($diagIdList as $did) {
|
||||||
|
$q = PrescriptionOrder::where('diagnosis_id', $did)->whereNull('delete_time');
|
||||||
|
YejiStatsLogic::applyPrescriptionOrderNotCancelledForPerformanceQuery($q, '');
|
||||||
|
$orderIds = $q
|
||||||
|
->order(['create_time' => 'asc', 'id' => 'asc'])
|
||||||
|
->column('id');
|
||||||
|
$seq = 0;
|
||||||
|
foreach ($orderIds as $oid) {
|
||||||
|
$seq++;
|
||||||
|
$seqByOrderId[(int) $oid] = $seq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($lists as &$row) {
|
||||||
|
$oid = (int) ($row['id'] ?? 0);
|
||||||
|
$did = (int) ($row['diagnosis_id'] ?? 0);
|
||||||
|
$seq = (int) ($seqByOrderId[$oid] ?? 0);
|
||||||
|
$offset = (int) ($offsetMap[$did] ?? 1);
|
||||||
|
$effectiveSlot = $seq > 0 ? $seq + $offset : 0;
|
||||||
|
$row['global_visit_seq'] = $effectiveSlot > 0 ? $effectiveSlot : null;
|
||||||
|
$row['raw_visit_seq'] = $seq > 0 ? $seq : null;
|
||||||
|
$row['counts_for_revisit_rate'] = $effectiveSlot >= 2 ? 1 : 0;
|
||||||
|
}
|
||||||
|
unset($row);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 列表行标注:指派日志快照(related_po_creator_id + related_po_create_time)是否指向本业务单,
|
* 列表行标注:指派日志快照(related_po_creator_id + related_po_create_time)是否指向本业务单,
|
||||||
* 以及该次操作的新医助(to_assistant_id)是否归属「二中心」部门子树(与 DeptLogic / 业绩看板一致)。
|
* 以及该次操作的新医助(to_assistant_id)是否归属「二中心」部门子树(与 DeptLogic / 业绩看板一致)。
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use think\facade\Db;
|
|||||||
* 同一诊单当月被多次指派给同一医助只计 1 次。
|
* 同一诊单当月被多次指派给同一医助只计 1 次。
|
||||||
* - 第 N 次下单 = 诊单(患者)名下计入业绩的业务订单(剔除履约 4/9/10、软删)按 create_time 升序的**全局**序列中第 N 笔;
|
* - 第 N 次下单 = 诊单(患者)名下计入业绩的业务订单(剔除履约 4/9/10、软删)按 create_time 升序的**全局**序列中第 N 笔;
|
||||||
* 诊次**跨月累计不重置**:例如 5 月指派后旗下成交 4 单为二诊~五诊,6 月再成交即为六诊。
|
* 诊次**跨月累计不重置**:例如 5 月指派后旗下成交 4 单为二诊~五诊,6 月再成交即为六诊。
|
||||||
|
* 诊单可配置 `revisit_slot_start_offset`(默认 1:第 1 笔实单计为二诊;设为 2 则第 1 笔实单计为三诊,即在实单序号上叠加偏移,5 笔实单等价于计至七诊)。
|
||||||
* - 当月 N 诊单数 = **当月内下单**且全局序号为 N 的订单数,归属下单时点的**持有医助**——
|
* - 当月 N 诊单数 = **当月内下单**且全局序号为 N 的订单数,归属下单时点的**持有医助**——
|
||||||
* 按指派日志时间线取「订单时间之前最近一次指派」的 to_assistant_id(释放 to=0 即不再归属;
|
* 按指派日志时间线取「订单时间之前最近一次指派」的 to_assistant_id(释放 to=0 即不再归属;
|
||||||
* 「继承」指派会转移持有人用于归属,但不计被指派数)。指派可发生在往月。
|
* 「继承」指派会转移持有人用于归属,但不计被指派数)。指派可发生在往月。
|
||||||
@@ -323,7 +324,7 @@ class RevisitRateLogic
|
|||||||
* 核心统计上下文:
|
* 核心统计上下文:
|
||||||
* 1. 全量指派日志(≤ 月末)构建持有时间线;
|
* 1. 全量指派日志(≤ 月末)构建持有时间线;
|
||||||
* 2. 分母:当月非继承指派的「医助 × 诊单」;
|
* 2. 分母:当月非继承指派的「医助 × 诊单」;
|
||||||
* 3. 分子:曾被指派诊单的当月订单按全局序号 ≥2 归属持有医助;
|
* 3. 分子:曾被指派诊单的当月订单,统计诊次 = 实单序号 + 诊单偏移(默认第 1 笔实单为二诊);
|
||||||
* 4. 应用部门筛选(含组织下级)。
|
* 4. 应用部门筛选(含组织下级)。
|
||||||
*
|
*
|
||||||
* @param array{month?:string,dept_ids?:int[]|string} $params
|
* @param array{month?:string,dept_ids?:int[]|string} $params
|
||||||
@@ -375,9 +376,10 @@ class RevisitRateLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分子:曾被指派诊单的当月订单(全局序号 ≥2),归属下单时点的持有医助
|
// 分子:曾被指派诊单的当月订单,统计诊次 = 实单全局序号 + 诊单偏移(默认偏移 1 → 第 1 笔实单为二诊)
|
||||||
/** @var array<int, array<int, list<array<string, mixed>>>> $slotOrdersByAssistant */
|
/** @var array<int, array<int, list<array<string, mixed>>>> $slotOrdersByAssistant */
|
||||||
$slotOrdersByAssistant = [];
|
$slotOrdersByAssistant = [];
|
||||||
|
$offsetMap = self::fetchRevisitSlotStartOffsetMap(array_keys($candidateDiagSet));
|
||||||
foreach (array_chunk(array_keys($candidateDiagSet), 2000) as $chunk) {
|
foreach (array_chunk(array_keys($candidateDiagSet), 2000) as $chunk) {
|
||||||
$orderRows = self::fetchOrderSeqRows(
|
$orderRows = self::fetchOrderSeqRows(
|
||||||
$chunk,
|
$chunk,
|
||||||
@@ -387,6 +389,7 @@ class RevisitRateLogic
|
|||||||
$seq = 0;
|
$seq = 0;
|
||||||
$ptr = 0;
|
$ptr = 0;
|
||||||
$holder = 0;
|
$holder = 0;
|
||||||
|
$offset = 1;
|
||||||
foreach ($orderRows as $r) {
|
foreach ($orderRows as $r) {
|
||||||
$did = (int) ($r['diagnosis_id'] ?? 0);
|
$did = (int) ($r['diagnosis_id'] ?? 0);
|
||||||
if ($did <= 0) {
|
if ($did <= 0) {
|
||||||
@@ -397,8 +400,10 @@ class RevisitRateLogic
|
|||||||
$seq = 0;
|
$seq = 0;
|
||||||
$ptr = 0;
|
$ptr = 0;
|
||||||
$holder = 0;
|
$holder = 0;
|
||||||
|
$offset = self::resolveRevisitSlotStartOffset($did, $offsetMap);
|
||||||
}
|
}
|
||||||
$seq++;
|
$seq++;
|
||||||
|
$effectiveSlot = $seq + $offset;
|
||||||
$ct = (int) ($r['create_time'] ?? 0);
|
$ct = (int) ($r['create_time'] ?? 0);
|
||||||
// 推进时间线指针:订单时间之前(含同刻)最近一次指派的持有人
|
// 推进时间线指针:订单时间之前(含同刻)最近一次指派的持有人
|
||||||
$tl = $timeline[$did] ?? [];
|
$tl = $timeline[$did] ?? [];
|
||||||
@@ -407,14 +412,14 @@ class RevisitRateLogic
|
|||||||
$holder = (int) $tl[$ptr]['to'];
|
$holder = (int) $tl[$ptr]['to'];
|
||||||
$ptr++;
|
$ptr++;
|
||||||
}
|
}
|
||||||
if ($seq < 2 || $seq > self::MAX_VISIT_SLOT) {
|
if ($effectiveSlot < 2 || $effectiveSlot > self::MAX_VISIT_SLOT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($ct < $startTs || $ct > $endTs) {
|
if ($ct < $startTs || $ct > $endTs) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($holder > 0) {
|
if ($holder > 0) {
|
||||||
$slotOrdersByAssistant[$holder][$seq][] = $r;
|
$slotOrdersByAssistant[$holder][$effectiveSlot][] = $r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -619,6 +624,48 @@ class RevisitRateLogic
|
|||||||
->toArray();
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param list<int> $diagIds
|
||||||
|
*
|
||||||
|
* @return array<int, int> diagnosis_id => revisit_slot_start_offset
|
||||||
|
*/
|
||||||
|
private static function fetchRevisitSlotStartOffsetMap(array $diagIds): array
|
||||||
|
{
|
||||||
|
if ($diagIds === []) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$out = [];
|
||||||
|
foreach (array_chunk($diagIds, 2000) as $chunk) {
|
||||||
|
$rows = Db::name('tcm_diagnosis')
|
||||||
|
->whereIn('id', $chunk)
|
||||||
|
->whereNull('delete_time')
|
||||||
|
->column('revisit_slot_start_offset', 'id');
|
||||||
|
foreach ($rows as $id => $offset) {
|
||||||
|
$out[(int) $id] = (int) $offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 诊单复诊统计起始偏移(默认 1:第 1 笔实单计为二诊;统计诊次 = 实单序号 + 偏移)
|
||||||
|
*
|
||||||
|
* @param array<int, int> $offsetMap
|
||||||
|
*/
|
||||||
|
private static function resolveRevisitSlotStartOffset(int $diagId, array $offsetMap): int
|
||||||
|
{
|
||||||
|
$offset = (int) ($offsetMap[$diagId] ?? 1);
|
||||||
|
if ($offset < 1) {
|
||||||
|
$offset = 1;
|
||||||
|
}
|
||||||
|
if ($offset > 20) {
|
||||||
|
$offset = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $offset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param list<int> $diagIds
|
* @param list<int> $diagIds
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -748,6 +748,46 @@ class DiagnosisLogic extends BaseLogic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notes 诊单指派医助操作记录列表
|
||||||
|
*/
|
||||||
|
public static function setRevisitSlotStartOffset(int $diagnosisId, int $offset, array $adminInfo): bool
|
||||||
|
{
|
||||||
|
self::$error = '';
|
||||||
|
if ($diagnosisId <= 0) {
|
||||||
|
self::setError('诊单不存在');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($offset < 1 || $offset > 20) {
|
||||||
|
self::setError('起始偏移须在 1~20 之间');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$diagnosis = Diagnosis::where('id', $diagnosisId)->whereNull('delete_time')->find();
|
||||||
|
if (!$diagnosis) {
|
||||||
|
self::setError('诊单不存在');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$old = (int) ($diagnosis->revisit_slot_start_offset ?? 1);
|
||||||
|
if ($old < 1) {
|
||||||
|
$old = 1;
|
||||||
|
}
|
||||||
|
if ($old === $offset) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$diagnosis->save(['revisit_slot_start_offset' => $offset]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
self::setError($e->getMessage());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notes 诊单指派医助操作记录列表
|
* @notes 诊单指派医助操作记录列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3407,17 +3407,14 @@ class PrescriptionOrderLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出用:主方/辅方服用天数(优先业务订单 medication_days,缺省回退处方 usage_days / 辅方 aux_usage)
|
* 导出用:主方/辅方开立天数(与详情侧栏「处方开立」同口径:主方取处方 usage_days,辅方取 aux_usage.usage_days)
|
||||||
|
* 订单服用天数单独导出在 export_medication_days 列,不在此混用。
|
||||||
*
|
*
|
||||||
* @param array<string, mixed> $rx
|
* @param array<string, mixed> $rx
|
||||||
* @param array<string, mixed>|null $auxUsage
|
* @param array<string, mixed>|null $auxUsage
|
||||||
*/
|
*/
|
||||||
private static function resolveExportUsageDays(array $rx, ?array $auxUsage, $orderMedicationDays, bool $isAux): string
|
private static function resolveExportUsageDays(array $rx, ?array $auxUsage, bool $isAux): string
|
||||||
{
|
{
|
||||||
$medDays = $orderMedicationDays;
|
|
||||||
if ($medDays !== null && $medDays !== '' && (int) $medDays > 0) {
|
|
||||||
return (string) (int) $medDays;
|
|
||||||
}
|
|
||||||
if ($isAux) {
|
if ($isAux) {
|
||||||
$days = (int) ($auxUsage['usage_days'] ?? 0);
|
$days = (int) ($auxUsage['usage_days'] ?? 0);
|
||||||
|
|
||||||
@@ -3990,10 +3987,9 @@ class PrescriptionOrderLogic
|
|||||||
} else {
|
} else {
|
||||||
$item['export_aux_usage'] = '';
|
$item['export_aux_usage'] = '';
|
||||||
}
|
}
|
||||||
$orderMedDays = $item['medication_days'] ?? null;
|
$item['export_main_usage_days'] = self::resolveExportUsageDays($rxArr, $auxUsageNorm, false);
|
||||||
$item['export_main_usage_days'] = self::resolveExportUsageDays($rxArr, $auxUsageNorm, $orderMedDays, false);
|
|
||||||
$item['export_aux_usage_days'] = $auxHerbs !== []
|
$item['export_aux_usage_days'] = $auxHerbs !== []
|
||||||
? self::resolveExportUsageDays($rxArr, $auxUsageNorm, $orderMedDays, true)
|
? self::resolveExportUsageDays($rxArr, $auxUsageNorm, true)
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
$item['export_service_package'] = self::formatServicePackageForExport(
|
$item['export_service_package'] = self::formatServicePackageForExport(
|
||||||
@@ -4906,8 +4902,8 @@ class PrescriptionOrderLogic
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (in_array((int) $order->fulfillment_status, [3, 4], true)) {
|
if ((int) $order->fulfillment_status === 4) {
|
||||||
self::setError('已完成或已取消的订单不可修改');
|
self::setError('已取消的订单不可修改');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class DiagnosisValidate extends BaseValidate
|
|||||||
'end_date' => 'date|checkDateRange',
|
'end_date' => 'date|checkDateRange',
|
||||||
'diagnosis_id' => 'require|integer|checkDiagnosisId',
|
'diagnosis_id' => 'require|integer|checkDiagnosisId',
|
||||||
'tracking_content' => 'require|length:1,1000',
|
'tracking_content' => 'require|length:1,1000',
|
||||||
|
'revisit_slot_start_offset' => 'integer|between:1,20',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $message = [
|
protected $message = [
|
||||||
@@ -139,6 +140,13 @@ class DiagnosisValidate extends BaseValidate
|
|||||||
return $this->only(['id']);
|
return $this->only(['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 业务订单 tab:设置复诊接诊率统计起始偏移 */
|
||||||
|
public function sceneSetRevisitSlotStartOffset()
|
||||||
|
{
|
||||||
|
return $this->only(['id', 'revisit_slot_start_offset'])
|
||||||
|
->append('revisit_slot_start_offset', 'require|integer|between:1,20');
|
||||||
|
}
|
||||||
|
|
||||||
protected function checkDiagnosis($value)
|
protected function checkDiagnosis($value)
|
||||||
{
|
{
|
||||||
$diagnosis = Diagnosis::findOrEmpty($value);
|
$diagnosis = Diagnosis::findOrEmpty($value);
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
-- 诊单:复诊接诊率统计起始偏移(1=从二诊起计,2=从三诊起计…)
|
||||||
|
-- 执行前确认表前缀为 zyt_。
|
||||||
|
|
||||||
|
ALTER TABLE `zyt_tcm_diagnosis`
|
||||||
|
ADD COLUMN `revisit_slot_start_offset` tinyint(3) unsigned NOT NULL DEFAULT 1
|
||||||
|
COMMENT '复诊接诊率统计起始偏移:统计诊次=实单序号+偏移(1=第1笔实单计二诊,2=计三诊,5笔实单等价七诊)'
|
||||||
|
AFTER `show_card`;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
-- 诊单业务订单 tab:设置复诊统计起始偏移
|
||||||
|
SET @diag_menu_id := (SELECT id FROM zyt_system_menu WHERE perms = 'tcm.diagnosis/lists' LIMIT 1);
|
||||||
|
|
||||||
|
INSERT INTO zyt_system_menu (
|
||||||
|
pid, type, name, icon, sort, perms, paths, component,
|
||||||
|
selected, params, is_cache, is_show, is_disable, create_time, update_time
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@diag_menu_id, 'A', '设置复诊统计起始偏移', '', 71,
|
||||||
|
'tcm.diagnosis/setRevisitSlotStartOffset', '', '',
|
||||||
|
'', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||||
|
FROM DUAL
|
||||||
|
WHERE @diag_menu_id IS NOT NULL
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.diagnosis/setRevisitSlotStartOffset');
|
||||||
Reference in New Issue
Block a user