@liujitcn/kratos-uni-app-core 0.0.81 → 0.0.83
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/module.mjs +28 -69
- package/package.json +1 -1
- package/src/components/KratosEmpty.vue +35 -0
- package/src/components/KratosTabBar.vue +8 -17
- package/src/index.ts +2 -0
- package/src/locales/README.md +1 -1
- package/src/locales/en-US.json +7 -17
- package/src/locales/ja-JP.json +7 -17
- package/src/locales/zh-CN.json +7 -17
- package/src/locales/zh-TW.json +7 -17
- package/src/navigation.ts +42 -16
- package/src/pages.ts +0 -1
- package/src/styles/base.scss +21 -0
- package/src/styles/components.scss +122 -73
- package/src/utils/http.ts +25 -9
- package/src/utils/navigation.ts +36 -5
- package/src/views/pages/index/index.vue +35 -15
- package/src/views/pages/login/login.vue +13 -19
package/src/locales/zh-CN.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"common.action.back": "返回",
|
|
2
3
|
"common.action.cancel": "取消",
|
|
3
4
|
"common.action.confirm": "确定",
|
|
4
5
|
"common.action.delete": "删除",
|
|
@@ -9,16 +10,11 @@
|
|
|
9
10
|
"common.action.save": "保存",
|
|
10
11
|
"common.action.view": "查看",
|
|
11
12
|
"common.field.language": "语言",
|
|
12
|
-
"common.language.en-US": "English",
|
|
13
|
-
"common.language.zh-CN": "简体中文",
|
|
14
|
-
"common.language.zh-TW": "繁体中文",
|
|
15
|
-
"common.language.ja-JP": "日语",
|
|
16
13
|
"common.message.loading": "正在加载",
|
|
17
14
|
"common.message.network_error": "网络错误,换个网络试试",
|
|
18
15
|
"common.message.request_error": "请求错误",
|
|
19
16
|
"common.message.unknown": "暂时无法处理,请稍后重试",
|
|
20
17
|
"common.title.notice": "提示",
|
|
21
|
-
"core.auth.login_again": "重新登录",
|
|
22
18
|
"core.auth.session_expired": "当前页面已失效,请重新登录",
|
|
23
19
|
"core.config.missing": "移动端配置缺失:{names}",
|
|
24
20
|
"core.crypto.base64_decode_unsupported": "当前环境不支持 Base64 解码",
|
|
@@ -33,18 +29,20 @@
|
|
|
33
29
|
"core.password.verify_label": "当前密码",
|
|
34
30
|
"core.file.upload_failed": "上传失败",
|
|
35
31
|
"core.home.account_capability": "账户能力",
|
|
36
|
-
"core.home.account_capability_description": "
|
|
32
|
+
"core.home.account_capability_description": "登录、个人资料、多因素认证与应用设置开箱即用",
|
|
37
33
|
"core.home.cross_platform": "跨端页面",
|
|
38
34
|
"core.home.cross_platform_description": "同一套页面代码适配 H5 和微信小程序",
|
|
39
35
|
"core.home.demo_scope": "功能概览",
|
|
36
|
+
"core.home.dynamic_config": "动态配置",
|
|
37
|
+
"core.home.dynamic_config_description": "首页 Logo 与标语支持后台远程配置",
|
|
40
38
|
"core.home.framework": "应用框架",
|
|
41
39
|
"core.home.language": "开发语言",
|
|
42
40
|
"core.home.main_title": "应用首页",
|
|
41
|
+
"core.home.message_center": "消息中心",
|
|
42
|
+
"core.home.message_center_description": "未读消息统一收纳,红点提醒不错过",
|
|
43
43
|
"core.home.state_management": "状态管理",
|
|
44
|
-
"core.home.static_home": "静态首页",
|
|
45
|
-
"core.home.static_home_description": "当前首页用于展示框架信息,不依赖业务接口",
|
|
46
44
|
"core.home.style_solution": "样式方案",
|
|
47
|
-
"core.home.sub_title": "
|
|
45
|
+
"core.home.sub_title": "账号、消息与智能助手,一站触达",
|
|
48
46
|
"core.home.tech_stack": "当前技术栈",
|
|
49
47
|
"core.login.agree_prefix": "我已阅读并同意",
|
|
50
48
|
"core.login.agree_separator": "和",
|
|
@@ -67,7 +65,6 @@
|
|
|
67
65
|
"core.login.mfa_recovery_code": "恢复码(可选)",
|
|
68
66
|
"core.login.mfa_setup_title": "绑定多因素认证",
|
|
69
67
|
"core.login.mfa_copy_uri": "复制绑定地址",
|
|
70
|
-
"core.login.mfa_copy_success": "绑定地址已复制",
|
|
71
68
|
"core.login.mfa_recovery_codes_copied": "恢复码已复制",
|
|
72
69
|
"core.login.mfa_recovery_codes_title": "保存 MFA 恢复码",
|
|
73
70
|
"core.login.mfa_recovery_codes_warning": "每个恢复码只能使用一次,此弹窗关闭后不会再次显示。",
|
|
@@ -140,14 +137,7 @@
|
|
|
140
137
|
"core.webview.embed_blocked": "当前 H5 页面可能被目标站点限制嵌入",
|
|
141
138
|
"core.webview.invalid_url": "缺少有效链接地址",
|
|
142
139
|
"core.webview.open_failed": "链接无法打开",
|
|
143
|
-
"common.value.top_level": "顶级节点",
|
|
144
|
-
"common.resource.default": "{resource}",
|
|
145
|
-
"common.action.delete_resource": "删除{resource}",
|
|
146
|
-
"common.action.set_field_status": "设置{field}",
|
|
147
140
|
"common.action.load_more": "加载更多",
|
|
148
|
-
"common.status.loading": "加载中…",
|
|
149
|
-
"core.navigation.analytics": "分析",
|
|
150
|
-
"core.navigation.report": "报表",
|
|
151
141
|
"core.settings.theme": "主题外观",
|
|
152
142
|
"core.theme.auto": "跟随系统",
|
|
153
143
|
"core.theme.dark": "暗黑",
|
package/src/locales/zh-TW.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"common.action.back": "返回",
|
|
2
3
|
"common.action.cancel": "取消",
|
|
3
4
|
"common.action.confirm": "確定",
|
|
4
5
|
"common.action.delete": "刪除",
|
|
@@ -9,16 +10,11 @@
|
|
|
9
10
|
"common.action.save": "儲存",
|
|
10
11
|
"common.action.view": "檢視",
|
|
11
12
|
"common.field.language": "語言",
|
|
12
|
-
"common.language.en-US": "English",
|
|
13
|
-
"common.language.zh-CN": "簡體中文",
|
|
14
|
-
"common.language.zh-TW": "繁體中文",
|
|
15
|
-
"common.language.ja-JP": "日語",
|
|
16
13
|
"common.message.loading": "正在載入",
|
|
17
14
|
"common.message.network_error": "網路錯誤,換個網路試試",
|
|
18
15
|
"common.message.request_error": "請求錯誤",
|
|
19
16
|
"common.message.unknown": "暫時無法處理,請稍後重試",
|
|
20
17
|
"common.title.notice": "提示",
|
|
21
|
-
"core.auth.login_again": "重新登入",
|
|
22
18
|
"core.auth.session_expired": "當前頁面已失效,請重新登入",
|
|
23
19
|
"core.config.missing": "移動端配置缺失:{names}",
|
|
24
20
|
"core.crypto.base64_decode_unsupported": "當前環境不支援 Base64 解碼",
|
|
@@ -33,18 +29,20 @@
|
|
|
33
29
|
"core.password.verify_label": "當前密碼",
|
|
34
30
|
"core.file.upload_failed": "上傳失敗",
|
|
35
31
|
"core.home.account_capability": "賬戶能力",
|
|
36
|
-
"core.home.account_capability_description": "
|
|
32
|
+
"core.home.account_capability_description": "登入、個人資料、多因素認證與應用設定開箱即用",
|
|
37
33
|
"core.home.cross_platform": "跨端頁面",
|
|
38
34
|
"core.home.cross_platform_description": "同一套頁面程式碼適配 H5 和微信小程式",
|
|
39
35
|
"core.home.demo_scope": "功能概覽",
|
|
36
|
+
"core.home.dynamic_config": "動態設定",
|
|
37
|
+
"core.home.dynamic_config_description": "首頁 Logo 與標語支援後台遠端設定",
|
|
40
38
|
"core.home.framework": "應用框架",
|
|
41
39
|
"core.home.language": "開發語言",
|
|
42
40
|
"core.home.main_title": "應用首頁",
|
|
41
|
+
"core.home.message_center": "訊息中心",
|
|
42
|
+
"core.home.message_center_description": "未讀訊息統一查看,紅點提醒不錯過",
|
|
43
43
|
"core.home.state_management": "狀態管理",
|
|
44
|
-
"core.home.static_home": "靜態首頁",
|
|
45
|
-
"core.home.static_home_description": "當前首頁用於展示框架資訊,不依賴業務介面",
|
|
46
44
|
"core.home.style_solution": "樣式方案",
|
|
47
|
-
"core.home.sub_title": "
|
|
45
|
+
"core.home.sub_title": "帳號、訊息與智慧助手,一站觸達",
|
|
48
46
|
"core.home.tech_stack": "當前技術棧",
|
|
49
47
|
"core.login.agree_prefix": "我已閱讀並同意",
|
|
50
48
|
"core.login.agree_separator": "和",
|
|
@@ -67,7 +65,6 @@
|
|
|
67
65
|
"core.login.mfa_recovery_code": "恢復碼(可選)",
|
|
68
66
|
"core.login.mfa_setup_title": "綁定多因素認證",
|
|
69
67
|
"core.login.mfa_copy_uri": "複製綁定地址",
|
|
70
|
-
"core.login.mfa_copy_success": "綁定地址已複製",
|
|
71
68
|
"core.login.mfa_recovery_codes_copied": "恢復碼已複製",
|
|
72
69
|
"core.login.mfa_recovery_codes_title": "儲存 MFA 恢復碼",
|
|
73
70
|
"core.login.mfa_recovery_codes_warning": "每個恢復碼只能使用一次,關閉此視窗後不會再次顯示。",
|
|
@@ -140,14 +137,7 @@
|
|
|
140
137
|
"core.webview.embed_blocked": "當前 H5 頁面可能被目標站點限制嵌入",
|
|
141
138
|
"core.webview.invalid_url": "缺少有效連結地址",
|
|
142
139
|
"core.webview.open_failed": "連結無法開啟",
|
|
143
|
-
"common.value.top_level": "頂級節點",
|
|
144
|
-
"common.resource.default": "{resource}",
|
|
145
|
-
"common.action.delete_resource": "刪除{resource}",
|
|
146
|
-
"common.action.set_field_status": "設定{field}",
|
|
147
140
|
"common.action.load_more": "載入更多",
|
|
148
|
-
"common.status.loading": "載入中…",
|
|
149
|
-
"core.navigation.analytics": "分析",
|
|
150
|
-
"core.navigation.report": "報表",
|
|
151
141
|
"core.settings.theme": "主題外觀",
|
|
152
142
|
"core.theme.auto": "跟隨系統",
|
|
153
143
|
"core.theme.dark": "暗黑",
|
package/src/navigation.ts
CHANGED
|
@@ -73,6 +73,16 @@ const createDefaultMenus = (): AppMenu[] => [
|
|
|
73
73
|
icon: 'MESSAGE_DEFAULT',
|
|
74
74
|
selectedIcon: 'MESSAGE_SELECTED',
|
|
75
75
|
},
|
|
76
|
+
{
|
|
77
|
+
id: 99050100,
|
|
78
|
+
parentId: 99040000,
|
|
79
|
+
name: 'AppMessageDetail',
|
|
80
|
+
path: 'app/message/detail',
|
|
81
|
+
viewKey: 'MESSAGE_DETAIL',
|
|
82
|
+
title: '',
|
|
83
|
+
access: 'AUTHENTICATED',
|
|
84
|
+
inTabBar: false,
|
|
85
|
+
},
|
|
76
86
|
{
|
|
77
87
|
id: 99090000,
|
|
78
88
|
parentId: APP_MENU_ROOT_ID,
|
|
@@ -181,8 +191,9 @@ export async function initializeAppNavigation(): Promise<void> {
|
|
|
181
191
|
const cached = readCachedMenus(cacheKey)
|
|
182
192
|
menus.value = filterUnavailableMenus(cached ?? createDefaultMenus())
|
|
183
193
|
try {
|
|
184
|
-
const nextMenus =
|
|
185
|
-
|
|
194
|
+
const nextMenus = validateMenus(
|
|
195
|
+
filterUnavailableMenus(normalizeMenuResponse(await adapter.list())),
|
|
196
|
+
)
|
|
186
197
|
uni.setStorageSync(cacheKey, nextMenus)
|
|
187
198
|
menus.value = nextMenus
|
|
188
199
|
} catch (error) {
|
|
@@ -202,8 +213,7 @@ function filterUnavailableMenus(nextMenus: AppMenu[]): AppMenu[] {
|
|
|
202
213
|
|
|
203
214
|
/** 使用已经校验的整份配置进行原子切换。 */
|
|
204
215
|
export function installAppNavigation(nextMenus: AppMenu[]): void {
|
|
205
|
-
validateMenus(nextMenus)
|
|
206
|
-
const snapshot = nextMenus.map((menu) => ({ ...menu }))
|
|
216
|
+
const snapshot = validateMenus(nextMenus).map((menu) => ({ ...menu }))
|
|
207
217
|
uni.setStorageSync(resolveCacheKey(), snapshot)
|
|
208
218
|
menus.value = snapshot
|
|
209
219
|
ready.value = true
|
|
@@ -394,9 +404,16 @@ function readCachedMenus(cacheKey: string): AppMenu[] | undefined {
|
|
|
394
404
|
const cached = uni.getStorageSync(cacheKey) as unknown
|
|
395
405
|
if (!Array.isArray(cached)) return
|
|
396
406
|
try {
|
|
397
|
-
const cachedMenus = cached as AppMenu[]
|
|
398
|
-
|
|
399
|
-
|
|
407
|
+
const cachedMenus = (cached as AppMenu[]).map((menu) => ({
|
|
408
|
+
...menu,
|
|
409
|
+
title:
|
|
410
|
+
menu.viewKey === 'HOME'
|
|
411
|
+
? t('core.navigation.home')
|
|
412
|
+
: menu.viewKey === 'MESSAGE_INBOX'
|
|
413
|
+
? t('core.navigation.message')
|
|
414
|
+
: menu.title,
|
|
415
|
+
}))
|
|
416
|
+
return validateMenus(cachedMenus)
|
|
400
417
|
} catch {
|
|
401
418
|
uni.removeStorageSync(cacheKey)
|
|
402
419
|
}
|
|
@@ -415,7 +432,12 @@ function normalizeMenu(item: BaseMenu): AppMenu {
|
|
|
415
432
|
name: item.name,
|
|
416
433
|
path: item.path,
|
|
417
434
|
viewKey: app?.view_key ?? '',
|
|
418
|
-
title:
|
|
435
|
+
title:
|
|
436
|
+
app?.view_key === 'HOME'
|
|
437
|
+
? t('core.navigation.home')
|
|
438
|
+
: app?.view_key === 'MESSAGE_INBOX'
|
|
439
|
+
? t('core.navigation.message')
|
|
440
|
+
: (meta?.title ?? ''),
|
|
419
441
|
access: (app?.access ?? 'AUTHENTICATED') as AppMenuAccess,
|
|
420
442
|
inTabBar: app?.in_tab_bar ?? false,
|
|
421
443
|
icon: meta?.icon,
|
|
@@ -423,11 +445,17 @@ function normalizeMenu(item: BaseMenu): AppMenu {
|
|
|
423
445
|
}
|
|
424
446
|
}
|
|
425
447
|
|
|
426
|
-
function validateMenus(nextMenus: AppMenu[]):
|
|
448
|
+
function validateMenus(nextMenus: AppMenu[]): AppMenu[] {
|
|
449
|
+
// 多端共用后端时菜单可能携带本应用未注册的视图键,过滤跳过而不是让整份菜单失效。
|
|
450
|
+
const knownMenus = nextMenus.filter((menu) => {
|
|
451
|
+
if (resolveStaticView(menu.viewKey)) return true
|
|
452
|
+
console.warn(t('core.navigation.error.view_key', { viewKey: menu.viewKey }))
|
|
453
|
+
return false
|
|
454
|
+
})
|
|
427
455
|
const ids = new Set<number>()
|
|
428
456
|
const names = new Set<string>()
|
|
429
457
|
const paths = new Set<string>()
|
|
430
|
-
for (const menu of
|
|
458
|
+
for (const menu of knownMenus) {
|
|
431
459
|
if (!Number.isSafeInteger(menu.id) || !menu.name || !menu.path.startsWith('app/')) {
|
|
432
460
|
throw new Error(t('core.navigation.error.identity'))
|
|
433
461
|
}
|
|
@@ -437,9 +465,6 @@ function validateMenus(nextMenus: AppMenu[]): void {
|
|
|
437
465
|
if (!['PUBLIC', 'GUEST_ONLY', 'AUTHENTICATED'].includes(menu.access)) {
|
|
438
466
|
throw new Error(t('core.navigation.error.access', { access: menu.access }))
|
|
439
467
|
}
|
|
440
|
-
if (!resolveStaticView(menu.viewKey)) {
|
|
441
|
-
throw new Error(t('core.navigation.error.view_key', { viewKey: menu.viewKey }))
|
|
442
|
-
}
|
|
443
468
|
if (ids.has(menu.id) || names.has(menu.name) || paths.has(menu.path)) {
|
|
444
469
|
throw new Error(t('core.navigation.error.unique'))
|
|
445
470
|
}
|
|
@@ -447,8 +472,8 @@ function validateMenus(nextMenus: AppMenu[]): void {
|
|
|
447
472
|
names.add(menu.name)
|
|
448
473
|
paths.add(menu.path)
|
|
449
474
|
}
|
|
450
|
-
const menuMap = new Map(
|
|
451
|
-
for (const menu of
|
|
475
|
+
const menuMap = new Map(knownMenus.map((menu) => [menu.id, menu]))
|
|
476
|
+
for (const menu of knownMenus) {
|
|
452
477
|
if (menu.parentId === undefined) {
|
|
453
478
|
throw new Error(t('core.navigation.error.parent_missing', { name: menu.name }))
|
|
454
479
|
}
|
|
@@ -471,6 +496,7 @@ function validateMenus(nextMenus: AppMenu[]): void {
|
|
|
471
496
|
parentId = parent.parentId
|
|
472
497
|
}
|
|
473
498
|
}
|
|
474
|
-
const tabCount =
|
|
499
|
+
const tabCount = knownMenus.filter((menu) => menu.parentId === APP_MENU_ROOT_ID).length
|
|
475
500
|
if (tabCount === 1 || tabCount > 5) throw new Error(t('core.navigation.error.tab_count'))
|
|
501
|
+
return knownMenus
|
|
476
502
|
}
|
package/src/pages.ts
CHANGED
package/src/styles/base.scss
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
@use './theme.scss';
|
|
2
2
|
@use './components.scss';
|
|
3
3
|
|
|
4
|
+
page,
|
|
5
|
+
body,
|
|
6
|
+
uni-page-body {
|
|
7
|
+
font-family:
|
|
8
|
+
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
|
|
9
|
+
'Microsoft YaHei', sans-serif;
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
view,
|
|
5
13
|
navigator,
|
|
6
14
|
input,
|
|
@@ -97,3 +105,16 @@ html.theme-light .uni-input-input:-webkit-autofill {
|
|
|
97
105
|
caret-color: #102232;
|
|
98
106
|
}
|
|
99
107
|
/* #endif */
|
|
108
|
+
|
|
109
|
+
/* H5 隐藏滚动条但保留滚动能力,视觉对齐小程序;小程序端滚动条本就不存在,无副作用。 */
|
|
110
|
+
/* #ifdef H5 */
|
|
111
|
+
::-webkit-scrollbar {
|
|
112
|
+
width: 0;
|
|
113
|
+
height: 0;
|
|
114
|
+
display: none;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
* {
|
|
118
|
+
scrollbar-width: none;
|
|
119
|
+
}
|
|
120
|
+
/* #endif */
|