@liujitcn/kratos-taro-app-core 0.0.21 → 0.0.23

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.
@@ -6,10 +6,8 @@
6
6
  "common.action.login": "登入",
7
7
  "common.action.logout": "退出登入",
8
8
  "common.action.new": "新建",
9
- "common.action.openInNewWindow": "新視窗開啟",
10
- "common.action.retry": "重試",
9
+ "common.action.open_in_new_window": "新視窗開啟",
11
10
  "common.action.save": "儲存",
12
- "common.action.search": "搜尋",
13
11
  "common.field.language": "語言",
14
12
  "common.language.en-US": "English",
15
13
  "common.language.ja-JP": "日本語",
@@ -19,95 +17,92 @@
19
17
  "common.language.fr-FR": "法語",
20
18
  "common.language.es-ES": "西班牙語",
21
19
  "common.message.loading": "正在載入",
22
- "common.message.networkError": "網路錯誤,換個網路試試",
23
- "common.message.requestError": "請求錯誤",
20
+ "common.message.network_error": "網路錯誤,換個網路試試",
21
+ "common.message.request_error": "請求錯誤",
24
22
  "common.message.unknown": "暫時無法處理,請稍後重試",
25
23
  "common.title.notice": "提示",
26
- "core.auth.loginAgain": "重新登入",
27
- "core.auth.sessionExpired": "當前頁面已失效,請重新登入",
24
+ "core.auth.login_again": "重新登入",
25
+ "core.auth.session_expired": "當前頁面已失效,請重新登入",
28
26
  "core.config.missing": "移動端配置缺失:{names}",
29
- "core.crypto.base64DecodeUnsupported": "當前環境不支援 Base64 解碼",
30
- "core.crypto.base64EncodeUnsupported": "當前環境不支援 Base64 編碼",
31
- "core.crypto.encryptFailed": "密碼加密失敗",
32
- "core.crypto.passwordRequired": "密碼不能為空",
33
- "core.crypto.passwordTooLong": "密碼長度超出限制",
34
- "core.crypto.publicKeyInvalid": "公鑰格式無效",
35
- "core.crypto.randomFailed": "隨機數生成失敗",
36
- "core.crypto.unsupported": "當前環境不支援密碼加密",
37
- "core.file.downloadFailed": "下載失敗",
38
- "core.file.temporaryPathRequired": "小程式端請使用檔案臨時路徑上傳",
39
- "core.file.uploadFailed": "上傳失敗",
40
- "core.home.accountCapability": "賬戶能力",
41
- "core.home.accountCapabilityDescription": "個人資料、應用設定與智慧助手入口已保留",
42
- "core.home.crossPlatform": "跨端頁面",
43
- "core.home.crossPlatformDescription": "同一套頁面程式碼適配 H5 和微信小程式",
44
- "core.home.demoScope": "演示範圍",
27
+ "core.crypto.base64_decode_unsupported": "當前環境不支援 Base64 解碼",
28
+ "core.crypto.base64_encode_unsupported": "當前環境不支援 Base64 編碼",
29
+ "core.crypto.encrypt_failed": "密碼加密失敗",
30
+ "core.crypto.password_required": "密碼不能為空",
31
+ "core.crypto.password_too_long": "密碼長度超出限制",
32
+ "core.crypto.public_key_invalid": "公鑰格式無效",
33
+ "core.file.download_failed": "下載失敗",
34
+ "core.file.temporary_path_required": "小程式端請使用檔案臨時路徑上傳",
35
+ "core.file.upload_failed": "上傳失敗",
36
+ "core.home.account_capability": "賬戶能力",
37
+ "core.home.account_capability_description": "個人資料、應用設定與智慧助手入口已保留",
38
+ "core.home.cross_platform": "跨端頁面",
39
+ "core.home.cross_platform_description": "同一套頁面程式碼適配 H5 和微信小程式",
40
+ "core.home.demo_scope": "演示範圍",
45
41
  "core.home.framework": "應用框架",
46
42
  "core.home.language": "開發語言",
