YzTableV2.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. <template>
  2. <div>
  3. <xc-table-v2 :data="tempYzData"
  4. :rowStyle="rowStyle"
  5. @rowClick="rowClick"
  6. row-key="actOrderNo"
  7. @contextmenu="contextmenuItem"
  8. :height="getWindowSize.h / 1.7"
  9. @dbRowClick="setDefaultStopTime"
  10. ref="tableRef"
  11. :columns="header"/>
  12. <right-click-menu :mouse-position="mousePosition" :config="opt"/>
  13. </div>
  14. </template>
  15. <script setup name='Test' lang="tsx">
  16. import {Ref, ref} from 'vue'
  17. import XcTableV2 from "@/components/xiao-chan/xc-table-v2/XcTableV2.vue";
  18. import {stringIsBlank} from "@/utils/blank-utils";
  19. import {getFormatDatetime} from "@/utils/date";
  20. import {getServerDateApi} from '@/api/public-api'
  21. import {getWindowSize} from "@/utils/window-size";
  22. import {
  23. tempYzData,
  24. yiZhuData,
  25. associateOrders,
  26. clearAssociate,
  27. drugManual,
  28. } from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng";
  29. import {XcTableV2Type} from "@/components/xiao-chan/xc-table-v2/XcTableV2Type";
  30. import sleep from "@/utils/sleep";
  31. import RightClickMenu from "@/components/menu-item/RightClickMenu.vue";
  32. const emits = defineEmits(['rowClick', 'clickAssociate', 'voidOrders'])
  33. const tableRef: Ref<XcTableV2Type> = ref(null)
  34. const header = [
  35. {type: 'selected', width: 20},
  36. {width: 30, type: 'index'},
  37. {width: 20, code: 'orderGroup', name: '组'},
  38. {
  39. width: 20, code: 'statusFlag', cellRenderer: ({cellData}) => {
  40. return getYiZhuFlag(cellData)
  41. }
  42. },
  43. {
  44. width: 70, code: 'actOrderNo', name: '医嘱号', cellRenderer: ({data}) => {
  45. if (data.error) {
  46. return (<span style="color: red"
  47. class={orderNoClass(data)}>{data.actOrderNo}</span>)
  48. } else {
  49. return (<span class={orderNoClass(data)}>{data.actOrderNo}</span>)
  50. }
  51. }
  52. },
  53. {width: 225, code: 'orderName', name: '医嘱名称'},
  54. {
  55. code: 'dose', name: '剂量', width: 75, cellRenderer: ({data}) => {
  56. return <span>{nu(data.dose) + ' ' + nu(data.doseUnitName)}</span>
  57. }
  58. },
  59. {code: 'frequCode', name: '频率', width: 75},
  60. {code: 'supplyCodeName', name: '给药方式', width: 60},
  61. {
  62. code: 'startTime', name: '开始时间', width: 95, cellRenderer: ({data}) => {
  63. return (<span>{timeFomat(data.startTime)}</span>)
  64. }
  65. },
  66. {
  67. // 出院时间的大小不能改
  68. code: 'endTime', name: '结束时间', width: 160, cellRenderer: ({data}) => {
  69. if (stringIsBlank(data.endTime) && stringIsBlank(data.parentNo) && data.frequCode !== 'ONCE') {
  70. return <input type="datetime-local"
  71. style={endDateStyle(data)}
  72. value={data.endTimeTemp}
  73. oninput={(val: Event) => {
  74. data.endTimeTemp = val.target.value
  75. }
  76. }
  77. onclick={(event: Event) => {
  78. event.stopPropagation()
  79. }
  80. }
  81. oncontextmenu={(event: Event) => {
  82. event.stopPropagation()
  83. event.preventDefault();
  84. cancelStopTime(data)
  85. }}/>
  86. }
  87. return <span>{timeFomat(data.endTime)}</span>
  88. }
  89. },
  90. {
  91. code: 'emergencyFlag', name: '紧急', cellRenderer: ({cellData}) => {
  92. return <span>{cellData === '1' ? '√' : ''}</span>
  93. },
  94. width: 30
  95. },
  96. {
  97. code: 'ybSelfFlag', name: '自费', cellRenderer: ({cellData}) => {
  98. return <span>{cellData === '1' ? '√' : ''}</span>
  99. },
  100. width: 30
  101. },
  102. {code: 'physicianName', name: '医生', width: 65},
  103. {code: 'selfBuyName', name: '费用标志', width: 60},
  104. {code: 'execUnitName', name: '执行科室', width: 80},
  105. {
  106. code: 'drugQuan', name: '领量', cellRenderer: ({data}) => {
  107. return <span>{nu(data.drugQuan) + nu(data.drugQuanName)}</span>
  108. },
  109. width: 30
  110. },
  111. {code: 'groupNoName', name: '药房', width: 91},
  112. {code: 'serial', name: '序号', width: 35},
  113. {code: 'instruction', name: '嘱托', width: 150},
  114. {
  115. name: '操作', width: 53, cellRenderer: ({data}) => (
  116. <button onclick={(e) => {
  117. e.preventDefault();
  118. e.stopImmediatePropagation();
  119. emits('voidOrders', data)
  120. }}>作废</button>
  121. )
  122. }
  123. ];
  124. const orderNoClass = (data) => {
  125. let c = ''
  126. if (data.newOrderFlag > 0) {
  127. c = 'new_order'
  128. }
  129. return c
  130. }
  131. const timeFomat = (val) => {
  132. return getFormatDatetime(val, 'YY-MM-DD HH:mm')
  133. }
  134. function getYiZhuFlag(val) {
  135. if (stringIsBlank(val)) {
  136. return val
  137. }
  138. switch (val) {
  139. case '1':
  140. return (<span style="color: #05ff00">R</span>)
  141. case '2':
  142. return (<span style="color: #0000fb">Q</span>)
  143. case '3':
  144. return (<span style="color: #ff07f3">Z</span>)
  145. case '4':
  146. return (<span style="color: #ff07f3">Z</span>)
  147. case '5':
  148. return (<span style="color: red">T</span>)
  149. case '-1':
  150. return (<span style="color: #00ffe0">D</span>)
  151. default:
  152. return 'warning'
  153. }
  154. }
  155. const endDateStyle = (item) => {
  156. if (item.endTimeTemp && item.tempCheckbox) {
  157. return {
  158. width: '140px',
  159. color: 'white',
  160. backgroundColor: 'red',
  161. border: 0,
  162. }
  163. } else {
  164. return {
  165. width: '140px',
  166. border: 0,
  167. }
  168. }
  169. }
  170. const rowClick = (data) => {
  171. emits('rowClick', data)
  172. }
  173. const rowStyle = (data) => {
  174. if (typeof twinkleList.value[data.actOrderNo] !== 'undefined') {
  175. sleep(3000).then(() => {
  176. delete twinkleList.value[data.actOrderNo]
  177. })
  178. return {
  179. animation: 'hzfirst 1s linear infinite',
  180. }
  181. } else if (typeof twinkleList.value[data.parentNo] !== 'undefined') {
  182. return {
  183. animation: 'hzfirst 1s linear infinite',
  184. }
  185. }
  186. // 父级
  187. if (data.associationFlag) {
  188. return {
  189. background: 'red',
  190. color: '#fff'
  191. }
  192. }
  193. // 子级
  194. if (associateOrders.value.actOrderNo === data.actOrderNo) {
  195. return {
  196. background: 'rgba(3,255,15,0.68)',
  197. color: '#fff'
  198. }
  199. }
  200. if (data.actOrderNo === yiZhuData.value.actOrderNo) {
  201. return {
  202. background: 'rgba(0, 58, 241, 0.68)',
  203. color: '#fff'
  204. }
  205. }
  206. }
  207. const setDefaultStopTime = async (item) => {
  208. if (item.parentNo) return
  209. item.endTimeTemp = getFormatDatetime(await getServerDateApi(), 'yyyy-MM-DD HH:mm')
  210. if (!item.tempCheckbox) {
  211. clickSelected(item)
  212. }
  213. }
  214. const cancelStopTime = (val) => {
  215. if (val.parentNo) return
  216. val.endTimeTemp = ''
  217. if (val.tempCheckbox) {
  218. clickSelected(val)
  219. }
  220. }
  221. const clickSelected = (row) => {
  222. tableRef.value.selectedRow(row)
  223. }
  224. const twinkleList = ref({})
  225. const scrollTo = (key) => {
  226. twinkleList.value[key] = true
  227. let index = tableRef.value.scrollToByKey(key)
  228. if (index < 0) {
  229. scrollToEnd()
  230. }
  231. }
  232. const scrollToEnd = () => {
  233. tableRef.value.scrollTo(tempYzData.value.length)
  234. }
  235. const mousePosition = ref()
  236. const opt = [
  237. {
  238. name: '关联', click: (data, index) => {
  239. emits('clickAssociate', data)
  240. }
  241. }, {
  242. name: '退出关联模式', click: () => {
  243. clearAssociate()
  244. }
  245. }, {
  246. name: '药品说明书', click: (data) => {
  247. if (data.groupNo !== '00') {
  248. drugManual.value.open(data.orderCode, data.serial);
  249. }
  250. }
  251. }, {
  252. name: '停止医嘱', click: (data) => {
  253. if (data.tempCheckbox) {
  254. cancelStopTime(data)
  255. } else {
  256. setDefaultStopTime(data)
  257. }
  258. },
  259. validator: (data) => {
  260. return !data.parentNo;
  261. }
  262. }, {
  263. name: '作废', click: (data) => {
  264. emits('voidOrders', data)
  265. }
  266. }
  267. ]
  268. const contextmenuItem = (data: any, index: Number, event: Event) => {
  269. mousePosition.value = {
  270. event,
  271. data: data,
  272. index
  273. }
  274. }
  275. const getSelectedData = () => {
  276. return tableRef.value.getSelectedData()
  277. }
  278. const clearSelected = () => {
  279. tableRef.value.clearSelected()
  280. }
  281. const nu = (val) => {
  282. if (val === null) {
  283. return ''
  284. } else if (typeof val === 'undefined') {
  285. return ''
  286. } else {
  287. return val
  288. }
  289. }
  290. const callTemplate = (list) => {
  291. twinkleList.value = list
  292. scrollToEnd()
  293. }
  294. defineExpose({
  295. scrollTo,
  296. scrollToEnd,
  297. getSelectedData,
  298. clearSelected,
  299. callTemplate
  300. })
  301. </script>
  302. <style lang="scss">
  303. .new_order {
  304. position: relative;
  305. &:before {
  306. position: absolute;
  307. right: -6px;
  308. font-size: 15px;
  309. top: -5px;
  310. content: "*";
  311. color: red;
  312. }
  313. }
  314. @keyframes hzfirst {
  315. from {
  316. background-color: #95d475
  317. }
  318. to {
  319. background-color: white;
  320. }
  321. }
  322. </style>