@liujitcn/kratos-uni-app-core 0.0.43 → 0.0.44

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/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "type": "git",
8
8
  "url": "git@github.com:liujitcn/kratos-admin.git"
9
9
  },
10
- "version": "0.0.43",
10
+ "version": "0.0.44",
11
11
  "type": "module",
12
12
  "files": [
13
13
  "dist",
package/src/bootstrap.ts CHANGED
@@ -36,8 +36,17 @@ export function bootstrapKratosApp(options: KratosAppBootstrapOptions) {
36
36
  .catch(() => {
37
37
  // 语言公共接口失败时继续使用静态语言包和系统语言。
38
38
  })
39
- registerLocaleChangeHandler(initializeAppNavigation)
40
- registerLocaleChangeHandler(() => useSettingStore(options.pinia).loadData())
39
+ registerLocaleChangeHandler(async () => {
40
+ const settingStore = useSettingStore(options.pinia)
41
+ await settingStore.loadData()
42
+ await initializeAppNavigation()
43
+ })
44
+ void useSettingStore(options.pinia)
45
+ .loadData()
46
+ .then(() => initializeAppNavigation())
47
+ .catch((error) => {
48
+ console.warn('application configuration unavailable', error)
49
+ })
41
50
  const app = options.createSSRApp(options.app)
42
51
  app.use(options.pinia)
43
52
  return { app }
package/src/navigation.ts CHANGED
@@ -7,6 +7,7 @@ import { resolveStaticView } from './module'
7
7
  import { matchLogicalPath, parseLogicalQuery } from './navigation-pattern.mjs'
8
8
  import { buildMenuTree } from './navigation-tree.mjs'
9
9
  import { getCurrentLocale, t } from './locales'
10
+ import { useSettingStore } from './stores'
10
11
 
11
12
  /** 移动菜单访问模式。 */
12
13
  export type AppMenuAccess = 'PUBLIC' | 'GUEST_ONLY' | 'AUTHENTICATED'
@@ -178,9 +179,9 @@ export function setAppNavigationAdapter(nextAdapter: AppNavigationAdapter): void
178
179
  export async function initializeAppNavigation(): Promise<void> {
179
180
  const cacheKey = resolveCacheKey()
180
181
  const cached = readCachedMenus(cacheKey)
181
- menus.value = cached ?? createDefaultMenus()
182
+ menus.value = filterUnavailableMenus(cached ?? createDefaultMenus())
182
183
  try {
183
- const nextMenus = normalizeMenuResponse(await adapter.list())
184
+ const nextMenus = filterUnavailableMenus(normalizeMenuResponse(await adapter.list()))
184
185
  validateMenus(nextMenus)
185
186
  uni.setStorageSync(cacheKey, nextMenus)
186
187
  menus.value = nextMenus
@@ -193,6 +194,12 @@ export async function initializeAppNavigation(): Promise<void> {
193
194
  }
194
195
  }
195
196
 
197
+ /** 根据运行时能力过滤不可用的移动端入口。 */
198
+ function filterUnavailableMenus(nextMenus: AppMenu[]): AppMenu[] {
199
+ if (useSettingStore().aiEnabled) return nextMenus
200
+ return nextMenus.filter((menu) => menu.viewKey !== 'AI')
201
+ }
202
+
196
203
  /** 使用已经校验的整份配置进行原子切换。 */
197
204
  export function installAppNavigation(nextMenus: AppMenu[]): void {
198
205
  validateMenus(nextMenus)
@@ -210,6 +217,7 @@ export function resolveAppRoute(rawRoute: string): ResolvedAppRoute | undefined
210
217
  if (!params) continue
211
218
  const physicalRoute = resolveStaticView(menu.viewKey)
212
219
  if (!physicalRoute) return
220
+ if (menu.viewKey === 'AI' && !useSettingStore().aiEnabled) return
213
221
  return {
214
222
  menu,
215
223
  physicalRoute,
@@ -38,6 +38,8 @@ export interface ConfigItem {
38
38
  export interface GetConfigResponse {
39
39
  /** 系统配置列表 */
40
40
  configs: ConfigItem[];
41
+ /** AI 助手是否可用 */
42
+ ai_enabled: boolean;
41
43
  }
42
44
 
43
45
  /** Base系统配置公共服务 */
@@ -12,6 +12,7 @@ const REQUIRED_APP_CONFIGS = [
12
12
 
13
13
  export const useSettingStore = defineStore('setting', () => {
14
14
  const data = ref<Map<string, string>>()
15
+ const aiEnabled = ref(false)
15
16
  let loading: Promise<void> | undefined
16
17
 
17
18
  /** 读取移动端配置项。 */
@@ -26,9 +27,15 @@ export const useSettingStore = defineStore('setting', () => {
26
27
  }
27
28
 
28
29
  const request = (async () => {
29
- const res = await defConfigService.GetConfig({
30
- site: BaseConfigSite.BASE_CONFIG_SITE_APP,
31
- })
30
+ let res
31
+ try {
32
+ res = await defConfigService.GetConfig({
33
+ site: BaseConfigSite.BASE_CONFIG_SITE_APP,
34
+ })
35
+ } catch {
36
+ aiEnabled.value = false
37
+ return
38
+ }
32
39
  const nextData = new Map<string, string>()
33
40
  res.configs.forEach((item) => {
34
41
  nextData.set(item.key, item.value)
@@ -44,6 +51,7 @@ export const useSettingStore = defineStore('setting', () => {
44
51
  }
45
52
 
46
53
  data.value = nextData
54
+ aiEnabled.value = res.ai_enabled === true
47
55
  })()
48
56
  loading = request
49
57
 
@@ -56,6 +64,7 @@ export const useSettingStore = defineStore('setting', () => {
56
64
 
57
65
  return {
58
66
  getData,
67
+ aiEnabled,
59
68
  loadData,
60
69
  }
61
70
  })
@@ -5,6 +5,7 @@ import BootstrapStatus from '../../../components/BootstrapStatus.vue'
5
5
  import { initializeAppNavigation, launchAppStatus, navigateAppRoute } from '../../../navigation'
6
6
  import type { BootstrapViewKey } from '../../../module'
7
7
  import { useI18n } from '../../../locales'
8
+ import { useSettingStore } from '../../../stores'
8
9
 
9
10
  const state = ref<BootstrapViewKey>('BOOTSTRAP_LOADING')
10
11
  const detail = ref('')
@@ -17,16 +18,28 @@ onLoad((options) => {
17
18
  state.value = (options?.state as BootstrapViewKey | undefined) ?? 'BOOTSTRAP_LOADING'
18
19
  detail.value = options?.detail ? decodeURIComponent(options.detail) : ''
19
20
  if (options?.bootstrap !== '1') return
20
- void initializeAppNavigation()
21
+ void useSettingStore()
22
+ .loadData()
23
+ .then(() => initializeAppNavigation())
21
24
  .then(() => {
22
25
  navigateAppRoute(options?.route ? decodeURIComponent(options.route) : 'app/home', {
23
26
  replace: true,
24
27
  })
25
28
  })
26
29
  .catch((error) => {
27
- launchAppStatus('CONFIG_ERROR', error instanceof Error ? error.message : String(error))
30
+ launchAppStatus('CONFIG_ERROR', resolveErrorMessage(error))
28
31
  })
29
32
  })
33
+
34
+ /** 将请求错误转换为可展示的文本,避免直接显示 Object。 */
35
+ function resolveErrorMessage(error: unknown): string {
36
+ if (error instanceof Error) return error.message
37
+ if (typeof error === 'string') return error
38
+ if (error && typeof error === 'object' && 'message' in error) {
39
+ return String((error as { message?: unknown }).message || '')
40
+ }
41
+ return ''
42
+ }
30
43
  </script>
31
44
 
32
45
  <template>