47
- "core.home.mainTitle": "應用框架示例",
48
- "core.home.stateManagement": "狀態管理",
49
- "core.home.staticHome": "靜態首頁",
50
- "core.home.staticHomeDescription": "當前首頁用於展示框架資訊,不依賴業務介面",
51
- "core.home.styleSolution": "樣式方案",
52
- "core.home.subTitle": "保留通用導航與個人中心體驗",
53
- "core.home.techStack": "當前技術棧",
54
- "core.login.agreePrefix": "我已閱讀並同意",
55
- "core.login.agreeSeparator": "和",
56
- "core.login.behaviorClick": "請按順序點選文字",
57
- "core.login.behaviorLoading": "載入中...",
58
- "core.login.behaviorPuzzle": "請拖動滑塊完成拼圖",
59
- "core.login.behaviorRotate": "拖動滑塊,將內圈圖片轉正",
60
- "core.login.bindWechat": "登入並繫結微信",
43
+ "core.home.main_title": "應用框架示例",
44
+ "core.home.state_management": "狀態管理",
45
+ "core.home.static_home": "靜態首頁",
46
+ "core.home.static_home_description": "當前首頁用於展示框架資訊,不依賴業務介面",
47
+ "core.home.style_solution": "樣式方案",
48
+ "core.home.sub_title": "保留通用導航與個人中心體驗",
49
+ "core.home.tech_stack": "當前技術棧",
50
+ "core.login.agree_prefix": "我已閱讀並同意",
51
+ "core.login.agree_separator": "和",
52
+ "core.login.behavior_click": "請按順序點選文字",
53
+ "core.login.behavior_loading": "載入中...",
54
+ "core.login.behavior_puzzle": "請拖動滑塊完成拼圖",
55
+ "core.login.behavior_rotate": "拖動滑塊,將內圈圖片轉正",
56
+ "core.login.bind_wechat": "登入並繫結微信",
61
57
  "core.login.captcha": "請輸入驗證碼",
62
- "core.login.captchaLoadFailed": "驗證碼載入失敗",
63
- "core.login.captchaTypeMissing": "登入驗證碼型別未配置",
64
- "core.login.captchaTypeName": "登入驗證碼型別",
65
- "core.login.captchaTypeResponseMissing": "驗證碼介面未返回型別",
66
- "core.login.captchaWriteFailed": "驗證碼圖片寫入失敗",
67
- "core.login.defaultSubTitle": "歡迎使用本應用",
68
- "core.login.loginFailed": "登入失敗,請重試",
69
- "core.login.loginSuccess": "登入成功",
58
+ "core.login.captcha_load_failed": "驗證碼載入失敗",
59
+ "core.login.captcha_type_missing": "登入驗證碼型別未配置",
60
+ "core.login.captcha_type_name": "登入驗證碼型別",
61
+ "core.login.captcha_type_response_missing": "驗證碼介面未返回型別",
62
+ "core.login.captcha_write_failed": "驗證碼圖片寫入失敗",
63
+ "core.login.default_sub_title": "歡迎使用本應用",
64
+ "core.login.login_failed": "登入失敗,請重試",
65
+ "core.login.login_success": "登入成功",
70
66
  "core.login.password": "請輸入密碼",
71
67
  "core.login.privacy": "《隱私協議》",
72
- "core.login.protocolMissing": "服務條款和隱私協議未配置",
73
- "core.login.protocolPrompt": "請先閱讀並勾選協議內容,點選確定後將自動勾選並繼續登入",
68
+ "core.login.protocol_missing": "服務條款和隱私協議未配置",
69
+ "core.login.protocol_prompt": "請先閱讀並勾選協議內容,點選確定後將自動勾選並繼續登入",
74
70
  "core.login.service": "《服務條款》",
75
71
  "core.login.tenant": "請輸入租戶編號",
76
- "core.login.userName": "請輸入使用者名稱或手機號",
77
- "core.login.userNameMobile": "請輸入使用者名稱/手機號碼",
78
- "core.login.userNamePassword": "請輸入使用者名稱和密碼",
72
+ "core.login.user_name": "請輸入使用者名稱或手機號",
73
+ "core.login.user_name_mobile": "請輸入使用者名稱/手機號碼",
74
+ "core.login.user_name_password": "請輸入使用者名稱和密碼",
79
75
  "core.login.wechat": "微信一鍵登入",
80
- "core.login.wechatBindTip": "該微信尚未繫結,請登入已有賬號完成繫結",
81
- "core.login.wechatFailed": "微信登入失敗,請稍後重試",
76
+ "core.login.wechat_bind_tip": "該微信尚未繫結,請登入已有賬號完成繫結",
77
+ "core.login.wechat_failed": "微信登入失敗,請稍後重試",
82
78
  "core.navigation.home": "首頁",
83
79
  "core.navigation.error.access": "選單訪問模式無效:{access}",
84
- "core.navigation.error.childTab": "只有移動端二級選單可以作為 tab:{name}",
80
+ "core.navigation.error.child_tab": "只有移動端二級選單可以作為 tab:{name}",
85
81
  "core.navigation.error.cycle": "移動端選單存在迴圈父級:{name}",
86
82
  "core.navigation.error.identity": "選單 id、name 或 app/ 路徑無效",
