96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select"
|
|
import { Label } from "@/components/ui/label"
|
|
import { Database } from "lucide-react"
|
|
import { getAvailableSources } from "@/lib/api"
|
|
import type { DataSourceInfo } from "@/lib/types"
|
|
|
|
interface DataSourceSelectorProps {
|
|
market: string
|
|
selectedSource: string
|
|
onSourceChange: (source: string) => void
|
|
disabled?: boolean
|
|
showLabel?: boolean
|
|
}
|
|
|
|
export function DataSourceSelector({
|
|
market,
|
|
selectedSource,
|
|
onSourceChange,
|
|
disabled = false,
|
|
showLabel = true
|
|
}: DataSourceSelectorProps) {
|
|
const [sources, setSources] = useState<DataSourceInfo[]>([])
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
useEffect(() => {
|
|
async function loadSources() {
|
|
if (!market) return
|
|
|
|
setLoading(true)
|
|
try {
|
|
const data = await getAvailableSources(market)
|
|
setSources(data.sources.filter(s => s.available))
|
|
|
|
// 如果当前选中的源不可用,自动选择第一个可用的
|
|
const availableSources = data.sources.filter(s => s.available)
|
|
if (availableSources.length > 0 && !availableSources.find(s => s.source === selectedSource)) {
|
|
onSourceChange(availableSources[0].source)
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to load data sources:", error)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
loadSources()
|
|
}, [market])
|
|
|
|
if (sources.length === 0) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
{showLabel && (
|
|
<div className="flex items-center gap-2">
|
|
<Database className="h-4 w-4 text-muted-foreground" />
|
|
<Label>数据源</Label>
|
|
</div>
|
|
)}
|
|
<Select
|
|
value={selectedSource}
|
|
onValueChange={onSourceChange}
|
|
disabled={disabled || loading}
|
|
>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="选择数据源" />
|
|
</SelectTrigger>
|
|
<SelectContent portal={false}>
|
|
{sources.map((source) => (
|
|
<SelectItem key={source.source} value={source.source}>
|
|
{source.source}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
{
|
|
sources.length === 1 && (
|
|
<p className="text-xs text-muted-foreground">
|
|
该市场仅支持 {sources[0].source} 数据源
|
|
</p>
|
|
)
|
|
}
|
|
</div >
|
|
)
|
|
}
|