YzEditor.vue 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. <template>
  2. <div ref="editorMainRef" style="width: max-content">
  3. <div class="editing_area"
  4. :style="{color: isEdit ? '#0014fc' : ''}">
  5. <div class="yz_editor__disable" v-if="isEdit"/>
  6. <div class="yz_input__box">
  7. <div>
  8. 医嘱名称:
  9. <CyComboGrid
  10. ref="orderCodeRef"
  11. style="width: 220px"
  12. placement="bottom"
  13. :fallbackPlacements="['top', 'bottom']"
  14. v-model="yiZhuData"
  15. :disabled="isEdit"
  16. value="orderCode"
  17. label="orderName"
  18. :remote-method="searchOrders"
  19. @rowClick="({row}) => searchClickFunc(row)"
  20. :table-header="tableHeaderV2"
  21. :rowHeight="30"
  22. />
  23. </div>
  24. <div class="input__style">
  25. {{ yiZhuData.drugSpecification }}
  26. </div>
  27. <div>
  28. 频率:
  29. <select-v4
  30. :data="yaoPinPingLvData"
  31. ref="pingLvRef"
  32. v-model="yiZhuData.frequCode"
  33. :disabled="queryParam.frequCode === frequCodeEnum.temporary"
  34. style="width: 120px"/>
  35. </div>
  36. <div>
  37. 一次剂量:
  38. <el-input-number
  39. v-model="yiZhuData.dose"
  40. :step="jiLiangValue"
  41. :controls="false"
  42. :min="0"
  43. ref="doseRef"
  44. id="yz_dose"
  45. :precision="dosePrecision"
  46. style="width: 110px"
  47. @change="jiSuanLingLiang"
  48. />
  49. <CyComboGrid
  50. v-model="yiZhuData"
  51. :data="yaoPinJiLiangData"
  52. style="width: 80px"
  53. value="doseUnit"
  54. label="doseUnitName"
  55. @rowClick="xuanZheJiLiang"
  56. />
  57. </div>
  58. <div>
  59. 领量:
  60. <template v-if="queryParam.frequCode === 'takeMedicine'">
  61. <el-input-number
  62. style="width: 60px"
  63. ref="drugQuanRef"
  64. @keydown="drugQuanChange"
  65. v-model="yiZhuData.drugQuan"
  66. :min="1"
  67. :controls="false"/>
  68. <span style="color: red">{{ yiZhuData.miniUnitName }}</span>
  69. </template>
  70. <template v-else-if="yiZhuData.serial === '00'">
  71. <el-input-number
  72. style="width: 60px"
  73. v-model="yiZhuData.drugQuan"
  74. :min="0"
  75. :controls="false"/>
  76. </template>
  77. <template v-else>
  78. {{ yiZhuData.drugQuan }}
  79. {{ yiZhuData.miniUnitName }}
  80. </template>
  81. </div>
  82. </div>
  83. <div class="yz_input__box">
  84. <div>
  85. 给药方式:
  86. <select-v4
  87. key="supplyCode"
  88. :disabled="supplyDisabled"
  89. style="width: 120px"
  90. v-model="yiZhuData.supplyCode"
  91. :data="geiYaoFangShiData"
  92. clearable/>
  93. </div>
  94. <div>
  95. 开始时间:
  96. <el-date-picker
  97. style="width: 160px"
  98. v-model="yiZhuData.startTime"
  99. :disabled-date="disabledDate"
  100. id="yz_startTime"
  101. type="datetime"
  102. format="YYYY-MM-DD HH:mm:ss"
  103. value-format="YYYY-MM-DD HH:mm:ss"
  104. ></el-date-picker>
  105. </div>
  106. <div>
  107. 停止时间:
  108. <el-date-picker
  109. style="width: 160px"
  110. v-model="yiZhuData.endTime"
  111. id="yz_endTime"
  112. :disabled="yiZhuData.frequCode === 'ONCE'"
  113. :disabled-date="disabledDate"
  114. format="YYYY-MM-DD HH:mm:ss"
  115. type="datetime"
  116. value-format="YYYY-MM-DD HH:mm:ss"
  117. ></el-date-picker>
  118. </div>
  119. <div class="input__style" style="width: 120px">
  120. 医生: {{ yiZhuData.enterOperName ? yiZhuData.enterOperName : userStore.userInfo.name }}
  121. </div>
  122. <div>
  123. 执行科室:
  124. <SystemDeptSelect
  125. v-model="yiZhuData"
  126. id="yz_execUnit"
  127. value="execUnit"
  128. label="execUnitName"
  129. style="width: 120px"
  130. />
  131. </div>
  132. </div>
  133. <div class="yz_input__box">
  134. <div class="div_center__box">
  135. 医嘱时间:
  136. <div class="input__style"> {{ yiZhuData.orderTime }}</div>
  137. </div>
  138. <div>
  139. 父医嘱:
  140. <CyComboGrid
  141. v-model="yiZhuData"
  142. style="width: 120px;"
  143. placeholder="父医嘱"
  144. clearable
  145. :disabled="supplyDisabled"
  146. @clear="clearDoctorSOrder"
  147. @focus="fuYiZhuClick"
  148. @rowClick="({row}) => modifyDosingMethod(row)"
  149. :table-header="parentOrder"
  150. :data="fuYiZhuData"
  151. value="parentNo"
  152. label="parentNoName"
  153. />
  154. </div>
  155. <div :title="yiZhuData.discription" class="div_center__box">
  156. 描述:
  157. <div class="input__style" style="overflow: auto;width: 240px">
  158. {{ yiZhuData.discription }}
  159. </div>
  160. </div>
  161. </div>
  162. <div class="yz_input__box">
  163. <div class="div_center__box" :title="yiZhuData.instruction">
  164. <div style="width: 87px">
  165. 医生嘱托:
  166. </div>
  167. <el-input v-model="yiZhuData.instruction"
  168. clearable
  169. style="width: 220px"
  170. maxlength="50"
  171. show-word-limit/>
  172. </div>
  173. <div class="div_center__box">
  174. <el-select
  175. v-model="yiZhuData.kfFlag"
  176. id="yz_kfFlag"
  177. clearable
  178. style="width: 80px"
  179. @clear="yiZhuData.kfFlag = null">
  180. <el-option key="1" label="饭前" value="1"></el-option>
  181. <el-option key="2" label="饭后" value="2"></el-option>
  182. </el-select>
  183. </div>
  184. <div>
  185. 费用标志:
  186. <el-select v-model="yiZhuData.selfBuy"
  187. :disabled="supplyDisabled"
  188. clearable style="width: 120px"
  189. @clear="yiZhuData.selfBuy = null">
  190. <el-option label="自备" value="1"/>
  191. <el-option label="嘱托" value="2"/>
  192. <el-option label="基数药" value="3"/>
  193. <el-option :disabled="queryParam.frequCode !== 'takeMedicine'" label="出院带药"
  194. value="4"/>
  195. <el-option label="GCP自费" value="5"/>
  196. </el-select>
  197. </div>
  198. <div class="div_center__box">
  199. <xc-checkbox
  200. label="医保自费"
  201. v-model="yiZhuData.ybSelfFlag"
  202. inactive-value="0"
  203. active-value="1"/>
  204. &nbsp;&nbsp;&nbsp;
  205. <xc-checkbox
  206. label="紧急"
  207. v-model="yiZhuData.emergencyFlag"
  208. @keydown.tab="toAddAnOrder"
  209. active-value="1"
  210. inactive-value="0"/>
  211. </div>
  212. <div>
  213. 录入/确认/停止
  214. <div style="display: inline-block">
  215. <span style="background-color:#05ff00;padding: 2px;">
  216. {{ yiZhuData.enterOperName }}
  217. </span>
  218. /
  219. <span style="background-color:#0000fa;padding: 2px;color: white ">
  220. {{ yiZhuData.signerName }}
  221. </span>
  222. /
  223. <span style="background-color:red;padding: 2px;">
  224. {{ yiZhuData.modifierName }}
  225. </span>
  226. </div>
  227. </div>
  228. </div>
  229. </div>
  230. <BaoCuoXinXi v-if="errorMsg.dialog"
  231. @click-error="clickError"/>
  232. <!-- 弹窗医嘱 -->
  233. <YzDialog :yz-data="yiZhuData" v-if="yzDialogRef" @closed="yzDialogRef = false"/>
  234. </div>
  235. </template>
  236. <script setup lang="ts">
  237. import {
  238. confirmOrders,
  239. copyOrder,
  240. enterOrders,
  241. FeeInfo,
  242. getOrderNo,
  243. huoQuFeiYongXinXi,
  244. huoQuXiangMu,
  245. huoQuZhiXinKeShi,
  246. toDeleteAnOrder,
  247. YaoPingJiLiang
  248. } from '@/api/zhu-yuan-yi-sheng/yi-zhu-lu-ru'
  249. import {listNotBlank, listToStr, stringIsBlank, stringNotBlank} from '@/utils/blank-utils'
  250. import XcCheckbox from "@/components/xiao-chan/checkbox/XcCheckbox";
  251. import {BizException, ExceptionEnum} from "@/utils/BizException";
  252. import {
  253. queryParam,
  254. yiZhuData,
  255. yzData,
  256. isCydy,
  257. tableHeaderV2,
  258. frequCodeEnum,
  259. yaoPinPingLvData,
  260. geiYaoFangShiData,
  261. yzMitt,
  262. huanZheXinXi,
  263. frequencyConfig,
  264. addTempOrderNo,
  265. yiZhuDataInit,
  266. setOrderDataAndTwinkle,
  267. feeKey,
  268. YzType,
  269. SearchOrdersType,
  270. RefFillingValue,
  271. errorMsgFunc,
  272. errorMsg, yzInfoPrompt, jsQueryYzData
  273. } from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/zhu-yuan-yi-sheng";
  274. import {ElMessageBox} from "element-plus";
  275. import YzDialog from "@/components/zhu-yuan-yi-sheng/yi-zhu-lu-ru/dialog/YzDialog";
  276. import Dig from "@/utils/math";
  277. import SelectV4 from "@/components/xiao-chan/select-v4/SelectV4.vue";
  278. import {shortcutTrigger, xcEvent} from "@/utils/xckeydown";
  279. import {xcMessage} from "@/utils/xiaochan-element-plus";
  280. import DoctorAuthorization
  281. from "@/views/hospitalization/zhu-yuan-yi-sheng/yi-zhu-lu-ru/components/DoctorAuthorization.vue";
  282. import sleep from "@/utils/sleep";
  283. import XEUtils from 'xe-utils'
  284. import {
  285. ref,
  286. computed,
  287. nextTick,
  288. onDeactivated,
  289. onActivated,
  290. watch,
  291. onMounted
  292. } from 'vue'
  293. import {getServerDate} from "@/utils/moment-utils";
  294. import {CyMessageBox} from "@/components/cy/message-box";
  295. import setDialogToJs from "@/components/js-dialog-comp/useDialogToJs";
  296. import CyComboGrid from "@/components/cy/combo-grid/src/CyComboGrid.vue";
  297. import BaoCuoXinXi from "@/components/zhu-yuan-yi-sheng/yi-zhu-lu-ru/BaoCuoXinXi.vue";
  298. import SystemDeptSelect from "@/components/system/dept-select/SystemDeptSelect.vue";
  299. import setPatientDoctor from "@/views/hospitalization/zhu-yuan-yi-sheng/patient-doctor/setPatientDoctor";
  300. import {useUserStore} from "@/pinia/user-store";
  301. import doctorStore, {YzSidebarEnum} from "@/views/hospitalization/zhu-yuan-yi-sheng/public-js/useDoctorStore";
  302. const props = withDefaults(defineProps<{
  303. patientInfo: {
  304. inpatientNo: string,
  305. admissTimes: number,
  306. zkWard: string,
  307. zkWardName: string
  308. admissDate: Date
  309. },
  310. openGroupOrderTemplate: (val: string) => void
  311. }>(), {
  312. patientInfo: null,
  313. })
  314. const parentOrder = [
  315. {code: 'actOrderNo', name: "医嘱号", width: 90},
  316. {code: 'orderName', name: "医嘱名称", width: 160},
  317. {code: 'orderTime', name: "时间", width: 150}
  318. ]
  319. const userStore = useUserStore()
  320. const searchOrders = (val) => {
  321. return huoQuXiangMu(val, queryParam.value.groupNo)
  322. }
  323. const searchClickFunc = async (row: SearchOrdersType): Promise<void> => {
  324. // 这个是选择了医嘱模板医嘱,需要打开弹窗
  325. if (row.serial === '0000' && row.groupNo === '0000') {
  326. props.openGroupOrderTemplate(row.orderCode)
  327. return
  328. }
  329. // 在出院带药的页面中选择数据
  330. if (row.serial === '00' && isCydy()) {
  331. clearAndErrorMessage('出院带药不能开项目')
  332. }
  333. // 医嘱号是空的,或者是临时医嘱号的就需要一个新的医嘱号
  334. if (stringIsBlank(yiZhuData.value.actOrderNo) || yiZhuData.value.actOrderNo === addTempOrderNo) {
  335. setYzData('actOrderNo', parseInt(await getOrderNo()));
  336. }
  337. // 清空数据但是保留原来的医嘱号
  338. qingKong(false)
  339. // 设置医嘱的一些默认值
  340. const setYz = new RefFillingValue(yiZhuData, row);
  341. setYz.setValue('orderCode')
  342. .setValue('orderName')
  343. .setValue('serial')
  344. .setValue('discription')
  345. .setValue('groupNo')
  346. .setValue('groupName')
  347. .setValue('infusionFlag')
  348. .setValue('drugFlag')
  349. .setValue('packSize')
  350. .setValue('packSizeName')
  351. .setValue('orderClass')
  352. .setValue('dosage')
  353. .setValue('ybType')
  354. .setValue('execDept')
  355. .setValue('execDeptName')
  356. .setValue('drugSpecification')
  357. .setDefaultValueByName('newOrderFlag', 1)
  358. .setDefaultValueByName('statusFlag', '1');
  359. // 查询一下父医嘱
  360. fuYiZhuClick()
  361. // 药品
  362. if (row.serial !== '00') {
  363. await drugDefaultValue(true, row)
  364. } else {
  365. itemDefaultValue(true, row)
  366. }
  367. await defaultAll(true, row)
  368. }
  369. let oneMessageCount = true;
  370. const oneMessage = () => {
  371. if (oneMessageCount) {
  372. oneMessageCount = false
  373. xcMessage.warning('请注意表格中切换医嘱是不会保存医嘱的,一切数据以录入的医嘱为准。')
  374. }
  375. }
  376. const rowClickFillData = async (data: YzType) => {
  377. if (yiZhuData.value.actOrderNo !== addTempOrderNo && yiZhuData.value.statusFlag === '1') {
  378. oneMessage()
  379. }
  380. // 先清空一遍
  381. qingKong()
  382. yiZhuData.value = data
  383. if (data.serial !== '00') {
  384. await drugDefaultValue(false, data)
  385. } else {
  386. await itemDefaultValue(false, data)
  387. }
  388. await defaultAll(false, data)
  389. }
  390. const clearAndErrorMessage = (message: string) => {
  391. qingKong()
  392. BizException(ExceptionEnum.MESSAGE_ERROR, message)
  393. }
  394. const drugDefaultValue = async (isSearch: boolean, data: SearchOrdersType | YzType) => {
  395. const queryKey = feeKey(data.orderCode, data.serial, props.patientInfo.zkWard, queryParam.value.groupNo, yiZhuData.value.superiorDoctor, yiZhuData.value.statusFlag)
  396. const {
  397. permissionPrompt,
  398. prompt,
  399. data: drugData,
  400. yaoPingJiLiang
  401. }: FeeInfo = await huoQuFeiYongXinXi(queryKey).catch(() => {
  402. clearAndErrorMessage('请联系管理员。')
  403. })
  404. yzInfoPrompt.value = XEUtils.isArray(prompt) ? prompt : []
  405. const drugKey = `${data.orderCode}_${data.serial}`;
  406. // 医生没有权限
  407. if (permissionPrompt) {
  408. await setDialogToJs(DoctorAuthorization, {drugCode: drugKey}).then((res) => {
  409. setYzData('superiorDoctor', res.code)
  410. yzInfoPrompt.value.push('医生授权')
  411. }).catch(() => {
  412. clearAndErrorMessage('取消授权。')
  413. yzInfoPrompt.value.push('取消授权')
  414. })
  415. }
  416. // 加载药品的计量
  417. yaoPinJiLiangData.value = XEUtils.eachAndReturnList(yaoPingJiLiang, (item) => {
  418. return {
  419. ...item,
  420. value: item.code,
  421. label: item.name,
  422. step: item.value
  423. }
  424. })
  425. setYzData('kjywFlag', drugData.kjywFlag)
  426. if (isSearch) {
  427. setYzData('miniUnit', drugData.packUnit)
  428. setYzData('miniUnitName', drugData.packUnitName)
  429. // 是搜索的医嘱都没有剂量这里需要默认拿到第一个剂量
  430. if (listNotBlank(yaoPingJiLiang) && yaoPingJiLiang.length > 0) {
  431. const doseOne: YaoPingJiLiang = yaoPingJiLiang[0]
  432. setYzData('doseUnit', doseOne.code)
  433. setYzData('dose', doseOne.value)
  434. setYzData('doseUnitName', doseOne.name)
  435. jiLiangValue.value = doseOne.value
  436. }
  437. // 使用默认的频率,如果有的话
  438. if (drugData.frequCode) {
  439. setYzData('frequCode', drugData.frequCode)
  440. yzInfoPrompt.value.push('请注意已使用【默认频率】,药剂科维护默认执行频率。')
  441. }
  442. if (drugData.supplyCode) {
  443. setYzData('supplyCode', drugData.supplyCode)
  444. yzInfoPrompt.value.push('请注意已使用【默认给药方式】,药剂科维护默认给药方式。')
  445. }
  446. }
  447. if (stringIsBlank(yiZhuData.value.frequCode)) {
  448. // 如果在临时医嘱页面的话,就变成临时的其他都是长期的
  449. if (queryParam.value.frequCode === frequCodeEnum.temporary) {
  450. setYzData('frequCode', 'ONCE')
  451. } else {
  452. setYzData('frequCode', frequencyConfig)
  453. }
  454. }
  455. setYzData('packSize', drugData.packSize)
  456. setYzData('packUnit', drugData.packUnit)
  457. setYzData('drugVolume', drugData.volum)
  458. setYzData('drugVolUnit', drugData.volUnit)
  459. if (stringNotBlank(yiZhuData.value.doseUnit)) {
  460. yaoPinJiLiangData.value.forEach(item => {
  461. if (item.code === yiZhuData.value.doseUnit) {
  462. jiLiangValue.value = item.step
  463. }
  464. })
  465. }
  466. await jiSuanLingLiang(yiZhuData.value.dose)
  467. openTheOrderPopUpWindow()
  468. }
  469. const itemDefaultValue = (isSearch: boolean, data: SearchOrdersType | YzType) => {
  470. setYzData('kjywFlag', 0)
  471. const queryKey = feeKey(data.orderCode, '00', props.patientInfo.zkWard, queryParam.value.groupNo, yiZhuData.value.superiorDoctor, yiZhuData.value.statusFlag)
  472. const {
  473. prompt
  474. }: FeeInfo = huoQuFeiYongXinXi(queryKey).catch(() => {
  475. clearAndErrorMessage('请联系管理员。')
  476. })
  477. yzInfoPrompt.value = XEUtils.isArray(prompt) ? prompt : []
  478. if (isSearch) {
  479. setYzData('dose', 1)
  480. setYzData('supplyCode', null)
  481. setYzData('drugQuan', 1)
  482. }
  483. if (yiZhuData.value.statusFlag === '1') {
  484. openTheOrderPopUpWindow()
  485. }
  486. if (stringIsBlank(yiZhuData.value.frequCode)) {
  487. // 如果在临时医嘱页面的话,就变成临时的其他都是长期的
  488. if (queryParam.value.frequCode === frequCodeEnum.temporary) {
  489. yzInfoPrompt.value.push('使用频率 【ONCE】')
  490. setYzData('frequCode', 'ONCE')
  491. } else {
  492. yzInfoPrompt.value.push(`使用频率 【${frequencyConfig}】`)
  493. setYzData('frequCode', frequencyConfig)
  494. }
  495. }
  496. }
  497. const defaultAll = async (isSearch: boolean, data: SearchOrdersType | YzType) => {
  498. if (isSearch) {
  499. doctorStore.setYzSidebar(YzSidebarEnum.YZ)
  500. let now = await getServerDate()
  501. setYzData('orderTime', now);
  502. setYzData('startTime', now);
  503. // 如果有默认科室的话就用项目中自带的科室,没有的话就用患者的科室
  504. if (data.execDept) {
  505. setYzData('execUnit', data.execDept)
  506. setYzData('execUnitName', data.execDeptName)
  507. yzInfoPrompt.value.push('请注意,已使用默认执行科室,如需修改请在执行科室下拉框中搜索科室。')
  508. }
  509. }
  510. if (stringIsBlank(yiZhuData.value.execUnit)) {
  511. setYzData('execUnit', huanZheXinXi.value.zkWard)
  512. setYzData('execUnitName', huanZheXinXi.value.zkWardName)
  513. }
  514. try {
  515. pingLvRef.value.focus()
  516. } catch {
  517. }
  518. if (isCydy()) {
  519. setYzData('selfBuy', '4');
  520. setYzData('frequCode', 'ONCE');
  521. setYzData('supplyCode', '007');
  522. yzInfoPrompt.value.push('请注意,出院带药频率默认 【ONCE】 给药方式变为【出院带药】。')
  523. }
  524. if (yiZhuData.value.statusFlag !== '1' && yiZhuData.value.parentNo) {
  525. fuYiZhuData.value = []
  526. fuYiZhuData.value.push({
  527. actOrderNo: yiZhuData.value.parentNo,
  528. orderName: yiZhuData.value.parentNoName
  529. })
  530. }
  531. if (queryParam.value.frequCode === frequCodeEnum.temporary) {
  532. setYzData('frequCode', 'ONCE')
  533. yzInfoPrompt.value.push('请注意,频率强制设置 【ONCE】')
  534. }
  535. // 如果搜索了医嘱那么 这里就需要 重新赋值,不认表格就没办法变化了,把原来的换掉
  536. if (isSearch) {
  537. for (let i = yzData.value.length - 1; i >= 0; i--) {
  538. let item = yzData.value[i];
  539. if (yiZhuData.value.actOrderNo === item.actOrderNo) {
  540. yzData.value[i] = yiZhuData.value
  541. return
  542. }
  543. }
  544. }
  545. }
  546. const setYzData = (name: keyof YzType, value: any): void => {
  547. yiZhuData.value[name] = value
  548. }
  549. /* 频率 */
  550. const pingLvRef = ref()
  551. /*计算领量*/
  552. const jiSuanLingLiang = async (val) => {
  553. await nextTick()
  554. if (yiZhuData.value.statusFlag !== '1') {
  555. return
  556. }
  557. // 出院带药
  558. if (yiZhuData.value.selfBuy === '4') {
  559. return;
  560. }
  561. if (jiLiangValue.value <= 0) {
  562. return;
  563. }
  564. let drugQuanA = Math.ceil(Dig.division(val, jiLiangValue.value))
  565. if (yiZhuData.value.serial === '99') {
  566. drugQuanA = Math.ceil(Dig.division(drugQuanA, yiZhuData.value.packSize))
  567. }
  568. yiZhuData.value.drugQuan = drugQuanA;
  569. }
  570. /* 选择剂量 */
  571. const yaoPinJiLiangData = ref<YaoPingJiLiang[]>([])
  572. const jiLiangValue = ref(0)
  573. const xuanZheJiLiang = ({row}) => {
  574. jiLiangValue.value = row.step
  575. yiZhuData.value.dose = row.step
  576. jiSuanLingLiang(yiZhuData.value.dose)
  577. }
  578. // 医嘱限制时间不能在之前
  579. const disabledDate = (time: Date) => {
  580. if (props.patientInfo?.admissDate) {
  581. return time.getTime() < new Date(props.patientInfo.admissDate).getTime() - 8.64e7;
  582. }
  583. return true;
  584. }
  585. /* 父医嘱 */
  586. const fuYiZhuData = ref<any[]>([])
  587. const fuYiZhuClick = () => {
  588. fuYiZhuData.value = [];
  589. const eachName = queryParam.value.sort === 'asc' ? 'lastArrayEach' : 'arrayEach'
  590. const eachFunction = XEUtils[eachName]
  591. let hasParentNo = false
  592. // @ts-ignore
  593. eachFunction(yzData.value, (item) => {
  594. const {statusFlag, serial, parentNo, drugFlag, actOrderNo} = item
  595. if (statusFlag !== '1') {
  596. return
  597. }
  598. if (parentNo === yiZhuData.value.actOrderNo) {
  599. hasParentNo = true
  600. return;
  601. }
  602. if (serial !== '00' && stringIsBlank(parentNo) && drugFlag !== 'd') {
  603. if (yiZhuData.value.actOrderNo !== actOrderNo) {
  604. fuYiZhuData.value.push(item)
  605. }
  606. }
  607. })
  608. if (hasParentNo) {
  609. fuYiZhuData.value = []
  610. }
  611. }
  612. const modifyDosingMethod = (val) => {
  613. if (yiZhuData.value.actOrderNo == val.actOrderNo) {
  614. BizException(ExceptionEnum.MESSAGE_ERROR, '无法选择自己');
  615. }
  616. yiZhuData.value.parentNo = val.actOrderNo
  617. yiZhuData.value.parentNoName = val.orderName
  618. yiZhuData.value.orderTime = val.orderTime
  619. yiZhuData.value.startTime = val.startTime
  620. yiZhuData.value.endTime = val.endTime
  621. yiZhuData.value.supplyCode = '044'
  622. yiZhuData.value.supplyCodeName = '副药'
  623. yiZhuData.value.frequCode = val.frequCode
  624. yiZhuData.value.frequCodeName = val.frequCodeName
  625. yiZhuData.value.groupNo = val.groupNo
  626. yiZhuData.value.groupNoName = val.groupNoName
  627. }
  628. const clearDoctorSOrder = () => {
  629. yiZhuData.value.parentNo = null
  630. yiZhuData.value.parentNoName = ''
  631. }
  632. const orderCodeRef = ref()
  633. /**
  634. * 设置医嘱为临时变量,可以新增医嘱,关闭医嘱错误信息的弹窗。
  635. */
  636. const setTheTemporaryVariableMedicalOrder = () => {
  637. qingKong()
  638. yiZhuData.value.actOrderNo = addTempOrderNo
  639. try {
  640. orderCodeRef.value.focus()
  641. } catch {
  642. }
  643. }
  644. const qingKong = (clearOrderNo: boolean = true) => {
  645. yaoPinJiLiangData.value = [];
  646. jiLiangValue.value = 0;
  647. yzInfoPrompt.value = [];
  648. yiZhuDataInit(clearOrderNo);
  649. }
  650. // 判断是否可以编辑
  651. const isEdit = computed(() => {
  652. return (stringIsBlank(yiZhuData.value.actOrderNo) || yiZhuData.value.statusFlag !== '1' || stringIsBlank(props.patientInfo.inpatientNo));
  653. })
  654. /**
  655. * 保存, 录入状态的医嘱
  656. * @returns {Promise<boolean>}
  657. */
  658. const toAddAnOrder = async () => {
  659. if (stringIsBlank(props.patientInfo.inpatientNo)) {
  660. BizException(ExceptionEnum.MESSAGE_ERROR, '请先选择一位患者,后点击此按钮。')
  661. }
  662. if (stringIsBlank(yiZhuData.value.actOrderNo) || yiZhuData.value.actOrderNo === addTempOrderNo) {
  663. BizException(ExceptionEnum.MESSAGE_ERROR, '工作台中,没有正在编辑的医嘱,请在医嘱名称中搜索一条医嘱,后在点击此按钮。')
  664. }
  665. // 不是录入状态的医嘱,直接清空就可以了
  666. if (stringNotBlank(yiZhuData.value.orderCode) && yiZhuData.value.statusFlag !== '1') {
  667. setTheTemporaryVariableMedicalOrder()
  668. return true
  669. }
  670. let param = {
  671. inpatientNo: props.patientInfo.inpatientNo,
  672. admissTimes: props.patientInfo.admissTimes,
  673. actOrderNo: yiZhuData.value.actOrderNo,
  674. groupNo: queryParam.value.groupNo,
  675. data: yiZhuData.value,
  676. }
  677. try {
  678. let res = await enterOrders(param)
  679. if (res && res.error) {
  680. errorMsgFunc.add(res.data)
  681. return false
  682. }
  683. // 数据完全没问题
  684. if (res != null && res.code && res.code === 200) {
  685. let orderNo = yiZhuData.value.actOrderNo
  686. errorMsgFunc.delByOrder(orderNo)
  687. await setOrderDataAndTwinkle(orderNo, res.data)
  688. }
  689. setTheTemporaryVariableMedicalOrder()
  690. } catch (e) {
  691. console.log(e)
  692. }
  693. return true
  694. }
  695. /**
  696. * 点击了确认医嘱
  697. */
  698. const confirmOrdersClick = async () => {
  699. try {
  700. let errorList = []
  701. if (stringIsBlank(huanZheXinXi.value.referPhysician)) {
  702. errorList.push('管床医生为空')
  703. }
  704. if (stringIsBlank(huanZheXinXi.value.consultPhysician)) {
  705. errorList.push('主治医生为空')
  706. }
  707. if (stringIsBlank(huanZheXinXi.value.deptDirector)) {
  708. errorList.push('主任医生为空')
  709. }
  710. if (listNotBlank(errorList)) {
  711. const pat = unref(huanZheXinXi)
  712. setPatientDoctor(pat).then(res => {
  713. // @ts-ignore
  714. huanZheXinXi.value = {...huanZheXinXi.value, ...res}
  715. })
  716. sleep(200).then(() => {
  717. xcMessage.error("按医务部要求:" + listToStr(errorList) + "无法确认医嘱。")
  718. })
  719. return
  720. }
  721. let res = await confirmOrders(props.patientInfo)
  722. if (res !== null && res.error) {
  723. errorMsgFunc.add(res.data)
  724. }
  725. } catch (e) {
  726. }
  727. }
  728. const yzDialogRef = ref(false)
  729. const openTheOrderPopUpWindow = () => {
  730. if (!isEdit.value) {
  731. const specialOrders = ['06286', '06054']
  732. if (yiZhuData.value.statusFlag !== '1') {
  733. return
  734. }
  735. if (specialOrders.includes(yiZhuData.value.orderCode)) {
  736. yzDialogRef.value = true
  737. } else if (yiZhuData.value.kjywFlag === 1) {
  738. yzDialogRef.value = true
  739. }
  740. }
  741. }
  742. /**
  743. * 点击了查看错误信息
  744. * @param orderNo 医嘱号
  745. */
  746. const clickError = (orderNo) => {
  747. let index = XEUtils.findLastIndexOf(yzData.value, (item) => {
  748. return item.actOrderNo === orderNo
  749. })
  750. if (index > -1) {
  751. rowClickFillData(yzData.value[index])
  752. }
  753. }
  754. const fillData = async (data) => {
  755. fuYiZhuClick()
  756. await rowClickFillData(data)
  757. }
  758. // 删除医嘱
  759. const toDeleteAnOrderClick = () => {
  760. if (stringIsBlank(yiZhuData.value.actOrderNo)) {
  761. BizException(ExceptionEnum.MESSAGE_ERROR, '请先选择要删除的医嘱')
  762. }
  763. ElMessageBox.confirm(`确认是否要删除<span style="color: red"> ${yiZhuData.value.orderName} </span>`, '提示', {
  764. type: 'warning',
  765. dangerouslyUseHTMLString: true
  766. }).then(() => {
  767. toDeleteAnOrder(yiZhuData.value.actOrderNo).then(() => {
  768. jsQueryYzData()
  769. qingKong()
  770. })
  771. })
  772. }
  773. const editorMainRef = ref()
  774. const dosePrecision = computed(() => {
  775. return yiZhuData.value.serial === '00' ? 2 : 3
  776. })
  777. const copyOrderNo = ref<{
  778. actOrderNo: number | null,
  779. frequCode: string
  780. deptCode: string
  781. inpatientNo: string
  782. admissTimes: number
  783. }>({
  784. actOrderNo: null,
  785. frequCode: '',
  786. deptCode: '',
  787. inpatientNo: '',
  788. admissTimes: 0
  789. })
  790. const copy = (actOrderNo, frequCode) => {
  791. copyOrderNo.value.actOrderNo = actOrderNo
  792. copyOrderNo.value.frequCode = frequCode
  793. xcMessage.success('复制成功。')
  794. }
  795. const pasteClick = () => {
  796. if (queryParam.value.frequCode === frequCodeEnum.temporary && copyOrderNo.value.frequCode !== 'ONCE') {
  797. copyOrderNo.value.frequCode = 'ONCE'
  798. } else if (queryParam.value.frequCode === frequCodeEnum.longTerm && copyOrderNo.value.frequCode === 'ONCE') {
  799. copyOrderNo.value.frequCode = frequencyConfig
  800. } else if (queryParam.value.frequCode === frequCodeEnum.takeMedicine) {
  801. copyOrderNo.value.frequCode = 'ONCE'
  802. }
  803. copyOrderNo.value.deptCode = props.patientInfo.zkWard
  804. copyOrderNo.value.inpatientNo = props.patientInfo.inpatientNo
  805. copyOrderNo.value.admissTimes = props.patientInfo.admissTimes
  806. copyFuncApi()
  807. }
  808. const copyFuncApi = async () => {
  809. let {list, data} = await copyOrder(copyOrderNo.value)
  810. let temp = {}
  811. XEUtils.arrayEach(list, (item) => {
  812. temp[item] = true
  813. })
  814. yzData.value.push(...data)
  815. yzMitt.emit('scrollEndAndTwinkle', temp)
  816. copyOrderNo.value.actOrderNo = null
  817. }
  818. /**
  819. * 复制粘贴医嘱
  820. * @returns {Promise<void>}
  821. */
  822. const duplicateAndPaste = () => {
  823. if (stringIsBlank(yiZhuData.value.actOrderNo) || yiZhuData.value.actOrderNo === addTempOrderNo) {
  824. BizException(ExceptionEnum.MESSAGE_ERROR, '请先选择医嘱')
  825. }
  826. copyOrderNo.value = {
  827. actOrderNo: yiZhuData.value.actOrderNo,
  828. frequCode: yiZhuData.value.frequCode,
  829. deptCode: props.patientInfo.zkWard,
  830. inpatientNo: props.patientInfo.inpatientNo,
  831. admissTimes: props.patientInfo.admissTimes
  832. }
  833. copyFuncApi()
  834. }
  835. let shortcutKeyRegistration = {
  836. ctrl: {s: toAddAnOrder},
  837. alt: {a: toAddAnOrder, q: () => yzMitt.emit('confirmMedicalAdvice')}
  838. }
  839. const supplyDisabled = computed(() => {
  840. if (yiZhuData.value.orderCode === '06054') {
  841. return false
  842. }
  843. return yiZhuData.value.serial === '00';
  844. })
  845. onMounted(() => {
  846. yzMitt.on('toAddAnOrder', toAddAnOrder)
  847. yzMitt.on('duplicateAndPaste', duplicateAndPaste)
  848. yzMitt.on('openTheOrderPopUpWindow', openTheOrderPopUpWindow)
  849. yzMitt.on('emptyTheWorkbench', qingKong)
  850. yzMitt.on('copy', copy)
  851. yzMitt.on('paste', pasteClick)
  852. yzMitt.on('allowReplication', () => {
  853. return copyOrderNo.value.actOrderNo !== null
  854. })
  855. yzMitt.on('deleteAnOrderByOrderNo', ({actOrderNo, orderName}, clearOrNot = true) => {
  856. if (stringIsBlank(actOrderNo)) {
  857. BizException(ExceptionEnum.MESSAGE_ERROR, '请先选择要删除的医嘱')
  858. }
  859. CyMessageBox.confirm({
  860. message: `确认是否要删除<span style="color: red"> ${orderName} </span>`,
  861. dangerouslyUseHTMLString: true,
  862. type: 'delete',
  863. }).then(() => {
  864. toDeleteAnOrder(actOrderNo).then(() => {
  865. jsQueryYzData()
  866. if (clearOrNot) {
  867. qingKong()
  868. }
  869. errorMsgFunc.delByOrder(actOrderNo)
  870. })
  871. }).catch(() => {
  872. })
  873. })
  874. })
  875. const drugQuanRef = ref()
  876. const drugQuanChange = async (event) => {
  877. await nextTick()
  878. await sleep(200)
  879. yiZhuData.value.drugQuan = parseInt(event.target.value)
  880. }
  881. let keyWatch = null
  882. onDeactivated(() => {
  883. if (keyWatch != null) {
  884. keyWatch()
  885. }
  886. })
  887. onActivated(() => {
  888. keyWatch = watch(() => xcEvent.value, () => {
  889. shortcutTrigger(xcEvent.value, shortcutKeyRegistration)
  890. })
  891. })
  892. defineExpose({
  893. fillData,
  894. toDeleteAnOrderClick,
  895. confirmOrdersClick,
  896. isEdit
  897. })
  898. </script>
  899. <style scoped lang="scss">
  900. .editing_area {
  901. position: relative;
  902. width: max-content;
  903. }
  904. .editor__title {
  905. background-color: #ffdb04;
  906. padding: 5px;
  907. width: 100%;
  908. overflow-x: auto;
  909. }
  910. .yz_editor__disable {
  911. position: absolute;
  912. height: 100%;
  913. width: 100%;
  914. z-index: 89;
  915. border: 1px solid red;
  916. &::before {
  917. position: absolute;
  918. content: '只读';
  919. bottom: 0;
  920. right: 0;
  921. color: red;
  922. }
  923. }
  924. .yz_input__box {
  925. display: flex;
  926. margin-top: 6px;
  927. flex-wrap: wrap;
  928. div {
  929. margin-left: 3px;
  930. }
  931. .div_center__box {
  932. display: flex;
  933. justify-content: center;
  934. align-items: center;
  935. }
  936. .input__style {
  937. width: 125px;
  938. line-height: 22px;
  939. height: 22px;
  940. border: 1px solid
  941. }
  942. }
  943. </style>