From a99886eb9c73018235e2c373f3d82a2b0b2311d5 Mon Sep 17 00:00:00 2001
From: zhangchen <1652267879@qq.com>
Date: 星期二, 16 九月 2025 13:36:40 +0800
Subject: [PATCH] Merge branch 'ID1766-添加推送登录功能' into test
---
src/api/user/index.ts | 17
src/api/patient_hemo_med_start/types/index.type.ts | 70 ++
src/utils/httpApi.ts | 18
src/assets/font/iconfont.woff | 0
src/api/patient_hemo_med_start/index.ts | 67 +
src/api/dict/types/index.type.ts | 9
src/store/type/user.type.ts | 27
src/api/dict/index.ts | 14
src/assets/font/iconfont.woff2 | 0
src/assets/font/iconfont.ttf | 0
src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue | 91 +
src/utils/axios.ts | 134 +++
src/api/inventory/itemDict.ts | 15
src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue | 34
src/store/bedsideAuxiliaryScreen.ts | 29
src/api/user.ts | 16
src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue | 26
src/views/mobile/bedsideAuxiliaryScreen/components/StartDialysis/index.vue | 865 +++++++++++++++++++++++++
src/main.ts | 4
src/views/mobile/bedsideAuxiliaryScreen/components/Login/userInfo.vue | 70 +
src/views/mobile/bedsideAuxiliaryScreen/components/EndDialysis/index.vue | 360 ++++++++++
src/store/type/bedsideAuxiliaryScreen.type.ts | 19
src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue | 34
src/assets/css/iconfont.css | 7
src/api/inventory/types/itemDict.type.ts | 6
src/api/commom.type.ts | 6
postcss.config.js | 49
27 files changed, 1,868 insertions(+), 119 deletions(-)
diff --git a/postcss.config.js b/postcss.config.js
index 86ee644..d4d24ba 100644
--- a/postcss.config.js
+++ b/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,
}
}
diff --git a/src/api/commom.type.ts b/src/api/commom.type.ts
new file mode 100644
index 0000000..431408a
--- /dev/null
+++ b/src/api/commom.type.ts
@@ -0,0 +1,6 @@
+export interface ListParams {
+ page: number;
+ size: number;
+ wherecondition: string;
+ ordercondition: string;
+}
\ No newline at end of file
diff --git a/src/api/dict/index.ts b/src/api/dict/index.ts
new file mode 100644
index 0000000..8a531a6
--- /dev/null
+++ b/src/api/dict/index.ts
@@ -0,0 +1,14 @@
+import request from "@/utils/axios";
+import type { DictTypeParams } from './types/index.type';
+
+
+export function getDictTypeApi(params: DictTypeParams) {
+ return request({
+ url: '/dict/base/info/listDictValuesByType',
+ method: 'post',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ params,
+ })
+}
\ No newline at end of file
diff --git a/src/api/dict/types/index.type.ts b/src/api/dict/types/index.type.ts
new file mode 100644
index 0000000..0451bb5
--- /dev/null
+++ b/src/api/dict/types/index.type.ts
@@ -0,0 +1,9 @@
+export enum DictType {
+ 穿刺方式 = 'in_med_cc_method',
+ 穿刺针类型 = 'in_med_cc_zhen_type',
+ 穿刺方向 = 'in_med_cc_ccfx'
+}
+
+export interface DictTypeParams {
+ dictType: DictType;
+}
diff --git a/src/api/inventory/itemDict.ts b/src/api/inventory/itemDict.ts
new file mode 100644
index 0000000..3a95a1e
--- /dev/null
+++ b/src/api/inventory/itemDict.ts
@@ -0,0 +1,15 @@
+import request from "@/utils/axios";
+import type { InventoryItemListParams } from './types/itemDict.type';
+
+/**
+ * 获取库存字典api
+ * @param params
+ * @returns
+ */
+export function getInventoryItemListApi(params: InventoryItemListParams) {
+ return request({
+ url: '/inventory/item/detail/info/list',
+ method: 'post',
+ params
+ })
+}
\ No newline at end of file
diff --git a/src/api/inventory/types/itemDict.type.ts b/src/api/inventory/types/itemDict.type.ts
new file mode 100644
index 0000000..5c3329a
--- /dev/null
+++ b/src/api/inventory/types/itemDict.type.ts
@@ -0,0 +1,6 @@
+import { ListParams } from '@/api/commom.type';
+
+
+export interface InventoryItemListParams extends ListParams {
+ isPure?: number;
+}
\ No newline at end of file
diff --git a/src/api/patient_hemo_med_start/index.ts b/src/api/patient_hemo_med_start/index.ts
new file mode 100644
index 0000000..05f7b70
--- /dev/null
+++ b/src/api/patient_hemo_med_start/index.ts
@@ -0,0 +1,67 @@
+import request from "@/utils/axios";
+import type {
+ StartRecord,
+ RecordData,
+} from "../patient_hemo_med_start/types/index.type";
+
+/**
+ * 获取开始透析数据api
+ * @param params `recordCode=${recordCode}`
+ * @returns
+ */
+export function addDefaultRowApi(
+ params: string
+): Promise<{ data: StartRecord }> {
+ return request({
+ url: "/patient/hemo/med/start/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,
+ });
+}
+
+/**
+ * 获取结束透析数据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 updateEndRowApi(params: RecordData) {
+ return request({
+ url: "/patient/hemo/med/end/update",
+ method: "post",
+ data: params,
+ });
+}
diff --git a/src/api/patient_hemo_med_start/types/index.type.ts b/src/api/patient_hemo_med_start/types/index.type.ts
new file mode 100644
index 0000000..013e1ce
--- /dev/null
+++ b/src/api/patient_hemo_med_start/types/index.type.ts
@@ -0,0 +1,70 @@
+export interface StartRecord {
+ code: string;
+ createTime: string; // "2025-09-12 17:06:42"
+ createUser: string | null;
+ deletedTime: string | null;
+ doneByg: string;
+ doneBygName: string;
+ doneBygSpecName: string;
+ doneGl: string;
+ doneGlName: string;
+ doneGlSpecName: string;
+ id: number | null;
+ isDeleted: number | null;
+ monitorDataCode: string;
+ recordCode: string;
+ remark: string;
+ schemeName: string;
+ /** 穿刺方向 */
+ startCcASideDirection: string;
+ startCcNurse: string;
+ startCcNurseName: string;
+ /** 穿刺方式 */
+ startCcType: string;
+ startCcZhenA: string;
+ startCcZhenAName: string;
+ startCcZhenASpecName: string;
+ startCcZhenType: string;
+ startCcZhenV: string;
+ startCcZhenVName: string;
+ startCcZhenVSpecName: string;
+ startEntranceType: string;
+ startIsCcOrHy: number | null;
+ startIsSave: number | null;
+ startMedNurse: string;
+ startMedNurseName: string;
+ startTime: string | null;
+ startTxqNo: string;
+ startUpNurse: string;
+ startUpNurseName: string;
+ startUseHlb: string;
+ startUseHlbName: string;
+ startUseHlbSpecName: string;
+ startUseNsy: string;
+ startUseNsyName: string;
+ startUseNsySpecName: string;
+ startYcNurse: string;
+ startYcNurseName: string;
+ startYingxue: string;
+ 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;
+}
diff --git a/src/api/user.ts b/src/api/user.ts
new file mode 100644
index 0000000..f033caf
--- /dev/null
+++ b/src/api/user.ts
@@ -0,0 +1,16 @@
+import request from "@/utils/axios";
+
+/**
+ * 副屏退出登录Api
+ * @returns
+ */
+export function logOutApi(params: string) {
+ return request({
+ url: "/user/info/logoutForSubScreen",
+ method: "post",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ data: params,
+ });
+}
diff --git a/src/api/user/index.ts b/src/api/user/index.ts
new file mode 100644
index 0000000..4f9fa00
--- /dev/null
+++ b/src/api/user/index.ts
@@ -0,0 +1,17 @@
+import request from "@/utils/axios";
+
+/**
+ * 根据角色获取用户列表api
+ * @param params
+ * @returns
+ */
+export function getUsersByRoleCodeApi(params: string) {
+ return request({
+ url: "/user/info/getUsersByRoleCode",
+ method: "post",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ data: params,
+ });
+}
diff --git a/src/assets/css/iconfont.css b/src/assets/css/iconfont.css
index ada5478..9780895 100644
--- a/src/assets/css/iconfont.css
+++ b/src/assets/css/iconfont.css
@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 5011061 */
- src: url('//at.alicdn.com/t/c/font_5011061_crebeujq91a.woff2?t=1756705233110') format('woff2'),
- url('//at.alicdn.com/t/c/font_5011061_crebeujq91a.woff?t=1756705233110') format('woff'),
- url('//at.alicdn.com/t/c/font_5011061_crebeujq91a.ttf?t=1756705233110') format('truetype');
+ src: url('../font/iconfont.woff2') format('woff2'),
+ url('../font/iconfont.woff') format('woff'),
+ url('../font/iconfont.ttf') format('truetype');
}
.iconfont {
@@ -20,3 +20,4 @@
.icon-saoma:before {
content: "\e749";
}
+
diff --git a/src/assets/font/iconfont.ttf b/src/assets/font/iconfont.ttf
index 0ed3ab5..a017a4c 100644
--- a/src/assets/font/iconfont.ttf
+++ b/src/assets/font/iconfont.ttf
Binary files differ
diff --git a/src/assets/font/iconfont.woff b/src/assets/font/iconfont.woff
index 71bb5d9..24b64cc 100644
--- a/src/assets/font/iconfont.woff
+++ b/src/assets/font/iconfont.woff
Binary files differ
diff --git a/src/assets/font/iconfont.woff2 b/src/assets/font/iconfont.woff2
index 66aa294..6dee77b 100644
--- a/src/assets/font/iconfont.woff2
+++ b/src/assets/font/iconfont.woff2
Binary files differ
diff --git a/src/main.ts b/src/main.ts
index 267b11f..b3d124c 100644
--- a/src/main.ts
+++ b/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')
diff --git a/src/store/bedsideAuxiliaryScreen.ts b/src/store/bedsideAuxiliaryScreen.ts
index de157fa..d40dbc8 100644
--- a/src/store/bedsideAuxiliaryScreen.ts
+++ b/src/store/bedsideAuxiliaryScreen.ts
@@ -14,7 +14,8 @@
} from "./type/bedsideAuxiliaryScreen.type";
import { ElMessage } from "element-plus/es";
import { Local } from "@/utils/storage";
-import type { UserInfo } from './type/user.type';
+import type { DeviceLoginRecord } from './type/user.type';
+import { logOutApi } from "@/api/user";
export const useBedsideAuxiliaryScreenStore = defineStore(
"bedsideAuxiliaryScreen",
@@ -32,10 +33,7 @@
const taskData = ref<Task[]>([]);
/** 用户信息 */
- const userInfo = ref<UserInfo | null>(Local.get('userInfo'));
-
- /** 用户token */
- const token = ref<string>(Local.get('token'));
+ const userInfo = ref<DeviceLoginRecord | null>(null);
/** 设置副屏版本号 */
const setVersion = (val: string) => {
@@ -78,23 +76,15 @@
};
/** 设置用户信息 */
- const setUserInfo = (user: UserInfo) => {
+ const setUserInfo = (user: DeviceLoginRecord | null) => {
userInfo.value = user;
- Local.set('userInfo', user);
};
- /** 设置token */
- const setToken = (str: string) => {
- token.value = str;
- Local.set('token', str);
- }
/** 退出登录 */
- const logout = () => {
- Local.remove('token');
- Local.remove('userInfo');
- token.value = '';
- userInfo.value = null;
+ const logout = async (deviceCodeStr: string) => {
+ await logOutApi(deviceCodeStr);
+ setUserInfo(null);
};
// SSE 相关状态
@@ -185,6 +175,9 @@
}
deviceData.value = formatDeviceData(deviceData.value, dataBody);
+ // 当前登录的用户信息
+ setUserInfo(dataBody.当前登录状态);
+
// 判断本地的版本号与远程的版本号是否一致,如果不一致则执行刷新操作
if (dataBody.服务端版本号 !== version.value) {
refreshVersion(dataBody.服务端版本号);
@@ -249,9 +242,7 @@
setVersion,
refreshVersion,
userInfo,
- token,
setUserInfo,
- setToken,
logout,
};
}
diff --git a/src/store/type/bedsideAuxiliaryScreen.type.ts b/src/store/type/bedsideAuxiliaryScreen.type.ts
index 59b28af..1552f67 100644
--- a/src/store/type/bedsideAuxiliaryScreen.type.ts
+++ b/src/store/type/bedsideAuxiliaryScreen.type.ts
@@ -1,6 +1,7 @@
import { tryConvertToInt, deepClone } from "@/utils/utils";
import { Local } from "@/utils/storage";
import dayjs from "dayjs";
+import type { DeviceLoginRecord } from './user.type';
export interface IotInfo {
属性历史列表: any[];
床号: string;
@@ -24,6 +25,7 @@
管路: string[];
透析器: string[];
透析模式: string[];
+ 透析单编号: string;
}
enum EPushType {
@@ -212,6 +214,7 @@
自定义配置项: Customconfiguration;
服务端版本号: string;
是否需要立即刷新: 0 | 1;
+ 当前登录状态: DeviceLoginRecord | null;
}
interface Customconfiguration {
@@ -247,6 +250,7 @@
sphygmomanometer: Sphygmomanometer;
customConfiguration: Customconfiguration;
患者出生日期: string;
+ 客户编号: string;
}
export const defaultSphygmomanometer = () :Sphygmomanometer => {
@@ -315,6 +319,7 @@
carePackage: any[];
punctureNeedle: PunctureNeedle[];
vascularAccess: VascularAccess[];
+ 透析单编号: string;
}
export const defaultconsumablesCollection = (): ConsumablesCollection => {
@@ -326,6 +331,7 @@
管路: [],
透析器: [],
透析模式: [],
+ 透析单编号: '',
};
};
@@ -339,6 +345,7 @@
carePackage: [], // 一次性使用透析护理包列表
punctureNeedle: [], // 穿刺针列表
vascularAccess: [], // 血管通路列表
+ 透析单编号: ''
};
};
@@ -373,6 +380,7 @@
体重增长_透前_上次透后: number | null; // 体重增长(透前-上次透后)
体重增持_透前_干体重: number | null; // 体重增长(透前-干体重)
四点血压图数据: 四点血压图数据[];
+ 透析单编号: string;
}
export const defaultSignedIn = (): SignedIn => {
@@ -407,6 +415,7 @@
体重增长_透前_上次透后: null, // 体重增长(透前-上次透后)
体重增持_透前_干体重: null, // 体重增长(透前-干体重)
四点血压图数据: [],
+ 透析单编号: '',
};
};
@@ -443,6 +452,7 @@
venousPressure2: number | null; // 静脉压
transmembranePressure2: number | null; // 跨膜压
处方脱水量: number | null; // 处方脱水量
+ 透析单编号: string;
}
export interface MonitoringRecord {
@@ -485,6 +495,7 @@
venousPressure2: null, // 静脉压
transmembranePressure2: null, // 跨膜压
处方脱水量: null,
+ 透析单编号: ''
};
};
@@ -510,6 +521,7 @@
// @ts-ignore
pageType, // 当前要展示的页面
treatmentStatus: EMedStatus.NOT_CHECKED_IN, // 透析状态
+ 客户编号: "",
consumablesCollection: defaultconsumablesCollection(), // 未排班时需要的数据
notSignedIn: defalutNotSignedIn(), // 未签到时需要的数据
signedIn: defaultSignedIn(), // 已签到时需要的数据
@@ -540,6 +552,7 @@
// 默认床号(设备号)
result.devicdeNo = seeMsg.IOT信息?.床号;
result.deviceCode = seeMsg.IOT信息?.设备唯一编号;
+
// 自定义配置项
result.customConfiguration = seeMsg.自定义配置项 ?? defaultCustomconfiguration();
@@ -577,6 +590,9 @@
result.patFormNumber = seeMsg.透析状态?.患者门诊住院号;
result.患者出生日期 = seeMsg.透析状态?.患者出生日期 || "";
+ result.客户编号 = seeMsg.透析状态?.clientCode;
+
+
// 未签到页面需要显示的
if (treatmentStatus === EMedStatus.NOT_CHECKED_IN) {
result.pageType = EPageType.NOT_SIGNED_IN;
@@ -589,6 +605,7 @@
notSignedIn.punctureNeedle = seeMsg.透析状态?.穿刺针列表 ?? [];
notSignedIn.vascularAccess = seeMsg.透析状态?.血管通路列表 ?? [];
notSignedIn.anticoagulant = seeMsg.透析状态?.抗凝剂列表 ?? [];
+ notSignedIn.透析单编号 = seeMsg.透析状态?.透析单编号;
result.notSignedIn = notSignedIn;
}
@@ -635,6 +652,7 @@
signedIn.上次透析单所属日期 = dayjs(signedIn.四点血压图数据[0].透析日期).format("YYYY-MM-DD");
// signedIn.本次透析单所属日期 = dayjs(signedIn.四点血压图数据[0].透析日期).format("YYYY-MM-DD");
}
+ signedIn.透析单编号 = seeMsg.透析状态?.透析单编号;
result.signedIn = signedIn;
}
// 剩下的全使用治疗中的页面
@@ -698,6 +716,7 @@
?.realTimeKtvCalcDetailResultInfo ?? [];
underTreatment.dialysisAge = seeMsg.透析状态?.透析龄 ?? null;
underTreatment.处方脱水量 = seeMsg.透析状态?.处方脱水量 ?? null;
+ underTreatment.透析单编号 = seeMsg.透析状态?.透析单编号;
result.underTreatment = underTreatment;
}
diff --git a/src/store/type/user.type.ts b/src/store/type/user.type.ts
index da40248..5e69b20 100644
--- a/src/store/type/user.type.ts
+++ b/src/store/type/user.type.ts
@@ -1,11 +1,18 @@
-export interface UserInfo {
- 用户头像: string;
- 用户昵称: string;
-}
-
-export const defaultUserInfo = (): UserInfo => {
- return {
- 用户头像: '',
- 用户昵称: ''
- }
+export interface DeviceLoginRecord {
+ clientCode: string;
+ code: string;
+ createTime: string; // 格式:YYYY-MM-DD HH:mm:ss
+ createUser: string | null;
+ deletedTime: string | null;
+ deviceCode: string;
+ id: number;
+ isDeleted: number; // 0/1 标识
+ loginTime: string; // 格式:YYYY-MM-DD HH:mm:ss
+ remark: string | null;
+ token: string | null;
+ updateTime: string; // 格式:YYYY-MM-DD HH:mm:ss
+ updateUser: string | null;
+ userCode: string;
+ userName: string;
+ userAvatar: string | null;
}
\ No newline at end of file
diff --git a/src/utils/axios.ts b/src/utils/axios.ts
new file mode 100644
index 0000000..6dcc26f
--- /dev/null
+++ b/src/utils/axios.ts
@@ -0,0 +1,134 @@
+import axios, { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
+import Qs from 'qs'
+import { useBedsideAuxiliaryScreenStore } from '@/store/bedsideAuxiliaryScreen'
+import { ElMessage } from 'element-plus/es'
+
+// ====== 配置 ======
+const BASE_URL = import.meta.env.VITE_API_BASE_URL
+const TIME_OUT = 60 * 1 * 1000
+
+// 正在进行中的请求列表,避免重复请求
+let reqList: string[] = []
+
+/**
+ * 允许某个请求再次发送
+ */
+const allowRequest = (url?: string) => {
+ if (!url) return
+ const idx = reqList.indexOf(url)
+ if (idx > -1) reqList.splice(idx, 1)
+}
+
+/**
+ * 创建 axios 实例
+ */
+const instance = axios.create({
+ baseURL: BASE_URL,
+ timeout: TIME_OUT,
+ paramsSerializer: (params) => Qs.stringify(params, { arrayFormat: 'brackets' }),
+})
+
+// ====== 错误处理函数 ======
+const errorHandle = (status: number, error: any): void => {
+ const msg = error?.msg || error?.message || ''
+ switch (status) {
+ case 401:
+ ElMessage.error(`Error Code: 401, Message: ${msg || '登录失效,请重新登录'}`);
+ break
+ case 403:
+ ElMessage.error(`Error Code: 403, Message: ${msg || '你没有访问权限'}`);
+ break
+ case 500:
+ ElMessage.error(`Error Code: 500, Message: ${msg || '后台错误,请联系管理员'}`);
+ break
+ case 502:
+ alert()
+ ElMessage.error(`Error Code: 502, Message: ${msg || '平台环境异常'}`);
+ break
+ default:
+ ElMessage.error(`Error Code: ${status}, Message: ${msg || '未知错误,请刷新重试'}`);
+ }
+}
+
+// ====== 请求拦截 ======
+instance.interceptors.request.use(
+ (config: InternalAxiosRequestConfig) => {
+ const store = useBedsideAuxiliaryScreenStore()
+
+ // 加 token
+ if (store.userInfo?.token) {
+ config.headers.set('Authorization', `Bearer ${store.userInfo.token}`)
+ }
+
+ // 防止同一接口短时间内重复请求
+ if (config.url) {
+ if (reqList.includes(config.url)) {
+ // return Promise.reject(new axios.Cancel(`重复请求:${config.url}`))
+ } else {
+ reqList.push(config.url)
+ }
+ }
+
+ return config
+ },
+ (error) => Promise.reject(error),
+)
+
+// ====== 响应拦截 ======
+instance.interceptors.response.use(
+ (res: AxiosResponse) => {
+
+ // setTimeout(() => allowRequest(res.config.url), 1000)
+ if (String(res.status).charAt(0) !== '2') {
+ return Promise.reject({
+ code: res.status,
+ message: res.data?.message || '请求异常,请刷新重试',
+ })
+ }
+ if (res.data?.code === 200) return res.data
+ const whiteList: string[] = []
+ const requestUrl: string = res?.config?.url || ''
+ const isInWhiteList = whiteList.some((item) => requestUrl.includes(item))
+ ElMessage.error(res.data.message);
+ if (isInWhiteList) return Promise.reject(res.data)
+ return Promise.reject(res.data)
+ },
+
+
+ (err: unknown) => {
+
+ const anyErr = err as any
+ const configUrl = anyErr?.config?.url
+ // 失败后 1s 允许再次请求
+ // setTimeout(() => allowRequest(configUrl), 1000)
+
+ // 先判断是否是取消请求
+ // if (axios.isCancel(err as any)) {
+ // console.warn('请求被取消:', (err as any)?.message)
+ // return Promise.reject(err)
+ // }
+
+ // 判断是否为 axios 的错误类型(有 response)
+ if (axios.isAxiosError(err)) {
+ const axErr = err // 现在 TypeScript 知道这是 AxiosError
+ if (axErr.response) {
+ // 使用你现有的错误处理函数
+ errorHandle(axErr.response.status, axErr.response.data)
+
+ if (axErr.response.status === 401) {
+ ElMessage.error('请登录');
+ }
+ return Promise.reject(axErr.response.data || axErr.response)
+ }
+
+ ElMessage.error('网络请求失败, 请刷新重试');
+ return Promise.reject(axErr)
+ }
+
+ //(未知错误)
+ ElMessage.error('网络请求失败, 请刷新重试');
+ return Promise.reject(err)
+ },
+)
+
+export default instance
diff --git a/src/utils/httpApi.ts b/src/utils/httpApi.ts
index d8f0c2e..632b95f 100644
--- a/src/utils/httpApi.ts
+++ b/src/utils/httpApi.ts
@@ -93,4 +93,22 @@
} catch (error) {
throw error;
}
+}
+
+/**
+ * 推出登录
+ * @param deviceCode
+ * @returns
+ */
+export const logoutForSubScreen = async(deviceCode: string) => {
+ try {
+ const response = await axios.post(`${apiBaseUrl}/user/info/logoutForSubScreen`, { deviceCode }, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ }
+ });
+ return response.data
+ } catch (error) {
+ throw error;
+ }
}
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/EndDialysis/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/EndDialysis/index.vue
new file mode 100644
index 0000000..a292564
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/EndDialysis/index.vue
@@ -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>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
index cb20147..2807483 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Header.vue
@@ -65,7 +65,8 @@
alt=""
@click="openSettingDeviceDialog"
/>
- <img :src="userImg" class="btn-img" alt="" @click="openLoginDialog" />
+ <img v-if="userInfo?.code" :src="userInfo?.userAvatar" class="btn-img" alt="" @click="openLoginDialog" />
+ <img v-else :src="userImg" class="btn-img" alt="" @click="openLoginDialog" />
</div>
</div>
<!-- 设置设备编号组件 -->
@@ -164,6 +165,14 @@
}
});
+
+const userInfo = computed(() => {
+ if (!bedsideAuxiliaryScreenStore.userInfo) return null
+ return Object.assign({}, bedsideAuxiliaryScreenStore.userInfo, {
+ userAvatar: bedsideAuxiliaryScreenStore.userInfo?.userAvatar ? bedsideAuxiliaryScreenStore.userInfo?.userAvatar : generateCircularAvatar(bedsideAuxiliaryScreenStore.userInfo?.userName)
+ });
+});
+
watch(
() => bedsideAuxiliaryScreenStore.taskData?.[0]?.countdown,
(val) => {
@@ -246,6 +255,29 @@
loginDialogRef.value.openDialog();
};
+function generateCircularAvatar(name: string, size = 100): string {
+ console.log('name: ', name)
+ const canvas = document.createElement('canvas');
+ canvas.width = size;
+ canvas.height = size;
+ const ctx = canvas.getContext('2d')!;
+
+ // 绘制圆形背景
+ ctx.fillStyle = '#dae5ec';
+ ctx.beginPath();
+ ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
+ ctx.fill();
+
+ // 绘制文字(第一个字)
+ ctx.fillStyle = '#70a3dd'; // 字体颜色
+ ctx.font = `${size * 0.5}px sans-serif`; // 字体大小为头像大小的一半
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+ ctx.fillText(name.charAt(0), size / 2, size / 2);
+
+ return canvas.toDataURL('image/png'); // 返回 Base64 图片
+}
+
onUnmounted(() => {
clearTimer();
});
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue
index 43c53fc..a30b281 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Login/index.vue
@@ -59,13 +59,24 @@
});
const isLoginng = computed(() => {
- return !!bedsideAuxiliaryScreenStore.token;
+ return !!bedsideAuxiliaryScreenStore.userInfo?.code;
});
const qrCodeData = computed(() => {
return {
deviceCode: bedsideAuxiliaryScreenStore.deviceCode,
+ deviceNo: bedsideAuxiliaryScreenStore.deviceData.devicdeNo,
};
+ });
+
+ const userInfo = computed(() => {
+ const userInfo = bedsideAuxiliaryScreenStore.userInfo;
+ if (!userInfo) return null;
+ return {
+ ...userInfo,
+ 床号: bedsideAuxiliaryScreenStore.deviceData.devicdeNo,
+ 设备编号: bedsideAuxiliaryScreenStore.deviceCode
+ }
});
const openDialog = () => {
@@ -77,17 +88,25 @@
};
const onLogout = () => {
+ if (state.loading) return ElMessage.warning('正在退出中...')
ElMessageBox.confirm("是否确认退出当前登录用户?", "提示", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "warning",
})
- .then(() => {
- bedsideAuxiliaryScreenStore.logout();
- ElMessage({
- type: "success",
- message: "退出成功!",
- });
+ .then(async() => {
+ state.loading = true
+ try {
+ await bedsideAuxiliaryScreenStore.logout(`deviceCode=${bedsideAuxiliaryScreenStore.deviceCode}`);
+ handleCancel();
+ ElMessage.success('退出登录成功')
+ handleCancel();
+ } catch (error) {
+ console.error('error: ', error)
+ // ElMessage.error('退出登录失败')
+ } finally {
+ state.loading = false;
+ }
})
.catch(() => {});
};
@@ -100,6 +119,7 @@
handleCancel,
openDialog,
onLogout,
+ userInfo,
};
},
};
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/Login/userInfo.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/Login/userInfo.vue
index f5e9fa2..ced0bff 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/components/Login/userInfo.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/Login/userInfo.vue
@@ -1,7 +1,7 @@
<template>
<div class="userinfo-container">
- <img :src="userInfo.用户头像" alt="" srcset="" class="user-avatar">
- <div class="user-text">当前账户:{{ userInfo.用户昵称 }}</div>
+ <img :src="userInfo.userAvatar" alt="" srcset="" class="user-avatar" />
+ <div class="user-text">当前账户:{{ userInfo.userName }}</div>
<div class="user-text">床号:{{ userInfo.床号 }}</div>
<div class="user-text">设备号:{{ userInfo.设备编号 }}</div>
</div>
@@ -10,7 +10,6 @@
<script lang="ts">
import { computed } from "vue";
import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
-import { defaultUserInfo } from '@/store/type/user.type';
export default {
name: "UserInfo",
@@ -18,16 +17,41 @@
const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
const userInfo = computed(() => {
- const userInfo = bedsideAuxiliaryScreenStore.userInfo || defaultUserInfo();
+ const userInfo = bedsideAuxiliaryScreenStore.userInfo;
+ if (!userInfo) return null;
return {
...userInfo,
床号: bedsideAuxiliaryScreenStore.deviceData.devicdeNo,
- 设备编号: bedsideAuxiliaryScreenStore.deviceCode
- }
+ 设备编号: bedsideAuxiliaryScreenStore.deviceCode,
+ userAvatar: userInfo?.userAvatar ? userInfo?.userAvatar : generateCircularAvatar(userInfo?.userName)
+ };
});
+ function generateCircularAvatar(name: string, size = 100): string {
+ console.log("name: ", name);
+ const canvas = document.createElement("canvas");
+ canvas.width = size;
+ canvas.height = size;
+ const ctx = canvas.getContext("2d")!;
+
+ // 绘制圆形背景
+ ctx.fillStyle = "#769aff";
+ ctx.beginPath();
+ ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
+ ctx.fill();
+
+ // 绘制文字(第一个字)
+ ctx.fillStyle = "#FFFFFF"; // 字体颜色
+ ctx.font = `${size * 0.5}px sans-serif`; // 字体大小为头像大小的一半
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.fillText(name.charAt(0), size / 2, size / 2);
+
+ return canvas.toDataURL("image/png"); // 返回 Base64 图片
+ }
+
return {
- userInfo
+ userInfo,
};
},
};
@@ -35,21 +59,21 @@
<style lang="less" scoped>
.userinfo-container {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- .user-avatar {
- width: 15px;
- height: 15px;
- border-radius: 50%;
- overflow: hidden;
- margin-bottom: 5px;
- }
- .user-text {
- font-size: 5px;
- color: #000;
- margin-bottom: 4px;
- }
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ .user-avatar {
+ width: 15px;
+ height: 15px;
+ border-radius: 50%;
+ overflow: hidden;
+ margin-bottom: 5px;
+ }
+ .user-text {
+ font-size: 5px;
+ color: #000;
+ margin-bottom: 4px;
+ }
}
</style>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/components/StartDialysis/index.vue b/src/views/mobile/bedsideAuxiliaryScreen/components/StartDialysis/index.vue
new file mode 100644
index 0000000..0a9958f
--- /dev/null
+++ b/src/views/mobile/bedsideAuxiliaryScreen/components/StartDialysis/index.vue
@@ -0,0 +1,865 @@
+<template>
+ <div class="start-dialysis-container">
+ <el-dialog
+ v-model="show"
+ center
+ title="开始透析"
+ width="80%"
+ :show-close="false"
+ class="start-dialysis-dialog"
+ :destroy-on-close="true"
+ :close-on-click-modal="false"
+ >
+ <template #header>
+ <div class="start-dialysis-header">
+ <span class="header-title">开始透析</span>
+ <img
+ :src="closeImg"
+ class="header-close"
+ @click="handleCancel"
+ alt=""
+ />
+ </div>
+ </template>
+ <div class="start-dialysis-content" v-loading="loading">
+ <el-form :model="formData" size="large">
+ <el-row :gutter="10">
+ <el-col :span="6">
+ <el-form-item label="开始时间">
+ <el-time-select
+ v-model="formData.startTime"
+ start="00:00"
+ step="00:01"
+ end="23:59"
+ placeholder="请选择"
+ :clearable="false"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="治疗护士">
+ <el-select
+ @change="onStartMedNurseChange"
+ style="width: 100%"
+ v-model="formData.startMedNurse"
+ 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="6">
+ <el-form-item label="上机护士">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startUpNurse"
+ 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="6">
+ <el-form-item label="预充管路">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startYcNurse"
+ 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="6">
+ <el-form-item label="穿刺/换药">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startIsCcOrHy"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="(item, index) in startIsCcOrHyOptions"
+ :key="index"
+ :label="item.label"
+ :value="item.value"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <template v-if="formData.startIsCcOrHy === 1">
+ <el-col :span="6">
+ <el-form-item label="换药护士">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startCcNurse"
+ 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>
+ </template>
+ <template v-else-if="formData.startIsCcOrHy === 0">
+ <el-col :span="6">
+ <el-form-item label="穿刺护士">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startCcNurse"
+ 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>
+ </template>
+ <template v-else-if="formData.startIsCcOrHy === 2">
+ <el-col :span="6">
+ <el-form-item label="换药护士">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startCcNurse"
+ 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>
+ </template>
+ <template
+ v-if="
+ formData.startIsCcOrHy === 2 || formData.startIsCcOrHy === 0
+ "
+ >
+ <el-col :span="6">
+ <el-form-item label="穿刺方式" prop="doneCcType">
+ <el-select
+ style="width: 100%"
+ multiple
+ v-model="formData.startCcType"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="item in punctureMethodOptions"
+ :key="item.code"
+ :label="item.dictText"
+ :value="item.dictText"
+ >
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="穿刺针A">
+ <el-select
+ clearable
+ style="width: 100%"
+ v-model="formData.startCcZhenA"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="item in punctureNeedleOptions"
+ :key="item.code"
+ :label="item.itemName + ' ' + item.itemSpec"
+ :value="item.code"
+ :disabled="item.isShow !== 1"
+ >
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item clearable label="穿刺针V">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startCcZhenV"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="item in punctureNeedleOptions"
+ :key="item.code"
+ :label="item.itemName + ' ' + item.itemSpec"
+ :value="item.code"
+ :disabled="item.isShow !== 1"
+ >
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="穿刺方向">
+ <el-select
+ style="width: 100%"
+ multiple
+ v-model="formData.startCcASideDirection"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="item in punctureDirectionOptions"
+ :key="item.code"
+ :label="item.dictText"
+ :value="item.dictText"
+ >
+ </el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </template>
+ <el-col :span="6">
+ <el-form-item label="引血(ml/min)">
+ <el-input style="width: 100%" v-model="formData.startYingxue" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="透析器编号">
+ <el-input style="width: 100%" v-model="formData.startTxqNo" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="入科方式">
+ <el-select
+ style="width: 100%"
+ v-model="formData.startEntranceType"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="(item, index) in startEntranceTypeOptions"
+ :key="index"
+ :label="item.label"
+ :value="item.value"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="一次性使用管路">
+ <el-select v-model="formData.doneGl" placeholder="请选择">
+ <el-option
+ v-for="(item, index) in disposablePipelineOptions"
+ :key="index"
+ :label="item.itemName + ' ' + item.itemSpec"
+ :value="item.code"
+ :disabled="item.isShow !== 1"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="血滤管">
+ <el-select
+ v-model="formData.doneByg"
+ :disabled="formData.schemeName !== 'HDF'"
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="(item, index) in hemofiltrationTubeOptions"
+ :key="index"
+ :label="item.itemName + ' ' + item.itemSpec"
+ :value="item.code"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="透析浓缩液">
+ <el-select
+ v-model="formData.startUseNsy"
+ multiple
+ filterable
+ clearable
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="(item, index) in doneUseNsyOptions"
+ :key="index"
+ :label="item.itemName + ' ' + item.itemSpec"
+ :value="item.code"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="6">
+ <el-form-item label="透析护理包">
+ <el-select
+ v-model="formData.startUseHlb"
+ filterable
+ clearable
+ placeholder="请选择"
+ >
+ <el-option
+ v-for="(item, index) in doneUseHlbOptions"
+ :key="index"
+ :label="item.itemName + ' ' + item.itemSpec"
+ :value="item.code"
+ ></el-option>
+ </el-select>
+ </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 {
+ addDefaultRowApi,
+ updateMedstartDataApi,
+} from "@/api/patient_hemo_med_start/index";
+import type { StartRecord } from "@/api/patient_hemo_med_start/types/index.type";
+import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
+import { getInventoryItemListApi } from "@/api/inventory/itemDict";
+import { getUsersByRoleCodeApi } from "@/api/user/index";
+import { getDictTypeApi } from "@/api/dict/index";
+import { DictType } from "@/api/dict/types/index.type";
+import dayjs from "dayjs";
+import { ElMessage } from "element-plus/es";
+
+interface FormData
+ extends Omit<
+ StartRecord,
+ "startCcType" | "startCcASideDirection" | "startUseNsy"
+ > {
+ /** 穿刺方式 */
+ startCcType: string[];
+ /** 穿刺方向 */
+ startCcASideDirection: string[];
+ startUseNsy: string[];
+}
+
+interface State {
+ loading: boolean;
+ show: boolean;
+ formData: FormData;
+ doneUseNsyOptions: any[];
+ doneUseHlbOptions: any[];
+ disposablePipelineOptions: any[];
+ hemofiltrationTubeOptions: any[];
+ nurseOptions: any[];
+ punctureMethodOptions: any[];
+ typePunctureNeedleOptions: any[];
+ punctureDirectionOptions: any[];
+ punctureNeedleOptions: any[];
+ startIsCcOrHyOptions: any[];
+ startEntranceTypeOptions: any[];
+ startDate: string;
+}
+export default {
+ name: "StartDialysis",
+ setup() {
+ const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
+
+ const state = reactive<State>({
+ loading: false,
+ show: false,
+ formData: {
+ code: "",
+ createTime: "",
+ createUser: null,
+ deletedTime: null,
+ doneByg: "",
+ doneBygName: "",
+ doneBygSpecName: "",
+ doneGl: "",
+ doneGlName: "",
+ doneGlSpecName: "",
+ id: null,
+ isDeleted: null,
+ monitorDataCode: "",
+ recordCode: "",
+ remark: "",
+ schemeName: "",
+ /** 穿刺方向 */
+ startCcASideDirection: [],
+ startCcNurse: "",
+ startCcNurseName: "",
+ /** 穿刺方式 */
+ startCcType: [],
+ startCcZhenA: "",
+ startCcZhenAName: "",
+ startCcZhenASpecName: "",
+ startCcZhenType: "",
+ startCcZhenV: "",
+ startCcZhenVName: "",
+ startCcZhenVSpecName: "",
+ startEntranceType: "",
+ startIsCcOrHy: null,
+ startIsSave: null,
+ startMedNurse: "",
+ startMedNurseName: "",
+ startTime: null,
+ startTxqNo: "",
+ startUpNurse: "",
+ startUpNurseName: "",
+ startUseHlb: "",
+ startUseHlbName: "",
+ startUseHlbSpecName: "",
+ startUseNsy: [],
+ startUseNsyName: "",
+ startUseNsySpecName: "",
+ startYcNurse: "",
+ startYcNurseName: "",
+ startYingxue: "",
+ updateTime: "",
+ updateUser: null,
+ },
+ doneUseNsyOptions: [], // 透析浓缩液列表
+ doneUseHlbOptions: [], // 透析护理包列表
+ disposablePipelineOptions: [], // 一次性使用管路列表
+ hemofiltrationTubeOptions: [], // 血滤管列表
+ nurseOptions: [], // 护士列表
+ punctureMethodOptions: [], // 穿刺方式列表
+ typePunctureNeedleOptions: [], // 穿刺针类型列表
+ punctureDirectionOptions: [], // 穿刺方向列表
+ punctureNeedleOptions: [], // 穿刺针列表
+ startIsCcOrHyOptions: [
+ { label: "穿刺", value: 0 },
+ { label: "换药", value: 1 },
+ { label: "穿刺+换药", value: 2 },
+ ],
+ startEntranceTypeOptions: [
+ { label: "步行", value: "步行" },
+ { label: "扶行", value: "扶行" },
+ { label: "轮椅", value: "轮椅" },
+ { label: "平床", value: "平床" },
+ { label: "床旁", value: "床旁" },
+ { label: "助行器", value: "助行器" },
+ ],
+ startDate: "", // 日期部分
+ });
+
+ const recordCode = computed(() => {
+ return bedsideAuxiliaryScreenStore.deviceData.signedIn.透析单编号;
+ });
+
+ const clientCode = computed(() => {
+ return bedsideAuxiliaryScreenStore.deviceData.客户编号;
+ });
+
+ const userCode = computed(() => {
+ return bedsideAuxiliaryScreenStore.userInfo.userCode;
+ });
+
+ const openDialog = async () => {
+ state.show = true;
+ state.loading = true;
+ try {
+ const promiseFuns = [
+ getDoneUseNsys(),
+ getdoneUseHlbs(),
+ getDisposablePipelines(),
+ getHemofiltrationTubes(),
+ getPunctureNeedles(),
+ getNurses(),
+ getPunctureMethods(),
+ getTypePunctureNeedles(),
+ getPunctureDirectionOptions(),
+ ];
+ // if (state.doneUseNsyOptions.length <= 0) {
+ // promiseFuns.push(getDoneUseNsys());
+ // }
+ // if (state.doneUseHlbOptions.length <= 0) {
+ // promiseFuns.push(getdoneUseHlbs());
+ // }
+ // if (state.disposablePipelineOptions.length <= 0) {
+ // promiseFuns.push(getDisposablePipelines());
+ // }
+ // if (state.hemofiltrationTubeOptions.length <= 0) {
+ // promiseFuns.push(getHemofiltrationTubes());
+ // }
+ // if (state.punctureNeedleOptions.length <= 0) {
+ // promiseFuns.push(getPunctureNeedles());
+ // }
+ // if (state.nurseOptions.length <= 0) {
+ // promiseFuns.push(getNurses());
+ // }
+ // if (state.punctureMethodOptions.length <= 0) {
+ // promiseFuns.push(getPunctureMethods());
+ // }
+ // if (state.typePunctureNeedleOptions.length <= 0) {
+ // promiseFuns.push(getTypePunctureNeedles());
+ // }
+ // if (state.punctureDirectionOptions.length <= 0) {
+ // promiseFuns.push(getPunctureDirectionOptions());
+ // }
+ await Promise.all(promiseFuns);
+ await getStartData();
+ } catch (error) {
+ console.error("开始透析初始化失败", error);
+ state.show = false;
+ } finally {
+ state.loading = false;
+ }
+ };
+
+ /**
+ * 获取开始透析默认数据
+ */
+ const getStartData = async () => {
+ const { data } = await addDefaultRowApi(`recordCode=${recordCode.value}`);
+ const dataCopy = JSON.parse(JSON.stringify(data));
+ const nots = ["", null];
+
+ if (!nots.includes(data.startCcType)) {
+ // @ts-ignore
+ dataCopy.startCcType = data.startCcType.split(",");
+ } else {
+ // @ts-ignore
+ dataCopy.startCcType = [];
+ }
+
+ if (!nots.includes(data.startCcASideDirection)) {
+ // @ts-ignore
+ dataCopy.startCcASideDirection = data.startCcASideDirection.split(",");
+ } else {
+ // @ts-ignore
+ dataCopy.startCcASideDirection = [];
+ }
+
+ if (nots.includes(data.startTime)) {
+ dataCopy.startTime = dayjs().format("HH:mm");
+ state.startDate = dayjs().format("YYYY-MM-DD");
+ } else {
+ dataCopy.startTime = dayjs(data.startTime).format("HH:mm");
+ state.startDate = dayjs(data.startTime).format("YYYY-MM-DD");
+ }
+
+ if (nots.includes(data.startMedNurse)) {
+ dataCopy.startMedNurse = userCode.value;
+ }
+
+ if (nots.includes(data.startCcNurse)) {
+ dataCopy.startCcNurse = userCode.value;
+ }
+ if (nots.includes(data.startUpNurse)) {
+ dataCopy.startUpNurse = userCode.value;
+ }
+ if (nots.includes(data.startYcNurse)) {
+ dataCopy.startYcNurse = userCode.value;
+ }
+ if (!nots.includes(data.startUseNsy)) {
+ // @ts-ignore
+ dataCopy.startUseNsy = data.startUseNsy.split(",");
+ } else {
+ // @ts-ignore
+ dataCopy.startUseNsy = [];
+ }
+
+ if (data.schemeName !== "HDF") {
+ // 如果透析模式不算HDF的话血滤管置空
+ dataCopy.doneByg = "";
+ dataCopy.doneBygName = "";
+ } else {
+ const defaultXlg = state.hemofiltrationTubeOptions.find(
+ (e) => e.itemName === "义鑫血液净化补液管路(HDIT-1)"
+ );
+ if (defaultXlg) {
+ dataCopy.doneByg = defaultXlg.code;
+ dataCopy.doneBygName = defaultXlg.itemName;
+ }
+ }
+ state.formData = dataCopy as unknown as FormData;
+ };
+
+ /**
+ * 获取透析浓缩液字典数据
+ */
+ const getDoneUseNsys = async () => {
+ const params = {
+ page: 0,
+ size: 0,
+ wherecondition: `inventory_type_code='IT2112291619002680' and is_show = 1 and client_code='${clientCode.value}'`,
+ ordercondition: "item_is_use desc, item_sort_order asc",
+ isPure: 0,
+ };
+ const { data } = await getInventoryItemListApi(params);
+ state.doneUseNsyOptions = data.list;
+ };
+
+ /**
+ * 获取透析护理包字典数据
+ */
+ const getdoneUseHlbs = async () => {
+ const params = {
+ page: 0,
+ size: 0,
+ wherecondition: `inventory_type_code='IT2112291619003161' and is_show = 1 and client_code='${clientCode.value}'`,
+ ordercondition: "item_is_use desc, item_sort_order asc",
+ isPure: 0,
+ };
+ const { data } = await getInventoryItemListApi(params);
+ state.doneUseHlbOptions = data.list;
+ };
+
+ /**
+ * 获取一次性使用管路字典数据
+ */
+ const getDisposablePipelines = async () => {
+ const params = {
+ page: 0,
+ size: 0,
+ wherecondition: `inventory_type_code='IT2112291619006054' and is_show = 1 and client_code='${clientCode.value}'`,
+ ordercondition: "item_is_use desc, item_sort_order asc",
+ isPure: 0,
+ };
+ const { data } = await getInventoryItemListApi(params);
+ state.disposablePipelineOptions = data.list;
+ };
+
+ /**
+ * 获取血滤管字典数据
+ */
+ const getHemofiltrationTubes = async () => {
+ const params = {
+ page: 1,
+ size: 10,
+ wherecondition: `inventory_type_code='IT9024215920713quQV' and is_show = 1 and client_code='${clientCode.value}'`,
+ ordercondition: "item_is_use desc, item_sort_order asc",
+ isPure: 0,
+ };
+ const { data } = await getInventoryItemListApi(params);
+ state.hemofiltrationTubeOptions = data.list;
+ };
+
+ /**
+ * 获取穿刺针字典数据
+ */
+ const getPunctureNeedles = async () => {
+ const params = {
+ page: 1,
+ size: 10,
+ wherecondition: `(inventory_type_code='IT3561011130526051' OR inventory_type_code='IT2112291619000061') and client_code='${clientCode.value}'`,
+ ordercondition: "item_is_use desc, item_sort_order asc",
+ };
+ const { data } = await getInventoryItemListApi(params);
+ state.punctureNeedleOptions = data.list;
+ };
+
+ /**
+ * 获取护士数据
+ */
+ const getNurses = async () => {
+ const { data } = await getUsersByRoleCodeApi(
+ `clientCode=${clientCode.value}&roleClass=nurse`
+ );
+ state.nurseOptions = data;
+ };
+
+ /**
+ * 获取穿刺方式字典数据
+ */
+ const getPunctureMethods = async () => {
+ const { data } = await getDictTypeApi({ dictType: DictType.穿刺方式 });
+ state.punctureMethodOptions = data;
+ };
+
+ /**
+ * 获取穿刺针类型字典数据
+ */
+ const getTypePunctureNeedles = async () => {
+ const { data } = await getDictTypeApi({ dictType: DictType.穿刺针类型 });
+ state.typePunctureNeedleOptions = data;
+ };
+
+ /**
+ * 获取穿刺针方向字典数据
+ */
+ const getPunctureDirectionOptions = async () => {
+ const { data } = await getDictTypeApi({ dictType: DictType.穿刺方向 });
+ state.punctureDirectionOptions = data;
+ };
+
+ const handleCancel = () => {
+ state.show = false;
+ state.loading = false;
+ };
+
+ const handleConfirm = async () => {
+ state.loading = true;
+ try {
+ const paramsData = Object.assign({}, state.formData, {
+ startCcASideDirection:
+ state.formData.startCcASideDirection.toString(),
+ startCcType: state.formData.startCcType.toString(),
+ startUseNsy: state.formData.startUseNsy.join(","),
+ startTime: `${state.startDate} ${state.formData.startTime}:00`,
+ });
+ await updateMedstartDataApi(paramsData);
+ ElMessage.success("操作成功!");
+ state.show = false;
+ } finally {
+ state.loading = false;
+ }
+ };
+
+ /**
+ * 治疗护士的改变
+ * @param val
+ */
+ const onStartMedNurseChange = (val: string) => {
+ state.formData.startCcNurse = val;
+ state.formData.startUpNurse = val;
+ state.formData.startYcNurse = val;
+ };
+
+ return {
+ ...toRefs(state),
+ closeImg,
+ handleCancel,
+ openDialog,
+ handleConfirm,
+ onStartMedNurseChange,
+ };
+ },
+};
+</script>
+
+<style lang="less" scoped>
+.start-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;
+ }
+ .start-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);
+ }
+ }
+ }
+ .start-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>
\ No newline at end of file
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue
index 9e9d42f..6b33391 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/SignedIn.vue
@@ -251,7 +251,8 @@
<tr>
<td>体重增长</td>
<td class="flex-td">
- <span class="sub-text">(透前-干体重)</span><span class="text-right">{{ weightGain2 }}kg</span>
+ <span class="sub-text">(透前-干体重)</span
+ ><span class="text-right">{{ weightGain2 }}kg</span>
</td>
</tr>
<!-- <tr>
@@ -294,14 +295,15 @@
@click="() => onScheduledTasksClick()"
class="btn"
/>
- <BlockBotttom
+ <!-- <BlockBotttom
:icon="jiaoHaoImg"
text="叫号"
backgroundColor="#20C6B6"
@click="() => onCallBumberClick()"
class="btn"
- />
+ /> -->
<BlockBotttom
+ v-if="isShowStartBtn"
:icon="kaiShiImg"
text="开始"
backgroundColor="#409EFF"
@@ -311,6 +313,8 @@
</div>
<!-- 定时任务 -->
<ScheduledTaskDialog ref="scheduledTaskDialogRef" />
+ <!-- 开始透析组件 -->
+ <StartDialysis ref="startDialysisRef" />
</div>
</template>
<script lang="ts" setup name="SignedIn">
@@ -345,9 +349,11 @@
// @ts-ignore
import BlockBotttom from "../components/BlockBotttom.vue";
import { ElMessage } from "element-plus";
+import { EMedStatus } from '@/store/type/bedsideAuxiliaryScreen.type';
const ScheduledTaskDialog = defineAsyncComponent(
() => import("../components/ScheduledTask.vue")
);
+const StartDialysis = defineAsyncComponent(() => import('../components/StartDialysis/index.vue'));
interface Props {
height: number;
@@ -358,7 +364,7 @@
const bloodPressureRectangularChart = ref<HTMLElement | null>(null);
const scheduledTaskDialogRef = ref<any>(null);
-
+const startDialysisRef = ref<any>(null);
const pageData = computed(() => {
return Object.assign(bedsideAuxiliaryScreenStore.deviceData.signedIn, {
@@ -416,12 +422,19 @@
return formattedValue;
});
+/**
+ * 是否显示开始透析按钮
+ */
+const isShowStartBtn = computed(() => {
+ return +bedsideAuxiliaryScreenStore.deviceData.treatmentStatus === EMedStatus.SIGNED_IN;
+})
watch(
() => pageData.value.四点血压图数据,
(newVal) => {
genderBloodPressureRectangularChart(newVal);
-});
+ }
+);
/** 点击定时任务 */
const onScheduledTasksClick = () => {
@@ -441,20 +454,27 @@
};
const onStartClick = () => {
- ElMessage({
- message: "功能开发中,敬请期待!",
- type: "warning",
- });
+ if (
+ !bedsideAuxiliaryScreenStore.deviceCode ||
+ !bedsideAuxiliaryScreenStore.deviceData.deviceCode
+ )
+ return ElMessage.warning("未初始化或正在进行初始化操作中");
+ if (!bedsideAuxiliaryScreenStore.userInfo?.token)
+ return ElMessage.warning("请登录");
+ startDialysisRef.value?.openDialog();
};
-const genderBloodPressureRectangularChart = (datas: 四点血压图数据[] | null) => {
+const genderBloodPressureRectangularChart = (
+ datas: 四点血压图数据[] | null
+) => {
if (!bloodPressureRectangularChart.value) return;
const benchmarkData = { width: 386, height: 280 };
// 获取容器宽高(90% 缩放)
const containerWidth = bloodPressureRectangularChart.value.offsetWidth * 0.9;
- const containerHeight = bloodPressureRectangularChart.value.offsetHeight * 0.9;
+ const containerHeight =
+ bloodPressureRectangularChart.value.offsetHeight * 0.9;
// 获取设备像素比
const dpr = window.devicePixelRatio || 1;
@@ -515,10 +535,22 @@
// ========== 血压数据 ==========
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 },
+ {
+ 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);
@@ -580,10 +612,7 @@
const cylinderHeight = 计算脱水量刻度 * (datas?.[0]?.超滤总量 || 0);
const 体重增长_透前减干体重 = weightGain2.value;
const 透前减干体重减超滤总量差值 =
- Math.round(
- (体重增长_透前减干体重 - (datas?.[0]?.超滤总量 || 0)) * 10
- ) / 10;
-
+ Math.round((体重增长_透前减干体重 - (datas?.[0]?.超滤总量 || 0)) * 10) / 10;
drawCylinder(
ctx,
@@ -597,13 +626,11 @@
datas?.[0]?.脱水百分比 ?? 0,
datas?.[0]?.透后体重减干体重的差值 ?? 0,
体重增长_透前减干体重,
- 透前减干体重减超滤总量差值,
+ 透前减干体重减超滤总量差值
);
ctx.restore(); // 恢复
};
-
-
const drawCylinder = (
ctx: CanvasRenderingContext2D,
@@ -617,7 +644,7 @@
脱水百分比: number, // 脱水百分比
透后体重减干体重的差值: number, // 透后体重减干体重的差值
体重增长_透前减干体重: number, // 体重增长_透前减干体重
- 透前减干体重减超滤总量差值: number, // 透前减干体重减超滤总量差值
+ 透前减干体重减超滤总量差值: number // 透前减干体重减超滤总量差值
) => {
ctx.beginPath();
ctx.arc(x, y + height, radius, 0, Math.PI * 2);
@@ -652,24 +679,26 @@
// 如果超滤总量 与 体重增长_透前减干体重 相等,则显示 "/超滤总量"
if (Number(超滤总量) && 体重增长_透前减干体重 === Number(超滤总量)) {
- ctx.font = `${baseFontSize * scale}px Arial`;
- ctx.textAlign = "center";
- ctx.fillStyle = "#07c160";
- ctx.fillText('/' + 超滤总量, textX, canvasHeight - height + height * 0.3 + 10);
+ ctx.font = `${baseFontSize * scale}px Arial`;
+ ctx.textAlign = "center";
+ ctx.fillStyle = "#07c160";
+ ctx.fillText(
+ "/" + 超滤总量,
+ textX,
+ canvasHeight - height + height * 0.3 + 10
+ );
} else {
// 透析前-干体重
ctx.font = `${baseFontSize * scale}px Arial`;
ctx.textAlign = "center";
ctx.fillStyle = "#409EFF";
- ctx.fillText(体重增长_透前减干体重 + '', textX, canvasHeight - height + 10);
+ ctx.fillText(体重增长_透前减干体重 + "", textX, canvasHeight - height + 10);
// 超滤总量
ctx.font = `${baseFontSize * scale}px Arial`;
ctx.textAlign = "center";
ctx.fillStyle = "#07c160";
ctx.fillText(超滤总量, textX, canvasHeight - height + height * 0.3 + 10);
}
-
-
if (透前减干体重减超滤总量差值 > 0) {
ctx.font = `${baseFontSize * scale}px Arial`;
@@ -1095,7 +1124,7 @@
font-size: 3px;
color: #666;
margin-right: 1.2px;
- white-space: nowrap;
+ white-space: nowrap;
}
// .text-right {
// position: absolute;
diff --git a/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
index c8f442b..359069f 100644
--- a/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
+++ b/src/views/mobile/bedsideAuxiliaryScreen/pages/UnderTreatment.vue
@@ -304,20 +304,20 @@
@click="() => onScheduledTasksClick()"
class="btn"
/>
- <BlockBotttom
+ <!-- <BlockBotttom
:icon="jiaoHaoImg"
text="叫号"
backgroundColor="#20C6B6"
@click="() => onCallBumberClick()"
class="btn"
- />
- <BlockBotttom
+ /> -->
+ <!-- <BlockBotttom
:icon="addImg"
text="添加记录"
backgroundColor="#409EFF"
@click="() => onAddRecordClick()"
class="btn"
- />
+ /> -->
<BlockBotttom
v-if="!whetherDialysisHasBeenEnded"
:icon="kaiShiImg"
@@ -331,6 +331,8 @@
</div>
<!-- 定时任务 -->
<ScheduledTaskDialog ref="scheduledTaskDialogRef" />
+ <!-- 结束透析组件 -->
+ <EndDialysis ref="endDialysisRef" />
</div>
</template>
<script lang="ts" setup name="UnderTreatment">
@@ -355,6 +357,7 @@
const ScheduledTaskDialog = defineAsyncComponent(
() => import("../components/ScheduledTask.vue")
);
+const EndDialysis = defineAsyncComponent(() => import("../components/EndDialysis/index.vue"));
import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen";
import {
formatSubstituteMode,
@@ -390,6 +393,7 @@
const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore();
const scheduledTaskDialogRef = ref<any>(null);
+const endDialysisRef = ref<any>(null);
// ktv趋势图的
const ktvListEchartRef = ref<HTMLElement | null>(null);
@@ -419,6 +423,8 @@
+bedsideAuxiliaryScreenStore.deviceData.treatmentStatus >= EMedStatus.END
);
});
+
+
watch(
() => pageData.value.ktvList,
@@ -785,10 +791,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(() => {
--
Gitblit v1.8.0