@liujitcn/kratos-admin-core 0.0.29 → 0.0.32

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.
Files changed (147) hide show
  1. package/README.md +15 -8
  2. package/build/auto-imports.json +73 -0
  3. package/build/plugins.ts +2 -58
  4. package/dist/package/declarations/src/api/base/{config.d.ts → v1/config.d.ts} +1 -1
  5. package/dist/package/declarations/src/api/base/{file.d.ts → v1/file.d.ts} +3 -1
  6. package/dist/package/declarations/src/api/base/{language.d.ts → v1/language.d.ts} +1 -1
  7. package/dist/package/declarations/src/api/base/{login.d.ts → v1/login.d.ts} +2 -2
  8. package/dist/package/declarations/src/api/base/v1/mfa.d.ts +26 -0
  9. package/dist/package/declarations/src/api/base/{oauth.d.ts → v1/oauth.d.ts} +1 -1
  10. package/dist/package/declarations/src/api/system/{auth.d.ts → admin/v1/auth.d.ts} +2 -2
  11. package/dist/package/declarations/src/api/system/{base_dict.d.ts → admin/v1/base_dict.d.ts} +1 -1
  12. package/dist/package/declarations/src/api/system/{base_tenant.d.ts → admin/v1/base_tenant.d.ts} +2 -2
  13. package/dist/package/declarations/src/components/Dialog/FormDialog.vue.d.ts +3 -3
  14. package/dist/package/declarations/src/components/Dialog/PasswordVerifyDialog.vue.d.ts +65 -0
  15. package/dist/package/declarations/src/components/Dialog/ProDialog.vue.d.ts +1 -1
  16. package/dist/package/declarations/src/components/Grid/components/GridItem.vue.d.ts +1 -1
  17. package/dist/package/declarations/src/components/Mfa/MfaRecoveryCodesDialog.vue.d.ts +19 -0
  18. package/dist/package/declarations/src/components/Mfa/MfaSetupPanel.vue.d.ts +8 -0
  19. package/dist/package/declarations/src/components/ProForm/components/ProFormItem.vue.d.ts +4 -4
  20. package/dist/package/declarations/src/components/ProForm/index.vue.d.ts +1 -1
  21. package/dist/package/declarations/src/components/ProForm/interface/index.d.ts +4 -1
  22. package/dist/package/declarations/src/components/ProTable/index.vue.d.ts +114 -0
  23. package/dist/package/declarations/src/components/RichTextPreview/index.vue.d.ts +8 -0
  24. package/dist/package/declarations/src/components/TreeFilter/index.vue.d.ts +84 -76
  25. package/dist/package/declarations/src/components/Upload/File.vue.d.ts +1 -1
  26. package/dist/package/declarations/src/components/Upload/Files.vue.d.ts +1 -1
  27. package/dist/package/declarations/src/components/Upload/Img.vue.d.ts +2 -2
  28. package/dist/package/declarations/src/components/Upload/Imgs.vue.d.ts +2 -2
  29. package/dist/package/declarations/src/components/WangEditor/index.vue.d.ts +2 -0
  30. package/dist/package/declarations/src/documentTitle.d.ts +2 -0
  31. package/dist/package/declarations/src/format.d.ts +1 -1
  32. package/dist/package/declarations/src/index.d.ts +2 -1
  33. package/dist/package/declarations/src/layouts/components/LockScreen.vue.d.ts +3 -0
  34. package/dist/package/declarations/src/locales/generated.d.ts +208 -0
  35. package/dist/package/declarations/src/locales/index.d.ts +2 -0
  36. package/dist/package/declarations/src/modules/index.d.ts +1 -3
  37. package/dist/package/declarations/src/request.d.ts +1 -1
  38. package/dist/package/declarations/src/routers/index.d.ts +1 -1
  39. package/dist/package/declarations/src/rpc/base/v1/login.d.ts +37 -5
  40. package/dist/package/declarations/src/rpc/base/v1/mfa.d.ts +152 -0
  41. package/dist/package/declarations/src/rpc/base/v1/oauth.d.ts +25 -0
  42. package/dist/package/declarations/src/rpc/base/v1/oauth_client.d.ts +23 -0
  43. package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +13 -0
  44. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +0 -101
  45. package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n.d.ts +10 -6
  46. package/dist/package/declarations/src/rpc/system/common/v1/common.d.ts +26 -0
  47. package/dist/package/declarations/src/security.d.ts +2 -0
  48. package/dist/package/declarations/src/stores/interface/index.d.ts +19 -1
  49. package/dist/package/declarations/src/stores/modules/lockScreen.d.ts +20 -0
  50. package/dist/package/declarations/src/stores/modules/user.d.ts +7 -6
  51. package/dist/package/declarations/src/stores/runtime.d.ts +1 -0
  52. package/dist/package/declarations/src/utils/clipboard.d.ts +2 -0
  53. package/dist/package/declarations/src/utils/passwordStrength.d.ts +1 -12
  54. package/dist/package/declarations/src/utils/request.d.ts +13 -2
  55. package/dist/package/declarations/src/utils/utils.d.ts +4 -0
  56. package/dist/package/declarations/src/utils/webauthn.d.ts +4 -0
  57. package/dist/package/declarations/vite.config.d.ts +2 -0
  58. package/dist/package/src/api/base/{config.ts → v1/config.ts} +2 -2
  59. package/dist/package/src/api/base/{file.ts → v1/file.ts} +20 -24
  60. package/dist/package/src/api/base/{language.ts → v1/language.ts} +2 -2
  61. package/dist/package/src/api/base/{login.ts → v1/login.ts} +3 -3
  62. package/dist/package/src/api/base/v1/mfa.ts +114 -0
  63. package/dist/package/src/api/base/{oauth.ts → v1/oauth.ts} +2 -2
  64. package/dist/package/src/api/system/{auth.ts → admin/v1/auth.ts} +3 -3
  65. package/dist/package/src/api/system/{base_dict.ts → admin/v1/base_dict.ts} +2 -2
  66. package/dist/package/src/api/system/{base_tenant.ts → admin/v1/base_tenant.ts} +3 -3
  67. package/dist/package/src/bootstrap.ts +6 -5
  68. package/dist/package/src/components/CronExpression/index.vue +4 -3
  69. package/dist/package/src/components/Dialog/PasswordVerifyDialog.vue +176 -0
  70. package/dist/package/src/components/Dialog/ProDialog.vue +1 -0
  71. package/dist/package/src/components/ImportExcel/index.vue +4 -2
  72. package/dist/package/src/components/Loading/fullScreen.ts +2 -1
  73. package/dist/package/src/components/MarkdownPreview/index.vue +22 -2
  74. package/dist/package/src/components/Mfa/MfaRecoveryCodesDialog.vue +91 -0
  75. package/dist/package/src/components/Mfa/MfaSetupPanel.vue +81 -0
  76. package/dist/package/src/components/PasswordStrength/index.vue +1 -1
  77. package/dist/package/src/components/ProForm/components/ProFormItem.vue +16 -1
  78. package/dist/package/src/components/ProForm/interface/index.ts +4 -0
  79. package/dist/package/src/components/ProTable/components/ColSetting.vue +1 -1
  80. package/dist/package/src/components/ProTable/components/TableColumn.vue +14 -6
  81. package/dist/package/src/components/ProTable/index.vue +9 -5
  82. package/dist/package/src/components/RichTextPreview/index.vue +56 -0
  83. package/dist/package/src/components/SelectIcon/index.vue +3 -2
  84. package/dist/package/src/components/Upload/File.vue +2 -2
  85. package/dist/package/src/components/Upload/Files.vue +2 -2
  86. package/dist/package/src/components/Upload/Img.vue +7 -5
  87. package/dist/package/src/components/Upload/Imgs.vue +6 -5
  88. package/dist/package/src/components/WangEditor/index.vue +10 -7
  89. package/dist/package/src/config/index.ts +1 -1
  90. package/dist/package/src/documentTitle.ts +8 -0
  91. package/dist/package/src/format.ts +1 -1
  92. package/dist/package/src/index.ts +2 -1
  93. package/dist/package/src/layouts/LayoutClassic/index.vue +3 -1
  94. package/dist/package/src/layouts/LayoutColumns/index.vue +3 -1
  95. package/dist/package/src/layouts/LayoutTransverse/index.vue +3 -1
  96. package/dist/package/src/layouts/LayoutVertical/index.vue +9 -1
  97. package/dist/package/src/layouts/components/Header/components/Avatar.vue +26 -6
  98. package/dist/package/src/layouts/components/Header/components/InfoDialog.vue +4 -3
  99. package/dist/package/src/layouts/components/Header/components/PasswordDialog.vue +4 -3
  100. package/dist/package/src/layouts/components/Header/components/SearchMenu.vue +16 -8
  101. package/dist/package/src/layouts/components/LockScreen.vue +573 -0
  102. package/dist/package/src/layouts/components/Tabs/index.vue +12 -3
  103. package/dist/package/src/layouts/components/ThemeDrawer/index.scss +4 -4
  104. package/dist/package/src/layouts/index.vue +2 -0
  105. package/dist/package/src/layouts/indexAsync.vue +2 -0
  106. package/dist/package/src/locales/README.md +2 -1
  107. package/dist/package/src/locales/en-US.json +51 -3
  108. package/dist/package/src/locales/index.ts +16 -12
  109. package/dist/package/src/locales/ja-JP.json +51 -3
  110. package/dist/package/src/locales/zh-CN.json +51 -3
  111. package/dist/package/src/locales/zh-TW.json +51 -3
  112. package/dist/package/src/modules/index.ts +2 -4
  113. package/dist/package/src/request.ts +3 -0
  114. package/dist/package/src/routers/index.ts +15 -14
  115. package/dist/package/src/rpc/base/v1/login.ts +37 -4
  116. package/dist/package/src/rpc/base/v1/mfa.ts +180 -0
  117. package/dist/package/src/rpc/base/v1/oauth.ts +25 -0
  118. package/dist/package/src/rpc/base/v1/oauth_client.ts +33 -0
  119. package/dist/package/src/rpc/system/admin/v1/auth.ts +13 -0
  120. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +0 -112
  121. package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +10 -6
  122. package/dist/package/src/rpc/system/common/v1/common.ts +35 -0
  123. package/dist/package/src/security.ts +2 -0
  124. package/dist/package/src/stores/interface/index.ts +20 -1
  125. package/dist/package/src/stores/modules/auth.ts +1 -1
  126. package/dist/package/src/stores/modules/config.ts +2 -2
  127. package/dist/package/src/stores/modules/dict.ts +1 -1
  128. package/dist/package/src/stores/modules/lockScreen.ts +78 -0
  129. package/dist/package/src/stores/modules/user.ts +34 -22
  130. package/dist/package/src/stores/runtime.ts +1 -0
  131. package/dist/package/src/styles/element.scss +35 -4
  132. package/dist/package/src/utils/clipboard.ts +22 -0
  133. package/dist/package/src/utils/passwordCrypto.ts +1 -1
  134. package/dist/package/src/utils/passwordStrength.ts +7 -24
  135. package/dist/package/src/utils/request.ts +175 -40
  136. package/dist/package/src/utils/tenant.ts +1 -1
  137. package/dist/package/src/utils/utils.ts +25 -6
  138. package/dist/package/src/utils/webauthn.ts +90 -0
  139. package/dist/package/src/views/login/components/LoginForm.vue +257 -24
  140. package/dist/package/src/views/login/index.scss +2 -2
  141. package/dist/package/src/views/login/index.vue +3 -1
  142. package/dist/package/types/generated/auto-imports.d.ts +132 -129
  143. package/dist/package/types/generated/components.d.ts +4 -72
  144. package/package.json +22 -1
  145. package/types/generated/auto-imports.d.ts +132 -129
  146. package/types/generated/components.d.ts +4 -72
  147. package/vite.config.ts +4 -1
