complex.jsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. import React, {
  2. useRef,
  3. useState,
  4. useEffect,
  5. forwardRef,
  6. useImperativeHandle,
  7. } from "react";
  8. import { Form, Input, Select, message } from "antd";
  9. import { Modal, Button, Table, Radio } from "antd";
  10. import Formular from "./components/Formular";
  11. import API2 from "../../../api/alarm";
  12. import styles from "./complex.module.less";
  13. import oneNode from "./components/oneNode";
  14. import { useMemoizedFn } from "ahooks";
  15. const { Search } = Input;
  16. function TranslateText(arr) {
  17. const dtLanguage = localStorage.getItem("dtLanguage");
  18. if (!Array.isArray(arr)) {
  19. return arr;
  20. }
  21. if (arr.length < 2 && arr.length > 0) {
  22. return arr?.[0];
  23. }
  24. if (dtLanguage === "en") {
  25. return arr?.[1];
  26. }
  27. return arr?.[0];
  28. }
  29. const Complex = (props, ref) => {
  30. const { editId, groupList = [], showList } = props;
  31. const [form] = Form.useForm();
  32. const formuRef = useRef();
  33. // const [alarmId, setAlarmId] = useState(searchParams.get('alarm_id'))
  34. // const [token, setToken] = useState(searchParams.get('token'))
  35. // const [apiUrl, setApiUrl] = useState(decodeURIComponent(searchParams.get('api_url')) + '/')
  36. const [data, setData] = useState();
  37. const [loading, setLoading] = useState(false);
  38. const [deviceList, setDeviceList] = useState([]);
  39. const [paginationProps, setPaginationProps] = useState({
  40. pageSize: 10,
  41. current: 1,
  42. showTotal: (total) => `共${total}条`,
  43. // showQuickJumper: true,
  44. // showSizeChanger:true,
  45. // size:'Large',
  46. });
  47. const [alarmId, setAlarmId] = useState(null);
  48. const [type, setType] = useState(0);
  49. const [ruleOptions, setRuleOptions] = useState([]);
  50. const handleTableChange = async (pagination) => {
  51. setPaginationProps({ ...pagination, showTotal: (total) => `共${total}条` });
  52. // setCurrentPage(pagination.current);
  53. // setPageSize(pagination.pageSize)
  54. };
  55. useEffect(() => {
  56. onSearch("");
  57. }, []);
  58. useEffect(() => {
  59. async function run() {
  60. if (alarmId && alarmId != -1) {
  61. const { state, data } = await API2.detailAlarm(Number(alarmId));
  62. form.setFieldsValue({
  63. name: data.name,
  64. alarm_level: data.alarm_level,
  65. group_id: data.group_id,
  66. });
  67. formuRef.current.backEndInput(data.formula);
  68. setData(data);
  69. } else {
  70. form.resetFields();
  71. form.setFieldsValue({
  72. alarm_level: 1,
  73. });
  74. setData(null);
  75. }
  76. }
  77. run();
  78. }, [alarmId]);
  79. const onModalOk = useMemoizedFn(async () => {
  80. if (type === 0 && showList) {
  81. props.onConfirm(null);
  82. return;
  83. }
  84. if (alarmId == -1) {
  85. const value = await form.validateFields();
  86. const obj = {
  87. ...value,
  88. formula: formuRef.current.getFinalStr(),
  89. ext_notify_list: [],
  90. is_complex: true,
  91. type: 1,
  92. sub_type: 12,
  93. status: 1,
  94. defer_unit: 2,
  95. };
  96. const { state, data } = await API2.addRule(obj);
  97. if (state === 0) {
  98. props?.onConfirm?.(data?.id);
  99. form.resetFields();
  100. message.success("保存成功");
  101. } else {
  102. message.error("保存失败");
  103. }
  104. } else {
  105. const value = await form.validateFields();
  106. const obj = {
  107. ...data,
  108. ...value,
  109. formula: formuRef.current.getFinalStr(),
  110. ext_notify_list: [],
  111. };
  112. const { state } = await API2.editRule(obj);
  113. if (state === 0) {
  114. props?.onConfirm?.(data.id);
  115. form.resetFields();
  116. message.success("保存成功");
  117. } else {
  118. message.error("保存失败");
  119. }
  120. }
  121. });
  122. useImperativeHandle(ref, () => {
  123. return {
  124. ok: onModalOk,
  125. };
  126. });
  127. const symbClick = (e) => {
  128. let innerText = e.target.innerText;
  129. if (innerText === "≥") {
  130. innerText = ">=";
  131. } else if (innerText === "≤") {
  132. innerText = "<=";
  133. } else if (innerText === "&&(and)") {
  134. innerText = "&&";
  135. } else if (innerText === "||(or)") {
  136. innerText = "||";
  137. }
  138. formuRef.current.dtInsertFormular(innerText);
  139. if (innerText === "()") {
  140. //判断为括号则把光标移到括号中间
  141. formuRef.current.moveInTextNode();
  142. }
  143. };
  144. const insertToFomular = (poi) => {
  145. const { point_id, name } = poi;
  146. const res = oneNode(point_id, name);
  147. formuRef.current.dtInsertFormular(res);
  148. };
  149. const columns = [
  150. {
  151. title: TranslateText(["点位编号", "Point id"]),
  152. dataIndex: "point_id",
  153. ellipsis: true,
  154. },
  155. {
  156. title: TranslateText(["点位名称", "Point name"]),
  157. dataIndex: "name",
  158. ellipsis: true,
  159. },
  160. ];
  161. const onSearch = async (v) => {
  162. const res = await API2.searchPoint({
  163. key_word: v ?? "",
  164. count: 50,
  165. type: 1,
  166. no_child: true,
  167. });
  168. if (res.state === 0) {
  169. setDeviceList(res.data || []);
  170. return;
  171. }
  172. setDeviceList([]);
  173. };
  174. const clickTableRow = (record) => {
  175. // child.current.handlePickPoint({name:record.name, point_id:record.point_id})
  176. insertToFomular({ name: record.name, point_id: record.point_id });
  177. };
  178. const onModalCancel = () => {
  179. props.onConfirm();
  180. form.resetFields();
  181. };
  182. useEffect(() => {
  183. function run() {
  184. if (editId && editId !== -1) {
  185. setAlarmId(editId);
  186. if (showList) {
  187. setType(1);
  188. }
  189. } else if (showList) {
  190. setType(0);
  191. } else if (!showList) {
  192. setAlarmId(-1);
  193. }
  194. }
  195. run();
  196. }, [editId, showList]);
  197. useEffect(() => {
  198. async function run() {
  199. if (showList) {
  200. const res = await API2.getRuleList();
  201. setRuleOptions(
  202. res?.data?.rules?.map((item) => ({
  203. label: item.name,
  204. value: item.id,
  205. }))
  206. );
  207. }
  208. }
  209. run();
  210. }, [showList]);
  211. useEffect(() => {
  212. if (showList) {
  213. if (type === 2) {
  214. setAlarmId(-1);
  215. } else if (alarmId === -1 && type !== 2) {
  216. setAlarmId(null);
  217. }
  218. }
  219. }, [type, alarmId, showList]);
  220. return (
  221. <div className={styles.wrapper}>
  222. <div className="main">
  223. <div className="left">
  224. <Form
  225. name="basic"
  226. autoComplete="off"
  227. form={form}
  228. requiredMark={true}
  229. labelAlign="right"
  230. colon={false}
  231. labelCol={{
  232. span: 4,
  233. }}
  234. wrapperCol={{
  235. span: 15,
  236. }}
  237. >
  238. {showList && (
  239. <>
  240. <Form.Item label="类型">
  241. <Radio.Group
  242. value={type}
  243. onChange={(e) => setType(e.target.value)}
  244. >
  245. <Radio value={0}>无规则</Radio>
  246. <Radio value={1}>关联规则</Radio>
  247. <Radio value={2}>新建规则</Radio>
  248. </Radio.Group>
  249. </Form.Item>
  250. {type === 1 && (
  251. <Form.Item label="关联规则">
  252. <Select
  253. value={alarmId}
  254. onChange={setAlarmId}
  255. style={{ width: 240 }}
  256. options={ruleOptions}
  257. placeholder={TranslateText(["请选择", "Please choose"])}
  258. />
  259. </Form.Item>
  260. )}
  261. </>
  262. )}
  263. {(!showList || type !== 0) && (
  264. <>
  265. <Form.Item
  266. label={TranslateText(["告警名称", "Alarm name"])}
  267. name="name"
  268. rules={[
  269. {
  270. required: true,
  271. message: TranslateText([
  272. "请输入告警名称",
  273. "Please input",
  274. ]),
  275. },
  276. ]}
  277. >
  278. <Input
  279. placeholder={TranslateText([
  280. "请输入告警名称",
  281. "Please input",
  282. ])}
  283. style={{ width: "240px" }}
  284. />
  285. </Form.Item>
  286. <Form.Item
  287. label={TranslateText(["条件符号", "Symbol"])}
  288. // name="symb"
  289. >
  290. <div className="symb" style={{ width: "500px" }}>
  291. <Button type="primary" onClick={symbClick}>
  292. ()
  293. </Button>
  294. <Button type="primary" onClick={symbClick}>
  295. {"&&(and)"}
  296. </Button>
  297. <Button type="primary" onClick={symbClick}>
  298. {"||(or)"}
  299. </Button>
  300. <Button type="primary" onClick={symbClick}>
  301. </Button>
  302. <Button type="primary" onClick={symbClick}>
  303. {">"}
  304. </Button>
  305. <Button type="primary" onClick={symbClick}>
  306. =
  307. </Button>
  308. <Button type="primary" onClick={symbClick}>{`<`}</Button>
  309. <Button type="primary" onClick={symbClick}>
  310. </Button>
  311. <Button type="primary" onClick={symbClick}>
  312. +
  313. </Button>
  314. <Button type="primary" onClick={symbClick}>
  315. -
  316. </Button>
  317. <Button type="primary" onClick={symbClick}>
  318. *
  319. </Button>
  320. <Button type="primary" onClick={symbClick}>
  321. /
  322. </Button>
  323. </div>
  324. </Form.Item>
  325. <Form.Item
  326. label={TranslateText(["条件编辑", "Edit"])}
  327. name="formu"
  328. rules={[
  329. {
  330. required: true,
  331. message: "请输入条件",
  332. validator: () => {
  333. return new Promise((resolve, reject) => {
  334. console.log(formuRef.current.getFinalStr());
  335. if (formuRef.current.getFinalStr()) {
  336. resolve();
  337. } else {
  338. reject();
  339. }
  340. });
  341. },
  342. },
  343. ]}
  344. >
  345. <Formular ref={formuRef} key={`${type}-${alarmId}`} />
  346. </Form.Item>
  347. <Form.Item
  348. label={TranslateText(["告警组", "Alarm group"])}
  349. name={"group_id"}
  350. >
  351. <Select
  352. style={{ width: 240 }}
  353. options={[
  354. ...[
  355. {
  356. label: "未分组",
  357. value: 0,
  358. },
  359. ],
  360. ...(groupList?.map((item) => {
  361. return {
  362. label: item?.name,
  363. value: item?.id,
  364. };
  365. }) ?? []),
  366. ]}
  367. placeholder={TranslateText(["请选择", "Please choose"])}
  368. />
  369. </Form.Item>
  370. <Form.Item
  371. label={TranslateText(["告警级别", "Alarm level"])}
  372. name="alarm_level"
  373. rules={[
  374. {
  375. required: true,
  376. message: TranslateText([
  377. "请输入告警级别",
  378. "Please input",
  379. ]),
  380. },
  381. ]}
  382. >
  383. <Select
  384. placeholder={TranslateText(["请选择", "Please choose"])}
  385. style={{ width: "240px" }}
  386. >
  387. <Select.Option value={1}>
  388. {TranslateText(["低", "Low"])}
  389. </Select.Option>
  390. <Select.Option value={2}>
  391. {TranslateText(["中", "Medium"])}
  392. </Select.Option>
  393. <Select.Option value={3}>
  394. {TranslateText(["高", "High"])}
  395. </Select.Option>
  396. </Select>
  397. </Form.Item>
  398. </>
  399. )}
  400. </Form>
  401. </div>
  402. {(!showList || type !== 0) && (
  403. <>
  404. <div
  405. style={{
  406. borderRight: "1px solid rgba(255, 255, 255, 0.12)",
  407. marginLeft: "16px",
  408. }}
  409. ></div>
  410. <div className="right">
  411. <div className="header">
  412. <Search
  413. placeholder={TranslateText([
  414. "请输入点位名称",
  415. "Please input",
  416. ])}
  417. onSearch={onSearch}
  418. style={{ width: "240px" }}
  419. // className={styles.deviceListTreeSearch}
  420. />
  421. </div>
  422. <Table
  423. onRow={(record) => {
  424. return {
  425. onClick: (event) => {
  426. clickTableRow(record);
  427. }, // 点击行
  428. };
  429. }}
  430. key={deviceList}
  431. loading={loading}
  432. columns={columns}
  433. dataSource={deviceList}
  434. rowKey="point_id"
  435. // className="deviceListTable"
  436. pagination={paginationProps}
  437. onChange={handleTableChange}
  438. size="middle"
  439. />
  440. </div>
  441. </>
  442. )}
  443. </div>
  444. </div>
  445. );
  446. };
  447. export default forwardRef(Complex);