修复鉴权:401拦截器加refresh重试 + admin refresh接口 + 路由守卫完善

根因:access_token每2小时过期,前端收到401直接清token跳登录,没有用refresh_token续期

后端修复:
- adminauth模块新增 POST /admin/auth/refresh 接口
- Service 注入 JWTManager,支持 admin refresh token 换新 token pair
- Refresh 方法验证 subjectType=admin + tokenType=refresh

前端修复:
- 401 拦截器核心改造:收到401先调 refresh 接口续期
- 加 isRefreshing 锁 + pendingRequests 队列防止并发刷新
- refresh 用原生 axios.post 避免拦截器递归
- 成功则更新 localStorage + 重试原请求,失败才清 token 跳登录
- 排除 /auth/refresh 自身避免死循环
- 支持 /admin/ 请求独立 token 管理
- auth.ts/adminAuth.ts 新增手动 refreshUserToken/refreshAdminSession
- 路由守卫给所有需登录路由添加 meta.requiresAuth
- 守卫同时支持 PC 端 /login 和移动端 /m/login
This commit is contained in:
yml2213
2026-05-24 07:00:13 +08:00
parent 3631e70321
commit cdee93c7c5
61 changed files with 1735 additions and 722 deletions
+66 -14
View File
@@ -488,36 +488,45 @@ func (r *Repository) AcceptCheckout(userID uint64, orderID uint64) error {
})
}
func (r *Repository) ListForUser(userID uint64) ([]OrderDTO, error) {
var rows []orderRow
err := r.baseQuery().
Where("o.renter_id = ?", userID).
func (r *Repository) ListForUser(userID uint64, page int, pageSize int) (*PaginatedOrders, error) {
var total int64
r.db.Model(&model.RentalOrder{}).Where("renter_id = ? OR owner_id = ?", userID, userID).Count(&total)
offset := (page - 1) * pageSize
var rows []orderListRow
err := r.listItemBaseQuery().
Where("o.renter_id = ? OR o.owner_id = ?", userID, userID).
Order("o.id DESC").
Offset(offset).Limit(pageSize).
Scan(&rows).Error
if err != nil {
return nil, err
}
items := make([]OrderDTO, 0, len(rows))
items := make([]OrderListItemDTO, 0, len(rows))
for _, row := range rows {
items = append(items, row.toDTO())
items = append(items, row.toListItemDTO())
}
return items, nil
return &PaginatedOrders{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
}
func (r *Repository) ListAdmin() ([]OrderDTO, error) {
var rows []orderRow
err := r.adminQuery().
func (r *Repository) ListAdmin(page int, pageSize int) (*PaginatedOrders, error) {
var total int64
r.db.Model(&model.RentalOrder{}).Count(&total)
offset := (page - 1) * pageSize
var rows []orderListRow
err := r.listItemBaseQuery().
Order("o.id DESC").
Limit(200).
Offset(offset).Limit(pageSize).
Scan(&rows).Error
if err != nil {
return nil, err
}
items := make([]OrderDTO, 0, len(rows))
items := make([]OrderListItemDTO, 0, len(rows))
for _, row := range rows {
items = append(items, row.toDTO())
items = append(items, row.toListItemDTO())
}
return items, nil
return &PaginatedOrders{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
}
func (r *Repository) FindAdmin(orderID uint64) (*OrderDTO, error) {
@@ -898,6 +907,16 @@ func (r *Repository) findHandoffRecord(id uint64) (*HandoffRecordDTO, error) {
return &dto, nil
}
func (r *Repository) listItemBaseQuery() *gorm.DB {
return r.db.Table("rental_orders AS o").
Select("o.id, o.order_no, o.status, o.handoff_status, o.settlement_status, o.rent_amount, o.deposit_amount, o.created_at, "+
"a.title AS account_title, a.game_name, "+
"owner.nickname AS owner_nickname, renter.nickname AS renter_nickname").
Joins("JOIN game_accounts AS a ON a.id = o.account_id").
Joins("JOIN users AS owner ON owner.id = o.owner_id").
Joins("JOIN users AS renter ON renter.id = o.renter_id")
}
func (r *Repository) baseQuery() *gorm.DB {
return r.db.Table("rental_orders AS o").
Select("o.*, a.title, a.server_region, a.login_platform").
@@ -948,6 +967,39 @@ func (row orderRow) toDTO() OrderDTO {
}
}
type orderListRow struct {
ID uint64
OrderNo string
Status string
HandoffStatus string
SettlementStatus string
RentAmount float64
DepositAmount float64
CreatedAt time.Time
AccountTitle string
GameName string
OwnerNickname string
RenterNickname string
}
func (row orderListRow) toListItemDTO() OrderListItemDTO {
return OrderListItemDTO{
ID: row.ID,
OrderNo: row.OrderNo,
ListingTitle: row.AccountTitle,
GameName: row.GameName,
AccountTitle: row.AccountTitle,
RenterNickname: row.RenterNickname,
OwnerNickname: row.OwnerNickname,
Status: row.Status,
HandoffStatus: row.HandoffStatus,
SettlementStatus: row.SettlementStatus,
RentAmount: row.RentAmount,
DepositAmount: row.DepositAmount,
CreatedAt: row.CreatedAt,
}
}
func toHandoffDTO(record model.HandoffRecord) HandoffRecordDTO {
return HandoffRecordDTO{
ID: record.ID,