@liujitcn/kratos-taro-app-core 0.0.78 → 0.0.80
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/dist/build.mjs +4 -2
- package/package.json +1 -1
- package/src/components/BootstrapStatus.scss +3 -3
- package/src/components/BootstrapStatus.tsx +3 -1
- package/src/components/KratosTabBar.scss +32 -13
- package/src/components/KratosTabBar.tsx +34 -3
- package/src/components/MfaRecoveryCodesDialog.scss +11 -10
- package/src/components/MfaSetupPanel.scss +4 -4
- package/src/components/PasswordVerifyDialog.scss +21 -21
- package/src/navigation.ts +6 -3
- package/src/pages.ts +4 -2
- package/src/rpc/base/v1/config.ts +1 -1
- package/src/rpc/base/v1/file.ts +1 -1
- package/src/rpc/base/v1/language.ts +1 -1
- package/src/rpc/base/v1/login.ts +1 -1
- package/src/rpc/base/v1/mcp.ts +1 -1
- package/src/rpc/base/v1/mfa.ts +1 -1
- package/src/rpc/base/v1/oauth.ts +1 -1
- package/src/rpc/base/v1/secret_crypto.ts +1 -1
- package/src/rpc/base/v1/sse.ts +1 -1
- package/src/rpc/common/v1/common.ts +1 -1
- package/src/rpc/common/v1/types.ts +1 -1
- package/src/rpc/google/protobuf/empty.ts +1 -1
- package/src/rpc/google/protobuf/struct.ts +2 -2
- package/src/rpc/google/protobuf/wrappers.ts +1 -1
- package/src/rpc/system/app/v1/auth.ts +1 -1
- package/src/rpc/system/app/v1/base_area.ts +1 -1
- package/src/rpc/system/app/v1/base_dict.ts +1 -1
- package/src/rpc/system/app/v1/base_menu.ts +1 -1
- package/src/rpc/system/common/v1/common.ts +1 -1
- package/src/stores/index.ts +1 -0
- package/src/stores/theme.ts +108 -0
- package/src/styles/base.scss +90 -5
- package/src/styles/components.scss +765 -0
- package/src/utils/http.ts +3 -0
- package/src/utils/index.ts +19 -0
- package/src/utils/navigation.ts +12 -0
- package/src/views/pages/index/index.scss +69 -73
- package/src/views/pages/index/index.tsx +50 -34
- package/src/views/pages/login/login.scss +109 -142
- package/src/views/pages/login/login.tsx +142 -82
- package/src/views/pages/login/protocal.scss +14 -14
- package/src/views/pages/login/protocal.tsx +16 -3
- package/src/views/pages/webview/webview.scss +6 -5
- package/src/views/pages/webview/webview.tsx +3 -1
package/src/utils/http.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from './auth'
|
|
12
12
|
import { saveCurrentRoute } from './navigation'
|
|
13
13
|
import { getLocaleRequestHeaders, t } from '../locales'
|
|
14
|
+
import { useThemeStore } from '../stores/theme'
|
|
14
15
|
|
|
15
16
|
const apiBasePath = process.env.VITE_APP_BASE_API || '/api'
|
|
16
17
|
const apiTargetUrl = process.env.VITE_APP_API_URL || ''
|
|
@@ -265,11 +266,13 @@ async function promptRelogin(): Promise<void> {
|
|
|
265
266
|
if (isPromptingRelogin) return
|
|
266
267
|
isPromptingRelogin = true
|
|
267
268
|
try {
|
|
269
|
+
const theme = useThemeStore.getState().theme
|
|
268
270
|
const modal = await Taro.showModal({
|
|
269
271
|
title: t('common.title.notice'),
|
|
270
272
|
content: t('core.auth.session_expired'),
|
|
271
273
|
showCancel: false,
|
|
272
274
|
confirmText: t('core.auth.login_again'),
|
|
275
|
+
confirmColor: theme === 'light' ? '#039e8c' : '#28f0d4',
|
|
273
276
|
})
|
|
274
277
|
if (!modal.confirm) return
|
|
275
278
|
await new Promise((resolve) => setTimeout(resolve, 80))
|
package/src/utils/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import Taro from '@tarojs/taro'
|
|
2
|
+
|
|
1
3
|
const configuredStaticUrl =
|
|
2
4
|
process.env.VITE_APP_STATIC_URL || process.env.VITE_APP_API_URL || ''
|
|
3
5
|
|
|
@@ -44,3 +46,20 @@ export function formatSrc(src: string): string {
|
|
|
44
46
|
? `${staticOrigin}${src}`
|
|
45
47
|
: `${staticOrigin}/${src.replace(/^\/+/, '')}`
|
|
46
48
|
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 微信小程序原生胶囊按钮(右上角 ⋯ / ◯)右侧避让宽度(px)。
|
|
52
|
+
* 自定义导航栏(navigationStyle: 'custom')在 weapp 下仍会显示原生胶囊,
|
|
53
|
+
* 页头右侧若放置可交互图标/按钮需预留该宽度,避免与胶囊重叠;
|
|
54
|
+
* 非 weapp 平台返回 0,无需特殊处理。
|
|
55
|
+
*/
|
|
56
|
+
export function getMpCapsuleRightGap(): number {
|
|
57
|
+
if (process.env.TARO_ENV !== 'weapp') return 0
|
|
58
|
+
try {
|
|
59
|
+
const menu = Taro.getMenuButtonBoundingClientRect()
|
|
60
|
+
const { windowWidth } = Taro.getSystemInfoSync()
|
|
61
|
+
return Math.max(0, Math.round(windowWidth - menu.left + 12))
|
|
62
|
+
} catch {
|
|
63
|
+
return 0
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/utils/navigation.ts
CHANGED
|
@@ -80,6 +80,18 @@ export function navigateToLogin(redirectUrl?: string): void {
|
|
|
80
80
|
})
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
/** 跳转登录页并替换当前页面:路由守卫使用,避免反复拦截时在页面栈堆积登录页。 */
|
|
84
|
+
export function redirectToLogin(redirectUrl?: string): void {
|
|
85
|
+
if (typeof redirectUrl === 'string' && redirectUrl) saveLoginRedirectUrl(redirectUrl)
|
|
86
|
+
else saveCurrentRoute()
|
|
87
|
+
void Taro.redirectTo({
|
|
88
|
+
url: LOGIN_PAGE,
|
|
89
|
+
fail: () => {
|
|
90
|
+
void Taro.reLaunch({ url: LOGIN_PAGE })
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
83
95
|
/** 返回首页。 */
|
|
84
96
|
export function switchTabToHome(): Promise<TaroGeneral.CallbackResult> {
|
|
85
97
|
return Taro.reLaunch({ url: homeTabPage })
|
|
@@ -1,122 +1,118 @@
|
|
|
1
|
+
page {
|
|
2
|
+
background-color: #eef3f8;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
.home-page {
|
|
6
|
+
position: relative;
|
|
2
7
|
min-height: 100vh;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
overflow: hidden;
|
|
9
|
+
background: var(--kratos-bg-gradient);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.home-page--weapp .home-content {
|
|
13
|
+
/* 44PX 是系统导航栏高度,88px 按设计稿转换为 44 物理像素。 */
|
|
14
|
+
padding-top: calc(44PX + 88px);
|
|
6
15
|
}
|
|
7
16
|
|
|
8
|
-
.home-
|
|
9
|
-
|
|
17
|
+
.home-content {
|
|
18
|
+
position: relative;
|
|
19
|
+
z-index: 1;
|
|
20
|
+
padding: calc(env(safe-area-inset-top) + 20px) 32px 220px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.home-top {
|
|
24
|
+
padding: 8px 4px 24px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* 页面大标题 */
|
|
28
|
+
.home-top__title {
|
|
29
|
+
margin-top: 14px;
|
|
30
|
+
color: var(--kratos-color-text);
|
|
31
|
+
font-size: 44px;
|
|
32
|
+
font-weight: 800;
|
|
33
|
+
letter-spacing: -0.5px;
|
|
10
34
|
}
|
|
11
35
|
|
|
12
36
|
.home-hero {
|
|
37
|
+
padding: 40px 36px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.home-hero__main {
|
|
13
41
|
display: flex;
|
|
14
42
|
align-items: center;
|
|
15
|
-
padding: 34px 28px;
|
|
16
|
-
border-radius: 12px;
|
|
17
|
-
background-color: #27ba9b;
|
|
18
|
-
box-shadow: 0 8px 18px rgba(39, 186, 155, 0.18);
|
|
19
43
|
}
|
|
20
44
|
|
|
45
|
+
/* 简洁 Logo:圆角方块 + 细描边 */
|
|
21
46
|
.home-logo {
|
|
22
47
|
flex: 0 0 auto;
|
|
23
|
-
width:
|
|
24
|
-
height:
|
|
25
|
-
border-radius:
|
|
26
|
-
|
|
48
|
+
width: 104px;
|
|
49
|
+
height: 104px;
|
|
50
|
+
border-radius: 26px;
|
|
51
|
+
border: 1PX solid var(--kratos-color-border-accent);
|
|
52
|
+
background: var(--kratos-color-surface-2);
|
|
27
53
|
}
|
|
28
54
|
|
|
29
55
|
.home-hero__copy {
|
|
30
56
|
min-width: 0;
|
|
31
|
-
margin-left:
|
|
57
|
+
margin-left: 26px;
|
|
32
58
|
}
|
|
33
59
|
|
|
34
|
-
.home-title,
|
|
35
60
|
.home-subtitle {
|
|
36
61
|
display: block;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
margin-top: 8px;
|
|
41
|
-
color: #fff;
|
|
42
|
-
font-size: 40px;
|
|
43
|
-
font-weight: 600;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.home-subtitle {
|
|
47
|
-
margin-top: 10px;
|
|
48
|
-
color: rgba(255, 255, 255, 0.86);
|
|
49
|
-
font-size: 24px;
|
|
62
|
+
color: var(--kratos-color-text-muted);
|
|
63
|
+
font-size: 26px;
|
|
64
|
+
line-height: 1.6;
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
.home-section {
|
|
53
|
-
margin-top:
|
|
68
|
+
margin-top: 36px;
|
|
54
69
|
}
|
|
55
70
|
|
|
56
71
|
.home-section__title {
|
|
57
72
|
display: block;
|
|
58
|
-
margin: 0
|
|
59
|
-
color:
|
|
60
|
-
font-size:
|
|
61
|
-
font-weight:
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.home-info-list,
|
|
65
|
-
.home-demo-list {
|
|
66
|
-
overflow: hidden;
|
|
67
|
-
border-radius: 10px;
|
|
68
|
-
background-color: #fff;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.home-info-row {
|
|
72
|
-
display: flex;
|
|
73
|
-
align-items: center;
|
|
74
|
-
justify-content: space-between;
|
|
75
|
-
padding: 26px 24px;
|
|
76
|
-
border-bottom: 1px solid #edf1ef;
|
|
77
|
-
|
|
78
|
-
&:last-child {
|
|
79
|
-
border-bottom: 0;
|
|
80
|
-
}
|
|
73
|
+
margin: 0 4px 16px;
|
|
74
|
+
color: var(--kratos-color-text-muted);
|
|
75
|
+
font-size: 26px;
|
|
76
|
+
font-weight: 700;
|
|
81
77
|
}
|
|
82
78
|
|
|
83
|
-
.home-info-
|
|
84
|
-
|
|
85
|
-
font-size: 26px;
|
|
79
|
+
.home-info-list {
|
|
80
|
+
padding: 8px 28px;
|
|
86
81
|
}
|
|
87
82
|
|
|
88
|
-
.home-
|
|
89
|
-
|
|
90
|
-
font-size: 26px;
|
|
91
|
-
font-weight: 500;
|
|
83
|
+
.home-demo-list {
|
|
84
|
+
padding: 10px 28px;
|
|
92
85
|
}
|
|
93
86
|
|
|
94
87
|
.home-demo-item {
|
|
95
88
|
display: flex;
|
|
96
89
|
align-items: flex-start;
|
|
97
|
-
padding:
|
|
98
|
-
border-
|
|
90
|
+
padding: 28px 0;
|
|
91
|
+
border-top: 1PX solid var(--kratos-color-border);
|
|
99
92
|
|
|
100
|
-
&:
|
|
101
|
-
border-
|
|
93
|
+
&:first-child {
|
|
94
|
+
border-top: 0;
|
|
102
95
|
}
|
|
103
96
|
}
|
|
104
97
|
|
|
105
98
|
.home-demo-dot {
|
|
106
99
|
flex: 0 0 auto;
|
|
107
|
-
width:
|
|
108
|
-
height:
|
|
109
|
-
border-radius:
|
|
110
|
-
background-color
|
|
111
|
-
|
|
100
|
+
width: 48px;
|
|
101
|
+
height: 48px;
|
|
102
|
+
border-radius: 14px;
|
|
103
|
+
background: var(--kratos-color-primary-soft);
|
|
104
|
+
border: 1PX solid var(--kratos-color-primary-edge);
|
|
105
|
+
color: var(--kratos-color-primary);
|
|
112
106
|
font-size: 24px;
|
|
113
|
-
|
|
107
|
+
font-family: var(--kratos-font-mono);
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
line-height: 46px;
|
|
114
110
|
text-align: center;
|
|
115
111
|
}
|
|
116
112
|
|
|
117
113
|
.home-demo-copy {
|
|
118
114
|
min-width: 0;
|
|
119
|
-
margin-left:
|
|
115
|
+
margin-left: 22px;
|
|
120
116
|
}
|
|
121
117
|
|
|
122
118
|
.home-demo-title,
|
|
@@ -125,14 +121,14 @@
|
|
|
125
121
|
}
|
|
126
122
|
|
|
127
123
|
.home-demo-title {
|
|
128
|
-
color:
|
|
124
|
+
color: var(--kratos-color-text);
|
|
129
125
|
font-size: 28px;
|
|
130
|
-
font-weight:
|
|
126
|
+
font-weight: 600;
|
|
131
127
|
}
|
|
132
128
|
|
|
133
129
|
.home-demo-desc {
|
|
134
130
|
margin-top: 8px;
|
|
135
|
-
color:
|
|
131
|
+
color: var(--kratos-color-text-muted);
|
|
136
132
|
font-size: 24px;
|
|
137
133
|
line-height: 1.5;
|
|
138
134
|
}
|
|
@@ -2,7 +2,7 @@ import { Image, Text, View } from '@tarojs/components'
|
|
|
2
2
|
import { useLoad } from '@tarojs/taro'
|
|
3
3
|
import { useEffect, useState } from 'react'
|
|
4
4
|
import defaultLogo from '@liujitcn/kratos-taro-app-core/static/images/logo_icon.png'
|
|
5
|
-
import { useSettingStore } from '../../../stores'
|
|
5
|
+
import { useSettingStore, useThemeStore } from '../../../stores'
|
|
6
6
|
import { formatSrc } from '../../../utils'
|
|
7
7
|
import './index.scss'
|
|
8
8
|
import { useI18n } from '../../../locales'
|
|
@@ -10,6 +10,7 @@ import { useI18n } from '../../../locales'
|
|
|
10
10
|
/** 应用首页。 */
|
|
11
11
|
export default function HomePage() {
|
|
12
12
|
const { t } = useI18n()
|
|
13
|
+
const themeStore = useThemeStore()
|
|
13
14
|
const settings = useSettingStore((state) => state.data)
|
|
14
15
|
const loadData = useSettingStore((state) => state.loadData)
|
|
15
16
|
const mainTitle = settings?.get('mainTitle') || t('core.home.main_title')
|
|
@@ -37,46 +38,61 @@ export default function HomePage() {
|
|
|
37
38
|
[t('core.home.account_capability'), t('core.home.account_capability_description')],
|
|
38
39
|
[t('core.home.static_home'), t('core.home.static_home_description')],
|
|
39
40
|
]
|
|
40
|
-
|
|
41
41
|
return (
|
|
42
|
-
<View
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<Text className='home-title'>{mainTitle}</Text>
|
|
52
|
-
<Text className='home-subtitle'>{subTitle}</Text>
|
|
42
|
+
<View
|
|
43
|
+
className={`home-page${process.env.TARO_ENV === 'weapp' ? ' home-page--weapp' : ''} ${
|
|
44
|
+
themeStore.theme === 'light' ? 'theme-light' : 'theme-dark'
|
|
45
|
+
}`}
|
|
46
|
+
>
|
|
47
|
+
<View className='k-grid-bg' aria-hidden />
|
|
48
|
+
<View className='home-content'>
|
|
49
|
+
<View className='home-top'>
|
|
50
|
+
<View className='home-top__title'>{mainTitle}</View>
|
|
53
51
|
</View>
|
|
54
|
-
</View>
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
<View className='k-glass k-glass--lit home-hero'>
|
|
54
|
+
<View className='k-cnr k-cnr--tl' aria-hidden />
|
|
55
|
+
<View className='k-cnr k-cnr--tr' aria-hidden />
|
|
56
|
+
<View className='k-cnr k-cnr--bl' aria-hidden />
|
|
57
|
+
<View className='k-cnr k-cnr--br' aria-hidden />
|
|
58
|
+
<View className='home-hero__main'>
|
|
59
|
+
<Image
|
|
60
|
+
className='home-logo'
|
|
61
|
+
src={appLogo}
|
|
62
|
+
mode='aspectFit'
|
|
63
|
+
onError={() => setAppLogo(defaultLogo)}
|
|
64
|
+
/>
|
|
65
|
+
<View className='home-hero__copy'>
|
|
66
|
+
<Text className='home-subtitle'>{subTitle}</Text>
|
|
63
67
|
</View>
|
|
64
|
-
|
|
68
|
+
</View>
|
|
65
69
|
</View>
|
|
66
|
-
</View>
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<Text className='home-demo-title'>{title}</Text>
|
|
76
|
-
<Text className='home-demo-desc'>{description}</Text>
|
|
71
|
+
<View className='home-section'>
|
|
72
|
+
<Text className='home-section__title'>{t('core.home.tech_stack')}</Text>
|
|
73
|
+
<View className='k-glass home-info-list'>
|
|
74
|
+
{stack.map(([label, value]) => (
|
|
75
|
+
<View className='k-field' key={label}>
|
|
76
|
+
<Text className='k-field__k'>{label}</Text>
|
|
77
|
+
<Text className='k-field__v'>{value}</Text>
|
|
77
78
|
</View>
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
))}
|
|
80
|
+
</View>
|
|
81
|
+
</View>
|
|
82
|
+
|
|
83
|
+
<View className='home-section'>
|
|
84
|
+
<Text className='home-section__title'>{t('core.home.demo_scope')}</Text>
|
|
85
|
+
<View className='k-glass home-demo-list'>
|
|
86
|
+
{demos.map(([title, description], index) => (
|
|
87
|
+
<View className='home-demo-item' key={title}>
|
|
88
|
+
<View className='home-demo-dot'>{index + 1}</View>
|
|
89
|
+
<View className='home-demo-copy'>
|
|
90
|
+
<Text className='home-demo-title'>{title}</Text>
|
|
91
|
+
<Text className='home-demo-desc'>{description}</Text>
|
|
92
|
+
</View>
|
|
93
|
+
</View>
|
|
94
|
+
))}
|
|
95
|
+
</View>
|
|
80
96
|
</View>
|
|
81
97
|
</View>
|
|
82
98
|
</View>
|