fix: 问题修复
This commit is contained in:
parent
3a6e88bea6
commit
635d0a8a0f
BIN
src/assets/seal_custom.png
Normal file
BIN
src/assets/seal_custom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<el-drawer :model-value="visible" title="处方订单详情" size="70%" style="--el-drawer-padding-primary: 0" @close="close()">
|
||||
<el-drawer :model-value="visible" title="处方详情" size="70%" style="--el-drawer-padding-primary: 0" @close="close()">
|
||||
<my-layout>
|
||||
<layout-main>
|
||||
<div v-if="data" ref="paperRef" class="prescription-container rx-print-area">
|
||||
<div v-if="data" ref="paperRef" class="prescription-container rx-print-area">
|
||||
<div class="header">
|
||||
<div class="row">
|
||||
<div class="company"></div>
|
||||
@ -11,21 +11,21 @@
|
||||
<div>处方</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hospital">海宁康华互联网医院</div>
|
||||
<div class="hospital">海宁康华医院互联网医院 <br />处方笺</div>
|
||||
<div class="sub-header">
|
||||
<span class="no">NO:{{ no }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="patient-info">
|
||||
<div class="info-row">
|
||||
<div class="info-item" style="width: 28%">姓名:{{ data.name }}</div>
|
||||
<div class="info-item" style="width: 20%">性别:{{ info.sex }}</div>
|
||||
<div class="info-item" style="width: 28%">费别:{{ data.feeType === 'YB' ? '医保' : '自费' }}</div>
|
||||
<div class="info-item" style="width: 24%">年龄:{{ info.age }}</div>
|
||||
<div class="info-item w-1/4">姓名:{{ data.name }}</div>
|
||||
<div class="info-item w-1/4">性别:{{ info.sex }}</div>
|
||||
<div class="info-item w-1/4">年龄:{{ info.age }}</div>
|
||||
<div class="info-item w-1/4">费别:{{ data.feeType === 'YB' ? '医保' : '自费' }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-item" style="width: 60%">门诊病历号:{{ data.blhno }}</div>
|
||||
<div class="info-item" style="width: 40%">科别:{{ data.deptName }}</div>
|
||||
<div class="info-item" style="width: 50%">门诊病历号:{{ data.blhno }}</div>
|
||||
<div class="info-item" style="width: 50%">科别:{{ data.deptName }}</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-item full-width">地址: {{ data.address }}</div>
|
||||
@ -37,25 +37,27 @@
|
||||
<!-- 诊断信息 -->
|
||||
<div class="diagnosis-section">
|
||||
<div class="diagnosis-header">
|
||||
<span>诊断:</span>
|
||||
<span class="date">开方日期:{{ info.time }}</span>
|
||||
</div>
|
||||
<div class="diagnosis-items">
|
||||
<div v-for="(i, idx) in diagnosis" :key="i.code">{{ idx + 1 }}. {{ i.name }}</div>
|
||||
<div class="w-0 flex-grow flex">
|
||||
<div class="flex-shrink-0">诊断:</div>
|
||||
<div class="w-0 flex-grow break-all">{{ diagnosisStr }}</div>
|
||||
</div>
|
||||
<div class="min-w-1/4 flex-shrink-0 white-space-nowrap">开方日期:{{ info.time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 药品处方区域 -->
|
||||
<div class="medicine-section">
|
||||
<div class="rp-symbol">Rp</div>
|
||||
<div v-if="data.prescriptionType === 'medicalWinePurchase'" class="medicine-list">
|
||||
<div v-for="i in data.wines" :key="i._id" class="medicine-item">
|
||||
<div class="medicine-name">{{ i.name }} x {{ i.quantity }} {{ i.unit }}</div>
|
||||
<div class="medicine-spec">{{ i.details }}</div>
|
||||
<div class="flex items-center mb-2 relative">
|
||||
<div class="w-3 border-t border-gray-500 border-dashed"></div>
|
||||
<div class="rp-symbol mx-2">Rp</div>
|
||||
<div class="flex-grow border-t border-gray-500 border-dashed"></div>
|
||||
<div class="absolute right-0 -top-2">
|
||||
<div class="border-2 border-red-500 px-2 py-1 text-red-500 transform rotate-15">处方外购专用章</div>
|
||||
<img class="w-30 h-30 mt-3" :src="stampPng" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="medicine-list">
|
||||
<div v-for="i in drugList" :key="i.insurance_code" class="medicine-item">
|
||||
<div class="medicine-name">{{ i.drugName }} x {{ i.quantity }} {{ i.unit }}</div>
|
||||
<div class="medicine-list">
|
||||
<div v-for="(i, idx) in drugList" :key="i.insurance_code" class="medicine-item">
|
||||
<div class="medicine-name">{{ idx + 1 }}. {{ i.drugName }} x {{ i.quantity }} {{ i.unit }}</div>
|
||||
<div class="medicine-spec">规格:{{ i.specification }}</div>
|
||||
<div class="medicine-usage">用法:{{ i.memo }}</div>
|
||||
</div>
|
||||
@ -63,32 +65,33 @@
|
||||
</div>
|
||||
<!-- 底部签章区域 -->
|
||||
<div class="footer">
|
||||
<div class="stamp-area">
|
||||
<div class="signatures">
|
||||
<div class="signature-item" style="width: 33%">
|
||||
<div>医生:
|
||||
<img v-if="data.doctorSignImg" class="signImage" :src="data.doctorSignImg" />
|
||||
<text v-else>{{ data.doctorName }}</text>
|
||||
</div>
|
||||
<div class="stamp">
|
||||
<!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
|
||||
</div>
|
||||
<div class="flex pt-3">
|
||||
<div class="flex-shrink-0 w-1/3">
|
||||
<div>医生:
|
||||
<img v-if="data.doctorSignImg" class="signImage" :src="data.doctorSignImg" />
|
||||
<text v-else>{{ data.doctorName }}</text>
|
||||
</div>
|
||||
<div class="signature-item" style="width: 33%">
|
||||
<div>审方:<img v-if="data.pharmacistSignImg" class="signImage" :src="data.pharmacistSignImg" />
|
||||
<text v-else>{{ data.pharmacist }}</text>
|
||||
</div>
|
||||
<div>发药:</div>
|
||||
<div class="stamp">
|
||||
<!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
|
||||
</div>
|
||||
<div class="signature-item" style="width: 34%">
|
||||
<div class="stamp">收费盖章:
|
||||
<!-- <image class="stamp-img" src="/static/stamp.png"></image> -->
|
||||
</div>
|
||||
<div>配方:</div>
|
||||
<div>复核:</div>
|
||||
</div>
|
||||
<div class="flex-shrink-0 w-1/3">
|
||||
<div>审方:<img v-if="data.pharmacistSignImg" class="signImage" :src="data.pharmacistSignImg" />
|
||||
<text v-else>{{ data.pharmacist }}</text>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex pt-3">
|
||||
<div class="flex-shrink-0 w-1/3">
|
||||
调配:
|
||||
</div>
|
||||
<div class="flex-shrink-0 w-1/3">
|
||||
复核发药:
|
||||
</div>
|
||||
<div class="flex-shrink-0 w-1/3">
|
||||
发药:
|
||||
</div>
|
||||
</div>
|
||||
<div class="notice">注意:请勿丢失,处方当日有效,因特殊情况,该处方有效为天(签名:)</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -107,6 +110,8 @@ import { getSealImage } from '@/api/hlw';
|
||||
import validate from "@/utils/validate";
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const stampPng = new URL("@/assets/seal_custom.png", import.meta.url).href; // 默认logo
|
||||
|
||||
const emits = defineEmits(['close', 'printed'])
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
@ -124,8 +129,9 @@ const props = defineProps({
|
||||
})
|
||||
const paperRef = ref(null)
|
||||
const doctorCode = ref('')
|
||||
const pharmacistNo=ref('')
|
||||
const pharmacistNo = ref('')
|
||||
const diagnosis = computed(() => props.data && Array.isArray(props.data.diagnosisList) ? props.data.diagnosisList : [])
|
||||
const diagnosisStr = computed(() => diagnosis.value.map((item) => item.name).join('+'))
|
||||
const drugList = computed(() => {
|
||||
const drugs = props.data && Array.isArray(props.data.drugs) ? props.data.drugs : [];
|
||||
return drugs.map((item) => {
|
||||
@ -136,18 +142,18 @@ const drugList = computed(() => {
|
||||
const info = computed(() => {
|
||||
const idNo = typeof props.data.idCard === 'string' ? props.data.idCard : '';
|
||||
const [isIdNo] = validate.isChinaId(idNo || '');
|
||||
if(!isIdNo){return {age:'',sex:''}}
|
||||
if (!isIdNo) { return { age: '', sex: '' } }
|
||||
const birthDate = `${idNo.slice(6, 10)}-${idNo.slice(10, 12)}-${idNo.slice(12, 14)}`;
|
||||
const sexCode = idNo.slice(16, 17);
|
||||
const createTime = props.data.createTime && dayjs(props.data.createTime).isValid() ? dayjs(props.data.createTime) : '';
|
||||
const info = {sex: sexCode % 2 === 0 ? '女' : '男'};
|
||||
if(createTime){
|
||||
const info = { sex: sexCode % 2 === 0 ? '女' : '男' };
|
||||
if (createTime) {
|
||||
info.age = createTime.diff(dayjs(birthDate), 'year') + '岁';
|
||||
info.time = createTime.format('YYYY-MM-DD');
|
||||
}
|
||||
return info
|
||||
})
|
||||
const no = computed(()=> {
|
||||
const no = computed(() => {
|
||||
// if(props.data.prescriptionType === "medicalWinePurchase"){
|
||||
// return props.data.orderNo
|
||||
// }
|
||||
@ -218,7 +224,7 @@ defineExpose({ print });
|
||||
/* 头部样式 */
|
||||
.header {
|
||||
border-bottom: 1px solid #000;
|
||||
padding-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
@ -253,13 +259,12 @@ defineExpose({ print });
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 患者信息表格 */
|
||||
.patient-info {
|
||||
margin: 12px 0;
|
||||
margin: 12px 0 0;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
@ -282,32 +287,24 @@ defineExpose({ print });
|
||||
|
||||
/* 诊断区域 */
|
||||
.diagnosis-section {
|
||||
margin: 15px 0;
|
||||
margin: 12px 0 0;
|
||||
}
|
||||
|
||||
.diagnosis-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
/* 药品处方 */
|
||||
.medicine-section {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
margin: 18px 0;
|
||||
margin: 12px 0 0;
|
||||
}
|
||||
|
||||
.rp-symbol {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.medicine-item {
|
||||
@ -326,8 +323,8 @@ defineExpose({ print });
|
||||
/* 底部签章 */
|
||||
.footer {
|
||||
border-top: 1px dashed #999;
|
||||
padding-top: 15px;
|
||||
margin-top: 20px;
|
||||
// padding-top: 15px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.stamp-area {
|
||||
@ -379,25 +376,31 @@ defineExpose({ print });
|
||||
|
||||
@media print {
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 12mm;
|
||||
size: A5 portrait;
|
||||
margin: 8mm;
|
||||
}
|
||||
|
||||
body.printing-rx > :not(.rx-print-root) {
|
||||
body.printing-rx> :not(.rx-print-root) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body.printing-rx > .rx-print-root {
|
||||
body.printing-rx>.rx-print-root {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
body.printing-rx > .rx-print-root .rx-print-area {
|
||||
body.printing-rx>.rx-print-root .rx-print-area {
|
||||
position: static !important;
|
||||
width: 100% !important;
|
||||
box-sizing: border-box !important;
|
||||
padding: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
body.printing-rx>.rx-print-root .medicine-item,
|
||||
body.printing-rx>.rx-print-root .footer {
|
||||
break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<el-input :model-value="form.mobile" placeholder="请输入" maxlength="50" :disabled="disableMobile"
|
||||
@update:model-value="change($event,'mobile')" />
|
||||
</el-form-item>
|
||||
<el-form-item class="is-required" label="手机号" prop="phone">
|
||||
<el-form-item label="手机号" prop="phone">
|
||||
<el-input :model-value="form.phone" placeholder="请输入手机号" maxlength="20"
|
||||
@update:model-value="change($event,'phone')" />
|
||||
</el-form-item>
|
||||
@ -95,6 +95,7 @@ const rules = [
|
||||
}
|
||||
},
|
||||
{ key: 'phone', test: val => {
|
||||
if (!val) return [true, ''];
|
||||
// 基础非空/长度校验
|
||||
const [pass, v] = verifyString(val, '手机号', 1, 20);
|
||||
if (!pass) return [false, v];
|
||||
|
||||
@ -13,6 +13,15 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div active-title-bar class="my-2.5">适应诊断</div>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item class="mb-5px" label="适应诊断">
|
||||
<span v-if="diagnosisLoading">加载中...</span>
|
||||
<span v-else>{{ diagnosisText || '-' }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div active-title-bar class="my-2.5">药品标准用法用量</div>
|
||||
<el-row>
|
||||
<el-col :span="12" v-for="item in usageInfo" :key="item.prop">
|
||||
@ -75,7 +84,7 @@ import { computed, ref, watch } from 'vue';
|
||||
import { storeToRefs } from "pinia";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import dayjs from "dayjs";
|
||||
import { setHlwDrugOnSale, setOnlineDrugOnSale } from "@/api/hlw";
|
||||
import { setHlwDrugOnSale, setOnlineDrugOnSale, getHlwDiagnosisList } from "@/api/hlw";
|
||||
import { getDrugFieldDict } from './drug-dict.js'
|
||||
import { memberStore } from "@/store/member";
|
||||
|
||||
@ -179,6 +188,33 @@ const showForm = computed(() => {
|
||||
})
|
||||
const form = computed(() => ({ ...props.data, ...showForm.value }))
|
||||
const loading = ref(false)
|
||||
const diagnosisLoading = ref(false)
|
||||
const diagnosisList = ref([])
|
||||
let diagnosisRequestId = 0
|
||||
const diagnosisText = computed(() => diagnosisList.value
|
||||
.map(item => item.code ? `${item.name}(${item.code})` : item.name)
|
||||
.filter(Boolean)
|
||||
.join('、'))
|
||||
|
||||
async function loadDiagnoses() {
|
||||
const requestId = ++diagnosisRequestId;
|
||||
const ids = Array.isArray(props.data.applicableDiagnosisIds)
|
||||
? props.data.applicableDiagnosisIds.map(id => String(id))
|
||||
: [];
|
||||
diagnosisList.value = [];
|
||||
if (!ids.length) return;
|
||||
diagnosisLoading.value = true;
|
||||
const res = await getHlwDiagnosisList({ ids, page: 1, pageSize: Math.max(30, ids.length) });
|
||||
if (requestId !== diagnosisRequestId) return;
|
||||
diagnosisLoading.value = false;
|
||||
if (res.success) {
|
||||
const list = res.data && Array.isArray(res.data.data) ? res.data.data : [];
|
||||
const diagnosisMap = new Map(list.map(item => [String(item._id), item]));
|
||||
diagnosisList.value = ids.map(id => diagnosisMap.get(id)).filter(Boolean);
|
||||
} else {
|
||||
ElMessage.error(res.message || '适应诊断加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function close() {
|
||||
@ -221,4 +257,13 @@ async function setOnSale() {
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.visible, (visible) => {
|
||||
if (visible) {
|
||||
loadDiagnoses();
|
||||
} else {
|
||||
diagnosisRequestId += 1;
|
||||
diagnosisLoading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@ -31,50 +31,33 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div active-title-bar class="mb-2.5">药品规则配置</div>
|
||||
<div active-title-bar class="mb-2.5">适应诊断</div>
|
||||
<el-row>
|
||||
<template v-if="libType === 'online'">
|
||||
<el-col :span="12" v-for="item in suitableInfo" :key="item.prop">
|
||||
<el-form-item :label="item.label" :prop="item.prop"
|
||||
:class="requiredMap[item.prop] ? 'is-required' : ''">
|
||||
<el-select filterable clearable :model-value="form[item.prop]" :placeholder="`请选择${item.label}`"
|
||||
class="w-full" @update:model-value="changeValue($event, item.prop)">
|
||||
<el-option v-for="option in item.options" :key="option" :label="option.label"
|
||||
:value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" :key="repeatTag">
|
||||
<el-form-item label="重复用药标识" prop="repeatTag">
|
||||
<!-- <el-select-v2 filterable clearable :multiple="true" :model-value="form.repeatTag" placeholder="请选择重复用药标识"
|
||||
class="w-full" @update:model-value="changeValue($event, 'repeatTag')">
|
||||
<el-option v-for="option in repeatTagList" :key="option.value" :label="option.label"
|
||||
:value="option.value" />
|
||||
</el-select-v2> -->
|
||||
<el-select-v2 :model-value="form.repeatTag || []" :options="repeatTagList" placeholder="请选择重复用药标识"
|
||||
class="w-full" multiple filterable clearable
|
||||
@update:model-value="changeValue($event, 'repeatTag')" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
<el-col v-for="item in otherInfo" :key="item.prop">
|
||||
<el-form-item :label="item.label" :prop="item.prop" :class="requiredMap[item.prop] ? 'is-required' : ''">
|
||||
<div class="other-info-row">
|
||||
<el-select class="other-info-select" placeholder="请选择" :model-value="form[item.prop]"
|
||||
@change="val => selectChange(item.prop, val)">
|
||||
<el-option v-for="option in item.options" :key="option.value" :label="option.label"
|
||||
:value="option.value" />
|
||||
</el-select>
|
||||
<!-- 当选择为 true 时才渲染输入框,同时把输入框拉伸占满剩余空间 -->
|
||||
<div v-if="item.prop === 'need_medication_proof' && form.need_medication_proof"
|
||||
class="other-info-desc">
|
||||
<el-input clearable :model-value="form.medication_proof_desc" placeholder="描述需上传的用药证明文件类型,用于患者端显示"
|
||||
style="width:100%" @update:model-value="val => changeValue(val, 'medication_proof_desc')" />
|
||||
</div>
|
||||
<div v-else-if="item.prop === 'has_usage_restriction' && form.has_usage_restriction"
|
||||
class="other-info-desc">
|
||||
<el-input clearable :model-value="form.usage_restriction_desc" placeholder="描述该药品的限制使用范围,用于医生、药师端展示"
|
||||
style="width:100%" @update:model-value="val => changeValue(val, 'usage_restriction_desc')" />
|
||||
<el-col :span="24">
|
||||
<el-form-item label="适应诊断" prop="applicableDiagnosisIds">
|
||||
<div class="w-full">
|
||||
<el-popover v-model:visible="diagnosisPopoverVisible" placement="bottom-start" trigger="click"
|
||||
:width="600">
|
||||
<template #reference>
|
||||
<el-input v-model="diagnosisKeyword" clearable placeholder="请输入诊断名称、编码或拼音码搜索"
|
||||
@input="searchDiagnoses" />
|
||||
</template>
|
||||
<div v-loading="diagnosisLoading" class="diagnosis-dropdown">
|
||||
<div v-for="item in diagnosisOptions" :key="item._id" class="diagnosis-option"
|
||||
:class="{ 'diagnosis-option--selected': isDiagnosisSelected(item._id) }"
|
||||
@click="toggleDiagnosis(item)">
|
||||
<span class="diagnosis-option-label">{{ diagnosisLabel(item) }}</span>
|
||||
<span v-if="isDiagnosisSelected(item._id)" class="diagnosis-option-check">√</span>
|
||||
</div>
|
||||
<el-empty v-if="!diagnosisLoading && !diagnosisOptions.length" :image-size="60"
|
||||
description="暂无诊断" />
|
||||
</div>
|
||||
</el-popover>
|
||||
<div v-if="selectedDiagnosisOptions.length" class="selected-diagnoses">
|
||||
<el-tag v-for="item in selectedDiagnosisOptions" :key="item._id" closable
|
||||
@close="toggleDiagnosis(item)">
|
||||
{{ diagnosisLabel(item) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
@ -95,7 +78,7 @@
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ElMessage } from "element-plus";
|
||||
import { addHlwDrugInfo, editHlwDrugInfo, addOnlineDrugInfo, editOnlineDrugInfo, getOnlineDrugRepeatTags } from "@/api/hlw";
|
||||
import { addHlwDrugInfo, editHlwDrugInfo, addOnlineDrugInfo, editOnlineDrugInfo, getOnlineDrugRepeatTags, getHlwDiagnosisList } from "@/api/hlw";
|
||||
import categoryList from '@/baseData/drug-category';
|
||||
import dosageUnitList from '@/baseData/dosageUnit.js';
|
||||
import medicineInfoStore from '@/store/medicine-info';
|
||||
@ -132,6 +115,13 @@ const frequencyOptions = computed(() => getOptionNames(medicineUseInfo.value.fre
|
||||
const usageOptions = computed(() => getOptionNames(medicineUseInfo.value.usageList))
|
||||
|
||||
const repeatTagList = ref([])
|
||||
const diagnosisOptions = ref([])
|
||||
const diagnosisDefaultOptions = ref([])
|
||||
const diagnosisLoading = ref(false)
|
||||
const diagnosisKeyword = ref('')
|
||||
const diagnosisPopoverVisible = ref(false)
|
||||
let diagnosisRequestId = 0
|
||||
let diagnosisSearchTimer = null
|
||||
const basicInfo = computed(() => [
|
||||
{ label: '药品名称', prop: "name", maxlength: 100 },
|
||||
{ label: '药品规格', prop: "specification", maxlength: 100 },
|
||||
@ -176,11 +166,6 @@ const suitableInfo = [
|
||||
{ label: '是否儿童用药', prop: 'suitableChild', options: [{ label: '是', value: true }, { label: '否', value: false }] },
|
||||
// { label: '重复用药标识', prop: 'repeatTag', multiple: true, options: new Array(5).fill(1).map((_, index) => ({ label: index + 1, value: index + 1 })) },
|
||||
]
|
||||
// 其他信息:是否需要上传用药证明/是否有使用范围限制 与 对应描述
|
||||
const otherInfo = [
|
||||
{ label: '是否上传用药证明', prop: 'need_medication_proof', type: 'select', options: [{ label: '是', value: true }, { label: '否', value: false }] },
|
||||
{ label: '是否限制使用范围', prop: 'has_usage_restriction', type: 'select', options: [{ label: '是', value: true }, { label: '否', value: false }] }
|
||||
]
|
||||
|
||||
const requiredMap = computed(() => {
|
||||
const m = getDrugFieldDict(props.libType).reduce((acc, cur) => {
|
||||
@ -204,6 +189,96 @@ function changeValue(val, prop) {
|
||||
editForm.value[prop] = val
|
||||
}
|
||||
|
||||
function diagnosisLabel(item) {
|
||||
return item.code ? `${item.name}(${item.code})` : item.name;
|
||||
}
|
||||
|
||||
const selectedDiagnosisOptions = computed(() => {
|
||||
const optionMap = new Map(diagnosisOptions.value.map(item => [String(item._id), item]));
|
||||
const defaultOptionMap = new Map(diagnosisDefaultOptions.value.map(item => [String(item._id), item]));
|
||||
return (form.value.applicableDiagnosisIds || [])
|
||||
.map(id => optionMap.get(String(id)) || defaultOptionMap.get(String(id)))
|
||||
.filter(Boolean);
|
||||
})
|
||||
|
||||
function isDiagnosisSelected(id) {
|
||||
return (form.value.applicableDiagnosisIds || []).some(item => String(item) === String(id));
|
||||
}
|
||||
|
||||
function toggleDiagnosis(item) {
|
||||
const id = String(item._id);
|
||||
const selectedIds = (form.value.applicableDiagnosisIds || []).map(itemId => String(itemId));
|
||||
const nextIds = selectedIds.includes(id)
|
||||
? selectedIds.filter(itemId => itemId !== id)
|
||||
: [...selectedIds, id];
|
||||
changeValue(nextIds, 'applicableDiagnosisIds');
|
||||
}
|
||||
|
||||
function mergeDiagnosisOptions(items = []) {
|
||||
const optionMap = new Map(diagnosisOptions.value.map(item => [String(item._id), item]));
|
||||
items.forEach(item => optionMap.set(String(item._id), item));
|
||||
diagnosisOptions.value = [...optionMap.values()];
|
||||
}
|
||||
|
||||
function replaceDiagnosisOptions(items = []) {
|
||||
const selectedIds = new Set((form.value.applicableDiagnosisIds || []).map(id => String(id)));
|
||||
const selectedOptions = diagnosisOptions.value.filter(item => selectedIds.has(String(item._id)));
|
||||
const optionMap = new Map(selectedOptions.map(item => [String(item._id), item]));
|
||||
items.forEach(item => optionMap.set(String(item._id), item));
|
||||
diagnosisOptions.value = [...optionMap.values()];
|
||||
}
|
||||
|
||||
async function fetchDiagnoses(params, requestId, replace = false) {
|
||||
const res = await getHlwDiagnosisList({ page: 1, pageSize: 30, ...params });
|
||||
if (requestId !== diagnosisRequestId) return;
|
||||
if (!res.success) {
|
||||
ElMessage.error(res.message || '适应诊断加载失败');
|
||||
return;
|
||||
}
|
||||
const list = res.data && Array.isArray(res.data.data) ? res.data.data : [];
|
||||
if (replace) {
|
||||
replaceDiagnosisOptions(list);
|
||||
} else {
|
||||
mergeDiagnosisOptions(list);
|
||||
}
|
||||
}
|
||||
|
||||
function searchDiagnoses(keyword = '') {
|
||||
if (diagnosisSearchTimer) {
|
||||
clearTimeout(diagnosisSearchTimer);
|
||||
diagnosisSearchTimer = null;
|
||||
}
|
||||
const normalizedKeyword = typeof keyword === 'string' ? keyword.trim() : '';
|
||||
const requestId = ++diagnosisRequestId;
|
||||
if (!normalizedKeyword) {
|
||||
diagnosisLoading.value = false;
|
||||
replaceDiagnosisOptions(diagnosisDefaultOptions.value);
|
||||
return;
|
||||
}
|
||||
diagnosisLoading.value = true;
|
||||
diagnosisSearchTimer = setTimeout(async () => {
|
||||
await fetchDiagnoses({ keyword: normalizedKeyword }, requestId, true);
|
||||
if (requestId === diagnosisRequestId) diagnosisLoading.value = false;
|
||||
diagnosisSearchTimer = null;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
async function initializeDiagnoses() {
|
||||
diagnosisOptions.value = [];
|
||||
const selectedIds = Array.isArray(props.data.applicableDiagnosisIds)
|
||||
? props.data.applicableDiagnosisIds.map(id => String(id))
|
||||
: [];
|
||||
const requestId = ++diagnosisRequestId;
|
||||
diagnosisLoading.value = true;
|
||||
const requests = [fetchDiagnoses({}, requestId)];
|
||||
if (selectedIds.length) {
|
||||
requests.push(fetchDiagnoses({ ids: selectedIds, pageSize: Math.max(30, selectedIds.length) }, requestId));
|
||||
}
|
||||
await Promise.all(requests);
|
||||
diagnosisDefaultOptions.value = [...diagnosisOptions.value];
|
||||
if (requestId === diagnosisRequestId) diagnosisLoading.value = false;
|
||||
}
|
||||
|
||||
|
||||
function close() {
|
||||
if (loading.value) return;
|
||||
@ -241,7 +316,6 @@ async function save() {
|
||||
if (!props.data._id) {
|
||||
payload.params.onSale = true;
|
||||
}
|
||||
loading.value = false;
|
||||
const { success, message } = await api(payload);
|
||||
loading.value = false;
|
||||
if (success) {
|
||||
@ -264,7 +338,8 @@ watch(() => props.visible, async (val) => {
|
||||
if (val) {
|
||||
// reset local editForm when opening drawer
|
||||
editForm.value = {}
|
||||
await attachMedicineConfig()
|
||||
diagnosisKeyword.value = ''
|
||||
await Promise.all([attachMedicineConfig(), initializeDiagnoses()])
|
||||
if (props.libType === 'online') {
|
||||
getRepeatTags()
|
||||
}
|
||||
@ -286,6 +361,14 @@ watch(() => props.visible, async (val) => {
|
||||
editForm.value.repeatTag = [props.data.repeatTag]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diagnosisPopoverVisible.value = false
|
||||
diagnosisRequestId += 1
|
||||
diagnosisLoading.value = false
|
||||
if (diagnosisSearchTimer) {
|
||||
clearTimeout(diagnosisSearchTimer)
|
||||
diagnosisSearchTimer = null
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -321,4 +404,52 @@ function selectChange(prop, val) {
|
||||
min-width: 0;
|
||||
/* allow input to shrink properly inside flex */
|
||||
}
|
||||
|
||||
.diagnosis-dropdown {
|
||||
min-height: 60px;
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.diagnosis-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 36px;
|
||||
padding: 0 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
|
||||
.diagnosis-option:hover,
|
||||
.diagnosis-option--selected {
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
.diagnosis-option--selected {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.diagnosis-option-label {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.diagnosis-option-check {
|
||||
flex-shrink: 0;
|
||||
margin-left: 16px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.selected-diagnoses {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -25,12 +25,13 @@
|
||||
|
||||
</el-form>
|
||||
<div class="mt-6 flex justify-end text-sm">
|
||||
<span class="cursor-pointer text-gray-600 hover:text-blue-500 transition-colors" @click.prevent="editPassword">修改密码</span>
|
||||
<span class="cursor-pointer text-gray-600 hover:text-blue-500 transition-colors"
|
||||
@click.prevent="editPassword">修改密码</span>
|
||||
</div>
|
||||
</div>
|
||||
<ModifyPasswordDialog :showModifyDialog="showModifyDialog" @close="closeModifyDialog"
|
||||
:username="loginForm.username" />
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
@ -59,6 +60,7 @@ const loginFormRef = ref();
|
||||
const loading = ref(false);
|
||||
const loginForm = reactive({
|
||||
username: "",
|
||||
// password: "",
|
||||
password: "zytzyy6789",
|
||||
});
|
||||
const loginRules = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user