提取IP页面地区筛选数据更新为调用后端接口返回
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lanhu-web",
|
"name": "lanhu-web",
|
||||||
"version": "1.12.0",
|
"version": "1.13.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev -H 0.0.0.0 --turbopack",
|
"dev": "next dev -H 0.0.0.0 --turbopack",
|
||||||
|
|||||||
@@ -29,23 +29,23 @@ export async function createChannels(params: {
|
|||||||
protocol: number
|
protocol: number
|
||||||
auth_type: number
|
auth_type: number
|
||||||
count: number
|
count: number
|
||||||
prov?: string
|
// prov?: string
|
||||||
city?: string
|
area_id?: number
|
||||||
isp?: number
|
isp?: number
|
||||||
host_format?: number
|
host_format?: number
|
||||||
}) {
|
}) {
|
||||||
return callPublic<CreateChannelsResp[]>('/api/channel/create', params)
|
return callPublic<CreateChannelsResp[]>('/api/channel/create', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createChannelsV2(params: {
|
export async function createChannelsV3(params: {
|
||||||
resource_no: string
|
resource_no: string
|
||||||
protocol: number
|
protocol: number
|
||||||
auth_type: number
|
auth_type: number
|
||||||
count: number
|
count: number
|
||||||
prov?: string
|
// prov?: string
|
||||||
city?: string
|
area_id?: number
|
||||||
isp?: number
|
isp?: number
|
||||||
host_format?: number
|
host_format?: number
|
||||||
}) {
|
}) {
|
||||||
return callPublic<CreateChannelsResp[]>('/api/channel/create/v2', params)
|
return callPublic<CreateChannelsResp[]>('/api/channel/create/v3', params)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,3 +110,7 @@ export async function updateCheckip(props: {
|
|||||||
}) {
|
}) {
|
||||||
return callByUser('/api/resource/update/checkip', props)
|
return callByUser('/api/resource/update/checkip', props)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAreaList(props: {}) {
|
||||||
|
return callByUser('/api/area/list', props)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import {NextRequest, NextResponse} from 'next/server'
|
import {NextRequest, NextResponse} from 'next/server'
|
||||||
import {createChannels, createChannelsV2} from '@/actions/channel'
|
import {createChannels, createChannelsV3} from '@/actions/channel'
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
const params = req.nextUrl.searchParams
|
const params = req.nextUrl.searchParams
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resourceParam = params.get('i')
|
const resourceParam = params.get('i')
|
||||||
|
|
||||||
@@ -21,20 +22,33 @@ export async function GET(req: NextRequest) {
|
|||||||
if (!count) {
|
if (!count) {
|
||||||
throw new Error('需要指定通道创建数量')
|
throw new Error('需要指定通道创建数量')
|
||||||
}
|
}
|
||||||
const prov = params.get('a') || undefined
|
// const prov = params.get('a') || undefined
|
||||||
const city = params.get('b') || undefined
|
const area_id = params.get('b') || undefined
|
||||||
const isp = params.get('s') || undefined
|
const isp = params.get('s') || undefined
|
||||||
const hostFormat = params.get('rh') || 'domain'
|
const hostFormat = params.get('rh') || 'domain'
|
||||||
const isNumeric = /^\d+$/.test(resourceParam)
|
const isNumeric = /^\d+$/.test(resourceParam)
|
||||||
|
|
||||||
let result
|
let result
|
||||||
if (!isNumeric) {
|
if (!isNumeric) {
|
||||||
result = await createChannelsV2({
|
console.log(area_id, 'area_id', params.get('b'), 'params.get')
|
||||||
|
|
||||||
|
result = await createChannelsV3({
|
||||||
resource_no: resourceParam,
|
resource_no: resourceParam,
|
||||||
auth_type: Number(auth_type),
|
auth_type: Number(auth_type),
|
||||||
protocol: Number(protocol),
|
protocol: Number(protocol),
|
||||||
count: Number(count),
|
count: Number(count),
|
||||||
prov,
|
// prov,
|
||||||
city,
|
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),
|
isp: Number(isp),
|
||||||
host_format: hostFormat === 'domain' ? 1 : 2,
|
host_format: hostFormat === 'domain' ? 1 : 2,
|
||||||
})
|
})
|
||||||
@@ -45,8 +59,8 @@ export async function GET(req: NextRequest) {
|
|||||||
auth_type: Number(auth_type),
|
auth_type: Number(auth_type),
|
||||||
protocol: Number(protocol),
|
protocol: Number(protocol),
|
||||||
count: Number(count),
|
count: Number(count),
|
||||||
prov,
|
// prov,
|
||||||
city,
|
area_id: Number(area_id),
|
||||||
isp: Number(isp),
|
isp: Number(isp),
|
||||||
host_format: hostFormat === 'domain' ? 1 : 2,
|
host_format: hostFormat === 'domain' ? 1 : 2,
|
||||||
})
|
})
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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 {ArrowRight, Box, CircleAlert, CopyIcon, ExternalLinkIcon, LinkIcon, Loader, Plus, Timer} from 'lucide-react'
|
||||||
import {memo, ReactNode, Suspense, use, useEffect, useRef, useState} from 'react'
|
import {memo, ReactNode, Suspense, use, useEffect, useRef, useState} from 'react'
|
||||||
import {useStatus} from '@/lib/states'
|
import {useStatus} from '@/lib/states'
|
||||||
import {allResource} from '@/actions/resource'
|
import {allResource, getAreaList} from '@/actions/resource'
|
||||||
import {Resource} from '@/lib/models'
|
import {Resource} from '@/lib/models'
|
||||||
import {format, intlFormatDistance} from 'date-fns'
|
import {format, intlFormatDistance} from 'date-fns'
|
||||||
import {toast} from 'sonner'
|
import {toast} from 'sonner'
|
||||||
import {merge} from '@/lib/utils'
|
import {merge} from '@/lib/utils'
|
||||||
import {Combobox} from '@/components/ui/combobox'
|
import {Combobox} from '@/components/ui/combobox'
|
||||||
import cities from './_assets/cities.json'
|
|
||||||
import ExtractDocs from '@/app/(home)/docs/(product)/api-docs/page.md'
|
import ExtractDocs from '@/app/(home)/docs/(product)/api-docs/page.md'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import {useProfileStore} from '@/components/stores/profile'
|
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() {
|
function SelectRegion() {
|
||||||
const {control, setValue} = useFormContext<Schema>()
|
const {control, setValue} = useFormContext<Schema>()
|
||||||
const regionType = useWatch({control, name: 'regionType'})
|
const regionType = useWatch({control, name: 'regionType'})
|
||||||
const prov = useWatch({control, name: 'prov'})
|
const prov = useWatch({control, name: 'prov'})
|
||||||
const city = useWatch({control, name: 'city'})
|
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 (
|
return (
|
||||||
<div className="flex flex-col gap-4 md:max-w-[calc(160px*2+1rem)]">
|
<div className="flex flex-col gap-4 md:max-w-[calc(160px*2+1rem)]">
|
||||||
@@ -531,15 +581,22 @@ function SelectRegion() {
|
|||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
{regionType === 'specific' && (
|
{regionType === 'specific' && (
|
||||||
<Combobox
|
loading ? (
|
||||||
placeholder="请选择地区"
|
<div className="flex gap-2 items-center">
|
||||||
options={cities.options}
|
<Loader className="animate-spin" size={16}/>
|
||||||
value={[prov || '', city || '']}
|
<span className="text-sm text-weak">加载地区数据中...</span>
|
||||||
onChange={(value) => {
|
</div>
|
||||||
setValue('prov', value[0])
|
) : (
|
||||||
setValue('city', value[1])
|
<Combobox
|
||||||
}}
|
placeholder="请选择地区"
|
||||||
/>
|
options={options}
|
||||||
|
value={[prov || '', city || '']}
|
||||||
|
onChange={(value) => {
|
||||||
|
setValue('prov', value[0] || '')
|
||||||
|
setValue('city', value[1] || '')
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -655,12 +712,13 @@ function ApplyLink() {
|
|||||||
|
|
||||||
function link(values: Schema) {
|
function link(values: Schema) {
|
||||||
const {resource, prov, city, isp, proto, authType, distinct, format: formatType, hostFormat, separator, breaker, count} = values
|
const {resource, prov, city, isp, proto, authType, distinct, format: formatType, hostFormat, separator, breaker, count} = values
|
||||||
|
console.log(values, 'values')
|
||||||
|
|
||||||
const sp = new URLSearchParams()
|
const sp = new URLSearchParams()
|
||||||
if (resource) sp.set('i', String(resource))
|
if (resource) sp.set('i', String(resource))
|
||||||
if (authType) sp.set('t', authType)
|
if (authType) sp.set('t', authType)
|
||||||
if (proto != 'all') sp.set('x', proto)
|
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 (city) sp.set('b', city)
|
||||||
|
|
||||||
if (isp != 'all') sp.set('s', isp)
|
if (isp != 'all') sp.set('s', isp)
|
||||||
|
|||||||
Reference in New Issue
Block a user