业务订单
This commit is contained in:
@@ -15,7 +15,8 @@
|
|||||||
"Bash(npx eslint *)",
|
"Bash(npx eslint *)",
|
||||||
"Bash(git *)",
|
"Bash(git *)",
|
||||||
"Bash(tail -c 100000 /Users/long/.claude/projects/-Users-long-Work-zyt/7be9f770-afc3-497d-87a3-2ffa1fbe3fd1.jsonl)",
|
"Bash(tail -c 100000 /Users/long/.claude/projects/-Users-long-Work-zyt/7be9f770-afc3-497d-87a3-2ffa1fbe3fd1.jsonl)",
|
||||||
"Read(//tmp/**)"
|
"Read(//tmp/**)",
|
||||||
|
"Bash(npx --no-install vue-tsc --noEmit)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<template>
|
||||||
|
<div class="patient-order-list">
|
||||||
|
<div v-if="!patientIdAvailable" class="po-empty-tip">
|
||||||
|
<el-empty description="当前诊单未携带患者ID,无法列出业务订单" />
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<el-table
|
||||||
|
v-loading="pager.loading"
|
||||||
|
:data="pager.lists"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
empty-text="暂无业务订单"
|
||||||
|
>
|
||||||
|
<el-table-column label="订单编号" prop="order_no" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column label="金额" width="120" align="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span class="text-red-500 font-semibold">¥{{ formatAmount(row.amount) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="医生" prop="doctor_name" width="110" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.doctor_name || '—' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="医助" prop="assistant_name" width="110" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.assistant_name || '—' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="履约状态" width="110">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="fulfillmentTagType(row.fulfillment_status)" size="small" effect="light">
|
||||||
|
{{ fulfillmentText(row.fulfillment_status) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" min-width="170">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatTime(row.create_time) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="flex justify-end mt-3">
|
||||||
|
<pagination v-model="pager" @change="getLists" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, watch } from 'vue'
|
||||||
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
|
import { prescriptionOrderLists } from '@/api/tcm'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
diagnosisId: number
|
||||||
|
patientId?: number | string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const patientIdNum = computed(() => {
|
||||||
|
const n = Number(props.patientId)
|
||||||
|
return Number.isFinite(n) && n > 0 ? n : 0
|
||||||
|
})
|
||||||
|
const patientIdAvailable = computed(() => patientIdNum.value > 0)
|
||||||
|
|
||||||
|
const queryParams = reactive<Record<string, number | string>>({})
|
||||||
|
|
||||||
|
const { pager, getLists, resetPage } = usePaging({
|
||||||
|
fetchFun: prescriptionOrderLists,
|
||||||
|
params: queryParams,
|
||||||
|
size: 10
|
||||||
|
})
|
||||||
|
|
||||||
|
const buildParams = () => {
|
||||||
|
Object.keys(queryParams).forEach((k) => delete queryParams[k])
|
||||||
|
if (patientIdAvailable.value) {
|
||||||
|
queryParams.patient_id = patientIdNum.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatAmount = (value: unknown) => {
|
||||||
|
const n = Number(value)
|
||||||
|
return Number.isFinite(n) ? n.toFixed(2) : '0.00'
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatTime = (value: unknown) => {
|
||||||
|
if (value === null || value === undefined || value === '') return '—'
|
||||||
|
if (typeof value === 'number' && value > 1e9 && value < 1e11) {
|
||||||
|
const d = new Date(value * 1000)
|
||||||
|
const pad = (n: number) => String(n).padStart(2, '0')
|
||||||
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||||
|
}
|
||||||
|
return String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fulfillmentText = (s: number | undefined) => {
|
||||||
|
const m: Record<number, string> = {
|
||||||
|
1: '待双审通过',
|
||||||
|
2: '待发货',
|
||||||
|
3: '已完成',
|
||||||
|
4: '已取消',
|
||||||
|
5: '已发货',
|
||||||
|
6: '已签收',
|
||||||
|
7: '进行中',
|
||||||
|
8: '暂不制药',
|
||||||
|
9: '拒收',
|
||||||
|
10: '退款',
|
||||||
|
11: '保留药方',
|
||||||
|
12: '制药缓发'
|
||||||
|
}
|
||||||
|
return m[Number(s)] ?? '—'
|
||||||
|
}
|
||||||
|
|
||||||
|
const fulfillmentTagType = (s: number | undefined): 'success' | 'warning' | 'danger' | 'info' | 'primary' => {
|
||||||
|
const n = Number(s)
|
||||||
|
if (n === 3 || n === 6) return 'success'
|
||||||
|
if (n === 5) return 'primary'
|
||||||
|
if (n === 4 || n === 9 || n === 10) return 'danger'
|
||||||
|
if (n === 2 || n === 7) return 'warning'
|
||||||
|
if (n === 8 || n === 11 || n === 12) return 'info'
|
||||||
|
return 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [props.diagnosisId, patientIdNum.value] as const,
|
||||||
|
() => {
|
||||||
|
if (!patientIdAvailable.value) {
|
||||||
|
pager.lists = []
|
||||||
|
pager.count = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buildParams()
|
||||||
|
resetPage()
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
defineExpose({ refresh: () => getLists() })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.patient-order-list {
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.po-empty-tip {
|
||||||
|
padding: 24px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -638,6 +638,22 @@
|
|||||||
<el-empty v-else description="请先保存诊单,开方后病历将在此显示" />
|
<el-empty v-else description="请先保存诊单,开方后病历将在此显示" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 业务订单:复用处方业务订单接口,按患者ID聚合 / 按当前诊单过滤 -->
|
||||||
|
<el-tab-pane
|
||||||
|
label="业务订单"
|
||||||
|
name="patientOrders"
|
||||||
|
:disabled="!formData.id"
|
||||||
|
lazy
|
||||||
|
v-if="hasPermission(['tcm.diagnosis/patientOrders'])"
|
||||||
|
>
|
||||||
|
<patient-order-list
|
||||||
|
v-if="formData.id"
|
||||||
|
:diagnosis-id="Number(formData.id)"
|
||||||
|
:patient-id="Number(formData.patient_id) || 0"
|
||||||
|
/>
|
||||||
|
<el-empty v-else description="请先保存诊单后查看业务订单" />
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-if="hasPermission(['tcm.diagnosis/huifang'])"
|
v-if="hasPermission(['tcm.diagnosis/huifang'])"
|
||||||
label="视频录制回放记录"
|
label="视频录制回放记录"
|
||||||
@@ -741,6 +757,7 @@ import AssignLogPanel from './components/AssignLogPanel.vue'
|
|||||||
import AppointmentRecordPanel from './components/AppointmentRecordPanel.vue'
|
import AppointmentRecordPanel from './components/AppointmentRecordPanel.vue'
|
||||||
import NoteTimeline from '@/views/patient/reception/components/NoteTimeline.vue'
|
import NoteTimeline from '@/views/patient/reception/components/NoteTimeline.vue'
|
||||||
import TrackingNoteTimeline from './components/TrackingNoteTimeline.vue'
|
import TrackingNoteTimeline from './components/TrackingNoteTimeline.vue'
|
||||||
|
import PatientOrderList from './components/PatientOrderList.vue'
|
||||||
import TcmPrescription from '@/components/tcm-prescription/index.vue'
|
import TcmPrescription from '@/components/tcm-prescription/index.vue'
|
||||||
import { getDoctorNotes } from '@/api/patient'
|
import { getDoctorNotes } from '@/api/patient'
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
public function setSearch(): array
|
public function setSearch(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'=' => ['prescription_id', 'fulfillment_status', 'prescription_audit_status', 'payment_slip_audit_status'],
|
'=' => ['prescription_id', 'diagnosis_id', 'fulfillment_status', 'prescription_audit_status', 'payment_slip_audit_status'],
|
||||||
'%like%' => ['order_no'],
|
'%like%' => ['order_no'],
|
||||||
'between_time' => 'create_time',
|
'between_time' => 'create_time',
|
||||||
];
|
];
|
||||||
@@ -96,6 +96,7 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
{
|
{
|
||||||
$this->applyDoctorAssistantFilters($query);
|
$this->applyDoctorAssistantFilters($query);
|
||||||
$this->applyPatientKeywordFilter($query);
|
$this->applyPatientKeywordFilter($query);
|
||||||
|
$this->applyPatientIdFilter($query);
|
||||||
$this->applyExpressCompanyFilter($query);
|
$this->applyExpressCompanyFilter($query);
|
||||||
$this->applyExpressKeywordFilter($query);
|
$this->applyExpressKeywordFilter($query);
|
||||||
$this->applySupplyModeFilter($query);
|
$this->applySupplyModeFilter($query);
|
||||||
@@ -395,6 +396,10 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
if ($diagIdsForAssist !== []) {
|
if ($diagIdsForAssist !== []) {
|
||||||
$assistantByDiag = Diagnosis::whereIn('id', $diagIdsForAssist)->whereNull('delete_time')->column('assistant_id', 'id');
|
$assistantByDiag = Diagnosis::whereIn('id', $diagIdsForAssist)->whereNull('delete_time')->column('assistant_id', 'id');
|
||||||
}
|
}
|
||||||
|
$assistantIds = array_values(array_unique(array_filter(array_map('intval', array_values($assistantByDiag)))));
|
||||||
|
$assistantNames = $assistantIds !== []
|
||||||
|
? \app\common\model\auth\Admin::whereIn('id', $assistantIds)->column('name', 'id')
|
||||||
|
: [];
|
||||||
foreach ($lists as &$item) {
|
foreach ($lists as &$item) {
|
||||||
PrescriptionOrderLogic::maskInternalCostIfNeeded($item, $this->adminInfo);
|
PrescriptionOrderLogic::maskInternalCostIfNeeded($item, $this->adminInfo);
|
||||||
$pid = (int) ($item['id'] ?? 0);
|
$pid = (int) ($item['id'] ?? 0);
|
||||||
@@ -410,11 +415,19 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
$this->adminInfo,
|
$this->adminInfo,
|
||||||
$assistantByDiag
|
$assistantByDiag
|
||||||
);
|
);
|
||||||
|
|
||||||
// 添加创建人姓名
|
// 添加创建人姓名
|
||||||
$creatorId = (int) ($item['creator_id'] ?? 0);
|
$creatorId = (int) ($item['creator_id'] ?? 0);
|
||||||
$item['creator_name'] = $creatorId > 0 ? ($creatorNames[$creatorId] ?? '') : '';
|
$item['creator_name'] = $creatorId > 0 ? ($creatorNames[$creatorId] ?? '') : '';
|
||||||
|
|
||||||
|
// 添加医助(来自诊单 assistant_id)
|
||||||
|
$diagIdForAssist = (int) ($item['diagnosis_id'] ?? 0);
|
||||||
|
$assistantIdForItem = (int) ($assistantByDiag[$diagIdForAssist] ?? 0);
|
||||||
|
$item['assistant_id'] = $assistantIdForItem;
|
||||||
|
$item['assistant_name'] = $assistantIdForItem > 0
|
||||||
|
? ($assistantNames[$assistantIdForItem] ?? '')
|
||||||
|
: '';
|
||||||
|
|
||||||
// 添加开方人姓名、处方登记手机(与业务订单收货手机比对用)
|
// 添加开方人姓名、处方登记手机(与业务订单收货手机比对用)
|
||||||
$rxId = (int) ($item['prescription_id'] ?? 0);
|
$rxId = (int) ($item['prescription_id'] ?? 0);
|
||||||
$item['doctor_name'] = $rxId > 0 ? ($prescriptionCreators[$rxId]['doctor_name'] ?? '') : '';
|
$item['doctor_name'] = $rxId > 0 ? ($prescriptionCreators[$rxId]['doctor_name'] ?? '') : '';
|
||||||
@@ -745,6 +758,26 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按真实患者ID精确过滤(tcm_diagnosis.patient_id 是跨诊单的患者唯一ID)
|
||||||
|
* 用于诊单编辑抽屉「业务订单」tab 列出该患者所有诊单产生的处方业务订单。
|
||||||
|
*/
|
||||||
|
private function applyPatientIdFilter($query): void
|
||||||
|
{
|
||||||
|
$patientId = (int) ($this->params['patient_id'] ?? 0);
|
||||||
|
if ($patientId <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$poTbl = (new PrescriptionOrder())->getTable();
|
||||||
|
$diagTbl = (new Diagnosis())->getTable();
|
||||||
|
|
||||||
|
$query->whereExists(
|
||||||
|
"SELECT 1 FROM `{$diagTbl}` dg WHERE dg.`id` = `{$poTbl}`.`diagnosis_id` "
|
||||||
|
. "AND dg.`delete_time` IS NULL AND dg.`patient_id` = {$patientId}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按快递单号 / 快递公司 模糊检索
|
* 按快递单号 / 快递公司 模糊检索
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# 诊单编辑抽屉「业务订单」tab:菜单按钮权限注册(2026-05-07)
|
||||||
|
# 挂在「中医诊单」(perms=tcm.diagnosis/lists) 菜单下,按钮型权限节点:
|
||||||
|
# tcm.diagnosis/patientOrders 在编辑诊单抽屉查看「业务订单」tab
|
||||||
|
#
|
||||||
|
# 说明:
|
||||||
|
# - 此权限仅控制前端 tab 可见性。
|
||||||
|
# - tab 内拉取数据复用 /tcm.prescriptionOrder/lists 接口,因此需同时分配
|
||||||
|
# tcm.prescriptionOrder/lists 接口权限给目标角色,否则 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', '业务订单查看', '', 70,
|
||||||
|
'tcm.diagnosis/patientOrders', '', '',
|
||||||
|
'', '', 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/patientOrders');
|
||||||
Reference in New Issue
Block a user