fix(crypto-tail): 周期切换时按周期拉取 tokenIds,修复手动下单 orderbook 不存在
- 后端 initMonitor 支持可选 periodStartUnix,按指定周期取市场与 tokenIds - 前端周期切换时调用 monitorInit 传入 pushPeriod,确保 tokenIds 与当前周期一致 - 修复切换周期无变化及手动下单报 orderbook does not exist Made-with: Cursor
This commit is contained in:
@@ -5,7 +5,9 @@ package com.wrbug.polymarketbot.dto
|
|||||||
*/
|
*/
|
||||||
data class CryptoTailMonitorInitRequest(
|
data class CryptoTailMonitorInitRequest(
|
||||||
/** 策略ID */
|
/** 策略ID */
|
||||||
val strategyId: Long = 0L
|
val strategyId: Long = 0L,
|
||||||
|
/** 指定周期开始时间 (Unix 秒),不传则用服务器当前周期 */
|
||||||
|
val periodStartUnix: Long? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+2
-1
@@ -147,7 +147,8 @@ class CryptoTailMonitorService(
|
|||||||
|
|
||||||
val account = accountRepository.findById(strategy.accountId).orElse(null)
|
val account = accountRepository.findById(strategy.accountId).orElse(null)
|
||||||
val nowSeconds = System.currentTimeMillis() / 1000
|
val nowSeconds = System.currentTimeMillis() / 1000
|
||||||
val periodStartUnix = (nowSeconds / strategy.intervalSeconds) * strategy.intervalSeconds
|
val periodStartUnix = request.periodStartUnix
|
||||||
|
?: ((nowSeconds / strategy.intervalSeconds) * strategy.intervalSeconds)
|
||||||
|
|
||||||
// 获取市场信息
|
// 获取市场信息
|
||||||
val slug = "${strategy.marketSlugPrefix}-$periodStartUnix"
|
val slug = "${strategy.marketSlugPrefix}-$periodStartUnix"
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ const CryptoTailMonitor: React.FC = () => {
|
|||||||
const marketChartRef = useRef<HTMLDivElement>(null)
|
const marketChartRef = useRef<HTMLDivElement>(null)
|
||||||
const marketChartInstance = useRef<echarts.ECharts | null>(null)
|
const marketChartInstance = useRef<echarts.ECharts | null>(null)
|
||||||
const lastPeriodStartRef = useRef<number | null>(null)
|
const lastPeriodStartRef = useRef<number | null>(null)
|
||||||
|
const selectedStrategyIdRef = useRef<number | null>(null)
|
||||||
|
useEffect(() => {
|
||||||
|
selectedStrategyIdRef.current = selectedStrategyId
|
||||||
|
}, [selectedStrategyId])
|
||||||
|
|
||||||
// localStorage key for period switch mode
|
// localStorage key for period switch mode
|
||||||
const PERIOD_SWITCH_MODE_KEY = 'cryptoTailMonitor_periodSwitchMode'
|
const PERIOD_SWITCH_MODE_KEY = 'cryptoTailMonitor_periodSwitchMode'
|
||||||
@@ -148,7 +152,7 @@ const CryptoTailMonitor: React.FC = () => {
|
|||||||
setPendingPeriodData(null)
|
setPendingPeriodData(null)
|
||||||
setIsViewingOldPeriod(false)
|
setIsViewingOldPeriod(false)
|
||||||
try {
|
try {
|
||||||
const res = await apiService.cryptoTailStrategy.monitorInit(selectedStrategyId)
|
const res = await apiService.cryptoTailStrategy.monitorInit({ strategyId: selectedStrategyId })
|
||||||
if (res.data.code === 0 && res.data.data) {
|
if (res.data.code === 0 && res.data.data) {
|
||||||
setInitData(res.data.data)
|
setInitData(res.data.data)
|
||||||
} else {
|
} else {
|
||||||
@@ -193,11 +197,23 @@ const CryptoTailMonitor: React.FC = () => {
|
|||||||
const lastPeriod = lastPeriodStartRef.current
|
const lastPeriod = lastPeriodStartRef.current
|
||||||
|
|
||||||
if (pushPeriod != null && pushPeriod !== lastPeriod) {
|
if (pushPeriod != null && pushPeriod !== lastPeriod) {
|
||||||
// 新周期到来
|
// 新周期到来:重新拉取 init(含 tokenIds),再更新状态
|
||||||
lastPeriodStartRef.current = pushPeriod
|
lastPeriodStartRef.current = pushPeriod
|
||||||
|
const marketTitle = (data as { marketTitle?: string }).marketTitle
|
||||||
|
const applyFreshInit = (fresh: CryptoTailMonitorInitResponse) => {
|
||||||
|
if (selectedStrategyIdRef.current !== fresh.strategyId) return
|
||||||
|
const merged: CryptoTailMonitorInitResponse = {
|
||||||
|
...fresh,
|
||||||
|
periodStartUnix: pushPeriod,
|
||||||
|
marketTitle: marketTitle ?? fresh.marketTitle ?? ''
|
||||||
|
}
|
||||||
|
if (periodSwitchMode === 'manual' && lastPeriod != null) {
|
||||||
|
setPendingPeriodData(p => p ? { ...p, initData: merged } : null)
|
||||||
|
} else {
|
||||||
|
setInitData(merged)
|
||||||
|
}
|
||||||
|
}
|
||||||
if (periodSwitchMode === 'manual' && lastPeriod != null) {
|
if (periodSwitchMode === 'manual' && lastPeriod != null) {
|
||||||
// 手动模式:保存新周期数据到 pending,保留当前显示
|
|
||||||
setPendingPeriodData({
|
setPendingPeriodData({
|
||||||
periodStartUnix: pushPeriod,
|
periodStartUnix: pushPeriod,
|
||||||
priceHistory: [newPoint],
|
priceHistory: [newPoint],
|
||||||
@@ -205,26 +221,35 @@ const CryptoTailMonitor: React.FC = () => {
|
|||||||
pushData: data
|
pushData: data
|
||||||
})
|
})
|
||||||
setIsViewingOldPeriod(true)
|
setIsViewingOldPeriod(true)
|
||||||
// 更新 pending 数据的 initData
|
apiService.cryptoTailStrategy.monitorInit({ strategyId: selectedStrategyId!, periodStartUnix: pushPeriod }).then(res => {
|
||||||
setInitData(prev => {
|
if (res.data?.code === 0 && res.data?.data) applyFreshInit(res.data.data)
|
||||||
if (prev) {
|
else {
|
||||||
setPendingPeriodData(p => p ? { ...p, initData: { ...prev, periodStartUnix: pushPeriod, marketTitle: (data as { marketTitle?: string }).marketTitle ?? prev.marketTitle } } : null)
|
setInitData(prev => {
|
||||||
|
if (prev) setPendingPeriodData(p => p ? { ...p, initData: { ...prev, periodStartUnix: pushPeriod, marketTitle: marketTitle ?? prev.marketTitle ?? '' } } : null)
|
||||||
|
return prev ?? null
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return prev
|
}).catch(() => {
|
||||||
|
setInitData(prev => {
|
||||||
|
if (prev) setPendingPeriodData(p => p ? { ...p, initData: { ...prev, periodStartUnix: pushPeriod, marketTitle: marketTitle ?? prev.marketTitle ?? '' } } : null)
|
||||||
|
return prev ?? null
|
||||||
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 自动模式或首次推送:直接切换
|
if (lastPeriod != null) setHasSwitchedPeriod(true)
|
||||||
if (lastPeriod != null) {
|
|
||||||
setHasSwitchedPeriod(true)
|
|
||||||
}
|
|
||||||
setFirstDataTime(newPoint.time)
|
setFirstDataTime(newPoint.time)
|
||||||
setInitData(prev => prev ? { ...prev, periodStartUnix: pushPeriod, marketTitle: (data as { marketTitle?: string }).marketTitle ?? prev.marketTitle } : null)
|
|
||||||
setPriceHistory([newPoint])
|
setPriceHistory([newPoint])
|
||||||
setPushData(data)
|
setPushData(data)
|
||||||
setIsViewingOldPeriod(false)
|
setIsViewingOldPeriod(false)
|
||||||
setPendingPeriodData(null)
|
setPendingPeriodData(null)
|
||||||
return
|
apiService.cryptoTailStrategy.monitorInit({ strategyId: selectedStrategyId!, periodStartUnix: pushPeriod }).then(res => {
|
||||||
|
if (res.data?.code === 0 && res.data?.data) applyFreshInit(res.data.data)
|
||||||
|
else setInitData(prev => prev ? { ...prev, periodStartUnix: pushPeriod, marketTitle: marketTitle ?? prev.marketTitle ?? '' } : null)
|
||||||
|
}).catch(() => {
|
||||||
|
setInitData(prev => prev ? { ...prev, periodStartUnix: pushPeriod, marketTitle: marketTitle ?? prev.marketTitle ?? '' } : null)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
// 同周期:追加数据
|
// 同周期:追加数据
|
||||||
if (periodSwitchMode === 'manual' && isViewingOldPeriod && pendingPeriodData) {
|
if (periodSwitchMode === 'manual' && isViewingOldPeriod && pendingPeriodData) {
|
||||||
|
|||||||
@@ -498,8 +498,8 @@ export const apiService = {
|
|||||||
apiClient.post<ApiResponse<import('../types').CryptoTailMarketOptionDto[]>>('/crypto-tail-strategy/market-options', {}),
|
apiClient.post<ApiResponse<import('../types').CryptoTailMarketOptionDto[]>>('/crypto-tail-strategy/market-options', {}),
|
||||||
autoMinSpread: (data: { intervalSeconds: number }) =>
|
autoMinSpread: (data: { intervalSeconds: number }) =>
|
||||||
apiClient.post<ApiResponse<import('../types').CryptoTailAutoMinSpreadResponse>>('/crypto-tail-strategy/auto-min-spread', data),
|
apiClient.post<ApiResponse<import('../types').CryptoTailAutoMinSpreadResponse>>('/crypto-tail-strategy/auto-min-spread', data),
|
||||||
monitorInit: (strategyId: number) =>
|
monitorInit: (data: { strategyId: number; periodStartUnix?: number }) =>
|
||||||
apiClient.post<ApiResponse<import('../types').CryptoTailMonitorInitResponse>>('/crypto-tail-strategy/monitor/init', { strategyId }),
|
apiClient.post<ApiResponse<import('../types').CryptoTailMonitorInitResponse>>('/crypto-tail-strategy/monitor/init', data),
|
||||||
manualOrder: (data: {
|
manualOrder: (data: {
|
||||||
strategyId: number
|
strategyId: number
|
||||||
periodStartUnix: number
|
periodStartUnix: number
|
||||||
|
|||||||
Reference in New Issue
Block a user