Sfoglia il codice sorgente

feat(app): 新增风险档案管理功能

- 实现了风险档案的新增、编辑、查看和删除功能
- 添加了风险等级、风险评分等字段,并进行了可视化展示
- 集成了雷达图展示风险因子分析
- 优化了用户界面,包括筛选控件、风险概览等模块
nahida 9 mesi fa
parent
commit
b85ed47cc9
1 ha cambiato i file con 483 aggiunte e 0 eliminazioni
  1. 483 0
      app/(other)/test8/components/risk-archive.tsx

+ 483 - 0
app/(other)/test8/components/risk-archive.tsx

@@ -0,0 +1,483 @@
+"use client"
+
+import {useState} from "react"
+import {
+  Button,
+  Card,
+  Col,
+  DatePicker,
+  Descriptions,
+  Form,
+  Input,
+  Modal,
+  Popconfirm,
+  Progress,
+  Row,
+  Select,
+  Space,
+  Table,
+  Tag,
+} from "antd"
+import {DeleteOutlined, EditOutlined, EyeOutlined, PlusOutlined} from "@ant-design/icons"
+import {Radar} from "@ant-design/plots"
+import dayjs from "dayjs"
+import globalMessage from "@/app/_modules/globalMessage";
+
+const { Option } = Select
+const { TextArea } = Input
+
+// 模拟风险档案数据
+const mockRiskData = [
+  {
+    id: "R001",
+    title: "解放路段高压管线风险",
+    location: "解放路与建设路交叉口",
+    riskType: "管线老化",
+    riskLevel: "高",
+    riskScore: 85,
+    assessmentDate: "2024-01-15",
+    assessor: "张三",
+    status: "待处理",
+    description: "高压管线使用年限超过20年,存在老化风险",
+    impactArea: "500m范围内",
+    affectedPopulation: 2000,
+    economicLoss: 500000,
+    mitigationMeasures: "定期检测,制定更换计划",
+    monitoringFrequency: "每月",
+    lastUpdate: "2024-01-15",
+    factors: {
+      管线状态: 80,
+      环境因素: 70,
+      人员密度: 90,
+      设备完好性: 75,
+      管理水平: 85,
+    },
+  },
+  {
+    id: "R002",
+    title: "人民路段泄漏风险",
+    location: "人民路中段",
+    riskType: "泄漏隐患",
+    riskLevel: "中",
+    riskScore: 65,
+    assessmentDate: "2024-01-10",
+    assessor: "李四",
+    status: "监控中",
+    description: "管道接头处存在微量泄漏风险",
+    impactArea: "200m范围内",
+    affectedPopulation: 800,
+    economicLoss: 200000,
+    mitigationMeasures: "加强巡检,安装泄漏检测设备",
+    monitoringFrequency: "每周",
+    lastUpdate: "2024-01-12",
+    factors: {
+      管线状态: 60,
+      环境因素: 65,
+      人员密度: 70,
+      设备完好性: 80,
+      管理水平: 75,
+    },
+  },
+  {
+    id: "R003",
+    title: "建设路段压力风险",
+    location: "建设路北段",
+    riskType: "压力异常",
+    riskLevel: "低",
+    riskScore: 35,
+    assessmentDate: "2024-01-08",
+    assessor: "王五",
+    status: "已控制",
+    description: "调压设备运行正常,风险可控",
+    impactArea: "100m范围内",
+    affectedPopulation: 300,
+    economicLoss: 50000,
+    mitigationMeasures: "定期维护调压设备",
+    monitoringFrequency: "每季度",
+    lastUpdate: "2024-01-10",
+    factors: {
+      管线状态: 40,
+      环境因素: 35,
+      人员密度: 30,
+      设备完好性: 45,
+      管理水平: 40,
+    },
+  },
+]
+
+export default function RiskArchive() {
+  const [isModalVisible, setIsModalVisible] = useState(false)
+  const [isDetailModalVisible, setIsDetailModalVisible] = useState(false)
+  const [editingRecord, setEditingRecord] = useState(null)
+  const [viewingRecord, setViewingRecord] = useState(null)
+  const [form] = Form.useForm()
+
+  const handleAdd = () => {
+    setEditingRecord(null)
+    form.resetFields()
+    setIsModalVisible(true)
+  }
+
+  const handleEdit = (record: any) => {
+    setEditingRecord(record)
+    form.setFieldsValue({
+      ...record,
+      assessmentDate: record.assessmentDate ? dayjs(record.assessmentDate) : null,
+    })
+    setIsModalVisible(true)
+  }
+
+  const handleView = (record: any) => {
+    setViewingRecord(record)
+    setIsDetailModalVisible(true)
+  }
+
+  const handleDelete = (id: string) => {
+    globalMessage.success("删除成功")
+  }
+
+  const handleModalOk = () => {
+    form.validateFields().then((values) => {
+      if (editingRecord) {
+        globalMessage.success("更新成功")
+      } else {
+        globalMessage.success("添加成功")
+      }
+      setIsModalVisible(false)
+      form.resetFields()
+    })
+  }
+
+  const getRiskLevelColor = (level: string) => {
+    switch (level) {
+      case "高":
+        return "red"
+      case "中":
+        return "orange"
+      case "低":
+        return "blue"
+      default:
+        return "default"
+    }
+  }
+
+  const getStatusColor = (status: string) => {
+    switch (status) {
+      case "待处理":
+        return "red"
+      case "监控中":
+        return "orange"
+      case "已控制":
+        return "green"
+      default:
+        return "default"
+    }
+  }
+
+  const getRiskScoreColor = (score: number) => {
+    if (score >= 80) return "#f5222d"
+    if (score >= 60) return "#faad14"
+    if (score >= 40) return "#52c41a"
+    return "#1890ff"
+  }
+
+  const columns = [
+    { title: "风险编号", dataIndex: "id", key: "id", width: 100 },
+    { title: "风险标题", dataIndex: "title", key: "title", width: 200 },
+    { title: "位置", dataIndex: "location", key: "location", width: 150 },
+    { title: "风险类型", dataIndex: "riskType", key: "riskType", width: 120 },
+    {
+      title: "风险等级",
+      dataIndex: "riskLevel",
+      key: "riskLevel",
+      width: 100,
+      render: (level: string) => <Tag color={getRiskLevelColor(level)}>{level}</Tag>,
+    },
+    {
+      title: "风险评分",
+      dataIndex: "riskScore",
+      key: "riskScore",
+      width: 120,
+      render: (score: number) => (
+        <div>
+          <Progress
+            percent={score}
+            size="small"
+            strokeColor={getRiskScoreColor(score)}
+            format={(percent) => `${percent}`}
+          />
+        </div>
+      ),
+    },
+    { title: "评估日期", dataIndex: "assessmentDate", key: "assessmentDate", width: 120 },
+    { title: "评估人", dataIndex: "assessor", key: "assessor", width: 100 },
+    {
+      title: "状态",
+      dataIndex: "status",
+      key: "status",
+      width: 100,
+      render: (status: string) => <Tag color={getStatusColor(status)}>{status}</Tag>,
+    },
+    { title: "影响人口", dataIndex: "affectedPopulation", key: "affectedPopulation", width: 100 },
+    {
+      title: "操作",
+      key: "action",
+      width: 200,
+      fixed: "right",
+      render: (_, record) => (
+        <Space>
+          <Button type="link" icon={<EyeOutlined />} onClick={() => handleView(record)}>
+            查看
+          </Button>
+          <Button type="link" icon={<EditOutlined />} onClick={() => handleEdit(record)}>
+            编辑
+          </Button>
+          <Popconfirm title="确定删除吗?" onConfirm={() => handleDelete(record.id)}>
+            <Button type="link" danger icon={<DeleteOutlined />}>
+              删除
+            </Button>
+          </Popconfirm>
+        </Space>
+      ),
+    },
+  ]
+
+  const radarConfig = viewingRecord
+    ? {
+      data: Object.entries(viewingRecord.factors).map(([key, value]) => ({
+        factor: key,
+        value: value,
+      })),
+      xField: "factor",
+      yField: "value",
+      area: {
+        style: {
+          fill: getRiskScoreColor(viewingRecord.riskScore),
+          fillOpacity: 0.3,
+        },
+      },
+      point: {
+        size: 3,
+      },
+      line: {
+        style: {
+          stroke: getRiskScoreColor(viewingRecord.riskScore),
+          lineWidth: 2,
+        },
+      },
+    }
+    : null
+
+  const highRiskCount = mockRiskData.filter((item) => item.riskLevel === "高").length
+  const mediumRiskCount = mockRiskData.filter((item) => item.riskLevel === "中").length
+  const lowRiskCount = mockRiskData.filter((item) => item.riskLevel === "低").length
+
+  return (
+    <div className="p-6">
+      <Card title="风险档案管理">
+        {/* 风险概览 */}
+        <Row gutter={16} className="mb-6">
+          <Col span={6}>
+            <Card size="small">
+              <div className="text-center">
+                <div className="text-2xl font-bold text-red-600">{highRiskCount}</div>
+                <div className="text-gray-600">高风险</div>
+              </div>
+            </Card>
+          </Col>
+          <Col span={6}>
+            <Card size="small">
+              <div className="text-center">
+                <div className="text-2xl font-bold text-orange-600">{mediumRiskCount}</div>
+                <div className="text-gray-600">中风险</div>
+              </div>
+            </Card>
+          </Col>
+          <Col span={6}>
+            <Card size="small">
+              <div className="text-center">
+                <div className="text-2xl font-bold text-blue-600">{lowRiskCount}</div>
+                <div className="text-gray-600">低风险</div>
+              </div>
+            </Card>
+          </Col>
+          <Col span={6}>
+            <Card size="small">
+              <div className="text-center">
+                <div className="text-2xl font-bold text-gray-600">{mockRiskData.length}</div>
+                <div className="text-gray-600">风险总数</div>
+              </div>
+            </Card>
+          </Col>
+        </Row>
+
+        {/* 筛选控件 */}
+        <div className="mb-4">
+          <Space>
+            <Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
+              新增风险
+            </Button>
+            <Input.Search placeholder="搜索风险..." style={{ width: 300 }} />
+            <Select placeholder="风险类型" style={{ width: 120 }}>
+              <Option value="aging">管线老化</Option>
+              <Option value="leak">泄漏隐患</Option>
+              <Option value="pressure">压力异常</Option>
+              <Option value="other">其他</Option>
+            </Select>
+            <Select placeholder="风险等级" style={{ width: 120 }}>
+              <Option value="high">高</Option>
+              <Option value="medium">中</Option>
+              <Option value="low">低</Option>
+            </Select>
+            <Select placeholder="状态" style={{ width: 120 }}>
+              <Option value="pending">待处理</Option>
+              <Option value="monitoring">监控中</Option>
+              <Option value="controlled">已控制</Option>
+            </Select>
+          </Space>
+        </div>
+
+        {/* 风险列表 */}
+        <Table
+          columns={columns}
+          dataSource={mockRiskData}
+          rowKey="id"
+          pagination={{ pageSize: 10 }}
+          scroll={{ x: 1400 }}
+        />
+
+        {/* 编辑/新增模态框 */}
+        <Modal
+          title={editingRecord ? "编辑风险" : "新增风险"}
+          open={isModalVisible}
+          onOk={handleModalOk}
+          onCancel={() => setIsModalVisible(false)}
+          width={800}
+        >
+          <Form form={form} layout="vertical">
+            <Row gutter={16}>
+              <Col span={12}>
+                <Form.Item name="title" label="风险标题" rules={[{ required: true }]}>
+                  <Input />
+                </Form.Item>
+              </Col>
+              <Col span={12}>
+                <Form.Item name="location" label="位置" rules={[{ required: true }]}>
+                  <Input />
+                </Form.Item>
+              </Col>
+            </Row>
+            <Row gutter={16}>
+              <Col span={12}>
+                <Form.Item name="riskType" label="风险类型" rules={[{ required: true }]}>
+                  <Select>
+                    <Option value="管线老化">管线老化</Option>
+                    <Option value="泄漏隐患">泄漏隐患</Option>
+                    <Option value="压力异常">压力异常</Option>
+                    <Option value="其他">其他</Option>
+                  </Select>
+                </Form.Item>
+              </Col>
+              <Col span={12}>
+                <Form.Item name="riskLevel" label="风险等级" rules={[{ required: true }]}>
+                  <Select>
+                    <Option value="高">高</Option>
+                    <Option value="中">中</Option>
+                    <Option value="低">低</Option>
+                  </Select>
+                </Form.Item>
+              </Col>
+            </Row>
+            <Row gutter={16}>
+              <Col span={12}>
+                <Form.Item name="riskScore" label="风险评分" rules={[{ required: true }]}>
+                  <Input type="number" min={0} max={100} />
+                </Form.Item>
+              </Col>
+              <Col span={12}>
+                <Form.Item name="assessmentDate" label="评估日期" rules={[{ required: true }]}>
+                  <DatePicker style={{ width: "100%" }} />
+                </Form.Item>
+              </Col>
+            </Row>
+            <Form.Item name="description" label="风险描述" rules={[{ required: true }]}>
+              <TextArea rows={3} />
+            </Form.Item>
+            <Row gutter={16}>
+              <Col span={12}>
+                <Form.Item name="affectedPopulation" label="影响人口" rules={[{ required: true }]}>
+                  <Input type="number" />
+                </Form.Item>
+              </Col>
+              <Col span={12}>
+                <Form.Item name="economicLoss" label="潜在经济损失" rules={[{ required: true }]}>
+                  <Input type="number" />
+                </Form.Item>
+              </Col>
+            </Row>
+            <Form.Item name="mitigationMeasures" label="缓解措施">
+              <TextArea rows={3} />
+            </Form.Item>
+          </Form>
+        </Modal>
+
+        {/* 详情查看模态框 */}
+        <Modal
+          title="风险详情"
+          open={isDetailModalVisible}
+          onCancel={() => setIsDetailModalVisible(false)}
+          footer={[
+            <Button key="close" onClick={() => setIsDetailModalVisible(false)}>
+              关闭
+            </Button>,
+          ]}
+          width={1000}
+        >
+          {viewingRecord && (
+            <Row gutter={16}>
+              <Col span={14}>
+                <Descriptions column={2} bordered>
+                  <Descriptions.Item label="风险编号">{viewingRecord.id}</Descriptions.Item>
+                  <Descriptions.Item label="风险标题">{viewingRecord.title}</Descriptions.Item>
+                  <Descriptions.Item label="位置">{viewingRecord.location}</Descriptions.Item>
+                  <Descriptions.Item label="风险类型">{viewingRecord.riskType}</Descriptions.Item>
+                  <Descriptions.Item label="风险等级">
+                    <Tag color={getRiskLevelColor(viewingRecord.riskLevel)}>{viewingRecord.riskLevel}</Tag>
+                  </Descriptions.Item>
+                  <Descriptions.Item label="风险评分">
+                    <Progress
+                      percent={viewingRecord.riskScore}
+                      size="small"
+                      strokeColor={getRiskScoreColor(viewingRecord.riskScore)}
+                    />
+                  </Descriptions.Item>
+                  <Descriptions.Item label="评估日期">{viewingRecord.assessmentDate}</Descriptions.Item>
+                  <Descriptions.Item label="评估人">{viewingRecord.assessor}</Descriptions.Item>
+                  <Descriptions.Item label="影响范围">{viewingRecord.impactArea}</Descriptions.Item>
+                  <Descriptions.Item label="影响人口">{viewingRecord.affectedPopulation}人</Descriptions.Item>
+                  <Descriptions.Item label="潜在损失">¥{viewingRecord.economicLoss.toLocaleString()}</Descriptions.Item>
+                  <Descriptions.Item label="监测频率">{viewingRecord.monitoringFrequency}</Descriptions.Item>
+                </Descriptions>
+
+                <div className="mt-4">
+                  <h4 className="font-medium mb-2">风险描述</h4>
+                  <div className="p-3 bg-gray-50 rounded">{viewingRecord.description}</div>
+                </div>
+
+                <div className="mt-4">
+                  <h4 className="font-medium mb-2">缓解措施</h4>
+                  <div className="p-3 bg-blue-50 rounded">{viewingRecord.mitigationMeasures}</div>
+                </div>
+              </Col>
+              <Col span={10}>
+                <Card title="风险因子分析" size="small">
+                  {radarConfig && <Radar {...radarConfig} height={300} />}
+                </Card>
+              </Col>
+            </Row>
+          )}
+        </Modal>
+      </Card>
+    </div>
+  )
+}