@pubinfo/core 2.0.0-rc.3 → 2.0.0-rc.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/{AppSetting-3wJKvibc.js → AppSetting-DqVYDIHj.js} +15 -15
- package/dist/{HCheckList.vue_vue_type_script_setup_true_lang-17EywJvs.js → HCheckList.vue_vue_type_script_setup_true_lang-SrNklW3P.js} +1 -1
- package/dist/{HToggle-B-ZjSh6S.js → HToggle-DGTP9jYA.js} +1 -1
- package/dist/{PreferencesContent-xT4paU7N.js → PreferencesContent-5NtwK9RQ.js} +4 -4
- package/dist/{SettingBreadcrumb-CYnO51Ek.js → SettingBreadcrumb-BudqQsuJ.js} +3 -3
- package/dist/{SettingCopyright-FOW5ObHK.js → SettingCopyright-VUberG4R.js} +2 -2
- package/dist/{SettingEnableTransition-Q5cvubmF.js → SettingEnableTransition-C6NYf021.js} +2 -2
- package/dist/SettingHome-BTaeKgwN.js +46 -0
- package/dist/{SettingMenu-BNAJ3el9.js → SettingMenu-D9Aon2LP.js} +3 -3
- package/dist/{SettingMode-LzlRsBL9.js → SettingMode-DaqVd9Mq.js} +1 -1
- package/dist/{SettingNavSearch-BA08vYuw.js → SettingNavSearch-N4JIheIk.js} +2 -2
- package/dist/{SettingOther-BE8dDCYD.js → SettingOther-tLulcors.js} +2 -2
- package/dist/{SettingPage-D061yXCv.js → SettingPage-CEjWB45R.js} +2 -2
- package/dist/{SettingTabbar-COwdPPKy.js → SettingTabbar-DyeLhcCT.js} +3 -3
- package/dist/{SettingThemes-BHaYERNp.js → SettingThemes-C2M3tsVl.js} +1 -1
- package/dist/{SettingToolbar-fSuzu6ND.js → SettingToolbar-DI7de6i0.js} +24 -31
- package/dist/{SettingTopbar-D7GgP0KB.js → SettingTopbar-BgIoXeAq.js} +3 -3
- package/dist/{SettingWidthMode-CNjzChe1.js → SettingWidthMode-DIAU4s5e.js} +1 -1
- package/dist/{TopThinMode-B-28sBJD.js → TopThinMode-JNUHrJI2.js} +1 -1
- package/dist/built-in/authentication/alova/helper.d.ts +34 -0
- package/dist/built-in/authentication/alova/token.d.ts +16 -0
- package/dist/built-in/authentication/helper.d.ts +10 -1
- package/dist/built-in/index.d.ts +1 -1
- package/dist/built-in/layout-component/components/Tools/SearchPanel.vue.d.ts +7 -2
- package/dist/built-in/layout-component/components/ui/HSlideover.vue.d.ts +1 -1
- package/dist/built-in/layout-component/composables/useContext.d.ts +1 -1
- package/dist/built-in/layout-component/composables/useGlobalSearch.d.ts +7 -0
- package/dist/built-in/layout-component/composables/useTitle.d.ts +1 -1
- package/dist/built-in/system-info/components/SystemInfo.vue.d.ts +2 -0
- package/dist/built-in/system-info/index.d.ts +5 -0
- package/dist/{colors-BIQSd520.js → colors-DxWfHM_v.js} +1 -1
- package/dist/core/interface.d.ts +14 -5
- package/dist/core/request.d.ts +2 -8
- package/dist/features/api/modules/auth/renzhengfuwu.d.ts +8 -8
- package/dist/features/api/modules/configData/heibaimingdanfuwu.d.ts +5 -5
- package/dist/features/api/modules/configData/xitongpeizhifuwu.d.ts +14 -14
- package/dist/features/api/modules/configData/zidifuwu.d.ts +10 -10
- package/dist/features/api/modules/rbac/gangweijiekou.d.ts +6 -6
- package/dist/features/api/modules/rbac/jiaosejiekou.d.ts +7 -7
- package/dist/features/api/modules/rbac/pubJiaosezukongzhiqi.d.ts +7 -7
- package/dist/features/api/modules/rbac/shujuquanxianzhubiaokongzhiqi.d.ts +9 -9
- package/dist/features/api/modules/rbac/yonghujiekou.d.ts +15 -15
- package/dist/features/api/modules/rbac/yonghushoucangbiaojiekou.d.ts +5 -5
- package/dist/features/api/modules/rbac/yonghuzuijinchangyongbiaojiekou.d.ts +4 -4
- package/dist/features/api/modules/rbac/ziyuanjiekou.d.ts +13 -13
- package/dist/features/api/modules/rbac/zuhuguanlijiekou.d.ts +5 -5
- package/dist/features/api/modules/rbac/zuzhijiaosebiaokongzhiqi.d.ts +4 -4
- package/dist/features/api/modules/rbac/zuzhijiekou.d.ts +9 -9
- package/dist/features/api/system/user.d.ts +4 -4
- package/dist/features/components/PubinfoIcon/PrismBox.vue.d.ts +21 -0
- package/dist/features/components/PubinfoIcon/SquareBox.vue.d.ts +17 -0
- package/dist/features/components/PubinfoIcon/index.vue.d.ts +13 -9
- package/dist/features/components/PubinfoIcon/props.d.ts +58 -0
- package/dist/features/components/index.d.ts +2 -0
- package/dist/{index-Dlf6GQBd.js → index-5fRpGyLW.js} +4 -4
- package/dist/{index-DNdH93AP.js → index-BFRIv97x.js} +2 -2
- package/dist/{index-WubcSL0v.js → index-BH-vHGvk.js} +1 -1
- package/dist/{index-YSjb6X1D.js → index-C7xIGcDc.js} +4 -7
- package/dist/{index-DYMBkmAp.js → index-CNVn3Ubv.js} +2 -2
- package/dist/{index-CPRiufg0.js → index-Cf-u1Zqh.js} +1 -1
- package/dist/{index-wxEEuQXu.js → index-D4v4g8FJ.js} +111 -97
- package/dist/{index-IscoZG-Y.js → index-DQGnbEGS.js} +2 -2
- package/dist/{index-Beb7_0-E.js → index-Dv7UUFkD.js} +24237 -23807
- package/dist/index.d.ts +1 -1
- package/dist/index.js +55 -48
- package/dist/{pick-D_XPbQHB.js → pick-VFuUwFn-.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/utils/global.d.ts +33 -0
- package/dist/utils/index.d.ts +2 -1
- package/package.json +10 -7
- package/src/built-in/authentication/alova/helper.ts +158 -0
- package/src/built-in/authentication/alova/token.ts +122 -0
- package/src/built-in/authentication/helper.ts +7 -3
- package/src/built-in/authentication/index.ts +6 -20
- package/src/built-in/index.ts +1 -1
- package/src/built-in/layout-component/components/Header/TopMode/index.vue +30 -9
- package/src/built-in/layout-component/components/Menu/item.vue +44 -9
- package/src/built-in/layout-component/components/SettingBar/components/SettingHome.vue +1 -4
- package/src/built-in/layout-component/components/SettingBar/components/SettingToolbar.vue +0 -6
- package/src/built-in/layout-component/components/Sidebar/MainSidebar.vue +3 -3
- package/src/built-in/layout-component/components/Tools/SearchBar.vue +1 -3
- package/src/built-in/layout-component/components/Tools/SearchPanel.vue +125 -57
- package/src/built-in/layout-component/components/Tools/index.vue +9 -12
- package/src/built-in/layout-component/components/Topbar/Tabbar/MoreAction.vue +64 -11
- package/src/built-in/layout-component/components/Topbar/Tabbar/index.vue +73 -18
- package/src/built-in/layout-component/components/Topbar/Toolbar/Favorites.vue +4 -7
- package/src/built-in/layout-component/components/Topbar/Toolbar/index.vue +6 -6
- package/src/built-in/layout-component/composables/useContext.ts +1 -1
- package/src/built-in/layout-component/composables/useGlobalSearch.ts +40 -1
- package/src/built-in/layout-component/composables/useTitle.ts +8 -14
- package/src/built-in/layout-component/provider.ts +2 -2
- package/src/built-in/system-info/components/SystemInfo.vue +53 -0
- package/src/built-in/system-info/index.ts +16 -0
- package/src/core/ctx.ts +7 -1
- package/src/core/interface.ts +18 -5
- package/src/core/request.ts +35 -15
- package/src/core/resolver/icon.ts +9 -5
- package/src/features/components/PubinfoIcon/PrismBox.vue +203 -0
- package/src/features/components/PubinfoIcon/SquareBox.vue +59 -0
- package/src/features/components/PubinfoIcon/index.vue +128 -37
- package/src/features/components/PubinfoIcon/props.ts +54 -0
- package/src/features/components/index.ts +4 -1
- package/src/features/context/index.ts +1 -16
- package/src/features/router/systemRoutes.ts +0 -1
- package/src/features/settings/index.ts +0 -1
- package/src/features/stores/modules/favorites.ts +0 -1
- package/src/features/stores/modules/route.ts +2 -9
- package/src/features/stores/modules/tabbar.ts +0 -3
- package/src/features/stores/utils/routerHelper.ts +35 -4
- package/src/index.ts +7 -2
- package/src/utils/global.ts +161 -0
- package/src/utils/index.ts +2 -1
- package/src/utils/proxy.ts +7 -8
- package/types/global.d.ts +7 -0
- package/types/menu.d.ts +10 -0
- package/types/settings.d.ts +0 -7
- package/types/vue-router.d.ts +0 -3
- package/dist/SettingHome-Df7-AlWB.js +0 -55
- package/dist/built-in/locales/helpler.d.ts +0 -594
- package/dist/built-in/locales/index.d.ts +0 -5
- package/dist/built-in/locales/lang/en.json.d.ts +0 -99
- package/dist/built-in/locales/lang/zh-cn.json.d.ts +0 -100
- package/dist/built-in/locales/lang/zh-tw.json.d.ts +0 -100
- package/dist/built-in/locales/ui.d.ts +0 -3
- package/src/built-in/locales/helpler.ts +0 -76
- package/src/built-in/locales/index.ts +0 -20
- package/src/built-in/locales/lang/en.json +0 -96
- package/src/built-in/locales/lang/zh-cn.json +0 -97
- package/src/built-in/locales/lang/zh-tw.json +0 -97
- package/src/built-in/locales/ui.ts +0 -3
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { useI18n } from 'vue-i18n';
|
|
3
2
|
import IconamoonSearch from '~icons/iconamoon/search';
|
|
4
3
|
import { useContext } from '../../composables/useContext';
|
|
5
4
|
import { useGlobalSearch } from '../../composables/useGlobalSearch';
|
|
@@ -10,7 +9,6 @@ defineOptions({
|
|
|
10
9
|
|
|
11
10
|
const { settingsStore } = useContext();
|
|
12
11
|
const { toggle: toggleSearch } = useGlobalSearch();
|
|
13
|
-
const { t } = useI18n();
|
|
14
12
|
|
|
15
13
|
const searchComponentsClass = computed(() => {
|
|
16
14
|
const componentsClass = {
|
|
@@ -33,7 +31,7 @@ const searchComponentsClass = computed(() => {
|
|
|
33
31
|
@click="toggleSearch('menu')"
|
|
34
32
|
>
|
|
35
33
|
<IconamoonSearch text="14px" />
|
|
36
|
-
<span class="text-sm transition ">{{
|
|
34
|
+
<span class="text-sm transition ">{{ '搜索' }}</span>
|
|
37
35
|
<HKbd
|
|
38
36
|
v-if="settingsStore.settings.navSearch.enableHotkeys"
|
|
39
37
|
class="ml-2"
|
|
@@ -6,7 +6,7 @@ import { Dialog, DialogDescription, DialogPanel, TransitionChild, TransitionRoot
|
|
|
6
6
|
import hotkeys from 'hotkeys-js';
|
|
7
7
|
import { cloneDeep } from 'lodash-es';
|
|
8
8
|
import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue';
|
|
9
|
-
import {
|
|
9
|
+
import { computed, onBeforeUpdate, onUnmounted, ref, watch } from 'vue';
|
|
10
10
|
import AntDesignCaretDownFilled from '~icons/ant-design/caret-down-filled';
|
|
11
11
|
import AntDesignCaretUpFilled from '~icons/ant-design/caret-up-filled';
|
|
12
12
|
import EpSearch from '~icons/ep/search';
|
|
@@ -25,6 +25,10 @@ defineOptions({
|
|
|
25
25
|
name: 'SearchPanel',
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
const props = withDefaults(defineProps<{ priority?: number }>(), {
|
|
29
|
+
priority: 0,
|
|
30
|
+
});
|
|
31
|
+
|
|
28
32
|
const overlayTransitionClass = ref({
|
|
29
33
|
enter: 'ease-in-out duration-500',
|
|
30
34
|
enterFrom: 'opacity-0',
|
|
@@ -45,22 +49,35 @@ const transitionClass = computed(() => {
|
|
|
45
49
|
};
|
|
46
50
|
});
|
|
47
51
|
|
|
48
|
-
const { t } = useI18n();
|
|
49
|
-
|
|
50
52
|
const router = useRouter();
|
|
51
|
-
const { settingsStore, routeStore, tabbarStore,
|
|
53
|
+
const { settingsStore, routeStore, tabbarStore, generateTitle } = useContext();
|
|
52
54
|
|
|
53
55
|
type searchTypes = 'menu' | 'tab';
|
|
54
56
|
interface listTypes {
|
|
55
57
|
path: string
|
|
56
58
|
icon?: string
|
|
57
59
|
title?: string | (() => string)
|
|
58
|
-
i18n?: string
|
|
59
60
|
link?: string
|
|
60
61
|
breadcrumb: any[]
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
const { isShow, searchType, toggle: globalToggle } = useGlobalSearch();
|
|
64
|
+
const { isShow, searchType, activePanelId, toggle: globalToggle, close: globalClose, registerPanel, unregisterPanel, setPanelPriority } = useGlobalSearch();
|
|
65
|
+
const panelId = Symbol('global-search-panel');
|
|
66
|
+
const hasRegisteredGlobalHotkeys = ref(false);
|
|
67
|
+
registerPanel(panelId, props.priority);
|
|
68
|
+
onUnmounted(() => {
|
|
69
|
+
unregisterPanel(panelId);
|
|
70
|
+
if (hasRegisteredGlobalHotkeys.value) {
|
|
71
|
+
hotkeys.unbind('alt+s', handleOpenHotkey);
|
|
72
|
+
hotkeys.unbind('esc', handleCloseHotkey);
|
|
73
|
+
hasRegisteredGlobalHotkeys.value = false;
|
|
74
|
+
}
|
|
75
|
+
hotkeys.unbind('up', keyUp);
|
|
76
|
+
hotkeys.unbind('down', keyDown);
|
|
77
|
+
hotkeys.unbind('enter', keyEnter);
|
|
78
|
+
});
|
|
79
|
+
watch(() => props.priority, val => setPanelPriority(panelId, val));
|
|
80
|
+
const isActivePanel = computed(() => activePanelId.value === panelId);
|
|
64
81
|
const searchInput = ref('');
|
|
65
82
|
const sourceList = ref<listTypes[]>([]);
|
|
66
83
|
const actived = ref(-1);
|
|
@@ -76,13 +93,13 @@ const resultList = computed(() => {
|
|
|
76
93
|
let result = [];
|
|
77
94
|
result = sourceList.value.filter((item) => {
|
|
78
95
|
let flag = false;
|
|
79
|
-
if (
|
|
96
|
+
if (generateTitle(item.title).toString().includes(searchInput.value)) {
|
|
80
97
|
flag = true;
|
|
81
98
|
}
|
|
82
99
|
if (item.path.includes(searchInput.value)) {
|
|
83
100
|
flag = true;
|
|
84
101
|
}
|
|
85
|
-
if (item.breadcrumb.some((b: {
|
|
102
|
+
if (item.breadcrumb.some((b: { title: any }) => generateTitle(b.title).toString().includes(searchInput.value))) {
|
|
86
103
|
flag = true;
|
|
87
104
|
}
|
|
88
105
|
return flag;
|
|
@@ -90,44 +107,79 @@ const resultList = computed(() => {
|
|
|
90
107
|
return result;
|
|
91
108
|
});
|
|
92
109
|
|
|
93
|
-
watch(
|
|
94
|
-
|
|
95
|
-
|
|
110
|
+
watch(
|
|
111
|
+
[() => isShow.value, () => isActivePanel.value],
|
|
112
|
+
([show, active]) => {
|
|
113
|
+
if (!active) {
|
|
114
|
+
hotkeys.unbind('up', keyUp);
|
|
115
|
+
hotkeys.unbind('down', keyDown);
|
|
116
|
+
hotkeys.unbind('enter', keyEnter);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (show) {
|
|
120
|
+
searchInput.value = '';
|
|
121
|
+
actived.value = -1;
|
|
122
|
+
// 当搜索显示的时候绑定上、下、回车快捷键,隐藏的时候再解绑。另外当 input 处于 focus 状态时,采用 vue 来绑定键盘事件
|
|
123
|
+
hotkeys('up', keyUp);
|
|
124
|
+
hotkeys('down', keyDown);
|
|
125
|
+
hotkeys('enter', keyEnter);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
hotkeys.unbind('up', keyUp);
|
|
129
|
+
hotkeys.unbind('down', keyDown);
|
|
130
|
+
hotkeys.unbind('enter', keyEnter);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{ immediate: true },
|
|
134
|
+
);
|
|
135
|
+
watch(
|
|
136
|
+
() => resultList.value,
|
|
137
|
+
() => {
|
|
138
|
+
if (!isActivePanel.value || !isShow.value) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
96
141
|
actived.value = -1;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
142
|
+
handleScroll();
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
function handleOpenHotkey(e: KeyboardEvent) {
|
|
147
|
+
if (settingsStore.settings.navSearch.enable && settingsStore.settings.navSearch.enableHotkeys) {
|
|
148
|
+
e.preventDefault();
|
|
149
|
+
initSourceList();
|
|
150
|
+
isShow.value = true;
|
|
101
151
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function handleCloseHotkey(e: KeyboardEvent) {
|
|
155
|
+
if (settingsStore.settings.navSearch.enable && settingsStore.settings.navSearch.enableHotkeys) {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
isShow.value = false;
|
|
106
158
|
}
|
|
107
|
-
}
|
|
108
|
-
watch(() => resultList.value, () => {
|
|
109
|
-
actived.value = -1;
|
|
110
|
-
handleScroll();
|
|
111
|
-
});
|
|
159
|
+
}
|
|
112
160
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
161
|
+
watch(
|
|
162
|
+
() => isActivePanel.value,
|
|
163
|
+
(active) => {
|
|
164
|
+
if (active && !hasRegisteredGlobalHotkeys.value) {
|
|
165
|
+
hotkeys('alt+s', handleOpenHotkey);
|
|
166
|
+
hotkeys('esc', handleCloseHotkey);
|
|
167
|
+
hasRegisteredGlobalHotkeys.value = true;
|
|
117
168
|
initSourceList();
|
|
118
|
-
isShow.value = true;
|
|
119
169
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
isShow.value = false;
|
|
170
|
+
else if (!active && hasRegisteredGlobalHotkeys.value) {
|
|
171
|
+
hotkeys.unbind('alt+s', handleOpenHotkey);
|
|
172
|
+
hotkeys.unbind('esc', handleCloseHotkey);
|
|
173
|
+
hasRegisteredGlobalHotkeys.value = false;
|
|
125
174
|
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
175
|
+
},
|
|
176
|
+
{ immediate: true },
|
|
177
|
+
);
|
|
129
178
|
|
|
130
179
|
function switchType(type: any) {
|
|
180
|
+
if (!isActivePanel.value) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
131
183
|
searchInputRef.value.focus();
|
|
132
184
|
initSourceList(type);
|
|
133
185
|
}
|
|
@@ -155,27 +207,24 @@ function hasChildren(item: RouteRecordRaw) {
|
|
|
155
207
|
}
|
|
156
208
|
return flag;
|
|
157
209
|
}
|
|
158
|
-
function getSourceList(arr: RouteRecordRaw[], basePath?: string, icon?: string, breadcrumb?: { title?: string | (() => string)
|
|
210
|
+
function getSourceList(arr: RouteRecordRaw[], basePath?: string, icon?: string, breadcrumb?: { title?: string | (() => string) }[]) {
|
|
159
211
|
arr.forEach((item) => {
|
|
160
212
|
if (item.meta?.sidebar !== false) {
|
|
161
213
|
const breadcrumbTemp = cloneDeep(breadcrumb) || [];
|
|
162
214
|
if (item.children && hasChildren(item)) {
|
|
163
215
|
breadcrumbTemp.push({
|
|
164
216
|
title: item.meta?.title,
|
|
165
|
-
i18n: item.meta?.i18n,
|
|
166
217
|
});
|
|
167
218
|
getSourceList(item.children, resolveRoutePath(basePath, item.path), item.meta?.icon ?? icon, breadcrumbTemp);
|
|
168
219
|
}
|
|
169
220
|
else {
|
|
170
221
|
breadcrumbTemp.push({
|
|
171
222
|
title: item.meta?.title,
|
|
172
|
-
i18n: item.meta?.i18n,
|
|
173
223
|
});
|
|
174
224
|
sourceList.value.push({
|
|
175
225
|
path: resolveRoutePath(basePath, item.path),
|
|
176
226
|
icon: item.meta?.icon ?? icon,
|
|
177
227
|
title: item.meta?.title,
|
|
178
|
-
i18n: item.meta?.i18n,
|
|
179
228
|
link: item.meta?.link,
|
|
180
229
|
breadcrumb: breadcrumbTemp,
|
|
181
230
|
});
|
|
@@ -190,13 +239,15 @@ function getSourceListByTabs(arr: Tabbar.recordRaw[]) {
|
|
|
190
239
|
icon: item.icon,
|
|
191
240
|
title: item.title,
|
|
192
241
|
path: item.fullPath,
|
|
193
|
-
i18n: item.i18n,
|
|
194
242
|
breadcrumb: [],
|
|
195
243
|
});
|
|
196
244
|
});
|
|
197
245
|
}
|
|
198
246
|
|
|
199
247
|
function keyUp() {
|
|
248
|
+
if (!isActivePanel.value) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
200
251
|
if (resultList.value.length) {
|
|
201
252
|
actived.value -= 1;
|
|
202
253
|
if (actived.value < 0) {
|
|
@@ -206,6 +257,9 @@ function keyUp() {
|
|
|
206
257
|
}
|
|
207
258
|
}
|
|
208
259
|
function keyDown() {
|
|
260
|
+
if (!isActivePanel.value) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
209
263
|
if (resultList.value.length) {
|
|
210
264
|
actived.value += 1;
|
|
211
265
|
if (actived.value > resultList.value.length - 1) {
|
|
@@ -215,11 +269,17 @@ function keyDown() {
|
|
|
215
269
|
}
|
|
216
270
|
}
|
|
217
271
|
function keyEnter() {
|
|
272
|
+
if (!isActivePanel.value) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
218
275
|
if (actived.value !== -1) {
|
|
219
276
|
searchResultItemRef.value.find(item => Number.parseInt(item.dataset.index!) === actived.value)?.click();
|
|
220
277
|
}
|
|
221
278
|
}
|
|
222
279
|
function handleScroll() {
|
|
280
|
+
if (!isActivePanel.value) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
223
283
|
if (searchResultRef.value) {
|
|
224
284
|
const contentDom = searchResultRef.value.osInstance()!.elements().content;
|
|
225
285
|
let scrollTo = 0;
|
|
@@ -249,7 +309,9 @@ function pageJump(path: listTypes['path'], link: listTypes['link']) {
|
|
|
249
309
|
else {
|
|
250
310
|
router.push(path);
|
|
251
311
|
}
|
|
252
|
-
|
|
312
|
+
if (isActivePanel.value) {
|
|
313
|
+
globalClose();
|
|
314
|
+
}
|
|
253
315
|
}
|
|
254
316
|
|
|
255
317
|
function toggle(type?: 'menu' | 'tab') {
|
|
@@ -260,11 +322,17 @@ function toggle(type?: 'menu' | 'tab') {
|
|
|
260
322
|
}
|
|
261
323
|
|
|
262
324
|
// 初始化本地 searchTypeLocal 与全局 searchType 同步
|
|
263
|
-
watch(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
325
|
+
watch(
|
|
326
|
+
() => searchType.value,
|
|
327
|
+
(val) => {
|
|
328
|
+
if (!isActivePanel.value) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (val) {
|
|
332
|
+
initSourceList(val as searchTypes);
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
);
|
|
268
336
|
|
|
269
337
|
defineExpose({
|
|
270
338
|
toggle,
|
|
@@ -272,7 +340,7 @@ defineExpose({
|
|
|
272
340
|
</script>
|
|
273
341
|
|
|
274
342
|
<template>
|
|
275
|
-
<TransitionRoot as="template" :show="isShow">
|
|
343
|
+
<TransitionRoot v-if="isActivePanel" as="template" :show="isShow">
|
|
276
344
|
<Dialog :initial-focus="searchInputRef" class="fixed inset-0 z-2000 flex" @close="isShow && toggle()">
|
|
277
345
|
<TransitionChild as="template" v-bind="overlayTransitionClass">
|
|
278
346
|
<div class="fixed inset-0 bg-stone-200/75 backdrop-blur-sm transition-opacity dark:bg-stone-8/75" />
|
|
@@ -285,8 +353,8 @@ defineExpose({
|
|
|
285
353
|
v-if="settingsStore.settings.tabbar.enable"
|
|
286
354
|
v-model="searchType"
|
|
287
355
|
:options="[
|
|
288
|
-
{ label:
|
|
289
|
-
{ label:
|
|
356
|
+
{ label: '搜索导航菜单', value: 'menu' },
|
|
357
|
+
{ label: '搜索标签页', value: 'tab' },
|
|
290
358
|
]"
|
|
291
359
|
class="mb-4 flex!"
|
|
292
360
|
@click.stop
|
|
@@ -298,7 +366,7 @@ defineExpose({
|
|
|
298
366
|
<input
|
|
299
367
|
ref="searchInputRef"
|
|
300
368
|
v-model="searchInput"
|
|
301
|
-
|
|
369
|
+
placeholder="搜索页面,支持标题、URL模糊查询"
|
|
302
370
|
class="w-full border-0 rounded-md bg-transparent px-3 text-base text-dark dark:text-white focus:outline-none placeholder-stone-4 dark:placeholder-stone-5"
|
|
303
371
|
@keydown.esc="toggle()"
|
|
304
372
|
@keydown.up.prevent="keyUp"
|
|
@@ -332,10 +400,10 @@ defineExpose({
|
|
|
332
400
|
:class="{ 'scale-120 text-ui-primary': index === actived }"
|
|
333
401
|
/>
|
|
334
402
|
<div class="flex flex-1 flex-col gap-1 truncate px-4 py-3" border-l="~ solid stone-2 dark:stone-7">
|
|
335
|
-
<div class="truncate text-base font-bold">{{
|
|
403
|
+
<div class="truncate text-base font-bold">{{ generateTitle(item.title) }}</div>
|
|
336
404
|
<Breadcrumb v-if="item.breadcrumb.length" class="truncate">
|
|
337
405
|
<BreadcrumbItem v-for="(bc, bcIndex) in item.breadcrumb" :key="bcIndex" class="text-xs">
|
|
338
|
-
{{
|
|
406
|
+
{{ generateTitle(bc.title) }}
|
|
339
407
|
</BreadcrumbItem>
|
|
340
408
|
</Breadcrumb>
|
|
341
409
|
</div>
|
|
@@ -357,7 +425,7 @@ defineExpose({
|
|
|
357
425
|
<HKbd>
|
|
358
426
|
<IonMdReturnLeft text="14px" />
|
|
359
427
|
</HKbd>
|
|
360
|
-
<span>{{
|
|
428
|
+
<span>{{ '访问' }}</span>
|
|
361
429
|
</div>
|
|
362
430
|
<div class="inline-flex items-center gap-1 text-xs">
|
|
363
431
|
<HKbd>
|
|
@@ -366,14 +434,14 @@ defineExpose({
|
|
|
366
434
|
<HKbd>
|
|
367
435
|
<AntDesignCaretDownFilled text="14px" />
|
|
368
436
|
</HKbd>
|
|
369
|
-
<span>{{
|
|
437
|
+
<span>{{ '切换' }}</span>
|
|
370
438
|
</div>
|
|
371
439
|
</div>
|
|
372
440
|
<div v-if="settingsStore.settings.navSearch.enableHotkeys" class="inline-flex items-center gap-1 text-xs">
|
|
373
441
|
<HKbd>
|
|
374
442
|
ESC
|
|
375
443
|
</HKbd>
|
|
376
|
-
<span>{{
|
|
444
|
+
<span>{{ '退出' }}</span>
|
|
377
445
|
</div>
|
|
378
446
|
</div>
|
|
379
447
|
</div>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { DropdownMenuRender } from './interface';
|
|
3
|
-
import { useI18n } from 'vue-i18n';
|
|
4
3
|
import CarbonUserAvatarFilledAlt from '~icons/carbon/user-avatar-filled-alt';
|
|
5
4
|
import MaterialSymbolsExpandMoreRounded from '~icons/material-symbols/expand-more-rounded';
|
|
6
5
|
|
|
@@ -31,9 +30,7 @@ const props = withDefaults(
|
|
|
31
30
|
);
|
|
32
31
|
|
|
33
32
|
const router = useRouter();
|
|
34
|
-
const { settingsStore, userStore,
|
|
35
|
-
|
|
36
|
-
const { t } = useI18n();
|
|
33
|
+
const { settingsStore, userStore, generateTitle } = useContext();
|
|
37
34
|
|
|
38
35
|
const hotkeysIntroRef = ref();
|
|
39
36
|
const preferencesRef = ref();
|
|
@@ -42,28 +39,28 @@ const userMenu = computed(() => {
|
|
|
42
39
|
return {
|
|
43
40
|
Home: {
|
|
44
41
|
key: 'home',
|
|
45
|
-
label:
|
|
42
|
+
label: generateTitle(settingsStore.settings.home.title),
|
|
46
43
|
icon: 'i-ant-design:home-twotone',
|
|
47
44
|
onClick: () => router.push({ name: 'Home' }),
|
|
48
45
|
hide: !settingsStore.settings.home.enable,
|
|
49
46
|
},
|
|
50
47
|
Preferences: {
|
|
51
48
|
key: 'preferences',
|
|
52
|
-
label:
|
|
49
|
+
label: '个人偏好设置',
|
|
53
50
|
icon: 'i-iconamoon-star-duotone',
|
|
54
51
|
onClick: () => preferencesRef.value?.open?.(),
|
|
55
52
|
hide: !settingsStore.settings.app.enableUserPreferences,
|
|
56
53
|
},
|
|
57
54
|
Hotkeys: {
|
|
58
55
|
key: 'hotkeys',
|
|
59
|
-
label:
|
|
56
|
+
label: '快捷键介绍',
|
|
60
57
|
icon: 'i-iconamoon-lightning-2-duotone',
|
|
61
58
|
onClick: () => hotkeysIntroRef.value?.open?.(),
|
|
62
59
|
hide: settingsStore.mode !== 'pc',
|
|
63
60
|
},
|
|
64
61
|
Org: {
|
|
65
62
|
key: 'org',
|
|
66
|
-
label:
|
|
63
|
+
label: '切换组织',
|
|
67
64
|
icon: 'i-iconamoon-synchronize-duotone',
|
|
68
65
|
onClick: () => router.push({
|
|
69
66
|
name: 'ChangeOrganization',
|
|
@@ -73,13 +70,13 @@ const userMenu = computed(() => {
|
|
|
73
70
|
},
|
|
74
71
|
Profile: {
|
|
75
72
|
key: 'profile',
|
|
76
|
-
label:
|
|
73
|
+
label: '个人中心',
|
|
77
74
|
icon: 'i-iconamoon-profile-duotone',
|
|
78
75
|
onClick: () => router.push({ name: 'Profile' }),
|
|
79
76
|
},
|
|
80
77
|
Password: {
|
|
81
78
|
key: 'password',
|
|
82
|
-
label:
|
|
79
|
+
label: '修改密码',
|
|
83
80
|
icon: 'i-iconamoon-lock-duotone',
|
|
84
81
|
onClick: () => router.push({
|
|
85
82
|
name: 'ChangePassword',
|
|
@@ -90,7 +87,7 @@ const userMenu = computed(() => {
|
|
|
90
87
|
},
|
|
91
88
|
Logout: {
|
|
92
89
|
key: 'logout',
|
|
93
|
-
label:
|
|
90
|
+
label: '退出登录',
|
|
94
91
|
icon: 'i-iconamoon-arrow-left-3-square-duotone',
|
|
95
92
|
onClick: () => userStore.logout(),
|
|
96
93
|
},
|
|
@@ -146,7 +143,7 @@ watch(() => userStore.user.avatar, () => {
|
|
|
146
143
|
</div>
|
|
147
144
|
|
|
148
145
|
<HotkeysIntro ref="hotkeysIntroRef" />
|
|
149
|
-
<SearchPanel />
|
|
146
|
+
<SearchPanel :priority="10" />
|
|
150
147
|
<Preferences v-if="settingsStore.settings.app.enableUserPreferences" ref="preferencesRef" />
|
|
151
148
|
</div>
|
|
152
149
|
</template>
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import type { Tabbar } from '#/tabbar';
|
|
3
3
|
import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue';
|
|
4
4
|
import Sortable from 'sortablejs';
|
|
5
|
-
import { useI18n } from 'vue-i18n';
|
|
6
5
|
import EpClose from '~icons/ep/close';
|
|
7
6
|
import EpSearch from '~icons/ep/search';
|
|
8
7
|
import PhArrowLineLeft from '~icons/ph/arrow-line-left';
|
|
@@ -22,12 +21,10 @@ defineOptions({
|
|
|
22
21
|
|
|
23
22
|
const router = useRouter();
|
|
24
23
|
|
|
25
|
-
const { settingsStore, tabbarStore,
|
|
24
|
+
const { settingsStore, tabbarStore, generateTitle, routeStore } = useContext();
|
|
26
25
|
|
|
27
26
|
const tabbar = useTabbar();
|
|
28
27
|
|
|
29
|
-
const { t } = useI18n();
|
|
30
|
-
|
|
31
28
|
const activedTabId = computed(() => tabbar.getId());
|
|
32
29
|
|
|
33
30
|
const dropdownTabContainerRef = ref();
|
|
@@ -88,6 +85,44 @@ function iconName(isActive: boolean, icon: Tabbar.recordRaw['icon'], activeIcon:
|
|
|
88
85
|
}
|
|
89
86
|
return name;
|
|
90
87
|
}
|
|
88
|
+
|
|
89
|
+
// 解析 fullPath 的纯路径部分(去掉 query/hash)
|
|
90
|
+
function stripPath(fullPath: string) {
|
|
91
|
+
return fullPath.split(/[?#]/)[0];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 查找与 tab 对应的路由记录
|
|
95
|
+
function findRouteRecordByElement(element: Tabbar.recordRaw) {
|
|
96
|
+
const pathOnly = stripPath(element.fullPath);
|
|
97
|
+
const all = [...routeStore.flatSystemRoutes, ...routeStore.flatRoutes] as any[];
|
|
98
|
+
return all.find(r => r.path === pathOnly);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 解析该 tab 的 iconOptions(优先当前路由,其次面包屑链路上最近的一个)
|
|
102
|
+
function resolveIconOptions(element: Tabbar.recordRaw): undefined | {
|
|
103
|
+
boxType?: 'square' | 'prism' | 'null'
|
|
104
|
+
angle?: number | string
|
|
105
|
+
background?: any
|
|
106
|
+
radius?: number | string
|
|
107
|
+
iconColor?: string
|
|
108
|
+
} {
|
|
109
|
+
const r: any = findRouteRecordByElement(element);
|
|
110
|
+
let options = (r?.meta as any)?.iconOptions;
|
|
111
|
+
if (!options && r?.meta?.breadcrumbNeste?.length) {
|
|
112
|
+
const found = [...r.meta.breadcrumbNeste].reverse().find((it: any) => it?.iconOptions);
|
|
113
|
+
options = found?.iconOptions;
|
|
114
|
+
}
|
|
115
|
+
return options;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function computeBoxType(options: ReturnType<typeof resolveIconOptions>) {
|
|
119
|
+
const bt = (options as any)?.boxType as any;
|
|
120
|
+
return bt && bt !== 'null' ? bt : 'prism';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function getSafeIconColor(options: ReturnType<typeof resolveIconOptions>): string | undefined {
|
|
124
|
+
return (options as any)?.iconColor || undefined;
|
|
125
|
+
}
|
|
91
126
|
</script>
|
|
92
127
|
|
|
93
128
|
<template>
|
|
@@ -99,22 +134,22 @@ function iconName(isActive: boolean, icon: Tabbar.recordRaw['icon'], activeIcon:
|
|
|
99
134
|
<template #dropdown>
|
|
100
135
|
<div class="quick-button">
|
|
101
136
|
<button v-if="settingsStore.settings.navSearch.enable" class="button" @click="actionCommand('search-tabs')">
|
|
102
|
-
<HTooltip
|
|
137
|
+
<HTooltip text="搜索标签页">
|
|
103
138
|
<EpSearch />
|
|
104
139
|
</HTooltip>
|
|
105
140
|
</button>
|
|
106
141
|
<button class="button" :disabled="!tabbar.checkCloseOtherSide()" @click="actionCommand('other-side')">
|
|
107
|
-
<HTooltip
|
|
142
|
+
<HTooltip text="关闭其它标签页">
|
|
108
143
|
<EpClose />
|
|
109
144
|
</HTooltip>
|
|
110
145
|
</button>
|
|
111
146
|
<button class="button" :disabled="!tabbar.checkCloseLeftSide()" @click="actionCommand('left-side')">
|
|
112
|
-
<HTooltip
|
|
147
|
+
<HTooltip text="关闭左侧标签页">
|
|
113
148
|
<PhArrowLineLeft />
|
|
114
149
|
</HTooltip>
|
|
115
150
|
</button>
|
|
116
151
|
<button class="button" :disabled="!tabbar.checkCloseRightSide()" @click="actionCommand('right-side')">
|
|
117
|
-
<HTooltip
|
|
152
|
+
<HTooltip text="关闭右侧标签页">
|
|
118
153
|
<PhArrowLineRight />
|
|
119
154
|
</HTooltip>
|
|
120
155
|
</button>
|
|
@@ -127,9 +162,27 @@ function iconName(isActive: boolean, icon: Tabbar.recordRaw['icon'], activeIcon:
|
|
|
127
162
|
'no-drag': element.isPermanent || element.isPin,
|
|
128
163
|
}"
|
|
129
164
|
>
|
|
130
|
-
<div :key="element.tabId" class="title" :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title ||
|
|
131
|
-
<
|
|
132
|
-
|
|
165
|
+
<div :key="element.tabId" class="title" :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title)" @click="router.push(element.fullPath)">
|
|
166
|
+
<template v-if="settingsStore.settings.tabbar.enableIcon && iconName(element.tabId === activedTabId, element.icon, element.activeIcon)">
|
|
167
|
+
<PubinfoIcon
|
|
168
|
+
v-if="resolveIconOptions(element)"
|
|
169
|
+
small
|
|
170
|
+
:name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
|
|
171
|
+
:box="computeBoxType(resolveIconOptions(element)) as any"
|
|
172
|
+
:size="16"
|
|
173
|
+
:angle="resolveIconOptions(element)?.angle"
|
|
174
|
+
:background="resolveIconOptions(element)?.background"
|
|
175
|
+
:radius="resolveIconOptions(element)?.radius"
|
|
176
|
+
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? (getSafeIconColor(resolveIconOptions(element)) || '#ffffff') : undefined"
|
|
177
|
+
/>
|
|
178
|
+
<PubinfoIcon
|
|
179
|
+
v-else
|
|
180
|
+
:name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
|
|
181
|
+
:size="16"
|
|
182
|
+
:color="(iconName(element.tabId === activedTabId, element.icon, element.activeIcon) || '').startsWith('antd:') ? getSafeIconColor(resolveIconOptions(element)) : undefined"
|
|
183
|
+
/>
|
|
184
|
+
</template>
|
|
185
|
+
{{ element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title) }}
|
|
133
186
|
</div>
|
|
134
187
|
<div v-if="!element.isPermanent && element.isPin" class="action-icon" @click.stop="tabbarStore.unPin(element.tabId)">
|
|
135
188
|
<RiPushpin2Fill />
|