1. 特色方功能迭代
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
This commit is contained in:
@@ -33,3 +33,18 @@ export async function deleteSpecialPrescription(data: Record<string, any>) {
|
|||||||
export async function applySpecialPrescriptionApi(data: { register_id: number }) {
|
export async function applySpecialPrescriptionApi(data: { register_id: number }) {
|
||||||
return requestClient.post<any>(`${prefix}apply`, data);
|
return requestClient.post<any>(`${prefix}apply`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 自动均分药品单价 */
|
||||||
|
export async function distributeDrugPricesApi(data: Record<string, any>) {
|
||||||
|
return requestClient.post<any>(`${prefix}distribute-drug-prices`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 价格配置详情(路由与 cc_auto_route_register 生成的 price-config-detail 对齐) */
|
||||||
|
export async function getSpecialPrescriptionPriceConfig(id: number) {
|
||||||
|
return requestClient.get<any>(`${prefix}price-config-detail`, { params: { id } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 保存价格配置 */
|
||||||
|
export async function saveSpecialPrescriptionPriceConfig(data: Record<string, any>) {
|
||||||
|
return requestClient.post<any>(`${prefix}save-price-config`, data);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onMounted, ref } from 'vue';
|
import { computed, nextTick, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { useUserStore } from '@vben/stores';
|
import { useUserStore } from '@vben/stores';
|
||||||
|
|
||||||
@@ -22,6 +22,8 @@ import {
|
|||||||
getProductListDoctorReception,
|
getProductListDoctorReception,
|
||||||
} from '#/views/doctor/doctor-reception/api';
|
} from '#/views/doctor/doctor-reception/api';
|
||||||
|
|
||||||
|
import PrescriptionDiagnosisOrderCards from './PrescriptionDiagnosisOrderCards.vue';
|
||||||
|
|
||||||
export interface ChineseDrugItem {
|
export interface ChineseDrugItem {
|
||||||
_key?: number;
|
_key?: number;
|
||||||
id: number;
|
id: number;
|
||||||
@@ -29,6 +31,7 @@ export interface ChineseDrugItem {
|
|||||||
drug_name: string;
|
drug_name: string;
|
||||||
number: number;
|
number: number;
|
||||||
price: number;
|
price: number;
|
||||||
|
buy_price?: number;
|
||||||
way_id: number;
|
way_id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +40,26 @@ const props = withDefaults(
|
|||||||
modelValue?: ChineseDrugItem[];
|
modelValue?: ChineseDrugItem[];
|
||||||
dosage?: number;
|
dosage?: number;
|
||||||
dayDosage?: number;
|
dayDosage?: number;
|
||||||
|
/** 固定价/SKU方案下允许编辑单价 */
|
||||||
|
priceEditable?: boolean;
|
||||||
|
/** 价格配置弹窗:药名/克数/用法只读,仅价格可改 */
|
||||||
|
structureReadonly?: boolean;
|
||||||
|
/** 预选诊断(导入特色方时带入) */
|
||||||
|
clinicalDiagnose?: string;
|
||||||
|
/** 预选医嘱 */
|
||||||
|
doctorOrder?: string;
|
||||||
|
/** 是否展示诊断/医嘱气泡卡(价格配置等场景可关闭) */
|
||||||
|
showDiagnosisOrder?: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
modelValue: () => [],
|
modelValue: () => [],
|
||||||
dosage: 7,
|
dosage: 7,
|
||||||
dayDosage: 2,
|
dayDosage: 2,
|
||||||
|
priceEditable: false,
|
||||||
|
structureReadonly: false,
|
||||||
|
clinicalDiagnose: '',
|
||||||
|
doctorOrder: '',
|
||||||
|
showDiagnosisOrder: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -49,12 +67,33 @@ const emit = defineEmits<{
|
|||||||
'update:modelValue': [value: ChineseDrugItem[]];
|
'update:modelValue': [value: ChineseDrugItem[]];
|
||||||
'update:dosage': [value: number];
|
'update:dosage': [value: number];
|
||||||
'update:dayDosage': [value: number];
|
'update:dayDosage': [value: number];
|
||||||
|
'update:clinicalDiagnose': [value: string];
|
||||||
|
'update:doctorOrder': [value: string];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const drugList = ref<ChineseDrugItem[]>([]);
|
const drugList = ref<ChineseDrugItem[]>([]);
|
||||||
const dosageLocal = ref(props.dosage);
|
const dosageLocal = ref(props.dosage);
|
||||||
const dayDosageLocal = ref(props.dayDosage);
|
const dayDosageLocal = ref(props.dayDosage);
|
||||||
|
const diagnosisOrderCardsRef = ref<InstanceType<typeof PrescriptionDiagnosisOrderCards>>();
|
||||||
|
|
||||||
|
/** 价格配置只读模式下不展示诊断/医嘱区 */
|
||||||
|
const showDiagnosisOrderPanel = computed(
|
||||||
|
() => props.showDiagnosisOrder && !props.structureReadonly,
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 预选诊断双向绑定 */
|
||||||
|
const clinicalDiagnoseModel = computed({
|
||||||
|
get: () => props.clinicalDiagnose ?? '',
|
||||||
|
set: (val: string) => emit('update:clinicalDiagnose', val),
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 预选医嘱双向绑定 */
|
||||||
|
const doctorOrderModel = computed({
|
||||||
|
get: () => props.doctorOrder ?? '',
|
||||||
|
set: (val: string) => emit('update:doctorOrder', val),
|
||||||
|
});
|
||||||
|
|
||||||
const drugUseWay = ref<any[]>([]);
|
const drugUseWay = ref<any[]>([]);
|
||||||
const chineseSearchResults = ref<any[]>([]);
|
const chineseSearchResults = ref<any[]>([]);
|
||||||
const newDrugInfo = ref<{
|
const newDrugInfo = ref<{
|
||||||
@@ -75,6 +114,12 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getWayName(wayId: number) {
|
||||||
|
if (!wayId) return '煎服';
|
||||||
|
const item = drugUseWay.value.find((w) => Number(w.id) === Number(wayId));
|
||||||
|
return item?.name || '煎服';
|
||||||
|
}
|
||||||
|
|
||||||
function syncToParent() {
|
function syncToParent() {
|
||||||
emit('update:modelValue', [...drugList.value]);
|
emit('update:modelValue', [...drugList.value]);
|
||||||
emit('update:dosage', dosageLocal.value);
|
emit('update:dosage', dosageLocal.value);
|
||||||
@@ -200,21 +245,66 @@ function onDosageChange() {
|
|||||||
syncToParent();
|
syncToParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadDrugs(recipes: any[], dosage?: number, dayDosage?: number) {
|
function loadDrugs(recipes: any[], dosage?: number, dayDosage?: number, drugPrices?: any[]) {
|
||||||
drugList.value = (recipes || []).map((recipe) => ({
|
const priceMap = new Map<number, { buy_price: number; sell_price: number }>();
|
||||||
_key: Date.now() + Math.random(),
|
(drugPrices || []).forEach((item) => {
|
||||||
id: recipe.drug_id || recipe.id,
|
priceMap.set(Number(item.drug_id), {
|
||||||
drug_id: recipe.drug_id || recipe.id,
|
buy_price: Number(item.buy_price || 0),
|
||||||
drug_name: recipe.drug_name || recipe.name || '',
|
sell_price: Number(item.sell_price || item.price || 0),
|
||||||
number: recipe.number || 1,
|
});
|
||||||
price: recipe.price || 0,
|
});
|
||||||
way_id: recipe.way_id || 0,
|
drugList.value = (recipes || []).map((recipe) => {
|
||||||
}));
|
const drugId = recipe.drug_id || recipe.id;
|
||||||
|
const configured = priceMap.get(Number(drugId));
|
||||||
|
return {
|
||||||
|
_key: Date.now() + Math.random(),
|
||||||
|
id: drugId,
|
||||||
|
drug_id: drugId,
|
||||||
|
drug_name: recipe.drug_name || recipe.name || '',
|
||||||
|
number: recipe.number || 1,
|
||||||
|
price: configured?.sell_price ?? recipe.price ?? 0,
|
||||||
|
buy_price: configured?.buy_price ?? recipe.buy_price ?? 0,
|
||||||
|
way_id: recipe.way_id || 0,
|
||||||
|
};
|
||||||
|
});
|
||||||
if (dosage !== undefined) dosageLocal.value = dosage;
|
if (dosage !== undefined) dosageLocal.value = dosage;
|
||||||
if (dayDosage !== undefined) dayDosageLocal.value = dayDosage;
|
if (dayDosage !== undefined) dayDosageLocal.value = dayDosage;
|
||||||
syncToParent();
|
syncToParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyDistributedPrices(items: Array<{ drug_id: number; buy_price: number | string; sell_price: number | string }>) {
|
||||||
|
const priceMap = new Map<number, { buy_price: number; sell_price: number }>();
|
||||||
|
items.forEach((item) => {
|
||||||
|
priceMap.set(Number(item.drug_id), {
|
||||||
|
buy_price: Number(item.buy_price || 0),
|
||||||
|
sell_price: Number(item.sell_price || 0),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
drugList.value.forEach((drug) => {
|
||||||
|
const configured = priceMap.get(Number(drug.drug_id || drug.id));
|
||||||
|
if (configured) {
|
||||||
|
drug.price = configured.sell_price;
|
||||||
|
drug.buy_price = configured.buy_price;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
syncToParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDrugPricesPayload() {
|
||||||
|
return drugList.value.map((drug) => ({
|
||||||
|
drug_id: drug.drug_id || drug.id,
|
||||||
|
buy_price: drug.buy_price ?? 0,
|
||||||
|
sell_price: drug.price ?? 0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDrugsForDistribute() {
|
||||||
|
return drugList.value.map((drug) => ({
|
||||||
|
drug_id: drug.drug_id || drug.id,
|
||||||
|
number: drug.number || 1,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
function getDrugsPayload() {
|
function getDrugsPayload() {
|
||||||
return drugList.value.map((drug) => ({
|
return drugList.value.map((drug) => ({
|
||||||
drug_id: drug.drug_id || drug.id,
|
drug_id: drug.drug_id || drug.id,
|
||||||
@@ -227,14 +317,22 @@ function getDrugsPayload() {
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
getDrugsPayload,
|
getDrugsPayload,
|
||||||
|
getDrugPricesPayload,
|
||||||
|
getDrugsForDistribute,
|
||||||
|
applyDistributedPrices,
|
||||||
loadDrugs,
|
loadDrugs,
|
||||||
drugList,
|
drugList,
|
||||||
|
getDiagnosisOrderPayload: () =>
|
||||||
|
diagnosisOrderCardsRef.value?.getDiagnosisOrderPayload?.() ?? {
|
||||||
|
clinical_diagnose: props.clinicalDiagnose || '',
|
||||||
|
doctor_order: props.doctorOrder || '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="chinese-drug-editor">
|
<div class="chinese-drug-editor">
|
||||||
<Row :gutter="16" class="mb-4">
|
<Row v-if="!structureReadonly" :gutter="16" class="mb-4">
|
||||||
<Col :span="12">
|
<Col :span="12">
|
||||||
<FormItem label="剂量(天/剂)">
|
<FormItem label="剂量(天/剂)">
|
||||||
<InputNumber
|
<InputNumber
|
||||||
@@ -258,8 +356,17 @@ defineExpose({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<div v-else-if="dosageLocal || dayDosageLocal" class="readonly-meta mb-3 text-gray-500">
|
||||||
|
剂量 {{ dosageLocal }} 天/剂 · 频次 {{ dayDosageLocal }} 次/天
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormItem label="药品列表" required>
|
<FormItem :label="structureReadonly ? '' : '药品列表'" :required="!structureReadonly">
|
||||||
|
<PrescriptionDiagnosisOrderCards
|
||||||
|
v-if="showDiagnosisOrderPanel"
|
||||||
|
ref="diagnosisOrderCardsRef"
|
||||||
|
v-model:clinical-diagnose="clinicalDiagnoseModel"
|
||||||
|
v-model:doctor-order="doctorOrderModel"
|
||||||
|
/>
|
||||||
<Row :gutter="[12, 12]">
|
<Row :gutter="[12, 12]">
|
||||||
<Col
|
<Col
|
||||||
v-for="(drug, index) in drugList"
|
v-for="(drug, index) in drugList"
|
||||||
@@ -272,7 +379,14 @@ defineExpose({
|
|||||||
<Card size="small" class="chinese-drug-card">
|
<Card size="small" class="chinese-drug-card">
|
||||||
<div class="chinese-drug-content">
|
<div class="chinese-drug-content">
|
||||||
<span class="chinese-drug-index">{{ index + 1 }}、</span>
|
<span class="chinese-drug-index">{{ index + 1 }}、</span>
|
||||||
<div class="chinese-drug-form">
|
<div v-if="structureReadonly" class="chinese-drug-readonly">
|
||||||
|
<span class="chinese-drug-name-text">{{ drug.drug_name }}</span>
|
||||||
|
<span class="chinese-drug-comma">,</span>
|
||||||
|
<span>{{ drug.number }}g</span>
|
||||||
|
<span class="chinese-drug-comma">,</span>
|
||||||
|
<span>{{ getWayName(drug.way_id) }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="chinese-drug-form">
|
||||||
<Select
|
<Select
|
||||||
v-model:value="drug.id"
|
v-model:value="drug.id"
|
||||||
show-search
|
show-search
|
||||||
@@ -322,16 +436,50 @@ defineExpose({
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div class="chinese-drug-price">
|
<div class="chinese-drug-price">
|
||||||
¥{{ ((drug.price || 0) * (drug.number || 1)).toFixed(2) }}
|
<template v-if="priceEditable">
|
||||||
|
<div class="price-edit-row">
|
||||||
|
<span>售</span>
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="drug.price"
|
||||||
|
:min="0"
|
||||||
|
:precision="4"
|
||||||
|
:controls="false"
|
||||||
|
size="small"
|
||||||
|
style="width: 72px"
|
||||||
|
@change="onDrugNumberChange"
|
||||||
|
/>
|
||||||
|
<span>供</span>
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="drug.buy_price"
|
||||||
|
:min="0"
|
||||||
|
:precision="4"
|
||||||
|
:controls="false"
|
||||||
|
size="small"
|
||||||
|
style="width: 72px"
|
||||||
|
@change="onDrugNumberChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="price-line-total">
|
||||||
|
小计 ¥{{ ((drug.price || 0) * (drug.number || 1)).toFixed(2) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
¥{{ ((drug.price || 0) * (drug.number || 1)).toFixed(2) }}
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<Button type="link" class="chinese-drug-delete" @click="removeDrug(index)">
|
<Button
|
||||||
|
v-if="!structureReadonly"
|
||||||
|
type="link"
|
||||||
|
class="chinese-drug-delete"
|
||||||
|
@click="removeDrug(index)"
|
||||||
|
>
|
||||||
<DeleteTwoTone two-tone-color="#ff4d4f" />
|
<DeleteTwoTone two-tone-color="#ff4d4f" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col :xs="24" :sm="12" :md="8" :lg="8">
|
<Col v-if="!structureReadonly" :xs="24" :sm="12" :md="8" :lg="8">
|
||||||
<Card size="small" class="chinese-drug-card chinese-drug-card-new">
|
<Card size="small" class="chinese-drug-card chinese-drug-card-new">
|
||||||
<div class="chinese-drug-content">
|
<div class="chinese-drug-content">
|
||||||
<span class="chinese-drug-index">{{ drugList.length + 1 }}、</span>
|
<span class="chinese-drug-index">{{ drugList.length + 1 }}、</span>
|
||||||
@@ -427,6 +575,16 @@ defineExpose({
|
|||||||
max-width: 120px;
|
max-width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chinese-drug-readonly {
|
||||||
|
display: inline;
|
||||||
|
padding-left: 24px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chinese-drug-name-text {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.chinese-drug-comma {
|
.chinese-drug-comma {
|
||||||
@apply text-muted-foreground;
|
@apply text-muted-foreground;
|
||||||
}
|
}
|
||||||
@@ -440,6 +598,19 @@ defineExpose({
|
|||||||
right: 24px;
|
right: 24px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@apply text-destructive font-medium;
|
@apply text-destructive font-medium;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-edit-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-line-total {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chinese-drug-delete {
|
.chinese-drug-delete {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ const prescriptionType = ref<'chinese' | 'west' | 'granular'>('chinese');
|
|||||||
const chineseDrugEditorRef = ref<InstanceType<typeof ChineseDrugEditor>>();
|
const chineseDrugEditorRef = ref<InstanceType<typeof ChineseDrugEditor>>();
|
||||||
const dosage = ref(7);
|
const dosage = ref(7);
|
||||||
const dayDosage = ref(2);
|
const dayDosage = ref(2);
|
||||||
|
const clinicalDiagnose = ref('');
|
||||||
|
const doctorOrder = ref('');
|
||||||
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
fullscreenButton: true,
|
fullscreenButton: true,
|
||||||
@@ -38,12 +40,19 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
message.warning('请至少添加一种中药');
|
message.warning('请至少添加一种中药');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const diagnosisOrder =
|
||||||
|
chineseDrugEditorRef.value?.getDiagnosisOrderPayload?.() ?? {
|
||||||
|
clinical_diagnose: clinicalDiagnose.value,
|
||||||
|
doctor_order: doctorOrder.value,
|
||||||
|
};
|
||||||
const payload = buildSpecialPrescriptionPayload(detailRes.value, {
|
const payload = buildSpecialPrescriptionPayload(detailRes.value, {
|
||||||
drugs,
|
drugs,
|
||||||
dosage: dosage.value,
|
dosage: dosage.value,
|
||||||
day_dosage: dayDosage.value,
|
day_dosage: dayDosage.value,
|
||||||
rule_type: 1,
|
rule_type: 1,
|
||||||
package_method_id: 2,
|
package_method_id: 2,
|
||||||
|
clinical_diagnose: diagnosisOrder.clinical_diagnose ?? '',
|
||||||
|
doctor_order: diagnosisOrder.doctor_order ?? '',
|
||||||
});
|
});
|
||||||
modalApi.setState({ loading: true, confirmLoading: true });
|
modalApi.setState({ loading: true, confirmLoading: true });
|
||||||
updateSpecialPrescription(payload)
|
updateSpecialPrescription(payload)
|
||||||
@@ -65,12 +74,15 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
if (!res) return;
|
if (!res) return;
|
||||||
detailRes.value = res;
|
detailRes.value = res;
|
||||||
prescriptionType.value = res.prescription_type || 'chinese';
|
prescriptionType.value = res.prescription_type || 'chinese';
|
||||||
|
clinicalDiagnose.value = res.clinical_diagnose || '';
|
||||||
|
doctorOrder.value = res.doctor_order || '';
|
||||||
if (res.prescription_type === 'chinese' && res.prescription_detail?.length) {
|
if (res.prescription_type === 'chinese' && res.prescription_detail?.length) {
|
||||||
const first = res.prescription_detail[0];
|
const first = res.prescription_detail[0];
|
||||||
chineseDrugEditorRef.value?.loadDrugs(
|
chineseDrugEditorRef.value?.loadDrugs(
|
||||||
res.prescription_detail,
|
res.prescription_detail,
|
||||||
first?.dosage ?? 7,
|
first?.dosage ?? 7,
|
||||||
first?.consumption ?? 2,
|
first?.consumption ?? 2,
|
||||||
|
res.drug_prices || [],
|
||||||
);
|
);
|
||||||
dosage.value = first?.dosage ?? 7;
|
dosage.value = first?.dosage ?? 7;
|
||||||
dayDosage.value = first?.consumption ?? 2;
|
dayDosage.value = first?.consumption ?? 2;
|
||||||
@@ -80,6 +92,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
detailRes.value = null;
|
detailRes.value = null;
|
||||||
|
clinicalDiagnose.value = '';
|
||||||
|
doctorOrder.value = '';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -90,6 +104,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
<div v-if="prescriptionType === 'chinese'">
|
<div v-if="prescriptionType === 'chinese'">
|
||||||
<ChineseDrugEditor
|
<ChineseDrugEditor
|
||||||
ref="chineseDrugEditorRef"
|
ref="chineseDrugEditorRef"
|
||||||
|
v-model:clinical-diagnose="clinicalDiagnose"
|
||||||
|
v-model:doctor-order="doctorOrder"
|
||||||
v-model:dosage="dosage"
|
v-model:dosage="dosage"
|
||||||
v-model:day-dosage="dayDosage"
|
v-model:day-dosage="dayDosage"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import { Button, Card, Col, Row, Textarea } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import DiagnosisModal from '#/views/doctor/doctor-reception/components/DiagnosisModal.vue';
|
||||||
|
import DoctorOrderModal from '#/views/doctor/doctor-reception/components/DoctorOrderModal.vue';
|
||||||
|
|
||||||
|
/** 预选诊断、预选医嘱(与接诊开方交互一致) */
|
||||||
|
const clinicalDiagnose = defineModel<string>('clinicalDiagnose', { default: '' });
|
||||||
|
const doctorOrder = defineModel<string>('doctorOrder', { default: '' });
|
||||||
|
|
||||||
|
const [DiagnosisModals, DiagnosisModalApi] = useVbenModal({
|
||||||
|
connectedComponent: DiagnosisModal,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [DoctorOrderModals, DoctorOrderModalApi] = useVbenModal({
|
||||||
|
connectedComponent: DoctorOrderModal,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 打开常用诊断弹窗 */
|
||||||
|
function openDiagnosisModal() {
|
||||||
|
DiagnosisModalApi.setData({
|
||||||
|
values: clinicalDiagnose.value,
|
||||||
|
updateDiagnosis,
|
||||||
|
});
|
||||||
|
DiagnosisModalApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 常用诊断弹窗回调:写回预选诊断 */
|
||||||
|
function updateDiagnosis(values: string) {
|
||||||
|
clinicalDiagnose.value = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 打开常用医嘱弹窗 */
|
||||||
|
function openDoctorOrderModal() {
|
||||||
|
DoctorOrderModalApi.setData({
|
||||||
|
values: doctorOrder.value,
|
||||||
|
updateDoctorOrder,
|
||||||
|
});
|
||||||
|
DoctorOrderModalApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 常用医嘱弹窗回调:写回预选医嘱 */
|
||||||
|
function updateDoctorOrder(values: string) {
|
||||||
|
doctorOrder.value = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 供父组件读取当前值 */
|
||||||
|
const payload = computed(() => ({
|
||||||
|
clinical_diagnose: clinicalDiagnose.value || '',
|
||||||
|
doctor_order: doctorOrder.value || '',
|
||||||
|
}));
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getDiagnosisOrderPayload: () => payload.value,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Row :gutter="[12, 12]" class="prescription-meta-row mb-3">
|
||||||
|
<Col :xs="24" :md="12">
|
||||||
|
<Card size="small" class="chinese-drug-card prescription-meta-card">
|
||||||
|
<div class="prescription-meta-card__title">预选诊断</div>
|
||||||
|
<Button type="primary" class="mb-2" @click="openDiagnosisModal">
|
||||||
|
常用诊断
|
||||||
|
</Button>
|
||||||
|
<Textarea
|
||||||
|
v-model:value="clinicalDiagnose"
|
||||||
|
placeholder="输入诊断结果..."
|
||||||
|
:rows="3"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col :xs="24" :md="12">
|
||||||
|
<Card size="small" class="chinese-drug-card prescription-meta-card">
|
||||||
|
<div class="prescription-meta-card__title">预选医嘱</div>
|
||||||
|
<Button type="primary" class="mb-2" @click="openDoctorOrderModal">
|
||||||
|
常用医嘱
|
||||||
|
</Button>
|
||||||
|
<Textarea
|
||||||
|
v-model:value="doctorOrder"
|
||||||
|
placeholder="输入医嘱..."
|
||||||
|
:rows="3"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<DiagnosisModals />
|
||||||
|
<DoctorOrderModals />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.chinese-drug-card {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
:deep(.ant-card-body) {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prescription-meta-card {
|
||||||
|
min-height: 140px;
|
||||||
|
|
||||||
|
:deep(.ant-card-body) {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prescription-meta-card__title {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prescription-meta-row :deep(textarea) {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 72px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
border-radius: 4px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,339 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, nextTick, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import { Button, Col, InputNumber, message, Radio, RadioGroup, Row } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import ChineseDrugEditor from './ChineseDrugEditor.vue';
|
||||||
|
import SkuEditor, { type SkuItem } from './SkuEditor.vue';
|
||||||
|
import {
|
||||||
|
distributeDrugPricesApi,
|
||||||
|
getSpecialPrescriptionPriceConfig,
|
||||||
|
saveSpecialPrescriptionPriceConfig,
|
||||||
|
} from '../api';
|
||||||
|
|
||||||
|
/** 药品分摊价条目 */
|
||||||
|
interface DrugPriceItem {
|
||||||
|
drug_id: number;
|
||||||
|
buy_price: number;
|
||||||
|
sell_price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gridApi = ref<any>();
|
||||||
|
const configId = ref(0);
|
||||||
|
const configName = ref('');
|
||||||
|
const priceCalcScheme = ref(3);
|
||||||
|
const buyPricePerDose = ref(0);
|
||||||
|
const salePricePerDose = ref(0);
|
||||||
|
const skus = ref<SkuItem[]>([]);
|
||||||
|
const chineseDrugEditorRef = ref<InstanceType<typeof ChineseDrugEditor>>();
|
||||||
|
const skuEditorRef = ref<InstanceType<typeof SkuEditor>>();
|
||||||
|
|
||||||
|
/** 当前分摊视图:0=单帖,>0=SKU id */
|
||||||
|
const activeSkuId = ref(0);
|
||||||
|
/** 各 scope 分摊价缓存 sku_id -> prices[] */
|
||||||
|
const drugPricesCache = ref<Record<number, DrugPriceItem[]>>({});
|
||||||
|
const prescriptionDetailCache = ref<any[]>([]);
|
||||||
|
const prescriptionDosage = ref(7);
|
||||||
|
const prescriptionDayDosage = ref(2);
|
||||||
|
|
||||||
|
const showFixedPriceBlock = computed(() => priceCalcScheme.value === 1);
|
||||||
|
|
||||||
|
/** 左侧标题:单帖或 SKU 名称 */
|
||||||
|
const allocationTitle = computed(() => {
|
||||||
|
if (activeSkuId.value <= 0) {
|
||||||
|
return '单帖均摊价格';
|
||||||
|
}
|
||||||
|
const sku = skus.value.find((item) => Number(item.id) === Number(activeSkuId.value));
|
||||||
|
const name = sku?.sku_name || `${sku?.dose_count || ''}贴`;
|
||||||
|
return `${name} 均摊价格`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
fullscreenButton: true,
|
||||||
|
draggable: true,
|
||||||
|
onCancel() {
|
||||||
|
modalApi.close();
|
||||||
|
},
|
||||||
|
onConfirm: async () => {
|
||||||
|
if (configId.value <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
persistCurrentScopePrices();
|
||||||
|
const payload: Record<string, any> = {
|
||||||
|
id: configId.value,
|
||||||
|
price_calc_scheme: priceCalcScheme.value,
|
||||||
|
skus: skuEditorRef.value?.getSkusPayload() || skus.value,
|
||||||
|
};
|
||||||
|
if (priceCalcScheme.value === 1) {
|
||||||
|
payload.buy_price_per_dose = buyPricePerDose.value;
|
||||||
|
payload.sale_price_per_dose = salePricePerDose.value;
|
||||||
|
payload.drug_prices = drugPricesCache.value[0] || [];
|
||||||
|
const skuDrugPrices: Array<{ sku_id: number; drug_prices: DrugPriceItem[] }> = [];
|
||||||
|
Object.keys(drugPricesCache.value).forEach((key) => {
|
||||||
|
const skuId = Number(key);
|
||||||
|
if (skuId > 0 && drugPricesCache.value[skuId]?.length) {
|
||||||
|
skuDrugPrices.push({
|
||||||
|
sku_id: skuId,
|
||||||
|
drug_prices: drugPricesCache.value[skuId],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
payload.sku_drug_prices = skuDrugPrices;
|
||||||
|
}
|
||||||
|
modalApi.setState({ loading: true, confirmLoading: true });
|
||||||
|
saveSpecialPrescriptionPriceConfig(payload)
|
||||||
|
.then(() => {
|
||||||
|
message.success('价格配置保存成功');
|
||||||
|
gridApi.value?.reload();
|
||||||
|
modalApi.close();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
modalApi.setState({ loading: false, confirmLoading: false });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onOpenChange(isOpen: boolean) {
|
||||||
|
if (isOpen) {
|
||||||
|
const { values, gridApi: grid } = modalApi.getData<Record<string, any>>();
|
||||||
|
gridApi.value = grid;
|
||||||
|
configId.value = values?.id || 0;
|
||||||
|
activeSkuId.value = 0;
|
||||||
|
drugPricesCache.value = {};
|
||||||
|
if (!configId.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getSpecialPrescriptionPriceConfig(configId.value).then((res: any) => {
|
||||||
|
if (!res) return;
|
||||||
|
configName.value = res.name || '';
|
||||||
|
priceCalcScheme.value = res.price_calc_scheme ?? 3;
|
||||||
|
buyPricePerDose.value = res.buy_price_per_dose ?? 0;
|
||||||
|
salePricePerDose.value = res.sale_price_per_dose ?? res.price_per_dose ?? 0;
|
||||||
|
skus.value = res.skus || [];
|
||||||
|
skuEditorRef.value?.setSkus(res.skus || []);
|
||||||
|
|
||||||
|
prescriptionDetailCache.value = res.prescription_detail || [];
|
||||||
|
const first = prescriptionDetailCache.value[0];
|
||||||
|
prescriptionDosage.value = first?.dosage ?? 7;
|
||||||
|
prescriptionDayDosage.value = first?.consumption ?? 2;
|
||||||
|
|
||||||
|
drugPricesCache.value[0] = (res.drug_prices || []).map((item: any) => ({
|
||||||
|
drug_id: Number(item.drug_id),
|
||||||
|
buy_price: Number(item.buy_price || 0),
|
||||||
|
sell_price: Number(item.sell_price || item.price || 0),
|
||||||
|
}));
|
||||||
|
const bySku = res.drug_prices_by_sku || {};
|
||||||
|
Object.keys(bySku).forEach((skuKey) => {
|
||||||
|
drugPricesCache.value[Number(skuKey)] = (bySku[skuKey] || []).map((item: any) => ({
|
||||||
|
drug_id: Number(item.drug_id),
|
||||||
|
buy_price: Number(item.buy_price || 0),
|
||||||
|
sell_price: Number(item.sell_price || item.price || 0),
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
switchAllocationView(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(priceCalcScheme, (scheme) => {
|
||||||
|
if (scheme === 1) {
|
||||||
|
nextTick(() => switchAllocationView(activeSkuId.value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 将编辑器当前分摊写入缓存 */
|
||||||
|
function persistCurrentScopePrices() {
|
||||||
|
const prices = chineseDrugEditorRef.value?.getDrugPricesPayload() || [];
|
||||||
|
drugPricesCache.value[activeSkuId.value] = prices.map((item) => ({
|
||||||
|
drug_id: Number(item.drug_id),
|
||||||
|
buy_price: Number(item.buy_price || 0),
|
||||||
|
sell_price: Number(item.sell_price || 0),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 切换单帖 / SKU 分摊视图 */
|
||||||
|
function switchAllocationView(skuId: number) {
|
||||||
|
persistCurrentScopePrices();
|
||||||
|
activeSkuId.value = skuId;
|
||||||
|
const prices = drugPricesCache.value[skuId] || drugPricesCache.value[0] || [];
|
||||||
|
chineseDrugEditorRef.value?.loadDrugs(
|
||||||
|
prescriptionDetailCache.value,
|
||||||
|
prescriptionDosage.value,
|
||||||
|
prescriptionDayDosage.value,
|
||||||
|
prices,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSkuSelectForPrice(skuId: number) {
|
||||||
|
switchAllocationView(skuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function backToDoseAllocation() {
|
||||||
|
switchAllocationView(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 自动均分:单帖用 per_dose,SKU 用套餐总价 */
|
||||||
|
async function handleDistributePrices() {
|
||||||
|
const drugs = chineseDrugEditorRef.value?.getDrugsForDistribute() || [];
|
||||||
|
if (drugs.length === 0) {
|
||||||
|
message.warning('请先配置特色方药品');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let buyPrice = buyPricePerDose.value;
|
||||||
|
let salePrice = salePricePerDose.value;
|
||||||
|
if (activeSkuId.value > 0) {
|
||||||
|
const sku = skus.value.find((item) => Number(item.id) === Number(activeSkuId.value));
|
||||||
|
if (!sku) {
|
||||||
|
message.warning('请先保存 SKU 后再均分');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dose = Math.max(1, Number(sku.dose_count || 1));
|
||||||
|
buyPrice = Number(sku.buy_price || 0) / dose;
|
||||||
|
salePrice = Number(sku.sale_price || 0) / dose;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const result = await distributeDrugPricesApi({
|
||||||
|
drugs,
|
||||||
|
buy_price_per_dose: buyPrice,
|
||||||
|
sale_price_per_dose: salePrice,
|
||||||
|
buy_price: buyPrice,
|
||||||
|
sale_price: salePrice,
|
||||||
|
});
|
||||||
|
chineseDrugEditorRef.value?.applyDistributedPrices(result || []);
|
||||||
|
persistCurrentScopePrices();
|
||||||
|
message.success('已自动均分药品单价');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Modal :title="`价格配置 - ${configName}`" class="w-[90%]">
|
||||||
|
<div class="price-config-modal">
|
||||||
|
<div class="section-title">价格计算方案</div>
|
||||||
|
<RadioGroup v-model:value="priceCalcScheme">
|
||||||
|
<Radio :value="1">固定单价(含 SKU 快捷选贴)</Radio>
|
||||||
|
<Radio :value="3">门店浮动</Radio>
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<div v-if="showFixedPriceBlock" class="mt-4">
|
||||||
|
<Row :gutter="16">
|
||||||
|
<Col :span="12">
|
||||||
|
<div class="allocation-panel">
|
||||||
|
<div class="allocation-header">
|
||||||
|
<span class="allocation-title">{{ allocationTitle }}</span>
|
||||||
|
<Button
|
||||||
|
v-if="activeSkuId > 0"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
@click="backToDoseAllocation"
|
||||||
|
>
|
||||||
|
返回单帖均摊
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<ChineseDrugEditor
|
||||||
|
ref="chineseDrugEditorRef"
|
||||||
|
:price-editable="true"
|
||||||
|
:structure-readonly="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col :span="12">
|
||||||
|
<div class="section-title">固定单价</div>
|
||||||
|
<div class="price-row">
|
||||||
|
<div class="price-field">
|
||||||
|
<span class="label">一贴供货价</span>
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="buyPricePerDose"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="price-field">
|
||||||
|
<span class="label">一贴销售价</span>
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="salePricePerDose"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button type="primary" ghost @click="handleDistributePrices">
|
||||||
|
自动均分药品单价
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div class="section-title mt-4">SKU 规格(点击行查看分摊)</div>
|
||||||
|
<SkuEditor
|
||||||
|
ref="skuEditorRef"
|
||||||
|
v-model="skus"
|
||||||
|
:selected-price-sku-id="activeSkuId"
|
||||||
|
@select-for-price="handleSkuSelectForPrice"
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="mt-4 store-float-tip">
|
||||||
|
门店浮动方案无需配置药品分摊,SKU 仍可配置快捷选贴数。
|
||||||
|
<div class="section-title mt-4">SKU 规格</div>
|
||||||
|
<SkuEditor ref="skuEditorRef" v-model="skus" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.section-title {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.allocation-panel {
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
min-height: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.allocation-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.allocation-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
gap: 16px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-field {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-field .label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
color: #666;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.store-float-tip {
|
||||||
|
color: #666;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,278 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Input,
|
||||||
|
InputNumber,
|
||||||
|
Radio,
|
||||||
|
Select,
|
||||||
|
SelectOption,
|
||||||
|
Table,
|
||||||
|
} from 'ant-design-vue';
|
||||||
|
|
||||||
|
export interface SkuItem {
|
||||||
|
id?: number;
|
||||||
|
_key?: number;
|
||||||
|
sku_name: string;
|
||||||
|
dose_count: number;
|
||||||
|
buy_price?: number;
|
||||||
|
sale_price?: number;
|
||||||
|
status: number;
|
||||||
|
is_default?: number;
|
||||||
|
sort: number;
|
||||||
|
store_id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
modelValue?: SkuItem[];
|
||||||
|
/** 当前查看分摊的 SKU(0=单帖,在 PriceConfigModal 中由父组件控制) */
|
||||||
|
selectedPriceSkuId?: number;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
modelValue: () => [],
|
||||||
|
selectedPriceSkuId: 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:modelValue': [value: SkuItem[]];
|
||||||
|
/** 点击行切换左侧分摊视图 */
|
||||||
|
'select-for-price': [skuId: number];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const skuList = ref<SkuItem[]>([]);
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: '默认', key: 'is_default', width: 70 },
|
||||||
|
{ title: 'SKU名称', key: 'sku_name', width: 120 },
|
||||||
|
{ title: '贴数', key: 'dose_count', width: 90 },
|
||||||
|
{ title: '供货总价', key: 'buy_price', width: 110 },
|
||||||
|
{ title: '销售总价', key: 'sale_price', width: 110 },
|
||||||
|
{ title: '状态', key: 'status', width: 90 },
|
||||||
|
{ title: '排序', key: 'sort', width: 80 },
|
||||||
|
{ title: '操作', key: 'action', width: 70 },
|
||||||
|
];
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(val) => {
|
||||||
|
skuList.value = (val || []).map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
_key: item._key ?? item.id ?? Date.now() + index,
|
||||||
|
sort: item.sort ?? index,
|
||||||
|
store_id: item.store_id ?? 0,
|
||||||
|
status: item.status ?? 1,
|
||||||
|
is_default: item.is_default ?? 0,
|
||||||
|
buy_price: item.buy_price ?? 0,
|
||||||
|
sale_price: item.sale_price ?? 0,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
function syncToParent() {
|
||||||
|
emit('update:modelValue', [...skuList.value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSku() {
|
||||||
|
skuList.value.push({
|
||||||
|
_key: Date.now(),
|
||||||
|
sku_name: '',
|
||||||
|
dose_count: 7,
|
||||||
|
buy_price: 0,
|
||||||
|
sale_price: 0,
|
||||||
|
status: 1,
|
||||||
|
is_default: skuList.value.length === 0 ? 1 : 0,
|
||||||
|
sort: skuList.value.length,
|
||||||
|
store_id: 0,
|
||||||
|
});
|
||||||
|
syncToParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeSku(index: number) {
|
||||||
|
const removed = skuList.value[index];
|
||||||
|
const removedDefault = removed?.is_default === 1;
|
||||||
|
const removedId = Number(removed?.id || 0);
|
||||||
|
skuList.value.splice(index, 1);
|
||||||
|
if (removedDefault && skuList.value.length > 0) {
|
||||||
|
skuList.value[0].is_default = 1;
|
||||||
|
}
|
||||||
|
syncToParent();
|
||||||
|
if (removedId > 0 && props.selectedPriceSkuId === removedId) {
|
||||||
|
emit('select-for-price', 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDefault(index: number) {
|
||||||
|
skuList.value.forEach((item, i) => {
|
||||||
|
item.is_default = i === index ? 1 : 0;
|
||||||
|
});
|
||||||
|
syncToParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFieldChange() {
|
||||||
|
syncToParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 点击行查看该 SKU 分摊(需已保存有 id) */
|
||||||
|
function onRowClick(record: SkuItem) {
|
||||||
|
const skuId = Number(record.id || 0);
|
||||||
|
if (skuId <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('select-for-price', skuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function customRow(record: SkuItem) {
|
||||||
|
const skuId = Number(record.id || 0);
|
||||||
|
return {
|
||||||
|
class: skuId > 0 && skuId === Number(props.selectedPriceSkuId)
|
||||||
|
? 'sku-row--price-active'
|
||||||
|
: '',
|
||||||
|
onClick: () => onRowClick(record),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getSkusPayload: () => skuList.value,
|
||||||
|
setSkus: (skus: SkuItem[]) => {
|
||||||
|
skuList.value = (skus || []).map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
_key: item._key ?? item.id ?? Date.now() + index,
|
||||||
|
sort: item.sort ?? index,
|
||||||
|
store_id: item.store_id ?? 0,
|
||||||
|
is_default: item.is_default ?? 0,
|
||||||
|
buy_price: item.buy_price ?? 0,
|
||||||
|
sale_price: item.sale_price ?? 0,
|
||||||
|
}));
|
||||||
|
syncToParent();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="sku-editor">
|
||||||
|
<div class="sku-editor-header">
|
||||||
|
<span class="font-medium">SKU 规格(快捷选贴数,价格为套餐总价)</span>
|
||||||
|
<Button type="dashed" size="small" @click="addSku">
|
||||||
|
<PlusOutlined />
|
||||||
|
添加 SKU
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
:columns="columns"
|
||||||
|
:data-source="skuList"
|
||||||
|
:pagination="false"
|
||||||
|
:custom-row="customRow"
|
||||||
|
row-key="_key"
|
||||||
|
size="small"
|
||||||
|
bordered
|
||||||
|
class="mt-2 sku-table"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record, index }">
|
||||||
|
<template v-if="column.key === 'is_default'">
|
||||||
|
<Radio
|
||||||
|
:checked="record.is_default === 1"
|
||||||
|
@click.stop="setDefault(index)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'sku_name'">
|
||||||
|
<Input
|
||||||
|
v-model:value="record.sku_name"
|
||||||
|
placeholder="如 7贴"
|
||||||
|
@click.stop
|
||||||
|
@change="onFieldChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'dose_count'">
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="record.dose_count"
|
||||||
|
:min="1"
|
||||||
|
:max="99"
|
||||||
|
style="width: 100%"
|
||||||
|
@click.stop
|
||||||
|
@change="onFieldChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'buy_price'">
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="record.buy_price"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
style="width: 100%"
|
||||||
|
@click.stop
|
||||||
|
@change="onFieldChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'sale_price'">
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="record.sale_price"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
style="width: 100%"
|
||||||
|
@click.stop
|
||||||
|
@change="onFieldChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'status'">
|
||||||
|
<Select
|
||||||
|
v-model:value="record.status"
|
||||||
|
style="width: 100%"
|
||||||
|
@click.stop
|
||||||
|
@change="onFieldChange"
|
||||||
|
>
|
||||||
|
<SelectOption :value="1">上架</SelectOption>
|
||||||
|
<SelectOption :value="0">下架</SelectOption>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'sort'">
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="record.sort"
|
||||||
|
:min="0"
|
||||||
|
style="width: 100%"
|
||||||
|
@click.stop
|
||||||
|
@change="onFieldChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'action'">
|
||||||
|
<Button type="link" danger size="small" @click.stop="removeSku(index)">
|
||||||
|
<DeleteOutlined />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
|
<div v-if="skuList.length === 0" class="sku-empty-tip">
|
||||||
|
暂无 SKU,用户端将使用手动输入贴数
|
||||||
|
</div>
|
||||||
|
<div v-else class="sku-hint">
|
||||||
|
点击已保存的 SKU 行可在左侧查看/编辑该规格分摊价
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sku-editor-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-empty-tip,
|
||||||
|
.sku-hint {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.sku-row--price-active) {
|
||||||
|
background-color: #e6f4ff !important;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.sku-table .ant-table-row) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -22,6 +22,9 @@ const chineseDrugEditorRef = ref<InstanceType<typeof ChineseDrugEditor>>();
|
|||||||
const dosage = ref(7);
|
const dosage = ref(7);
|
||||||
const dayDosage = ref(2);
|
const dayDosage = ref(2);
|
||||||
const drugsChanged = ref(false);
|
const drugsChanged = ref(false);
|
||||||
|
/** 预选诊断/医嘱(在药品列表气泡卡中编辑) */
|
||||||
|
const clinicalDiagnose = ref('');
|
||||||
|
const doctorOrder = ref('');
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm(modalFormProps);
|
const [Form, formApi] = useVbenForm(modalFormProps);
|
||||||
|
|
||||||
@@ -64,6 +67,14 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
.filter(Boolean),
|
.filter(Boolean),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const diagnosisOrder =
|
||||||
|
chineseDrugEditorRef.value?.getDiagnosisOrderPayload?.() ?? {
|
||||||
|
clinical_diagnose: clinicalDiagnose.value,
|
||||||
|
doctor_order: doctorOrder.value,
|
||||||
|
};
|
||||||
|
payload.clinical_diagnose = diagnosisOrder.clinical_diagnose ?? '';
|
||||||
|
payload.doctor_order = diagnosisOrder.doctor_order ?? '';
|
||||||
|
|
||||||
if (prescriptionType.value === 'chinese' && drugs.length > 0) {
|
if (prescriptionType.value === 'chinese' && drugs.length > 0) {
|
||||||
payload.drugs = drugs;
|
payload.drugs = drugs;
|
||||||
payload.dosage = dosage.value;
|
payload.dosage = dosage.value;
|
||||||
@@ -110,6 +121,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
intro_text: res.intro_text || '',
|
intro_text: res.intro_text || '',
|
||||||
introduction_images: res.introduction_images || [],
|
introduction_images: res.introduction_images || [],
|
||||||
});
|
});
|
||||||
|
clinicalDiagnose.value = res.clinical_diagnose || '';
|
||||||
|
doctorOrder.value = res.doctor_order || '';
|
||||||
if (res.prescription_type === 'chinese' && res.prescription_detail?.length) {
|
if (res.prescription_type === 'chinese' && res.prescription_detail?.length) {
|
||||||
const first = res.prescription_detail[0];
|
const first = res.prescription_detail[0];
|
||||||
chineseDrugEditorRef.value?.loadDrugs(
|
chineseDrugEditorRef.value?.loadDrugs(
|
||||||
@@ -140,6 +153,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||||||
intro_text: '',
|
intro_text: '',
|
||||||
introduction_images: [],
|
introduction_images: [],
|
||||||
});
|
});
|
||||||
|
clinicalDiagnose.value = '';
|
||||||
|
doctorOrder.value = '';
|
||||||
chineseDrugEditorRef.value?.loadDrugs([], 7, 2);
|
chineseDrugEditorRef.value?.loadDrugs([], 7, 2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -168,6 +183,8 @@ function bindPrescriptionTypeChange() {
|
|||||||
<div v-if="prescriptionType === 'chinese'" class="mt-4 border-t pt-4">
|
<div v-if="prescriptionType === 'chinese'" class="mt-4 border-t pt-4">
|
||||||
<ChineseDrugEditor
|
<ChineseDrugEditor
|
||||||
ref="chineseDrugEditorRef"
|
ref="chineseDrugEditorRef"
|
||||||
|
v-model:clinical-diagnose="clinicalDiagnose"
|
||||||
|
v-model:doctor-order="doctorOrder"
|
||||||
v-model:dosage="dosage"
|
v-model:dosage="dosage"
|
||||||
v-model:day-dosage="dayDosage"
|
v-model:day-dosage="dayDosage"
|
||||||
@update:model-value="drugsChanged = true"
|
@update:model-value="drugsChanged = true"
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export const modalFormProps: VbenFormProps = {
|
|||||||
{
|
{
|
||||||
component: 'InputNumber',
|
component: 'InputNumber',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '每剂价格',
|
placeholder: '展示兜底价/贴',
|
||||||
min: 0,
|
min: 0,
|
||||||
precision: 2,
|
precision: 2,
|
||||||
style: { width: '100%' },
|
style: { width: '100%' },
|
||||||
@@ -106,6 +106,20 @@ export const modalFormProps: VbenFormProps = {
|
|||||||
formItemClass: 'col-span-6',
|
formItemClass: 'col-span-6',
|
||||||
defaultValue: 1,
|
defaultValue: 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: 'VbenSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '是否包邮',
|
||||||
|
options: [
|
||||||
|
{ label: '不包邮', value: 0 },
|
||||||
|
{ label: '包邮', value: 1 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
fieldName: 'is_free_shipping',
|
||||||
|
label: '是否包邮',
|
||||||
|
formItemClass: 'col-span-6',
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: 'VbenSelect',
|
component: 'VbenSelect',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
updateSpecialPrescriptionStatus,
|
updateSpecialPrescriptionStatus,
|
||||||
} from './api';
|
} from './api';
|
||||||
import EditPrescriptionModal from './components/EditPrescriptionModal.vue';
|
import EditPrescriptionModal from './components/EditPrescriptionModal.vue';
|
||||||
|
import PriceConfigModal from './components/PriceConfigModal.vue';
|
||||||
import SpecialPrescriptionModal from './components/modal.vue';
|
import SpecialPrescriptionModal from './components/modal.vue';
|
||||||
import { formOptions as searchFormOptions } from './config/search';
|
import { formOptions as searchFormOptions } from './config/search';
|
||||||
import { gridOptions } from './config/table';
|
import { gridOptions } from './config/table';
|
||||||
@@ -47,6 +48,10 @@ const [EditPrescriptionModalComp, editPrescriptionModalApi] = useVbenModal({
|
|||||||
connectedComponent: EditPrescriptionModal,
|
connectedComponent: EditPrescriptionModal,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [PriceConfigModalComp, priceConfigModalApi] = useVbenModal({
|
||||||
|
connectedComponent: PriceConfigModal,
|
||||||
|
});
|
||||||
|
|
||||||
const showModal = (data = {}, isUpdate = false) => {
|
const showModal = (data = {}, isUpdate = false) => {
|
||||||
formModalApi.setData({
|
formModalApi.setData({
|
||||||
values: data,
|
values: data,
|
||||||
@@ -64,6 +69,14 @@ const showEditPrescriptionModal = (row: any) => {
|
|||||||
editPrescriptionModalApi.open();
|
editPrescriptionModalApi.open();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showPriceConfigModal = (row: any) => {
|
||||||
|
priceConfigModalApi.setData({
|
||||||
|
values: row,
|
||||||
|
gridApi,
|
||||||
|
});
|
||||||
|
priceConfigModalApi.open();
|
||||||
|
};
|
||||||
|
|
||||||
/** 点击状态 Tag 切换上下架 */
|
/** 点击状态 Tag 切换上下架 */
|
||||||
const toggleStatus = async (row: any) => {
|
const toggleStatus = async (row: any) => {
|
||||||
if (statusLoadingId.value === row.id) {
|
if (statusLoadingId.value === row.id) {
|
||||||
@@ -98,6 +111,7 @@ const deleteApi = (row: any) => {
|
|||||||
<Page auto-content-height title="特色方管理">
|
<Page auto-content-height title="特色方管理">
|
||||||
<FormModal />
|
<FormModal />
|
||||||
<EditPrescriptionModalComp />
|
<EditPrescriptionModalComp />
|
||||||
|
<PriceConfigModalComp />
|
||||||
|
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<TableAction
|
<TableAction
|
||||||
@@ -161,6 +175,10 @@ const deleteApi = (row: any) => {
|
|||||||
ifShow: row.prescription_sub_type === 1,
|
ifShow: row.prescription_sub_type === 1,
|
||||||
onClick: () => showEditPrescriptionModal(row),
|
onClick: () => showEditPrescriptionModal(row),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '价格配置',
|
||||||
|
onClick: () => showPriceConfigModal(row),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '删除',
|
label: '删除',
|
||||||
color: 'error',
|
color: 'error',
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ export function buildSpecialPrescriptionPayload(
|
|||||||
day_dosage?: number;
|
day_dosage?: number;
|
||||||
rule_type?: number;
|
rule_type?: number;
|
||||||
package_method_id?: number;
|
package_method_id?: number;
|
||||||
|
clinical_diagnose?: string;
|
||||||
|
doctor_order?: string;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const payload: Record<string, any> = {
|
const payload: Record<string, any> = {
|
||||||
@@ -20,9 +22,12 @@ export function buildSpecialPrescriptionPayload(
|
|||||||
price_per_dose: detail.price_per_dose ?? 0,
|
price_per_dose: detail.price_per_dose ?? 0,
|
||||||
sales_count: detail.sales_count ?? 0,
|
sales_count: detail.sales_count ?? 0,
|
||||||
status: detail.status ?? 1,
|
status: detail.status ?? 1,
|
||||||
|
is_free_shipping: detail.is_free_shipping ?? 0,
|
||||||
prescription_type: detail.prescription_type || 'chinese',
|
prescription_type: detail.prescription_type || 'chinese',
|
||||||
intro_text: detail.intro_text || '',
|
intro_text: detail.intro_text || '',
|
||||||
introduction_images: detail.introduction_images || [],
|
introduction_images: detail.introduction_images || [],
|
||||||
|
clinical_diagnose: detail.clinical_diagnose || '',
|
||||||
|
doctor_order: detail.doctor_order || '',
|
||||||
};
|
};
|
||||||
if (drugOverrides?.drugs?.length) {
|
if (drugOverrides?.drugs?.length) {
|
||||||
payload.drugs = drugOverrides.drugs;
|
payload.drugs = drugOverrides.drugs;
|
||||||
@@ -31,5 +36,11 @@ export function buildSpecialPrescriptionPayload(
|
|||||||
payload.rule_type = drugOverrides.rule_type ?? 1;
|
payload.rule_type = drugOverrides.rule_type ?? 1;
|
||||||
payload.package_method_id = drugOverrides.package_method_id ?? 2;
|
payload.package_method_id = drugOverrides.package_method_id ?? 2;
|
||||||
}
|
}
|
||||||
|
if (drugOverrides?.clinical_diagnose !== undefined) {
|
||||||
|
payload.clinical_diagnose = drugOverrides.clinical_diagnose;
|
||||||
|
}
|
||||||
|
if (drugOverrides?.doctor_order !== undefined) {
|
||||||
|
payload.doctor_order = drugOverrides.doctor_order;
|
||||||
|
}
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { Image, Tag } from 'ant-design-vue';
|
||||||
|
|
||||||
|
/** 患者选方记录(含特色方封面、SKU 等) */
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
record: Record<string, any> | null;
|
||||||
|
purchaseLabel?: string;
|
||||||
|
loading?: boolean;
|
||||||
|
/** 是否可点击导入(有待导入/已应用记录时) */
|
||||||
|
clickable?: boolean;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
purchaseLabel: '',
|
||||||
|
loading: false,
|
||||||
|
clickable: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
apply: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
/** 封面图 */
|
||||||
|
const coverImage = computed(
|
||||||
|
() => props.record?.special_prescription?.cover_image || '',
|
||||||
|
);
|
||||||
|
/** 药方名称 */
|
||||||
|
const prescriptionName = computed(
|
||||||
|
() => props.record?.special_prescription?.name || '特色方',
|
||||||
|
);
|
||||||
|
/** 状态文案与颜色 */
|
||||||
|
const statusMeta = computed(() => {
|
||||||
|
const status = Number(props.record?.status ?? -1);
|
||||||
|
if (status === 0) return { text: '待导入', color: 'orange' as const };
|
||||||
|
if (status === 1) return { text: '已应用', color: 'green' as const };
|
||||||
|
return { text: '已完成', color: 'default' as const };
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击卡片触发导入
|
||||||
|
* loading 或不可点击时不响应
|
||||||
|
*/
|
||||||
|
function handleCardClick() {
|
||||||
|
if (!props.clickable || props.loading) return;
|
||||||
|
emit('apply');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="record"
|
||||||
|
class="sp-import-card mt-4 rounded-lg border p-3 transition-shadow
|
||||||
|
bg-[#fffaf5] border-[#ffe0c2]
|
||||||
|
dark:bg-[#2c2419] dark:border-[#5c4a32]"
|
||||||
|
:class="{
|
||||||
|
'sp-import-card--clickable cursor-pointer hover:shadow-md dark:hover:shadow-[0_2px_8px_rgba(255,152,0,0.25)]':
|
||||||
|
clickable && !loading,
|
||||||
|
'sp-import-card--loading': loading,
|
||||||
|
}"
|
||||||
|
@click="handleCardClick"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="sp-import-card__hint mb-2.5 text-[13px] text-[#fa8c16] dark:text-[#ffa940]"
|
||||||
|
>
|
||||||
|
点击卡片导入药方
|
||||||
|
</div>
|
||||||
|
<div class="sp-import-card__body flex flex-wrap items-center gap-4">
|
||||||
|
<Image
|
||||||
|
v-if="coverImage"
|
||||||
|
:src="coverImage"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
class="sp-import-card__cover shrink-0 rounded object-cover"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="sp-import-card__cover sp-import-card__cover--placeholder flex h-20 w-20 shrink-0 items-center justify-center rounded text-xs
|
||||||
|
bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400"
|
||||||
|
>
|
||||||
|
无封面
|
||||||
|
</div>
|
||||||
|
<div class="sp-import-card__info min-w-0 flex-1">
|
||||||
|
<div
|
||||||
|
class="sp-import-card__name text-base font-semibold text-gray-900 dark:text-gray-100"
|
||||||
|
>
|
||||||
|
{{ prescriptionName }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="sp-import-card__sku mt-1 text-sm text-gray-600 dark:text-gray-400"
|
||||||
|
>
|
||||||
|
规格:{{ purchaseLabel || '单剂' }}
|
||||||
|
</div>
|
||||||
|
<Tag class="sp-import-card__tag mt-2" :color="statusMeta.color">
|
||||||
|
{{ statusMeta.text }}
|
||||||
|
</Tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sp-import-card--loading {
|
||||||
|
opacity: 0.75;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -52,6 +52,7 @@ import {
|
|||||||
withdrawPrescriptionApi,
|
withdrawPrescriptionApi,
|
||||||
} from '#/views/doctor/doctor-reception/api';
|
} from '#/views/doctor/doctor-reception/api';
|
||||||
|
|
||||||
|
import SpecialPrescriptionImportCard from './components/SpecialPrescriptionImportCard.vue';
|
||||||
import DiagnosisModal from './components/DiagnosisModal.vue';
|
import DiagnosisModal from './components/DiagnosisModal.vue';
|
||||||
import DoctorOrderModal from './components/DoctorOrderModal.vue';
|
import DoctorOrderModal from './components/DoctorOrderModal.vue';
|
||||||
import PrescriptionDetail from './components/PrescriptionDetail.vue';
|
import PrescriptionDetail from './components/PrescriptionDetail.vue';
|
||||||
@@ -108,6 +109,8 @@ interface Patient {
|
|||||||
status: number;
|
status: number;
|
||||||
special_prescription_id: number;
|
special_prescription_id: number;
|
||||||
dose_count: number;
|
dose_count: number;
|
||||||
|
sku_id?: number;
|
||||||
|
sku_name?: string;
|
||||||
special_prescription?: {
|
special_prescription?: {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -346,7 +349,40 @@ const hasSpecialPrescriptionRecord = computed(
|
|||||||
const specialPrescriptionRecord = computed(
|
const specialPrescriptionRecord = computed(
|
||||||
() => patientInfo.value?.special_prescription_patient_record ?? null,
|
() => patientInfo.value?.special_prescription_patient_record ?? null,
|
||||||
);
|
);
|
||||||
|
/** 导入卡片规格:SKU 名或单剂 */
|
||||||
|
function resolveSpecialPrescriptionPurchaseLabel(
|
||||||
|
record?: { sku_id?: number; sku_name?: string } | null,
|
||||||
|
) {
|
||||||
|
if (!record) return '';
|
||||||
|
return Number(record.sku_id) > 0
|
||||||
|
? (record.sku_name || 'SKU套餐')
|
||||||
|
: '单剂';
|
||||||
|
}
|
||||||
|
const specialPrescriptionPurchaseLabel = computed(() =>
|
||||||
|
resolveSpecialPrescriptionPurchaseLabel(specialPrescriptionRecord.value),
|
||||||
|
);
|
||||||
const applyingSpecialPrescription = ref(false);
|
const applyingSpecialPrescription = ref(false);
|
||||||
|
/** 医生已导入的特色方 ID,仅 >0 时提交走特色方计价 */
|
||||||
|
const appliedSpecialPrescriptionId = ref(0);
|
||||||
|
/** apply 返回的 SKU/贴数套餐总价,用于底部合计 */
|
||||||
|
const appliedSpecialPrescriptionExpectedTotal = ref<number | null>(null);
|
||||||
|
function clearAppliedSpecialPrescription() {
|
||||||
|
appliedSpecialPrescriptionId.value = 0;
|
||||||
|
appliedSpecialPrescriptionExpectedTotal.value = null;
|
||||||
|
}
|
||||||
|
/** 已应用特色方时锁定药方(不可改删增) */
|
||||||
|
const isSpecialPrescriptionCartLocked = computed(
|
||||||
|
() => appliedSpecialPrescriptionId.value > 0,
|
||||||
|
);
|
||||||
|
const SP_CART_LOCK_MSG = '特色方药方不可修改,请先清空药方';
|
||||||
|
/** 特色方锁定中则提示并返回 true */
|
||||||
|
function guardSpecialPrescriptionCartEdit(): boolean {
|
||||||
|
if (isSpecialPrescriptionCartLocked.value) {
|
||||||
|
message.warning(SP_CART_LOCK_MSG);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const diagnosis = ref('');
|
const diagnosis = ref('');
|
||||||
const medicalAdvice = ref('');
|
const medicalAdvice = ref('');
|
||||||
const treatmentPrice = ref(0);
|
const treatmentPrice = ref(0);
|
||||||
@@ -398,6 +434,7 @@ function selectProductChange(id) {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
function selectDrugUseWayChange(id) {
|
function selectDrugUseWayChange(id) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
if (
|
if (
|
||||||
selectProductIndex.value < 0 ||
|
selectProductIndex.value < 0 ||
|
||||||
selectProductIndex.value >= currentDrugs.value.length
|
selectProductIndex.value >= currentDrugs.value.length
|
||||||
@@ -417,6 +454,14 @@ function selectDrugUseWayChange(id) {
|
|||||||
* 计算商品总价
|
* 计算商品总价
|
||||||
*/
|
*/
|
||||||
const totalProductCost = computed(() => {
|
const totalProductCost = computed(() => {
|
||||||
|
const expected = appliedSpecialPrescriptionExpectedTotal.value;
|
||||||
|
if (
|
||||||
|
expected != null
|
||||||
|
&& !Number.isNaN(Number(expected))
|
||||||
|
&& Number(expected) > 0
|
||||||
|
) {
|
||||||
|
return Number(expected);
|
||||||
|
}
|
||||||
if (currentDrugs.value.length === 0) {
|
if (currentDrugs.value.length === 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -509,6 +554,7 @@ const setVisible = (value, instruction = ''): void => {
|
|||||||
* @param isUpdateTabType
|
* @param isUpdateTabType
|
||||||
*/
|
*/
|
||||||
const selectPatient = (patient: Patient, isUpdateTabType = true) => {
|
const selectPatient = (patient: Patient, isUpdateTabType = true) => {
|
||||||
|
clearAppliedSpecialPrescription();
|
||||||
selectPatientId.value = patient.id;
|
selectPatientId.value = patient.id;
|
||||||
receptionStatus.value = patient.status;
|
receptionStatus.value = patient.status;
|
||||||
if (isUpdateTabType === true) {
|
if (isUpdateTabType === true) {
|
||||||
@@ -561,12 +607,14 @@ const selectPatient = (patient: Patient, isUpdateTabType = true) => {
|
|||||||
|
|
||||||
// 数量增加
|
// 数量增加
|
||||||
const increment = (index: number) => {
|
const increment = (index: number) => {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
currentDrugs.value[index].select_number++;
|
currentDrugs.value[index].select_number++;
|
||||||
saveToLocalStorage();
|
saveToLocalStorage();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 数量减少
|
// 数量减少
|
||||||
const decrement = (index: number) => {
|
const decrement = (index: number) => {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
if (currentDrugs.value[index].select_number > 1) {
|
if (currentDrugs.value[index].select_number > 1) {
|
||||||
currentDrugs.value[index].select_number--;
|
currentDrugs.value[index].select_number--;
|
||||||
saveToLocalStorage();
|
saveToLocalStorage();
|
||||||
@@ -575,6 +623,7 @@ const decrement = (index: number) => {
|
|||||||
|
|
||||||
// 切换药品用法编辑状态
|
// 切换药品用法编辑状态
|
||||||
const toggleEditDrug = (index: number) => {
|
const toggleEditDrug = (index: number) => {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
currentDrugs.value[index].isEditing = !currentDrugs.value[index].isEditing;
|
currentDrugs.value[index].isEditing = !currentDrugs.value[index].isEditing;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -635,6 +684,7 @@ function clearCartPriceDiscount() {
|
|||||||
const priceDiscountLabel = computed(() => formatPriceDiscountLabel(priceDiscount.value));
|
const priceDiscountLabel = computed(() => formatPriceDiscountLabel(priceDiscount.value));
|
||||||
|
|
||||||
function openOrderPriceAdjust() {
|
function openOrderPriceAdjust() {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
if (!priceAdjustEnabled.value || !currentDrugs.value.length) return;
|
if (!priceAdjustEnabled.value || !currentDrugs.value.length) return;
|
||||||
currentDrugs.value = snapshotDrugOrigins(currentDrugs.value);
|
currentDrugs.value = snapshotDrugOrigins(currentDrugs.value);
|
||||||
const discount = Number(priceDiscount.value);
|
const discount = Number(priceDiscount.value);
|
||||||
@@ -654,6 +704,7 @@ function openOrderPriceAdjust() {
|
|||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
const removeDrug = (index: number) => {
|
const removeDrug = (index: number) => {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
currentDrugs.value.splice(index, 1);
|
currentDrugs.value.splice(index, 1);
|
||||||
updateLocalStorage();
|
updateLocalStorage();
|
||||||
};
|
};
|
||||||
@@ -790,6 +841,7 @@ const sendPrescription = () => {
|
|||||||
doctor_second_sign: doctorSecondSign.value,
|
doctor_second_sign: doctorSecondSign.value,
|
||||||
salesperson_transfer_prescription_id: salespersonTransferPrescriptionId.value || undefined,
|
salesperson_transfer_prescription_id: salespersonTransferPrescriptionId.value || undefined,
|
||||||
price_discount: priceDiscount.value,
|
price_discount: priceDiscount.value,
|
||||||
|
special_prescription_id: appliedSpecialPrescriptionId.value || 0,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
message.success('处方已发送');
|
message.success('处方已发送');
|
||||||
|
|
||||||
@@ -807,17 +859,10 @@ const sendPrescription = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清空当前数据
|
// 清空当前数据
|
||||||
currentDrugs.value = [];
|
clearPrescriptionCart(false);
|
||||||
diagnosis.value = '';
|
|
||||||
medicalAdvice.value = '';
|
|
||||||
packageMethodId.value = 2;
|
|
||||||
processRulePrice.value = 0;
|
|
||||||
dosage.value = 7;
|
|
||||||
dayDosage.value = 2;
|
|
||||||
tabType.value = 1;
|
tabType.value = 1;
|
||||||
salespersonTransferPrescriptionId.value = 0;
|
salespersonTransferPrescriptionId.value = 0;
|
||||||
newDrugInfo.value = {};
|
processRulePrice.value = 0;
|
||||||
updateLocalStorage();
|
|
||||||
checkSalespersonTransfer();
|
checkSalespersonTransfer();
|
||||||
|
|
||||||
// 刷新患者信息
|
// 刷新患者信息
|
||||||
@@ -898,7 +943,7 @@ const [DoctorOrderModals, DoctorOrderModalApi] = useVbenModal({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const openDoctorOrderModal = () => {
|
const openDoctorOrderModal = () => {
|
||||||
// 打开常用诊断模态框逻辑
|
// 打开常用医嘱模态框逻辑
|
||||||
DoctorOrderModalApi.setData({
|
DoctorOrderModalApi.setData({
|
||||||
values: medicalAdvice.value,
|
values: medicalAdvice.value,
|
||||||
updateDoctorOrder,
|
updateDoctorOrder,
|
||||||
@@ -953,6 +998,7 @@ function openCommonPrescriptionModal() {
|
|||||||
* @description 选择常用方后,将药品列表填充到当前处方中
|
* @description 选择常用方后,将药品列表填充到当前处方中
|
||||||
*/
|
*/
|
||||||
async function handleSelectCommonPrescription(data: any, type: number) {
|
async function handleSelectCommonPrescription(data: any, type: number) {
|
||||||
|
clearAppliedSpecialPrescription();
|
||||||
const { prescription, recipes } = data;
|
const { prescription, recipes } = data;
|
||||||
|
|
||||||
// 根据类型处理药品:整表覆盖为常用方内容,不与当前处方按药品 ID 去重合并
|
// 根据类型处理药品:整表覆盖为常用方内容,不与当前处方按药品 ID 去重合并
|
||||||
@@ -1069,6 +1115,10 @@ async function handleApplySpecialPrescription(switchToPrescription = false) {
|
|||||||
typeMap[prescriptionType] || 2,
|
typeMap[prescriptionType] || 2,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
appliedSpecialPrescriptionId.value = Number(res.special_prescription_id) || 0;
|
||||||
|
appliedSpecialPrescriptionExpectedTotal.value =
|
||||||
|
res.expected_total_price != null ? Number(res.expected_total_price) : null;
|
||||||
|
|
||||||
if (selectPatientId.value) {
|
if (selectPatientId.value) {
|
||||||
const value = await getPatientItem(selectPatientId.value);
|
const value = await getPatientItem(selectPatientId.value);
|
||||||
patientInfo.value = value;
|
patientInfo.value = value;
|
||||||
@@ -1197,6 +1247,7 @@ const cancelSaveCommonPrescription = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openWesternModal = () => {
|
const openWesternModal = () => {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
// 判断是否为简单产品类型(3,5,6,7)
|
// 判断是否为简单产品类型(3,5,6,7)
|
||||||
const simpleProductTypes = [3, 5, 6, 7];
|
const simpleProductTypes = [3, 5, 6, 7];
|
||||||
if (simpleProductTypes.includes(activeCategory.value)) {
|
if (simpleProductTypes.includes(activeCategory.value)) {
|
||||||
@@ -1674,6 +1725,7 @@ loadProcessRuleData();
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
function selectProcessRule(id) {
|
function selectProcessRule(id) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
processRuleId.value = id;
|
processRuleId.value = id;
|
||||||
loadProcessRuleData(id); // 加载煎法选项
|
loadProcessRuleData(id); // 加载煎法选项
|
||||||
}
|
}
|
||||||
@@ -1683,6 +1735,7 @@ function selectProcessRule(id) {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
function selectProcessRuleNot(id) {
|
function selectProcessRuleNot(id) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
childProcessRuleId.value = id;
|
childProcessRuleId.value = id;
|
||||||
loadProcessRuleData(0, id); // 加载备注选项
|
loadProcessRuleData(0, id); // 加载备注选项
|
||||||
}
|
}
|
||||||
@@ -1692,6 +1745,7 @@ function selectProcessRuleNot(id) {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
function selectProcessRuleNotCommit(id) {
|
function selectProcessRuleNotCommit(id) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
processRuleNoteId.value = id;
|
processRuleNoteId.value = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1702,6 +1756,7 @@ const packageMethod = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
function selectPackageMethod(id) {
|
function selectPackageMethod(id) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
packageMethodId.value = id;
|
packageMethodId.value = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1709,6 +1764,41 @@ function selectPackageMethod(id) {
|
|||||||
const dosage = ref(7);
|
const dosage = ref(7);
|
||||||
const dayDosage = ref(2);
|
const dayDosage = ref(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空药方:退出特色方 SKU 计价状态,恢复可编辑
|
||||||
|
* @param showToast 是否提示成功
|
||||||
|
*/
|
||||||
|
function clearPrescriptionCart(showToast = true) {
|
||||||
|
currentDrugs.value = [];
|
||||||
|
diagnosis.value = '';
|
||||||
|
medicalAdvice.value = '';
|
||||||
|
packageMethodId.value = 2;
|
||||||
|
dosage.value = 7;
|
||||||
|
dayDosage.value = 2;
|
||||||
|
newDrugInfo.value = {};
|
||||||
|
clearAppliedSpecialPrescription();
|
||||||
|
priceDiscount.value = 100;
|
||||||
|
updateLocalStorage();
|
||||||
|
if (showToast) {
|
||||||
|
message.success('已清空药方');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 清空药方(有药品时二次确认) */
|
||||||
|
function handleClearPrescriptionCart() {
|
||||||
|
if (currentDrugs.value.length === 0 && !appliedSpecialPrescriptionId.value) {
|
||||||
|
message.info('当前无药方内容');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AntModal.confirm({
|
||||||
|
title: '清空药方',
|
||||||
|
content: '确定清空当前药方吗?特色方将需重新应用。',
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => clearPrescriptionCart(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function updateChineseNumber() {
|
function updateChineseNumber() {
|
||||||
updateLocalStorage();
|
updateLocalStorage();
|
||||||
}
|
}
|
||||||
@@ -1833,6 +1923,7 @@ const selectChineseId = ref(0);
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
function selectOldDrugInfo(id) {
|
function selectOldDrugInfo(id) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
const check = JSON.parse(
|
const check = JSON.parse(
|
||||||
localStorage.getItem(getStorageKey(activePatient.value?.id, activeCategory.value)) || '[]',
|
localStorage.getItem(getStorageKey(activePatient.value?.id, activeCategory.value)) || '[]',
|
||||||
).find((v) => v.id === id);
|
).find((v) => v.id === id);
|
||||||
@@ -1923,6 +2014,7 @@ function searchOption(inputValue) {
|
|||||||
* 添加中药
|
* 添加中药
|
||||||
*/
|
*/
|
||||||
function addDrugByChinese() {
|
function addDrugByChinese() {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
// 如果是新药品输入框,调用添加新药品方法
|
// 如果是新药品输入框,调用添加新药品方法
|
||||||
const check = currentDrugs.value.find(
|
const check = currentDrugs.value.find(
|
||||||
(v) => v.id === newDrugInfo.value.id,
|
(v) => v.id === newDrugInfo.value.id,
|
||||||
@@ -1976,6 +2068,7 @@ function selectDrugByNewDrugInfo(event: KeyboardEvent, isNewDrug: boolean) {
|
|||||||
* @param {object} data - 商品对象
|
* @param {object} data - 商品对象
|
||||||
*/
|
*/
|
||||||
function addProducts(data) {
|
function addProducts(data) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
// 查找是否已存在于选择列表中
|
// 查找是否已存在于选择列表中
|
||||||
const existItem = currentDrugs.value.find(
|
const existItem = currentDrugs.value.find(
|
||||||
(item) => item.index_id === data.id,
|
(item) => item.index_id === data.id,
|
||||||
@@ -2046,6 +2139,7 @@ function addProducts(data) {
|
|||||||
* @param drug 选中的药品数据
|
* @param drug 选中的药品数据
|
||||||
*/
|
*/
|
||||||
function handleSimpleProductSelect(drug: any) {
|
function handleSimpleProductSelect(drug: any) {
|
||||||
|
if (guardSpecialPrescriptionCartEdit()) return;
|
||||||
// 检查是否已存在
|
// 检查是否已存在
|
||||||
const existItem = currentDrugs.value.find(
|
const existItem = currentDrugs.value.find(
|
||||||
(item) => item.id === (drug._drugId || drug.drug_id || drug.drug?.id),
|
(item) => item.id === (drug._drugId || drug.drug_id || drug.drug?.id),
|
||||||
@@ -2285,52 +2379,13 @@ watch(
|
|||||||
}}
|
}}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
<Card
|
<SpecialPrescriptionImportCard
|
||||||
v-if="specialPrescriptionRecord"
|
v-if="specialPrescriptionRecord && hasSpecialPrescriptionRecord"
|
||||||
class="mt-5"
|
:record="specialPrescriptionRecord"
|
||||||
title="特色方"
|
:purchase-label="specialPrescriptionPurchaseLabel"
|
||||||
>
|
:loading="applyingSpecialPrescription"
|
||||||
<div class="flex flex-wrap items-center gap-4">
|
@apply="handleApplySpecialPrescription(true)"
|
||||||
<Image
|
/>
|
||||||
v-if="specialPrescriptionRecord.special_prescription?.cover_image"
|
|
||||||
:src="specialPrescriptionRecord.special_prescription.cover_image"
|
|
||||||
:width="80"
|
|
||||||
:height="80"
|
|
||||||
class="rounded object-cover"
|
|
||||||
/>
|
|
||||||
<div class="flex-1">
|
|
||||||
<div class="text-base font-medium">
|
|
||||||
{{ specialPrescriptionRecord.special_prescription?.name || '特色方' }}
|
|
||||||
</div>
|
|
||||||
<div class="mt-1 text-gray-500">
|
|
||||||
剂量:{{ specialPrescriptionRecord.dose_count }} 剂
|
|
||||||
</div>
|
|
||||||
<Tag
|
|
||||||
v-if="specialPrescriptionRecord.status === 0"
|
|
||||||
class="mt-2"
|
|
||||||
color="orange"
|
|
||||||
>
|
|
||||||
待导入
|
|
||||||
</Tag>
|
|
||||||
<Tag
|
|
||||||
v-else-if="specialPrescriptionRecord.status === 1"
|
|
||||||
class="mt-2"
|
|
||||||
color="green"
|
|
||||||
>
|
|
||||||
已应用
|
|
||||||
</Tag>
|
|
||||||
<Tag v-else class="mt-2" color="default">已完成</Tag>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
v-if="hasSpecialPrescriptionRecord"
|
|
||||||
type="primary"
|
|
||||||
:loading="applyingSpecialPrescription"
|
|
||||||
@click="handleApplySpecialPrescription(true)"
|
|
||||||
>
|
|
||||||
导入
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
<Descriptions
|
<Descriptions
|
||||||
v-if="userPatientHealthInquiry"
|
v-if="userPatientHealthInquiry"
|
||||||
:column="{ xxl: 2, xl: 2, lg: 2, md: 2, sm: 2, xs: 2 }"
|
:column="{ xxl: 2, xl: 2, lg: 2, md: 2, sm: 2, xs: 2 }"
|
||||||
@@ -2520,15 +2575,23 @@ watch(
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<SpecialPrescriptionImportCard
|
||||||
|
v-if="hasSpecialPrescriptionRecord"
|
||||||
|
class="mt-5 max-w-xl"
|
||||||
|
:record="specialPrescriptionRecord"
|
||||||
|
:purchase-label="specialPrescriptionPurchaseLabel"
|
||||||
|
:loading="applyingSpecialPrescription"
|
||||||
|
@apply="() => handleApplySpecialPrescription()"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
<Button
|
<Button
|
||||||
v-if="activeCategory === 2"
|
v-if="activeCategory === 2 && !isSpecialPrescriptionCartLocked"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="openWesternModal"
|
@click="openWesternModal"
|
||||||
>
|
>
|
||||||
添加商品
|
添加商品
|
||||||
</Button>
|
</Button>
|
||||||
<!-- 常用方按钮(产品服务包/非药品/医疗器械无模板接口) -->
|
|
||||||
<Button
|
<Button
|
||||||
v-if="canUseCommonPrescription"
|
v-if="canUseCommonPrescription"
|
||||||
type="primary"
|
type="primary"
|
||||||
@@ -2537,15 +2600,6 @@ watch(
|
|||||||
>
|
>
|
||||||
选择常用方
|
选择常用方
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
v-if="hasSpecialPrescriptionRecord"
|
|
||||||
type="primary"
|
|
||||||
class="ml-3"
|
|
||||||
:loading="applyingSpecialPrescription"
|
|
||||||
@click="() => handleApplySpecialPrescription()"
|
|
||||||
>
|
|
||||||
应用特色方
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
v-if="canUseCommonPrescription"
|
v-if="canUseCommonPrescription"
|
||||||
type="default"
|
type="default"
|
||||||
@@ -2555,6 +2609,14 @@ watch(
|
|||||||
<SaveOutlined />
|
<SaveOutlined />
|
||||||
保存常用方
|
保存常用方
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
danger
|
||||||
|
class="ml-3"
|
||||||
|
@click="handleClearPrescriptionCart"
|
||||||
|
>
|
||||||
|
清空药方
|
||||||
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
v-if="activeCategory === 1 && hasSalespersonTransfer"
|
v-if="activeCategory === 1 && hasSalespersonTransfer"
|
||||||
type="default"
|
type="default"
|
||||||
@@ -2613,6 +2675,7 @@ watch(
|
|||||||
<p>
|
<p>
|
||||||
<Select
|
<Select
|
||||||
v-model:value="drug.id"
|
v-model:value="drug.id"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
:filter-option="false"
|
:filter-option="false"
|
||||||
class="old-select-drug-name"
|
class="old-select-drug-name"
|
||||||
style="min-width: 100px"
|
style="min-width: 100px"
|
||||||
@@ -2639,6 +2702,7 @@ watch(
|
|||||||
,
|
,
|
||||||
<InputNumber
|
<InputNumber
|
||||||
v-model:value="drug.number"
|
v-model:value="drug.number"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
:class="`w-1/5 old-number-input-${index}`"
|
:class="`w-1/5 old-number-input-${index}`"
|
||||||
style="min-width: 100px"
|
style="min-width: 100px"
|
||||||
:controls="false"
|
:controls="false"
|
||||||
@@ -2651,6 +2715,7 @@ watch(
|
|||||||
<span>
|
<span>
|
||||||
<Select
|
<Select
|
||||||
:value="drug?.way_id"
|
:value="drug?.way_id"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
placeholder="用法"
|
placeholder="用法"
|
||||||
@change="selectDrugUseWayChange"
|
@change="selectDrugUseWayChange"
|
||||||
@dropdown-visible-change="
|
@dropdown-visible-change="
|
||||||
@@ -2677,6 +2742,7 @@ watch(
|
|||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
|
v-if="!isSpecialPrescriptionCartLocked"
|
||||||
class="card-delete"
|
class="card-delete"
|
||||||
type="link"
|
type="link"
|
||||||
@click="removeDrug(index)"
|
@click="removeDrug(index)"
|
||||||
@@ -2688,6 +2754,7 @@ watch(
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col
|
<Col
|
||||||
|
v-if="!isSpecialPrescriptionCartLocked"
|
||||||
:lg="12"
|
:lg="12"
|
||||||
:md="12"
|
:md="12"
|
||||||
:sm="12"
|
:sm="12"
|
||||||
@@ -2943,6 +3010,7 @@ watch(
|
|||||||
<span>用法:</span>
|
<span>用法:</span>
|
||||||
<Select
|
<Select
|
||||||
:value="drug.use_type?.id"
|
:value="drug.use_type?.id"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
@change="(val) => updateDrugUsage(index, 'use_type', drugUseType.find(item => item.id === val))"
|
@change="(val) => updateDrugUsage(index, 'use_type', drugUseType.find(item => item.id === val))"
|
||||||
@@ -2953,6 +3021,7 @@ watch(
|
|||||||
</Select>
|
</Select>
|
||||||
<Select
|
<Select
|
||||||
:value="drug.use_frequency?.id"
|
:value="drug.use_frequency?.id"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 100px; margin-left: 4px"
|
style="width: 100px; margin-left: 4px"
|
||||||
@change="(val) => updateDrugUsage(index, 'use_frequency', drugUseFrequency.find(item => item.id === val))"
|
@change="(val) => updateDrugUsage(index, 'use_frequency', drugUseFrequency.find(item => item.id === val))"
|
||||||
@@ -2963,6 +3032,7 @@ watch(
|
|||||||
</Select>
|
</Select>
|
||||||
<Select
|
<Select
|
||||||
:value="drug.use_num?.id"
|
:value="drug.use_num?.id"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 80px; margin-left: 4px"
|
style="width: 80px; margin-left: 4px"
|
||||||
@change="(val) => updateDrugUsage(index, 'use_num', drugTime.find(item => item.id === val))"
|
@change="(val) => updateDrugUsage(index, 'use_num', drugTime.find(item => item.id === val))"
|
||||||
@@ -2974,12 +3044,14 @@ watch(
|
|||||||
<span style="margin-left: 4px">每次</span>
|
<span style="margin-left: 4px">每次</span>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
v-model:value="drug.number"
|
v-model:value="drug.number"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
:min="1"
|
:min="1"
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 60px; margin-left: 4px"
|
style="width: 60px; margin-left: 4px"
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
:value="drug.unit?.id"
|
:value="drug.unit?.id"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
size="small"
|
size="small"
|
||||||
style="width: 60px; margin-left: 4px"
|
style="width: 60px; margin-left: 4px"
|
||||||
@change="(val) => updateDrugUsage(index, 'unit', drugUnit.find(item => item.id === val))"
|
@change="(val) => updateDrugUsage(index, 'unit', drugUnit.find(item => item.id === val))"
|
||||||
@@ -3001,15 +3073,15 @@ watch(
|
|||||||
</InputNumber>
|
</InputNumber>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="quantity-control">
|
<div v-else class="quantity-control">
|
||||||
<Button type="primary" @click="decrement(index)">-</Button>
|
<Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="decrement(index)">-</Button>
|
||||||
<span style="margin: 0 20px">{{ drug.select_number }}</span>
|
<span style="margin: 0 20px">{{ drug.select_number }}</span>
|
||||||
<Button type="primary" @click="increment(index)">+</Button>
|
<Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="increment(index)">+</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>{{ drug.price }}</span>
|
<span>{{ drug.price }}</span>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
v-if="activeCategory !== 1 && !drug.isEditing"
|
v-if="activeCategory !== 1 && !drug.isEditing && !isSpecialPrescriptionCartLocked"
|
||||||
type="link"
|
type="link"
|
||||||
@click="toggleEditDrug(index)"
|
@click="toggleEditDrug(index)"
|
||||||
>编辑</Button>
|
>编辑</Button>
|
||||||
@@ -3018,7 +3090,7 @@ watch(
|
|||||||
type="link"
|
type="link"
|
||||||
@click="saveEditDrug(index)"
|
@click="saveEditDrug(index)"
|
||||||
>保存</Button>
|
>保存</Button>
|
||||||
<Button type="link" @click="removeDrug(index)">删除</Button>
|
<Button v-if="!isSpecialPrescriptionCartLocked" type="link" @click="removeDrug(index)">删除</Button>
|
||||||
<Button
|
<Button
|
||||||
v-if="drug.instruction !== ''"
|
v-if="drug.instruction !== ''"
|
||||||
type="link"
|
type="link"
|
||||||
@@ -3036,6 +3108,7 @@ watch(
|
|||||||
<!-- 搜索组件 -->
|
<!-- 搜索组件 -->
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<DrugSearchSelect
|
<DrugSearchSelect
|
||||||
|
v-if="!isSpecialPrescriptionCartLocked"
|
||||||
:type="activeCategory"
|
:type="activeCategory"
|
||||||
:store-id="myStoreId"
|
:store-id="myStoreId"
|
||||||
:placeholder="`输入${categories.find(c => c.value === activeCategory)?.label || '商品'}名称搜索`"
|
:placeholder="`输入${categories.find(c => c.value === activeCategory)?.label || '商品'}名称搜索`"
|
||||||
@@ -3067,14 +3140,14 @@ watch(
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="quantity-control">
|
<div class="quantity-control">
|
||||||
<Button type="primary" @click="decrement(index)">-</Button>
|
<Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="decrement(index)">-</Button>
|
||||||
<span style="margin: 0 20px">{{ drug.select_number }}</span>
|
<span style="margin: 0 20px">{{ drug.select_number }}</span>
|
||||||
<Button type="primary" @click="increment(index)">+</Button>
|
<Button type="primary" :disabled="isSpecialPrescriptionCartLocked" @click="increment(index)">+</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>{{ drug.price }}</span>
|
<span>{{ drug.price }}</span>
|
||||||
<div>
|
<div>
|
||||||
<Button type="link" @click="removeDrug(index)">删除</Button>
|
<Button v-if="!isSpecialPrescriptionCartLocked" type="link" @click="removeDrug(index)">删除</Button>
|
||||||
<Button
|
<Button
|
||||||
v-if="drug.instruction !== ''"
|
v-if="drug.instruction !== ''"
|
||||||
type="link"
|
type="link"
|
||||||
@@ -3091,7 +3164,7 @@ watch(
|
|||||||
<!-- 诊断和医嘱 -->
|
<!-- 诊断和医嘱 -->
|
||||||
<div class="diagnosis-area">
|
<div class="diagnosis-area">
|
||||||
<div v-if="activeCategory === 1" class="mb-5">
|
<div v-if="activeCategory === 1" class="mb-5">
|
||||||
<RadioGroup v-model:value="ruleType">
|
<RadioGroup v-model:value="ruleType" :disabled="isSpecialPrescriptionCartLocked">
|
||||||
<RadioButton :value="1">自制剂</RadioButton>
|
<RadioButton :value="1">自制剂</RadioButton>
|
||||||
<RadioButton :value="2">委托调剂</RadioButton>
|
<RadioButton :value="2">委托调剂</RadioButton>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
@@ -3099,6 +3172,7 @@ watch(
|
|||||||
<!-- 选择包法-->
|
<!-- 选择包法-->
|
||||||
<Select
|
<Select
|
||||||
:value="packageMethodId"
|
:value="packageMethodId"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
class="mt-3 w-1/5"
|
class="mt-3 w-1/5"
|
||||||
placeholder="请选择包法"
|
placeholder="请选择包法"
|
||||||
@change="selectPackageMethod"
|
@change="selectPackageMethod"
|
||||||
@@ -3116,6 +3190,7 @@ watch(
|
|||||||
<!-- 选择制剂-->
|
<!-- 选择制剂-->
|
||||||
<Select
|
<Select
|
||||||
v-model:value="processRuleId"
|
v-model:value="processRuleId"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
class="mt-3 w-1/5"
|
class="mt-3 w-1/5"
|
||||||
placeholder="请选择制剂"
|
placeholder="请选择制剂"
|
||||||
@change="selectProcessRule"
|
@change="selectProcessRule"
|
||||||
@@ -3131,6 +3206,7 @@ watch(
|
|||||||
<!-- 选择规格-->
|
<!-- 选择规格-->
|
||||||
<Select
|
<Select
|
||||||
v-model:value="childProcessRuleId"
|
v-model:value="childProcessRuleId"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
class="ml-3 mt-3 w-1/5"
|
class="ml-3 mt-3 w-1/5"
|
||||||
placeholder="请选择煎法"
|
placeholder="请选择煎法"
|
||||||
@change="selectProcessRuleNot"
|
@change="selectProcessRuleNot"
|
||||||
@@ -3146,6 +3222,7 @@ watch(
|
|||||||
<!-- 选择备注-->
|
<!-- 选择备注-->
|
||||||
<Select
|
<Select
|
||||||
v-model:value="processRuleNoteId"
|
v-model:value="processRuleNoteId"
|
||||||
|
:disabled="isSpecialPrescriptionCartLocked"
|
||||||
class="ml-3 mt-3 w-1/5"
|
class="ml-3 mt-3 w-1/5"
|
||||||
placeholder="请选择备注"
|
placeholder="请选择备注"
|
||||||
@change="selectProcessRuleNotCommit"
|
@change="selectProcessRuleNotCommit"
|
||||||
@@ -3161,17 +3238,17 @@ watch(
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
用量:
|
用量:
|
||||||
<InputNumber v-model:value="dosage" class="w-1/5">
|
<InputNumber v-model:value="dosage" :disabled="isSpecialPrescriptionCartLocked" class="w-1/5">
|
||||||
<template #addonBefore>
|
<template #addonBefore>
|
||||||
<MinusOutlined
|
<MinusOutlined
|
||||||
key="prop"
|
key="prop"
|
||||||
@click="dosage = dosage > 1 ? dosage - 1 : 1"
|
@click="!isSpecialPrescriptionCartLocked && (dosage = dosage > 1 ? dosage - 1 : 1)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #addonAfter>
|
<template #addonAfter>
|
||||||
<PlusOutlined
|
<PlusOutlined
|
||||||
key="add"
|
key="add"
|
||||||
@click="dosage = dosage < 100 ? dosage + 1 : 100"
|
@click="!isSpecialPrescriptionCartLocked && (dosage = dosage < 100 ? dosage + 1 : 100)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</InputNumber>
|
</InputNumber>
|
||||||
@@ -3179,27 +3256,37 @@ watch(
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
频次:
|
频次:
|
||||||
<InputNumber v-model:value="dayDosage" class="w-1/5">
|
<InputNumber v-model:value="dayDosage" :disabled="isSpecialPrescriptionCartLocked" class="w-1/5">
|
||||||
<template #addonBefore>
|
<template #addonBefore>
|
||||||
<MinusOutlined
|
<MinusOutlined
|
||||||
key="prop"
|
key="prop"
|
||||||
@click="dayDosage = dayDosage > 1 ? dayDosage - 1 : 1"
|
@click="!isSpecialPrescriptionCartLocked && (dayDosage = dayDosage > 1 ? dayDosage - 1 : 1)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #addonAfter>
|
<template #addonAfter>
|
||||||
<PlusOutlined
|
<PlusOutlined
|
||||||
key="add"
|
key="add"
|
||||||
@click="dayDosage = dayDosage < 100 ? dayDosage + 1 : 100"
|
@click="!isSpecialPrescriptionCartLocked && (dayDosage = dayDosage < 100 ? dayDosage + 1 : 100)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</InputNumber>
|
</InputNumber>
|
||||||
次/天
|
次/天
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button type="primary" @click="openDiagnosisModal">常用诊断</Button>
|
<Button type="primary" @click="openDiagnosisModal">
|
||||||
<Textarea v-model:value="diagnosis" placeholder="输入诊断结果..."/>
|
常用诊断
|
||||||
<Button type="primary" @click="openDoctorOrderModal">常用医嘱</Button>
|
</Button>
|
||||||
<Textarea v-model:value="medicalAdvice" placeholder="输入医嘱..."/>
|
<Textarea
|
||||||
|
v-model:value="diagnosis"
|
||||||
|
placeholder="输入诊断结果..."
|
||||||
|
/>
|
||||||
|
<Button type="primary" @click="openDoctorOrderModal">
|
||||||
|
常用医嘱
|
||||||
|
</Button>
|
||||||
|
<Textarea
|
||||||
|
v-model:value="medicalAdvice"
|
||||||
|
placeholder="输入医嘱..."
|
||||||
|
/>
|
||||||
诊疗费用:
|
诊疗费用:
|
||||||
<InputNumber
|
<InputNumber
|
||||||
v-model:value="treatmentPrice"
|
v-model:value="treatmentPrice"
|
||||||
@@ -3215,7 +3302,7 @@ watch(
|
|||||||
<div class="total-cost">
|
<div class="total-cost">
|
||||||
商品价格:
|
商品价格:
|
||||||
<Button
|
<Button
|
||||||
v-if="priceAdjustEnabled && currentDrugs.length"
|
v-if="priceAdjustEnabled && currentDrugs.length && !isSpecialPrescriptionCartLocked"
|
||||||
type="link"
|
type="link"
|
||||||
class="!p-0"
|
class="!p-0"
|
||||||
@click="openOrderPriceAdjust"
|
@click="openOrderPriceAdjust"
|
||||||
@@ -3257,6 +3344,14 @@ watch(
|
|||||||
>
|
>
|
||||||
发送处方
|
发送处方
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="canUseCommonPrescription && currentDrugs.length"
|
||||||
|
type="link"
|
||||||
|
class="mt-2 w-full"
|
||||||
|
@click="openSaveCommonPrescriptionModal"
|
||||||
|
>
|
||||||
|
保存为常用方
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Page>
|
</Page>
|
||||||
<div v-else-if="tabType === 0" class="prescription-panel">
|
<div v-else-if="tabType === 0" class="prescription-panel">
|
||||||
|
|||||||
Reference in New Issue
Block a user