Merge branch 'main' of ssh://git.jizhiweb.cn:2222/clinic-v2/web

This commit is contained in:
LiJianZhao 2025-04-30 16:00:58 +08:00
commit 5adbb2f037
6 changed files with 377 additions and 72 deletions

View File

@ -17,25 +17,25 @@
<div class="list">
<el-scrollbar>
<ul>
<li class="list-item" :class="curItem.id == item.id ? 'active' : ''" v-for="(item, index) in orderList"
<li class="list-item" :class="curItem.id == item.id ? 'active' : ''" v-for="(item, index) in ChargeQueueList"
:key="index" @click="clickItem(item)">
<span>
<img v-if="item.patientRegistration.gender=='1'" class="avatar"
<img v-if="item.patientGender=='1'" class="avatar"
src="/static/images/outpatient/man.png"
alt="头像"/>
<img v-if="item.patientRegistration.gender=='2'" class="avatar"
<img v-if="item.patientGender=='2'" class="avatar"
src="/static/images/outpatient/women.png"
alt="头像"/>
</span>
<span class="item_name">{{ item.patientInfo.name }}</span>
<span class="item_name">{{ item.patientName }}</span>
<el-tooltip
class="box-item"
effect="dark"
:content="formatTime(item.patientRegistration.createDatetime)||'-'"
:content="formatTime(item.createTime)||'-'"
placement="bottom-start"
>
<span class="item_time">
{{ formatTime(item.patientRegistration.createDatetime) || '-' }}
{{ formatTime(item.createTime) || '-' }}
</span>
</el-tooltip>
<span :class="[item.status == 0 ?'status-active':'']">{{ item.status == 0 ? '未收' : '已收' }}</span>
@ -62,7 +62,7 @@ const clickItem = (item: any) => {
emit('clickItem', item, query.value.status);
}
const orderList = ref<any>([]);
const ChargeQueueList = ref<any>([]);
const query = ref({
pageSize: 20,
pageNum: 1,
@ -75,25 +75,25 @@ const addChargeOrder = () => {
patientName: "匿名患者",
payType: -1,
}
if (orderList.value[0]?.id == -1) {
if (ChargeQueueList.value[0]?.id == -1) {
return
}
orderList.value.unshift(newOrder)
ChargeQueueList.value.unshift(newOrder)
clickFirst()
}
const clickFirst = () => {
clickItem(orderList.value[0])
clickItem(ChargeQueueList.value[0])
}
const getOrderList = () => {
post("medical/record/getChargeQueue", {query: query.value}).then(
(res: any) => {
orderList.value = res.list
ChargeQueueList.value = res.list
clickFirst()
}
)
}
const delDraft = () => {
orderList.value.shift();
ChargeQueueList.value.shift();
clickFirst()
}
defineExpose({delDraft, getOrderList})

View File

@ -0,0 +1,46 @@
<template>
<Panel title="患者信息">
<div style="height: 100%;">
<el-descriptions
border
:column="2"
style="padding: 0 10px;height: 100%"
>
<el-descriptions-item label="姓名">
{{patientInfo.name}}
</el-descriptions-item>
<el-descriptions-item label="性别">
{{ patientInfo.sex == 1 ? '男' : '女'}}
</el-descriptions-item>
<el-descriptions-item label="年龄">
{{patientInfo.age}}
</el-descriptions-item>
<el-descriptions-item label="民族">
{{getKey(antys,patientInfo.nation)}}
</el-descriptions-item>
<el-descriptions-item :span="2" label="手机号">
{{patientInfo.phone }}
</el-descriptions-item>
<el-descriptions-item :span="2" label="证件类型">
{{getKey(psnCertTypes,patientInfo.certType)}}
</el-descriptions-item>
<el-descriptions-item :span="2" label="证件号码">
{{ patientInfo.certNo}}
</el-descriptions-item>
</el-descriptions>
</div>
</Panel>
</template>
<style scoped lang="scss">
</style>
<script setup lang="ts">
import {getKey} from "@/utils/discrotyUtil.ts";
import antys from "@/assets/config/directory/antys.json";
import psnCertTypes from "@/assets/config/directory/psnCertTypes.json";
import Panel from "@/components/common/Panel.vue";
const patientInfo:any = defineModel();
</script>

View File

@ -0,0 +1,77 @@
<template>
<Panel :title="'缴费记录'">
<div class="list">
<el-scrollbar>
<el-collapse accordion>
<el-collapse-item :name="index" v-for="(item, index) in list" :key="index">
<template #title>
<div class="list-item-content">
<el-tooltip
class="box-item"
effect="dark"
:content="item.diagnosisMedicalRecord.diagnosisSummary"
placement="bottom-start"
>
<span class="disease-name">{{ item.diagnosisMedicalRecord.diagnosisSummary }}</span>
</el-tooltip>
<!-- <span class="doctor">{{ item.patientId }}</span>-->
<!-- <span class="time">{{ item.createDatetime }}</span>-->
</div>
</template>
<div>
<Detail :detail="item"></Detail>
</div>
</el-collapse-item>
</el-collapse>
</el-scrollbar>
</div>
</Panel>
</template>
<script setup lang="ts">
import Panel from '@/components/common/Panel.vue';
import Detail from './RecordsLog/Detail.vue';
import {post} from "@/utils/request.ts";
import {ref} from "vue";
const list = ref<any>([])
const init = (patientId: any) => {
const query = {
patientId: patientId
}
post('charge/list', {query}).then((res: any) => {
list.value = res.list
})
}
const clearList = () => {
list.value = []
}
defineExpose({init,clearList})
</script>
<style scoped lang="scss">
.list {
display: flex;
flex-direction: column;
height: 100%;
.list-item-content {
padding: 0 21px 0 24px;
display: flex;
justify-content: space-between;
.disease-name {
width: 135px;
overflow: hidden; /* 隐藏溢出的内容 */
white-space: nowrap; /* 防止文本换行 */
text-overflow: ellipsis; /* 显示省略号 */
}
.doctor {
width: 85px;
}
}
}
:deep .el-collapse-item__content {
padding: 0;
}
</style>

View File

@ -0,0 +1,151 @@
<template>
<div class="disease-detail">
<div class="content">
<div class="content-title">
<div class="name">服务项目</div>
</div>
<div class="content-middle">
<div class="item" v-for="item in detailObj.serviceDetail">
<el-tooltip
class="box-item"
effect="dark"
:content="item.name"
placement="bottom-start"
>
<div class="name">{{ item.name }}</div>
</el-tooltip>
<div class="price">
<div class="price-left">{{ item.number || 0 }}{{ item.unit }}</div>
<div class="price-right">{{ item.unitPrice }}</div>
</div>
</div>
</div>
</div>
<div class="content">
<div class="content-title">
<div class="name">药品耗材</div>
</div>
<div class="content-middle">
<div class="item" v-for="item in detailObj.goodsDetail">
<el-tooltip
class="box-item"
effect="dark"
:content="item.name"
placement="bottom-start"
>
<div class="name">{{ item.name }}</div>
</el-tooltip>
<div class="price">
<div class="price-left">{{ item.number || 0 }}{{ item.unit }}</div>
<div class="price-right">{{ item.unitPrice }}</div>
</div>
</div>
</div>
</div>
<div class="content">
<div class="content-middle">
<div class="item">
<div class="name">合计</div>
<div class="price">
<div class="price-right">{{ sumPrice }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {ref, defineProps, onMounted} from 'vue'
const {detail} = defineProps(['detail']);
const detailObj = ref<any>(detail)
const sumPrice = ref(0)
onMounted(() => {
const pharmaceuticalTotalAmount = detailObj.value.serviceDetail.reduce((pre: any, cur: any) => {
return pre + cur.number * cur.unitPrice
}, 0);
const serviceTotalAmount = detailObj.value.goodsDetail.reduce((pre: any, cur: any) => {
return pre + cur.number * cur.unitPrice
}, 0);
sumPrice.value = pharmaceuticalTotalAmount + serviceTotalAmount;
})
</script>
<style scoped lang="scss">
.disease-detail {
background: #F9FAFC;
padding: 0 21px 0 27px;
.top {
height: 60px;
border-bottom: 1px solid #EAEAEC;
display: flex;
justify-content: space-between;
align-items: center;
span {
background: #F9FAFC;
border-radius: 8px;
border: 1px solid #D8D8D8;
padding: 6px 24px;
font-weight: 400;
font-size: 16px;
color: #999999;
}
}
.content {
border-bottom: 1px solid #EAEAEC;
.content-title {
height: 46px;
display: flex;
align-items: center;
justify-content: space-between;
.name {
font-weight: bold;
font-size: 16px;
}
.btn {
color: #4D6DE4; //
border: none; //
font-size: 16px; //
cursor: pointer; //
background: #f9fafc;
}
}
.content-middle {
font-weight: 500;
font-size: 14px;
color: #999999;
p {
margin-bottom: 8px;
}
.item {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
.name{
white-space: nowrap; /* 防止文本换行 */
overflow: hidden; /* 隐藏溢出的文本 */
text-overflow: ellipsis; /* 显示省略号 */
width: 100px;
}
.price {
display: flex;
.price-left {
margin-right: 38px;
}
}
}
}
}
}
</style>

View File

@ -1,4 +1,5 @@
export function getKey(map: any, key: any) {
console.log(key)
if (Object.keys(map).length === 0) {
return "未知";
}

View File

@ -5,40 +5,18 @@
</div>
<div class="middle">
<el-scrollbar>
<Panel title="零售收费">
<el-form :model="formData" inline label-width="0">
<el-form-item>
<el-input v-model="formData.patientInfo.name" :disabled="statusDisabled==1"
placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item>
<el-select v-model="formData.patientInfo.sex" style="width: 80px;" :disabled="statusDisabled==1">
<el-option :label="'男'" :value="'1'"></el-option>
<el-option :label="'女'" :value="'2'"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-input v-model="formData.patientInfo.age" :disabled="statusDisabled==1">
<template #suffix>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-input v-model="formData.patientInfo.phone" placeholder="手机号" :disabled="statusDisabled==1">
</el-input>
</el-form-item>
<el-form-item>
<el-select v-model="formData.diagnosisMedicalRecord.dockerId" placeholder="医生" style="width: 100px"
:disabled="statusDisabled==1">
<el-option v-for="item in dockerList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
</Panel>
<div style="margin-top: 24px">
<div>
<Panel title="医疗诊断">
<template #tools>
<el-cascader
v-model="formData.doctorId"
:options="sectionDoctorOption"
:props="props"
@change="handleChange"
clearable
/>
</template>
<template #default>
<div style="height:64px;padding:0 24px 24px">
<DiagnosisSearchInput
v-model="diagnosisKeyword"
@ -49,10 +27,10 @@
:show-header="false"
:disabled="statusDisabled==1"
>
</DiagnosisSearchInput>
</div>
</template>
</Panel>
</div>
<div style="margin-top: 24px">
@ -72,8 +50,10 @@
</div>
<div class="right">
<div class="top">
<PatientCard v-model="formData.patientInfo"></PatientCard>
</div>
<div class="bottom">
<RecordsLog ref="recordsConsumptionRef"></RecordsLog>
</div>
</div>
</div>
@ -96,6 +76,11 @@ import GoodsDetail from "@/components/charge/GoodsDetail.vue";
import DiagnosisSearchInput from "@/components/outpatient/DiagnosisSearchInput.vue";
import Settlement from "@/components/charge/Settlement.vue";
import TotalPrice from "@/components/charge/TotalPrice.vue";
import psnCertTypes from "@/assets/config/directory/psnCertTypes.json"
import {getKey} from "@/utils/discrotyUtil.ts";
import antys from "@/assets/config/directory/antys.json"
import RecordsLog from "@/components/charge/RecordsLog.vue";
import PatientCard from "@/components/charge/PatientCard.vue";
const socialCard = ref<any>({payInfo: {}})
const formData = ref<any>({
@ -112,7 +97,7 @@ const delDraft = () => {
}
const settlementRef = ref()
const saveAndCharge = () => {
post('charge/save', {data: formData.value}).then((res: any) => {
post('charge/save', {data: {...formData.value,doctorId: doctorId.value}}).then((res: any) => {
formData.value.code = res
nextTick(() => {
settlementRef.value?.init(res)
@ -136,17 +121,18 @@ const diagnosisSelect = (list: any) => {
formData.value.diagnosisMedicalRecord.diagnosisDetail = JSON.stringify(list)
formData.value.diagnosisMedicalRecord.diagnosisSummary = diagnosisNames
}
const recordsConsumptionRef= ref<any>("")
const clickItem = async (item: any, status: any) => {
const clickItem = (item: any, status: any) => {
formData.value = item
formData.value = await post('medical/record/getByDiagnosisCode', {diagnosisCode: item.code})
statusDisabled.value = status
getOrderTotalPrice()
nextTick(() => {
let list = JSON.parse(formData.value.diagnosisMedicalRecord.diagnosisDetail)
let nList = formData.value.diagnosisMedicalRecord.diagnosisSummary.split(',')
diagnosisSearchRef.value?.init(list, nList);
recordsConsumptionRef.value?.init(formData.value.patientInfo.id);
})
}
const dockerList = ref<any[]>([])
const getDockerList = () => {
@ -172,6 +158,7 @@ const orderCanceled = () => {
onMounted(() => {
getDockerList()
list()
})
const getOrderTotalPrice = () => {
let totalPrice = 0
@ -184,13 +171,58 @@ const getOrderTotalPrice = () => {
formData.value.preTotalPrice = totalPrice
formData.value.totalPrice = totalPrice
}
const props = {
expandTrigger: 'hover' as const,
}
const doctorId=ref<any>('')
const handleChange = (value: any) => {
doctorId.value = value[value.length - 1]
}
const cardTypeList = ref<any>(Object.entries(psnCertTypes).map(([id, name]) => ({id, name})))
const sectionList = ref<any>([])
const doctorList = ref<any>([])
const sectionDoctorOption = ref<any>('')
const list = () => {
post('organization/section/allList').then((res: any) => {
sectionList.value = res
post('organization/member/search', {query: {role: 1}}).then((res: any) => {
doctorList.value = res
nextTick(() => {
generateOptions()
})
})
})
}
const generateOptions = () => {
if (!sectionList.value || !doctorList.value) return [];
sectionDoctorOption.value = sectionList.value.map((section: any) => {
console.log(section)
//
const doctors = doctorList.value.filter((doc: any) => doc.sectionId === section.id);
console.log(doctors)
return {
value: section.id,
label: section.name,
children: doctors.map((doc: any) => ({
value: doc.id,
label: doc.name,
})),
};
});
};
</script>
<style scoped lang="scss">
.container {
display: flex;
padding: 0 24px;
height: 100%;
width: 100%;
display: flex;
.left {
width: 320px;
@ -200,9 +232,9 @@ const getOrderTotalPrice = () => {
.middle {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
overflow: hidden;
.case {
background: #FFFFFF;
@ -234,16 +266,13 @@ const getOrderTotalPrice = () => {
}
.right {
width: 364px;
display: flex;
width: 400px;
margin-left: 24px;
display: flex;
flex-direction: column;
.top {
width: 100%;
height: 240px;
background: #FFFFFF;
border-radius: 8px;
height: 312px;
}
.bottom {
@ -261,7 +290,8 @@ const getOrderTotalPrice = () => {
}
.bottom{
.bottom {
margin-top: 24px;
height: 86px;
background: #FFFFFF;