87
- "core.navigation.error.itemObject": "選單項不是物件",
88
- "core.navigation.error.listMissing": "選單響應缺少扁平列表",
89
- "core.navigation.error.namePrefix": "選單名稱必須使用 App 字首:{name}",
90
- "core.navigation.error.parentInvalid": "移動端選單父級編號無效:{name}",
91
- "core.navigation.error.parentMissing": "選單缺少父級編號:{name}",
92
- "core.navigation.error.parentNotFound": "移動端選單父級不存在:{name}",
93
- "core.navigation.error.responseObject": "選單響應不是物件",
94
- "core.navigation.error.rootTab": "移動端二級選單必須作為 tab:{name}",
95
- "core.navigation.error.tabCount": "tabBar 只能配置 0 或 2-5 項",
83
+ "core.navigation.error.item_object": "選單項不是物件",
84
+ "core.navigation.error.list_missing": "選單響應缺少扁平列表",
85
+ "core.navigation.error.name_prefix": "選單名稱必須使用 App 字首:{name}",
86
+ "core.navigation.error.parent_missing": "選單缺少父級編號:{name}",
87
+ "core.navigation.error.parent_not_found": "移動端選單父級不存在:{name}",
88
+ "core.navigation.error.response_object": "選單響應不是物件",
89
+ "core.navigation.error.root_tab": "移動端二級選單必須作為 tab:{name}",
90
+ "core.navigation.error.tab_count": "tabBar 只能配置 0 或 2-5 項",
96
91
  "core.navigation.error.unique": "選單 id、name、path 必須唯一",
97
- "core.navigation.error.viewKey": "未註冊 viewKey:{viewKey}",
92
+ "core.navigation.error.view_key": "未註冊 viewKey:{viewKey}",
98
93
  "core.navigation.my": "我的",
99
94
  "core.navigation.protocol": "協議詳情",
100
- "core.protocol.loadFailed": "移動端配置載入失敗",
101
- "core.protocol.notConfigured": "{title}未配置,暫時無法檢視",
95
+ "core.protocol.load_failed": "移動端配置載入失敗",
96
+ "core.protocol.not_configured": "{title}未配置,暫時無法檢視",
102
97
  "core.protocol.privacy": "隱私協議",
103
98
  "core.protocol.service": "服務條款",
104
99
  "core.status.CONFIG_ERROR": "導航配置無效",
105
- "core.status.FORBIDDEN": "暫無訪問許可權",
100
+ "core.status.forbidden": "暫無訪問許可權",
106
101
  "core.status.NOT_FOUND": "頁面不存在",
107
- "core.status.OFFLINE": "網路不可用",
108
- "core.status.PAGE_UNAVAILABLE": "頁面暫不可用",
102
+ "core.status.offline": "網路不可用",
103
+ "core.status.page_unavailable": "頁面暫不可用",
109
104
  "core.status.loading": "正在載入",
110
- "core.webview.embedBlocked": "當前 H5 頁面可能被目標站點限制嵌入",
111
- "core.webview.invalidUrl": "缺少有效連結地址",
112
- "core.webview.openFailed": "連結無法開啟"
105
+ "core.webview.embed_blocked": "當前 H5 頁面可能被目標站點限制嵌入",
106
+ "core.webview.invalid_url": "缺少有效連結地址",
107
+ "core.webview.open_failed": "連結無法開啟"
113
108
  }
package/src/module.ts CHANGED
@@ -62,6 +62,6 @@ export function resolveModuleIcon(icon: string | undefined): string | undefined
62
62
  /** 解析随应用打包的静态资源路径。 */
63
63
  export function resolveBundledAsset(source: string): string {
64
64
  if (/^(?:https?:|data:)/.test(source)) return source
65
- const base = process.env.KRATOS_TARO_PUBLIC_PATH || '/'
65
+ const base = process.env.VITE_APP_BASE_PATH || '/'
66
66
  return `${base.replace(/\/?$/, '/')}${source.replace(/^\/+/, '')}`
67
67
  }
package/src/navigation.ts CHANGED
@@ -150,7 +150,7 @@ const defaultMenuTitleKeys: Record<string, string> = {
150
150
  AppProtocol: 'core.navigation.protocol',
151
151
  AppProfile: 'system.profile.title',
152
152
  AppSettings: 'system.settings.title',
153
- AppAi: 'system.ai.chatTitle',
153
+ AppAi: 'system.ai.chat_title',
154
154
  }
155
155
 
