版本更新
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取患者列表
|
||||
*/
|
||||
export function getList(queryParams) {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/encounter-list',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 诊疗列表
|
||||
*/
|
||||
export function getDisposalList(encounterId) {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/treatment-list?encounterId=' + encounterId,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行列表
|
||||
*/
|
||||
export function getExecuteList(queryParams) {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/execute-list',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
export function init() {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/init',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行
|
||||
*/
|
||||
export function execute(data) {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/perform',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
export function cancel(data) {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/cancel-perform',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取执行记录
|
||||
*/
|
||||
export function getPerformRecord(params) {
|
||||
return request({
|
||||
url: '/outpatient-manage/treatment/perform-record',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="执行记录"
|
||||
v-model="props.open"
|
||||
width="1000px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="close"
|
||||
@open="openDialog"
|
||||
>
|
||||
<el-table
|
||||
:data="recordList"
|
||||
highlight-current-row
|
||||
@row-click="handlePatientSelect"
|
||||
max-height="650"
|
||||
style="width: 100%"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="occurrenceTime" label="执行时间" align="center" width="150" />
|
||||
<el-table-column prop="statusEnum_enumText" label="执行状态" align="center" />
|
||||
<el-table-column prop="orgName" label="执行科室" align="center" width="100" />
|
||||
<el-table-column prop="practitionerName" label="执行人" align="center" width="100" />
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="close">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
recordList: {
|
||||
type: [],
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['close']);
|
||||
|
||||
function close() {
|
||||
emit('close');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
541
openhis-ui-vue3/src/views/clinicmanagement/disposal/index.vue
Normal file
541
openhis-ui-vue3/src/views/clinicmanagement/disposal/index.vue
Normal file
@@ -0,0 +1,541 @@
|
||||
<template>
|
||||
<div class="his-container">
|
||||
<!-- 主体内容区域 -->
|
||||
<div class="main-content">
|
||||
<!-- 左侧患者列表区域 -->
|
||||
<div class="section patient-section">
|
||||
<div class="section-header">
|
||||
<div class="section-title">
|
||||
<i class="el-icon-user"></i>
|
||||
<h2>患者列表</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-area">
|
||||
<el-input v-model="patientSearch" placeholder="搜索患者" clearable class="search-input" />
|
||||
</div>
|
||||
<el-table
|
||||
:data="patientList"
|
||||
highlight-current-row
|
||||
@row-click="handlePatientSelect"
|
||||
max-height="650"
|
||||
style="width: 100%"
|
||||
border
|
||||
>
|
||||
<el-table-column prop="encounterNo" label="就诊号" align="center" width="150" />
|
||||
<el-table-column prop="patientName" label="姓名" align="center" />
|
||||
<el-table-column prop="genderEnum_enumText" label="性别" align="center" width="100" />
|
||||
<el-table-column prop="age" label="年龄" align="center" width="100" />
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@pagination="getPatientList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 右侧区域 -->
|
||||
<div class="right-section">
|
||||
<!-- 处置项目区域 -->
|
||||
<div class="section treatment-section">
|
||||
<div class="section-header">
|
||||
<div class="section-title">
|
||||
<i class="el-icon-first-aid-kit"></i>
|
||||
<h2>处置项目</h2>
|
||||
<el-button type="primary" plain @click="printBottleLabel()">打印瓶签</el-button>
|
||||
<el-button type="primary" plain @click="printPrescription()">打印处方</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
:data="activityList"
|
||||
height="calc(100% - 60px)"
|
||||
style="width: 100%"
|
||||
border
|
||||
v-loading="loading"
|
||||
:span-method="operationSpanMethod"
|
||||
>
|
||||
<el-table-column type="selection" align="center" width="50" />
|
||||
<el-table-column label="序号" align="center" prop="sortNumber" width="60" />
|
||||
<el-table-column align="center" prop="busNo" label="项目编号" width="150" />
|
||||
<el-table-column align="center" prop="itemName" label="项目名称" />
|
||||
<!-- <el-table-column align="center" prop="medicationName" label="药品名称" /> -->
|
||||
<el-table-column
|
||||
align="center"
|
||||
prop="serviceCategory_dictText"
|
||||
label="项目类型"
|
||||
width="80"
|
||||
>
|
||||
<template #default="scope">
|
||||
{{
|
||||
scope.row.medCategory
|
||||
? scope.row.medCategory_dictText
|
||||
: scope.row.serviceCategory_dictText
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="size" label="规格" width="100" />
|
||||
<el-table-column align="center" prop="executeNum" label="执行次数" width="90" />
|
||||
<el-table-column align="center" label="已执行次数" width="90">
|
||||
<template #default="scope">
|
||||
{{ scope.row.performCount - scope.row.cancelCount }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="right"
|
||||
header-align="center"
|
||||
prop="unitPrice"
|
||||
label="单价"
|
||||
width="90"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>
|
||||
{{
|
||||
scope.row.unitPrice ? scope.row.unitPrice.toFixed(2) + ' 元' : '0.00' + ' 元'
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="right"
|
||||
header-align="center"
|
||||
prop="totalPrice"
|
||||
label="总价"
|
||||
width="90"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>{{
|
||||
scope.row.totalPrice ? scope.row.totalPrice.toFixed(2) + ' 元' : '0.00' + ' 元'
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="serviceStatus_enumText" label="状态" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" size="small">
|
||||
{{ row.serviceStatus_enumText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="text" @click="handleExecute(row)"> 执行 </el-button>
|
||||
<el-button type="danger" link @click="handleCancel(row)"> 取消 </el-button>
|
||||
<el-button type="text" @click="getRecord(row)">执行记录</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<!-- 耗材区域 -->
|
||||
<div class="section material-section">
|
||||
<div class="section-header">
|
||||
<div class="section-title">
|
||||
<i class="el-icon-box"></i>
|
||||
<h2>耗材使用</h2>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
:data="deviceList"
|
||||
height="calc(100% - 60px)"
|
||||
style="width: 100%"
|
||||
ref="deviceListRef"
|
||||
v-loading="loading"
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" align="center" width="50" />
|
||||
<el-table-column type="index" label="序号" align="center" width="60" />
|
||||
<el-table-column prop="itemName" align="center" label="耗材名称" />
|
||||
<el-table-column prop="size" align="center" label="规格" />
|
||||
<el-table-column prop="quantity" align="center" label="使用数量">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.quantity + ' ' + scope.row.unitCode_dictText }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" header-align="center" prop="unitPrice" label="单价">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.unitPrice ? scope.unitPrice.toFixed(2) : '0.00' + ' 元' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" header-align="center" prop="totalPrice" label="总价">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.totalPrice ? scope.totalPrice.toFixed(2) : '0.00' + ' 元' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="serviceStatus_enumText" label="状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag type="primary" size="small">
|
||||
{{ row.dispenseStatus_enumText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="操作" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-button type="text" size="small" @click="removeMaterial(row)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<PerformRecordDialog :open="openDialog" :recordList="recordList" @close="openDialog = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import { getList, getDisposalList, execute, cancel, getPerformRecord } from './components/api';
|
||||
import PerformRecordDialog from './components/performRecordDialog';
|
||||
|
||||
// 患者搜索
|
||||
const patientSearch = ref('');
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
const total = ref(0);
|
||||
// 患者数据
|
||||
const patientList = ref([]);
|
||||
// 处置项目列表
|
||||
const activityList = ref([]);
|
||||
// 耗材列表
|
||||
const deviceList = ref([]);
|
||||
|
||||
// 当前选中的患者
|
||||
const currentPatient = ref({});
|
||||
const recordList = ref([]);
|
||||
const openDialog = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 总费用计算
|
||||
const totalCost = computed(() => {
|
||||
if (!currentPatient.value.id) return 0;
|
||||
|
||||
const treatmentCost = currentPatient.value.treatments.reduce((sum, item) => sum + item.cost, 0);
|
||||
|
||||
const materialCost = currentPatient.value.materials.reduce(
|
||||
(sum, item) => sum + item.cost * item.quantity,
|
||||
0
|
||||
);
|
||||
|
||||
return treatmentCost + materialCost;
|
||||
});
|
||||
getPatientList();
|
||||
function getPatientList() {
|
||||
getList(queryParams.value).then((res) => {
|
||||
patientList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
}
|
||||
|
||||
function handlePatientSelect(row) {
|
||||
console.log(row, 3456789);
|
||||
loading.value = true;
|
||||
getDisposalList(row.encounterId).then((res) => {
|
||||
deviceList.value = res.data.records.filter((item) => {
|
||||
return item.requestTable == 'wor_device_request';
|
||||
});
|
||||
activityList.value = res.data.records.filter((item) => {
|
||||
return (
|
||||
item.requestTable == 'wor_service_request' || item.requestTable == 'med_medication_request'
|
||||
);
|
||||
});
|
||||
loading.value = false;
|
||||
console.log(activityList.value, 345678);
|
||||
});
|
||||
}
|
||||
|
||||
function handleExecute(row) {
|
||||
let data = {
|
||||
requestId: row.requestId,
|
||||
dispenseId: row.dispenseId,
|
||||
requestTable: row.requestTable,
|
||||
};
|
||||
let params = activityList.value
|
||||
.filter((item) => {
|
||||
return item.groupId == row.groupId;
|
||||
})
|
||||
.map((item) => {
|
||||
return {
|
||||
requestId: item.requestId,
|
||||
dispenseId: item.dispenseId,
|
||||
requestTable: item.requestTable,
|
||||
};
|
||||
});
|
||||
let list = proxy.$refs.deviceListRef.getSelectionRows().map((item) => {
|
||||
return {
|
||||
requestId: item.requestId,
|
||||
dispenseId: item.dispenseId,
|
||||
requestTable: item.requestTable,
|
||||
};
|
||||
});
|
||||
list.push(data);
|
||||
execute(params).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('执行成功');
|
||||
handlePatientSelect(row);
|
||||
} else {
|
||||
proxy.$modal.msgError(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 添加操作列的合并方法
|
||||
function operationSpanMethod({ row, column, rowIndex, columnIndex }) {
|
||||
// 操作列是最后一列,索引为11 (从0开始)
|
||||
if (columnIndex === 11) {
|
||||
const groupId = row.groupId;
|
||||
// 如果没有groupId,则不合并
|
||||
if (groupId === undefined || groupId === null) {
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
// 向上查找相同groupId的行,如果找到则隐藏当前行
|
||||
for (let i = rowIndex - 1; i >= 0; i--) {
|
||||
if (activityList.value[i].groupId === groupId) {
|
||||
return [0, 0]; // 隐藏被合并的行
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 向下统计相同groupId的行数
|
||||
let spanCount = 1;
|
||||
for (let i = rowIndex + 1; i < activityList.value.length; i++) {
|
||||
if (activityList.value[i].groupId === groupId) {
|
||||
spanCount++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [spanCount, 1];
|
||||
}
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
// 判断是否为组内的第一行
|
||||
function isFirstRowInGroup(rowIndex) {
|
||||
const row = activityList.value[rowIndex];
|
||||
const groupId = row.groupId;
|
||||
|
||||
// 如果没有groupId,每行都显示操作按钮
|
||||
if (groupId === undefined || groupId === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查是否为该groupId的第一行
|
||||
for (let i = rowIndex - 1; i >= 0; i--) {
|
||||
if (activityList.value[i].groupId === groupId) {
|
||||
return false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCancel(row) {
|
||||
let data = {
|
||||
requestId: row.requestId,
|
||||
dispenseId: row.dispenseId,
|
||||
requestTable: row.requestTable,
|
||||
};
|
||||
let params = activityList.value
|
||||
.filter((item) => {
|
||||
return item.groupId == row.groupId;
|
||||
})
|
||||
.map((item) => {
|
||||
return {
|
||||
requestId: item.requestId,
|
||||
dispenseId: item.dispenseId,
|
||||
requestTable: item.requestTable,
|
||||
};
|
||||
});
|
||||
cancel(params).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('操作成功');
|
||||
handlePatientSelect(row);
|
||||
} else {
|
||||
proxy.$modal.msgError(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
function getRecord(row) {
|
||||
getPerformRecord({ reqId: row.requestId }).then((res) => {
|
||||
recordList.value = res.data;
|
||||
openDialog.value = true;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.his-container {
|
||||
height: 90vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #f0f2f5;
|
||||
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', Arial, sans-serif;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 20px;
|
||||
overflow: hidden;
|
||||
height: calc(100% - 70px);
|
||||
}
|
||||
|
||||
.patient-section {
|
||||
min-width: 400px;
|
||||
width: 28%;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.right-section {
|
||||
flex: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
.current-patient {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.patient-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.patient-avatar {
|
||||
background: #e6f7ff;
|
||||
border-radius: 50%;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.patient-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.patient-name {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.patient-gender,
|
||||
.patient-age {
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.patient-meta {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.meta-item i {
|
||||
margin-right: 5px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.patient-status {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.total-cost {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.cost-value {
|
||||
font-weight: 600;
|
||||
color: #e53935;
|
||||
font-size: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.treatment-section,
|
||||
.material-section {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
padding: 20px 10px 5px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.section-title h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.section-title i {
|
||||
font-size: 20px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 200px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user