feat: 更新mock数据和用户store逻辑

重构用户模块的异步函数,添加租户和租户计划的mock接口,优化字典表单和请求拦截器的实现。
This commit is contained in:
Ray.Hao
2026-03-06 22:47:09 +08:00
parent 92db6b1c0a
commit ff6f68c0ce
11 changed files with 631 additions and 297 deletions

View File

@@ -1 +1 @@
npm run lint:lint-staged npm run lint:lint-staged -- --no-stash

View File

@@ -472,19 +472,6 @@ export default defineMock([
params: null, params: null,
}, },
children: [ children: [
{
path: "vxe-table",
component: "demo/vxe-table/index",
name: "VxeTable",
meta: {
title: "VxeTable",
icon: "el-icon-MagicStick",
hidden: false,
keepAlive: true,
alwaysShow: false,
params: null,
},
},
{ {
path: "icon-demo", path: "icon-demo",
component: "demo/icons", component: "demo/icons",
@@ -499,11 +486,24 @@ export default defineMock([
}, },
}, },
{ {
path: "/function/ai-command", path: "dict-sync",
component: "demo/ai-command", component: "demo/dict-sync",
name: "/function/ai-command", name: "DictSync",
meta: { meta: {
title: "AI 命令助手", title: "字典实时同步",
icon: "",
hidden: false,
keepAlive: true,
alwaysShow: false,
params: null,
},
},
{
path: "vxe-table",
component: "demo/vxe-table/index",
name: "VxeTable",
meta: {
title: "VxeTable",
icon: "el-icon-MagicStick", icon: "el-icon-MagicStick",
hidden: false, hidden: false,
keepAlive: true, keepAlive: true,
@@ -512,13 +512,14 @@ export default defineMock([
}, },
}, },
{ {
path: "other/:id", path: "curd-single",
component: "demo/other", component: "demo/curd-single",
name: "Other/:id", name: "CurdSingle",
meta: { meta: {
title: "敬请期待...", title: "CURD单文件",
icon: "", icon: "el-icon-Reading",
hidden: false, hidden: false,
keepAlive: true,
alwaysShow: false, alwaysShow: false,
params: null, params: null,
}, },
@@ -1530,7 +1531,7 @@ export default defineMock([
], ],
}, },
{ {
id: 89, id: 7,
parentId: 0, parentId: 0,
name: "功能演示", name: "功能演示",
type: "CATALOG", type: "CATALOG",
@@ -1544,8 +1545,8 @@ export default defineMock([
perm: null, perm: null,
children: [ children: [
{ {
id: 97, id: 801,
parentId: 89, parentId: 7,
name: "Icons", name: "Icons",
type: "MENU", type: "MENU",
routeName: null, routeName: null,
@@ -1559,20 +1560,50 @@ export default defineMock([
children: [], children: [],
}, },
{ {
id: 91, id: 802,
parentId: 89, parentId: 7,
name: "敬请期待...", name: "字典实时同步",
type: "CATALOG", type: "MENU",
routeName: null, routeName: null,
routePath: "other/:id", routePath: "dict-sync",
component: "demo/other", component: "demo/dict-sync",
sort: 4, sort: 3,
visible: 1, visible: 1,
icon: "", icon: "",
redirect: "", redirect: "",
perm: null, perm: null,
children: [], children: [],
}, },
{
id: 803,
parentId: 7,
name: "VxeTable",
type: "MENU",
routeName: null,
routePath: "vxe-table",
component: "demo/vxe-table/index",
sort: 4,
visible: 1,
icon: "el-icon-MagicStick",
redirect: "",
perm: null,
children: [],
},
{
id: 804,
parentId: 7,
name: "CURD单文件",
type: "MENU",
routeName: null,
routePath: "curd-single",
component: "demo/curd-single",
sort: 5,
visible: 1,
icon: "el-icon-Reading",
redirect: "",
perm: null,
children: [],
},
], ],
}, },
], ],
@@ -1902,20 +1933,24 @@ export default defineMock([
], ],
}, },
{ {
value: "89", value: "7",
label: "功能演示", label: "功能演示",
children: [ children: [
{ {
value: "97", value: "801",
label: "Icons", label: "Icons",
}, },
{ {
value: "90", value: "802",
label: "Websocket", label: "字典实时同步",
}, },
{ {
value: "91", value: "803",
label: "敬请期待...", label: "VxeTable",
},
{
value: "804",
label: "CURD单文件",
}, },
], ],
}, },
@@ -2077,4 +2112,89 @@ const menuMap: Record<string, any> = {
keepAlive: 1, keepAlive: 1,
alwaysShow: null, alwaysShow: null,
}, },
7: {
id: 7,
parentId: 0,
name: "功能演示",
type: "CATALOG",
routeName: "",
routePath: "/function",
component: "Layout",
perm: null,
visible: 1,
sort: 3,
icon: "menu",
redirect: "/function/icon-demo",
keepAlive: null,
alwaysShow: null,
params: null,
},
801: {
id: 801,
parentId: 7,
name: "Icons",
type: "MENU",
routeName: "IconDemo",
routePath: "icon-demo",
component: "demo/icons",
perm: null,
visible: 1,
sort: 1,
icon: "el-icon-Notification",
redirect: null,
keepAlive: 1,
alwaysShow: null,
params: null,
},
802: {
id: 802,
parentId: 7,
name: "字典实时同步",
type: "MENU",
routeName: "DictSync",
routePath: "dict-sync",
component: "demo/dict-sync",
perm: null,
visible: 1,
sort: 2,
icon: "",
redirect: null,
keepAlive: 1,
alwaysShow: null,
params: null,
},
803: {
id: 803,
parentId: 7,
name: "VxeTable",
type: "MENU",
routeName: "VxeTable",
routePath: "vxe-table",
component: "demo/vxe-table/index",
perm: null,
visible: 1,
sort: 3,
icon: "el-icon-MagicStick",
redirect: null,
keepAlive: 1,
alwaysShow: null,
params: null,
},
804: {
id: 804,
parentId: 7,
name: "CURD单文件",
type: "MENU",
routeName: "CurdSingle",
routePath: "curd-single",
component: "demo/curd-single",
perm: null,
visible: 1,
sort: 4,
icon: "el-icon-Reading",
redirect: null,
keepAlive: 1,
alwaysShow: null,
params: null,
},
}; };

View File

@@ -7,50 +7,12 @@ export default defineMock([
body: { body: {
code: "00000", code: "00000",
data: [ data: [
{ { value: 2, label: "系统管理员" },
value: 2, { value: 4, label: "部门主管" },
label: "系统管理员", { value: 5, label: "部门成员" },
}, { value: 6, label: "普通员工" },
{ { value: 7, label: "自定义权限用户" },
value: 4, { value: 3, label: "访问游客" },
label: "系统管理员1",
},
{
value: 5,
label: "系统管理员2",
},
{
value: 6,
label: "系统管理员3",
},
{
value: 7,
label: "系统管理员4",
},
{
value: 8,
label: "系统管理员5",
},
{
value: 9,
label: "系统管理员6",
},
{
value: 10,
label: "系统管理员7",
},
{
value: 11,
label: "系统管理员8",
},
{
value: 12,
label: "系统管理员9",
},
{
value: 3,
label: "访问游客",
},
], ],
msg: "一切ok", msg: "一切ok",
}, },
@@ -69,6 +31,7 @@ export default defineMock([
code: "ADMIN", code: "ADMIN",
status: 1, status: 1,
sort: 2, sort: 2,
dataScope: 1,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
@@ -78,83 +41,52 @@ export default defineMock([
code: "GUEST", code: "GUEST",
status: 1, status: 1,
sort: 3, sort: 3,
dataScope: 3,
createTime: "2021-05-26 15:49:05", createTime: "2021-05-26 15:49:05",
updateTime: "2019-05-05 16:00:00", updateTime: "2019-05-05 16:00:00",
}, },
{ {
id: 4, id: 4,
name: "系统管理员1", name: "部门主管",
code: "ADMIN1", code: "DEPT_MANAGER",
status: 1, status: 1,
sort: 2, sort: 4,
dataScope: 2,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
{ {
id: 5, id: 5,
name: "系统管理员2", name: "部门成员",
code: "ADMIN2", code: "DEPT_MEMBER",
status: 1, status: 1,
sort: 2, sort: 5,
dataScope: 3,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
{ {
id: 6, id: 6,
name: "系统管理员3", name: "普通员工",
code: "ADMIN3", code: "EMPLOYEE",
status: 1, status: 1,
sort: 2, sort: 6,
dataScope: 4,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
{ {
id: 7, id: 7,
name: "系统管理员4", name: "自定义权限用户",
code: "ADMIN4", code: "CUSTOM_USER",
status: 1, status: 1,
sort: 2, sort: 7,
createTime: "2021-03-25 12:39:54", dataScope: 5,
updateTime: null,
},
{
id: 8,
name: "系统管理员5",
code: "ADMIN5",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54",
updateTime: null,
},
{
id: 9,
name: "系统管理员6",
code: "ADMIN6",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54",
updateTime: "2023-12-04 11:43:15",
},
{
id: 10,
name: "系统管理员7",
code: "ADMIN7",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54",
updateTime: null,
},
{
id: 11,
name: "系统管理员8",
code: "ADMIN8",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
], ],
total: 10, total: 6,
}, },
msg: "一切ok", msg: "一切ok",
}, },
@@ -236,6 +168,20 @@ export default defineMock([
msg: "一切ok", msg: "一切ok",
}, },
}, },
// 获取角色部门ID列表(自定义数据权限)
{
url: "roles/:id/dept-ids",
method: ["GET"],
body: ({ params }) => {
const role = roleMap[params.id];
return {
code: "00000",
data: role?.dataScope === 5 ? role.deptIds || [1, 2] : [],
msg: "一切ok",
};
},
},
]); ]);
// 角色映射表数据 // 角色映射表数据
@@ -246,6 +192,7 @@ const roleMap: Record<string, any> = {
code: "ADMIN", code: "ADMIN",
status: 1, status: 1,
sort: 2, sort: 2,
dataScope: 1,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
@@ -255,79 +202,48 @@ const roleMap: Record<string, any> = {
code: "GUEST", code: "GUEST",
status: 1, status: 1,
sort: 3, sort: 3,
dataScope: 3,
createTime: "2021-05-26 15:49:05", createTime: "2021-05-26 15:49:05",
updateTime: "2019-05-05 16:00:00", updateTime: "2019-05-05 16:00:00",
}, },
4: { 4: {
id: 4, id: 4,
name: "系统管理员1", name: "部门主管",
code: "ADMIN1", code: "DEPT_MANAGER",
status: 1, status: 1,
sort: 2, sort: 4,
dataScope: 2,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
5: { 5: {
id: 5, id: 5,
name: "系统管理员2", name: "部门成员",
code: "ADMIN2", code: "DEPT_MEMBER",
status: 1, status: 1,
sort: 2, sort: 5,
dataScope: 3,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
6: { 6: {
id: 6, id: 6,
name: "系统管理员3", name: "普通员工",
code: "ADMIN3", code: "EMPLOYEE",
status: 1, status: 1,
sort: 2, sort: 6,
dataScope: 4,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },
7: { 7: {
id: 7, id: 7,
name: "系统管理员4", name: "自定义权限用户",
code: "ADMIN4", code: "CUSTOM_USER",
status: 1, status: 1,
sort: 2, sort: 7,
createTime: "2021-03-25 12:39:54", dataScope: 5,
updateTime: null, deptIds: [1, 2],
},
8: {
id: 8,
name: "系统管理员5",
code: "ADMIN5",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54",
updateTime: null,
},
9: {
id: 9,
name: "系统管理员6",
code: "ADMIN6",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54",
updateTime: "2023-12-04 11:43:15",
},
10: {
id: 10,
name: "系统管理员7",
code: "ADMIN7",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54",
updateTime: null,
},
11: {
id: 11,
name: "系统管理员8",
code: "ADMIN8",
status: 1,
sort: 2,
createTime: "2021-03-25 12:39:54", createTime: "2021-03-25 12:39:54",
updateTime: null, updateTime: null,
}, },

125
mock/tenant-plan.mock.ts Normal file
View File

@@ -0,0 +1,125 @@
import { defineMock } from "./base";
export default defineMock([
{
url: "tenant-plans",
method: ["GET"],
body: {
code: "00000",
data: {
list: [
{
id: 1,
name: "基础版",
code: "BASIC",
status: 1,
sort: 1,
remark: "",
createTime: "2026-03-01 10:00:00",
updateTime: "2026-03-01 10:00:00",
},
{
id: 2,
name: "专业版",
code: "PRO",
status: 1,
sort: 2,
remark: "",
createTime: "2026-03-02 10:00:00",
updateTime: "2026-03-02 10:00:00",
},
],
total: 2,
},
msg: "一切ok",
},
},
{
url: "tenant-plans/options",
method: ["GET"],
body: {
code: "00000",
data: [
{ value: 1, label: "基础版" },
{ value: 2, label: "专业版" },
],
msg: "一切ok",
},
},
{
url: "tenant-plans/:planId/form",
method: ["GET"],
body: ({ params }) => {
const planId = Number(params.planId);
const form =
planId === 2
? {
id: 2,
name: "专业版",
code: "PRO",
status: 1,
sort: 2,
remark: "",
}
: {
id: 1,
name: "基础版",
code: "BASIC",
status: 1,
sort: 1,
remark: "",
};
return {
code: "00000",
data: form,
msg: "一切ok",
};
},
},
{
url: "tenant-plans",
method: ["POST"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{
url: "tenant-plans/:planId",
method: ["PUT"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{
url: "tenant-plans/:ids",
method: ["DELETE"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{
url: "tenant-plans/:planId/menuIds",
method: ["GET"],
body: {
code: "00000",
data: [1, 2, 3, 4, 5, 6],
msg: "一切ok",
},
},
{
url: "tenant-plans/:planId/menus",
method: ["PUT"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
]);

View File

@@ -2,7 +2,7 @@ import { defineMock } from "./base";
export default defineMock([ export default defineMock([
{ {
url: "tenants", url: "tenants/options",
method: ["GET"], method: ["GET"],
body: { body: {
code: "00000", code: "00000",
@@ -10,12 +10,32 @@ export default defineMock([
{ {
id: 1, id: 1,
name: "默认租户", name: "默认租户",
code: "default",
contactName: "管理员",
contactPhone: "17621210366",
contactEmail: "",
domain: "default", domain: "default",
logo: "",
planId: 1,
status: 1,
remark: "",
expireTime: null,
isDefault: true,
}, },
{ {
id: 2, id: 2,
name: "演示租户", name: "演示租户",
code: "demo",
contactName: "演示用户",
contactPhone: "17621210366",
contactEmail: "",
domain: "demo", domain: "demo",
logo: "",
planId: 2,
status: 1,
remark: "",
expireTime: null,
isDefault: false,
}, },
], ],
msg: "一切ok", msg: "一切ok",
@@ -29,11 +49,170 @@ export default defineMock([
data: { data: {
id: 1, id: 1,
name: "默认租户", name: "默认租户",
code: "default",
contactName: "管理员",
contactPhone: "17621210366",
contactEmail: "",
domain: "default", domain: "default",
logo: "",
planId: 1,
status: 1,
remark: "",
expireTime: null,
isDefault: true,
}, },
msg: "一切ok", msg: "一切ok",
}, },
}, },
{
url: "tenants",
method: ["GET"],
body: {
code: "00000",
data: {
list: [
{
id: 1,
name: "默认租户",
code: "default",
contactName: "管理员",
contactPhone: "17621210366",
contactEmail: "",
domain: "default",
logo: "",
planId: 1,
status: 1,
remark: "",
expireTime: null,
createTime: "2026-03-01 10:00:00",
updateTime: "2026-03-01 10:00:00",
},
{
id: 2,
name: "演示租户",
code: "demo",
contactName: "演示用户",
contactPhone: "17621210366",
contactEmail: "",
domain: "demo",
logo: "",
planId: 2,
status: 1,
remark: "",
expireTime: null,
createTime: "2026-03-02 10:00:00",
updateTime: "2026-03-02 10:00:00",
},
],
total: 2,
},
msg: "一切ok",
},
},
{
url: "tenants/:tenantId/form",
method: ["GET"],
body: ({ params }) => {
const tenantId = Number(params.tenantId);
const form =
tenantId === 2
? {
id: 2,
name: "演示租户",
code: "demo",
domain: "demo",
contactName: "演示用户",
contactPhone: "17621210366",
contactEmail: "",
logo: "",
planId: 2,
status: 1,
remark: "",
expireTime: null,
}
: {
id: 1,
name: "默认租户",
code: "default",
domain: "default",
contactName: "管理员",
contactPhone: "17621210366",
contactEmail: "",
logo: "",
planId: 1,
status: 1,
remark: "",
expireTime: null,
};
return {
code: "00000",
data: form,
msg: "一切ok",
};
},
},
{
url: "tenants",
method: ["POST"],
body: {
code: "00000",
data: {
tenantId: 3,
tenantCode: "test",
tenantName: "测试租户",
adminUsername: "admin",
adminInitialPassword: "123456",
adminRoleCode: "TENANT_ADMIN",
},
msg: "一切ok",
},
},
{
url: "tenants/:tenantId",
method: ["PUT"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{
url: "tenants/:ids",
method: ["DELETE"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{
url: "tenants/:tenantId/status",
method: ["PUT"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{
url: "tenants/:tenantId/menuIds",
method: ["GET"],
body: {
code: "00000",
data: [1, 2, 3, 4, 5, 6],
msg: "一切ok",
},
},
{
url: "tenants/:tenantId/menus",
method: ["PUT"],
body: {
code: "00000",
data: null,
msg: "一切ok",
},
},
{ {
url: "tenants/:tenantId/switch", url: "tenants/:tenantId/switch",
method: ["POST"], method: ["POST"],
@@ -44,12 +223,32 @@ export default defineMock([
{ {
id: 1, id: 1,
name: "默认租户", name: "默认租户",
code: "default",
contactName: "管理员",
contactPhone: "17621210366",
contactEmail: "",
domain: "default", domain: "default",
logo: "",
planId: 1,
status: 1,
remark: "",
expireTime: null,
isDefault: true,
}, },
{ {
id: 2, id: 2,
name: "演示租户", name: "演示租户",
code: "demo",
contactName: "演示用户",
contactPhone: "17621210366",
contactEmail: "",
domain: "demo", domain: "demo",
logo: "",
planId: 2,
status: 1,
remark: "",
expireTime: null,
isDefault: false,
}, },
]; ];

View File

@@ -13,49 +13,48 @@ export default defineMock([
avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif", avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif",
roles: ["ADMIN"], roles: ["ADMIN"],
perms: [ perms: [
"sys:user:query", "sys:user:list",
"sys:user:add", "sys:user:create",
"sys:user:edit", "sys:user:update",
"sys:user:delete", "sys:user:delete",
"sys:user:import", "sys:user:import",
"sys:user:export", "sys:user:export",
"sys:user:reset-password", "sys:user:reset-password",
"sys:role:query", "sys:role:list",
"sys:role:add", "sys:role:create",
"sys:role:edit", "sys:role:update",
"sys:role:delete", "sys:role:delete",
"sys:dept:query", "sys:dept:list",
"sys:dept:add", "sys:dept:create",
"sys:dept:edit", "sys:dept:update",
"sys:dept:delete", "sys:dept:delete",
"sys:menu:query", "sys:menu:list",
"sys:menu:add", "sys:menu:create",
"sys:menu:edit", "sys:menu:update",
"sys:menu:delete", "sys:menu:delete",
"sys:dict:query", "sys:dict:list",
"sys:dict:add", "sys:dict:create",
"sys:dict:edit", "sys:dict:update",
"sys:dict:delete",
"sys:dict:delete", "sys:dict:delete",
"sys:dict-item:query", "sys:dict-item:list",
"sys:dict-item:add", "sys:dict-item:create",
"sys:dict-item:edit", "sys:dict-item:update",
"sys:dict-item:delete", "sys:dict-item:delete",
"sys:notice:query", "sys:notice:list",
"sys:notice:add", "sys:notice:create",
"sys:notice:edit", "sys:notice:update",
"sys:notice:delete", "sys:notice:delete",
"sys:notice:revoke", "sys:notice:revoke",
"sys:notice:publish", "sys:notice:publish",
"sys:config:query", "sys:config:list",
"sys:config:add", "sys:config:create",
"sys:config:update", "sys:config:update",
"sys:config:delete", "sys:config:delete",
"sys:config:refresh", "sys:config:refresh",

View File

@@ -18,37 +18,24 @@ export const useUserStore = defineStore("user", () => {
/** /**
* 登录 * 登录
*
* @param {LoginRequest}
* @returns
*/ */
function login(loginRequest: LoginRequest) { async function login(loginRequest: LoginRequest): Promise<void> {
return new Promise<void>((resolve, reject) => { const { accessToken, refreshToken } = await AuthAPI.login(loginRequest);
AuthAPI.login(loginRequest) rememberMe.value = loginRequest.rememberMe ?? false;
.then((data) => { AuthStorage.setTokens(accessToken, refreshToken, rememberMe.value);
const { accessToken, refreshToken } = data;
// 保存记住我状态和token
rememberMe.value = loginRequest.rememberMe ?? false;
AuthStorage.setTokens(accessToken, refreshToken, rememberMe.value);
resolve();
})
.catch((error) => {
reject(error);
});
});
} }
let refreshPromise: Promise<void> | null = null; let refreshPromise: Promise<void> | null = null;
/** /**
* 刷新 token单飞 * 刷新 token单飞模式
* *
* 多个并发请求遇到 token 过期时,共享同一次 refresh 请求。 * 多个并发请求遇到 token 过期时,共享同一次 refresh 请求。
*/ */
function refreshTokenOnce() { function refreshTokenOnce(): Promise<void> {
if (refreshPromise) return refreshPromise; if (refreshPromise) return refreshPromise;
refreshPromise = refreshToken().finally(() => { refreshPromise = doRefreshToken().finally(() => {
refreshPromise = null; refreshPromise = null;
}); });
@@ -57,118 +44,84 @@ export const useUserStore = defineStore("user", () => {
/** /**
* 获取用户信息 * 获取用户信息
*
* @returns {UserInfo} 用户信息
*/ */
function getUserInfo() { async function getUserInfo(): Promise<UserInfo> {
return new Promise<UserInfo>((resolve, reject) => { const data = await UserAPI.getInfo();
UserAPI.getInfo() if (!data) {
.then((data) => { throw new Error("Verification failed, please Login again.");
if (!data) { }
reject("Verification failed, please Login again."); Object.assign(userInfo.value, data);
return; return data;
}
Object.assign(userInfo.value, { ...data });
resolve(data);
})
.catch((error) => {
reject(error);
});
});
} }
/** /**
* 登出 * 登出
*/ */
function logout() { async function logout(): Promise<void> {
return new Promise<void>((resolve, reject) => { await AuthAPI.logout();
AuthAPI.logout() resetAllState();
.then(() => {
// 重置所有系统状态
resetAllState();
resolve();
})
.catch((error) => {
reject(error);
});
});
} }
/** /**
* 重置所有系统状态 * 重置所有系统状态
*
* 统一处理所有清理工作,包括用户凭证、路由、缓存等 * 统一处理所有清理工作,包括用户凭证、路由、缓存等
*/ */
function resetAllState() { function resetAllState(): void {
// 1. 重置用户状态 // 1. 重置用户状态
resetUserState(); resetUserState();
// 2. 重置其他模块状态 // 2. 重置其他模块状态
// 重置路由
usePermissionStoreHook().resetRouter(); usePermissionStoreHook().resetRouter();
// 清除字典缓存
useDictStoreHook().clearDictCache(); useDictStoreHook().clearDictCache();
// 清除标签视图
useTagsViewStore().delAllViews(); useTagsViewStore().delAllViews();
// 3. 清理 WebSocket 连接 // 3. 清理 WebSocket 连接
cleanupWebSocket(); cleanupWebSocket();
console.log("[UserStore] WebSocket connections cleaned up");
return Promise.resolve();
} }
/** /**
* 重置用户状态 * 重置用户状态
*
* 仅处理用户模块内的状态 * 仅处理用户模块内的状态
*/ */
function resetUserState() { function resetUserState(): void {
// 清除用户凭证
AuthStorage.clearAuth(); AuthStorage.clearAuth();
// 重置用户信息
userInfo.value = {} as UserInfo; userInfo.value = {} as UserInfo;
} }
/** /**
* 刷新 token * 刷新 token
*/ */
function refreshToken() { async function doRefreshToken(): Promise<void> {
const refreshToken = AuthStorage.getRefreshToken(); const currentRefreshToken = AuthStorage.getRefreshToken();
if (!refreshToken) { if (!currentRefreshToken) {
return Promise.reject(new Error("没有有效的刷新令牌")); throw new Error("没有有效的刷新令牌");
} }
return new Promise<void>((resolve, reject) => { const { accessToken, refreshToken: newRefreshToken } =
AuthAPI.refreshToken(refreshToken) await AuthAPI.refreshToken(currentRefreshToken);
.then((data) => { AuthStorage.setTokens(accessToken, newRefreshToken, AuthStorage.getRememberMe());
const { accessToken, refreshToken: newRefreshToken } = data;
// 更新令牌,保持当前记住我状态
AuthStorage.setTokens(accessToken, newRefreshToken, AuthStorage.getRememberMe());
resolve();
})
.catch((error) => {
console.log(" refreshToken 刷新失败", error);
reject(error);
});
});
} }
return { return {
userInfo, userInfo,
rememberMe, rememberMe,
isLoggedIn: () => !!AuthStorage.getAccessToken(), isLoggedIn: () => !!AuthStorage.getAccessToken(),
getUserInfo,
login, login,
logout, logout,
getUserInfo,
resetAllState, resetAllState,
resetUserState, resetUserState,
refreshToken, refreshToken: doRefreshToken,
refreshTokenOnce, refreshTokenOnce,
}; };
}); });
/** /**
* 在组件外部使用UserStore的钩子函数 * 在组件外部使用 UserStore 的钩子函数
*
* @see https://pinia.vuejs.org/core-concepts/outside-component-usage.html * @see https://pinia.vuejs.org/core-concepts/outside-component-usage.html
*/ */
export function useUserStoreHook() { export function useUserStoreHook() {

View File

@@ -78,8 +78,7 @@ http.interceptors.response.use(
const token = AuthStorage.getAccessToken(); const token = AuthStorage.getAccessToken();
if (token) { if (token) {
config.headers = config.headers || ({} as any); config.headers.set("Authorization", `Bearer ${token}`);
(config.headers as any).Authorization = `Bearer ${token}`;
} }
return http(config); return http(config);

View File

@@ -184,7 +184,11 @@ const dialogState = reactive({
}); });
// 表单数据 // 表单数据
const formData = reactive<DictItemForm>({}); const formData = reactive<DictItemForm>({
sort: 1,
status: 1,
tagType: "",
});
// 标签类型选项 // 标签类型选项
const tagType = ["primary", "success", "info", "warning", "danger"] as const; const tagType = ["primary", "success", "info", "warning", "danger"] as const;
@@ -239,6 +243,7 @@ function handleSelectionChange(selection: DictItem[]): void {
* @param row 字典项数据(编辑时传入) * @param row 字典项数据(编辑时传入)
*/ */
function openDialog(row?: DictItem): void { function openDialog(row?: DictItem): void {
resetForm();
dialogState.visible = true; dialogState.visible = true;
dialogState.title = row ? "编辑字典值" : "新增字典值"; dialogState.title = row ? "编辑字典值" : "新增字典值";
@@ -249,6 +254,17 @@ function openDialog(row?: DictItem): void {
} }
} }
function resetForm(): void {
dataFormRef.value?.clearValidate();
formData.id = undefined;
formData.dictCode = dictCode.value;
formData.label = undefined;
formData.value = undefined;
formData.sort = 1;
formData.status = 1;
formData.tagType = "";
}
/** /**
* 提交表单 * 提交表单
*/ */
@@ -286,11 +302,7 @@ function handleSubmit(): void {
function closeDialog(): void { function closeDialog(): void {
dialogState.visible = false; dialogState.visible = false;
dataFormRef.value?.resetFields(); dataFormRef.value?.resetFields();
dataFormRef.value?.clearValidate(); resetForm();
formData.id = undefined;
formData.sort = 1;
formData.status = 1;
formData.tagType = "";
} }
/** /**

View File

@@ -162,7 +162,9 @@ const dialogState = reactive({
}); });
// 表单数据 // 表单数据
const formData = reactive<DictTypeForm>({}); const formData = reactive<DictTypeForm>({
status: 1,
});
// 验证规则 // 验证规则
const rules: FormRules = { const rules: FormRules = {
@@ -213,6 +215,7 @@ function handleSelectionChange(selection: DictTypeItem[]): void {
* 新增按钮点击事件 * 新增按钮点击事件
*/ */
function handleCreateClick(): void { function handleCreateClick(): void {
resetForm();
dialogState.visible = true; dialogState.visible = true;
dialogState.title = "新增字典"; dialogState.title = "新增字典";
} }
@@ -222,6 +225,7 @@ function handleCreateClick(): void {
* @param id 字典ID * @param id 字典ID
*/ */
function handleEditClick(id: string): void { function handleEditClick(id: string): void {
resetForm();
dialogState.visible = true; dialogState.visible = true;
dialogState.title = "修改字典"; dialogState.title = "修改字典";
DictAPI.getFormData(id).then((data) => { DictAPI.getFormData(id).then((data) => {
@@ -229,6 +233,15 @@ function handleEditClick(id: string): void {
}); });
} }
function resetForm(): void {
dataFormRef.value?.clearValidate();
formData.id = undefined;
formData.name = undefined;
formData.dictCode = undefined;
formData.status = 1;
formData.remark = undefined;
}
/** /**
* 提交表单 * 提交表单
*/ */
@@ -264,8 +277,7 @@ function handleSubmit(): void {
function closeDialog(): void { function closeDialog(): void {
dialogState.visible = false; dialogState.visible = false;
dataFormRef.value?.resetFields(); dataFormRef.value?.resetFields();
dataFormRef.value?.clearValidate(); resetForm();
formData.id = undefined;
} }
/** /**

View File

@@ -97,7 +97,6 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
"axios", "axios",
"@vueuse/core", "@vueuse/core",
"codemirror-editor-vue3", "codemirror-editor-vue3",
"default-passive-events",
"exceljs", "exceljs",
"path-to-regexp", "path-to-regexp",
"echarts/core", "echarts/core",