@pubinfo/core 2.0.0-rc.2 → 2.0.0-rc.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.
Files changed (133) hide show
  1. package/dist/{AppSetting-D2RJrc9O.js → AppSetting-BI-oNc4e.js} +19 -19
  2. package/dist/{HCheckList.vue_vue_type_script_setup_true_lang-DusVz35O.js → HCheckList.vue_vue_type_script_setup_true_lang-BdLpkcoh.js} +1 -1
  3. package/dist/{HToggle-DMcVgMVY.js → HToggle-DxdWLgp-.js} +1 -1
  4. package/dist/{PreferencesContent-Dtd9rtew.js → PreferencesContent-CCYkZeCT.js} +52 -52
  5. package/dist/{SettingBreadcrumb-QSCSviKM.js → SettingBreadcrumb-BTyfiy4k.js} +5 -5
  6. package/dist/{SettingCopyright-Dr5P6yfq.js → SettingCopyright-g6UHi8pZ.js} +2 -2
  7. package/dist/{SettingEnableTransition-DGiHEbCI.js → SettingEnableTransition-Ci-5bhbR.js} +12 -12
  8. package/dist/{SettingHome-CEPcBlds.js → SettingHome-K4Iel0Hr.js} +8 -8
  9. package/dist/{SettingMenu-BJdjnRA6.js → SettingMenu-BYLWzA5i.js} +14 -14
  10. package/dist/{SettingMode-BnuCHoEY.js → SettingMode-tRisyKtg.js} +3 -3
  11. package/dist/{SettingNavSearch-CiU4BmlU.js → SettingNavSearch-CSM6mPf8.js} +6 -6
  12. package/dist/{SettingOther-DTHjVlFe.js → SettingOther-Bj5KF_vC.js} +11 -11
  13. package/dist/{SettingPage-D75_Nf05.js → SettingPage-CFjmrVI7.js} +2 -2
  14. package/dist/{SettingTabbar-D48dzvgA.js → SettingTabbar-uFYiaZhK.js} +13 -13
  15. package/dist/{SettingThemes-D-8vTs5n.js → SettingThemes-C-tMq9o5.js} +12 -12
  16. package/dist/{SettingToolbar-DjIjm9V-.js → SettingToolbar-BfDzijNU.js} +10 -10
  17. package/dist/{SettingTopbar-Cg30OTH3.js → SettingTopbar-DTDv4NXD.js} +6 -6
  18. package/dist/{SettingWidthMode-BKV_7kb8.js → SettingWidthMode-PkiwrHe3.js} +11 -11
  19. package/dist/{TopThinMode-JFYsp_lJ.js → TopThinMode-BrvA8pV0.js} +3 -3
  20. package/dist/built-in/authentication/alova/helper.d.ts +34 -0
  21. package/dist/built-in/authentication/alova/token.d.ts +16 -0
  22. package/dist/built-in/authentication/helper.d.ts +10 -1
  23. package/dist/built-in/index.d.ts +0 -1
  24. package/dist/built-in/layout-component/Layout.vue.d.ts +1 -0
  25. package/dist/built-in/layout-component/components/Tools/Fullscreen.vue.d.ts +2 -0
  26. package/dist/built-in/layout-component/components/Tools/PageReload.vue.d.ts +2 -0
  27. package/dist/built-in/layout-component/components/Tools/SearchBar.vue.d.ts +2 -0
  28. package/dist/built-in/layout-component/components/Tools/index.vue.d.ts +47 -1
  29. package/dist/built-in/layout-component/components/Tools/interface.d.ts +26 -0
  30. package/dist/built-in/layout-component/components/ui/HDropdownMenu.vue.d.ts +2 -7
  31. package/dist/built-in/layout-component/components/ui/HSlideover.vue.d.ts +1 -1
  32. package/dist/built-in/layout-component/composables/useContext.d.ts +1 -1
  33. package/dist/built-in/layout-component/composables/useHotkey.d.ts +1 -5
  34. package/dist/built-in/layout-component/composables/useMainPage.d.ts +1 -1
  35. package/dist/built-in/layout-component/composables/useMenu.d.ts +1 -1
  36. package/dist/built-in/layout-component/composables/useTabbar.d.ts +1 -1
  37. package/dist/built-in/layout-component/composables/useTitle.d.ts +3 -2
  38. package/dist/built-in/layout-component/composables/useWatermark.d.ts +3 -1
  39. package/dist/built-in/layout-component/index.d.ts +9 -6
  40. package/dist/built-in/layout-component/utils/index.d.ts +0 -1
  41. package/dist/{colors-CODcBxrF.js → colors-VoaDbOhe.js} +1 -1
  42. package/dist/core/interface.d.ts +14 -5
  43. package/dist/core/request.d.ts +2 -8
  44. package/dist/features/api/modules/auth/renzhengfuwu.d.ts +8 -8
  45. package/dist/features/api/modules/configData/heibaimingdanfuwu.d.ts +5 -5
  46. package/dist/features/api/modules/configData/xitongpeizhifuwu.d.ts +14 -14
  47. package/dist/features/api/modules/configData/zidifuwu.d.ts +10 -10
  48. package/dist/features/api/modules/rbac/gangweijiekou.d.ts +6 -6
  49. package/dist/features/api/modules/rbac/jiaosejiekou.d.ts +7 -7
  50. package/dist/features/api/modules/rbac/pubJiaosezukongzhiqi.d.ts +7 -7
  51. package/dist/features/api/modules/rbac/shujuquanxianzhubiaokongzhiqi.d.ts +9 -9
  52. package/dist/features/api/modules/rbac/yonghujiekou.d.ts +15 -15
  53. package/dist/features/api/modules/rbac/yonghushoucangbiaojiekou.d.ts +5 -5
  54. package/dist/features/api/modules/rbac/yonghuzuijinchangyongbiaojiekou.d.ts +4 -4
  55. package/dist/features/api/modules/rbac/ziyuanjiekou.d.ts +13 -13
  56. package/dist/features/api/modules/rbac/zuhuguanlijiekou.d.ts +5 -5
  57. package/dist/features/api/modules/rbac/zuzhijiaosebiaokongzhiqi.d.ts +4 -4
  58. package/dist/features/api/modules/rbac/zuzhijiekou.d.ts +9 -9
  59. package/dist/features/api/system/user.d.ts +4 -4
  60. package/dist/{index-RT-QBzm0.js → index-BSevJVD5.js} +10 -15
  61. package/dist/{index-BVLkBCRY.js → index-BfGqLWFB.js} +6418 -6439
  62. package/dist/{index-DQn1WFMa.js → index-CYoFRwvw.js} +2 -2
  63. package/dist/{index-DmcblkoZ.js → index-ConeY38N.js} +13 -13
  64. package/dist/{index-BAoB7aoj.js → index-DV3hkzKA.js} +1 -1
  65. package/dist/{index-D4_xmL_A.js → index-Ddw98rJ5.js} +25 -25
  66. package/dist/{index-DvJr0paY.js → index-DrC787X_.js} +2 -2
  67. package/dist/{index-BROqFYXS.js → index-Dv9ndBoi.js} +1 -1
  68. package/dist/{index-Jd3PYkpj.js → index-IAYhIBQH.js} +16815 -16694
  69. package/dist/index.d.ts +4 -2
  70. package/dist/index.js +53 -55
  71. package/dist/{pick-BLJM77QN.js → pick-vpv9EEvu.js} +1 -1
  72. package/dist/style.css +1 -1
  73. package/package.json +11 -11
  74. package/src/built-in/authentication/alova/helper.ts +158 -0
  75. package/src/built-in/authentication/alova/token.ts +122 -0
  76. package/src/built-in/authentication/helper.ts +7 -3
  77. package/src/built-in/authentication/index.ts +6 -20
  78. package/src/built-in/index.ts +0 -1
  79. package/src/built-in/layout-component/Layout.vue +11 -22
  80. package/src/built-in/layout-component/components/Header/TopMode/index.vue +4 -4
  81. package/src/built-in/layout-component/components/Menu/item.vue +3 -3
  82. package/src/built-in/layout-component/components/Sidebar/MainSidebar.vue +4 -4
  83. package/src/built-in/layout-component/components/Sidebar/index.vue +1 -1
  84. package/src/built-in/layout-component/components/Tools/DarkModeToggle.vue +108 -0
  85. package/src/built-in/layout-component/components/Tools/Fullscreen.vue +24 -0
  86. package/src/built-in/layout-component/components/Tools/PageReload.vue +22 -0
  87. package/src/built-in/layout-component/components/Tools/SearchBar.vue +42 -0
  88. package/src/built-in/layout-component/components/Tools/{Search.vue → SearchPanel.vue} +13 -21
  89. package/src/built-in/layout-component/components/Tools/index.vue +71 -142
  90. package/src/built-in/layout-component/components/Tools/interface.ts +27 -0
  91. package/src/built-in/layout-component/components/Topbar/Tabbar/MoreAction.vue +9 -12
  92. package/src/built-in/layout-component/components/Topbar/Tabbar/index.vue +12 -15
  93. package/src/built-in/layout-component/components/Topbar/Toolbar/Favorites.vue +4 -7
  94. package/src/built-in/layout-component/components/Topbar/Toolbar/index.vue +6 -6
  95. package/src/built-in/layout-component/components/ui/HDropdownMenu.vue +19 -26
  96. package/src/built-in/layout-component/composables/useContext.ts +1 -1
  97. package/src/built-in/layout-component/composables/useGetComputedStyle.ts +2 -3
  98. package/src/built-in/layout-component/composables/useHotkey.ts +6 -10
  99. package/src/built-in/layout-component/composables/useMainPage.ts +5 -6
  100. package/src/built-in/layout-component/composables/useMenu.ts +3 -5
  101. package/src/built-in/layout-component/composables/useTabbar.ts +3 -5
  102. package/src/built-in/layout-component/composables/useTitle.ts +10 -17
  103. package/src/built-in/layout-component/composables/useWatermark.ts +25 -12
  104. package/src/built-in/layout-component/index.ts +21 -12
  105. package/src/built-in/layout-component/provider.ts +7 -3
  106. package/src/built-in/layout-component/utils/index.ts +0 -1
  107. package/src/built-in/settings/router.ts +5 -1
  108. package/src/core/interface.ts +18 -5
  109. package/src/core/request.ts +35 -15
  110. package/src/features/router/systemRoutes.ts +0 -1
  111. package/src/features/stores/modules/favorites.ts +0 -1
  112. package/src/features/stores/modules/route.ts +2 -9
  113. package/src/features/stores/modules/tabbar.ts +0 -3
  114. package/src/features/stores/utils/routerHelper.ts +38 -4
  115. package/src/index.ts +7 -11
  116. package/types/vue-router.d.ts +0 -3
  117. package/dist/built-in/layout-component/utils/eventBus.d.ts +0 -5
  118. package/dist/built-in/locales/helpler.d.ts +0 -594
  119. package/dist/built-in/locales/index.d.ts +0 -5
  120. package/dist/built-in/locales/lang/en.json.d.ts +0 -99
  121. package/dist/built-in/locales/lang/zh-cn.json.d.ts +0 -100
  122. package/dist/built-in/locales/lang/zh-tw.json.d.ts +0 -100
  123. package/dist/built-in/locales/ui.d.ts +0 -3
  124. package/src/built-in/layout-component/components/Tools/DayNightSwitch.vue +0 -70
  125. package/src/built-in/layout-component/utils/eventBus.ts +0 -8
  126. package/src/built-in/locales/helpler.ts +0 -76
  127. package/src/built-in/locales/index.ts +0 -20
  128. package/src/built-in/locales/lang/en.json +0 -96
  129. package/src/built-in/locales/lang/zh-cn.json +0 -97
  130. package/src/built-in/locales/lang/zh-tw.json +0 -97
  131. package/src/built-in/locales/ui.ts +0 -3
  132. /package/dist/built-in/layout-component/components/Tools/{DayNightSwitch.vue.d.ts → DarkModeToggle.vue.d.ts} +0 -0
  133. /package/dist/built-in/layout-component/components/Tools/{Search.vue.d.ts → SearchPanel.vue.d.ts} +0 -0
