单应用项目,可以创建很多独立工具类页面 ,不用登录 初始化的页面
zhangchen
2025-08-27 863a99f05466a93112a6c02ba1b671c7ecbf2d06
src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue
@@ -16,7 +16,7 @@
          title="治疗模式"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row1-col2-row1"
          class="mini-card row1-col2-row1"
          header-class-name="mihi-header"
        >
          <div class="item-box dialysis-mode-content">
@@ -30,7 +30,7 @@
          title="处方脱水量"
          :icon="cljdImg"
          background-color="#ffffff"
          class="row1-col2-row2"
          class="mini-card row1-col2-row2"
          header-class-name="mihi-header"
        >
          <div class="item-box prescription-ehydration-olume">
@@ -46,7 +46,7 @@
          title="置换总量"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row1-col3-row1"
          class="mini-card row1-col3-row1"
          header-class-name="mihi-header"
        >
          <div class="item-box total-amount-replacement">
@@ -57,7 +57,7 @@
          title="透析时长"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row1-col3-row2"
          class="mini-card row1-col3-row2"
          header-class-name="mihi-header"
        >
          <div class="item-box dialysis-duration">
@@ -70,7 +70,7 @@
          title="透析器"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row1-col4-row1"
          class="mini-card row1-col4-row1"
          header-class-name="mihi-header"
        >
          <div class="item-box dialyzer">
@@ -81,7 +81,7 @@
          title="抗凝剂"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row1-col4-row2"
          class="mini-card row1-col4-row2"
          header-class-name="mihi-header"
        >
          <div class="item-box anticoagulant">
@@ -141,7 +141,7 @@
          title="处方备注"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row1-col5-row2"
          class="mini-card row1-col5-row2"
          header-class-name="mihi-header"
        >
          <div class="item-box prescription-remarks">
@@ -157,7 +157,7 @@
            title="处方血流量"
            :icon="zlmsImg"
            background-color="#ffffff"
            class="row2-col1-row1-col1"
            class="mini-card row2-col1-row1-col1"
            header-class-name="mihi-header"
          >
            <div class="item-box blood-flow">
@@ -168,7 +168,7 @@
            title="处方钠"
            :icon="zlmsImg"
            background-color="#ffffff"
            class="row2-col1-row1-col2"
            class="mini-card row2-col1-row1-col2"
            header-class-name="mihi-header"
          >
            <div class="item-box prescription-sodium">
@@ -181,7 +181,7 @@
            title="透析液流量"
            :icon="zlmsImg"
            background-color="#ffffff"
            class="row2-col1-row2-col1"
            class="mini-card row2-col1-row2-col1"
            header-class-name="mihi-header"
          >
            <div class="item-box dialysis-fluid-flow-rate">
@@ -192,7 +192,7 @@
            title="透析液种类"
            :icon="zlmsImg"
            background-color="#ffffff"
            class="row2-col1-row2-col2"
            class="mini-card row2-col1-row2-col2"
            header-class-name="mihi-header"
          >
            <div class="item-box types-dialysis-fluid">
@@ -205,7 +205,7 @@
          title="治疗状态"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="row2-col1-row3"
          class="mini-card row2-col1-row3"
          header-class-name="mihi-header"
        >
          <div class="item-box treatment-status">
@@ -218,7 +218,7 @@
          title="参考指标"
          :icon="zlmsImg"
          background-color="#ffffff"
          class="mini-card reference-indicators"
          class="reference-indicators"
          header-class-name="mihi-header"
        >
          <template #right>
@@ -227,7 +227,7 @@
          <table class="item-box reference-indicators-content">
            <tbody>
              <tr>
                <td>血压<br />超滤量<br />{{ pageData.上次透析单所属日期 }}</td>
                <td>血压<br />超滤量<br /></td>
                <td
                  ref="bloodPressureRectangularChart"
                  style="overflow: hidden"
@@ -237,20 +237,19 @@
              </tr>
              <tr>
                <td>干体重</td>
                <td>{{ pageData.干体重 }}kg</td>
                <td>{{ fourPointBloodPressureMap.干体重 }}kg</td>
              </tr>
              <tr>
                <td>体重增长</td>
                <td>
                <td class="flex-td">
                  <span class="sub-text">(透前-上次透后)</span
                  >{{ pageData.体重增长_透前_上次透后 }}kg
                  ><span class="right-text">{{ weightGain1 }}kg</span>
                </td>
              </tr>
              <tr>
                <td>体重增长</td>
                <td>
                  <span class="sub-text">(透前-干体重)</span
                  >{{ pageData.体重增持_透前_干体重 }}kg
                <td class="flex-td">
                  <span class="sub-text">(透前-干体重)</span><span class="text-right">{{ weightGain2 }}kg</span>
                </td>
              </tr>
              <!-- <tr>
