!33 添加前端无感刷新功能,并将token相关改为localstage存储

Merge pull request !33 from daxiongok/master
This commit is contained in:
橙子
2024-09-04 08:33:00 +00:00
committed by Gitee
8 changed files with 173 additions and 34 deletions

View File

@@ -13,5 +13,35 @@ namespace Yi.Framework.Ddd.Application.Contracts
/// 查询结束时间条件 /// 查询结束时间条件
/// </summary> /// </summary>
public DateTime? EndTime { get; set; } public DateTime? EndTime { get; set; }
/// <summary>
/// 排序列名,字段名对应前端
/// </summary>
public string? OrderByColumn { get; set; }
/// <summary>
/// 是否顺序,字段名对应前端
/// </summary>
public string? IsAsc { get; set; }
/// <summary>
/// 是否顺序
/// </summary>
public bool CanAsc => IsAsc?.ToLower() == "ascending" ? true : false;
private string _sorting;
//排序引用
public new string? Sorting
{
get
{
if (!OrderByColumn.IsNullOrWhiteSpace())
{
return $"{OrderByColumn} {(CanAsc ? "ASC" : "DESC")}";
}
else
{
return _sorting;
}
}
set => _sorting = value;
} }
} }

View File

@@ -20,10 +20,12 @@ namespace Yi.Framework.Rbac.Application.Services.RecordLog
public override async Task<PagedResultDto<LoginLogGetListOutputDto>> GetListAsync(LoginLogGetListInputVo input) public override async Task<PagedResultDto<LoginLogGetListOutputDto>> GetListAsync(LoginLogGetListInputVo input)
{ {
RefAsync<int> total = 0; RefAsync<int> total = 0;
if (input.Sorting.IsNullOrWhiteSpace())
input.Sorting = $"{nameof(LoginLogAggregateRoot.CreationTime)} Desc";
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.LoginIp), x => x.LoginIp.Contains(input.LoginIp!)) var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.LoginIp), x => x.LoginIp.Contains(input.LoginIp!))
.WhereIF(!string.IsNullOrEmpty(input.LoginUser), x => x.LoginUser!.Contains(input.LoginUser!)) .WhereIF(!string.IsNullOrEmpty(input.LoginUser), x => x.LoginUser!.Contains(input.LoginUser!))
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime) .WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
.OrderBy(input.Sorting)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total); .ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
return new PagedResultDto<LoginLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities)); return new PagedResultDto<LoginLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
} }

View File

@@ -24,9 +24,12 @@ namespace Yi.Framework.Rbac.Application.Services.RecordLog
public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input) public override async Task<PagedResultDto<OperationLogGetListOutputDto>> GetListAsync(OperationLogGetListInputVo input)
{ {
RefAsync<int> total = 0; RefAsync<int> total = 0;
if (input.Sorting.IsNullOrWhiteSpace())
input.Sorting = $"{nameof(OperationLogEntity.CreationTime)} Desc";
var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.OperUser), x => x.OperUser.Contains(input.OperUser!)) var entities = await _repository._DbQueryable.WhereIF(!string.IsNullOrEmpty(input.OperUser), x => x.OperUser.Contains(input.OperUser!))
.WhereIF(input.OperType is not null, x => x.OperType == input.OperType) .WhereIF(input.OperType is not null, x => x.OperType == input.OperType)
.WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime) .WhereIF(input.StartTime is not null && input.EndTime is not null, x => x.CreationTime >= input.StartTime && x.CreationTime <= input.EndTime)
.OrderBy(input.Sorting)
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total); .ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
return new PagedResultDto<OperationLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities)); return new PagedResultDto<OperationLogGetListOutputDto>(total, await MapToGetListOutputDtosAsync(entities));
} }

View File

@@ -1,18 +1,38 @@
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token' const TokenKey = 'Admin-Token'
const RefreshTokenKey = 'Refresh-Token'
const TenantIdKey='Tenant-Id' const TenantIdKey='Tenant-Id'
export function getToken() { export function getToken() {
return Cookies.get(TokenKey) return localStorage.getItem(TokenKey)
// return Cookies.get(TokenKey)
} }
export function setToken(token) { export function setToken(token) {
return Cookies.set(TokenKey, token) return localStorage.setItem(TokenKey, token)
// return Cookies.set(TokenKey, token)
} }
export function removeToken() { export function removeToken() {
return Cookies.remove(TokenKey) return localStorage.removeItem(TokenKey)
// return Cookies.remove(TokenKey)
} }
export function getRefreshToken() {
return localStorage.getItem(RefreshTokenKey)
// return Cookies.get(RefreshTokenKey)
}
export function setRefreshToken(token) {
return localStorage.setItem(RefreshTokenKey, token)
// return Cookies.set(RefreshTokenKey, token)
}
export function removeRefreshToken() {
return localStorage.removeItem(RefreshTokenKey)
// return Cookies.remove(RefreshTokenKey)
}
export function getTenantId() { export function getTenantId() {
return Cookies.get(TenantIdKey) return Cookies.get(TenantIdKey)
} }

View File

