@liujitcn/kratos-taro-app-core 0.0.43 → 0.0.45
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 +1 -1
- package/src/bootstrap.ts +7 -1
- package/src/navigation.ts +10 -2
- package/src/rpc/base/v1/config.ts +2 -0
- package/src/stores/setting.ts +10 -2
- package/src/views/pages/status/index.tsx +17 -2
package/package.json
CHANGED
package/src/bootstrap.ts
CHANGED
|
@@ -58,7 +58,10 @@ export function bootstrapKratosTaroApp(options: KratosTaroBootstrapOptions): voi
|
|
|
58
58
|
bootstrapped = true
|
|
59
59
|
syncH5DocumentTitle()
|
|
60
60
|
registerLocaleChangeHandler(initializeAppNavigation)
|
|
61
|
-
registerLocaleChangeHandler(() =>
|
|
61
|
+
registerLocaleChangeHandler(async () => {
|
|
62
|
+
await useSettingStore.getState().loadData()
|
|
63
|
+
await initializeAppNavigation()
|
|
64
|
+
})
|
|
62
65
|
registerLocaleChangeHandler(syncH5DocumentTitle)
|
|
63
66
|
startUserStoreEventBridge()
|
|
64
67
|
registerUserStoreExtension({
|
|
@@ -67,4 +70,7 @@ export function bootstrapKratosTaroApp(options: KratosTaroBootstrapOptions): voi
|
|
|
67
70
|
onSilentLogout: initializeAppNavigation,
|
|
68
71
|
})
|
|
69
72
|
useUserStore.getState().hydrate()
|
|
73
|
+
void useSettingStore.getState().loadData().then(() => initializeAppNavigation()).catch((error) => {
|
|
74
|
+
console.warn('application configuration unavailable', error)
|
|
75
|
+
})
|
|
70
76
|
}
|
package/src/navigation.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { buildMenuTree } from './navigation-tree.mjs'
|
|
|
8
8
|
import { hasValidToken } from './utils/auth'
|
|
9
9
|
import { navigateToLogin } from './utils/navigation'
|
|
10
10
|
import { getCurrentLocale, t } from './locales'
|
|
11
|
+
import { useSettingStore } from './stores'
|
|
11
12
|
|
|
12
13
|
/** 移动菜单访问模式。 */
|
|
13
14
|
export type AppMenuAccess = 'PUBLIC' | 'GUEST_ONLY' | 'AUTHENTICATED'
|
|
@@ -219,9 +220,9 @@ export function setAppNavigationAdapter(nextAdapter: AppNavigationAdapter): void
|
|
|
219
220
|
export async function initializeAppNavigation(): Promise<void> {
|
|
220
221
|
const cacheKey = resolveCacheKey()
|
|
221
222
|
const cached = readCachedMenus(cacheKey)
|
|
222
|
-
useAppNavigation.setState(createNavigationState(cached ?? localizedDefaultAppMenus(), false))
|
|
223
|
+
useAppNavigation.setState(createNavigationState(filterUnavailableMenus(cached ?? localizedDefaultAppMenus()), false))
|
|
223
224
|
try {
|
|
224
|
-
const nextMenus = normalizeMenuResponse(await adapter.list())
|
|
225
|
+
const nextMenus = filterUnavailableMenus(normalizeMenuResponse(await adapter.list()))
|
|
225
226
|
validateMenus(nextMenus)
|
|
226
227
|
Taro.setStorageSync(cacheKey, nextMenus)
|
|
227
228
|
useAppNavigation.setState(createNavigationState(nextMenus, true))
|
|
@@ -231,6 +232,12 @@ export async function initializeAppNavigation(): Promise<void> {
|
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
/** 根据运行时能力过滤不可用的移动端入口。 */
|
|
236
|
+
function filterUnavailableMenus(nextMenus: AppMenu[]): AppMenu[] {
|
|
237
|
+
if (useSettingStore.getState().aiEnabled) return nextMenus
|
|
238
|
+
return nextMenus.filter((menu) => menu.viewKey !== 'AI')
|
|
239
|
+
}
|
|
240
|
+
|
|
234
241
|
/** 使用已经校验的整份配置进行原子切换。 */
|
|
235
242
|
export function installAppNavigation(nextMenus: AppMenu[]): void {
|
|
236
243
|
validateMenus(nextMenus)
|
|
@@ -247,6 +254,7 @@ export function resolveAppRoute(rawRoute: string): ResolvedAppRoute | undefined
|
|
|
247
254
|
if (!params) continue
|
|
248
255
|
const physicalRoute = resolveStaticView(menu.viewKey)
|
|
249
256
|
if (!physicalRoute) return
|
|
257
|
+
if (menu.viewKey === 'AI' && !useSettingStore.getState().aiEnabled) return
|
|
250
258
|
return {
|
|
251
259
|
menu,
|
|
252
260
|
physicalRoute,
|
package/src/stores/setting.ts
CHANGED
|
@@ -12,6 +12,7 @@ const REQUIRED_APP_CONFIGS = [
|
|
|
12
12
|
/** 应用配置状态及操作。 */
|
|
13
13
|
export interface SettingStoreState {
|
|
14
14
|
data?: Map<string, string>
|
|
15
|
+
aiEnabled: boolean
|
|
15
16
|
getData: (key: string) => string | undefined
|
|
16
17
|
loadData: () => Promise<void>
|
|
17
18
|
}
|
|
@@ -21,13 +22,20 @@ let loading: Promise<void> | undefined
|
|
|
21
22
|
/** 应用配置 Zustand Store。 */
|
|
22
23
|
export const useSettingStore = create<SettingStoreState>((set, get) => ({
|
|
23
24
|
data: undefined,
|
|
25
|
+
aiEnabled: false,
|
|
24
26
|
getData(key) {
|
|
25
27
|
return get().data?.get(key)
|
|
26
28
|
},
|
|
27
29
|
async loadData() {
|
|
28
30
|
if (loading) return loading
|
|
29
31
|
loading = (async () => {
|
|
30
|
-
|
|
32
|
+
let response
|
|
33
|
+
try {
|
|
34
|
+
response = await defConfigService.GetConfig({ site: BaseConfigSite.BASE_CONFIG_SITE_APP })
|
|
35
|
+
} catch {
|
|
36
|
+
set({ aiEnabled: false })
|
|
37
|
+
return
|
|
38
|
+
}
|
|
31
39
|
const nextData = new Map(response.configs.map((item) => [item.key, item.value]))
|
|
32
40
|
const missing = REQUIRED_APP_CONFIGS.filter(({ key }) => !nextData.get(key))
|
|
33
41
|
if (missing.length) {
|
|
@@ -37,7 +45,7 @@ export const useSettingStore = create<SettingStoreState>((set, get) => ({
|
|
|
37
45
|
}),
|
|
38
46
|
)
|
|
39
47
|
}
|
|
40
|
-
set({ data: nextData })
|
|
48
|
+
set({ data: nextData, aiEnabled: response.ai_enabled === true })
|
|
41
49
|
})()
|
|
42
50
|
try {
|
|
43
51
|
await loading
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from '../../../navigation'
|
|
9
9
|
import type { BootstrapViewKey } from '../../../module'
|
|
10
10
|
import { useI18n } from '../../../locales'
|
|
11
|
+
import { useSettingStore } from '../../../stores'
|
|
11
12
|
|
|
12
13
|
/** 启动与错误状态页。 */
|
|
13
14
|
export default function StatusPage() {
|
|
@@ -20,17 +21,31 @@ export default function StatusPage() {
|
|
|
20
21
|
setState(nextState)
|
|
21
22
|
setDetail(options?.detail ? decodeURIComponent(options.detail) : '')
|
|
22
23
|
if (options?.bootstrap !== '1') return
|
|
23
|
-
void
|
|
24
|
+
void useSettingStore
|
|
25
|
+
.getState()
|
|
26
|
+
.loadData()
|
|
27
|
+
.catch(() => undefined)
|
|
28
|
+
.then(() => initializeAppNavigation())
|
|
24
29
|
.then(() => {
|
|
25
30
|
navigateAppRoute(options?.route ? decodeURIComponent(options.route) : 'app/home', {
|
|
26
31
|
replace: true,
|
|
27
32
|
})
|
|
28
33
|
})
|
|
29
34
|
.catch((error: unknown) => {
|
|
30
|
-
launchAppStatus('CONFIG_ERROR',
|
|
35
|
+
launchAppStatus('CONFIG_ERROR', resolveErrorMessage(error))
|
|
31
36
|
})
|
|
32
37
|
})
|
|
33
38
|
|
|
34
39
|
const title = state === 'BOOTSTRAP_LOADING' ? t('core.status.loading') : t(`core.status.${state}`)
|
|
35
40
|
return <BootstrapStatus title={title} detail={detail} />
|
|
36
41
|
}
|
|
42
|
+
|
|
43
|
+
/** 将请求错误转换为可展示的文本,避免直接显示 Object。 */
|
|
44
|
+
function resolveErrorMessage(error: unknown): string {
|
|
45
|
+
if (error instanceof Error) return error.message
|
|
46
|
+
if (typeof error === 'string') return error
|
|
47
|
+
if (error && typeof error === 'object' && 'message' in error) {
|
|
48
|
+
return String((error as { message?: unknown }).message || '')
|
|
49
|
+
}
|
|
50
|
+
return ''
|
|
51
|
+
}
|