@@ -0,0 +1,108 @@
1
+ <script setup lang="ts">
2
+ import { useContext } from '../../composables/useContext';
3
+ import useViewTransition from '../../composables/useViewTransition';
4
+
5
+ defineOptions({
6
+ name: 'DarkModeToggle',
7
+ });
8
+
9
+ const { settingsStore } = useContext();
10
+
11
+ function toggleColorScheme(event: MouseEvent) {
12
+ const { startViewTransition } = useViewTransition(async () => {
13
+ const colorScheme = settingsStore.settings.app.colorScheme === 'dark' ? 'light' : 'dark';
14
+ settingsStore.setColorScheme(colorScheme);
15
+ await settingsStore.setPreferencesSetting({
16
+ app: {
17
+ colorScheme,
18
+ },
19
+ });
20
+ });
21
+
22
+ nextTick(() => {
23
+ startViewTransition()?.ready.then(() => {
24
+ const x = event.clientX;
25
+ const y = event.clientY;
26
+ const endRadius = Math.hypot(
27
+ Math.max(x, innerWidth - x),
28
+ Math.max(y, innerHeight - y),
29
+ );
30
+ const clipPath = [
31
+ `circle(0px at ${x}px ${y}px)`,
32
+ `circle(${endRadius}px at ${x}px ${y}px)`,
33
+ ];
34
+ document.documentElement.animate(
35
+ {
36
+ clipPath: settingsStore.settings.app.colorScheme !== 'dark' ? clipPath : clipPath.reverse(),
37
+ },
38
+ {
39
+ duration: 300,
40
+ easing: 'ease-out',
41
+ pseudoElement: settingsStore.settings.app.colorScheme !== 'dark' ? '::view-transition-new(root)' : '::view-transition-old(root)',
42
+ },
43
+ );
44
+ });
45
+ });
46
+ }
47
+ </script>
48
+
49
+ <template>
50
+ <div
51
+ v-if="settingsStore.settings.toolbar.enableColorScheme"
52
+ class="inline-flex items-center justify-center cursor-pointer"
53
+ @click="toggleColorScheme"
54
+ >
55
+ <div
56
+ class="animate-icon"
57
+ :class="{
58
+ 'animate-icon-day': settingsStore.settings.app.colorScheme !== 'dark',
59
+ }"
60
+ />
61
+ </div>
62
+ </template>
63
+
64
+ <style scoped>
65
+ .animate-icon {
66
+ --at-apply: relative size-[20px] rounded-1/2 inline-block align-middle;
67
+ box-shadow: inset 6px -6px 0 0 #fff; /* 比例缩小 */
68
+ transition: box-shadow 0.5s ease 0s, transform 0.4s ease 0.1s;
69
+ transform: scale(1) rotate(-2deg);
70
+ }
71
+
72
+ .animate-icon::before {
73
+ --at-apply: absolute size-[20px] content-empty rounded-[inherit] left-0 top-0 block;
74
+ transition: background 0.3s ease;
75
+ }
76
+
77
+ .animate-icon::after {
78
+ --at-apply: absolute top-1/2 left-1/2 size-1 -ml-0.5 -mt-0.5 rounded-[50%] content-empty block;
79
+ box-shadow:
80
+ 0 -12px 0 #ffce6e,
81
+ 0 12px 0 #ffce6e,
82
+ 12px 0 0 #ffce6e,
83
+ -12px 0 0 #ffce6e,
84
+ 8px 8px 0 #ffce6e,
85
+ -8px 8px 0 #ffce6e,
86
+ 8px -8px 0 #ffce6e,
87
+ -8px -8px 0 #ffce6e;
88
+ transition: all 0.3s ease;
89
+ transform: scale(0);
90
+ }
91
+
92
+ .animate-icon-day {
93
+ --at-apply: size-5;
94
+ box-shadow: inset 10px -10px 0 0 #fff; /* 缩小后的太阳核心 */
95
+ transition: transform 0.3s ease 0.1s, box-shadow 0.2s ease 0s;
96
+ transform: scale(0.5) rotate(0deg);
97
+ }
98
+
99
+ .animate-icon-day::before {
100
+ background: #ffce6e;
101
+ transition: background 0.3s ease 0.1s;
102
+ }
103
+
104
+ .animate-icon-day::after {
105
+ transition: transform 0.5s ease 0.15s;
106
+ transform: scale(1.2);
107
+ }
108
+ </style>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ import { useFullscreen } from '@vueuse/core';
3
+ import FluentFullScreenMaximize16Filled from '~icons/fluent/full-screen-maximize-16-filled';
4
+ import FluentFullScreenMinimize16Filled from '~icons/fluent/full-screen-minimize-16-filled';
5
+ import { useContext } from '../../composables/useContext';
6
+
7
+ defineOptions({
8
+ name: 'Fullscreen',
9
+ });
10
+
11
+ const { isFullscreen, toggle } = useFullscreen();
12
+ const { settingsStore } = useContext();
13
+ </script>
14
+
15
+ <template>
16
+ <div
17
+ v-if="settingsStore.mode === 'pc' && settingsStore.settings.toolbar.enableFullscreen"
18
+ class="size-5 cursor-pointer"
19
+ @click="toggle"
20
+ >
21
+ <FluentFullScreenMinimize16Filled v-if="isFullscreen" text="16px" />
22
+ <FluentFullScreenMaximize16Filled v-else text="16px" />
23
+ </div>
24
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import FluentArrowSync16Filled from '~icons/fluent/arrow-sync-16-filled';
3
+ import { useContext } from '../../composables/useContext';
4
+ import { useMainPage } from '../../composables/useMainPage';
5
+
6
+ defineOptions({
7
+ name: 'PageReload',
8
+ });
9
+
10
+ const { settingsStore } = useContext();
11
+ const mainPage = useMainPage();
12
+ </script>
13
+
14
+ <template>
15
+ <div
16
+ v-if="settingsStore.settings.toolbar.enablePageReload"
17
+ class="size-5 cursor-pointer"
18
+ @click="mainPage.reload()"
19
+ >
20
+ <FluentArrowSync16Filled text="16px" />
21
+ </div>
22
+ </template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ import IconamoonSearch from '~icons/iconamoon/search';
3
+ import { useContext } from '../../composables/useContext';
4
+ import { useGlobalSearch } from '../../composables/useGlobalSearch';
5
+
6
+ defineOptions({
7
+ name: 'SearchBar',
8
+ });
9
+
10
+ const { settingsStore } = useContext();
11
+ const { toggle: toggleSearch } = useGlobalSearch();
12
+
13
+ const searchComponentsClass = computed(() => {
14
+ const componentsClass = {
15
+ 'side': 'ring-1 ',
16
+ 'head': 'bg-[var(--g-header-menu-active-bg)]',
17
+ 'single': ' ring-1',
18
+ 'only-side': 'ring-1',
19
+ 'only-head': ' bg-[var(--g-header-menu-active-bg)]',
20
+ };
21
+ const menuMode = settingsStore.settings.menu.menuMode;
22
+ return componentsClass[menuMode];
23
+ });
24
+ </script>
25
+
26
+ <template>
27
+ <span
28
+ v-if="settingsStore.settings.navSearch.enable"
29
+ class="group inline-flex cursor-pointer items-center gap-1 rounded-2 px-2 py-1.5 hover:ring-1 ring-inset transition ring-stone-3 dark:ring-stone-7"
30
+ :class="searchComponentsClass"
31
+ @click="toggleSearch('menu')"
32
+ >
33
+ <IconamoonSearch text="14px" />
34
+ <span class="text-sm transition ">{{ '搜索' }}</span>
35
+ <HKbd
36
+ v-if="settingsStore.settings.navSearch.enableHotkeys"
37
+ class="ml-2"
38
+ >
39
+ {{ settingsStore.os === 'mac' ? '⌥' : 'Alt' }} S
40
+ </HKbd>
41
+ </span>
42
+ </template>
@@ -6,7 +6,6 @@ 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 { useI18n } from 'vue-i18n';
10
9
  import AntDesignCaretDownFilled from '~icons/ant-design/caret-down-filled';
