提取IP页面地区筛选数据更新为调用后端接口返回

This commit is contained in:
Eamon-meng
2026-06-12 16:42:05 +08:00
parent 7947fc48a2
commit 49725fd38e
6 changed files with 103 additions and 1697 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "lanhu-web",
"version": "1.12.0",
"version": "1.13.0",
"private": true,
"scripts": {
"dev": "next dev -H 0.0.0.0 --turbopack",

View File

@@ -29,23 +29,23 @@ export async function createChannels(params: {
protocol: number
auth_type: number
count: number
prov?: string
city?: string
// prov?: string
area_id?: number
isp?: number
host_format?: number
}) {
return callPublic<CreateChannelsResp[]>('/api/channel/create', params)
}
export async function createChannelsV2(params: {
export async function createChannelsV3(params: {
resource_no: string
protocol: number
auth_type: number
count: number
prov?: string
city?: string
// prov?: string
area_id?: number
isp?: number
host_format?: number
}) {
return callPublic<CreateChannelsResp[]>('/api/channel/create/v2', params)
return callPublic<CreateChannelsResp[]>('/api/channel/create/v3', params)
}

View File

@@ -110,3 +110,7 @@ export async function updateCheckip(props: {
}) {
return callByUser('/api/resource/update/checkip', props)
}
export async function getAreaList(props: {}) {
return callByUser('/api/area/list', props)
}

View File

@@ -1,8 +1,9 @@
import {NextRequest, NextResponse} from 'next/server'
import {createChannels, createChannelsV2} from '@/actions/channel'
import {createChannels, createChannelsV3} from '@/actions/channel'
export async function GET(req: NextRequest) {
const params = req.nextUrl.searchParams
try {
const resourceParam = params.get('i')
@@ -21,20 +22,33 @@ export async function GET(req: NextRequest) {
if (!count) {
throw new Error('需要指定通道创建数量')
}
const prov = params.get('a') || undefined
const city = params.get('b') || undefined
// const prov = params.get('a') || undefined
const area_id = params.get('b') || undefined
const isp = params.get('s') || undefined
const hostFormat = params.get('rh') || 'domain'
const isNumeric = /^\d+$/.test(resourceParam)
let result
if (!isNumeric) {
result = await createChannelsV2({
console.log(area_id, 'area_id', params.get('b'), 'params.get')
result = await createChannelsV3({
resource_no: resourceParam,
auth_type: Number(auth_type),
protocol: Number(protocol),
count: Number(count),
prov,
city,
// prov,
area_id: Number(area_id),
isp: Number(isp),
host_format: hostFormat === 'domain' ? 1 : 2,
})
console.log({
resource_no: resourceParam,
auth_type: Number(auth_type),
protocol: Number(protocol),
count: Number(count),
// prov,
area_id: Number(area_id),
isp: Number(isp),
host_format: hostFormat === 'domain' ? 1 : 2,
})
@@ -45,8 +59,8 @@ export async function GET(req: NextRequest) {
auth_type: Number(auth_type),
protocol: Number(protocol),
count: Number(count),
prov,
city,
// prov,
area_id: Number(area_id),
isp: Number(isp),
host_format: hostFormat === 'domain' ? 1 : 2,
})

File diff suppressed because it is too large Load Diff

View File

@@ -11,13 +11,12 @@ import {Alert, AlertTitle} from '@/components/ui/alert'
import {ArrowRight, Box, CircleAlert, CopyIcon, ExternalLinkIcon, LinkIcon, Loader, Plus, Timer} from 'lucide-react'
import {memo, ReactNode, Suspense, use, useEffect, useRef, useState} from 'react'
import {useStatus} from '@/lib/states'
import {allResource} from '@/actions/resource'
import {allResource, getAreaList} from '@/actions/resource'
import {Resource} from '@/lib/models'
import {format, intlFormatDistance} from 'date-fns'
import {toast} from 'sonner'
import {merge} from '@/lib/utils'
import {Combobox} from '@/components/ui/combobox'
import cities from './_assets/cities.json'
import ExtractDocs from '@/app/(home)/docs/(product)/api-docs/page.md'
import Link from 'next/link'
import {useProfileStore} from '@/components/stores/profile'
@@ -497,11 +496,62 @@ function SelectResource() {
)
}
type AreaItem = {
id: number
parent_id: number
level: number
name: string
created_at: string
updated_at: string
}
function AreaTree(flatList: AreaItem[]) {
const provinces = flatList.filter(item => item.level === 1)
const cities = flatList.filter(item => item.level === 2)
return provinces.map(prov => ({
value: String(prov.id),
label: prov.name,
children: cities
.filter(city => city.parent_id === prov.id)
.map(city => ({
value: String(city.id),
label: city.name,
})),
}))
}
function SelectRegion() {
const {control, setValue} = useFormContext<Schema>()
const regionType = useWatch({control, name: 'regionType'})
const prov = useWatch({control, name: 'prov'})
const city = useWatch({control, name: 'city'})
const [options, setOptions] = useState<ReturnType<typeof AreaTree>>([])
const [loading, setLoading] = useState(false)
useEffect(() => {
if (regionType === 'specific') {
const fetchData = async () => {
setLoading(true)
try {
const req = await getAreaList({})
console.log(req, 'req')
if (req.success && req.data) {
setOptions(AreaTree(req.data))
}
}
catch (error) {
toast.error('无法选择区域')
}
finally {
setLoading(false)
}
}
fetchData()
}
}, [regionType])
return (
<div className="flex flex-col gap-4 md:max-w-[calc(160px*2+1rem)]">
@@ -531,15 +581,22 @@ function SelectRegion() {
</FormField>
{regionType === 'specific' && (
<Combobox
placeholder="请选择地区"
options={cities.options}
value={[prov || '', city || '']}
onChange={(value) => {
setValue('prov', value[0])
setValue('city', value[1])
}}
/>
loading ? (
<div className="flex gap-2 items-center">
<Loader className="animate-spin" size={16}/>
<span className="text-sm text-weak">...</span>
</div>
) : (
<Combobox
placeholder="请选择地区"
options={options}
value={[prov || '', city || '']}
onChange={(value) => {
setValue('prov', value[0] || '')
setValue('city', value[1] || '')
}}
/>
)
)}
</div>
)
@@ -655,12 +712,13 @@ function ApplyLink() {
function link(values: Schema) {
const {resource, prov, city, isp, proto, authType, distinct, format: formatType, hostFormat, separator, breaker, count} = values
console.log(values, 'values')
const sp = new URLSearchParams()
if (resource) sp.set('i', String(resource))
if (authType) sp.set('t', authType)
if (proto != 'all') sp.set('x', proto)
if (prov) sp.set('a', prov)
if (prov) sp.set('b', prov)
if (city) sp.set('b', city)
if (isp != 'all') sp.set('s', isp)