AllAdverseEvent.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <template>
  2. <div class="layout_container">
  3. <header class="round-header">
  4. <el-select v-model="queryParam.type" style="width: 100px">
  5. <el-option :value="1" label="护理安全" />
  6. <el-option :value="2" label="医疗安全" />
  7. <el-option :value="0" label="全部" />
  8. </el-select>
  9. <el-select v-model="queryParam.level" style="width: 100px" clearable>
  10. <el-option :value="0" label="Ⅰ级事件" />
  11. <el-option :value="1" label="Ⅱ级事件" />
  12. <el-option :value="2" label="Ⅲ级事件" />
  13. <el-option :value="3" label="IV级事件" />
  14. </el-select>
  15. <el-date-picker
  16. v-model="dateRange"
  17. type="daterange"
  18. range-separator="至"
  19. start-placeholder="开始日期"
  20. end-placeholder="结束日期"
  21. :shortcuts="shortcuts"
  22. style="width: 260px"
  23. ></el-date-picker>
  24. <el-select v-model="queryParam.wardCode" placeholder="请选择科室" clearable style="width: 160px">
  25. <el-option v-for="item in allWards" :key="item.code" :label="item.name" :value="item.code"></el-option>
  26. </el-select>
  27. <el-divider direction="vertical"></el-divider>
  28. <el-button type="primary" icon="Refresh" @click="fetchReports">检索数据</el-button>
  29. <el-button type="primary" icon="Upload" @click="exportExcel">导出Excel</el-button>
  30. </header>
  31. <div class="layout_main layout_el-table">
  32. <el-table :data="reports" stripe highlight-current-row>
  33. <el-table-column prop="occurDatetime" label="发生时间" sortable></el-table-column>
  34. <el-table-column prop="category" label="事件类型"></el-table-column>
  35. <el-table-column prop="submitDatetime" label="提交时间"></el-table-column>
  36. <el-table-column prop="userName" label="提交人" width="80"></el-table-column>
  37. <el-table-column prop="department" label="科室" width="120"></el-table-column>
  38. <el-table-column label="处理" width="60">
  39. <template v-slot="scope">
  40. <span v-html="filterHandled(scope.row.handled)"></span>
  41. </template>
  42. </el-table-column>
  43. <el-table-column prop="deptDealerName" label="处理人" width="80"></el-table-column>
  44. <el-table-column label="打印" width="60">
  45. <template v-slot="scope">
  46. <span v-html="filterPrinted(scope.row.printed)"></span>
  47. </template>
  48. </el-table-column>
  49. <el-table-column label="操作">
  50. <template v-slot="scope">
  51. <el-button type="primary" icon="View" @click="viewReport(scope.row.pid)">查看</el-button>
  52. <el-button type="danger" icon="Close" @click="deleteReport(scope.row.pid)" :disabled="isNotHlb">删除
  53. </el-button>
  54. </template>
  55. </el-table-column>
  56. </el-table>
  57. <el-pagination
  58. @size-change="handleSizeChange"
  59. @current-change="handleCurrentChange"
  60. :current-page="queryParam.currentPage"
  61. :page-sizes="[15, 30, 45, 70, 100]"
  62. :page-size="queryParam.pageSize"
  63. layout="total, sizes, prev, pager, next, jumper"
  64. :total="totalSize"
  65. ></el-pagination>
  66. </div>
  67. </div>
  68. <el-dialog v-model="showViewReport" title="报告详情" fullscreen>
  69. <EventViewer :report="report" :disableHlbDealing="disableHlbDealing"/>
  70. <div style="width: 100%; text-align: right; margin: 50px 0 0 0">
  71. <el-button type="primary" icon="Edit" @click="editCurrentReport">
  72. 修改此报告
  73. </el-button>
  74. <el-button type="primary" icon="Upload" @click="submitHlbDealing">
  75. 提交处理
  76. </el-button>
  77. <el-button type="primary" icon="Printer" @click="toPrintPage">打印</el-button>
  78. <el-button type="danger" icon="Close" @click="showViewReport = false">关闭</el-button>
  79. </div>
  80. </el-dialog>
  81. <el-dialog
  82. v-model="showModifyReport"
  83. title="修改报告"
  84. width="70%"
  85. >
  86. <EventEditor ref="editorRef" :report="report"/>
  87. <div style="width: 100%; text-align: right; margin: 20px 0 10px 0">
  88. <el-button type="info" icon="Close" @click="cancelModify">取消</el-button>
  89. <el-button type="primary" icon="Check" @click="confirmModify">提交</el-button>
  90. </div>
  91. </el-dialog>
  92. <div id="printArea" style="opacity: 0; position: fixed">
  93. <EventPrinter :report="report"/>
  94. </div>
  95. </template>
  96. <script setup>
  97. import {shortcuts} from '@/data/shortcuts'
  98. import {computed, onMounted, reactive, ref} from 'vue'
  99. import {
  100. getAllDepts,
  101. getAllReports,
  102. getReportDetail,
  103. submitNewReport,
  104. updateDeleted,
  105. updateFinalHandled, updatePrinted
  106. } from '@/api/adverse-event'
  107. import EventViewer from "@/views/hospitalization/adverse-event/component/EventViewer.vue";
  108. import {ElMessage, ElMessageBox} from 'element-plus'
  109. import {formatDatetime} from '@/utils/date'
  110. import {downloadExcel} from '@/utils/excel'
  111. import {getLodop, initLodop} from '@/utils/c-lodop'
  112. import {useUserStore} from "@/pinia/user-store";
  113. import {startLoading} from "@/utils/loading";
  114. import EventEditor from "@/views/hospitalization/adverse-event/component/EventEditor.vue";
  115. import EventPrinter from "@/views/hospitalization/adverse-event/component/EventPrinter.vue";
  116. const dateRange = ref(null)
  117. const allWards = ref([])
  118. const editorRef = ref()
  119. const queryParam = reactive({
  120. start: null,
  121. end: null,
  122. type: 1,
  123. level: null,
  124. wardCode: '',
  125. currentPage: 1,
  126. pageSize: 30,
  127. })
  128. const reports = ref([])
  129. const totalSize = ref(0)
  130. const handleSizeChange = (val) => {
  131. queryParam.pageSize = val
  132. fetchReports()
  133. }
  134. const handleCurrentChange = (val) => {
  135. queryParam.currentPage = val
  136. fetchReports()
  137. }
  138. const report = ref({})
  139. const showViewReport = ref(false)
  140. const showModifyReport = ref(false)
  141. const fetchReports = () => {
  142. if (dateRange.value) {
  143. queryParam.start = formatDatetime(dateRange.value[0])
  144. queryParam.end = formatDatetime(dateRange.value[1])
  145. } else {
  146. queryParam.start = null
  147. queryParam.end = null
  148. }
  149. getAllReports(queryParam).then((res) => {
  150. reports.value = res.list
  151. totalSize.value = res.totalSize
  152. })
  153. }
  154. const roles = useUserStore().userInfo.roles
  155. const isNotHlb = computed(() => {
  156. return roles.indexOf(24) === -1 && roles.indexOf(1) === -1 && roles.indexOf(2) === -1
  157. })
  158. const disableHlbDealing = computed(() => {
  159. if (roles.indexOf(24) === -1 && roles.indexOf(1) === -1 && roles.indexOf(2) === -1) {
  160. return true
  161. }
  162. return report.value.finalDealTime !== null
  163. })
  164. const viewReport = (pid) => {
  165. getReportDetail(pid, 'final').then((res) => {
  166. report.value = res
  167. showViewReport.value = true
  168. })
  169. }
  170. const deleteReport = (pid) => {
  171. ElMessageBox.confirm('是否删除此报告?删除后不可恢复,请谨慎选择。', '提示', {
  172. confirmButtonText: '确定删除',
  173. cancelButtonText: '再考虑考虑',
  174. type: 'warning',
  175. }).then(() => {
  176. updateDeleted(pid).then(() => {
  177. ElMessage({
  178. message: '删除成功',
  179. type: 'success',
  180. duration: 2500,
  181. showClose: true,
  182. })
  183. fetchReports()
  184. })
  185. }).catch(() => {
  186. })
  187. }
  188. const cancelModify = () => {
  189. showModifyReport.value = false
  190. }
  191. const confirmModify = () => {
  192. report.value.isModify = true
  193. submitNewReport(report.value).then(() => {
  194. ElMessage({
  195. message: '修改成功',
  196. type: 'success',
  197. duration: 2500,
  198. showClose: true,
  199. })
  200. })
  201. showModifyReport.value = false
  202. }
  203. function editCurrentReport() {
  204. showModifyReport.value = true
  205. nextTick(() => {
  206. editorRef.value.initCascader(report.value.category)
  207. })
  208. }
  209. const submitHlbDealing = () => {
  210. if (report.value.finalDealing === '未处理') {
  211. ElMessage({
  212. message: '请填写处理内容!',
  213. type: 'warning',
  214. duration: 2500,
  215. showClose: true,
  216. })
  217. return
  218. }
  219. const param = {
  220. pid: report.value.pid,
  221. dealing: report.value.finalDealing,
  222. eventLevel: report.value.eventLevel,
  223. }
  224. updateFinalHandled(param).then((res) => {
  225. report.value = res
  226. ElMessage({
  227. message: '处理成功',
  228. type: 'success',
  229. duration: 2500,
  230. showClose: true,
  231. })
  232. })
  233. }
  234. const toPrintPage = () => {
  235. let LODOP = getLodop()
  236. const prntStyle = `<style>table, tr, th, td {border: 1px solid #c1dbfa;border-collapse: collapse;text-align: left;padding: 0 10px;vertical-align: center;word-break: break-all;font-size: 13px;}</style>`
  237. const prntContent = document.getElementById('printArea').innerHTML
  238. let pagePrint = prntStyle + '<body>' + prntContent + '</body>'
  239. LODOP.PRINT_INIT('normaladverseevent')
  240. LODOP.SET_PRINT_PAGESIZE(1, '210mm', '297mm', '')
  241. LODOP.SET_PRINT_MODE('FULL_HEIGHT_FOR_OVERFLOW', true) // 整宽不变形
  242. LODOP.SET_PRINT_MODE('FULL_WIDTH_FOR_OVERFLOW', true) // 整宽不变形
  243. LODOP.ADD_PRINT_HTM('1mm', '1mm', '100%', '100%', pagePrint)
  244. LODOP.SET_PRINT_STYLE('ItemType', 3)
  245. LODOP.PREVIEW()
  246. updatePrinted(report.value.pid)
  247. }
  248. const exportExcel = () => {
  249. startLoading()
  250. const data = {
  251. param: {
  252. start: null,
  253. end: null,
  254. wardCode: queryParam.wardCode,
  255. },
  256. url: '/adverseEvent/exportExcel',
  257. fileName: '不良事件统计.xlsx',
  258. }
  259. if (dateRange.value) {
  260. data.param.start = formatDatetime(dateRange.value[0])
  261. data.param.end = formatDatetime(dateRange.value[1])
  262. }
  263. setTimeout(() => {
  264. downloadExcel(data)
  265. }, 100)
  266. }
  267. onMounted(() => {
  268. initLodop()
  269. getAllDepts().then((res) => {
  270. allWards.value = res
  271. fetchReports()
  272. })
  273. })
  274. function filterHandled(val) {
  275. return val === 1 ? '<span style="color:green">已处理</span>' : '<span style="color:red">未处理</span>'
  276. }
  277. function filterPrinted(val) {
  278. return val === 1 ? '<span style="color:green">已打印</span>' : '<span style="color:red">未打印</span>'
  279. }
  280. </script>