YzTableV2.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. <template>
  2. <xc-table-v2 :data="tempYzData"
  3. @rowClick="rowClick"
  4. :width="getWindowSize.w - 160"
  5. row-key="actOrderNo"
  6. @contextmenu="contextmenuItem"
  7. :height="getWindowSize.h - (yzHeaderSize) - 180 "
  8. @dbRowClick="setDefaultStopTime"
  9. ref="tableRef"
  10. :row-class="rowClass"
  11. :columns="header"/>
  12. <right-click-menu :mouse-position="mousePosition" :config="opt"/>
  13. </template>
  14. <script setup name='Test' lang="jsx">
  15. import {onMounted, ref} from 'vue'
  16. import XcTableV2 from "@/components/xiao-chan/xc-table-v2/XcTableV2.vue";
  17. import {stringIsBlank} from "@/utils/blank-utils";
  18. import {getFormatDatetime} from "@/utils/date";
  19. import {getServerDateApi} from '@/api/public-api'
  20. import {getWindowSize} from "@/utils/window-size";
  21. import {
  22. tempYzData,
  23. yiZhuData,
  24. associateOrders,
  25. clearAssociate,
  26. drugManual,
  27. yzHeaderSize,
  28. yzMitt,
  29. } from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng";
  30. import sleep from "@/utils/sleep";
  31. import RightClickMenu from "@/components/menu-item/RightClickMenu.vue";
  32. import {nullToEmpty} from "@/utils/public";
  33. import {ElIcon} from "element-plus";
  34. import {DocumentCopy} from "@element-plus/icons-vue";
  35. const emits = defineEmits(['rowClick', 'clickAssociate', 'voidOrders'])
  36. const tableRef = ref(null)
  37. const header = [
  38. {type: 'selected', width: 20},
  39. {width: 30, type: 'index'},
  40. {width: 20, code: 'orderGroup', name: '组'},
  41. {
  42. width: 20, code: 'statusFlag', cellRenderer: ({cellData}) => {
  43. return getYiZhuFlag(cellData)
  44. }
  45. },
  46. {
  47. width: 70, code: 'actOrderNo', name: '医嘱号', cellRenderer: ({data}) => {
  48. if (data.error) {
  49. return h('span', {
  50. style: {
  51. color: 'red'
  52. },
  53. class: () => orderNoClass(data)
  54. }, data.actOrderNo)
  55. } else {
  56. return h('span', {
  57. class: orderNoClass(data)
  58. }, data.actOrderNo)
  59. }
  60. }
  61. },
  62. {width: 225, code: 'orderName', name: '医嘱名称'},
  63. {
  64. code: 'dose', name: '剂量', width: 75, cellRenderer: ({data}) => {
  65. return h('span', {}, nullToEmpty(data.dose) + ' ' + nullToEmpty(data.doseUnitName))
  66. }
  67. },
  68. {code: 'frequCode', name: '频率', width: 75},
  69. {code: 'supplyCodeName', name: '给药方式', width: 60},
  70. {
  71. code: 'startTime', name: '开始时间', width: 95, cellRenderer: ({data}) => {
  72. return h('span', {}, timeFomat(data.startTime)) // (<span>{timeFomat(data.startTime)}</span>)
  73. }
  74. },
  75. {
  76. code: 'endTime', name: '结束时间', width: 160, cellRenderer: ({data, index}) => {
  77. if (stringIsBlank(data.endTime) && stringIsBlank(data.parentNo) && data.frequCode !== 'ONCE') {
  78. return h('input', {
  79. type: 'datetime-local',
  80. style: endDateStyle(data),
  81. value: data.endTimeTemp,
  82. onInput: (event) => {
  83. data.endTimeTemp = event.target.value
  84. },
  85. onclick: (event) => {
  86. event.stopPropagation()
  87. },
  88. onContextmenu: (event) => {
  89. event.stopPropagation()
  90. event.preventDefault();
  91. cancelStopTime(data, index)
  92. }
  93. }, null)
  94. }
  95. return h('span', null, timeFomat(data.endTime))
  96. }
  97. },
  98. {
  99. code: 'emergencyFlag', name: '紧急', cellRenderer: ({cellData}) => {
  100. return h('span', null, cellData === '1' ? '√' : '')
  101. },
  102. width: 30
  103. },
  104. {
  105. code: 'ybSelfFlag', name: '自费', cellRenderer: ({cellData}) => {
  106. return h('span', null, cellData === '1' ? '√' : '')
  107. },
  108. width: 30
  109. },
  110. {code: 'physicianName', name: '医生', width: 65},
  111. {code: 'selfBuyName', name: '费用标志', width: 60},
  112. {code: 'execUnitName', name: '执行科室', width: 80},
  113. {
  114. code: 'drugQuan', name: '领量', cellRenderer: ({data}) => {
  115. return h('span', null, nullToEmpty(data.drugQuan) + nullToEmpty(data.miniUnitName))
  116. },
  117. width: 30
  118. },
  119. {code: 'groupNoName', name: '药房', width: 91},
  120. {code: 'serial', name: '序号', width: 35},
  121. {code: 'instruction', name: '嘱托', width: 150},
  122. {
  123. name: '操作', width: 100, fixed: 'right', cellRenderer: ({data}) => {
  124. return h('div', {
  125. class: 'yz_button',
  126. onclick: (e) => {
  127. e.preventDefault();
  128. e.stopImmediatePropagation();
  129. emits('voidOrders', data)
  130. }
  131. }, [hToVoidNode(data), hDeleteNode(data)])
  132. }
  133. }
  134. ];
  135. const hToVoidNode = (data) => {
  136. return h('div', {
  137. class: 'toVoid',
  138. onclick: (e) => {
  139. e.preventDefault();
  140. e.stopImmediatePropagation();
  141. emits('voidOrders', data)
  142. }
  143. }, {default: () => '作废'})
  144. }
  145. const hDeleteNode = (data) => {
  146. return h('div', {
  147. class: 'delete',
  148. onclick: (e) => {
  149. e.preventDefault();
  150. e.stopImmediatePropagation();
  151. yzMitt.emit('deleteAnOrderByOrderNo', data, false)
  152. }
  153. }, {default: () => '删除'})
  154. }
  155. const orderNoClass = (data) => {
  156. let c = ''
  157. if (data.newOrderFlag > 0) {
  158. c = 'new_order'
  159. }
  160. return c
  161. }
  162. const timeFomat = (val) => {
  163. return getFormatDatetime(val, 'YY-MM-DD HH:mm')
  164. }
  165. function getYiZhuFlag(val) {
  166. if (stringIsBlank(val)) {
  167. return val
  168. }
  169. switch (val) {
  170. case '1':
  171. return h('span', {style: {color: '#05ff00'}}, 'R') // (<span style="color: #05ff00">R</span>)
  172. case '2':
  173. return h('span', {style: {color: '#0000fb'}}, 'Q')//(<span style="color: #0000fb">Q</span>)
  174. case '3':
  175. return h('span', {style: {color: '#ff07f3'}}, 'Z')// (<span style="color: #ff07f3">Z</span>)
  176. case '4':
  177. return h('span', {style: {color: '#ff07f3'}}, 'Z')// (<span style="color: #ff07f3">Z</span>)
  178. case '5':
  179. return h('span', {style: {color: 'red'}}, 'T')// (<span style="color: red">T</span>)
  180. case '-1':
  181. return h('span', {style: {color: '#00ffe0'}}, 'D') // (<span style="color: #00ffe0">D</span>)
  182. default:
  183. return 'warning'
  184. }
  185. }
  186. const endDateStyle = (item) => {
  187. if (item.endTimeTemp && item.$selected) {
  188. return {
  189. width: '140px',
  190. color: 'white',
  191. backgroundColor: 'red',
  192. border: 0,
  193. }
  194. } else {
  195. return {
  196. width: '140px',
  197. border: 0,
  198. }
  199. }
  200. }
  201. const rowClick = (data) => {
  202. emits('rowClick', data)
  203. }
  204. const rowClass = (data) => {
  205. if (typeof twinkleList.value[data.actOrderNo] !== 'undefined') {
  206. sleep(3000).then(() => {
  207. delete twinkleList.value[data.actOrderNo]
  208. })
  209. return 'animation_hzfirst'
  210. } else if (typeof twinkleList.value[data.parentNo] !== 'undefined') {
  211. return 'animation_hzfirst'
  212. }
  213. // 父级
  214. if (data.associationFlag) {
  215. return 'parent_level'
  216. }
  217. // 子级
  218. if (associateOrders.value.actOrderNo === data.actOrderNo) {
  219. return 'child_level'
  220. }
  221. if (data.actOrderNo === yiZhuData.value.actOrderNo) {
  222. return 'activation'
  223. }
  224. }
  225. const setDefaultStopTime = async ({data, index}) => {
  226. if (stringIsBlank(data.endTime) && stringIsBlank(data.parentNo) && data.frequCode !== 'ONCE') {
  227. data.endTimeTemp = getFormatDatetime(await getServerDateApi(), 'YYYY-MM-DDTHH:mm')
  228. clickSelected(true, data, index)
  229. }
  230. }
  231. const cancelStopTime = (val, index) => {
  232. if (val.parentNo) return
  233. val.endTimeTemp = ''
  234. clickSelected(false, val, index)
  235. }
  236. const clickSelected = (isSelected, data, index) => {
  237. data.$selected = !data.$selected
  238. }
  239. const twinkleList = ref({})
  240. const scrollTo = (key) => {
  241. twinkleList.value[key] = true
  242. let index = tableRef.value.scrollToByKey(key)
  243. if (index < 0) {
  244. scrollToEnd()
  245. }
  246. }
  247. const scrollToEnd = () => {
  248. tableRef.value.scrollTo(tempYzData.value.length)
  249. }
  250. const mousePosition = ref()
  251. const opt = [
  252. {
  253. name: '医嘱费用', click: (data) => {
  254. yzMitt.emit('queryFeeByOrderNo', data)
  255. }
  256. },
  257. {
  258. name: '复制', click: (data) => {
  259. yzMitt.emit('copy', data.actOrderNo, data.frequCode)
  260. },
  261. icon: h(ElIcon, null, () => h(DocumentCopy))
  262. },
  263. {
  264. name: '粘贴', click: (data) => {
  265. yzMitt.emit('paste')
  266. },
  267. validator: () => {
  268. return yzMitt.emit('allowReplication')
  269. },
  270. icon: h('i', {
  271. class: 'iconfont icon-zhantie'
  272. })
  273. },
  274. {
  275. name: '关联', click: (data, index) => {
  276. emits('clickAssociate', data)
  277. }
  278. }, {
  279. name: '退出关联', click: () => {
  280. clearAssociate()
  281. }
  282. }, {
  283. name: '说明书', click: (data) => {
  284. if (data.groupNo !== '00') {
  285. drugManual.value.open(data.orderCode, data.serial);
  286. }
  287. }
  288. }, {
  289. name: '停止医嘱', click: (data, index) => {
  290. if (data.$selected) {
  291. cancelStopTime({data, index})
  292. } else {
  293. setDefaultStopTime({data, index})
  294. }
  295. },
  296. validator: (data) => {
  297. return !data.parentNo;
  298. }
  299. }, {
  300. name: '作废', click: (data) => {
  301. emits('voidOrders', data)
  302. }
  303. }
  304. ];
  305. const contextmenuItem = (data, index, event) => {
  306. mousePosition.value = {
  307. event,
  308. data: data,
  309. index
  310. }
  311. }
  312. const clearSelected = () => {
  313. }
  314. const callTemplate = (list) => {
  315. twinkleList.value = list
  316. scrollToEnd()
  317. }
  318. onMounted(() => {
  319. yzMitt.on('tableScroll', (val) => {
  320. tableRef.value.scrollTo(val)
  321. })
  322. yzMitt.on('clearSelected', () => {
  323. tableRef.value.clearSelected()
  324. })
  325. yzMitt.on('scrollEndAndTwinkle', async (val) => {
  326. twinkleList.value = val;
  327. await nextTick()
  328. scrollToEnd()
  329. });
  330. yzMitt.on('getSelectedData', () => {
  331. return tableRef.value.getSelectedData()
  332. })
  333. })
  334. watch(() => tempYzData.value.length, () => {
  335. tableRef.value.scrollTo(0)
  336. })
  337. defineExpose({
  338. scrollTo,
  339. scrollToEnd,
  340. callTemplate
  341. })
  342. </script>
  343. <style lang="scss">
  344. .new_order {
  345. position: relative;
  346. &:before {
  347. position: absolute;
  348. right: -6px;
  349. font-size: 15px;
  350. top: -5px;
  351. content: "*";
  352. color: red;
  353. }
  354. }
  355. @keyframes hzfirst {
  356. from {
  357. background-color: #95d475
  358. }
  359. to {
  360. background-color: white;
  361. }
  362. }
  363. .yz_button {
  364. width: 100%;
  365. cursor: pointer;
  366. padding: 0 5px;
  367. display: flex;
  368. justify-content: space-between;
  369. div {
  370. width: max-content;
  371. margin: 0 5px;
  372. }
  373. .toVoid {
  374. color: #E6A23C;
  375. background-color: inherit;
  376. }
  377. .delete {
  378. color: #F56C6C;
  379. background-color: inherit;
  380. }
  381. }
  382. .animation_hzfirst {
  383. .cell {
  384. animation: hzfirst 1s linear infinite
  385. }
  386. }
  387. .activation {
  388. background-color: rgba(0, 58, 241) !important;
  389. color: white;
  390. }
  391. .parent_level {
  392. background-color: red;
  393. color: white;
  394. }
  395. .child_level {
  396. background-color: rgba(3, 255, 15);
  397. color: black;
  398. }
  399. </style>