@liujitcn/kratos-admin-core 0.0.38 → 0.0.40

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 (50) hide show
  1. package/README.md +2 -0
  2. package/build/codegen-hmr.ts +37 -0
  3. package/build/plugins.ts +2 -0
  4. package/build/source-patterns.ts +7 -0
  5. package/dist/package/declarations/build/codegen-hmr.d.ts +3 -0
  6. package/dist/package/declarations/build/source-patterns.d.ts +2 -0
  7. package/dist/package/declarations/src/components/ProForm/components/ProFormItem.vue.d.ts +9 -4
  8. package/dist/package/declarations/src/components/ProForm/interface/index.d.ts +2 -0
  9. package/dist/package/declarations/src/index.d.ts +5 -0
  10. package/dist/package/declarations/src/locales/generated.d.ts +12 -0
  11. package/dist/package/declarations/src/rpc/base/v1/language.d.ts +1 -1
  12. package/dist/package/declarations/src/rpc/base/v1/login.d.ts +2 -0
  13. package/dist/package/declarations/src/rpc/base/v1/mfa.d.ts +2 -0
  14. package/dist/package/declarations/src/rpc/base/v1/oauth.d.ts +4 -0
  15. package/dist/package/declarations/src/rpc/base/v1/oauth_client.d.ts +1 -1
  16. package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n.d.ts +1 -1
  17. package/dist/package/declarations/src/views/login/components/LoginForm.vue.d.ts +5 -1
  18. package/dist/package/src/components/ProForm/components/ProFormItem.vue +5 -1
  19. package/dist/package/src/components/ProForm/index.vue +27 -5
  20. package/dist/package/src/components/ProForm/interface/index.ts +2 -0
  21. package/dist/package/src/index.ts +5 -5
  22. package/dist/package/src/layouts/index.vue +0 -6
  23. package/dist/package/src/layouts/indexAsync.vue +0 -6
  24. package/dist/package/src/locales/en-US.json +4 -1
  25. package/dist/package/src/locales/ja-JP.json +4 -1
  26. package/dist/package/src/locales/zh-CN.json +4 -1
  27. package/dist/package/src/locales/zh-TW.json +4 -1
  28. package/dist/package/src/rpc/base/v1/config.ts +1 -1
  29. package/dist/package/src/rpc/base/v1/file.ts +1 -1
  30. package/dist/package/src/rpc/base/v1/language.ts +2 -2
  31. package/dist/package/src/rpc/base/v1/login.ts +3 -1
  32. package/dist/package/src/rpc/base/v1/mfa.ts +3 -1
  33. package/dist/package/src/rpc/base/v1/oauth.ts +5 -1
  34. package/dist/package/src/rpc/base/v1/oauth_client.ts +2 -2
  35. package/dist/package/src/rpc/common/v1/common.ts +1 -1
  36. package/dist/package/src/rpc/common/v1/enum.ts +1 -1
  37. package/dist/package/src/rpc/common/v1/types.ts +1 -1
  38. package/dist/package/src/rpc/google/protobuf/empty.ts +1 -1
  39. package/dist/package/src/rpc/google/protobuf/wrappers.ts +1 -1
  40. package/dist/package/src/rpc/system/admin/v1/auth.ts +1 -1
  41. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +1 -1
  42. package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +2 -2
  43. package/dist/package/src/rpc/system/admin/v1/base_tenant.ts +1 -1
  44. package/dist/package/src/rpc/system/admin/v1/common.ts +1 -1
  45. package/dist/package/src/rpc/system/common/v1/common.ts +1 -1
  46. package/dist/package/src/views/login/components/LoginForm.vue +66 -12
  47. package/dist/package/src/views/login/index.scss +24 -2
  48. package/dist/package/src/views/login/index.vue +3 -2
  49. package/package.json +2 -2
  50. package/vite.config.ts +2 -3
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # @liujitcn/kratos-admin-core
2
2
 
3
+ 账号密码、OAuth 票据兑换和微信登录统一返回 `mfa_remember_days`,表示当前登录策略允许的 MFA 设备免验证天数;为 `0` 时不提供记住设备选项。
4
+
3
5
  kratos-admin 前端底座包。它不包含具体业务模块,提供登录、MFA 校验、菜单、用户信息、应用启动、动态路由、布局、运行状态、公共组件和静态状态页;MFA 绑定面板与恢复码弹窗由登录页和 System 模块共用。宿主可以只安装 core;个人中心、AI 助手和系统管理能力必须由 System 模块提供。
4
6
 
5
7
  浏览器认证使用 Cookie-only 刷新令牌与内存访问令牌。Core 不持久化任何访问令牌或刷新令牌,刷新请求统一携带 `X-Refresh-Token-Transport: cookie` 并启用凭据 Cookie。
