优化:历史数据接口对接
This commit is contained in:
parent
d44e7157e8
commit
9dd61be92f
185
src/api/historyRecord.ts
Normal file
185
src/api/historyRecord.ts
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/**
|
||||||
|
* 历史记录接口:getHistoryRecordListClient(需鉴权)、getHistoryRecordPublic(无需鉴权)
|
||||||
|
* 用于 Wallet.vue 历史 Tab 数据
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { buildQuery, get } from './request'
|
||||||
|
import type { PageResult } from './types'
|
||||||
|
|
||||||
|
/** 单条历史记录(与 doc.json definitions["polymarket.HistoryRecord"] 对齐) */
|
||||||
|
export interface HistoryRecordItem {
|
||||||
|
ID?: number
|
||||||
|
asset?: string
|
||||||
|
bio?: string
|
||||||
|
conditionId?: string
|
||||||
|
createdAt?: string
|
||||||
|
eventSlug?: string
|
||||||
|
icon?: string
|
||||||
|
name?: string
|
||||||
|
outcome?: string
|
||||||
|
outcomeIndex?: number
|
||||||
|
price?: number
|
||||||
|
profileImage?: string
|
||||||
|
profileImageOptimized?: string
|
||||||
|
proxyWallet?: string
|
||||||
|
pseudonym?: string
|
||||||
|
side?: string
|
||||||
|
size?: number
|
||||||
|
slug?: string
|
||||||
|
timestamp?: number
|
||||||
|
title?: string
|
||||||
|
transactionHash?: string
|
||||||
|
type?: string
|
||||||
|
updatedAt?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GET /hr/getHistoryRecordPublic 请求参数 */
|
||||||
|
export interface GetHistoryRecordPublicParams {
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
keyword?: string
|
||||||
|
slug?: string
|
||||||
|
title?: string
|
||||||
|
name?: string
|
||||||
|
bio?: string
|
||||||
|
createdAtRange?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GET /hr/getHistoryRecordListClient 请求参数(客户端分页,需鉴权) */
|
||||||
|
export interface GetHistoryRecordListClientParams {
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
userId?: number
|
||||||
|
keyword?: string
|
||||||
|
slug?: string
|
||||||
|
title?: string
|
||||||
|
name?: string
|
||||||
|
bio?: string
|
||||||
|
createdAtRange?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 响应 data 可能为分页或数组 */
|
||||||
|
export interface HistoryRecordPublicResponse {
|
||||||
|
code: number
|
||||||
|
data?: PageResult<HistoryRecordItem> | HistoryRecordItem[]
|
||||||
|
msg: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** getHistoryRecordListClient 响应 data 为 PageResult */
|
||||||
|
export interface HistoryRecordListClientResponse {
|
||||||
|
code: number
|
||||||
|
data?: PageResult<HistoryRecordItem>
|
||||||
|
msg: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端分页获取历史记录(需鉴权:x-token、x-user-id)
|
||||||
|
* GET /hr/getHistoryRecordListClient
|
||||||
|
*/
|
||||||
|
export async function getHistoryRecordListClient(
|
||||||
|
params: GetHistoryRecordListClientParams = {},
|
||||||
|
config?: { headers?: Record<string, string> },
|
||||||
|
): Promise<HistoryRecordListClientResponse> {
|
||||||
|
const query = buildQuery({
|
||||||
|
page: params.page,
|
||||||
|
pageSize: params.pageSize,
|
||||||
|
userId: params.userId,
|
||||||
|
keyword: params.keyword,
|
||||||
|
slug: params.slug,
|
||||||
|
title: params.title,
|
||||||
|
name: params.name,
|
||||||
|
bio: params.bio,
|
||||||
|
createdAtRange: params.createdAtRange,
|
||||||
|
})
|
||||||
|
return get<HistoryRecordListClientResponse>('/hr/getHistoryRecordListClient', query, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史记录(公开接口,无需鉴权)
|
||||||
|
* GET /hr/getHistoryRecordPublic
|
||||||
|
*/
|
||||||
|
export async function getHistoryRecordPublic(
|
||||||
|
params: GetHistoryRecordPublicParams = {},
|
||||||
|
): Promise<HistoryRecordPublicResponse> {
|
||||||
|
const query = buildQuery({
|
||||||
|
page: params.page,
|
||||||
|
pageSize: params.pageSize,
|
||||||
|
keyword: params.keyword,
|
||||||
|
slug: params.slug,
|
||||||
|
title: params.title,
|
||||||
|
name: params.name,
|
||||||
|
bio: params.bio,
|
||||||
|
createdAtRange: params.createdAtRange,
|
||||||
|
})
|
||||||
|
return get<HistoryRecordPublicResponse>('/hr/getHistoryRecordPublic', query)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 钱包 History 展示项(与 Wallet.vue HistoryItem / order.HistoryDisplayItem 一致) */
|
||||||
|
export interface HistoryDisplayItem {
|
||||||
|
id: string
|
||||||
|
market: string
|
||||||
|
side: 'Yes' | 'No'
|
||||||
|
activity: string
|
||||||
|
value: string
|
||||||
|
activityDetail?: string
|
||||||
|
profitLoss?: string
|
||||||
|
profitLossNegative?: boolean
|
||||||
|
timeAgo?: string
|
||||||
|
avgPrice?: string
|
||||||
|
shares?: string
|
||||||
|
iconChar?: string
|
||||||
|
iconClass?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTimeAgo(createdAt: string | undefined, timestamp?: number): string {
|
||||||
|
const ms = createdAt ? new Date(createdAt).getTime() : (timestamp != null ? timestamp * 1000 : 0)
|
||||||
|
if (!ms) return ''
|
||||||
|
const diff = Date.now() - ms
|
||||||
|
if (diff < 60000) return 'Just now'
|
||||||
|
if (diff < 3600000) return `${Math.floor(diff / 60000)} minutes ago`
|
||||||
|
if (diff < 86400000) return `${Math.floor(diff / 3600000)} hours ago`
|
||||||
|
if (diff < 604800000) return `${Math.floor(diff / 86400000)} days ago`
|
||||||
|
return new Date(ms).toLocaleDateString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 HistoryRecordItem 映射为钱包 History 展示项
|
||||||
|
*/
|
||||||
|
export function mapHistoryRecordToDisplayItem(record: HistoryRecordItem): HistoryDisplayItem {
|
||||||
|
const id = String(record.ID ?? '')
|
||||||
|
const market = record.title ?? record.name ?? record.eventSlug ?? ''
|
||||||
|
const outcome = (record.outcome ?? record.side ?? 'Yes').toString()
|
||||||
|
const side = outcome === 'No' || outcome === 'Down' ? 'No' : 'Yes'
|
||||||
|
const typeLabel = record.type ?? 'Trade'
|
||||||
|
const activity = `${typeLabel} ${outcome}`.trim()
|
||||||
|
const price = record.price ?? 0
|
||||||
|
const size = record.size ?? 0
|
||||||
|
const valueUsd = price * size
|
||||||
|
const value = `$${Math.abs(valueUsd).toFixed(2)}`
|
||||||
|
const priceCents = Math.round(price * 100)
|
||||||
|
const activityDetail = size > 0 ? `Sold ${Math.floor(size)} ${outcome} at ${priceCents}¢` : value
|
||||||
|
const timeAgo = formatTimeAgo(record.createdAt, record.timestamp)
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
market,
|
||||||
|
side,
|
||||||
|
activity,
|
||||||
|
value,
|
||||||
|
activityDetail,
|
||||||
|
profitLoss: value,
|
||||||
|
profitLossNegative: valueUsd < 0,
|
||||||
|
timeAgo,
|
||||||
|
avgPrice: priceCents ? `${priceCents}¢` : undefined,
|
||||||
|
shares: size > 0 ? String(Math.floor(size)) : undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 从响应中取出 list 并映射为展示项,同时返回 total(数组时为 length) */
|
||||||
|
export function getHistoryRecordList(
|
||||||
|
data: HistoryRecordPublicResponse['data'],
|
||||||
|
): { list: HistoryDisplayItem[]; total: number } {
|
||||||
|
if (!data) return { list: [], total: 0 }
|
||||||
|
const list = Array.isArray(data) ? data : (data as PageResult<HistoryRecordItem>).list ?? []
|
||||||
|
const total = Array.isArray(data) ? data.length : (data as PageResult<HistoryRecordItem>).total ?? list.length
|
||||||
|
return { list: list.map(mapHistoryRecordToDisplayItem), total }
|
||||||
|
}
|
||||||
@ -16,6 +16,8 @@ export interface ClobPositionMarket {
|
|||||||
outcomes?: string[]
|
outcomes?: string[]
|
||||||
outcomePrices?: string[] | number[]
|
outcomePrices?: string[] | number[]
|
||||||
clobTokenIds?: string[]
|
clobTokenIds?: string[]
|
||||||
|
/** 市场是否已关闭,closed=true 表示可结算/可领取 */
|
||||||
|
closed?: boolean
|
||||||
[key: string]: unknown
|
[key: string]: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,8 +164,8 @@ export interface PositionDisplayItem {
|
|||||||
marketID?: string
|
marketID?: string
|
||||||
/** Token ID(用于 claimPosition,API 返回 tokenId) */
|
/** Token ID(用于 claimPosition,API 返回 tokenId) */
|
||||||
tokenID?: string
|
tokenID?: string
|
||||||
/** 是否待领取/未结算(needClaim 为 true 时显示领取按钮) */
|
/** 所属市场是否已关闭,market.closed=true 表示可结算/可领取 */
|
||||||
needClaim?: boolean
|
marketClosed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,6 +232,7 @@ export function mapPositionToDisplayItem(pos: ClobPositionItem): PositionDisplay
|
|||||||
const marketID = String(pos.marketID ?? pos.market?.ID ?? '')
|
const marketID = String(pos.marketID ?? pos.market?.ID ?? '')
|
||||||
const tokenID = pos.tokenId ?? (pos as { tokenID?: string }).tokenID ?? ''
|
const tokenID = pos.tokenId ?? (pos as { tokenID?: string }).tokenID ?? ''
|
||||||
const imageUrl = (pos.market?.image ?? pos.market?.icon) as string | undefined
|
const imageUrl = (pos.market?.image ?? pos.market?.icon) as string | undefined
|
||||||
|
const marketClosed = pos.market?.closed === true
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
@ -252,6 +255,6 @@ export function mapPositionToDisplayItem(pos: ClobPositionItem): PositionDisplay
|
|||||||
availableSharesNum: availableNum >= 0 ? availableNum : undefined,
|
availableSharesNum: availableNum >= 0 ? availableNum : undefined,
|
||||||
marketID: marketID || undefined,
|
marketID: marketID || undefined,
|
||||||
tokenID: tokenID || undefined,
|
tokenID: tokenID || undefined,
|
||||||
needClaim: pos.needClaim,
|
marketClosed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
97
src/api/priceHistory.ts
Normal file
97
src/api/priceHistory.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* 价格历史接口(GET /pmPriceHistory/getPmPriceHistoryPublic)
|
||||||
|
* 用于 TradeDetail.vue 折线图数据
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { buildQuery, get } from './request'
|
||||||
|
import type { ApiResponse } from './types'
|
||||||
|
import type { PageResult } from './types'
|
||||||
|
|
||||||
|
/** 单条价格历史(与 doc.json definitions["polymarket.PmPriceHistory"] 对齐) */
|
||||||
|
export interface PmPriceHistoryItem {
|
||||||
|
ID?: number
|
||||||
|
createdAt?: string
|
||||||
|
fidelity?: number
|
||||||
|
interval?: string
|
||||||
|
/** 市场标识 */
|
||||||
|
market?: string
|
||||||
|
/** 价格(通常 0–1 小数,前端展示可乘 100 为百分比) */
|
||||||
|
price?: number
|
||||||
|
/** 时间戳(Unix 秒) */
|
||||||
|
time?: number
|
||||||
|
updatedAt?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/** GET /pmPriceHistory/getPmPriceHistoryPublic 请求参数 */
|
||||||
|
export interface GetPmPriceHistoryPublicParams {
|
||||||
|
/** 市场标识(必填,用于筛选) */
|
||||||
|
market: string
|
||||||
|
page?: number
|
||||||
|
pageSize?: number
|
||||||
|
/** 数据间隔 */
|
||||||
|
interval?: string
|
||||||
|
/** 时间筛选 */
|
||||||
|
time?: number
|
||||||
|
/** 创建时间范围 */
|
||||||
|
createdAtRange?: string[]
|
||||||
|
fidelity?: number
|
||||||
|
keyword?: string
|
||||||
|
order?: string
|
||||||
|
sort?: string
|
||||||
|
price?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 响应 data 为 PageResult<PmPriceHistoryItem> */
|
||||||
|
export interface PmPriceHistoryPublicResponse {
|
||||||
|
code: number
|
||||||
|
data?: PageResult<PmPriceHistoryItem>
|
||||||
|
msg: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取价格历史(公开接口,无需鉴权)
|
||||||
|
* GET /pmPriceHistory/getPmPriceHistoryPublic
|
||||||
|
*/
|
||||||
|
export async function getPmPriceHistoryPublic(
|
||||||
|
params: GetPmPriceHistoryPublicParams,
|
||||||
|
config?: { headers?: Record<string, string> },
|
||||||
|
): Promise<PmPriceHistoryPublicResponse> {
|
||||||
|
const { market, page = 1, pageSize = 500, interval, time, createdAtRange, fidelity, keyword, order, sort, price } = params
|
||||||
|
const query = buildQuery({
|
||||||
|
market,
|
||||||
|
page,
|
||||||
|
pageSize,
|
||||||
|
interval,
|
||||||
|
time,
|
||||||
|
createdAtRange,
|
||||||
|
fidelity,
|
||||||
|
keyword,
|
||||||
|
order,
|
||||||
|
sort,
|
||||||
|
price,
|
||||||
|
})
|
||||||
|
return get<PmPriceHistoryPublicResponse>('/pmPriceHistory/getPmPriceHistoryPublic', query, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 图表单点格式 [timestamp_ms, value_0_100] */
|
||||||
|
export type ChartDataPoint = [number, number]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将接口返回的 list 转为 ECharts 折线图数据
|
||||||
|
* - time 转为毫秒时间戳
|
||||||
|
* - price 若 ≤1 视为小数概率,乘 100;否则视为 0–100
|
||||||
|
*/
|
||||||
|
export function priceHistoryToChartData(list: PmPriceHistoryItem[]): ChartDataPoint[] {
|
||||||
|
if (!list?.length) return []
|
||||||
|
const out: ChartDataPoint[] = []
|
||||||
|
for (const item of list) {
|
||||||
|
const t = item.time
|
||||||
|
const p = item.price
|
||||||
|
if (t == null || p == null || !Number.isFinite(Number(t))) continue
|
||||||
|
const tsMs = Number(t) < 1e12 ? Number(t) * 1000 : Number(t)
|
||||||
|
const value = Number(p) <= 1 ? Number(p) * 100 : Number(p)
|
||||||
|
out.push([tsMs, value])
|
||||||
|
}
|
||||||
|
out.sort((a, b) => a[0] - b[0])
|
||||||
|
return out
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user