@pubinfo/core 2.0.0-rc.3 → 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 (97) hide show
  1. package/dist/{AppSetting-3wJKvibc.js → AppSetting-BI-oNc4e.js} +15 -15
  2. package/dist/{HCheckList.vue_vue_type_script_setup_true_lang-17EywJvs.js → HCheckList.vue_vue_type_script_setup_true_lang-BdLpkcoh.js} +1 -1
  3. package/dist/{HToggle-B-ZjSh6S.js → HToggle-DxdWLgp-.js} +1 -1
  4. package/dist/{PreferencesContent-xT4paU7N.js → PreferencesContent-CCYkZeCT.js} +4 -4
  5. package/dist/{SettingBreadcrumb-CYnO51Ek.js → SettingBreadcrumb-BTyfiy4k.js} +3 -3
  6. package/dist/{SettingCopyright-FOW5ObHK.js → SettingCopyright-g6UHi8pZ.js} +2 -2
  7. package/dist/{SettingEnableTransition-Q5cvubmF.js → SettingEnableTransition-Ci-5bhbR.js} +2 -2
  8. package/dist/{SettingHome-Df7-AlWB.js → SettingHome-K4Iel0Hr.js} +2 -2
  9. package/dist/{SettingMenu-BNAJ3el9.js → SettingMenu-BYLWzA5i.js} +3 -3
  10. package/dist/{SettingMode-LzlRsBL9.js → SettingMode-tRisyKtg.js} +1 -1
  11. package/dist/{SettingNavSearch-BA08vYuw.js → SettingNavSearch-CSM6mPf8.js} +2 -2
  12. package/dist/{SettingOther-BE8dDCYD.js → SettingOther-Bj5KF_vC.js} +2 -2
  13. package/dist/{SettingPage-D061yXCv.js → SettingPage-CFjmrVI7.js} +2 -2
  14. package/dist/{SettingTabbar-COwdPPKy.js → SettingTabbar-uFYiaZhK.js} +3 -3
  15. package/dist/{SettingThemes-BHaYERNp.js → SettingThemes-C-tMq9o5.js} +1 -1
  16. package/dist/{SettingToolbar-fSuzu6ND.js → SettingToolbar-BfDzijNU.js} +2 -2
  17. package/dist/{SettingTopbar-D7GgP0KB.js → SettingTopbar-DTDv4NXD.js} +3 -3
  18. package/dist/{SettingWidthMode-CNjzChe1.js → SettingWidthMode-PkiwrHe3.js} +1 -1
  19. package/dist/{TopThinMode-B-28sBJD.js → TopThinMode-BrvA8pV0.js} +1 -1
  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/components/ui/HSlideover.vue.d.ts +1 -1
  25. package/dist/built-in/layout-component/composables/useContext.d.ts +1 -1
  26. package/dist/built-in/layout-component/composables/useTitle.d.ts +1 -1
  27. package/dist/{colors-BIQSd520.js → colors-VoaDbOhe.js} +1 -1
  28. package/dist/core/interface.d.ts +14 -5
  29. package/dist/core/request.d.ts +2 -8
  30. package/dist/features/api/modules/auth/renzhengfuwu.d.ts +8 -8
  31. package/dist/features/api/modules/configData/heibaimingdanfuwu.d.ts +5 -5
  32. package/dist/features/api/modules/configData/xitongpeizhifuwu.d.ts +14 -14
  33. package/dist/features/api/modules/configData/zidifuwu.d.ts +10 -10
  34. package/dist/features/api/modules/rbac/gangweijiekou.d.ts +6 -6
  35. package/dist/features/api/modules/rbac/jiaosejiekou.d.ts +7 -7
  36. package/dist/features/api/modules/rbac/pubJiaosezukongzhiqi.d.ts +7 -7
  37. package/dist/features/api/modules/rbac/shujuquanxianzhubiaokongzhiqi.d.ts +9 -9
  38. package/dist/features/api/modules/rbac/yonghujiekou.d.ts +15 -15
  39. package/dist/features/api/modules/rbac/yonghushoucangbiaojiekou.d.ts +5 -5
  40. package/dist/features/api/modules/rbac/yonghuzuijinchangyongbiaojiekou.d.ts +4 -4
  41. package/dist/features/api/modules/rbac/ziyuanjiekou.d.ts +13 -13
  42. package/dist/features/api/modules/rbac/zuhuguanlijiekou.d.ts +5 -5
  43. package/dist/features/api/modules/rbac/zuzhijiaosebiaokongzhiqi.d.ts +4 -4
  44. package/dist/features/api/modules/rbac/zuzhijiekou.d.ts +9 -9
  45. package/dist/features/api/system/user.d.ts +4 -4
  46. package/dist/{index-YSjb6X1D.js → index-BSevJVD5.js} +4 -7
  47. package/dist/{index-Dlf6GQBd.js → index-BfGqLWFB.js} +4 -4
  48. package/dist/{index-DYMBkmAp.js → index-CYoFRwvw.js} +2 -2
  49. package/dist/{index-DNdH93AP.js → index-ConeY38N.js} +2 -2
  50. package/dist/{index-CPRiufg0.js → index-DV3hkzKA.js} +1 -1
  51. package/dist/{index-wxEEuQXu.js → index-Ddw98rJ5.js} +9 -9
  52. package/dist/{index-IscoZG-Y.js → index-DrC787X_.js} +2 -2
  53. package/dist/{index-WubcSL0v.js → index-Dv9ndBoi.js} +1 -1
  54. package/dist/{index-Beb7_0-E.js → index-IAYhIBQH.js} +16305 -16239
  55. package/dist/index.js +1 -1
  56. package/dist/{pick-D_XPbQHB.js → pick-vpv9EEvu.js} +1 -1
  57. package/dist/style.css +1 -1
  58. package/package.json +7 -7
  59. package/src/built-in/authentication/alova/helper.ts +158 -0
  60. package/src/built-in/authentication/alova/token.ts +122 -0
  61. package/src/built-in/authentication/helper.ts +7 -3
  62. package/src/built-in/authentication/index.ts +6 -20
  63. package/src/built-in/index.ts +0 -1
  64. package/src/built-in/layout-component/components/Header/TopMode/index.vue +3 -3
  65. package/src/built-in/layout-component/components/Menu/item.vue +3 -3
  66. package/src/built-in/layout-component/components/Sidebar/MainSidebar.vue +3 -3
  67. package/src/built-in/layout-component/components/Tools/SearchBar.vue +1 -3
  68. package/src/built-in/layout-component/components/Tools/SearchPanel.vue +12 -20
  69. package/src/built-in/layout-component/components/Tools/index.vue +8 -11
  70. package/src/built-in/layout-component/components/Topbar/Tabbar/MoreAction.vue +7 -10
  71. package/src/built-in/layout-component/components/Topbar/Tabbar/index.vue +10 -13
  72. package/src/built-in/layout-component/components/Topbar/Toolbar/Favorites.vue +4 -7
  73. package/src/built-in/layout-component/components/Topbar/Toolbar/index.vue +6 -6
  74. package/src/built-in/layout-component/composables/useContext.ts +1 -1
  75. package/src/built-in/layout-component/composables/useTitle.ts +8 -14
  76. package/src/built-in/layout-component/provider.ts +2 -2
  77. package/src/core/interface.ts +18 -5
  78. package/src/core/request.ts +35 -15
  79. package/src/features/router/systemRoutes.ts +0 -1
  80. package/src/features/stores/modules/favorites.ts +0 -1
  81. package/src/features/stores/modules/route.ts +2 -9
  82. package/src/features/stores/modules/tabbar.ts +0 -3
  83. package/src/features/stores/utils/routerHelper.ts +35 -4
  84. package/src/index.ts +0 -2
  85. package/types/vue-router.d.ts +0 -3
  86. package/dist/built-in/locales/helpler.d.ts +0 -594
  87. package/dist/built-in/locales/index.d.ts +0 -5
  88. package/dist/built-in/locales/lang/en.json.d.ts +0 -99
  89. package/dist/built-in/locales/lang/zh-cn.json.d.ts +0 -100
  90. package/dist/built-in/locales/lang/zh-tw.json.d.ts +0 -100
  91. package/dist/built-in/locales/ui.d.ts +0 -3
  92. package/src/built-in/locales/helpler.ts +0 -76
  93. package/src/built-in/locales/index.ts +0 -20
  94. package/src/built-in/locales/lang/en.json +0 -96
  95. package/src/built-in/locales/lang/zh-cn.json +0 -97
  96. package/src/built-in/locales/lang/zh-tw.json +0 -97
  97. package/src/built-in/locales/ui.ts +0 -3
