index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import type { InjectionKey, ShallowRef } from "vue";
  2. import { getPatientAll } from "@/api/inpatient/patient";
  3. import * as archiveApi from "@/api/archive/archive-api";
  4. import {
  5. getPatientArchives,
  6. PatientArchive,
  7. submitTask,
  8. } from "@/api/archive/archive-api";
  9. import XEUtils from "xe-utils";
  10. import { useWebSocket } from "@vueuse/core";
  11. import { useUserStore } from "@/pinia/user-store";
  12. import { useDialog } from "@/components/cy/CyDialog/index";
  13. import ArchiveUpload from "./ArchiveUpload.vue";
  14. import ArchiveAllLog from "@/views/archive/ArchiveAllLog.vue";
  15. import { ElButton, ElNotification } from "element-plus";
  16. type PatInfo = {
  17. inpatientNo: string;
  18. admissTimes: number;
  19. admissDate: string;
  20. disDate: string;
  21. };
  22. type Socket = {
  23. [key: string]: (value: any) => void;
  24. };
  25. const useSocket = (cb: Socket) => {
  26. const socketUrl = ref();
  27. const { data, open } = useWebSocket(socketUrl, {
  28. immediate: false,
  29. });
  30. watch(
  31. () => data.value,
  32. () => {
  33. try {
  34. const json = JSON.parse(data.value);
  35. cb[json.code]?.(json.data);
  36. } catch (e) {
  37. console.error(e);
  38. }
  39. },
  40. { immediate: false, deep: true }
  41. );
  42. return {
  43. setUrl(url: string) {
  44. socketUrl.value = url;
  45. open();
  46. },
  47. };
  48. };
  49. export const useArchive = () => {
  50. const store = reactive({
  51. patNo: "",
  52. times: 0,
  53. patInfo: {} as PatInfo,
  54. treeList: [] as PatientArchive[],
  55. pdfUrl: "",
  56. asideValue: "archive",
  57. footerValue: "footer",
  58. footerVisible: true,
  59. logMessage: [],
  60. footerRef: null as ShallowRef<{ scroll: (val: boolean) => void }>,
  61. mainIframe: null as HTMLIFrameElement,
  62. mainTabsValue: "pdf",
  63. });
  64. function notification(message) {
  65. const MessageNode = (
  66. <div>
  67. <div>{message}</div>
  68. <div>
  69. <ElButton
  70. text
  71. type="danger"
  72. onClick={() => ElNotification.closeAll()}
  73. >
  74. 取消
  75. </ElButton>
  76. <ElButton
  77. text
  78. type="primary"
  79. onClick={() => {
  80. ElNotification.closeAll();
  81. mutation.getData();
  82. }}
  83. >
  84. 更新目录
  85. </ElButton>
  86. </div>
  87. </div>
  88. );
  89. ElNotification.success({
  90. title: "文件有变化",
  91. position: "bottom-right",
  92. duration: 0,
  93. message: MessageNode,
  94. });
  95. }
  96. const socket = useSocket({
  97. log: data => {
  98. store.logMessage.push(JSON.parse(data));
  99. store.footerVisible = true;
  100. mutation.logScroll(false);
  101. },
  102. change: data => {
  103. if (useUserStore().userInfo.code !== data.code) {
  104. notification(data.message);
  105. }
  106. },
  107. taskComplete: () => {
  108. mutation.getData();
  109. },
  110. });
  111. const mutation = {
  112. async getData() {
  113. store.treeList = await getPatientArchives(store.patNo, store.times);
  114. },
  115. async setPatInfo(patInfo: string) {
  116. const split = patInfo.split("_");
  117. store.patNo = split[0];
  118. store.times = XEUtils.toNumber(split[1]);
  119. socket.setUrl(
  120. `${import.meta.env.VITE_SOCKET_URL}archive-${store.patNo}-${store.times}-${useUserStore().userInfo.code}`
  121. );
  122. const res = await getPatientAll(store.patNo, store.times);
  123. store.patInfo = res as any;
  124. this.getData();
  125. },
  126. setPdfUrl(url: string) {
  127. store.mainIframe?.contentWindow?.scrollTo(0, 0);
  128. store.pdfUrl = "/thyyemrpdfserver" + url;
  129. },
  130. async sort() {
  131. function forEach(
  132. data: PatientArchive[],
  133. fatherLevel: PatientArchive | null = null
  134. ) {
  135. data.forEach((item, index) => {
  136. if (fatherLevel) {
  137. item.parentId = fatherLevel.id;
  138. } else {
  139. item.parentId = null;
  140. }
  141. item.sort = index;
  142. if (item.children !== null && item.children.length > 0) {
  143. forEach(item.children, item);
  144. }
  145. });
  146. }
  147. forEach(store.treeList);
  148. const tmp = {
  149. patNo: store.patInfo.inpatientNo,
  150. times: store.patInfo.admissTimes,
  151. archives: mutation.toTreeArray(),
  152. };
  153. await archiveApi.sort(tmp);
  154. },
  155. toTreeArray(): PatientArchive[] {
  156. return XEUtils.toTreeArray(XEUtils.cloneDeep(store.treeList), {
  157. clear: true,
  158. });
  159. },
  160. archiveTask() {
  161. submitTask([{ patNo: store.patNo, times: store.times }]);
  162. },
  163. clearLog() {
  164. store.logMessage = [];
  165. },
  166. async logScroll(top = false) {
  167. await nextTick();
  168. store.footerRef?.scroll?.(top);
  169. },
  170. async uploadFiles(parent: string) {
  171. await useDialog(ArchiveUpload, {
  172. dialogProps: {
  173. title: "上传文件",
  174. closeOnClickModal: false,
  175. showClose: false,
  176. closeOnPressEscape: false,
  177. },
  178. showCancel: false,
  179. params: {
  180. patNo: store.patInfo.inpatientNo,
  181. times: store.patInfo.admissTimes,
  182. parent,
  183. },
  184. });
  185. await mutation.getData();
  186. },
  187. getPatNoAndTimes() {
  188. return {
  189. patNo: store.patInfo.inpatientNo,
  190. times: store.patInfo.admissTimes,
  191. };
  192. },
  193. getAllLog() {
  194. useDialog(ArchiveAllLog, {
  195. dialogProps: { title: "全部日志", fullscreen: true },
  196. showCancel: false,
  197. params: {
  198. ...mutation.getPatNoAndTimes(),
  199. },
  200. }).catch(XEUtils.noop);
  201. },
  202. };
  203. return { store, mutation };
  204. };
  205. type UseArchive = ReturnType<typeof useArchive>;
  206. export const useArchiveKey: InjectionKey<UseArchive> = Symbol("useArchiveKey");