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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;