@@ -0,0 +1,19 @@
import { getRefreshToken } from './auth'
import request from './request'
export function refreshToken() {
return request({
url: '/account/refresh',
method: 'post',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Authorization': 'Bearer ' + getRefreshToken(),
'isToken' :false
},
__isRefreshToken: true
})
}
export function isRefreshRequest(config) {
return !!config.__isRefreshToken
}

View File

@@ -1,6 +1,7 @@
import axios from 'axios' import axios from 'axios'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus' import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken,getTenantId } from '@/utils/auth' import { getToken,setToken,setRefreshToken,getTenantId } from '@/utils/auth'
import { refreshToken, isRefreshRequest } from './refreshToken.js'
import errorCode from '@/utils/errorCode' import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi' import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache' import cache from '@/plugins/cache'
@@ -10,6 +11,8 @@ import JsonBig from 'json-bigint'
import qs from 'qs' import qs from 'qs'
let downloadLoadingInstance; let downloadLoadingInstance;
let isRefreshing = false;
let waitRequests = [] // 请求队列
// 是否显示重新登录 // 是否显示重新登录
export let isRelogin = { show: false }; export let isRelogin = { show: false };
@@ -126,16 +129,69 @@ service.interceptors.response.use(res => {
// handler(code, msg); // handler(code, msg);
return Promise.resolve(res); return Promise.resolve(res);
}, }, async function(error) {
error => {
console.log(error.response, "error") console.log(error.response, "error")
const errorRes = error.response; const errorRes = error.response;
const code = errorRes.status || 200; console.log('isRefreshingbefore',isRefreshing)
const msg = `${errorRes.data?.error?.message}` ;
if (errorRes?.status == '401' && !isRefreshRequest(errorRes.config)) { // 如果没有权限且不是刷新token的请求
console.log('isRefreshing',isRefreshing,new Date())
if (!isRefreshing) {
isRefreshing = true
let newToken = ''
// 刷新token
try {
const res = await refreshToken()
// 保存新的token
newToken = res.data.token
setToken(newToken)
setRefreshToken(res.data.refreshToken)
} catch(e) {
console.log("触发重新登录",e)
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '/index';
})
}).catch(() => {
isRelogin.show = false;
});
return Promise.reject(error)
}
// 有新token后再重新请求
errorRes.config.headers['Authorization'] = 'Bearer ' + newToken // 新token
// token 刷新后将数组的方法重新执行
waitRequests.forEach((cb) => cb(newToken))
waitRequests = [] // 重新请求完清空
const resp = await service.request(errorRes.config)
isRefreshing = false
console.log('closseRefreshing',isRefreshing)
return Promise.resolve(resp);
} else {
// 返回未执行 resolve 的 Promise
return new Promise(resolve => {
// 用函数形式将 resolve 存入,等待刷新后再执行
waitRequests.push(token => {
errorRes.config.headers['Authorization'] = 'Bearer ' + `${token}`
resolve(service(errorRes.config))
})
})
}
}
else
{
const code = errorRes && errorRes.status || 200;
const msg = `${errorRes?.data?.error?.message}`;
handler(code, msg); handler(code, msg);
return Promise.reject(error) return Promise.reject(error)
} }
}
) )
// 通用下载方法 // 通用下载方法
@@ -180,22 +236,22 @@ const handler = (code, msg) => {
title: msg title: msg
}) })
break; break;
//未授权 // //未授权
case 401: // case 401:
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { // ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录', // confirmButtonText: '重新登录',
cancelButtonText: '取消', // cancelButtonText: '取消',
type: 'warning' // type: 'warning'
}) // })
.then(() => { // .then(() => {
isRelogin.show = false; // isRelogin.show = false;
useUserStore().logOut().then(() => { // useUserStore().logOut().then(() => {
location.href = '/index'; // location.href = '/index';
}) // })
}).catch(() => { // }).catch(() => {
isRelogin.show = false; // isRelogin.show = false;
}); // });
break; // break;
case 404: case 404:
ElMessage({ ElMessage({
message: "404未找到资源", message: "404未找到资源",

View File

@@ -181,7 +181,11 @@ function handleSelectionChange(selection) {
} }
/** 排序触发事件 */ /** 排序触发事件 */
function handleSortChange(column, prop, order) { function handleSortChange(column, prop, order) {
if (!column.order) {
queryParams.value.orderByColumn = null;
} else {
queryParams.value.orderByColumn = column.prop; queryParams.value.orderByColumn = column.prop;
}
queryParams.value.isAsc = column.order; queryParams.value.isAsc = column.order;
getList(); getList();
} }

View File

@@ -202,7 +202,8 @@ const data = reactive({
title: undefined, title: undefined,
operUser: undefined, operUser: undefined,
operType: undefined, operType: undefined,
state: undefined state: undefined,
orderByColumn: undefined
} }
}); });
@@ -240,7 +241,11 @@ function handleSelectionChange(selection) {
} }
/** 排序触发事件 */ /** 排序触发事件 */
function handleSortChange(column, prop, order) { function handleSortChange(column, prop, order) {
if (!column.order) {
queryParams.value.orderByColumn = null;
} else {
queryParams.value.orderByColumn = column.prop; queryParams.value.orderByColumn = column.prop;
}
queryParams.value.isAsc = column.order; queryParams.value.isAsc = column.order;
getList(); getList();
} }