FrontSheetQuality.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <template>
  2. <CyFlex>
  3. <template #header>
  4. <div style="padding: 6px 4px; background-color: white; border-radius: 4px">
  5. <CyDateRange/>
  6. <el-select
  7. v-model="auditInquiryRequest.state"
  8. @change="handleStateChanged"
  9. style="width: 90px">
  10. <el-option label="未质控" value="INITIAL"></el-option>
  11. <el-option label="已通过" value="APPROVED"></el-option>
  12. <el-option label="已驳回" value="REJECTED"></el-option>
  13. </el-select>
  14. <el-input
  15. v-model="auditInquiryRequest.patNo"
  16. clearable
  17. placeholder="住院号"
  18. style="width: 110px"
  19. @keyup.enter="querySearch" />
  20. <el-divider direction="vertical"></el-divider>
  21. <el-button icon="Search" type="primary" @click="querySearch">检索</el-button>
  22. <el-button icon="Document" type="primary" @click="openEmr">电子病历</el-button>
  23. <span v-if="auditInquiryRequest.state === 'INITIAL'" style="margin: 0 12px">
  24. <el-button icon="DataLine" type="primary" @click="basicControl">基础质控</el-button>
  25. <el-button icon="Check" type="success" @click="approveAudit">审核通过</el-button>
  26. <el-button icon="Close" type="danger" @click="rejectAudit">审核不通过</el-button>
  27. </span>
  28. <el-button icon="Clock" type="info" @click="viewAuditHistory">审核记录</el-button>
  29. </div>
  30. </template>
  31. <CyFlex tab-position="vertical">
  32. <template #header>
  33. <div style="margin-top: 4px;height: calc(100% - 4px)">
  34. <CyVxeTable>
  35. <VxeColumn title="姓名" width="80">
  36. <template #default="{row}">
  37. <img :src="row.patGender === 'MALE' ? maleIcon : femaleIcon" class="sex-icon"/>
  38. {{ row.patName }}
  39. </template>
  40. </VxeColumn>
  41. <VxeColumn title="住院号" width="90">
  42. <template #default="{row}">
  43. <span style="font-weight: bold; color: black">{{ row.patNo }}</span
  44. >-{{ row.times }}
  45. </template>
  46. </VxeColumn>
  47. <VxeColumn title="医生" field="doctorName" width="70"></VxeColumn>
  48. <VxeColumn title="申请时间" field="applicationTime" width="135"></VxeColumn>
  49. </CyVxeTable>
  50. </div>
  51. </template>
  52. <template #content>
  53. <div style="margin-top: 4px;height: calc(100% - 4px)">
  54. <FullPage :dics="dics" :patient="sheet"/>
  55. </div>
  56. </template>
  57. </CyFlex>
  58. <el-drawer v-model="showMessageDrawer" title="首页基础质控结果">
  59. <div class="page-inner">
  60. <div v-if="forceVerifies.length === 0 && adviceVerifies.length === 0" class="no-verify-message">暂无校验内容
  61. </div>
  62. <div v-show="forceVerifies.length > 0" style="padding: 8px 0 4px 0; font-weight: bold">
  63. 以下条目为强制要求,请完善。
  64. </div>
  65. <div v-for="(item, index) in forceVerifies" :key="index" :style="messageColor(index)" class="message-item"
  66. @click="currentMessageIndex = index">
  67. {{ index + 1 }}、{{ item.name }}
  68. </div>
  69. <div v-show="adviceVerifies.length > 0" style="padding: 8px 0 4px 0; font-weight: bold">
  70. 以下条目为建议执行,不做强制要求。
  71. </div>
  72. <div v-for="(item, index) in adviceVerifies" :key="index"
  73. style="padding: 6px; margin-bottom: 6px; border-radius: 4px; background: #eea7a752; color: #ff2b2b">
  74. {{ index + 1 }}、{{ item.name }}
  75. </div>
  76. </div>
  77. </el-drawer>
  78. <div class="btn_right-side" @click="showMessageDrawer = !showMessageDrawer">首页基础质控结果</div>
  79. </CyFlex>
  80. </template>
  81. <script setup lang="ts">
  82. import {autopsies, haveOrNot, yesOrNo} from './common'
  83. import {onMounted, reactive} from 'vue'
  84. import store from '@/store'
  85. import {operations} from '@/data'
  86. import {
  87. executeAudit,
  88. executePrintVerify,
  89. fetchQualityVerifications,
  90. getAllDictionary,
  91. getSheetInfo,
  92. } from '@/api/case-front-sheet'
  93. import maleIcon from '@/assets/male-icon.png'
  94. import femaleIcon from '@/assets/female-icon.png'
  95. import FullPage from "@/components/inpatient/frontsheet-printpage/FullPage.vue";
  96. import useDateRange from "@/utils/cy-use/useDateRange";
  97. import useVxeTable from "@/utils/cy-use/useVxeTable";
  98. import CyFlex from "@/components/cy/flex/src/CyFlex.vue";
  99. import {xcMessage} from "@/utils/xiaochan-element-plus";
  100. import {CyMessageBox} from "@/components/cy/message-box";
  101. import RejectAudit from "@/components/inpatient/frontsheet-printpage/RejectAudit.vue";
  102. import AuditHistory from "@/components/inpatient/frontsheet-printpage/AuditHistory.vue";
  103. import useDialogToJs from "@/components/js-dialog-comp/useDialogToJs";
  104. import {
  105. emrStateEnum,
  106. getEmrUrl
  107. } from "@/views/hospitalization/zhu-yuan-yi-sheng/electronic-medical-record/emr-editor/emr-init";
  108. import {magicApi} from "@/utils/database/magic-api-request";
  109. const windowSize = store.state.app.windowSize
  110. const userName = store.state.user.info.name
  111. const tableHeight = windowSize.h
  112. const {CyDateRange, dateRange} = useDateRange({shortcutsIndex: 1, clearable: false})
  113. const auditInquiryRequest = reactive({
  114. state: 'INITIAL',
  115. patNo: ''
  116. })
  117. const currentRow = ref({})
  118. const {CyVxeTable, querySearch} = useVxeTable<{
  119. patNo: string,
  120. times: number
  121. }>({
  122. keyField: 'id',
  123. mountedQuery: true,
  124. remoteSearch: () => fetchQualityVerifications({
  125. start: dateRange.value.start,
  126. end: dateRange.value.end,
  127. state: auditInquiryRequest.state,
  128. patNo: auditInquiryRequest.patNo
  129. }),
  130. tableProps: {
  131. onCellClick: ({row}) => {
  132. currentRow.value = row
  133. fetchSheetInfo(row.patNo, row.times)
  134. }
  135. }
  136. })
  137. const sheet = ref(initSheet())
  138. const dics = ref({})
  139. function handleStateChanged() {
  140. querySearch()
  141. sheet.value = initSheet()
  142. }
  143. function initSheet() {
  144. return {
  145. disdiagList: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}],
  146. surgeryList: [{}, {}, {}, {}, {}],
  147. }
  148. }
  149. const fetchSheetInfo = (patNo, times) => {
  150. if (patNo !== sheet.value.bah || times !== sheet.value.admissTimes) {
  151. forceVerifies.value = []
  152. adviceVerifies.value = []
  153. }
  154. getSheetInfo({
  155. bah: patNo,
  156. times: times,
  157. inOutFlag: 2
  158. }).then((res) => {
  159. sheet.value = res
  160. })
  161. }
  162. const nullPatient = () => {
  163. if (!sheet.value.bah) {
  164. xcMessage.warning('请先选择患者!')
  165. return true
  166. }
  167. return false
  168. }
  169. function openEmr() {
  170. if (nullPatient()) return
  171. magicApi({
  172. url: '/intergration/patientInfo/getActCount',
  173. method: 'get',
  174. params: { patNo: sheet.value.bah, times: sheet.value.admissTimes}
  175. }).then(res => {
  176. const emrState = res.count === 0 ? emrStateEnum.出院只读 : emrStateEnum.在院只读
  177. window.open(getEmrUrl(sheet.value.bah, sheet.value.admissTimes, emrState), '_blank')
  178. })
  179. }
  180. const showMessageDrawer = ref(false)
  181. const basicControl = () => {
  182. if (nullPatient()) return
  183. executePrintVerify({
  184. sheet: sheet.value,
  185. }).then(() => {
  186. xcMessage.success('基础质控通过。')
  187. }).catch((e) => {
  188. forceVerifies.value = e.data.force
  189. adviceVerifies.value = e.data.advice
  190. showMessageDrawer.value = true
  191. })
  192. }
  193. const forceVerifies = ref([])
  194. const adviceVerifies = ref([])
  195. const currentMessageIndex = ref(null)
  196. const messageColor = (id) => {
  197. return currentMessageIndex.value === id ?
  198. {
  199. background: '#ff2b2b',
  200. color: 'white',
  201. } :
  202. {
  203. background: '#eea7a752',
  204. color: '#ff2b2b',
  205. };
  206. }
  207. function approveAudit() {
  208. if (nullPatient()) {
  209. return
  210. }
  211. CyMessageBox.confirm({
  212. title: '提示',
  213. message: '确定审核通过吗?',
  214. type: 'warning'
  215. }).then(() => {
  216. currentRow.value.auditState = 'APPROVED'
  217. currentRow.value.auditRemark = '审核通过'
  218. currentRow.value.sheet = sheet.value
  219. executeAudit(currentRow.value).then((res) => {
  220. xcMessage.success(res)
  221. querySearch()
  222. })
  223. }).catch(() => {});
  224. }
  225. function rejectAudit() {
  226. if (nullPatient()) {
  227. return
  228. }
  229. useDialogToJs(RejectAudit, { verification: currentRow.value }).then((res) => {
  230. xcMessage.success(res)
  231. querySearch()
  232. })
  233. }
  234. function viewAuditHistory() {
  235. useDialogToJs(AuditHistory, { patinfo: currentRow.value })
  236. }
  237. onMounted(() => {
  238. getAllDictionary().then((res) => {
  239. res.getOperations = operations
  240. res.getYesOrNo = yesOrNo
  241. res.getHaveOrNot = haveOrNot
  242. res.getAutopsies = autopsies
  243. dics.value = res
  244. })
  245. })
  246. </script>
  247. <style scoped>
  248. :deep(.el-drawer__header) {
  249. margin-bottom: 8px;
  250. }
  251. .page-inner {
  252. padding: 0 20px 10px 26px;
  253. border-radius: 12px;
  254. text-align: justify;
  255. }
  256. .message-item {
  257. padding: 6px;
  258. margin-bottom: 6px;
  259. border-radius: 4px;
  260. }
  261. .message-item:hover {
  262. cursor: pointer;
  263. }
  264. .btn_right-side {
  265. display: flex;
  266. align-items: center;
  267. text-align: center;
  268. color: white;
  269. border-radius: 4px;
  270. width: 20px;
  271. height: 135px;
  272. position: fixed;
  273. background: rgb(238, 98, 5);
  274. top: 260px;
  275. right: 10px;
  276. cursor: pointer;
  277. }
  278. .no-verify-message {
  279. width: 100%;
  280. text-align: center;
  281. margin-top: 50px;
  282. font-size: 18px;
  283. color: gray;
  284. }
  285. </style>