feat:诊所问题优化,气泡卡片优化,修复了导入药品的时候无法打开开方组件并且切换tab的问题

This commit is contained in:
李琦
2026-07-28 14:23:50 +08:00
parent 05885ed405
commit 5506c8917f
5 changed files with 154 additions and 15 deletions

View File

@@ -1,10 +0,0 @@
---
description:
alwaysApply: true
---
1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则
2. 注意不要生成太多的空行上一部分代码和下一部分代码中间的空行不要大于2行
3. 有封装好的方法、组件需要复用,不要重复造轮子
4. 小程序端的抽屉全部需要用page-container来防止用户意外退出页面记得使用v-if而不是v-show
5. 数据库的created_at、updated_at、deleted_at统一使用时间戳不要使用字符串并且我在查询器中一级格式化成字符串了无需再次格式化

View File

@@ -582,8 +582,25 @@ export const usePrescriptionStore = defineStore('prescription', () => {
} }
}, 300); }, 300);
// 药品操作 /**
* 从商品/药品数据解析处方分类 tab与 activeCategory 对齐)
* 1 中药 / 2 西药 / 3 保健食品 / 5 产品服务包 / 6 非药品 / 7 医疗器械
* 缺省按西药 2避免挂号选药误入中药开方
*/
const resolveDrugCategory = (data: any): number => {
const raw = data?.drug?.type ?? data?.type;
const n = Number(raw);
if (Number.isFinite(n) && n > 0) return n;
return 2;
};
// 药品操作:写入前按药型自动切到对应 tab避免西药落入中药开方组件
const addProducts = (data: any) => { const addProducts = (data: any) => {
const targetCategory = resolveDrugCategory(data);
if (Number(activeCategory.value) !== targetCategory) {
changeCategory(targetCategory);
}
const existItem = currentDrugs.value.find( const existItem = currentDrugs.value.find(
(item) => item.index_id === data.id, (item) => item.index_id === data.id,
); );
@@ -1077,6 +1094,38 @@ export const usePrescriptionStore = defineStore('prescription', () => {
}, },
userStore.currentUser.doctor_id, userStore.currentUser.doctor_id,
); );
// 在线复诊开方后自动连发购药指引与用药温馨提示
const tipTexts = [
'根据您的病情描述,已为您开具电子处方,请点击上方的‘立即支付’,进行购药;如有商品价格和订单等问题请咨询平台客服。',
'温馨提示:用药前请详细阅读药品说明书,并严格按照线下医嘱用药。如用药过程中出现病情变化或其它不适症状,请立即停药并及时就医。(请您注意,如果您尚未在医院就诊或未曾使用过本次申请的药品,请暂时不要支付订单。我们建议您在医生的指导下使用药品,以确保用药安全。)',
];
tipTexts.forEach((tip, tipIdx) => {
sendMessage({
roomId: chatStore.currentFriend.room_id,
senderId: userStore.currentUser.doctor_id,
receiverId: chatStore.currentFriend.id,
type: 'text',
content: tip,
});
chatStore.addMessage(
{
id: `${Date.now()}_tip_${tipIdx}`,
room_id: chatStore.currentFriend.room_id,
sender_user_id: `doctor-${userStore.currentUser.doctor_id}`,
receiver_user_id: chatStore.currentFriend.id,
message_type: 0,
message_content: tip,
messageTypeName: 'text',
created_at: Date.now() + tipIdx + 1,
created_at_text: new Date().toLocaleTimeString().slice(0, 5),
timestamp: Date.now() + tipIdx + 1,
isSent: true,
read: true,
duration: 0,
},
userStore.currentUser.doctor_id,
);
});
resetForm(); resetForm();
// 发送成功后清空本挂号下全部分类草稿(含另一分类与 activeCategory // 发送成功后清空本挂号下全部分类草稿(含另一分类与 activeCategory
clearLocalPrescriptionCache(); clearLocalPrescriptionCache();
@@ -1240,6 +1289,7 @@ export const usePrescriptionStore = defineStore('prescription', () => {
resetInitializationState, resetInitializationState,
getDrugList, getDrugList,
addProducts, addProducts,
resolveDrugCategory,
removeDrug, removeDrug,
updateDrugQuantity, updateDrugQuantity,
increment, increment,

View File

@@ -1,13 +1,29 @@
<script setup> <script setup>
/**
* 诊所复诊 type11 follow_up_drug 助理用药确认卡
* 展示问题、药品、是否用过、适用症/补充;可一键导入处方单
*/
import { computed } from 'vue'; import { computed } from 'vue';
import { Button } from 'ant-design-vue';
const props = defineProps({ const props = defineProps({
content: { content: {
type: Object, type: Object,
required: true, required: true,
}, },
/** 是否展示「添加到处方单」(接诊中且有药) */
showAddToRx: {
type: Boolean,
default: false,
},
addToRxLoading: {
type: Boolean,
default: false,
},
}); });
const emit = defineEmits(['add-to-rx']);
const data = computed(() => const data = computed(() =>
typeof props.content === 'string' typeof props.content === 'string'
? (() => { ? (() => {
@@ -30,6 +46,25 @@ const answeredLabel = computed(() => {
const drugs = computed(() => const drugs = computed(() =>
Array.isArray(data.value.drugs) ? data.value.drugs : [], Array.isArray(data.value.drugs) ? data.value.drugs : [],
); );
/** 适用症文案(有值才展示) */
const illnessInfo = computed(() => {
const v = data.value.illness_info;
return v != null && String(v).trim() ? String(v).trim() : '';
});
/**
* 补充信息:优先独立字段;若 illness_info 已含「;补充:」且无独立字段则不重复展示
*/
const supplementText = computed(() => {
const v = data.value.supplement;
if (v != null && String(v).trim()) return String(v).trim();
return '';
});
const canShowAddBtn = computed(
() => props.showAddToRx && drugs.value.length > 0,
);
</script> </script>
<template> <template>
@@ -63,12 +98,36 @@ const drugs = computed(() =>
<span class="value">{{ answeredLabel }}</span> <span class="value">{{ answeredLabel }}</span>
</div> </div>
<div v-if="illnessInfo" class="info-block">
<div class="info-block-label">适用症/症状</div>
<div class="info-block-content">{{ illnessInfo }}</div>
</div>
<div v-if="supplementText" class="info-block">
<div class="info-block-label">补充信息</div>
<div class="info-block-content">{{ supplementText }}</div>
</div>
<div <div
v-else-if="data.answer_status === 'pending'" v-else-if="!answeredLabel && data.answer_status === 'pending'"
class="pending-tip" class="pending-tip"
> >
待患者在小程序端填写用药信息 待患者在小程序端填写用药信息
</div> </div>
<div v-if="canShowAddBtn" class="add-rx-wrap">
<Button
:loading="addToRxLoading"
block
size="small"
type="primary"
ghost
@click.stop="emit('add-to-rx')"
>
<i class="fas fa-plus-circle mr-1"></i>
添加到处方单
</Button>
</div>
</div> </div>
</template> </template>
@@ -122,7 +181,7 @@ const drugs = computed(() =>
} }
.answer-row { .answer-row {
@apply flex items-center justify-between rounded-lg bg-emerald-50 px-3 py-2 text-sm dark:bg-emerald-900/30; @apply mb-3 flex items-center justify-between rounded-lg bg-emerald-50 px-3 py-2 text-sm dark:bg-emerald-900/30;
} }
.answer-row .label { .answer-row .label {
@@ -133,7 +192,23 @@ const drugs = computed(() =>
@apply font-medium text-emerald-800 dark:text-emerald-300; @apply font-medium text-emerald-800 dark:text-emerald-300;
} }
.info-block {
@apply mb-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-900/50;
}
.info-block-label {
@apply mb-1 text-xs text-slate-500 dark:text-slate-400;
}
.info-block-content {
@apply text-sm leading-relaxed text-slate-800 dark:text-slate-100;
}
.pending-tip { .pending-tip {
@apply rounded-lg border border-dashed border-amber-200 bg-amber-50 px-3 py-2 text-center text-xs text-amber-800 dark:border-amber-700 dark:bg-amber-900/20 dark:text-amber-200; @apply rounded-lg border border-dashed border-amber-200 bg-amber-50 px-3 py-2 text-center text-xs text-amber-800 dark:border-amber-700 dark:bg-amber-900/20 dark:text-amber-200;
} }
.add-rx-wrap {
@apply mt-3 border-t border-slate-100 pt-3 dark:border-slate-600;
}
</style> </style>

View File

@@ -251,10 +251,15 @@ const canAddRegisterDrugsToRx = computed(() => {
const handleAddRegisterDrugsToPrescription = async () => { const handleAddRegisterDrugsToPrescription = async () => {
if (registerAddToRxLoading.value) return; if (registerAddToRxLoading.value) return;
const cardRegisterId = registerCardDisplay.value?.id; const cardRegisterId = registerCardDisplay.value?.id;
const followUpRegisterId =
isFollowUpDrugAssistant.value && parsedContent.value?.register_id
? parsedContent.value.register_id
: '';
const registerId = const registerId =
prescriptionStore.currentRegisterId || prescriptionStore.currentRegisterId ||
chatStore.currentFriend?.register_id || chatStore.currentFriend?.register_id ||
cardRegisterId; cardRegisterId ||
followUpRegisterId;
if (!registerId) { if (!registerId) {
antdMessage.warning('请先接诊患者'); antdMessage.warning('请先接诊患者');
return; return;
@@ -308,6 +313,22 @@ const isFollowUpDrugAssistant = computed(() => {
return !!(pc && typeof pc === 'object' && pc.flow === 'follow_up_drug'); return !!(pc && typeof pc === 'object' && pc.flow === 'follow_up_drug');
}); });
/**
* 复诊用药卡「添加到处方单」:有药、非本人发送、当前会话有挂号
* 与挂号卡加方共用 handleAddRegisterDrugsToPrescription
*/
const canAddFollowUpDrugsToRx = computed(() => {
if (!isFollowUpDrugAssistant.value || props.isSent) return false;
const pc = parsedContent.value;
const drugs = pc && Array.isArray(pc.drugs) ? pc.drugs : [];
if (!drugs.length) return false;
return !!(
prescriptionStore.currentRegisterId ||
chatStore.currentFriend?.register_id ||
pc.register_id
);
});
function fetchRegisterCard() { function fetchRegisterCard() {
if (props.message.message_type !== 10) return; if (props.message.message_type !== 10) return;
const content = getParsedContent( const content = getParsedContent(
@@ -1044,6 +1065,9 @@ const getSexText = (sex) => {
<FollowUpDrugAssistantCard <FollowUpDrugAssistantCard
v-else-if="message.message_type === 11 && isFollowUpDrugAssistant" v-else-if="message.message_type === 11 && isFollowUpDrugAssistant"
:content="parsedContent" :content="parsedContent"
:show-add-to-rx="canAddFollowUpDrugsToRx"
:add-to-rx-loading="registerAddToRxLoading"
@add-to-rx="handleAddRegisterDrugsToPrescription"
/> />
<!-- 患者就诊经历卡片 (type=11) --> <!-- 患者就诊经历卡片 (type=11) -->

View File

@@ -54,7 +54,7 @@ function readStoredTab() {
if (stored === 'price_adjust' || stored === 'input_audit' || stored === 'miniprogram' || stored === 'oa_notify') { if (stored === 'price_adjust' || stored === 'input_audit' || stored === 'miniprogram' || stored === 'oa_notify') {
activeKey.value = stored; activeKey.value = stored;
} }
} }}
function parseBoolConfig(val: unknown, defaultVal: boolean): boolean { function parseBoolConfig(val: unknown, defaultVal: boolean): boolean {
if (val === undefined || val === null || val === '') return defaultVal; if (val === undefined || val === null || val === '') return defaultVal;