page.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. "use client"
  2. import {useState} from "react"
  3. import {Badge, Card, Col, Layout, Menu, Row, Statistic, Switch} from "antd"
  4. import {
  5. BellOutlined,
  6. DashboardOutlined,
  7. DatabaseOutlined,
  8. EnvironmentOutlined,
  9. ExclamationCircleOutlined,
  10. MonitorOutlined,
  11. MoonOutlined,
  12. SafetyOutlined,
  13. SunOutlined,
  14. } from "@ant-design/icons"
  15. import dynamic from "next/dynamic"
  16. const GasNetworkMap = dynamic(() => import("./components/gas-network-map"), {
  17. ssr: false,
  18. loading: () => <div className="flex items-center justify-center h-96">加载地图中...</div>,
  19. })
  20. const PipelineDataManagement = dynamic(() => import("./components/pipeline-data-management"), {
  21. ssr: false,
  22. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  23. })
  24. const DeviceManagement = dynamic(() => import("./components/device-management"), {
  25. ssr: false,
  26. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  27. })
  28. const HazardArchive = dynamic(() => import("./components/hazard-archive"), {
  29. ssr: false,
  30. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  31. })
  32. const HazardTreatmentStats = dynamic(() => import("./components/hazard-treatment-stats"), {
  33. ssr: false,
  34. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  35. })
  36. const KeyIndicatorsMonitoring = dynamic(() => import("./components/key-indicators-monitoring"), {
  37. ssr: false,
  38. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  39. })
  40. const MonitoringVisualization = dynamic(() => import("./components/monitoring-visualization"), {
  41. ssr: false,
  42. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  43. })
  44. const AbnormalAlarm = dynamic(() => import("./components/abnormal-alarm"), {
  45. ssr: false,
  46. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  47. })
  48. const AlarmVisualization = dynamic(() => import("./components/alarm-visualization"), {
  49. ssr: false,
  50. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  51. })
  52. // 添加风险评估模块组件的动态导入
  53. const RiskArchive = dynamic(() => import("./components/risk-archive"), {
  54. ssr: false,
  55. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  56. })
  57. const RiskVisualization = dynamic(() => import("./components/risk-visualization"), {
  58. ssr: false,
  59. loading: () => <div className="flex items-center justify-center h-96">加载中...</div>,
  60. })
  61. const { Header, Sider, Content } = Layout
  62. export default function HomePage() {
  63. const [selectedKey, setSelectedKey] = useState("dashboard")
  64. const [isDarkMode, setIsDarkMode] = useState(false)
  65. const menuItems = [
  66. {
  67. key: "dashboard",
  68. icon: <DashboardOutlined />,
  69. label: "总览仪表板",
  70. },
  71. {
  72. key: "basic-data",
  73. icon: <DatabaseOutlined />,
  74. label: "基础数据管理",
  75. children: [
  76. { key: "pipeline-data", label: "燃气管网数据" },
  77. { key: "device-management", label: "监测设备管理" },
  78. ],
  79. },
  80. {
  81. key: "hazard-management",
  82. icon: <ExclamationCircleOutlined />,
  83. label: "隐患管理",
  84. children: [
  85. { key: "hazard-archive", label: "隐患台账" },
  86. { key: "hazard-treatment", label: "隐患治理统计" },
  87. ],
  88. },
  89. {
  90. key: "operation-monitoring",
  91. icon: <MonitorOutlined />,
  92. label: "运行监测",
  93. children: [
  94. { key: "key-indicators", label: "关键指标监测" },
  95. { key: "monitoring-visualization", label: "监测可视化" },
  96. ],
  97. },
  98. {
  99. key: "alarm-monitoring",
  100. icon: <BellOutlined />,
  101. label: "监测报警",
  102. children: [
  103. { key: "abnormal-alarm", label: "异常报警" },
  104. { key: "alarm-visualization", label: "报警可视化" },
  105. ],
  106. },
  107. {
  108. key: "risk-assessment",
  109. icon: <SafetyOutlined />,
  110. label: "风险评估",
  111. children: [
  112. { key: "risk-archive", label: "风险档案" },
  113. { key: "risk-visualization", label: "风险可视化" },
  114. ],
  115. },
  116. ]
  117. const renderContent = () => {
  118. switch (selectedKey) {
  119. case "dashboard":
  120. return (
  121. <div className="p-6">
  122. <div className="mb-6">
  123. <h1 className={`text-2xl font-bold mb-2 ${isDarkMode ? "text-white" : "text-gray-800"}`}>
  124. 燃气管网安全运行监测系统 - 长沙市
  125. </h1>
  126. <p className={isDarkMode ? "text-gray-300" : "text-gray-600"}>
  127. 实时监控长沙市燃气管网运行状态,保障城市燃气安全
  128. </p>
  129. </div>
  130. <Row gutter={[16, 16]} className="mb-6">
  131. <Col span={6}>
  132. <Card className="dashboard-card">
  133. <Statistic title="管网总长度" value={2156.8} suffix="km" valueStyle={{ color: "#1890ff" }} />
  134. </Card>
  135. </Col>
  136. <Col span={6}>
  137. <Card className="dashboard-card">
  138. <Statistic title="监测设备" value={568} suffix="台" valueStyle={{ color: "#52c41a" }} />
  139. </Card>
  140. </Col>
  141. <Col span={6}>
  142. <Card className="dashboard-card">
  143. <Statistic title="待处理隐患" value={12} suffix="项" valueStyle={{ color: "#faad14" }} />
  144. </Card>
  145. </Col>
  146. <Col span={6}>
  147. <Card className="dashboard-card">
  148. <Statistic title="活跃报警" value={3} suffix="个" valueStyle={{ color: "#f5222d" }} />
  149. </Card>
  150. </Col>
  151. </Row>
  152. <Row gutter={[16, 16]} className="mb-6">
  153. <Col span={24}>
  154. <Card title="长沙市燃气管网一张图" className="mb-4">
  155. <GasNetworkMap height="500px" />
  156. </Card>
  157. </Col>
  158. </Row>
  159. <Row gutter={[16, 16]}>
  160. <Col span={12}>
  161. <Card title="系统状态" className="h-64">
  162. <div className="flex items-center justify-center h-full">
  163. <div className="text-center">
  164. <Badge status="processing" />
  165. <span className="ml-2 text-lg">系统运行正常</span>
  166. </div>
  167. </div>
  168. </Card>
  169. </Col>
  170. <Col span={12}>
  171. <Card title="最新动态" className="h-64">
  172. <div className="space-y-3">
  173. <div className="flex items-center">
  174. <Badge status="warning" />
  175. <span className="ml-2">管线压力异常 - 五一大道段</span>
  176. </div>
  177. <div className="flex items-center">
  178. <Badge status="success" />
  179. <span className="ml-2">设备维护完成 - 监测点CS001</span>
  180. </div>
  181. <div className="flex items-center">
  182. <Badge status="processing" />
  183. <span className="ml-2">隐患整改中 - 芙蓉路段</span>
  184. </div>
  185. </div>
  186. </Card>
  187. </Col>
  188. </Row>
  189. </div>
  190. )
  191. case "pipeline-data":
  192. return <PipelineDataManagement />
  193. case "device-management":
  194. return <DeviceManagement />
  195. case "hazard-archive":
  196. return <HazardArchive />
  197. case "hazard-treatment":
  198. return <HazardTreatmentStats />
  199. case "key-indicators":
  200. return <KeyIndicatorsMonitoring />
  201. case "monitoring-visualization":
  202. return <MonitoringVisualization />
  203. case "abnormal-alarm":
  204. return <AbnormalAlarm />
  205. case "alarm-visualization":
  206. return <AlarmVisualization />
  207. // 添加风险评估模块页面的渲染逻辑
  208. case "risk-archive":
  209. return <RiskArchive />
  210. case "risk-visualization":
  211. return <RiskVisualization />
  212. default:
  213. return (
  214. <div className="p-6">
  215. <Card>
  216. <div className="text-center py-12">
  217. <h2 className="text-xl font-semibold mb-4">功能开发中</h2>
  218. <p className="text-gray-600">该功能模块正在开发中,敬请期待...</p>
  219. </div>
  220. </Card>
  221. </div>
  222. )
  223. }
  224. }
  225. return (
  226. <>
  227. <style jsx>{`
  228. /* 添加主题相关样式 */
  229. :global(.dark-theme) {
  230. background-color: #141414;
  231. color: #ffffff;
  232. }
  233. :global(.dark-theme .ant-layout) {
  234. background-color: #141414;
  235. }
  236. :global(.dark-theme .ant-layout-header) {
  237. background-color: #1f1f1f !important;
  238. border-bottom: 1px solid #303030;
  239. }
  240. :global(.dark-theme .ant-layout-sider) {
  241. background-color: #1f1f1f !important;
  242. }
  243. :global(.dark-theme .ant-layout-content) {
  244. background-color: #0f0f0f !important;
  245. }
  246. :global(.dark-theme .ant-menu) {
  247. background-color: #1f1f1f !important;
  248. color: #ffffff;
  249. }
  250. :global(.dark-theme .ant-menu-item) {
  251. color: #ffffff !important;
  252. }
  253. :global(.dark-theme .ant-menu-item:hover) {
  254. background-color: #303030 !important;
  255. }
  256. :global(.dark-theme .ant-menu-item-selected) {
  257. background-color: #1890ff !important;
  258. }
  259. :global(.dark-theme .ant-card) {
  260. background-color: #1f1f1f !important;
  261. border-color: #303030 !important;
  262. }
  263. :global(.dark-theme .ant-card-head) {
  264. background-color: #1f1f1f !important;
  265. border-bottom-color: #303030 !important;
  266. }
  267. :global(.dark-theme .ant-card-head-title) {
  268. color: #ffffff !important;
  269. }
  270. :global(.dark-theme .ant-statistic-title) {
  271. color: #bfbfbf !important;
  272. }
  273. /* Ant Design customizations - 只在此组件内生效 */
  274. :global(.ant-layout-header) {
  275. padding: 0 24px;
  276. line-height: 64px;
  277. }
  278. :global(.ant-menu-inline) {
  279. border-right: none;
  280. }
  281. :global(.ant-card) {
  282. border-radius: 8px;
  283. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  284. }
  285. :global(.ant-statistic-title) {
  286. font-size: 14px;
  287. color: #666;
  288. }
  289. :global(.ant-statistic-content) {
  290. font-size: 24px;
  291. font-weight: 600;
  292. }
  293. /* Custom dashboard card styles */
  294. :global(.dashboard-card) {
  295. transition: all 0.3s ease;
  296. }
  297. :global(.dashboard-card:hover) {
  298. transform: translateY(-2px);
  299. box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  300. }
  301. `}</style>
  302. <div className={isDarkMode ? "dark-theme" : ""}>
  303. <Layout className="min-h-screen">
  304. <Header className={isDarkMode ? "bg-gray-800" : "bg-blue-600"} style={{ padding: "0 24px" }}>
  305. <div className="flex items-center justify-between">
  306. <div className="flex items-center">
  307. <EnvironmentOutlined className="text-white text-2xl mr-3" />
  308. <h1 className="text-white text-xl font-semibold">长沙市燃气管网安全监测平台</h1>
  309. </div>
  310. <div className="flex items-center gap-2">
  311. <SunOutlined className="text-white" />
  312. <Switch
  313. checked={isDarkMode}
  314. onChange={setIsDarkMode}
  315. checkedChildren={<MoonOutlined />}
  316. unCheckedChildren={<SunOutlined />}
  317. />
  318. <MoonOutlined className="text-white" />
  319. </div>
  320. </div>
  321. </Header>
  322. <Layout>
  323. <Sider
  324. width={250}
  325. className={isDarkMode ? "bg-gray-800" : "bg-white"}
  326. style={{ boxShadow: "2px 0 8px rgba(0,0,0,0.1)" }}
  327. >
  328. <Menu
  329. mode="inline"
  330. selectedKeys={[selectedKey]}
  331. defaultOpenKeys={[
  332. "basic-data",
  333. "hazard-management",
  334. "operation-monitoring",
  335. "alarm-monitoring",
  336. "risk-assessment",
  337. ]}
  338. items={menuItems}
  339. onClick={({ key }) => setSelectedKey(key)}
  340. className="border-r-0"
  341. theme={isDarkMode ? "dark" : "light"}
  342. />
  343. </Sider>
  344. <Content className={isDarkMode ? "bg-gray-900" : "bg-gray-50"}>{renderContent()}</Content>
  345. </Layout>
  346. </Layout>
  347. </div>
  348. </>
  349. )
  350. }