@@ -259,15 +258,15 @@
              </tr> -->
              <tr>
                <td>透前体重</td>
                <td>{{ pageData.透前体重 }}kg</td>
                <td>{{ fourPointBloodPressureMap?.透前体重 }}kg</td>
              </tr>
              <tr>
                <td>上次透后体重</td>
                <td>{{ pageData.上次透后体重 }}kg</td>
                <td>透后体重</td>
                <td>{{ fourPointBloodPressureMap?.透后体重 }}kg</td>
              </tr>
              <tr>
                <td>透析时间</td>
                <td>{{ pageData.上次透析单所属日期 }}</td>
                <td>{{ fourPointBloodPressureMap?.透析时间 }}</td>
              </tr>
            </tbody>
          </table>
@@ -319,6 +318,7 @@
import Card from "../components/Card.vue";
import DoctorAdvice from "../components/DoctorAdvice/index.vue";
import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
import type { 四点血压图数据 } from "@/store/type/bedsideAuxiliaryScreen.type";
import tslImg from "@/img/tsl.png";
import dingShiImg from "@/img/dingshi2.png";
import jiaoHaoImg from "@/img/jiaoHao.png";
@@ -356,13 +356,54 @@
  });
});
const fourPointBloodPressureMap = computed(() => {
  let result = {};
  if (
    pageData.value.四点血压图数据 &&
    pageData.value.四点血压图数据.length > 0
  ) {
    result = pageData.value.四点血压图数据[0];
  }
  return result;
});
const nowDateText = computed(() => {
  if (pageData.value.本次透析单所属日期) {
    let result = dayjs(pageData.value.本次透析单所属日期).format("YYYY-MM-DD");
    result += `(${dayjs(pageData.value.本次透析单所属日期).format("ddd")})`;
  if (fourPointBloodPressureMap.value?.透析日期) {
    let result = dayjs(fourPointBloodPressureMap.value?.透析日期).format(
      "YYYY-MM-DD"
    );
    result += `(${dayjs(fourPointBloodPressureMap.value?.透析日期).format(
      "ddd"
    )})`;
    return result;
  }
  return "";
});
const weightGain1 = computed(() => {
  if (
    pageData.value.四点血压图数据 &&
    pageData.value.四点血压图数据.length > 1
  ) {
    const value =
      pageData.value.四点血压图数据[0].透前体重 -
      pageData.value.四点血压图数据[1].透后体重;
    const formattedValue = Number.isInteger(value)
      ? value
      : Number(value.toFixed(1));
    return formattedValue;
  }
  return "";
});
const weightGain2 = computed(() => {
  const value =
    fourPointBloodPressureMap.value.透前体重 -
    fourPointBloodPressureMap.value.干体重;
  const formattedValue = Number.isInteger(value)
    ? value
    : Number(value.toFixed(1));
  return formattedValue;
});
/** 点击定时任务 */
@@ -381,186 +422,161 @@
    type: "warning",
  });
};
const genderBloodPressureRectangularChart = (datas: any) => {
  if (bloodPressureRectangularChart.value) {
    const benchmarkData = {
      width: 386,
      height: 280,
    };
    // 获取容器实际宽高
    const containerWidth = bloodPressureRectangularChart.value.offsetWidth;
    const containerHeight = bloodPressureRectangularChart.value.offsetHeight;
    // 等比例缩放因子
    const scale = Math.min(
      containerWidth / benchmarkData.width,
      containerHeight / benchmarkData.height
    );
    // 拿到 canvas
    let canvas = bloodPressureRectangularChart.value.querySelector("canvas");
    if (!canvas) {
      canvas = document.createElement("canvas");
      bloodPressureRectangularChart.value.appendChild(canvas);
    }
const genderBloodPressureRectangularChart = (datas: 四点血压图数据[] | null) => {
  if (!bloodPressureRectangularChart.value) return;
    // 设置 canvas 尺寸
    canvas.width = benchmarkData.width * scale;
    canvas.height = benchmarkData.height * scale;
    canvas.style.width = `${canvas.width}px`;
    canvas.style.height = `${canvas.height}px`;
  const benchmarkData = { width: 386, height: 280 };
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
  // 获取容器宽高(90% 缩放)
  const containerWidth = bloodPressureRectangularChart.value.offsetWidth * 0.9;
  const containerHeight = bloodPressureRectangularChart.value.offsetHeight * 0.9;
    // 清除画布
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  // 获取设备像素比
  const dpr = window.devicePixelRatio || 1;
    // 按缩放因子缩放绘制环境
    ctx.save();
    // ctx.scale(scale, scale);
  // 等比例缩放因子(保持比例)
  const scale = Math.min(
    containerWidth / benchmarkData.width,
    containerHeight / benchmarkData.height
  );
    // 设置字体样式
    ctx.font = `12px Arial`;
    ctx.textAlign = "center";
  // 计算实际画布 CSS 尺寸
  const cssWidth = benchmarkData.width * scale;
  const cssHeight = benchmarkData.height * scale;
    // 处理数据
    const measurements = [
      { systolic: 143, diastolic: 74 },
      { systolic: 136, diastolic: 71 },
      { systolic: 139, diastolic: 73 },
      { systolic: 139, diastolic: 73 },
    ];
    // if (datas && datas.血压1_透前收缩压) {
    //   measurements[0].systolic = datas?.血压1_透前收缩压 ?? null;
    //   measurements[0].diastolic = datas?.血压1_透前舒张压 ?? null;
    //   measurements[1].systolic = datas?.血压2_前半程最低收缩压 ?? null;
    //   measurements[1].diastolic = datas?.血压2_前半程最低舒张压 ?? null;
    //   measurements[2].systolic = datas?.血压3_后半程最低收缩压 ?? null;
    //   measurements[2].diastolic = datas?.血压3_后半程最低舒张压 ?? null;
    //   measurements[3].systolic = datas?.血压4_透后收缩压 ?? null;
    //   measurements[3].diastolic = datas?.血压4_透后舒张压 ?? null;
    // }
    const chartHeight = canvas.height;
    const chartWidth = canvas.width;
    // 限所在位置 200
    const upperLimitY = chartHeight * 0.5;
    ctx.beginPath();
    ctx.moveTo(0, upperLimitY);
    ctx.lineTo(chartWidth, upperLimitY);
    ctx.strokeStyle = "red";
    ctx.lineWidth = 1;
    ctx.stroke();
    // 下限所在位置 140
    const lowerLimitY = chartHeight * (1 - 0.2857);
    console.log("lowerLimitY:", lowerLimitY);
    ctx.beginPath();
    ctx.moveTo(0, lowerLimitY);
    ctx.lineTo(chartWidth, lowerLimitY);
    ctx.strokeStyle = "blue";
    ctx.lineWidth = 1;
    ctx.stroke();
    // 绘制收缩压折线图
    const measurementWidth = canvas.width / (measurements.length + 1);
    // 收缩压线
    let systolicEnd = { x: null, y: null };
    ctx.beginPath();
    ctx.moveTo(
      measurementWidth,
      chartHeight - measurements[0].systolic * scale
    );
    for (let i = 1; i < measurements.length; i++) {
      const x = (i + 1) * measurementWidth;
      ctx.lineTo(x, chartHeight - measurements[i].systolic * scale);
      if (i === measurements.length - 1) {
        systolicEnd.x = x;
        systolicEnd.y = chartHeight - measurements[i].systolic * scale;
      }
    }
    ctx.strokeStyle = "black";
    ctx.lineWidth = 1;
    ctx.stroke();
    // 舒张压线
    let diastolicEnd = { x: null, y: null };
    ctx.beginPath();
    ctx.moveTo(
      measurementWidth,
      chartHeight - measurements[0].diastolic * scale
    );
    for (let i = 1; i < measurements.length; i++) {
      const x = (i + 1) * measurementWidth;
      ctx.lineTo(x, chartHeight - measurements[i].diastolic * scale);
      if (i === measurements.length - 1) {
        diastolicEnd.x = x;
        diastolicEnd.y = chartHeight - measurements[i].diastolic * scale;
      }
    }
    // 连接收缩压和舒张压的起始点和结束点
    ctx.moveTo(
      measurementWidth,
      chartHeight - measurements[0].systolic * scale
    );
    ctx.lineTo(
      measurementWidth,
      chartHeight - measurements[0].diastolic * scale
    );
    ctx.moveTo(systolicEnd.x, systolicEnd.y);
    ctx.lineTo(diastolicEnd.x, diastolicEnd.y);
    ctx.strokeStyle = "black";
    ctx.lineWidth = 1;
    ctx.stroke();
    const baseFontSize = 24;
    ctx.font = `${baseFontSize * scale}px Arial`;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillStyle = "black";
    measurements.forEach((m, i) => {
      const x = (i + 1) * measurementWidth;
      ctx.fillText(
        m.systolic.toString(),
        x,
        chartHeight - m.systolic * scale - 5
      );
      ctx.fillText(
        m.diastolic.toString(),
        x,
        chartHeight - m.diastolic * scale + 10
      );
    });
    // 绘制圆柱体
    const 计算脱水量刻度 = 100 / datas.超滤总量;
    const cylinderX = canvas.width * 0.9; // 圆柱体中心X坐标
    const cylinderY = canvas.height; // 圆柱体中心Y坐标
    const cylinderRadius = 6 * scale; // 圆柱体半径
    const cylinderHeight = 计算脱水量刻度 * datas.超滤总量 || 20; // 圆柱体高度
    const 超滤总量 = datas.超滤总量 || "0 L"; // 超滤总量
    const 脱水百分比 = datas.脱水百分比 || 0; // 脱水百分比
    const 透后体重减干体重的差值 = datas.透后体重减干体重的差值 || 0; // 透后体重减干体重的差值
    drawCylinder(
      ctx,
      cylinderX,
      cylinderY,
      cylinderRadius,
      cylinderHeight,
      超滤总量,
      脱水百分比,
      透后体重减干体重的差值
    );
  // 获取 canvas
  let canvas = bloodPressureRectangularChart.value.querySelector("canvas");
  if (!canvas) {
    canvas = document.createElement("canvas");
    bloodPressureRectangularChart.value.appendChild(canvas);
  }
  // 物理像素
  canvas.width = cssWidth * dpr;
  canvas.height = cssHeight * dpr;
  canvas.style.width = `${cssWidth}px`;
  canvas.style.height = `${cssHeight}px`;
  const ctx = canvas.getContext("2d");
  if (!ctx) return;
  // 先清除画布(按物理像素)
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // 缩放到实际坐标系(dpr & scale)
  ctx.save();
  ctx.scale(dpr * scale, dpr * scale);
  // 基准坐标系:benchmarkData.width × benchmarkData.height
  const chartWidth = benchmarkData.width;
  const chartHeight = benchmarkData.height;
  // ========== 绘制基线 ==========
  const upperLimitY = chartHeight * 0.5; // 200
  ctx.beginPath();
  ctx.moveTo(0, upperLimitY);
  ctx.lineTo(chartWidth, upperLimitY);
  ctx.strokeStyle = "red";
  ctx.lineWidth = 1;
  ctx.stroke();
  const lowerLimitY = chartHeight * (1 - 0.2857); // 140
  ctx.beginPath();
  ctx.moveTo(0, lowerLimitY);
  ctx.lineTo(chartWidth, lowerLimitY);
  ctx.strokeStyle = "blue";
  ctx.lineWidth = 1;
  ctx.stroke();
  // ========== 血压数据 ==========
  const measurements = [
    { systolic: datas?.[0]?.血压1_透前收缩压 ?? 0, diastolic: datas?.[0]?.血压1_透前舒张压 ?? 0 },
    { systolic: datas?.[0]?.血压2_前半程最低收缩压 ?? 0, diastolic: datas?.[0]?.血压2_前半程最低舒张压 ?? 0 },
    { systolic: datas?.[0]?.血压3_后半程最低收缩压 ?? 0, diastolic: datas?.[0]?.血压3_后半程最低舒张压 ?? 0 },
    { systolic: datas?.[0]?.血压4_透后收缩压 ?? 0, diastolic: datas?.[0]?.血压4_透后舒张压 ?? 0 },
  ];
  const measurementWidth = chartWidth / (measurements.length + 1);
  // 收缩压线
  let systolicEnd = { x: 0, y: 0 };
  ctx.beginPath();
  ctx.moveTo(measurementWidth, chartHeight - measurements[0].systolic);
  for (let i = 1; i < measurements.length; i++) {
    const x = (i + 1) * measurementWidth;
    ctx.lineTo(x, chartHeight - measurements[i].systolic);
    if (i === measurements.length - 1) {
      systolicEnd = { x, y: chartHeight - measurements[i].systolic };
    }
  }
  ctx.strokeStyle = "black";
  ctx.stroke();
  // 舒张压线
  let diastolicEnd = { x: 0, y: 0 };
  ctx.beginPath();
  ctx.moveTo(measurementWidth, chartHeight - measurements[0].diastolic);
  for (let i = 1; i < measurements.length; i++) {
    const x = (i + 1) * measurementWidth;
    ctx.lineTo(x, chartHeight - measurements[i].diastolic);
    if (i === measurements.length - 1) {
      diastolicEnd = { x, y: chartHeight - measurements[i].diastolic };
    }
  }
  ctx.strokeStyle = "black";
  ctx.stroke();
  // 连接起始 & 结束
  ctx.beginPath();
  ctx.moveTo(measurementWidth, chartHeight - measurements[0].systolic);
  ctx.lineTo(measurementWidth, chartHeight - measurements[0].diastolic);
  ctx.moveTo(systolicEnd.x, systolicEnd.y);
  ctx.lineTo(diastolicEnd.x, diastolicEnd.y);
  ctx.stroke();
  // ========== 文本 ==========
  const baseFontSize = 24;
  ctx.font = `${baseFontSize}px Arial`;
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillStyle = "black";
  measurements.forEach((m, i) => {
    const x = (i + 1) * measurementWidth;
    ctx.fillText(m.systolic.toString(), x, chartHeight - m.systolic - 5);
    ctx.fillText(m.diastolic.toString(), x, chartHeight - m.diastolic + 10);
  });
  // ========== 圆柱体 ==========
  const 计算脱水量刻度 = 100 / (datas?.[0]?.超滤总量 || 1);
  const cylinderX = chartWidth * 0.9;
  const cylinderY = chartHeight;
  const cylinderRadius = 6;
  const cylinderHeight = 计算脱水量刻度 * (datas?.[0]?.超滤总量 || 0);
  drawCylinder(
    ctx,
    chartHeight,
    1, // 因为已经 scale 过了
    cylinderX,
    cylinderY,
    cylinderRadius,
    cylinderHeight,
    datas?.[0]?.超滤总量?.toString() ?? "0 L",
    datas?.[0]?.脱水百分比 ?? 0,
    datas?.[0]?.透后体重减干体重的差值 ?? 0
  );
  ctx.restore(); // 恢复
};
const drawCylinder = (
  ctx: CanvasRenderingContext2D,
  canvasHeight: number,
  scale: number,
  x: number,
  y: number,
  radius: number,
@@ -593,21 +609,23 @@
  ctx.fill();
  ctx.stroke();
  const baseFontSize = 16;
  // 添加文本说明
  ctx.font = "16px Arial";
  ctx.font = `${baseFontSize * scale}px Arial`;
  ctx.textAlign = "center";
  ctx.fillStyle = "#409EFF";
  ctx.fillText(超滤总量, 180, 280 - height - 10); // 文本位于圆柱上方一点
  ctx.fillText(超滤总量, x, canvasHeight - height - 5); // 文本位于圆柱上方一点
  if (透后体重减干体重的差值 > 0) {
    ctx.font = "16px Arial";
    ctx.font = `${baseFontSize * scale}px Arial`;
    ctx.textAlign = "center";
    ctx.fillStyle = "#000000";
    ctx.fillText(透后体重减干体重的差值 + "", x, 280); // 文本位于圆柱上方一点
    ctx.fillText(透后体重减干体重的差值 + "", x, canvasHeight - 5); // 文本位于圆柱上方一点
  }
};
onMounted(() => {
  genderBloodPressureRectangularChart({});
  genderBloodPressureRectangularChart(pageData.value.四点血压图数据);
});
</script>
<style lang="less" scoped>
@@ -724,7 +742,7 @@
          .dialyzer {
            font-family: PingFangSC, PingFang SC;
            font-weight: 600;
            font-size: 11px;
            font-size: 9px;
            color: #333333;
            text-align: center;
            font-style: normal;
@@ -943,6 +961,17 @@
}
.item-box {
  height: 100%;
  overflow-y: auto !important;
}
:deep(.mini-header) {
  flex: 0 0 4px !important;
  .card-icon {
    width: 4px !important;
    height: 4px !important;
  }
  .card-title {
    font-size: 4px !important;
  }
}
</style>
// <style lang="less">
@@ -980,6 +1009,7 @@
      font-style: normal;
    }
    & td:last-child {
      position: relative;
      width: 64%;
      border-right: none;
      font-family: PingFangSC, PingFang SC;
@@ -988,11 +1018,26 @@
      color: #333333;
      text-align: center;
      font-style: normal;
      &.flex-td {
        display: flex;
        align-items: center;
        justify-content: space-around;
        width: 100%;
      }
      .sub-text {
        font-size: 3.2px;
        font-size: 3px;
        color: #666;
        margin-right: 1.2px;
         white-space: nowrap;
      }
      // .text-right {
      //   position: absolute;
      //   right: 0;
      //   top: 50%;
      //   transform: translateY(-50%);
      //   font-size: 3px;
      //   color: #666;
      // }
    }
    & tr:not(:first-child) td {
      height: 6px;