瀏覽代碼

护理看板

ZZhuangFW 2 月之前
父節點
當前提交
911e4ed711

二進制
src/assets/dashboard/bed.png


二進制
src/assets/dashboard/notice.png


二進制
src/assets/dashboard/nursingLevel1.png


二進制
src/assets/dashboard/nursingLevel2.png


二進制
src/assets/dashboard/nursingLevel3.png


二進制
src/assets/dashboard/nursingLevel4.png


二進制
src/assets/dashboard/remind.png


+ 13 - 1
src/components/nursing-dashboard/RenderTable.vue

@@ -152,10 +152,17 @@ defineExpose({
 </script>
 
 <template>
-  <div class="layout_container render-table" ref="divRaf"></div>
+  <div class="container" id="container">
+    <div class="layout_container render-table" ref="divRaf"></div>
+  </div>
 </template>
 
 <style lang="scss">
+.container{
+  width: 100%;
+  height: 100%;
+  // overflow: auto
+}
 .render-table {
   background: #0f1628;
   font-size: 1.13rem;
@@ -172,6 +179,7 @@ defineExpose({
   td {
     border: 1px solid white;
     text-align: center !important;
+    color: #0f1628;
   }
 
   .td-text_hidden {
@@ -196,4 +204,8 @@ defineExpose({
     }
   }
 }
+::-webkit-scrollbar {
+width: 0 !important;
+height: 0 !important;
+}
 </style>

+ 344 - 0
src/views/single-page/InpatientBoardV2/BoardCardNew.vue

@@ -0,0 +1,344 @@
+<script setup lang="tsx">
+import {
+  anonymizeName,
+  getHuloColor,
+  InpatientBoardKey,
+  InpatientBoardType,
+} from "@/views/single-page/InpatientBoardV2/index";
+import type { InpatientBrief } from "@/views/single-page/InpatientBoardV2/index";
+import { ElTag } from "element-plus";
+import XEUtils from "xe-utils";
+import sleep from "@/utils/sleep";
+
+const store = inject(InpatientBoardKey) as InpatientBoardType;
+
+const tempInfoKey = {
+  patNo: "住院号1111",
+  convertAdmissDate: "入院",
+  physician: "管床",
+  medTypeName: "类别",
+};
+
+function sexName(value: any) {
+  if (value == 1) {
+    return "男";
+  }
+  if (value == 2) {
+    return "女";
+  }
+  return "";
+}
+
+const handleNursingImg = (item)=>{
+    console.log(item,'item');
+    let url = ""
+    switch (item.nursingLevel) {
+        case "特级护理":
+             url = "/src/assets/dashboard/nursingLevel4.png"
+            break;
+        case "一级护理":
+             url = "/src/assets/dashboard/nursingLevel1.png"
+            break;
+        case "二级护理":
+             url = "/src/assets/dashboard/nursingLevel2.png"
+            break;
+        case "三级护理":
+             url = "/src/assets/dashboard/nursingLevel3.png"
+            break;
+        default:
+            break;
+    }
+    
+    return url
+    // console.log("item",item.name);
+}
+
+const daysDistance = (date1,date2) => { 
+    console.log('date1',date1);
+    console.log('date2',date2);
+    //date格式为字符串 2025-6-27
+    date1 = Date.parse(date1);
+    date2 = Date.parse(date2);
+    let   ms = Math.abs(date1-date2); // 相差的毫秒数
+    return Math.floor(ms/(1000 * 60 * 60 * 24)); // 相差的天数
+};
+
+function huliFunc(value: InpatientBrief) {
+  const Tag = (name: string) => {
+    return (
+      <ElTag
+        effect="dark"
+        round
+        size="large"
+        disableTransitions
+        color={getHuloColor(name)}
+      >
+        {() => name}
+      </ElTag>
+    );
+  };
+  if (value.sickLevelOrderName) {
+    return Tag(value.sickLevelOrderName);
+  }
+  return null;
+}
+
+const scrollingInfo = reactive({
+  rowCount: 5,
+  interval: null,
+  currentIndex: 0,
+  maxDataLength: 25,
+  data: [],
+  clear() {
+    clearTimeout(scrollingInfo.interval);
+  },
+});
+
+function hasScrollDiv(divElement) {
+  // 获取div的总高度(包括内容和任何滚动条)
+  const totalHeight = divElement.scrollHeight;
+  // 获取可见区域的高度(不包含任何滚动条)
+  const clientHeight = divElement.clientHeight;
+  // 如果总高度大于可见区域的高度,则说明该div元素有滚动条
+  return totalHeight > clientHeight;
+}
+
+function 开启滚动动画(value) {
+  scrollingInfo.clear();
+  scrollingInfo.interval = setTimeout(
+    () => 动画(value),
+    store.urlQuery.speedBarDisplay * 1000
+  );
+}
+
+async function 动画(value) {
+  const el = store.infoEl.value;
+  const items = el.querySelectorAll(".board-row");
+  const item = items[1];
+  if (item) {
+    item.scrollIntoView({
+      block: "start",
+      inline: "nearest",
+      behavior: "smooth",
+    });
+    await nextTick();
+    await sleep(500);
+    const shiftData = scrollingInfo.data.shift();
+    scrollingInfo.currentIndex++;
+    el.scrollTop = 0;
+    scrollingInfo.data.push(shiftData);
+  }
+  开启滚动动画(value);
+}
+
+const chunkSize = 3;
+
+async function start(data: any[]) {
+  scrollingInfo.clear();
+  const chunk = XEUtils.chunk(data, chunkSize);
+  if (chunk.length === chunkSize) {
+    scrollingInfo.data = [...chunk, ...chunk];
+  } else {
+    scrollingInfo.data = chunk;
+  }
+  await nextTick();
+  if (hasScrollDiv(store.infoEl.value)) {
+    开启滚动动画(scrollingInfo.data);
+  }
+}
+
+onMounted(() => {
+  store.mutation.boardStart = start;
+});
+</script>
+
+<template>
+  <div
+    style="overflow: hidden; flex-wrap: wrap; height: 100%"
+    :ref="(el: any) => store.infoEl.value = el"
+  >
+    <div v-for="father in scrollingInfo.data" class="board-row">
+      <div class="board-col" v-for="item in father">
+        <div class="board-card">
+          <div class="card-top flex-center-row">
+            <div class="card-top-area-1 flex-center-row">
+              <img
+                style="width: 20px; height: 20px"
+                :src="handleNursingImg(item)"
+                alt=""
+              />
+              <!-- <img src="../../../assets/dashboard/nursingLevel4.png" 
+              style="width: 20px;height: 20px;"
+              alt="" /> -->
+            </div>
+            <div class="card-top-area-2 flex-center-row">
+              <span>{{ item.bedNo }}</span>
+              <span>{{ anonymizeName(item.name) }}</span>
+            </div>
+            <div class="card-top-area-3 flex-center-row">
+              <img src="../../../assets/dashboard/bed.png" alt="" />
+            </div>
+          </div>
+          <div class="card-content flex-center-column">
+            <div class="card-content-1">
+              <span>{{ item.patNo }}</span>
+              <span>{{ sexName(item.gender) }} {{ item.age }}岁</span>
+            </div>
+            <div class="card-content-2">
+              <span>
+                住院天数 : {{ daysDistance(item.admissDate, new Date()) }} 天
+              </span>
+              <span> </span>
+            </div>
+          </div>
+          <div class="card-bottom">
+            <div class="card-bottom-left">
+              {{ item.physician }}
+            </div>
+            <div class="card-bottom-right">
+              {{ item.dutyNurseName }}
+            </div>
+          </div>
+        </div>
+        <!-- <div class="board-card">
+          <div
+            class="layout_container layout-horizontal board-card-header"
+            style="height: max-content"
+          >
+            <div class="layout_flex_1-x board-col-header">
+              {{ anonymizeName(item.name) }}
+              <span style="font-size: 1.25rem">{{ sexName(item.gender) }}</span>
+              <span style="font-size: 1.25rem">{{ item.age }}岁</span>
+            </div>
+            <div style="width: max-content">
+              <b style="font-size: 1.25rem"> {{ item.bedNo }}床 </b>
+              <Component :is="huliFunc(item)" />
+            </div>
+          </div>
+          <div class="board-card-body">
+            <div
+              class="layout_display_flex"
+              v-for="(infoValue, infoKey) in tempInfoKey"
+              style="height: max-content; margin: 0.31rem 0"
+            >
+              <div style="width: 40%; text-align: right">{{ infoValue }}:</div>
+              <div class="layout_flex_1-x" style="padding-left: 6px">
+                {{ item[infoKey] }}
+              </div>
+            </div>
+          </div>
+        </div> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss">
+$padding: 0.63rem;
+
+.board-row {
+  display: grid;
+  padding: 0.31rem 0;
+  grid-template-columns: 1fr 1fr 1fr;
+
+  .board-col {
+    flex: 0 0 40%;
+    padding-left: $padding;
+    padding-right: $padding;
+    font-size: 0.75rem;
+
+    .board-col-header {
+      font-size: 1.4rem;
+    }
+
+    .board-card {
+      height: 12rem;
+      border: 1px solid #7684ca;
+      border-radius: 15px;
+      box-sizing: border-box;
+      background-color: #ffffff;
+      color: #747e92;
+      img {
+        width: 30px;
+        height: 30px;
+      }
+      .card-top {
+        width: 100%;
+        height: 25%;
+        border-bottom: 1px solid #e6e6e6;
+        display: flex;
+        // display: flex;
+        .card-top-area-1 {
+          width: 20%;
+          height: 100%;
+        }
+        .card-top-area-2 {
+          width: 60%;
+          height: 100%;
+          justify-content: space-around;
+          font-size: 1.5rem;
+          font-weight: bold;
+        }
+        .card-top-area-3 {
+          width: 20%;
+          height: 100%;
+        }
+      }
+
+      .card-content {
+        width: 100%;
+        height: 50%;
+        border-bottom: 1px solid #e6e6e6;
+        box-sizing: border-box;
+        padding: 5px 20px;
+        font-size: 1.2rem;
+
+        .card-content-1 {
+          width: 100%;
+          height: 50%;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+        .card-content-2 {
+          width: 100%;
+          height: 50%;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        }
+      }
+
+      .card-bottom {
+        width: 100%;
+        height: 25%;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 5px 20px;
+        font-size: 1rem;
+      }
+      //   background: #204698;
+      //   border-radius: 15px;
+    }
+
+    .board-card-body {
+      font-size: 0.9rem;
+      background-color: #162858;
+      border-radius: 15px;
+    }
+  }
+}
+
+.flex-center-row {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.flex-center-column {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+}
+</style>

+ 186 - 16
src/views/single-page/InpatientBoardV2/BoardInfo.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { SYSTEM_CONFIG } from "@/utils/public";
 import { InpatientBoardKey, type InpatientBoardType } from "./index";
-import BoardCard from "./BoardCard.vue";
+import BoardCard from "./BoardCardNew.vue";
 import RenderTable from "@/components/nursing-dashboard/RenderTable.vue";
 
 const store = inject(InpatientBoardKey) as InpatientBoardType;
@@ -9,8 +9,20 @@ const store = inject(InpatientBoardKey) as InpatientBoardType;
 
 <template>
   <div class="layout_container info_main">
+    <div class="top-area">
+      <div class="top-title">
+        <b style="font-size: 2.5rem"
+          >{{ SYSTEM_CONFIG.HOSPITAL_NAME }} | {{ store.urlQuery.wardName }}</b
+        >
+      </div>
+      <div class="top-time-area">
+        {{ store.time.weekName }}
+        <br />
+        {{ store.time.now }}
+      </div>
+    </div>
     <div class="layout_container" style="height: max-content">
-      <div class="layout_main layout_container layout-horizontal">
+      <!-- <div class="layout_main layout_container layout-horizontal">
         <div class="layout_main">
           <b style="font-size: 2.63rem"
             >{{ SYSTEM_CONFIG.HOSPITAL_NAME }} |
@@ -32,35 +44,193 @@ const store = inject(InpatientBoardKey) as InpatientBoardType;
             {{ store.time.now }}
           </div>
         </div>
-      </div>
+      </div> -->
     </div>
 
     <div
       class="layout_main layout_container layout-horizontal"
-      style="padding: 0 0.63rem"
+      style="padding: 0 0.63rem; height: 70%"
     >
+      <div class="left-area">
+        <div class="left-title-1">通知公告</div>
+        <div class="left-content-1"></div>
+        <div class="left-title-2">病区统计</div>
+        <div class="table-area">
+          <RenderTable
+            :ref="
+              el => {
+                store.renderTableRef.value = el;
+              }
+            "
+            :html-data="store.store.htmlData"
+            :ward-code="store.urlQuery.ward"
+          />
+        </div>
+      </div>
       <div class="layout_main" style="padding: 0">
         <BoardCard />
       </div>
-      <div class="右边宽度">
-        <RenderTable
-          :ref="
-            el => {
-              store.renderTableRef.value = el;
-            }
-          "
-          :html-data="store.store.htmlData"
-          :ward-code="store.urlQuery.ward"
-        />
+    </div>
+
+    <div class="bottom-area">
+      <div class="bottom-area-1">
+        <div>
+          床位使用情况: 总床位 (<span>{{ store.bedCount.value }}</span
+          >)
+        </div>
+        <div>
+          已使用 (<span> {{ store.data.value.length }}</span
+          >)
+        </div>
+        <div>
+          空床 (<span>{{ store.bedCount.value - store.data.value.length }}</span
+          >)
+        </div>
+      </div>
+      <div class="bottom-area-2">
+        <div>
+          <img src="../../../assets/dashboard/remind.png" alt="" />
+          温馨提示:请大家保持安静,请勿大声喧哗!
+        </div>
+      </div>
+      <div class="bottom-area-3">
+        <div>
+          <img src="../../../assets/dashboard/nursingLevel4.png" alt="" />
+          特级护理
+        </div>
+        <div>
+          <img src="../../../assets/dashboard/nursingLevel1.png" alt="" />
+          一级护理
+        </div>
+        <div>
+          <img src="../../../assets/dashboard/nursingLevel2.png" alt="" />
+
+          二级护理
+        </div>
+        <div>
+          <img src="../../../assets/dashboard/nursingLevel3.png" alt="" />
+          三级护理
+        </div>
       </div>
     </div>
   </div>
 </template>
 
 <style lang="scss">
+.top-area {
+  width: 100%;
+  height: 10%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  position: relative;
+  background-color: #5373eb;
+  margin-top: 0.31rem;
+  margin-bottom: 0.5rem;
+  .top-time-area {
+    position: absolute;
+    right: 40px;
+    font-size: 1.5rem;
+  }
+}
 .info_main {
-  .右边宽度 {
-    width: 70%;
+  .left-area {
+    width: 30%;
+    border: 3px solid #a7b6ff;
+    color: #1c2641;
+    background-color: #ffffff;
+    .left-title-1 {
+      height: 10%;
+      // height: 3.5rem;
+      font-size: 1.2rem;
+      display: flex;
+      align-items: center;
+      padding: 10px;
+      font-weight: bold;
+      border-bottom: 2px solid #a7b6ff;
+    }
+
+    .left-content-1 {
+      height: 15%;
+      // height: 8rem;
+      border-bottom: 2px solid #a7b6ff;
+    }
+    .left-title-2 {
+      height: 10%;
+      // height: 3.5rem;
+      font-size: 1.2rem;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-weight: bold;
+      border-bottom: 2px solid #a7b6ff;
+      padding: 10px;
+    }
+    .table-area {
+      height: 65%;
+      // padding: 10px;
+      overflow: auto;
+    }
+    // padding: 2px;
+  }
+
+  .bottom-area {
+    width: 100%;
+    height: 5%;
+    display: flex;
+    background-color: #ffffff;
+    color: #6f7474;
+    box-sizing: border-box;
+    padding: 0 10px;
+
+    .bottom-area-1 {
+      width: 30%;
+      display: flex;
+      align-items: center;
+
+      div {
+        margin-right: 10px;
+      }
+
+      span {
+        color: #ff6830;
+      }
+    }
+
+    .bottom-area-2 {
+      width: 42%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      div {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+      img {
+        width: 20px;
+        height: 20px;
+        margin-right: 5px;
+      }
+    }
+
+    .bottom-area-3 {
+      width: 28%;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      div {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-left: 20px;
+      }
+      img {
+        width: 20px;
+        height: 20px;
+        margin-right: 5px;
+      }
+    }
   }
 
   .蓝色底框 {

+ 2 - 1
src/views/single-page/InpatientBoardV2/Index.vue

@@ -100,7 +100,8 @@ onMounted(async () => {
   }
 
   .layout_main {
-    background: #0f1628;
+    background: #EFEFEF;
+    // background: #0f1628;
     padding: 0.63rem;
     color: white;
   }

+ 4 - 0
src/views/single-page/InpatientBoardV2/index.ts

@@ -231,7 +231,11 @@ export function useInpatientBoard() {
   async function setData(value: InpatientBrief[]) {
     if (XEUtils.isArray(value)) {
       data.value = value;
+      // for(let i = 0; i < 30; i++){
+      //   data.value.push(value[0])
+      // }
       mutation.boardStart(data.value);
+
     } else {
       data.value = [];
     }