InspectionReportIndex.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <template>
  2. <div class="layout_container">
  3. <header class="round-header">
  4. <el-select
  5. v-model="reportCategory"
  6. @change="onCategoryChange"
  7. style="width: 100px"
  8. >
  9. <el-option-group
  10. v-for="group in reportTypes"
  11. :key="group.label"
  12. :label="group.label"
  13. >
  14. <el-option
  15. v-for="item in group.options"
  16. :key="item.value"
  17. :label="item.label"
  18. :value="item.value"
  19. ></el-option>
  20. </el-option-group>
  21. </el-select>
  22. <el-select v-model="patType" style="width: 80px">
  23. <el-option
  24. v-for="item in patientTypes"
  25. :key="item.code"
  26. :value="item.code"
  27. :label="item.name"
  28. ></el-option>
  29. </el-select>
  30. <el-input
  31. v-model="patNo"
  32. clearable
  33. :placeholder="placeHolder"
  34. style="width: 120px"
  35. ></el-input>
  36. <el-date-picker
  37. v-model="datePeriod"
  38. type="daterange"
  39. range-separator="至"
  40. start-placeholder="开始日期"
  41. end-placeholder="结束日期"
  42. :shortcuts="shortcuts"
  43. style="width: 260px"
  44. ></el-date-picker>
  45. <el-button
  46. type="primary"
  47. icon="Search"
  48. @click="queryIndex"
  49. :disabled="inPrintProcess"
  50. style="margin-left: 20px"
  51. >
  52. 查询
  53. </el-button>
  54. <el-button
  55. type="primary"
  56. icon="Printer"
  57. :disabled="inPrintProcess"
  58. @click="beforePrint"
  59. >
  60. 打印
  61. </el-button>
  62. </header>
  63. <div class="layout_main layout_container layout-horizontal">
  64. <aside class="layout_el-table">
  65. <el-table
  66. ref="tableRef"
  67. :data="inspectionIndex"
  68. stripe
  69. highlight-current-row
  70. @row-click="beforeQueryDetail"
  71. >
  72. <el-table-column
  73. v-if="reportCategory === 'JY'"
  74. type="selection"
  75. width="30"
  76. ></el-table-column>
  77. <el-table-column
  78. prop="trscDate"
  79. label="报告时间"
  80. width="130"
  81. ></el-table-column>
  82. <el-table-column
  83. prop="examPurpose"
  84. label="检验名称"
  85. width="170"
  86. ></el-table-column>
  87. <el-table-column
  88. v-if="reportCategory === 'JY'"
  89. prop="reportType"
  90. label="报告类别"
  91. width="70"
  92. ></el-table-column>
  93. </el-table>
  94. </aside>
  95. <div
  96. id="reportDetail"
  97. class="layout_main"
  98. style="
  99. position: relative;
  100. width: 90%;
  101. min-height: 96%;
  102. padding: 0 30px;
  103. background-color: white;
  104. overflow-y: auto;
  105. "
  106. >
  107. <div v-if="reportCategory === 'JY'" style="height: 98%">
  108. <div
  109. v-for="(jyData, index) in jyDataList"
  110. :id="'jyData' + index"
  111. style="height: 100%"
  112. >
  113. <JyResult :data="jyData" />
  114. </div>
  115. </div>
  116. <div v-if="reportCategory === 'JC'">
  117. <div v-if="jcbg.reportUrl">
  118. <el-image :src="jcbg.reportUrl"></el-image>
  119. </div>
  120. <div v-else>
  121. <h3
  122. style="
  123. width: 100%;
  124. text-align: center;
  125. font-weight: bold;
  126. height: 30px;
  127. line-height: 30px;
  128. "
  129. >
  130. {{ env.VITE_HOSPITAL_NAME }}检查报告单
  131. </h3>
  132. <div style="display: flex">
  133. <div style="width: 32%">姓名:{{ jcbg.patientName }}</div>
  134. <div style="width: 32%">
  135. {{ ptntType }}:
  136. {{ jcbg.patNo }}
  137. </div>
  138. <div style="width: 32%">
  139. <div>申请项目:{{ jcbg.examPurpose.substring(0, 13) }}</div>
  140. <div>{{ jcbg.examPurpose.substring(13) }}</div>
  141. </div>
  142. </div>
  143. <div style="display: flex">
  144. <div style="width: 32%">医生姓名:{{ jcbg.doctorName }}</div>
  145. <div style="width: 32%">检查时间:{{ jcbg.reportTime }}</div>
  146. <div style="width: 32%">报告时间:{{ jcbg.trscDate }}</div>
  147. </div>
  148. <el-divider content-position="left">检查所见</el-divider>
  149. <div v-html="jcbg.examinationSee"></div>
  150. <el-divider content-position="left">检查结论</el-divider>
  151. <div v-html="jcbg.examinationreSult"></div>
  152. <div v-if="jcbg.reportUrl" style="margin-top: 30px">
  153. <el-button type="primary" size="large" link @click="showJcImage"
  154. >查看图像</el-button
  155. >
  156. </div>
  157. </div>
  158. </div>
  159. <div v-if="reportCategory === 'BL' || reportCategory === 'XD'">
  160. <el-image :src="blxdUrl" style="width: 100%" fit="contain" />
  161. </div>
  162. </div>
  163. </div>
  164. </div>
  165. </template>
  166. <script setup>
  167. import { computed, onActivated, ref, onMounted } from "vue";
  168. import { shortcuts } from "@/data/shortcuts";
  169. import {
  170. checkExamDetail,
  171. checkIndexByCategory,
  172. checkTestDetail,
  173. } from "@/api/inspections";
  174. import router from "@/router";
  175. import { ElMessage } from "element-plus";
  176. import { initLodop, getLodop } from "@/utils/c-lodop";
  177. import { getDateRangeFormatDate } from "@/utils/date";
  178. import Sleep from "@/utils/sleep";
  179. import JyResult from "@/views/examination/component/JyResult.vue";
  180. import env from "../../utils/setting.js";
  181. const props = defineProps({
  182. patNo: {
  183. type: String,
  184. default: null,
  185. },
  186. start: {
  187. type: String,
  188. },
  189. end: {
  190. type: String,
  191. },
  192. });
  193. const tableRef = ref(null);
  194. const patType = ref("InPatient");
  195. const reportCategory = ref("JY");
  196. const patNo = ref(null);
  197. const datePeriod = ref([]);
  198. const placeHolder = computed(() => {
  199. return "请输入" + ptntType.value;
  200. });
  201. const ptntType = computed(() => {
  202. if (patType.value === "InPatient") {
  203. return "住院号";
  204. } else if (patType.value === "OutPatient") {
  205. return "门诊号";
  206. }
  207. return "";
  208. });
  209. const jyDataList = ref([]);
  210. const inspectionIndex = ref([]);
  211. function onCategoryChange(val) {
  212. inspectionIndex.value = [];
  213. }
  214. const queryIndex = () => {
  215. if (!patNo.value) {
  216. ElMessage({
  217. message: "请输入患者" + ptntType.value + "。",
  218. type: "warning",
  219. duration: 2000,
  220. showClose: true,
  221. });
  222. return;
  223. }
  224. if (!datePeriod.value || datePeriod.value.length < 2) {
  225. ElMessage({
  226. message: "请选择日期范围。",
  227. type: "warning",
  228. duration: 2000,
  229. showClose: true,
  230. });
  231. return;
  232. }
  233. let { startTime, endTime } = getDateRangeFormatDate(datePeriod.value);
  234. const params = {
  235. patType: patType.value,
  236. reportCategory: reportCategory.value,
  237. patNo: patNo.value,
  238. reqStartTime: startTime,
  239. reqEndTime: endTime,
  240. };
  241. checkIndexByCategory(params).then(res => {
  242. inspectionIndex.value = res;
  243. });
  244. };
  245. const blxdUrl = ref("");
  246. function beforeQueryDetail(row) {
  247. if (reportCategory.value === "JY") {
  248. queryJyDetail(row, true);
  249. } else if (reportCategory.value === "JC") {
  250. queryJcDetail(row);
  251. } else {
  252. blxdUrl.value = row.reportUrl;
  253. }
  254. }
  255. const jcbg = ref({
  256. examPurpose: "",
  257. });
  258. function queryJcDetail(row) {
  259. checkTestDetail({
  260. reportId: row.patientUid,
  261. }).then(res => {
  262. jcbg.value = res;
  263. });
  264. }
  265. const queryJyDetail = (row, clear) => {
  266. if (clear) {
  267. jyDataList.value = [];
  268. }
  269. return new Promise((resolve, reject) => {
  270. checkExamDetail({
  271. reportId: row.reportId,
  272. }).then(res => {
  273. const bacterias = [];
  274. if (res.bacterias && res.bacterias.length > 0) {
  275. res.bacterias.forEach(bac => {
  276. const bacSize = bac.antiList ? Math.ceil(bac.antiList.length / 2) : 1;
  277. const tempBacResult = {
  278. halfBacSize: bacSize,
  279. germName: bac.bacNameCn,
  280. antiList: bac.antiList,
  281. type: bac.itmName,
  282. };
  283. bacterias.push(tempBacResult);
  284. });
  285. }
  286. const tempJyData = {
  287. inspectionDetail: {
  288. order: res.order,
  289. items: res.items,
  290. },
  291. bacterias: bacterias,
  292. halfSize: Math.ceil(res.items.length / 2),
  293. ptntType: ptntType.value,
  294. reportType: row.reportType,
  295. };
  296. jyDataList.value.push(tempJyData);
  297. resolve();
  298. });
  299. });
  300. };
  301. const inPrintProcess = ref(false);
  302. const beforePrint = async () => {
  303. inPrintProcess.value = true;
  304. const selection = tableRef.value.getSelectionRows();
  305. if (selection && selection.length > 0) {
  306. jyDataList.value = [];
  307. for (let i = 0; i < selection.length; i++) {
  308. await queryJyDetail(selection[i], false);
  309. await Sleep(1000);
  310. }
  311. await doPrint();
  312. inPrintProcess.value = false;
  313. } else {
  314. await doPrint();
  315. inPrintProcess.value = false;
  316. }
  317. };
  318. onMounted(() => {
  319. initLodop();
  320. const vueName = router.currentRoute.value.name;
  321. if (vueName === "inspectionReportV2") {
  322. checkPathParams();
  323. } else {
  324. checkPropsParams();
  325. }
  326. });
  327. onActivated(() => {
  328. checkPathParams();
  329. });
  330. function checkPropsParams() {
  331. if (props.patNo && props.start && props.end) {
  332. patType.value = "InPatient";
  333. patNo.value = props.patNo;
  334. datePeriod.value[0] = props.start;
  335. datePeriod.value[1] = props.end;
  336. queryIndex();
  337. }
  338. }
  339. function checkPathParams() {
  340. const params = router.currentRoute.value.params;
  341. if (params.patNo && params.start && params.end) {
  342. patType.value =
  343. params.patNo.indexOf("-") === -1 ? "InPatient" : "OutPatient";
  344. patNo.value = params.patNo;
  345. datePeriod.value[0] = params.start;
  346. datePeriod.value[1] = params.end;
  347. queryIndex();
  348. }
  349. }
  350. function doPrint() {
  351. return new Promise(resolve => {
  352. const LODOP = getLodop();
  353. LODOP.PRINT_INIT("jyjc");
  354. LODOP.SET_PRINT_MODE("FULL_WIDTH_FOR_OVERFLOW", true); //宽度溢出缩放
  355. if (reportCategory.value === "JY") {
  356. LODOP.SET_PRINT_PAGESIZE(2, 0, 0, "A5");
  357. for (let i = 0; i < jyDataList.value.length; i++) {
  358. const printarea = document.getElementById("jyData" + i).innerHTML;
  359. LODOP.ADD_PRINT_HTM(0, 0, "208mm", "146mm", printarea);
  360. LODOP.NEWPAGE();
  361. }
  362. } else {
  363. const ori = reportCategory.value === "XD" ? 2 : 1;
  364. LODOP.SET_PRINT_PAGESIZE(ori, "210mm", "267mm", "CreateCustomPage");
  365. const imgUrl =
  366. reportCategory.value === "JC" ? jcbg.value.reportUrl : blxdUrl.value;
  367. LODOP.ADD_PRINT_IMAGE(0, 0, "210mm", "267mm", imgUrl);
  368. LODOP.SET_PRINT_STYLEA(0, "Horient", 3);
  369. LODOP.SET_PRINT_STYLEA(0, "Vorient", 3);
  370. LODOP.SET_PRINT_STYLEA(0, "Stretch", 1);
  371. }
  372. LODOP.PREVIEW();
  373. resolve();
  374. });
  375. }
  376. const patientTypes = [
  377. { code: "InPatient", name: "住院号" },
  378. { code: "OutPatient", name: "门诊号" },
  379. ];
  380. const reportTypes = [
  381. {
  382. label: "检验",
  383. options: [
  384. {
  385. label: "检验报告",
  386. value: "JY",
  387. },
  388. ],
  389. },
  390. {
  391. label: "检查",
  392. options: [
  393. {
  394. label: "检查报告",
  395. value: "JC",
  396. },
  397. {
  398. label: "病理报告",
  399. value: "BL",
  400. },
  401. {
  402. label: "心电报告",
  403. value: "XD",
  404. },
  405. ],
  406. },
  407. ];
  408. </script>