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.

769 lines
32 KiB
JavaScript

1 month ago
import React, { PureComponent } from 'react';
import {
DeleteOutlined,
EditOutlined,
PlusOutlined,
SearchOutlined,
RedoOutlined,
DownOutlined,
ExclamationCircleFilled,
UpOutlined,
SafetyOutlined,
ImportOutlined,
ExportOutlined,
UserOutlined,
TeamOutlined,
SettingOutlined,
FileTextOutlined,
ProjectOutlined,
WarningOutlined,
AlertOutlined,
} from '@ant-design/icons';
import { Button, Card, Divider, Dropdown, message, Modal, Popconfirm, Space, Switch, Tag, Row, Col, Tree, Progress, Input, Select } from 'antd';
import StandardTable from '@/components/StandardTable';
import ReactECharts from 'echarts-for-react';
import { MyIcon } from "@/components/Icon"
import style from "@/global.less";
import BasicInfoCreateForm from '../form/BasicInfoCreateForm'; //新增表单
import BasicInfoUpdateForm from '../form/BasicInfoUpdateForm'; //修改表单
import BasicInfoViewForm from '../form/BasicInfoViewForm'; //查看表单
import BasicInfoImportForm from '../form/BasicInfoImportForm'; //修改表单
import styles from '../BasicInformation.less';
import datadictionary from "@/utils/dataDictionary";
import { formatDate } from "@/utils/formatUtils";
import { formatDictText, checkButtonAuthority } from "@/utils/globalCommon";
import riskShieldImg from '@/assets/basic_information/risk-shield.png'; // 新增:引入盾牌图片
import riskTip from '@/assets/basic_information/risk-tip.png';
const { confirm } = Modal;
//预约类型
const sex_type = datadictionary.sex
const user_status = datadictionary.user_status
const sys_user_post = datadictionary.sys_user_post
const mockData = {
list: [
{
id: '01',
projectName: '安全项目一',
location: '北京朝阳区',
area: '15,000m²',
organization: '安全生产部',
staffCount: 168,
safetyLevel: '高',
},
{
id: '02',
projectName: '安全项目二',
location: '北京朝阳区',
area: '15,000m²',
organization: '安全生产部',
staffCount: 168,
safetyLevel: '中',
},
{
id: '03',
projectName: '安全项目三',
location: '北京朝阳区',
area: '15,000m²',
organization: '安全生产部',
staffCount: 168,
safetyLevel: '低',
},
{
id: '04',
projectName: '安全项目四',
location: '北京朝阳区',
area: '15,000m²',
organization: '安全生产部',
staffCount: 168,
safetyLevel: '低',
},
{
id: '05',
projectName: '安全项目五',
location: '北京朝阳区',
area: '15,000m²',
organization: '安全生产部',
staffCount: 168,
safetyLevel: '中',
},
],
pagination: {
total: 48,
current: 1,
pageSize: 5,
},
}
class BasicInfoManagement extends PureComponent {
state = {
modalVisible: false,
updateModalVisible: false,
viewModalVisible: false,
importModalVisible: false, // 新增导入弹窗状态
expandForm: false,
selectedRows: [],
formValues: {},
updateFormValues: {},
viewFormValues: {},
toggleExpand: false,
}
columns = [
{
title: '编号',
dataIndex: 'id',
key: 'id',
width: 80,
fixed: 'left',
render: (text) => (
<span style={{ fontSize: '12px' }}>{text}</span>
),
},
{
title: '项目名称',
dataIndex: 'projectName',
key: 'projectName',
width: 150,
fixed: 'left',
render: (text) => (
<span style={{ fontSize: '12px' }}>{text}</span>
),
},
{
title: '地理信息',
dataIndex: 'location',
key: 'location',
width: 120,
render: (text) => (
<span style={{ fontSize: '12px' }}>{text}</span>
),
},
{
title: '占地面积',
dataIndex: 'area',
key: 'area',
width: 100,
render: (text) => (
<span style={{ fontSize: '12px' }}>{text}</span>
),
},
{
title: '组织机构',
dataIndex: 'organization',
key: 'organization',
width: 120,
render: (text) => (
<span style={{ fontSize: '12px' }}>{text}</span>
),
},
{
title: '职业人数',
dataIndex: 'staffCount',
key: 'staffCount',
width: 100,
render: (text) => (
<span style={{ fontSize: '12px' }}>{text} </span>
),
},
{
title: '安全等级',
dataIndex: 'safetyLevel',
key: 'safetyLevel',
width: 100,
render: (text) => {
let color = '#FF2526';
let bgColor = '#FFE0E2';
if (text === '中') {
color = '#FF8800';
bgColor = '#FFF3E9';
} else if (text === '低') {
color = '#00AAFA';
bgColor = '#DAF3FF';
}
return (
<Tag
style={{
color: color,
backgroundColor: bgColor,
border: 'none',
borderRadius: 14,
padding: '4px 8px',
fontSize: '12px'
}}
>
{text}
</Tag>
);
},
},
{
title: '操作',
fixed: 'right',
align: 'center',
width: 200,
render: (text, record) => {
return (
<div>
<a className={styles.operateStyle} style={{ marginRight: 15, fontSize: '12px' }} onClick={() => this.handleViewModalVisible(true, record)}> 详情 </a>
<a className={styles.operateStyle} style={{ marginRight: 15, fontSize: '12px' }} onClick={() => this.handleUpdateModalVisible(true, record)}> 修改 </a>
<a className={styles.operateStyle} style={{ color: '#FF2626', fontSize: '12px' }}> 删除 </a>
</div>
)
}
},
]
getPieChartOption = () => {
return {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c}% ({d}%)'
},
legend: {
orient: 'vertical',
right: '20%',
top: '27%',
itemWidth: 16,
itemHeight: 4,
itemGap: 16,
textStyle: {
fontSize: 12,
color: '#666',
fontWeight: 'normal'
}
},
series: [
{
name: '功能区域占比',
type: 'pie',
radius: ['30%', '45%'],
center: ['30%', '45%'],
avoidLabelOverlap: false,
label: {
show: false
},
emphasis: {
scale: true,
scaleSize: 5
},
labelLine: {
show: false
},
data: [
{
value: 45,
name: '生产区',
itemStyle: {
color: '#4B69F1'
}
},
{
value: 20,
name: '仓储区',
itemStyle: {
color: '#44BB5F'
}
},
{
value: 20,
name: '办公区',
itemStyle: {
color: '#A493FB'
}
},
{
value: 15,
name: '辅助区',
itemStyle: {
color: '#FFD85A'
}
}
]
}
]
};
}
handleStandardTableChange = (pagination, sorter) => {
const { dispatch } = this.props
const { formValues } = this.state
const params = {
currentPage: pagination.current,
pageSize: pagination.pageSize,
...formValues
}
sorter.field && (params.sorter = `${sorter.field}_${sorter.order}`)
// 这里应该调用实际的数据获取方法
// 由于当前使用的是mockData我们可以在这里添加日志或者调用相应的action
console.log('分页参数:', params);
// 如果有实际的数据获取action应该这样调用
// dispatch({
// type: 'namespace/fetch',
// payload: params,
// });
}
handleFormReset = () => {
const { dispatch } = this.props
this.setState({
formValues: {}
})
}
toggleForm = () => {
const { expandForm } = this.state
this.setState({
expandForm: !expandForm
})
}
handleSelectRows = rows => {
this.setState({
selectedRows: rows
})
}
handleSearch = values => {
const { dispatch } = this.props
const { expandForm } = this.state
this.setState({
formValues: values
})
}
handleModalVisible = flag => {
this.setState({
modalVisible: !!flag
})
}
handleUpdateModalVisible = (flag, record) => {
this.setState({
updateModalVisible: !!flag,
updateFormValues: record || {}
})
}
handleViewModalVisible = (flag, record) => {
this.setState({
viewModalVisible: !!flag,
viewFormValues: record || {}
})
}
handleAdd = fields => {
const { dispatch } = this.props
// 添加逻辑
}
handleDeleteRecord = record => {
const { dispatch } = this.props
// 删除逻辑
}
handleUpdate = fields => {
const { dispatch } = this.props
// 更新逻辑
}
handleCollapse = () => {
const { toggleExpand } = this.state
this.setState({
toggleExpand: !toggleExpand
})
}
handleImportModalVisible = (flag) => {
this.setState({
importModalVisible: !!flag
});
}
render() {
const {
loading,
dispatch
} = this.props
const {
selectedRows,
modalVisible,
updateModalVisible,
viewModalVisible,
updateFormValues,
viewFormValues,
toggleExpand,
importModalVisible,
} = this.state
const parentMethods = {
handleAdd: this.handleAdd,
handleModalVisible: this.handleModalVisible,
dispatch: dispatch,
loading,
}
const updateMethods = {
handleUpdateModalVisible: this.handleUpdateModalVisible,
handleUpdate: this.handleUpdate,
dispatch: dispatch,
loading,
}
const viewMethods = {
handleViewModalVisible: this.handleViewModalVisible
}
return (
<Card bordered={false} className={styles['card-container']}>
{/* 主要内容区域 */}
<Row gutter={16} style={{ marginBottom: 15 }}>
{/* 左侧:组织机构人员管理 */}
<Col span={9}>
<div
className={styles['organ-area-bg']}
style={{
border: '1px solid #e9ecef',
borderRadius: 4,
padding: 20,
height: 300
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
marginBottom: 20,
color: '#333',
fontSize: 14,
fontWeight: 500
}}>
<span style={{
display: 'inline-block',
width: 2,
height: 16,
background: '#2E4CD4 ',
marginRight: 8
}}></span>
组织机构与人员管理
</div>
{/* 组织架构图 */}
<div className={styles['org-chart-container']}>
{/* 顶部按钮 */}
<div className={styles['org-top-button-container']}>
<Button
type="primary"
className={styles['org-top-button']}
>
项目安全管理组织架构
</Button>
</div>
{/* 连接线 - 顶部到第一层 */}
<div className={styles['org-connect-line-vertical']}></div>
{/* 第一层水平连接线 */}
<div className={styles['org-connect-line-horizontal']}></div>
{/* 第一层垂直连接线 */}
<div className={`${styles['org-connect-line-branch']} ${styles['org-connect-line-branch-left']}`}></div>
<div className={`${styles['org-connect-line-branch']} ${styles['org-connect-line-branch-center']}`}></div>
<div className={`${styles['org-connect-line-branch']} ${styles['org-connect-line-branch-right']}`}></div>
{/* 第一层部门 */}
<div className={styles['org-departments-container']}>
<div className={styles['org-department']}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div className={`${styles['org-department-icon']} ${styles['org-department-icon-safety']}`}>
<SafetyOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-department-label']} style={{ color: '#3CC82D' }}>安监部</div>
</div>
{/* 安监部连接线 */}
<div className={styles['org-department-connect-v']}></div>
<div className={styles['org-department-connect-h']}></div>
<div className={`${styles['org-department-connect-sub']} ${styles['org-department-connect-sub-left']}`}></div>
<div className={`${styles['org-department-connect-sub']} ${styles['org-department-connect-sub-right']}`}></div>
</div>
<div className={styles['org-department']}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div className={`${styles['org-department-icon']} ${styles['org-department-icon-production']}`}>
<ProjectOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-department-label']} style={{ color: '#3F78FA' }}>生产部</div>
</div>
{/* 生产部连接线 */}
<div className={styles['org-department-connect-v']}></div>
<div className={styles['org-department-connect-h']}></div>
<div className={`${styles['org-department-connect-sub']} ${styles['org-department-connect-sub-left']}`}></div>
<div className={`${styles['org-department-connect-sub']} ${styles['org-department-connect-sub-right']}`}></div>
</div>
<div className={styles['org-department']}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<div className={`${styles['org-department-icon']} ${styles['org-department-icon-equipment']}`}>
<SettingOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-department-label']} style={{ color: '#20C3FE' }}>设备部</div>
</div>
{/* 设备部连接线 */}
<div className={styles['org-department-connect-v']}></div>
<div className={styles['org-department-connect-h']}></div>
<div className={`${styles['org-department-connect-sub']} ${styles['org-department-connect-sub-left']}`}></div>
<div className={`${styles['org-department-connect-sub']} ${styles['org-department-connect-sub-right']}`}></div>
</div>
</div>
{/* 第二层子部门 */}
<div className={styles['org-sub-row-group']}>
{/* 安监部子部门 */}
<div className={styles['org-sub-group']}>
<div className={styles['org-sub-item']}>
<div className={styles['org-sub-icon-green']}>
<UserOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-sub-label-green']}>安全监督岗</div>
</div>
<div className={styles['org-sub-item']}>
<div className={styles['org-sub-icon-green']}>
<TeamOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-sub-label-green']}>风险评估岗</div>
</div>
</div>
{/* 生产部子部门 */}
<div className={styles['org-sub-group']}>
<div className={styles['org-sub-item']}>
<div className={styles['org-sub-icon-blue']}>
<UserOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-sub-label-blue']}>生产调度岗</div>
</div>
<div className={styles['org-sub-item']}>
<div className={styles['org-sub-icon-blue']}>
<TeamOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-sub-label-blue']}>现场管理岗</div>
</div>
</div>
{/* 设备部子部门 */}
<div className={styles['org-sub-group']}>
<div className={styles['org-sub-item']}>
<div className={styles['org-sub-icon-cyan']}>
<UserOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-sub-label-cyan']}>设备维护岗</div>
</div>
<div className={styles['org-sub-item']}>
<div className={styles['org-sub-icon-cyan']}>
<SettingOutlined style={{ color: 'white', fontSize: 16 }} />
</div>
<div className={styles['org-sub-label-cyan']}>备件管理岗</div>
</div>
</div>
</div>
</div>
</div>
</Col>
{/* 中间:功能区域占比 */}
<Col span={8}>
<div
className={styles['func-area-bg']}
style={{
border: '1px solid #E3E7FB',
borderRadius: 4,
padding: 20,
height: 300
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
marginBottom: 20,
color: '#333',
fontSize: 14,
fontWeight: 500
}}>
<span style={{
display: 'inline-block',
width: 2,
height: 16,
background: '#2E4CD4',
marginRight: 8
}}></span>
功能区面积占比
</div>
<div className={styles['chart-container']}>
<ReactECharts
option={this.getPieChartOption()}
className={styles['chart-full-size']}
opts={{ renderer: 'canvas' }}
/>
</div>
</div>
</Col>
{/* 右侧:实时风险评估 */}
<Col span={7}>
<div className={styles['risk-assessment-container']}>
{/* 顶部装饰性背景层 */}
{/* <div className={styles['risk-background-top']}></div> */}
{/* 底部装饰性背景层 */}
{/* <div className={styles['risk-background-bottom']}></div> */}
{/* 标题 */}
<div className={styles['risk-title']}>
<span className={styles['risk-title-indicator']}></span>
<span className={styles['risk-title-text']}>实时风险评估</span>
</div>
{/* 主要内容区域 */}
<div className={styles['risk-content-area']}>
{/* 左侧盾牌图标 */}
<div className={styles['risk-shield-container']}>
<img
src={riskShieldImg}
alt="风险盾牌"
style={{ width: 130, height: 130, marginLeft: '-20px', objectFit: 'contain' }}
/>
</div>
{/* 右侧内容 */}
<div className={styles['risk-info-container']}>
{/* 风险等级提示框 */}
<div className={styles['risk-level-alert']}>
<span className={styles['risk-level-text']}>
当前风险等级
<span className={styles['risk-level-danger']}>重大风险</span>
</span>
</div>
{/* 提示信息 */}
<div className={styles['risk-tip-container']}>
<div className={styles['risk-tip-icon']}>
<img
src={riskTip}
alt="提示"
style={{ width: 20, height: 20, display: 'block' }}
/>
</div>
<div className={styles['risk-tip-content']}>
<div className={styles['risk-tip-text']}>
提示安全等级分为 蓝四级当前风险等级为红区存在重大风险
</div>
</div>
</div>
</div>
</div>
</div>
</Col>
</Row>
{/* 底部表格区域 */}
<div>
<div className={styles['table-toolbar-container']}>
<Row justify="space-between" align="middle">
<Col>
<Space>
<Input.Search
placeholder="搜索项目名称、地理信息..."
className={styles['search-input']}
onSearch={this.handleSearch}
/>
<span style={{ marginLeft: 20 }}>筛选条件</span>
<Select
placeholder="请选择"
className={styles['filter-select']}
options={[
{ value: 'all', label: '全部' },
{ value: 'high', label: '高风险' },
{ value: 'medium', label: '中风险' },
{ value: 'low', label: '低风险' },
]}
/>
</Space>
</Col>
<Col>
<Space>
<Button
icon={<PlusOutlined />}
className={styles['button-style']}
onClick={() => this.handleModalVisible(true)}
>
新建项目
</Button>
<Button
icon={<ImportOutlined />}
className={styles['button-style']}
onClick={() => this.handleImportModalVisible(true)} // 新增点击事件
>
导入数据
</Button>
<Button
icon={<ExportOutlined />}
className={styles['button-style']}
>
导出数据
</Button>
</Space>
</Col>
</Row>
</div>
<StandardTable
rowKey={'id'}
selectedRows={selectedRows}
loading={loading}
data={mockData}
columns={this.columns}
onSelectRow={this.handleSelectRows}
onChange={this.handleStandardTableChange}
scroll={{ x: 1200 }}
showTotal={(total, range) => `${total}`}
/>
</div>
{modalVisible && <BasicInfoCreateForm {...parentMethods} modalVisible={modalVisible} />}
{updateFormValues && Object.keys(updateFormValues).length ? (
<BasicInfoUpdateForm
{...updateMethods}
updateModalVisible={updateModalVisible}
values={updateFormValues}
/>
) : null}
{viewFormValues && Object.keys(viewFormValues).length ? (
<BasicInfoViewForm
{...viewMethods}
viewModalVisible={viewModalVisible}
values={viewFormValues}
/>
) : null}
{importModalVisible && (
<BasicInfoImportForm
modalVisible={importModalVisible}
handleModalVisible={this.handleImportModalVisible}
/>
)}
</Card>
)
}
}
export default BasicInfoManagement;