Detail.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. import ModuleTitle from '@/components/ManagementPage/moduleTitle';
  2. import TabsContent from '@/components/TabsContent';
  3. import ThresholdDetail from '@/components/ThresholdDetail';
  4. import ThresholdModal from '@/components/ThresholdDetail/ThresholdModal';
  5. import { changeRecordStatus, getDumuDetail } from '@/services/eqSelfInspection';
  6. import { UnityAction } from '@/utils/utils';
  7. import { connect, useRequest } from '@umijs/max';
  8. import {
  9. Col,
  10. DatePicker,
  11. Form,
  12. Input,
  13. Modal,
  14. Row,
  15. Select,
  16. Spin,
  17. Table,
  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. if (window.HightlightEquipment) {
  31. window.HightlightEquipment(data);
  32. }
  33. };
  34. const getTextColor = (status) => {
  35. switch (status) {
  36. case '警告':
  37. return '#FFE26D';
  38. case '异常':
  39. return '#FE5850';
  40. case '正常':
  41. return '#12CEB3';
  42. default:
  43. return '#12CEB3';
  44. }
  45. };
  46. const { run: detailRun } = useRequest(getDumuDetail, {
  47. manual: true,
  48. fetchKey: (id) => id,
  49. onSuccess: (data) => {
  50. var item = dumuList?.find((child) => child.id === data.id);
  51. if (item) {
  52. item.url = base64ToImageUrl(data.event_bg);
  53. }
  54. setDumuList([...dumuList]);
  55. },
  56. });
  57. const result = useMemo(() => {
  58. var resultArr = [];
  59. var tempResult = data?.PatrolResult;
  60. var tempArr = tempResult?.split(';');
  61. if (tempArr?.length > 0) {
  62. tempArr?.forEach((item, index) => {
  63. var tempItem = item;
  64. var itemSplit = tempItem.split(':');
  65. if (itemSplit?.length > 1) {
  66. var label = '';
  67. var value = itemSplit[1];
  68. if (index === 0) label = '设备自检';
  69. else if (index === 1) label = '工艺自检';
  70. else {
  71. label = '安全隐患';
  72. value = data?.secureStatus === 0 ? '正常' : '异常';
  73. }
  74. resultArr.push({
  75. label,
  76. value,
  77. color: getTextColor(value),
  78. });
  79. }
  80. });
  81. }
  82. return resultArr;
  83. }, [data]);
  84. useEffect(() => {
  85. dispatch({
  86. type: 'eqSelfInspection/fetchUserList',
  87. payload: {
  88. projectId,
  89. },
  90. });
  91. }, []);
  92. useEffect(() => {
  93. setDumuList(data?.dumuList);
  94. data?.dumuList?.map((item) => {
  95. detailRun(item.id);
  96. });
  97. }, [data?.dumuList]);
  98. return (
  99. <Spin spinning={loading} wrapperClassName="card-box">
  100. <div className={styles.card}>
  101. {data.Status == 0 ? (
  102. <div className={`${styles.orderIcon}`}>正常</div>
  103. ) : (
  104. <div className={`${styles.orderIcon} ${styles.error}`}>异常</div>
  105. )}
  106. <Row>
  107. <Col span={24} className={styles.cardText}>
  108. 自检时间:{data?.CreatedTime}
  109. </Col>
  110. </Row>
  111. <Row>
  112. <Col span={16} className={styles.cardText}>
  113. 自检路线:{data?.RouteInfo?.Name}
  114. </Col>
  115. <Col span={8} className={styles.cardText}>
  116. 工艺段:{data?.RouteInfo?.GroupID}
  117. </Col>
  118. </Row>
  119. <Row>
  120. {result?.map((item) => {
  121. return (
  122. <Col span={8} className={styles.cardText}>
  123. {item?.label}:
  124. <span style={{ color: item.color, fontWeight: 'bold' }}>
  125. {item?.value}
  126. </span>
  127. </Col>
  128. );
  129. })}
  130. </Row>
  131. </div>
  132. <div style={{ padding: 20, background: '#fff' }}>
  133. {/* 设备自检报告 */}
  134. <ReportCom
  135. sendMessageToUnity={sendMessageToUnity}
  136. select={select}
  137. waringData={data?.extendWarningData}
  138. allData={data?.extendWarningAllData}
  139. key="extend"
  140. type={'extend'}
  141. userList={userList}
  142. title={<ModuleTitle title="设备自检报告" />}
  143. ></ReportCom>
  144. {/* 液位异常 */}
  145. <LiquidLevelCom
  146. sendMessageToUnity={sendMessageToUnity}
  147. select={select}
  148. allData={data?.FluidLevelList}
  149. key="liquid"
  150. type={'liquid'}
  151. userList={userList}
  152. title={<ModuleTitle title="液位异常" />}
  153. />
  154. {/* 加药流量校验 */}
  155. {/* <FlowCom
  156. sendMessageToUnity={sendMessageToUnity}
  157. select={select}
  158. allData={data?.FluidLevelList}
  159. title={<ModuleTitle title="加药流量校验" />}
  160. /> */}
  161. {/* 工艺自检报告"> */}
  162. <div className={styles.content}>
  163. <div className={styles.tableStatus}>
  164. 异常({data?.FaultAnalysis?.length || 0})
  165. </div>
  166. <ModuleTitle title="工艺自检报告" />
  167. <AalysisTable
  168. onClickItem={sendMessageToUnity}
  169. select={select}
  170. data={data}
  171. />
  172. </div>
  173. {/* 安全隐患自检报告"> */}
  174. <div className={styles.content}>
  175. {/* 环境异常 */}
  176. <ReportCom
  177. sendMessageToUnity={sendMessageToUnity}
  178. select={select}
  179. waringData={data?.sensorWaringData}
  180. allData={data?.sensor}
  181. data={data?.sensorWaringData}
  182. key="sensor"
  183. type={'sensor'}
  184. userList={userList}
  185. title={<ModuleTitle title="环境异常" />}
  186. ></ReportCom>
  187. {/* 液位异常 */}
  188. {/* <LiquidLevelCom
  189. sendMessageToUnity={sendMessageToUnity}
  190. select={select}
  191. allData={data?.FluidLevelList}
  192. key="liquid"
  193. type={'liquid'}
  194. userList={userList}
  195. title={<ModuleTitle title="液位异常" />}
  196. /> */}
  197. {/* 安防检测异常 */}
  198. <ReportDumCom
  199. data={dumuList}
  200. title={<ModuleTitle title="安防检测异常" />}
  201. />
  202. {/* 电器检测异常 */}
  203. <ReportCom
  204. sendMessageToUnity={sendMessageToUnity}
  205. select={select}
  206. waringData={[]}
  207. allData={[]}
  208. key="extend"
  209. type={'extend'}
  210. userList={userList}
  211. title={<ModuleTitle title="电气检测异常" />}
  212. ></ReportCom>
  213. {/* 密闭空间检测异常 */}
  214. <ReportCom
  215. sendMessageToUnity={sendMessageToUnity}
  216. select={select}
  217. waringData={[]}
  218. allData={[]}
  219. key="extend"
  220. type={'extend'}
  221. userList={userList}
  222. title={<ModuleTitle title="密闭空间检测异常" />}
  223. ></ReportCom>
  224. </div>
  225. </div>
  226. {/* </Card> */}
  227. </Spin>
  228. );
  229. }
  230. export function DeviceTable(props) {
  231. const {
  232. onClickItem,
  233. data = {},
  234. items,
  235. onErrorHandle,
  236. select,
  237. userList,
  238. type,
  239. } = props;
  240. const { ProjectId, Id } = data;
  241. const [loading, setLoading] = useState(false);
  242. const [visible, setVisible] = useState(false);
  243. const [errVisible, setErrVisible] = useState(false);
  244. const [currentItem, setCurrentItem] = useState({});
  245. const isSensor = type == 'sensor';
  246. const onClickThreshold = (record) => {
  247. setCurrentItem(record);
  248. setVisible(true);
  249. };
  250. const onClickError = (record) => {
  251. setCurrentItem(record);
  252. setErrVisible(true);
  253. };
  254. const handleError = async (values) => {
  255. setLoading(true);
  256. var res = await changeRecordStatus({
  257. ...values,
  258. Id: currentItem.Id,
  259. DeviceCode: currentItem.DeviceCode,
  260. DeviceName: currentItem.DeviceName,
  261. RecordId: data.Id,
  262. RepairMan: values.RepairMan * 1,
  263. });
  264. setLoading(false);
  265. if (res) {
  266. message.success('操作成功');
  267. setErrVisible(false);
  268. }
  269. };
  270. const columns = [
  271. {
  272. title: '设备名称',
  273. dataIndex: 'DeviceName',
  274. },
  275. {
  276. title: '巡检项',
  277. width: '20%',
  278. dataIndex: 'TemplateItem.Name',
  279. },
  280. // {
  281. // title: '设备位号',
  282. // width: '16%',
  283. // dataIndex: 'DeviceCode',
  284. // },
  285. {
  286. title: '设定值范围',
  287. width: '30%',
  288. render: (record) => (
  289. <ThresholdDetail
  290. current={record.Value || 0}
  291. data={record || {}}
  292. // onClick={() => onClickThreshold(record)}
  293. />
  294. ),
  295. },
  296. {
  297. title: '状态',
  298. width: '13%',
  299. dataIndex: 'Status',
  300. render: (Status) => {
  301. switch (Status) {
  302. case -1:
  303. case 0:
  304. return (
  305. <div>
  306. <i
  307. className={styles.iconStatus}
  308. style={{ background: '#12CEB3' }}
  309. ></i>
  310. 正常
  311. </div>
  312. );
  313. case 1:
  314. return (
  315. <div>
  316. <i
  317. className={styles.iconStatus}
  318. style={{ background: '#FE5850' }}
  319. ></i>
  320. 异常
  321. </div>
  322. );
  323. case 2:
  324. return (
  325. <div>
  326. <i
  327. className={styles.iconStatus}
  328. style={{ background: '#FFE26D' }}
  329. ></i>
  330. 警告
  331. </div>
  332. );
  333. }
  334. },
  335. },
  336. ];
  337. const handleClickItem = (data) => {
  338. if (!isSensor) {
  339. onClickItem(`DeviceTable-${data.Id}`, {
  340. type: data.Status,
  341. deviceCode: data.DeviceCode,
  342. });
  343. } else {
  344. onClickItem(`DeviceTable-${data.Id}`, {
  345. // type: data.Status,
  346. deviceCode: data.DeviceCode,
  347. value: Number(data.Value || 0),
  348. threshold: data.JsonNumThreshold,
  349. });
  350. UnityAction.sendMsg('SinglePowerEnvironFromWeb', JSON.stringify(data));
  351. }
  352. };
  353. useEffect(() => {
  354. console.log('温控', items);
  355. if (isSensor)
  356. UnityAction.sendMsg('PowerEnvironsFromWeb', JSON.stringify(items));
  357. }, [items]);
  358. if (!isSensor) {
  359. columns.push({
  360. title: '操作',
  361. width: 120,
  362. render: (record) =>
  363. record.Status == 1 && (
  364. <a style={{ color: '#FE5850' }} onClick={() => onClickError(record)}>
  365. 异常处理
  366. </a>
  367. ),
  368. });
  369. }
  370. return (
  371. <div>
  372. <Table
  373. columns={columns}
  374. dataSource={items}
  375. rowKey="Id"
  376. locale={{
  377. emptyText: <Empty />,
  378. }}
  379. pagination={false}
  380. />
  381. <ThresholdModal
  382. open={visible}
  383. data={currentItem.JsonNumThreshold}
  384. onClose={() => setVisible(false)}
  385. />
  386. <ErrorHandleModal
  387. open={errVisible}
  388. userList={userList}
  389. onCancel={() => setErrVisible(false)}
  390. onOk={handleError}
  391. />
  392. </div>
  393. );
  394. }
  395. function AalysisTable(props) {
  396. const { onClickItem, data = {}, select } = props;
  397. const { FaultAnalysis } = data;
  398. const columns = [
  399. {
  400. title: '异常名称',
  401. width: '18%',
  402. dataIndex: 'device_name',
  403. },
  404. // {
  405. // title: '位号',
  406. // width: '15%',
  407. // dataIndex: 'device_code',
  408. // },
  409. {
  410. title: '可能原因',
  411. width: '30%',
  412. render: (record) => record.reason,
  413. },
  414. {
  415. title: '解决方案',
  416. width: '52%',
  417. render: (record) => {
  418. if (record.fix_plan instanceof Array) {
  419. return (
  420. <div>
  421. {record.fix_plan.map((item) => (
  422. <div>
  423. {item.content}
  424. <br />
  425. </div>
  426. ))}
  427. </div>
  428. );
  429. } else {
  430. return record.fix_plan;
  431. }
  432. },
  433. },
  434. ];
  435. return (
  436. <div>
  437. <Table
  438. columns={columns}
  439. dataSource={FaultAnalysis}
  440. rowKey="device_code"
  441. locale={{
  442. emptyText: <Empty />,
  443. }}
  444. pagination={false}
  445. />
  446. </div>
  447. );
  448. }
  449. function ErrorHandleModal(props) {
  450. const { visible, onCancel, onOk, userList } = props;
  451. const [form] = Form.useForm();
  452. const status = form.getFieldValue('Status');
  453. const handleOk = () => {
  454. form.validateFields((error, values) => {
  455. if (error) return;
  456. onOk({
  457. ...values,
  458. PlanTime: values?.PlanTime?.format('YYYY-MM-DD HH:mm:ss'),
  459. });
  460. });
  461. };
  462. return (
  463. <Modal
  464. title="异常处理"
  465. open={visible}
  466. onCancel={onCancel}
  467. onOk={handleOk}
  468. destroyOnClose
  469. >
  470. <Form labelCol={{ span: 7 }} wrapperCol={{ span: 16 }}>
  471. <Form.Item label="异常处理备注" name="ExceptionHandling">
  472. <Input.TextArea />
  473. </Form.Item>
  474. <Form.Item
  475. label="审核状态"
  476. name="Status"
  477. rules={[{ required: true, message: '请选择验收状态' }]}
  478. >
  479. <Select style={{ width: '100%' }} placeholder="请选择验收状态">
  480. <Select.Option value={1}>已派遣</Select.Option>
  481. <Select.Option value={2}>已通过</Select.Option>
  482. </Select>
  483. </Form.Item>
  484. <Form.Item
  485. label="维修人"
  486. name="RepairMan"
  487. rules={[{ required: true, message: '请选择维修人' }]}
  488. >
  489. <Select
  490. showSearch
  491. placeholder="请选择维修人"
  492. filterOption={(input, option) =>
  493. option.props.children.indexOf(input) >= 0
  494. }
  495. style={{ width: '100%' }}
  496. >
  497. {userList?.map((item) => (
  498. <Select.Option key={item.ID}>{item.CName}</Select.Option>
  499. ))}
  500. </Select>
  501. </Form.Item>
  502. {status == 1 && (
  503. <>
  504. <Form.Item
  505. label="难度级别"
  506. name="DifficultyLevel"
  507. rules={[{ required: true, message: '请选择难度级别' }]}
  508. >
  509. <Select placeholder="请选择难度级别" style={{ width: '100%' }}>
  510. <Select.Option value={0}>大修</Select.Option>
  511. <Select.Option value={1}>项目维修</Select.Option>
  512. <Select.Option value={2}>小修</Select.Option>
  513. </Select>
  514. </Form.Item>
  515. <Form.Item
  516. label="维修方式"
  517. name="RepairType"
  518. rules={[{ required: true, message: '请选择维修方式' }]}
  519. >
  520. <Select placeholder="请选择维修方式" style={{ width: '100%' }}>
  521. <Select.Option value={0}>自维</Select.Option>
  522. <Select.Option value={1}>外委</Select.Option>
  523. </Select>
  524. </Form.Item>
  525. <Form.Item
  526. label="计划完成日期"
  527. name="PlanTime"
  528. rules={[{ required: true, message: '请选择计划完成日期' }]}
  529. >
  530. <DatePicker inputReadOnly />
  531. </Form.Item>
  532. </>
  533. )}
  534. </Form>
  535. </Modal>
  536. );
  537. }
  538. export function WarningTable(props) {
  539. const {
  540. onClickItem,
  541. data = {},
  542. onErrorHandle,
  543. select,
  544. userList,
  545. type,
  546. items,
  547. } = props;
  548. const { ProjectId, Id } = data;
  549. const [loading, setLoading] = useState(false);
  550. const [visible, setVisible] = useState(false);
  551. const [errVisible, setErrVisible] = useState(false);
  552. const [currentItem, setCurrentItem] = useState({});
  553. const isSensor = type == 'sensor';
  554. const onClickThreshold = (record) => {
  555. setCurrentItem(record);
  556. setVisible(true);
  557. };
  558. const onClickError = (record) => {
  559. setCurrentItem(record);
  560. setErrVisible(true);
  561. };
  562. const handleError = async (values) => {
  563. setLoading(true);
  564. var res = await changeRecordStatus({
  565. ...values,
  566. Id: currentItem.Id,
  567. DeviceCode: currentItem.DeviceCode,
  568. DeviceName: currentItem.DeviceName,
  569. RecordId: data.Id,
  570. RepairMan: values.RepairMan * 1,
  571. });
  572. setLoading(false);
  573. if (res) {
  574. message.success('操作成功');
  575. setErrVisible(false);
  576. }
  577. };
  578. const columns = [
  579. {
  580. title: '设备名称',
  581. dataIndex: 'DeviceName',
  582. },
  583. {
  584. title: '巡检项',
  585. width: '20%',
  586. dataIndex: 'TemplateItem.Name',
  587. },
  588. // {
  589. // title: '设备位号',
  590. // width: '16%',
  591. // dataIndex: 'DeviceCode',
  592. // },
  593. {
  594. title: '设定值范围',
  595. width: '30%',
  596. render: (record) => (
  597. <ThresholdDetail
  598. current={record.Value || 0}
  599. data={record || {}}
  600. // onClick={() => onClickThreshold(record)}
  601. />
  602. ),
  603. },
  604. {
  605. title: '状态',
  606. width: '13%',
  607. dataIndex: 'Status',
  608. render: (Status) => {
  609. switch (Status) {
  610. case -1:
  611. case 0:
  612. return (
  613. <div>
  614. <i
  615. className={styles.iconStatus}
  616. style={{ background: '#12CEB3' }}
  617. ></i>
  618. 正常
  619. </div>
  620. );
  621. case 1:
  622. return (
  623. <div>
  624. <i
  625. className={styles.iconStatus}
  626. style={{ background: '#FE5850' }}
  627. ></i>
  628. 异常
  629. </div>
  630. );
  631. case 2:
  632. return (
  633. <div>
  634. <i
  635. className={styles.iconStatus}
  636. style={{ background: '#FFE26D' }}
  637. ></i>
  638. 警告
  639. </div>
  640. );
  641. }
  642. },
  643. },
  644. ];
  645. const handleClickItem = (data) => {
  646. if (!isSensor) {
  647. onClickItem(`DeviceTable-${data.Id}`, {
  648. type: data.Status,
  649. deviceCode: data.DeviceCode,
  650. });
  651. } else {
  652. onClickItem(`DeviceTable-${data.Id}`, {
  653. // type: data.Status,
  654. deviceCode: data.DeviceCode,
  655. value: Number(data.Value || 0),
  656. threshold: data.JsonNumThreshold,
  657. });
  658. UnityAction.sendMsg('SinglePowerEnvironFromWeb', JSON.stringify(data));
  659. }
  660. };
  661. if (!isSensor) {
  662. columns.push({
  663. title: '操作',
  664. width: 120,
  665. render: (record) =>
  666. record.Status == 1 && (
  667. <a style={{ color: '#FE5850' }} onClick={() => onClickError(record)}>
  668. 异常处理
  669. </a>
  670. ),
  671. });
  672. }
  673. useEffect(() => {
  674. if (isSensor)
  675. UnityAction.sendMsg('PowerEnvironsFromWeb', JSON.stringify(items));
  676. }, [items]);
  677. return (
  678. <div>
  679. <Table
  680. columns={columns}
  681. dataSource={items}
  682. rowKey="Id"
  683. locale={{
  684. emptyText: <Empty />,
  685. }}
  686. pagination={false}
  687. />
  688. <ThresholdModal
  689. open={visible}
  690. data={currentItem.JsonNumThreshold}
  691. onClose={() => setVisible(false)}
  692. />
  693. <ErrorHandleModal
  694. open={errVisible}
  695. userList={userList}
  696. onCancel={() => setErrVisible(false)}
  697. onOk={handleError}
  698. />
  699. </div>
  700. );
  701. }
  702. function ReportCom(props) {
  703. const {
  704. sendMessageToUnity,
  705. select,
  706. waringData = [],
  707. allData = [],
  708. userList,
  709. type,
  710. title,
  711. data,
  712. } = props;
  713. const [activeKey, setActiveKey] = useState('1');
  714. const handleTabsChange = (activeKey) => {
  715. setActiveKey(activeKey);
  716. };
  717. return (
  718. <div className={styles.detailCard}>
  719. <div className={styles.tableTop}>
  720. {title}
  721. <TabsContent
  722. defaultActiveKey="1"
  723. onChange={handleTabsChange}
  724. small={true}
  725. items={[
  726. {
  727. key: '1',
  728. label: `异常/警告(${waringData.length || 0})`,
  729. children: <div></div>,
  730. },
  731. {
  732. key: '2',
  733. label: `全部(${allData.length || 0})`,
  734. children: <div></div>,
  735. },
  736. ]}
  737. ></TabsContent>
  738. </div>
  739. {activeKey == '1' && (
  740. <WarningTable
  741. onClickItem={sendMessageToUnity}
  742. select={select}
  743. items={waringData}
  744. key={type}
  745. data={data}
  746. type={type}
  747. userList={userList}
  748. />
  749. )}
  750. {activeKey == '2' && (
  751. <DeviceTable
  752. onClickItem={sendMessageToUnity}
  753. select={select}
  754. items={allData}
  755. data={data}
  756. key={type}
  757. type={type}
  758. userList={userList}
  759. />
  760. )}
  761. </div>
  762. );
  763. }
  764. export function LiquidTable(props) {
  765. const { onClickItem, data = {}, items, select, type } = props;
  766. const { ProjectId, Id } = data;
  767. const [loading, setLoading] = useState(false);
  768. const [currentItem, setCurrentItem] = useState({});
  769. const columns = [
  770. {
  771. title: '设备名称',
  772. width: '25%',
  773. dataIndex: 'device_name',
  774. },
  775. {
  776. title: '液位数',
  777. width: '20%',
  778. dataIndex: 'origin_value',
  779. },
  780. {
  781. title: '差值',
  782. width: '16%',
  783. dataIndex: 'value',
  784. },
  785. {
  786. title: '设定值范围',
  787. width: '30%',
  788. render: (record) => (
  789. <ThresholdDetail
  790. current={record.value || 0}
  791. data={{
  792. JsonNumThreshold: record?.json_num_threshold,
  793. Type: record.type || 2,
  794. }}
  795. />
  796. ),
  797. },
  798. {
  799. title: '状态',
  800. width: '13%',
  801. dataIndex: 'status',
  802. render: (status) => {
  803. switch (status) {
  804. case -1:
  805. case 0:
  806. return (
  807. <div>
  808. <i
  809. className={styles.iconStatus}
  810. style={{ background: '#12CEB3' }}
  811. ></i>
  812. 正常
  813. </div>
  814. );
  815. case 1:
  816. return (
  817. <div>
  818. <i
  819. className={styles.iconStatus}
  820. style={{ background: '#FFE26D' }}
  821. ></i>
  822. 异常
  823. </div>
  824. );
  825. case 2:
  826. return (
  827. <div>
  828. <i
  829. className={styles.iconStatus}
  830. style={{ background: '#FFE26D' }}
  831. ></i>
  832. 警告
  833. </div>
  834. );
  835. }
  836. },
  837. },
  838. ];
  839. const handleClickItem = (data) => {
  840. onClickItem(`DeviceTable-${data.device_code}`, {
  841. type: data.status,
  842. deviceCode: data.device_code,
  843. });
  844. };
  845. return (
  846. <Table
  847. columns={columns}
  848. dataSource={items}
  849. rowKey="device_code"
  850. locale={{
  851. emptyText: <Empty />,
  852. }}
  853. pagination={false}
  854. />
  855. );
  856. }
  857. function LiquidLevelCom(props) {
  858. const { sendMessageToUnity, select, allData = [], type, title } = props;
  859. const [activeKey, setActiveKey] = useState('1');
  860. const errorData = useMemo(() => {
  861. const errorData = allData?.filter((item) => item.status);
  862. return errorData;
  863. }, [allData]);
  864. const handleTabsChange = (activeKey) => {
  865. setActiveKey(activeKey);
  866. };
  867. return (
  868. <div className={styles.detailCard}>
  869. <div className={styles.tableTop}>
  870. {title}
  871. <TabsContent
  872. defaultActiveKey="1"
  873. onChange={handleTabsChange}
  874. small={true}
  875. items={[
  876. {
  877. key: '1',
  878. label: `异常/警告(${errorData?.length || 0})`,
  879. children: <div></div>,
  880. },
  881. {
  882. key: '2',
  883. label: `全部(${allData?.length || 0})`,
  884. children: <div></div>,
  885. },
  886. ]}
  887. ></TabsContent>
  888. </div>
  889. {activeKey == '1' && (
  890. <LiquidTable
  891. onClickItem={sendMessageToUnity}
  892. select={select}
  893. items={errorData}
  894. key={type}
  895. type={type}
  896. />
  897. )}
  898. {activeKey == '2' && (
  899. <LiquidTable
  900. onClickItem={sendMessageToUnity}
  901. select={select}
  902. items={allData}
  903. key={type}
  904. type={type}
  905. />
  906. )}
  907. </div>
  908. // <div className={styles.detailCard}>
  909. // <Tabs
  910. // defaultActiveKey="1"
  911. // tabBarExtraContent={<div className={styles.tabBarExtraContent}>{title} </div>}
  912. // onChange={handleTabsChange}
  913. // >
  914. // <Tabs.TabPane tab={`异常/警告(${errorData.length || 0})`} key="1">
  915. // {activeKey == '1' && (
  916. // <LiquidTable
  917. // onClickItem={sendMessageToUnity}
  918. // select={select}
  919. // items={errorData}
  920. // key={type}
  921. // // data={data}
  922. // type={type}
  923. // />
  924. // )}
  925. // </Tabs.TabPane>
  926. // <Tabs.TabPane tab={`全部(${allData.length || 0})`} key="2">
  927. // {activeKey == '2' && (
  928. // <LiquidTable
  929. // onClickItem={sendMessageToUnity}
  930. // select={select}
  931. // items={allData}
  932. // // data={data}
  933. // key={type}
  934. // type={type}
  935. // />
  936. // )}
  937. // </Tabs.TabPane>
  938. // </Tabs>
  939. // </div>
  940. );
  941. }
  942. function FlowTable(props) {
  943. const { onClickItem, data = {}, items } = props;
  944. const columns = [
  945. {
  946. title: '设备名称',
  947. width: '20%',
  948. dataIndex: 'device_name',
  949. },
  950. {
  951. title: '实际流量',
  952. width: '20%',
  953. dataIndex: 'origin_value',
  954. },
  955. {
  956. title: '计量流量',
  957. width: '16%',
  958. dataIndex: 'value',
  959. },
  960. {
  961. title: '差值',
  962. width: '15%',
  963. dataIndex: 'value',
  964. },
  965. {
  966. title: '设定值范围',
  967. width: '30%',
  968. render: (record) => (
  969. <ThresholdDetail
  970. current={record.value || 0}
  971. data={{
  972. JsonNumThreshold: record?.json_num_threshold,
  973. Type: record.type || 2,
  974. }}
  975. />
  976. ),
  977. },
  978. {
  979. title: '状态',
  980. dataIndex: 'status',
  981. render: (status) => {
  982. switch (status) {
  983. case -1:
  984. case 0:
  985. return (
  986. <div>
  987. <i
  988. className={styles.iconStatus}
  989. style={{ background: '#12CEB3' }}
  990. ></i>
  991. 正常
  992. </div>
  993. );
  994. case 1:
  995. return (
  996. <div>
  997. <i
  998. className={styles.iconStatus}
  999. style={{ background: '#FFE26D' }}
  1000. ></i>
  1001. 异常
  1002. </div>
  1003. );
  1004. case 2:
  1005. return (
  1006. <div>
  1007. <i
  1008. className={styles.iconStatus}
  1009. style={{ background: '#FFE26D' }}
  1010. ></i>
  1011. 警告
  1012. </div>
  1013. );
  1014. }
  1015. },
  1016. },
  1017. ];
  1018. const handleClickItem = (data) => {
  1019. onClickItem(`DeviceTable-${data.device_code}`, {
  1020. type: data.status,
  1021. deviceCode: data.device_code,
  1022. });
  1023. };
  1024. return (
  1025. <Table
  1026. columns={columns}
  1027. dataSource={items}
  1028. rowKey="device_code"
  1029. locale={{
  1030. emptyText: <Empty />,
  1031. }}
  1032. pagination={false}
  1033. />
  1034. );
  1035. }
  1036. function FlowCom(props) {
  1037. const { sendMessageToUnity, select, allData = [], type, title } = props;
  1038. const [activeKey, setActiveKey] = useState('1');
  1039. const errorData = useMemo(() => {
  1040. const errorData = allData?.filter((item) => item.status);
  1041. return errorData;
  1042. }, [allData]);
  1043. const handleTabsChange = (activeKey) => {
  1044. setActiveKey(activeKey);
  1045. };
  1046. return (
  1047. <div className={styles.detailCard}>
  1048. <div className={styles.tableTop}>
  1049. {title}
  1050. <TabsContent
  1051. defaultActiveKey="1"
  1052. onChange={handleTabsChange}
  1053. small={true}
  1054. items={[
  1055. {
  1056. key: '1',
  1057. label: `异常/警告(${errorData?.length || 0})`,
  1058. children: <div></div>,
  1059. },
  1060. {
  1061. key: '2',
  1062. label: `全部(${allData?.length || 0})`,
  1063. children: <div></div>,
  1064. },
  1065. ]}
  1066. ></TabsContent>
  1067. </div>
  1068. {activeKey == '1' && (
  1069. <FlowTable
  1070. onClickItem={sendMessageToUnity}
  1071. select={select}
  1072. items={errorData}
  1073. key={type}
  1074. type={type}
  1075. />
  1076. )}
  1077. {activeKey == '2' && (
  1078. <FlowTable
  1079. onClickItem={sendMessageToUnity}
  1080. select={select}
  1081. items={allData}
  1082. key={type}
  1083. type={type}
  1084. />
  1085. )}
  1086. </div>
  1087. );
  1088. }
  1089. function ReportDumCom(props) {
  1090. const { data = [], title } = props;
  1091. const columns = [
  1092. {
  1093. title: '报警时间',
  1094. dataIndex: 'event_time',
  1095. render: (time) => dayjs(time).format('YYYY-MM-DD HH:mm:ss'),
  1096. },
  1097. {
  1098. title: '设备名称',
  1099. dataIndex: 'device_name',
  1100. },
  1101. {
  1102. title: '报警类型',
  1103. dataIndex: 'event_type',
  1104. // render: type => alarmType[type],
  1105. },
  1106. {
  1107. title: '报警图片',
  1108. render: (item) => (
  1109. <ReactZmage
  1110. controller={{
  1111. // 关闭按钮
  1112. close: true,
  1113. // 旋转按钮
  1114. rotate: true,
  1115. // 缩放按钮
  1116. zoom: false,
  1117. // 下载按钮
  1118. download: false,
  1119. // 翻页按钮
  1120. flip: false,
  1121. // 多页指示
  1122. pagination: false,
  1123. }}
  1124. backdrop="rgba(255,255,255,0.5)"
  1125. style={{ height: '0.9rem' }}
  1126. src={item.path}
  1127. />
  1128. ),
  1129. },
  1130. ];
  1131. return (
  1132. <div>
  1133. <div className={styles.tabBarExtraContent}>
  1134. <div className={styles.text} style={{ width: '60%' }}>
  1135. {title}
  1136. </div>
  1137. <div className={styles.abnormal}>
  1138. <div className={styles.text} style={{ float: 'right' }}>
  1139. 异常({data?.length || 0})
  1140. </div>
  1141. </div>
  1142. </div>
  1143. <Table
  1144. bordered
  1145. rowKey="event_time"
  1146. columns={columns}
  1147. dataSource={data}
  1148. locale={{
  1149. emptyText: <Empty />,
  1150. }}
  1151. pagination={false}
  1152. />
  1153. </div>
  1154. );
  1155. }
  1156. function base64ToImageUrl(base64String) {
  1157. const byteCharacters = atob(base64String);
  1158. const byteArrays = [];
  1159. for (let i = 0; i < byteCharacters.length; i++) {
  1160. byteArrays.push(byteCharacters.charCodeAt(i));
  1161. }
  1162. const byteArray = new Uint8Array(byteArrays);
  1163. const blob = new Blob([byteArray], { type: 'image/png' });
  1164. const imageUrl = URL.createObjectURL(blob);
  1165. return imageUrl;
  1166. }
  1167. function Empty() {
  1168. return (
  1169. <div>
  1170. <img
  1171. src={require('@/assets/self-empty.png')}
  1172. style={{ margin: '0.2rem 0' }}
  1173. />
  1174. <p style={{ textAlign: 'center', color: '#555' }}>自检正常</p>
  1175. </div>
  1176. );
  1177. }
  1178. export default connect(({ eqSelfInspection }) => ({
  1179. userList: eqSelfInspection.userList,
  1180. mandateInfo: eqSelfInspection.mandateInfo,
  1181. }))(Detail);