feat: 整体pure,核心功能对接完成
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Lazy.Captcha.Core;
|
using Lazy.Captcha.Core;
|
||||||
|
using Mapster;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -25,6 +27,7 @@ using Yi.Framework.Rbac.Domain.Repositories;
|
|||||||
using Yi.Framework.Rbac.Domain.Shared.Caches;
|
using Yi.Framework.Rbac.Domain.Shared.Caches;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Etos;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Options;
|
using Yi.Framework.Rbac.Domain.Shared.Options;
|
||||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
@@ -40,7 +43,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
private readonly IAliyunManger _aliyunManger;
|
private readonly IAliyunManger _aliyunManger;
|
||||||
private IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> _userCache;
|
private IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> _userCache;
|
||||||
private UserManager _userManager;
|
private UserManager _userManager;
|
||||||
|
private IHttpContextAccessor _httpContextAccessor;
|
||||||
public AccountService(IUserRepository userRepository,
|
public AccountService(IUserRepository userRepository,
|
||||||
ICurrentUser currentUser,
|
ICurrentUser currentUser,
|
||||||
IAccountManager accountManager,
|
IAccountManager accountManager,
|
||||||
@@ -51,7 +54,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
IGuidGenerator guidGenerator,
|
IGuidGenerator guidGenerator,
|
||||||
IOptions<RbacOptions> options,
|
IOptions<RbacOptions> options,
|
||||||
IAliyunManger aliyunManger,
|
IAliyunManger aliyunManger,
|
||||||
UserManager userManager)
|
UserManager userManager, IHttpContextAccessor httpContextAccessor)
|
||||||
{
|
{
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
@@ -64,6 +67,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
_aliyunManger = aliyunManger;
|
_aliyunManger = aliyunManger;
|
||||||
_userCache = userCache;
|
_userCache = userCache;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
|
_httpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -109,10 +113,21 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
//校验
|
//校验
|
||||||
await _accountManager.LoginValidationAsync(input.UserName, input.Password, x => user = x);
|
await _accountManager.LoginValidationAsync(input.UserName, input.Password, x => user = x);
|
||||||
|
|
||||||
|
var userInfo = new UserRoleMenuDto();
|
||||||
//获取token
|
//获取token
|
||||||
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id);
|
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id, (info) => userInfo = info);
|
||||||
var refreshToken = _accountManager.CreateRefreshToken(user.Id);
|
var refreshToken = _accountManager.CreateRefreshToken(user.Id);
|
||||||
|
|
||||||
|
//这里抛出一个登录的事件,也可以在全部流程走完,在应用层组装
|
||||||
|
if (_httpContextAccessor.HttpContext is not null)
|
||||||
|
{
|
||||||
|
var loginEntity = new LoginLogAggregateRoot().GetInfoByHttpContext(_httpContextAccessor.HttpContext);
|
||||||
|
var loginEto = loginEntity.Adapt<LoginEventArgs>();
|
||||||
|
loginEto.UserName = userInfo.User.UserName;
|
||||||
|
loginEto.UserId = userInfo.User.Id;
|
||||||
|
await LocalEventBus.PublishAsync(loginEto);
|
||||||
|
}
|
||||||
|
|
||||||
return new { Token = accessToken, RefreshToken = refreshToken };
|
return new { Token = accessToken, RefreshToken = refreshToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,11 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
private readonly ILocalEventBus _localEventBus;
|
private readonly ILocalEventBus _localEventBus;
|
||||||
private readonly JwtOptions _jwtOptions;
|
private readonly JwtOptions _jwtOptions;
|
||||||
private readonly RbacOptions _options;
|
private readonly RbacOptions _options;
|
||||||
private IHttpContextAccessor _httpContextAccessor;
|
|
||||||
private UserManager _userManager;
|
private UserManager _userManager;
|
||||||
private ISqlSugarRepository<RoleAggregateRoot> _roleRepository;
|
private ISqlSugarRepository<RoleAggregateRoot> _roleRepository;
|
||||||
private RefreshJwtOptions _refreshJwtOptions;
|
private RefreshJwtOptions _refreshJwtOptions;
|
||||||
|
|
||||||
public AccountManager(IUserRepository repository
|
public AccountManager(IUserRepository repository
|
||||||
, IHttpContextAccessor httpContextAccessor
|
|
||||||
, IOptions<JwtOptions> jwtOptions
|
, IOptions<JwtOptions> jwtOptions
|
||||||
, ILocalEventBus localEventBus
|
, ILocalEventBus localEventBus
|
||||||
, UserManager userManager
|
, UserManager userManager
|
||||||
@@ -49,7 +47,6 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
, IOptions<RbacOptions> options)
|
, IOptions<RbacOptions> options)
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
_httpContextAccessor = httpContextAccessor;
|
|
||||||
_jwtOptions = jwtOptions.Value;
|
_jwtOptions = jwtOptions.Value;
|
||||||
_localEventBus = localEventBus;
|
_localEventBus = localEventBus;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
@@ -62,9 +59,10 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
/// 根据用户id获取token
|
/// 根据用户id获取token
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId"></param>
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="getUserInfo"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="UserFriendlyException"></exception>
|
/// <exception cref="UserFriendlyException"></exception>
|
||||||
public async Task<string> GetTokenByUserIdAsync(Guid userId)
|
public async Task<string> GetTokenByUserIdAsync(Guid userId,Action<UserRoleMenuDto>? getUserInfo=null)
|
||||||
{
|
{
|
||||||
//获取用户信息
|
//获取用户信息
|
||||||
var userInfo = await _userManager.GetInfoAsync(userId);
|
var userInfo = await _userManager.GetInfoAsync(userId);
|
||||||
@@ -79,23 +77,18 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
{
|
{
|
||||||
throw new UserFriendlyException(UserConst.No_Role);
|
throw new UserFriendlyException(UserConst.No_Role);
|
||||||
}
|
}
|
||||||
if (userInfo.PermissionCodes.Count() == 0)
|
if (!userInfo.PermissionCodes.Any())
|
||||||
{
|
{
|
||||||
throw new UserFriendlyException(UserConst.No_Permission);
|
throw new UserFriendlyException(UserConst.No_Permission);
|
||||||
}
|
}
|
||||||
//这里抛出一个登录的事件,也可以在全部流程走完,在应用层组装
|
|
||||||
if (_httpContextAccessor.HttpContext is not null)
|
if (getUserInfo is not null)
|
||||||
{
|
{
|
||||||
var loginEntity = new LoginLogAggregateRoot().GetInfoByHttpContext(_httpContextAccessor.HttpContext);
|
getUserInfo(userInfo);
|
||||||
var loginEto = loginEntity.Adapt<LoginEventArgs>();
|
|
||||||
loginEto.UserName = userInfo.User.UserName;
|
|
||||||
loginEto.UserId = userInfo.User.Id;
|
|
||||||
await _localEventBus.PublishAsync(loginEto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var accessToken = CreateToken(this.UserInfoToClaim(userInfo));
|
var accessToken = CreateToken(this.UserInfoToClaim(userInfo));
|
||||||
//将用户信息添加到缓存中,需要考虑的是更改了用户、角色、菜单等整个体系都需要将缓存进行刷新,看具体业务进行选择
|
//将用户信息添加到缓存中,需要考虑的是更改了用户、角色、菜单等整个体系都需要将缓存进行刷新,看具体业务进行选择
|
||||||
|
|
||||||
|
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Volo.Abp.Domain.Services;
|
using Volo.Abp.Domain.Services;
|
||||||
using Yi.Framework.Rbac.Domain.Entities;
|
using Yi.Framework.Rbac.Domain.Entities;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
||||||
|
|
||||||
namespace Yi.Framework.Rbac.Domain.Managers
|
namespace Yi.Framework.Rbac.Domain.Managers
|
||||||
{
|
{
|
||||||
public interface IAccountManager : IDomainService
|
public interface IAccountManager : IDomainService
|
||||||
{
|
{
|
||||||
string CreateRefreshToken(Guid userId);
|
string CreateRefreshToken(Guid userId);
|
||||||
Task<string> GetTokenByUserIdAsync(Guid userId);
|
Task<string> GetTokenByUserIdAsync(Guid userId,Action<UserRoleMenuDto>? getUserInfo=null);
|
||||||
Task LoginValidationAsync(string userName, string password, Action<UserAggregateRoot> userAction = null);
|
Task LoginValidationAsync(string userName, string password, Action<UserAggregateRoot>? userAction = null);
|
||||||
Task RegisterAsync(string userName, string password, long phone);
|
Task RegisterAsync(string userName, string password, long phone);
|
||||||
Task<bool> RestPasswordAsync(Guid userId, string password);
|
Task<bool> RestPasswordAsync(Guid userId, string password);
|
||||||
Task UpdatePasswordAsync(Guid userId, string newPassword, string oldPassword);
|
Task UpdatePasswordAsync(Guid userId, string newPassword, string oldPassword);
|
||||||
|
|||||||
@@ -162,14 +162,23 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询用户信息,已缓存
|
/// 查询用户信息,取消缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<UserRoleMenuDto> GetInfoAsync(Guid userId)
|
public async Task<UserRoleMenuDto> GetInfoAsync(Guid userId)
|
||||||
{
|
{
|
||||||
|
var user = await _userRepository.GetUserAllInfoAsync(userId);
|
||||||
var output = await GetInfoByCacheAsync(userId);
|
var data = EntityMapToDto(user);
|
||||||
return output;
|
//系统用户数据被重置,老前端访问重新授权
|
||||||
|
if (data is null)
|
||||||
|
{
|
||||||
|
throw new AbpAuthorizationException();
|
||||||
|
}
|
||||||
|
//data.Menus.Clear();
|
||||||
|
// output = data;
|
||||||
|
return data;
|
||||||
|
// var output = await GetInfoByCacheAsync(userId);
|
||||||
|
// return output;
|
||||||
}
|
}
|
||||||
private async Task<UserRoleMenuDto> GetInfoByCacheAsync(Guid userId)
|
private async Task<UserRoleMenuDto> GetInfoByCacheAsync(Guid userId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// 模拟后端动态生成路由
|
// 模拟后端动态生成路由
|
||||||
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
||||||
import { system, monitor, permission, frame, tabs } from "@/router/enums";
|
import { system, monitor } from "@/router/enums";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* roles:页面级别权限,这里模拟二种 "admin"、"common"
|
* roles:页面级别权限,这里模拟二种 "admin"、"common"
|
||||||
@@ -21,7 +21,7 @@ const systemManagementRouter = {
|
|||||||
name: "SystemUser",
|
name: "SystemUser",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:admin-line",
|
icon: "ri:admin-line",
|
||||||
title: "menus.pureUser",
|
title: "menus.pureUser"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -30,7 +30,7 @@ const systemManagementRouter = {
|
|||||||
name: "SystemRole",
|
name: "SystemRole",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:admin-fill",
|
icon: "ri:admin-fill",
|
||||||
title: "menus.pureRole",
|
title: "menus.pureRole"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -39,7 +39,7 @@ const systemManagementRouter = {
|
|||||||
name: "SystemMenu",
|
name: "SystemMenu",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ep:menu",
|
icon: "ep:menu",
|
||||||
title: "menus.pureSystemMenu",
|
title: "menus.pureSystemMenu"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -48,7 +48,7 @@ const systemManagementRouter = {
|
|||||||
name: "SystemDept",
|
name: "SystemDept",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:git-branch-line",
|
icon: "ri:git-branch-line",
|
||||||
title: "menus.pureDept",
|
title: "menus.pureDept"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -57,7 +57,7 @@ const systemManagementRouter = {
|
|||||||
name: "SystemPost",
|
name: "SystemPost",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ant-design:deployment-unit-outlined",
|
icon: "ant-design:deployment-unit-outlined",
|
||||||
title: "menus.purePost",
|
title: "menus.purePost"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ const systemMonitorRouter = {
|
|||||||
name: "OnlineUser",
|
name: "OnlineUser",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:user-voice-line",
|
icon: "ri:user-voice-line",
|
||||||
title: "menus.pureOnlineUser",
|
title: "menus.pureOnlineUser"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -88,7 +88,7 @@ const systemMonitorRouter = {
|
|||||||
name: "LoginLog",
|
name: "LoginLog",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:window-line",
|
icon: "ri:window-line",
|
||||||
title: "menus.pureLoginLog",
|
title: "menus.pureLoginLog"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -98,7 +98,7 @@ const systemMonitorRouter = {
|
|||||||
name: "OperationLog",
|
name: "OperationLog",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:history-fill",
|
icon: "ri:history-fill",
|
||||||
title: "menus.pureOperationLog",
|
title: "menus.pureOperationLog"
|
||||||
//roles: ["admin"]
|
//roles: ["admin"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,220 +114,220 @@ const systemMonitorRouter = {
|
|||||||
// }
|
// }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
//
|
||||||
const permissionRouter = {
|
// const permissionRouter = {
|
||||||
path: "/permission",
|
// path: "/permission",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.purePermission",
|
// title: "menus.purePermission",
|
||||||
icon: "ep:lollipop",
|
// icon: "ep:lollipop",
|
||||||
rank: permission
|
// rank: permission
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: "/permission/page/index",
|
// path: "/permission/page/index",
|
||||||
name: "PermissionPage",
|
// name: "PermissionPage",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.purePermissionPage",
|
// title: "menus.purePermissionPage"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/permission/button",
|
// path: "/permission/button",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.purePermissionButton",
|
// title: "menus.purePermissionButton"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: "/permission/button/router",
|
// path: "/permission/button/router",
|
||||||
component: "permission/button/index",
|
// component: "permission/button/index",
|
||||||
name: "PermissionButtonRouter",
|
// name: "PermissionButtonRouter",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.purePermissionButtonRouter",
|
// title: "menus.purePermissionButtonRouter",
|
||||||
auths: [
|
// auths: [
|
||||||
"permission:btn:add",
|
// "permission:btn:add",
|
||||||
"permission:btn:edit",
|
// "permission:btn:edit",
|
||||||
"permission:btn:delete"
|
// "permission:btn:delete"
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/permission/button/login",
|
// path: "/permission/button/login",
|
||||||
component: "permission/button/perms",
|
// component: "permission/button/perms",
|
||||||
name: "PermissionButtonLogin",
|
// name: "PermissionButtonLogin",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.purePermissionButtonLogin"
|
// title: "menus.purePermissionButtonLogin"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const frameRouter = {
|
// const frameRouter = {
|
||||||
path: "/iframe",
|
// path: "/iframe",
|
||||||
meta: {
|
// meta: {
|
||||||
icon: "ri:links-fill",
|
// icon: "ri:links-fill",
|
||||||
title: "menus.pureExternalPage",
|
// title: "menus.pureExternalPage",
|
||||||
rank: frame
|
// rank: frame
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: "/iframe/embedded",
|
// path: "/iframe/embedded",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureEmbeddedDoc"
|
// title: "menus.pureEmbeddedDoc"
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: "/iframe/colorhunt",
|
// path: "/iframe/colorhunt",
|
||||||
name: "FrameColorHunt",
|
// name: "FrameColorHunt",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureColorHuntDoc",
|
// title: "menus.pureColorHuntDoc",
|
||||||
frameSrc: "https://colorhunt.co/",
|
// frameSrc: "https://colorhunt.co/",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/uigradients",
|
// path: "/iframe/uigradients",
|
||||||
name: "FrameUiGradients",
|
// name: "FrameUiGradients",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureUiGradients",
|
// title: "menus.pureUiGradients",
|
||||||
frameSrc: "https://uigradients.com/",
|
// frameSrc: "https://uigradients.com/",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/ep",
|
// path: "/iframe/ep",
|
||||||
name: "FrameEp",
|
// name: "FrameEp",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureEpDoc",
|
// title: "menus.pureEpDoc",
|
||||||
frameSrc: "https://element-plus.org/zh-CN/",
|
// frameSrc: "https://element-plus.org/zh-CN/",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/tailwindcss",
|
// path: "/iframe/tailwindcss",
|
||||||
name: "FrameTailwindcss",
|
// name: "FrameTailwindcss",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureTailwindcssDoc",
|
// title: "menus.pureTailwindcssDoc",
|
||||||
frameSrc: "https://tailwindcss.com/docs/installation",
|
// frameSrc: "https://tailwindcss.com/docs/installation",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/vue3",
|
// path: "/iframe/vue3",
|
||||||
name: "FrameVue",
|
// name: "FrameVue",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureVueDoc",
|
// title: "menus.pureVueDoc",
|
||||||
frameSrc: "https://cn.vuejs.org/",
|
// frameSrc: "https://cn.vuejs.org/",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/vite",
|
// path: "/iframe/vite",
|
||||||
name: "FrameVite",
|
// name: "FrameVite",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureViteDoc",
|
// title: "menus.pureViteDoc",
|
||||||
frameSrc: "https://cn.vitejs.dev/",
|
// frameSrc: "https://cn.vitejs.dev/",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/pinia",
|
// path: "/iframe/pinia",
|
||||||
name: "FramePinia",
|
// name: "FramePinia",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.purePiniaDoc",
|
// title: "menus.purePiniaDoc",
|
||||||
frameSrc: "https://pinia.vuejs.org/zh/index.html",
|
// frameSrc: "https://pinia.vuejs.org/zh/index.html",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/vue-router",
|
// path: "/iframe/vue-router",
|
||||||
name: "FrameRouter",
|
// name: "FrameRouter",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureRouterDoc",
|
// title: "menus.pureRouterDoc",
|
||||||
frameSrc: "https://router.vuejs.org/zh/",
|
// frameSrc: "https://router.vuejs.org/zh/",
|
||||||
keepAlive: true,
|
// keepAlive: true
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/iframe/external",
|
// path: "/iframe/external",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureExternalDoc"
|
// title: "menus.pureExternalDoc"
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: "/external",
|
// path: "/external",
|
||||||
name: "https://pure-admin.github.io/pure-admin-doc",
|
// name: "https://pure-admin.github.io/pure-admin-doc",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureExternalLink",
|
// title: "menus.pureExternalLink"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
path: "/pureUtilsLink",
|
// path: "/pureUtilsLink",
|
||||||
name: "https://pure-admin-utils.netlify.app/",
|
// name: "https://pure-admin-utils.netlify.app/",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureUtilsLink",
|
// title: "menus.pureUtilsLink"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const tabsRouter = {
|
// const tabsRouter = {
|
||||||
path: "/tabs",
|
// path: "/tabs",
|
||||||
meta: {
|
// meta: {
|
||||||
icon: "ri:bookmark-2-line",
|
// icon: "ri:bookmark-2-line",
|
||||||
title: "menus.pureTabs",
|
// title: "menus.pureTabs",
|
||||||
rank: tabs
|
// rank: tabs
|
||||||
},
|
// },
|
||||||
children: [
|
// children: [
|
||||||
{
|
// {
|
||||||
path: "/tabs/index",
|
// path: "/tabs/index",
|
||||||
name: "Tabs",
|
// name: "Tabs",
|
||||||
meta: {
|
// meta: {
|
||||||
title: "menus.pureTabs",
|
// title: "menus.pureTabs"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
// query 传参模式
|
// // query 传参模式
|
||||||
{
|
// {
|
||||||
path: "/tabs/query-detail",
|
// path: "/tabs/query-detail",
|
||||||
name: "TabQueryDetail",
|
// name: "TabQueryDetail",
|
||||||
meta: {
|
// meta: {
|
||||||
// 不在menu菜单中显示
|
// // 不在menu菜单中显示
|
||||||
showLink: false,
|
// showLink: false,
|
||||||
activePath: "/tabs/index",
|
// activePath: "/tabs/index"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
// params 传参模式
|
// // params 传参模式
|
||||||
{
|
// {
|
||||||
path: "/tabs/params-detail/:id",
|
// path: "/tabs/params-detail/:id",
|
||||||
component: "params-detail",
|
// component: "params-detail",
|
||||||
name: "TabParamsDetail",
|
// name: "TabParamsDetail",
|
||||||
meta: {
|
// meta: {
|
||||||
// 不在menu菜单中显示
|
// // 不在menu菜单中显示
|
||||||
showLink: false,
|
// showLink: false,
|
||||||
activePath: "/tabs/index",
|
// activePath: "/tabs/index"
|
||||||
//roles: ["admin", "common"]
|
// //roles: ["admin", "common"]
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default defineFakeRoute([
|
export default defineFakeRoute([
|
||||||
{
|
{
|
||||||
@@ -336,7 +336,7 @@ export default defineFakeRoute([
|
|||||||
response: () => {
|
response: () => {
|
||||||
return [
|
return [
|
||||||
systemManagementRouter,
|
systemManagementRouter,
|
||||||
systemMonitorRouter,
|
systemMonitorRouter
|
||||||
//permissionRouter,
|
//permissionRouter,
|
||||||
// frameRouter,
|
// frameRouter,
|
||||||
// tabsRouter
|
// tabsRouter
|
||||||
|
|||||||
12
Yi.Pure.Vue3/src/api/file.ts
Normal file
12
Yi.Pure.Vue3/src/api/file.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { http } from "@/utils/http";
|
||||||
|
import type { ResultFile } from "@/api/result";
|
||||||
|
|
||||||
|
/** 上传文件*/
|
||||||
|
export const uploadFile = (data?: object) => {
|
||||||
|
return http.request<ResultFile>("post", "/file", {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
|
||||||
|
},
|
||||||
|
data
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -17,3 +17,10 @@ export type ResultPage = {
|
|||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ResultFile = {
|
||||||
|
status: number;
|
||||||
|
data?: Array<{
|
||||||
|
id: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export const updatePostStatus = (id, state) => {
|
|||||||
|
|
||||||
/** 删除岗位 */
|
/** 删除岗位 */
|
||||||
export const delPost = ids => {
|
export const delPost = ids => {
|
||||||
return http.request<Result>("delete", `/post`, { params: { id:ids } });
|
return http.request<Result>("delete", `/post`, { params: { id: ids } });
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 获取岗位选择框列表 */
|
/** 获取岗位选择框列表 */
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const addUser = (data: any) => {
|
|||||||
|
|
||||||
/** 查询用户个人信息 */
|
/** 查询用户个人信息 */
|
||||||
export const getUserProfile = () => {
|
export const getUserProfile = () => {
|
||||||
return http.request<Result>("get", `/account`, {});
|
return http.request<UserInfoResult>("get", `/account`, {});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 修改用户个人信息 */
|
/** 修改用户个人信息 */
|
||||||
@@ -63,3 +63,29 @@ export const updateUserPwd = (oldPassword, newPassword) => {
|
|||||||
};
|
};
|
||||||
return http.request<Result>("put", `/account/password`, { data });
|
return http.request<Result>("put", `/account/password`, { data });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UserInfoResult = {
|
||||||
|
status: number;
|
||||||
|
data: UserInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserInfo = {
|
||||||
|
user: {
|
||||||
|
/** 头像 */
|
||||||
|
icon: string;
|
||||||
|
/** 用户名 */
|
||||||
|
userName: string;
|
||||||
|
/** 昵称 */
|
||||||
|
nick: string;
|
||||||
|
/** 邮箱 */
|
||||||
|
email: string;
|
||||||
|
/** 联系电话 */
|
||||||
|
phone: string;
|
||||||
|
/** 简介 */
|
||||||
|
introduction: string;
|
||||||
|
};
|
||||||
|
/** 当前登录用户的角色 */
|
||||||
|
roleCodes: Array<string>;
|
||||||
|
/** 按钮级别权限 */
|
||||||
|
permissions: Array<string>;
|
||||||
|
};
|
||||||
|
|||||||
@@ -55,40 +55,6 @@ export type RefreshTokenResult = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserInfo = {
|
|
||||||
/** 头像 */
|
|
||||||
avatar: string;
|
|
||||||
/** 用户名 */
|
|
||||||
username: string;
|
|
||||||
/** 昵称 */
|
|
||||||
nickname: string;
|
|
||||||
/** 邮箱 */
|
|
||||||
email: string;
|
|
||||||
/** 联系电话 */
|
|
||||||
phone: string;
|
|
||||||
/** 简介 */
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserInfoResult = {
|
|
||||||
success: boolean;
|
|
||||||
data: UserInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ResultTable = {
|
|
||||||
success: boolean;
|
|
||||||
data?: {
|
|
||||||
/** 列表数据 */
|
|
||||||
list: Array<any>;
|
|
||||||
/** 总条目数 */
|
|
||||||
total?: number;
|
|
||||||
/** 每页显示条目个数 */
|
|
||||||
pageSize?: number;
|
|
||||||
/** 当前页数 */
|
|
||||||
currentPage?: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 登录 */
|
/** 登录 */
|
||||||
export const getLogin = (data?: object) => {
|
export const getLogin = (data?: object) => {
|
||||||
return http.request<LoginResult>("post", "/account/login", { data });
|
return http.request<LoginResult>("post", "/account/login", { data });
|
||||||
@@ -107,13 +73,3 @@ export const getCodeImg = () => {
|
|||||||
export const refreshTokenApi = (data?: object) => {
|
export const refreshTokenApi = (data?: object) => {
|
||||||
return http.request<RefreshTokenResult>("post", "/refresh-token", { data });
|
return http.request<RefreshTokenResult>("post", "/refresh-token", { data });
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 账户设置-个人信息 */
|
|
||||||
export const getMine = (data?: object) => {
|
|
||||||
return http.request<UserInfoResult>("get", "/mine", { data });
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 账户设置-个人安全日志 */
|
|
||||||
export const getMineLogs = (data?: object) => {
|
|
||||||
return http.request<ResultTable>("get", "/mine-logs", { data });
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { useUserStoreHook } from "@/store/modules/user";
|
|||||||
import { useGlobal, isAllEmpty } from "@pureadmin/utils";
|
import { useGlobal, isAllEmpty } from "@pureadmin/utils";
|
||||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import {getFileUrl} from "@/utils/file"
|
import { getFileUrl } from "@/utils/file";
|
||||||
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
||||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ export function useNav() {
|
|||||||
|
|
||||||
/** 头像(如果头像为空则使用 src/assets/user.jpg ) */
|
/** 头像(如果头像为空则使用 src/assets/user.jpg ) */
|
||||||
const userAvatar = computed(() => {
|
const userAvatar = computed(() => {
|
||||||
return getFileUrl(useUserStoreHook()?.avatar,Avatar);
|
return getFileUrl(useUserStoreHook()?.avatar, Avatar);
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 昵称(如果昵称为空则显示用户名) */
|
/** 昵称(如果昵称为空则显示用户名) */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {isAllEmpty} from "@pureadmin/utils";
|
import { isAllEmpty } from "@pureadmin/utils";
|
||||||
|
|
||||||
export function getFileUrl(fileId: string, tryPath: string): string {
|
export function getFileUrl(fileId: string, tryPath: string): string {
|
||||||
if (isAllEmpty(fileId)) {
|
if (isAllEmpty(fileId)) {
|
||||||
|
|||||||
@@ -3,17 +3,13 @@ import Axios, {
|
|||||||
type AxiosRequestConfig,
|
type AxiosRequestConfig,
|
||||||
type CustomParamsSerializer
|
type CustomParamsSerializer
|
||||||
} from "axios";
|
} from "axios";
|
||||||
import type {
|
import type { RequestMethods, PureHttpRequestConfig } from "./types.d";
|
||||||
PureHttpError,
|
|
||||||
RequestMethods,
|
|
||||||
PureHttpRequestConfig
|
|
||||||
} from "./types.d";
|
|
||||||
import { stringify } from "qs";
|
import { stringify } from "qs";
|
||||||
import NProgress from "../progress";
|
import NProgress from "../progress";
|
||||||
import { getToken, formatToken } from "@/utils/auth";
|
import { getToken, formatToken } from "@/utils/auth";
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
import {message} from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
// import { transformI18n } from "@/plugins/i18n";
|
||||||
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
|
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
|
||||||
const defaultConfig: AxiosRequestConfig = {
|
const defaultConfig: AxiosRequestConfig = {
|
||||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||||
@@ -142,7 +138,7 @@ class PureHttp {
|
|||||||
// 关闭进度条动画
|
// 关闭进度条动画
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
// 所有的响应异常 区分来源为取消请求/非取消请求
|
// 所有的响应异常 区分来源为取消请求/非取消请求
|
||||||
return Promise.reject($error);
|
return Promise.reject($error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,27 +12,30 @@ const list = ref([
|
|||||||
title: "账户密码",
|
title: "账户密码",
|
||||||
illustrate: "当前密码强度:强",
|
illustrate: "当前密码强度:强",
|
||||||
button: "修改"
|
button: "修改"
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "密保手机",
|
|
||||||
illustrate: "已经绑定手机:158****6789",
|
|
||||||
button: "修改"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "密保问题",
|
|
||||||
illustrate: "未设置密保问题,密保问题可有效保护账户安全",
|
|
||||||
button: "修改"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "备用邮箱",
|
|
||||||
illustrate: "已绑定邮箱:pure***@163.com",
|
|
||||||
button: "修改"
|
|
||||||
}
|
}
|
||||||
|
// {
|
||||||
|
// title: "密保手机",
|
||||||
|
// illustrate: "已经绑定手机:158****6789",
|
||||||
|
// button: "修改"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: "密保问题",
|
||||||
|
// illustrate: "未设置密保问题,密保问题可有效保护账户安全",
|
||||||
|
// button: "修改"
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// title: "备用邮箱",
|
||||||
|
// illustrate: "已绑定邮箱:pure***@163.com",
|
||||||
|
// button: "修改"
|
||||||
|
// }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function onClick(item) {
|
function onClick(item) {
|
||||||
console.log("onClick", item.title);
|
switch (item.title) {
|
||||||
message("请根据具体业务自行实现", { type: "success" });
|
case "账户密码":
|
||||||
|
message("密码更改成功", { type: "success" });
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,19 @@
|
|||||||
import { reactive, ref } from "vue";
|
import { reactive, ref } from "vue";
|
||||||
import { formUpload } from "@/api/mock";
|
import { formUpload } from "@/api/mock";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { type UserInfo, getMine } from "@/api/user";
|
|
||||||
import type { FormInstance, FormRules } from "element-plus";
|
import type { FormInstance, FormRules } from "element-plus";
|
||||||
import ReCropperPreview from "@/components/ReCropperPreview";
|
import ReCropperPreview from "@/components/ReCropperPreview";
|
||||||
import { createFormData, deviceDetection } from "@pureadmin/utils";
|
import { createFormData, deviceDetection } from "@pureadmin/utils";
|
||||||
import uploadLine from "@iconify-icons/ri/upload-line";
|
import uploadLine from "@iconify-icons/ri/upload-line";
|
||||||
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
|
import {
|
||||||
|
getUserProfile,
|
||||||
|
updateUserIcon,
|
||||||
|
updateUserProfile
|
||||||
|
} from "@/api/system/user";
|
||||||
|
import userAvatar from "@/assets/user.jpg";
|
||||||
|
import { getFileUrl } from "@/utils/file";
|
||||||
|
import { uploadFile } from "@/api/file";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Profile"
|
name: "Profile"
|
||||||
@@ -20,15 +28,16 @@ const isShow = ref(false);
|
|||||||
const userInfoFormRef = ref<FormInstance>();
|
const userInfoFormRef = ref<FormInstance>();
|
||||||
|
|
||||||
const userInfos = reactive({
|
const userInfos = reactive({
|
||||||
avatar: "",
|
icon: "",
|
||||||
nickname: "",
|
nick: "",
|
||||||
email: "",
|
email: "",
|
||||||
phone: "",
|
phone: "",
|
||||||
description: ""
|
introduction: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive<FormRules<UserInfo>>({
|
const rules = reactive<FormRules>({
|
||||||
nickname: [{ required: true, message: "昵称必填", trigger: "blur" }]
|
userName: [{ required: true, message: "用户名必填", trigger: "blur" }],
|
||||||
|
nick: [{ required: true, message: "昵称必填", trigger: "blur" }]
|
||||||
});
|
});
|
||||||
|
|
||||||
function queryEmail(queryString, callback) {
|
function queryEmail(queryString, callback) {
|
||||||
@@ -70,11 +79,13 @@ const onCropper = ({ blob }) => (cropperBlob.value = blob);
|
|||||||
|
|
||||||
const handleSubmitImage = () => {
|
const handleSubmitImage = () => {
|
||||||
const formData = createFormData({
|
const formData = createFormData({
|
||||||
files: new File([cropperBlob.value], "avatar")
|
files: new File([cropperBlob.value], "file")
|
||||||
});
|
});
|
||||||
formUpload(formData)
|
uploadFile(formData)
|
||||||
.then(({ success, data }) => {
|
.then(async ({ status, data }) => {
|
||||||
if (success) {
|
if (status == 200) {
|
||||||
|
await updateUserIcon(data[0].id);
|
||||||
|
useUserStoreHook().SET_AVATAR(data[0].id);
|
||||||
message("更新头像成功", { type: "success" });
|
message("更新头像成功", { type: "success" });
|
||||||
handleClose();
|
handleClose();
|
||||||
} else {
|
} else {
|
||||||
@@ -88,18 +99,17 @@ const handleSubmitImage = () => {
|
|||||||
|
|
||||||
// 更新信息
|
// 更新信息
|
||||||
const onSubmit = async (formEl: FormInstance) => {
|
const onSubmit = async (formEl: FormInstance) => {
|
||||||
await formEl.validate((valid, fields) => {
|
await formEl.validate(async (valid, fields) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
console.log(userInfos);
|
await updateUserProfile(userInfos);
|
||||||
message("更新信息成功", { type: "success" });
|
message("更新信息成功", { type: "success" });
|
||||||
} else {
|
} else {
|
||||||
console.log("error submit!", fields);
|
console.log("error submit!", fields);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
getUserProfile().then(res => {
|
||||||
getMine().then(res => {
|
Object.assign(userInfos, res.data.user);
|
||||||
Object.assign(userInfos, res.data);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -118,7 +128,7 @@ getMine().then(res => {
|
|||||||
:model="userInfos"
|
:model="userInfos"
|
||||||
>
|
>
|
||||||
<el-form-item label="头像">
|
<el-form-item label="头像">
|
||||||
<el-avatar :size="80" :src="userInfos.avatar" />
|
<el-avatar :size="80" :src="getFileUrl(userInfos.icon, userAvatar)" />
|
||||||
<el-upload
|
<el-upload
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
@@ -135,7 +145,7 @@ getMine().then(res => {
|
|||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="昵称" prop="nickname">
|
<el-form-item label="昵称" prop="nickname">
|
||||||
<el-input v-model="userInfos.nickname" placeholder="请输入昵称" />
|
<el-input v-model="userInfos.nick" placeholder="请输入昵称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="邮箱" prop="email">
|
<el-form-item label="邮箱" prop="email">
|
||||||
<el-autocomplete
|
<el-autocomplete
|
||||||
@@ -156,7 +166,7 @@ getMine().then(res => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="简介">
|
<el-form-item label="简介">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="userInfos.description"
|
v-model="userInfos.introduction"
|
||||||
placeholder="请输入简介"
|
placeholder="请输入简介"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:autosize="{ minRows: 6, maxRows: 8 }"
|
:autosize="{ minRows: 6, maxRows: 8 }"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { getMineLogs } from "@/api/user";
|
// import { getMineLogs } from "@/api/user";
|
||||||
import { reactive, ref, onMounted } from "vue";
|
import { reactive, ref, onMounted } from "vue";
|
||||||
import { deviceDetection } from "@pureadmin/utils";
|
import { deviceDetection } from "@pureadmin/utils";
|
||||||
import type { PaginationProps } from "@pureadmin/table";
|
import type { PaginationProps } from "@pureadmin/table";
|
||||||
@@ -55,11 +55,11 @@ const columns: TableColumnList = [
|
|||||||
|
|
||||||
async function onSearch() {
|
async function onSearch() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await getMineLogs();
|
// const { data } = await getMineLogs();
|
||||||
dataList.value = data.list;
|
// dataList.value = data.list;
|
||||||
pagination.total = data.total;
|
// pagination.total = data.total;
|
||||||
pagination.pageSize = data.pageSize;
|
// pagination.pageSize = data.pageSize;
|
||||||
pagination.currentPage = data.currentPage;
|
// pagination.currentPage = data.currentPage;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getMine } from "@/api/user";
|
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { ref, onBeforeMount } from "vue";
|
import { ref, onBeforeMount } from "vue";
|
||||||
import { ReText } from "@/components/ReText";
|
import { ReText } from "@/components/ReText";
|
||||||
@@ -11,11 +10,14 @@ import AccountManagement from "./components/AccountManagement.vue";
|
|||||||
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
|
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
|
||||||
import LaySidebarTopCollapse from "@/layout/components/lay-sidebar/components/SidebarTopCollapse.vue";
|
import LaySidebarTopCollapse from "@/layout/components/lay-sidebar/components/SidebarTopCollapse.vue";
|
||||||
|
|
||||||
|
import userAvatar from "@/assets/user.jpg";
|
||||||
|
import { getFileUrl } from "@/utils/file";
|
||||||
import leftLine from "@iconify-icons/ri/arrow-left-s-line";
|
import leftLine from "@iconify-icons/ri/arrow-left-s-line";
|
||||||
import ProfileIcon from "@iconify-icons/ri/user-3-line";
|
import ProfileIcon from "@iconify-icons/ri/user-3-line";
|
||||||
import PreferencesIcon from "@iconify-icons/ri/settings-3-line";
|
import PreferencesIcon from "@iconify-icons/ri/settings-3-line";
|
||||||
import SecurityLogIcon from "@iconify-icons/ri/window-line";
|
import SecurityLogIcon from "@iconify-icons/ri/window-line";
|
||||||
import AccountManagementIcon from "@iconify-icons/ri/profile-line";
|
import AccountManagementIcon from "@iconify-icons/ri/profile-line";
|
||||||
|
import { getUserProfile } from "@/api/system/user";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "AccountSettings"
|
name: "AccountSettings"
|
||||||
@@ -29,7 +31,7 @@ onBeforeMount(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const userInfo = ref({
|
const userInfo = ref({
|
||||||
avatar: "",
|
icon: "",
|
||||||
userName: "",
|
userName: "",
|
||||||
nick: ""
|
nick: ""
|
||||||
});
|
});
|
||||||
@@ -40,12 +42,12 @@ const panes = [
|
|||||||
icon: ProfileIcon,
|
icon: ProfileIcon,
|
||||||
component: Profile
|
component: Profile
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
key: "preferences",
|
// key: "preferences",
|
||||||
label: "偏好设置",
|
// label: "偏好设置",
|
||||||
icon: PreferencesIcon,
|
// icon: PreferencesIcon,
|
||||||
component: Preferences
|
// component: Preferences
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
key: "securityLog",
|
key: "securityLog",
|
||||||
label: "安全日志",
|
label: "安全日志",
|
||||||
@@ -61,8 +63,8 @@ const panes = [
|
|||||||
];
|
];
|
||||||
const witchPane = ref("profile");
|
const witchPane = ref("profile");
|
||||||
|
|
||||||
getMine().then(res => {
|
getUserProfile().then(res => {
|
||||||
userInfo.value = res.data;
|
userInfo.value = res.data.user;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -84,13 +86,13 @@ getMine().then(res => {
|
|||||||
</div>
|
</div>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
<div class="flex items-center ml-8 mt-4 mb-4">
|
<div class="flex items-center ml-8 mt-4 mb-4">
|
||||||
<el-avatar :size="48" :src="userInfo.avatar" />
|
<el-avatar :size="48" :src="getFileUrl(userInfo.icon, userAvatar)" />
|
||||||
<div class="ml-4 flex flex-col max-w-[130px]">
|
<div class="ml-4 flex flex-col max-w-[130px]">
|
||||||
<ReText class="font-bold !self-baseline">
|
<ReText class="font-bold !self-baseline">
|
||||||
{{ userInfo.nickname }}
|
{{ userInfo.nick }}
|
||||||
</ReText>
|
</ReText>
|
||||||
<ReText class="!self-baseline" type="info">
|
<ReText class="!self-baseline" type="info">
|
||||||
{{ userInfo.username }}
|
{{ userInfo.nick }}
|
||||||
</ReText>
|
</ReText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ getCode();
|
|||||||
:src="codeUrl"
|
:src="codeUrl"
|
||||||
width="120"
|
width="120"
|
||||||
height="40"
|
height="40"
|
||||||
style="width: 120px; height: 40px;max-width: none; "
|
style="width: 120px; height: 40px; max-width: none"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
alt=""
|
alt=""
|
||||||
@click="getCode"
|
@click="getCode"
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function useRole(tableRef: Ref) {
|
|||||||
label: "登录状态",
|
label: "登录状态",
|
||||||
prop: "state",
|
prop: "state",
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
cellRenderer: ({ row, props }) => (
|
cellRenderer: ({ props }) => (
|
||||||
<el-tag size={props.size} style={tagStyle.value(1)}>
|
<el-tag size={props.size} style={tagStyle.value(1)}>
|
||||||
{1 === 1 ? "成功" : "失败"}
|
{1 === 1 ? "成功" : "失败"}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
|
|||||||
@@ -85,11 +85,7 @@ const {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<PureTableBar
|
<PureTableBar title="登录日志" :columns="columns" @refresh="onSearch">
|
||||||
title="登录日志"
|
|
||||||
:columns="columns"
|
|
||||||
@refresh="onSearch"
|
|
||||||
>
|
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<el-popconfirm title="确定要删除所有日志数据吗?" @confirm="clearAll">
|
<el-popconfirm title="确定要删除所有日志数据吗?" @confirm="clearAll">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function useRole(tableRef: Ref) {
|
|||||||
label: "操作状态",
|
label: "操作状态",
|
||||||
prop: "status",
|
prop: "status",
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
cellRenderer: ({ row, props }) => (
|
cellRenderer: ({ props }) => (
|
||||||
<el-tag size={props.size} style={tagStyle.value(1)}>
|
<el-tag size={props.size} style={tagStyle.value(1)}>
|
||||||
{1 === 1 ? "成功" : "失败"}
|
{1 === 1 ? "成功" : "失败"}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
@@ -81,10 +81,10 @@ export function useRole(tableRef: Ref) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "操作时间",
|
label: "操作时间",
|
||||||
prop: "operatingTime",
|
prop: "creationTime",
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
formatter: ({ operatingTime }) =>
|
formatter: ({ creationTime }) =>
|
||||||
dayjs(operatingTime).format("YYYY-MM-DD HH:mm:ss")
|
dayjs(creationTime).format("YYYY-MM-DD HH:mm:ss")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "操作",
|
label: "操作",
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const tableRef = ref();
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
form,
|
form,
|
||||||
timeQuery,
|
|
||||||
loading,
|
loading,
|
||||||
columns,
|
columns,
|
||||||
dataList,
|
dataList,
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { getOnlineLogsList } from "@/api/system";
|
|
||||||
import { reactive, ref, onMounted, toRaw } from "vue";
|
import { reactive, ref, onMounted, toRaw } from "vue";
|
||||||
import type { PaginationProps } from "@pureadmin/table";
|
import type { PaginationProps } from "@pureadmin/table";
|
||||||
import {forceLogout, getOnlineList} from "@/api/monitor/online";
|
import { forceLogout, getOnlineList } from "@/api/monitor/online";
|
||||||
|
|
||||||
export function useRole() {
|
export function useRole() {
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ defineExpose({ getRef });
|
|||||||
<Segmented
|
<Segmented
|
||||||
v-model="newFormInline.menuType"
|
v-model="newFormInline.menuType"
|
||||||
:options="menuTypeOptions"
|
:options="menuTypeOptions"
|
||||||
@change="changeSegmented"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import editForm from "../form.vue";
|
import editForm from "../form.vue";
|
||||||
import { handleTree } from "@/utils/tree";
|
import { handleTree } from "@/utils/tree";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import {addMenu, delMenu, getListMenu, getMenu, updateMenu} from "@/api/system/menu";
|
import {
|
||||||
|
addMenu,
|
||||||
|
delMenu,
|
||||||
|
getListMenu,
|
||||||
|
getMenu,
|
||||||
|
updateMenu
|
||||||
|
} from "@/api/system/menu";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
import { transformI18n } from "@/plugins/i18n";
|
||||||
import { addDialog } from "@/components/ReDialog";
|
import { addDialog } from "@/components/ReDialog";
|
||||||
import { reactive, ref, onMounted, h } from "vue";
|
import { reactive, ref, onMounted, h } from "vue";
|
||||||
|
|||||||
@@ -48,27 +48,15 @@ const treeHeight = ref();
|
|||||||
const {
|
const {
|
||||||
form,
|
form,
|
||||||
isShow,
|
isShow,
|
||||||
curRow,
|
|
||||||
loading,
|
loading,
|
||||||
columns,
|
columns,
|
||||||
rowStyle,
|
rowStyle,
|
||||||
dataList,
|
dataList,
|
||||||
treeData,
|
|
||||||
treeProps,
|
|
||||||
isLinkage,
|
|
||||||
pagination,
|
pagination,
|
||||||
isExpandAll,
|
|
||||||
isSelectAll,
|
|
||||||
treeSearchValue,
|
|
||||||
onSearch,
|
onSearch,
|
||||||
resetForm,
|
resetForm,
|
||||||
openDialog,
|
openDialog,
|
||||||
handleMenu,
|
|
||||||
handleSave,
|
|
||||||
handleDelete,
|
handleDelete,
|
||||||
filterMethod,
|
|
||||||
transformI18n,
|
|
||||||
onQueryChanged,
|
|
||||||
handleSizeChange,
|
handleSizeChange,
|
||||||
handleCurrentChange,
|
handleCurrentChange,
|
||||||
handleSelectionChange
|
handleSelectionChange
|
||||||
@@ -209,69 +197,6 @@ onMounted(() => {
|
|||||||
</pure-table>
|
</pure-table>
|
||||||
</template>
|
</template>
|
||||||
</PureTableBar>
|
</PureTableBar>
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="isShow"
|
|
||||||
class="!min-w-[calc(100vw-60vw-268px)] w-full mt-2 px-2 pb-2 bg-bg_color ml-2 overflow-auto"
|
|
||||||
>
|
|
||||||
<div class="flex justify-between w-full px-3 pt-5 pb-4">
|
|
||||||
<div class="flex">
|
|
||||||
<span :class="iconClass">
|
|
||||||
<IconifyIconOffline
|
|
||||||
v-tippy="{
|
|
||||||
content: '关闭'
|
|
||||||
}"
|
|
||||||
class="dark:text-white"
|
|
||||||
width="18px"
|
|
||||||
height="18px"
|
|
||||||
:icon="Close"
|
|
||||||
@click="handleMenu"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span :class="[iconClass, 'ml-2']">
|
|
||||||
<IconifyIconOffline
|
|
||||||
v-tippy="{
|
|
||||||
content: '保存菜单权限'
|
|
||||||
}"
|
|
||||||
class="dark:text-white"
|
|
||||||
width="18px"
|
|
||||||
height="18px"
|
|
||||||
:icon="Check"
|
|
||||||
@click="handleSave"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p class="font-bold truncate">
|
|
||||||
菜单权限
|
|
||||||
{{ `${curRow?.name ? `(${curRow.name})` : ""}` }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<el-input
|
|
||||||
v-model="treeSearchValue"
|
|
||||||
placeholder="请输入菜单进行搜索"
|
|
||||||
class="mb-1"
|
|
||||||
clearable
|
|
||||||
@input="onQueryChanged"
|
|
||||||
/>
|
|
||||||
<div class="flex flex-wrap">
|
|
||||||
<el-checkbox v-model="isExpandAll" label="展开/折叠" />
|
|
||||||
<el-checkbox v-model="isSelectAll" label="全选/全不选" />
|
|
||||||
<el-checkbox v-model="isLinkage" label="父子联动" />
|
|
||||||
</div>
|
|
||||||
<el-tree-v2
|
|
||||||
ref="treeRef"
|
|
||||||
show-checkbox
|
|
||||||
:data="treeData"
|
|
||||||
:props="treeProps"
|
|
||||||
:height="treeHeight"
|
|
||||||
:check-strictly="!isLinkage"
|
|
||||||
:filter-method="filterMethod"
|
|
||||||
>
|
|
||||||
<template #default="{ node }">
|
|
||||||
<span>{{ transformI18n(node.label) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-tree-v2>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import editForm from "../form.vue";
|
import editForm from "../form.vue";
|
||||||
import {message} from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import {ElMessageBox} from "element-plus";
|
import { ElMessageBox } from "element-plus";
|
||||||
import {usePublicHooks} from "../../hooks";
|
import { usePublicHooks } from "../../hooks";
|
||||||
import {transformI18n} from "@/plugins/i18n";
|
import { transformI18n } from "@/plugins/i18n";
|
||||||
import {addDialog} from "@/components/ReDialog";
|
import { addDialog } from "@/components/ReDialog";
|
||||||
import type {FormItemProps} from "../utils/types";
|
import type { FormItemProps } from "../utils/types";
|
||||||
import type {PaginationProps} from "@pureadmin/table";
|
import type { PaginationProps } from "@pureadmin/table";
|
||||||
import {getKeyList, deviceDetection} from "@pureadmin/utils";
|
import { deviceDetection } from "@pureadmin/utils";
|
||||||
import {
|
import {
|
||||||
getPostList,
|
getPostList,
|
||||||
addPost,
|
addPost,
|
||||||
@@ -15,20 +15,11 @@ import {
|
|||||||
delPost,
|
delPost,
|
||||||
getPost,
|
getPost,
|
||||||
updatePostStatus
|
updatePostStatus
|
||||||
} from "@/api/system/post"
|
} from "@/api/system/post";
|
||||||
|
|
||||||
import {
|
import { reactive, ref, onMounted, h, toRaw } from "vue";
|
||||||
type Ref,
|
|
||||||
reactive,
|
|
||||||
ref,
|
|
||||||
onMounted,
|
|
||||||
h,
|
|
||||||
toRaw,
|
|
||||||
watch,
|
|
||||||
nextTick
|
|
||||||
} from "vue";
|
|
||||||
|
|
||||||
export function usePost(treeRef: Ref) {
|
export function usePost() {
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
postName: "",
|
postName: "",
|
||||||
postCode: "",
|
postCode: "",
|
||||||
@@ -39,7 +30,6 @@ export function usePost(treeRef: Ref) {
|
|||||||
const curRow = ref();
|
const curRow = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const dataList = ref([]);
|
const dataList = ref([]);
|
||||||
const treeIds = ref([]);
|
|
||||||
const treeData = ref([]);
|
const treeData = ref([]);
|
||||||
const isShow = ref(false);
|
const isShow = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@@ -48,7 +38,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
const switchLoadMap = ref({});
|
const switchLoadMap = ref({});
|
||||||
const isExpandAll = ref(false);
|
const isExpandAll = ref(false);
|
||||||
const isSelectAll = ref(false);
|
const isSelectAll = ref(false);
|
||||||
const {switchStyle} = usePublicHooks();
|
const { switchStyle } = usePublicHooks();
|
||||||
const pagination = reactive<PaginationProps>({
|
const pagination = reactive<PaginationProps>({
|
||||||
total: 0,
|
total: 0,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@@ -86,7 +76,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
),
|
),
|
||||||
minWidth: 90
|
minWidth: 90
|
||||||
},
|
},
|
||||||
{label:"排序",prop:"orderNum"},
|
{ label: "排序", prop: "orderNum" },
|
||||||
{
|
{
|
||||||
label: "备注",
|
label: "备注",
|
||||||
prop: "remark",
|
prop: "remark",
|
||||||
@@ -96,7 +86,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
label: "创建时间",
|
label: "创建时间",
|
||||||
prop: "creationTime",
|
prop: "creationTime",
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
formatter: ({creationTime}) =>
|
formatter: ({ creationTime }) =>
|
||||||
dayjs(creationTime).format("YYYY-MM-DD HH:mm:ss")
|
dayjs(creationTime).format("YYYY-MM-DD HH:mm:ss")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -107,7 +97,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
async function onChange({row, index}) {
|
async function onChange({ row, index }) {
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
`确认要<strong>${
|
`确认要<strong>${
|
||||||
row.state === false ? "停用" : "启用"
|
row.state === false ? "停用" : "启用"
|
||||||
@@ -152,7 +142,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
|
|
||||||
async function handleDelete(row) {
|
async function handleDelete(row) {
|
||||||
await delPost([row.id]);
|
await delPost([row.id]);
|
||||||
message(`您删除了角色名称为${row.roleName}的这条数据`, {type: "success"});
|
message(`您删除了角色名称为${row.roleName}的这条数据`, { type: "success" });
|
||||||
onSearch();
|
onSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +162,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
|
|
||||||
async function onSearch() {
|
async function onSearch() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const {data} = await getPostList(toRaw(form));
|
const { data } = await getPostList(toRaw(form));
|
||||||
dataList.value = data.items;
|
dataList.value = data.items;
|
||||||
pagination.total = data.totalCount;
|
pagination.total = data.totalCount;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@@ -196,7 +186,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
postName: row?.postName ?? "",
|
postName: row?.postName ?? "",
|
||||||
postCode: row?.postCode ?? "",
|
postCode: row?.postCode ?? "",
|
||||||
remark: row?.remark ?? "",
|
remark: row?.remark ?? "",
|
||||||
orderNum: data?.orderNum ?? 0,
|
orderNum: data?.orderNum ?? 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
width: "40%",
|
width: "40%",
|
||||||
@@ -204,8 +194,8 @@ export function usePost(treeRef: Ref) {
|
|||||||
fullscreen: deviceDetection(),
|
fullscreen: deviceDetection(),
|
||||||
fullscreenIcon: true,
|
fullscreenIcon: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
contentRenderer: () => h(editForm, {ref: formRef}),
|
contentRenderer: () => h(editForm, { ref: formRef }),
|
||||||
beforeSure: (done, {options}) => {
|
beforeSure: (done, { options }) => {
|
||||||
const FormRef = formRef.value.getRef();
|
const FormRef = formRef.value.getRef();
|
||||||
const curData = options.props.formInline as FormItemProps;
|
const curData = options.props.formInline as FormItemProps;
|
||||||
|
|
||||||
@@ -236,7 +226,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 高亮当前权限选中行 */
|
/** 高亮当前权限选中行 */
|
||||||
function rowStyle({row: {id}}) {
|
function rowStyle({ row: { id } }) {
|
||||||
return {
|
return {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
background: id === curRow.value?.id ? "var(--el-fill-color-light)" : ""
|
background: id === curRow.value?.id ? "var(--el-fill-color-light)" : ""
|
||||||
@@ -244,11 +234,7 @@ export function usePost(treeRef: Ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 数据权限 可自行开发 */
|
/** 数据权限 可自行开发 */
|
||||||
// function handleDatabase() {}
|
// function handleDatabase() {}
|
||||||
|
|
||||||
const onQueryChanged = (query: string) => {
|
|
||||||
treeRef.value!.filter(query);
|
|
||||||
};
|
|
||||||
|
|
||||||
const filterMethod = (query: string, node) => {
|
const filterMethod = (query: string, node) => {
|
||||||
return transformI18n(node.title)!.includes(query);
|
return transformI18n(node.title)!.includes(query);
|
||||||
@@ -258,18 +244,6 @@ export function usePost(treeRef: Ref) {
|
|||||||
onSearch();
|
onSearch();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(isExpandAll, val => {
|
|
||||||
val
|
|
||||||
? treeRef.value.setExpandedKeys(treeIds.value)
|
|
||||||
: treeRef.value.setExpandedKeys([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(isSelectAll, val => {
|
|
||||||
val
|
|
||||||
? treeRef.value.setCheckedKeys(treeIds.value)
|
|
||||||
: treeRef.value.setCheckedKeys([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
form,
|
||||||
isShow,
|
isShow,
|
||||||
@@ -290,7 +264,6 @@ export function usePost(treeRef: Ref) {
|
|||||||
handleDelete,
|
handleDelete,
|
||||||
filterMethod,
|
filterMethod,
|
||||||
transformI18n,
|
transformI18n,
|
||||||
onQueryChanged,
|
|
||||||
handleSizeChange,
|
handleSizeChange,
|
||||||
handleCurrentChange,
|
handleCurrentChange,
|
||||||
handleSelectionChange
|
handleSelectionChange
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ interface FormItemProps {
|
|||||||
/** 备注 */
|
/** 备注 */
|
||||||
remark: string;
|
remark: string;
|
||||||
orderNum: number;
|
orderNum: number;
|
||||||
|
|
||||||
}
|
}
|
||||||
interface FormProps {
|
interface FormProps {
|
||||||
formInline: FormItemProps;
|
formInline: FormItemProps;
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import {
|
|||||||
updateRole,
|
updateRole,
|
||||||
changeRoleStatus,
|
changeRoleStatus,
|
||||||
delRole,
|
delRole,
|
||||||
getRoleMenuSelect,
|
getRoleMenuSelect
|
||||||
updataDataScope
|
|
||||||
} from "@/api/system/role";
|
} from "@/api/system/role";
|
||||||
import { getMenuOption } from "@/api/system/menu";
|
import { getMenuOption } from "@/api/system/menu";
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { PureTableBar } from "@/components/RePureTableBar";
|
|||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
|
||||||
import Upload from "@iconify-icons/ri/upload-line";
|
import Upload from "@iconify-icons/ri/upload-line";
|
||||||
import Role from "@iconify-icons/ri/admin-line";
|
|
||||||
import Password from "@iconify-icons/ri/lock-password-line";
|
import Password from "@iconify-icons/ri/lock-password-line";
|
||||||
import More from "@iconify-icons/ep/more-filled";
|
import More from "@iconify-icons/ep/more-filled";
|
||||||
import Delete from "@iconify-icons/ep/delete";
|
import Delete from "@iconify-icons/ep/delete";
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import "./reset.css";
|
import "./reset.css";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import editForm from "../form/index.vue";
|
import editForm from "../form/index.vue";
|
||||||
import {zxcvbn} from "@zxcvbn-ts/core";
|
import { zxcvbn } from "@zxcvbn-ts/core";
|
||||||
import {handleTree} from "@/utils/tree";
|
import { handleTree } from "@/utils/tree";
|
||||||
import {message} from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import userAvatar from "@/assets/user.jpg";
|
import userAvatar from "@/assets/user.jpg";
|
||||||
import {getFileUrl} from "@/utils/file"
|
import { getFileUrl } from "@/utils/file";
|
||||||
import {usePublicHooks} from "../../hooks";
|
import { usePublicHooks } from "../../hooks";
|
||||||
import {addDialog} from "@/components/ReDialog";
|
import { addDialog } from "@/components/ReDialog";
|
||||||
import type {PaginationProps} from "@pureadmin/table";
|
import type { PaginationProps } from "@pureadmin/table";
|
||||||
import ReCropperPreview from "@/components/ReCropperPreview";
|
import ReCropperPreview from "@/components/ReCropperPreview";
|
||||||
import type {FormItemProps} from "../utils/types";
|
import type { FormItemProps } from "../utils/types";
|
||||||
import {
|
import {
|
||||||
getKeyList,
|
getKeyList,
|
||||||
isAllEmpty,
|
isAllEmpty,
|
||||||
@@ -26,8 +26,8 @@ import {
|
|||||||
updateUser,
|
updateUser,
|
||||||
getUserList
|
getUserList
|
||||||
} from "@/api/system/user";
|
} from "@/api/system/user";
|
||||||
import {getRoleOption} from "@/api/system/role";
|
import { getRoleOption } from "@/api/system/role";
|
||||||
import {getDeptList} from "@/api/system/dept";
|
import { getDeptList } from "@/api/system/dept";
|
||||||
import {
|
import {
|
||||||
ElForm,
|
ElForm,
|
||||||
ElInput,
|
ElInput,
|
||||||
@@ -63,7 +63,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
// 上传头像信息
|
// 上传头像信息
|
||||||
const avatarInfo = ref();
|
const avatarInfo = ref();
|
||||||
const switchLoadMap = ref({});
|
const switchLoadMap = ref({});
|
||||||
const {switchStyle} = usePublicHooks();
|
const { switchStyle } = usePublicHooks();
|
||||||
const higherDeptOptions = ref();
|
const higherDeptOptions = ref();
|
||||||
const treeData = ref([]);
|
const treeData = ref([]);
|
||||||
const treeLoading = ref(true);
|
const treeLoading = ref(true);
|
||||||
@@ -89,12 +89,12 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
{
|
{
|
||||||
label: "用户头像",
|
label: "用户头像",
|
||||||
prop: "avatar",
|
prop: "avatar",
|
||||||
cellRenderer: ({row}) => (
|
cellRenderer: ({ row }) => (
|
||||||
<el-image
|
<el-image
|
||||||
fit="cover"
|
fit="cover"
|
||||||
preview-teleported={true}
|
preview-teleported={true}
|
||||||
src={getFileUrl(row.avatar, userAvatar)}
|
src={getFileUrl(row.avatar, userAvatar)}
|
||||||
preview-src-list={Array.of(getFileUrl(row.avatar , userAvatar))}
|
preview-src-list={Array.of(getFileUrl(row.avatar, userAvatar))}
|
||||||
class="w-[24px] h-[24px] rounded-full align-middle"
|
class="w-[24px] h-[24px] rounded-full align-middle"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -114,7 +114,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
label: "性别",
|
label: "性别",
|
||||||
prop: "sex",
|
prop: "sex",
|
||||||
minWidth: 90,
|
minWidth: 90,
|
||||||
cellRenderer: ({row, props}) => (
|
cellRenderer: ({ row, props }) => (
|
||||||
<el-tag
|
<el-tag
|
||||||
size={props.size}
|
size={props.size}
|
||||||
type={row.sex === "Woman" ? "danger" : null}
|
type={row.sex === "Woman" ? "danger" : null}
|
||||||
@@ -133,8 +133,8 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
label: "手机号码",
|
label: "手机号码",
|
||||||
prop: "phone",
|
prop: "phone",
|
||||||
minWidth: 90,
|
minWidth: 90,
|
||||||
formatter: ({phone}) =>
|
formatter: ({ phone }) =>
|
||||||
phone == null ? "-" : hideTextAtIndex(phone, {start: 3, end: 6})
|
phone == null ? "-" : hideTextAtIndex(phone, { start: 3, end: 6 })
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "状态",
|
label: "状态",
|
||||||
@@ -159,7 +159,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
label: "创建时间",
|
label: "创建时间",
|
||||||
minWidth: 90,
|
minWidth: 90,
|
||||||
prop: "creationTime",
|
prop: "creationTime",
|
||||||
formatter: ({creationTime}) =>
|
formatter: ({ creationTime }) =>
|
||||||
dayjs(creationTime).format("YYYY-MM-DD HH:mm:ss")
|
dayjs(creationTime).format("YYYY-MM-DD HH:mm:ss")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -183,17 +183,17 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
password: ""
|
password: ""
|
||||||
});
|
});
|
||||||
const pwdProgress = [
|
const pwdProgress = [
|
||||||
{color: "#e74242", text: "非常弱"},
|
{ color: "#e74242", text: "非常弱" },
|
||||||
{color: "#EFBD47", text: "弱"},
|
{ color: "#EFBD47", text: "弱" },
|
||||||
{color: "#ffa500", text: "一般"},
|
{ color: "#ffa500", text: "一般" },
|
||||||
{color: "#1bbf1b", text: "强"},
|
{ color: "#1bbf1b", text: "强" },
|
||||||
{color: "#008000", text: "非常强"}
|
{ color: "#008000", text: "非常强" }
|
||||||
];
|
];
|
||||||
// 当前密码强度(0-4)
|
// 当前密码强度(0-4)
|
||||||
const curScore = ref();
|
const curScore = ref();
|
||||||
const roleOptions = ref([]);
|
const roleOptions = ref([]);
|
||||||
|
|
||||||
function onChange({row, index}) {
|
function onChange({ row, index }) {
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
`确认要<strong>${
|
`确认要<strong>${
|
||||||
row.state === 0 ? "停用" : "启用"
|
row.state === 0 ? "停用" : "启用"
|
||||||
@@ -242,7 +242,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
|
|
||||||
async function handleDelete(row) {
|
async function handleDelete(row) {
|
||||||
await delUser([row.id]);
|
await delUser([row.id]);
|
||||||
message(`您删除了用户编号为${row.id}的这条数据`, {type: "success"});
|
message(`您删除了用户编号为${row.id}的这条数据`, { type: "success" });
|
||||||
onSearch();
|
onSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
|
|
||||||
async function onSearch() {
|
async function onSearch() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const {data} = await getUserList(toRaw(form));
|
const { data } = await getUserList(toRaw(form));
|
||||||
dataList.value = data.items;
|
dataList.value = data.items;
|
||||||
pagination.total = data.totalCount;
|
pagination.total = data.totalCount;
|
||||||
// pagination.pageSize = data.pageSize;
|
// pagination.pageSize = data.pageSize;
|
||||||
@@ -305,7 +305,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
onSearch();
|
onSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
function onTreeSelect({id, selected}) {
|
function onTreeSelect({ id, selected }) {
|
||||||
form.deptId = selected ? id : "";
|
form.deptId = selected ? id : "";
|
||||||
onSearch();
|
onSearch();
|
||||||
}
|
}
|
||||||
@@ -353,8 +353,8 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
fullscreen: deviceDetection(),
|
fullscreen: deviceDetection(),
|
||||||
fullscreenIcon: true,
|
fullscreenIcon: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
contentRenderer: () => h(editForm, {ref: formRef}),
|
contentRenderer: () => h(editForm, { ref: formRef }),
|
||||||
beforeSure: (done, {options}) => {
|
beforeSure: (done, { options }) => {
|
||||||
const FormRef = formRef.value.getRef();
|
const FormRef = formRef.value.getRef();
|
||||||
const curData = options.props.formInline as FormItemProps;
|
const curData = options.props.formInline as FormItemProps;
|
||||||
|
|
||||||
@@ -411,7 +411,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
pwdForm,
|
pwdForm,
|
||||||
({password}) =>
|
({ password }) =>
|
||||||
(curScore.value = isAllEmpty(password) ? -1 : zxcvbn(password).score)
|
(curScore.value = isAllEmpty(password) ? -1 : zxcvbn(password).score)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -446,10 +446,10 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElForm>
|
</ElForm>
|
||||||
<div class="mt-4 flex">
|
<div class="mt-4 flex">
|
||||||
{pwdProgress.map(({color, text}, idx) => (
|
{pwdProgress.map(({ color, text }, idx) => (
|
||||||
<div
|
<div
|
||||||
class="w-[19vw]"
|
class="w-[19vw]"
|
||||||
style={{marginLeft: idx !== 0 ? "4px" : 0}}
|
style={{ marginLeft: idx !== 0 ? "4px" : 0 }}
|
||||||
>
|
>
|
||||||
<ElProgress
|
<ElProgress
|
||||||
striped
|
striped
|
||||||
@@ -462,7 +462,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
/>
|
/>
|
||||||
<p
|
<p
|
||||||
class="text-center"
|
class="text-center"
|
||||||
style={{color: curScore.value === idx ? color : ""}}
|
style={{ color: curScore.value === idx ? color : "" }}
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</p>
|
</p>
|
||||||
@@ -494,7 +494,7 @@ export function useUser(tableRef: Ref, treeRef: Ref) {
|
|||||||
onSearch();
|
onSearch();
|
||||||
|
|
||||||
// 归属部门
|
// 归属部门
|
||||||
const {data} = await getDeptList();
|
const { data } = await getDeptList();
|
||||||
higherDeptOptions.value = handleTree(data.items);
|
higherDeptOptions.value = handleTree(data.items);
|
||||||
treeData.value = handleTree(data.items);
|
treeData.value = handleTree(data.items);
|
||||||
treeLoading.value = false;
|
treeLoading.value = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user