import { defineStore } from "pinia";
|
import { ref } from "vue";
|
import dayjs from "dayjs";
|
import { EventSourcePolyfill } from "event-source-polyfill";
|
import type {
|
BedsideAuxiliaryScreen,
|
SseMsgData,
|
} from "./type/bedsideAuxiliaryScreen.type";
|
import type { Task } from "./type/task.type";
|
import {
|
defaultDeviceData,
|
defaultconsumablesCollection,
|
formatDeviceData,
|
} from "./type/bedsideAuxiliaryScreen.type";
|
import { ElMessage } from "element-plus/es";
|
import { Local } from "@/utils/storage";
|
import type { UserInfo } from './type/user.type';
|
|
export const useBedsideAuxiliaryScreenStore = defineStore(
|
"bedsideAuxiliaryScreen",
|
() => {
|
/** 设备编号 */
|
const deviceCode = ref<string>(Local.get("devcieCode") || "");
|
|
/** 副屏版本号 */
|
const version = ref<string>(Local.get("version") || "0.0.0");
|
|
/** 设备信息数据 */
|
const deviceData = ref<BedsideAuxiliaryScreen>(defaultDeviceData());
|
|
/** 任务列表 */
|
const taskData = ref<Task[]>([]);
|
|
/** 用户信息 */
|
const userInfo = ref<UserInfo | null>(Local.get('userInfo'));
|
|
/** 用户token */
|
const token = ref<string>(Local.get('token'));
|
|
/** 设置副屏版本号 */
|
const setVersion = (val: string) => {
|
version.value = val;
|
Local.set("version", val);
|
};
|
|
/**
|
* 设置设备编号
|
* @param code
|
*/
|
const setDeviceCode = (code: string) => {
|
deviceCode.value = code;
|
Local.set("devcieCode", code);
|
};
|
|
/**
|
* 清除设备信息
|
*/
|
const clearDevice = () => {
|
deviceData.value = defaultDeviceData();
|
};
|
|
/**
|
* 追加定时任务
|
* @param taskItem
|
*/
|
const pushTask = (taskItem: Task) => {
|
taskData.value.push(taskItem);
|
};
|
|
/** 设置当前定时任务 */
|
const setSyncTask = (taskItem: Task) => {
|
taskData.value = [taskItem];
|
};
|
|
/** 清除当前定时任务 */
|
const clearTask = () => {
|
taskData.value = [];
|
};
|
|
/** 设置用户信息 */
|
const setUserInfo = (user: UserInfo) => {
|
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;
|
};
|
|
// SSE 相关状态
|
const source = ref<EventSource | null>(null);
|
const message = ref<string | null>(null);
|
const isConnected = ref(false);
|
|
// 重连控制
|
let retryCount = 0;
|
const maxRetryCount = 6000 * 60 * 24 * 30;
|
const baseRetryDelay = 1000; // 1秒开始重连延迟
|
|
/**
|
* 连接 SSE 服务
|
* @param url SSE 地址
|
*/
|
const connect = (url: string) => {
|
if (source.value) return; // 已连接,避免重复连接
|
ElMessage.success("正在连接设备,请稍候...");
|
|
source.value = new EventSourcePolyfill(url, {
|
heartbeatTimeout: 60000,
|
});
|
|
source.value.onopen = () => {
|
console.log("[SSE] 连接成功");
|
ElMessage.success("链接服务成功");
|
isConnected.value = true;
|
retryCount = 0; // 成功连接后重置重试计数
|
};
|
|
source.value.onerror = (e) => {
|
console.warn("[SSE] 错误,等待重连中", e);
|
isConnected.value = false;
|
close(); // 关闭旧连接,避免残留
|
if (retryCount < maxRetryCount) {
|
const delay = baseRetryDelay * Math.pow(2, retryCount); // 指数退避
|
retryCount++;
|
console.log(`[SSE] 第${retryCount}次重连,延迟${baseRetryDelay}ms`);
|
ElMessage.warning(
|
`链接服务失败, 第${retryCount}次重连,请耐心等待重连。。`
|
);
|
setTimeout(() => {
|
connect(url);
|
}, delay);
|
} else {
|
console.error("[SSE] 重连次数达到上限,停止重连");
|
ElMessage.error("重连次数达到上限,请检查网络或设备状态");
|
}
|
};
|
|
source.value.onmessage = (e) => {
|
console.log("[SSE] 消息:", e.data);
|
const msg = e.data;
|
let dif = msg.indexOf("event:message");
|
let beng = msg.indexOf("{");
|
let end = msg.length - 1;
|
if (beng !== -1 && end !== -1 && dif !== -1) {
|
const datax = msg.slice(beng, end + 1);
|
const dataBody = JSON.parse(datax) as SseMsgData;
|
console.log("dataBody: ", dataBody);
|
// 倒计时提示文本
|
if (
|
dataBody.倒计时?.提醒文本 &&
|
Number(dataBody.倒计时?.设定提醒倒计时 > 0)
|
) {
|
const serverTimeRaw = dataBody.倒计时?.当前服务器时间;
|
const reminderMinutes = Number(
|
dataBody.倒计时?.设定提醒倒计时 ?? 0
|
);
|
const serverTimeFormatted = serverTimeRaw.replace(" ", "T");
|
|
const taskTime = dayjs(serverTimeFormatted).add(
|
reminderMinutes,
|
"second"
|
);
|
setSyncTask({
|
deviceCode: dataBody.IOT信息.设备唯一编号,
|
recordCode: dataBody.透析状态?.透析单编号,
|
taskDate: taskTime.format("YYYY-MM-DD HH:mm"),
|
taskName: dataBody.倒计时?.提醒文本,
|
overdue: false,
|
sync: true,
|
countdown: dataBody.倒计时?.设定提醒倒计时,
|
});
|
} else {
|
clearTask();
|
}
|
|
deviceData.value = formatDeviceData(deviceData.value, dataBody);
|
// 判断本地的版本号与远程的版本号是否一致,如果不一致则执行刷新操作
|
if (dataBody.服务端版本号 !== version.value) {
|
refreshVersion(dataBody.服务端版本号);
|
} else if (dataBody.是否需要立即刷新 === 1) {
|
refreshVersion(dataBody.服务端版本号);
|
}
|
}
|
};
|
};
|
|
/** 刷新副屏 */
|
const refreshVersion = (val?: string) => {
|
if (val) {
|
setVersion(val);
|
}
|
ElMessage({
|
type: "success",
|
duration: 1000 * 3,
|
message: "系统更新···",
|
onClose: function () {
|
window.location.reload();
|
},
|
});
|
};
|
|
/**
|
* 关闭 SSE 连接
|
*/
|
const close = () => {
|
if (source.value) {
|
source.value.close();
|
source.value = null;
|
isConnected.value = false;
|
clearDevice();
|
clearTask();
|
console.log("[SSE] 连接已关闭");
|
}
|
};
|
|
/** 刷新 SSE 连接 */
|
const refresh = (url: string) => {
|
retryCount = 0;
|
close(); // 先关闭旧连接
|
connect(url); // 再重新连接
|
};
|
|
return {
|
version,
|
deviceCode,
|
deviceData,
|
setDeviceCode,
|
source,
|
message,
|
isConnected,
|
connect,
|
close,
|
refresh,
|
taskData,
|
pushTask,
|
setSyncTask,
|
clearTask,
|
setVersion,
|
refreshVersion,
|
userInfo,
|
token,
|
setUserInfo,
|
setToken,
|
logout,
|
};
|
}
|
);
|