mh_jy_safe_web/src/routes/HomeMobile.js
2025-08-25 10:08:30 +08:00

753 lines
24 KiB
JavaScript

import React, { useState, useEffect, useRef, Component } from 'react'
import { connect } from 'dva'
import storage from '../utils/storage'
import { initFilter, addRuleAndGroups, guid, extendInclude, extendRule, extend } from "../utils/common"
import './home.less'
// 组件库
import { Table, Modal, Row, Col, Icon, Button, Input, DatePicker, Form, Select, notification, Divider } from 'antd';
import { Chart, Geom, Axis, Tooltip, Legend } from "bizcharts";
import FormPage from '../components/FormPage'
import backlog from '../assets/home/backlog.png';
import backlog_i from '../assets/home/backlog_icon.png';
import styles from './dashboard.css';
import Slider from "react-slick";
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import moment from 'moment';
import flow from '../assets/home/flow.png';
import flow_i from '../assets/home/flow_icon.png';
import finished from '../assets/home/finished.png';
import finished_i from '../assets/home/finished_icon.png';
import remind from '../assets/home/remind.png';
import remind_i from '../assets/home/remind_icon.png';
import noticeImg from '../assets/home/noticeImg.jpg';
import scoreImg from '../assets/home/score.jpg';
import echarts from 'echarts';
const Option = Select.Option;
const RangePicker = DatePicker.RangePicker
const formItemLayout = {
labelCol: { span: 6 },
wrapperCol: { span: 14 },
};
const openNotification = placement => {
notification.info({
duration: null,
top: 43,
message: `签名照上传提示:`,
description:
'您还没上传自己的签名照片,请在我的资料中尽快上传您的签名照!',
placement,
});
};
class HomeMobile extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: false,
noticeTitle: '',
tmpData: {},
tableKey: "1",
pagination: {},
retData: [],
chartData: [],
columnData: [],
columnFields: [],
delayData: [],
Workbench: {
StockDetail: [],
ApprovalCount: 0,
InComingCount: 0,
OutingCount: 0,
ProductingCount: 0
},//工作台模型
showLoading: false, //待办事项数据刷新提示
searchVisible: false, //弹窗显示
columns: [
// {
// title: '消息编号',
// dataIndex: 'CODE',
// key: 'CODE'
// },
{
title: '任务名称',
dataIndex: 'NOTICE_TITLE',
key: 'NOTICE_TITLE',
render: (text, record) => (
<span>
<a onClick={() => this.showEditModal(record.SOURCE_DATA_ID, record.SOURCE_FORMCODE, record.ID, record.NOTICE_TITLE, record.CODE)}>{record.NOTICE_TITLE}</a>
</span>
),
},
{
title: '开始时间',
dataIndex: 'TASK_STARTDT',
key: 'TASK_STARTDT'
},
{
title: '结束时间',
dataIndex: 'TASK_ENDDT',
key: 'TASK_ENDDT'
},
{
title: '预警状态',
dataIndex: 'NOTICE_TYPE',
key: 'operation',
render: (text, record) => this.ShowState(record)
},
],
searchColumns: [
// {
// title: '消息编号',
// dataIndex: 'CODE',
// key: 'CODE'
// },
{
title: '任务名称',
dataIndex: 'NOTICE_TITLE',
key: 'NOTICE_TITLE',
render: (text, record) => (
<span>
<a onClick={() => this.showEditModal(record.SOURCE_DATA_ID, record.SOURCE_FORMCODE, record.ID, record.NOTICE_TITLE, record.CODE)}>{record.NOTICE_TITLE}</a>
</span>
),
},
{
title: '开始时间',
dataIndex: 'TASK_STARTDT',
key: 'TASK_STARTDT'
},
{
title: '结束时间',
dataIndex: 'TASK_ENDDT',
key: 'TASK_ENDDT'
},
{
title: '预警状态',
dataIndex: 'NOTICE_TYPE',
key: 'operation',
render: (recode) => this.ShowState(recode)
},
],
tableData: [{//工作台四个展示模块
key: '1',
bgImg: backlog,
title: '待办事项',
total: '0',
iconImg: backlog_i,
iconDisplay: 'block',
}, {
key: '2',
bgImg: flow,
title: '已办事项',
total: '0',
iconImg: flow_i,
iconDisplay: 'none',
}, {
key: '3',
bgImg: finished,
title: '今日新增',
total: '0',
iconImg: finished_i,
iconDisplay: 'none',
}
,
{
key: '4',
bgImg: remind,
title: '待办超时',
total: '0',
iconImg: remind_i,
iconDisplay: 'none',
}
],
visibleTitle: '',//点击title
isSearch: false, // 是否搜索
querySearch: {},//搜索集合
visibleStartTime: [],
visibleEndTime: [],
currentpageIndex: "1"
};
};
componentDidMount() {
this.getBaseInfoData(1, "1", 5);
//this.setMessageData();
//this.targetCheck();//个人指标考核(统计图)
//this.defectTreatment();//隐患整改(统计图)
//this.jobType();//岗位风险类别(统计图)
//this.mainJobPie();//主要工作分布(饼图)
//this.delayJobBar();// 超期事务(柱状图图)
//定时器功能,暂时不开启
//this.timerID = setInterval(() => this.reloadData(), 50000);
//this.showModalSign(); //验证是否有上传签名
this.showModalSign();
};
showModalSign = () => {
var userId = storage('lacal').getItem('userid')?.val; //登录后有存储登录信息
var orgId = storage('lacal').getItem('webOrgId')?.val; //登录后有存储登录信息
let json = initFilter(orgId);
this.props.dispatch({
type: 'app/getDataByPost',
payload: json,
url: 'FM/User/UserSign', //验证是否有签名照
onComplete: (ret) => { //返回查询结果ret
if (ret) { //判断是否有记录
openNotification('topRight');
}
}
});
};
//个人指标考核
targetCheck = () => {
let myChart = echarts.init(document.getElementById('targetCheck'));
myChart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
top: '3%',
containLabel: true
},
xAxis: {
type: 'value'
},
legend: {
data: ['加分', '减分'],
bottom: '10px'
},
yAxis: {
type: 'category',
axisTick: {
show: false
},
axisLine: {
show: false
},
data: ["安全教育参加情况", "安全活动参加情况", "'三违'行为", "事故事件(否决项)"]
},
series: [
{
name: '加分',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'inside',
color: '#000'
},
color: '#5B9BD5',
data: [28, 56, 7, '']
},
{
name: '减分',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'inside',
color: '#000'
},
color: '#ED7D31',
data: [-2, -4, -3, '']
},
],
});
}
//隐患整改情况
defectTreatment = () => {
const userInfo = storage('lacal').getItem('webUserInfo').val;
let json = initFilter(this.props.login.OrgId);
// this.props.dispatch({
// type: 'app/getDataByPost',
// url: "FM/MainRpt/GetRNQCount",
// payload: json,
// onlyData: false,
// onComplete: (data) => {
let data = { "IsSuccessful": true, "Data": [{ "USER_ID": "37c527b6-86cf-4549-8b2d-8528af5600d1", "DEPARTMENT_ID": "e3061909-1a7e-b60c-bc71-1845b79c4a11", "MONTH": "2021-08-01 00:00:00", "MONTHStr": "八月", "C_COUNT": 0, "D_COUNT": 0, "W_COUNT": 0, "T_COUNT": 0, "P_COUNT": 0, "C_F_COUNT": 0, "D_F_COUNT": 0, "W_F_COUNT": 0, "T_F_COUNT": 0, "P_F_COUNT": 0 }, { "USER_ID": "37c527b6-86cf-4549-8b2d-8528af5600d1", "DEPARTMENT_ID": "e3061909-1a7e-b60c-bc71-1845b79c4a11", "MONTH": "2021-09-01 00:00:00", "MONTHStr": "九月", "C_COUNT": 0, "D_COUNT": 0, "W_COUNT": 0, "T_COUNT": 0, "P_COUNT": 0, "C_F_COUNT": 0, "D_F_COUNT": 0, "W_F_COUNT": 0, "T_F_COUNT": 0, "P_F_COUNT": 0 }, { "USER_ID": "37c527b6-86cf-4549-8b2d-8528af5600d1", "DEPARTMENT_ID": "e3061909-1a7e-b60c-bc71-1845b79c4a11", "MONTH": "2021-10-01 00:00:00", "MONTHStr": "十月", "C_COUNT": 0, "D_COUNT": 0, "W_COUNT": 0, "T_COUNT": 0, "P_COUNT": 0, "C_F_COUNT": 0, "D_F_COUNT": 0, "W_F_COUNT": 0, "T_F_COUNT": 0, "P_F_COUNT": 0 }, { "USER_ID": "37c527b6-86cf-4549-8b2d-8528af5600d1", "DEPARTMENT_ID": "e3061909-1a7e-b60c-bc71-1845b79c4a11", "MONTH": "2021-11-01 00:00:00", "MONTHStr": "十一月", "C_COUNT": 0, "D_COUNT": 0, "W_COUNT": 0, "T_COUNT": 0, "P_COUNT": 0, "C_F_COUNT": 0, "D_F_COUNT": 0, "W_F_COUNT": 0, "T_F_COUNT": 0, "P_F_COUNT": 0 }, { "USER_ID": "37c527b6-86cf-4549-8b2d-8528af5600d1", "DEPARTMENT_ID": "e3061909-1a7e-b60c-bc71-1845b79c4a11", "MONTH": "2021-12-01 00:00:00", "MONTHStr": "十二月", "C_COUNT": 0, "D_COUNT": 0, "W_COUNT": 0, "T_COUNT": 0, "P_COUNT": 0, "C_F_COUNT": 0, "D_F_COUNT": 0, "W_F_COUNT": 0, "T_F_COUNT": 0, "P_F_COUNT": 0 }, { "USER_ID": "37c527b6-86cf-4549-8b2d-8528af5600d1", "DEPARTMENT_ID": "e3061909-1a7e-b60c-bc71-1845b79c4a11", "MONTH": "2022-01-01 00:00:00", "MONTHStr": "一月", "C_COUNT": 0, "D_COUNT": 0, "W_COUNT": 0, "T_COUNT": 0, "P_COUNT": 0, "C_F_COUNT": 0, "D_F_COUNT": 0, "W_F_COUNT": 0, "T_F_COUNT": 0, "P_F_COUNT": 0 }], "TotalCount": 0, "ErrorMessage": null }
if (data && data.IsSuccessful) {
let month = [];
let company = [];
let department = [];
let workshop = [];
let team = [];
let personal = [];
data.Data.forEach(item => {
month.push(item.MONTHStr);
company.push(item.C_COUNT);
department.push(item.D_COUNT);
workshop.push(item.W_COUNT);
team.push(item.T_COUNT);
personal.push(item.P_COUNT);
})
let myChart = echarts.init(document.getElementById('defectTreatment'));
myChart.setOption({
// title: {
// text: '折线图堆叠'
// },
tooltip: {
trigger: 'axis'
},
legend: {
// data: ['部门'],
data: ['公司', '部门', '车间', '班组', '个人'],
bottom: '10px'
},
grid: {
left: '3%',
right: '4%',
top: '3%',
containLabel: true
},
toolbox: {
feature: {
// saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: month
},
yAxis: {
type: 'value',
},
series: [
{
name: '公司',
type: 'line',
color: '#4b9bf3',
data: company
},
{
name: '部门',
type: 'line',
color: '#d61c7e',
data: department
},
{
name: '车间',
type: 'line',
color: '#6052ea',
data: workshop
}
,
{
name: '班组',
type: 'line',
color: '#8cc539',
data: team
}
,
{
name: '个人',
type: 'line',
color: '#FCD149',
data: personal
}
]
})
}
// }
// });
}
//获取数据
getBaseInfoData = (pagination, key, limit) => {
const current = pagination ? pagination.current : 1
const json = initFilter(this.props.login.OrgId, "", "CODE", 1, current)
//extendRule(json, "NOTICE_STATUS", 1, 0);
const querySearch = this.state.querySearch;
for (var item in querySearch) {
if (item == 'searchName') {
extendRule(json, 'NOTICE_TITLE', 9, querySearch[item])
}
if (item == 'searchCode') {
extendRule(json, 'CODE', 9, querySearch[item])
}
if (item == 'startTime1') {
extendRule(json, 'TASK_STARTDT', 6, querySearch[item])
}
if (item == 'startTime2') {
extendRule(json, 'TASK_STARTDT', 4, querySearch[item])
}
if (item == 'endTime1') {
extendRule(json, 'TASK_ENDDT', 6, querySearch[item])
}
if (item == 'endTime2') {
extendRule(json, 'TASK_ENDDT', 4, querySearch[item])
}
}
json.Limit = limit;
json.Parameter1 = key;//1待办事项2已办事项3今日新增4待办超时
this.props.dispatch({
type: 'app/getDataByPost',
url: 'FM/FMNotificationTask/OrderPaged',
payload: json,
onlyData: false,
onComplete: (re) => {
if (re && re.IsSuccessful && re.Data.newData) {
this.state.tableData[0].total = re.Data.todoCount;
this.state.tableData[1].total = re.Data.doneCount;
this.state.tableData[2].total = re.Data.todayNewCount;
this.state.tableData[3].total = re.Data.timeOverCount;
if (limit != null || limit != undefined) {
this.setState({
retData: re.Data.newData,
})
} else {
var pageInfo = {}
pageInfo.current = current;
pageInfo.total = Math.ceil(re.Data.TotalCount, 10);
this.setState({
retDataAll: re.Data.newData,
pagination: pageInfo,
})
}
}
}
})
};
clearData = () => {
let newtmpData = { ...this.state.tmpData }
newtmpData["data"].id = '';
newtmpData["data"].homeReload = false;
this.setState({
visible: false,
tmpData: newtmpData,
})
}
handleCancel = () => { // 退出弹窗
this.getBaseInfoData(1, this.state.tableKey, 5);
this.clearData();
}
closeModal = () => { // 退出弹窗
this.clearData();
}
showEditModal = (dataId, formCode, TaskID, title, taskCode) => {
const newtmpData = {
data: { id: dataId, TaskID: TaskID, onCancel: this.handleCancel, taskCode: taskCode, homeReload: true },
formCode: formCode,
}
this.setState({
noticeTitle: title,
taskCode: taskCode,
tmpData: newtmpData
}, () => this.setState({
visible: true
}));
}
setMessageData = (dataSource) => {
const data = dataSource ? dataSource : this.props.taskData;
}
//点击切换四个统计模块更改列表数据
totalModuleClick = (item) => {
const { tableData } = this.state;
tableData.map((_item, i) => {
if (_item.key == item.key) {
_item.iconDisplay = 'block';
this.setState({
tableKey: item.key
})
this.getBaseInfoData(1, item.key, 5);
} else {
_item.iconDisplay = 'none';
}
});
};
// 双击切换四个统计模块获取全部信息
totalMoonDoubleClick = (item) => {
const { tableData } = this.state;
tableData.map((_item) => {
if (_item.key == item.key) {
this.setState({
searchVisible: true,
querySearch: {}
})
}
})
this.setState({
tableData,
currentpageIndex: item.key
}, () => {
this.getBaseInfoData(1, item.key);
})
}
// 开始时间
startChange = (dates, dateStr) => {
const { querySearch } = this.state
if (dates.length != 2) {
// querySearch['startTime1'] = ''
// querySearch['startTime2'] = ''
this.setState({
visibleStartTime: [],
querySearch: {}
})
return;
}
this.state.visibleStartTime = dates
querySearch.startTime1 = this.state.visibleStartTime[0].format("YYYY-MM-DD HH:mm:ss")
querySearch.startTime2 = this.state.visibleStartTime[1].format("YYYY-MM-DD HH:mm:ss")
this.setState({
querySearch
// visibleStartTime: dates
}, () => {
})
}
// 结束时间
endChange = (dates, dateStr) => {
const { querySearch } = this.state
if (dates.length != 2) {
// querySearch['endTime1'] = ''
// querySearch['endTime2'] = ''
this.setState({
visibleEndTime: [],
querySearch: {}
})
return;
}
this.state.visibleEndTime = dates
querySearch.endTime1 = this.state.visibleEndTime[0].format("YYYY-MM-DD HH:mm:ss")
querySearch.endTime2 = this.state.visibleEndTime[1].format("YYYY-MM-DD HH:mm:ss")
this.setState({ querySearch })
}
// 搜索
handleSearch = (item) => {
this.getBaseInfoData(1, item, null);
}
// input输入
vauleChange = (e) => {
const { querySearch } = this.state
if (e.target.value) {
switch (e.target.name) {
case 'searchName':
querySearch[e.target.name] = e.target.value
this.setState({ querySearch })
break
case 'searchCode':
querySearch[e.target.name] = e.target.value
this.setState({ querySearch })
break
case 'searchType':
querySearch[e.target.name] = e.target.value
this.setState({ querySearch })
break
case 'searchContent':
querySearch[e.target.name] = e.target.value
this.setState({ querySearch })
break
}
} else {
this.setState({ querySearch: {} })
}
}
closeModal = () => {
this.setState({
searchVisible: false
})
}
ShowState(obj) {
var thisResult = (Date.parse(obj.TASK_ENDDT) - Date.parse(Date())) / 3600 / 1000;
if (thisResult > 0) {
return ('正常');
} else {
return (<span style={{ color: 'red' }}>超期</span>);
}
}
handleSelect = (e) => {
const { querySearch } = this.state
if (e != undefined) {
querySearch.status = e
} else {
querySearch.status = ''
}
this.setState({ querySearch })
}
render() {
const { tableData } = this.state;
const thingsData = this.state.delayData;
const settings = {
dots: true,
autoplay: false,
infinite: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
className: styles.slideHeight
};
return (
<div className='route-home' style={{ backgroundColor: '#ecf4f6', padding: '0 10px', minHeight: '600px' }}>
<div style={{ display: 'inline-block' }}>
<Modal
visible={this.state.visible}
title={this.state.noticeTitle + "(" + this.state.taskCode + ")"}
maskClosable={false}
onCancel={this.handleCancel}
footer={null}
className='antd-modal-fullscreen'
closeModal={this.closeModal}
// forceRender={true}
>
<FormPage {...this.state.tmpData} />
</Modal>
</div>
<Row gutter={12}>
{/* 五个图标模块 */}
<Col span={24}>
<Row gutter={10} >
<Col span={4}>
<div style={{ background: `url(${scoreImg}) 0 0 no-repeat`, height: '176px', backgroundSize: '100% 100%', borderRadius: '0px 0px 16px 16px' }}>
<div className='score-title-style'>标准化得分</div>
<div style={{ textAlign: 'center' }}>
<div className='score-num-style' style={{ width: 'auto', fontSize: '28pt', display: 'inline-block', marginTop: '45px' }}>81.72</div>
<div style={{ display: 'inline-block', fontSize: '30pt' }}>
<Icon type="arrow-up" className='score-icon-style' style={{ fontSize: '20pt', marginTop: '-27px' }} />
</div>
</div>
</div>
</Col>
<Col span={20}>
<Col span={24}>
<div className='slide-style'>
<p className='slide-text-style'>安全第一综合治理控制风险科学发展</p>
</div>
</Col>
<Row gutter={10} >
{
tableData.map((item) => {
return (
<Col span={6}>
<div
onClick={() => this.totalModuleClick(item)}
onDoubleClick={() => this.totalMoonDoubleClick(item)}
style={{ padding: '0px', background: `url(${item.bgImg}) 0 0 no-repeat`, height: '126px', backgroundSize: '100% 100%', borderRadius: '10px', cursor: 'pointer' }}
>
<div className='backlog-title-style'>{item.title}</div>
<div className='backlog-style'>{item.total}</div>
<img src={item.iconImg} className='backlog-icon-style' style={{ display: item.iconDisplay }} />
</div>
</Col>
)
})
}
</Row>
</Col>
</Row>
</Col>
{/* 通知 */}
</Row>
<Row gutter={12} style={{ marginTop: "14px", height: 'calc((100% - 250px) / 2)', minHeight: '260px' }}>
{/* 列表 */}
<Col span={24} style={{ height: '100%' }}>
<div className="dashboard-div-style" style={{ boxShadow: '0px 0px 10px rgba(0,0,0,.15)', overflow: 'auto' }}>
<Table
dataSource={this.state.retData}
columns={this.state.columns}
pagination={false}
loading={this.state.showLoading}
size="small"
padding="100px"
/>
</div>
</Col>
<Modal
visible={this.state.searchVisible}
title={this.state.visibleTitle}
maskClosable={false}
onCancel={this.closeModal}
footer={false}
className='antd-modal-fullscreen'
>
<div>
<Form>
<Row style={{ marginTop: '50px' }}>
<Col span={5}>
<Form.Item
label={'名称'}
{...formItemLayout}
>
<Input
value={this.state.querySearch.searchName}
placeholder={'请输入任务名称'}
name="searchName"
onChange={this.vauleChange} />
</Form.Item>
</Col>
{/* <Col span={5}>
<Form.Item
label={'编号'}
{...formItemLayout}
>
<Input
value={this.state.querySearch.searchCode}
placeholder={'消息编号'}
name="searchCode"
onChange={this.vauleChange} />
</Form.Item>
</Col> */}
<Col span={6}>
<Form.Item
label={'开始时间'}
{...formItemLayout}
>
<RangePicker
value={this.state.visibleStartTime}
// defaultValue={[moment(moment(this.state.querySearch.startTime1), "YYYY-MM-DD"), moment(moment(this.state.querySearch.startTime2), "YYYY-MM-DD")]}
onChange={this.startChange} />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
label={'结束时间'}
{...formItemLayout}
>
<RangePicker
value={this.state.visibleEndTime}
onChange={this.endChange} />
</Form.Item>
</Col>
<Col span={2}>
<Button type={'primary'} icon={'search'} onClick={() => this.handleSearch(this.state.currentpageIndex)}>搜索</Button>
</Col>
</Row>
</Form>
<Table
dataSource={this.state.retDataAll}
columns={this.state.searchColumns}
pagination={this.state.pagination}
onChange={(num) => this.getBaseInfoData(num, this.state.currentpageIndex, null)}
loading={this.state.showLoading}
size="small"
/>
</div>
</Modal>
</Row>
</div>
)
}
}
export default connect(({ login }) => ({ login }))(HomeMobile)