@liujitcn/kratos-taro-app-core 0.0.42 → 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/README.md +2 -0
- package/dist/runner.mjs +1 -1
- 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/runner.ts +1 -1
- package/src/stores/setting.ts +10 -2
- package/src/views/pages/status/index.tsx +17 -2
package/README.md
CHANGED
|
@@ -39,3 +39,5 @@ pnpm --filter @liujitcn/kratos-taro-app-core tsc
|
|
|
39
39
|
pnpm test
|
|
40
40
|
pnpm check:exports
|
|
41
41
|
```
|
|
42
|
+
|
|
43
|
+
构建产物按模式与平台隔离:开发使用 `dist/dev/h5`、`dist/dev/mp-weixin`,生产默认使用 `dist/build/h5`、`dist/build/mp-weixin`。`KRATOS_TARO_OUTPUT_ROOT` 可覆盖默认目录;仓库宿主及 Kratos 配套项目的 H5 生产构建输出到 `backend/data/taro-app`。微信开发者工具默认指向开发目录,发布时导入生产目录。
|
package/dist/runner.mjs
CHANGED
|
@@ -84,7 +84,7 @@ async function main() {
|
|
|
84
84
|
env: {
|
|
85
85
|
...process.env,
|
|
86
86
|
NODE_ENV: options.mode === "development" ? "development" : "production",
|
|
87
|
-
KRATOS_TARO_OUTPUT_ROOT: process.env.KRATOS_TARO_OUTPUT_ROOT ||
|
|
87
|
+
KRATOS_TARO_OUTPUT_ROOT: process.env.KRATOS_TARO_OUTPUT_ROOT || `dist/${options.mode === "development" ? "dev" : "build"}/${options.type === "h5" ? "h5" : "mp-weixin"}`
|
|
88
88
|
},
|
|
89
89
|
stdio: "inherit"
|
|
90
90
|
});
|
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/runner.ts
CHANGED
|
@@ -128,7 +128,7 @@ async function main(): Promise<void> {
|
|
|
128
128
|
NODE_ENV: options.mode === 'development' ? 'development' : 'production',
|
|
129
129
|
KRATOS_TARO_OUTPUT_ROOT:
|
|
130
130
|
process.env.KRATOS_TARO_OUTPUT_ROOT ||
|
|
131
|
-
|
|
131
|
+
`dist/${options.mode === 'development' ? 'dev' : 'build'}/${options.type === 'h5' ? 'h5' : 'mp-weixin'}`,
|
|
132
132
|
},
|
|
133
133
|
stdio: 'inherit',
|
|
134
134
|
})
|
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
|
+
}
|