EmrTest.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. <template>
  2. <div style="height: 10%;display: flex">
  3. <div>
  4. <el-date-picker v-model="dateRange"
  5. style="width: 220px"
  6. :clearable="false"
  7. type="daterange"/>
  8. <br>
  9. <hr>
  10. <el-button @click="query" type="primary">查询</el-button>
  11. <el-button @click="appendCopy" type="success">复制 / 追加</el-button>
  12. <el-button @click="copyClick" type="success">确认复制</el-button>
  13. <br>
  14. </div>
  15. <div class="describe">
  16. <el-button v-if="isEmr" type="primary" @click="copyOutcome('病理结果')">
  17. 病理结果
  18. </el-button>
  19. <el-button v-if="isEmr" type="primary" @click="copyOutcome('细菌培养结果')">
  20. 细菌培养结果
  21. </el-button>
  22. <div class="pat-info">
  23. <div>
  24. <test-describe front="姓名"
  25. :text="inspectionHeader?.ptnt_NAME"/>
  26. </div>
  27. <div>
  28. <test-describe front="性别"
  29. :text="filterSex(inspectionHeader?.ptnt_SEX)"/>
  30. </div>
  31. <div>
  32. <test-describe front="年龄"
  33. :text="inspectionHeader.ptnt_AGE + filterAgeUnit(inspectionHeader.ptnt_AGE_UNIT) "/>
  34. </div>
  35. <div>
  36. <test-describe front="住院号"
  37. :text="inspectionHeader.ptnt_NO"/>
  38. </div>
  39. <div>
  40. <test-describe front="科室"
  41. :text="inspectionHeader.dept_NAME"/>
  42. </div>
  43. <div>
  44. <test-describe front="床号"
  45. :text="inspectionHeader.ptnt_BED_NO"/>
  46. </div>
  47. <div>
  48. <test-describe front="标本类型"
  49. :text="inspectionHeader.smpl_NAME "/>
  50. </div>
  51. <div>
  52. <test-describe front="申请项目"
  53. :text="inspectionHeader?.aply_CNTN"/>
  54. </div>
  55. </div>
  56. <div class="test-date">
  57. <div>
  58. <test-describe front="接收时间"
  59. :text="inspectionHeader.aply_DATE"/>
  60. </div>
  61. <div>
  62. <test-describe front="检验时间"
  63. :text="inspectionHeader.ordr_CREATE_DATE"/>
  64. </div>
  65. <div>
  66. <test-describe front="报告时间"
  67. :text="inspectionHeader.audt_TIME"/>
  68. </div>
  69. <div>
  70. <test-describe front="送检医生"
  71. :text="inspectionHeader.test_USR_NAME"/>
  72. </div>
  73. <div>
  74. <test-describe front="检验人"
  75. :text="inspectionHeader.ordr_USR_NAME"/>
  76. </div>
  77. <div>
  78. <test-describe front="审核人"
  79. :text="inspectionHeader.audt_USR_NAME"/>
  80. </div>
  81. </div>
  82. </div>
  83. </div>
  84. <div class="container">
  85. <el-auto-resizer>
  86. <template #default="{ height, width }">
  87. <div style="display: flex">
  88. <div class="sidebar">
  89. <vxe-table :height="height"
  90. :row-config="{isHover : true, isCurrent: true,height: 24}"
  91. show-header-overflow
  92. show-overflow
  93. :scroll-x="{gt: 20}"
  94. :scroll-y="{gt: 50,enabled: true}"
  95. class="vxe-padding_zero"
  96. @cell-click="sidebarRow"
  97. :data="sidebarList">
  98. <vxe-column title="名称" field="aply_CTNT"/>
  99. <vxe-column title="时间" field="ordr_CREATE_DATE" width="180"/>
  100. </vxe-table>
  101. </div>
  102. <div class="main">
  103. <el-table :data="mainList"
  104. :height="height"
  105. row-key="itm_ORDR"
  106. ref="tableRef"
  107. @row-click="testRowClick"
  108. :expand-row-keys="expands">
  109. <el-table-column label="选择" type="selection"/>
  110. <el-table-column type="expand" width="20">
  111. <template #default="{row,$index}">
  112. <el-table :data="row.bacteriaResults[0].antibioticResults"
  113. :ref="(el) => setRefMap(el, $index)"
  114. @row-click="drugTable"
  115. v-if="row.bacteriaResults.length > 0">
  116. <el-table-column label="选择" type="selection"/>
  117. <el-table-column label="抗菌药物" prop="anti_NAME_CN"/>
  118. <el-table-column label="抗菌药物编码" prop="anti_ABB"/>
  119. <el-table-column label="MIC值" prop="anti_MIC"/>
  120. <el-table-column label="敏感性" prop="anti_VALUE"/>
  121. </el-table>
  122. </template>
  123. </el-table-column>
  124. <el-table-column label="检验项目" prop="itm_NAME" width="450"/>
  125. <el-table-column label="结果">
  126. <template #default="{row}">
  127. {{ result(row) }}
  128. </template>
  129. </el-table-column>
  130. <el-table-column label="单位" prop="itm_UNIT"/>
  131. <el-table-column label="说明" prop="itm_ALERT">
  132. <template #default="{row}">
  133. <span v-html="getItemAlert(row.itm_ALERT, row.itm_STR_VALUE, row.itm_VALUE)"></span>
  134. </template>
  135. </el-table-column>
  136. <el-table-column label="参考值" prop="range"/>
  137. </el-table>
  138. </div>
  139. </div>
  140. </template>
  141. </el-auto-resizer>
  142. </div>
  143. </template>
  144. <script setup name='EmrTest'>
  145. import {
  146. queryInspectionDetail,
  147. queryInspectionsIndex
  148. } from '@/api/inspections'
  149. import {onMounted, ref} from "vue";
  150. import {xcMessage} from '@/utils/xiaochan-element-plus'
  151. import TestDescribe from "@/components/zhu-yuan-yi-sheng/emr/auxiliary-tools/TestDescribe.vue";
  152. import {currentAndAFewDaysAgo, getDateRangeFormatDate} from '@/utils/date'
  153. import {
  154. elementReplication,
  155. emrCopyFunc
  156. } from '@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init'
  157. import {copyStrFunc} from "@/utils/public";
  158. const {patNo, isEmr} = defineProps({
  159. patNo: String,
  160. isEmr: {
  161. type: Boolean,
  162. default: true
  163. }
  164. })
  165. const emits = defineEmits(['close'])
  166. const sidebarList = ref()
  167. const mainList = ref()
  168. const tableRef = ref()
  169. const drugSensitivityRef = ref()
  170. const inspectionHeader = ref({
  171. aply_CNTN: ''
  172. })
  173. const dateRange = ref([])
  174. const refMap = {}
  175. const setRefMap = (el, item) => {
  176. refMap[`drug${item}`] = el
  177. }
  178. const query = async () => {
  179. let {startTime, endTime} = getDateRangeFormatDate(dateRange.value)
  180. const param = {
  181. type: 1,
  182. content: patNo,
  183. start: startTime,
  184. end: endTime,
  185. }
  186. queryInspectionsIndex(param).then((res) => {
  187. sidebarList.value = res
  188. })
  189. }
  190. const expands = ref([])
  191. let currentReportForm = {}
  192. const sidebarRow = ({row}) => {
  193. currentReportForm = row
  194. queryInspectionDetail(row.ordr_ID).then((res) => {
  195. mainList.value = res['inspectionItems']
  196. inspectionHeader.value = res['inspectionHeader']
  197. mainList.value.forEach(item => {
  198. if (item.bacteriaResults.length > 0) {
  199. expands.value.push(item.itm_ORDR)
  200. }
  201. })
  202. })
  203. }
  204. const testRowClick = (row) => {
  205. let temp = tableRef.value.getSelectionRows()
  206. tableRef.value.toggleRowSelection(row, !temp.includes(row))
  207. }
  208. const drugTable = (row) => {
  209. let temp = drugSensitivityRef.value.getSelectionRows()
  210. drugSensitivityRef.value.toggleRowSelection(row, !temp.includes(row))
  211. }
  212. let copyStr = ''
  213. const appendCopy = () => {
  214. let temp = tableRef.value.getSelectionRows()
  215. let data = currentReportForm.aply_CTNT + ":"
  216. temp.forEach(item => {
  217. data += `${item.itm_NAME}${result(item)}${item.itm_UNIT}${getItemStr(item.itm_ALERT, item.itm_STR_VALUE, item.itm_VALUE)},`
  218. })
  219. for (let key in refMap) {
  220. let item = refMap[key]
  221. let tempList = item.getSelectionRows()
  222. tempList.forEach(item => {
  223. data += `${item.anti_NAME_CN}${item.anti_ABB}${item.anti_MIC}${item.anti_VALUE},`
  224. })
  225. }
  226. copyStr += ' ' + data
  227. xcMessage.success('追加成功。')
  228. }
  229. const copyClick = () => {
  230. if (isEmr) {
  231. emrCopyFunc(copyStr)
  232. } else {
  233. copyStrFunc(copyStr)
  234. }
  235. emits('close')
  236. }
  237. const copyOutcome = (name) => {
  238. elementReplication(copyStr, name)
  239. }
  240. const result = (row) => {
  241. if (row.bacteriaResults.length > 0) {
  242. return row.bacteriaResults[0].bac_NAME_CN
  243. }
  244. return `${row.itm_VALUE} ${row.itm_STR_VALUE}`
  245. }
  246. function filterSex(val) {
  247. switch (val) {
  248. case '0':
  249. return '未填'
  250. case '1':
  251. return '男'
  252. case '2':
  253. return '女'
  254. case '3':
  255. return '未知'
  256. }
  257. return ''
  258. }
  259. function filterAgeUnit(val) {
  260. switch (val) {
  261. case '0':
  262. return '岁'
  263. case '1':
  264. return '月'
  265. case '2':
  266. return '天'
  267. case '3':
  268. return '时'
  269. }
  270. return ''
  271. }
  272. function getItemAlert(val, strValue, value) {
  273. if (strValue !== '' || value === '') return ''
  274. switch (val) {
  275. case 'L':
  276. return '<span style="color:#F56C6C;font-weight:bold">↓</span>'
  277. case 'H':
  278. return '<span style="color:#F56C6C;font-weight:bold">↑</span>'
  279. }
  280. return '<span style="color:#67C23A;font-weight:bold">正常</span>'
  281. }
  282. function getItemStr(val, strValue, value) {
  283. if (strValue !== '' || value === '') return ''
  284. switch (val) {
  285. case 'L':
  286. return '↓'
  287. case 'H':
  288. return '↑'
  289. }
  290. return '正常'
  291. }
  292. onMounted(async () => {
  293. dateRange.value = await currentAndAFewDaysAgo()
  294. await query()
  295. // todo 检验接口没有返回危急值。
  296. // let res = await getCriticalValueByPatInfo(patInfo.value.inpatientNo, patInfo.value.admissTimes)
  297. })
  298. </script>
  299. <style scoped lang="scss">
  300. .container {
  301. width: 100%;
  302. height: 90%;
  303. }
  304. .sidebar {
  305. width: 420px;
  306. }
  307. .main {
  308. width: 100%;
  309. height: 100%;
  310. }
  311. .describe {
  312. width: 100%;
  313. margin-left: 20px;
  314. font-size: 12px;
  315. .pat-info {
  316. display: flex;
  317. div {
  318. padding: 5px;
  319. }
  320. }
  321. .test-date {
  322. display: flex;
  323. div {
  324. padding: 5px;
  325. }
  326. }
  327. }
  328. </style>