TransferInOfExpenses.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. <template>
  2. <div class="layout_container">
  3. <DefaultTemplate>
  4. <el-descriptions border title="基本信息">
  5. <el-descriptions-item>
  6. <template #label>
  7. <i class="el-icon-user"></i>
  8. 患者姓名
  9. </template>
  10. {{ huanZheXinXi.name }}
  11. </el-descriptions-item>
  12. <el-descriptions-item>
  13. <template #label>
  14. <i class="el-icon-user"></i>
  15. 住院次数
  16. </template>
  17. {{ huanZheXinXi.admissTimes }}
  18. </el-descriptions-item>
  19. <el-descriptions-item>
  20. <template #label>
  21. <i class="el-icon-user-solid"></i>
  22. 性别
  23. </template>
  24. {{ cptSex(huanZheXinXi.sex) }}
  25. </el-descriptions-item>
  26. <el-descriptions-item>
  27. <template #label>
  28. <i class="el-icon-house"></i>
  29. 床号
  30. </template>
  31. {{ huanZheXinXi.bedNo }}
  32. </el-descriptions-item>
  33. <el-descriptions-item>
  34. <template #label>
  35. <i class="el-icon-s-home"></i>
  36. 病房
  37. </template>
  38. {{ huanZheXinXi.wardName }}
  39. </el-descriptions-item>
  40. <el-descriptions-item>
  41. <template #label>
  42. <i class="el-icon-date"></i>
  43. 入院日期
  44. </template>
  45. {{ huanZheXinXi.admissDate }}
  46. </el-descriptions-item>
  47. <el-descriptions-item>
  48. <template #label>
  49. <i class="el-icon-tickets"></i>
  50. 身份
  51. </template>
  52. {{ huanZheXinXi.responceTypeName }}
  53. </el-descriptions-item>
  54. <el-descriptions-item>
  55. <template #label>
  56. <i class="el-icon-coin"></i>
  57. 总费用
  58. </template>
  59. {{ huanZheXinXi.totalCharge }}
  60. </el-descriptions-item>
  61. <el-descriptions-item>
  62. <template #label>
  63. <i class="el-icon-coin"></i>
  64. 余额
  65. </template>
  66. <span style="color: red">{{ huanZheXinXi.balance }}</span>
  67. </el-descriptions-item>
  68. </el-descriptions>
  69. </DefaultTemplate>
  70. <ZyFeeTemplate>
  71. <el-tag> 住院收费项目:合计【{{ zySum }}】</el-tag>
  72. <el-table :data="zyXinXiList" height="100%" stripe>
  73. <el-table-column label="项目名称" prop="itemName"></el-table-column>
  74. <el-table-column label="收费编码" prop="chargeCodeMx"></el-table-column>
  75. <el-table-column label="数量" prop="chargeQuantity"></el-table-column>
  76. <el-table-column label="单价" prop="unitPrice"></el-table-column>
  77. <el-table-column label="金额" prop="chargeFee"></el-table-column>
  78. </el-table>
  79. </ZyFeeTemplate>
  80. <print-outpatient-dzfp ref="printQrCodeRef" />
  81. <el-dialog
  82. v-model="electronicPrescription.dialog"
  83. title="打印电子处方"
  84. destroy-on-close
  85. >
  86. <div style="text-align: center">
  87. <div>
  88. <img
  89. id="dzfpQrCode"
  90. :src="`data:image/png;base64,${electronicPrescription.qrCode}`"
  91. />
  92. <div></div>
  93. </div>
  94. </div>
  95. <template #footer>
  96. <el-button v-print="printObj" type="primary" size="default"
  97. >打印
  98. </el-button>
  99. </template>
  100. </el-dialog>
  101. <el-dialog v-model="saveStore.dialog" title="保存" destroy-on-close>
  102. <div style="color: red">收费日期: {{ huanZheXinXi.chargeDate }}</div>
  103. <div v-html="saveStore.message" style="color: red" />
  104. <PatientInfo />
  105. <div
  106. style="height: 400px; display: flex; flex-direction: column"
  107. class="layout_el-table"
  108. >
  109. <ZyTale />
  110. </div>
  111. <template #footer>
  112. <el-button v-el-btn="saveStore.func" type="primary" size="default"
  113. >保存
  114. </el-button>
  115. </template>
  116. </el-dialog>
  117. <header>
  118. 住院号:
  119. <el-input
  120. v-model="inpatientNo"
  121. clearable
  122. placeholder="在此输入住院号"
  123. prefix-icon="Search"
  124. size="small"
  125. style="width: 150px"
  126. @blur="inpatientNo = $event.target.value.trim()"
  127. @keyup.enter="queryClick"
  128. >
  129. </el-input>
  130. <el-button style="margin-left: 10px" type="primary" @click="queryClick"
  131. >患者
  132. </el-button>
  133. <el-divider direction="vertical"></el-divider>
  134. 机制号:
  135. <el-input
  136. v-model.number="serialNo"
  137. clearable
  138. onkeyup="this.value=this.value.replace(/\D/g,'') "
  139. placeholder="在此输入机制号"
  140. prefix-icon="Search"
  141. size="small"
  142. style="width: 150px"
  143. @keyup.enter="querySerialNo"
  144. >
  145. </el-input>
  146. <el-button style="margin-left: 10px" type="primary" @click="querySerialNo"
  147. >机制
  148. </el-button>
  149. <el-button @click="handleQueryQrCode"> 电子发票</el-button>
  150. <el-button
  151. style="margin-left: 10px"
  152. type="warning"
  153. @click="huanZheFeiYongDrawer = true"
  154. >患者费用
  155. </el-button>
  156. <el-button style="margin-left: 10px" type="success" @click="baoCunClick"
  157. >保存并冲红
  158. </el-button>
  159. <el-button @click="handleOnlyChargeRed"> 仅充红</el-button>
  160. </header>
  161. <div>
  162. <PatientInfo />
  163. </div>
  164. <div>
  165. 收费日期:
  166. <el-date-picker
  167. v-model="chargeDate"
  168. type="datetime"
  169. style="width: 165px"
  170. />
  171. 执行科室:
  172. <SystemDeptSelect
  173. clearable
  174. style="width: 120px"
  175. v-model="huanZheXinXi.execUnit"
  176. />
  177. </div>
  178. <div class="layout_main layout_container layout-horizontal">
  179. <div class="layout_flex_1-x layout_el-table">
  180. <el-tag> 门诊发票信息: 合计 【{{ mzSum }}】</el-tag>
  181. <el-table
  182. ref="multipleTable"
  183. :data="mzXinXiList"
  184. highlight-current-row
  185. @selection-change="mzSelectChecked"
  186. >
  187. <el-table-column :label="`门诊发票信息: 合计 【${mzSum}】`">
  188. <el-table-column label="项目名称" prop="itemName"></el-table-column>
  189. <el-table-column
  190. label="收费编码"
  191. prop="chargeCodeMx"
  192. ></el-table-column>
  193. <el-table-column
  194. label="数量"
  195. prop="chargeQuantity"
  196. ></el-table-column>
  197. <el-table-column label="单价" prop="unitPrice"></el-table-column>
  198. <el-table-column label="金额" prop="chargeFee"></el-table-column>
  199. <el-table-column
  200. label="选择"
  201. type="selection"
  202. width="60"
  203. ></el-table-column>
  204. </el-table-column>
  205. </el-table>
  206. </div>
  207. <div style="display: flex; align-items: center; margin: 0 20px">
  208. <el-button icon="Right" type="primary"></el-button>
  209. </div>
  210. <div class="layout_flex_1-x layout_el-table">
  211. <ZyTale />
  212. </div>
  213. </div>
  214. </div>
  215. <el-drawer
  216. v-model="huanZheFeiYongDrawer"
  217. size="50%"
  218. title="查看患者通过急门诊转入的费用"
  219. destroy-on-close
  220. >
  221. <div class="layout_display_flex_y">
  222. <div>
  223. <el-input
  224. v-model="inpatientNo"
  225. clearable
  226. placeholder="住院号"
  227. style="width: 200px"
  228. @blur="inpatientNo = $event.target.value.trim()"
  229. @keyup.enter="getZyJiMenZhenZhuangRuFeiYongClick"
  230. >
  231. <template #prepend>住院号</template>
  232. </el-input>
  233. <el-divider direction="vertical"></el-divider>
  234. 项目名称:
  235. <el-select
  236. style="width: 120px"
  237. v-model="chargeCodeMX"
  238. :remote-method="remoteMethodEntryName"
  239. clearable
  240. filterable
  241. placeholder="根据拼音首字母查找"
  242. remote
  243. >
  244. <el-option
  245. v-for="item in entryNameList"
  246. :key="item.code"
  247. :label="item.name"
  248. :value="item.code"
  249. >
  250. <span style="color: #8492a6; font-size: 12px">{{ item.code }}</span>
  251. <el-divider direction="vertical"></el-divider>
  252. <span>{{ item.name }}</span>
  253. </el-option>
  254. </el-select>
  255. <el-divider direction="vertical"></el-divider>
  256. <el-button type="primary" @click="getZyJiMenZhenZhuangRuFeiYongClick"
  257. >查询
  258. </el-button>
  259. <el-tag style="margin-left: 7px"
  260. >合计:{{ huanZheFeiYongZongHe }}
  261. </el-tag>
  262. </div>
  263. <div class="layout_flex_1-y layout_display_flex_y">
  264. <div class="layout_flex_1-y">
  265. <el-table :data="zyDetailChargeList" height="100%">
  266. <el-table-column
  267. label="住院号"
  268. prop="inpatientNo"
  269. ></el-table-column>
  270. <el-table-column label="流水号" prop="detailSn"></el-table-column>
  271. <el-table-column
  272. label="收费日期"
  273. prop="chargeDate"
  274. width="80"
  275. ></el-table-column>
  276. <el-table-column
  277. label="收费代码"
  278. prop="chargeCode"
  279. ></el-table-column>
  280. <el-table-column
  281. label="项目名称"
  282. prop="chargeCodeName"
  283. show-overflow-tooltip
  284. ></el-table-column>
  285. <el-table-column
  286. label="费用录入日期"
  287. prop="genTime"
  288. width="80"
  289. ></el-table-column>
  290. <el-table-column label="金额" prop="chargeFee"></el-table-column>
  291. <el-table-column label="数量" prop="chargeAmount"></el-table-column>
  292. <el-table-column label="操作">
  293. <template #default="scope">
  294. <el-popconfirm
  295. cancel-button-text="取消"
  296. confirm-button-text="删除"
  297. icon="Info"
  298. iconColor="red"
  299. title="是否删除该费用"
  300. @confirm="shanChuFeiYongClick(scope.$index, scope.row)"
  301. >
  302. <template #reference>
  303. <el-button type="danger">删除</el-button>
  304. </template>
  305. </el-popconfirm>
  306. </template>
  307. </el-table-column>
  308. </el-table>
  309. </div>
  310. <div>
  311. <el-pagination
  312. :page-size="huanZheFeiYongPageSize"
  313. :total="huanZheFeiYongTotal"
  314. background
  315. layout="prev, pager, next, total"
  316. @current-change="huanZheFeiYongCurrentChange"
  317. ></el-pagination>
  318. </div>
  319. </div>
  320. </div>
  321. </el-drawer>
  322. </template>
  323. <script setup lang="ts">
  324. import { ref } from "vue";
  325. import {
  326. baoCunHuanZheZhuYuanFeiYong,
  327. correctInvoice,
  328. getDzfpQrcodeBySerialNo,
  329. getSerialNo,
  330. getZyJiMenZhenZhuangRuFeiYong,
  331. queryEntryName,
  332. queryHuanZhe,
  333. shanChuFeiYong,
  334. } from "@/api/inpatient/transfer-in-of-expenses";
  335. import { cptSex } from "@/utils/computed";
  336. import { computed } from "vue";
  337. import { ElMessage, ElTable } from "element-plus";
  338. import { compareDate, formatDatetime } from "@/utils/date";
  339. import { stringIsBlank, stringNotBlank } from "@/utils/blank-utils";
  340. import Dig from "@/utils/math";
  341. import SystemDeptSelect from "@/components/system/dept-select/SystemDeptSelect.vue";
  342. import { isDev } from "@/utils/public";
  343. import dayjs from "dayjs";
  344. import { CyMessageBox } from "@/utils/cy-message-box";
  345. import { useCompShallowRef } from "@/utils/useCompRef";
  346. import { BizException, ExceptionEnum } from "@/utils/BizException";
  347. import { createReusableTemplate } from "@vueuse/core";
  348. import PrintOutpatientDzfp from "@/views/clinic/transfer-expenses/print-outpatient-dzfp.vue";
  349. //查询条件
  350. //住院号
  351. const inpatientNo = ref(isDev ? "022271" : "");
  352. //机制号
  353. const serialNo = ref(isDev ? 4744457 : null);
  354. //收费代码
  355. const chargeCodeMX = ref("");
  356. // 住院次数
  357. const admissTimes = ref("");
  358. const printQrCodeRef = useCompShallowRef(PrintOutpatientDzfp);
  359. let serialNoTmp = null;
  360. const [DefaultTemplate, PatientInfo] = createReusableTemplate();
  361. const [ZyFeeTemplate, ZyTale] = createReusableTemplate();
  362. const huanZheXinXi = ref({
  363. execUnit: "",
  364. });
  365. const mzXinXiList = ref([]);
  366. const zyXinXiList = ref([]);
  367. //查询患者信息
  368. const queryClick = async () => {
  369. if (!inpatientNo.value) {
  370. ElMessage({
  371. type: "warning",
  372. message: "请先输入患者住院号",
  373. showClose: true,
  374. duration: 2500,
  375. });
  376. return;
  377. }
  378. deptList.value = [{ code: "1070000", name: "急诊科" }];
  379. queryHuanZhe(inpatientNo.value).then(res => {
  380. huanZheXinXi.value = res;
  381. admissTimes.value = res.admissTimes;
  382. huanZheXinXi.value.execUnit = "1070000";
  383. chargeDate.value = new Date(
  384. dayjs(huanZheXinXi.value.admissDate ?? "").add(1, "minutes")
  385. );
  386. });
  387. };
  388. function checkZyFee() {
  389. if (zyXinXiList.value.length === 0) {
  390. BizException(ExceptionEnum.MESSAGE_ERROR, "请选择要转入的费用");
  391. }
  392. }
  393. //查询机制号
  394. const querySerialNo = () => {
  395. if (!serialNo.value) {
  396. ElMessage({
  397. type: "warning",
  398. message: "请先输入机制号",
  399. showClose: true,
  400. duration: 2500,
  401. });
  402. return;
  403. }
  404. serialNoTmp = serialNo.value;
  405. getSerialNo(serialNo.value)
  406. .then(res => {
  407. mzXinXiList.value = res;
  408. })
  409. .catch(() => {
  410. serialNoTmp = null;
  411. mzXinXiList.value = [];
  412. });
  413. };
  414. //定义用来删除 多选框的选中状态 以及点击选中多选框
  415. const multipleTable = useCompShallowRef(ElTable);
  416. //点击多选框,把里面的内容添加进去
  417. const mzSelectChecked = (selection, row) => {
  418. zyXinXiList.value = selection;
  419. };
  420. //门诊发票信息 金额总和
  421. let mzSum = computed(() => {
  422. let sum = 0;
  423. mzXinXiList.value.forEach(item => {
  424. sum = Dig.add(sum, Dig.multiply(item.unitPrice, item.chargeQuantity));
  425. });
  426. return sum.toFixed(2);
  427. });
  428. //住院收费项目 金额总和
  429. let zySum = computed(() => {
  430. let sum = 0;
  431. zyXinXiList.value.forEach(item => {
  432. sum = Dig.add(sum, Dig.multiply(item.unitPrice, item.chargeQuantity));
  433. });
  434. return sum.toFixed(2);
  435. });
  436. const huanZheFeiYongDrawer = ref(false);
  437. const HuanZheFeiYongCurrentPage = ref(1);
  438. const huanZheFeiYongPageSize = ref(10);
  439. const huanZheFeiYongTotal = ref(0);
  440. const huanZheFeiYongZongHe = ref(0);
  441. //住院患者的费用信息
  442. const zyDetailChargeList = ref([]);
  443. let resInpatientNo = null;
  444. let resChargeCodeMx = null;
  445. //点击查询患者 门急诊转入的费用 在定义两个字段,用来分页的时候就算输入框没值了 也能拿到数据
  446. const getZyJiMenZhenZhuangRuFeiYongClick = () => {
  447. if (!admissTimes.value) {
  448. ElMessage.warning({
  449. message: "请先查询出患者信息",
  450. showClose: true,
  451. duration: 2500,
  452. });
  453. return;
  454. }
  455. //通过住院号和项目编码 获取住院门诊装入费用
  456. getZyJiMenZhenZhuangRuFeiYong(
  457. inpatientNo.value,
  458. chargeCodeMX.value,
  459. admissTimes.value,
  460. HuanZheFeiYongCurrentPage.value,
  461. huanZheFeiYongPageSize.value
  462. ).then(res => {
  463. resInpatientNo = inpatientNo.value;
  464. resChargeCodeMx = chargeCodeMX.value;
  465. zyDetailChargeList.value = res.data;
  466. huanZheFeiYongTotal.value = res.total;
  467. huanZheFeiYongZongHe.value = res.sum;
  468. });
  469. };
  470. //点击上下分页触发的事件
  471. const huanZheFeiYongCurrentChange = val => {
  472. HuanZheFeiYongCurrentPage.value = val;
  473. if (zyDetailChargeList.value) {
  474. getZyJiMenZhenZhuangRuFeiYong(
  475. resInpatientNo,
  476. resChargeCodeMx,
  477. admissTimes.value,
  478. HuanZheFeiYongCurrentPage.value,
  479. huanZheFeiYongPageSize.value
  480. ).then(res => {
  481. zyDetailChargeList.value = res.data;
  482. huanZheFeiYongTotal.value = res.total;
  483. });
  484. }
  485. };
  486. const saveStore = reactive({
  487. dialog: false,
  488. message: "",
  489. func: null,
  490. });
  491. function openSaveDialog(message) {
  492. saveStore.dialog = true;
  493. saveStore.message = message;
  494. saveStore.func = handleSave;
  495. }
  496. //删除住院收费项目 前端删除 后端也删除 只是不执行一个查找的动作了
  497. const shanChuFeiYongClick = (index, val) => {
  498. shanChuFeiYong(val).then(res => {
  499. zyDetailChargeList.value.splice(index, 1);
  500. });
  501. };
  502. //点击保存触发的事件
  503. const baoCunClick = () => {
  504. if (compareDate(huanZheXinXi.value.admissDate, chargeDate.value)) {
  505. return ElMessage.error("费用发生时间不能在入院时间之前。");
  506. }
  507. if (
  508. stringNotBlank(huanZheXinXi.value.disDate) &&
  509. compareDate(chargeDate.value, huanZheXinXi.value.disDate)
  510. ) {
  511. return ElMessage.error("费用发生时间不能在出院时间之后。");
  512. }
  513. huanZheXinXi.value.chargeDate = formatDatetime(chargeDate.value);
  514. if (typeof huanZheXinXi.value.inpatientNo === "undefined") {
  515. ElMessage({
  516. type: "warning",
  517. message: "请先选择患者",
  518. showClose: true,
  519. duration: 2500,
  520. });
  521. return;
  522. }
  523. checkZyFee();
  524. huanZheXinXi.value.list = zyXinXiList.value;
  525. if (huanZheXinXi.value.chargeDate === "") {
  526. return ElMessage.error({
  527. message: "请选择日期",
  528. });
  529. }
  530. for (let i = 0; mzXinXiList.value.length; i++) {
  531. if (
  532. huanZheXinXi.value.name !== mzXinXiList.value[i].patientName &&
  533. typeof mzXinXiList.value[i].patientName !== "undefined"
  534. ) {
  535. return openSaveDialog(
  536. `门诊病人姓名【'${mzXinXiList.value[i].patientName}'】住院病人姓名【' ${huanZheXinXi.value.name}'】不一致,是否继续?`
  537. );
  538. } else if (
  539. huanZheXinXi.value.name === mzXinXiList.value[i].patientName &&
  540. typeof mzXinXiList.value[i].patientName !== "undefined"
  541. ) {
  542. return openSaveDialog();
  543. }
  544. }
  545. };
  546. const electronicPrescription = reactive({
  547. dialog: false,
  548. qrCode: "",
  549. });
  550. async function handleSave() {
  551. await baoCunHuanZheZhuYuanFeiYong({
  552. ...huanZheXinXi.value,
  553. serialNo: serialNoTmp,
  554. });
  555. await handleCorrectInvoice();
  556. }
  557. async function handleCorrectInvoice(inputFee = true) {
  558. checkZyFee();
  559. const zyCodes = zyXinXiList.value.map(item => {
  560. return item.chargeCodeMx;
  561. });
  562. const codes = [];
  563. mzXinXiList.value.forEach(item => {
  564. if (!zyCodes.includes(item.chargeCodeMx)) {
  565. codes.push(item.chargeCodeMx);
  566. }
  567. });
  568. const success = await correctInvoice({
  569. serialNo: serialNoTmp,
  570. codes: codes,
  571. })
  572. .then(res => {
  573. handleOpenPrint(res);
  574. return true;
  575. })
  576. .catch(() => {
  577. if (inputFee) {
  578. CyMessageBox.alert({
  579. message: "保存费用成功,但冲红发票失败,可以点击仅冲红发票按钮重试",
  580. });
  581. }
  582. return false;
  583. });
  584. if (success) {
  585. zyXinXiList.value = [];
  586. multipleTable.value.clearSelection();
  587. saveStore.dialog = false;
  588. }
  589. }
  590. //项目名称 数组
  591. const entryNameList = ref([]);
  592. //远程搜索项目名称
  593. const remoteMethodEntryName = val => {
  594. if (val.length >= 2) {
  595. queryEntryName(val).then(res => {
  596. entryNameList.value = res;
  597. });
  598. }
  599. };
  600. const chargeDate = ref(new Date());
  601. // 科室
  602. const deptList = ref([]);
  603. function handleOpenPrint(res) {
  604. if (stringIsBlank(res)) return;
  605. electronicPrescription.dialog = true;
  606. electronicPrescription.qrCode = res;
  607. }
  608. function handleQueryQrCode() {
  609. getDzfpQrcodeBySerialNo(serialNo.value).then(res => {
  610. printQrCodeRef.value.print({ ...res, serialNo: serialNo.value });
  611. });
  612. }
  613. async function handleOnlyChargeRed() {
  614. checkZyFee();
  615. saveStore.dialog = true;
  616. saveStore.message = "仅充红,不会在录入住院费用了。";
  617. saveStore.func = () => handleCorrectInvoice(false);
  618. }
  619. const printObj = {
  620. id: "#dzfpQrCode",
  621. extraCss: `/static/transferin-print.css`,
  622. };
  623. </script>
  624. <style lang="scss"></style>