提取IP页面地区筛选数据更新为调用后端接口返回
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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' && (
|
||||
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={cities.options}
|
||||
options={options}
|
||||
value={[prov || '', city || '']}
|
||||
onChange={(value) => {
|
||||
setValue('prov', value[0])
|
||||
setValue('city', value[1])
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user