@liujitcn/kratos-admin-core 0.0.31 → 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.
- package/README.md +10 -4
- package/dist/package/declarations/src/api/base/{config.d.ts → v1/config.d.ts} +1 -1
- package/dist/package/declarations/src/api/base/{file.d.ts → v1/file.d.ts} +3 -1
- package/dist/package/declarations/src/api/base/{language.d.ts → v1/language.d.ts} +1 -1
- package/dist/package/declarations/src/api/base/{login.d.ts → v1/login.d.ts} +2 -2
- package/dist/package/declarations/src/api/base/{mfa.d.ts → v1/mfa.d.ts} +3 -3
- package/dist/package/declarations/src/api/base/{oauth.d.ts → v1/oauth.d.ts} +1 -1
- package/dist/package/declarations/src/api/system/{auth.d.ts → admin/v1/auth.d.ts} +2 -2
- package/dist/package/declarations/src/api/system/{base_dict.d.ts → admin/v1/base_dict.d.ts} +1 -1
- package/dist/package/declarations/src/api/system/{base_tenant.d.ts → admin/v1/base_tenant.d.ts} +2 -2
- package/dist/package/declarations/src/components/ProTable/index.vue.d.ts +114 -0
- package/dist/package/declarations/src/components/TreeFilter/index.vue.d.ts +84 -76
- package/dist/package/declarations/src/components/Upload/File.vue.d.ts +1 -1
- package/dist/package/declarations/src/components/Upload/Files.vue.d.ts +1 -1
- package/dist/package/declarations/src/components/Upload/Img.vue.d.ts +1 -1
- package/dist/package/declarations/src/components/Upload/Imgs.vue.d.ts +1 -1
- package/dist/package/declarations/src/components/WangEditor/index.vue.d.ts +2 -0
- package/dist/package/declarations/src/documentTitle.d.ts +2 -0
- package/dist/package/declarations/src/format.d.ts +1 -1
- package/dist/package/declarations/src/index.d.ts +2 -1
- package/dist/package/declarations/src/locales/generated.d.ts +40 -0
- package/dist/package/declarations/src/modules/index.d.ts +1 -3
- package/dist/package/declarations/src/request.d.ts +1 -1
- package/dist/package/declarations/src/routers/index.d.ts +1 -1
- package/dist/package/declarations/src/rpc/base/v1/login.d.ts +5 -3
- package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +13 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +0 -101
- package/dist/package/declarations/src/rpc/system/common/v1/common.d.ts +26 -0
- package/dist/package/declarations/src/stores/interface/index.d.ts +6 -1
- package/dist/package/declarations/src/stores/modules/user.d.ts +2 -4
- package/dist/package/declarations/src/utils/passwordStrength.d.ts +1 -12
- package/dist/package/declarations/src/utils/request.d.ts +13 -2
- package/dist/package/declarations/src/utils/utils.d.ts +4 -0
- package/dist/package/src/api/base/{config.ts → v1/config.ts} +2 -2
- package/dist/package/src/api/base/{file.ts → v1/file.ts} +20 -24
- package/dist/package/src/api/base/{language.ts → v1/language.ts} +2 -2
- package/dist/package/src/api/base/{login.ts → v1/login.ts} +3 -3
- package/dist/package/src/api/base/{mfa.ts → v1/mfa.ts} +4 -4
- package/dist/package/src/api/base/{oauth.ts → v1/oauth.ts} +2 -2
- package/dist/package/src/api/system/{auth.ts → admin/v1/auth.ts} +3 -3
- package/dist/package/src/api/system/{base_dict.ts → admin/v1/base_dict.ts} +2 -2
- package/dist/package/src/api/system/{base_tenant.ts → admin/v1/base_tenant.ts} +3 -3
- package/dist/package/src/bootstrap.ts +6 -5
- package/dist/package/src/components/CronExpression/index.vue +4 -3
- package/dist/package/src/components/Dialog/ProDialog.vue +1 -0
- package/dist/package/src/components/ImportExcel/index.vue +4 -2
- package/dist/package/src/components/MarkdownPreview/index.vue +1 -1
- package/dist/package/src/components/PasswordStrength/index.vue +1 -1
- package/dist/package/src/components/ProTable/components/TableColumn.vue +14 -6
- package/dist/package/src/components/ProTable/index.vue +3 -3
- package/dist/package/src/components/RichTextPreview/index.vue +12 -1
- package/dist/package/src/components/SelectIcon/index.vue +3 -2
- package/dist/package/src/components/Upload/File.vue +2 -2
- package/dist/package/src/components/Upload/Files.vue +2 -2
- package/dist/package/src/components/Upload/Img.vue +7 -5
- package/dist/package/src/components/Upload/Imgs.vue +6 -5
- package/dist/package/src/components/WangEditor/index.vue +10 -7
- package/dist/package/src/documentTitle.ts +8 -0
- package/dist/package/src/format.ts +1 -1
- package/dist/package/src/index.ts +2 -1
- package/dist/package/src/layouts/components/Header/components/Avatar.vue +7 -6
- package/dist/package/src/layouts/components/Header/components/InfoDialog.vue +3 -2
- package/dist/package/src/layouts/components/Header/components/PasswordDialog.vue +3 -2
- package/dist/package/src/layouts/components/Header/components/SearchMenu.vue +16 -8
- package/dist/package/src/layouts/components/LockScreen.vue +175 -52
- package/dist/package/src/layouts/components/Tabs/index.vue +12 -3
- package/dist/package/src/layouts/components/ThemeDrawer/index.scss +4 -4
- package/dist/package/src/locales/en-US.json +8 -2
- package/dist/package/src/locales/ja-JP.json +8 -2
- package/dist/package/src/locales/zh-CN.json +8 -2
- package/dist/package/src/locales/zh-TW.json +8 -2
- package/dist/package/src/modules/index.ts +2 -4
- package/dist/package/src/request.ts +3 -0
- package/dist/package/src/routers/index.ts +15 -14
- package/dist/package/src/rpc/base/v1/login.ts +4 -2
- package/dist/package/src/rpc/system/admin/v1/auth.ts +13 -0
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +0 -112
- package/dist/package/src/rpc/system/common/v1/common.ts +35 -0
- package/dist/package/src/stores/interface/index.ts +6 -1
- package/dist/package/src/stores/modules/auth.ts +1 -1
- package/dist/package/src/stores/modules/config.ts +2 -2
- package/dist/package/src/stores/modules/dict.ts +1 -1
- package/dist/package/src/stores/modules/user.ts +21 -22
- package/dist/package/src/styles/element.scss +35 -4
- package/dist/package/src/utils/passwordCrypto.ts +1 -1
- package/dist/package/src/utils/passwordStrength.ts +7 -24
- package/dist/package/src/utils/request.ts +155 -36
- package/dist/package/src/utils/tenant.ts +1 -1
- package/dist/package/src/utils/utils.ts +25 -6
- package/dist/package/src/views/login/components/LoginForm.vue +32 -20
- package/dist/package/src/views/login/index.scss +2 -2
- package/package.json +1 -1
- package/vite.config.ts +1 -0
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"common.validation.phone_required": "請輸入手機號碼",
|
|
34
34
|
"common.title.notice": "提示",
|
|
35
35
|
"common.title.warning": "溫馨提示",
|
|
36
|
+
"common.confirm.delete": "確定要刪除嗎?",
|
|
36
37
|
"common.placeholder.input": "請輸入",
|
|
37
38
|
"common.placeholder.input_content": "請輸入內容",
|
|
38
39
|
"common.placeholder.select": "請選擇",
|
|
@@ -162,6 +163,7 @@
|
|
|
162
163
|
"core.layout.home": "首頁",
|
|
163
164
|
"core.layout.info": "個人資訊",
|
|
164
165
|
"core.layout.password_change": "修改密碼",
|
|
166
|
+
"core.layout.password_change_required": "密碼已過期,請先修改密碼",
|
|
165
167
|
"core.layout.unnamed_menu": "未命名選單",
|
|
166
168
|
"core.layout.lock_screen": "鎖定螢幕",
|
|
167
169
|
"core.layout.lock_screen_action": "鎖定",
|
|
@@ -197,7 +199,7 @@
|
|
|
197
199
|
"core.oauth.wechatmp": "微信公眾號",
|
|
198
200
|
"core.oauth.wechatwork": "企業微信",
|
|
199
201
|
"core.oauth.unknown": "未知方式",
|
|
200
|
-
"core.password.error": "
|
|
202
|
+
"core.password.error": "密碼不符合目前生效的密碼策略",
|
|
201
203
|
"core.password.crypto_unsupported": "當前環境不支援密碼加密",
|
|
202
204
|
"core.password.required": "密碼不能為空",
|
|
203
205
|
"core.password.verify_title": "驗證密碼",
|
|
@@ -207,7 +209,7 @@
|
|
|
207
209
|
"core.password.strength.high": "高",
|
|
208
210
|
"core.password.strength.low": "低",
|
|
209
211
|
"core.password.strength.medium": "中",
|
|
210
|
-
"core.password.tip": "
|
|
212
|
+
"core.password.tip": "密碼要求以目前生效的密碼策略為準。",
|
|
211
213
|
"core.theme.accordion": "選單手風琴",
|
|
212
214
|
"core.theme.aside_inverted": "側邊欄反轉色",
|
|
213
215
|
"core.theme.aside_inverted_tip": "側邊欄顏色變為深色模式",
|
|
@@ -291,11 +293,15 @@
|
|
|
291
293
|
"common.dialog.resource_field": "{field}:{value}",
|
|
292
294
|
"common.dialog.status_change": "是否確定{action}{resource}?\n{field}:{value}",
|
|
293
295
|
"common.field.created_at": "建立時間",
|
|
296
|
+
"common.field.department": "部門",
|
|
297
|
+
"common.field.post": "崗位",
|
|
294
298
|
"common.field.remark": "備註",
|
|
299
|
+
"common.field.role": "角色",
|
|
295
300
|
"common.field.sort": "排序",
|
|
296
301
|
"common.field.status": "狀態",
|
|
297
302
|
"common.field.tenant": "租戶",
|
|
298
303
|
"common.field.updated_at": "更新時間",
|
|
304
|
+
"common.field.user": "使用者",
|
|
299
305
|
"common.message.create_success": "新增{resource}成功",
|
|
300
306
|
"common.message.delete_success": "刪除{resource}成功",
|
|
301
307
|
"common.message.load_children_failed": "載入{resource}子節點失敗",
|
|
@@ -43,10 +43,8 @@ export interface AdminHeaderTool {
|
|
|
43
43
|
export interface AdminUserMenuAction {
|
|
44
44
|
/** 操作唯一名称。 */
|
|
45
45
|
name: string;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
/** 兼容未迁移模块的静态显示名称。 */
|
|
49
|
-
label?: string;
|
|
46
|
+
/** 操作显示名称对应的稳定语言键。 */
|
|
47
|
+
labelKey: string;
|
|
50
48
|
/** 对应后端动态菜单名称,菜单不存在时不显示操作。 */
|
|
51
49
|
menuName: string;
|
|
52
50
|
/** 操作图标。 */
|
|
@@ -2,8 +2,11 @@ export { default } from "./utils/request";
|
|
|
2
2
|
export {
|
|
3
3
|
ensureAccessToken,
|
|
4
4
|
getRequestAccessToken,
|
|
5
|
+
handlePasswordChangeRequired,
|
|
5
6
|
handleAuthExpired,
|
|
6
7
|
hasValidAccessToken,
|
|
8
|
+
clearPasswordChangeRequired,
|
|
9
|
+
passwordChangeState,
|
|
7
10
|
requestBaseURL
|
|
8
11
|
} from "./utils/request";
|
|
9
12
|
export { getLocaleRequestHeaders } from "./locales";
|
|
@@ -7,6 +7,8 @@ import NProgress from "../config/nprogress";
|
|
|
7
7
|
import { isUnmatchedRoute } from "../utils/router";
|
|
8
8
|
import { ensureAccessToken } from "../utils/request";
|
|
9
9
|
import { t } from "../locales";
|
|
10
|
+
import { useUserStore } from "../stores/modules/user";
|
|
11
|
+
import { setAdminDocumentTitle } from "../documentTitle";
|
|
10
12
|
|
|
11
13
|
const mode = import.meta.env.VITE_ROUTER_MODE;
|
|
12
14
|
|
|
@@ -42,20 +44,15 @@ const router = createRouter({
|
|
|
42
44
|
* */
|
|
43
45
|
router.beforeEach(async to => {
|
|
44
46
|
const authStore = useAuthStore();
|
|
47
|
+
const userStore = useUserStore();
|
|
45
48
|
const redirectQuery = typeof to.query.redirect === "string" ? to.query.redirect : "";
|
|
46
49
|
|
|
47
50
|
// 1.NProgress 开始
|
|
48
51
|
NProgress.start();
|
|
49
52
|
|
|
50
|
-
// 2.动态设置标题
|
|
51
|
-
const title = import.meta.env.VITE_GLOB_APP_TITLE;
|
|
52
|
-
const titleKey = typeof to.meta.titleKey === "string" ? to.meta.titleKey : "";
|
|
53
|
-
const routeTitle = titleKey ? t(titleKey) : String(to.meta.title ?? "");
|
|
54
|
-
document.title = routeTitle ? `${routeTitle} - ${title}` : title;
|
|
55
|
-
|
|
56
53
|
const hasAccessToken = await ensureAccessToken();
|
|
57
54
|
|
|
58
|
-
//
|
|
55
|
+
// 2.判断是访问登陆页,有 Token 就在当前页面,没有 Token 重置路由到登陆页
|
|
59
56
|
if (to.path.toLocaleLowerCase() === LOGIN_URL) {
|
|
60
57
|
const hasOauthCallback = typeof to.query.oauth_ticket === "string" || typeof to.query.oauth_error === "string";
|
|
61
58
|
if (hasOauthCallback) {
|
|
@@ -71,10 +68,10 @@ router.beforeEach(async to => {
|
|
|
71
68
|
return true;
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
//
|
|
71
|
+
// 3.判断访问页面是否在路由白名单地址(静态路由)中,如果存在直接放行
|
|
75
72
|
if (ROUTER_WHITE_LIST.includes(to.path)) return true;
|
|
76
73
|
|
|
77
|
-
//
|
|
74
|
+
// 4.判断是否有可用 Token,没有重定向到 login 页面
|
|
78
75
|
if (!hasAccessToken) {
|
|
79
76
|
const redirect = to.path === LOGIN_URL ? undefined : to.fullPath;
|
|
80
77
|
return {
|
|
@@ -84,24 +81,25 @@ router.beforeEach(async to => {
|
|
|
84
81
|
};
|
|
85
82
|
}
|
|
86
83
|
|
|
87
|
-
//
|
|
84
|
+
// 5.如果没有菜单列表,就重新请求菜单列表并添加动态路由
|
|
88
85
|
if (!authStore.authMenuListGet.length) {
|
|
86
|
+
await userStore.getUserInfo();
|
|
89
87
|
await initDynamicRouter();
|
|
90
88
|
if (isUnmatchedRoute(router, to.path)) return getFirstAccessibleRoutePath();
|
|
91
89
|
return { ...to, replace: true };
|
|
92
90
|
}
|
|
93
91
|
|
|
94
|
-
//
|
|
92
|
+
// 5.1 菜单已恢复但路由实例尚未重新挂载时,补跑一次动态路由注册,避免刷新或登录首跳直接命中 404。
|
|
95
93
|
if (isUnmatchedRoute(router, to.path)) {
|
|
96
94
|
await initDynamicRouter();
|
|
97
95
|
if (isUnmatchedRoute(router, to.path)) return getFirstAccessibleRoutePath();
|
|
98
96
|
return { ...to, replace: true };
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
//
|
|
99
|
+
// 6.存储 routerName 做按钮权限筛选
|
|
102
100
|
authStore.setRouteName(to.name as string);
|
|
103
101
|
|
|
104
|
-
//
|
|
102
|
+
// 7.正常访问页面
|
|
105
103
|
return true;
|
|
106
104
|
});
|
|
107
105
|
|
|
@@ -139,8 +137,11 @@ router.onError(error => {
|
|
|
139
137
|
/**
|
|
140
138
|
* @description 路由跳转结束
|
|
141
139
|
* */
|
|
142
|
-
router.afterEach(
|
|
140
|
+
router.afterEach(to => {
|
|
143
141
|
NProgress.done();
|
|
142
|
+
const titleKey = typeof to.meta.titleKey === "string" ? to.meta.titleKey : "";
|
|
143
|
+
const routeTitle = titleKey ? t(titleKey) : String(to.meta.title ?? "");
|
|
144
|
+
setAdminDocumentTitle(routeTitle);
|
|
144
145
|
});
|
|
145
146
|
|
|
146
147
|
export default router;
|
|
@@ -22,6 +22,8 @@ export enum PasswordCryptoScene {
|
|
|
22
22
|
PASSWORD_CRYPTO_SCENE_UPDATE_USER_PASSWORD = 4,
|
|
23
23
|
/** PASSWORD_CRYPTO_SCENE_MFA - 多因素认证敏感操作场景。 */
|
|
24
24
|
PASSWORD_CRYPTO_SCENE_MFA = 5,
|
|
25
|
+
/** PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY - 密码策略初始化密码配置场景。 */
|
|
26
|
+
PASSWORD_CRYPTO_SCENE_CONFIGURE_PASSWORD_POLICY = 6,
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -107,7 +109,7 @@ export interface RefreshTokenRequest {
|
|
|
107
109
|
export interface RefreshTokenResponse {
|
|
108
110
|
/** 访问令牌,必选项。 */
|
|
109
111
|
access_token: string;
|
|
110
|
-
/**
|
|
112
|
+
/** 更新令牌;管理端 Cookie-only 请求不在响应体返回,应用端请求可返回。 */
|
|
111
113
|
refresh_token: string;
|
|
112
114
|
/** 令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。 */
|
|
113
115
|
token_type: string;
|
|
@@ -135,7 +137,7 @@ export interface LoginRequest {
|
|
|
135
137
|
export interface LoginResponse {
|
|
136
138
|
/** 访问令牌,必选项。 */
|
|
137
139
|
access_token: string;
|
|
138
|
-
/**
|
|
140
|
+
/** 更新令牌;管理端 Cookie-only 请求不在响应体返回,应用端请求可返回。 */
|
|
139
141
|
refresh_token: string;
|
|
140
142
|
/** 令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。 */
|
|
141
143
|
token_type: string;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
/* eslint-disable */
|
|
8
8
|
import type { PasswordCrypto, StringValues } from "../../../common/v1/types";
|
|
9
9
|
import type { Empty } from "../../../google/protobuf/empty";
|
|
10
|
+
import type { BaseUserIDType } from "../../common/v1/common";
|
|
10
11
|
import type { BaseMenuType } from "./common";
|
|
11
12
|
|
|
12
13
|
/** 登录用户菜单树查询参数 */
|
|
@@ -35,6 +36,12 @@ export interface UserInfoForm {
|
|
|
35
36
|
nick_name: string;
|
|
36
37
|
/** 手机号 */
|
|
37
38
|
phone: string;
|
|
39
|
+
/** 邮箱 */
|
|
40
|
+
email: string;
|
|
41
|
+
/** 证件类型:枚举【BaseUserIDType】 */
|
|
42
|
+
id_type: BaseUserIDType;
|
|
43
|
+
/** 证件号 */
|
|
44
|
+
id_code: string;
|
|
38
45
|
/** 头像 */
|
|
39
46
|
avatar: string;
|
|
40
47
|
/** 角色编号 */
|
|
@@ -65,6 +72,12 @@ export interface UserProfileForm {
|
|
|
65
72
|
gender: number;
|
|
66
73
|
/** 手机号 */
|
|
67
74
|
phone: string;
|
|
75
|
+
/** 邮箱 */
|
|
76
|
+
email: string;
|
|
77
|
+
/** 证件类型:枚举【BaseUserIDType】 */
|
|
78
|
+
id_type: BaseUserIDType;
|
|
79
|
+
/** 证件号 */
|
|
80
|
+
id_code: string;
|
|
68
81
|
/** 角色名 */
|
|
69
82
|
role_name: string;
|
|
70
83
|
/** 部门名 */
|
|
@@ -63,30 +63,6 @@ export interface PageBaseDictResponse {
|
|
|
63
63
|
total: number;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
/** 字典属性分页查询条件 */
|
|
67
|
-
export interface PageBaseDictItemRequest {
|
|
68
|
-
/** 字典ID */
|
|
69
|
-
dict_id: number;
|
|
70
|
-
/** 字典属性名称 */
|
|
71
|
-
label: string;
|
|
72
|
-
/** 状态 */
|
|
73
|
-
status?:
|
|
74
|
-
| Status
|
|
75
|
-
| undefined;
|
|
76
|
-
/** 当前页码 */
|
|
77
|
-
page_num: number;
|
|
78
|
-
/** 每一页的行数 */
|
|
79
|
-
page_size: number;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** 字典属性分页响应 */
|
|
83
|
-
export interface PageBaseDictItemResponse {
|
|
84
|
-
/** 分页数据 */
|
|
85
|
-
base_dict_items: BaseDictItem[];
|
|
86
|
-
/** 总数 */
|
|
87
|
-
total: number;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
66
|
/** 查询字典请求参数 */
|
|
91
67
|
export interface GetBaseDictRequest {
|
|
92
68
|
/** 字典ID */
|
|
@@ -107,76 +83,24 @@ export interface BaseDictForm {
|
|
|
107
83
|
status: Status;
|
|
108
84
|
}
|
|
109
85
|
|
|
110
|
-
/** 查询字典属性请求参数 */
|
|
111
|
-
export interface GetBaseDictItemRequest {
|
|
112
|
-
/** 字典属性ID */
|
|
113
|
-
id: number;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** 字典属性表单 */
|
|
117
|
-
export interface BaseDictItemForm {
|
|
118
|
-
/** 字典项ID */
|
|
119
|
-
id: number;
|
|
120
|
-
/** 字典ID */
|
|
121
|
-
dict_id: number;
|
|
122
|
-
/** 字典项值 */
|
|
123
|
-
value: string;
|
|
124
|
-
/** 字典项标签 */
|
|
125
|
-
label: string;
|
|
126
|
-
/** 标签类型,用于前端样式展示(如success、warning等) */
|
|
127
|
-
tag_type: string;
|
|
128
|
-
/** 排序 */
|
|
129
|
-
sort: number;
|
|
130
|
-
/** 非主语言翻译 */
|
|
131
|
-
i18ns: BaseI18n[];
|
|
132
|
-
/** 状态 */
|
|
133
|
-
status: Status;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
86
|
/** 创建字典请求参数 */
|
|
137
87
|
export interface CreateBaseDictRequest {
|
|
138
88
|
/** 字典表单 */
|
|
139
89
|
base_dict: BaseDictForm | undefined;
|
|
140
90
|
}
|
|
141
91
|
|
|
142
|
-
/** 创建字典属性请求参数 */
|
|
143
|
-
export interface CreateBaseDictItemRequest {
|
|
144
|
-
/** 字典属性表单 */
|
|
145
|
-
base_dict_item: BaseDictItemForm | undefined;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
92
|
/** 更新字典请求参数 */
|
|
149
93
|
export interface UpdateBaseDictRequest {
|
|
150
94
|
/** 字典表单 */
|
|
151
95
|
base_dict: BaseDictForm | undefined;
|
|
152
96
|
}
|
|
153
97
|
|
|
154
|
-
/** 更新字典属性请求参数 */
|
|
155
|
-
export interface UpdateBaseDictItemRequest {
|
|
156
|
-
/** 字典属性表单 */
|
|
157
|
-
base_dict_item: BaseDictItemForm | undefined;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
98
|
/** 删除字典请求参数 */
|
|
161
99
|
export interface DeleteBaseDictRequest {
|
|
162
100
|
/** 字典ID列表 */
|
|
163
101
|
id: string;
|
|
164
102
|
}
|
|
165
103
|
|
|
166
|
-
/** 删除字典属性请求参数 */
|
|
167
|
-
export interface DeleteBaseDictItemRequest {
|
|
168
|
-
/** 字典属性ID列表 */
|
|
169
|
-
id: string;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** 设置字典属性状态请求参数 */
|
|
173
|
-
export interface SetBaseDictItemStatusRequest {
|
|
174
|
-
/** 字典属性ID */
|
|
175
|
-
id: number;
|
|
176
|
-
/** 状态 */
|
|
177
|
-
status: number;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
104
|
/** 设置字典状态请求参数 */
|
|
181
105
|
export interface SetBaseDictStatusRequest {
|
|
182
106
|
/** 字典ID */
|
|
@@ -203,56 +127,20 @@ export interface BaseDict {
|
|
|
203
127
|
i18ns: BaseI18n[];
|
|
204
128
|
}
|
|
205
129
|
|
|
206
|
-
/** 字典项 */
|
|
207
|
-
export interface BaseDictItem {
|
|
208
|
-
/** 字典项ID */
|
|
209
|
-
id: number;
|
|
210
|
-
/** 字典ID */
|
|
211
|
-
dict_id: number;
|
|
212
|
-
/** 字典项值 */
|
|
213
|
-
value: string;
|
|
214
|
-
/** 字典项标签 */
|
|
215
|
-
label: string;
|
|
216
|
-
/** 标签类型,用于前端样式展示(如success、warning等) */
|
|
217
|
-
tag_type: string;
|
|
218
|
-
/** 排序 */
|
|
219
|
-
sort: number;
|
|
220
|
-
/** 状态 */
|
|
221
|
-
status: Status;
|
|
222
|
-
/** 创建时间 */
|
|
223
|
-
created_at: string;
|
|
224
|
-
/** 更新时间 */
|
|
225
|
-
updated_at: string;
|
|
226
|
-
/** 非主语言翻译 */
|
|
227
|
-
i18ns: BaseI18n[];
|
|
228
|
-
}
|
|
229
|
-
|
|
230
130
|
/** Admin字典服务 */
|
|
231
131
|
export interface BaseDictService {
|
|
232
132
|
/** 查询字典列表 */
|
|
233
133
|
OptionBaseDict(request: OptionBaseDictRequest): Promise<OptionBaseDictResponse>;
|
|
234
134
|
/** 查询字典分页列表 */
|
|
235
135
|
PageBaseDict(request: PageBaseDictRequest): Promise<PageBaseDictResponse>;
|
|
236
|
-
/** 查询字典属性分页列表 */
|
|
237
|
-
PageBaseDictItem(request: PageBaseDictItemRequest): Promise<PageBaseDictItemResponse>;
|
|
238
136
|
/** 查询字典 */
|
|
239
137
|
GetBaseDict(request: GetBaseDictRequest): Promise<BaseDictForm>;
|
|
240
|
-
/** 查询字典属性 */
|
|
241
|
-
GetBaseDictItem(request: GetBaseDictItemRequest): Promise<BaseDictItemForm>;
|
|
242
138
|
/** 创建字典 */
|
|
243
139
|
CreateBaseDict(request: CreateBaseDictRequest): Promise<Empty>;
|
|
244
|
-
/** 创建字典属性 */
|
|
245
|
-
CreateBaseDictItem(request: CreateBaseDictItemRequest): Promise<Empty>;
|
|
246
140
|
/** 更新字典 */
|
|
247
141
|
UpdateBaseDict(request: UpdateBaseDictRequest): Promise<Empty>;
|
|
248
|
-
/** 更新字典属性 */
|
|
249
|
-
UpdateBaseDictItem(request: UpdateBaseDictItemRequest): Promise<Empty>;
|
|
250
142
|
/** 删除字典 */
|
|
251
143
|
DeleteBaseDict(request: DeleteBaseDictRequest): Promise<Empty>;
|
|
252
|
-
/** 删除字典属性 */
|
|
253
|
-
DeleteBaseDictItem(request: DeleteBaseDictItemRequest): Promise<Empty>;
|
|
254
|
-
/** 设置状态 */
|
|
255
|
-
SetBaseDictItemStatus(request: SetBaseDictItemStatusRequest): Promise<Empty>;
|
|
256
144
|
/** 设置状态 */
|
|
257
145
|
SetBaseDictStatus(request: SetBaseDictStatusRequest): Promise<Empty>;
|
|
258
146
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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: system/common/v1/common.proto
|
|
6
|
+
|
|
7
|
+
/* eslint-disable */
|
|
8
|
+
|
|
9
|
+
/** 系统公共用户相关枚举。 */
|
|
10
|
+
export enum BaseUserIDType {
|
|
11
|
+
/** BASE_USER_ID_TYPE_UNSPECIFIED - 未指定证件类型。 */
|
|
12
|
+
BASE_USER_ID_TYPE_UNSPECIFIED = 0,
|
|
13
|
+
/** BASE_USER_ID_TYPE_ID_CARD - 居民身份证。 */
|
|
14
|
+
BASE_USER_ID_TYPE_ID_CARD = 1,
|
|
15
|
+
/** BASE_USER_ID_TYPE_PASSPORT - 护照。 */
|
|
16
|
+
BASE_USER_ID_TYPE_PASSPORT = 2,
|
|
17
|
+
/** BASE_USER_ID_TYPE_HK_MACAO_PERMIT - 港澳居民来往内地通行证。 */
|
|
18
|
+
BASE_USER_ID_TYPE_HK_MACAO_PERMIT = 3,
|
|
19
|
+
/** BASE_USER_ID_TYPE_TAIWAN_PERMIT - 台湾居民来往大陆通行证。 */
|
|
20
|
+
BASE_USER_ID_TYPE_TAIWAN_PERMIT = 4,
|
|
21
|
+
/** BASE_USER_ID_TYPE_FOREIGN_PERMANENT_RESIDENCE - 外国人永久居留身份证。 */
|
|
22
|
+
BASE_USER_ID_TYPE_FOREIGN_PERMANENT_RESIDENCE = 5,
|
|
23
|
+
/** BASE_USER_ID_TYPE_OTHER - 其他证件。 */
|
|
24
|
+
BASE_USER_ID_TYPE_OTHER = 6,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** 用户密码修改状态。 */
|
|
28
|
+
export enum BaseUserPasswordChangeStatus {
|
|
29
|
+
/** BASE_USER_PASSWORD_CHANGE_STATUS_UNSPECIFIED - 未指定密码修改状态。 */
|
|
30
|
+
BASE_USER_PASSWORD_CHANGE_STATUS_UNSPECIFIED = 0,
|
|
31
|
+
/** BASE_USER_PASSWORD_CHANGE_STATUS_REQUIRED - 当前必须修改密码。 */
|
|
32
|
+
BASE_USER_PASSWORD_CHANGE_STATUS_REQUIRED = 1,
|
|
33
|
+
/** BASE_USER_PASSWORD_CHANGE_STATUS_NOT_REQUIRED - 当前无需修改密码。 */
|
|
34
|
+
BASE_USER_PASSWORD_CHANGE_STATUS_NOT_REQUIRED = 2,
|
|
35
|
+
}
|
|
@@ -53,9 +53,14 @@ export interface GlobalState {
|
|
|
53
53
|
/** 当前登录用户认证状态。 */
|
|
54
54
|
export interface UserState {
|
|
55
55
|
token: string;
|
|
56
|
-
refreshToken: string;
|
|
57
56
|
tokenType: string;
|
|
58
57
|
tokenExpiresAt: number;
|
|
58
|
+
/** 是否正在执行退出登录,阻止后台请求刷新令牌。 */
|
|
59
|
+
isLoggingOut: boolean;
|
|
60
|
+
/** 认证状态版本,用于丢弃退出期间完成的旧刷新请求。 */
|
|
61
|
+
authVersion: number;
|
|
62
|
+
/** 当前认证是否已被本地显式清理。 */
|
|
63
|
+
authInvalidated: boolean;
|
|
59
64
|
userInfo: UserInfoForm;
|
|
60
65
|
}
|
|
61
66
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineStore } from "pinia";
|
|
2
|
-
import { defAuthService } from "../../api/system/auth";
|
|
2
|
+
import { defAuthService } from "../../api/system/admin/v1/auth";
|
|
3
3
|
import { AuthState } from "../../stores/interface";
|
|
4
4
|
import { getFlatMenuList, getShowMenuList, getAllBreadcrumbList, isExternalPath } from "../../utils";
|
|
5
5
|
import type { RouteItem } from "../../rpc/system/admin/v1/auth";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineStore } from "pinia";
|
|
2
|
-
import { defConfigService } from "../../api/base/config";
|
|
2
|
+
import { defConfigService } from "../../api/base/v1/config";
|
|
3
3
|
import { BaseConfigSite } from "../../rpc/base/v1/config";
|
|
4
4
|
import type { LoginCaptchaConfig, SiteConfigState, SiteDisplayConfig } from "../../stores/interface";
|
|
5
5
|
import defaultLogoUrl from "../../assets/images/logo.svg";
|
|
@@ -9,7 +9,7 @@ const CAPTCHA_TYPE_KEY = "captchaType";
|
|
|
9
9
|
const I18N_DRAFT_ENABLED_KEY = "i18n.draft.enabled";
|
|
10
10
|
|
|
11
11
|
const DEFAULT_SITE_DISPLAY_CONFIG: SiteDisplayConfig = {
|
|
12
|
-
sysName:
|
|
12
|
+
sysName: import.meta.env.VITE_GLOB_APP_TITLE,
|
|
13
13
|
icp: "",
|
|
14
14
|
copyright: "2026 © Admin",
|
|
15
15
|
watermark: "Admin",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineStore } from "pinia";
|
|
2
2
|
import pinia from "../../stores";
|
|
3
|
-
import { defBaseDictService } from "../../api/system/base_dict";
|
|
3
|
+
import { defBaseDictService } from "../../api/system/admin/v1/base_dict";
|
|
4
4
|
import type { DictState } from "../../stores/interface";
|
|
5
5
|
import piniaPersistConfig from "../../stores/helper/persist";
|
|
6
6
|
import type { OptionBaseDictResponse_BaseDict, OptionBaseDictResponse_BaseDictItem } from "../../rpc/system/admin/v1/base_dict";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineStore } from "pinia";
|
|
2
|
-
import { defAuthService } from "../../api/system/auth";
|
|
3
|
-
import { defLoginService } from "../../api/base/login";
|
|
4
|
-
import { defMfaService } from "../../api/base/mfa";
|
|
2
|
+
import { defAuthService } from "../../api/system/admin/v1/auth";
|
|
3
|
+
import { defLoginService } from "../../api/base/v1/login";
|
|
4
|
+
import { defMfaService } from "../../api/base/v1/mfa";
|
|
5
5
|
import type { LoginRequest, LoginResponse } from "../../rpc/base/v1/login";
|
|
6
6
|
import type { VerifyMfaRequest } from "../../rpc/base/v1/mfa";
|
|
7
7
|
import type { UserInfoForm } from "../../rpc/system/admin/v1/auth";
|
|
@@ -9,12 +9,14 @@ import { UserState } from "../../stores/interface";
|
|
|
9
9
|
import piniaPersistConfig from "../../stores/helper/persist";
|
|
10
10
|
import { useDictStoreHook } from "../../stores/modules/dict";
|
|
11
11
|
import { useLockScreenStore } from "../../stores/modules/lockScreen";
|
|
12
|
-
import { t } from "../../locales";
|
|
13
12
|
|
|
14
13
|
const defaultUserInfo: UserInfoForm = {
|
|
15
14
|
user_name: "",
|
|
16
15
|
nick_name: "",
|
|
17
16
|
phone: "",
|
|
17
|
+
email: "",
|
|
18
|
+
id_type: 0,
|
|
19
|
+
id_code: "",
|
|
18
20
|
avatar: "",
|
|
19
21
|
role_code: "",
|
|
20
22
|
role_name: "",
|
|
@@ -26,9 +28,11 @@ const defaultUserInfo: UserInfoForm = {
|
|
|
26
28
|
export const useUserStore = defineStore("admin-user", {
|
|
27
29
|
state: (): UserState => ({
|
|
28
30
|
token: "",
|
|
29
|
-
refreshToken: "",
|
|
30
31
|
tokenType: "",
|
|
31
32
|
tokenExpiresAt: 0,
|
|
33
|
+
isLoggingOut: false,
|
|
34
|
+
authVersion: 0,
|
|
35
|
+
authInvalidated: false,
|
|
32
36
|
userInfo: defaultUserInfo
|
|
33
37
|
}),
|
|
34
38
|
getters: {},
|
|
@@ -37,10 +41,6 @@ export const useUserStore = defineStore("admin-user", {
|
|
|
37
41
|
setToken(token: string) {
|
|
38
42
|
this.token = token;
|
|
39
43
|
},
|
|
40
|
-
/** 设置刷新令牌 */
|
|
41
|
-
setRefreshToken(refreshToken: string) {
|
|
42
|
-
this.refreshToken = refreshToken;
|
|
43
|
-
},
|
|
44
44
|
/** 设置令牌类型 */
|
|
45
45
|
setTokenType(tokenType: string) {
|
|
46
46
|
this.tokenType = tokenType;
|
|
@@ -54,12 +54,12 @@ export const useUserStore = defineStore("admin-user", {
|
|
|
54
54
|
this.userInfo = userInfo;
|
|
55
55
|
},
|
|
56
56
|
/** 根据接口返回统一更新令牌信息 */
|
|
57
|
-
updateTokenAuth(accessToken: string,
|
|
57
|
+
updateTokenAuth(accessToken: string, tokenType: string, expiresIn?: number) {
|
|
58
58
|
const tokenPrefix = tokenType ? `${tokenType} ` : "";
|
|
59
59
|
const expiresAt = expiresIn ? Date.now() + expiresIn * 1000 : 0;
|
|
60
60
|
|
|
61
|
+
this.authInvalidated = false;
|
|
61
62
|
this.setToken(`${tokenPrefix}${accessToken}`.trim());
|
|
62
|
-
this.setRefreshToken(refreshToken ?? "");
|
|
63
63
|
this.setTokenType(tokenType ?? "");
|
|
64
64
|
this.setTokenExpiresAt(expiresAt);
|
|
65
65
|
},
|
|
@@ -71,24 +71,20 @@ export const useUserStore = defineStore("admin-user", {
|
|
|
71
71
|
async login(loginRequest: LoginRequest): Promise<LoginResponse> {
|
|
72
72
|
const data = await defLoginService.Login(loginRequest);
|
|
73
73
|
if (data.status === 1 || data.status === 0 || data.status === 4) {
|
|
74
|
-
this.updateTokenAuth(data.access_token, data.
|
|
74
|
+
this.updateTokenAuth(data.access_token, data.token_type ?? "", data.expires_in);
|
|
75
75
|
}
|
|
76
76
|
return data;
|
|
77
77
|
},
|
|
78
78
|
/** 校验登录阶段的多因素认证并保存正式令牌。 */
|
|
79
79
|
async verifyMfa(request: VerifyMfaRequest): Promise<LoginResponse> {
|
|
80
80
|
const data = await defMfaService.VerifyMfa(request);
|
|
81
|
-
this.updateTokenAuth(data.access_token, data.
|
|
81
|
+
this.updateTokenAuth(data.access_token, data.token_type ?? "", data.expires_in);
|
|
82
82
|
return data;
|
|
83
83
|
},
|
|
84
|
-
/**
|
|
84
|
+
/** 通过 HttpOnly Cookie 刷新认证令牌。 */
|
|
85
85
|
async refreshAccessToken() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const data = await defLoginService.RefreshToken({ refresh_token: this.refreshToken });
|
|
91
|
-
this.updateTokenAuth(data.access_token, data.refresh_token ?? this.refreshToken, data.token_type ?? "", data.expires_in);
|
|
86
|
+
const data = await defLoginService.RefreshToken({});
|
|
87
|
+
this.updateTokenAuth(data.access_token, data.token_type ?? "", data.expires_in);
|
|
92
88
|
return data;
|
|
93
89
|
},
|
|
94
90
|
/** 获取用户信息 */
|
|
@@ -102,22 +98,25 @@ export const useUserStore = defineStore("admin-user", {
|
|
|
102
98
|
// 清理登录态时同步清空字典缓存,避免切换账号后读到旧字典。
|
|
103
99
|
useDictStoreHook().clearDictionaryCache();
|
|
104
100
|
useLockScreenStore().clearLock();
|
|
101
|
+
this.authVersion += 1;
|
|
102
|
+
this.authInvalidated = true;
|
|
105
103
|
this.setToken("");
|
|
106
|
-
this.setRefreshToken("");
|
|
107
104
|
this.setTokenType("");
|
|
108
105
|
this.setTokenExpiresAt(0);
|
|
109
106
|
this.setUserInfo({ ...defaultUserInfo });
|
|
110
107
|
},
|
|
111
108
|
/** 退出登录 */
|
|
112
109
|
async logout() {
|
|
110
|
+
this.isLoggingOut = true;
|
|
113
111
|
try {
|
|
114
112
|
await defLoginService.Logout({});
|
|
115
113
|
} catch {
|
|
116
114
|
// 退出接口返回异常时,前端仍需清理本地登录态,避免用户卡在当前会话。
|
|
117
115
|
} finally {
|
|
118
116
|
this.clearAuthData();
|
|
117
|
+
this.isLoggingOut = false;
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
120
|
},
|
|
122
|
-
persist: piniaPersistConfig("admin-user", ["
|
|
121
|
+
persist: piniaPersistConfig("admin-user-security-v2", ["userInfo"])
|
|
123
122
|
});
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/* 统一 Element Plus 矩形控件与后台页面的圆角。 */
|
|
2
|
+
html:root {
|
|
3
|
+
--el-border-radius-base: var(--admin-page-radius);
|
|
4
|
+
--el-border-radius-small: 2px;
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
/* el-alert */
|
|
2
8
|
.el-alert {
|
|
3
9
|
border: 1px solid;
|
|
@@ -27,7 +33,18 @@
|
|
|
27
33
|
overflow-x: hidden;
|
|
28
34
|
background-color: var(--el-bg-color);
|
|
29
35
|
border: 1px solid var(--el-border-color-light);
|
|
30
|
-
border-radius:
|
|
36
|
+
border-radius: var(--admin-page-radius);
|
|
37
|
+
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* 非列表业务页沿用 ProTable 卡片外观 */
|
|
41
|
+
.el-card.admin-page-card {
|
|
42
|
+
background-color: var(--el-bg-color);
|
|
43
|
+
border: 1px solid var(--el-border-color-light);
|
|
44
|
+
border-radius: var(--admin-page-radius);
|
|
45
|
+
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
|
46
|
+
}
|
|
47
|
+
.el-card.admin-page-card.is-always-shadow {
|
|
31
48
|
box-shadow: 0 0 12px rgb(0 0 0 / 5%);
|
|
32
49
|
}
|
|
33
50
|
|
|
@@ -165,10 +182,9 @@
|
|
|
165
182
|
}
|
|
166
183
|
}
|
|
167
184
|
|
|
168
|
-
// 设置 el-table
|
|
185
|
+
// 设置 el-table 表头文字单行省略,完整内容由列标题悬浮提示展示。
|
|
169
186
|
.el-table__header .el-table__cell > .cell {
|
|
170
|
-
|
|
171
|
-
white-space: wrap;
|
|
187
|
+
white-space: nowrap;
|
|
172
188
|
}
|
|
173
189
|
|
|
174
190
|
// 空表时去掉底部那条默认分隔线,和菜单管理页保持一致。
|
|
@@ -328,6 +344,21 @@
|
|
|
328
344
|
}
|
|
329
345
|
}
|
|
330
346
|
|
|
347
|
+
// ProDialog 需要去掉 Element Plus 默认的外层内边距,避免异步样式重复加载后覆盖紧凑布局。
|
|
348
|
+
.el-dialog.pro-dialog {
|
|
349
|
+
padding: 0;
|
|
350
|
+
|
|
351
|
+
// 对齐原生 MessageBox 的紧凑上下间距,避免标题和操作区留白过大。
|
|
352
|
+
.el-dialog__header,
|
|
353
|
+
.el-dialog__body {
|
|
354
|
+
padding: 12px 20px;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.el-dialog__footer {
|
|
358
|
+
padding: 0 20px 12px;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
331
362
|
@media screen and (width <= 768px) {
|
|
332
363
|
.el-dialog {
|
|
333
364
|
margin-top: 4vh;
|