|
@@ -0,0 +1,932 @@
|
|
|
+import ThresholdDetail from '@/components/ThresholdDetail';
|
|
|
+import ThresholdModal from '@/components/ThresholdDetail/ThresholdModal';
|
|
|
+import { changeRecordStatus, getDumuDetail } from '@/services/eqSelfInspection';
|
|
|
+import { UnityAction } from '@/utils/utils';
|
|
|
+import { connect, useRequest } from '@umijs/max';
|
|
|
+import {
|
|
|
+ Card,
|
|
|
+ Col,
|
|
|
+ DatePicker,
|
|
|
+ Form,
|
|
|
+ Input,
|
|
|
+ Modal,
|
|
|
+ Row,
|
|
|
+ Select,
|
|
|
+ Spin,
|
|
|
+ Table,
|
|
|
+ Tabs,
|
|
|
+ message,
|
|
|
+} from 'antd';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import { useEffect, useMemo, useState } from 'react';
|
|
|
+import ReactZmage from 'react-zmage';
|
|
|
+import styles from './PatrolReportDetail.less';
|
|
|
+
|
|
|
+function Detail(props) {
|
|
|
+ const { data, userList, projectId, dispatch, loading = false } = props;
|
|
|
+
|
|
|
+ const [select, setSelect] = useState();
|
|
|
+ const [dumuList, setDumuList] = useState([]);
|
|
|
+ const sendMessageToUnity = (select, data) => {
|
|
|
+ setSelect(select);
|
|
|
+ // console.log(data);
|
|
|
+ if (window.HightlightEquipment) {
|
|
|
+ window.HightlightEquipment(data);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const getTextColor = (status) => {
|
|
|
+ switch (status) {
|
|
|
+ case '警告':
|
|
|
+ return '#FFE26D';
|
|
|
+ case '异常':
|
|
|
+ return '#FF8600';
|
|
|
+ case '正常':
|
|
|
+ return '#60FE76';
|
|
|
+ default:
|
|
|
+ return '#60FE76';
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const { run: detailRun } = useRequest(getDumuDetail, {
|
|
|
+ manual: true,
|
|
|
+ fetchKey: (id) => id,
|
|
|
+ onSuccess: (data) => {
|
|
|
+ var item = dumuList?.find((child) => child.id === data.id);
|
|
|
+ if (item) {
|
|
|
+ item.url = base64ToImageUrl(data.event_bg);
|
|
|
+ }
|
|
|
+ setDumuList([...dumuList]);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ const result = useMemo(() => {
|
|
|
+ var resultArr = [];
|
|
|
+ var tempResult = data?.PatrolResult;
|
|
|
+ var tempArr = tempResult?.split(';');
|
|
|
+ if (tempArr?.length > 0) {
|
|
|
+ tempArr?.forEach((item, index) => {
|
|
|
+ var tempItem = item;
|
|
|
+ var itemSplit = tempItem.split(':');
|
|
|
+ if (itemSplit?.length > 1) {
|
|
|
+ var label = '';
|
|
|
+ var value = itemSplit[1];
|
|
|
+ if (index === 0) label = '设备自检';
|
|
|
+ else if (index === 1) label = '工艺自检';
|
|
|
+ else {
|
|
|
+ label = '安全隐患';
|
|
|
+ value = data?.secureStatus === 0 ? '正常' : '异常';
|
|
|
+ }
|
|
|
+ resultArr.push({
|
|
|
+ label,
|
|
|
+ value,
|
|
|
+ color: getTextColor(value),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return resultArr;
|
|
|
+ }, [data]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ dispatch({
|
|
|
+ type: 'eqSelfInspection/fetchUserList',
|
|
|
+ payload: {
|
|
|
+ projectId,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ setDumuList(data?.dumuList);
|
|
|
+ data?.dumuList?.map((item) => {
|
|
|
+ detailRun(item.id);
|
|
|
+ });
|
|
|
+ }, [data?.dumuList]);
|
|
|
+
|
|
|
+ // useEffect(() => {
|
|
|
+ // dispatch({
|
|
|
+ // type: 'eqSelfInspection/getPatrolRecordMandateInfo',
|
|
|
+ // payload: {
|
|
|
+ // extend_id: data.Id,
|
|
|
+ // project_id: projectId,
|
|
|
+ // mandate_type: 2
|
|
|
+ // },
|
|
|
+ // });
|
|
|
+ // }, [data]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Spin spinning={loading}>
|
|
|
+ <div className={styles.card}>
|
|
|
+ <Card title="自检报告">
|
|
|
+ <div>
|
|
|
+ <Row>
|
|
|
+ <Col span={24} style={{ fontSize: 20 }}>
|
|
|
+ 自检时间:{data?.CreatedTime}
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ <Row>
|
|
|
+ <Col span={8} style={{ fontSize: 20 }}>
|
|
|
+ 自检路线:{data?.RouteInfo?.Name}
|
|
|
+ </Col>
|
|
|
+ <Col span={8} style={{ fontSize: 20 }}>
|
|
|
+ 工艺段:{data?.RouteInfo?.GroupID}
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ <Row>
|
|
|
+ {result?.map((item) => {
|
|
|
+ return (
|
|
|
+ <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
|
|
|
+ <div>{item?.label}:</div>
|
|
|
+ <div style={{ color: item.color }}>{item?.value}</div>
|
|
|
+ </Col>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </Row>
|
|
|
+ {/* <Row>
|
|
|
+ <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
|
|
|
+ <div>任务类型:</div>
|
|
|
+ <div style={{ color: '#7bfffb' }}>系统自检</div>
|
|
|
+ </Col>
|
|
|
+ <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
|
|
|
+ <div>任务负责人:</div>
|
|
|
+ <div style={{ color: '#fff' }}>{userList.find(item => item.ID === mandateInfo?.ResponsiblePeople)?.CName || ''}</div>
|
|
|
+ </Col>
|
|
|
+ <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
|
|
|
+ <div>任务状态:</div>
|
|
|
+ <div style={{ color: '#7bfffb' }}>{getStatusText(mandateInfo?.Status)}</div>
|
|
|
+ </Col>
|
|
|
+ </Row> */}
|
|
|
+ </div>
|
|
|
+ </Card>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 设备自检报告 */}
|
|
|
+ <ReportCom
|
|
|
+ sendMessageToUnity={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ waringData={data?.extendWarningData}
|
|
|
+ allData={data?.extendWarningAllData}
|
|
|
+ key="extend"
|
|
|
+ type={'extend'}
|
|
|
+ userList={userList}
|
|
|
+ title={
|
|
|
+ <>
|
|
|
+ <div className={styles.text}>设备自检报告</div>
|
|
|
+ </>
|
|
|
+ }
|
|
|
+ ></ReportCom>
|
|
|
+
|
|
|
+ {/* 工艺自检报告"> */}
|
|
|
+ <div>
|
|
|
+ <div className={styles.tabBarExtraContent}>
|
|
|
+ <div className={styles.text} style={{ height: 52, width: '50%' }}>
|
|
|
+ <>
|
|
|
+ <div>工艺自检报告</div>
|
|
|
+ </>
|
|
|
+ </div>
|
|
|
+ <div className={styles.abnormal}>
|
|
|
+ <div className={styles.text} style={{ float: 'right' }}>
|
|
|
+ 异常({data?.FaultAnalysis?.length || 0})
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <AalysisTable
|
|
|
+ onClickItem={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ data={data}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ {/* 安全隐患自检报告"> */}
|
|
|
+ <div>
|
|
|
+ <div className={styles.tabBarExtraContent}>
|
|
|
+ <div className={styles.text} style={{ height: 52, width: '50%' }}>
|
|
|
+ <>
|
|
|
+ <div>安全隐患自检报告</div>
|
|
|
+ </>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {/* 环境异常 */}
|
|
|
+ <ReportCom
|
|
|
+ sendMessageToUnity={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ waringData={data?.sensorWaringData}
|
|
|
+ allData={data?.sensor}
|
|
|
+ data={data?.sensorWaringData}
|
|
|
+ key="sensor"
|
|
|
+ type={'sensor'}
|
|
|
+ userList={userList}
|
|
|
+ title={<div style={{ color: '#7bfffb', fontSize: 22 }}>环境异常</div>}
|
|
|
+ ></ReportCom>
|
|
|
+
|
|
|
+ {/* 安防检测异常 */}
|
|
|
+ <ReportDumCom
|
|
|
+ data={dumuList}
|
|
|
+ title={
|
|
|
+ <div style={{ color: '#7bfffb', fontSize: 22 }}>安防检测异常</div>
|
|
|
+ }
|
|
|
+ />
|
|
|
+
|
|
|
+ {/* 电器检测异常 */}
|
|
|
+ <ReportCom
|
|
|
+ sendMessageToUnity={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ waringData={[]}
|
|
|
+ allData={[]}
|
|
|
+ key="extend"
|
|
|
+ type={'extend'}
|
|
|
+ userList={userList}
|
|
|
+ title={
|
|
|
+ <div style={{ color: '#7bfffb', fontSize: 22 }}>电气检测异常</div>
|
|
|
+ }
|
|
|
+ ></ReportCom>
|
|
|
+
|
|
|
+ {/* 密闭空间检测异常 */}
|
|
|
+ <ReportCom
|
|
|
+ sendMessageToUnity={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ waringData={[]}
|
|
|
+ allData={[]}
|
|
|
+ key="extend"
|
|
|
+ type={'extend'}
|
|
|
+ userList={userList}
|
|
|
+ title={
|
|
|
+ <div style={{ color: '#7bfffb', fontSize: 22 }}>
|
|
|
+ 密闭空间检测异常
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ ></ReportCom>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* </Card> */}
|
|
|
+ </Spin>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+export function DeviceTable(props) {
|
|
|
+ const {
|
|
|
+ onClickItem,
|
|
|
+ data = {},
|
|
|
+ items,
|
|
|
+ onErrorHandle,
|
|
|
+ select,
|
|
|
+ userList,
|
|
|
+ type,
|
|
|
+ } = props;
|
|
|
+ const { ProjectId, Id } = data;
|
|
|
+ const [loading, setLoading] = useState(false);
|
|
|
+ const [visible, setVisible] = useState(false);
|
|
|
+ const [errVisible, setErrVisible] = useState(false);
|
|
|
+ const [currentItem, setCurrentItem] = useState({});
|
|
|
+ const isSensor = type == 'sensor';
|
|
|
+
|
|
|
+ const onClickThreshold = (record) => {
|
|
|
+ setCurrentItem(record);
|
|
|
+ setVisible(true);
|
|
|
+ };
|
|
|
+ const onClickError = (record) => {
|
|
|
+ setCurrentItem(record);
|
|
|
+ setErrVisible(true);
|
|
|
+ };
|
|
|
+ const handleError = async (values) => {
|
|
|
+ setLoading(true);
|
|
|
+ var res = await changeRecordStatus({
|
|
|
+ ...values,
|
|
|
+ Id: currentItem.Id,
|
|
|
+ DeviceCode: currentItem.DeviceCode,
|
|
|
+ DeviceName: currentItem.DeviceName,
|
|
|
+ RecordId: data.Id,
|
|
|
+ RepairMan: values.RepairMan * 1,
|
|
|
+ });
|
|
|
+ setLoading(false);
|
|
|
+ if (res) {
|
|
|
+ message.success('操作成功');
|
|
|
+ setErrVisible(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '设备名称',
|
|
|
+ width: '25%',
|
|
|
+ dataIndex: 'DeviceName',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '巡检项',
|
|
|
+ width: '20%',
|
|
|
+ dataIndex: 'TemplateItem.Name',
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // title: '设备位号',
|
|
|
+ // width: '16%',
|
|
|
+ // dataIndex: 'DeviceCode',
|
|
|
+ // },
|
|
|
+ {
|
|
|
+ title: '设定值范围',
|
|
|
+ width: '30%',
|
|
|
+ render: (record) => (
|
|
|
+ <ThresholdDetail
|
|
|
+ current={record.Value || 0}
|
|
|
+ data={record || {}}
|
|
|
+ // onClick={() => onClickThreshold(record)}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ width: '13%',
|
|
|
+ dataIndex: 'Status',
|
|
|
+ render: (Status) => {
|
|
|
+ switch (Status) {
|
|
|
+ case -1:
|
|
|
+ case 0:
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <i
|
|
|
+ className={styles.iconStatus}
|
|
|
+ style={{ background: '#60FE76' }}
|
|
|
+ ></i>
|
|
|
+ 正常
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ case 1:
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <i
|
|
|
+ className={styles.iconStatus}
|
|
|
+ style={{ background: '#FF8600' }}
|
|
|
+ ></i>
|
|
|
+ 异常
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ case 2:
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <i
|
|
|
+ className={styles.iconStatus}
|
|
|
+ style={{ background: '#FFE26D' }}
|
|
|
+ ></i>
|
|
|
+ 警告
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const handleClickItem = (data) => {
|
|
|
+ if (!isSensor) {
|
|
|
+ onClickItem(`DeviceTable-${data.Id}`, {
|
|
|
+ type: data.Status,
|
|
|
+ deviceCode: data.DeviceCode,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ onClickItem(`DeviceTable-${data.Id}`, {
|
|
|
+ // type: data.Status,
|
|
|
+ deviceCode: data.DeviceCode,
|
|
|
+ value: Number(data.Value || 0),
|
|
|
+ threshold: data.JsonNumThreshold,
|
|
|
+ });
|
|
|
+ UnityAction.sendMsg('SinglePowerEnvironFromWeb', JSON.stringify(data));
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ console.log('温控', items);
|
|
|
+ if (isSensor)
|
|
|
+ UnityAction.sendMsg('PowerEnvironsFromWeb', JSON.stringify(items));
|
|
|
+ }, [items]);
|
|
|
+
|
|
|
+ if (!isSensor) {
|
|
|
+ columns.push({
|
|
|
+ title: '操作',
|
|
|
+ width: '12%',
|
|
|
+ render: (record) =>
|
|
|
+ record.Status == 1 && (
|
|
|
+ <a style={{ color: '#7BFFFB' }} onClick={() => onClickError(record)}>
|
|
|
+ 异常处理
|
|
|
+ </a>
|
|
|
+ ),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <Table
|
|
|
+ columns={columns}
|
|
|
+ dataSource={items}
|
|
|
+ rowKey="Id"
|
|
|
+ onRow={(data) => {
|
|
|
+ return {
|
|
|
+ onClick: () => {
|
|
|
+ handleClickItem(data);
|
|
|
+ },
|
|
|
+ };
|
|
|
+ }}
|
|
|
+ locale={{
|
|
|
+ emptyText: <Empty />,
|
|
|
+ }}
|
|
|
+ rowClassName={(record) =>
|
|
|
+ `DeviceTable-${record.Id}` == select ? styles.select : null
|
|
|
+ }
|
|
|
+ />
|
|
|
+ <ThresholdModal
|
|
|
+ open={visible}
|
|
|
+ data={currentItem.JsonNumThreshold}
|
|
|
+ onClose={() => setVisible(false)}
|
|
|
+ />
|
|
|
+ <ErrorHandleModal
|
|
|
+ open={errVisible}
|
|
|
+ userList={userList}
|
|
|
+ onCancel={() => setErrVisible(false)}
|
|
|
+ onOk={handleError}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function AalysisTable(props) {
|
|
|
+ const { onClickItem, data = {}, select } = props;
|
|
|
+ const { FaultAnalysis } = data;
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '异常名称',
|
|
|
+ width: '18%',
|
|
|
+ dataIndex: 'device_name',
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // title: '位号',
|
|
|
+ // width: '15%',
|
|
|
+ // dataIndex: 'device_code',
|
|
|
+ // },
|
|
|
+ {
|
|
|
+ title: '可能原因',
|
|
|
+ width: '30%',
|
|
|
+ render: (record) => record.reason,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '解决方案',
|
|
|
+ width: '52%',
|
|
|
+ render: (record) => {
|
|
|
+ if (record.fix_plan instanceof Array) {
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {record.fix_plan.map((item) => (
|
|
|
+ <div>
|
|
|
+ {item.content}
|
|
|
+ <br />
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ return record.fix_plan;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <Table
|
|
|
+ columns={columns}
|
|
|
+ dataSource={FaultAnalysis}
|
|
|
+ rowKey="device_code"
|
|
|
+ onRow={(data) => {
|
|
|
+ return {
|
|
|
+ onClick: () => {
|
|
|
+ onClickItem(`AalysisTable-${data.device_code}`, {
|
|
|
+ deviceCode: data.device_code,
|
|
|
+ });
|
|
|
+ }, // 点击行
|
|
|
+ };
|
|
|
+ }}
|
|
|
+ locale={{
|
|
|
+ emptyText: <Empty />,
|
|
|
+ }}
|
|
|
+ rowClassName={(record) =>
|
|
|
+ `AalysisTable-${record.device_code}` == select ? styles.select : null
|
|
|
+ }
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function ErrorHandleModal(props) {
|
|
|
+ const { visible, onCancel, onOk, userList } = props;
|
|
|
+ const [form] = Form.useForm();
|
|
|
+ const status = form.getFieldValue('Status');
|
|
|
+ const handleOk = () => {
|
|
|
+ form.validateFields((error, values) => {
|
|
|
+ if (error) return;
|
|
|
+ onOk({
|
|
|
+ ...values,
|
|
|
+ PlanTime: values?.PlanTime?.format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ });
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Modal
|
|
|
+ title="异常处理"
|
|
|
+ open={visible}
|
|
|
+ onCancel={onCancel}
|
|
|
+ onOk={handleOk}
|
|
|
+ destroyOnClose
|
|
|
+ >
|
|
|
+ <Form labelCol={{ span: 7 }} wrapperCol={{ span: 16 }}>
|
|
|
+ <Form.Item label="异常处理备注" name="ExceptionHandling">
|
|
|
+ <Input.TextArea />
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label="审核状态"
|
|
|
+ name="Status"
|
|
|
+ rules={[{ required: true, message: '请选择验收状态' }]}
|
|
|
+ >
|
|
|
+ <Select style={{ width: '100%' }} placeholder="请选择验收状态">
|
|
|
+ <Select.Option value={1}>已派遣</Select.Option>
|
|
|
+ <Select.Option value={2}>已通过</Select.Option>
|
|
|
+ </Select>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label="维修人"
|
|
|
+ name="RepairMan"
|
|
|
+ rules={[{ required: true, message: '请选择维修人' }]}
|
|
|
+ >
|
|
|
+ <Select
|
|
|
+ showSearch
|
|
|
+ placeholder="请选择维修人"
|
|
|
+ filterOption={(input, option) =>
|
|
|
+ option.props.children.indexOf(input) >= 0
|
|
|
+ }
|
|
|
+ style={{ width: '100%' }}
|
|
|
+ >
|
|
|
+ {userList?.map((item) => (
|
|
|
+ <Select.Option key={item.ID}>{item.CName}</Select.Option>
|
|
|
+ ))}
|
|
|
+ </Select>
|
|
|
+ </Form.Item>
|
|
|
+ {status == 1 && (
|
|
|
+ <>
|
|
|
+ <Form.Item
|
|
|
+ label="难度级别"
|
|
|
+ name="DifficultyLevel"
|
|
|
+ rules={[{ required: true, message: '请选择难度级别' }]}
|
|
|
+ >
|
|
|
+ <Select placeholder="请选择难度级别" style={{ width: '100%' }}>
|
|
|
+ <Select.Option value={0}>大修</Select.Option>
|
|
|
+ <Select.Option value={1}>项目维修</Select.Option>
|
|
|
+ <Select.Option value={2}>小修</Select.Option>
|
|
|
+ </Select>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label="维修方式"
|
|
|
+ name="RepairType"
|
|
|
+ rules={[{ required: true, message: '请选择维修方式' }]}
|
|
|
+ >
|
|
|
+ <Select placeholder="请选择维修方式" style={{ width: '100%' }}>
|
|
|
+ <Select.Option value={0}>自维</Select.Option>
|
|
|
+ <Select.Option value={1}>外委</Select.Option>
|
|
|
+ </Select>
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item
|
|
|
+ label="计划完成日期"
|
|
|
+ name="PlanTime"
|
|
|
+ rules={[{ required: true, message: '请选择计划完成日期' }]}
|
|
|
+ >
|
|
|
+ <DatePicker />
|
|
|
+ </Form.Item>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </Form>
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+export function WarningTable(props) {
|
|
|
+ const {
|
|
|
+ onClickItem,
|
|
|
+ data = {},
|
|
|
+ onErrorHandle,
|
|
|
+ select,
|
|
|
+ userList,
|
|
|
+ type,
|
|
|
+ items,
|
|
|
+ } = props;
|
|
|
+ const { ProjectId, Id } = data;
|
|
|
+ const [loading, setLoading] = useState(false);
|
|
|
+ const [visible, setVisible] = useState(false);
|
|
|
+ const [errVisible, setErrVisible] = useState(false);
|
|
|
+ const [currentItem, setCurrentItem] = useState({});
|
|
|
+ const isSensor = type == 'sensor';
|
|
|
+
|
|
|
+ const onClickThreshold = (record) => {
|
|
|
+ setCurrentItem(record);
|
|
|
+ setVisible(true);
|
|
|
+ };
|
|
|
+ const onClickError = (record) => {
|
|
|
+ setCurrentItem(record);
|
|
|
+ setErrVisible(true);
|
|
|
+ };
|
|
|
+ const handleError = async (values) => {
|
|
|
+ setLoading(true);
|
|
|
+ var res = await changeRecordStatus({
|
|
|
+ ...values,
|
|
|
+ Id: currentItem.Id,
|
|
|
+ DeviceCode: currentItem.DeviceCode,
|
|
|
+ DeviceName: currentItem.DeviceName,
|
|
|
+ RecordId: data.Id,
|
|
|
+ RepairMan: values.RepairMan * 1,
|
|
|
+ });
|
|
|
+ setLoading(false);
|
|
|
+ if (res) {
|
|
|
+ message.success('操作成功');
|
|
|
+ setErrVisible(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '设备名称',
|
|
|
+ width: '25%',
|
|
|
+ dataIndex: 'DeviceName',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '巡检项',
|
|
|
+ width: '20%',
|
|
|
+ dataIndex: 'TemplateItem.Name',
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // title: '设备位号',
|
|
|
+ // width: '16%',
|
|
|
+ // dataIndex: 'DeviceCode',
|
|
|
+ // },
|
|
|
+ {
|
|
|
+ title: '设定值范围',
|
|
|
+ width: '30%',
|
|
|
+ render: (record) => (
|
|
|
+ <ThresholdDetail
|
|
|
+ current={record.Value || 0}
|
|
|
+ data={record || {}}
|
|
|
+ // onClick={() => onClickThreshold(record)}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ width: '13%',
|
|
|
+ dataIndex: 'Status',
|
|
|
+ render: (Status) => {
|
|
|
+ switch (Status) {
|
|
|
+ case -1:
|
|
|
+ case 0:
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <i
|
|
|
+ className={styles.iconStatus}
|
|
|
+ style={{ background: '#60FE76' }}
|
|
|
+ ></i>
|
|
|
+ 正常
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ case 1:
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <i
|
|
|
+ className={styles.iconStatus}
|
|
|
+ style={{ background: '#FF8600' }}
|
|
|
+ ></i>
|
|
|
+ 异常
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ case 2:
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <i
|
|
|
+ className={styles.iconStatus}
|
|
|
+ style={{ background: '#FFE26D' }}
|
|
|
+ ></i>
|
|
|
+ 警告
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ const handleClickItem = (data) => {
|
|
|
+ if (!isSensor) {
|
|
|
+ onClickItem(`DeviceTable-${data.Id}`, {
|
|
|
+ type: data.Status,
|
|
|
+ deviceCode: data.DeviceCode,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ onClickItem(`DeviceTable-${data.Id}`, {
|
|
|
+ // type: data.Status,
|
|
|
+ deviceCode: data.DeviceCode,
|
|
|
+ value: Number(data.Value || 0),
|
|
|
+ threshold: data.JsonNumThreshold,
|
|
|
+ });
|
|
|
+ UnityAction.sendMsg('SinglePowerEnvironFromWeb', JSON.stringify(data));
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ if (!isSensor) {
|
|
|
+ columns.push({
|
|
|
+ title: '操作',
|
|
|
+ width: '12%',
|
|
|
+ render: (record) =>
|
|
|
+ record.Status == 1 && (
|
|
|
+ <a style={{ color: '#7BFFFB' }} onClick={() => onClickError(record)}>
|
|
|
+ 异常处理
|
|
|
+ </a>
|
|
|
+ ),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (isSensor)
|
|
|
+ UnityAction.sendMsg('PowerEnvironsFromWeb', JSON.stringify(items));
|
|
|
+ }, [items]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {/* <div className="table-total">当前列表总数 {Items?.length || 0}</div> */}
|
|
|
+ <Table
|
|
|
+ columns={columns}
|
|
|
+ dataSource={items}
|
|
|
+ rowKey="Id"
|
|
|
+ onRow={(data) => {
|
|
|
+ return {
|
|
|
+ onClick: () => {
|
|
|
+ handleClickItem(data);
|
|
|
+ },
|
|
|
+ };
|
|
|
+ }}
|
|
|
+ locale={{
|
|
|
+ emptyText: <Empty />,
|
|
|
+ }}
|
|
|
+ rowClassName={(record) =>
|
|
|
+ `DeviceTable-${record.Id}` == select ? styles.select : null
|
|
|
+ }
|
|
|
+ />
|
|
|
+ <ThresholdModal
|
|
|
+ open={visible}
|
|
|
+ data={currentItem.JsonNumThreshold}
|
|
|
+ onClose={() => setVisible(false)}
|
|
|
+ />
|
|
|
+ <ErrorHandleModal
|
|
|
+ open={errVisible}
|
|
|
+ userList={userList}
|
|
|
+ onCancel={() => setErrVisible(false)}
|
|
|
+ onOk={handleError}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function ReportCom(props) {
|
|
|
+ const {
|
|
|
+ sendMessageToUnity,
|
|
|
+ select,
|
|
|
+ waringData = [],
|
|
|
+ allData = [],
|
|
|
+ userList,
|
|
|
+ type,
|
|
|
+ title,
|
|
|
+ data,
|
|
|
+ } = props;
|
|
|
+ const [activeKey, setActiveKey] = useState('1');
|
|
|
+ const handleTabsChange = (activeKey) => {
|
|
|
+ setActiveKey(activeKey);
|
|
|
+ };
|
|
|
+ return (
|
|
|
+ <div className={styles.detailCard}>
|
|
|
+ <Tabs
|
|
|
+ defaultActiveKey="1"
|
|
|
+ tabBarExtraContent={
|
|
|
+ <div className={styles.tabBarExtraContent}>{title} </div>
|
|
|
+ }
|
|
|
+ onChange={handleTabsChange}
|
|
|
+ >
|
|
|
+ <Tabs.TabPane tab={`异常/警告(${waringData.length || 0})`} key="1">
|
|
|
+ {activeKey == '1' && (
|
|
|
+ <WarningTable
|
|
|
+ onClickItem={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ items={waringData}
|
|
|
+ key={type}
|
|
|
+ data={data}
|
|
|
+ type={type}
|
|
|
+ userList={userList}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Tabs.TabPane>
|
|
|
+ <Tabs.TabPane tab={`全部(${allData.length || 0})`} key="2">
|
|
|
+ {activeKey == '2' && (
|
|
|
+ <DeviceTable
|
|
|
+ onClickItem={sendMessageToUnity}
|
|
|
+ select={select}
|
|
|
+ items={allData}
|
|
|
+ data={data}
|
|
|
+ key={type}
|
|
|
+ type={type}
|
|
|
+ userList={userList}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Tabs.TabPane>
|
|
|
+ </Tabs>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function ReportDumCom(props) {
|
|
|
+ const { data = [], title } = props;
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '报警时间',
|
|
|
+ dataIndex: 'event_time',
|
|
|
+ render: (time) => dayjs(time).format('YYYY-MM-DD HH:mm:ss'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '设备名称',
|
|
|
+ dataIndex: 'device_name',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '报警类型',
|
|
|
+ dataIndex: 'event_type',
|
|
|
+ // render: type => alarmType[type],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '报警图片',
|
|
|
+ render: (item) => (
|
|
|
+ <ReactZmage
|
|
|
+ controller={{
|
|
|
+ // 关闭按钮
|
|
|
+ close: true,
|
|
|
+ // 旋转按钮
|
|
|
+ rotate: true,
|
|
|
+ // 缩放按钮
|
|
|
+ zoom: false,
|
|
|
+ // 下载按钮
|
|
|
+ download: false,
|
|
|
+ // 翻页按钮
|
|
|
+ flip: false,
|
|
|
+ // 多页指示
|
|
|
+ pagination: false,
|
|
|
+ }}
|
|
|
+ backdrop="rgba(255,255,255,0.5)"
|
|
|
+ style={{ height: '90px' }}
|
|
|
+ src={item.url}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <div className={styles.tabBarExtraContent}>
|
|
|
+ <div className={styles.text} style={{ height: 52, width: '60%' }}>
|
|
|
+ <>
|
|
|
+ <div>{title}</div>
|
|
|
+ </>
|
|
|
+ </div>
|
|
|
+ <div className={styles.abnormal}>
|
|
|
+ <div className={styles.text} style={{ float: 'right' }}>
|
|
|
+ 异常({data?.length || 0})
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Table
|
|
|
+ bordered
|
|
|
+ rowKey="event_time"
|
|
|
+ columns={columns}
|
|
|
+ dataSource={data}
|
|
|
+ locale={{
|
|
|
+ emptyText: <Empty />,
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+function base64ToImageUrl(base64String) {
|
|
|
+ const byteCharacters = atob(base64String);
|
|
|
+ const byteArrays = [];
|
|
|
+
|
|
|
+ for (let i = 0; i < byteCharacters.length; i++) {
|
|
|
+ byteArrays.push(byteCharacters.charCodeAt(i));
|
|
|
+ }
|
|
|
+
|
|
|
+ const byteArray = new Uint8Array(byteArrays);
|
|
|
+ const blob = new Blob([byteArray], { type: 'image/png' });
|
|
|
+ const imageUrl = URL.createObjectURL(blob);
|
|
|
+
|
|
|
+ return imageUrl;
|
|
|
+}
|
|
|
+
|
|
|
+function Empty() {
|
|
|
+ return (
|
|
|
+ <div style={{}}>
|
|
|
+ {/* <img src={require('@/assets/empty.png')} style={{ margin: '20px 0' }} /> */}
|
|
|
+ <p style={{ textAlign: 'center' }}>自检正常</p>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+export default connect(({ eqSelfInspection }) => ({
|
|
|
+ userList: eqSelfInspection.userList,
|
|
|
+ mandateInfo: eqSelfInspection.mandateInfo,
|
|
|
+}))(Detail);
|