修复 drizzle 编译问题 & 简化页面结构与排序功能
This commit is contained in:
@@ -62,7 +62,7 @@ export async function getAllocationStatus(hours: number = 24) {
|
||||
export type GatewayInfo = {
|
||||
macaddr: string
|
||||
inner_ip: string
|
||||
setid: string
|
||||
setid: number
|
||||
enable: number
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export async function getGatewayInfo() {
|
||||
enable: token.enable,
|
||||
})
|
||||
.from(token)
|
||||
.orderBy(token.macaddr)
|
||||
.orderBy(sql`cast(regexp_replace(token.inner_ip, '192.168.50.', '') as unsigned)`)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -128,7 +128,7 @@ export async function getGatewayConfig(page?: number, mac?: string): Promise<Res
|
||||
.leftJoin(cityhash, eq(cityhash.hash, gateway.cityhash))
|
||||
.leftJoin(edge, eq(edge.macaddr, gateway.edge))
|
||||
.where(mac ? eq(gateway.macaddr, mac) : undefined)
|
||||
.orderBy(gateway.macaddr, sql`cast(regexp_replace(gateway.network, '172.30.168.', '') as unsigned)`)
|
||||
.orderBy(sql`inet_aton(gateway.inner_ip)`)
|
||||
.offset((page - 1) * 250)
|
||||
.limit(250),
|
||||
])
|
||||
@@ -156,8 +156,8 @@ export type CityNode = {
|
||||
city: string
|
||||
count: number
|
||||
hash: string
|
||||
label: string
|
||||
offset: string
|
||||
label: string | null
|
||||
offset: number
|
||||
}
|
||||
|
||||
// 城市节点数量分布
|
||||
|
||||
@@ -137,13 +137,13 @@ function GatewayConfigContent() {
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="bg-gray-50">
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">端口</TableHead>
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">线路</TableHead>
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">城市</TableHead>
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">节点MAC</TableHead>
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">节点IP</TableHead>
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">配置更新</TableHead>
|
||||
<TableHead className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">在用状态</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">端口</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">线路</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">城市</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">节点MAC</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">节点IP</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">配置更新</TableHead>
|
||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider">在用状态</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
|
||||
@@ -16,16 +16,6 @@ const filterSchema = z.object({
|
||||
|
||||
type FilterSchema = z.infer<typeof filterSchema>
|
||||
|
||||
// IP地址排序函数
|
||||
const sortByIpAddress = (a: string, b: string): number => {
|
||||
const ipToNumber = (ip: string): number => {
|
||||
const parts = ip.split('.').map(part => parseInt(part, 10))
|
||||
return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3]
|
||||
}
|
||||
|
||||
return ipToNumber(a) - ipToNumber(b)
|
||||
}
|
||||
|
||||
export default function Gatewayinfo() {
|
||||
const [data, setData] = useState<GatewayInfo[]>([])
|
||||
const [filteredData, setFilteredData] = useState<GatewayInfo[]>([])
|
||||
@@ -71,11 +61,8 @@ export default function Gatewayinfo() {
|
||||
setError('')
|
||||
const result = await getGatewayInfo()
|
||||
|
||||
const sortedData = result.data.sort((a: GatewayInfo, b: GatewayInfo) =>
|
||||
sortByIpAddress(a.inner_ip, b.inner_ip),
|
||||
)
|
||||
setData(sortedData)
|
||||
setFilteredData(sortedData) // 初始化时设置filteredData
|
||||
setData(result.data)
|
||||
setFilteredData(result.data) // 初始化时设置filteredData
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to fetch gateway info:', error)
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import 'dotenv/config'
|
||||
import { drizzle as client } from 'drizzle-orm/mysql2'
|
||||
import { drizzle as client, MySql2Database } from 'drizzle-orm/mysql2'
|
||||
import * as schema from './schema'
|
||||
|
||||
declare global {
|
||||
var drizzle: ReturnType<typeof client<typeof schema>> | undefined
|
||||
var drizzle: MySql2Database<typeof schema> | undefined
|
||||
}
|
||||
|
||||
const { DATABASE_URL } = process.env
|
||||
if (!DATABASE_URL) {
|
||||
throw new Error('DATABASE_URL is not set')
|
||||
}
|
||||
|
||||
const drizzle = global.drizzle || client(DATABASE_URL, { mode: 'default', schema })
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
global.drizzle = drizzle
|
||||
}
|
||||
const drizzle = new Proxy({} as MySql2Database<typeof schema>, {
|
||||
get(_, prop) {
|
||||
if (!global.drizzle && process.env.NODE_ENV !== 'production') {
|
||||
global.drizzle = client(process.env.DATABASE_URL!, { mode: 'default', schema })
|
||||
}
|
||||
return global.drizzle![prop as keyof typeof global.drizzle]
|
||||
},
|
||||
})
|
||||
|
||||
export default drizzle
|
||||
export * from './schema'
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import 'server-only'
|
||||
import { createClient } from 'redis'
|
||||
|
||||
const client = createClient({
|
||||
url: process.env.REDIS_URL,
|
||||
})
|
||||
declare global {
|
||||
var redis: ReturnType<typeof createClient> | undefined
|
||||
}
|
||||
|
||||
const client = global.redis || createClient({ url: process.env.REDIS_URL })
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
global.redis = client
|
||||
}
|
||||
|
||||
const redis = await client.connect()
|
||||
export default redis
|
||||
|
||||
Reference in New Issue
Block a user