@@ -0,0 +1,37 @@
1
+ import type { HotPayload, Plugin, WebSocketClient } from "vite";
2
+
3
+ /** 暂缓生成期间的开发热更新,释放后统一刷新以加载完整产物。 */
4
+ export function codegenHmrPlugin(): Plugin {
5
+ return {
6
+ name: "admin-codegen-hmr",
7
+ apply: "serve",
8
+ configureServer(server) {
9
+ const clients = new Set<WebSocketClient>();
10
+ const send = server.ws.send.bind(server.ws);
11
+ let pending = false;
12
+ const release = (client: WebSocketClient) => {
13
+ clients.delete(client);
14
+ if (!clients.size && pending) {
15
+ pending = false;
16
+ send({ type: "full-reload", path: "*" });
17
+ }
18
+ };
19
+ server.ws.send = (payload: HotPayload | string, data?: unknown) => {
20
+ if (clients.size && typeof payload !== "string" && (payload.type === "update" || payload.type === "full-reload")) {
21
+ pending = true;
22
+ return;
23
+ }
24
+ if (typeof payload === "string") send(payload, data);
25
+ else send(payload);
26
+ };
27
+ server.ws.on("admin:codegen-hold", (_data, client) => {
28
+ if (!clients.has(client)) {
29
+ clients.add(client);
30
+ client.socket.once("close", () => release(client));
31
+ }
32
+ client.send("admin:codegen-held", {});
33
+ });
34
+ server.ws.on("admin:codegen-release", (_data, client) => release(client));
35
+ }
36
+ };
37
+ }
package/build/plugins.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { codegenHmrPlugin } from "./codegen-hmr";
1
2
  import { resolve } from "path";
2
3
  import { PluginOption } from "vite";
3
4
  import { VitePWA } from "vite-plugin-pwa";
