🔨 修改路由配置.
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.dto.UserInfoDTO;
|
||||
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.UserCollectInfoVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@@ -58,6 +58,6 @@ public interface SystemUserConvert {
|
||||
|
||||
UserInfoDTO toUserInfo(SystemUserDO domain);
|
||||
|
||||
UserCollectInfoVO toCollectInfo(LoginUser user);
|
||||
SystemUserBaseVO toBase(SystemUserDO user);
|
||||
|
||||
}
|
||||
|
||||
@@ -75,6 +75,14 @@ public class SystemUserDO extends BaseDO {
|
||||
@TableField("status")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "修改密码状态")
|
||||
@TableField("update_password_status")
|
||||
private Integer passwordUpdateStatus;
|
||||
|
||||
@Schema(description = "修改密码原因")
|
||||
@TableField("update_password_reason")
|
||||
private String passwordUpdateReason;
|
||||
|
||||
@Schema(description = "最后登录时间")
|
||||
@TableField("last_login_time")
|
||||
private Date lastLoginTime;
|
||||
|
||||
@@ -21,9 +21,6 @@ import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户基本信息 视图响应对象
|
||||
*
|
||||
@@ -35,8 +32,8 @@ import java.util.Map;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "UserCollectInfoVO", description = "用户聚合信息 视图响应对象")
|
||||
public class UserCollectInfoVO {
|
||||
@Schema(name = "SystemUserBaseVO", description = "用户基本信息 视图响应对象")
|
||||
public class SystemUserBaseVO {
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
@@ -50,10 +47,10 @@ public class UserCollectInfoVO {
|
||||
@Schema(description = "头像地址")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "系统偏好")
|
||||
private Map<String, Object> systemPreference;
|
||||
@Schema(description = "修改密码状态")
|
||||
private Integer passwordUpdateStatus;
|
||||
|
||||
@Schema(description = "已经提示的key")
|
||||
private List<String> tippedKeys;
|
||||
@Schema(description = "修改密码原因")
|
||||
private String passwordUpdateReason;
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户权限 视图响应对象
|
||||
@@ -38,8 +39,8 @@ import java.util.List;
|
||||
@Schema(name = "UserPermissionVO", description = "用户权限 视图响应对象")
|
||||
public class UserPermissionVO {
|
||||
|
||||
@Schema(description = "用户聚合信息")
|
||||
private UserCollectInfoVO user;
|
||||
@Schema(description = "用户信息")
|
||||
private SystemUserBaseVO user;
|
||||
|
||||
@Schema(description = "该用户已启用的角色")
|
||||
private Collection<String> roles;
|
||||
@@ -47,4 +48,10 @@ public class UserPermissionVO {
|
||||
@Schema(description = "该用户已启用的权限")
|
||||
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.request.user.*;
|
||||
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.service.*;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -118,6 +120,8 @@ public class SystemUserServiceImpl implements SystemUserService {
|
||||
this.checkNicknamePresent(record);
|
||||
// 加密密码
|
||||
record.setPassword(Signatures.md5(request.getPassword()));
|
||||
record.setPasswordUpdateStatus(UpdatePasswordStatusEnum.REQUIRED.getStatus());
|
||||
record.setPasswordUpdateReason(UpdatePasswordReasonEnum.NEW.name());
|
||||
// 插入
|
||||
int effect = systemUserDAO.insert(record);
|
||||
log.info("SystemUserService-createSystemUser effect: {}, record: {}", effect, JSON.toJSONString(record));
|
||||
@@ -309,6 +313,8 @@ public class SystemUserServiceImpl implements SystemUserService {
|
||||
SystemUserDO update = new SystemUserDO();
|
||||
update.setId(id);
|
||||
update.setPassword(Signatures.md5(request.getPassword()));
|
||||
update.setPasswordUpdateStatus(UpdatePasswordStatusEnum.NO_REQUIRE.getStatus());
|
||||
update.setPasswordUpdateReason(Const.EMPTY);
|
||||
int effect = systemUserDAO.updateById(update);
|
||||
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.SystemRoleDAO;
|
||||
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.entity.domain.SystemMenuDO;
|
||||
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.SystemUserDO;
|
||||
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.UserCollectInfoVO;
|
||||
import org.dromara.visor.module.infra.entity.vo.UserPermissionVO;
|
||||
import org.dromara.visor.module.infra.enums.MenuStatusEnum;
|
||||
import org.dromara.visor.module.infra.enums.MenuTypeEnum;
|
||||
@@ -76,6 +77,9 @@ public class UserPermissionServiceImpl implements UserPermissionService {
|
||||
@Getter
|
||||
private final Map<Long, List<SystemMenuCacheDTO>> roleMenuCache = new HashMap<>();
|
||||
|
||||
@Resource
|
||||
private SystemUserDAO systemUserDAO;
|
||||
|
||||
@Resource
|
||||
private SystemRoleDAO systemRoleDAO;
|
||||
|
||||
@@ -229,43 +233,24 @@ public class UserPermissionServiceImpl implements UserPermissionService {
|
||||
@Override
|
||||
public UserPermissionVO getUserPermission() {
|
||||
// 获取用户信息
|
||||
UserCollectInfoVO user = SystemUserConvert.MAPPER.toCollectInfo(SecurityUtils.getLoginUser());
|
||||
Long id = user.getId();
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
// 获取用户系统偏好
|
||||
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();
|
||||
// 获取用户权限
|
||||
List<String> permissions;
|
||||
if (roles.isEmpty()) {
|
||||
permissions = Lists.empty();
|
||||
} 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());
|
||||
// 获取角色权限
|
||||
List<String> permissions = this.getRolePermissions(roles);
|
||||
// 提示信息
|
||||
List<String> tippedKeys = tipsService.getTippedKeys();
|
||||
// 组装数据
|
||||
return UserPermissionVO.builder()
|
||||
.user(user)
|
||||
.user(SystemUserConvert.MAPPER.toBase(user))
|
||||
.roles(roles.values())
|
||||
.permissions(permissions)
|
||||
.systemPreference(systemPreference.get())
|
||||
.tippedKeys(tippedKeys)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -317,4 +302,31 @@ public class UserPermissionServiceImpl implements UserPermissionService {
|
||||
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="email" property="email"/>
|
||||
<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"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<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>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { MenuQueryResponse } from '@/api/system/menu';
|
||||
import axios from 'axios';
|
||||
|
||||
/**
|
||||
@@ -17,45 +16,15 @@ export interface LoginResponse {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户权限响应
|
||||
* 用户登录
|
||||
*/
|
||||
export interface UserPermissionResponse {
|
||||
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) {
|
||||
export function userLogin(data: LoginRequest) {
|
||||
return axios.post<LoginResponse>('/infra/auth/login', data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登出
|
||||
* 用户登出
|
||||
*/
|
||||
export function logout() {
|
||||
export function userLogout() {
|
||||
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 {
|
||||
beforePassword?: 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();
|
||||
copyTagList.splice(1, props.index - 1);
|
||||
|
||||
tabBarStore.freshTabList(copyTagList);
|
||||
if (currentRouteIdx < index) {
|
||||
await router.push({ name: itemData.name });
|
||||
@@ -131,7 +130,6 @@
|
||||
// 关闭右侧
|
||||
const currentRouteIdx = findCurrentRouteIndex();
|
||||
copyTagList.splice(props.index + 1);
|
||||
|
||||
tabBarStore.freshTabList(copyTagList);
|
||||
if (currentRouteIdx > index) {
|
||||
await router.push({ name: itemData.name });
|
||||
@@ -154,7 +152,8 @@
|
||||
} else {
|
||||
// 关闭全部
|
||||
tabBarStore.resetTabList();
|
||||
await router.push({ name: DEFAULT_ROUTE_NAME });
|
||||
// 跳转到首页 添加 query 强行刷新
|
||||
await router.push({ name: DEFAULT_ROUTE_NAME, query: { _: Date.now() } });
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<a-modal v-model:visible="visible"
|
||||
modal-class="modal-form-large"
|
||||
title-align="start"
|
||||
title="重置密码"
|
||||
title="修改密码"
|
||||
:top="120"
|
||||
:align-center="false"
|
||||
:draggable="true"
|
||||
@@ -16,16 +16,25 @@
|
||||
<a-form :model="formModel"
|
||||
ref="formRef"
|
||||
label-align="right"
|
||||
:rules="rules"
|
||||
:auto-label-width="true">
|
||||
<!-- 密码 -->
|
||||
<a-form-item field="beforePassword" label="原始密码">
|
||||
: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="新密码">
|
||||
<!-- 新密码 -->
|
||||
<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-spin>
|
||||
</a-modal>
|
||||
@@ -38,12 +47,13 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { FieldRule } from '@arco-design/web-vue';
|
||||
import type { UserUpdatePasswordRequest } from '@/api/user/mine';
|
||||
import { ref } from 'vue';
|
||||
import { md5 } from '@/utils';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { md5 } from '@/utils';
|
||||
import { updateCurrentUserPassword } from '@/api/user/mine';
|
||||
|
||||
const emits = defineEmits(['updated']);
|
||||
@@ -63,8 +73,26 @@
|
||||
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 formRef = ref();
|
||||
const formModel = ref<UserUpdatePasswordRequest>({});
|
||||
@@ -73,7 +101,8 @@
|
||||
const open = () => {
|
||||
formModel.value = {
|
||||
beforePassword: undefined,
|
||||
password: undefined
|
||||
password: undefined,
|
||||
checkPassword: undefined,
|
||||
};
|
||||
setVisible(true);
|
||||
};
|
||||
@@ -89,16 +118,6 @@
|
||||
if (error) {
|
||||
return false;
|
||||
}
|
||||
// 相同校验
|
||||
if (formModel.value.beforePassword === formModel.value.password) {
|
||||
formRef.value.setFields({
|
||||
password: {
|
||||
status: 'error',
|
||||
message: '新密码不能和原始密码相同'
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
// 修改
|
||||
await updateCurrentUserPassword({
|
||||
beforePassword: md5(formModel.value.beforePassword as string),
|
||||
|
||||
@@ -22,9 +22,7 @@ export default function usePermission() {
|
||||
const element = menuConfig.shift();
|
||||
if (element?.name === route.name) exist = true;
|
||||
if (element?.children) {
|
||||
menuConfig.push(
|
||||
...(element.children as unknown as RouteRecordNormalized[])
|
||||
);
|
||||
menuConfig.push(...(element.children as unknown as RouteRecordNormalized[]));
|
||||
}
|
||||
}
|
||||
return exist;
|
||||
|
||||
@@ -24,12 +24,15 @@ export default function useResponsive(immediate?: boolean) {
|
||||
}
|
||||
|
||||
const debounceFn = useDebounceFn(resizeHandler, 100);
|
||||
|
||||
onMounted(() => {
|
||||
if (immediate) debounceFn();
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
addEventListen(window, 'resize', debounceFn);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
removeEventListen(window, 'resize', debounceFn);
|
||||
});
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import { useUserStore } from '@/store';
|
||||
import { LOGIN_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
export default function useUser() {
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 退出登录
|
||||
const logout = async () => {
|
||||
const logout = async (msg: string = '已退出登录') => {
|
||||
await userStore.logout();
|
||||
Message.success('已退出登录');
|
||||
await router.push({ name: 'login' });
|
||||
if (msg) {
|
||||
Message.success(msg);
|
||||
}
|
||||
await router.push({ name: LOGIN_ROUTE_NAME });
|
||||
};
|
||||
|
||||
// 退出并重定向
|
||||
@@ -20,7 +22,7 @@ export default function useUser() {
|
||||
const currentRoute = router.currentRoute.value;
|
||||
Message.success('已退出登录');
|
||||
await router.push({
|
||||
name: logoutTo || 'login',
|
||||
name: logoutTo || LOGIN_ROUTE_NAME,
|
||||
query: {
|
||||
...router.currentRoute.value.query,
|
||||
redirect: currentRoute.name as string,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
import type { TagProps } from '@/store/modules/tab-bar/types';
|
||||
|
||||
export const LOGIN_ROUTE_NAME = 'login';
|
||||
|
||||
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';
|
||||
|
||||
@@ -24,6 +26,7 @@ export const DEFAULT_ROUTER = { name: DEFAULT_ROUTE_NAME, children: [] };
|
||||
export const WHITE_ROUTER_LIST = [
|
||||
{ name: LOGIN_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: [] },
|
||||
];
|
||||
|
||||
/**
|
||||
* 默认 tab 页面
|
||||
*/
|
||||
export const DEFAULT_TAB = {
|
||||
title: '工作台',
|
||||
name: DEFAULT_ROUTE_NAME,
|
||||
path: DEFAULT_ROUTE_FULL_PATH,
|
||||
fullPath: DEFAULT_ROUTE_FULL_PATH,
|
||||
};
|
||||
|
||||
/**
|
||||
* router 转 tag
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import NProgress from 'nprogress';
|
||||
import { useMenuStore } from '@/store';
|
||||
import { NOT_FOUND_ROUTER_NAME, WHITE_ROUTER_LIST } from '../constants';
|
||||
import NProgress from 'nprogress';
|
||||
import usePermission from '@/hooks/permission';
|
||||
|
||||
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 { useUserStore } from '@/store';
|
||||
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();
|
||||
const userStore = useUserStore();
|
||||
if (isLogin()) {
|
||||
// 获取用户信息
|
||||
if (userStore.id) {
|
||||
// 跳转
|
||||
next();
|
||||
} else {
|
||||
try {
|
||||
// 获取用户信息
|
||||
await userStore.info();
|
||||
next();
|
||||
const info = await userStore.getUserInfo();
|
||||
if (info.user.passwordUpdateStatus === 1) {
|
||||
// 跳转到修改密码页面
|
||||
next({
|
||||
name: UPDATE_PASSWORD_ROUTE_NAME,
|
||||
query: { reason: info.user.passwordUpdateReason },
|
||||
} as RouteLocationRaw);
|
||||
} else {
|
||||
// 跳转
|
||||
next();
|
||||
}
|
||||
} catch (error) {
|
||||
// 获取失败退出登录
|
||||
await userStore.logout();
|
||||
next({
|
||||
name: 'login',
|
||||
name: LOGIN_ROUTE_NAME,
|
||||
query: {
|
||||
redirect: to.name,
|
||||
...to.query,
|
||||
} as LocationQueryRaw,
|
||||
});
|
||||
},
|
||||
} as RouteLocationRaw);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 未登录跳转到登录页
|
||||
if (to.name === 'login') {
|
||||
if (to.name === LOGIN_ROUTE_NAME) {
|
||||
// 未登录跳转到登录页
|
||||
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 { createRouter, createWebHistory } from 'vue-router';
|
||||
import NProgress from 'nprogress';
|
||||
import { appRoutes } from './routes';
|
||||
import BASE_ROUTERS from './routes/base';
|
||||
import createRouteGuard from './guard';
|
||||
import { openWindow } from '@/utils';
|
||||
import { isStandaloneMode } from '@/utils/env';
|
||||
import createRouteGuard from './guard';
|
||||
import baseRouters from './routes/base';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
NProgress.configure({ showSpinner: false });
|
||||
@@ -14,7 +14,7 @@ NProgress.configure({ showSpinner: false });
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
...BASE_ROUTERS,
|
||||
...baseRouters,
|
||||
...appRoutes,
|
||||
],
|
||||
scrollBehavior() {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
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');
|
||||
@@ -8,13 +15,13 @@ export const DEFAULT_LAYOUT = () => import('@/layout/default-layout.vue');
|
||||
export const FULL_LAYOUT = () => import('@/layout/full-layout.vue');
|
||||
|
||||
// 根页面
|
||||
export const ROOT_ROUTER: RouteRecordRaw = {
|
||||
export const ROOT_ROUTE: RouteRecordRaw = {
|
||||
path: '/',
|
||||
redirect: DEFAULT_ROUTE_FULL_PATH,
|
||||
};
|
||||
|
||||
// 登录页面
|
||||
export const LOGIN_ROUTER: RouteRecordRaw = {
|
||||
export const LOGIN_ROUTE: RouteRecordRaw = {
|
||||
path: '/login',
|
||||
name: LOGIN_ROUTE_NAME,
|
||||
meta: {
|
||||
@@ -24,7 +31,7 @@ export const LOGIN_ROUTER: RouteRecordRaw = {
|
||||
};
|
||||
|
||||
// 重定向页面
|
||||
export const REDIRECT_ROUTER: RouteRecordRaw = {
|
||||
export const REDIRECT_ROUTE: RouteRecordRaw = {
|
||||
path: '/redirect',
|
||||
name: 'redirectWrapper',
|
||||
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 页面
|
||||
export const FORBIDDEN_ROUTE: RouteRecordRaw = {
|
||||
path: '/403',
|
||||
name: FORBIDDEN_ROUTER_NAME,
|
||||
component: () => import('@/views/base/status/forbidden/index.vue'),
|
||||
meta: {
|
||||
locale: '403'
|
||||
},
|
||||
component: () => import('@/views/base/status/forbidden/index.vue'),
|
||||
};
|
||||
|
||||
// 404 页面
|
||||
@@ -61,16 +78,17 @@ export const NOT_FOUND_ROUTE: RouteRecordRaw = {
|
||||
// path: '/:pathMatch(.*)*',
|
||||
path: '/404',
|
||||
name: NOT_FOUND_ROUTER_NAME,
|
||||
component: () => import('@/views/base/status/not-found/index.vue'),
|
||||
meta: {
|
||||
locale: '404'
|
||||
},
|
||||
component: () => import('@/views/base/status/not-found/index.vue'),
|
||||
};
|
||||
|
||||
export default [
|
||||
ROOT_ROUTER,
|
||||
LOGIN_ROUTER,
|
||||
REDIRECT_ROUTER,
|
||||
ROOT_ROUTE,
|
||||
LOGIN_ROUTE,
|
||||
REDIRECT_ROUTE,
|
||||
UPDATE_PASSWORD_ROUTE,
|
||||
NOT_FOUND_ROUTE,
|
||||
FORBIDDEN_ROUTE
|
||||
];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { AppRouteRecordRaw } from '../types';
|
||||
import { DEFAULT_LAYOUT } from '../base';
|
||||
import { DEFAULT_ROUTE_FULL_PATH, DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
const DASHBOARD: AppRouteRecordRaw = {
|
||||
name: 'dashboard',
|
||||
@@ -7,8 +8,8 @@ const DASHBOARD: AppRouteRecordRaw = {
|
||||
component: DEFAULT_LAYOUT,
|
||||
children: [
|
||||
{
|
||||
name: 'workplace',
|
||||
path: '/workplace',
|
||||
name: DEFAULT_ROUTE_NAME,
|
||||
path: DEFAULT_ROUTE_FULL_PATH,
|
||||
component: () => import('@/views/dashboard/workplace/index.vue'),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,8 +4,8 @@ import type { MenuQueryResponse } from '@/api/system/menu';
|
||||
import router from '@/router';
|
||||
import { defineStore } from 'pinia';
|
||||
import { Notification } from '@arco-design/web-vue';
|
||||
import { getMenuList } from '@/api/user/auth';
|
||||
import { EnabledStatus } from '@/types/const';
|
||||
import { getUserMenuList } from '@/api/user/permission';
|
||||
|
||||
export default defineStore('menu', {
|
||||
state: (): MenuState => ({
|
||||
@@ -54,7 +54,7 @@ export default defineStore('menu', {
|
||||
async fetchMenu() {
|
||||
try {
|
||||
// 查询菜单
|
||||
const { data } = await getMenuList();
|
||||
const { data } = await getUserMenuList();
|
||||
// 转换菜单
|
||||
this.serverMenus = data.map(s => {
|
||||
// 构建父目录
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type { TabBarState, TagProps } from './types';
|
||||
import { defineStore } from 'pinia';
|
||||
import { DEFAULT_ROUTE_NAME, DEFAULT_TAB } from '@/router/constants';
|
||||
import { isString } from '@/utils/is';
|
||||
|
||||
export default defineStore('tabBar', {
|
||||
state: (): TabBarState => ({
|
||||
cacheTabList: new Set([DEFAULT_ROUTE_NAME]),
|
||||
tagList: [DEFAULT_TAB],
|
||||
cacheTabList: new Set([]),
|
||||
tagList: [],
|
||||
}),
|
||||
|
||||
getters: {
|
||||
@@ -55,9 +54,8 @@ export default defineStore('tabBar', {
|
||||
|
||||
// 重设 tab
|
||||
resetTabList() {
|
||||
this.tagList = [DEFAULT_TAB];
|
||||
this.tagList = [];
|
||||
this.cacheTabList.clear();
|
||||
this.cacheTabList.add(DEFAULT_ROUTE_NAME);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { UserState } from './types';
|
||||
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 { clearToken, setToken } from '@/utils/auth';
|
||||
import { md5 } from '@/utils';
|
||||
import { removeRouteListener } from '@/utils/route-listener';
|
||||
import { getUserPermission } from '@/api/user/permission';
|
||||
import { useAppStore, useCacheStore, useMenuStore, useTabBarStore, useTipsStore } from '@/store';
|
||||
|
||||
export default defineStore('user', {
|
||||
@@ -25,15 +26,15 @@ export default defineStore('user', {
|
||||
|
||||
actions: {
|
||||
// 设置用户信息
|
||||
setInfo(partial: Partial<UserState>) {
|
||||
setUserInfo(partial: Partial<UserState>) {
|
||||
this.$patch(partial);
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
async info() {
|
||||
async getUserInfo() {
|
||||
const { data } = await getUserPermission();
|
||||
// 设置用户信息
|
||||
this.setInfo({
|
||||
this.setUserInfo({
|
||||
id: data.user.id,
|
||||
username: data.user.username,
|
||||
nickname: data.user.nickname,
|
||||
@@ -42,11 +43,10 @@ export default defineStore('user', {
|
||||
permission: data.permissions,
|
||||
});
|
||||
// 设置用户偏好
|
||||
const appStore = useAppStore();
|
||||
appStore.updateSettings(data.user.systemPreference);
|
||||
useAppStore().updateSettings(data.systemPreference);
|
||||
// 设置已经提示的key
|
||||
const tipsStore = useTipsStore();
|
||||
tipsStore.set(data.user.tippedKeys);
|
||||
useTipsStore().set(data.tippedKeys);
|
||||
return data;
|
||||
},
|
||||
|
||||
// 登录
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
import { useUserStore } from '@/store';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { isDemoMode } from '@/utils/env';
|
||||
import { DEFAULT_ROUTE_NAME } from '@/router/constants';
|
||||
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
@@ -83,7 +84,7 @@
|
||||
// 跳转路由
|
||||
const { redirect, ...othersQuery } = router.currentRoute.value.query;
|
||||
router.push({
|
||||
name: (redirect as string) || 'workplace',
|
||||
name: (redirect as string) || DEFAULT_ROUTE_NAME,
|
||||
query: {
|
||||
...othersQuery,
|
||||
},
|
||||
|
||||
@@ -23,6 +23,12 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'login',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Notification } from '@arco-design/web-vue';
|
||||
import { reLoginTipsKey } from '@/types/symbol';
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div></div>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'redirect',
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
|
||||
@@ -1,44 +1,34 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-result class="result" status="403" subtitle="您没有访问该资源的权限" />
|
||||
<div class="operation-row">
|
||||
<a-button class="mr8" key="back" type="primary" @click="logout">重新登录</a-button>
|
||||
<a-button key="back" type="primary" @click="to('workplace')">返回工作台</a-button>
|
||||
</div>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="() => logout()">重新登录</a-button>
|
||||
<a-button type="primary" @click="() => $router.push(DEFAULT_ROUTE_NAME)">返回工作台</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</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">
|
||||
export default {
|
||||
name: 'forbidden',
|
||||
};
|
||||
</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>
|
||||
.content {
|
||||
// padding-top: 100px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -95px;
|
||||
margin-top: -121px;
|
||||
margin-left: -96px;
|
||||
margin-top: -124px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,44 +1,34 @@
|
||||
<template>
|
||||
<div class="content">
|
||||
<a-result class="result" status="404" subtitle="糟糕! 页面不见了!" />
|
||||
<div class="operation-row">
|
||||
<a-button class="mr8" key="back" type="primary" @click="logout">重新登录</a-button>
|
||||
<a-button key="back" type="primary" @click="to('workplace')">返回工作台</a-button>
|
||||
</div>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="() => logout()">重新登录</a-button>
|
||||
<a-button type="primary" @click="() => $router.push(DEFAULT_ROUTE_NAME)">返回工作台</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</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">
|
||||
export default {
|
||||
name: 'notFound',
|
||||
};
|
||||
</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>
|
||||
.content {
|
||||
// padding-top: 100px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -95px;
|
||||
margin-top: -121px;
|
||||
margin-left: -96px;
|
||||
margin-top: -124px;
|
||||
text-align: center;
|
||||
}
|
||||
</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
|
||||
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);
|
||||
|
||||
@@ -9,10 +9,9 @@ CREATE TABLE `table` (
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='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 `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,
|
||||
|
||||
Reference in New Issue
Block a user