region-address-picker 接 region-picker API;订单支持按进价重算 market_price、追踪页资金流水;MES/ERP/中台同步日志共用内容查看组件;地区管理支持 pid 下钻与拼音检索。
673 lines
19 KiB
TypeScript
673 lines
19 KiB
TypeScript
import { computed, ref, nextTick } from "vue"
|
||
import { message, notification } from "ant-design-vue"
|
||
import { debounce } from "lodash-es"
|
||
|
||
import { calculateProcessingFee, parsePriceValue } from '#/utils/formatPrice'
|
||
import {
|
||
addWestPrescription,
|
||
checkChineseMedicineConflictApi,
|
||
getDrugUseList,
|
||
getMyStoreListApi,
|
||
getPatientItem,
|
||
getProcessRuleList,
|
||
getProductListDoctorReception,
|
||
} from "#/views/doctor/doctor-reception/api"
|
||
|
||
export const usePrescriptionStore = () => {
|
||
// 基础数据
|
||
const patientInfo = ref<any | null>(null)
|
||
const userPatientHealthInquiry = ref<any | null>(null)
|
||
const prescriptionList = ref([])
|
||
const currentRegisterId = ref<number | string>("")
|
||
const activePatient = ref<any | null>(null)
|
||
|
||
// 药品使用相关数据
|
||
const drugUseNum = ref([])
|
||
const drugUseFrequency = ref([])
|
||
const drugUseType = ref([])
|
||
const drugUnit = ref([])
|
||
const drugTime = ref([])
|
||
const drugUseWay = ref([])
|
||
const myStoreList = ref([])
|
||
|
||
// 处方状态
|
||
const myStoreId = ref(0)
|
||
const activeCategory = ref(2)
|
||
const diagnosis = ref("")
|
||
const medicalAdvice = ref("")
|
||
const treatmentPrice = ref(0)
|
||
const ruleType = ref(1)
|
||
const drugList = ref([])
|
||
const currentDrugs = ref([])
|
||
const category = ref(1)
|
||
const selectProductId = ref(0)
|
||
|
||
// 中药相关配置
|
||
const processRuleList = ref([])
|
||
const childProcessRuleList = ref([])
|
||
const processRuleNoteList = ref([])
|
||
const processRuleId = ref()
|
||
const processRuleNoteId = ref()
|
||
const childProcessRuleId = ref()
|
||
const packageMethodId = ref(2)
|
||
const dosage = ref(7)
|
||
const dayDosage = ref(2)
|
||
|
||
// 新药品相关
|
||
const newDrugInfo = ref<any>({})
|
||
const selectChineseIndex = ref(-1)
|
||
const selectChineseId = ref(0)
|
||
|
||
// 二次签名相关
|
||
const doctorSecondSign = ref(0)
|
||
const checkData = ref<any>({})
|
||
|
||
// 获取localStorage key(修改为在线复诊前缀)
|
||
const getStorageKey = () => `onlineConsultation-prescriptionData${currentRegisterId.value}`
|
||
|
||
// 计算属性
|
||
const totalProductCost = computed(() => {
|
||
if (currentDrugs.value.length === 0) {
|
||
return 0
|
||
}
|
||
if (activeCategory.value === 1) {
|
||
return currentDrugs.value.reduce((sum, drug) => sum + drug.price * (drug.number || 1) * dosage.value, 0)
|
||
}
|
||
return currentDrugs.value.reduce((sum, drug) => sum + drug.price * (drug.select_number || 1), 0)
|
||
})
|
||
|
||
const processingFee = computed(() => {
|
||
if (ruleType.value !== 2 || currentDrugs.value.length === 0) return 0
|
||
const processRule = childProcessRuleList.value.find((item) => item.id === childProcessRuleId.value)
|
||
const totalQty = currentDrugs.value.reduce(
|
||
(sum, drug) => sum + parsePriceValue(drug.number ?? 1),
|
||
0,
|
||
)
|
||
return calculateProcessingFee(processRule, dosage.value, totalQty)
|
||
})
|
||
|
||
const totalCost = computed(() => {
|
||
return totalProductCost.value + processingFee.value
|
||
})
|
||
|
||
// 重新设计的localStorage同步方法
|
||
const syncToLocalStorage = () => {
|
||
try {
|
||
const storageKey = getStorageKey()
|
||
localStorage.setItem(storageKey, JSON.stringify(currentDrugs.value))
|
||
console.log("已同步到localStorage:", storageKey, currentDrugs.value)
|
||
} catch (error) {
|
||
console.error("保存到localStorage失败:", error)
|
||
}
|
||
}
|
||
|
||
const loadFromLocalStorage = () => {
|
||
try {
|
||
const storageKey = getStorageKey()
|
||
const stored = localStorage.getItem(storageKey)
|
||
console.log("从localStorage加载:", storageKey, stored)
|
||
|
||
if (stored) {
|
||
const parsedData = JSON.parse(stored)
|
||
// 直接替换整个数组以确保响应式更新
|
||
currentDrugs.value.splice(0, currentDrugs.value.length, ...parsedData)
|
||
} else {
|
||
// 清空数组
|
||
currentDrugs.value.splice(0, currentDrugs.value.length)
|
||
}
|
||
} catch (error) {
|
||
console.error("从localStorage加载失败:", error)
|
||
currentDrugs.value.splice(0, currentDrugs.value.length)
|
||
}
|
||
}
|
||
|
||
// 更新currentDrugs并同步到localStorage
|
||
const updateCurrentDrugs = (newDrugs: any[]) => {
|
||
// 使用splice确保响应式更新
|
||
currentDrugs.value.splice(0, currentDrugs.value.length, ...newDrugs)
|
||
syncToLocalStorage()
|
||
}
|
||
|
||
// 方法
|
||
const initializePrescription = async (registerId: number | string) => {
|
||
currentRegisterId.value = registerId
|
||
|
||
// 先加载localStorage数据
|
||
loadFromLocalStorage()
|
||
|
||
await Promise.all([getMyStoreList(), getDrugUseListData(), getProcessRuleListData(), getPatientInfo()])
|
||
}
|
||
|
||
/**
|
||
* 拉取门店并保留已选/本地缓存门店,避免每次重置为列表第一项导致预设按店查空
|
||
*/
|
||
const getMyStoreList = async () => {
|
||
try {
|
||
const res = await getMyStoreListApi()
|
||
myStoreList.value = res || []
|
||
if (!myStoreList.value.length) return
|
||
const preferred =
|
||
Number(myStoreId.value || 0) ||
|
||
Number(localStorage.getItem("myStoreId") || 0)
|
||
const hit = myStoreList.value.find(
|
||
(s: any) => Number(s.id) === preferred,
|
||
)
|
||
myStoreId.value = hit
|
||
? Number(hit.id)
|
||
: Number(myStoreList.value[0].id)
|
||
} catch (error) {
|
||
console.error("获取诊所列表失败:", error)
|
||
}
|
||
}
|
||
|
||
const getDrugUseListData = async () => {
|
||
try {
|
||
const res = await getDrugUseList()
|
||
drugUseNum.value = res.drug_use_num
|
||
drugUseFrequency.value = res.drug_use_frequency
|
||
drugUseType.value = res.drug_use_type
|
||
drugUnit.value = res.drug_unit
|
||
drugTime.value = res.drug_time
|
||
drugUseWay.value = res.drug_use_way
|
||
} catch (error) {
|
||
console.error("获取药品使用列表失败:", error)
|
||
}
|
||
}
|
||
|
||
const getProcessRuleListData = async (pid = 0, ruleId = 0) => {
|
||
try {
|
||
const data = ruleId === 0 ? { pid } : { rule_id: ruleId }
|
||
const res = await getProcessRuleList(data)
|
||
|
||
if (ruleId !== 0) {
|
||
processRuleNoteList.value = res
|
||
} else if (pid === 0) {
|
||
processRuleList.value = res
|
||
} else {
|
||
childProcessRuleList.value = res
|
||
}
|
||
} catch (error) {
|
||
console.error("获取加工规则失败:", error)
|
||
}
|
||
}
|
||
|
||
const getPatientInfo = async () => {
|
||
try {
|
||
const res = await getPatientItem(currentRegisterId.value)
|
||
patientInfo.value = res
|
||
activePatient.value = res.user_patient
|
||
userPatientHealthInquiry.value = res.user_patient_health_inquiry
|
||
prescriptionList.value = res.prescription
|
||
} catch (error) {
|
||
console.error("获取患者信息失败:", error)
|
||
}
|
||
}
|
||
|
||
// 药品搜索
|
||
const getDrugList = debounce(async (searchText = "") => {
|
||
if (searchText === "" && activeCategory.value === 1) {
|
||
drugList.value = []
|
||
return
|
||
}
|
||
|
||
try {
|
||
const res = await getProductListDoctorReception({
|
||
store_id: myStoreId.value,
|
||
type: activeCategory.value,
|
||
name: searchText,
|
||
})
|
||
|
||
drugList.value = res.map((item) => {
|
||
const matched = currentDrugs.value.find((v) => v.index_id === item.id)
|
||
return {
|
||
...item,
|
||
select_number: matched?.select_number || 0,
|
||
drug: {
|
||
...item.drug,
|
||
number: matched?.number || 1,
|
||
},
|
||
}
|
||
})
|
||
} catch (error) {
|
||
console.error("获取药品列表失败:", error)
|
||
message.error("获取药品列表失败")
|
||
}
|
||
}, 300)
|
||
|
||
// 药品操作
|
||
const addProducts = (data: any) => {
|
||
const existItem = currentDrugs.value.find((item) => item.index_id === data.id)
|
||
if (existItem) {
|
||
message.warn("已经存在了")
|
||
return false
|
||
}
|
||
|
||
const newProduct = {
|
||
index_id: data.id,
|
||
id: data.drug.id,
|
||
drug_name: data.drug.drug_name,
|
||
number: data.drug.number,
|
||
use_num: drugTime.value.find((item) => item.id === data.drug.time_id),
|
||
use_type: drugUseType.value.find((item) => item.id === data.drug.type_id),
|
||
use_frequency: drugUseFrequency.value.find((item) => item.id === data.drug.frequency_id),
|
||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||
price: data.price,
|
||
way_id: data.drug?.way_id,
|
||
use_ways: drugUseWay.value.find((item) => item.id === data.drug.way_id),
|
||
time_id: data.drug.time_id,
|
||
type_id: data.drug.type_id,
|
||
frequency_id: data.drug.frequency_id,
|
||
unit_id: data.drug.unit_id,
|
||
image: data.drug.image,
|
||
instruction: data.drug.instruction,
|
||
type: data.drug.type,
|
||
select_number: 1,
|
||
}
|
||
|
||
// 使用新的更新方法
|
||
const newDrugs = [...currentDrugs.value, newProduct]
|
||
updateCurrentDrugs(newDrugs)
|
||
|
||
message.success(`已将${newProduct.drug_name}添加到清单中!`)
|
||
return true
|
||
}
|
||
|
||
const removeDrug = (index: number) => {
|
||
const newDrugs = currentDrugs.value.filter((_, i) => i !== index)
|
||
updateCurrentDrugs(newDrugs)
|
||
}
|
||
|
||
const updateDrugQuantity = (index: number, quantity: number) => {
|
||
if (quantity > 0) {
|
||
const newDrugs = [...currentDrugs.value]
|
||
newDrugs[index].select_number = quantity
|
||
updateCurrentDrugs(newDrugs)
|
||
}
|
||
}
|
||
|
||
const increment = (index: number) => {
|
||
const newDrugs = [...currentDrugs.value]
|
||
newDrugs[index].select_number++
|
||
updateCurrentDrugs(newDrugs)
|
||
}
|
||
|
||
const decrement = (index: number) => {
|
||
if (currentDrugs.value[index].select_number > 1) {
|
||
const newDrugs = [...currentDrugs.value]
|
||
newDrugs[index].select_number--
|
||
updateCurrentDrugs(newDrugs)
|
||
}
|
||
}
|
||
|
||
// 新药品操作
|
||
const selectNewDrugInfo = () => {
|
||
const check = currentDrugs.value.find((v) => v.id === newDrugInfo.value.id)
|
||
if (check) {
|
||
newDrugInfo.value.id = ""
|
||
message.error("该药品已经在处方中了!")
|
||
return
|
||
}
|
||
|
||
const data = drugList.value.find((v) => v.drug_id === newDrugInfo.value.id)
|
||
if (data) {
|
||
newDrugInfo.value.price = data.price
|
||
newDrugInfo.value.name = data.drug.drug_name
|
||
nextTick(() => {
|
||
const input = document.querySelector(".new-number-input input") as HTMLElement
|
||
input?.focus()
|
||
})
|
||
}
|
||
}
|
||
|
||
const selectOldDrugInfo = (id: number) => {
|
||
const check = currentDrugs.value.find((v) => v.id === id)
|
||
|
||
if (check) {
|
||
const newDrugs = [...currentDrugs.value]
|
||
newDrugs[selectChineseIndex.value].id = selectChineseId.value
|
||
updateCurrentDrugs(newDrugs)
|
||
drugList.value = []
|
||
message.error("该药品已经在处方中了!")
|
||
return
|
||
}
|
||
|
||
const data = drugList.value.find((v) => v.drug_id === id)
|
||
if (data) {
|
||
const newProduct = {
|
||
index_id: data.id,
|
||
id: data.drug.id,
|
||
drug_name: data.drug.drug_name,
|
||
number: data.drug.number,
|
||
use_num: drugTime.value.find((item) => item.id === data.drug.time_id),
|
||
use_type: drugUseType.value.find((item) => item.id === data.drug.type_id),
|
||
use_frequency: drugUseFrequency.value.find((item) => item.id === data.drug.frequency_id),
|
||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||
price: data.price,
|
||
way_id: data.drug?.way_id,
|
||
use_ways: drugUseWay.value.find((item) => item.id === data.drug.way_id),
|
||
time_id: data.drug.time_id,
|
||
type_id: data.drug.type_id,
|
||
frequency_id: data.drug.frequency_id,
|
||
unit_id: data.drug.unit_id,
|
||
image: data.drug.image,
|
||
instruction: data.drug.instruction,
|
||
type: data.drug.type,
|
||
}
|
||
|
||
const newDrugs = [...currentDrugs.value]
|
||
newDrugs[selectChineseIndex.value] = newProduct
|
||
updateCurrentDrugs(newDrugs)
|
||
|
||
nextTick(() => {
|
||
const input = document.querySelector(`.old-number-input-${selectChineseIndex.value} input`) as HTMLElement
|
||
input?.focus()
|
||
})
|
||
}
|
||
}
|
||
|
||
const setSelectChineseIndex = (index: number, id: number) => {
|
||
selectChineseIndex.value = index
|
||
selectChineseId.value = id
|
||
}
|
||
|
||
const addDrugByChinese = () => {
|
||
const check = currentDrugs.value.find((v) => v.id === newDrugInfo.value.id)
|
||
if (check) {
|
||
message.error("该药品已经在处方中了!")
|
||
return false
|
||
}
|
||
|
||
const data = drugList.value.find((v) => v.drug_id === newDrugInfo.value.id)
|
||
if (!data) {
|
||
message.error("请选择药品")
|
||
return false
|
||
}
|
||
|
||
data.drug.number = newDrugInfo.value.number
|
||
data.drug.way_id = newDrugInfo.value.way_id
|
||
const success = addProducts(data)
|
||
if (success) {
|
||
newDrugInfo.value = {}
|
||
}
|
||
return success
|
||
}
|
||
|
||
const selectDrugByNewDrugInfo = (event: KeyboardEvent, isNewDrug: boolean) => {
|
||
if (event.key === "Enter") {
|
||
event.preventDefault()
|
||
if (isNewDrug) {
|
||
addDrugByChinese()
|
||
} else {
|
||
syncToLocalStorage()
|
||
}
|
||
nextTick(() => {
|
||
const input = document.querySelector(".new-select-drug-name input") as HTMLElement
|
||
input?.focus()
|
||
})
|
||
}
|
||
}
|
||
|
||
const updateChineseNumber = () => {
|
||
syncToLocalStorage()
|
||
}
|
||
|
||
const updateChineseNumberGoNewDrug = (event: KeyboardEvent) => {
|
||
if (event.key === "Enter") {
|
||
syncToLocalStorage()
|
||
nextTick(() => {
|
||
const input = document.querySelector(".new-select-drug-name input") as HTMLElement
|
||
input?.focus()
|
||
})
|
||
}
|
||
}
|
||
|
||
// 药品用法选择
|
||
const selectProductChange = (id: number) => {
|
||
selectProductId.value = id
|
||
}
|
||
|
||
const selectDrugUseWayChange = (id: number) => {
|
||
const newDrugs = currentDrugs.value.map((item) =>
|
||
item.index_id === selectProductId.value
|
||
? {
|
||
...item,
|
||
way_id: id,
|
||
use_ways: drugUseWay.value.find((value) => value.id === id),
|
||
}
|
||
: item,
|
||
)
|
||
updateCurrentDrugs(newDrugs)
|
||
}
|
||
|
||
// 加工规则操作
|
||
const selectProcessRule = (id: number) => {
|
||
processRuleId.value = id
|
||
getProcessRuleListData(id)
|
||
}
|
||
|
||
const selectProcessRuleNot = (id: number) => {
|
||
childProcessRuleId.value = id
|
||
getProcessRuleListData(0, id)
|
||
}
|
||
|
||
const selectProcessRuleNotCommit = (id: number) => {
|
||
processRuleNoteId.value = id
|
||
}
|
||
|
||
const selectPackageMethod = (id: number) => {
|
||
packageMethodId.value = id
|
||
}
|
||
|
||
// 中药相冲检查
|
||
const checkChineseMedicineConflict = async () => {
|
||
if (activeCategory.value === 2) {
|
||
return { hasConflict: false }
|
||
}
|
||
|
||
notification.info({
|
||
message: "正在检查药物相冲",
|
||
duration: 1,
|
||
description: "正在检查药物相冲,请稍等...",
|
||
})
|
||
|
||
try {
|
||
const names = currentDrugs.value.map((item) => item.drug_name)
|
||
const res = await checkChineseMedicineConflictApi({ names })
|
||
|
||
if (res.is_exist === true) {
|
||
checkData.value = { message: res.message }
|
||
return { hasConflict: true, message: res.message }
|
||
} else {
|
||
notification.success({
|
||
message: "检查成功",
|
||
duration: 3,
|
||
description: "暂无相冲药品",
|
||
})
|
||
return { hasConflict: false }
|
||
}
|
||
} catch (error) {
|
||
console.error("检查药物相冲失败:", error)
|
||
return { hasConflict: false }
|
||
}
|
||
}
|
||
|
||
// 发送处方
|
||
const sendPrescription = async (doctorSecondSignValue = 0) => {
|
||
// 验证表单
|
||
if (currentDrugs.value.length === 0) {
|
||
message.error("请选择药品")
|
||
return false
|
||
}
|
||
|
||
if (activeCategory.value === 1) {
|
||
if (ruleType.value === 1 && packageMethodId.value == null) {
|
||
message.error("请选择包法")
|
||
return false
|
||
}
|
||
if (ruleType.value === 2) {
|
||
if (processRuleId.value == null) {
|
||
message.error("请选择制剂")
|
||
return false
|
||
}
|
||
if (processRuleNoteId.value == null) {
|
||
message.error("请选择规格")
|
||
return false
|
||
}
|
||
if (childProcessRuleId.value == null) {
|
||
message.error("请选择备注")
|
||
return false
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!diagnosis.value) {
|
||
message.error("诊断结果不能为空")
|
||
return false
|
||
}
|
||
|
||
if (!medicalAdvice.value) {
|
||
message.error("医嘱不能为空")
|
||
return false
|
||
}
|
||
|
||
try {
|
||
await addWestPrescription({
|
||
patient: activePatient.value,
|
||
drugs: currentDrugs.value,
|
||
diagnosis: diagnosis.value,
|
||
medicalAdvice: medicalAdvice.value,
|
||
total: totalCost.value,
|
||
category: category.value,
|
||
drug_type: 2,
|
||
register_id: currentRegisterId.value,
|
||
treatment_price: treatmentPrice.value,
|
||
package_method_id: packageMethodId.value,
|
||
process_rule_id: processRuleId.value,
|
||
process_rule_note_id: processRuleNoteId.value,
|
||
child_process_rule_id: childProcessRuleId.value,
|
||
process_rule_type: ruleType.value,
|
||
prescription_type: activeCategory.value,
|
||
processing_fee: processingFee.value,
|
||
dosage: dosage.value,
|
||
day_dosage: dayDosage.value,
|
||
doctor_second_sign: doctorSecondSignValue,
|
||
})
|
||
|
||
message.success("处方已发送")
|
||
resetForm()
|
||
return true
|
||
} catch (error) {
|
||
console.error("发送处方失败:", error)
|
||
message.error("发送处方失败")
|
||
return false
|
||
}
|
||
}
|
||
|
||
const resetForm = () => {
|
||
updateCurrentDrugs([])
|
||
diagnosis.value = ""
|
||
medicalAdvice.value = ""
|
||
packageMethodId.value = 2
|
||
dosage.value = 7
|
||
dayDosage.value = 2
|
||
newDrugInfo.value = {}
|
||
doctorSecondSign.value = 0
|
||
}
|
||
|
||
const changeCategory = (categoryValue: number) => {
|
||
activeCategory.value = categoryValue
|
||
updateCurrentDrugs([])
|
||
localStorage.setItem(`onlineConsultation-activeCategory${currentRegisterId.value}`, categoryValue.toString())
|
||
}
|
||
|
||
// 工具函数
|
||
const splitString = (str: string) => {
|
||
if (!str) return []
|
||
return str.split(",")
|
||
}
|
||
|
||
// 强制刷新currentDrugs(用于调试或特殊情况)
|
||
const refreshCurrentDrugs = () => {
|
||
loadFromLocalStorage()
|
||
}
|
||
|
||
return {
|
||
// 状态
|
||
patientInfo,
|
||
userPatientHealthInquiry,
|
||
prescriptionList,
|
||
currentRegisterId,
|
||
activePatient,
|
||
drugUseNum,
|
||
drugUseFrequency,
|
||
drugUseType,
|
||
drugUnit,
|
||
drugTime,
|
||
drugUseWay,
|
||
myStoreList,
|
||
myStoreId,
|
||
activeCategory,
|
||
diagnosis,
|
||
medicalAdvice,
|
||
treatmentPrice,
|
||
ruleType,
|
||
drugList,
|
||
currentDrugs,
|
||
category,
|
||
selectProductId,
|
||
processRuleList,
|
||
childProcessRuleList,
|
||
processRuleNoteList,
|
||
processRuleId,
|
||
processRuleNoteId,
|
||
childProcessRuleId,
|
||
packageMethodId,
|
||
dosage,
|
||
dayDosage,
|
||
newDrugInfo,
|
||
selectChineseIndex,
|
||
selectChineseId,
|
||
doctorSecondSign,
|
||
checkData,
|
||
|
||
// 计算属性
|
||
totalProductCost,
|
||
processingFee,
|
||
totalCost,
|
||
|
||
// 方法
|
||
initializePrescription,
|
||
getDrugList,
|
||
addProducts,
|
||
removeDrug,
|
||
updateDrugQuantity,
|
||
increment,
|
||
decrement,
|
||
selectNewDrugInfo,
|
||
selectOldDrugInfo,
|
||
setSelectChineseIndex,
|
||
addDrugByChinese,
|
||
selectDrugByNewDrugInfo,
|
||
updateChineseNumber,
|
||
updateChineseNumberGoNewDrug,
|
||
selectProductChange,
|
||
selectDrugUseWayChange,
|
||
selectProcessRule,
|
||
selectProcessRuleNot,
|
||
selectProcessRuleNotCommit,
|
||
selectPackageMethod,
|
||
checkChineseMedicineConflict,
|
||
sendPrescription,
|
||
resetForm,
|
||
changeCategory,
|
||
getProcessRuleListData,
|
||
splitString,
|
||
refreshCurrentDrugs,
|
||
|
||
// 新增的方法
|
||
syncToLocalStorage,
|
||
loadFromLocalStorage,
|
||
updateCurrentDrugs,
|
||
}
|
||
}
|