Spaces:
Running
Running
Fix end_date calculation: ensure dateBounds.max uses latest DB date and fix allDates generation with UTC
Browse files- src/components/AgentFilters.vue +32 -3
- src/lib/dataService.js +36 -3
src/components/AgentFilters.vue
CHANGED
|
@@ -116,13 +116,42 @@ export default {
|
|
| 116 |
allDates() {
|
| 117 |
if (!this.hasDateBounds) return []
|
| 118 |
const dates = []
|
| 119 |
-
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
const current = new Date(start)
|
|
|
|
|
|
|
| 122 |
while (current <= end) {
|
| 123 |
dates.push(new Date(current))
|
| 124 |
-
current.
|
| 125 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
return dates
|
| 127 |
},
|
| 128 |
maxSliderValue() {
|
|
|
|
| 116 |
allDates() {
|
| 117 |
if (!this.hasDateBounds) return []
|
| 118 |
const dates = []
|
| 119 |
+
|
| 120 |
+
// Normalize dates to YYYY-MM-DD strings first to avoid timezone issues
|
| 121 |
+
const normalizeDate = (d) => {
|
| 122 |
+
if (!d) return null
|
| 123 |
+
if (d instanceof Date) {
|
| 124 |
+
return d.toISOString().split('T')[0]
|
| 125 |
+
}
|
| 126 |
+
if (typeof d === 'string') {
|
| 127 |
+
return d.split('T')[0]
|
| 128 |
+
}
|
| 129 |
+
return null
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
const startStr = normalizeDate(this.dateBounds.min)
|
| 133 |
+
const endStr = normalizeDate(this.dateBounds.max)
|
| 134 |
+
|
| 135 |
+
if (!startStr || !endStr) return []
|
| 136 |
+
|
| 137 |
+
// Create dates at midnight UTC to avoid timezone issues
|
| 138 |
+
const start = new Date(startStr + 'T00:00:00.000Z')
|
| 139 |
+
const end = new Date(endStr + 'T00:00:00.000Z')
|
| 140 |
const current = new Date(start)
|
| 141 |
+
|
| 142 |
+
// Include the end date by using <= comparison
|
| 143 |
while (current <= end) {
|
| 144 |
dates.push(new Date(current))
|
| 145 |
+
current.setUTCDate(current.getUTCDate() + 1)
|
| 146 |
}
|
| 147 |
+
|
| 148 |
+
// Debug log to verify date range
|
| 149 |
+
if (dates.length > 0) {
|
| 150 |
+
const firstDateStr = dates[0].toISOString().split('T')[0]
|
| 151 |
+
const lastDateStr = dates[dates.length - 1].toISOString().split('T')[0]
|
| 152 |
+
console.log(`[AgentFilters] allDates generated: ${dates.length} dates from ${firstDateStr} to ${lastDateStr}, expected max: ${endStr}`)
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
return dates
|
| 156 |
},
|
| 157 |
maxSliderValue() {
|
src/lib/dataService.js
CHANGED
|
@@ -455,12 +455,45 @@ class DataService {
|
|
| 455 |
}
|
| 456 |
}
|
| 457 |
|
| 458 |
-
// 3. 计算全局日期范围
|
| 459 |
const allDates = all.map(r => r && r.date).filter(Boolean).sort()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 460 |
this.dateBounds = {
|
| 461 |
-
min:
|
| 462 |
-
max:
|
| 463 |
}
|
|
|
|
|
|
|
| 464 |
|
| 465 |
// 4. 按 agent_name|asset|model 分组去重
|
| 466 |
const keyToRow = new Map()
|
|
|
|
| 455 |
}
|
| 456 |
}
|
| 457 |
|
| 458 |
+
// 3. 计算全局日期范围 - 确保使用最新的日期
|
| 459 |
const allDates = all.map(r => r && r.date).filter(Boolean).sort()
|
| 460 |
+
const calculatedMin = allDates.length ? allDates[0] : null
|
| 461 |
+
const calculatedMax = allDates.length ? allDates[allDates.length - 1] : null
|
| 462 |
+
|
| 463 |
+
// Also verify with DB to ensure we have the latest max date
|
| 464 |
+
let dbMaxDate = null
|
| 465 |
+
try {
|
| 466 |
+
const { data: maxDateData, error: maxDateError } = await supabase
|
| 467 |
+
.from('trading_decisions')
|
| 468 |
+
.select('date')
|
| 469 |
+
.order('date', { ascending: false })
|
| 470 |
+
.limit(1)
|
| 471 |
+
if (!maxDateError && maxDateData && maxDateData.length > 0) {
|
| 472 |
+
dbMaxDate = maxDateData[0].date
|
| 473 |
+
}
|
| 474 |
+
} catch (e) {
|
| 475 |
+
console.error('[DataService] Error getting DB max date for dateBounds:', e)
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
// Use DB max date if it's newer than calculated max
|
| 479 |
+
let finalMax = calculatedMax
|
| 480 |
+
if (dbMaxDate && calculatedMax) {
|
| 481 |
+
const dbMaxDateStr = typeof dbMaxDate === 'string' ? dbMaxDate.split('T')[0] : dbMaxDate
|
| 482 |
+
const calculatedMaxStr = typeof calculatedMax === 'string' ? calculatedMax.split('T')[0] : calculatedMax
|
| 483 |
+
if (dbMaxDateStr > calculatedMaxStr) {
|
| 484 |
+
console.warn(`[DataService] dateBounds: DB max date ${dbMaxDateStr} is newer than calculated ${calculatedMaxStr}, using DB date`)
|
| 485 |
+
finalMax = dbMaxDate
|
| 486 |
+
}
|
| 487 |
+
} else if (dbMaxDate && !calculatedMax) {
|
| 488 |
+
finalMax = dbMaxDate
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
this.dateBounds = {
|
| 492 |
+
min: calculatedMin ? new Date(calculatedMin) : null,
|
| 493 |
+
max: finalMax ? new Date(finalMax) : null
|
| 494 |
}
|
| 495 |
+
|
| 496 |
+
console.log(`[DataService] dateBounds set: min = ${this.dateBounds.min?.toISOString().split('T')[0]}, max = ${this.dateBounds.max?.toISOString().split('T')[0]}`)
|
| 497 |
|
| 498 |
// 4. 按 agent_name|asset|model 分组去重
|
| 499 |
const keyToRow = new Map()
|