Detail.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. import ThresholdDetail from '@/components/ThresholdDetail';
  2. import ThresholdModal from '@/components/ThresholdDetail/ThresholdModal';
  3. import { changeRecordStatus, getDumuDetail } from '@/services/eqSelfInspection';
  4. import { UnityAction } from '@/utils/utils';
  5. import { connect, useRequest } from '@umijs/max';
  6. import {
  7. Card,
  8. Col,
  9. DatePicker,
  10. Form,
  11. Input,
  12. Modal,
  13. Row,
  14. Select,
  15. Spin,
  16. Table,
  17. Tabs,
  18. message,
  19. } from 'antd';
  20. import dayjs from 'dayjs';
  21. import { useEffect, useMemo, useState } from 'react';
  22. import ReactZmage from 'react-zmage';
  23. import styles from './PatrolReportDetail.less';
  24. function Detail(props) {
  25. const { data, userList, projectId, dispatch, loading = false } = props;
  26. const [select, setSelect] = useState();
  27. const [dumuList, setDumuList] = useState([]);
  28. const sendMessageToUnity = (select, data) => {
  29. setSelect(select);
  30. // console.log(data);
  31. if (window.HightlightEquipment) {
  32. window.HightlightEquipment(data);
  33. }
  34. };
  35. const getTextColor = (status) => {
  36. switch (status) {
  37. case '警告':
  38. return '#FFE26D';
  39. case '异常':
  40. return '#FF8600';
  41. case '正常':
  42. return '#60FE76';
  43. default:
  44. return '#60FE76';
  45. }
  46. };
  47. const { run: detailRun } = useRequest(getDumuDetail, {
  48. manual: true,
  49. fetchKey: (id) => id,
  50. onSuccess: (data) => {
  51. var item = dumuList?.find((child) => child.id === data.id);
  52. if (item) {
  53. item.url = base64ToImageUrl(data.event_bg);
  54. }
  55. setDumuList([...dumuList]);
  56. },
  57. });
  58. const result = useMemo(() => {
  59. var resultArr = [];
  60. var tempResult = data?.PatrolResult;
  61. var tempArr = tempResult?.split(';');
  62. if (tempArr?.length > 0) {
  63. tempArr?.forEach((item, index) => {
  64. var tempItem = item;
  65. var itemSplit = tempItem.split(':');
  66. if (itemSplit?.length > 1) {
  67. var label = '';
  68. var value = itemSplit[1];
  69. if (index === 0) label = '设备自检';
  70. else if (index === 1) label = '工艺自检';
  71. else {
  72. label = '安全隐患';
  73. value = data?.secureStatus === 0 ? '正常' : '异常';
  74. }
  75. resultArr.push({
  76. label,
  77. value,
  78. color: getTextColor(value),
  79. });
  80. }
  81. });
  82. }
  83. return resultArr;
  84. }, [data]);
  85. useEffect(() => {
  86. dispatch({
  87. type: 'eqSelfInspection/fetchUserList',
  88. payload: {
  89. projectId,
  90. },
  91. });
  92. }, []);
  93. useEffect(() => {
  94. setDumuList(data?.dumuList);
  95. data?.dumuList?.map((item) => {
  96. detailRun(item.id);
  97. });
  98. }, [data?.dumuList]);
  99. // useEffect(() => {
  100. // dispatch({
  101. // type: 'eqSelfInspection/getPatrolRecordMandateInfo',
  102. // payload: {
  103. // extend_id: data.Id,
  104. // project_id: projectId,
  105. // mandate_type: 2
  106. // },
  107. // });
  108. // }, [data]);
  109. return (
  110. <Spin spinning={loading}>
  111. <div className={styles.card}>
  112. <Card title="自检报告">
  113. <div>
  114. <Row>
  115. <Col span={24} style={{ fontSize: 20 }}>
  116. 自检时间:{data?.CreatedTime}
  117. </Col>
  118. </Row>
  119. <Row>
  120. <Col span={8} style={{ fontSize: 20 }}>
  121. 自检路线:{data?.RouteInfo?.Name}
  122. </Col>
  123. <Col span={8} style={{ fontSize: 20 }}>
  124. 工艺段:{data?.RouteInfo?.GroupID}
  125. </Col>
  126. </Row>
  127. <Row>
  128. {result?.map((item) => {
  129. return (
  130. <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
  131. <div>{item?.label}:</div>
  132. <div style={{ color: item.color }}>{item?.value}</div>
  133. </Col>
  134. );
  135. })}
  136. </Row>
  137. {/* <Row>
  138. <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
  139. <div>任务类型:</div>
  140. <div style={{ color: '#7bfffb' }}>系统自检</div>
  141. </Col>
  142. <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
  143. <div>任务负责人:</div>
  144. <div style={{ color: '#fff' }}>{userList.find(item => item.ID === mandateInfo?.ResponsiblePeople)?.CName || ''}</div>
  145. </Col>
  146. <Col span={8} style={{ display: 'flex', fontSize: 20 }}>
  147. <div>任务状态:</div>
  148. <div style={{ color: '#7bfffb' }}>{getStatusText(mandateInfo?.Status)}</div>
  149. </Col>
  150. </Row> */}
  151. </div>
  152. </Card>
  153. </div>
  154. {/* 设备自检报告 */}
  155. <ReportCom
  156. sendMessageToUnity={sendMessageToUnity}
  157. select={select}
  158. waringData={data?.extendWarningData}
  159. allData={data?.extendWarningAllData}
  160. key="extend"
  161. type={'extend'}
  162. userList={userList}
  163. title={
  164. <>
  165. <div className={styles.text}>设备自检报告</div>
  166. </>
  167. }
  168. ></ReportCom>
  169. {/* 工艺自检报告"> */}
  170. <div>
  171. <div className={styles.tabBarExtraContent}>
  172. <div className={styles.text} style={{ height: 52, width: '50%' }}>
  173. <>
  174. <div>工艺自检报告</div>
  175. </>
  176. </div>
  177. <div className={styles.abnormal}>
  178. <div className={styles.text} style={{ float: 'right' }}>
  179. 异常({data?.FaultAnalysis?.length || 0})
  180. </div>
  181. </div>
  182. </div>
  183. <AalysisTable
  184. onClickItem={sendMessageToUnity}
  185. select={select}
  186. data={data}
  187. />
  188. </div>
  189. {/* 安全隐患自检报告"> */}
  190. <div>
  191. <div className={styles.tabBarExtraContent}>
  192. <div className={styles.text} style={{ height: 52, width: '50%' }}>
  193. <>
  194. <div>安全隐患自检报告</div>
  195. </>
  196. </div>
  197. </div>
  198. {/* 环境异常 */}
  199. <ReportCom
  200. sendMessageToUnity={sendMessageToUnity}
  201. select={select}
  202. waringData={data?.sensorWaringData}
  203. allData={data?.sensor}
  204. data={data?.sensorWaringData}
  205. key="sensor"
  206. type={'sensor'}
  207. userList={userList}
  208. title={<div style={{ color: '#7bfffb', fontSize: 22 }}>环境异常</div>}
  209. ></ReportCom>
  210. {/* 安防检测异常 */}
  211. <ReportDumCom
  212. data={dumuList}
  213. title={
  214. <div style={{ color: '#7bfffb', fontSize: 22 }}>安防检测异常</div>
  215. }
  216. />
  217. {/* 电器检测异常 */}
  218. <ReportCom
  219. sendMessageToUnity={sendMessageToUnity}
  220. select={select}
  221. waringData={[]}
  222. allData={[]}
  223. key="extend"
  224. type={'extend'}
  225. userList={userList}
  226. title={
  227. <div style={{ color: '#7bfffb', fontSize: 22 }}>电气检测异常</div>
  228. }
  229. ></ReportCom>
  230. {/* 密闭空间检测异常 */}
  231. <ReportCom
  232. sendMessageToUnity={sendMessageToUnity}
  233. select={select}
  234. waringData={[]}
  235. allData={[]}
  236. key="extend"
  237. type={'extend'}
  238. userList={userList}
  239. title={
  240. <div style={{ color: '#7bfffb', fontSize: 22 }}>
  241. 密闭空间检测异常
  242. </div>
  243. }
  244. ></ReportCom>
  245. </div>
  246. {/* </Card> */}
  247. </Spin>
  248. );
  249. }
  250. export function DeviceTable(props) {
  251. const {
  252. onClickItem,
  253. data = {},
  254. items,
  255. onErrorHandle,
  256. select,
  257. userList,
  258. type,
  259. } = props;
  260. const { ProjectId, Id } = data;
  261. const [loading, setLoading] = useState(false);
  262. const [visible, setVisible] = useState(false);
  263. const [errVisible, setErrVisible] = useState(false);
  264. const [currentItem, setCurrentItem] = useState({});
  265. const isSensor = type == 'sensor';
  266. const onClickThreshold = (record) => {
  267. setCurrentItem(record);
  268. setVisible(true);
  269. };
  270. const onClickError = (record) => {
  271. setCurrentItem(record);
  272. setErrVisible(true);
  273. };
  274. const handleError = async (values) => {
  275. setLoading(true);
  276. var res = await changeRecordStatus({
  277. ...values,
  278. Id: currentItem.Id,
  279. DeviceCode: currentItem.DeviceCode,
  280. DeviceName: currentItem.DeviceName,
  281. RecordId: data.Id,
  282. RepairMan: values.RepairMan * 1,
  283. });
  284. setLoading(false);
  285. if (res) {
  286. message.success('操作成功');
  287. setErrVisible(false);
  288. }
  289. };
  290. const columns = [
  291. {
  292. title: '设备名称',
  293. width: '25%',
  294. dataIndex: 'DeviceName',
  295. },
  296. {
  297. title: '巡检项',
  298. width: '20%',
  299. dataIndex: 'TemplateItem.Name',
  300. },
  301. // {
  302. // title: '设备位号',
  303. // width: '16%',
  304. // dataIndex: 'DeviceCode',
  305. // },
  306. {
  307. title: '设定值范围',
  308. width: '30%',
  309. render: (record) => (
  310. <ThresholdDetail
  311. current={record.Value || 0}
  312. data={record || {}}
  313. // onClick={() => onClickThreshold(record)}
  314. />
  315. ),
  316. },
  317. {
  318. title: '状态',
  319. width: '13%',
  320. dataIndex: 'Status',
  321. render: (Status) => {
  322. switch (Status) {
  323. case -1:
  324. case 0:
  325. return (
  326. <div>
  327. <i
  328. className={styles.iconStatus}
  329. style={{ background: '#60FE76' }}
  330. ></i>
  331. 正常
  332. </div>
  333. );
  334. case 1:
  335. return (
  336. <div>
  337. <i
  338. className={styles.iconStatus}
  339. style={{ background: '#FF8600' }}
  340. ></i>
  341. 异常
  342. </div>
  343. );
  344. case 2:
  345. return (
  346. <div>
  347. <i
  348. className={styles.iconStatus}
  349. style={{ background: '#FFE26D' }}
  350. ></i>
  351. 警告
  352. </div>
  353. );
  354. }
  355. },
  356. },
  357. ];
  358. const handleClickItem = (data) => {
  359. if (!isSensor) {
  360. onClickItem(`DeviceTable-${data.Id}`, {
  361. type: data.Status,
  362. deviceCode: data.DeviceCode,
  363. });
  364. } else {
  365. onClickItem(`DeviceTable-${data.Id}`, {
  366. // type: data.Status,
  367. deviceCode: data.DeviceCode,
  368. value: Number(data.Value || 0),
  369. threshold: data.JsonNumThreshold,
  370. });
  371. UnityAction.sendMsg('SinglePowerEnvironFromWeb', JSON.stringify(data));
  372. }
  373. };
  374. useEffect(() => {
  375. console.log('温控', items);
  376. if (isSensor)
  377. UnityAction.sendMsg('PowerEnvironsFromWeb', JSON.stringify(items));
  378. }, [items]);
  379. if (!isSensor) {
  380. columns.push({
  381. title: '操作',
  382. width: '12%',
  383. render: (record) =>
  384. record.Status == 1 && (
  385. <a style={{ color: '#7BFFFB' }} onClick={() => onClickError(record)}>
  386. 异常处理
  387. </a>
  388. ),
  389. });
  390. }
  391. return (
  392. <div>
  393. <Table
  394. columns={columns}
  395. dataSource={items}
  396. rowKey="Id"
  397. onRow={(data) => {
  398. return {
  399. onClick: () => {
  400. handleClickItem(data);
  401. },
  402. };
  403. }}
  404. locale={{
  405. emptyText: <Empty />,
  406. }}
  407. rowClassName={(record) =>
  408. `DeviceTable-${record.Id}` == select ? styles.select : null
  409. }
  410. />
  411. <ThresholdModal
  412. open={visible}
  413. data={currentItem.JsonNumThreshold}
  414. onClose={() => setVisible(false)}
  415. />
  416. <ErrorHandleModal
  417. open={errVisible}
  418. userList={userList}
  419. onCancel={() => setErrVisible(false)}
  420. onOk={handleError}
  421. />
  422. </div>
  423. );
  424. }
  425. function AalysisTable(props) {
  426. const { onClickItem, data = {}, select } = props;
  427. const { FaultAnalysis } = data;
  428. const columns = [
  429. {
  430. title: '异常名称',
  431. width: '18%',
  432. dataIndex: 'device_name',
  433. },
  434. // {
  435. // title: '位号',
  436. // width: '15%',
  437. // dataIndex: 'device_code',
  438. // },
  439. {
  440. title: '可能原因',
  441. width: '30%',
  442. render: (record) => record.reason,
  443. },
  444. {
  445. title: '解决方案',
  446. width: '52%',
  447. render: (record) => {
  448. if (record.fix_plan instanceof Array) {
  449. return (
  450. <div>
  451. {record.fix_plan.map((item) => (
  452. <div>
  453. {item.content}
  454. <br />
  455. </div>
  456. ))}
  457. </div>
  458. );
  459. } else {
  460. return record.fix_plan;
  461. }
  462. },
  463. },
  464. ];
  465. return (
  466. <div>
  467. <Table
  468. columns={columns}
  469. dataSource={FaultAnalysis}
  470. rowKey="device_code"
  471. onRow={(data) => {
  472. return {
  473. onClick: () => {
  474. onClickItem(`AalysisTable-${data.device_code}`, {
  475. deviceCode: data.device_code,
  476. });
  477. }, // 点击行
  478. };
  479. }}
  480. locale={{
  481. emptyText: <Empty />,
  482. }}
  483. rowClassName={(record) =>
  484. `AalysisTable-${record.device_code}` == select ? styles.select : null
  485. }
  486. />
  487. </div>
  488. );
  489. }
  490. function ErrorHandleModal(props) {
  491. const { visible, onCancel, onOk, userList } = props;
  492. const [form] = Form.useForm();
  493. const status = form.getFieldValue('Status');
  494. const handleOk = () => {
  495. form.validateFields((error, values) => {
  496. if (error) return;
  497. onOk({
  498. ...values,
  499. PlanTime: values?.PlanTime?.format('YYYY-MM-DD HH:mm:ss'),
  500. });
  501. });
  502. };
  503. return (
  504. <Modal
  505. title="异常处理"
  506. open={visible}
  507. onCancel={onCancel}
  508. onOk={handleOk}
  509. destroyOnClose
  510. >
  511. <Form labelCol={{ span: 7 }} wrapperCol={{ span: 16 }}>
  512. <Form.Item label="异常处理备注" name="ExceptionHandling">
  513. <Input.TextArea />
  514. </Form.Item>
  515. <Form.Item
  516. label="审核状态"
  517. name="Status"
  518. rules={[{ required: true, message: '请选择验收状态' }]}
  519. >
  520. <Select style={{ width: '100%' }} placeholder="请选择验收状态">
  521. <Select.Option value={1}>已派遣</Select.Option>
  522. <Select.Option value={2}>已通过</Select.Option>
  523. </Select>
  524. </Form.Item>
  525. <Form.Item
  526. label="维修人"
  527. name="RepairMan"
  528. rules={[{ required: true, message: '请选择维修人' }]}
  529. >
  530. <Select
  531. showSearch
  532. placeholder="请选择维修人"
  533. filterOption={(input, option) =>
  534. option.props.children.indexOf(input) >= 0
  535. }
  536. style={{ width: '100%' }}
  537. >
  538. {userList?.map((item) => (
  539. <Select.Option key={item.ID}>{item.CName}</Select.Option>
  540. ))}
  541. </Select>
  542. </Form.Item>
  543. {status == 1 && (
  544. <>
  545. <Form.Item
  546. label="难度级别"
  547. name="DifficultyLevel"
  548. rules={[{ required: true, message: '请选择难度级别' }]}
  549. >
  550. <Select placeholder="请选择难度级别" style={{ width: '100%' }}>
  551. <Select.Option value={0}>大修</Select.Option>
  552. <Select.Option value={1}>项目维修</Select.Option>
  553. <Select.Option value={2}>小修</Select.Option>
  554. </Select>
  555. </Form.Item>
  556. <Form.Item
  557. label="维修方式"
  558. name="RepairType"
  559. rules={[{ required: true, message: '请选择维修方式' }]}
  560. >
  561. <Select placeholder="请选择维修方式" style={{ width: '100%' }}>
  562. <Select.Option value={0}>自维</Select.Option>
  563. <Select.Option value={1}>外委</Select.Option>
  564. </Select>
  565. </Form.Item>
  566. <Form.Item
  567. label="计划完成日期"
  568. name="PlanTime"
  569. rules={[{ required: true, message: '请选择计划完成日期' }]}
  570. >
  571. <DatePicker />
  572. </Form.Item>
  573. </>
  574. )}
  575. </Form>
  576. </Modal>
  577. );
  578. }
  579. export function WarningTable(props) {
  580. const {
  581. onClickItem,
  582. data = {},
  583. onErrorHandle,
  584. select,
  585. userList,
  586. type,
  587. items,
  588. } = props;
  589. const { ProjectId, Id } = data;
  590. const [loading, setLoading] = useState(false);
  591. const [visible, setVisible] = useState(false);
  592. const [errVisible, setErrVisible] = useState(false);
  593. const [currentItem, setCurrentItem] = useState({});
  594. const isSensor = type == 'sensor';
  595. const onClickThreshold = (record) => {
  596. setCurrentItem(record);
  597. setVisible(true);
  598. };
  599. const onClickError = (record) => {
  600. setCurrentItem(record);
  601. setErrVisible(true);
  602. };
  603. const handleError = async (values) => {
  604. setLoading(true);
  605. var res = await changeRecordStatus({
  606. ...values,
  607. Id: currentItem.Id,
  608. DeviceCode: currentItem.DeviceCode,
  609. DeviceName: currentItem.DeviceName,
  610. RecordId: data.Id,
  611. RepairMan: values.RepairMan * 1,
  612. });
  613. setLoading(false);
  614. if (res) {
  615. message.success('操作成功');
  616. setErrVisible(false);
  617. }
  618. };
  619. const columns = [
  620. {
  621. title: '设备名称',
  622. width: '25%',
  623. dataIndex: 'DeviceName',
  624. },
  625. {
  626. title: '巡检项',
  627. width: '20%',
  628. dataIndex: 'TemplateItem.Name',
  629. },
  630. // {
  631. // title: '设备位号',
  632. // width: '16%',
  633. // dataIndex: 'DeviceCode',
  634. // },
  635. {
  636. title: '设定值范围',
  637. width: '30%',
  638. render: (record) => (
  639. <ThresholdDetail
  640. current={record.Value || 0}
  641. data={record || {}}
  642. // onClick={() => onClickThreshold(record)}
  643. />
  644. ),
  645. },
  646. {
  647. title: '状态',
  648. width: '13%',
  649. dataIndex: 'Status',
  650. render: (Status) => {
  651. switch (Status) {
  652. case -1:
  653. case 0:
  654. return (
  655. <div>
  656. <i
  657. className={styles.iconStatus}
  658. style={{ background: '#60FE76' }}
  659. ></i>
  660. 正常
  661. </div>
  662. );
  663. case 1:
  664. return (
  665. <div>
  666. <i
  667. className={styles.iconStatus}
  668. style={{ background: '#FF8600' }}
  669. ></i>
  670. 异常
  671. </div>
  672. );
  673. case 2:
  674. return (
  675. <div>
  676. <i
  677. className={styles.iconStatus}
  678. style={{ background: '#FFE26D' }}
  679. ></i>
  680. 警告
  681. </div>
  682. );
  683. }
  684. },
  685. },
  686. ];
  687. const handleClickItem = (data) => {
  688. if (!isSensor) {
  689. onClickItem(`DeviceTable-${data.Id}`, {
  690. type: data.Status,
  691. deviceCode: data.DeviceCode,
  692. });
  693. } else {
  694. onClickItem(`DeviceTable-${data.Id}`, {
  695. // type: data.Status,
  696. deviceCode: data.DeviceCode,
  697. value: Number(data.Value || 0),
  698. threshold: data.JsonNumThreshold,
  699. });
  700. UnityAction.sendMsg('SinglePowerEnvironFromWeb', JSON.stringify(data));
  701. }
  702. };
  703. if (!isSensor) {
  704. columns.push({
  705. title: '操作',
  706. width: '12%',
  707. render: (record) =>
  708. record.Status == 1 && (
  709. <a style={{ color: '#7BFFFB' }} onClick={() => onClickError(record)}>
  710. 异常处理
  711. </a>
  712. ),
  713. });
  714. }
  715. useEffect(() => {
  716. if (isSensor)
  717. UnityAction.sendMsg('PowerEnvironsFromWeb', JSON.stringify(items));
  718. }, [items]);
  719. return (
  720. <div>
  721. {/* <div className="table-total">当前列表总数 {Items?.length || 0}</div> */}
  722. <Table
  723. columns={columns}
  724. dataSource={items}
  725. rowKey="Id"
  726. onRow={(data) => {
  727. return {
  728. onClick: () => {
  729. handleClickItem(data);
  730. },
  731. };
  732. }}
  733. locale={{
  734. emptyText: <Empty />,
  735. }}
  736. rowClassName={(record) =>
  737. `DeviceTable-${record.Id}` == select ? styles.select : null
  738. }
  739. />
  740. <ThresholdModal
  741. open={visible}
  742. data={currentItem.JsonNumThreshold}
  743. onClose={() => setVisible(false)}
  744. />
  745. <ErrorHandleModal
  746. open={errVisible}
  747. userList={userList}
  748. onCancel={() => setErrVisible(false)}
  749. onOk={handleError}
  750. />
  751. </div>
  752. );
  753. }
  754. function ReportCom(props) {
  755. const {
  756. sendMessageToUnity,
  757. select,
  758. waringData = [],
  759. allData = [],
  760. userList,
  761. type,
  762. title,
  763. data,
  764. } = props;
  765. const [activeKey, setActiveKey] = useState('1');
  766. const handleTabsChange = (activeKey) => {
  767. setActiveKey(activeKey);
  768. };
  769. return (
  770. <div className={styles.detailCard}>
  771. <Tabs
  772. defaultActiveKey="1"
  773. tabBarExtraContent={
  774. <div className={styles.tabBarExtraContent}>{title} </div>
  775. }
  776. onChange={handleTabsChange}
  777. >
  778. <Tabs.TabPane tab={`异常/警告(${waringData.length || 0})`} key="1">
  779. {activeKey == '1' && (
  780. <WarningTable
  781. onClickItem={sendMessageToUnity}
  782. select={select}
  783. items={waringData}
  784. key={type}
  785. data={data}
  786. type={type}
  787. userList={userList}
  788. />
  789. )}
  790. </Tabs.TabPane>
  791. <Tabs.TabPane tab={`全部(${allData.length || 0})`} key="2">
  792. {activeKey == '2' && (
  793. <DeviceTable
  794. onClickItem={sendMessageToUnity}
  795. select={select}
  796. items={allData}
  797. data={data}
  798. key={type}
  799. type={type}
  800. userList={userList}
  801. />
  802. )}
  803. </Tabs.TabPane>
  804. </Tabs>
  805. </div>
  806. );
  807. }
  808. function ReportDumCom(props) {
  809. const { data = [], title } = props;
  810. const columns = [
  811. {
  812. title: '报警时间',
  813. dataIndex: 'event_time',
  814. render: (time) => dayjs(time).format('YYYY-MM-DD HH:mm:ss'),
  815. },
  816. {
  817. title: '设备名称',
  818. dataIndex: 'device_name',
  819. },
  820. {
  821. title: '报警类型',
  822. dataIndex: 'event_type',
  823. // render: type => alarmType[type],
  824. },
  825. {
  826. title: '报警图片',
  827. render: (item) => (
  828. <ReactZmage
  829. controller={{
  830. // 关闭按钮
  831. close: true,
  832. // 旋转按钮
  833. rotate: true,
  834. // 缩放按钮
  835. zoom: false,
  836. // 下载按钮
  837. download: false,
  838. // 翻页按钮
  839. flip: false,
  840. // 多页指示
  841. pagination: false,
  842. }}
  843. backdrop="rgba(255,255,255,0.5)"
  844. style={{ height: '90px' }}
  845. src={item.url}
  846. />
  847. ),
  848. },
  849. ];
  850. return (
  851. <div>
  852. <div className={styles.tabBarExtraContent}>
  853. <div className={styles.text} style={{ height: 52, width: '60%' }}>
  854. <>
  855. <div>{title}</div>
  856. </>
  857. </div>
  858. <div className={styles.abnormal}>
  859. <div className={styles.text} style={{ float: 'right' }}>
  860. 异常({data?.length || 0})
  861. </div>
  862. </div>
  863. </div>
  864. <Table
  865. bordered
  866. rowKey="event_time"
  867. columns={columns}
  868. dataSource={data}
  869. locale={{
  870. emptyText: <Empty />,
  871. }}
  872. />
  873. </div>
  874. );
  875. }
  876. function base64ToImageUrl(base64String) {
  877. const byteCharacters = atob(base64String);
  878. const byteArrays = [];
  879. for (let i = 0; i < byteCharacters.length; i++) {
  880. byteArrays.push(byteCharacters.charCodeAt(i));
  881. }
  882. const byteArray = new Uint8Array(byteArrays);
  883. const blob = new Blob([byteArray], { type: 'image/png' });
  884. const imageUrl = URL.createObjectURL(blob);
  885. return imageUrl;
  886. }
  887. function Empty() {
  888. return (
  889. <div style={{}}>
  890. {/* <img src={require('@/assets/empty.png')} style={{ margin: '20px 0' }} /> */}
  891. <p style={{ textAlign: 'center' }}>自检正常</p>
  892. </div>
  893. );
  894. }
  895. export default connect(({ eqSelfInspection }) => ({
  896. userList: eqSelfInspection.userList,
  897. mandateInfo: eqSelfInspection.mandateInfo,
  898. }))(Detail);