diff --git a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py
index ed7cf7a..91d6611 100644
--- a/ruoyi-fastapi-backend/module_admin/controller/user_controller.py
+++ b/ruoyi-fastapi-backend/module_admin/controller/user_controller.py
@@ -165,6 +165,7 @@ async def reset_system_user_pwd(
edit_user = EditUserModel(
userId=reset_user.user_id,
password=PwdUtil.get_password_hash(reset_user.password),
+ pwdUpdateDate=datetime.now(),
updateBy=current_user.user.user_name,
updateTime=datetime.now(),
type='pwd',
@@ -304,6 +305,7 @@ async def reset_system_user_password(
userId=current_user.user.user_id,
oldPassword=reset_password.old_password,
password=reset_password.new_password,
+ pwdUpdateDate=datetime.now(),
updateBy=current_user.user.user_name,
updateTime=datetime.now(),
)
diff --git a/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py b/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py
index 246461f..c71b5b7 100644
--- a/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py
+++ b/ruoyi-fastapi-backend/module_admin/entity/do/user_do.py
@@ -32,6 +32,7 @@ class SysUser(Base):
del_flag = Column(CHAR(1), nullable=True, server_default='0', comment='删除标志(0代表存在 2代表删除)')
login_ip = Column(String(128), nullable=True, server_default="''", comment='最后登录IP')
login_date = Column(DateTime, nullable=True, comment='最后登录时间')
+ pwd_update_date = Column(DateTime, nullable=True, comment='密码最后更新时间')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者')
create_time = Column(DateTime, nullable=True, comment='创建时间', default=datetime.now())
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者')
diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
index 4eac953..9ef8867 100644
--- a/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
+++ b/ruoyi-fastapi-backend/module_admin/entity/vo/user_vo.py
@@ -40,6 +40,7 @@ class UserModel(BaseModel):
del_flag: Optional[Literal['0', '2']] = Field(default=None, description='删除标志(0代表存在 2代表删除)')
login_ip: Optional[str] = Field(default=None, description='最后登录IP')
login_date: Optional[datetime] = Field(default=None, description='最后登录时间')
+ pwd_update_date: Optional[datetime] = Field(default=None, description='密码最后更新时间')
create_by: Optional[str] = Field(default=None, description='创建者')
create_time: Optional[datetime] = Field(default=None, description='创建时间')
update_by: Optional[str] = Field(default=None, description='更新者')
@@ -125,6 +126,7 @@ class CurrentUserModel(BaseModel):
permissions: List = Field(description='权限信息')
roles: List = Field(description='角色信息')
user: Union[UserInfoModel, None] = Field(description='用户信息')
+ is_default_modify_pwd: bool = Field(default=False, description='是否初始密码修改提醒')
class UserDetailModel(BaseModel):
diff --git a/ruoyi-fastapi-backend/module_admin/service/login_service.py b/ruoyi-fastapi-backend/module_admin/service/login_service.py
index 9c61f22..e5a5f30 100644
--- a/ruoyi-fastapi-backend/module_admin/service/login_service.py
+++ b/ruoyi-fastapi-backend/module_admin/service/login_service.py
@@ -218,7 +218,7 @@ class LoginService:
else:
# 此方法可实现同一账号同一时间只能登录一次
redis_token = await request.app.state.redis.get(
- f"{RedisInitKeyConfig.ACCESS_TOKEN.key}:{query_user.get('user_basic_info').user_id}"
+ f'{RedisInitKeyConfig.ACCESS_TOKEN.key}:{query_user.get("user_basic_info").user_id}'
)
if token == redis_token:
if AppConfig.app_same_time_login:
@@ -229,7 +229,7 @@ class LoginService:
)
else:
await request.app.state.redis.set(
- f"{RedisInitKeyConfig.ACCESS_TOKEN.key}:{query_user.get('user_basic_info').user_id}",
+ f'{RedisInitKeyConfig.ACCESS_TOKEN.key}:{query_user.get("user_basic_info").user_id}',
redis_token,
ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes),
)
@@ -242,6 +242,9 @@ class LoginService:
post_ids = ','.join([str(row.post_id) for row in query_user.get('user_post_info')])
role_ids = ','.join([str(row.role_id) for row in query_user.get('user_role_info')])
roles = [row.role_key for row in query_user.get('user_role_info')]
+ is_default_modify_pwd = await cls.__init_password_is_modify(
+ request, query_user.get('user_basic_info').pwd_update_date
+ )
current_user = CurrentUserModel(
permissions=permissions,
@@ -253,12 +256,27 @@ class LoginService:
dept=CamelCaseUtil.transform_result(query_user.get('user_dept_info')),
role=CamelCaseUtil.transform_result(query_user.get('user_role_info')),
),
+ isDefaultModifyPwd=is_default_modify_pwd,
)
return current_user
else:
logger.warning('用户token已失效,请重新登录')
raise AuthException(data='', message='用户token已失效,请重新登录')
+ @classmethod
+ async def __init_password_is_modify(cls, request: Request, pwd_update_date: datetime):
+ """
+ 判断当前用户是否初始密码登录
+
+ :param request: Request对象
+ :param pwd_update_date: 密码最后更新时间
+ :return: 是否初始密码登录
+ """
+ init_password_is_modify = await request.app.state.redis.get(
+ f'{RedisInitKeyConfig.SYS_CONFIG.key}:sys.account.initPasswordModify'
+ )
+ return init_password_is_modify == '1' and pwd_update_date is None
+
@classmethod
async def get_current_user_routers(cls, user_id: int, query_db: AsyncSession):
"""
diff --git a/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql b/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql
index a47c14f..fbe559b 100644
--- a/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql
+++ b/ruoyi-fastapi-backend/sql/ruoyi-fastapi-pg.sql
@@ -69,6 +69,7 @@ create table sys_user (
del_flag char(1) default '0',
login_ip varchar(128) default '',
login_date timestamp(0),
+ pwd_update_date timestamp(0),
create_by varchar(64) default '',
create_time timestamp(0),
update_by varchar(64) default '',
@@ -91,6 +92,7 @@ comment on column sys_user.status is '帐号状态(0正常 1停用)';
comment on column sys_user.del_flag is '删除标志(0代表存在 2代表删除)';
comment on column sys_user.login_ip is '最后登录IP';
comment on column sys_user.login_date is '最后登录时间';
+comment on column sys_user.pwd_update_date is '密码最后更新时间';
comment on column sys_user.create_by is '创建者';
comment on column sys_user.create_time is '创建时间';
comment on column sys_user.update_by is '更新者';
@@ -98,6 +100,12 @@ comment on column sys_user.update_time is '更新时间';
comment on column sys_user.remark is '备注';
comment on table sys_user is '用户信息表';
+-- ----------------------------
+-- 初始化-用户信息表数据
+-- ----------------------------
+insert into sys_user values(1, 103, 'admin', '超级管理员', '00', 'niangao@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', current_timestamp, current_timestamp, 'admin', current_timestamp, '', null, '管理员');
+insert into sys_user values(2, 105, 'niangao', '年糕', '00', 'niangao@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', current_timestamp, current_timestamp, 'admin', current_timestamp, '', null, '测试员');
+
-- ----------------------------
-- 3、岗位信息表
-- ----------------------------
@@ -136,12 +144,6 @@ insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', current
insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', current_timestamp, '', null, '');
insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', current_timestamp, '', null, '');
--- ----------------------------
--- 初始化-用户信息表数据
--- ----------------------------
-insert into sys_user values(1, 103, 'admin', '超级管理员', '00', 'niangao@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', current_timestamp, 'admin', current_timestamp, '', null, '管理员');
-insert into sys_user values(2, 105, 'niangao', '年糕', '00', 'niangao@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', current_timestamp, 'admin', current_timestamp, '', null, '测试员');
-
-- ----------------------------
-- 4、角色信息表
-- ----------------------------
@@ -704,6 +706,7 @@ insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.
insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', current_timestamp, '', null, '是否开启验证码功能(true开启,false关闭)');
insert into sys_config values(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', current_timestamp, '', null, '是否开启注册用户功能(true开启,false关闭)');
insert into sys_config values(6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', current_timestamp, '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)');
+insert into sys_config values(7, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '1', 'Y', 'admin', current_timestamp, '', null, '0:初始密码修改策略关闭,没有任何提示,1:提醒用户,如果未修改初始密码,则在登录时就会提醒修改密码对话框');
-- ----------------------------
-- 14、系统访问记录
diff --git a/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql b/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql
index 7b796a7..2795698 100644
--- a/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql
+++ b/ruoyi-fastapi-backend/sql/ruoyi-fastapi.sql
@@ -54,6 +54,7 @@ create table sys_user (
del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)',
login_ip varchar(128) default '' comment '最后登录IP',
login_date datetime comment '最后登录时间',
+ pwd_update_date datetime comment '密码最后更新时间',
create_by varchar(64) default '' comment '创建者',
create_time datetime comment '创建时间',
update_by varchar(64) default '' comment '更新者',
@@ -65,8 +66,8 @@ create table sys_user (
-- ----------------------------
-- 初始化-用户信息表数据
-- ----------------------------
-insert into sys_user values(1, 103, 'admin', '超级管理员', '00', 'niangao@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '管理员');
-insert into sys_user values(2, 105, 'niangao', '年糕', '00', 'niangao@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), 'admin', sysdate(), '', null, '测试员');
+insert into sys_user values(1, 103, 'admin', '超级管理员', '00', 'niangao@163.com', '15888888888', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), sysdate(), 'admin', sysdate(), '', null, '管理员');
+insert into sys_user values(2, 105, 'niangao', '年糕', '00', 'niangao@qq.com', '15666666666', '1', '', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '0', '0', '127.0.0.1', sysdate(), sysdate(), 'admin', sysdate(), '', null, '测试员');
-- ----------------------------
@@ -554,6 +555,7 @@ insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.
insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能(true开启,false关闭)');
insert into sys_config values(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)');
insert into sys_config values(6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)');
+insert into sys_config values(7, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '1', 'Y', 'admin', sysdate(), '', null, '0:初始密码修改策略关闭,没有任何提示,1:提醒用户,如果未修改初始密码,则在登录时就会提醒修改密码对话框');
-- ----------------------------
diff --git a/ruoyi-fastapi-frontend/src/router/index.js b/ruoyi-fastapi-frontend/src/router/index.js
index e8b982d..f31c43f 100644
--- a/ruoyi-fastapi-frontend/src/router/index.js
+++ b/ruoyi-fastapi-frontend/src/router/index.js
@@ -77,7 +77,7 @@ export const constantRoutes = [
redirect: 'noredirect',
children: [
{
- path: 'profile',
+ path: 'profile/:activeTab?',
component: () => import('@/views/system/user/profile/index'),
name: 'Profile',
meta: { title: '个人中心', icon: 'user' }
diff --git a/ruoyi-fastapi-frontend/src/store/modules/user.js b/ruoyi-fastapi-frontend/src/store/modules/user.js
index 2c6398f..36b562f 100644
--- a/ruoyi-fastapi-frontend/src/store/modules/user.js
+++ b/ruoyi-fastapi-frontend/src/store/modules/user.js
@@ -1,3 +1,5 @@
+import router from '@/router'
+import { ElMessageBox } from 'element-plus'
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { isHttp, isEmpty } from "@/utils/validate"
@@ -51,6 +53,12 @@ const useUserStore = defineStore(
this.name = user.userName
this.nickName = user.nickName
this.avatar = avatar
+ /* 初始密码提示 */
+ if(res.isDefaultModifyPwd) {
+ ElMessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
+ router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
+ }).catch(() => {})
+ }
resolve(res)
}).catch(error => {
reject(error)
diff --git a/ruoyi-fastapi-frontend/src/views/system/user/profile/index.vue b/ruoyi-fastapi-frontend/src/views/system/user/profile/index.vue
index 5851f05..26f4bd4 100644
--- a/ruoyi-fastapi-frontend/src/views/system/user/profile/index.vue
+++ b/ruoyi-fastapi-frontend/src/views/system/user/profile/index.vue
@@ -48,7 +48,7 @@
基本资料
-
+
@@ -68,7 +68,8 @@ import userInfo from "./userInfo";
import resetPwd from "./resetPwd";
import { getUserProfile } from "@/api/system/user";
-const activeTab = ref("userinfo");
+const route = useRoute()
+const selectedTab = ref("userinfo")
const state = reactive({
user: {},
roleGroup: {},
@@ -83,5 +84,11 @@ function getUser() {
});
};
-getUser();
+onMounted(() => {
+ const activeTab = route.params && route.params.activeTab
+ if (activeTab) {
+ selectedTab.value = activeTab
+ }
+ getUser()
+})