index.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. import XEUtils from "xe-utils";
  2. import moment from "moment/moment";
  3. import { useEventListener, useWebSocket } from "@vueuse/core";
  4. import { documentVisibilityEnum } from "@/utils/cy-use/useChangeToken";
  5. import { getServerDate } from "@/utils/moment-utils";
  6. import router from "@/router";
  7. import { getAllWards } from "@/api/login";
  8. import sleep from "@/utils/sleep";
  9. import env from "@/utils/setting";
  10. import { isDev } from "@/utils/public";
  11. import { magicApi } from "@/utils/database/magic-api-request";
  12. import { useCompShallowRef } from "@/utils/useCompRef";
  13. import RenderTable from "@/components/nursing-dashboard/RenderTable.vue";
  14. import { stringNotBlank } from "@/utils/blank-utils";
  15. function getWeek(date: any): string {
  16. // 参数时间戳
  17. let week = moment(new Date(date)).day();
  18. switch (week) {
  19. case 1:
  20. return "星期一";
  21. case 2:
  22. return "星期二";
  23. case 3:
  24. return "星期三";
  25. case 4:
  26. return "星期四";
  27. case 5:
  28. return "星期五";
  29. case 6:
  30. return "星期六";
  31. case 0:
  32. return "星期日";
  33. default:
  34. return "";
  35. }
  36. }
  37. export function anonymizeName(name: string) {
  38. if (!name) return "";
  39. let prefix = "";
  40. // 如果是婴儿
  41. if (name.startsWith("(")) {
  42. const index = name.indexOf("(");
  43. const end = name.lastIndexOf(")");
  44. prefix = name.substring(index, end + 1);
  45. name = name.substring(end + 1, name.length);
  46. }
  47. if (name.length == 2) {
  48. name = name.substring(0, 1) + "*";
  49. return prefix + name;
  50. } else if (name.length == 3) {
  51. name = name.substring(0, 1) + "*" + name.substring(2, 3);
  52. return prefix + name;
  53. } else if (name.length > 3) {
  54. name = name.substring(0, 1) + "*" + "*" + name.substring(3, name.length);
  55. return prefix + name;
  56. }
  57. return "";
  58. }
  59. const huloColor = {
  60. 病重: "#E21606",
  61. 病危: "#f89898",
  62. Ⅰ级: "#79bbff",
  63. Ⅱ级: "#12D4F9",
  64. Ⅲ级: "#30C8A0",
  65. };
  66. export function getHuloColor(value: string) {
  67. return XEUtils.get(huloColor, value, "#b1b3b8");
  68. }
  69. export type InpatientBrief = {
  70. bedNo: string;
  71. name: string;
  72. gender: number;
  73. indays: number;
  74. patNo: string;
  75. birthDate: string;
  76. admissDate: string;
  77. convertAdmissDate: string;
  78. physician: string;
  79. medType: string;
  80. medTypeName: string;
  81. surgery: string;
  82. // 护理级别
  83. nursingLevel: string;
  84. // 病情医嘱:null,病重,病危
  85. sickLevelOrderName: string;
  86. // 患者状态: 0-正常,1-病重,2-病危
  87. sickLevel: number;
  88. leaveHospital: number;
  89. prompt: {
  90. text: string;
  91. color: string;
  92. };
  93. };
  94. interface CallData {
  95. ward: string;
  96. bedNo: string;
  97. emergency: boolean;
  98. state: "call" | string; // 可以更精确地定义可能的字符串值
  99. call: boolean;
  100. group: string;
  101. }
  102. function openSocket(callStore) {
  103. const url = ref("");
  104. let socket = null;
  105. function open(code: string) {
  106. if (socket != null) {
  107. socket.close();
  108. }
  109. url.value = isDev
  110. ? `ws://172.16.30.66:20922/websocket/nursingRecordBoard/${code}`
  111. : `${env.VITE_SOCKET_V2}/nursingRecordBoard/${code}`;
  112. socket = useWebSocket(url, {
  113. autoReconnect: true,
  114. immediate: true,
  115. onMessage: (ws, message) => {
  116. try {
  117. const data = JSON.parse(message.data);
  118. callStore[data.code](data.data);
  119. } catch (e) {
  120. console.error(e);
  121. }
  122. },
  123. heartbeat: {
  124. message: "ping",
  125. interval: 1000 * 60 * 3,
  126. pongTimeout: 1000,
  127. },
  128. });
  129. }
  130. return {
  131. open,
  132. };
  133. }
  134. export function useInpatientBoard() {
  135. const bedCount = ref(0);
  136. const selectRef = ref();
  137. const urlQuery = reactive({
  138. speedBarDisplay: 5,
  139. refresh: 30,
  140. ward: "",
  141. wardName: "",
  142. tempId: "",
  143. tableDisplay: 2,
  144. });
  145. const renderTableRef = useCompShallowRef(RenderTable);
  146. const store = reactive({
  147. // 表格模板
  148. htmlData: "",
  149. });
  150. const callStore = reactive({
  151. call: new Map<string, CallData>(),
  152. urgentCallForHelp: new Map<string, CallData>(),
  153. dialogVisible: true,
  154. });
  155. const socketOnMessage = {
  156. call: (data: CallData) => {
  157. const group = data.group;
  158. if (data.call) {
  159. callStore[group].set(data.bedNo, data);
  160. } else {
  161. callStore[group].delete(data.bedNo);
  162. }
  163. },
  164. empty: data => {
  165. callStore[data.group].clear();
  166. },
  167. };
  168. const socket = openSocket(socketOnMessage);
  169. let refreshTimeOut;
  170. const data = ref<InpatientBrief[]>([]);
  171. const allWards = ref<{ code: string; name: string }[]>([]);
  172. const time = reactive({
  173. now: moment().format("YYYY-MM-DD HH:mm:ss"),
  174. weekName: "",
  175. });
  176. const infoEl = ref<HTMLDivElement | null>(null);
  177. function changeRouterQuery() {
  178. const { wardName, ...tmp } = urlQuery;
  179. router
  180. .replace({
  181. query: {
  182. ...tmp,
  183. },
  184. })
  185. .then(XEUtils.noop);
  186. }
  187. async function handleWardChange(code: string) {
  188. clearTimeout(refreshTimeOut);
  189. if (code) {
  190. urlQuery.ward = code;
  191. magicApi({
  192. method: "get",
  193. params: { dept: code },
  194. url: "/public/dashboard/patientList",
  195. }).then(res => {
  196. setData(res.data);
  197. bedCount.value = res.bedCount;
  198. changeRouterQuery();
  199. });
  200. await nextTick();
  201. urlQuery.wardName = selectRef.value.states.selectedLabel;
  202. }
  203. await nextTick();
  204. refreshTimeOut = setTimeout(
  205. () => {
  206. handleWardChange(urlQuery.ward);
  207. },
  208. 60 * 1000 * urlQuery.refresh
  209. );
  210. mutation.getTemplate();
  211. socket.open(code);
  212. }
  213. async function setData(value: InpatientBrief[]) {
  214. if (XEUtils.isArray(value)) {
  215. data.value = value;
  216. mutation.boardStart(data.value);
  217. } else {
  218. data.value = [];
  219. }
  220. time.now = await getServerDate();
  221. time.weekName = getWeek(time.now);
  222. }
  223. let interval = setInterval(() => {
  224. time.now = moment(time.now).add(1, "seconds").format("YYYY-MM-DD HH:mm:ss");
  225. }, 1000);
  226. useEventListener(document, "visibilitychange", async val => {
  227. if (document.visibilityState === documentVisibilityEnum.hidden) {
  228. clearInterval(interval);
  229. } else {
  230. // @ts-ignore
  231. time.now = moment().format("YYYY-MM-DD HH:mm:ss");
  232. interval = setInterval(() => {
  233. time.now = moment(time.now)
  234. .add(1, "seconds")
  235. .format("YYYY-MM-DD HH:mm:ss");
  236. }, 1000);
  237. }
  238. });
  239. function changeInterval() {
  240. changeRouterQuery();
  241. }
  242. const mutation = {
  243. boardStart: (value: any[]): Promise<void> | number => 0,
  244. async getTemplate() {
  245. let params = { ward: urlQuery.ward, id: "" };
  246. if (stringNotBlank(urlQuery.tempId)) {
  247. params = {
  248. id: urlQuery.tempId,
  249. };
  250. }
  251. const tmp = await magicApi({
  252. url: "/public/dashboard/getTemplate",
  253. method: "get",
  254. params,
  255. });
  256. if (tmp === store.htmlData) {
  257. renderTableRef.value.reloadData();
  258. } else {
  259. store.htmlData = tmp;
  260. }
  261. },
  262. changeTableDisplay() {
  263. renderTableRef.value.reloadData();
  264. changeRouterQuery();
  265. },
  266. };
  267. onMounted(async () => {
  268. const query = router.currentRoute.value.query;
  269. urlQuery.speedBarDisplay = XEUtils.toNumber(
  270. XEUtils.get(query, "speedBarDisplay", 3)
  271. );
  272. urlQuery.tempId = query.tempId as string;
  273. urlQuery.refresh = XEUtils.toNumber(XEUtils.get(query, "refresh", 30));
  274. urlQuery.tableDisplay = XEUtils.toNumber(
  275. XEUtils.get(query, "tableDisplay", 2)
  276. );
  277. allWards.value = (await getAllWards()) as any;
  278. await sleep(500);
  279. const ward = XEUtils.get(query, "ward", "") as string;
  280. handleWardChange(ward);
  281. });
  282. return {
  283. data,
  284. allWards,
  285. handleWardChange,
  286. selectRef,
  287. time,
  288. infoEl,
  289. changeInterval,
  290. urlQuery,
  291. bedCount,
  292. mutation,
  293. callStore,
  294. store,
  295. renderTableRef,
  296. };
  297. }
  298. export type InpatientBoardType = ReturnType<typeof useInpatientBoard>;
  299. export const InpatientBoardKey = "inpatientBoardV2";