订单接口最小化与私有文件访问加固

- 订单列表使用独立最小 DTO 并分页,号主待办提供独立接口与统计
- 用户 token 增加版本控制,冻结/改密/退出即时撤销会话
- 移除 URL token 传参,SSE 与接口统一使用 HttpOnly Cookie
- 私有文件按上传归属与业务关联授权,收款凭证转私有访问并校验归属
- 公开商品接口返回最小字段,隐藏号主身份与内部状态
- 每日清理超过 30 天未关联业务的上传归属,上传归属失败时补偿删除对象
This commit is contained in:
yml2213
2026-08-16 21:47:46 +08:00
parent f48da14ed2
commit 85332df2bd
63 changed files with 1827 additions and 290 deletions
+78 -6
View File
@@ -75,6 +75,56 @@ export interface Order {
updated_at: string
}
// 订单列表只承载卡片和表格所需字段;完整订单信息由详情接口返回。
export interface UserOrderListItem {
id: number
order_no: string
listing_id: number
listing_no: string
role: 'owner' | 'renter'
title: string
server_region: string
login_platform: string
display_amount_cent: number
deposit_amount_cent: number
deposit_waived_amount_cent: number
status: OrderStatus
handoff_status: HandoffStatus
payment_deadline_at?: string
created_at: string
}
// 后台订单列表使用脱敏后的表格数据,敏感字段仅在详情接口中按权限返回。
export interface AdminOrderListItem {
id: number
order_no: string
listing_id: number
listing_no: string
owner_phone?: string
renter_phone?: string
title: string
server_region: string
login_platform: string
rent_amount_cent: number
deposit_amount_cent: number
status: OrderStatus
handoff_status: HandoffStatus
handoff_mode: string
settlement_mode: string
settlement_status: SettlementStatus
created_at: string
}
export interface SellerHandoffMetrics {
pending_handoff: number
pending_checkout: number
abnormal: number
}
export interface SellerHandoffResult extends PaginatedResult<UserOrderListItem> {
metrics: SellerHandoffMetrics
}
export interface AdminActions {
reset_handoff?: AdminAction
platform_handoff?: AdminAction
@@ -246,9 +296,28 @@ export async function fetchPostRentalNotice() {
return data.data
}
export async function fetchOrders() {
const { data } = await apiClient.get<ApiResponse<{ items: Order[] }>>('/orders')
return Array.isArray(data.data?.items) ? data.data.items : []
export async function fetchOrders(page = 1, pageSize = 20) {
const { data } = await apiClient.get<ApiResponse<PaginatedResult<UserOrderListItem>>>('/orders', {
params: { page, page_size: pageSize },
})
return data.data
}
export async function fetchSellerHandoffs(
params: {
page?: number
pageSize?: number
status?: string
} = {}
) {
const { data } = await apiClient.get<ApiResponse<SellerHandoffResult>>('/orders/handoffs', {
params: {
page: params.page || 1,
page_size: params.pageSize || 20,
status: params.status || undefined,
},
})
return data.data
}
export async function fetchOrder(id: string | number) {
@@ -363,9 +432,12 @@ export async function counterCheckout(id: number, payload: SubmitCheckoutPayload
}
export async function fetchAdminOrders(page = 1, pageSize = 20, query: AdminOrderQuery = {}) {
const { data } = await apiClient.get<ApiResponse<PaginatedResult<Order>>>('/admin/orders', {
params: { page, page_size: pageSize, ...query },
})
const { data } = await apiClient.get<ApiResponse<PaginatedResult<AdminOrderListItem>>>(
'/admin/orders',
{
params: { page, page_size: pageSize, ...query },
}
)
return data.data
}