156
156
  function localizedDefaultAppMenus(): AppMenu[] {
@@ -278,15 +278,15 @@ function readCachedMenus(cacheKey: string): AppMenu[] | undefined {
278
278
 
279
279
  function normalizeMenuResponse(response: unknown): AppMenu[] {
280
280
  if (Array.isArray(response)) return response.map(normalizeMenu)
281
- if (!response || typeof response !== 'object') throw new Error(t('core.navigation.error.responseObject'))
281
+ if (!response || typeof response !== 'object') throw new Error(t('core.navigation.error.response_object'))
282
282
  const record = response as Record<string, unknown>
283
283
  const list = record.items ?? record.list ?? record.data
284
- if (!Array.isArray(list)) throw new Error(t('core.navigation.error.listMissing'))
284
+ if (!Array.isArray(list)) throw new Error(t('core.navigation.error.list_missing'))
285
285
  return list.map(normalizeMenu)
286
286
  }
287
287
 
288
288
  function normalizeMenu(value: unknown): AppMenu {
289
- if (!value || typeof value !== 'object') throw new Error(t('core.navigation.error.itemObject'))
289
+ if (!value || typeof value !== 'object') throw new Error(t('core.navigation.error.item_object'))
290
290
  const item = value as Record<string, unknown>
291
291
  const meta = (item.meta ?? {}) as Record<string, unknown>
292
292
  const app = (meta.app ?? item.app ?? {}) as Record<string, unknown>
@@ -321,13 +321,13 @@ function validateMenus(nextMenus: AppMenu[]): void {
321
321
  throw new Error(t('core.navigation.error.identity'))
322
322
  }
323
323
  if (!menu.name.startsWith('App')) {
324
- throw new Error(t('core.navigation.error.namePrefix', { name: menu.name }))
324
+ throw new Error(t('core.navigation.error.name_prefix', { name: menu.name }))
325
325
  }
326
326
  if (!['PUBLIC', 'GUEST_ONLY', 'AUTHENTICATED'].includes(menu.access)) {
327
327
  throw new Error(t('core.navigation.error.access', { access: menu.access }))
328
328
  }
329
329
  if (!resolveStaticView(menu.viewKey)) {
330
- throw new Error(t('core.navigation.error.viewKey', { viewKey: menu.viewKey }))
330
+ throw new Error(t('core.navigation.error.view_key', { viewKey: menu.viewKey }))
331
331
  }
332
332
  if (ids.has(menu.id) || names.has(menu.name) || paths.has(menu.path)) {
333
333
  throw new Error(t('core.navigation.error.unique'))
@@ -339,23 +339,23 @@ function validateMenus(nextMenus: AppMenu[]): void {
339
339
  const menuMap = new Map(nextMenus.map((menu) => [menu.id, menu]))
340
340
  for (const menu of nextMenus) {
341
341
  if (menu.parentId === undefined) {
342
- throw new Error(t('core.navigation.error.parentMissing', { name: menu.name }))
342
+ throw new Error(t('core.navigation.error.parent_missing', { name: menu.name }))
343
343
  }
344
344
  if (menu.parentId === APP_MENU_ROOT_ID) {
345
- if (!menu.inTabBar) throw new Error(t('core.navigation.error.rootTab', { name: menu.name }))
345
+ if (!menu.inTabBar) throw new Error(t('core.navigation.error.root_tab', { name: menu.name }))
346
346
  continue
347
347
  }
348
- if (menu.inTabBar) throw new Error(t('core.navigation.error.childTab', { name: menu.name }))
348
+ if (menu.inTabBar) throw new Error(t('core.navigation.error.child_tab', { name: menu.name }))
349
349
  const visited = new Set<number>([menu.id])
350
350
  let parentId = menu.parentId
351
351
  while (parentId !== APP_MENU_ROOT_ID) {
352
352
  if (visited.has(parentId)) throw new Error(t('core.navigation.error.cycle', { name: menu.name }))
353
353
  visited.add(parentId)
354
354
  const parent = menuMap.get(parentId)
355
- if (!parent?.parentId) throw new Error(t('core.navigation.error.parentNotFound', { name: menu.name }))
355
+ if (!parent?.parentId) throw new Error(t('core.navigation.error.parent_not_found', { name: menu.name }))
356
356
  parentId = parent.parentId
357
357
  }
358
358
  }
359
359
  const tabCount = nextMenus.filter((menu) => menu.parentId === APP_MENU_ROOT_ID).length
360
- if (tabCount === 1 || tabCount > 5) throw new Error(t('core.navigation.error.tabCount'))
360
+ if (tabCount === 1 || tabCount > 5) throw new Error(t('core.navigation.error.tab_count'))
361
361
  }
@@ -5,7 +5,18 @@
5
5
  // source: base/v1/config.proto
6
6
 
7
7
  /* eslint-disable */
8
- import type { BaseConfigSite } from "./enum";
8
+
9
+ /** 系统配置位置。 */
10
+ export enum BaseConfigSite {
11
+ /** BASE_CONFIG_SITE_UNSPECIFIED - 未指定系统配置位置。 */
12
+ BASE_CONFIG_SITE_UNSPECIFIED = 0,
13
+ /** BASE_CONFIG_SITE_SYSTEM - 系统内使用。 */
14
+ BASE_CONFIG_SITE_SYSTEM = 1,
15
+ /** BASE_CONFIG_SITE_ADMIN - 管理端。 */
16
+ BASE_CONFIG_SITE_ADMIN = 2,
17
+ /** BASE_CONFIG_SITE_APP - 移动端。 */
18
+ BASE_CONFIG_SITE_APP = 3,
19
+ }
9
20
 
10
21
  /** 获取系统配置条件 */
11
22
  export interface GetConfigRequest {
@@ -6,32 +6,26 @@
6
6
 
7
7
  /* eslint-disable */
8
8
 
9
- /** 查询语言请求参数。 */
10
- export interface GetLanguageRequest {
9
+ /** 查询语言选项请求参数。 */
10
+ export interface OptionLanguageRequest {
11
11
  }
12
12
 
13
- /** 支持的语言。 */
13
+ /** 语言选择项。 */
14
14
  export interface LanguageItem {
15
15
  /** 标准语言代码 */
16
16
  language_code: string;
17
- /** 语言名称 */
18
- language_name: string;
19
17
  /** 本地语言名称 */
20
18
  native_name: string;
21
- /** 排序,值越小越靠前 */
22
- sort: number;
23
19
  }
24
20
 
25
- /** 当前支持的语言查询结果。 */
26
- export interface GetLanguageResponse {
21
+ /** 当前支持的语言选项查询结果。 */
22
+ export interface OptionLanguageResponse {
27
23
  /** 当前支持的语言列表 */
28
24
  languages: LanguageItem[];
29
- /** 主语言代码 */
30
- primary_language_code: string;
31
25
  }
32
26
 
33
27
  /** 语言公共服务。 */
34
28
  export interface LanguageService {
35
- /** 查询当前支持的语言和主语言。 */
36
- GetLanguage(request: GetLanguageRequest): Promise<GetLanguageResponse>;
29
+ /** 查询当前支持的语言选项。 */
30
+ OptionLanguage(request: OptionLanguageRequest): Promise<OptionLanguageResponse>;
37
31
  }
@@ -7,7 +7,20 @@
7
7
  /* eslint-disable */
8
8
  import type { PasswordCrypto } from "../../common/v1/types";
9
9
  import type { Empty } from "../../google/protobuf/empty";
10
- import type { PasswordCryptoScene } from "./enum";
10
+
11
+ /** 密码加密场景枚举。 */
12
+ export enum PasswordCryptoScene {
13
+ /** PASSWORD_CRYPTO_SCENE_UNSPECIFIED - 未指定密码加密场景。 */
14
+ PASSWORD_CRYPTO_SCENE_UNSPECIFIED = 0,
15
+ /** PASSWORD_CRYPTO_SCENE_LOGIN - 登录密码加密场景。 */
16
+ PASSWORD_CRYPTO_SCENE_LOGIN = 1,
17
+ /** PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER - 新增后台用户密码加密场景。 */
18
+ PASSWORD_CRYPTO_SCENE_CREATE_BASE_USER = 2,
19
+ /** PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD - 重置后台用户密码加密场景。 */
20
+ PASSWORD_CRYPTO_SCENE_RESET_BASE_USER_PASSWORD = 3,
21
+ /** PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD - 个人修改密码加密场景。 */
22
+ PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD = 4,
23
+ }
11
24
 
12
25
  /** 验证码获取条件 */
13
26
  export interface CaptchaRequest {
package/src/runner.ts CHANGED
@@ -109,7 +109,17 @@ async function main(): Promise<void> {
109
109
  process.once('SIGTERM', () => handleSignal('SIGTERM'))
110
110
 
111
111
  try {
112
- const args = ['exec', 'taro', 'build', '--type', options.type, '--mode', options.mode]
112
+ const args = [
113
+ 'exec',
114
+ 'taro',
115
+ 'build',
116
+ '--type',
117
+ options.type,
118
+ '--mode',
119
+ options.mode,
120
+ '--env-prefix',
121
+ 'VITE_APP_,TARO_APP_',
122
+ ]
113
123
  if (options.watch) args.push('--watch')
114
124
  child = spawn(process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm', args, {
115
125
  cwd: hostRoot,
@@ -1,12 +1,12 @@
1
1
  import { create } from 'zustand'
2
2
  import { defConfigService } from '../api/base/config'
3
3
  import { t } from '../locales'
4
- import { BaseConfigSite } from '../rpc/base/v1/enum'
4
+ import { BaseConfigSite } from '../rpc/base/v1/config'
5
5
 
6
6
  const REQUIRED_APP_CONFIGS = [
7
7
  { key: 'serviceProtocol', nameKey: 'core.login.service' },
8
8
  { key: 'privacyProtocol', nameKey: 'core.login.privacy' },
9
- { key: 'captchaType', nameKey: 'core.login.captchaTypeName' },
9
+ { key: 'captchaType', nameKey: 'core.login.captcha_type_name' },
10
10
  ] as const
11
11
 
12
12
  /** 应用配置状态及操作。 */
@@ -27,7 +27,7 @@ export const useSettingStore = create<SettingStoreState>((set, get) => ({
27
27
  async loadData() {
28
28
  if (loading) return loading
29
29
  loading = (async () => {
30
- const response = await defConfigService.GetConfig({ site: BaseConfigSite.APP })
30
+ const response = await defConfigService.GetConfig({ site: BaseConfigSite.BASE_CONFIG_SITE_APP })
31
31
  const nextData = new Map(response.configs.map((item) => [item.key, item.value]))
32
32
  const missing = REQUIRED_APP_CONFIGS.filter(({ key }) => !nextData.get(key))
33
33
  if (missing.length) {
package/src/utils/file.ts CHANGED
@@ -18,7 +18,7 @@ export async function uploadFile(fileType: string, filePath: string): Promise<Fi
18
18
  ...(token ? { Authorization: token } : {}),
19
19
  },
20
20
  })
21
- if (response.statusCode !== 200) throw new Error(t('core.file.uploadFailed'))
21
+ if (response.statusCode !== 200) throw new Error(t('core.file.upload_failed'))
22
22
  return JSON.parse(response.data) as FileInfo
23
23
  }
24
24
 
package/src/utils/http.ts CHANGED
@@ -12,8 +12,8 @@ import {
12
12
  import { saveCurrentRoute } from './navigation'
13
13
  import { getLocaleRequestHeaders, t } from '../locales'
14
14
 
15
- const apiBasePath = process.env.KRATOS_TARO_API_BASE || '/api'
16
- const apiTargetUrl = process.env.KRATOS_TARO_API_URL || ''
15
+ const apiBasePath = process.env.VITE_APP_BASE_API || '/api'
16
+ const apiTargetUrl = process.env.VITE_APP_API_URL || ''
17
17
  const normalizedApiBasePath = apiBasePath.startsWith('/') ? apiBasePath : `/${apiBasePath}`
18
18
  const requestOrigin = process.env.TARO_ENV === 'h5' ? '' : apiTargetUrl.replace(/\/$/, '')
19
19
  /** 请求基础地址。 */
@@ -144,7 +144,7 @@ async function sendRequest<T>(
144
144
  }
145
145
  await Taro.showToast({
146
146
  icon: 'none',
147
- title: responseData?.message || t('common.message.requestError'),
147
+ title: responseData?.message || t('common.message.request_error'),
148
148
  })
149
149
  throw response
150
150
  } catch (error) {
@@ -155,7 +155,7 @@ async function sendRequest<T>(
155
155
  ) {
156
156
  throw error
157
157
  }
158
- await Taro.showToast({ icon: 'none', title: t('common.message.networkError') })
158
+ await Taro.showToast({ icon: 'none', title: t('common.message.network_error') })
159
159
  throw error
160
160
  }
161
161
  }
@@ -241,9 +241,9 @@ async function promptRelogin(): Promise<void> {
241
241
  try {
242
242
  const modal = await Taro.showModal({
243
243
  title: t('common.title.notice'),
244
- content: t('core.auth.sessionExpired'),
244
+ content: t('core.auth.session_expired'),
245
245
  showCancel: false,
246
- confirmText: t('core.auth.loginAgain'),
246
+ confirmText: t('core.auth.login_again'),
247
247
  })
248
248
  if (!modal.confirm) return
249
249
  await new Promise((resolve) => setTimeout(resolve, 80))
@@ -269,7 +269,7 @@ function handleAuthExpiredByMode(
269
269
  if (authMode !== 'optional') {
270
270
  void Taro.showToast({
271
271
  icon: 'none',
272
- title: responseData?.message || t('common.message.requestError'),
272
+ title: responseData?.message || t('common.message.request_error'),
273
273
  })
274
274
  }
275
275
  }
@@ -1,4 +1,4 @@
1
- const configuredStaticUrl = process.env.KRATOS_TARO_STATIC_URL || ''
1
+ const configuredStaticUrl = process.env.VITE_APP_STATIC_URL || ''
2
2
 
3
3
  /** 日期格式化函数。 */
4
4
  export function formatDate(date: Date, format = 'YYYY-MM-DD HH:mm:ss'): string {
@@ -2,7 +2,7 @@ import Taro from '@tarojs/taro'
2
2
  import * as miniCrypto from 'asmcrypto.js'
3
3
  import { defLoginService } from '../api/base/login'
4
4
  import { t } from '../locales'
5
- import { PasswordCryptoScene } from '../rpc/base/v1/enum'
5
+ import { PasswordCryptoScene } from '../rpc/base/v1/login'
6
6
  import type { PasswordCrypto } from '../rpc/common/v1/types'
7
7
 
8
8
  type MiniCrypto = typeof import('asmcrypto.js')
@@ -18,7 +18,7 @@ function pemToArrayBuffer(pem: string) {
18
18
  .replace(/\s/g, '')
19
19
  const decode = globalThis.atob
20
20
  if (!decode) {
21
- throw new Error(t('core.crypto.base64DecodeUnsupported'))
21
+ throw new Error(t('core.crypto.base64_decode_unsupported'))
22
22
  }
23
23
  const binary = decode(base64)
24
24
  const buffer = new Uint8Array(binary.length)
@@ -37,7 +37,7 @@ function arrayBufferToBase64(buffer: ArrayBuffer) {
37
37
  }
38
38
  const encode = globalThis.btoa
39
39
  if (!encode) {
40
- throw new Error(t('core.crypto.base64EncodeUnsupported'))
40
+ throw new Error(t('core.crypto.base64_encode_unsupported'))
41
41
  }
42
42
  return encode(binary)
43
43
  }
@@ -60,7 +60,7 @@ type DerNode = {
60
60
  /** 读取 DER 编码节点,用于解析 RSA SubjectPublicKeyInfo。 */
61
61
  function readDerNode(data: Uint8Array, offset: number): DerNode {
62
62
  if (offset + 2 > data.length) {
63
- throw new Error(t('core.crypto.publicKeyInvalid'))
63
+ throw new Error(t('core.crypto.public_key_invalid'))
64
64
  }
65
65
  const tag = data[offset]
66
66
  const firstLengthByte = data[offset + 1]
@@ -69,7 +69,7 @@ function readDerNode(data: Uint8Array, offset: number): DerNode {
69
69
  if (firstLengthByte & 0x80) {
70
70
  const lengthByteCount = firstLengthByte & 0x7f
71
71
  if (lengthByteCount === 0 || valueOffset + lengthByteCount > data.length) {
72
- throw new Error(t('core.crypto.publicKeyInvalid'))
72
+ throw new Error(t('core.crypto.public_key_invalid'))
73
73
  }
74
74
  length = 0
75
75
  for (let index = 0; index < lengthByteCount; index += 1) {
@@ -79,7 +79,7 @@ function readDerNode(data: Uint8Array, offset: number): DerNode {
79
79
  }
80
80
  const end = valueOffset + length
81
81
  if (end > data.length) {
82
- throw new Error(t('core.crypto.publicKeyInvalid'))
82
+ throw new Error(t('core.crypto.public_key_invalid'))
83
83
  }
84
84
  return {
85
85
  tag,
@@ -108,13 +108,13 @@ function parseMiniRsaPublicKey(publicKey: string): [Uint8Array, Uint8Array] {
108
108
  const algorithm = readDerNode(subjectPublicKeyInfo.value, 0)
109
109
  const bitString = readDerNode(subjectPublicKeyInfo.value, algorithm.next)
110
110
  if (bitString.tag !== 0x03 || bitString.value[0] !== 0) {
111
- throw new Error(t('core.crypto.publicKeyInvalid'))
111
+ throw new Error(t('core.crypto.public_key_invalid'))
112
112
  }
113
113
  const rsaPublicKey = readDerNode(bitString.value, 1)
114
114
  const modulus = readDerNode(rsaPublicKey.value, 0)
115
115
  const exponent = readDerNode(rsaPublicKey.value, modulus.next)
116
116
  if (modulus.tag !== 0x02 || exponent.tag !== 0x02) {
117
- throw new Error(t('core.crypto.publicKeyInvalid'))
117
+ throw new Error(t('core.crypto.public_key_invalid'))
118
118
  }
119
119
  return [trimDerInteger(modulus.value), trimDerInteger(exponent.value)]
120
120
  }
@@ -132,7 +132,7 @@ function generateMgf1Mask(crypto: MiniCrypto, seed: Uint8Array, length: number)
132
132
  counter[3] = index
133
133
  let block = hash.reset().process(seed).process(counter).finish().result
134
134
  if (!block) {
135
- throw new Error(t('core.crypto.encryptFailed'))
135
+ throw new Error(t('core.crypto.encrypt_failed'))
136
136
  }
137
137
  const target = mask.subarray(index * hash.HASH_SIZE)
138
138
  if (block.length > target.length) {
@@ -172,14 +172,14 @@ async function encryptPortablePassword(
172
172
  const dataBlockLength = keySize - hash.HASH_SIZE - 1
173
173
  const paddingLength = dataBlockLength - aesKey.length - hash.HASH_SIZE - 1
174
174
  if (paddingLength < 0) {
175
- throw new Error(t('core.crypto.passwordTooLong'))
175
+ throw new Error(t('core.crypto.password_too_long'))
176
176
  }
177
177
  const encodedMessage = new Uint8Array(keySize)
178
178
  const maskedSeed = encodedMessage.subarray(1, hash.HASH_SIZE + 1)
179
179
  const dataBlock = encodedMessage.subarray(hash.HASH_SIZE + 1)
180
180
  const labelHash = hash.reset().process(new Uint8Array()).finish().result
181
181
  if (!labelHash) {
182
- throw new Error(t('core.crypto.encryptFailed'))
182
+ throw new Error(t('core.crypto.encrypt_failed'))
183
183
  }
184
184
  dataBlock.set(labelHash, 0)
185
185
  dataBlock.set(aesKey, hash.HASH_SIZE + paddingLength + 1)
@@ -197,7 +197,7 @@ async function encryptPortablePassword(
197
197
  new crypto.BigNumber(encodedMessage),
198
198
  ).result
199
199
  if (!encryptedKey) {
200
- throw new Error(t('core.crypto.encryptFailed'))
200
+ throw new Error(t('core.crypto.encrypt_failed'))
201
201
  }
202
202
  const ciphertext = crypto.AES_GCM.encrypt(plaintext, aesKey, iv)
203
203
  return {
@@ -217,7 +217,7 @@ export async function encryptPassword(
217
217
  ): Promise<PasswordCrypto> {
218
218
  const plainPassword = password.trim()
219
219
  if (!plainPassword) {
220
- throw new Error(t('core.crypto.passwordRequired'))
220
+ throw new Error(t('core.crypto.password_required'))
221
221
  }
222
222
 
223
223
  const publicKeyResponse = await defLoginService.PasswordPublicKey({ scene })
@@ -10,8 +10,8 @@ export default function HomePage() {
10
10
  const { t } = useI18n()
11
11
  const settings = useSettingStore((state) => state.data)
12
12
  const loadData = useSettingStore((state) => state.loadData)
13
- const mainTitle = settings?.get('mainTitle') || t('core.home.mainTitle')
14
- const subTitle = settings?.get('subTitle') || t('core.home.subTitle')
13
+ const mainTitle = settings?.get('mainTitle') || t('core.home.main_title')
14
+ const subTitle = settings?.get('subTitle') || t('core.home.sub_title')
15
15
  const appLogo = settings?.get('appLogo') || defaultLogo
16
16
  useLoad(() => {
17
17
  void loadData().catch(() => undefined)
@@ -20,13 +20,13 @@ export default function HomePage() {
20
20
  const stack = [
21
21
  [t('core.home.framework'), 'Taro + React 18'],
22
22
  [t('core.home.language'), 'TypeScript'],
23
- [t('core.home.stateManagement'), 'Zustand'],
24
- [t('core.home.styleSolution'), 'Sass + px'],
23
+ [t('core.home.state_management'), 'Zustand'],
24
+ [t('core.home.style_solution'), 'Sass + px'],
25
25
  ]
26
26
  const demos = [
27
- [t('core.home.crossPlatform'), t('core.home.crossPlatformDescription')],
28
- [t('core.home.accountCapability'), t('core.home.accountCapabilityDescription')],
29
- [t('core.home.staticHome'), t('core.home.staticHomeDescription')],
27
+ [t('core.home.cross_platform'), t('core.home.cross_platform_description')],
28
+ [t('core.home.account_capability'), t('core.home.account_capability_description')],
29
+ [t('core.home.static_home'), t('core.home.static_home_description')],
30
30
  ]
31
31
 
32
32
  return (
@@ -44,7 +44,7 @@ export default function HomePage() {
44
44
  </View>
45
45
 
46
46
  <View className='home-section'>
47
- <Text className='home-section__title'>{t('core.home.techStack')}</Text>
47
+ <Text className='home-section__title'>{t('core.home.tech_stack')}</Text>
48
48
  <View className='home-info-list'>
49
49
  {stack.map(([label, value]) => (
50
50
  <View className='home-info-row' key={label}>
@@ -56,7 +56,7 @@ export default function HomePage() {
56
56
  </View>
57
57
 
58
58
  <View className='home-section'>
59
- <Text className='home-section__title'>{t('core.home.demoScope')}</Text>
59
+ <Text className='home-section__title'>{t('core.home.demo_scope')}</Text>
60
60
  <View className='home-demo-list'>
61
61
  {demos.map(([title, description], index) => (
62
62
  <View className='home-demo-item' key={title}>