!33 添加前端无感刷新功能,并将token相关改为localstage存储
Merge pull request !33 from daxiongok/master
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
19
Yi.RuoYi.Vue3/src/utils/refreshToken.js
Normal file
19
Yi.RuoYi.Vue3/src/utils/refreshToken.js
Normal 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
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
const errorRes = error.response;
|
||||||
|
console.log('isRefreshingbefore',isRefreshing)
|
||||||
|
|
||||||
console.log(error.response,"error")
|
if (errorRes?.status == '401' && !isRefreshRequest(errorRes.config)) { // 如果没有权限且不是刷新token的请求
|
||||||
const errorRes=error.response;
|
console.log('isRefreshing',isRefreshing,new Date())
|
||||||
const code = errorRes.status || 200;
|
if (!isRefreshing) {
|
||||||
const msg = `${errorRes.data?.error?.message}` ;
|
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未找到资源",
|
||||||
|
|||||||
@@ -181,9 +181,13 @@ function handleSelectionChange(selection) {
|
|||||||
}
|
}
|
||||||
/** 排序触发事件 */
|
/** 排序触发事件 */
|
||||||
function handleSortChange(column, prop, order) {
|
function handleSortChange(column, prop, order) {
|
||||||
queryParams.value.orderByColumn = column.prop;
|
if (!column.order) {
|
||||||
queryParams.value.isAsc = column.order;
|
queryParams.value.orderByColumn = null;
|
||||||
getList();
|
} else {
|
||||||
|
queryParams.value.orderByColumn = column.prop;
|
||||||
|
}
|
||||||
|
queryParams.value.isAsc = column.order;
|
||||||
|
getList();
|
||||||
}
|
}
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
function handleDelete(row) {
|
function handleDelete(row) {
|
||||||
|
|||||||
@@ -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,8 +241,12 @@ function handleSelectionChange(selection) {
|
|||||||
}
|
}
|
||||||
/** 排序触发事件 */
|
/** 排序触发事件 */
|
||||||
function handleSortChange(column, prop, order) {
|
function handleSortChange(column, prop, order) {
|
||||||
queryParams.value.orderByColumn = column.prop;
|
if (!column.order) {
|
||||||
queryParams.value.isAsc = column.order;
|
queryParams.value.orderByColumn = null;
|
||||||
|
} else {
|
||||||
|
queryParams.value.orderByColumn = column.prop;
|
||||||
|
}
|
||||||
|
queryParams.value.isAsc = column.order;
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
/** 详细按钮操作 */
|
/** 详细按钮操作 */
|
||||||
|
|||||||
Reference in New Issue
Block a user