@@ -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, generateI18nTitle } = useContext();
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: generateI18nTitle('route.home', settingsStore.settings.home.title),
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: t('app.preferences'),
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: t('app.hotkeys'),
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: t('app.changeOrg'),
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: t('route.personal.profile'),
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: t('app.changePassword'),
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: t('app.logout'),
90
+ label: '退出登录',
94
91
  icon: 'i-iconamoon-arrow-left-3-square-duotone',
95
92
  onClick: () => userStore.logout(),
96
93
  },
@@ -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, generateI18nTitle } = useContext();
24
+ const { settingsStore, tabbarStore, generateTitle } = 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();
@@ -99,22 +96,22 @@ function iconName(isActive: boolean, icon: Tabbar.recordRaw['icon'], activeIcon:
99
96
  <template #dropdown>
100
97
  <div class="quick-button">
101
98
  <button v-if="settingsStore.settings.navSearch.enable" class="button" @click="actionCommand('search-tabs')">
102
- <HTooltip :text="t('app.tabbar.searchTabs')">
99
+ <HTooltip text="搜索标签页">
103
100
  <EpSearch />
104
101
  </HTooltip>
105
102
  </button>
106
103
  <button class="button" :disabled="!tabbar.checkCloseOtherSide()" @click="actionCommand('other-side')">
107
- <HTooltip :text="t('app.tabbar.closeOtherSide')">
104
+ <HTooltip text="关闭其它标签页">
108
105
  <EpClose />
109
106
  </HTooltip>
110
107
  </button>
111
108
  <button class="button" :disabled="!tabbar.checkCloseLeftSide()" @click="actionCommand('left-side')">
112
- <HTooltip :text="t('app.tabbar.closeLeftSide')">
109
+ <HTooltip text="关闭左侧标签页">
113
110
  <PhArrowLineLeft />
114
111
  </HTooltip>
115
112
  </button>
116
113
  <button class="button" :disabled="!tabbar.checkCloseRightSide()" @click="actionCommand('right-side')">
117
- <HTooltip :text="t('app.tabbar.closeRightSide')">
114
+ <HTooltip text="关闭右侧标签页">
118
115
  <PhArrowLineRight />
119
116
  </HTooltip>
120
117
  </button>
@@ -127,9 +124,9 @@ function iconName(isActive: boolean, icon: Tabbar.recordRaw['icon'], activeIcon:
127
124
  'no-drag': element.isPermanent || element.isPin,
128
125
  }"
129
126
  >
130
- <div :key="element.tabId" class="title" :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateI18nTitle(element.title)" @click="router.push(element.fullPath)">
127
+ <div :key="element.tabId" class="title" :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title)" @click="router.push(element.fullPath)">
131
128
  <PubinfoIcon v-if="settingsStore.settings.tabbar.enableIcon && iconName(element.tabId === activedTabId, element.icon, element.activeIcon)" :name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!" />
