| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- "use client"
- import {useState} from "react"
- import dynamic from "next/dynamic"
- import {Button, Card, Checkbox, Col, Input, Row, Select, Space, Tabs} from "antd"
- import {FullscreenOutlined, PlayCircleOutlined, SearchOutlined} from "@ant-design/icons"
- const MapView = dynamic(() => import("./MapView"), {
- ssr: false,
- loading: () => <div className="flex items-center justify-center h-full">地图加载中...</div>,
- })
- const { Option } = Select
- const { TabPane } = Tabs
- export default function VideoMonitoring() {
- const [selectedVideos, setSelectedVideos] = useState<string[]>([])
- const [viewMode, setViewMode] = useState<"1" | "4">("4")
- // 模拟视频数据
- const videoData = [
- {
- id: "V001",
- name: "人民路积水点监控",
- type: "积水点",
- location: "人民路与南京路交叉口",
- status: "online",
- associatedDevice: "LV002",
- },
- {
- id: "V002",
- name: "第一泵站监控",
- type: "泵站",
- location: "城东泵站",
- status: "online",
- associatedDevice: "PS001",
- },
- {
- id: "V003",
- name: "主干道管网监控",
- type: "管网",
- location: "淮海路主干管网",
- status: "online",
- associatedDevice: "FL001",
- },
- {
- id: "V004",
- name: "南京路积水点监控",
- type: "积水点",
- location: "南京路商业区",
- status: "offline",
- associatedDevice: "LV003",
- },
- ]
- const handleVideoSelect = (videoId: string, checked: boolean) => {
- if (checked) {
- setSelectedVideos([...selectedVideos, videoId])
- } else {
- setSelectedVideos(selectedVideos.filter((id) => id !== videoId))
- }
- }
- const renderVideoGrid = () => {
- const gridCols = viewMode === "1" ? 1 : viewMode === "4" ? 2 : 3
- const selectedVideoData = videoData.filter((video) => selectedVideos.includes(video.id))
- return (
- <div className={`grid grid-cols-${gridCols} gap-4 h-96`}>
- {selectedVideoData.slice(0, Number.parseInt(viewMode)).map((video) => (
- <Card
- key={video.id}
- title={video.name}
- size="small"
- className="h-full"
- extra={
- <Space>
- <Button size="small" icon={<PlayCircleOutlined />} />
- <Button size="small" icon={<FullscreenOutlined />} />
- </Space>
- }
- >
- <div className="bg-gray-800 h-full flex items-center justify-center text-white">
- {video.status === "online" ? (
- <div className="text-center">
- <PlayCircleOutlined className="text-4xl mb-2" />
- <div>视频监控画面</div>
- <div className="text-sm text-gray-300">{video.location}</div>
- </div>
- ) : (
- <div className="text-center text-gray-400">
- <div>设备离线</div>
- <div className="text-sm">{video.location}</div>
- </div>
- )}
- </div>
- </Card>
- ))}
- {/* 填充空白格子 */}
- {Array.from({ length: Number.parseInt(viewMode) - selectedVideoData.length }).map((_, index) => (
- <Card key={`empty-${index}`} className="h-full">
- <div className="bg-gray-100 h-full flex items-center justify-center text-gray-400">
- <div className="text-center">
- <div>请选择视频</div>
- </div>
- </div>
- </Card>
- ))}
- </div>
- )
- }
- return (
- <div className="space-y-6">
- <Tabs defaultActiveKey="batch-monitoring">
- <TabPane tab="视频批量监控" key="batch-monitoring">
- <Row gutter={[16, 16]}>
- <Col span={6}>
- <Card title="视频列表" className="h-full overflow-auto">
- <div className="mb-4">
- <Space direction="vertical" className="w-full">
- <Input placeholder="搜索视频" prefix={<SearchOutlined />} />
- <Select placeholder="视频类型" className="w-full">
- <Option value="waterlogging">积水点</Option>
- <Option value="pump">泵站</Option>
- <Option value="pipeline">管网</Option>
- </Select>
- </Space>
- </div>
- <div className="space-y-2">
- {videoData.map((video) => (
- <div key={video.id} className="flex items-center space-x-2 p-2 border rounded">
- <Checkbox
- checked={selectedVideos.includes(video.id)}
- onChange={(e) => handleVideoSelect(video.id, e.target.checked)}
- />
- <div className="flex-1">
- <div className="font-medium text-sm">{video.name}</div>
- <div className="text-xs text-gray-500">{video.location}</div>
- <div className="text-xs">
- <span
- className={`inline-block w-2 h-2 rounded-full mr-1 ${
- video.status === "online" ? "bg-green-500" : "bg-gray-400"
- }`}
- />
- {video.status === "online" ? "在线" : "离线"}
- </div>
- </div>
- </div>
- ))}
- </div>
- </Card>
- </Col>
- <Col span={18}>
- <Card
- title="视频监控"
- extra={
- <Space>
- <span>显示模式:</span>
- <Select value={viewMode} onChange={setViewMode} style={{ width: 80 }}>
- <Option value="1">1画面</Option>
- <Option value="4">4画面</Option>
- </Select>
- </Space>
- }
- >
- {renderVideoGrid()}
- </Card>
- </Col>
- </Row>
- </TabPane>
- <TabPane tab="视频地图" key="video-map">
- <Card title="监测视频 GIS " className="h-96">
- <MapView type="overview" />
- </Card>
- </TabPane>
- <TabPane tab="设备关联" key="device-association">
- <Card title="设备关联管理">
- <div className="mb-4">
- <Space>
- <Input placeholder="设备编号" prefix={<SearchOutlined />} />
- <Select placeholder="设备类型" style={{ width: 120 }}>
- <Option value="flow">流量计</Option>
- <Option value="level">液位计</Option>
- <Option value="pump">泵站</Option>
- </Select>
- <Button type="primary" icon={<SearchOutlined />}>
- 查询
- </Button>
- </Space>
- </div>
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
- {videoData.map((video) => (
- <Card key={video.id} size="small">
- <div className="space-y-2">
- <div>
- <strong>视频:</strong> {video.name}
- </div>
- <div>
- <strong>关联设备:</strong> {video.associatedDevice}
- </div>
- <div>
- <strong>位置:</strong> {video.location}
- </div>
- <div>
- <strong>状态:</strong>
- <span className={`ml-1 ${video.status === "online" ? "text-green-600" : "text-gray-400"}`}>
- {video.status === "online" ? "在线" : "离线"}
- </span>
- </div>
- <div className="pt-2">
- <Button size="small" type="primary">
- 查看视频
- </Button>
- </div>
- </div>
- </Card>
- ))}
- </div>
- </Card>
- </TabPane>
- </Tabs>
- </div>
- )
- }
|