diff --git a/localhost.session.sql b/localhost.session.sql deleted file mode 100644 index e69de29..0000000 diff --git a/src/actions/stats.ts b/src/actions/stats.ts index 008b155..8e35250 100644 --- a/src/actions/stats.ts +++ b/src/actions/stats.ts @@ -1,7 +1,7 @@ 'use server' import { Page, Res } from '@/lib/api' -import drizzle, { change, cityhash, count, desc, edge, eq, gateway, is, sql, token } from '@/lib/drizzle' +import drizzle, { and, change, cityhash, count, desc, edge, eq, gateway, is, sql, token } from '@/lib/drizzle' export type AllocationStatus = { city: string @@ -134,7 +134,13 @@ export async function getGatewayConfig(page?: number, filters?: { .from(gateway) .leftJoin(cityhash, eq(cityhash.hash, gateway.cityhash)) .leftJoin(edge, eq(edge.macaddr, gateway.edge)) - .where(filters?.mac ? eq(gateway.macaddr, filters?.mac) : undefined) + .where(filters ? and( + filters.mac ? eq(gateway.macaddr, filters.mac) : undefined, + filters.public ? eq(edge.public, filters.public) : undefined, + filters.city ? eq(cityhash.city, filters.city) : undefined, + filters.user ? eq(gateway.user, filters.user) : undefined, + filters.inner_ip ? eq(gateway.network, filters.inner_ip) : undefined, + ) : undefined) .orderBy(sql`inet_aton(gateway.inner_ip)`) .offset((page - 1) * 250) .limit(250), @@ -210,7 +216,7 @@ export async function getCityNodeCount() { export type Edge = { id: number macaddr: string - city: string + city: string | null public: string isp: string single: number | boolean @@ -220,19 +226,49 @@ export type Edge = { } // 获取节点信息 -export async function getEdgeNodes(page: number, size: number, props?: { +export async function getEdgeNodes(page: number, size: number, filters?: { macaddr?: string public?: string city?: string isp?: string -}, -) { +}): Promise>> { try { - const offset = Math.max(0, (page - 1)) * size - const limit = Math.min(100, Math.max(10, size)) + page = Math.max(1, page) + size = Math.min(100, Math.max(10, size)) - const [total, data] = await Promise.all([ - drizzle.$count(edge, eq(edge.active, 1)), + const condition = and( + eq(edge.active, 1), + filters?.macaddr ? eq(edge.macaddr, filters.macaddr) : undefined, + filters?.public ? eq(edge.public, filters.public) : undefined, + filters?.city ? eq(cityhash.city, filters.city) : undefined, + filters?.isp ? eq(edge.isp, filters.isp) : undefined, + ) + + console.log(drizzle + .select({ + id: edge.id, + macaddr: edge.macaddr, + city: cityhash.city, + public: edge.public, + isp: edge.isp, + single: edge.single, + sole: edge.sole, + arch: edge.arch, + online: edge.online, + }) + .from(edge) + .leftJoin(cityhash, eq(cityhash.id, edge.cityId)) + .where(condition) + .orderBy(edge.id) + .offset(page * size - size) + .limit(size).toSQL().sql) + + const [total, items] = await Promise.all([ + drizzle + .select({ value: count() }) + .from(edge) + .leftJoin(cityhash, eq(cityhash.id, edge.cityId)) + .where(condition), drizzle .select({ id: edge.id, @@ -247,25 +283,26 @@ export async function getEdgeNodes(page: number, size: number, props?: { }) .from(edge) .leftJoin(cityhash, eq(cityhash.id, edge.cityId)) - .where(eq(edge.active, 1)) + .where(condition) .orderBy(edge.id) - .offset(offset) - .limit(limit), - + .offset(page * size - size) + .limit(size), ]) return { - data, - totalCount: total, - currentPage: Math.floor(offset / limit) + 1, - totalPages: Math.ceil(total / limit), + success: true, + data: { + total: total[0].value, + page, + size, + items, + }, } } catch (error) { console.error('Edge nodes query error:', error) return { success: false, - data: [], error: '查询边缘节点失败', } } diff --git a/src/app/dashboard/components/edge.tsx b/src/app/dashboard/components/edge.tsx index 21e6125..9ef961b 100644 --- a/src/app/dashboard/components/edge.tsx +++ b/src/app/dashboard/components/edge.tsx @@ -8,16 +8,16 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useForm } from 'react-hook-form' import { z } from 'zod' import { Button } from '@/components/ui/button' -import { Form, FormField, FormItem, FormLabel } from '@/components/ui/form' +import { Form, FormControl, FormField, FormItem, FormLabel } from '@/components/ui/form' import { Input } from '@/components/ui/input' import { cn } from '@/lib/utils' // 定义表单验证规则 const filterSchema = z.object({ - macaddr: z.string().optional(), - public: z.string().optional(), - city: z.string().optional(), - isp: z.string().optional(), + macaddr: z.string(), + public: z.string(), + city: z.string(), + isp: z.string(), }) type FilterFormValues = z.infer @@ -28,9 +28,9 @@ export default function Edge() { const [error, setError] = useState(null) // 分页状态 - const [currentPage, setCurrentPage] = useState(1) - const [itemsPerPage, setItemsPerPage] = useState(100) // 默认100条 - const [totalItems, setTotalItems] = useState(0) + const [page, setPage] = useState(1) + const [size, setSize] = useState(100) + const [total, setTotal] = useState(0) // 初始化表单 const form = useForm({ @@ -43,57 +43,53 @@ export default function Edge() { }, }) - useEffect(() => { - fetchData({}) - }, [currentPage, itemsPerPage]) + const fetchData = async (page: number, size: number) => { + const filters = form.getValues() - const fetchData = async (val: { - macaddr?: string - public?: string - city?: string - isp?: string - }) => { + setLoading(true) try { + const result = await getEdgeNodes(page, size, filters) + if (!result.success) { + throw new Error(result.error) + } + + const data = result.data + console.log(data) + setData(data.items) + setTotal(data.total) + setPage(data.page) + setSize(data.size) + setError(null) - setLoading(true) - - // 计算偏移量 - const offset = (currentPage - 1) * itemsPerPage - const result = await getEdgeNodes(offset, itemsPerPage, val) - const validatedData = (result.data).map(item => ({ - id: item.id, - macaddr: item.macaddr || '', - city: item.city || '', - public: item.public || '', - isp: item.isp || '', - single: item.single, - sole: item.sole, - arch: item.arch, - online: item.online, - })) - - setData(validatedData) - setTotalItems(result.totalCount || 0) } catch (error) { - console.error('Failed to fetch edge nodes:', error) - setError(error instanceof Error ? error.message : '获取边缘节点数据失败') + setError('获取边缘节点数据失败' + (error instanceof Error ? `: ${error.message}` : '')) } finally { setLoading(false) } } - const onSubmit = async (values: FilterFormValues) => { - setCurrentPage(1) - const filters = { - macaddr: values.macaddr || undefined, - public: values.public || undefined, - city: values.city || undefined, - isp: values.isp || undefined, - } + const onSubmit = () => { + fetchData(page, size) + } - fetchData(filters) + const onReset = () => { + form.reset() + fetchData(page, size) + } + + // 处理页码变化 + const handlePageChange = (page: number) => { + setPage(page) + fetchData(page, size) + } + + // 处理每页显示数量变化 + const handleSizeChange = (size: number) => { + setPage(1) + setSize(size) + fetchData(1, size) } // 多IP节点格式化 @@ -165,32 +161,9 @@ export default function Edge() { return `${Math.floor(seconds / 86400)}天` } - // 处理页码变化 - const handlePageChange = (page: number) => { - setCurrentPage(page) - const formValues = form.getValues() - const filters = { - macaddr: formValues.macaddr || '', - public: formValues.public || '', - city: formValues.city || '', - isp: formValues.isp || '', - } - fetchData(filters) - } - - // 处理每页显示数量变化 - const handleSizeChange = (size: number) => { - setItemsPerPage(size) - setCurrentPage(1) - const formValues = form.getValues() - const filters = { - macaddr: formValues.macaddr || '', - public: formValues.public || '', - city: formValues.city || '', - isp: formValues.isp || '', - } - fetchData(filters) - } + useEffect(() => { + fetchData(page, size) + }, []) if (loading) return (
@@ -204,7 +177,7 @@ export default function Edge() {

节点列表

{error}
-
@@ -333,12 +315,11 @@ export default function Edge() { {/* 分页 */} )}