You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
12 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { Card, Table, Button, Modal, Form, Input, Select, message, Space, Tag, Rate, Progress } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
import './RiskAssessment.less';
const { Option } = Select;
const RiskAssessment = () => {
const [form] = Form.useForm();
const [dataSource, setDataSource] = useState([]);
const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [editingRecord, setEditingRecord] = useState(null);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
});
// 模拟数据
const mockData = [
{
id: 1,
riskName: '化学品泄漏风险',
riskType: '环境风险',
riskLevel: '高',
probability: 4,
impact: 5,
riskScore: 20,
assessor: '张三',
assessDate: '2024-01-15',
status: '待处理',
description: '生产过程中化学品可能发生泄漏,造成环境污染',
controlMeasures: '加强设备维护,安装泄漏检测装置',
},
{
id: 2,
riskName: '设备故障风险',
riskType: '设备风险',
riskLevel: '中',
probability: 3,
impact: 3,
riskScore: 9,
assessor: '李四',
assessDate: '2024-01-10',
status: '已处理',
description: '关键设备可能发生故障,影响生产安全',
controlMeasures: '定期维护保养,建立备件库存',
},
{
id: 3,
riskName: '人员操作风险',
riskType: '人员风险',
riskLevel: '低',
probability: 2,
impact: 2,
riskScore: 4,
assessor: '王五',
assessDate: '2024-01-08',
status: '监控中',
description: '操作人员误操作可能导致安全事故',
controlMeasures: '加强培训,完善操作规程',
},
];
useEffect(() => {
fetchData();
}, [pagination.current, pagination.pageSize]);
const fetchData = async () => {
setLoading(true);
try {
// 模拟API调用
setTimeout(() => {
setDataSource(mockData);
setPagination(prev => ({ ...prev, total: mockData.length }));
setLoading(false);
}, 500);
} catch (error) {
message.error('获取数据失败');
setLoading(false);
}
};
const handleAdd = () => {
setEditingRecord(null);
form.resetFields();
setModalVisible(true);
};
const handleEdit = (record) => {
setEditingRecord(record);
form.setFieldsValue(record);
setModalVisible(true);
};
const handleDelete = (record) => {
Modal.confirm({
title: '确认删除',
content: `确定要删除风险评估"${record.riskName}"吗?`,
onOk: () => {
setDataSource(dataSource.filter(item => item.id !== record.id));
message.success('删除成功');
},
});
};
const handleView = (record) => {
Modal.info({
title: '查看风险评估详情',
content: (
<div>
<p><strong>风险名称</strong>{record.riskName}</p>
<p><strong>风险类型</strong>{record.riskType}</p>
<p><strong>风险等级</strong>
<Tag color={record.riskLevel === '高' ? 'red' : record.riskLevel === '中' ? 'orange' : 'green'}>
{record.riskLevel}
</Tag>
</p>
<p><strong>发生概率</strong>
<Rate disabled value={record.probability} />
<span style={{ marginLeft: 8 }}>({record.probability}/5)</span>
</p>
<p><strong>影响程度</strong>
<Rate disabled value={record.impact} />
<span style={{ marginLeft: 8 }}>({record.impact}/5)</span>
</p>
<p><strong>风险评分</strong>{record.riskScore}</p>
<p><strong>评估人</strong>{record.assessor}</p>
<p><strong>评估日期</strong>{record.assessDate}</p>
<p><strong>处理状态</strong>
<Tag color={record.status === '已处理' ? 'green' : record.status === '待处理' ? 'red' : 'blue'}>
{record.status}
</Tag>
</p>
<p><strong>风险描述</strong>{record.description}</p>
<p><strong>控制措施</strong>{record.controlMeasures}</p>
</div>
),
width: 700,
});
};
const handleSubmit = async (values) => {
try {
const riskScore = values.probability * values.impact;
const riskLevel = riskScore >= 16 ? '高' : riskScore >= 9 ? '中' : '低';
const formData = {
...values,
riskScore,
riskLevel,
};
if (editingRecord) {
// 编辑
setDataSource(dataSource.map(item =>
item.id === editingRecord.id ? { ...item, ...formData } : item
));
message.success('编辑成功');
} else {
// 新增
const newRecord = {
id: Date.now(),
...formData,
assessor: '当前用户',
assessDate: new Date().toISOString().split('T')[0],
status: '待处理',
};
setDataSource([...dataSource, newRecord]);
message.success('添加成功');
}
setModalVisible(false);
form.resetFields();
} catch (error) {
message.error('操作失败');
}
};
const getRiskLevelColor = (level) => {
switch (level) {
case '高': return 'red';
case '中': return 'orange';
case '低': return 'green';
default: return 'default';
}
};
const getStatusColor = (status) => {
switch (status) {
case '已处理': return 'green';
case '待处理': return 'red';
case '监控中': return 'blue';
default: return 'default';
}
};
const columns = [
{
title: '风险名称',
dataIndex: 'riskName',
key: 'riskName',
width: 150,
},
{
title: '风险类型',
dataIndex: 'riskType',
key: 'riskType',
width: 120,
},
{
title: '风险等级',
dataIndex: 'riskLevel',
key: 'riskLevel',
width: 100,
render: (level) => (
<Tag color={getRiskLevelColor(level)}>
{level}
</Tag>
),
},
{
title: '风险评分',
dataIndex: 'riskScore',
key: 'riskScore',
width: 100,
render: (score) => (
<div>
<Progress
percent={(score / 25) * 100}
size="small"
status={score >= 16 ? 'exception' : score >= 9 ? 'active' : 'success'}
showInfo={false}
/>
<span style={{ fontSize: '12px' }}>{score}</span>
</div>
),
},
{
title: '发生概率',
dataIndex: 'probability',
key: 'probability',
width: 120,
render: (probability) => (
<div>
<Rate disabled value={probability} style={{ fontSize: '12px' }} />
<span style={{ marginLeft: 4, fontSize: '12px' }}>({probability}/5)</span>
</div>
),
},
{
title: '影响程度',
dataIndex: 'impact',
key: 'impact',
width: 120,
render: (impact) => (
<div>
<Rate disabled value={impact} style={{ fontSize: '12px' }} />
<span style={{ marginLeft: 4, fontSize: '12px' }}>({impact}/5)</span>
</div>
),
},
{
title: '处理状态',
dataIndex: 'status',
key: 'status',
width: 100,
render: (status) => (
<Tag color={getStatusColor(status)}>
{status}
</Tag>
),
},
{
title: '评估人',
dataIndex: 'assessor',
key: 'assessor',
width: 100,
},
{
title: '评估日期',
dataIndex: 'assessDate',
key: 'assessDate',
width: 120,
},
{
title: '操作',
key: 'action',
width: 200,
render: (_, record) => (
<Space size="small">
<Button
type="link"
icon={<EyeOutlined />}
onClick={() => handleView(record)}
>
查看
</Button>
<Button
type="link"
icon={<EditOutlined />}
onClick={() => handleEdit(record)}
>
编辑
</Button>
<Button
type="link"
danger
icon={<DeleteOutlined />}
onClick={() => handleDelete(record)}
>
删除
</Button>
</Space>
),
},
];
return (
<div className="risk-assessment">
<Card
title="风险评估管理"
extra={
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
新增评估
</Button>
}
>
<Table
columns={columns}
dataSource={dataSource}
loading={loading}
rowKey="id"
pagination={{
...pagination,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total, range) =>
`${range[0]}-${range[1]} 条/共 ${total}`,
onChange: (page, pageSize) => {
setPagination(prev => ({
...prev,
current: page,
pageSize: pageSize || prev.pageSize,
}));
},
}}
/>
</Card>
<Modal
title={editingRecord ? '编辑风险评估' : '新增风险评估'}
open={modalVisible}
onCancel={() => {
setModalVisible(false);
form.resetFields();
}}
onOk={() => form.submit()}
width={700}
>
<Form
form={form}
layout="vertical"
onFinish={handleSubmit}
>
<Form.Item
name="riskName"
label="风险名称"
rules={[{ required: true, message: '请输入风险名称' }]}
>
<Input placeholder="请输入风险名称" />
</Form.Item>
<Form.Item
name="riskType"
label="风险类型"
rules={[{ required: true, message: '请选择风险类型' }]}
>
<Select placeholder="请选择风险类型">
<Option value="环境风险">环境风险</Option>
<Option value="设备风险">设备风险</Option>
<Option value="人员风险">人员风险</Option>
<Option value="管理风险">管理风险</Option>
<Option value="技术风险">技术风险</Option>
</Select>
</Form.Item>
<Form.Item
name="probability"
label="发生概率 (1-5分)"
rules={[{ required: true, message: '请选择发生概率' }]}
>
<Rate />
</Form.Item>
<Form.Item
name="impact"
label="影响程度 (1-5分)"
rules={[{ required: true, message: '请选择影响程度' }]}
>
<Rate />
</Form.Item>
<Form.Item
name="description"
label="风险描述"
rules={[{ required: true, message: '请输入风险描述' }]}
>
<Input.TextArea rows={3} placeholder="请输入风险描述" />
</Form.Item>
<Form.Item
name="controlMeasures"
label="控制措施"
rules={[{ required: true, message: '请输入控制措施' }]}
>
<Input.TextArea rows={3} placeholder="请输入控制措施" />
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default RiskAssessment;