@liujitcn/kratos-uni-app-core 0.0.62 → 0.0.64
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 +1 -1
- package/dist/module.mjs +8 -0
- package/dist/vite.mjs +31 -4
- package/package.json +1 -1
- package/src/api/base/v1/file.ts +1 -1
- package/src/bootstrap.ts +12 -0
- package/src/locales/en-US.json +2 -0
- package/src/locales/index.ts +30 -5
- package/src/locales/ja-JP.json +2 -0
- package/src/locales/zh-CN.json +2 -0
- package/src/locales/zh-TW.json +2 -0
- package/src/rpc/base/v1/oauth.ts +16 -0
- package/src/rpc/google/protobuf/struct.ts +80 -0
- package/src/stores/modules/user.ts +1 -1
- package/src/vite-messages.ts +30 -0
- package/src/vite.ts +6 -4
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ packages/core
|
|
|
45
45
|
|
|
46
46
|
- `@liujitcn/kratos-uni-app-core`:运行时、导航、store 和组件。
|
|
47
47
|
- `@liujitcn/kratos-uni-app-core/module`:模块协议和 core 模块。
|
|
48
|
-
- `@liujitcn/kratos-uni-app-core/vite`:Vite
|
|
48
|
+
- `@liujitcn/kratos-uni-app-core/vite`:Vite 配置、页面装配插件和构建错误文案格式化器。
|
|
49
49
|
- `@liujitcn/kratos-uni-app-core/api/*`、`components/*.vue`、`utils/*`、`views/*`:白名单子路径。
|
|
50
50
|
|
|
51
51
|
## 公共设置页
|
package/dist/module.mjs
CHANGED
|
@@ -33,6 +33,7 @@ var zh_CN_default = {
|
|
|
33
33
|
"common.action.new": "\u65B0\u5EFA",
|
|
34
34
|
"common.action.open_in_new_window": "\u65B0\u7A97\u53E3\u6253\u5F00",
|
|
35
35
|
"common.action.save": "\u4FDD\u5B58",
|
|
36
|
+
"common.action.view": "\u67E5\u770B",
|
|
36
37
|
"common.field.language": "\u8BED\u8A00",
|
|
37
38
|
"common.language.en-US": "English",
|
|
38
39
|
"common.language.zh-CN": "\u7B80\u4F53\u4E2D\u6587",
|
|
@@ -115,6 +116,7 @@ var zh_CN_default = {
|
|
|
115
116
|
"core.login.user_name_password": "\u8BF7\u8F93\u5165\u7528\u6237\u540D\u548C\u5BC6\u7801",
|
|
116
117
|
"core.login.wechat": "\u5FAE\u4FE1\u4E00\u952E\u767B\u5F55",
|
|
117
118
|
"core.login.wechat_bind_tip": "\u8BE5\u5FAE\u4FE1\u5C1A\u672A\u7ED1\u5B9A\uFF0C\u8BF7\u767B\u5F55\u5DF2\u6709\u8D26\u53F7\u5B8C\u6210\u7ED1\u5B9A",
|
|
119
|
+
"core.login.login_failed": "\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5",
|
|
118
120
|
"core.login.wechat_failed": "\u5FAE\u4FE1\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
|
|
119
121
|
"core.navigation.home": "\u9996\u9875",
|
|
120
122
|
"core.navigation.message": "\u6D88\u606F",
|
|
@@ -178,6 +180,7 @@ var en_US_default = {
|
|
|
178
180
|
"common.action.new": "New",
|
|
179
181
|
"common.action.open_in_new_window": "Open in new window",
|
|
180
182
|
"common.action.save": "Save",
|
|
183
|
+
"common.action.view": "View",
|
|
181
184
|
"common.field.language": "Language",
|
|
182
185
|
"common.language.en-US": "English",
|
|
183
186
|
"common.language.zh-CN": "\u7B80\u4F53\u4E2D\u6587",
|
|
@@ -260,6 +263,7 @@ var en_US_default = {
|
|
|
260
263
|
"core.login.user_name_password": "Enter username and password",
|
|
261
264
|
"core.login.wechat": "Continue with WeChat",
|
|
262
265
|
"core.login.wechat_bind_tip": "This WeChat account is not linked. Log in to an existing account to link it.",
|
|
266
|
+
"core.login.login_failed": "Login failed. Try again.",
|
|
263
267
|
"core.login.wechat_failed": "WeChat login failed. Try again later.",
|
|
264
268
|
"core.navigation.home": "Home",
|
|
265
269
|
"core.navigation.message": "Messages",
|
|
@@ -323,6 +327,7 @@ var ja_JP_default = {
|
|
|
323
327
|
"common.action.new": "\u65B0\u898F",
|
|
324
328
|
"common.action.open_in_new_window": "\u65B0\u3057\u3044\u30A6\u30A3\u30F3\u30C9\u30A6\u304C\u958B\u304D\u307E\u3059",
|
|
325
329
|
"common.action.save": "\u4FDD\u5B58",
|
|
330
|
+
"common.action.view": "\u8868\u793A",
|
|
326
331
|
"common.field.language": "\u8A00\u8A9E",
|
|
327
332
|
"common.language.en-US": "\u82F1\u8A9E",
|
|
328
333
|
"common.language.zh-CN": "\u7C21\u4F53\u5B57\u4E2D\u56FD\u8A9E",
|
|
@@ -405,6 +410,7 @@ var ja_JP_default = {
|
|
|
405
410
|
"core.login.user_name_password": "\u30E6\u30FC\u30B6\u30FC\u540D\u3068\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
406
411
|
"core.login.wechat": "WeChat \u30EF\u30F3\u30AF\u30EA\u30C3\u30AF \u30ED\u30B0\u30A4\u30F3",
|
|
407
412
|
"core.login.wechat_bind_tip": "\u3053\u306E WeChat \u30A2\u30AB\u30A6\u30F3\u30C8\u306F\u307E\u3060\u30D0\u30A4\u30F3\u30C9\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30D0\u30A4\u30F3\u30C9\u3092\u5B8C\u4E86\u3059\u308B\u306B\u306F\u3001\u65E2\u5B58\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
413
|
+
"core.login.login_failed": "\u30ED\u30B0\u30A4\u30F3\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044\u3002",
|
|
408
414
|
"core.login.wechat_failed": "WeChat \u30ED\u30B0\u30A4\u30F3\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u5F8C\u3067\u3082\u3046\u4E00\u5EA6\u8A66\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
409
415
|
"core.navigation.home": "\u30DB\u30FC\u30E0",
|
|
410
416
|
"core.navigation.message": "\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
@@ -468,6 +474,7 @@ var zh_TW_default = {
|
|
|
468
474
|
"common.action.new": "\u65B0\u5EFA",
|
|
469
475
|
"common.action.open_in_new_window": "\u65B0\u8996\u7A97\u958B\u555F",
|
|
470
476
|
"common.action.save": "\u5132\u5B58",
|
|
477
|
+
"common.action.view": "\u6AA2\u8996",
|
|
471
478
|
"common.field.language": "\u8A9E\u8A00",
|
|
472
479
|
"common.language.en-US": "English",
|
|
473
480
|
"common.language.zh-CN": "\u7C21\u9AD4\u4E2D\u6587",
|
|
@@ -550,6 +557,7 @@ var zh_TW_default = {
|
|
|
550
557
|
"core.login.user_name_password": "\u8ACB\u8F38\u5165\u4F7F\u7528\u8005\u540D\u7A31\u548C\u5BC6\u78BC",
|
|
551
558
|
"core.login.wechat": "\u5FAE\u4FE1\u4E00\u9375\u767B\u5165",
|
|
552
559
|
"core.login.wechat_bind_tip": "\u8A72\u5FAE\u4FE1\u5C1A\u672A\u7E6B\u7D50\uFF0C\u8ACB\u767B\u5165\u5DF2\u6709\u8CEC\u865F\u5B8C\u6210\u7E6B\u7D50",
|
|
560
|
+
"core.login.login_failed": "\u767B\u5165\u5931\u6557\uFF0C\u8ACB\u91CD\u8A66",
|
|
553
561
|
"core.login.wechat_failed": "\u5FAE\u4FE1\u767B\u5165\u5931\u6557\uFF0C\u8ACB\u7A0D\u5F8C\u91CD\u8A66",
|
|
554
562
|
"core.navigation.home": "\u9996\u9801",
|
|
555
563
|
"core.navigation.message": "\u6D88\u606F",
|
package/dist/vite.mjs
CHANGED
|
@@ -14,6 +14,32 @@ import { createRequire } from "node:module";
|
|
|
14
14
|
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
15
15
|
import uniPlugin from "@dcloudio/vite-plugin-uni";
|
|
16
16
|
import { defineConfig, loadEnv } from "vite";
|
|
17
|
+
|
|
18
|
+
// src/vite-messages.ts
|
|
19
|
+
var messages = {
|
|
20
|
+
"zh-CN": {
|
|
21
|
+
https_certificate_missing: "VITE_APP_HTTPS \u5DF2\u5F00\u542F\uFF0C\u4F46\u672A\u627E\u5230\u8BC1\u4E66\u6587\u4EF6\uFF0C\u8BF7\u5148\u5728\u4ED3\u5E93\u6839\u76EE\u5F55\u8FD0\u884C scripts/generate-dev-cert.sh\uFF1B\u671F\u671B\u8DEF\u5F84\uFF1A{keyPath} \u548C {certPath}",
|
|
22
|
+
transaction_mismatch: "uni-app \u6784\u5EFA\u4E8B\u52A1\u76EE\u5F55\u4E0D\u5339\u914D\uFF1A{file}",
|
|
23
|
+
assembly_timeout: "\u7B49\u5F85 uni-app \u9875\u9762\u88C5\u914D\u9501\u8D85\u65F6\uFF1A{file}",
|
|
24
|
+
source_path_not_absolute: "\u6A21\u5757\u6E90\u7801\u8DEF\u5F84\u4E0D\u662F\u7EDD\u5BF9\u8DEF\u5F84\uFF1A{path}"
|
|
25
|
+
},
|
|
26
|
+
"en-US": {
|
|
27
|
+
https_certificate_missing: "VITE_APP_HTTPS is enabled, but certificate files were not found. Run scripts/generate-dev-cert.sh from the repository root; expected paths: {keyPath} and {certPath}",
|
|
28
|
+
transaction_mismatch: "The uni-app build transaction directory does not match: {file}",
|
|
29
|
+
assembly_timeout: "Timed out waiting for the uni-app page assembly lock: {file}",
|
|
30
|
+
source_path_not_absolute: "The module source path is not absolute: {path}"
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
function resolveViteLocale() {
|
|
34
|
+
const value = process.env.KRATOS_ADMIN_LOCALE ?? process.env.LC_ALL ?? process.env.LANG ?? "";
|
|
35
|
+
return value.toLowerCase().startsWith("zh") ? "zh-CN" : "en-US";
|
|
36
|
+
}
|
|
37
|
+
function viteMessage(key, params = {}) {
|
|
38
|
+
const template = messages[resolveViteLocale()][key] ?? messages["en-US"][key] ?? key;
|
|
39
|
+
return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_, name) => params[name] ?? `{${name}}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/vite.ts
|
|
17
43
|
var sourceVersionCounter = 0;
|
|
18
44
|
var PAGE_ASSEMBLY_WAIT_TIMEOUT_MS = 3e4;
|
|
19
45
|
var PAGE_ASSEMBLY_POLL_INTERVAL_MS = 25;
|
|
@@ -264,7 +290,7 @@ function readBuildTransaction(transactionFile, inputDir, pagesFile) {
|
|
|
264
290
|
return;
|
|
265
291
|
const transaction = JSON.parse(readFileSync(transactionFile, "utf8"));
|
|
266
292
|
if (transaction.inputDir !== inputDir || transaction.pagesFile !== pagesFile) {
|
|
267
|
-
throw new Error(
|
|
293
|
+
throw new Error(viteMessage("transaction_mismatch", { file: transactionFile }));
|
|
268
294
|
}
|
|
269
295
|
return transaction;
|
|
270
296
|
}
|
|
@@ -376,7 +402,7 @@ function acquirePageAssemblyLock(lockFile) {
|
|
|
376
402
|
continue;
|
|
377
403
|
}
|
|
378
404
|
if (Date.now() >= deadline) {
|
|
379
|
-
throw new Error(
|
|
405
|
+
throw new Error(viteMessage("assembly_timeout", { file: lockFile }));
|
|
380
406
|
}
|
|
381
407
|
waitForPageAssembly(PAGE_ASSEMBLY_POLL_INTERVAL_MS);
|
|
382
408
|
}
|
|
@@ -539,7 +565,7 @@ function resolveSourceFile(target) {
|
|
|
539
565
|
];
|
|
540
566
|
const resolved = candidates.find((candidate) => existsSync(candidate) && statSync(candidate).isFile()) ?? target;
|
|
541
567
|
if (!isAbsolute(resolved))
|
|
542
|
-
throw new Error(
|
|
568
|
+
throw new Error(viteMessage("source_path_not_absolute", { path: resolved }));
|
|
543
569
|
return resolved;
|
|
544
570
|
}
|
|
545
571
|
function dependencyVersionQuery(importer, sourceVersion) {
|
|
@@ -569,5 +595,6 @@ export {
|
|
|
569
595
|
defineConfig,
|
|
570
596
|
kratosApp,
|
|
571
597
|
loadEnv,
|
|
572
|
-
recoverStalePageTransaction
|
|
598
|
+
recoverStalePageTransaction,
|
|
599
|
+
viteMessage
|
|
573
600
|
};
|
package/package.json
CHANGED
package/src/api/base/v1/file.ts
CHANGED
package/src/bootstrap.ts
CHANGED
|
@@ -3,9 +3,11 @@ import type { App, Component } from 'vue'
|
|
|
3
3
|
import { registerKratosAppModules, type KratosAppModule } from './module'
|
|
4
4
|
import {
|
|
5
5
|
applyLanguageConfig,
|
|
6
|
+
getCurrentLocale,
|
|
6
7
|
initializeLocale,
|
|
7
8
|
registerLocaleChangeHandler,
|
|
8
9
|
registerLocaleMessages,
|
|
10
|
+
t,
|
|
9
11
|
} from './locales'
|
|
10
12
|
import { initializeAppNavigation } from './navigation'
|
|
11
13
|
import { useSettingStore } from './stores'
|
|
@@ -23,15 +25,25 @@ export interface KratosAppBootstrapOptions {
|
|
|
23
25
|
modules: KratosAppModule[]
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
function syncH5DocumentTitle(): void {
|
|
29
|
+
// #ifdef H5
|
|
30
|
+
if (typeof document === 'undefined') return
|
|
31
|
+
document.documentElement.lang = getCurrentLocale()
|
|
32
|
+
document.title = t('core.home.main_title')
|
|
33
|
+
// #endif
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
/** 创建 uni-app 实例并注册模块。 */
|
|
27
37
|
export function bootstrapKratosApp(options: KratosAppBootstrapOptions) {
|
|
28
38
|
registerKratosAppModules(options.modules)
|
|
29
39
|
registerLocaleMessages(options.modules)
|
|
30
40
|
initializeLocale()
|
|
41
|
+
syncH5DocumentTitle()
|
|
31
42
|
void defLanguageService
|
|
32
43
|
.OptionLanguage({})
|
|
33
44
|
.then((response) => {
|
|
34
45
|
applyLanguageConfig(response)
|
|
46
|
+
syncH5DocumentTitle()
|
|
35
47
|
})
|
|
36
48
|
.catch(() => {
|
|
37
49
|
// 语言公共接口失败时继续使用静态语言包和系统语言。
|
package/src/locales/en-US.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"common.action.new": "New",
|
|
8
8
|
"common.action.open_in_new_window": "Open in new window",
|
|
9
9
|
"common.action.save": "Save",
|
|
10
|
+
"common.action.view": "View",
|
|
10
11
|
"common.field.language": "Language",
|
|
11
12
|
"common.language.en-US": "English",
|
|
12
13
|
"common.language.zh-CN": "简体中文",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"core.login.user_name_password": "Enter username and password",
|
|
90
91
|
"core.login.wechat": "Continue with WeChat",
|
|
91
92
|
"core.login.wechat_bind_tip": "This WeChat account is not linked. Log in to an existing account to link it.",
|
|
93
|
+
"core.login.login_failed": "Login failed. Try again.",
|
|
92
94
|
"core.login.wechat_failed": "WeChat login failed. Try again later.",
|
|
93
95
|
"core.navigation.home": "Home",
|
|
94
96
|
"core.navigation.message": "Messages",
|
package/src/locales/index.ts
CHANGED
|
@@ -108,18 +108,19 @@ export function registerLocaleMessages(modules: KratosAppModule[]): void {
|
|
|
108
108
|
const expectedKeys = requiredLocaleKeys(module.messages?.[DEFAULT_LOCALE] || {})
|
|
109
109
|
SUPPORTED_LOCALES.forEach((locale) => {
|
|
110
110
|
const messages = module.messages?.[locale]
|
|
111
|
-
if (!messages)
|
|
111
|
+
if (!messages)
|
|
112
|
+
throw new Error(localeRuntimeMessage('missing_bundle', { module: module.name, locale }))
|
|
112
113
|
const keys = requiredLocaleKeys(messages)
|
|
113
114
|
if (keys.join('\u0000') !== expectedKeys.join('\u0000')) {
|
|
114
|
-
throw new Error(
|
|
115
|
+
throw new Error(localeRuntimeMessage('key_set_mismatch', { module: module.name, locale }))
|
|
115
116
|
}
|
|
116
117
|
const target = defaultLocaleMessages.get(locale) as LocaleMessages
|
|
117
118
|
Object.keys(messages).forEach((key) => {
|
|
118
119
|
if (!isAllowedLocaleKey(module.name, key)) {
|
|
119
|
-
throw new Error(
|
|
120
|
+
throw new Error(localeRuntimeMessage('namespace_invalid', { module: module.name, key }))
|
|
120
121
|
}
|
|
121
122
|
if (Object.prototype.hasOwnProperty.call(target, key)) {
|
|
122
|
-
throw new Error(
|
|
123
|
+
throw new Error(localeRuntimeMessage('duplicate_key', { locale, key }))
|
|
123
124
|
}
|
|
124
125
|
assertLocalePlaceholders(
|
|
125
126
|
module.name,
|
|
@@ -211,10 +212,34 @@ function assertLocalePlaceholders(
|
|
|
211
212
|
const placeholders = (value: string) =>
|
|
212
213
|
[...value.matchAll(/\{([A-Za-z0-9_]+)\}/g)].map((match) => match[1]).sort()
|
|
213
214
|
if (placeholders(message).join('\u0000') !== placeholders(sourceMessage).join('\u0000')) {
|
|
214
|
-
throw new Error(
|
|
215
|
+
throw new Error(localeRuntimeMessage('placeholder_mismatch', { module: moduleName, key }))
|
|
215
216
|
}
|
|
216
217
|
}
|
|
217
218
|
|
|
219
|
+
function localeRuntimeMessage(key: string, params: Record<string, string>): string {
|
|
220
|
+
const locale = getCurrentLocale().toLowerCase().startsWith('zh') ? 'zh-CN' : 'en-US'
|
|
221
|
+
const templates: Record<string, Record<string, string>> = {
|
|
222
|
+
'zh-CN': {
|
|
223
|
+
missing_bundle: '{module} 缺少 {locale} 语言包',
|
|
224
|
+
key_set_mismatch: '{module} 的 {locale} 语言包键集合不一致',
|
|
225
|
+
namespace_invalid: '{module} 的语言键命名空间无效: {key}',
|
|
226
|
+
duplicate_key: '{locale} 语言键重复: {key}',
|
|
227
|
+
placeholder_mismatch: '{module} 的 {key} 占位符集合不一致',
|
|
228
|
+
},
|
|
229
|
+
'en-US': {
|
|
230
|
+
missing_bundle: '{module} is missing the {locale} locale bundle',
|
|
231
|
+
key_set_mismatch: '{module} has inconsistent keys in the {locale} locale bundle',
|
|
232
|
+
namespace_invalid: 'Invalid locale key namespace for {module}: {key}',
|
|
233
|
+
duplicate_key: 'Duplicate locale key in {locale}: {key}',
|
|
234
|
+
placeholder_mismatch: 'Placeholder set mismatch for {module}: {key}',
|
|
235
|
+
},
|
|
236
|
+
}
|
|
237
|
+
return (templates[locale][key] ?? key).replace(
|
|
238
|
+
/\{([A-Za-z0-9_]+)\}/g,
|
|
239
|
+
(_, name: string) => params[name] ?? `{${name}}`,
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
218
243
|
function requiredLocaleKeys(messages: LocaleMessages): string[] {
|
|
219
244
|
return Object.keys(messages)
|
|
220
245
|
.filter((key) => !key.startsWith('common.language.'))
|
package/src/locales/ja-JP.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"common.action.new": "新規",
|
|
8
8
|
"common.action.open_in_new_window": "新しいウィンドウが開きます",
|
|
9
9
|
"common.action.save": "保存",
|
|
10
|
+
"common.action.view": "表示",
|
|
10
11
|
"common.field.language": "言語",
|
|
11
12
|
"common.language.en-US": "英語",
|
|
12
13
|
"common.language.zh-CN": "簡体字中国語",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"core.login.user_name_password": "ユーザー名とパスワードを入力してください",
|
|
90
91
|
"core.login.wechat": "WeChat ワンクリック ログイン",
|
|
91
92
|
"core.login.wechat_bind_tip": "この WeChat アカウントはまだバインドされていません。バインドを完了するには、既存のアカウントにログインしてください。",
|
|
93
|
+
"core.login.login_failed": "ログインに失敗しました。もう一度お試しください。",
|
|
92
94
|
"core.login.wechat_failed": "WeChat ログインに失敗しました。後でもう一度試してください。",
|
|
93
95
|
"core.navigation.home": "ホーム",
|
|
94
96
|
"core.navigation.message": "メッセージ",
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"common.action.new": "新建",
|
|
8
8
|
"common.action.open_in_new_window": "新窗口打开",
|
|
9
9
|
"common.action.save": "保存",
|
|
10
|
+
"common.action.view": "查看",
|
|
10
11
|
"common.field.language": "语言",
|
|
11
12
|
"common.language.en-US": "English",
|
|
12
13
|
"common.language.zh-CN": "简体中文",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"core.login.user_name_password": "请输入用户名和密码",
|
|
90
91
|
"core.login.wechat": "微信一键登录",
|
|
91
92
|
"core.login.wechat_bind_tip": "该微信尚未绑定,请登录已有账号完成绑定",
|
|
93
|
+
"core.login.login_failed": "登录失败,请重试",
|
|
92
94
|
"core.login.wechat_failed": "微信登录失败,请稍后重试",
|
|
93
95
|
"core.navigation.home": "首页",
|
|
94
96
|
"core.navigation.message": "消息",
|
package/src/locales/zh-TW.json
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"common.action.new": "新建",
|
|
8
8
|
"common.action.open_in_new_window": "新視窗開啟",
|
|
9
9
|
"common.action.save": "儲存",
|
|
10
|
+
"common.action.view": "檢視",
|
|
10
11
|
"common.field.language": "語言",
|
|
11
12
|
"common.language.en-US": "English",
|
|
12
13
|
"common.language.zh-CN": "簡體中文",
|
|
@@ -89,6 +90,7 @@
|
|
|
89
90
|
"core.login.user_name_password": "請輸入使用者名稱和密碼",
|
|
90
91
|
"core.login.wechat": "微信一鍵登入",
|
|
91
92
|
"core.login.wechat_bind_tip": "該微信尚未繫結,請登入已有賬號完成繫結",
|
|
93
|
+
"core.login.login_failed": "登入失敗,請重試",
|
|
92
94
|
"core.login.wechat_failed": "微信登入失敗,請稍後重試",
|
|
93
95
|
"core.navigation.home": "首頁",
|
|
94
96
|
"core.navigation.message": "消息",
|
package/src/rpc/base/v1/oauth.ts
CHANGED
|
@@ -191,14 +191,30 @@ export interface UnbindOauthAccountRequest {
|
|
|
191
191
|
export interface OauthProvider {
|
|
192
192
|
/** 登录方式标识 */
|
|
193
193
|
provider: string;
|
|
194
|
+
/** 登录方式名称 */
|
|
195
|
+
name: string;
|
|
196
|
+
/** 登录方式提示语 */
|
|
197
|
+
description: string;
|
|
198
|
+
/** 图标键或图片地址 */
|
|
199
|
+
icon: string;
|
|
200
|
+
/** Provider个性化配置JSON对象 */
|
|
201
|
+
config: { [key: string]: any } | undefined;
|
|
194
202
|
}
|
|
195
203
|
|
|
196
204
|
/** 个人中心三方账号绑定信息 */
|
|
197
205
|
export interface OauthBinding {
|
|
198
206
|
/** 登录方式标识 */
|
|
199
207
|
provider: string;
|
|
208
|
+
/** 登录方式名称 */
|
|
209
|
+
name: string;
|
|
210
|
+
/** 登录方式提示语 */
|
|
211
|
+
description: string;
|
|
200
212
|
/** 是否已绑定 */
|
|
201
213
|
bound: boolean;
|
|
214
|
+
/** 图标键或图片地址 */
|
|
215
|
+
icon: string;
|
|
216
|
+
/** Provider个性化配置JSON对象 */
|
|
217
|
+
config: { [key: string]: any } | undefined;
|
|
202
218
|
}
|
|
203
219
|
|
|
204
220
|
/** Base三方登录公共服务 */
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
2
|
+
// versions:
|
|
3
|
+
// protoc-gen-ts_proto v2.11.8
|
|
4
|
+
// protoc unknown
|
|
5
|
+
// source: google/protobuf/struct.proto
|
|
6
|
+
|
|
7
|
+
/* eslint-disable */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `NullValue` is a singleton enumeration to represent the null value for the
|
|
11
|
+
* `Value` type union.
|
|
12
|
+
*
|
|
13
|
+
* The JSON representation for `NullValue` is JSON `null`.
|
|
14
|
+
*/
|
|
15
|
+
export enum NullValue {
|
|
16
|
+
/** NULL_VALUE - Null value. */
|
|
17
|
+
NULL_VALUE = 0,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* `Struct` represents a structured data value, consisting of fields
|
|
22
|
+
* which map to dynamically typed values. In some languages, `Struct`
|
|
23
|
+
* might be supported by a native representation. For example, in
|
|
24
|
+
* scripting languages like JS a struct is represented as an
|
|
25
|
+
* object. The details of that representation are described together
|
|
26
|
+
* with the proto support for the language.
|
|
27
|
+
*
|
|
28
|
+
* The JSON representation for `Struct` is JSON object.
|
|
29
|
+
*/
|
|
30
|
+
export interface Struct {
|
|
31
|
+
/** Unordered map of dynamically typed values. */
|
|
32
|
+
fields: Map<string, any | undefined>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface Struct_FieldsEntry {
|
|
36
|
+
key: string;
|
|
37
|
+
value: any | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* `Value` represents a dynamically typed value which can be either
|
|
42
|
+
* null, a number, a string, a boolean, a recursive struct value, or a
|
|
43
|
+
* list of values. A producer of value is expected to set one of these
|
|
44
|
+
* variants. Absence of any variant indicates an error.
|
|
45
|
+
*
|
|
46
|
+
* The JSON representation for `Value` is JSON value.
|
|
47
|
+
*/
|
|
48
|
+
export interface Value {
|
|
49
|
+
/** The kind of value. */
|
|
50
|
+
kind:
|
|
51
|
+
| //
|
|
52
|
+
/** Represents a null value. */
|
|
53
|
+
{ $case: "null_value"; null_value: NullValue }
|
|
54
|
+
| //
|
|
55
|
+
/** Represents a double value. */
|
|
56
|
+
{ $case: "number_value"; number_value: number }
|
|
57
|
+
| //
|
|
58
|
+
/** Represents a string value. */
|
|
59
|
+
{ $case: "string_value"; string_value: string }
|
|
60
|
+
| //
|
|
61
|
+
/** Represents a boolean value. */
|
|
62
|
+
{ $case: "bool_value"; bool_value: boolean }
|
|
63
|
+
| //
|
|
64
|
+
/** Represents a structured value. */
|
|
65
|
+
{ $case: "struct_value"; struct_value: { [key: string]: any } | undefined }
|
|
66
|
+
| //
|
|
67
|
+
/** Represents a repeated `Value`. */
|
|
68
|
+
{ $case: "list_value"; list_value: Array<any> | undefined }
|
|
69
|
+
| undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* `ListValue` is a wrapper around a repeated field of values.
|
|
74
|
+
*
|
|
75
|
+
* The JSON representation for `ListValue` is JSON array.
|
|
76
|
+
*/
|
|
77
|
+
export interface ListValue {
|
|
78
|
+
/** Repeated field of dynamically typed values. */
|
|
79
|
+
values: any[];
|
|
80
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type ViteLocale = 'zh-CN' | 'en-US'
|
|
2
|
+
|
|
3
|
+
const messages: Record<ViteLocale, Record<string, string>> = {
|
|
4
|
+
'zh-CN': {
|
|
5
|
+
https_certificate_missing:
|
|
6
|
+
'VITE_APP_HTTPS 已开启,但未找到证书文件,请先在仓库根目录运行 scripts/generate-dev-cert.sh;期望路径:{keyPath} 和 {certPath}',
|
|
7
|
+
transaction_mismatch: 'uni-app 构建事务目录不匹配:{file}',
|
|
8
|
+
assembly_timeout: '等待 uni-app 页面装配锁超时:{file}',
|
|
9
|
+
source_path_not_absolute: '模块源码路径不是绝对路径:{path}',
|
|
10
|
+
},
|
|
11
|
+
'en-US': {
|
|
12
|
+
https_certificate_missing:
|
|
13
|
+
'VITE_APP_HTTPS is enabled, but certificate files were not found. Run scripts/generate-dev-cert.sh from the repository root; expected paths: {keyPath} and {certPath}',
|
|
14
|
+
transaction_mismatch: 'The uni-app build transaction directory does not match: {file}',
|
|
15
|
+
assembly_timeout: 'Timed out waiting for the uni-app page assembly lock: {file}',
|
|
16
|
+
source_path_not_absolute: 'The module source path is not absolute: {path}',
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** 根据环境变量选择 uni-app 构建器错误语言。 */
|
|
21
|
+
function resolveViteLocale(): ViteLocale {
|
|
22
|
+
const value = process.env.KRATOS_ADMIN_LOCALE ?? process.env.LC_ALL ?? process.env.LANG ?? ''
|
|
23
|
+
return value.toLowerCase().startsWith('zh') ? 'zh-CN' : 'en-US'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 渲染 uni-app 构建器稳定错误文案。 */
|
|
27
|
+
export function viteMessage(key: string, params: Record<string, string> = {}): string {
|
|
28
|
+
const template = messages[resolveViteLocale()][key] ?? messages['en-US'][key] ?? key
|
|
29
|
+
return template.replace(/\{([A-Za-z0-9_]+)\}/g, (_, name: string) => params[name] ?? `{${name}}`)
|
|
30
|
+
}
|
package/src/vite.ts
CHANGED
|
@@ -15,8 +15,9 @@ import uniPlugin from '@dcloudio/vite-plugin-uni'
|
|
|
15
15
|
import { defineConfig, loadEnv } from 'vite'
|
|
16
16
|
import type { Plugin, UserConfig } from 'vite'
|
|
17
17
|
import type { KratosAppModule, KratosAppPageConfig } from './module'
|
|
18
|
+
import { viteMessage } from './vite-messages.js'
|
|
18
19
|
|
|
19
|
-
export { defineConfig, loadEnv }
|
|
20
|
+
export { defineConfig, loadEnv, viteMessage }
|
|
20
21
|
export type { ConfigEnv, UserConfig } from 'vite'
|
|
21
22
|
|
|
22
23
|
type PageEntry = { path: string; style?: Record<string, unknown> }
|
|
@@ -343,7 +344,7 @@ function readBuildTransaction(
|
|
|
343
344
|
if (!existsSync(transactionFile)) return
|
|
344
345
|
const transaction = JSON.parse(readFileSync(transactionFile, 'utf8')) as BuildTransaction
|
|
345
346
|
if (transaction.inputDir !== inputDir || transaction.pagesFile !== pagesFile) {
|
|
346
|
-
throw new Error(
|
|
347
|
+
throw new Error(viteMessage('transaction_mismatch', { file: transactionFile }))
|
|
347
348
|
}
|
|
348
349
|
return transaction
|
|
349
350
|
}
|
|
@@ -459,7 +460,7 @@ function acquirePageAssemblyLock(lockFile: string): void {
|
|
|
459
460
|
continue
|
|
460
461
|
}
|
|
461
462
|
if (Date.now() >= deadline) {
|
|
462
|
-
throw new Error(
|
|
463
|
+
throw new Error(viteMessage('assembly_timeout', { file: lockFile }))
|
|
463
464
|
}
|
|
464
465
|
waitForPageAssembly(PAGE_ASSEMBLY_POLL_INTERVAL_MS)
|
|
465
466
|
}
|
|
@@ -637,7 +638,8 @@ function resolveSourceFile(target: string): string {
|
|
|
637
638
|
]
|
|
638
639
|
const resolved =
|
|
639
640
|
candidates.find((candidate) => existsSync(candidate) && statSync(candidate).isFile()) ?? target
|
|
640
|
-
if (!isAbsolute(resolved))
|
|
641
|
+
if (!isAbsolute(resolved))
|
|
642
|
+
throw new Error(viteMessage('source_path_not_absolute', { path: resolved }))
|
|
641
643
|
return resolved
|
|
642
644
|
}
|
|
643
645
|
|