132
- {{ element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateI18nTitle(element.i18n, element.title) }}
129
+ {{ element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title) }}
133
130
  </div>
134
131
  <div v-if="!element.isPermanent && element.isPin" class="action-icon" @click.stop="tabbarStore.unPin(element.tabId)">
135
132
  <RiPushpin2Fill />
@@ -4,7 +4,6 @@ import ContextMenu from '@imengyu/vue3-context-menu';
4
4
  import { useMagicKeys } from '@vueuse/core';
5
5
  import hotkeys from 'hotkeys-js';
6
6
  import Sortable from 'sortablejs';
7
- import { useI18n } from 'vue-i18n';
8
7
  import Message from 'vue-m-message';
9
8
  import RiCloseFill from '~icons/ri/close-fill';
10
9
  import RiPushpin2Fill from '~icons/ri/pushpin-2-fill';
@@ -23,15 +22,13 @@ defineOptions({
23
22
  const route = useRoute();
24
23
  const router = useRouter();
25
24
 
26
- const { settingsStore, tabbarStore, generateI18nTitle } = useContext();
25
+ const { settingsStore, tabbarStore, generateTitle } = useContext();
27
26
 
28
27
  const tabbar = useTabbar();
29
28
  const mainPage = useMainPage();
30
29
 
31
30
  const keys = useMagicKeys({ reactive: true });
32
31
 
33
- const { t } = useI18n();
34
-
35
32
  const activedTabId = computed(() => tabbar.getId());
36
33
  const isShowMoreAction = computed(() => tabbarStore.list.length > 1 && (tabbar.checkCloseOtherSide() || tabbar.checkCloseLeftSide() || tabbar.checkCloseRightSide()));
37
34
 
@@ -162,13 +159,13 @@ function onTabbarContextmenu(event: MouseEvent, routeItem: Tabbar.recordRaw) {
162
159
  customClass: 'tabbar-contextmenu',
163
160
  items: [
164
161
  {
165
- label: t('app.tabbar.reload'),
162
+ label: '重新加载',
166
163
  icon: 'i-ri-refresh-line',
167
164
  disabled: routeItem.tabId !== activedTabId.value,
168
165
  onClick: () => mainPage.reload(),
169
166
  },
170
167
  {
171
- label: t('app.tabbar.close'),
168
+ label: '关闭标签页',
172
169
  icon: 'i-ri-close-line',
173
170
  disabled: tabbarStore.list.length <= 1 || routeItem.isPin || routeItem.isPermanent,
174
171
  divided: true,
@@ -177,7 +174,7 @@ function onTabbarContextmenu(event: MouseEvent, routeItem: Tabbar.recordRaw) {
177
174
  },
178
175
  },
179
176
  {
180
- label: routeItem.isPin ? t('app.tabbar.unpin') : t('app.tabbar.pin'),
177
+ label: routeItem.isPin ? '取消固定' : '固定',
181
178
  icon: routeItem.isPin ? 'i-lucide-pin-off' : 'i-lucide-pin',
182
179
  // 主页不允许被固定,因为如果固定主页且主页未启用,会导致登录时进入路由死循环状态
183
180
  disabled: routeItem.fullPath === '/' || routeItem.isPermanent,
@@ -191,7 +188,7 @@ function onTabbarContextmenu(event: MouseEvent, routeItem: Tabbar.recordRaw) {
191
188
  },
192
189
  },
193
190
  {
194
- label: t('app.tabbar.maximize'),
191
+ label: '最大化',
195
192
  icon: 'i-ri-picture-in-picture-exit-line',
196
193
  onClick: () => {
197
194
  if (routeItem.tabId !== activedTabId.value) {
@@ -202,21 +199,21 @@ function onTabbarContextmenu(event: MouseEvent, routeItem: Tabbar.recordRaw) {
202
199
  },
203
200
  },
204
201
  {
205
- label: t('app.tabbar.closeOtherSide'),
202
+ label: '关闭其它标签页',
206
203
  disabled: !tabbar.checkCloseOtherSide(routeItem.tabId),
207
204
  onClick: () => {
208
205
  tabbar.closeOtherSide(routeItem.tabId);
209
206
  },
210
207
  },
211
208
  {
212
- label: t('app.tabbar.closeLeftSide'),
209
+ label: '关闭左侧标签页',
213
210
  disabled: !tabbar.checkCloseLeftSide(routeItem.tabId),
214
211
  onClick: () => {
215
212
  tabbar.closeLeftSide(routeItem.tabId);
216
213
  },
217
214
  },
218
215
  {
219
- label: t('app.tabbar.closeRightSide'),
216
+ label: '关闭右侧标签页',
220
217
  disabled: !tabbar.checkCloseRightSide(routeItem.tabId),
221
218
  onClick: () => {
222
219
  tabbar.closeRightSide(routeItem.tabId);
@@ -319,7 +316,7 @@ onUnmounted(() => {
319
316
  'actived': element.tabId === activedTabId,
320
317
  'no-drag': element.isPermanent || element.isPin,
321
318
  }"
322
- :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateI18nTitle(element.i18n, element.title)"
319
+ :title="element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title)"
323
320
  @click="router.push(element.fullPath)"
324
321
  @dblclick="settingsStore.setMainPageMaximize()"
325
322
  @contextmenu="onTabbarContextmenu($event, element)"
@@ -333,7 +330,7 @@ onUnmounted(() => {
333
330
  :name="iconName(element.tabId === activedTabId, element.icon, element.activeIcon)!"
334
331
  class="icon"
335
332
  />
336
- {{ element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateI18nTitle(element.i18n, element.title) }}
333
+ {{ element.customTitleList.find(item => item.fullPath === element.fullPath)?.title || generateTitle(element.title) }}
337
334
  </div>
338
335
  <div v-if="!element.isPermanent && element.isPin" class="action-icon" @click.stop="tabbarStore.unPin(element.tabId)" @dblclick.stop>
339
336
  <RiPushpin2Fill text="10px" />
@@ -2,7 +2,6 @@
2
2
  import { isUndefined } from 'lodash-es';
3
3
  import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue';
4
4
  import Sortable from 'sortablejs';
5
- import { useI18n } from 'vue-i18n';
6
5
  import FluentDelete24Filled from '~icons/fluent/delete-24-filled';
7
6
  import FluentStarAdd16Regular from '~icons/fluent/star-add-16-regular';
8
7
  import FluentStarDismiss16Regular from '~icons/fluent/star-dismiss-16-regular';
@@ -15,9 +14,7 @@ defineOptions({
15
14
 
16
15
  const route = useRoute();
17
16
  const router = useRouter();
18
- const { favoritesStore, routeStore, generateI18nTitle } = useContext();
19
- const { t } = useI18n();
20
-
17
+ const { favoritesStore, routeStore, generateTitle } = useContext();
21
18
  const favoritesContainerRef = ref<HTMLElement | null>(null);
22
19
 
23
20
  let _favoritesSortable: Sortable | null = null;
@@ -46,7 +43,7 @@ watch(favoritesContainerRef, (newSortableContainer) => {
46
43
  <div class="favorites-container w-80 dark:bg-[var(--g-container-bg)]">
47
44
  <div class="flex items-center justify-between px-4 py-3">
48
45
  <div class="text-sm font-bold">
49
- {{ t('app.tabbar.favorites.my-favorites') }}
46
+ {{ '我的收藏夾' }}
50
47
  </div>
51
48
  <template v-if="favoritesStore.canAdd(route.fullPath, routeStore.routes)">
52
49
  <FluentStarAdd16Regular
@@ -81,13 +78,13 @@ watch(favoritesContainerRef, (newSortableContainer) => {
81
78
  <div
82
79
  v-for="item in favoritesStore.list"
83
80
  :key="item.fullPath"
84
- :title="generateI18nTitle(item.i18n, item.title)"
81
+ :title="generateTitle(item.title)"
85
82
  class="draggable-item relative w-[calc(50%-0.25rem)] flex cursor-pointer items-center gap-1 rounded px-2 py-2 ring-1 ring-stone-3 ring-inset hover:bg-stone-1 dark:ring-stone-7 dark:hover:bg-dark/50"
86
83
  @click="router.push(item.fullPath)"
87
84
  >
88
85
  <PubinfoIcon v-if="item.icon" :name="item.icon" :size="18" />
89
86
  <div class="name flex-1 truncate pe-4">
90
- {{ generateI18nTitle(item.i18n, item.title) }}
87
+ {{ generateTitle(item.title) }}
91
88
  </div>
92
89
  <FluentDelete24Filled
93
90
  text-12px
@@ -17,7 +17,7 @@ defineOptions({
17
17
  const route = useRoute();
18
18
  const router = useRouter();
19
19
 
20
- const { settingsStore, menuStore, generateI18nTitle } = useContext();
20
+ const { settingsStore, menuStore, generateTitle } = useContext();
21
21
 
22
22
  /**
23
23
  * 计算属性:是否启用子菜单折叠按钮
@@ -52,7 +52,7 @@ const breadcrumbIsShow = computed(() =>
52
52
  function createHomeBreadcrumb() {
53
53
  return {
54
54
  path: '/',
55
- title: generateI18nTitle('route.home', settingsStore.settings.home.title),
55
+ title: generateTitle(settingsStore.settings.home.title),
56
56
  };
57
57
  }
58
58
 
@@ -78,7 +78,7 @@ const breadcrumbList = computed(() => {
78
78
  breadcrumbList.push({
79
79
  path: `__MAIN__${index}`,
80
80
  mainIndex: index,
81
- title: generateI18nTitle(menuStore.allMenus[index].meta?.i18n, menuStore.allMenus[index].meta?.title),
81
+ title: generateTitle(menuStore.allMenus[index].meta?.title),
82
82
  });
83
83
  }
84
84
  }
@@ -88,7 +88,7 @@ const breadcrumbList = computed(() => {
88
88
  if (item.hide === false) {
89
89
  breadcrumbList.push({
90
90
  path: item.path,
91
- title: generateI18nTitle(item.i18n, item.title),
91
+ title: generateTitle(item.title),
92
92
  });
93
93
  }
94
94
  });
@@ -155,14 +155,14 @@ function getCurrentBreadcrumb(path: string) {
155
155
  const main = menuStore.allMenus[idx];
156
156
  if (main) {
157
157
  const mapNode = (r: any): any => ({
158
- title: generateI18nTitle(r.meta?.i18n, r.meta?.title),
158
+ title: generateTitle(r.meta?.title),
159
159
  path: r.path,
160
160
  children: (r.children || [])
161
161
  .filter((c: any) => c.meta?.sidebar !== false)
162
162
  .map((c: any) => mapNode(c)),
163
163
  });
164
164
  return {
165
- title: generateI18nTitle(main.meta?.i18n, main.meta?.title),
165
+ title: generateTitle(main.meta?.title),
166
166
  path,
167
167
  children: (main.children || [])
168
168
  .filter(c => c.meta?.sidebar !== false)
@@ -22,7 +22,7 @@ interface LayoutContext {
22
22
 
23
23
  appTitle: string
24
24
  isDev: boolean
25
- generateI18nTitle: any
25
+ generateTitle: (titile?: string | (() => any)) => string
26
26
  }
27
27
 
28
28
  const layoutInjectionKey: InjectionKey<LayoutContext> = Symbol('Layout');
@@ -1,9 +1,8 @@
1
1
  import type { useSettingsStore } from '@/features/stores';
2
- import { useI18n } from 'vue-i18n';
3
2
 
4
3
  export function useTitle(appTitle: string, settingsStore: ReturnType<typeof useSettingsStore>) {
5
- const { t, te } = useI18n();
6
4
  const routeInfo = useRoute();
5
+
7
6
  watch(
8
7
  [
9
8
  () => settingsStore.settings.app.enableDynamicTitle,
@@ -13,11 +12,7 @@ export function useTitle(appTitle: string, settingsStore: ReturnType<typeof useS
13
12
  () => {
14
13
  if (settingsStore.settings.app.enableDynamicTitle && settingsStore.title) {
15
14
  const title = settingsStore.customTitleList.find(item => item.fullPath === routeInfo.fullPath)?.title
16
- || (
17
- routeInfo.meta.breadcrumbNeste?.at(-1)?.i18n
18
- ? generateI18nTitle(routeInfo.meta.breadcrumbNeste?.at(-1)?.i18n, settingsStore.title)
19
- : generateI18nTitle(routeInfo.meta.i18n, settingsStore.title)
20
- );
15
+ || generateTitle(settingsStore.title);
21
16
  document.title = `${title} - ${appTitle}`;
22
17
  }
23
18
  else {
@@ -27,14 +22,13 @@ export function useTitle(appTitle: string, settingsStore: ReturnType<typeof useS
27
22
  {
28
23
  deep: true,
29
24
  });
30
- function generateI18nTitle(key?: string, defaultTitle: string | (() => any) = t('route.undefined')) {
31
- return (settingsStore.settings.toolbar.enableI18n && !!key && te(key))
32
- ? t(key)
33
- : typeof defaultTitle === 'function'
34
- ? defaultTitle()
35
- : defaultTitle;
25
+
26
+ function generateTitle(defaultTitle: string | (() => any) = '[ 无标题 ]') {
27
+ return typeof defaultTitle === 'function'
28
+ ? defaultTitle()
29
+ : defaultTitle;
36
30
  }
37
31
  return {
38
- generateI18nTitle,
32
+ generateTitle,
39
33
  };
40
34
  }
@@ -38,7 +38,7 @@ export const Provider = defineComponent({
38
38
  const tabbarStore = useTabbarStore();
39
39
  const favoritesStore = useFavoritesStore();
40
40
 
41
- const { generateI18nTitle } = useTitle(props.appTitle, settingsStore);
41
+ const { generateTitle } = useTitle(props.appTitle, settingsStore);
42
42
 
43
43
  createContext({
44
44
  settingsStore,
@@ -52,7 +52,7 @@ export const Provider = defineComponent({
52
52
 
53
53
  appTitle: props.appTitle,
54
54
  isDev: props.isDev,
55
- generateI18nTitle,
55
+ generateTitle,
56
56
  });
57
57
 
58
58
  return () => h(
@@ -1,5 +1,5 @@
1
1
  import type { AdapterCreateOptions, AlovaAxiosRequestConfig } from '@alova/adapter-axios';
2
- import type { Alova, AlovaGenerics, AlovaOptions, Method } from 'alova';
2
+ import type { Alova, AlovaGenerics, AlovaOptions, Method, ResponseCompleteHandler, ResponseErrorHandler } from 'alova';
3
3
  import type { AxiosResponse, AxiosResponseHeaders } from 'axios';
4
4
  import type { Pinia } from 'pinia';
5
5
  import type { App, Component } from 'vue';
@@ -77,13 +77,26 @@ export type FalsyModule = false | null | undefined;
77
77
 
78
78
  export type ModuleOptions = Module | ModuleOptions[] | FalsyModule;
79
79
 
80
- type AG = AlovaGenerics<any, any, AlovaAxiosRequestConfig, AxiosResponse<any, any>, AxiosResponseHeaders, any, any, any>;
80
+ export type AG = AlovaGenerics<any, any, AlovaAxiosRequestConfig, AxiosResponse<any, any>, AxiosResponseHeaders, any, any, any>;
81
81
 
82
- export type RequestOptions = Omit<AlovaOptions<AG>, 'statesHook' | 'requestAdapter'> & { axios?: AdapterCreateOptions };
82
+ export type RequestOptions = Omit<AlovaOptions<AG>, 'statesHook' | 'requestAdapter' | 'beforeRequest' | 'responded'> & {
83
+ axios?: AdapterCreateOptions
84
+ beforeRequest?: Hooks['http:request']
85
+ responded?: Hooks['http:response']
86
+ };
83
87
  export type RequestInstance = Alova<AG>;
84
88
  export type RequestMethod = Method<AG>;
85
89
 
86
90
  export interface Hooks {
87
- 'http:request': AlovaOptions<AG>['beforeRequest']
88
- 'http:response': AlovaOptions<AG>['responded']
91
+ 'http:request': (method: Method<AG>) => void | Promise<void>
92
+ 'http:response': RespondedHandler<AG> | RespondedHandlerRecord<AG>
93
+ }
94
+
95
+ // overwrite alova
96
+ type Fn = () => void;
97
+ export type RespondedHandler<AG extends AlovaGenerics> = (response: AG['Response'], methodInstance: Method<AG>, stop: Fn) => any;
98
+ export interface RespondedHandlerRecord<AG extends AlovaGenerics> {
99
+ onSuccess?: RespondedHandler<AG>
100
+ onError?: ResponseErrorHandler<AG>
101
+ onComplete?: ResponseCompleteHandler<AG>
89
102
  }
@@ -1,8 +1,8 @@
1
+ import type { AxiosResponse } from 'axios';
1
2
  import type { RequestOptions } from './interface';
2
3
  import { axiosRequestAdapter } from '@alova/adapter-axios';
3
4
  import { createAlova } from 'alova';
4
5
  import vueHook from 'alova/vue';
5
- import { createTokenAuthentication } from '@/built-in';
6
6
  import { hooks } from './ctx';
7
7
 
8
8
  function normalizedResponded(handler: RequestOptions['responded']) {
@@ -12,9 +12,13 @@ function normalizedResponded(handler: RequestOptions['responded']) {
12
12
  return handler;
13
13
  }
14
14
 
15
- export function createRequest(options: RequestOptions) {
16
- const { onAuthRequired, onResponseRefreshToken } = createTokenAuthentication();
17
- const { axios, beforeRequest, responded: _responded, ...restOptions } = options;
15
+ export function createRequest(options: RequestOptions = {}) {
16
+ const {
17
+ axios,
18
+ beforeRequest,
19
+ responded: _responded,
20
+ ...restOptions
21
+ } = options;
18
22
 
19
23
  const responded = normalizedResponded(_responded);
20
24
 
@@ -25,25 +29,41 @@ export function createRequest(options: RequestOptions) {
25
29
  timeout: 60 * 1000,
26
30
  ...restOptions,
27
31
 
28
- beforeRequest: onAuthRequired(async (method) => {
32
+ beforeRequest: async (method) => {
29
33
  await hooks.callHook('http:request', method);
30
34
  await beforeRequest?.(method);
31
- }),
35
+ },
32
36
 
33
- responded: onResponseRefreshToken({
37
+ responded: {
34
38
  onSuccess: async (response, method) => {
35
- const res = await hooks.callHook('http:response:onSuccess', response, method) ?? response;
36
- return responded?.onSuccess?.(res, method) ?? res;
39
+ let stopped = false;
40
+
41
+ const res = await hooks.callHookWith(
42
+ async (hookFns, args) => {
43
+ let _response = args[0];
44
+ for (const fn of hookFns) {
45
+ if (stopped) {
46
+ break;
47
+ }
48
+ _response = await fn(_response, method, () => stopped = true);
49
+ }
50
+ return _response;
51
+ },
52
+ 'http:response:onSuccess',
53
+ response,
54
+ ) as AxiosResponse<any, any>;
55
+
56
+ return stopped ? res : (responded?.onSuccess?.(res, method, () => stopped = true) ?? res);
37
57
  },
38
- onError: (err, method) => {
39
- hooks.callHook('http:response:onError', err, method);
40
- responded?.onError?.(err, method);
58
+ onError: async (err, method) => {
59
+ await hooks.callHook('http:response:onError', err, method);
60
+ return responded?.onError?.(err, method);
41
61
  },
42
- onComplete: (method) => {
43
- hooks.callHook('http:response:onComplete', method);
62
+ onComplete: async (method) => {
63
+ await hooks.callHook('http:response:onComplete', method);
44
64
  responded?.onComplete?.(method);
45
65
  },
46
- }),
66
+ },
47
67
  });
48
68
 
49
69
  return instance;
@@ -18,7 +18,6 @@ const systemRoutes: RouteRecordRaw[] = [
18
18
  component: () => import('@/features/pages/profile/index.vue'),
19
19
  meta: {
20
20
  title: '个人中心',
21
- i18n: 'route.personal.profile',
22
21
  icon: 'i-iconamoon-profile-duotone',
23
22
  },
24
23
  },
@@ -113,7 +113,6 @@ const useFavoritesStore = defineStore(
113
113
  list.value.push({
114
114
  fullPath: route.fullPath,
115
115
  title: meta?.title,
116
- i18n: meta?.i18n,
117
116
  icon: meta?.icon ?? meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon,
118
117
  });
119
118
  }
@@ -40,12 +40,11 @@ const useRouteStore = defineStore(
40
40
  * @returns 面包屑对象
41
41
  */
42
42
  function createBreadcrumb(currentRouter: RouteRecordRaw, baseUrl?: RouteRecordRaw['path']): Route.breadcrumb {
43
- const { title, i18n, icon, activeIcon, breadcrumb = true } = defaultTo(currentRouter.meta, {} as RouteMeta);
43
+ const { title, icon, activeIcon, breadcrumb = true } = defaultTo(currentRouter.meta, {} as RouteMeta);
44
44
  const path = defaultTo(baseUrl, currentRouter.path);
45
45
  return {
46
46
  path,
47
47
  title,
48
- i18n,
49
48
  icon,
50
49
  activeIcon,
51
50
  hide: !breadcrumb,
@@ -163,7 +162,6 @@ const useRouteStore = defineStore(
163
162
 
164
163
  if (routesRaw.value.length) {
165
164
  routesRaw.value.forEach((item) => {
166
- // CLOSE: 开发模式应用的子路由不应该被扁平化到vue-router中
167
165
  // 开发模式应用只在TopMode中显示,点击时显示开发状态
168
166
  if (get(item, 'meta.isDev', false)) {
169
167
  useWarn(`开发模式应用"${item.meta?.title}"的子路由将不会被注册到vue-router中`);
@@ -304,7 +302,6 @@ const useRouteStore = defineStore(
304
302
  component: item.component,
305
303
  meta: {
306
304
  title: item.meta.title,
307
- i18n: item.meta.i18n,
308
305
  sidebar: false,
309
306
  breadcrumb: false,
310
307
  },
@@ -364,7 +361,6 @@ const useRouteStore = defineStore(
364
361
  // 将本地应用替换成静态路由
365
362
  if (route.type === RESOURCE_TYPE.APP) {
366
363
  const foundStaticRoute = staticRoutes.find(staticRoute => staticRoute.meta?.auth === route.code);
367
- // CLOSE: 静态应用如果是开发模式,仍然要返回路由对象供TopMode显示
368
364
  // 但其子路由不会被注册到vue-router中,这由菜单系统和路由扁平化逻辑处理
369
365
  if (foundStaticRoute && get(foundStaticRoute, 'meta.isDev', false)) {
370
366
  useWarn(`静态应用"${foundStaticRoute.meta?.title}"处于开发模式,将在TopMode中显示开发状态`);
@@ -374,10 +370,10 @@ const useRouteStore = defineStore(
374
370
 
375
371
  // 将动态应用数据格式化成路由数据
376
372
  if (route.type === RESOURCE_TYPE.DYNAMIC_APP) {
377
- // CLOSE: 动态应用如果是开发模式,仍然要返回路由对象供TopMode显示
378
373
  if (route.meta?.isDev) {
379
374
  useWarn(`动态应用"${route.name}"处于开发模式,将在TopMode中显示开发状态`);
380
375
  }
376
+
381
377
  return formatBackRoutes([route])[0] as any;
382
378
  }
383
379
 
@@ -400,9 +396,6 @@ const useRouteStore = defineStore(
400
396
  }
401
397
  });
402
398
 
403
- // FIX-ME routesRaw 最终会被 routes 使用,在 menuStore 中作为生成 allMenus 的数据源。
404
- // 为了解决这个问题,我们需要重构一下逻辑,想办法将 路由 和 菜单 分开处理。
405
- // 可以考虑直接让 menuStore 的菜单根据 remoteRoutesRaw 生成。
406
399
  routesRaw.value = [...remoteRoutes, ...restStaticRoutes];
407
400
  }
408
401
 
@@ -37,7 +37,6 @@ const useTabbarStore = defineStore(
37
37
  routeName: route.name,
38
38
  activeMenu: route.meta.activeMenu,
39
39
  title: typeof route.meta.title === 'function' ? route.meta.title() : route.meta.title,
40
- i18n: route.meta.i18n,
41
40
  iframe: route.meta.iframe,
42
41
  icon: route.meta?.icon ?? route.meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon,
43
42
  activeIcon: route.meta?.activeIcon ?? route.meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon,
@@ -95,7 +94,6 @@ const useTabbarStore = defineStore(
95
94
  routeName: route.name!,
96
95
  activeMenu: meta?.activeMenu,
97
96
  title: typeof meta?.title === 'function' ? meta.title() : meta?.title,
98
- i18n: meta?.i18n,
99
97
  iframe: meta?.iframe,
100
98
  icon: meta?.icon ?? meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon,
101
99
  activeIcon: meta?.activeIcon ?? meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon,
@@ -121,7 +119,6 @@ const useTabbarStore = defineStore(
121
119
  findTab.routeName = route.name!;
122
120
  findTab.activeMenu = meta?.activeMenu;
123
121
  findTab.title = typeof meta?.title === 'function' ? meta.title() : meta?.title;
124
- findTab.i18n = meta?.i18n;
125
122
  findTab.iframe = meta?.iframe;
126
123
  findTab.icon = meta?.icon ?? meta?.breadcrumbNeste?.findLast(item => item.icon)?.icon;
127
124
  findTab.activeIcon = meta?.activeIcon ?? meta?.breadcrumbNeste?.findLast(item => item.activeIcon)?.activeIcon;