前端最新版本同步
This commit is contained in:
59
openhis-ui-vue3/src/views/basicmanage/caseTemplates/api.js
Normal file
59
openhis-ui-vue3/src/views/basicmanage/caseTemplates/api.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询诊疗项目列表
|
||||
export function getTreeList(queryParams) {
|
||||
return request({
|
||||
url: '/document/definition/treeList',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化
|
||||
export function init() {
|
||||
return request({
|
||||
url: '/document/definition/init',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增
|
||||
export function add(data) {
|
||||
return request({
|
||||
url: '/document/definition/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改
|
||||
export function update(data) {
|
||||
return request({
|
||||
url: '/document/definition/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 查询就诊科室
|
||||
export function getLocationTree(query) {
|
||||
return request({
|
||||
url: '/charge-manage/register/org-list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询就诊科室
|
||||
export function getDefinitionById(id) {
|
||||
return request({
|
||||
url: `/document/definition/${id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export function deleteDefinition(id) {
|
||||
return request({
|
||||
url: `/document/definition/delete/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
<template>
|
||||
<!-- 病历文件基本信息弹窗 -->
|
||||
<el-dialog
|
||||
:title="title"
|
||||
v-model="dialogVisible"
|
||||
width="900px"
|
||||
destroy-on-close
|
||||
@open="handleOpen"
|
||||
>
|
||||
<!-- 使用el-form包裹表单 -->
|
||||
<el-form :model="formData" ref="formRef" :rules="rules" label-width="120px">
|
||||
<el-form-item label="一级菜单" prop="primaryMenuEnum">
|
||||
<el-select
|
||||
v-model="formData.primaryMenuEnum"
|
||||
placeholder="请选择一级菜单"
|
||||
value-key="value"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in props.docTypes || []"
|
||||
:key="item.value"
|
||||
:label="item.info"
|
||||
:value="Number(item.value)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="二级菜单" prop="subMenu">
|
||||
<el-input v-model="formData.subMenu" placeholder="二级菜单"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本" prop="version">
|
||||
<el-input v-model="formData.version" placeholder="请输入版本"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件" prop="vueRouter">
|
||||
<el-select v-model="formData.vueRouter" placeholder="请选择文件路径">
|
||||
<el-option
|
||||
v-for="item in components"
|
||||
:key="item.name"
|
||||
:label="item.name"
|
||||
:value="item.name"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- <el-input v-model="formData.vueRouter" placeholder="请输入文件路径"></el-input>s -->
|
||||
</el-form-item>
|
||||
<el-form-item label="显示顺序" prop="displayOrder">
|
||||
<el-input-number v-model="formData.displayOrder" :min="1" label="描述文字"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="使用范围" prop="useRangeEnum">
|
||||
<div class="radio-group">
|
||||
<el-radio
|
||||
v-for="item in props.useRanges"
|
||||
:key="item.value"
|
||||
v-model="formData.useRangeEnum"
|
||||
:label="item.value"
|
||||
>{{item.info}}</el-radio>
|
||||
|
||||
{{ formData.organizationIds }}
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 科室选择框,仅当使用范围为科室使用时显示 -->
|
||||
<el-form-item v-if="formData.useRangeEnum === 2" label="科室选择" prop="organizationIds">
|
||||
<el-transfer
|
||||
v-model="formData.organizationIds"
|
||||
filterable
|
||||
:titles="['未分配科室', '已分配科室']"
|
||||
:button-texts="['移除', '添加']"
|
||||
:format="{
|
||||
noChecked: '${total}',
|
||||
hasChecked: '${checked}/${total}',
|
||||
}"
|
||||
:props="{key: 'id', label: 'name',}"
|
||||
:data="transferData"
|
||||
>
|
||||
</el-transfer>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer"></div>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script setup >
|
||||
import { ref, onMounted } from 'vue'
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { add, update,getLocationTree } from '../api';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { components } from '@/template';
|
||||
const emits = defineEmits(['submitOk'])
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '编辑病历文件信息'
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
currentNodeData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
docTypes: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
useRanges: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
})
|
||||
const userStore = useUserStore();
|
||||
const formRef = ref(null)
|
||||
|
||||
const dialogVisible= defineModel( 'dialogVisible', {
|
||||
type: Boolean,
|
||||
default: false
|
||||
})
|
||||
|
||||
// 表单数据
|
||||
const formData = ref({
|
||||
primaryMenuEnum: undefined,
|
||||
subMenu: '',
|
||||
displayOrder: 1,
|
||||
version: '',
|
||||
name: '',
|
||||
vueRouter: '',
|
||||
useRangeEnum: 0, // 默认"暂不使用"(0:暂不使用,1:全院使用,2:科室使用)
|
||||
organizationIds: [], // 选中的科室ID列表(整数类型)
|
||||
environment: '0'
|
||||
});
|
||||
// 表单验证规则(响应式,支持动态验证)
|
||||
const rules = reactive({
|
||||
primaryMenuEnum: [{ required: true, message: '请选择一级菜单', trigger: 'change' }],
|
||||
// subMenu: [{ required: true, message: '请输入二级菜单', trigger: 'blur' }],
|
||||
version: [{ required: true, message: '请输入版本', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
||||
vueRouter: [{ required: true, message: '请输入文件路径', trigger: 'blur' }],
|
||||
displayOrder: [{ required: true, message: '请设置显示顺序', trigger: 'change' }],
|
||||
useRangeEnum: [{ required: true, message: '请选择使用范围', trigger: 'change' }],
|
||||
organizationIds: [
|
||||
{
|
||||
required: () => formData.value.useRangeEnum === 2, // 仅当"科室使用"时必填
|
||||
message: '请选择科室',
|
||||
trigger: ['change', 'blur']
|
||||
}
|
||||
]
|
||||
});
|
||||
const transferData = ref([]);
|
||||
/** 查询科室树数据(TreeSelect和Transfer共用) */
|
||||
const getLocationInfo = () => {
|
||||
|
||||
getLocationTree().then((response) => {
|
||||
transferData.value = response?.data || [];
|
||||
}).catch((error) => {
|
||||
ElMessage.error('获取科室树失败');
|
||||
});
|
||||
}
|
||||
/** 递归将所有ID转换为整数类型 */
|
||||
const convertIdsToNumbers = (item) => {
|
||||
return {
|
||||
...item,
|
||||
id: Number(item.id), // 确保ID为整数
|
||||
...(item.children && item.children.length > 0
|
||||
? { children: item.children.map((child ) => convertIdsToNumbers(child)) }
|
||||
: {})
|
||||
};
|
||||
};
|
||||
const handleOpen = () => {
|
||||
|
||||
|
||||
if (props.formData) {
|
||||
console.log('props.formData', props.formData);
|
||||
formData.value= props.formData
|
||||
} else {
|
||||
resetForm();
|
||||
formRef.value.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const submitForm = () => {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
// 表单验证通过,执行保存操作
|
||||
saveForm();
|
||||
} else {
|
||||
// 表单验证失败
|
||||
ElMessage.error('请填写必填项');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
// 保存表单
|
||||
const saveForm =async () => {
|
||||
const userStore = useUserStore()
|
||||
console.log('提交表单数据:', formData.value);
|
||||
let data = { ...formData.value, tenantId: userStore.tenantId }
|
||||
if (formData.value.useRangeEnum !== 2) {
|
||||
formData.value.organizationIds = [];
|
||||
}
|
||||
try {
|
||||
// 如果有当前节点数据,表示是编辑操作
|
||||
if (props.currentNodeData) {
|
||||
data.id = props.currentNodeData.id; // 添加ID
|
||||
data.busNo = props.currentNodeData.busNo;
|
||||
data.hospitalId = props.currentNodeData.hospitalId;
|
||||
console.log('data',data)
|
||||
const res = await update(data);
|
||||
if (res.code == 200) {
|
||||
ElMessage.success('更新成功');
|
||||
emits('submitOk')
|
||||
}else {
|
||||
ElMessage.error('保存失败');
|
||||
}
|
||||
} else {
|
||||
// 新建操作
|
||||
const res = await add(data);
|
||||
if (res.code == 200) {
|
||||
ElMessage.success('保存成功');
|
||||
emits('submitOk')
|
||||
}else {
|
||||
ElMessage.error('保存失败',error);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error)
|
||||
// ElMessage.error('保存失败',error);
|
||||
}
|
||||
}
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
formRef.value?.resetFields();
|
||||
formData.value.useRangeEnum = 0;
|
||||
formData.value.environment = '0';
|
||||
formData.value.organizationIds = [];
|
||||
};
|
||||
|
||||
onMounted(()=>{
|
||||
getLocationInfo()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -1,2 +1,436 @@
|
||||
<template>
|
||||
</template>
|
||||
<div class="case-templates-container">
|
||||
<!-- 顶部工具栏 -->
|
||||
<div class="toolbar">
|
||||
<el-button type="primary" @click="newTemplate">新建</el-button>
|
||||
<el-button type="primary" @click="editTemplate">编辑</el-button>
|
||||
<el-button @click="refresh">刷新</el-button>
|
||||
<el-button type="danger" @click="deleteTemplate">删除</el-button>
|
||||
<el-button @click="printTemplate">打印</el-button>
|
||||
</div>
|
||||
|
||||
<div class="content-area">
|
||||
<!-- 左侧病历类型树 -->
|
||||
<div class="left-panel">
|
||||
<div style="margin-bottom: 10px">
|
||||
<el-tree-select
|
||||
v-model="orgId"
|
||||
:data="orgOptions"
|
||||
:props="{
|
||||
value: 'id',
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
}"
|
||||
value-key="id"
|
||||
placeholder="请选择就诊科室"
|
||||
check-strictly
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
ref="locationTreeRef"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="initTemplateTree"
|
||||
@clear="handleOrgClear"
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="search-box">
|
||||
<el-input
|
||||
placeholder="病历名称搜索..."
|
||||
v-model="searchKeyword"
|
||||
></el-input>
|
||||
<el-button class="search-btn" @click="handleSearch">查询</el-button>
|
||||
</div>
|
||||
|
||||
<el-tree
|
||||
ref="templateTree"
|
||||
:data="templateData"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
@node-click="handleNodeClick"
|
||||
class="template-tree"
|
||||
></el-tree>
|
||||
<el-button @click="toggleExpand">{{ isExpanded ? '全部收起' : '全部展开' }}</el-button>
|
||||
</div>
|
||||
<div class="middle-panel">
|
||||
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick">
|
||||
<el-tab-pane label="打印预览" name="first">
|
||||
<!-- {{components}} -->
|
||||
<component :is="currentComponent" />
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="编辑内容" name="second">
|
||||
<component :is="currentComponent" />
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
<EditTemplate
|
||||
v-model:dialogVisible="dialogVisible"
|
||||
:title="currentNodeData ? '编辑病历文件信息' : '病历文件基本信息'"
|
||||
:formData="formData"
|
||||
:currentNodeData="currentNodeData"
|
||||
@submitOk="handleSubmitOk"
|
||||
:docTypes="templateDataInit.docTypes"
|
||||
:useRanges="templateDataInit.useRanges"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
// 从Vue导入所需的API
|
||||
import { ref, reactive, onMounted, defineAsyncComponent, nextTick, watch } from 'vue';
|
||||
import { ElMessageBox, ElMessage, ElLoading, ElTree } from 'element-plus';
|
||||
import { getTreeList, init, getDefinitionById, deleteDefinition,getLocationTree } from './api';
|
||||
import EditTemplate from './components/editTemplate.vue';
|
||||
// 添加当前模板路径和组件的响应式变量
|
||||
const currentComponent = ref('');
|
||||
const currentNodeData = ref(null); // 存储当前选中的节点数据
|
||||
const isExpanded = ref(true); // 控制树形结构的展开状态
|
||||
// 弹窗可见性
|
||||
const dialogVisible = ref(false);
|
||||
|
||||
const orgId = ref('');
|
||||
const orgOptions = ref([]); // 科室选项(整数ID)
|
||||
const locationTreeRef = ref(null); // TreeSelect引用
|
||||
const templateTree = ref(null);
|
||||
const searchKeyword = ref(''); // 搜索关键字
|
||||
|
||||
const activeName = ref('first');
|
||||
// Transfer组件选项类型定义(ID为整数类型)
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
primaryMenuEnum: undefined,
|
||||
subMenu: '',
|
||||
displayOrder: 1,
|
||||
version: '',
|
||||
name: '',
|
||||
vueRouter: '',
|
||||
useRangeEnum: 0, // 默认"暂不使用"(0:暂不使用,1:全院使用,2:科室使用)
|
||||
organizationIds: [], // 选中的科室ID列表(整数类型)
|
||||
environment: '0',
|
||||
});
|
||||
|
||||
const initFormData = () => {
|
||||
formData.primaryMenuEnum = undefined;
|
||||
formData.subMenu = '';
|
||||
formData.displayOrder = 1;
|
||||
formData.version = '';
|
||||
formData.name = '';
|
||||
formData.vueRouter = '';
|
||||
formData.useRangeEnum = 0;
|
||||
formData.organizationIds = [];
|
||||
formData.environment = '0';
|
||||
};
|
||||
const getLocationInfo = () => {
|
||||
getLocationTree().then((response) => {
|
||||
orgOptions.value = response?.data || [];
|
||||
}).catch((error) => {
|
||||
ElMessage.error('获取科室树失败');
|
||||
});
|
||||
}
|
||||
const handleSubmitOk = () => {
|
||||
dialogVisible.value = false;
|
||||
initFormData();
|
||||
refresh();
|
||||
};
|
||||
|
||||
// 组件初始化时加载基础数据
|
||||
onMounted(() => {
|
||||
getInit(); // 加载模板初始化数据(一级菜单、使用范围等)
|
||||
getLocationInfo(); // 加载科室树
|
||||
handleOrgClear(); // 初始化模板树(加载所有科室模板)
|
||||
});
|
||||
|
||||
/** 将树形结构转换为Transfer组件所需的格式(不扁平化,保留层级关系) */
|
||||
const convertTreeToTransferFormat = (tree) => {
|
||||
return tree.map((item) => {
|
||||
const option = {
|
||||
key: item.id, // 整数ID
|
||||
label: item.name,
|
||||
disabled: false,
|
||||
};
|
||||
|
||||
// 如果有子节点,递归处理(Transfer组件会自动处理层级显示)
|
||||
if (item.children && item.children.length > 0) {
|
||||
option.children = convertTreeToTransferFormat(item.children);
|
||||
}
|
||||
|
||||
return option;
|
||||
});
|
||||
};
|
||||
|
||||
// 病历模板树数据
|
||||
const templateData = ref([]);
|
||||
const templateDataInit = ref({}); // 初始化数据(菜单、使用范围)
|
||||
|
||||
// 树配置(模板树)
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
};
|
||||
|
||||
/** 过滤节点(科室TreeSelect搜索) */
|
||||
const filterNode = (value, data) => {
|
||||
if (!value) return true;
|
||||
return data?.name.toLowerCase().includes(value.toLowerCase()); // 不区分大小写搜索
|
||||
};
|
||||
|
||||
/** 统一的API错误处理函数 */
|
||||
const handleApiError = (userMessage, logMessage) => {
|
||||
return (error) => {
|
||||
// 记录详细错误日志,包括错误对象和调用栈
|
||||
console.error(`${logMessage}:`, error);
|
||||
// 显示用户友好的错误提示
|
||||
ElMessage.error(
|
||||
`${userMessage}失败${error.message ? ': ' + error.message : ',请刷新页面重试'}`
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/** 加载模板初始化数据(一级菜单、使用范围枚举) */
|
||||
const getInit = async () => {
|
||||
try {
|
||||
const response = await init();
|
||||
templateDataInit.value = response.data || {};
|
||||
console.log('模板初始化数据:', templateDataInit.value);
|
||||
} catch (error) {
|
||||
handleApiError('初始化', '初始化接口异常')(error);
|
||||
}
|
||||
};
|
||||
|
||||
/** 清除科室选择时,加载所有科室模板 */
|
||||
const handleOrgClear = () => {
|
||||
orgId.value = '';
|
||||
initTemplateTree({ id: '' });
|
||||
};
|
||||
|
||||
/** 搜索模板(可扩展按科室+关键字筛选) */
|
||||
const handleSearch = () => {
|
||||
console.log('搜索模板,关键字:', searchKeyword.value);
|
||||
initTemplateTree({ id: orgId.value });
|
||||
};
|
||||
|
||||
/** 初始化病历模板树(按科室筛选) */
|
||||
function initTemplateTree(data) {
|
||||
const queryParams = {
|
||||
organizationId: data.id || '', // 科室ID(空表示所有科室)
|
||||
name: searchKeyword.value || '', // 模板名称(空表示不筛选)
|
||||
};
|
||||
|
||||
getTreeList(queryParams)
|
||||
.then((res) => {
|
||||
templateData.value = res.data || [];
|
||||
nextTick().then(() => {
|
||||
expandTree(); // 展开树节点
|
||||
})
|
||||
|
||||
// console.log('模板树数据(按科室筛选):', templateData.value);
|
||||
})
|
||||
.catch((error) => {
|
||||
handleApiError('获取模板列表', '获取模板树失败')(error);
|
||||
templateData.value = [];
|
||||
});
|
||||
}
|
||||
|
||||
/** 编辑模板(打开弹窗并回显数据) */
|
||||
const editTemplate = async () => {
|
||||
if (!currentNodeData.value) {
|
||||
ElMessage.warning('请先选择一个模板节点');
|
||||
return;
|
||||
}
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '加载模板信息...',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await getDefinitionById(currentNodeData.value.id);
|
||||
if (response.data) {
|
||||
openEditDialog(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
handleApiError('加载模板信息', '加载模板信息失败')(error);
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
};
|
||||
|
||||
/** 打开编辑弹窗,回显选中的模板数据并正确初始化科室选择 */
|
||||
const openEditDialog = async (nodeData) => {
|
||||
currentNodeData.value = nodeData;
|
||||
console.log('回显模板数据:', nodeData);
|
||||
|
||||
// 回显表单数据(与接口返回字段匹配)
|
||||
formData.primaryMenuEnum = nodeData.primaryMenuEnum;
|
||||
formData.subMenu = nodeData.subMenu;
|
||||
formData.version = nodeData.version;
|
||||
formData.name = nodeData.name;
|
||||
formData.vueRouter = nodeData.vueRouter;
|
||||
formData.displayOrder = nodeData.displayOrder;
|
||||
formData.useRangeEnum = nodeData.useRangeEnum;
|
||||
formData.environment = nodeData.environment || '0';
|
||||
|
||||
formData.organizationIds = nodeData.organizationIds.map((id) => id.toString());
|
||||
// 打开弹窗
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 处理节点点击,根据后台返回的路径加载组件
|
||||
const handleNodeClick = async (data, node) => {
|
||||
console.log('点击节点:', data, node);
|
||||
// 检查是否为子节点(没有children或children为空)
|
||||
// const isLeafNode = !data.children || data.children.length === 0;
|
||||
if (node.isLeaf) {
|
||||
// 存储当前节点数据
|
||||
currentNodeData.value = data.document;
|
||||
// 检查是否为子节点(没有children或children为空)
|
||||
currentComponent.value = data.document.vueRouter || '';
|
||||
} else {
|
||||
currentNodeData.value = null;
|
||||
currentComponent.value = null;
|
||||
}
|
||||
};
|
||||
const toggleExpand = () => {
|
||||
isExpanded.value = !isExpanded.value;
|
||||
console.log('展开状态:', templateTree.value.store);
|
||||
expandTree();
|
||||
};
|
||||
const expandTree = () => {
|
||||
templateTree.value.store._getAllNodes().forEach((node) => {
|
||||
node.expanded = isExpanded.value;
|
||||
});
|
||||
};
|
||||
const refresh = () => {
|
||||
initTemplateTree({ id: orgId.value });
|
||||
};
|
||||
|
||||
// 新建模板
|
||||
const newTemplate = () => {
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
// 删除模板
|
||||
const deleteTemplate = async () => {
|
||||
// 1. 检查是否选中节点
|
||||
if (!currentNodeData.value) {
|
||||
ElMessage.warning('请先选择一个模板节点');
|
||||
return;
|
||||
}
|
||||
|
||||
let loading = null;
|
||||
const templateName = currentNodeData.value.name;
|
||||
const templateId = currentNodeData.value.id;
|
||||
try {
|
||||
// 2. 显示确认对话框,增加操作描述
|
||||
const confirmResult = await ElMessageBox.confirm(
|
||||
`确定要删除模板「${templateName}」吗?<br>此操作不可撤销,删除后将无法恢复。`,
|
||||
'删除确认',
|
||||
{
|
||||
confirmButtonText: '确认删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
dangerouslyUseHTMLString: true,
|
||||
center: true,
|
||||
closeOnClickModal: false,
|
||||
}
|
||||
);
|
||||
|
||||
// 3. 用户确认删除后执行操作
|
||||
if (confirmResult === 'confirm') {
|
||||
// 显示加载状态
|
||||
loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '正在删除模板...',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
});
|
||||
|
||||
// 调用删除API
|
||||
await deleteDefinition(templateId);
|
||||
// 删除成功处理
|
||||
ElMessage.success(`模板「${templateName}」删除成功`);
|
||||
// 清空当前选中状态
|
||||
currentNodeData.value = null;
|
||||
initFormData();
|
||||
currentComponent.value = null;
|
||||
// 刷新列表
|
||||
refresh();
|
||||
}
|
||||
} catch (error) {
|
||||
// 错误处理:区分用户取消和API错误
|
||||
if (error === 'cancel' || error === undefined) {
|
||||
// 用户取消删除,不显示错误提示
|
||||
console.log('用户取消删除操作');
|
||||
} else {
|
||||
// API错误或其他错误,使用统一的错误处理函数
|
||||
handleApiError('删除模板', '删除模板失败')(error);
|
||||
}
|
||||
} finally {
|
||||
// 确保加载状态总是被关闭
|
||||
if (loading) {
|
||||
loading.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 打印模板
|
||||
const printTemplate = () => {
|
||||
window.print();
|
||||
};
|
||||
|
||||
// 标签页点击事件
|
||||
const handleClick = (tab) => {
|
||||
console.log('标签页点击:', tab);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.case-templates-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 91vh;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
background-color: #f5f5f5;
|
||||
border-bottom: 1px solid #ddd;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
width: 280px;
|
||||
border-right: 1px solid #ddd;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.template-tree {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.middle-panel {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<PopoverList @search="handleSearch" :width="800" :modelValue="scope.row.name">
|
||||
<template #popover-content="{}">
|
||||
<DeviceList
|
||||
v-if="scope.row.type == '2'"
|
||||
v-if="scope.row.type == '2' || props.tab == 2 "
|
||||
@selectRow="(row) => selectRow(row, scope.$index)"
|
||||
:searchKey="searchKey"
|
||||
/>
|
||||
@@ -58,6 +58,26 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" align="center" prop="unitCode_dictText" width="100">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isEdit">{{ scope.row.unitCode_dictText }}</span>
|
||||
<el-form-item
|
||||
v-else
|
||||
:prop="`consumablesList.${scope.$index}.unitCode`"
|
||||
:rules="rules.unitCode"
|
||||
>
|
||||
<el-select v-model="scope.row.unitCode" placeholder="">
|
||||
<el-option
|
||||
v-for="(item, index) in scope.row.unitCodeList"
|
||||
@click="handleUnitCodeClick(item)"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="使用范围" align="center" prop="rangeCode" width="150">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isEdit">{{ scope.row.rangeCode_dictText }}</span>
|
||||
@@ -70,7 +90,7 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="范围" align="center" prop="rangeCode" width="250">
|
||||
<!-- <el-table-column label="范围" align="center" prop="rangeCode" width="250">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isEdit">{{ scope.row.rangeCode_dictText }}</span>
|
||||
<el-form-item
|
||||
@@ -88,7 +108,7 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="启用状态" align="center" prop="statusEnum" width="250">
|
||||
<template #default="scope">
|
||||
<span v-if="!scope.row.isEdit">{{ scope.row.statusEnum_dictText }}</span>
|
||||
@@ -208,6 +228,8 @@ watch(
|
||||
quantity: item.quantity,
|
||||
rangeCode: item.rangeCode,
|
||||
rangeCode_dictText: item.rangeCode_dictText,
|
||||
unitCode: item.unitCode,
|
||||
unitCode_dictText: item.unitCode_dictText,
|
||||
statusEnum: item.statusEnum,
|
||||
statusEnum_dictText: item.statusEnum_enumText,
|
||||
typeCode: item.typeCode,
|
||||
@@ -259,8 +281,9 @@ function handleSave(row, index) {
|
||||
itemNo: props.bindInfo.id,
|
||||
devActId: row.devActId,
|
||||
typeCode: props.bindInfo.typeCode,
|
||||
rangeCode: row.rangeCode,
|
||||
rangeCode: '3',
|
||||
quantity: row.quantity,
|
||||
unitCode: row.unitCode,
|
||||
statusEnum: row.statusEnum,
|
||||
id: row.id ? row.id : undefined,
|
||||
devActTable: row.type == '1' ? 'wor_activity_definition' : 'adm_device_definition',
|
||||
@@ -298,6 +321,10 @@ function initOptions() {
|
||||
});
|
||||
}
|
||||
|
||||
function handleUnitCodeClick(row, item) {
|
||||
row.unitCode_dictText = item.label;
|
||||
}
|
||||
|
||||
function handleSearch(value) {
|
||||
searchKey.value = value;
|
||||
}
|
||||
@@ -306,6 +333,16 @@ initOptions();
|
||||
function selectRow(row, index) {
|
||||
form.consumablesList[index].devActId = row.id;
|
||||
form.consumablesList[index].name = row.name;
|
||||
if (row.minUnitCode == row.unitCode) {
|
||||
form.consumablesList[index].unitCodeList = [
|
||||
{ label: row.unitCode_dictText, value: row.unitCode },
|
||||
];
|
||||
} else {
|
||||
form.consumablesList[index].unitCodeList = [
|
||||
{ label: row.unitCode_dictText, value: row.unitCode },
|
||||
{ label: row.minUnitCode_dictText, value: row.minUnitCode },
|
||||
];
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ import {
|
||||
deleteImplementDepartment,
|
||||
} from './components/implementDepartment';
|
||||
import { debounce } from 'lodash-es';
|
||||
import { fa } from 'element-plus/es/locales.mjs';
|
||||
const { proxy } = getCurrentInstance();
|
||||
const organization = ref([]);
|
||||
const loading = ref(true);
|
||||
@@ -256,12 +257,14 @@ function DiagnosisTreatmentList(row,index,type) {
|
||||
}else if(type == 2){
|
||||
params.searchKey = row.activityDefinitionId_dictText
|
||||
}
|
||||
console.log(params,'params');
|
||||
getImplementDepartmentOne(params)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
projectList.value = [];
|
||||
row.name = null;
|
||||
projectList.value = res.data.records.map((item) => ({ value: item.id, info: item.name }));
|
||||
|
||||
catagoryList.value[index].projectList = projectList.value
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg);
|
||||
@@ -278,7 +281,12 @@ function remoteMethod(query, row) {
|
||||
statusEnum: 2,
|
||||
activityCategoryCode: row.activityCategoryCode, // 确保已选诊疗目录
|
||||
searchKey: query, // 模糊搜索关键字
|
||||
...row,
|
||||
categoryCode: row.activityCategoryCode,
|
||||
pageSize:100,
|
||||
};
|
||||
console.log(params,row,query,'params');
|
||||
|
||||
getImplementDepartmentOne(params).then((res) => {
|
||||
loading.value = false;
|
||||
if (res.code === 200) {
|
||||
@@ -291,6 +299,8 @@ function remoteMethod(query, row) {
|
||||
proxy.$modal.msgError(res.msg);
|
||||
}
|
||||
});
|
||||
loading.value = false;
|
||||
|
||||
}
|
||||
|
||||
/** 选择条数 */
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div @keyup="handleKeyDown" tabindex="0" ref="tableWrapper">
|
||||
<el-table
|
||||
ref="adviceBaseRef"
|
||||
height="400"
|
||||
:data="adviceBaseList"
|
||||
highlight-current-row
|
||||
@current-change="handleCurrentChange"
|
||||
row-key="patientId"
|
||||
@cell-click="clickRow"
|
||||
>
|
||||
<el-table-column label="名称" align="center" prop="adviceName" />
|
||||
<el-table-column label="类型" align="center" prop="activityType_enumText" />
|
||||
<el-table-column label="包装单位" align="center" prop="unitCode_dictText" />
|
||||
<el-table-column label="最小单位" align="center" prop="minUnitCode_dictText" />
|
||||
<el-table-column label="规格" align="center" prop="volume" />
|
||||
<el-table-column label="用法" align="center" prop="methodCode_dictText" />
|
||||
<el-table-column label="频次" align="center" prop="rateCode_dictText" />
|
||||
<el-table-column label="单次剂量" align="center" prop="dose" />
|
||||
<el-table-column label="剂量单位" align="center" prop="doseUnitCode_dictText" />
|
||||
<el-table-column label="注射药品" align="center" prop="injectFlag_enumText" />
|
||||
<el-table-column label="皮试" align="center" prop="skinTestFlag_enumText" />
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { nextTick } from 'vue';
|
||||
import { getAdviceBaseInfo } from './api';
|
||||
import { throttle } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
adviceQueryParams: {
|
||||
type: Object,
|
||||
default: '',
|
||||
},
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['selectAdviceBase']);
|
||||
const total = ref(0);
|
||||
const adviceBaseRef = ref();
|
||||
const tableWrapper = ref();
|
||||
const currentIndex = ref(0); // 当前选中行索引
|
||||
const currentSelectRow = ref({});
|
||||
const queryParams = ref({
|
||||
pageSize: 100,
|
||||
pageNum: 1,
|
||||
adviceTypes: '2,3',
|
||||
});
|
||||
const adviceBaseList = ref([]);
|
||||
// 节流函数
|
||||
const throttledGetList = throttle(
|
||||
() => {
|
||||
getList();
|
||||
},
|
||||
300,
|
||||
{ leading: true, trailing: true }
|
||||
);
|
||||
|
||||
// 监听adviceQueryParams变化
|
||||
watch(
|
||||
() => props.adviceQueryParams,
|
||||
(newValue) => {
|
||||
queryParams.value.searchKey = newValue.searchKey;
|
||||
queryParams.value.adviceType = newValue.adviceType;
|
||||
console.log(queryParams.value);
|
||||
throttledGetList();
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 监听searchKey变化
|
||||
watch(
|
||||
() => props.adviceQueryParams?.searchKey,
|
||||
(newVal) => {
|
||||
queryParams.value.searchKey = newVal;
|
||||
throttledGetList();
|
||||
}
|
||||
);
|
||||
|
||||
getList();
|
||||
function getList() {
|
||||
// queryParams.value.organizationId = '1922545444781481985';
|
||||
getAdviceBaseInfo(queryParams.value).then((res) => {
|
||||
adviceBaseList.value = res.data.records;
|
||||
console.log(adviceBaseList.value)
|
||||
total.value = res.data.total;
|
||||
nextTick(() => {
|
||||
currentIndex.value = 0;
|
||||
if (adviceBaseList.value.length > 0) {
|
||||
adviceBaseRef.value.setCurrentRow(adviceBaseList.value[0]);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 处理键盘事件
|
||||
const handleKeyDown = (event) => {
|
||||
const key = event.key;
|
||||
const data = adviceBaseList.value;
|
||||
|
||||
switch (key) {
|
||||
case 'ArrowUp': // 上箭头
|
||||
event.preventDefault(); // 阻止默认滚动行为
|
||||
if (currentIndex.value > 0) {
|
||||
currentIndex.value--;
|
||||
setCurrentRow(data[currentIndex.value]);
|
||||
}
|
||||
break;
|
||||
case 'ArrowDown': // 下箭头`
|
||||
event.preventDefault();
|
||||
if (currentIndex.value < data.length - 1) {
|
||||
currentIndex.value++;
|
||||
setCurrentRow(data[currentIndex.value]);
|
||||
}
|
||||
break;
|
||||
case 'Enter': // 回车键
|
||||
// const currentRow = adviceBaseRef.value.getSelectionRows();
|
||||
event.preventDefault();
|
||||
if (currentSelectRow.value) {
|
||||
// 这里可以触发自定义逻辑,如弹窗、跳转等
|
||||
emit('selectAdviceBase', currentSelectRow.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// 设置选中行(带滚动)
|
||||
const setCurrentRow = (row) => {
|
||||
adviceBaseRef.value.setCurrentRow(row);
|
||||
// 滚动到选中行
|
||||
const tableBody = adviceBaseRef.value.$el.querySelector('.el-table__body-wrapper');
|
||||
const currentRowEl = adviceBaseRef.value.$el.querySelector('.current-row');
|
||||
if (tableBody && currentRowEl) {
|
||||
currentRowEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
};
|
||||
|
||||
// 当前行变化时更新索引
|
||||
const handleCurrentChange = (currentRow) => {
|
||||
currentIndex.value = adviceBaseList.value.findIndex((item) => item === currentRow);
|
||||
currentSelectRow.value = currentRow;
|
||||
};
|
||||
|
||||
function clickRow(row) {
|
||||
emit('selectAdviceBase', row);
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleKeyDown,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.popover-table-wrapper:focus {
|
||||
outline: 2px solid #409eff; /* 聚焦时的高亮效果 */
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,129 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取个人组套
|
||||
* @param {*} queryParams
|
||||
*/
|
||||
export function getPersonalList(queryParams) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/get-personal',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取科室组套
|
||||
* @param {*} queryParams
|
||||
*/
|
||||
export function getDeptList(queryParams) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/get-organization',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全院组套
|
||||
* @param {*} queryParams
|
||||
*/
|
||||
export function getAllList(queryParams) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/get-hospital',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存个人组套
|
||||
* @param {*} data
|
||||
*/
|
||||
export function savePersonal(data) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/save-personal',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存科室组套
|
||||
* @param {*} data
|
||||
*/
|
||||
export function saveDepartment(data) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/save-organization',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存全院组套
|
||||
* @param {*} data
|
||||
*/
|
||||
export function saveAll(data) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/save-hospital',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询组套明细
|
||||
* @param {*} data
|
||||
*/
|
||||
export function queryGroupDetail(params) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/get-group-package-detail',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除组套
|
||||
* @param {*} data
|
||||
*/
|
||||
export function deleteGroup(data) {
|
||||
return request({
|
||||
url: '/personalization/orders-group-package/group-package-detail?groupPackageId=' + data.groupPackageId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询参与者下拉列表
|
||||
* @param {*} data
|
||||
*/
|
||||
export function queryParticipantList(params) {
|
||||
return request({
|
||||
url: '/app-common/practitioner-list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取药品列表
|
||||
*/
|
||||
export function getAdviceBaseInfo(queryParams) {
|
||||
return request({
|
||||
url: '/doctor-station/advice/advice-base-info',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取科室列表
|
||||
*/
|
||||
export function getOrgTree() {
|
||||
return request({
|
||||
url: '/base-data-manage/organization/organization',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
686
openhis-ui-vue3/src/views/basicmanage/medicalOrderSet/index.vue
Normal file
686
openhis-ui-vue3/src/views/basicmanage/medicalOrderSet/index.vue
Normal file
@@ -0,0 +1,686 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||
<el-tab-pane label="个人" name="personal">
|
||||
<div class="mb10">
|
||||
<el-row :gutter="10" class="mb10">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="personalQuery.searchKey" placeholder="请输入名称" clearable @keyup.enter="getPersonalListData" />
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" icon="Search" @click="getPersonalListData">查询</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd('personal')">新增</el-button>
|
||||
</div>
|
||||
<el-table :data="personalList" border v-loading="loading.personal">
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="practitionerName" label="参与者" />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit('personal', scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete('personal', scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="科室" name="department">
|
||||
<div class="mb10">
|
||||
<el-row :gutter="10" class="mb10">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="departmentQuery.searchKey" placeholder="请输入名称" clearable @keyup.enter="getDepartmentListData" />
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" icon="Search" @click="getDepartmentListData">查询</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd('department')">新增</el-button>
|
||||
</div>
|
||||
<el-table :data="departmentList" border v-loading="loading.department">
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column prop="organizationName" label="科室" />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit('department', scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete('department', scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="全院" name="hospital">
|
||||
<div class="mb10">
|
||||
<el-row :gutter="10" class="mb10">
|
||||
<el-col :span="6">
|
||||
<el-input v-model="hospitalQuery.searchKey" placeholder="请输入名称" clearable @keyup.enter="getHospitalListData" />
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" icon="Search" @click="getHospitalListData">查询</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd('hospital')">新增</el-button>
|
||||
</div>
|
||||
<el-table :data="hospitalList" border v-loading="loading.hospital">
|
||||
<el-table-column prop="name" label="名称" />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleEdit('hospital', scope.row)">编辑</el-button>
|
||||
<el-button link type="danger" icon="Delete" @click="handleDelete('hospital', scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
v-model="dialogVisible"
|
||||
width="800px"
|
||||
@close="handleDialogClose"
|
||||
>
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="参与者" prop="practitionerId" v-if="currentTab == 'personal'">
|
||||
<el-select
|
||||
v-model="formData.practitionerId"
|
||||
placeholder="请选择参与者"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in participantListOptions"
|
||||
:key="item.practitionerId"
|
||||
:label="item.practitionerName"
|
||||
:value="item.practitionerId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="科室" prop="organizationId" v-if="currentTab == 'department'">
|
||||
<el-tree-select
|
||||
clearable
|
||||
v-model="formData.organizationId"
|
||||
:data="organization"
|
||||
:props="{ value: 'id', label: 'name', children: 'children' }"
|
||||
value-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
placeholder="请选择科室"
|
||||
:render-after-expand="false"
|
||||
@change="handleOrgChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-table
|
||||
max-height="650"
|
||||
ref="prescriptionRef"
|
||||
:data="prescriptionList"
|
||||
row-key="uniqueKey"
|
||||
border
|
||||
@cell-click="clickRow"
|
||||
:expand-row-keys="expandOrder"
|
||||
>
|
||||
<el-table-column label="医嘱" align="center" prop="productName">
|
||||
<template #default="scope">
|
||||
<template v-if="getRowDisabled(scope.row)">
|
||||
<el-popover
|
||||
:popper-style="{ padding: '0' }"
|
||||
placement="bottom-start"
|
||||
:visible="scope.row.showPopover"
|
||||
:width="1200"
|
||||
>
|
||||
<adviceBaseList
|
||||
ref="adviceTableRef"
|
||||
:popoverVisible="scope.row.showPopover"
|
||||
:adviceQueryParams="adviceQueryParams"
|
||||
@selectAdviceBase="(row) => selectAdviceBase(scope.row.uniqueKey, row)"
|
||||
/>
|
||||
<template #reference>
|
||||
<el-input
|
||||
:ref="'adviceRef' + scope.$index"
|
||||
style="width: 50%"
|
||||
v-model="scope.row.adviceName"
|
||||
placeholder="请选择项目"
|
||||
@input="(value) => handleInput(value, scope.row, scope.$index)"
|
||||
@click="handleFocus(scope.row, scope.$index)"
|
||||
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
|
||||
@keydown="
|
||||
(e) => {
|
||||
if (!scope.row.showPopover) return;
|
||||
// 拦截上下键和回车事件
|
||||
if (['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
// 传递事件到弹窗容器
|
||||
adviceTableRef.handleKeyDown(e);
|
||||
}
|
||||
}
|
||||
"
|
||||
@blur="handleBlur(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
<span v-else>{{ scope.row.adviceName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" align="center" width="100" prop="sortNumber">
|
||||
<template #default="scope">
|
||||
<template v-if="!scope.row.groupPackageId">
|
||||
<el-input
|
||||
v-model="scope.row.sortNumber"
|
||||
type="number"
|
||||
min="1"
|
||||
@change="handleQuantityChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
<span v-else>{{ scope.row.sortNumber }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" align="center" width="120" prop="unitCode">
|
||||
<template #default="scope">
|
||||
<template v-if="!scope.row.groupPackageId">
|
||||
<el-select
|
||||
v-model="scope.row.selectUnitCode"
|
||||
placeholder="请选择单位"
|
||||
@change="handleUnitChange(scope.row)"
|
||||
>
|
||||
<el-option
|
||||
v-if="scope.row.minUnitCode"
|
||||
:key="scope.row.minUnitCode"
|
||||
:label="scope.row.minUnitCode_dictText || scope.row.minUnitCode"
|
||||
:value="scope.row.minUnitCode"
|
||||
/>
|
||||
<el-option
|
||||
v-if="scope.row.unitCode"
|
||||
:key="scope.row.unitCode"
|
||||
:label="scope.row.unitCode_dictText || scope.row.unitCode"
|
||||
:value="scope.row.unitCode"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<span>{{ scope.row.unitCodeName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="80">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="Delete"
|
||||
circle
|
||||
size="small"
|
||||
@click="handleDeleteRow(scope.$index, scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm" :loading="submitLoading">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import {
|
||||
getPersonalList,
|
||||
getDeptList,
|
||||
getAllList,
|
||||
queryParticipantList,
|
||||
savePersonal,
|
||||
saveDepartment,
|
||||
saveAll,
|
||||
queryGroupDetail,
|
||||
getOrgTree,
|
||||
deleteGroup
|
||||
} from './components/api.js';
|
||||
import adviceBaseList from './components/adviceBaseList';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
// 定义tab相关数据
|
||||
const activeTab = ref('personal')
|
||||
|
||||
// 定义各tab列表数据
|
||||
const personalList = ref([])
|
||||
const departmentList = ref([])
|
||||
const hospitalList = ref([])
|
||||
const prescriptionList = ref([]);
|
||||
const expandOrder = ref([]); //目前的展开行
|
||||
|
||||
// 查询参数
|
||||
const personalQuery = reactive({ searchKey: '' })
|
||||
const departmentQuery = reactive({ searchKey: '' })
|
||||
const hospitalQuery = reactive({ searchKey: '' })
|
||||
|
||||
// 加载状态
|
||||
const loading = reactive({
|
||||
personal: false,
|
||||
department: false,
|
||||
hospital: false
|
||||
})
|
||||
|
||||
// 提交按钮加载状态
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 弹窗相关数据
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const currentTab = ref('') // 记录当前操作的tab
|
||||
const isEdit = ref(false) // 是否为编辑模式
|
||||
const currentRow = ref(null) // 当前编辑的行数据
|
||||
const participantListOptions = ref([])
|
||||
const organization = ref([]);
|
||||
const adviceQueryParams = reactive({})
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
id: undefined,
|
||||
name: ''
|
||||
})
|
||||
const nextId = ref(1);
|
||||
const rowIndex = ref(0);
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
name: [
|
||||
{ required: true, message: '请输入名称', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref()
|
||||
|
||||
// 页面加载时获取所有列表数据
|
||||
onMounted(() => {
|
||||
// 可以添加初始查询参数
|
||||
const initialParams = {
|
||||
searchKey: '' // 初始查询关键字
|
||||
};
|
||||
|
||||
fetchAllData(initialParams)
|
||||
getInit()
|
||||
})
|
||||
|
||||
function getInit() {
|
||||
queryParticipantList().then((res) => {
|
||||
participantListOptions.value = res.data
|
||||
});
|
||||
getOrgTree().then(res => {
|
||||
organization.value = res.data.records;
|
||||
})
|
||||
}
|
||||
|
||||
// 获取所有数据
|
||||
function fetchAllData(params = {}) {
|
||||
getPersonalListData(params)
|
||||
getDepartmentListData(params)
|
||||
getHospitalListData(params)
|
||||
}
|
||||
|
||||
// 获取个人医嘱列表
|
||||
function getPersonalListData(params = {}) {
|
||||
// 合并查询参数
|
||||
Object.assign(personalQuery, params);
|
||||
|
||||
loading.personal = true
|
||||
getPersonalList(personalQuery).then(response => {
|
||||
personalList.value = response.data
|
||||
loading.personal = false
|
||||
}).catch(error => {
|
||||
console.error('获取个人医嘱列表失败:', error)
|
||||
loading.personal = false
|
||||
proxy.$modal.msgError('获取个人医嘱列表失败')
|
||||
})
|
||||
}
|
||||
|
||||
// 获取科室医嘱列表
|
||||
function getDepartmentListData(params = {}) {
|
||||
// 合并查询参数
|
||||
Object.assign(departmentQuery, params);
|
||||
|
||||
loading.department = true
|
||||
getDeptList(departmentQuery).then(response => {
|
||||
departmentList.value = response.data
|
||||
loading.department = false
|
||||
}).catch(error => {
|
||||
console.error('获取科室医嘱列表失败:', error)
|
||||
loading.department = false
|
||||
proxy.$modal.msgError('获取科室医嘱列表失败')
|
||||
})
|
||||
}
|
||||
|
||||
// 获取全院医嘱列表
|
||||
function getHospitalListData(params = {}) {
|
||||
// 合并查询参数
|
||||
Object.assign(hospitalQuery, params);
|
||||
|
||||
loading.hospital = true
|
||||
getAllList(hospitalQuery).then(response => {
|
||||
hospitalList.value = response.data
|
||||
loading.hospital = false
|
||||
}).catch(error => {
|
||||
console.error('获取全院医嘱列表失败:', error)
|
||||
loading.hospital = false
|
||||
proxy.$modal.msgError('获取全院医嘱列表失败')
|
||||
})
|
||||
}
|
||||
|
||||
// tab切换处理
|
||||
function handleTabChange(tab) {
|
||||
// 根据切换到的tab调用相应的接口获取数据
|
||||
switch (tab) {
|
||||
case 'personal':
|
||||
getPersonalListData()
|
||||
break
|
||||
case 'department':
|
||||
getDepartmentListData()
|
||||
break
|
||||
case 'hospital':
|
||||
getHospitalListData()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 新增按钮处理
|
||||
function handleAdd(tab) {
|
||||
currentTab.value = tab
|
||||
isEdit.value = false
|
||||
dialogTitle.value = '新增医嘱'
|
||||
dialogVisible.value = true
|
||||
// 重置表单
|
||||
prescriptionList.value.unshift({
|
||||
uniqueKey: nextId.value++,
|
||||
showPopover: false,
|
||||
check: false,
|
||||
isEdit: true,
|
||||
statusEnum: 1,
|
||||
});
|
||||
formData.groupPackageId = undefined
|
||||
formData.name = ''
|
||||
|
||||
// 获取当前登录用户信息
|
||||
const userStore = useUserStore()
|
||||
const userId = userStore.id
|
||||
const orgId = userStore.orgId
|
||||
const practitionerId = userStore.practitionerId
|
||||
|
||||
// 根据不同tab设置默认值
|
||||
if (tab === 'personal') {
|
||||
// 个人医嘱默认设置当前用户为参与者
|
||||
formData.practitionerId = practitionerId
|
||||
} else if (tab === 'department') {
|
||||
// 科室医嘱默认设置当前科室
|
||||
formData.organizationId = orgId
|
||||
}
|
||||
// 全院医嘱不需要设置默认值
|
||||
}
|
||||
|
||||
// 编辑按钮处理
|
||||
function handleEdit(tab, row) {
|
||||
currentTab.value = tab
|
||||
isEdit.value = true
|
||||
currentRow.value = row
|
||||
dialogTitle.value = '编辑医嘱'
|
||||
dialogVisible.value = true
|
||||
formData.groupPackageId = row.groupPackageId
|
||||
formData.name = row.name
|
||||
formData.practitionerId = row.practitionerId
|
||||
formData.organizationId = row.organizationId
|
||||
// 填充表单数据
|
||||
queryGroupDetail({ groupPackageId: row.groupPackageId }).then(res => {
|
||||
prescriptionList.value = res.data.map(item => {
|
||||
return {
|
||||
groupPackageId: item.groupPackageId,
|
||||
adviceDefinitionId: item.orderDefinitionId,
|
||||
adviceTableName: item.orderDefinitionTable,
|
||||
sortNumber: item.quantity,
|
||||
selectUnitCode: item.unitCode,
|
||||
adviceName: item.orderDefinitionName,
|
||||
unitCodeName: item.unitCodeName
|
||||
}
|
||||
})
|
||||
prescriptionList.value.unshift({
|
||||
uniqueKey: nextId.value++,
|
||||
showPopover: false,
|
||||
check: false,
|
||||
isEdit: true,
|
||||
statusEnum: 1,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// 删除按钮处理
|
||||
function handleDelete(tab, row) {
|
||||
// 显示确认框
|
||||
proxy.$modal.confirm('确定要删除该医嘱吗?').then(() => {
|
||||
deleteGroup({groupPackageId: row.groupPackageId}).then(res => {
|
||||
proxy.$modal.msgSuccess(res.msg)
|
||||
fetchAllData()
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
function submitForm() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
|
||||
// 模拟提交操作(这里应该调用相应的API)
|
||||
setTimeout(() => {
|
||||
console.log('提交表单数据:', formData)
|
||||
let params = {...formData}
|
||||
// 过滤掉空列表项(没有adviceDefinitionId的项)
|
||||
params.detailList = prescriptionList.value
|
||||
.filter(item => item.adviceDefinitionId) // 过滤掉空列表项
|
||||
.map(item => {
|
||||
return {
|
||||
orderDefinitionId: item.adviceDefinitionId,
|
||||
orderDefinitionTable: item.adviceTableName,
|
||||
quantity: item.sortNumber,
|
||||
unitCode: item.selectUnitCode,
|
||||
}
|
||||
})
|
||||
// 编辑模式
|
||||
switch (currentTab.value) {
|
||||
case 'personal':
|
||||
savePersonal(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.message)
|
||||
// 重新获取数据以保持一致性
|
||||
fetchAllData()
|
||||
}
|
||||
submitLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 清空处方列表
|
||||
prescriptionList.value = []
|
||||
})
|
||||
break
|
||||
case 'department':
|
||||
saveDepartment(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.message)
|
||||
// 重新获取数据以保持一致性
|
||||
fetchAllData()
|
||||
}
|
||||
submitLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 清空处方列表
|
||||
prescriptionList.value = []
|
||||
})
|
||||
break
|
||||
case 'hospital':
|
||||
saveAll(params).then(res => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success(res.message)
|
||||
// 重新获取数据以保持一致性
|
||||
fetchAllData()
|
||||
}
|
||||
submitLoading.value = false
|
||||
dialogVisible.value = false
|
||||
// 清空处方列表
|
||||
prescriptionList.value = []
|
||||
})
|
||||
break
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择药品回调
|
||||
*/
|
||||
function selectAdviceBase(key, row) {
|
||||
prescriptionList.value[rowIndex.value] = {
|
||||
...prescriptionList.value[rowIndex.value],
|
||||
...JSON.parse(JSON.stringify(row)),
|
||||
};
|
||||
prescriptionList.value[rowIndex.value].orgId = undefined;
|
||||
prescriptionList.value[rowIndex.value].dose = undefined;
|
||||
prescriptionList.value[rowIndex.value].doseUnitCode = row.doseUnitCode;
|
||||
prescriptionList.value[rowIndex.value].minUnitCode = row.minUnitCode;
|
||||
prescriptionList.value[rowIndex.value].unitCode =
|
||||
row.partAttributeEnum == 1 ? row.minUnitCode : row.unitCode;
|
||||
prescriptionList.value[rowIndex.value].categoryEnum = row.categoryCode;
|
||||
prescriptionList.value[rowIndex.value].isEdit = false;
|
||||
prescriptionList.value[rowIndex.value].definitionId = JSON.parse(
|
||||
JSON.stringify(row)
|
||||
).chargeItemDefinitionId;
|
||||
prescriptionList.value.unshift({
|
||||
uniqueKey: nextId.value++,
|
||||
showPopover: false,
|
||||
check: false,
|
||||
isEdit: true,
|
||||
statusEnum: 1,
|
||||
});
|
||||
expandOrder.value = [key];
|
||||
}
|
||||
|
||||
function handleFocus(row, index) {
|
||||
rowIndex.value = index;
|
||||
row.showPopover = true;
|
||||
// 将输入框的值传递给adviceBaseList组件作为查询条件
|
||||
adviceQueryParams.searchKey = row.adviceName || '';
|
||||
}
|
||||
|
||||
// 处理输入事件
|
||||
function handleInput(value, row, index) {
|
||||
// 更新查询参数
|
||||
adviceQueryParams.searchKey = value || '';
|
||||
// 显示弹窗
|
||||
handleFocus(row, index);
|
||||
}
|
||||
|
||||
function handleBlur(row) {
|
||||
row.showPopover = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击行赋值
|
||||
*/
|
||||
function clickRow(row) {
|
||||
|
||||
}
|
||||
|
||||
function getRowDisabled(row) {
|
||||
return row.isEdit;
|
||||
}
|
||||
|
||||
// 处理数量变化
|
||||
function handleQuantityChange(row) {
|
||||
// 验证数量是否为正整数
|
||||
if (row.sortNumber && row.sortNumber > 0) {
|
||||
row.sortNumber = parseInt(row.sortNumber);
|
||||
} else {
|
||||
row.sortNumber = 1;
|
||||
}
|
||||
|
||||
// 触发更新列表事件
|
||||
prescriptionList.value = [...prescriptionList.value];
|
||||
}
|
||||
|
||||
// 处理单位变化
|
||||
function handleUnitChange(row) {
|
||||
// 当单位改变时触发的逻辑可以在这里添加
|
||||
console.log('单位已更改:', row.unitCode);
|
||||
|
||||
// 触发更新列表事件
|
||||
prescriptionList.value = [...prescriptionList.value];
|
||||
}
|
||||
|
||||
// 删除行
|
||||
function handleDeleteRow(index, row) {
|
||||
// 确保至少保留一行
|
||||
if (prescriptionList.value.length <= 1) {
|
||||
proxy.$modal.msgWarning('至少保留一行');
|
||||
return;
|
||||
}
|
||||
|
||||
// 确认删除
|
||||
proxy.$modal.confirm('确定要删除该行吗?').then(() => {
|
||||
prescriptionList.value.splice(index, 1);
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
}).catch(() => {
|
||||
// 取消删除
|
||||
});
|
||||
}
|
||||
|
||||
// 判断是否为叶子节点
|
||||
function isLeafNode(node) {
|
||||
return !node.children || node.children.length === 0;
|
||||
}
|
||||
|
||||
// 弹窗关闭处理
|
||||
function handleDialogClose() {
|
||||
formRef.value.resetFields()
|
||||
// 清空处方列表
|
||||
prescriptionList.value = []
|
||||
}
|
||||
|
||||
// 处理科室选择变化
|
||||
function handleOrgChange(value) {
|
||||
if (!value) return;
|
||||
|
||||
// 查找选中的节点
|
||||
const findNode = (nodes) => {
|
||||
for (let node of nodes) {
|
||||
if (node.id === value) {
|
||||
return node;
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
const found = findNode(node.children);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const selectedNode = findNode(organization.value);
|
||||
|
||||
// 如果选中的不是叶子节点,则清空选择
|
||||
if (selectedNode && !isLeafNode(selectedNode)) {
|
||||
proxy.$modal.msgWarning('只能选择末级科室');
|
||||
formData.organizationId = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前实例用于使用proxy
|
||||
const { proxy } = getCurrentInstance()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mb10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user