11
10
  import AntDesignCaretUpFilled from '~icons/ant-design/caret-up-filled';
12
11
  import EpSearch from '~icons/ep/search';
@@ -22,7 +21,7 @@ import Breadcrumb from './Breadcrumb/index.vue';
22
21
  import BreadcrumbItem from './Breadcrumb/item.vue';
23
22
 
24
23
  defineOptions({
25
- name: 'ToolsSearch',
24
+ name: 'SearchPanel',
26
25
  });
27
26
 
28
27
  const overlayTransitionClass = ref({
@@ -45,17 +44,14 @@ const transitionClass = computed(() => {
45
44
  };
46
45
  });
47
46
 
48
- const { t } = useI18n();
49
-
50
47
  const router = useRouter();
51
- const { settingsStore, routeStore, tabbarStore, generateI18nTitle } = useContext();
48
+ const { settingsStore, routeStore, tabbarStore, generateTitle } = useContext();
52
49
 
53
50
  type searchTypes = 'menu' | 'tab';
54
51
  interface listTypes {
55
52
  path: string
56
53
  icon?: string
57
54
  title?: string | (() => string)
58
- i18n?: string
59
55
  link?: string
60
56
  breadcrumb: any[]
61
57
  }
@@ -76,13 +72,13 @@ const resultList = computed(() => {
76
72
  let result = [];
77
73
  result = sourceList.value.filter((item) => {
78
74
  let flag = false;
79
- if (generateI18nTitle(item.i18n, item.title).toString().includes(searchInput.value)) {
75
+ if (generateTitle(item.title).toString().includes(searchInput.value)) {
80
76
  flag = true;
81
77
  }
82
78
  if (item.path.includes(searchInput.value)) {
83
79
  flag = true;
84
80
  }
85
- if (item.breadcrumb.some((b: { i18n: any, title: any }) => generateI18nTitle(b.i18n, b.title).toString().includes(searchInput.value))) {
81
+ if (item.breadcrumb.some((b: { title: any }) => generateTitle(b.title).toString().includes(searchInput.value))) {
86
82
  flag = true;
87
83
  }
88
84
  return flag;
@@ -155,27 +151,24 @@ function hasChildren(item: RouteRecordRaw) {
155
151
  }
156
152
  return flag;
157
153
  }
158
- function getSourceList(arr: RouteRecordRaw[], basePath?: string, icon?: string, breadcrumb?: { title?: string | (() => string), i18n?: string }[]) {
154
+ function getSourceList(arr: RouteRecordRaw[], basePath?: string, icon?: string, breadcrumb?: { title?: string | (() => string) }[]) {
159
155
  arr.forEach((item) => {
160
156
  if (item.meta?.sidebar !== false) {
161
157
  const breadcrumbTemp = cloneDeep(breadcrumb) || [];
162
158
  if (item.children && hasChildren(item)) {
163
159
  breadcrumbTemp.push({
164
160
  title: item.meta?.title,
165
- i18n: item.meta?.i18n,
166
161
  });
167
162
  getSourceList(item.children, resolveRoutePath(basePath, item.path), item.meta?.icon ?? icon, breadcrumbTemp);
168
163
  }
169
164
  else {
170
165
  breadcrumbTemp.push({
171
166
  title: item.meta?.title,
172
- i18n: item.meta?.i18n,
173
167
  });
174
168
  sourceList.value.push({
175
169
  path: resolveRoutePath(basePath, item.path),
176
170
  icon: item.meta?.icon ?? icon,
177
171
  title: item.meta?.title,
178
- i18n: item.meta?.i18n,
179
172
  link: item.meta?.link,
180
173
  breadcrumb: breadcrumbTemp,
181
174
  });
@@ -190,7 +183,6 @@ function getSourceListByTabs(arr: Tabbar.recordRaw[]) {
190
183
  icon: item.icon,
191
184
  title: item.title,
192
185
  path: item.fullPath,
193
- i18n: item.i18n,
194
186
  breadcrumb: [],
195
187
  });
196
188
  });
@@ -285,8 +277,8 @@ defineExpose({
285
277
  v-if="settingsStore.settings.tabbar.enable"
286
278
  v-model="searchType"
287
279
  :options="[
288
- { label: t('app.search.type.menu'), value: 'menu' },
289
- { label: t('app.search.type.tab'), value: 'tab' },
280
+ { label: '搜索导航菜单', value: 'menu' },
281
+ { label: '搜索标签页', value: 'tab' },
290
282
  ]"
291
283
  class="mb-4 flex!"
292
284
  @click.stop
@@ -298,7 +290,7 @@ defineExpose({
298
290
  <input
299
291
  ref="searchInputRef"
300
292
  v-model="searchInput"
301
- :placeholder="t('app.search.input')"
293
+ placeholder="搜索页面,支持标题、URL模糊查询"
302
294
  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
295
  @keydown.esc="toggle()"
304
296
  @keydown.up.prevent="keyUp"
@@ -332,10 +324,10 @@ defineExpose({
332
324
  :class="{ 'scale-120 text-ui-primary': index === actived }"
333
325
  />
334
326
  <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">{{ generateI18nTitle(item.i18n, item.title) }}</div>
327
+ <div class="truncate text-base font-bold">{{ generateTitle(item.title) }}</div>
336
328
  <Breadcrumb v-if="item.breadcrumb.length" class="truncate">
337
329
  <BreadcrumbItem v-for="(bc, bcIndex) in item.breadcrumb" :key="bcIndex" class="text-xs">
338
- {{ generateI18nTitle(bc.i18n, bc.title) }}
330
+ {{ generateTitle(bc.title) }}
339
331
  </BreadcrumbItem>
340
332
  </Breadcrumb>
341
333
  </div>
@@ -357,7 +349,7 @@ defineExpose({
357
349
  <HKbd>
358
350
  <IonMdReturnLeft text="14px" />
359
351
  </HKbd>
360
- <span>{{ t('app.search.enter') }}</span>
352
+ <span>{{ '访问' }}</span>
361
353
  </div>
362
354
  <div class="inline-flex items-center gap-1 text-xs">
363
355
  <HKbd>
@@ -366,14 +358,14 @@ defineExpose({
366
358
  <HKbd>
367
359
  <AntDesignCaretDownFilled text="14px" />
368
360
  </HKbd>
369
- <span>{{ t('app.search.up_down') }}</span>
361
+ <span>{{ '切换' }}</span>
370
362
  </div>
371
363
  </div>
372
364
  <div v-if="settingsStore.settings.navSearch.enableHotkeys" class="inline-flex items-center gap-1 text-xs">
373
365
  <HKbd>
374
366
  ESC
375
367
  </HKbd>
376
- <span>{{ t('app.search.esc') }}</span>
368
+ <span>{{ '退出' }}</span>
377
369
  </div>
378
370
  </div>
379
371
  </div>
@@ -1,130 +1,105 @@
1
1
  <script setup lang="ts">
2
- import { useFullscreen } from '@vueuse/core';
3
- import { useI18n } from 'vue-i18n';
2
+ import type { DropdownMenuRender } from './interface';
4
3
  import CarbonUserAvatarFilledAlt from '~icons/carbon/user-avatar-filled-alt';
5
- import FluentArrowSync16Filled from '~icons/fluent/arrow-sync-16-filled';
6
- import FluentFullScreenMaximize16Filled from '~icons/fluent/full-screen-maximize-16-filled';
7
- import FluentFullScreenMinimize16Filled from '~icons/fluent/full-screen-minimize-16-filled';
8
- import IconamoonSearch from '~icons/iconamoon/search';
9
4
  import MaterialSymbolsExpandMoreRounded from '~icons/material-symbols/expand-more-rounded';
10
- import PhLineVerticalThin from '~icons/ph/line-vertical-thin';
11
5
 
6
+ import PhLineVerticalThin from '~icons/ph/line-vertical-thin';
12
7
  import { useContext } from '../../composables/useContext';
13
- import { useGlobalSearch } from '../../composables/useGlobalSearch';
14
- import useMainPage from '../../composables/useMainPage';
15
- import useViewTransition from '../../composables/useViewTransition';
16
- import DayNightSwitch from './DayNightSwitch.vue';
8
+ import DarkModeToggle from './DarkModeToggle.vue';
9
+ import Fullscreen from './Fullscreen.vue';
17
10
  import HotkeysIntro from './HotkeysIntro.vue';
11
+ import PageReload from './PageReload.vue';
18
12
  import Preferences from './Preferences/index.vue';
19
- import Search from './Search.vue';
13
+ import SearchBar from './SearchBar.vue';
14
+ import SearchPanel from './SearchPanel.vue';
20
15
 
21
16
  defineOptions({
22
17
  name: 'Tools',
23
18
  });
24
19
 
25
- const router = useRouter();
26
- const { settingsStore, userStore, generateI18nTitle } = useContext();
27
-
28
- const { t } = useI18n();
29
-
30
- const mainPage = useMainPage();
31
- const { isFullscreen, toggle } = useFullscreen();
20
+ const props = withDefaults(
21
+ defineProps<{
22
+ // 用户菜单渲染函数
23
+ dropdownMenuRender?: DropdownMenuRender
24
+ }>(),
25
+ {
26
+ dropdownMenuRender: (({ Home, Preferences, Hotkeys, Org, Profile, Password, Logout, Divider }) => {
27
+ return [Home, Preferences, Divider, Hotkeys, Divider, Org, Profile, Password, Logout];
28
+ }) as DropdownMenuRender,
29
+ },
30
+ );
32
31
 
33
- const { toggle: toggleSearch } = useGlobalSearch();
32
+ const router = useRouter();
33
+ const { settingsStore, userStore, generateTitle } = useContext();
34
34
 
35
35
  const hotkeysIntroRef = ref();
36
36
  const preferencesRef = ref();
37
37
 
38
- const userMenu = computed(() => [
39
- [
40
- {
41
- label: generateI18nTitle('route.home', settingsStore.settings.home.title),
38
+ const userMenu = computed(() => {
39
+ return {
40
+ Home: {
41
+ key: 'home',
42
+ label: generateTitle(settingsStore.settings.home.title),
42
43
  icon: 'i-ant-design:home-twotone',
43
- handle: () => router.push({ name: 'Home' }),
44
+ onClick: () => router.push({ name: 'Home' }),
44
45
  hide: !settingsStore.settings.home.enable,
45
46
  },
46
- {
47
- label: t('app.preferences'),
47
+ Preferences: {
48
+ key: 'preferences',
49
+ label: '个人偏好设置',
48
50
  icon: 'i-iconamoon-star-duotone',
49
- handle: () => preferencesRef.value?.open?.(),
51
+ onClick: () => preferencesRef.value?.open?.(),
50
52
  hide: !settingsStore.settings.app.enableUserPreferences,
51
53
  },
52
- ],
53
- [
54
- {
55
- label: t('app.hotkeys'),
54
+ Hotkeys: {
55
+ key: 'hotkeys',
56
+ label: '快捷键介绍',
56
57
  icon: 'i-iconamoon-lightning-2-duotone',
57
- handle: () => hotkeysIntroRef.value?.open?.(),
58
+ onClick: () => hotkeysIntroRef.value?.open?.(),
58
59
  hide: settingsStore.mode !== 'pc',
59
60
  },
60
- ],
61
- [
62
- {
63
- label: t('app.changeOrg'),
61
+ Org: {
62
+ key: 'org',
63
+ label: '切换组织',
64
64
  icon: 'i-iconamoon-synchronize-duotone',
65
- handle: () => router.push({
65
+ onClick: () => router.push({
66
66
  name: 'ChangeOrganization',
67
67
  params: { orgId: userStore.user.orgId },
68
68
  }),
69
69
  hide: userStore.user.orgList.length <= 1,
70
70
  },
71
- {
72
- label: t('route.personal.profile'),
71
+ Profile: {
72
+ key: 'profile',
73
+ label: '个人中心',
73
74
  icon: 'i-iconamoon-profile-duotone',
74
- handle: () => router.push({ name: 'Profile' }),
75
+ onClick: () => router.push({ name: 'Profile' }),
75
76
  },
76
- {
77
- label: t('app.changePassword'),
77
+ Password: {
78
+ key: 'password',
79
+ label: '修改密码',
78
80
  icon: 'i-iconamoon-lock-duotone',
79
- handle: () => router.push({
81
+ onClick: () => router.push({
80
82
  name: 'ChangePassword',
81
83
  params: {
82
84
  changePassWordToken: userStore.user.token,
83
85
  },
84
86
  }),
85
87
  },
86
- {
87
- label: t('app.logout'),
88
+ Logout: {
89
+ key: 'logout',
90
+ label: '退出登录',
88
91
  icon: 'i-iconamoon-arrow-left-3-square-duotone',
89
- handle: () => userStore.logout(),
92
+ onClick: () => userStore.logout(),
90
93
  },
91
- ],
92
- ]);
93
-
94
- function toggleColorScheme(event: MouseEvent) {
95
- const { startViewTransition } = useViewTransition(async () => {
96
- const colorScheme = settingsStore.settings.app.colorScheme === 'dark' ? 'light' : 'dark';
97
- settingsStore.setColorScheme(colorScheme);
98
- await settingsStore.setPreferencesSetting({
99
- app: {
100
- colorScheme,
101
- },
102
- });
103
- });
94
+ Divider: {
95
+ key: 'divider',
96
+ },
97
+ };
98
+ });
104
99
 
105
- startViewTransition()?.ready.then(() => {
106
- const x = event.clientX;
107
- const y = event.clientY;
108
- const endRadius = Math.hypot(
109
- Math.max(x, innerWidth - x),
110
- Math.max(y, innerHeight - y),
111
- );
112
- const clipPath = [
113
- `circle(0px at ${x}px ${y}px)`,
114
- `circle(${endRadius}px at ${x}px ${y}px)`,
115
- ];
116
- document.documentElement.animate(
117
- {
118
- clipPath: settingsStore.settings.app.colorScheme !== 'dark' ? clipPath : clipPath.reverse(),
119
- },
120
- {
121
- duration: 300,
122
- easing: 'ease-out',
123
- pseudoElement: settingsStore.settings.app.colorScheme !== 'dark' ? '::view-transition-new(root)' : '::view-transition-old(root)',
124
- },
125
- );
126
- });
127
- }
100
+ const menus = computed(() => {
101
+ return props.dropdownMenuRender?.(userMenu.value);
102
+ });
128
103
 
129
104
  const avatarError = ref(false);
130
105
 
@@ -133,73 +108,33 @@ watch(() => userStore.user.avatar, () => {
133
108
  avatarError.value = false;
134
109
  }
135
110
  });
136
-
137
- const searchComponentsClass = computed(() => {
138
- const componentsClass = {
139
- 'side': 'ring-1 ',
140
- 'head': 'bg-[var(--g-header-menu-active-bg)]',
141
- 'single': ' ring-1',
142
- 'only-side': 'ring-1',
143
- 'only-head': ' bg-[var(--g-header-menu-active-bg)]',
144
- };
145
- const menuMode = settingsStore.settings.menu.menuMode;
146
- return componentsClass[menuMode];
147
- });
148
111
  </script>
149
112
 
150
113
  <template>
151
114
  <div class="tools flex items-center gap-4 whitespace-nowrap px-4">
152
- <span
153
- v-if="settingsStore.settings.navSearch.enable && settingsStore.mode === 'pc'"
154
- class="group inline-flex cursor-pointer items-center gap-1 rounded-2 px-2 py-1.5 hover:ring-1 ring-inset transition ring-stone-3 dark:ring-stone-7"
155
- :class="searchComponentsClass"
156
- @click="toggleSearch('menu')"
157
- >
158
- <IconamoonSearch text="14px" />
159
- <span class="text-sm transition ">{{ t('app.search.text') }}</span>
160
- <HKbd
161
- v-if="settingsStore.settings.navSearch.enableHotkeys"
162
- class="ml-2"
163
- >{{ settingsStore.os === 'mac' ? '⌥' : 'Alt' }} S</HKbd>
164
- </span>
165
- <div class="flex items-center empty:hidden">
166
- <span
167
- v-if="settingsStore.settings.navSearch.enable && settingsStore.mode === 'mobile'"
168
- class="item"
169
- @click="toggleSearch('menu')"
170
- >
171
- <IconamoonSearch text="14px" />
172
- </span>
173
- <span
174
- v-if="settingsStore.mode === 'pc' && settingsStore.settings.toolbar.enableFullscreen"
175
- class="item"
176
- @click="toggle"
177
- >
178
- <FluentFullScreenMinimize16Filled v-if="isFullscreen" text="16px" />
179
- <FluentFullScreenMaximize16Filled v-else text="16px" />
180
- </span>
181
- <span
182
- v-if="settingsStore.settings.toolbar.enablePageReload"
183
- class="item"
184
- @click="mainPage.reload()"
185
- >
186
- <FluentArrowSync16Filled text="15px" />
187
- </span>
188
- <DayNightSwitch @click="toggleColorScheme" />
115
+ <SearchBar />
116
+
117
+ <div class="flex items-center empty:hidden gap-3">
118
+ <slot name="default">
119
+ <Fullscreen />
120
+ <PageReload />
121
+ <DarkModeToggle />
122
+ </slot>
189
123
  </div>
124
+
190
125
  <div flex-center cursor-pointer gap-1>
191
126
  <img
192
127
  v-if="userStore.user.avatar && !avatarError"
193
128
  :src="userStore.user.avatar"
194
129
  :onerror="() => (avatarError = true)"
195
- class="h-[24px] w-[24px] rounded-full"
130
+ class="size-[24px] rounded-full"
196
131
  >
197
132
  <CarbonUserAvatarFilledAlt v-else text="20px" mr-2px />
198
133
  <div class="flex-center cursor-pointer">
199
134
  {{ userStore.userOrgName }}
200
135
  </div>
201
- <PhLineVerticalThin />
202
- <HDropdownMenu :items="userMenu">
136
+ <PhLineVerticalThin v-if="userStore?.userOrgName" />
137
+ <HDropdownMenu :items="menus">
203
138
  <div flex-center cursor-pointer gap-1>
204
139
  {{ userStore.user.account }}
205
140
  <MaterialSymbolsExpandMoreRounded ml="5px" mr="10px" />
@@ -208,13 +143,7 @@ const searchComponentsClass = computed(() => {
208
143
  </div>
209
144
 
210
145
  <HotkeysIntro ref="hotkeysIntroRef" />
211
- <Search />
146
+ <SearchPanel />
212
147
  <Preferences v-if="settingsStore.settings.app.enableUserPreferences" ref="preferencesRef" />
213
148
  </div>
214
149
  </template>
215
-
216
- <style scoped>
217
- .item {
218
- --at-apply: flex px-2 py-1 cursor-pointer;
219
- }
220
- </style>
@@ -0,0 +1,27 @@
1
+ export interface DropdownMenu {
2
+ key?: string | 'divider'
3
+ icon?: string
4
+ label?: string
5
+ disabled?: boolean
6
+ hide?: boolean
7
+ onClick?: () => void
8
+ }
9
+
10
+ export type DropdownMenuRender = (items: {
11
+ /** 主页 */
12
+ Home: DropdownMenu
13
+ /** 个人偏好设置 */
14
+ Preferences: DropdownMenu
15
+ /** 快捷键介绍 */
16
+ Hotkeys: DropdownMenu
17
+ /** 切换组织 */
18
+ Org: DropdownMenu
19
+ /** 个人中心 */
20
+ Profile: DropdownMenu
21
+ /** 修改密码 */
22
+ Password: DropdownMenu
23
+ /** 登出 */
24
+ Logout: DropdownMenu
25
+ /** 分割线 */
26
+ Divider: DropdownMenu
27
+ }) => DropdownMenu[];