单应用项目,可以创建很多独立工具类页面 ,不用登录 初始化的页面
zhangchen
2025-09-16 2a8070b96f4aec8059ea96935b9166aec75b188b
ID1766-结束透析完成
5个文件已修改
1个文件已添加
506 ■■■■■ 已修改文件
postcss.config.js 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/patient_hemo_med_start/index.ts 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/patient_hemo_med_start/types/index.type.ts 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobile/bedsideAuxiliaryScreen/components/EndDialysis/index.vue 360 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
postcss.config.js
@@ -1,24 +1,41 @@
// module.exports = {
//   plugins: {
//     'postcss-pxtorem': {
//       rootValue: 37.5,
//       propList: ['*'],
//       include: file => {
//         if (!file) return false;
//         const normalized = file.replace(/\\/g, '/');
//         // 只转换 mobile 目录里的样式 OR element-plus 目录里的样式
//         // 但 element-plus 样式只在 mobile 目录被引用时才生效,需保证引用范围
//         return normalized.includes('/src/views/mobile/') || normalized.includes('/node_modules/element-plus/');
//       },
//       exclude: file => {
//         if (!file) return false;
//         const normalized = file.replace(/\\/g, '/');
//         // 排除除 element-plus 外的 node_modules,防止无关样式被转
//         if (/node_modules/.test(normalized) && !normalized.includes('/node_modules/element-plus/')) {
//           return true;
//         }
//         return false;
//       },
//       minPixelValue: 2,
//     }
//   }
// }
module.exports = {
  plugins: {
    'postcss-pxtorem': {
      rootValue: 37.5,
      propList: ['*'],
      include: file => {
        if (!file) return false;
        const normalized = file.replace(/\\/g, '/');
        // 只转换 mobile 目录里的样式 OR element-plus 目录里的样式
        // 但 element-plus 样式只在 mobile 目录被引用时才生效,需保证引用范围
        return normalized.includes('/src/views/mobile/') || normalized.includes('/node_modules/element-plus/');
      },
      exclude: file => {
        if (!file) return false;
        const normalized = file.replace(/\\/g, '/');
        // 排除除 element-plus 外的 node_modules,防止无关样式被转
        if (/node_modules/.test(normalized) && !normalized.includes('/node_modules/element-plus/')) {
          return true;
        }
        return false;
      },
      // ✅ 用正则匹配路径,不依赖字符串 includes
      include: [
        /src[\/\\]views[\/\\]mobile/, // 只转 mobile 目录
        /node_modules[\/\\]element-plus/ // 转 element-plus 样式
      ],
      // ✅ 排除其他 node_modules
      exclude: (file) => /node_modules/.test(file) && !/node_modules[\/\\]element-plus/.test(file),
      minPixelValue: 2,
    }
  }
src/api/patient_hemo_med_start/index.ts
@@ -1,12 +1,17 @@
import request from "@/utils/axios";
import type { StartRecord } from "../patient_hemo_med_start/types/index.type";
import type {
  StartRecord,
  RecordData,
} from "../patient_hemo_med_start/types/index.type";
/**
 * 获取开始透析数据api
 * @param params `recordCode=${recordCode}`
 * @returns
 * @returns
 */
export function addDefaultRowApi(params: string) :Promise<{ data: StartRecord }> {
export function addDefaultRowApi(
  params: string
): Promise<{ data: StartRecord }> {
  return request({
    url: "/patient/hemo/med/start/addDefaultRow",
    method: "post",
@@ -19,13 +24,44 @@
/**
 * 修改开始透析数据api
 * @param params
 * @returns
 */
export function updateMedstartDataApi(params: StartRecord) {
  return request({
    url: "/patient/hemo/med/start/update",
    method: "post",
    data: params,
  });
}
/**
 * 获取结束透析数据api
 * @param params `recordCode=${recordCode}`
 * @returns
 */
export function addDefaultEndRowApi(
  params: string
): Promise<{ data: RecordData }> {
  return request({
    url: "/patient/hemo/med/end/addDefaultRow",
    method: "post",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    data: params,
  });
}
/**
 * 修改结束透析数据api
 * @param params 
 * @returns 
 */
export function updateMedstartDataApi(params: StartRecord) {
    return request({
        url: '/patient/hemo/med/start/update',
        method: 'post',
        data: params,
    });
}
export function updateEndRowApi(params: RecordData) {
  return request({
    url: "/patient/hemo/med/end/update",
    method: "post",
    data: params,
  });
}
src/api/patient_hemo_med_start/types/index.type.ts
@@ -46,6 +46,25 @@
  startYcNurse: string;
  startYcNurseName: string;
  startYingxue: string;
  updateTime: string; // "2025-09-12 17:06:42"
  updateTime: string;
  updateUser: string | null;
}
export interface RecordData {
  code: string;
  createTime: string;
  createUser: string | null;
  deletedTime: string | null;
  endDownNurse: string;
  endDownNurseName: string;
  endHuixue: string;
  endTime: string;
  id: number | null;
  isDeleted: number | null;
  lastTimeMonitorDataTime: string;
  monitorDataCode: string;
  recordCode: string;
  remark: string;
  updateTime: string;
  updateUser: string | null;
}
src/main.ts
@@ -10,6 +10,8 @@
import VConsole from 'vconsole'
import { createPinia } from 'pinia'
import '@/assets/css/iconfont.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
if (import.meta.env.VITE_ENV === 'development') {
// 如果需要在手机平板上打开控制台,安装一个这个
    const vConsole = new VConsole()
@@ -18,4 +20,4 @@
const app = createApp(App)
app.use(router).use(pinia).use(ElementPlus).use(Vant).mount('#app')
app.use(router).use(pinia).use(ElementPlus, { locale: zhCn }).use(Vant).mount('#app')
src/views/mobile/bedsideAuxiliaryScreen/components/EndDialysis/index.vue
New file
@@ -0,0 +1,360 @@
<template>
  <div class="end-dialysis-container">
    <el-dialog
      v-model="show"
      center
      title="结束透析"
      width="80%"
      :show-close="false"
      class="end-dialysis-dialog"
      :destroy-on-close="true"
      :close-on-click-modal="false"
    >
      <template #header>
        <div class="end-dialysis-header">
          <span class="header-title">结束透析</span>
          <img
            :src="closeImg"
            class="header-close"
            @click="handleCancel"
            alt=""
          />
        </div>
      </template>
      <div class="end-dialysis-content" v-loading="loading">
        <el-form :model="formData" size="large">
          <el-row :gutter="10">
            <el-col :span="24">
              <el-form-item label="结束时间">
                <el-row>
                  <el-col :span="8">
                    <el-date-picker
                      v-model="formData.endData"
                      :clearable="false"
                      type="date"
                      placeholder="选择日期"
                      format="YYYY/MM/DD"
                      value-format="YYYY-MM-DD"
                      style="width: 100%"
                    />
                  </el-col>
                  <el-col :span="8">
                    <el-time-select
                      :clearable="false"
                      v-model="formData.endTime"
                      start="00:00"
                      step="00:01"
                      end="23:59"
                      placeholder="选择时间"
                      style="width: 100%"
                    />
                  </el-col>
                  <el-col :span="3">
                    <el-button type="primary" @click="addTime(1)"
                      >时间+1</el-button
                    >
                  </el-col>
                  <el-col :span="3">
                    <el-button type="primary" @click="addTime(0.5)"
                      >时间+0.5</el-button
                    >
                  </el-col>
                </el-row>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="10">
            <el-col :span="8">
              <el-form-item label="下机护士">
                <el-select
                  style="width: 100%"
                  v-model="formData.endDownNurse"
                  placeholder="请选择"
                >
                  <el-option
                    v-for="item in nurseOptions"
                    :key="item.code"
                    :label="item.userName"
                    :disabled="item.isValid === 0"
                    :value="item.code"
                  >
                  </el-option>
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="回血(ml/min)">
                <el-input style="width: 100%" v-model="formData.endHuixue" />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </div>
      <template #footer>
        <div class="my-button cancel" @click="handleCancel">取消</div>
        <div
          class="my-button confirm"
          :class="loading ? 'cancel' : ''"
          @click="handleConfirm"
        >
          确认
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script lang="ts">
import { computed, reactive, toRefs } from "vue";
import closeImg from "@/img/close.png";
import {
  addDefaultEndRowApi,
  updateEndRowApi,
} from "@/api/patient_hemo_med_start/index";
import type { RecordData } from "@/api/patient_hemo_med_start/types/index.type";
import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
import dayjs from "dayjs";
import { getUsersByRoleCodeApi } from "@/api/user/index";
import { ElMessage } from "element-plus";
interface FormData {
  id: number;
  recordCode: string;
  endTime: string;
  endDownNurse: string;
  endDownNurseName: string;
  lastTimeMonitorDataTime: string;
  endHuixue: string;
  endData: string;
}
interface State {
  show: boolean;
  loading: boolean;
  formData: FormData;
  nurseOptions: any[];
  defaultEndTime: string;
}
export default {
  name: "EndDialysis",
  setup() {
    const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
    const state = reactive<State>({
      show: false,
      loading: false,
      formData: {
        id: 0,
        recordCode: "",
        endTime: "",
        endDownNurse: "",
        endDownNurseName: "",
        lastTimeMonitorDataTime: "",
        endHuixue: "",
        endData: "",
      },
      nurseOptions: [],
      defaultEndTime: "", // 默认的日期,原始数据,用于计算
    });
    const recordCode = computed(() => {
      return bedsideAuxiliaryScreenStore.deviceData.underTreatment.透析单编号;
    });
    const clientCode = computed(() => {
      return bedsideAuxiliaryScreenStore.deviceData.客户编号;
    });
    const userCode = computed(() => {
      return bedsideAuxiliaryScreenStore.userInfo.userCode;
    });
    const openDialog = async () => {
      state.loading = true;
      state.show = true;
      try {
        const { data } = await addDefaultEndRowApi(
          `recordCode=${recordCode.value}`
        );
        const dataCopy = JSON.parse(JSON.stringify(data));
        const notLs = [null, ""];
        if (notLs.includes(data.endDownNurse)) {
          dataCopy.endDownNurse = userCode.value;
        }
        if (notLs.includes(data.endTime)) {
          dataCopy.endTime = dayjs().format("HH:mm");
          // @ts-ignore
          dataCopy.endData = dayjs().format("YYYY-MM-DD");
          state.defaultEndTime = dayjs().format("YYYY-MM-DD HH:mm");
        } else {
          dataCopy.endTime = dayjs(data.endTime).format("HH:mm");
          // @ts-ignore
          dataCopy.endData = dayjs(data.endTime).format("YYYY-MM-DD");
          state.defaultEndTime = dayjs(data.endTime).format("YYYY-MM-DD HH:mm");
        }
        state.formData = dataCopy as unknown as FormData;
        await getNurses();
      } catch (error) {
        setTimeout(() => {
          state.show = false;
        }, 1000);
      } finally {
        state.loading = false;
      }
    };
    const handleCancel = () => {
      state.show = false;
    };
    const handleConfirm = async () => {
      if (state.loading) return false;
      state.loading = true;
      try {
        const paramsData = Object.assign({}, state.formData, {
          endTime: dayjs(
            `${state.formData.endData} ${state.formData.endTime}`
          ).format("YYYY-MM-DD HH:mm:ss"),
        });
        await updateEndRowApi(paramsData as unknown as RecordData);
        ElMessage.success("操作成功!");
        state.show = false;
      } finally {
        state.loading = false;
      }
    };
    const addTime = (hourNum: number) => {
      if (["", null].includes(state.formData.lastTimeMonitorDataTime))
        return false;
      const addDate = addHours(
        state.formData.lastTimeMonitorDataTime + "",
        hourNum
      );
      state.formData.endData = dayjs(addDate).format("YYYY-MM-DD");
      state.formData.endTime = dayjs(addDate).format("HH:mm");
    };
    const addHours = (dateStr: string, hours: number): string => {
      return dayjs(dateStr).add(hours, "hour").format("YYYY-MM-DD HH:mm:ss");
    };
    /**
     * 获取护士数据
     */
    const getNurses = async () => {
      const { data } = await getUsersByRoleCodeApi(
        `clientCode=${clientCode.value}&roleClass=nurse`
      );
      state.nurseOptions = data;
    };
    return {
      ...toRefs(state),
      closeImg,
      handleCancel,
      handleConfirm,
      openDialog,
      addTime,
    };
  },
};
</script>
<style lang="less" scoped>
.end-dialysis-container {
  ::v-deep(.el-dialog) {
    padding: 0;
    border-radius: 6px;
    overflow: hidden;
  }
  ::v-deep(.el-dialog__footer) {
    padding: 4px;
  }
  ::v-deep(.el-upload-dragger) {
    height: 65px;
    padding: 0 !important;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  ::v-deep(.el-upload-dragger .el-icon--upload) {
    display: none;
  }
  ::v-deep(.el-dialog__header) {
    padding-bottom: 6px;
  }
  .end-dialysis-header {
    position: relative;
    height: 16px;
    background: #769aff;
    .header-title {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translateX(-50%) translateY(-50%);
      font-family: AlibabaPuHuiTi, AlibabaPuHuiTi;
      font-weight: 500;
      font-size: 8px;
      color: #ffffff;
      line-height: 11px;
      text-align: center;
    }
    .header-close {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      right: 6px;
      width: 15px;
      height: 15px;
      transition: transform 0.2s;
      &:active {
        opacity: 0.6;
        transform: translateY(-50%) scale(0.95);
      }
    }
  }
  .end-dialysis-content {
    padding: 0 12px 0px 12px;
    margin-bottom: 4px;
    border-bottom: 1px solid #d8d8d8;
  }
  .my-button {
    display: inline-block;
    border-radius: 2px;
    padding: 0px 10px;
    font-family: PingFangSC, PingFang SC;
    font-weight: 500;
    font-size: 7px;
    color: #ffffff;
    line-height: 16px;
    letter-spacing: 1px;
    text-align: center;
    font-style: normal;
    transition: transform 0.1s ease, opacity 0.1s ease;
    cursor: pointer;
    &:active {
      transform: scale(0.95);
      opacity: 0.8;
    }
    &:not(:first-child) {
      margin-left: 6px;
    }
    &.confirm {
      background: #769aff;
    }
    &.cancel {
      background: #bbc6dd;
    }
    &.refresh {
      background: #e6a23c;
    }
  }
}
</style>
src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
@@ -330,6 +330,8 @@
    </div>
    <!-- 定时任务 -->
    <ScheduledTaskDialog ref="scheduledTaskDialogRef" />
    <!-- 结束透析组件 -->
    <EndDialysis ref="endDialysisRef" />
  </div>
</template>
<script lang="ts" setup name="UnderTreatment">
@@ -354,6 +356,7 @@
const ScheduledTaskDialog = defineAsyncComponent(
  () => import("../components/ScheduledTask.vue")
);
const EndDialysis = defineAsyncComponent(() => import("../components/EndDialysis/index.vue"));
import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
import {
  formatSubstituteMode,
@@ -389,6 +392,7 @@
const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
const scheduledTaskDialogRef = ref<any>(null);
const endDialysisRef = ref<any>(null);
// ktv趋势图的
const ktvListEchartRef = ref<HTMLElement | null>(null);
@@ -784,10 +788,14 @@
/** 结束透析 */
const onEndClick = () => {
  ElMessage({
    message: "功能开发中,敬请期待!",
    type: "warning",
  });
  if (
    !bedsideAuxiliaryScreenStore.deviceCode ||
    !bedsideAuxiliaryScreenStore.deviceData.deviceCode
  )
    return ElMessage.warning("未初始化或正在进行初始化操作中");
  if (!bedsideAuxiliaryScreenStore.userInfo?.token)
    return ElMessage.warning("请登录");
  endDialysisRef.value?.openDialog();
};
onMounted(() => {