123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- <template>
- <div>
- <el-input v-model="filterText"
- placeholder="节点过滤"
- style="width: 100%"
- @input="filterChange" clearable/>
- <el-radio-group v-model="templateType" @change="typeChange">
- <el-radio-button v-if="props.isCreate" :disabled="!editor" :label="0">全院</el-radio-button>
- <el-radio-button v-if="props.isCreate" :disabled="!editor" :label="1">科室</el-radio-button>
- <el-radio-button :label="2">当前</el-radio-button>
- <el-radio-button :label="3">历史</el-radio-button>
- </el-radio-group>
- <div :style="{maxHeight : maxHeight - 100 + 'px'}"
- style="overflow: auto; "
- class="down-tree">
- <el-tree v-show="templateType === 3"
- :props="defaultProps"
- ref="hisTreeRef"
- :filter-node-method="filterNode"
- :data="hisData"
- @node-click="hisClick">
- </el-tree>
- <el-tree v-show="templateType !== 3"
- :data="treeData"
- :props="defaultProps"
- @node-click="handleNodeClick"
- node-key="_id"
- ref="treeRef"
- draggable
- @node-drag-end="dragEnd"
- :allow-drag="allowDrag"
- :allow-drop="dragLimit"
- @node-contextmenu="contextmenuItem"
- highlight-current
- :filter-node-method="filterNode"
- default-expand-all>
- <template #default="{ node, data }">
- <el-icon v-if="data.submit">
- <Lock/>
- </el-icon>
- <component :is="isItAFolder(data)"/>
- <span :title="fileName(data)">
- {{ fileName(data) }}
- </span>
- </template>
- </el-tree>
- </div>
- <right-click-menu :mouse-position="mousePosition" :config="opt"/>
- </div>
- </template>
- <script setup lang="ts">
- import {
- electronicMedicalRecordSequencing,
- getEmrTree, getPastHistory,
- getPatientDataTree,
- queryWhetherThePatientHasASpecifiedMedicalRecord,
- whetherItExistsInTheDepartment
- } from "@/api/zhu-yuan-yi-sheng/emr-patient";
- import {BizException, ExceptionEnum} from "@/utils/BizException";
- import {
- canIUnlockIt,
- emrConfig,
- emrMitt,
- unlockEnum
- } from '@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init'
- import {stringIsBlank} from "@/utils/blank-utils";
- import {getAllWards} from "@/api/zhu-yuan-yi-sheng/resident-doctor";
- import RightClickMenu from "@/components/menu-item/RightClickMenu.vue";
- import {xcMessage} from "@/utils/xiaochan-element-plus";
- import {ElIcon, ElTree} from "element-plus";
- // @ts-ignore
- import {Folder, Document, Open, Sort, View} from "@element-plus/icons-vue";
- import {isDev} from "@/utils/public";
- import {ref, computed, h, onMounted} from 'vue'
- import {useCompRef} from "@/utils/useCompRef";
- import {userInfoStore} from "@/utils/store-public";
- const props = defineProps({
- maxHeight: {
- type: Number
- },
- huanZheXinXi: {
- type: Object
- },
- patientData: {
- type: Object
- },
- extractData: {
- type: Object
- },
- doctorGrade: {
- type: Number
- },
- isCreate: {
- type: Boolean,
- default: true
- }
- })
- let editor = emrConfig.value.editor
- const emit = defineEmits(['nodeClick', 'typeChange', 'patientMedicalRecord', 'openAndSaveTheMedicalRecord'])
- const returnData = ref({
- emrTree: [],
- deptTree: [],
- patientTree: []
- })
- const filterText = ref('')
- const treeRef = useCompRef(ElTree)
- const dialog = ref(false)
- let wardList = []
- const defaultProps = {
- children: 'children',
- label: 'name',
- }
- const templateType = ref(0)
- const treeData = computed(() => {
- switch (templateType.value) {
- case 0 :
- return returnData.value.emrTree;
- case 1:
- return returnData.value.deptTree;
- case 2:
- return returnData.value.patientTree;
- }
- })
- const wardCreationJudgment = async () => {
- if (determineWhetherItCanBeCreated()) {
- return
- }
- if (await judgeTheCreationOfTransfer()) {
- return;
- }
- if (canIUnlockIt(unlockEnum.转科创建病历)) {
- return;
- }
- if (isDev) {
- return
- }
- BizException(ExceptionEnum.MESSAGE_ERROR, "当前患者所在病区不在您的管理病区范围内,无法创建病历。");
- }
- const handleNodeClick = async (val, node, parent, event) => {
- if (val.type === 'group-category') return
- let temp: {
- code?: string
- value?: string
- // 电子病历的 id 如果是新建就没有
- documentId?: string | null
- categoryId?: string | null
- // 电子病历的 编码
- categoryCode?: string
- // 患者的 id
- patientId?: string | null
- // 电子病历 名称
- name?: string
- // 创建人 id
- createId?: string | null
- // 父级节点
- parent?: string
- createName?: string
- } = {}
- if (templateType.value === 0 || templateType.value === 1) {
- temp = {
- documentId: null,
- categoryCode: val.code,
- categoryId: val._id,
- patientId: null,
- name: val.name,
- createId: null,
- parent: val.parent,
- }
- await wardCreationJudgment()
- } else if (templateType.value === 2) {
- temp = {
- documentId: val.emrDocumentId,
- categoryCode: val.emrCategoryCode,
- categoryId: null,
- patientId: null,
- name: val.name ? val.name : val.emrName,
- createId: val.createId,
- createName: val.createName
- }
- if (val.jump) {
- let tempVal = node.parent.data
- emrMitt.emit('audit', {
- id: tempVal.id,
- code: tempVal.emrCategoryCode,
- createId: tempVal.createId,
- referPhysician: props.huanZheXinXi.referPhysician,
- patNo: props.huanZheXinXi.inpatientNo,
- times: props.huanZheXinXi.admissTimes
- });
- } else {
- emrMitt.emit('audit', {
- id: val.id,
- code: val.emrCategoryCode,
- createId: val.createId,
- referPhysician: props.huanZheXinXi.referPhysician,
- patNo: props.huanZheXinXi.inpatientNo,
- times: props.huanZheXinXi.admissTimes
- });
- }
- }
- if (val.children) {
- return
- }
- if (val.labels) {
- // 根据 这个编码来限制是不是唯一一个
- if (val.labels.includes('唯一') && templateType.value !== 2) {
- let flag = await queryWhetherThePatientHasASpecifiedMedicalRecord({
- patNo: props.huanZheXinXi.inpatientNo,
- times: props.huanZheXinXi.admissTimes,
- emrCategoryCode: val.code
- })
- if (flag) {
- BizException(ExceptionEnum.LOGICAL_ERROR, '此病历只能创建一次。')
- }
- }
- }
- if (val.jump) {
- temp.code = val.code
- temp.value = val.value
- emit('nodeClick', temp, true, templateType.value);
- } else {
- emit('nodeClick', temp, false, templateType.value);
- }
- }
- const determineWhetherItCanBeCreated = () => {
- if (userInfoStore.value.code === props.patientData['管床医生编码'] || props.doctorGrade > 1) {
- return true;
- }
- return wardList.includes(props.huanZheXinXi.ward);
- }
- const judgeTheCreationOfTransfer = async () => {
- let res = await whetherItExistsInTheDepartment(props.huanZheXinXi.inpatientNo, props.huanZheXinXi.admissTimes) as any;
- if (res === null) {
- return false;
- }
- if (res.timeout) {
- return false;
- }
- return wardList.includes(res.fDeptCode);
- }
- const typeChange = (val) => {
- emit("typeChange", val)
- }
- const filterChange = (val) => {
- try {
- hisTreeRef.value.filter(val)
- } catch {
- }
- try {
- treeRef.value.filter(val);
- } catch {
- }
- }
- const filterNode = (value, data) => {
- if (!value) return true
- return data.name.includes(value)
- }
- const changeTemplateType = (val) => {
- templateType.value = val
- typeChange(val)
- }
- const deleteTheSpecifiedNode = (id) => {
- for (let i = 0, len = returnData.value.patientTree.length; i < len; i++) {
- let item = returnData.value.patientTree[i]
- if (item.emrDocumentId === id) {
- returnData.value.patientTree.splice(i, 1)
- return
- }
- if (item.children) {
- for (let j = 0; j < item.children.length; j++) {
- let child = item.children[j]
- if (child.emrDocumentId === id) {
- item.children.splice(i, 1)
- return
- }
- }
- }
- }
- }
- let findNode = false
- const diseaseDurationRecordTime = (id, list) => {
- findNode = false;
- findMedicalRecordById(id, list, returnData.value.patientTree);
- }
- const findMedicalRecordById = (id, roundTimes, list) => {
- for (let i = 0, len = list.length; i < len; i++) {
- if (findNode) return;
- let item = list[i]
- if (item.emrDocumentId === id) {
- findNode = true
- item.type = 'group-category'
- item.children = roundTimes
- return
- }
- if (item.children) {
- findMedicalRecordById(id, roundTimes, item.children)
- }
- }
- }
- const queryData = () => {
- getPatientDataTree(props.huanZheXinXi.inpatientNo, props.huanZheXinXi.admissTimes).then((res) => {
- if (res?.length > 0) {
- templateType.value = 2
- emit('patientMedicalRecord')
- }
- returnData.value.patientTree = res
- })
- }
- const hisData = ref([])
- const hisTreeRef = ref(null)
- const pastHistory = () => {
- getPastHistory(props.huanZheXinXi.inpatientNo, props.huanZheXinXi.admissTimes).then((res) => {
- let temp = []
- for (let key in res) {
- temp.push({
- name: `第${key}次住院`,
- children: res[key]
- })
- }
- hisData.value = temp
- })
- }
- const hisClick = (val) => {
- if (!val.emrDocumentId) return
- emrMitt.emit('setShowIframe', 3, val.emrDocumentId)
- }
- const fileName = (val) => {
- if (val.jump) {
- let tempDate = val.trueCreationTime
- if (!tempDate) {
- tempDate = val.createDate
- }
- return val.name + nullToEmpty(val.createName) + nullToEmpty(tempDate)
- }
- if (templateType.value === 2) {
- return val.name + nullToEmpty(val.createName) + nullToEmpty(val.createDate)
- } else {
- return val.name
- }
- }
- const nullToEmpty = (val) => {
- return stringIsBlank(val) ? '' : ' \\ ' + val
- }
- const mousePosition = ref()
- const opt = [
- {
- name: '打开(只读)', click: (data) => {
- if (!data.unlock.id) {
- xcMessage.error('请选中保存的病历。')
- return
- }
- emit('openAndSaveTheMedicalRecord', data.unlock.id)
- },
- icon: h(ElIcon, {}, () => h(Open))
- },
- {
- name: '同时打开', click: (data) => {
- if (!data.unlock.id) {
- xcMessage.error('请选中保存的病历。')
- return
- }
- emit('openAndSaveTheMedicalRecord', data.unlock.id, 3)
- },
- icon: h(ElIcon, {}, () => h(View))
- },
- {
- name: '确认排序', click: (data) => {
- let temp = []
- drag.forEach((value, key) => {
- if (value.newParent !== value.oldParent) {
- temp.push({id: key, parent: value.newParent})
- }
- })
- if (temp.length === 0) {
- drag.clear()
- return xcMessage.error('文件夹没有变化,无需点击。')
- }
- electronicMedicalRecordSequencing(temp).then(() => {
- drag.clear()
- })
- },
- validator: () => {
- return drag.size > 0
- },
- icon: h(ElIcon, {}, () => h(Sort))
- }
- ]
- const contextmenuItem = (event, data) => {
- let tempData;
- if (data.emrDocumentId) {
- tempData = {
- id: data.emrDocumentId,
- code: data.emrCategoryCode,
- patNo: data.patNo,
- times: data.times,
- name: data.name ? data.name : data.emrName,
- }
- } else {
- tempData = {
- id: null,
- code: data.code,
- patNo: props.huanZheXinXi.inpatientNo,
- times: props.huanZheXinXi.admissTimes,
- name: data.name,
- }
- }
- event.returnValue = false;
- mousePosition.value = {
- event,
- index: 0,
- data: {
- unlock: tempData,
- original: data
- }
- };
- }
- const isItAFolder = (data) => {
- return h(ElIcon, null,
- {
- default: () => {
- if (data.type === 'category') {
- return h(Document)
- } else {
- return h(Folder)
- }
- }
- }
- )
- }
- const dragLimit = (moveNode, inNode, type) => {
- if (templateType.value !== 2) return false;
- if (moveNode.data.jump) return false;
- if (inNode.data._id && type === 'inner') {
- return true;
- }
- }
- const allowDrag = (node) => {
- if (templateType.value !== 2) return false;
- if (node.data.emrCategoryCode === 'shoucibingchengjilu') {
- return true;
- }
- return node.data.type !== "group-category";
- }
- let drag = new Map();
- const dragEnd = (moveNode, inNode, type, event) => {
- if (type === 'none') return
- let temp = {
- newParent: inNode.data._id,
- oldParent: moveNode.data.parent
- }
- drag.set(moveNode.data.id, temp)
- }
- onMounted(() => {
- emrMitt.on('患者病区判断', () => {
- return determineWhetherItCanBeCreated()
- })
- emrMitt.on('querySidebar', queryData)
- pastHistory()
- queryData()
- if (editor) {
- getAllWards().then((res) => {
- if (res.length > 0) {
- for (let i = 0, len = res.length; i < len; i++) {
- wardList.push(res[i].code)
- }
- }
- })
- getEmrTree().then((res) => {
- returnData.value.emrTree = res.all
- returnData.value.deptTree = res.dept
- })
- } else {
- templateType.value = 2
- }
- })
- defineExpose({
- changeTemplateType,
- deleteTheSpecifiedNode,
- diseaseDurationRecordTime,
- queryData
- })
- </script>
- <style scoped lang="scss">
- .down-tree {
- :deep(.el-tree-node.is-expanded > .el-tree-node__children) {
- display: inline;
- }
- }
- </style>
|