hrp-ui-base 1.0.2 → 1.0.4
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 +1 -1
- package/dist/components.es.js +3595 -1224
- package/dist/index.cjs +1 -1
- package/dist/index.es.js +86 -69
- package/dist/style.css +1 -1
- package/package.json +2 -1
- package/src/api/notice/NoticeController.ts +73 -0
- package/src/api/notice/bo/NoticePageBO.ts +24 -0
- package/src/api/notice/bo/NoticeVO.ts +31 -0
- package/src/assets/layout/avatar-default.svg +6 -0
- package/src/assets/layout/collect-active.svg +7 -0
- package/src/assets/layout/collect-default.svg +7 -0
- package/src/assets/layout/download-active.svg +8 -0
- package/src/assets/layout/download-default.svg +8 -0
- package/src/assets/layout/export-dark.svg +7 -0
- package/src/assets/layout/export-default.svg +7 -0
- package/src/assets/layout/font-active.svg +6 -0
- package/src/assets/layout/font-default.svg +6 -0
- package/src/assets/layout/help-active.svg +10 -0
- package/src/assets/layout/help-default.svg +10 -0
- package/src/assets/layout/home-active.svg +6 -0
- package/src/assets/layout/home.svg +6 -0
- package/src/assets/layout/menu-expand.svg +6 -0
- package/src/assets/layout/menu-icon.png +0 -0
- package/src/assets/layout/menu-position-active.svg +6 -0
- package/src/assets/layout/menu-position-default.svg +6 -0
- package/src/assets/layout/message-active.svg +9 -0
- package/src/assets/layout/message-default.svg +9 -0
- package/src/assets/layout/moon.svg +8 -0
- package/src/assets/layout/router-all-dark.svg +11 -0
- package/src/assets/layout/router-all-default.svg +17 -0
- package/src/assets/layout/search-active.svg +20 -0
- package/src/assets/layout/search-default.svg +20 -0
- package/src/assets/layout/star-active.svg +1 -0
- package/src/assets/layout/star-default.svg +3 -0
- package/src/assets/layout/sun-active.svg +6 -0
- package/src/assets/layout/sun-default.svg +6 -0
- package/src/assets/layout/switch-moon.svg +3 -0
- package/src/assets/layout/switch-sun.svg +41 -0
- package/src/assets/layout/todo-active.svg +12 -0
- package/src/assets/layout/todo-default.svg +12 -0
- package/src/assets/layout/user-dark.svg +13 -0
- package/src/assets/layout/user-default.svg +13 -0
- package/src/components/base-layout/index.vue +198 -0
- package/src/components/layout/SysHeader.vue +90 -0
- package/src/components/layout/SysHeaderLeft.vue +116 -0
- package/src/components/layout/SysHeaderRight.vue +112 -0
- package/src/components/layout/SysHeaderTabs.vue +289 -0
- package/src/components/layout/components/avatar-component.vue +77 -0
- package/src/components/layout/components/dark-component.vue +82 -0
- package/src/components/layout/components/download-component.vue +49 -0
- package/src/components/layout/components/font-size-component.vue +66 -0
- package/src/components/layout/components/menu-position-component.vue +97 -0
- package/src/components/layout/components/message-component.vue +64 -0
- package/src/components/layout/components/todo-component.vue +55 -0
- package/src/components/layout/index.ts +24 -0
- package/src/components/layout/message/message-dictionary.ts +27 -0
- package/src/components/layout/message/message-icon//345/205/250/351/203/250/351/200/232/347/237/245-/350/223/235.svg +8 -0
- package/src/components/layout/message/message-icon//345/205/250/351/203/250/351/200/232/347/237/245-/351/273/221.svg +8 -0
- package/src/components/layout/message/message-icon//345/205/250/351/203/250/351/200/232/347/237/245.svg +8 -0
- package/src/components/layout/message/message-icon//345/205/254/345/221/212/351/200/232/347/237/245-/350/223/235.svg +12 -0
- package/src/components/layout/message/message-icon//345/205/254/345/221/212/351/200/232/347/237/245-/351/273/221.svg +12 -0
- package/src/components/layout/message/message-icon//345/205/254/345/221/212/351/200/232/347/237/245.svg +12 -0
- package/src/components/layout/message/message-icon//345/256/241/346/211/271/351/200/232/347/237/245-/350/223/235.svg +8 -0
- package/src/components/layout/message/message-icon//345/256/241/346/211/271/351/200/232/347/237/245-/351/273/221.svg +8 -0
- package/src/components/layout/message/message-icon//345/256/241/346/211/271/351/200/232/347/237/245.svg +8 -0
- package/src/components/layout/message/message-icon//345/257/274/345/207/272/351/200/232/347/237/245-/350/223/235.svg +13 -0
- package/src/components/layout/message/message-icon//345/257/274/345/207/272/351/200/232/347/237/245-/351/273/221.svg +13 -0
- package/src/components/layout/message/message-icon//345/257/274/345/207/272/351/200/232/347/237/245.svg +13 -0
- package/src/components/layout/message/message-icon//346/234/252/350/257/273/351/200/232/347/237/245-/350/223/235.svg +11 -0
- package/src/components/layout/message/message-icon//346/234/252/350/257/273/351/200/232/347/237/245-/351/273/221.svg +11 -0
- package/src/components/layout/message/message-icon//346/234/252/350/257/273/351/200/232/347/237/245.svg +11 -0
- package/src/components/layout/message/message-icon//347/251/272/347/212/266/346/200/201.svg +17 -0
- package/src/components/layout/message/message-icon//347/263/273/347/273/237/351/200/232/347/237/245-/350/223/235.svg +13 -0
- package/src/components/layout/message/message-icon//347/263/273/347/273/237/351/200/232/347/237/245-/351/273/221.svg +13 -0
- package/src/components/layout/message/message-icon//347/263/273/347/273/237/351/200/232/347/237/245.svg +13 -0
- package/src/components/layout/message/message-notification-drawer.vue +529 -0
- package/src/components/layout/personalization-guide-dialog.vue +255 -0
- package/src/components/layout/sideMenu-global.scss +115 -0
- package/src/components/layout/sideMenu.scss +312 -0
- package/src/components/layout/sideMenu.vue +542 -0
- package/src/components/layout/sideMenuSonList.vue +185 -0
- package/src/components/layout/styles/icon.scss +72 -0
- package/src/components/layout/types.ts +98 -0
- package/src/components.ts +19 -4
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="top-tabs-header" @wheel="handleWheel">
|
|
3
|
+
<el-scrollbar ref="scrollbar" class="scroll-container">
|
|
4
|
+
<div ref="container" class="scrollbar-flex-content">
|
|
5
|
+
<div
|
|
6
|
+
v-for="item in tabs"
|
|
7
|
+
:key="item.path"
|
|
8
|
+
:ref="(el) => setTabRef(item.path, el)"
|
|
9
|
+
:class="{ active: activeTab === item.path }"
|
|
10
|
+
class="tags-view-item"
|
|
11
|
+
>
|
|
12
|
+
<span
|
|
13
|
+
class="tags-view-item-link"
|
|
14
|
+
@click="handleTabClick(item)"
|
|
15
|
+
@contextmenu.prevent="openMenu(item, $event)"
|
|
16
|
+
>
|
|
17
|
+
{{ item.name || item.title }}
|
|
18
|
+
</span>
|
|
19
|
+
<el-icon v-if="item.path !== homeUrl" @click="handleTabClose(item)">
|
|
20
|
+
<Close />
|
|
21
|
+
</el-icon>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</el-scrollbar>
|
|
25
|
+
<ul
|
|
26
|
+
v-show="visible"
|
|
27
|
+
:style="{ left: coord.left + 'px', top: coord.top + 'px' }"
|
|
28
|
+
class="contextmenu"
|
|
29
|
+
>
|
|
30
|
+
<li
|
|
31
|
+
v-if="selectedTag?.path !== homeUrl"
|
|
32
|
+
@click="handleTabClose(selectedTag!)"
|
|
33
|
+
>
|
|
34
|
+
关闭当前
|
|
35
|
+
</li>
|
|
36
|
+
<li @click="handleCloseOthers">关闭其他</li>
|
|
37
|
+
<li v-if="!isFirstView()" @click="handleCloseLeft">关闭左侧</li>
|
|
38
|
+
<li v-if="!isLastView()" @click="handleCloseRight">关闭右侧</li>
|
|
39
|
+
<li @click="handleCloseAll">全部关闭</li>
|
|
40
|
+
</ul>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script lang="ts" setup>
|
|
45
|
+
import { computed, ref, watch, nextTick, PropType } from "vue";
|
|
46
|
+
import { ElScrollbar } from "element-plus";
|
|
47
|
+
import type { TabItem } from "./types";
|
|
48
|
+
|
|
49
|
+
const props = defineProps({
|
|
50
|
+
tabs: {
|
|
51
|
+
type: Array as PropType<TabItem[]>,
|
|
52
|
+
default: () => []
|
|
53
|
+
},
|
|
54
|
+
activeTab: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: ''
|
|
57
|
+
},
|
|
58
|
+
homeUrl: {
|
|
59
|
+
type: String,
|
|
60
|
+
default: '/application-entry'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const emit = defineEmits<{
|
|
65
|
+
(e: 'tab-click', tab: TabItem): void
|
|
66
|
+
(e: 'tab-close', tab: TabItem): void
|
|
67
|
+
(e: 'tab-close-other', tab: TabItem): void
|
|
68
|
+
(e: 'tab-close-all'): void
|
|
69
|
+
(e: 'tab-close-left', tab: TabItem): void
|
|
70
|
+
(e: 'tab-close-right', tab: TabItem): void
|
|
71
|
+
}>();
|
|
72
|
+
|
|
73
|
+
const scrollbar = ref<InstanceType<typeof ElScrollbar>>();
|
|
74
|
+
const container = ref<HTMLElement>();
|
|
75
|
+
const tabRefs = ref<Record<string, HTMLElement | null>>({});
|
|
76
|
+
|
|
77
|
+
/** 右键菜单状态 */
|
|
78
|
+
const visible = ref(false);
|
|
79
|
+
const coord = ref({ left: 0, top: 0 });
|
|
80
|
+
const selectedTag = ref<TabItem>();
|
|
81
|
+
|
|
82
|
+
/** 设置标签引用 */
|
|
83
|
+
function setTabRef(path: string, el: any) {
|
|
84
|
+
tabRefs.value["tag" + path] = el;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 点击标签 */
|
|
88
|
+
function handleTabClick(tab: TabItem) {
|
|
89
|
+
emit('tab-click', tab);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** 关闭标签 */
|
|
93
|
+
function handleTabClose(tab: TabItem) {
|
|
94
|
+
if (tab.path === props.homeUrl) return;
|
|
95
|
+
emit('tab-close', tab);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** 打开右键菜单 */
|
|
99
|
+
function openMenu(tag: TabItem, e: MouseEvent) {
|
|
100
|
+
coord.value.left = e.clientX;
|
|
101
|
+
coord.value.top = e.clientY;
|
|
102
|
+
visible.value = true;
|
|
103
|
+
selectedTag.value = tag;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** 关闭右键菜单 */
|
|
107
|
+
function closeMenu() {
|
|
108
|
+
visible.value = false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** 关闭其他标签 */
|
|
112
|
+
function handleCloseOthers() {
|
|
113
|
+
if (selectedTag.value) {
|
|
114
|
+
emit('tab-close-other', selectedTag.value);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** 关闭全部标签 */
|
|
119
|
+
function handleCloseAll() {
|
|
120
|
+
emit('tab-close-all');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** 关闭左侧标签 */
|
|
124
|
+
function handleCloseLeft() {
|
|
125
|
+
if (selectedTag.value) {
|
|
126
|
+
emit('tab-close-left', selectedTag.value);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** 关闭右侧标签 */
|
|
131
|
+
function handleCloseRight() {
|
|
132
|
+
if (selectedTag.value) {
|
|
133
|
+
emit('tab-close-right', selectedTag.value);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** 是否是第一个标签 */
|
|
138
|
+
function isFirstView(): boolean {
|
|
139
|
+
if (!selectedTag.value || props.tabs.length === 0) return true;
|
|
140
|
+
return selectedTag.value.path === props.tabs[0]?.path;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** 是否是最后一个标签 */
|
|
144
|
+
function isLastView(): boolean {
|
|
145
|
+
if (!selectedTag.value || props.tabs.length === 0) return true;
|
|
146
|
+
return selectedTag.value.path === props.tabs[props.tabs.length - 1]?.path;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** 滚动到当前标签 */
|
|
150
|
+
function scrollToActiveTab() {
|
|
151
|
+
nextTick(() => {
|
|
152
|
+
const activeTabRef = tabRefs.value["tag" + props.activeTab];
|
|
153
|
+
if (activeTabRef && scrollbar.value) {
|
|
154
|
+
const containerWidth = container.value?.offsetWidth || 0;
|
|
155
|
+
const tabLeft = activeTabRef.offsetLeft;
|
|
156
|
+
const tabWidth = activeTabRef.offsetWidth;
|
|
157
|
+
if (tabLeft + tabWidth > containerWidth) {
|
|
158
|
+
scrollbar.value.setScrollLeft(tabLeft - containerWidth + tabWidth + 20);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** 处理鼠标滚轮事件 */
|
|
165
|
+
function handleWheel(event: WheelEvent) {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
if (scrollbar.value) {
|
|
168
|
+
const wrapRef = scrollbar.value.wrapRef;
|
|
169
|
+
if (wrapRef) {
|
|
170
|
+
wrapRef.scrollLeft += event.deltaY;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** 监听右键菜单显示状态 */
|
|
176
|
+
watch(visible, (value) => {
|
|
177
|
+
if (value) {
|
|
178
|
+
document.body.addEventListener("click", closeMenu);
|
|
179
|
+
} else {
|
|
180
|
+
document.body.removeEventListener("click", closeMenu);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
/** 监听 activeTab 变化滚动到对应位置 */
|
|
185
|
+
watch(() => props.activeTab, () => {
|
|
186
|
+
scrollToActiveTab();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
/** 暴露方法 */
|
|
190
|
+
defineExpose({ scrollToActiveTab });
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
<style lang="scss" scoped>
|
|
194
|
+
.top-tabs-header {
|
|
195
|
+
height: 32px;
|
|
196
|
+
position: relative;
|
|
197
|
+
overflow: visible;
|
|
198
|
+
box-sizing: border-box;
|
|
199
|
+
background: var(--custom-theme-fill-1);
|
|
200
|
+
|
|
201
|
+
:deep(.el-scrollbar) {
|
|
202
|
+
height: 32px;
|
|
203
|
+
overflow: visible;
|
|
204
|
+
|
|
205
|
+
.el-scrollbar__wrap {
|
|
206
|
+
overflow-x: scroll;
|
|
207
|
+
overflow-y: hidden;
|
|
208
|
+
scrollbar-width: none;
|
|
209
|
+
-ms-overflow-style: none;
|
|
210
|
+
&::-webkit-scrollbar { display: none; }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.el-scrollbar__bar.is-horizontal {
|
|
214
|
+
height: 6px;
|
|
215
|
+
bottom: -6px;
|
|
216
|
+
left: 0;
|
|
217
|
+
right: 0;
|
|
218
|
+
border-radius: 3px;
|
|
219
|
+
background-color: var(--custom-theme-fill-4);
|
|
220
|
+
.el-scrollbar__thumb {
|
|
221
|
+
background-color: var(--custom-theme-text-4);
|
|
222
|
+
border-radius: 3px;
|
|
223
|
+
&:hover { background-color: var(--custom-theme-text-3); }
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.el-scrollbar__bar.is-vertical { display: none; }
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.scrollbar-flex-content {
|
|
231
|
+
display: flex;
|
|
232
|
+
background: var(--custom-theme-fill-7);
|
|
233
|
+
height: 32px;
|
|
234
|
+
padding-top: 2px;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.tags-view-item {
|
|
238
|
+
display: flex;
|
|
239
|
+
flex-shrink: 0;
|
|
240
|
+
align-items: center;
|
|
241
|
+
justify-content: center;
|
|
242
|
+
cursor: pointer;
|
|
243
|
+
height: 30px;
|
|
244
|
+
line-height: 30px;
|
|
245
|
+
border-right: 1px solid var(--custom-theme-border-3);
|
|
246
|
+
border-bottom: 1px solid var(--custom-theme-border-3);
|
|
247
|
+
color: var(--custom-theme-text-2);
|
|
248
|
+
background: var(--custom-theme-fill-7);
|
|
249
|
+
font-size: var(--el-menu-item-font-size);
|
|
250
|
+
padding: 0 10px;
|
|
251
|
+
|
|
252
|
+
.tags-view-item-link {
|
|
253
|
+
display: inline-block;
|
|
254
|
+
padding: 0 8px;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.tags-view-item.active {
|
|
259
|
+
background: var(--custom-main-bg-fill);
|
|
260
|
+
color: var(--custom-theme-normal-normal);
|
|
261
|
+
border-bottom: none;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.contextmenu {
|
|
265
|
+
margin: 0;
|
|
266
|
+
background: var(--custom-theme-fill-7);
|
|
267
|
+
z-index: 3000;
|
|
268
|
+
position: fixed;
|
|
269
|
+
list-style-type: none;
|
|
270
|
+
padding: 5px 0;
|
|
271
|
+
border-radius: 4px;
|
|
272
|
+
font-size: 12px;
|
|
273
|
+
font-weight: 400;
|
|
274
|
+
color: var(--custom-theme-text-1);
|
|
275
|
+
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
276
|
+
border: 1px solid var(--custom-theme-border-3);
|
|
277
|
+
|
|
278
|
+
li {
|
|
279
|
+
margin: 0;
|
|
280
|
+
padding: 7px 16px;
|
|
281
|
+
cursor: pointer;
|
|
282
|
+
&:hover {
|
|
283
|
+
background: var(--custom-theme-fill-4);
|
|
284
|
+
color: var(--custom-theme-normal-normal);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
</style>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @description: 用户头像组件
|
|
3
|
+
* @fileName: avatar-component.vue
|
|
4
|
+
!-->
|
|
5
|
+
<template>
|
|
6
|
+
<div>
|
|
7
|
+
<el-dropdown>
|
|
8
|
+
<div class="icon-box" style="border:none;margin-right: 10px;">
|
|
9
|
+
<img :src="(avatar ? avatar : AvatarDefaultImg)"
|
|
10
|
+
style="width: 30px;border-radius: 6px;" id="tourPersonalId">
|
|
11
|
+
</div>
|
|
12
|
+
<template #dropdown>
|
|
13
|
+
<el-dropdown-menu>
|
|
14
|
+
<el-dropdown-item @click="handlePersonalSignClick">个人签名</el-dropdown-item>
|
|
15
|
+
</el-dropdown-menu>
|
|
16
|
+
<el-dropdown-menu>
|
|
17
|
+
<el-dropdown-item @click="handleCleanCache">清理缓存</el-dropdown-item>
|
|
18
|
+
</el-dropdown-menu>
|
|
19
|
+
<el-dropdown-menu v-if="!isInDD && !isInOA">
|
|
20
|
+
<el-dropdown-item @click="handleExitLogin">退出登录</el-dropdown-item>
|
|
21
|
+
</el-dropdown-menu>
|
|
22
|
+
</template>
|
|
23
|
+
</el-dropdown>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang='ts'>
|
|
28
|
+
import { ref, onMounted } from 'vue'
|
|
29
|
+
import AvatarDefaultImg from "../../../assets/layout/avatar-default.svg";
|
|
30
|
+
import dd from "dingtalk-jsapi";
|
|
31
|
+
|
|
32
|
+
const props = defineProps<{
|
|
33
|
+
avatar?: string
|
|
34
|
+
}>()
|
|
35
|
+
|
|
36
|
+
const emit = defineEmits<{
|
|
37
|
+
(e: 'personal-sign'): void
|
|
38
|
+
(e: 'clean-cache'): void
|
|
39
|
+
(e: 'logout'): void
|
|
40
|
+
}>()
|
|
41
|
+
|
|
42
|
+
const isInDD = ref<boolean>(false)
|
|
43
|
+
const isInOA = ref<boolean>(false)
|
|
44
|
+
const avatar = ref(props.avatar)
|
|
45
|
+
|
|
46
|
+
import { watch } from 'vue'
|
|
47
|
+
watch(() => props.avatar, (val) => { avatar.value = val })
|
|
48
|
+
|
|
49
|
+
const handlePersonalSignClick = () => {
|
|
50
|
+
emit('personal-sign')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const handleCleanCache = () => {
|
|
54
|
+
emit('clean-cache')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const handleExitLogin = () => {
|
|
58
|
+
emit('logout')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
onMounted(() => {
|
|
62
|
+
if (dd.env.platform !== "notInDingTalk") {
|
|
63
|
+
isInDD.value = true
|
|
64
|
+
} else {
|
|
65
|
+
isInDD.value = false
|
|
66
|
+
}
|
|
67
|
+
if ((window as any).oaTool && (window as any).oaTool.isOA) {
|
|
68
|
+
isInOA.value = true
|
|
69
|
+
} else {
|
|
70
|
+
isInOA.value = false
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<style scoped lang='scss'>
|
|
76
|
+
@use '../styles/icon.scss';
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @description: 昼夜模式切换组件
|
|
3
|
+
* @fileName: dark-component.vue
|
|
4
|
+
!-->
|
|
5
|
+
<template>
|
|
6
|
+
<div>
|
|
7
|
+
<!-- 昼夜模式 -->
|
|
8
|
+
<el-dropdown trigger="click" @visible-change="clickChange">
|
|
9
|
+
<div :class="'icon-box ' + (isClick ?'icon-box-active':'')" id="tourDarkId" ref="iconRef" @mouseenter="mouseEnterIcon"
|
|
10
|
+
@mouseleave="mouseLeaveIcon" @mousemove="mouseEnterIcon">
|
|
11
|
+
<img :src="sunDefaultIcon" v-if="!isClick">
|
|
12
|
+
<img :src="sunActiveIcon" v-if="isClick">
|
|
13
|
+
</div>
|
|
14
|
+
<template #dropdown>
|
|
15
|
+
<div class="flex-row-center common-switch-box">
|
|
16
|
+
<span>是否跟随系统</span>
|
|
17
|
+
<el-switch v-model="localFollowSystem" style="margin: 0 12px;"
|
|
18
|
+
@change="changeFollowSystem" :active-value="true" :inactive-value="false"/>
|
|
19
|
+
</div>
|
|
20
|
+
<div v-if="!localFollowSystem" class="flex-row-center common-switch-box" ref="changeDarkRef">
|
|
21
|
+
<span>黑夜模式</span>
|
|
22
|
+
<el-switch v-model="localDayOrNight"
|
|
23
|
+
style="--el-switch-on-color: #333333;--el-switch-off-color:var(--custom-theme-info-normal);--switch-border-color:#f3f3f3;margin: 0 12px;"
|
|
24
|
+
@change="handleDarkChange" active-action-icon="Moon"
|
|
25
|
+
inactive-action-icon="Sunny" active-value="night" inactive-value="day"/>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
</el-dropdown>
|
|
29
|
+
<div class="popover-tooltip-custom" ref="popoverTooptipRef" v-show="isMouseEnter && !isClick" style="left: -50%;">
|
|
30
|
+
<div class="triangle-top"></div>
|
|
31
|
+
<div>昼夜模式切换</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang='ts'>
|
|
37
|
+
import { ref, watch } from 'vue'
|
|
38
|
+
import sunDefaultIcon from '../../../assets/layout/sun-default.svg'
|
|
39
|
+
import sunActiveIcon from '../../../assets/layout/sun-active.svg'
|
|
40
|
+
|
|
41
|
+
const props = defineProps<{
|
|
42
|
+
dayOrNight: string
|
|
43
|
+
followSystem: boolean
|
|
44
|
+
}>()
|
|
45
|
+
|
|
46
|
+
const emit = defineEmits<{
|
|
47
|
+
(e: 'change-dark', value: string, ref?: HTMLElement): void
|
|
48
|
+
(e: 'change-follow-system', value: boolean): void
|
|
49
|
+
}>()
|
|
50
|
+
|
|
51
|
+
const isMouseEnter = ref(false)
|
|
52
|
+
const isClick = ref(false)
|
|
53
|
+
const changeDarkRef = ref<HTMLElement>()
|
|
54
|
+
const localFollowSystem = ref(props.followSystem)
|
|
55
|
+
const localDayOrNight = ref(props.dayOrNight)
|
|
56
|
+
|
|
57
|
+
watch(() => props.followSystem, (val) => { localFollowSystem.value = val })
|
|
58
|
+
watch(() => props.dayOrNight, (val) => { localDayOrNight.value = val })
|
|
59
|
+
|
|
60
|
+
const mouseEnterIcon = () => { isMouseEnter.value = true }
|
|
61
|
+
const mouseLeaveIcon = () => { isMouseEnter.value = false }
|
|
62
|
+
|
|
63
|
+
const changeFollowSystem = () => {
|
|
64
|
+
emit('change-follow-system', localFollowSystem.value)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const handleDarkChange = () => {
|
|
68
|
+
emit('change-dark', localDayOrNight.value, changeDarkRef.value)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const popoverTooptipRef = ref()
|
|
72
|
+
const iconRef = ref()
|
|
73
|
+
|
|
74
|
+
const clickChange = (isVisiable: boolean) => {
|
|
75
|
+
isClick.value = isVisiable
|
|
76
|
+
isMouseEnter.value = false
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<style scoped lang='scss'>
|
|
81
|
+
@use '../styles/icon.scss';
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @description: 下载中心(抽屉展示)
|
|
3
|
+
* @fileName: download-component.vue
|
|
4
|
+
!-->
|
|
5
|
+
<template>
|
|
6
|
+
<div>
|
|
7
|
+
<!-- 下载中心 -->
|
|
8
|
+
<div :class="'icon-box ' + (isActive ? 'icon-box-active' : '')" @click="showDownload" id="tourDownloadId"
|
|
9
|
+
@mouseenter="mouseEnterIcon" @mouseleave="mouseLeaveIcon" @mousemove="mouseEnterIcon" style="overflow: visible">
|
|
10
|
+
<img :src="downloadDefaultIcon" v-if="!isActive">
|
|
11
|
+
<img :src="downloadActiveIcon" v-if="isActive">
|
|
12
|
+
</div>
|
|
13
|
+
<div class="popover-tooltip-custom" ref="popoverTooptipRef" v-show="isMouseEnter && !isActive">
|
|
14
|
+
<div class="triangle-top"></div>
|
|
15
|
+
<div>下载中心</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup lang='ts'>
|
|
21
|
+
import { ref, watch } from 'vue'
|
|
22
|
+
import downloadDefaultIcon from '../../../assets/layout/download-default.svg'
|
|
23
|
+
import downloadActiveIcon from '../../../assets/layout/download-active.svg'
|
|
24
|
+
|
|
25
|
+
const props = defineProps<{
|
|
26
|
+
active?: boolean
|
|
27
|
+
}>()
|
|
28
|
+
|
|
29
|
+
const emit = defineEmits<{
|
|
30
|
+
(e: 'click'): void
|
|
31
|
+
}>()
|
|
32
|
+
|
|
33
|
+
const isMouseEnter = ref(false)
|
|
34
|
+
const isActive = ref(props.active || false)
|
|
35
|
+
|
|
36
|
+
watch(() => props.active, (val) => { isActive.value = !!val })
|
|
37
|
+
|
|
38
|
+
const mouseEnterIcon = () => { isMouseEnter.value = true }
|
|
39
|
+
const mouseLeaveIcon = () => { isMouseEnter.value = false }
|
|
40
|
+
|
|
41
|
+
/** 点击下载中心 */
|
|
42
|
+
const showDownload = () => {
|
|
43
|
+
emit('click')
|
|
44
|
+
}
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<style scoped lang='scss'>
|
|
48
|
+
@use '../styles/icon.scss';
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @description: 字体大小调整组件
|
|
3
|
+
* @fileName: font-size-component.vue
|
|
4
|
+
!-->
|
|
5
|
+
<template>
|
|
6
|
+
<div>
|
|
7
|
+
<el-dropdown trigger="click" @visible-change="clickChange">
|
|
8
|
+
<div id="tourFontSizeId" :class="'icon-box ' + (isClick ? 'icon-box-active' : '')" @mouseenter="mouseEnterIcon"
|
|
9
|
+
@mouseleave="mouseLeaveIcon" @mousemove="mouseEnterIcon">
|
|
10
|
+
<img :src="fontDefaultIcon" v-if="!isClick">
|
|
11
|
+
<img :src="fontActiveIcon" v-if="isClick">
|
|
12
|
+
</div>
|
|
13
|
+
<template #dropdown>
|
|
14
|
+
<el-segmented @change="changeFontSize" v-model="localFontSize" :options="fontSizeOption"
|
|
15
|
+
size="default" />
|
|
16
|
+
</template>
|
|
17
|
+
</el-dropdown>
|
|
18
|
+
<div class="popover-tooltip-custom" ref="popoverTooptipRef" v-show="isMouseEnter && !isClick">
|
|
19
|
+
<div class="triangle-top"></div>
|
|
20
|
+
<div>字体大小</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang='ts'>
|
|
26
|
+
import { ref, watch } from 'vue'
|
|
27
|
+
import fontDefaultIcon from '../../../assets/layout/font-default.svg'
|
|
28
|
+
import fontActiveIcon from '../../../assets/layout/font-active.svg'
|
|
29
|
+
|
|
30
|
+
const props = defineProps<{
|
|
31
|
+
fontSize: string
|
|
32
|
+
}>()
|
|
33
|
+
|
|
34
|
+
const emit = defineEmits<{
|
|
35
|
+
(e: 'change', size: string): void
|
|
36
|
+
}>()
|
|
37
|
+
|
|
38
|
+
const localFontSize = ref(props.fontSize)
|
|
39
|
+
watch(() => props.fontSize, (val) => { localFontSize.value = val })
|
|
40
|
+
|
|
41
|
+
/** 字体的选项 */
|
|
42
|
+
const fontSizeOption = ref([
|
|
43
|
+
{ label: '小', value: 'small' },
|
|
44
|
+
{ label: '中', value: 'medium' },
|
|
45
|
+
{ label: '大', value: 'large' },
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
const isMouseEnter = ref(false)
|
|
49
|
+
const isClick = ref(false)
|
|
50
|
+
|
|
51
|
+
const mouseEnterIcon = () => { isMouseEnter.value = true }
|
|
52
|
+
const mouseLeaveIcon = () => { isMouseEnter.value = false }
|
|
53
|
+
|
|
54
|
+
const clickChange = (isVisiable: boolean) => {
|
|
55
|
+
isClick.value = isVisiable
|
|
56
|
+
isMouseEnter.value = false
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const changeFontSize = (size: string | number | boolean) => {
|
|
60
|
+
emit('change', size as string)
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<style scoped lang='scss'>
|
|
65
|
+
@use '../styles/icon.scss';
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
* @description: 菜单栏位置配置
|
|
3
|
+
* @fileName: menu-position-component.vue
|
|
4
|
+
!-->
|
|
5
|
+
<template>
|
|
6
|
+
<div>
|
|
7
|
+
<el-dropdown trigger="click" @visible-change="clickChange">
|
|
8
|
+
<div
|
|
9
|
+
id="tourMenuPositionId"
|
|
10
|
+
:class="'icon-box menu-position-icon ' + (isClick ? 'icon-box-active' : '')"
|
|
11
|
+
@mouseenter="mouseEnterIcon"
|
|
12
|
+
@mouseleave="mouseLeaveIcon"
|
|
13
|
+
@mousemove="mouseEnterIcon"
|
|
14
|
+
>
|
|
15
|
+
<img :src="menuPositionDefaultIcon" v-if="!isClick" />
|
|
16
|
+
<img :src="menuPositionActiveIcon" v-if="isClick" />
|
|
17
|
+
</div>
|
|
18
|
+
<template #dropdown>
|
|
19
|
+
<div class="menu-position-dropdown">
|
|
20
|
+
<span>菜单栏位置</span>
|
|
21
|
+
<el-segmented
|
|
22
|
+
v-model="localMenuPosition"
|
|
23
|
+
:options="menuPositionOption"
|
|
24
|
+
size="default"
|
|
25
|
+
@change="changeMenuPosition"
|
|
26
|
+
/>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
</el-dropdown>
|
|
30
|
+
<div
|
|
31
|
+
class="popover-tooltip-custom"
|
|
32
|
+
ref="popoverTooptipRef"
|
|
33
|
+
v-show="isMouseEnter && !isClick"
|
|
34
|
+
style="left: -50%;"
|
|
35
|
+
>
|
|
36
|
+
<div class="triangle-top"></div>
|
|
37
|
+
<div>菜单栏位置</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script setup lang="ts">
|
|
43
|
+
import { ref, watch } from "vue";
|
|
44
|
+
import menuPositionDefaultIcon from '../../../assets/layout/menu-position-default.svg'
|
|
45
|
+
import menuPositionActiveIcon from '../../../assets/layout/menu-position-active.svg'
|
|
46
|
+
|
|
47
|
+
const props = defineProps<{
|
|
48
|
+
menuPosition: string
|
|
49
|
+
}>()
|
|
50
|
+
|
|
51
|
+
const emit = defineEmits<{
|
|
52
|
+
(e: 'change', value: string): void
|
|
53
|
+
}>()
|
|
54
|
+
|
|
55
|
+
const localMenuPosition = ref(props.menuPosition)
|
|
56
|
+
watch(() => props.menuPosition, (val) => { localMenuPosition.value = val })
|
|
57
|
+
|
|
58
|
+
/** 菜单栏位置选项 */
|
|
59
|
+
const menuPositionOption = ref([
|
|
60
|
+
{ label: "顶部", value: "top" },
|
|
61
|
+
{ label: "左侧", value: "left" },
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
const isMouseEnter = ref(false);
|
|
65
|
+
const isClick = ref(false);
|
|
66
|
+
const popoverTooptipRef = ref();
|
|
67
|
+
|
|
68
|
+
const mouseEnterIcon = () => { isMouseEnter.value = true };
|
|
69
|
+
const mouseLeaveIcon = () => { isMouseEnter.value = false };
|
|
70
|
+
|
|
71
|
+
const clickChange = (isVisiable: boolean) => {
|
|
72
|
+
isClick.value = isVisiable;
|
|
73
|
+
isMouseEnter.value = false;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const changeMenuPosition = (menuPosition: string | number | boolean) => {
|
|
77
|
+
emit('change', menuPosition as string);
|
|
78
|
+
};
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<style scoped lang="scss">
|
|
82
|
+
@use '../styles/icon.scss';
|
|
83
|
+
|
|
84
|
+
.menu-position-dropdown {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
gap: 12px;
|
|
88
|
+
padding: 10px 12px;
|
|
89
|
+
white-space: nowrap;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.menu-position-icon {
|
|
93
|
+
img {
|
|
94
|
+
width: 23px;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
</style>
|