@@ -37,6 +38,7 @@ export const createVitePlugins = (viteEnv: ViteEnv, options: VitePluginOptions =
37
38
  const { VITE_GLOB_APP_TITLE, VITE_REPORT, VITE_DEVTOOLS, VITE_PWA, VITE_CODEINSPECTOR } = viteEnv;
38
39
  const sourcePatterns = options.sourcePatterns;
39
40
  return [
41
+ codegenHmrPlugin(),
40
42
  vue(),
41
43
  // vue 可以使用 jsx/tsx 语法
42
44
  vueJsx(),
@@ -0,0 +1,7 @@
1
+ /** 为 API 和组件自动导入创建跨平台源码匹配规则,包含 npm 包内源码。 */
2
+ export function createSourcePatterns(sourceRoots: string[]): RegExp[] {
3
+ return [...new Set(sourceRoots.map(sourceRoot => sourceRoot.replaceAll("\\", "/")))].map(sourceRoot => {
4
+ const escapedRoot = sourceRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5
+ return new RegExp(`^${escapedRoot.replaceAll("/", "[/\\\\]")}[/\\\\].*\\.(?:vue|[jt]sx?)(?:\\?.*)?$`);
6
+ });
7
+ }
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from "vite";
2
+ /** 暂缓生成期间的开发热更新,释放后统一刷新以加载完整产物。 */
3
+ export declare function codegenHmrPlugin(): Plugin;
@@ -0,0 +1,2 @@
1
+ /** 为 API 和组件自动导入创建跨平台源码匹配规则,包含 npm 包内源码。 */
2
+ export declare function createSourcePatterns(sourceRoots: string[]): RegExp[];
@@ -4,18 +4,23 @@ interface ProFormItemProps {
4
4
  field: ProFormField;
5
5
  model: Record<string, any>;
6
6
  }
7
- declare var __VLS_127: string, __VLS_128: {
7
+ declare var __VLS_10: string, __VLS_11: {
8
+ field: ProFormField;
9
+ model: Record<string, any>;
10
+ }, __VLS_133: string, __VLS_134: {
8
11
  option: import("element-plus").TransferDataItem;
9
12
  field: ProFormField;
10
13
  model: Record<string, any>;
11
- }, __VLS_173: string, __VLS_174: {
14
+ }, __VLS_179: string, __VLS_180: {
12
15
  field: ProFormField;
13
16
  model: Record<string, any>;
14
17
  };
15
18
  type __VLS_Slots = {} & {
16
- [K in NonNullable<typeof __VLS_127>]?: (props: typeof __VLS_128) => any;
19
+ [K in NonNullable<typeof __VLS_10>]?: (props: typeof __VLS_11) => any;
20
+ } & {
21
+ [K in NonNullable<typeof __VLS_133>]?: (props: typeof __VLS_134) => any;
17
22
  } & {
18
- [K in NonNullable<typeof __VLS_173>]?: (props: typeof __VLS_174) => any;
23
+ [K in NonNullable<typeof __VLS_179>]?: (props: typeof __VLS_180) => any;
19
24
  };
20
25
  declare const __VLS_base: import("vue").DefineComponent<ProFormItemProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ProFormItemProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
26
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -33,6 +33,8 @@ export interface ProFormField {
33
33
  rowBreakBefore?: boolean;
34
34
  /** 自定义插槽名称。 */
35
35
  slotName?: string;
36
+ /** 输入控件旁的附加操作插槽。 */
37
+ suffixSlotName?: string;
36
38
  /** 标题提示文案。 */
37
39
  labelTooltip?: string;
38
40
  /** 字段校验规则。 */
@@ -1,3 +1,8 @@
1
+ import "./vite-env.d.ts";
2
+ import "./typings/global.d.ts";
3
+ import "./typings/utils.d.ts";
4
+ import "../types/generated/auto-imports.d.ts";
5
+ import "../types/generated/components.d.ts";
1
6
  export * from "./modules";
2
7
  export * from "./locales";
3
8
  export { defLanguageService } from "./api/base/v1/language";
@@ -181,6 +181,7 @@ export declare const LOCALE_MESSAGES: {
181
181
  "core.login.welcome": string;
182
182
  "core.login.mfa_title": string;
183
183
  "core.login.mfa_code": string;
184
+ "core.login.mfa_remember_device": string;
184
185
  "core.login.mfa_recovery_code": string;
185
186
  "core.login.mfa_setup_title": string;
186
187
  "core.login.mfa_setup_qr_alt": string;
@@ -337,6 +338,8 @@ export declare const LOCALE_MESSAGES: {
337
338
  "common.resource.default": string;
338
339
  "common.action.delete_resource": string;
339
340
  "common.action.set_field_status": string;
341
+ "core.home.demo_scope": string;
342
+ "core.home.main_title": string;
340
343
  };
341
344
  readonly "en-US": {
342
345
  "common.action.back": string;
@@ -514,6 +517,7 @@ export declare const LOCALE_MESSAGES: {
514
517
  "core.login.tenant_code": string;
515
518
  "core.login.user_name": string;
516
519
  "core.login.welcome": string;
520
+ "core.login.mfa_remember_device": string;
517
521
  "core.login.mfa_title": string;
518
522
  "core.login.mfa_code": string;
519
523
  "core.login.mfa_recovery_code": string;
@@ -672,6 +676,8 @@ export declare const LOCALE_MESSAGES: {
672
676
  "common.resource.default": string;
673
677
  "common.action.delete_resource": string;
674
678
  "common.action.set_field_status": string;
679
+ "core.home.demo_scope": string;
680
+ "core.home.main_title": string;
675
681
  };
676
682
  readonly "ja-JP": {
677
683
  "common.action.back": string;
@@ -730,6 +736,7 @@ export declare const LOCALE_MESSAGES: {
730
736
  "core.layout.avatar": string;
731
737
  "core.layout.logo_alt": string;
732
738
  "core.login.background_alt": string;
739
+ "core.login.mfa_remember_device": string;
733
740
  "core.login.mfa_title": string;
734
741
  "core.login.mfa_code": string;
735
742
  "core.login.mfa_recovery_code": string;
@@ -1007,6 +1014,8 @@ export declare const LOCALE_MESSAGES: {
1007
1014
  "common.resource.default": string;
1008
1015
  "common.action.delete_resource": string;
1009
1016
  "common.action.set_field_status": string;
1017
+ "core.home.demo_scope": string;
1018
+ "core.home.main_title": string;
1010
1019
  };
1011
1020
  readonly "zh-TW": {
1012
1021
  "common.action.back": string;
@@ -1065,6 +1074,7 @@ export declare const LOCALE_MESSAGES: {
1065
1074
  "core.layout.avatar": string;
1066
1075
  "core.layout.logo_alt": string;
1067
1076
  "core.login.background_alt": string;
1077
+ "core.login.mfa_remember_device": string;
1068
1078
  "core.login.mfa_title": string;
1069
1079
  "core.login.mfa_code": string;
1070
1080
  "core.login.mfa_recovery_code": string;
@@ -1342,6 +1352,8 @@ export declare const LOCALE_MESSAGES: {
1342
1352
  "common.resource.default": string;
1343
1353
  "common.action.delete_resource": string;
1344
1354
  "common.action.set_field_status": string;
1355
+ "core.home.demo_scope": string;
1356
+ "core.home.main_title": string;
1345
1357
  };
1346
1358
  };
1347
1359
  export type GeneratedLocale = keyof typeof LOCALE_MESSAGES;
@@ -13,7 +13,7 @@ export interface OptionLanguageResponse {
13
13
  /** 当前支持的语言列表 */
14
14
  languages: LanguageItem[];
15
15
  }
16
- /** 语言公共服务。 */
16
+ /** Base语言公共服务。 */
17
17
  export interface LanguageService {
18
18
  /** 查询当前支持的语言选项。 */
19
19
  OptionLanguage(request: OptionLanguageRequest): Promise<OptionLanguageResponse>;
@@ -133,6 +133,8 @@ export interface LoginResponse {
133
133
  mfa_method: string;
134
134
  /** WebAuthn认证选项JSON */
135
135
  mfa_webauthn_options_json: string;
136
+ /** 当前登录策略允许的MFA设备免验证天数 */
137
+ mfa_remember_days: number;
136
138
  }
137
139
  /** Base登录公共服务 */
138
140
  export interface LoginService {
@@ -11,6 +11,8 @@ export interface VerifyMfaRequest {
11
11
  recovery_code: string;
12
12
  /** WebAuthn认证响应JSON */
13
13
  webauthn_response_json: string;
14
+ /** 是否记住当前设备 */
15
+ remember_device: boolean;
14
16
  }
15
17
  /** 登录强制绑定多因素认证请求。 */
16
18
  export interface BeginMfaEnrollmentRequest {
@@ -89,6 +89,8 @@ export interface CreateOauthSessionResponse {
89
89
  mfa_method: string;
90
90
  /** WebAuthn认证选项JSON */
91
91
  mfa_webauthn_options_json: string;
92
+ /** 当前登录策略允许的MFA设备免验证天数 */
93
+ mfa_remember_days: number;
92
94
  }
93
95
  /** 三方登录回调请求 */
94
96
  export interface HandleOauthCallbackRequest {
@@ -133,6 +135,8 @@ export interface ExchangeOauthTicketResponse {
133
135
  mfa_method: string;
134
136
  /** WebAuthn认证选项JSON */
135
137
  mfa_webauthn_options_json: string;
138
+ /** 当前登录策略允许的MFA设备免验证天数 */
139
+ mfa_remember_days: number;
136
140
  }
137
141
  /** 个人中心三方账号绑定回调请求 */
138
142
  export interface HandleOauthBindingCallbackRequest {
@@ -16,7 +16,7 @@ export interface IssueOauthClientTokenResponse {
16
16
  /** 令牌有效时间,单位为秒 */
17
17
  expires_in: number;
18
18
  }
19
- /** 开放授权客户端令牌服务。 */
19
+ /** Base开放授权客户端令牌服务。 */
20
20
  export interface OauthClientService {
21
21
  /** 使用客户端凭据换取访问令牌。 */
22
22
  IssueOauthClientToken(request: IssueOauthClientTokenRequest): Promise<IssueOauthClientTokenResponse>;
@@ -70,7 +70,7 @@ export interface CodeGenLocaleConfig {
70
70
  /** 左树描述 */
71
71
  left_tree_comment: string;
72
72
  }
73
- /** 国际化翻译信息服务。 */
73
+ /** Admin国际化翻译信息服务。 */
74
74
  export interface BaseI18nService {
75
75
  /** 翻译单个文本。 */
76
76
  DraftBaseI18n(request: DraftBaseI18nRequest): Promise<DraftBaseI18nResponse>;
@@ -1,4 +1,8 @@
1
1
  import "go-captcha-vue/dist/style.css";
2
- declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ /** 登录表单属性,验证弹窗以外层登录卡片的中心定位。 */
3
+ interface LoginFormProps {
4
+ dialogAnchor?: HTMLElement;
5
+ }
6
+ declare const __VLS_export: import("vue").DefineComponent<LoginFormProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LoginFormProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
7
  declare const _default: typeof __VLS_export;
4
8
  export default _default;
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <el-input v-if="field.component === 'input'" v-model.trim="fieldValue" v-bind="fieldProps" />
2
+ <el-input v-if="field.component === 'input'" v-model.trim="fieldValue" v-bind="fieldProps">
3
+ <template v-if="field.suffixSlotName" #append>
4
+ <slot :name="field.suffixSlotName" :field="field" :model="model" />
5
+ </template>
6
+ </el-input>
3
7
 
4
8
  <el-input
5
9
  v-else-if="field.component === 'password'"
@@ -16,11 +16,21 @@
16
16
  </el-tooltip>
17
17
  </div>
18
18
  </template>
19
- <ProFormItem :field="field" :model="model">
20
- <template v-for="slotName in slotNames" #[slotName]="slotScope">
21
- <slot :name="slotName" v-bind="slotScope" />
22
- </template>
23
- </ProFormItem>
19
+ <div class="pro-form__control">
20
+ <div class="pro-form__input">
21
+ <ProFormItem :field="field" :model="model">
22
+ <template v-for="slotName in slotNames" #[slotName]="slotScope">
23
+ <slot :name="slotName" v-bind="slotScope" />
24
+ </template>
25
+ </ProFormItem>
26
+ </div>
27
+ <slot
28
+ v-if="field.suffixSlotName && field.component !== 'input'"
29
+ :name="field.suffixSlotName"
30
+ :model="model"
31
+ :field="field"
32
+ />
33
+ </div>
24
34
  </el-form-item>
25
35
  </el-col>
26
36
  </template>
@@ -104,6 +114,18 @@ defineExpose({
104
114
  </script>
105
115
 
106
116
  <style scoped lang="scss">
117
+ .pro-form__control {
118
+ display: flex;
119
+ align-items: flex-start;
120
+ gap: 8px;
121
+ width: 100%;
122
+ min-width: 0;
123
+ }
124
+ .pro-form__input {
125
+ flex: 1;
126
+ min-width: 0;
127
+ }
128
+
107
129
  .pro-form__row-break {
108
130
  flex: 0 0 100%;
109
131
  height: 0;
@@ -60,6 +60,8 @@ export interface ProFormField {
60
60
  rowBreakBefore?: boolean;
61
61
  /** 自定义插槽名称。 */
62
62
  slotName?: string;
63
+ /** 输入控件旁的附加操作插槽。 */
64
+ suffixSlotName?: string;
63
65
  /** 标题提示文案。 */
64
66
  labelTooltip?: string;
65
67
  /** 字段校验规则。 */
@@ -1,8 +1,8 @@
1
- /// <reference path="./vite-env.d.ts" />
2
- /// <reference path="./typings/global.d.ts" />
3
- /// <reference path="./typings/utils.d.ts" />
4
- /// <reference path="../types/generated/auto-imports.d.ts" />
5
- /// <reference path="../types/generated/components.d.ts" />
1
+ import "./vite-env.d.ts";
2
+ import "./typings/global.d.ts";
3
+ import "./typings/utils.d.ts";
4
+ import "../types/generated/auto-imports.d.ts";
5
+ import "../types/generated/components.d.ts";
6
6
 
7
7
  export * from "./modules";
8
8
  export * from "./locales";
@@ -44,9 +44,3 @@ watch(isDark, () => (font.color = isDark.value ? "rgba(255, 255, 255, .15)" : "r
44
44
  immediate: true
45
45
  });
46
46
  </script>
47
-
48
- <style scoped lang="scss">
49
- .layout {
50
- min-width: 600px;
51
- }
52
- </style>
@@ -48,9 +48,3 @@ watch(isDark, () => (font.color = isDark.value ? "rgba(255, 255, 255, .15)" : "r
48
48
  immediate: true
49
49
  });
50
50
  </script>
51
-
52
- <style scoped lang="scss">
53
- .layout {
54
- min-width: 600px;
55
- }
56
- </style>
@@ -174,6 +174,7 @@
174
174
  "core.login.tenant_code": "Enter tenant code",
175
175
  "core.login.user_name": "Enter username",
176
176
  "core.login.welcome": "Welcome to the admin console",
177
+ "core.login.mfa_remember_device": "Skip verification on this device for {days} days",
177
178
  "core.login.mfa_title": "Multi-factor authentication",
178
179
  "core.login.mfa_code": "Enter the authenticator code",
179
180
  "core.login.mfa_recovery_code": "Recovery code (optional)",
@@ -331,5 +332,7 @@
331
332
  "common.value.top_level": "Top level",
332
333
  "common.resource.default": "{resource}",
333
334
  "common.action.delete_resource": "Delete {resource}",
334
- "common.action.set_field_status": "Set {field}"
335
+ "common.action.set_field_status": "Set {field}",
336
+ "core.home.demo_scope": "Overview",
337
+ "core.home.main_title": "Admin Application"
335
338
  }
@@ -55,6 +55,7 @@
55
55
  "core.layout.avatar": "ユーザーアバター",
56
56
  "core.layout.logo_alt": "システムロゴ",
57
57
  "core.login.background_alt": "ログイン画面の背景",
58
+ "core.login.mfa_remember_device": "この端末では{days}日間、追加認証を省略する",
58
59
  "core.login.mfa_title": "多要素認証",
59
60
  "core.login.mfa_code": "認証コードを入力",
60
61
  "core.login.mfa_recovery_code": "リカバリーコード(任意)",
@@ -331,5 +332,7 @@
331
332
  "common.value.top_level": "トップレベル",
332
333
  "common.resource.default": "{resource}",
333
334
  "common.action.delete_resource": "{resource}を削除",
334
- "common.action.set_field_status": "{field}を設定"
335
+ "common.action.set_field_status": "{field}を設定",
336
+ "core.home.demo_scope": "機能概要",
337
+ "core.home.main_title": "管理アプリケーション"
335
338
  }
@@ -176,6 +176,7 @@
176
176
  "core.login.welcome": "欢迎登录管理后台",
177
177
  "core.login.mfa_title": "多因素认证",
178
178
  "core.login.mfa_code": "请输入动态口令",
179
+ "core.login.mfa_remember_device": "{days}天内免验证此设备",
179
180
  "core.login.mfa_recovery_code": "恢复码(可选)",
180
181
  "core.login.mfa_setup_title": "绑定多因素认证",
181
182
  "core.login.mfa_setup_qr_alt": "多因素认证绑定二维码",
@@ -331,5 +332,7 @@
331
332
  "common.value.top_level": "顶级节点",
332
333
  "common.resource.default": "{resource}",
333
334
  "common.action.delete_resource": "删除{resource}",
334
- "common.action.set_field_status": "设置{field}"
335
+ "common.action.set_field_status": "设置{field}",
336
+ "core.home.demo_scope": "功能概览",
337
+ "core.home.main_title": "管理应用"
335
338
  }
@@ -55,6 +55,7 @@
55
55
  "core.layout.avatar": "使用者頭像",
56
56
  "core.layout.logo_alt": "系統標誌",
57
57
  "core.login.background_alt": "登入頁背景",
58
+ "core.login.mfa_remember_device": "{days}天內免驗證此裝置",
58
59
  "core.login.mfa_title": "多因素認證",
59
60
  "core.login.mfa_code": "請輸入動態密碼",
60
61
  "core.login.mfa_recovery_code": "恢復碼(可選)",
@@ -331,5 +332,7 @@
331
332
  "common.value.top_level": "頂級節點",
332
333
  "common.resource.default": "{resource}",
333
334
  "common.action.delete_resource": "刪除{resource}",
334
- "common.action.set_field_status": "設定{field}"
335
+ "common.action.set_field_status": "設定{field}",
336
+ "core.home.demo_scope": "功能概覽",
337
+ "core.home.main_title": "管理應用程式"
335
338
  }
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/config.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/file.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/language.proto
6
6
 
@@ -24,7 +24,7 @@ export interface OptionLanguageResponse {
24
24
  languages: LanguageItem[];
25
25
  }
26
26
 
27
- /** 语言公共服务。 */
27
+ /** Base语言公共服务。 */
28
28
  export interface LanguageService {
29
29
  /** 查询当前支持的语言选项。 */
30
30
  OptionLanguage(request: OptionLanguageRequest): Promise<OptionLanguageResponse>;
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/login.proto
6
6
 
@@ -155,6 +155,8 @@ export interface LoginResponse {
155
155
  mfa_method: string;
156
156
  /** WebAuthn认证选项JSON */
157
157
  mfa_webauthn_options_json: string;
158
+ /** 当前登录策略允许的MFA设备免验证天数 */
159
+ mfa_remember_days: number;
158
160
  }
159
161
 
160
162
  /** Base登录公共服务 */
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/mfa.proto
6
6
 
@@ -19,6 +19,8 @@ export interface VerifyMfaRequest {
19
19
  recovery_code: string;
20
20
  /** WebAuthn认证响应JSON */
21
21
  webauthn_response_json: string;
22
+ /** 是否记住当前设备 */
23
+ remember_device: boolean;
22
24
  }
23
25
 
24
26
  /** 登录强制绑定多因素认证请求。 */
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/oauth.proto
6
6
 
@@ -109,6 +109,8 @@ export interface CreateOauthSessionResponse {
109
109
  mfa_method: string;
110
110
  /** WebAuthn认证选项JSON */
111
111
  mfa_webauthn_options_json: string;
112
+ /** 当前登录策略允许的MFA设备免验证天数 */
113
+ mfa_remember_days: number;
112
114
  }
113
115
 
114
116
  /** 三方登录回调请求 */
@@ -157,6 +159,8 @@ export interface ExchangeOauthTicketResponse {
157
159
  mfa_method: string;
158
160
  /** WebAuthn认证选项JSON */
159
161
  mfa_webauthn_options_json: string;
162
+ /** 当前登录策略允许的MFA设备免验证天数 */
163
+ mfa_remember_days: number;
160
164
  }
161
165
 
162
166
  /** 个人中心三方账号绑定回调请求 */
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: base/v1/oauth_client.proto
6
6
 
@@ -26,7 +26,7 @@ export interface IssueOauthClientTokenResponse {
26
26
  expires_in: number;
27
27
  }
28
28
 
29
- /** 开放授权客户端令牌服务。 */
29
+ /** Base开放授权客户端令牌服务。 */
30
30
  export interface OauthClientService {
31
31
  /** 使用客户端凭据换取访问令牌。 */
32
32
  IssueOauthClientToken(request: IssueOauthClientTokenRequest): Promise<IssueOauthClientTokenResponse>;
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: common/v1/common.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: common/v1/enum.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: common/v1/types.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: google/protobuf/empty.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: google/protobuf/wrappers.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: system/admin/v1/auth.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: system/admin/v1/base_dict.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: system/admin/v1/base_i18n.proto
6
6
 
@@ -85,7 +85,7 @@ export interface CodeGenLocaleConfig {
85
85
  left_tree_comment: string;
86
86
  }
87
87
 
88
- /** 国际化翻译信息服务。 */
88
+ /** Admin国际化翻译信息服务。 */
89
89
  export interface BaseI18nService {
90
90
  /** 翻译单个文本。 */
91
91
  DraftBaseI18n(request: DraftBaseI18nRequest): Promise<DraftBaseI18nResponse>;
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: system/admin/v1/base_tenant.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: system/admin/v1/common.proto
6
6
 
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.12.1
3
+ // protoc-gen-ts_proto v2.11.8
4
4
  // protoc unknown
5
5
  // source: system/common/v1/common.proto
6
6
 
@@ -63,13 +63,7 @@
63
63
  <el-icon><CircleClose /></el-icon>
64
64
  {{ t("common.action.reset") }}
65
65
  </el-button>
66
- <el-button
67
- round
68
- size="large"
69
- type="primary"
70
- :loading="loading || oauthTicketLoading"
71
- @click="handleLogin(loginFormRef)"
72
- >
66
+ <el-button round size="large" type="primary" :loading="loading || oauthTicketLoading" @click="handleLogin(loginFormRef)">
73
67
  <el-icon><UserFilled /></el-icon>
74
68
  {{ t("common.action.login") }}
75
69
  </el-button>
@@ -102,11 +96,11 @@
102
96
  <ProDialog
103
97
  v-model="behaviorDialogVisible"
104
98
  width="364px"
105
- top="16vh"
99
+ :style="loginDialogStyle"
106
100
  :show-close="false"
107
101
  :show-footer="false"
108
102
  append-to-body
109
- class="behavior-captcha-dialog"
103
+ class="login-verification-dialog behavior-captcha-dialog"
110
104
  >
111
105
  <div v-loading="behaviorLoading" class="behavior-captcha-body">
112
106
  <GoCaptchaSlide
@@ -132,7 +126,15 @@
132
126
  />
133
127
  </div>
134
128
  </ProDialog>
135
- <ProDialog v-model="mfaDialogVisible" :title="t('core.login.mfa_title')" width="360px" :close-on-click-modal="false">
129
+ <ProDialog
130
+ v-model="mfaDialogVisible"
131
+ :title="t('core.login.mfa_title')"
132
+ width="364px"
133
+ :style="loginDialogStyle"
134
+ class="login-verification-dialog"
135
+ append-to-body
136
+ :close-on-click-modal="false"
137
+ >
136
138
  <ProForm
137
139
  ref="mfaLoginFormRef"
138
140
  :model="mfaLoginForm"
@@ -142,6 +144,9 @@
142
144
  label-width="auto"
143
145
  @keyup.enter.prevent="verifyMfaLogin"
144
146
  />
147
+ <el-checkbox v-if="mfaRememberDays > 0" v-model="rememberMfaDevice">
148
+ {{ t("core.login.mfa_remember_device", { days: mfaRememberDays }) }}
149
+ </el-checkbox>
145
150
  <template #footer>
146
151
  <el-button @click="mfaDialogVisible = false">{{ t("common.action.cancel") }}</el-button>
147
152
  <el-button type="primary" :loading="mfaLoading" @click="verifyMfaLogin">
@@ -149,7 +154,15 @@
149
154
  </el-button>
150
155
  </template>
151
156
  </ProDialog>
152
- <ProDialog v-model="mfaSetupDialogVisible" :title="t('core.login.mfa_setup_title')" width="520px" :close-on-click-modal="false">
157
+ <ProDialog
158
+ v-model="mfaSetupDialogVisible"
159
+ :title="t('core.login.mfa_setup_title')"
160
+ width="520px"
161
+ :style="loginDialogStyle"
162
+ class="login-verification-dialog"
163
+ append-to-body
164
+ :close-on-click-modal="false"
165
+ >
153
166
  <template v-if="mfaSetupMethod !== 'webauthn'">
154
167
  <MfaSetupPanel :uri="mfaSetupUri" />
155
168
  <ProForm
@@ -172,6 +185,9 @@
172
185
  <MfaRecoveryCodesDialog
173
186
  v-model="recoveryCodesDialogVisible"
174
187
  :codes="recoveryCodes"
188
+ :style="loginDialogStyle"
189
+ class="login-verification-dialog"
190
+ append-to-body
175
191
  @confirm="finishMfaEnrollment"
176
192
  />
177
193
  </template>
@@ -179,6 +195,7 @@
179
195
  <script setup lang="ts">
180
196
  import { computed, ref, reactive, onMounted, watch } from "vue";
181
197
  import { useRoute, useRouter } from "vue-router";
198
+ import { useElementBounding } from "@vueuse/core";
182
199
  import { HOME_URL } from "../../../config";
183
200
  import { getTimeState } from "../../../utils";
184
201
  import { defLoginService } from "../../../api/base/v1/login";
@@ -207,6 +224,19 @@ import "go-captcha-vue/dist/style.css";
207
224
  import { useLocaleStore } from "../../../locales";
208
225
  import { clearPasswordChangeRequired, handlePasswordChangeRequired } from "../../../utils/request";
209
226
 
227
+ /** 登录表单属性,验证弹窗以外层登录卡片的中心定位。 */
228
+ interface LoginFormProps {
229
+ dialogAnchor?: HTMLElement;
230
+ }
231
+
232
+ const props = defineProps<LoginFormProps>();
233
+ const dialogAnchorBounds = useElementBounding(() => props.dialogAnchor);
234
+ const loginDialogStyle = computed(() => ({
235
+ "--login-dialog-center-x": `${dialogAnchorBounds.left.value + dialogAnchorBounds.width.value / 2}px`,
236
+ "--login-dialog-center-y": `${dialogAnchorBounds.top.value + dialogAnchorBounds.height.value / 2}px`,
237
+ "--login-dialog-anchor-width": `${dialogAnchorBounds.width.value}px`
238
+ }));
239
+
210
240
  const router = useRouter();
211
241
  const route = useRoute();
212
242
  const userStore = useUserStore();
@@ -242,6 +272,8 @@ const mfaChallengeId = ref("");
242
272
  const mfaLoginFormRef = ref<ProFormInstance>();
243
273
  const mfaLoginForm = reactive({ code: "", recoveryCode: "" });
244
274
  const mfaMethod = ref("totp");
275
+ const mfaRememberDays = ref(0);
276
+ const rememberMfaDevice = ref(false);
245
277
  const mfaWebAuthnOptionsJson = ref("");
246
278
  const mfaSetupDialogVisible = ref(false);
247
279
  const mfaSetupTicket = ref("");
@@ -576,6 +608,8 @@ const handleLoginResponse = async (result: LoginResponse) => {
576
608
  if (result.status === LoginStatus.LOGIN_STATUS_MFA_REQUIRED) {
577
609
  mfaChallengeId.value = result.mfa_challenge_id;
578
610
  mfaMethod.value = result.mfa_method || "totp";
611
+ mfaRememberDays.value = result.mfa_remember_days || 0;
612
+ rememberMfaDevice.value = false;
579
613
  mfaWebAuthnOptionsJson.value = result.mfa_webauthn_options_json || "";
580
614
  mfaLoginForm.code = "";
581
615
  mfaLoginForm.recoveryCode = "";
@@ -612,7 +646,8 @@ const verifyMfaLogin = async () => {
612
646
  challenge_id: mfaChallengeId.value,
613
647
  code: useRecoveryCode ? "" : mfaLoginForm.code,
614
648
  recovery_code: mfaLoginForm.recoveryCode,
615
- webauthn_response_json: webauthnResponseJson
649
+ webauthn_response_json: webauthnResponseJson,
650
+ remember_device: rememberMfaDevice.value
616
651
  });
617
652
  mfaDialogVisible.value = false;
618
653
  await handleLoginResponse(result);
@@ -960,6 +995,25 @@ watch(
960
995
  color: var(--el-color-primary);
961
996
  }
962
997
 
998
+ /* 各验证步骤共用登录卡片中心;靠近视口边缘时限制尺寸,内容在弹窗内滚动。 */
999
+ :global(.login-verification-dialog.el-dialog) {
1000
+ --login-dialog-width: min(var(--el-dialog-width), var(--login-dialog-anchor-width), calc(100vw - 32px));
1001
+ --login-dialog-y: clamp(25dvh, var(--login-dialog-center-y), 75dvh);
1002
+
1003
+ position: fixed;
1004
+ top: var(--login-dialog-y);
1005
+ left: clamp(
1006
+ calc(var(--login-dialog-width) / 2 + 16px),
1007
+ var(--login-dialog-center-x),
1008
+ calc(100vw - var(--login-dialog-width) / 2 - 16px)
1009
+ );
1010
+ width: var(--login-dialog-width);
1011
+ max-height: calc(min(var(--login-dialog-y), 100dvh - var(--login-dialog-y)) * 2 - 32px);
1012
+ margin: 0;
1013
+ overflow: auto;
1014
+ translate: -50% -50%;
1015
+ }
1016
+
963
1017
  :global(.behavior-captcha-dialog) {
964
1018
  --go-captcha-theme-text-color: var(--el-text-color-primary);
965
1019
  --go-captcha-theme-bg-color: var(--el-bg-color);
@@ -1,4 +1,8 @@
1
1
  .login-container {
2
+ box-sizing: border-box;
3
+ width: 100%;
4
+ max-width: 100%;
5
+ overflow-x: hidden;
2
6
  height: 100%;
3
7
  min-height: 550px;
4
8
  background-color: #eeeeee;
@@ -9,6 +13,8 @@
9
13
  position: relative;
10
14
  box-sizing: border-box;
11
15
  display: flex;
16
+ min-width: 0;
17
+ max-width: calc(100% - 32px);
12
18
  align-items: center;
13
19
  justify-content: space-around;
14
20
  width: 96.5%;
@@ -28,6 +34,9 @@
28
34
  right: 72px;
29
35
  }
30
36
  .login-left {
37
+ min-width: 0;
38
+ max-width: 800px;
39
+ flex: 1 1 800px;
31
40
  width: 800px;
32
41
  margin-right: 10px;
33
42
  .login-left-img {
@@ -36,7 +45,10 @@
36
45
  }
37
46
  }
38
47
  .login-form {
48
+ position: relative;
39
49
  box-sizing: border-box;
50
+ min-width: 0;
51
+ flex: 0 1 420px;
40
52
  width: 420px;
41
53
  max-width: 100%;
42
54
  padding: 50px 40px 45px;
@@ -82,7 +94,8 @@
82
94
  margin-top: 40px;
83
95
  white-space: nowrap;
84
96
  .el-button {
85
- width: 185px;
97
+ width: calc(50% - 6px);
98
+ min-width: 0;
86
99
  }
87
100
  }
88
101
  }
@@ -93,11 +106,20 @@
93
106
  .login-left {
94
107
  display: none;
95
108
  }
109
+
110
+ .login-container .login-box {
111
+ justify-content: center;
112
+ }
96
113
  }
97
114
 
98
115
  @media screen and (width <= 600px) {
116
+ .login-container .login-box {
117
+ max-width: calc(100% - 16px);
118
+ padding: 0 8px;
119
+ }
120
+
99
121
  .login-form {
100
- width: 97% !important;
122
+ width: 100% !important;
101
123
  padding: 40px 24px 32px !important;
102
124
  .login-logo {
103
125
  margin-bottom: 32px !important;
@@ -6,12 +6,12 @@
6
6
  <div class="login-left">
7
7
  <img class="login-left-img" :src="backgroundUrl" :alt="t('core.login.background_alt')" />
8
8
  </div>
9
- <div class="login-form">
9
+ <div ref="loginFormRef" class="login-form">
10
10
  <div ref="loginLogoRef" class="login-logo">
11
11
  <img v-show="showLogoIcon" ref="logoIconRef" class="login-icon" :src="logoUrl" alt="" />
12
12
  <h2 ref="logoTextRef" class="logo-text" :style="{ fontSize: `${logoFontSize}px` }">{{ projectName }}</h2>
13
13
  </div>
14
- <LoginForm />
14
+ <LoginForm :dialog-anchor="loginFormRef" />
15
15
  </div>
16
16
  </div>
17
17
  </div>
@@ -36,6 +36,7 @@ const PREFERRED_MIN_LOGO_FONT_SIZE = 30;
36
36
  const MIN_LOGO_FONT_SIZE = 8;
37
37
  const LOGO_TEXT_GAP = 16;
38
38
 
39
+ const loginFormRef = ref<HTMLElement>();
39
40
  const loginLogoRef = ref<HTMLElement>();
40
41
  const logoIconRef = ref<HTMLImageElement>();
41
42
  const logoTextRef = ref<HTMLElement>();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@liujitcn/kratos-admin-core",
3
3
  "private": false,
4
- "version": "0.0.38",
4
+ "version": "0.0.40",
5
5
  "type": "module",
6
6
  "description": "kratos-admin frontend runtime and base modules",
7
7
  "author": {
@@ -224,7 +224,7 @@
224
224
  "scripts": {
225
225
  "build": "pnpm build:package",
226
226
  "build:package": "node ../../scripts/build-package.mjs .",
227
- "test": "tsc -p tsconfig.test.json && node --test dist/test/tests/modules.test.js dist/test/tests/dict.test.js dist/test/tests/menu.test.js",
227
+ "test": "tsc -p tsconfig.test.json && node --test dist/test/tests/modules.test.js dist/test/tests/dict.test.js dist/test/tests/menu.test.js dist/test/tests/source-patterns.test.js",
228
228
  "type:check": "vue-tsc --noEmit --skipLibCheck"
229
229
  }
230
230
  }
package/vite.config.ts CHANGED
@@ -8,6 +8,7 @@ import dayjs from "dayjs";
8
8
  import { wrapperEnv } from "./build/getEnv";
9
9
  import { createProxy } from "./build/proxy";
10
10
  import { createVitePlugins } from "./build/plugins";
11
+ import { createSourcePatterns } from "./build/source-patterns";
11
12
 
12
13
  const coreRoot = dirname(fileURLToPath(import.meta.url));
13
14
  const viteLogger = createLogger();
@@ -52,9 +53,7 @@ export function defineAdminViteConfig(options: AdminViteConfigOptions = {}) {
52
53
  ...resolvePackageSource(root, packageName)
53
54
  }));
54
55
  const sourceRoots = [resolve(root, "src"), coreSourceRoot, ...modulePackages.map(item => item.sourceRoot)];
55
- const sourcePatterns = [...new Set(sourceRoots)].map(
56
- sourceRoot => new RegExp(`${escapeRegExp(sourceRoot)}[\\/\\\\].*\\.(?:vue|[jt]sx?)(?:\\?.*)?$`)
57
- );
56
+ const sourcePatterns = createSourcePatterns(sourceRoots);
58
57
  const aliases = [
59
58
  { find: "@", replacement: coreSourceRoot },
60
59
  ...createPackageAliases(corePackage),