@@ -1,5 +1,5 @@
1
- import service from "../../utils/request";
2
- import type { DownloadFileRequest, MultiUploadFileResponse, FileInfo } from "../../rpc/base/v1/file";
1
+ import service from "../../../utils/request";
2
+ import type { DownloadFileRequest, MultiUploadFileResponse, FileInfo } from "../../../rpc/base/v1/file";
3
3
 
4
4
  const FILE_URL = "/v1/base/file";
5
5
 
@@ -35,33 +35,29 @@ export class FileServiceImpl {
35
35
  }
36
36
  });
37
37
  }
38
+
39
+ /** 读取文件内容并返回 Blob。 */
40
+ async GetFileBlob(file: string, fileName: string): Promise<Blob> {
41
+ const response = await service<DownloadFileRequest, any>({
42
+ url: `${FILE_URL}`,
43
+ method: "get",
44
+ params: {
45
+ name: fileName,
46
+ path: file
47
+ } as DownloadFileRequest,
48
+ responseType: "blob"
49
+ });
50
+ return response.data instanceof Blob ? response.data : new Blob([response.data]);
51
+ }
52
+
38
53
  /** 下载文件 */
39
- async DownloadFile(file: string, fileName: string) {
54
+ async DownloadFile(file: string, fileName: string): Promise<void> {
40
55
  try {
41
- const response = await service<DownloadFileRequest, any>({
42
- url: `${FILE_URL}`,
43
- method: "get",
44
- params: {
45
- name: fileName,
46
- path: file
47
- } as DownloadFileRequest,
48
- responseType: "blob" // 明确要求返回 Blob 类型
49
- });
50
- // 获取文件名
51
- const contentDisposition = response.headers["content-disposition"];
52
- let downloadFilename = fileName;
53
- if (contentDisposition) {
54
- const match = contentDisposition.match(/filename="?(.+?)"?$/);
55
- if (match && match[1]) {
56
- downloadFilename = match[1];
57
- }
58
- }
59
-
60
56
  // 创建下载链接
61
- const url = window.URL.createObjectURL(new Blob([response.data]));
57
+ const url = window.URL.createObjectURL(await this.GetFileBlob(file, fileName));
62
58
  const a = document.createElement("a");
63
59
  a.href = url;
64
- a.download = downloadFilename;
60
+ a.download = fileName;
65
61
  document.body.appendChild(a);
66
62
  a.click();
67
63
  document.body.removeChild(a);
@@ -1,5 +1,5 @@
1
- import service from "../../utils/request";
2
- import type { LanguageService, OptionLanguageRequest, OptionLanguageResponse } from "../../rpc/base/v1/language";
1
+ import service from "../../../utils/request";
2
+ import type { LanguageService, OptionLanguageRequest, OptionLanguageResponse } from "../../../rpc/base/v1/language";
3
3
 
4
4
  const LANGUAGE_URL = "/v1/base/language";
5
5
 
@@ -1,4 +1,4 @@
1
- import service from "../../utils/request";
1
+ import service from "../../../utils/request";
2
2
  import type {
3
3
  CaptchaRequest,
4
4
  CaptchaResponse,
@@ -12,8 +12,8 @@ import type {
12
12
  VerifyCaptchaRequest,
13
13
  VerifyCaptchaResponse,
14
14
  LoginService
15
- } from "../../rpc/base/v1/login";
16
- import type { Empty } from "../../rpc/google/protobuf/empty";
15
+ } from "../../../rpc/base/v1/login";
16
+ import type { Empty } from "../../../rpc/google/protobuf/empty";
17
17
 
18
18
  const CAPTCHA_URL = "/v1/base/captcha";
19
19
  const CAPTCHA_VERIFY_URL = "/v1/base/captcha/verify";
@@ -0,0 +1,114 @@
1
+ import service from "../../../utils/request";
2
+ import type { LoginResponse } from "../../../rpc/base/v1/login";
3
+ import type {
4
+ BeginMfaDisableRequest,
5
+ BeginMfaDisableResponse,
6
+ BeginMfaEnrollmentRequest,
7
+ BeginMfaEnrollmentResponse,
8
+ BeginMfaSetupRequest,
9
+ BeginMfaSetupResponse,
10
+ ConfirmMfaEnrollmentRequest,
11
+ ConfirmMfaEnrollmentResponse,
12
+ ConfirmMfaSetupRequest,
13
+ ConfirmMfaSetupResponse,
14
+ DisableMfaRequest,
15
+ GetMfaStatusRequest,
16
+ MfaService,
17
+ MfaStatusResponse,
18
+ RecoveryCodesResponse,
19
+ RegenerateMfaRecoveryCodesRequest,
20
+ VerifyMfaRequest
21
+ } from "../../../rpc/base/v1/mfa";
22
+ import type { Empty } from "../../../rpc/google/protobuf/empty";
23
+
24
+ const MFA_URL = "/v1/base/mfa";
25
+
26
+ /** 多因素认证公共服务。 */
27
+ export class MfaServiceImpl implements MfaService {
28
+ /** 校验登录阶段多因素认证。 */
29
+ VerifyMfa(request: VerifyMfaRequest): Promise<LoginResponse> {
30
+ return service<VerifyMfaRequest, LoginResponse>({
31
+ url: `${MFA_URL}/verify`,
32
+ method: "post",
33
+ data: request,
34
+ headers: { Authorization: "no-auth" }
35
+ });
36
+ }
37
+
38
+ /** 开始登录阶段的强制多因素认证绑定。 */
39
+ BeginMfaEnrollment(request: BeginMfaEnrollmentRequest): Promise<BeginMfaEnrollmentResponse> {
40
+ return service<BeginMfaEnrollmentRequest, BeginMfaEnrollmentResponse>({
41
+ url: `${MFA_URL}/enrollment`,
42
+ method: "post",
43
+ data: request,
44
+ headers: { Authorization: "no-auth" }
45
+ });
46
+ }
47
+
48
+ /** 确认登录阶段的强制多因素认证绑定。 */
49
+ ConfirmMfaEnrollment(request: ConfirmMfaEnrollmentRequest): Promise<ConfirmMfaEnrollmentResponse> {
50
+ return service<ConfirmMfaEnrollmentRequest, ConfirmMfaEnrollmentResponse>({
51
+ url: `${MFA_URL}/enrollment/confirm`,
52
+ method: "post",
53
+ data: request,
54
+ headers: { Authorization: "no-auth" }
55
+ });
56
+ }
57
+
58
+ /** 查询当前用户多因素认证状态。 */
59
+ GetMfaStatus(request: GetMfaStatusRequest): Promise<MfaStatusResponse> {
60
+ return service<GetMfaStatusRequest, MfaStatusResponse>({
61
+ url: MFA_URL,
62
+ method: "get",
63
+ params: request
64
+ });
65
+ }
66
+
67
+ /** 开始绑定当前用户的多因素认证方式。 */
68
+ BeginMfaSetup(request: BeginMfaSetupRequest): Promise<BeginMfaSetupResponse> {
69
+ return service<BeginMfaSetupRequest, BeginMfaSetupResponse>({
70
+ url: `${MFA_URL}/setup`,
71
+ method: "post",
72
+ data: request
73
+ });
74
+ }
75
+
76
+ /** 确认绑定当前用户的多因素认证方式。 */
77
+ ConfirmMfaSetup(request: ConfirmMfaSetupRequest): Promise<ConfirmMfaSetupResponse> {
78
+ return service<ConfirmMfaSetupRequest, ConfirmMfaSetupResponse>({
79
+ url: `${MFA_URL}/setup/confirm`,
80
+ method: "post",
81
+ data: request
82
+ });
83
+ }
84
+
85
+ /** 开始禁用 WebAuthn 多因素认证的 Passkey 验证。 */
86
+ BeginMfaDisable(request: BeginMfaDisableRequest): Promise<BeginMfaDisableResponse> {
87
+ return service<BeginMfaDisableRequest, BeginMfaDisableResponse>({
88
+ url: `${MFA_URL}/disable/challenge`,
89
+ method: "post",
90
+ data: request
91
+ });
92
+ }
93
+
94
+ /** 禁用当前用户的多因素认证。 */
95
+ DisableMfa(request: DisableMfaRequest): Promise<Empty> {
96
+ return service<DisableMfaRequest, Empty>({
97
+ url: `${MFA_URL}/disable`,
98
+ method: "post",
99
+ data: request
100
+ });
101
+ }
102
+
103
+ /** 重新生成当前用户的多因素认证恢复码。 */
104
+ RegenerateMfaRecoveryCodes(request: RegenerateMfaRecoveryCodesRequest): Promise<RecoveryCodesResponse> {
105
+ return service<RegenerateMfaRecoveryCodesRequest, RecoveryCodesResponse>({
106
+ url: `${MFA_URL}/recovery-codes`,
107
+ method: "post",
108
+ data: request
109
+ });
110
+ }
111
+ }
112
+
113
+ /** defMfaService 多因素认证公共服务实例。 */
114
+ export const defMfaService = new MfaServiceImpl();
@@ -1,4 +1,4 @@
1
- import service from "../../utils/request";
1
+ import service from "../../../utils/request";
2
2
  import type {
3
3
  CreateOauthAuthorizationRequest,
4
4
  CreateOauthAuthorizationResponse,
@@ -6,7 +6,7 @@ import type {
6
6
  ExchangeOauthTicketResponse,
7
7
  ListOauthProviderRequest,
8
8
  ListOauthProviderResponse
9
- } from "../../rpc/base/v1/oauth";
9
+ } from "../../../rpc/base/v1/oauth";
10
10
 
11
11
  const OAUTH_PROVIDER_URL = "/v1/base/oauth/provider";
12
12
  const OAUTH_AUTHORIZATION_URL = "/v1/base/oauth/authorization";
@@ -1,12 +1,12 @@
1
- import service from "../../utils/request";
1
+ import service from "../../../../utils/request";
2
2
  import type {
3
3
  GetUserInfoRequest,
4
4
  ListUserButtonRequest,
5
5
  TreeRouteResponse,
6
6
  TreeUserMenuRequest,
7
7
  UserInfoForm
8
- } from "../../rpc/system/admin/v1/auth";
9
- import type { StringValues } from "../../rpc/common/v1/types";
8
+ } from "../../../../rpc/system/admin/v1/auth";
9
+ import type { StringValues } from "../../../../rpc/common/v1/types";
10
10
 
11
11
  const AUTH_URL = "/v1/admin/auth";
12
12
 
@@ -1,5 +1,5 @@
1
- import service from "../../utils/request";
2
- import type { OptionBaseDictRequest, OptionBaseDictResponse } from "../../rpc/system/admin/v1/base_dict";
1
+ import service from "../../../../utils/request";
2
+ import type { OptionBaseDictRequest, OptionBaseDictResponse } from "../../../../rpc/system/admin/v1/base_dict";
3
3
 
4
4
  const BASE_DICT_URL = "/v1/admin/base/dict";
5
5
 
@@ -1,6 +1,6 @@
1
- import service from "../../utils/request";
2
- import type { SelectOptionResponse } from "../../rpc/common/v1/common";
3
- import type { OptionBaseTenantRequest } from "../../rpc/system/admin/v1/base_tenant";
1
+ import service from "../../../../utils/request";
2
+ import type { SelectOptionResponse } from "../../../../rpc/common/v1/common";
3
+ import type { OptionBaseTenantRequest } from "../../../../rpc/system/admin/v1/base_tenant";
4
4
 
5
5
  const BASE_TENANT_URL = "/v1/admin/base/tenant";
6
6
 
@@ -28,7 +28,8 @@ import { useDictStore } from "./stores/modules/dict";
28
28
  import { useTabsStore } from "./stores/modules/tabs";
29
29
  import { useUserStore } from "./stores/modules/user";
30
30
  import { getRouteMetaTitle } from "./utils";
31
- import { defLanguageService } from "./api/base/language";
31
+ import { defLanguageService } from "./api/base/v1/language";
32
+ import { setAdminDocumentTitle } from "./documentTitle";
32
33
 
33
34
  /**
34
35
  * 管理端启动参数。
@@ -44,7 +45,7 @@ export interface AdminBootstrapOptions {
44
45
  * 创建并启动管理端应用,业务项目可通过 modules 注册自己的页面。
45
46
  */
46
47
  export async function bootstrapAdminApp(options: AdminBootstrapOptions = {}) {
47
- const modules = [kratosAdminModule, ...(options.modules ?? [])];
48
+ const modules = [kratosAdminModule, ...(options.modules ?? [])];
48
49
  registerAdminModules(modules);
49
50
  registerLocaleMessages(modules);
50
51
  initializeLocale();
@@ -79,6 +80,7 @@ export async function bootstrapAdminApp(options: AdminBootstrapOptions = {}) {
79
80
  } catch {
80
81
  // 配置接口失败时继续使用本地默认配置,避免阻断应用启动。
81
82
  }
83
+ updateDocumentTitle();
82
84
 
83
85
  app.mount(options.mount ?? "#app");
84
86
  return app;
@@ -91,7 +93,7 @@ async function refreshLocalizedRuntimeData() {
91
93
  const dictStore = useDictStore(pinia);
92
94
  const configStore = useConfigStore(pinia);
93
95
  await Promise.allSettled([configStore.loadDisplayConfig()]);
94
- if (userStore.token || userStore.refreshToken) {
96
+ if (userStore.token) {
95
97
  await Promise.allSettled([authStore.getAuthMenuList(), dictStore.updateDictionaryCache()]);
96
98
  syncLocalizedRouteState();
97
99
  }
@@ -119,6 +121,5 @@ function updateDocumentTitle() {
119
121
  const route = router.currentRoute.value;
120
122
  const titleKey = typeof route.meta.titleKey === "string" ? route.meta.titleKey : "";
121
123
  const routeTitle = titleKey ? t(titleKey) : String(route.meta.title ?? "");
122
- const appTitle = import.meta.env.VITE_GLOB_APP_TITLE;
123
- document.title = routeTitle ? `${routeTitle} - ${appTitle}` : appTitle;
124
+ setAdminDocumentTitle(routeTitle);
124
125
  }
@@ -12,7 +12,7 @@
12
12
  </template>
13
13
  </el-input>
14
14
 
15
- <el-dialog v-model="dialogVisible" :title="t('core.cron.title')" width="980px" top="2vh" destroy-on-close>
15
+ <ProDialog v-model="dialogVisible" :title="t('core.cron.title')" width="980px" top="2vh" destroy-on-close>
16
16
  <div class="cron-editor">
17
17
  <div class="cron-editor__preset">
18
18
  <div class="cron-editor__section-title">{{ t("core.cron.presets") }}</div>
@@ -107,7 +107,7 @@
107
107
  <el-button @click="dialogVisible = false">{{ t("common.action.cancel") }}</el-button>
108
108
  </div>
109
109
  </template>
110
- </el-dialog>
110
+ </ProDialog>
111
111
  </div>
112
112
  </template>
113
113
 
@@ -116,6 +116,7 @@ import { computed, defineComponent, h, reactive, ref, watch } from "vue";
116
116
  import type { PropType } from "vue";
117
117
  import { ElCheckbox, ElCheckboxGroup, ElInputNumber, ElRadio } from "element-plus";
118
118
  import { Operation } from "@element-plus/icons-vue";
119
+ import ProDialog from "../../components/Dialog/ProDialog.vue";
119
120
  import { useLocaleStore } from "../../locales";
120
121
 
121
122
  const { t } = useLocaleStore();
@@ -669,7 +670,7 @@ const CronSegmentEditor = defineComponent({
669
670
  gap: 8px;
670
671
  padding: 12px;
671
672
  background: var(--el-fill-color-light);
672
- border-radius: 8px;
673
+ border-radius: var(--admin-page-radius);
673
674
  }
674
675
  .cron-editor__preset-list {
675
676
  display: flex;
@@ -0,0 +1,176 @@
1
+ <template>
2
+ <ProDialog
3
+ :model-value="modelValue"
4
+ :title="dialogTitle"
5
+ :width="width"
6
+ :top="top"
7
+ :confirm-text="confirmText"
8
+ :cancel-text="cancelText"
9
+ :confirm-loading="submitting"
10
+ :destroy-on-close="destroyOnClose"
11
+ :close-on-click-modal="closeOnClickModal"
12
+ :close-on-press-escape="closeOnPressEscape"
13
+ @update:model-value="handleVisibleChange"
14
+ @confirm="handleConfirm"
15
+ @cancel="handleCancel"
16
+ @close="handleClose"
17
+ @closed="handleClosed"
18
+ >
19
+ <p v-if="description" class="password-verify-dialog__description">{{ description }}</p>
20
+ <ProForm
21
+ ref="formRef"
22
+ :model="form"
23
+ :fields="fields"
24
+ :rules="rules"
25
+ :label-width="labelWidth"
26
+ @keyup.enter.prevent="handleConfirm"
27
+ />
28
+ </ProDialog>
29
+ </template>
30
+
31
+ <script setup lang="ts" name="PasswordVerifyDialog">
32
+ import { computed, reactive, ref } from "vue";
33
+ import type { FormRules } from "element-plus";
34
+ import ProDialog from "../../components/Dialog/ProDialog.vue";
35
+ import ProForm from "../../components/ProForm/index.vue";
36
+ import type { ProFormField, ProFormInstance } from "../../components/ProForm/interface";
37
+ import { useLocaleStore } from "../../locales";
38
+ import { PASSWORD_CRYPTO_SCENE, encryptPassword } from "../../utils/passwordCrypto";
39
+ import type { PasswordCryptoScene } from "../../utils/passwordCrypto";
40
+ import type { PasswordCrypto } from "../../rpc/common/v1/types";
41
+
42
+ const { t } = useLocaleStore();
43
+
44
+ /** 通用密码验证弹窗属性。 */
45
+ interface PasswordVerifyDialogProps {
46
+ /** 弹窗显示状态。 */
47
+ modelValue: boolean;
48
+ /** 弹窗标题。 */
49
+ title?: string;
50
+ /** 密码输入前的可选补充说明。 */
51
+ description?: string;
52
+ /** 弹窗宽度。 */
53
+ width?: string | number;
54
+ /** 弹窗顶部距离。 */
55
+ top?: string;
56
+ /** 密码字段标题。 */
57
+ passwordLabel?: string;
58
+ /** 密码输入提示。 */
59
+ passwordPlaceholder?: string;
60
+ /** 确认按钮文案。 */
61
+ confirmText?: string;
62
+ /** 取消按钮文案。 */
63
+ cancelText?: string;
64
+ /** 外部业务提交状态。 */
65
+ confirmLoading?: boolean;
66
+ /** 密码加密场景。 */
67
+ scene?: PasswordCryptoScene;
68
+ /** 是否关闭时销毁内容。 */
69
+ destroyOnClose?: boolean;
70
+ /** 是否允许点击遮罩关闭。 */
71
+ closeOnClickModal?: boolean;
72
+ /** 是否允许按 Esc 关闭。 */
73
+ closeOnPressEscape?: boolean;
74
+ /** 表单标签宽度。 */
75
+ labelWidth?: string;
76
+ }
77
+
78
+ const props = withDefaults(defineProps<PasswordVerifyDialogProps>(), {
79
+ title: "",
80
+ description: "",
81
+ width: "500px",
82
+ top: "8vh",
83
+ passwordLabel: "",
84
+ passwordPlaceholder: "",
85
+ confirmText: "",
86
+ cancelText: "",
87
+ confirmLoading: false,
88
+ scene: PASSWORD_CRYPTO_SCENE.PASSWORD_CRYPTO_SCENE_MFA,
89
+ destroyOnClose: false,
90
+ closeOnClickModal: false,
91
+ closeOnPressEscape: true,
92
+ labelWidth: "auto"
93
+ });
94
+
95
+ const emit = defineEmits<{
96
+ "update:modelValue": [value: boolean];
97
+ confirm: [password: PasswordCrypto];
98
+ cancel: [];
99
+ close: [];
100
+ closed: [];
101
+ }>();
102
+
103
+ const formRef = ref<ProFormInstance>();
104
+ const form = reactive({ password: "" });
105
+ const encrypting = ref(false);
106
+ const submitting = computed(() => props.confirmLoading || encrypting.value);
107
+ const dialogTitle = computed(() => props.title || t("core.password.verify_title"));
108
+ const passwordLabel = computed(() => props.passwordLabel || t("core.password.verify_label"));
109
+ const passwordPlaceholder = computed(() => props.passwordPlaceholder || t("core.password.required"));
110
+ const confirmText = computed(() => props.confirmText || t("common.action.confirm"));
111
+ const cancelText = computed(() => props.cancelText || t("common.action.cancel"));
112
+
113
+ const fields = computed<ProFormField[]>(() => [
114
+ {
115
+ prop: "password",
116
+ label: passwordLabel.value,
117
+ component: "password",
118
+ props: {
119
+ autocomplete: "current-password",
120
+ placeholder: passwordPlaceholder.value,
121
+ showPassword: true
122
+ }
123
+ }
124
+ ]);
125
+
126
+ const rules = computed<FormRules>(() => ({
127
+ password: [{ required: true, message: t("core.password.required"), trigger: "blur" }]
128
+ }));
129
+
130
+ /** 同步弹窗显示状态到外部。 */
131
+ function handleVisibleChange(value: boolean) {
132
+ emit("update:modelValue", value);
133
+ }
134
+
135
+ /** 校验密码并向业务方返回加密结果。 */
136
+ async function handleConfirm() {
137
+ if (submitting.value) return;
138
+ if (!(await formRef.value?.validate())) return;
139
+ encrypting.value = true;
140
+ try {
141
+ const password = await encryptPassword(form.password, props.scene);
142
+ emit("confirm", password);
143
+ } finally {
144
+ encrypting.value = false;
145
+ }
146
+ }
147
+
148
+ /** 对外透传取消事件。 */
149
+ function handleCancel() {
150
+ emit("cancel");
151
+ }
152
+
153
+ /** 对外透传关闭事件。 */
154
+ function handleClose() {
155
+ emit("close");
156
+ }
157
+
158
+ /** 关闭弹窗后清理密码和校验状态。 */
159
+ function handleClosed() {
160
+ form.password = "";
161
+ formRef.value?.clearValidate();
162
+ emit("closed");
163
+ }
164
+ </script>
165
+
166
+ <style scoped lang="scss">
167
+ .password-verify-dialog__description {
168
+ margin: 0 0 16px;
169
+ color: var(--el-text-color-regular);
170
+ line-height: 1.6;
171
+ }
172
+
173
+ .password-verify-dialog__description + :deep(.pro-form) {
174
+ margin-top: 0;
175
+ }
176
+ </style>
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <el-dialog
3
+ class="pro-dialog"
3
4
  :model-value="modelValue"
4
5
  :title="title"
5
6
  :width="width"
@@ -1,9 +1,10 @@
1
1
  <template>
2
- <el-dialog
2
+ <ProDialog
3
3
  v-model="dialogVisible"
4
4
  :title="t('core.upload.batch_add', { resource: parameter.title })"
5
5
  :destroy-on-close="true"
6
6
  width="580px"
7
+ :show-footer="false"
7
8
  draggable
8
9
  >
9
10
  <el-form class="drawer-multiColumn-form" label-width="180px">
@@ -44,11 +45,12 @@
44
45
  <el-switch v-model="isCover" />
45
46
  </el-form-item>
46
47
  </el-form>
47
- </el-dialog>
48
+ </ProDialog>
48
49
  </template>
49
50
 
50
51
  <script setup lang="ts" name="ImportExcel">
51
52
  import { ref } from "vue";
53
+ import ProDialog from "../../components/Dialog/ProDialog.vue";
52
54
  import { useDownload } from "../../hooks/useDownload";
53
55
  import { Download } from "@element-plus/icons-vue";
54
56
  import { ElNotification, UploadRequestOptions, UploadRawFile } from "element-plus";
@@ -1,4 +1,5 @@
1
1
  import { ElLoading } from "element-plus";
2
+ import { t } from "../../locales";
2
3
 
3
4
  /* 全局请求 loading */
4
5
  let loadingInstance: ReturnType<typeof ElLoading.service>;
@@ -10,7 +11,7 @@ const startLoading = () => {
10
11
  loadingInstance = ElLoading.service({
11
12
  fullscreen: true,
12
13
  lock: true,
13
- text: "Loading",
14
+ text: t("core.loading.text"),
14
15
  background: "rgba(0, 0, 0, 0.7)"
15
16
  });
16
17
  };
@@ -7,7 +7,7 @@
7
7
  :theme="props.isDark ? 'dark' : 'light'"
8
8
  preview-theme="github"
9
9
  code-theme="github"
10
- language="zh-CN"
10
+ :language="locale"
11
11
  :show-code-row-number="false"
12
12
  :code-foldable="false"
13
13
  :no-mermaid="true"
@@ -26,6 +26,7 @@ import DOMPurify from "dompurify";
26
26
  import hljs from "highlight.js";
27
27
  import { config as configureMarkdownPreview, MdPreview } from "md-editor-v3";
28
28
  import type { MdHeadingId } from "md-editor-v3";
29
+ import { getLocaleText, useLocaleStore } from "../../locales";
29
30
  import "md-editor-v3/lib/preview.css";
30
31
 
31
32
  defineOptions({
@@ -53,12 +54,31 @@ const props = withDefaults(defineProps<MarkdownPreviewProps>(), {
53
54
  const generatedId = useId();
54
55
  const resolvedId = computed(() => props.id || `core-markdown-preview-${generatedId.replaceAll(":", "")}`);
55
56
  const markdownHeadingIdCounts = new Map<string, number>();
57
+ const { locale } = useLocaleStore();
56
58
 
57
59
  configureMarkdownPreview({
58
60
  editorExtensions: {
59
61
  highlight: {
60
62
  instance: hljs
61
63
  }
64
+ },
65
+ editorConfig: {
66
+ languageUserDefined: {
67
+ "zh-TW": {
68
+ copyCode: {
69
+ text: getLocaleText("zh-TW", "core.markdown.action.copy_code"),
70
+ successTips: getLocaleText("zh-TW", "core.markdown.message.copy_success"),
71
+ failTips: getLocaleText("zh-TW", "core.markdown.message.copy_failed")
72
+ }
73
+ },
74
+ "ja-JP": {
75
+ copyCode: {
76
+ text: getLocaleText("ja-JP", "core.markdown.action.copy_code"),
77
+ successTips: getLocaleText("ja-JP", "core.markdown.message.copy_success"),
78
+ failTips: getLocaleText("ja-JP", "core.markdown.message.copy_failed")
79
+ }
80
+ }
81
+ }
62
82
  }
63
83
  });
64
84
 
@@ -221,7 +241,7 @@ function createMarkdownHeadingId({ text, index }: Parameters<MdHeadingId>[0]) {
221
241
  cursor: pointer;
222
242
  background: var(--admin-page-card-bg);
223
243
  border: 1px solid var(--admin-page-card-border-soft);
224
- border-radius: 4px;
244
+ border-radius: var(--admin-page-radius);
225
245
  box-shadow: var(--admin-page-shadow);
226
246
  }
227
247
  .core-markdown-preview :deep(.md-editor-code pre) {