修复分配状态里的时间筛选查询问题

This commit is contained in:
wmp
2025-09-22 10:31:49 +08:00
parent 4f3671c8a6
commit 826d8fc4c3
3 changed files with 55 additions and 78 deletions

View File

@@ -23,7 +23,7 @@ export async function GET(request: NextRequest) {
case 'city_node_count':
return await getCityNodeCount()
case 'allocation_status':
return await getAllocationStatus()
return await getAllocationStatus(request)
case 'edge_nodes':
return await getEdgeNodes(request)
default:
@@ -105,42 +105,47 @@ async function getCityNodeCount() {
}
// 城市分配状态
async function getAllocationStatus() {
async function getAllocationStatus(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const hours = searchParams.get('hours') || '24'
const hoursNum = parseInt(hours) || 24
// 使用参数化查询防止SQL注入
const result = await prisma.$queryRaw`
SELECT
SELECT
city,
c1.count AS count,
c2.assigned AS assigned
FROM
cityhash
LEFT JOIN (
SELECT
city_id,
COUNT(*) AS count
FROM
edge
WHERE
active = 1
GROUP BY
city_id
SELECT
city_id,
COUNT(*) AS count
FROM
edge
WHERE
active = 1
GROUP BY
city_id
) c1 ON c1.city_id = cityhash.id
LEFT JOIN (
SELECT
city AS city_id,
COUNT(*) AS assigned
FROM
\`change\`
WHERE
time > NOW() - INTERVAL 1 DAY
GROUP BY
city
SELECT
city AS city_id,
COUNT(*) AS assigned
FROM
\`change\`
WHERE
time > NOW() - INTERVAL ${hoursNum} HOUR
GROUP BY
city
) c2 ON c2.city_id = cityhash.id
WHERE
cityhash.macaddr IS NOT NULL;
`
`
return NextResponse.json(safeSerialize(result))
} catch (error) {
console.error('Allocation status query error:', error)
const errorMessage = error instanceof Error ? error.message : 'Unknown error'

View File

@@ -23,49 +23,19 @@ export default function AllocationStatus({ detailed = false }: { detailed?: bool
const [data, setData] = useState<AllocationStatus[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const [timeFilter, setTimeFilter] = useState('24h') // 默认24小时
const [customTime, setCustomTime] = useState('')
const [timeFilter, setTimeFilter] = useState('24') // 默认24小时
const [customHours, setCustomHours] = useState('')
// 生成时间筛选条件
const getTimeCondition = useCallback(() => {
if (timeFilter === 'custom' && customTime) {
// 将datetime-local格式转换为SQL datetime格式
return customTime.replace('T', ' ') + ':00'
}
const now = new Date()
let filterDate
// 获取时间参数(小时数)
const getTimeHours = useCallback(() => {
switch(timeFilter) {
case '1h':
filterDate = new Date(now.getTime() - 60 * 60 * 1000)
break
case '6h':
filterDate = new Date(now.getTime() - 6 * 60 * 60 * 1000)
break
case '12h':
filterDate = new Date(now.getTime() - 12 * 60 * 60 * 1000)
break
case '24h':
filterDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
break
case '7d':
filterDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)
break
case 'fixed':
return '2025-08-24 11:27:00'
case 'custom':
if (customTime) {
return customTime
}
// 如果自定义时间为空默认使用24小时
filterDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
break
default:
filterDate = new Date(now.getTime() - 24 * 60 * 60 * 1000)
if (timeFilter === 'custom' && customHours) {
const hours = parseInt(customHours)
return isNaN(hours) ? 24 : Math.max(1, hours) // 默认24小时最少1小时
}
return filterDate.toISOString().slice(0, 19).replace('T', ' ')
}, [timeFilter, customTime])
return parseInt(timeFilter) || 24 // 默认24小时
}, [timeFilter, customHours])
// 计算超额量
const calculateOverage = (assigned: number, count: number) => {
@@ -78,8 +48,9 @@ export default function AllocationStatus({ detailed = false }: { detailed?: bool
setError(null)
setLoading(true)
const timeCondition = getTimeCondition()
const response = await fetch(`/api/stats?type=allocation_status&time=${encodeURIComponent(timeCondition)}`)
const hours = getTimeHours()
const response = await fetch(`/api/stats?type=allocation_status&hours=${hours}`)
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
@@ -101,7 +72,7 @@ export default function AllocationStatus({ detailed = false }: { detailed?: bool
} finally {
setLoading(false)
}
}, [getTimeCondition])
}, [getTimeHours])
useEffect(() => {
fetchData()
@@ -124,23 +95,26 @@ export default function AllocationStatus({ detailed = false }: { detailed?: bool
onChange={(e) => setTimeFilter(e.target.value)}
className="border rounded p-2"
>
<option value="1h">1</option>
<option value="6h">6</option>
<option value="12h">12</option>
<option value="24h">24</option>
<option value="7d">7</option>
<option value="custom"></option>
<option value="1">1</option>
<option value="6">6</option>
<option value="12">12</option>
<option value="24">24</option>
<option value="168">7</option>
<option value="custom"></option>
</select>
{timeFilter === 'custom' && (
<div className="flex items-center gap-2">
<input
type="datetime-local"
value={customTime}
onChange={(e) => setCustomTime(e.target.value)}
className="border rounded p-2"
type="number"
min="1"
max="720"
value={customHours}
onChange={(e) => setCustomHours(e.target.value)}
placeholder="输入小时数"
className="border rounded p-2 w-24"
/>
<small>格式: YYYY-MM-DDTHH:MM</small>
<small> (1-720)</small>
</div>
)}
@@ -151,6 +125,7 @@ export default function AllocationStatus({ detailed = false }: { detailed?: bool
</button>
</div>
<div className='flex gap-6 overflow-hidden'>
<div className="flex flex-3 w-full">
<Table>

View File

@@ -127,9 +127,6 @@ function GatewayConfigContent() {
<h2 className="text-xl font-semibold text-gray-800"></h2>
<p className="text-sm text-gray-600 mt-1"></p>
</div>
<div className="text-sm text-gray-500">
: {new Date().toLocaleTimeString()}
</div>
</div>
{/* 查询表单 */}