hrp-ui-base 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components.cjs +10 -1
- package/dist/components.es.js +3577 -2398
- package/dist/index.cjs +1 -1
- package/dist/index.es.js +87 -80
- package/dist/style.css +1 -1
- package/package.json +4 -2
- package/src/components/layout/LayoutContainer.vue +503 -0
- package/src/components/layout/index.ts +8 -0
- package/src/components/layout/plugin.ts +32 -0
- package/src/components/layout/stores/index.ts +5 -0
- package/src/components/layout/stores/useLayoutConfigStore.ts +229 -0
- package/src/components/layout/stores/useLayoutMenuStore.ts +232 -0
- package/src/components/layout/stores/useLayoutNoticeStore.ts +77 -0
- package/src/components/layout/stores/useLayoutTabsStore.ts +367 -0
- package/src/components.ts +5 -3
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { defineStore } from "pinia";
|
|
3
|
+
import { ElMessage } from "element-plus";
|
|
4
|
+
import HomeController from "../../../api/bms/home/HomeController";
|
|
5
|
+
import { setDarkStyle, setWhiteStyle, setFontSizeMode } from "../../../styles/style-set";
|
|
6
|
+
|
|
7
|
+
export class UserConfigBo {
|
|
8
|
+
/** 字体大小 small medium large */
|
|
9
|
+
fontSize: "small" | "medium" | "large" = "medium";
|
|
10
|
+
/** 白天/黑夜 day night */
|
|
11
|
+
dayOrNight: "day" | "night" = "day";
|
|
12
|
+
/** 是否跟随系统 */
|
|
13
|
+
followSystem: boolean = false;
|
|
14
|
+
/** 是否开启新手引导 */
|
|
15
|
+
noviceGuide: boolean = false;
|
|
16
|
+
/** 用户id */
|
|
17
|
+
userId: string = "";
|
|
18
|
+
/** 用户名称 */
|
|
19
|
+
userName: string = "";
|
|
20
|
+
/** 用户头像 */
|
|
21
|
+
avatar: string = "";
|
|
22
|
+
/** 部门列表 */
|
|
23
|
+
deptBaseVoList: { deptId: string; deptName: string }[] = [];
|
|
24
|
+
/** 租户id */
|
|
25
|
+
tenantId: string = "";
|
|
26
|
+
/** 租户name */
|
|
27
|
+
tenantName: string = "";
|
|
28
|
+
/** 文件上传类型 */
|
|
29
|
+
fileUploadType: string = "";
|
|
30
|
+
/** 是否折叠左侧导航栏 */
|
|
31
|
+
navigationBar: boolean = false;
|
|
32
|
+
/** 菜单栏位置 top 顶部 left 左侧 */
|
|
33
|
+
menuPosition: "top" | "left" = "top";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const useLayoutConfigStore = defineStore(
|
|
37
|
+
"layout-config",
|
|
38
|
+
() => {
|
|
39
|
+
const userConfig = ref<UserConfigBo>(new UserConfigBo());
|
|
40
|
+
|
|
41
|
+
/** 获取用户个性化配置 */
|
|
42
|
+
const getUserConfig = async () => {
|
|
43
|
+
await HomeController.getPersonalization()
|
|
44
|
+
.then((data) => {
|
|
45
|
+
if (data.code == 200 && data.res) {
|
|
46
|
+
userConfig.value.fontSize = data.res.personalizationBo.fontSize;
|
|
47
|
+
userConfig.value.dayOrNight = data.res.personalizationBo.dayOrNight;
|
|
48
|
+
userConfig.value.followSystem = data.res.personalizationBo.followSystem;
|
|
49
|
+
userConfig.value.noviceGuide = data.res.personalizationBo.noviceGuide;
|
|
50
|
+
userConfig.value.userId = data.res.userBaseInfoVo.userId;
|
|
51
|
+
userConfig.value.userName = data.res.userBaseInfoVo.userName;
|
|
52
|
+
userConfig.value.avatar = data.res.userBaseInfoVo.avatar;
|
|
53
|
+
userConfig.value.deptBaseVoList = data.res.deptBaseVoList;
|
|
54
|
+
userConfig.value.tenantId = data.res.tenantId;
|
|
55
|
+
userConfig.value.tenantName = data.res.tenantName;
|
|
56
|
+
userConfig.value.fileUploadType = data.res.fileUploadType;
|
|
57
|
+
userConfig.value.navigationBar = data.res.personalizationBo.navigationBar;
|
|
58
|
+
userConfig.value.menuPosition = data.res.personalizationBo.menuPosition || "top";
|
|
59
|
+
setLocalUserConfig();
|
|
60
|
+
followSystemColorModel(userConfig.value.followSystem, true);
|
|
61
|
+
changeFontSize(userConfig.value.fontSize, true);
|
|
62
|
+
} else {
|
|
63
|
+
changeFontSize("medium", true);
|
|
64
|
+
changeDark("day", true);
|
|
65
|
+
ElMessage({ message: "获取个人信息失败..", type: "error" });
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
.catch(() => {
|
|
69
|
+
changeFontSize("medium", true);
|
|
70
|
+
changeDark("day", true);
|
|
71
|
+
ElMessage({ message: "获取个人信息失败..", type: "error" });
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/** 更改用户配置 */
|
|
76
|
+
const changeUserConfig = async () => {
|
|
77
|
+
const submitObj = {
|
|
78
|
+
fontSize: userConfig.value.fontSize,
|
|
79
|
+
dayOrNight: userConfig.value.dayOrNight,
|
|
80
|
+
followSystem: !!userConfig.value.followSystem,
|
|
81
|
+
noviceGuide: !!userConfig.value.noviceGuide,
|
|
82
|
+
navigationBar: !!userConfig.value.navigationBar,
|
|
83
|
+
menuPosition: userConfig.value.menuPosition || "top",
|
|
84
|
+
};
|
|
85
|
+
await HomeController.savePersonalization(submitObj).then((data) => {
|
|
86
|
+
if (data.code === 200) {
|
|
87
|
+
console.debug("修改成功!");
|
|
88
|
+
getUserConfig();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/** 设置本地存储 */
|
|
94
|
+
const setLocalUserConfig = () => {
|
|
95
|
+
sessionStorage.setItem("userConfig", JSON.stringify(userConfig.value));
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/** 读取本地存储 */
|
|
99
|
+
const readLocalUserConfig = async () => {
|
|
100
|
+
try {
|
|
101
|
+
const userConfigSession = sessionStorage.getItem("userConfig");
|
|
102
|
+
if (userConfigSession) {
|
|
103
|
+
userConfig.value = JSON.parse(userConfigSession);
|
|
104
|
+
} else {
|
|
105
|
+
await getUserConfig();
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
await getUserConfig();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/** 修改字体大小 */
|
|
113
|
+
const changeFontSize = (size: "small" | "medium" | "large", isSystem?: boolean) => {
|
|
114
|
+
userConfig.value.fontSize = size;
|
|
115
|
+
setFontSizeMode(size);
|
|
116
|
+
if (!isSystem) {
|
|
117
|
+
changeUserConfig();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/** 修改黑夜模式 */
|
|
122
|
+
const changeDark = (dayOrNight: "day" | "night", isSystem?: boolean) => {
|
|
123
|
+
userConfig.value.dayOrNight = dayOrNight;
|
|
124
|
+
if (dayOrNight === "night") {
|
|
125
|
+
setDarkStyle();
|
|
126
|
+
} else {
|
|
127
|
+
setWhiteStyle();
|
|
128
|
+
}
|
|
129
|
+
if (!isSystem) {
|
|
130
|
+
changeUserConfig();
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/** 跟随系统颜色模式 */
|
|
135
|
+
const followSystemColorModel = (followSystem: boolean, isSystem?: boolean) => {
|
|
136
|
+
userConfig.value.followSystem = followSystem;
|
|
137
|
+
if (followSystem) {
|
|
138
|
+
changeDark(isDarkMode() ? "night" : "day", isSystem);
|
|
139
|
+
} else {
|
|
140
|
+
changeDark(userConfig.value.dayOrNight, isSystem);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/** 切换昼夜模式的动画 */
|
|
145
|
+
function changeDarkAnimation(dayOrNight: "day" | "night", event: any) {
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
if (!document.startViewTransition) {
|
|
148
|
+
changeDark(dayOrNight);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// @ts-ignore
|
|
152
|
+
const transition = document.startViewTransition(() => changeDark(dayOrNight));
|
|
153
|
+
transition.ready.then(() => {
|
|
154
|
+
const x = event?.clientX || window.innerWidth - 130;
|
|
155
|
+
const y = event?.clientY || 50;
|
|
156
|
+
const endRadius = Math.hypot(
|
|
157
|
+
Math.max(x, innerWidth - x),
|
|
158
|
+
Math.max(y, innerHeight - y)
|
|
159
|
+
);
|
|
160
|
+
const clipPath = [
|
|
161
|
+
`circle(0px at ${x}px ${y}px)`,
|
|
162
|
+
`circle(${endRadius}px at ${x}px ${y}px)`,
|
|
163
|
+
];
|
|
164
|
+
document.documentElement.animate(
|
|
165
|
+
{
|
|
166
|
+
clipPath:
|
|
167
|
+
userConfig.value.dayOrNight === "night"
|
|
168
|
+
? [...clipPath].reverse()
|
|
169
|
+
: clipPath,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
duration: 400,
|
|
173
|
+
easing: "ease-in",
|
|
174
|
+
pseudoElement:
|
|
175
|
+
userConfig.value.dayOrNight === "night"
|
|
176
|
+
? "::view-transition-old(root)"
|
|
177
|
+
: "::view-transition-new(root)",
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** 判断当前环境是否是黑夜模式 */
|
|
184
|
+
function isDarkMode() {
|
|
185
|
+
return !!(
|
|
186
|
+
window.matchMedia &&
|
|
187
|
+
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** 初始化基础配置 — 监听系统颜色模式变化 */
|
|
192
|
+
const initUserConfig = () => {
|
|
193
|
+
const mqList = window.matchMedia("(prefers-color-scheme: dark)");
|
|
194
|
+
mqList.addEventListener("change", (event) => {
|
|
195
|
+
if (userConfig.value.followSystem) {
|
|
196
|
+
changeDark(event.matches ? "night" : "day");
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/** 修改新手引导的配置 */
|
|
202
|
+
const changeNoviceGuide = (noviceGuide: boolean) => {
|
|
203
|
+
userConfig.value.noviceGuide = noviceGuide;
|
|
204
|
+
changeUserConfig();
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** 修改菜单栏位置 */
|
|
208
|
+
const changeMenuPosition = (menuPosition: "top" | "left") => {
|
|
209
|
+
userConfig.value.menuPosition = menuPosition;
|
|
210
|
+
changeUserConfig();
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
userConfig,
|
|
215
|
+
getUserConfig,
|
|
216
|
+
setLocalUserConfig,
|
|
217
|
+
readLocalUserConfig,
|
|
218
|
+
changeUserConfig,
|
|
219
|
+
changeFontSize,
|
|
220
|
+
changeDark,
|
|
221
|
+
changeDarkAnimation,
|
|
222
|
+
followSystemColorModel,
|
|
223
|
+
isDarkMode,
|
|
224
|
+
initUserConfig,
|
|
225
|
+
changeNoviceGuide,
|
|
226
|
+
changeMenuPosition,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
);
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { defineStore } from "pinia";
|
|
3
|
+
import { ElMessage } from "element-plus";
|
|
4
|
+
import HomeController from "../../../api/bms/home/HomeController";
|
|
5
|
+
import type HomeMenu from "../../../api/bms/home/bo/HomeMenu";
|
|
6
|
+
import type DomainVO from "../../../api/bms/home/bo/DomainVO";
|
|
7
|
+
import exitLogin from "../../../utils/exitLogin";
|
|
8
|
+
import { useLayoutTabsStore } from "./useLayoutTabsStore";
|
|
9
|
+
|
|
10
|
+
/** 布局菜单 Store — 管理菜单树、系统切换、domain 信息 */
|
|
11
|
+
export const useLayoutMenuStore = defineStore(
|
|
12
|
+
"layout-menu",
|
|
13
|
+
() => {
|
|
14
|
+
/** 当前人所有的权限菜单数据 */
|
|
15
|
+
const routerData = ref<HomeMenu[]>([]);
|
|
16
|
+
/** 当前选中的二级菜单 index */
|
|
17
|
+
const currentSecondIndex = ref<number>(0);
|
|
18
|
+
/** 当前应用信息 */
|
|
19
|
+
const currentApplication = ref<DomainVO>({} as DomainVO);
|
|
20
|
+
/** 收藏的列表 */
|
|
21
|
+
const collectionList = ref<HomeMenu[]>([]);
|
|
22
|
+
/** 常用的列表 */
|
|
23
|
+
const commonUseList = ref<HomeMenu[]>([]);
|
|
24
|
+
|
|
25
|
+
/** 获取路由数据 */
|
|
26
|
+
const getRouterData = async () => {
|
|
27
|
+
const sysId: string =
|
|
28
|
+
typeof localStorage.getItem("current-application-id") === "string"
|
|
29
|
+
? (localStorage.getItem("current-application-id") as string)
|
|
30
|
+
: "";
|
|
31
|
+
await HomeController.getHomeMenu("2", sysId).then((data) => {
|
|
32
|
+
if (data.code === 200 && data.res) {
|
|
33
|
+
routerData.value =
|
|
34
|
+
data.res.homeMenuList &&
|
|
35
|
+
Array.isArray(data.res.homeMenuList) &&
|
|
36
|
+
data.res.homeMenuList.length > 0
|
|
37
|
+
? data.res.homeMenuList
|
|
38
|
+
: [];
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** 切换二级菜单 index,isUserChange 时自动跳转第一个页面 */
|
|
44
|
+
const changeCurrentSecondIndex = (
|
|
45
|
+
index: number,
|
|
46
|
+
isUserChange: boolean = false,
|
|
47
|
+
router?: any
|
|
48
|
+
) => {
|
|
49
|
+
currentSecondIndex.value = index;
|
|
50
|
+
try {
|
|
51
|
+
const firstUrl =
|
|
52
|
+
routerData.value[0]?.children?.[index]?.children?.[0]?.children?.[0]?.url;
|
|
53
|
+
if (firstUrl && isUserChange && router) {
|
|
54
|
+
router.push(firstUrl);
|
|
55
|
+
// 通过事件通知侧边栏展开
|
|
56
|
+
const targetThirdMenuId =
|
|
57
|
+
routerData.value[0].children[index].children[0].menuId;
|
|
58
|
+
if (targetThirdMenuId) {
|
|
59
|
+
window.dispatchEvent(
|
|
60
|
+
new CustomEvent("openSidebarMenu", {
|
|
61
|
+
detail: { url: firstUrl, targetThirdMenuId },
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.log(error);
|
|
68
|
+
ElMessage.warning("路由信息维护异常!");
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/** 获取当前的 domain 信息与路由信息 */
|
|
73
|
+
const getDomainAndHomeMenu = async (aimPath: string, router?: any) => {
|
|
74
|
+
await HomeController.getDomainInfoByUrl(aimPath).then(async (data) => {
|
|
75
|
+
if (data.code == 200 && data.res) {
|
|
76
|
+
currentApplication.value = data.res;
|
|
77
|
+
localStorage.setItem("current-application-id", data.res.domainId);
|
|
78
|
+
localStorage.setItem("current-application-name", data.res.domainName);
|
|
79
|
+
localStorage.setItem("current-application", JSON.stringify(data.res));
|
|
80
|
+
// 切换系统时加载对应系统的标签页数据
|
|
81
|
+
const tabsStore = useLayoutTabsStore();
|
|
82
|
+
tabsStore.switchSystem();
|
|
83
|
+
await getRouterData();
|
|
84
|
+
|
|
85
|
+
let aimSystemIndex = -1;
|
|
86
|
+
try {
|
|
87
|
+
for (let i = 0; i < routerData.value[0].children.length; i++) {
|
|
88
|
+
let ifFindI = false;
|
|
89
|
+
for (let j = 0; j < routerData.value[0].children[i].children.length; j++) {
|
|
90
|
+
let ifFindJ = false;
|
|
91
|
+
for (
|
|
92
|
+
let z = 0;
|
|
93
|
+
z < routerData.value[0].children[i].children[j].children.length;
|
|
94
|
+
z++
|
|
95
|
+
) {
|
|
96
|
+
if (
|
|
97
|
+
aimPath.indexOf(
|
|
98
|
+
routerData.value[0].children[i].children[j].children[z].url
|
|
99
|
+
) > -1
|
|
100
|
+
) {
|
|
101
|
+
ifFindJ = true;
|
|
102
|
+
ifFindI = true;
|
|
103
|
+
aimSystemIndex = i;
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (ifFindJ) break;
|
|
108
|
+
}
|
|
109
|
+
if (ifFindI) break;
|
|
110
|
+
}
|
|
111
|
+
} catch (error) {}
|
|
112
|
+
|
|
113
|
+
if (aimSystemIndex > -1) {
|
|
114
|
+
changeCurrentSecondIndex(aimSystemIndex, false);
|
|
115
|
+
} else {
|
|
116
|
+
ElMessage.warning("系统与菜单不匹配,跳转失败,请手动跳转!");
|
|
117
|
+
changeCurrentSecondIndex(0, true, router);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/** 消息跳转前先判断是否跨系统 */
|
|
124
|
+
const getDomainAndHomeMenuBefore = async (aimPath: string, router?: any) => {
|
|
125
|
+
const originApplicationId = localStorage.getItem("current-application-id");
|
|
126
|
+
await HomeController.getDomainInfoByUrl(aimPath).then(async (data) => {
|
|
127
|
+
if (data.code == 200 && data.res) {
|
|
128
|
+
if (originApplicationId != data.res.domainId) {
|
|
129
|
+
currentApplication.value = data.res;
|
|
130
|
+
localStorage.setItem("current-application-id", data.res.domainId);
|
|
131
|
+
localStorage.setItem("current-application-name", data.res.domainName);
|
|
132
|
+
localStorage.setItem("current-application", JSON.stringify(data.res));
|
|
133
|
+
await getRouterData();
|
|
134
|
+
|
|
135
|
+
let aimSystemIndex = -1;
|
|
136
|
+
try {
|
|
137
|
+
for (let i = 0; i < routerData.value[0].children.length; i++) {
|
|
138
|
+
let ifFindI = false;
|
|
139
|
+
for (let j = 0; j < routerData.value[0].children[i].children.length; j++) {
|
|
140
|
+
let ifFindJ = false;
|
|
141
|
+
for (
|
|
142
|
+
let z = 0;
|
|
143
|
+
z < routerData.value[0].children[i].children[j].children.length;
|
|
144
|
+
z++
|
|
145
|
+
) {
|
|
146
|
+
if (
|
|
147
|
+
aimPath.indexOf(
|
|
148
|
+
routerData.value[0].children[i].children[j].children[z].url
|
|
149
|
+
) > -1
|
|
150
|
+
) {
|
|
151
|
+
ifFindJ = true;
|
|
152
|
+
ifFindI = true;
|
|
153
|
+
aimSystemIndex = i;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (ifFindJ) break;
|
|
158
|
+
}
|
|
159
|
+
if (ifFindI) break;
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {}
|
|
162
|
+
|
|
163
|
+
if (aimSystemIndex > -1) {
|
|
164
|
+
changeCurrentSecondIndex(aimSystemIndex, false);
|
|
165
|
+
} else {
|
|
166
|
+
ElMessage.warning("系统与菜单不匹配,跳转失败,请手动跳转!");
|
|
167
|
+
changeCurrentSecondIndex(0, true, router);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/** 新增/取消收藏菜单 */
|
|
175
|
+
const addCollectionList = async (
|
|
176
|
+
toCollect: boolean,
|
|
177
|
+
menuId: string,
|
|
178
|
+
menuItem?: HomeMenu
|
|
179
|
+
) => {
|
|
180
|
+
await HomeController.saveCollectedMenu({
|
|
181
|
+
menuId,
|
|
182
|
+
collected: toCollect,
|
|
183
|
+
}).then((data) => {
|
|
184
|
+
if (data.code == 200) {
|
|
185
|
+
ElMessage.success(toCollect ? "收藏成功" : "取消收藏成功");
|
|
186
|
+
getCollectionList();
|
|
187
|
+
getRouterData();
|
|
188
|
+
if (menuItem) {
|
|
189
|
+
menuItem.collected = toCollect;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** 获取收藏列表 */
|
|
196
|
+
const getCollectionList = async () => {
|
|
197
|
+
// 可按需启用
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/** 获取常用列表 */
|
|
201
|
+
const getCommonUseList = async () => {
|
|
202
|
+
// 可按需启用
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/** 退出登录 */
|
|
206
|
+
const doExitLogin = (clear?: number) => {
|
|
207
|
+
exitLogin(clear);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/** 埋点 */
|
|
211
|
+
const buryingPoint = async (menuId: string) => {
|
|
212
|
+
await HomeController.buryingPoint(menuId);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
routerData,
|
|
217
|
+
currentSecondIndex,
|
|
218
|
+
currentApplication,
|
|
219
|
+
collectionList,
|
|
220
|
+
commonUseList,
|
|
221
|
+
getRouterData,
|
|
222
|
+
changeCurrentSecondIndex,
|
|
223
|
+
getDomainAndHomeMenu,
|
|
224
|
+
getDomainAndHomeMenuBefore,
|
|
225
|
+
addCollectionList,
|
|
226
|
+
getCollectionList,
|
|
227
|
+
getCommonUseList,
|
|
228
|
+
doExitLogin,
|
|
229
|
+
buryingPoint,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
import { defineStore } from "pinia";
|
|
3
|
+
import NoticeController from "../../../api/notice/NoticeController";
|
|
4
|
+
import type NoticeVO from "../../../api/notice/bo/NoticeVO";
|
|
5
|
+
|
|
6
|
+
/** 消息通知 Store */
|
|
7
|
+
export const useLayoutNoticeStore = defineStore("layout-notice", () => {
|
|
8
|
+
/** 未读消息数量 */
|
|
9
|
+
const unReadCount = ref<number>(0);
|
|
10
|
+
/** 轮询定时器 */
|
|
11
|
+
const pollingTimer = ref<any>(null);
|
|
12
|
+
/** 最新消息列表(轮询获取) */
|
|
13
|
+
const latestNotices = ref<NoticeVO[]>([]);
|
|
14
|
+
|
|
15
|
+
/** 获取未读消息数量 */
|
|
16
|
+
const getNoReadNoticeCount = async () => {
|
|
17
|
+
await NoticeController.getNoReadNoticeCount("").then((data) => {
|
|
18
|
+
if (data.code === 200) {
|
|
19
|
+
unReadCount.value = data.res || 0;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** 标记消息已读 */
|
|
25
|
+
const readNoticeInfo = async (noticeId: string) => {
|
|
26
|
+
await NoticeController.readNoticeInfo(noticeId).then((data) => {
|
|
27
|
+
if (data.code === 200 && data.res) {
|
|
28
|
+
console.log("消息已读");
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** 获取最新通知(轮询使用) */
|
|
34
|
+
const fetchNoticeInfo = async (): Promise<NoticeVO[]> => {
|
|
35
|
+
try {
|
|
36
|
+
const res = await NoticeController.getNoticeInfo();
|
|
37
|
+
if (res.code === 200 && res.res && res.res.length > 0) {
|
|
38
|
+
latestNotices.value = res.res;
|
|
39
|
+
return res.res;
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error("获取通知失败", error);
|
|
43
|
+
}
|
|
44
|
+
return [];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** 开始轮询 */
|
|
48
|
+
const startPolling = (onNewNotice?: (notices: NoticeVO[]) => void, interval: number = 3000) => {
|
|
49
|
+
// 立即执行一次
|
|
50
|
+
const doFetch = async () => {
|
|
51
|
+
const notices = await fetchNoticeInfo();
|
|
52
|
+
if (notices.length > 0 && onNewNotice) {
|
|
53
|
+
onNewNotice(notices);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
doFetch();
|
|
57
|
+
pollingTimer.value = setInterval(doFetch, interval);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** 停止轮询 */
|
|
61
|
+
const stopPolling = () => {
|
|
62
|
+
if (pollingTimer.value) {
|
|
63
|
+
clearInterval(pollingTimer.value);
|
|
64
|
+
pollingTimer.value = null;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
unReadCount,
|
|
70
|
+
latestNotices,
|
|
71
|
+
getNoReadNoticeCount,
|
|
72
|
+
readNoticeInfo,
|
|
73
|
+
fetchNoticeInfo,
|
|
74
|
+
startPolling,
|
|
75
|
+
stopPolling,
|
|
76
|
+
};
|
|
77
|
+
});
|