🔨 修改路由配置.
This commit is contained in:
@@ -19,8 +19,8 @@ import org.dromara.visor.framework.common.security.LoginUser;
|
|||||||
import org.dromara.visor.module.infra.entity.domain.SystemUserDO;
|
import org.dromara.visor.module.infra.entity.domain.SystemUserDO;
|
||||||
import org.dromara.visor.module.infra.entity.dto.UserInfoDTO;
|
import org.dromara.visor.module.infra.entity.dto.UserInfoDTO;
|
||||||
import org.dromara.visor.module.infra.entity.request.user.*;
|
import org.dromara.visor.module.infra.entity.request.user.*;
|
||||||
|
import org.dromara.visor.module.infra.entity.vo.SystemUserBaseVO;
|
||||||
import org.dromara.visor.module.infra.entity.vo.SystemUserVO;
|
import org.dromara.visor.module.infra.entity.vo.SystemUserVO;
|
||||||
import org.dromara.visor.module.infra.entity.vo.UserCollectInfoVO;
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
@@ -58,6 +58,6 @@ public interface SystemUserConvert {
|
|||||||
|
|
||||||
UserInfoDTO toUserInfo(SystemUserDO domain);
|
UserInfoDTO toUserInfo(SystemUserDO domain);
|
||||||
|
|
||||||
UserCollectInfoVO toCollectInfo(LoginUser user);
|
SystemUserBaseVO toBase(SystemUserDO user);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ public class SystemUserDO extends BaseDO {
|
|||||||
@TableField("status")
|
@TableField("status")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "修改密码状态")
|
||||||
|
@TableField("update_password_status")
|
||||||
|
private Integer passwordUpdateStatus;
|
||||||
|
|
||||||
|
@Schema(description = "修改密码原因")
|
||||||
|
@TableField("update_password_reason")
|
||||||
|
private String passwordUpdateReason;
|
||||||
|
|
||||||
@Schema(description = "最后登录时间")
|
@Schema(description = "最后登录时间")
|
||||||
@TableField("last_login_time")
|
@TableField("last_login_time")
|
||||||
private Date lastLoginTime;
|
private Date lastLoginTime;
|
||||||
|
|||||||
@@ -21,9 +21,6 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户基本信息 视图响应对象
|
* 用户基本信息 视图响应对象
|
||||||
*
|
*
|
||||||
@@ -35,8 +32,8 @@ import java.util.Map;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Schema(name = "UserCollectInfoVO", description = "用户聚合信息 视图响应对象")
|
@Schema(name = "SystemUserBaseVO", description = "用户基本信息 视图响应对象")
|
||||||
public class UserCollectInfoVO {
|
public class SystemUserBaseVO {
|
||||||
|
|
||||||
@Schema(description = "id")
|
@Schema(description = "id")
|
||||||
private Long id;
|
private Long id;
|
||||||
@@ -50,10 +47,10 @@ public class UserCollectInfoVO {
|
|||||||
@Schema(description = "头像地址")
|
@Schema(description = "头像地址")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
|
|
||||||
@Schema(description = "系统偏好")
|
@Schema(description = "修改密码状态")
|
||||||
private Map<String, Object> systemPreference;
|
private Integer passwordUpdateStatus;
|
||||||
|
|
||||||
@Schema(description = "已经提示的key")
|
@Schema(description = "修改密码原因")
|
||||||
private List<String> tippedKeys;
|
private String passwordUpdateReason;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ import lombok.NoArgsConstructor;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户权限 视图响应对象
|
* 用户权限 视图响应对象
|
||||||
@@ -38,8 +39,8 @@ import java.util.List;
|
|||||||
@Schema(name = "UserPermissionVO", description = "用户权限 视图响应对象")
|
@Schema(name = "UserPermissionVO", description = "用户权限 视图响应对象")
|
||||||
public class UserPermissionVO {
|
public class UserPermissionVO {
|
||||||
|
|
||||||
@Schema(description = "用户聚合信息")
|
@Schema(description = "用户信息")
|
||||||
private UserCollectInfoVO user;
|
private SystemUserBaseVO user;
|
||||||
|
|
||||||
@Schema(description = "该用户已启用的角色")
|
@Schema(description = "该用户已启用的角色")
|
||||||
private Collection<String> roles;
|
private Collection<String> roles;
|
||||||
@@ -47,4 +48,10 @@ public class UserPermissionVO {
|
|||||||
@Schema(description = "该用户已启用的权限")
|
@Schema(description = "该用户已启用的权限")
|
||||||
private List<String> permissions;
|
private List<String> permissions;
|
||||||
|
|
||||||
|
@Schema(description = "系统偏好")
|
||||||
|
private Map<String, Object> systemPreference;
|
||||||
|
|
||||||
|
@Schema(description = "已经提示的key")
|
||||||
|
private List<String> tippedKeys;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Jiahang Li (visor.orionsec.cn ljh1553488six@139.com).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.module.infra.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新密码原因
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/12/11 14:37
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum UpdatePasswordReasonEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新用户
|
||||||
|
*/
|
||||||
|
NEW,
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 - present Jiahang Li (visor.orionsec.cn ljh1553488six@139.com).
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.dromara.visor.module.infra.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新密码状态
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/12/11 14:37
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum UpdatePasswordStatusEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无需修改
|
||||||
|
*/
|
||||||
|
NO_REQUIRE(0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要修改
|
||||||
|
*/
|
||||||
|
REQUIRED(1),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer status;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -49,6 +49,8 @@ import org.dromara.visor.module.infra.entity.domain.SystemUserDO;
|
|||||||
import org.dromara.visor.module.infra.entity.dto.UserInfoDTO;
|
import org.dromara.visor.module.infra.entity.dto.UserInfoDTO;
|
||||||
import org.dromara.visor.module.infra.entity.request.user.*;
|
import org.dromara.visor.module.infra.entity.request.user.*;
|
||||||
import org.dromara.visor.module.infra.entity.vo.SystemUserVO;
|
import org.dromara.visor.module.infra.entity.vo.SystemUserVO;
|
||||||
|
import org.dromara.visor.module.infra.enums.UpdatePasswordReasonEnum;
|
||||||
|
import org.dromara.visor.module.infra.enums.UpdatePasswordStatusEnum;
|
||||||
import org.dromara.visor.module.infra.enums.UserStatusEnum;
|
import org.dromara.visor.module.infra.enums.UserStatusEnum;
|
||||||
import org.dromara.visor.module.infra.service.*;
|
import org.dromara.visor.module.infra.service.*;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
@@ -118,6 +120,8 @@ public class SystemUserServiceImpl implements SystemUserService {
|
|||||||
this.checkNicknamePresent(record);
|
this.checkNicknamePresent(record);
|
||||||
// 加密密码
|
// 加密密码
|
||||||
record.setPassword(Signatures.md5(request.getPassword()));
|
record.setPassword(Signatures.md5(request.getPassword()));
|
||||||
|
record.setPasswordUpdateStatus(UpdatePasswordStatusEnum.REQUIRED.getStatus());
|
||||||
|
record.setPasswordUpdateReason(UpdatePasswordReasonEnum.NEW.name());
|
||||||
// 插入
|
// 插入
|
||||||
int effect = systemUserDAO.insert(record);
|
int effect = systemUserDAO.insert(record);
|
||||||
log.info("SystemUserService-createSystemUser effect: {}, record: {}", effect, JSON.toJSONString(record));
|
log.info("SystemUserService-createSystemUser effect: {}, record: {}", effect, JSON.toJSONString(record));
|
||||||
@@ -309,6 +313,8 @@ public class SystemUserServiceImpl implements SystemUserService {
|
|||||||
SystemUserDO update = new SystemUserDO();
|
SystemUserDO update = new SystemUserDO();
|
||||||
update.setId(id);
|
update.setId(id);
|
||||||
update.setPassword(Signatures.md5(request.getPassword()));
|
update.setPassword(Signatures.md5(request.getPassword()));
|
||||||
|
update.setPasswordUpdateStatus(UpdatePasswordStatusEnum.NO_REQUIRE.getStatus());
|
||||||
|
update.setPasswordUpdateReason(Const.EMPTY);
|
||||||
int effect = systemUserDAO.updateById(update);
|
int effect = systemUserDAO.updateById(update);
|
||||||
log.info("SystemUserService-resetPassword record: {}, effect: {}", JSON.toJSONString(update), effect);
|
log.info("SystemUserService-resetPassword record: {}, effect: {}", JSON.toJSONString(update), effect);
|
||||||
// 删除登录失败次数缓存
|
// 删除登录失败次数缓存
|
||||||
|
|||||||
@@ -30,13 +30,14 @@ import org.dromara.visor.module.infra.convert.SystemUserConvert;
|
|||||||
import org.dromara.visor.module.infra.dao.SystemMenuDAO;
|
import org.dromara.visor.module.infra.dao.SystemMenuDAO;
|
||||||
import org.dromara.visor.module.infra.dao.SystemRoleDAO;
|
import org.dromara.visor.module.infra.dao.SystemRoleDAO;
|
||||||
import org.dromara.visor.module.infra.dao.SystemRoleMenuDAO;
|
import org.dromara.visor.module.infra.dao.SystemRoleMenuDAO;
|
||||||
|
import org.dromara.visor.module.infra.dao.SystemUserDAO;
|
||||||
import org.dromara.visor.module.infra.define.RoleDefine;
|
import org.dromara.visor.module.infra.define.RoleDefine;
|
||||||
import org.dromara.visor.module.infra.entity.domain.SystemMenuDO;
|
import org.dromara.visor.module.infra.entity.domain.SystemMenuDO;
|
||||||
import org.dromara.visor.module.infra.entity.domain.SystemRoleDO;
|
import org.dromara.visor.module.infra.entity.domain.SystemRoleDO;
|
||||||
import org.dromara.visor.module.infra.entity.domain.SystemRoleMenuDO;
|
import org.dromara.visor.module.infra.entity.domain.SystemRoleMenuDO;
|
||||||
|
import org.dromara.visor.module.infra.entity.domain.SystemUserDO;
|
||||||
import org.dromara.visor.module.infra.entity.dto.SystemMenuCacheDTO;
|
import org.dromara.visor.module.infra.entity.dto.SystemMenuCacheDTO;
|
||||||
import org.dromara.visor.module.infra.entity.vo.SystemMenuVO;
|
import org.dromara.visor.module.infra.entity.vo.SystemMenuVO;
|
||||||
import org.dromara.visor.module.infra.entity.vo.UserCollectInfoVO;
|
|
||||||
import org.dromara.visor.module.infra.entity.vo.UserPermissionVO;
|
import org.dromara.visor.module.infra.entity.vo.UserPermissionVO;
|
||||||
import org.dromara.visor.module.infra.enums.MenuStatusEnum;
|
import org.dromara.visor.module.infra.enums.MenuStatusEnum;
|
||||||
import org.dromara.visor.module.infra.enums.MenuTypeEnum;
|
import org.dromara.visor.module.infra.enums.MenuTypeEnum;
|
||||||
@@ -76,6 +77,9 @@ public class UserPermissionServiceImpl implements UserPermissionService {
|
|||||||
@Getter
|
@Getter
|
||||||
private final Map<Long, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>();
|
private final Map<Long, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>();
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SystemUserDAO systemUserDAO;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SystemRoleDAO systemRoleDAO;
|
private SystemRoleDAO systemRoleDAO;
|
||||||
|
|
||||||
@@ -229,43 +233,24 @@ public class UserPermissionServiceImpl implements UserPermissionService {
|
|||||||
@Override
|
@Override
|
||||||
public UserPermissionVO getUserPermission() {
|
public UserPermissionVO getUserPermission() {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
UserCollectInfoVO user = SystemUserConvert.MAPPER.toCollectInfo(SecurityUtils.getLoginUser());
|
Long userId = SecurityUtils.getLoginUserId();
|
||||||
Long id = user.getId();
|
|
||||||
// 获取用户系统偏好
|
// 获取用户系统偏好
|
||||||
Future<Map<String, Object>> systemPreference = preferenceService.getPreferenceAsync(id, PreferenceTypeEnum.SYSTEM);
|
Future<Map<String, Object>> systemPreference = preferenceService.getPreferenceAsync(userId, PreferenceTypeEnum.SYSTEM);
|
||||||
|
// 查询用户信息
|
||||||
|
SystemUserDO user = systemUserDAO.selectById(userId);
|
||||||
// 获取用户角色
|
// 获取用户角色
|
||||||
Map<Long, String> roles = this.getUserEnabledRoles();
|
Map<Long, String> roles = this.getUserEnabledRoles();
|
||||||
// 获取用户权限
|
// 获取角色权限
|
||||||
List<String> permissions;
|
List<String> permissions = this.getRolePermissions(roles);
|
||||||
if (roles.isEmpty()) {
|
// 提示信息
|
||||||
permissions = Lists.empty();
|
List<String> tippedKeys = tipsService.getTippedKeys();
|
||||||
} else {
|
|
||||||
if (RoleDefine.containsAdmin(roles.values())) {
|
|
||||||
// 管理员拥有全部权限
|
|
||||||
permissions = Lists.of(Const.ASTERISK);
|
|
||||||
} else {
|
|
||||||
// 当前用户所适配的角色的权限
|
|
||||||
permissions = roles.keySet()
|
|
||||||
.stream()
|
|
||||||
.map(roleMenuCache::get)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus()))
|
|
||||||
.map(SystemMenuCacheDTO::getPermission)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.distinct()
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 设置已提示的 key
|
|
||||||
user.setTippedKeys(tipsService.getTippedKeys());
|
|
||||||
// 获取异步结果
|
|
||||||
user.setSystemPreference(systemPreference.get());
|
|
||||||
// 组装数据
|
// 组装数据
|
||||||
return UserPermissionVO.builder()
|
return UserPermissionVO.builder()
|
||||||
.user(user)
|
.user(SystemUserConvert.MAPPER.toBase(user))
|
||||||
.roles(roles.values())
|
.roles(roles.values())
|
||||||
.permissions(permissions)
|
.permissions(permissions)
|
||||||
|
.systemPreference(systemPreference.get())
|
||||||
|
.tippedKeys(tippedKeys)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,4 +302,31 @@ public class UserPermissionServiceImpl implements UserPermissionService {
|
|||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取角色对应的权限
|
||||||
|
*
|
||||||
|
* @param roles roles
|
||||||
|
* @return 权限
|
||||||
|
*/
|
||||||
|
private List<String> getRolePermissions(Map<Long, String> roles) {
|
||||||
|
if (Maps.isEmpty(roles)) {
|
||||||
|
return Lists.empty();
|
||||||
|
}
|
||||||
|
// 管理员拥有全部权限
|
||||||
|
if (RoleDefine.containsAdmin(roles.values())) {
|
||||||
|
return Lists.singleton(Const.ASTERISK);
|
||||||
|
}
|
||||||
|
// 角色权限
|
||||||
|
return roles.keySet()
|
||||||
|
.stream()
|
||||||
|
.map(roleMenuCache::get)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.filter(s -> MenuStatusEnum.ENABLED.getStatus().equals(s.getStatus()))
|
||||||
|
.map(SystemMenuCacheDTO::getPermission)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
<result column="mobile" property="mobile"/>
|
<result column="mobile" property="mobile"/>
|
||||||
<result column="email" property="email"/>
|
<result column="email" property="email"/>
|
||||||
<result column="status" property="status"/>
|
<result column="status" property="status"/>
|
||||||
|
<result column="update_password_status" property="passwordUpdateStatus"/>
|
||||||
|
<result column="update_password_reason" property="passwordUpdateReason"/>
|
||||||
<result column="last_login_time" property="lastLoginTime"/>
|
<result column="last_login_time" property="lastLoginTime"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<!-- 通用查询结果列 -->
|
<!-- 通用查询结果列 -->
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
id, username, password, nickname, avatar, mobile, email, status, last_login_time, create_time, update_time, creator, updater, deleted
|
id, username, password, nickname, avatar, mobile, email, status, update_password_status, update_password_reason, last_login_time, create_time, update_time, creator, updater, deleted
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { MenuQueryResponse } from '@/api/system/menu';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,45 +16,15 @@ export interface LoginResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户权限响应
|
* 用户登录
|
||||||
*/
|
*/
|
||||||
export interface UserPermissionResponse {
|
export function userLogin(data: LoginRequest) {
|
||||||
user: {
|
|
||||||
id: number;
|
|
||||||
username: string;
|
|
||||||
nickname: string;
|
|
||||||
avatar: string;
|
|
||||||
systemPreference: Record<string, any>;
|
|
||||||
tippedKeys: Array<string>;
|
|
||||||
};
|
|
||||||
roles: Array<string>;
|
|
||||||
permissions: Array<string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录
|
|
||||||
*/
|
|
||||||
export function login(data: LoginRequest) {
|
|
||||||
return axios.post<LoginResponse>('/infra/auth/login', data);
|
return axios.post<LoginResponse>('/infra/auth/login', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登出
|
* 用户登出
|
||||||
*/
|
*/
|
||||||
export function logout() {
|
export function userLogout() {
|
||||||
return axios.get('/infra/auth/logout');
|
return axios.get('/infra/auth/logout');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取用户信息
|
|
||||||
*/
|
|
||||||
export function getUserPermission() {
|
|
||||||
return axios.get<UserPermissionResponse>('/infra/user-permission/user');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取菜单列表
|
|
||||||
*/
|
|
||||||
export function getMenuList() {
|
|
||||||
return axios.get<Array<MenuQueryResponse>>('/infra/user-permission/menu');
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import axios from 'axios';
|
|||||||
export interface UserUpdatePasswordRequest {
|
export interface UserUpdatePasswordRequest {
|
||||||
beforePassword?: string;
|
beforePassword?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
|
checkPassword?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
39
orion-visor-ui/src/api/user/permission.ts
Normal file
39
orion-visor-ui/src/api/user/permission.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import type { MenuQueryResponse } from '@/api/system/menu';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户权限响应
|
||||||
|
*/
|
||||||
|
export interface UserPermissionResponse {
|
||||||
|
user: UserBaseResponse;
|
||||||
|
roles: Array<string>;
|
||||||
|
permissions: Array<string>;
|
||||||
|
systemPreference: Record<string, any>;
|
||||||
|
tippedKeys: Array<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户基础信息
|
||||||
|
*/
|
||||||
|
export interface UserBaseResponse {
|
||||||
|
id: number;
|
||||||
|
username: string;
|
||||||
|
nickname: string;
|
||||||
|
avatar: string;
|
||||||
|
passwordUpdateStatus: number;
|
||||||
|
passwordUpdateReason: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户信息
|
||||||
|
*/
|
||||||
|
export function getUserPermission() {
|
||||||
|
return axios.get<UserPermissionResponse>('/infra/user-permission/user');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取菜单列表
|
||||||
|
*/
|
||||||
|
export function getUserMenuList() {
|
||||||
|
return axios.get<Array<MenuQueryResponse>>('/infra/user-permission/menu');
|
||||||
|
}
|
||||||
@@ -122,7 +122,6 @@
|
|||||||
// 关闭左侧
|
// 关闭左侧
|
||||||
const currentRouteIdx = findCurrentRouteIndex();
|
const currentRouteIdx = findCurrentRouteIndex();
|
||||||
copyTagList.splice(1, props.index - 1);
|
copyTagList.splice(1, props.index - 1);
|
||||||
|
|
||||||
tabBarStore.freshTabList(copyTagList);
|
tabBarStore.freshTabList(copyTagList);
|
||||||
if (currentRouteIdx < index) {
|
if (currentRouteIdx < index) {
|
||||||
await router.push({ name: itemData.name });
|
await router.push({ name: itemData.name });
|
||||||
@@ -131,7 +130,6 @@
|
|||||||
// 关闭右侧
|
// 关闭右侧
|
||||||
const currentRouteIdx = findCurrentRouteIndex();
|
const currentRouteIdx = findCurrentRouteIndex();
|
||||||
copyTagList.splice(props.index + 1);
|
copyTagList.splice(props.index + 1);
|
||||||
|
|
||||||
tabBarStore.freshTabList(copyTagList);
|
tabBarStore.freshTabList(copyTagList);
|
||||||
if (currentRouteIdx > index) {
|
if (currentRouteIdx > index) {
|
||||||
await router.push({ name: itemData.name });
|
await router.push({ name: itemData.name });
|
||||||
@@ -154,7 +152,8 @@
|
|||||||
} else {
|
} else {
|
||||||
// 关闭全部
|
// 关闭全部
|
||||||
tabBarStore.resetTabList();
|
tabBarStore.resetTabList();
|
||||||
await router.push({ name: DEFAULT_ROUTE_NAME });
|
// 跳转到首页 添加 query 强行刷新
|
||||||
|
await router.push({ name: DEFAULT_ROUTE_NAME, query: { _: Date.now() } });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<a-modal v-model:visible="visible"
|
<a-modal v-model:visible="visible"
|
||||||
modal-class="modal-form-large"
|
modal-class="modal-form-large"
|
||||||
title-align="start"
|
title-align="start"
|
||||||
title="重置密码"
|
title="修改密码"
|
||||||
:top="120"
|
:top="120"
|
||||||
:align-center="false"
|
:align-center="false"
|
||||||
:draggable="true"
|
:draggable="true"
|
||||||
@@ -16,16 +16,25 @@
|
|||||||
<a-form :model="formModel"
|
<a-form :model="formModel"
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
label-align="right"
|
label-align="right"
|
||||||
:rules="rules"
|
:rules="rules">
|
||||||
:auto-label-width="true">
|
<!-- 原始密码 -->
|
||||||
<!-- 密码 -->
|
<a-form-item field="beforePassword"
|
||||||
<a-form-item field="beforePassword" label="原始密码">
|
label="原始密码"
|
||||||
|
hide-label>
|
||||||
<a-input-password v-model="formModel.beforePassword" placeholder="请输入原始密码" />
|
<a-input-password v-model="formModel.beforePassword" placeholder="请输入原始密码" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<!-- 密码 -->
|
<!-- 新密码 -->
|
||||||
<a-form-item field="password" label="新密码">
|
<a-form-item field="password"
|
||||||
|
label="新密码"
|
||||||
|
hide-label>
|
||||||
<a-input-password v-model="formModel.password" placeholder="请输入新密码" />
|
<a-input-password v-model="formModel.password" placeholder="请输入新密码" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<!-- 确认密码 -->
|
||||||
|
<a-form-item field="checkPassword"
|
||||||
|
label="确认密码"
|
||||||
|
hide-label>
|
||||||
|
<a-input-password v-model="formModel.checkPassword" placeholder="请再次输入新密码" />
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
@@ -38,12 +47,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import type { FieldRule } from '@arco-design/web-vue';
|
||||||
import type { UserUpdatePasswordRequest } from '@/api/user/mine';
|
import type { UserUpdatePasswordRequest } from '@/api/user/mine';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { md5 } from '@/utils';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import { md5 } from '@/utils';
|
|
||||||
import { updateCurrentUserPassword } from '@/api/user/mine';
|
import { updateCurrentUserPassword } from '@/api/user/mine';
|
||||||
|
|
||||||
const emits = defineEmits(['updated']);
|
const emits = defineEmits(['updated']);
|
||||||
@@ -63,8 +73,26 @@
|
|||||||
minLength: 8,
|
minLength: 8,
|
||||||
maxLength: 32,
|
maxLength: 32,
|
||||||
message: '新密码长度需要在 8-32 位之间'
|
message: '新密码长度需要在 8-32 位之间'
|
||||||
|
}, {
|
||||||
|
validator: (value, cb) => {
|
||||||
|
if (formModel.value.beforePassword === value) {
|
||||||
|
cb('新密码不能和原始密码相同');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}],
|
}],
|
||||||
};
|
checkPassword: [{
|
||||||
|
required: true,
|
||||||
|
message: '请再次输入新密码'
|
||||||
|
}, {
|
||||||
|
validator: (value, cb) => {
|
||||||
|
if (formModel.value.password !== value) {
|
||||||
|
cb('两次输入的密码不一致');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
} as Record<string, FieldRule | FieldRule[]>;
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formModel = ref<UserUpdatePasswordRequest>({});
|
const formModel = ref<UserUpdatePasswordRequest>({});
|
||||||
@@ -73,7 +101,8 @@
|
|||||||
const open = () => {
|
const open = () => {
|
||||||
formModel.value = {
|
formModel.value = {
|
||||||
beforePassword: undefined,
|
beforePassword: undefined,
|
||||||
password: undefined
|
password: undefined,
|
||||||
|
checkPassword: undefined,
|
||||||
};
|
};
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
};
|
};
|
||||||
@@ -89,16 +118,6 @@
|
|||||||
if (error) {
|
if (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 相同校验
|
|
||||||
if (formModel.value.beforePassword === formModel.value.password) {
|
|
||||||
formRef.value.setFields({
|
|
||||||
password: {
|
|
||||||
status: 'error',
|
|
||||||
message: '新密码不能和原始密码相同'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 修改
|
// 修改
|
||||||
await updateCurrentUserPassword({
|
await updateCurrentUserPassword({
|
||||||
beforePassword: md5(formModel.value.beforePassword as string),
|
beforePassword: md5(formModel.value.beforePassword as string),
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ export default function usePermission() {
|
|||||||
const element = menuConfig.shift();
|
const element = menuConfig.shift();
|
||||||
if (element?.name === route.name) exist = true;
|
if (element?.name === route.name) exist = true;
|
||||||
if (element?.children) {
|
if (element?.children) {
|
||||||
menuConfig.push(
|
menuConfig.push(...(element.children as unknown as RouteRecordNormalized[]));
|
||||||
...(element.children as unknown as RouteRecordNormalized[])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return exist;
|
return exist;
|
||||||
|
|||||||
@@ -24,12 +24,15 @@ export default function useResponsive(immediate?: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const debounceFn = useDebounceFn(resizeHandler, 100);
|
const debounceFn = useDebounceFn(resizeHandler, 100);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (immediate) debounceFn();
|
if (immediate) debounceFn();
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
addEventListen(window, 'resize', debounceFn);
|
addEventListen(window, 'resize', debounceFn);
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
removeEventListen(window, 'resize', debounceFn);
|
removeEventListen(window, 'resize', debounceFn);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
|
import { LOGIN_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
export default function useUser() {
|
export default function useUser() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
// 退出登录
|
// 退出登录
|
||||||
const logout = async () => {
|
const logout = async (msg: string = '已退出登录') => {
|
||||||
await userStore.logout();
|
await userStore.logout();
|
||||||
Message.success('已退出登录');
|
if (msg) {
|
||||||
await router.push({ name: 'login' });
|
Message.success(msg);
|
||||||
|
}
|
||||||
|
await router.push({ name: LOGIN_ROUTE_NAME });
|
||||||
};
|
};
|
||||||
|
|
||||||
// 退出并重定向
|
// 退出并重定向
|
||||||
@@ -20,7 +22,7 @@ export default function useUser() {
|
|||||||
const currentRoute = router.currentRoute.value;
|
const currentRoute = router.currentRoute.value;
|
||||||
Message.success('已退出登录');
|
Message.success('已退出登录');
|
||||||
await router.push({
|
await router.push({
|
||||||
name: logoutTo || 'login',
|
name: logoutTo || LOGIN_ROUTE_NAME,
|
||||||
query: {
|
query: {
|
||||||
...router.currentRoute.value.query,
|
...router.currentRoute.value.query,
|
||||||
redirect: currentRoute.name as string,
|
redirect: currentRoute.name as string,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import type { RouteLocationNormalized } from 'vue-router';
|
import type { RouteLocationNormalized } from 'vue-router';
|
||||||
import type { TagProps } from '@/store/modules/tab-bar/types';
|
import type { TagProps } from '@/store/modules/tab-bar/types';
|
||||||
|
|
||||||
|
export const LOGIN_ROUTE_NAME = 'login';
|
||||||
|
|
||||||
export const REDIRECT_ROUTE_NAME = 'redirect';
|
export const REDIRECT_ROUTE_NAME = 'redirect';
|
||||||
|
|
||||||
export const LOGIN_ROUTE_NAME = 'login';
|
export const UPDATE_PASSWORD_ROUTE_NAME = 'updatePassword';
|
||||||
|
|
||||||
export const FORBIDDEN_ROUTER_NAME = 'forbidden';
|
export const FORBIDDEN_ROUTER_NAME = 'forbidden';
|
||||||
|
|
||||||
@@ -24,6 +26,7 @@ export const DEFAULT_ROUTER = { name: DEFAULT_ROUTE_NAME, children: [] };
|
|||||||
export const WHITE_ROUTER_LIST = [
|
export const WHITE_ROUTER_LIST = [
|
||||||
{ name: LOGIN_ROUTE_NAME, children: [] },
|
{ name: LOGIN_ROUTE_NAME, children: [] },
|
||||||
{ name: REDIRECT_ROUTE_NAME, children: [] },
|
{ name: REDIRECT_ROUTE_NAME, children: [] },
|
||||||
|
{ name: UPDATE_PASSWORD_ROUTE_NAME, children: [] },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,16 +37,6 @@ export const STATUS_ROUTER_LIST = [
|
|||||||
{ name: FORBIDDEN_ROUTER_NAME, children: [] },
|
{ name: FORBIDDEN_ROUTER_NAME, children: [] },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认 tab 页面
|
|
||||||
*/
|
|
||||||
export const DEFAULT_TAB = {
|
|
||||||
title: '工作台',
|
|
||||||
name: DEFAULT_ROUTE_NAME,
|
|
||||||
path: DEFAULT_ROUTE_FULL_PATH,
|
|
||||||
fullPath: DEFAULT_ROUTE_FULL_PATH,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* router 转 tag
|
* router 转 tag
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Router } from 'vue-router';
|
import type { Router } from 'vue-router';
|
||||||
import NProgress from 'nprogress';
|
|
||||||
import { useMenuStore } from '@/store';
|
import { useMenuStore } from '@/store';
|
||||||
import { NOT_FOUND_ROUTER_NAME, WHITE_ROUTER_LIST } from '../constants';
|
import { NOT_FOUND_ROUTER_NAME, WHITE_ROUTER_LIST } from '../constants';
|
||||||
|
import NProgress from 'nprogress';
|
||||||
import usePermission from '@/hooks/permission';
|
import usePermission from '@/hooks/permission';
|
||||||
|
|
||||||
export default function setupPermissionGuard(router: Router) {
|
export default function setupPermissionGuard(router: Router) {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { LocationQueryRaw, Router } from 'vue-router';
|
import type { RouteLocationRaw, Router } from 'vue-router';
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import { isLogin } from '@/utils/auth';
|
import { isLogin } from '@/utils/auth';
|
||||||
|
import { LOGIN_ROUTE_NAME, UPDATE_PASSWORD_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化用户登录路由守卫
|
* 初始化用户登录路由守卫
|
||||||
@@ -11,40 +12,49 @@ export default function setupUserLoginInfoGuard(router: Router) {
|
|||||||
NProgress.start();
|
NProgress.start();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
if (isLogin()) {
|
if (isLogin()) {
|
||||||
// 获取用户信息
|
|
||||||
if (userStore.id) {
|
if (userStore.id) {
|
||||||
|
// 跳转
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
await userStore.info();
|
const info = await userStore.getUserInfo();
|
||||||
next();
|
if (info.user.passwordUpdateStatus === 1) {
|
||||||
|
// 跳转到修改密码页面
|
||||||
|
next({
|
||||||
|
name: UPDATE_PASSWORD_ROUTE_NAME,
|
||||||
|
query: { reason: info.user.passwordUpdateReason },
|
||||||
|
} as RouteLocationRaw);
|
||||||
|
} else {
|
||||||
|
// 跳转
|
||||||
|
next();
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 获取失败退出登录
|
// 获取失败退出登录
|
||||||
await userStore.logout();
|
await userStore.logout();
|
||||||
next({
|
next({
|
||||||
name: 'login',
|
name: LOGIN_ROUTE_NAME,
|
||||||
query: {
|
query: {
|
||||||
redirect: to.name,
|
redirect: to.name,
|
||||||
...to.query,
|
...to.query,
|
||||||
} as LocationQueryRaw,
|
},
|
||||||
});
|
} as RouteLocationRaw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 未登录跳转到登录页
|
if (to.name === LOGIN_ROUTE_NAME) {
|
||||||
if (to.name === 'login') {
|
// 未登录跳转到登录页
|
||||||
next();
|
next();
|
||||||
return;
|
} else {
|
||||||
|
// 跳转到登录页
|
||||||
|
next({
|
||||||
|
name: LOGIN_ROUTE_NAME,
|
||||||
|
query: {
|
||||||
|
redirect: to.name,
|
||||||
|
...to.query,
|
||||||
|
},
|
||||||
|
} as RouteLocationRaw);
|
||||||
}
|
}
|
||||||
// 跳转到登录页
|
|
||||||
next({
|
|
||||||
name: 'login',
|
|
||||||
query: {
|
|
||||||
redirect: to.name,
|
|
||||||
...to.query,
|
|
||||||
} as LocationQueryRaw,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { RouteLocationRaw } from 'vue-router';
|
import type { RouteLocationRaw } from 'vue-router';
|
||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
import NProgress from 'nprogress';
|
|
||||||
import { appRoutes } from './routes';
|
import { appRoutes } from './routes';
|
||||||
import BASE_ROUTERS from './routes/base';
|
|
||||||
import createRouteGuard from './guard';
|
|
||||||
import { openWindow } from '@/utils';
|
import { openWindow } from '@/utils';
|
||||||
import { isStandaloneMode } from '@/utils/env';
|
import { isStandaloneMode } from '@/utils/env';
|
||||||
|
import createRouteGuard from './guard';
|
||||||
|
import baseRouters from './routes/base';
|
||||||
|
import NProgress from 'nprogress';
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false });
|
NProgress.configure({ showSpinner: false });
|
||||||
@@ -14,7 +14,7 @@ NProgress.configure({ showSpinner: false });
|
|||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes: [
|
routes: [
|
||||||
...BASE_ROUTERS,
|
...baseRouters,
|
||||||
...appRoutes,
|
...appRoutes,
|
||||||
],
|
],
|
||||||
scrollBehavior() {
|
scrollBehavior() {
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import type { RouteRecordRaw } from 'vue-router';
|
import type { RouteRecordRaw } from 'vue-router';
|
||||||
import { DEFAULT_ROUTE_FULL_PATH, FORBIDDEN_ROUTER_NAME, LOGIN_ROUTE_NAME, NOT_FOUND_ROUTER_NAME, REDIRECT_ROUTE_NAME, } from '@/router/constants';
|
import {
|
||||||
|
DEFAULT_ROUTE_FULL_PATH,
|
||||||
|
FORBIDDEN_ROUTER_NAME,
|
||||||
|
LOGIN_ROUTE_NAME,
|
||||||
|
NOT_FOUND_ROUTER_NAME,
|
||||||
|
REDIRECT_ROUTE_NAME,
|
||||||
|
UPDATE_PASSWORD_ROUTE_NAME,
|
||||||
|
} from '@/router/constants';
|
||||||
|
|
||||||
// 默认布局
|
// 默认布局
|
||||||
export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
||||||
@@ -8,13 +15,13 @@ export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
|||||||
export const FULL_LAYOUT = () => import('@/layout/full-layout.vue');
|
export const FULL_LAYOUT = () => import('@/layout/full-layout.vue');
|
||||||
|
|
||||||
// 根页面
|
// 根页面
|
||||||
export const ROOT_ROUTER: RouteRecordRaw = {
|
export const ROOT_ROUTE: RouteRecordRaw = {
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: DEFAULT_ROUTE_FULL_PATH,
|
redirect: DEFAULT_ROUTE_FULL_PATH,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 登录页面
|
// 登录页面
|
||||||
export const LOGIN_ROUTER: RouteRecordRaw = {
|
export const LOGIN_ROUTE: RouteRecordRaw = {
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: LOGIN_ROUTE_NAME,
|
name: LOGIN_ROUTE_NAME,
|
||||||
meta: {
|
meta: {
|
||||||
@@ -24,7 +31,7 @@ export const LOGIN_ROUTER: RouteRecordRaw = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 重定向页面
|
// 重定向页面
|
||||||
export const REDIRECT_ROUTER: RouteRecordRaw = {
|
export const REDIRECT_ROUTE: RouteRecordRaw = {
|
||||||
path: '/redirect',
|
path: '/redirect',
|
||||||
name: 'redirectWrapper',
|
name: 'redirectWrapper',
|
||||||
component: DEFAULT_LAYOUT,
|
component: DEFAULT_LAYOUT,
|
||||||
@@ -46,14 +53,24 @@ export const REDIRECT_ROUTER: RouteRecordRaw = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 修改密码
|
||||||
|
export const UPDATE_PASSWORD_ROUTE: RouteRecordRaw = {
|
||||||
|
path: '/update-password',
|
||||||
|
name: UPDATE_PASSWORD_ROUTE_NAME,
|
||||||
|
component: () => import('@/views/base/update-password/index.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: '修改密码'
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// 403 页面
|
// 403 页面
|
||||||
export const FORBIDDEN_ROUTE: RouteRecordRaw = {
|
export const FORBIDDEN_ROUTE: RouteRecordRaw = {
|
||||||
path: '/403',
|
path: '/403',
|
||||||
name: FORBIDDEN_ROUTER_NAME,
|
name: FORBIDDEN_ROUTER_NAME,
|
||||||
|
component: () => import('@/views/base/status/forbidden/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: '403'
|
locale: '403'
|
||||||
},
|
},
|
||||||
component: () => import('@/views/base/status/forbidden/index.vue'),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 404 页面
|
// 404 页面
|
||||||
@@ -61,16 +78,17 @@ export const NOT_FOUND_ROUTE: RouteRecordRaw = {
|
|||||||
// path: '/:pathMatch(.*)*',
|
// path: '/:pathMatch(.*)*',
|
||||||
path: '/404',
|
path: '/404',
|
||||||
name: NOT_FOUND_ROUTER_NAME,
|
name: NOT_FOUND_ROUTER_NAME,
|
||||||
|
component: () => import('@/views/base/status/not-found/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
locale: '404'
|
locale: '404'
|
||||||
},
|
},
|
||||||
component: () => import('@/views/base/status/not-found/index.vue'),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
ROOT_ROUTER,
|
ROOT_ROUTE,
|
||||||
LOGIN_ROUTER,
|
LOGIN_ROUTE,
|
||||||
REDIRECT_ROUTER,
|
REDIRECT_ROUTE,
|
||||||
|
UPDATE_PASSWORD_ROUTE,
|
||||||
NOT_FOUND_ROUTE,
|
NOT_FOUND_ROUTE,
|
||||||
FORBIDDEN_ROUTE
|
FORBIDDEN_ROUTE
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { AppRouteRecordRaw } from '../types';
|
import type { AppRouteRecordRaw } from '../types';
|
||||||
import { DEFAULT_LAYOUT } from '../base';
|
import { DEFAULT_LAYOUT } from '../base';
|
||||||
|
import { DEFAULT_ROUTE_FULL_PATH, DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
const DASHBOARD: AppRouteRecordRaw = {
|
const DASHBOARD: AppRouteRecordRaw = {
|
||||||
name: 'dashboard',
|
name: 'dashboard',
|
||||||
@@ -7,8 +8,8 @@ const DASHBOARD: AppRouteRecordRaw = {
|
|||||||
component: DEFAULT_LAYOUT,
|
component: DEFAULT_LAYOUT,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'workplace',
|
name: DEFAULT_ROUTE_NAME,
|
||||||
path: '/workplace',
|
path: DEFAULT_ROUTE_FULL_PATH,
|
||||||
component: () => import('@/views/dashboard/workplace/index.vue'),
|
component: () => import('@/views/dashboard/workplace/index.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import type { MenuQueryResponse } from '@/api/system/menu';
|
|||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { Notification } from '@arco-design/web-vue';
|
import { Notification } from '@arco-design/web-vue';
|
||||||
import { getMenuList } from '@/api/user/auth';
|
|
||||||
import { EnabledStatus } from '@/types/const';
|
import { EnabledStatus } from '@/types/const';
|
||||||
|
import { getUserMenuList } from '@/api/user/permission';
|
||||||
|
|
||||||
export default defineStore('menu', {
|
export default defineStore('menu', {
|
||||||
state: (): MenuState => ({
|
state: (): MenuState => ({
|
||||||
@@ -54,7 +54,7 @@ export default defineStore('menu', {
|
|||||||
async fetchMenu() {
|
async fetchMenu() {
|
||||||
try {
|
try {
|
||||||
// 查询菜单
|
// 查询菜单
|
||||||
const { data } = await getMenuList();
|
const { data } = await getUserMenuList();
|
||||||
// 转换菜单
|
// 转换菜单
|
||||||
this.serverMenus = data.map(s => {
|
this.serverMenus = data.map(s => {
|
||||||
// 构建父目录
|
// 构建父目录
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import type { TabBarState, TagProps } from './types';
|
import type { TabBarState, TagProps } from './types';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { DEFAULT_ROUTE_NAME, DEFAULT_TAB } from '@/router/constants';
|
|
||||||
import { isString } from '@/utils/is';
|
import { isString } from '@/utils/is';
|
||||||
|
|
||||||
export default defineStore('tabBar', {
|
export default defineStore('tabBar', {
|
||||||
state: (): TabBarState => ({
|
state: (): TabBarState => ({
|
||||||
cacheTabList: new Set([DEFAULT_ROUTE_NAME]),
|
cacheTabList: new Set([]),
|
||||||
tagList: [DEFAULT_TAB],
|
tagList: [],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
@@ -55,9 +54,8 @@ export default defineStore('tabBar', {
|
|||||||
|
|
||||||
// 重设 tab
|
// 重设 tab
|
||||||
resetTabList() {
|
resetTabList() {
|
||||||
this.tagList = [DEFAULT_TAB];
|
this.tagList = [];
|
||||||
this.cacheTabList.clear();
|
this.cacheTabList.clear();
|
||||||
this.cacheTabList.add(DEFAULT_ROUTE_NAME);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import type { UserState } from './types';
|
import type { UserState } from './types';
|
||||||
import type { LoginRequest } from '@/api/user/auth';
|
import type { LoginRequest } from '@/api/user/auth';
|
||||||
import { getUserPermission, login as userLogin, logout as userLogout } from '@/api/user/auth';
|
import { userLogin, userLogout } from '@/api/user/auth';
|
||||||
|
import { md5 } from '@/utils';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { clearToken, setToken } from '@/utils/auth';
|
import { clearToken, setToken } from '@/utils/auth';
|
||||||
import { md5 } from '@/utils';
|
|
||||||
import { removeRouteListener } from '@/utils/route-listener';
|
import { removeRouteListener } from '@/utils/route-listener';
|
||||||
|
import { getUserPermission } from '@/api/user/permission';
|
||||||
import { useAppStore, useCacheStore, useMenuStore, useTabBarStore, useTipsStore } from '@/store';
|
import { useAppStore, useCacheStore, useMenuStore, useTabBarStore, useTipsStore } from '@/store';
|
||||||
|
|
||||||
export default defineStore('user', {
|
export default defineStore('user', {
|
||||||
@@ -25,15 +26,15 @@ export default defineStore('user', {
|
|||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
// 设置用户信息
|
// 设置用户信息
|
||||||
setInfo(partial: Partial<UserState>) {
|
setUserInfo(partial: Partial<UserState>) {
|
||||||
this.$patch(partial);
|
this.$patch(partial);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
async info() {
|
async getUserInfo() {
|
||||||
const { data } = await getUserPermission();
|
const { data } = await getUserPermission();
|
||||||
// 设置用户信息
|
// 设置用户信息
|
||||||
this.setInfo({
|
this.setUserInfo({
|
||||||
id: data.user.id,
|
id: data.user.id,
|
||||||
username: data.user.username,
|
username: data.user.username,
|
||||||
nickname: data.user.nickname,
|
nickname: data.user.nickname,
|
||||||
@@ -42,11 +43,10 @@ export default defineStore('user', {
|
|||||||
permission: data.permissions,
|
permission: data.permissions,
|
||||||
});
|
});
|
||||||
// 设置用户偏好
|
// 设置用户偏好
|
||||||
const appStore = useAppStore();
|
useAppStore().updateSettings(data.systemPreference);
|
||||||
appStore.updateSettings(data.user.systemPreference);
|
|
||||||
// 设置已经提示的key
|
// 设置已经提示的key
|
||||||
const tipsStore = useTipsStore();
|
useTipsStore().set(data.tippedKeys);
|
||||||
tipsStore.set(data.user.tippedKeys);
|
return data;
|
||||||
},
|
},
|
||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { isDemoMode } from '@/utils/env';
|
import { isDemoMode } from '@/utils/env';
|
||||||
|
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -83,7 +84,7 @@
|
|||||||
// 跳转路由
|
// 跳转路由
|
||||||
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
||||||
router.push({
|
router.push({
|
||||||
name: (redirect as string) || 'workplace',
|
name: (redirect as string) || DEFAULT_ROUTE_NAME,
|
||||||
query: {
|
query: {
|
||||||
...othersQuery,
|
...othersQuery,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,6 +23,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'login',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Notification } from '@arco-design/web-vue';
|
import { Notification } from '@arco-design/web-vue';
|
||||||
import { reLoginTipsKey } from '@/types/symbol';
|
import { reLoginTipsKey } from '@/types/symbol';
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'redirect',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<a-result class="result" status="403" subtitle="您没有访问该资源的权限" />
|
<a-result class="result" status="403" subtitle="您没有访问该资源的权限" />
|
||||||
<div class="operation-row">
|
<a-space>
|
||||||
<a-button class="mr8" key="back" type="primary" @click="logout">重新登录</a-button>
|
<a-button type="primary" @click="() => logout()">重新登录</a-button>
|
||||||
<a-button key="back" type="primary" @click="to('workplace')">返回工作台</a-button>
|
<a-button type="primary" @click="() => $router.push(DEFAULT_ROUTE_NAME)">返回工作台</a-button>
|
||||||
</div>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { useUserStore } from '@/store';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const to = (name: string) => {
|
|
||||||
router.push({ name: name });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 重新登录
|
|
||||||
const logout = () => {
|
|
||||||
const userStore = useUserStore();
|
|
||||||
userStore.logout();
|
|
||||||
to('login');
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'forbidden',
|
name: 'forbidden',
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import useUser from '@/hooks/user';
|
||||||
|
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
|
const { logout } = useUser();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.content {
|
.content {
|
||||||
// padding-top: 100px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
margin-left: -95px;
|
margin-left: -96px;
|
||||||
margin-top: -121px;
|
margin-top: -124px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,44 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<a-result class="result" status="404" subtitle="糟糕! 页面不见了!" />
|
<a-result class="result" status="404" subtitle="糟糕! 页面不见了!" />
|
||||||
<div class="operation-row">
|
<a-space>
|
||||||
<a-button class="mr8" key="back" type="primary" @click="logout">重新登录</a-button>
|
<a-button type="primary" @click="() => logout()">重新登录</a-button>
|
||||||
<a-button key="back" type="primary" @click="to('workplace')">返回工作台</a-button>
|
<a-button type="primary" @click="() => $router.push(DEFAULT_ROUTE_NAME)">返回工作台</a-button>
|
||||||
</div>
|
</a-space>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { useUserStore } from '@/store';
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const to = (name: string) => {
|
|
||||||
router.push({ name: name });
|
|
||||||
};
|
|
||||||
|
|
||||||
// 重新登录
|
|
||||||
const logout = () => {
|
|
||||||
const userStore = useUserStore();
|
|
||||||
userStore.logout();
|
|
||||||
to('login');
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: 'notFound',
|
name: 'notFound',
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import useUser from '@/hooks/user';
|
||||||
|
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||||
|
|
||||||
|
const { logout } = useUser();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.content {
|
.content {
|
||||||
// padding-top: 100px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
margin-left: -95px;
|
margin-left: -96px;
|
||||||
margin-top: -121px;
|
margin-top: -124px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
165
orion-visor-ui/src/views/base/update-password/index.vue
Normal file
165
orion-visor-ui/src/views/base/update-password/index.vue
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
<template>
|
||||||
|
<a-spin class="content" :loading="loading">
|
||||||
|
<!-- 原因 -->
|
||||||
|
<p class="reason">{{ reason }}</p>
|
||||||
|
<!-- 表单 -->
|
||||||
|
<a-form :model="formModel"
|
||||||
|
ref="formRef"
|
||||||
|
label-align="right"
|
||||||
|
:rules="rules">
|
||||||
|
<!-- 原始密码 -->
|
||||||
|
<a-form-item field="beforePassword"
|
||||||
|
label="原始密码"
|
||||||
|
hide-label>
|
||||||
|
<a-input-password v-model="formModel.beforePassword" placeholder="请输入原始密码" />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 新密码 -->
|
||||||
|
<a-form-item field="password"
|
||||||
|
label="新密码"
|
||||||
|
hide-label>
|
||||||
|
<a-input-password v-model="formModel.password" placeholder="请输入新密码" />
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 确认密码 -->
|
||||||
|
<a-form-item field="checkPassword"
|
||||||
|
label="确认密码"
|
||||||
|
hide-label>
|
||||||
|
<a-input-password v-model="formModel.checkPassword" placeholder="请再次输入新密码" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<!-- 按钮 -->
|
||||||
|
<a-space>
|
||||||
|
<!-- 确认修改 -->
|
||||||
|
<a-button class="action"
|
||||||
|
type="primary"
|
||||||
|
@click="doUpdate">
|
||||||
|
确认修改
|
||||||
|
</a-button>
|
||||||
|
<!-- 退出登录 -->
|
||||||
|
<a-button class="action"
|
||||||
|
type="primary"
|
||||||
|
@click="() => logout()">
|
||||||
|
退出登录
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-spin>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'updatePassword',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { UserUpdatePasswordRequest } from '@/api/user/mine';
|
||||||
|
import type { FieldRule } from '@arco-design/web-vue';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { md5 } from '@/utils';
|
||||||
|
import useUser from '@/hooks/user';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import { useDictStore } from '@/store';
|
||||||
|
import { dictKeys, updatePasswordReasonKey } from './types/const';
|
||||||
|
import { updateCurrentUserPassword } from '@/api/user/mine';
|
||||||
|
|
||||||
|
const { logout } = useUser();
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
beforePassword: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入原始密码'
|
||||||
|
}],
|
||||||
|
password: [{
|
||||||
|
required: true,
|
||||||
|
message: '请输入新密码'
|
||||||
|
}, {
|
||||||
|
minLength: 8,
|
||||||
|
maxLength: 32,
|
||||||
|
message: '新密码长度需要在 8-32 位之间'
|
||||||
|
}, {
|
||||||
|
validator: (value, cb) => {
|
||||||
|
if (formModel.value.beforePassword === value) {
|
||||||
|
cb('新密码不能和原始密码相同');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
checkPassword: [{
|
||||||
|
required: true,
|
||||||
|
message: '请再次输入新密码'
|
||||||
|
}, {
|
||||||
|
validator: (value, cb) => {
|
||||||
|
if (formModel.value.password !== value) {
|
||||||
|
cb('两次输入的密码不一致');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
} as Record<string, FieldRule | FieldRule[]>;
|
||||||
|
|
||||||
|
const reason = ref();
|
||||||
|
const formRef = ref();
|
||||||
|
const formModel = ref<UserUpdatePasswordRequest>({});
|
||||||
|
|
||||||
|
// 确认修改
|
||||||
|
const doUpdate = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
// 验证参数
|
||||||
|
const error = await formRef.value.validate();
|
||||||
|
if (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 修改密码
|
||||||
|
await updateCurrentUserPassword({
|
||||||
|
beforePassword: md5(formModel.value.beforePassword as string),
|
||||||
|
password: md5(formModel.value.password as string)
|
||||||
|
});
|
||||||
|
// 退出登录
|
||||||
|
await logout('修改成功');
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const reasonKey = useRoute().query?.reason;
|
||||||
|
if (reasonKey) {
|
||||||
|
const { loadKeys, getDictValue } = useDictStore();
|
||||||
|
// 加载字典值
|
||||||
|
await loadKeys(dictKeys);
|
||||||
|
// 获取原因
|
||||||
|
reason.value = getDictValue(updatePasswordReasonKey, reasonKey);
|
||||||
|
} else {
|
||||||
|
reason.value = '修改密码';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.content {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -96px;
|
||||||
|
margin-top: -168px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.reason {
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
width: 148px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// 修改密码原因
|
||||||
|
export const updatePasswordReasonKey = 'updatePasswordReason';
|
||||||
|
|
||||||
|
// 加载的字典值
|
||||||
|
export const dictKeys = [updatePasswordReasonKey];
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
-- 默认管理员账号
|
-- 默认管理员账号
|
||||||
-- 账号: admin 密码: admin
|
-- 账号: admin 密码: admin
|
||||||
INSERT INTO `system_user` VALUES (1, 'admin', 'c3284d0f94606de1fd2af172aba15bf3', '管理员', '', '', '', 1, '2023-08-17 14:23:59', '2023-07-13 22:11:57', '2023-08-17 14:23:59', '1', '1', 0);
|
INSERT INTO `system_user` VALUES (1, 'admin', 'c3284d0f94606de1fd2af172aba15bf3', '管理员', NULL, NULL, NULL, 1, 1, 'INIT', NULL, NOW(), NOW(), '1', '1', 0);
|
||||||
|
|
||||||
-- 角色配置
|
-- 角色配置
|
||||||
INSERT INTO `system_role` VALUES (1, '管理员', 'admin', 1, '2023-07-16 21:13:14', '2023-07-17 17:31:29', '1', '1', 0);
|
INSERT INTO `system_role` VALUES (1, '管理员', 'admin', 1, '2023-07-16 21:13:14', '2023-07-17 17:31:29', '1', '1', 0);
|
||||||
|
|||||||
@@ -9,10 +9,9 @@ CREATE TABLE `table` (
|
|||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='table';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='table';
|
||||||
|
|
||||||
|
|
||||||
-- 添加默认列
|
-- 添加默认列
|
||||||
ALTER TABLE `table`
|
ALTER TABLE `table`
|
||||||
ADD COLUMN `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER type,
|
ADD COLUMN `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER id,
|
||||||
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间' AFTER create_time,
|
ADD COLUMN `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间' AFTER create_time,
|
||||||
ADD COLUMN `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建人' AFTER update_time,
|
ADD COLUMN `creator` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '创建人' AFTER update_time,
|
||||||
ADD COLUMN `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '更新人' AFTER creator,
|
ADD COLUMN `updater` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '更新人' AFTER creator,
|
||||||
|
|||||||
Reference in New Issue
Block a user