瀏覽代碼

feat: 新增子设备

wzyyy 3 年之前
父節點
當前提交
203fda5761

+ 112 - 10
src/pages/device/Instance/Detail/ChildDevice/SaveChild/index.tsx

@@ -1,13 +1,83 @@
 import TitleComponent from '@/components/TitleComponent';
 import TitleComponent from '@/components/TitleComponent';
-import { Button, Col, Form, Input, Row } from 'antd';
+import { Button, Col, Form, Input, Row, Select } from 'antd';
+import { useEffect, useState } from 'react';
+import { service } from '../../EdgeMap';
 import MapTable from '../../EdgeMap/mapTable';
 import MapTable from '../../EdgeMap/mapTable';
 
 
 interface Props {
 interface Props {
+  data: any;
   close: () => void;
   close: () => void;
+  childData: any;
 }
 }
 
 
 const SaveChild = (props: Props) => {
 const SaveChild = (props: Props) => {
   const [form] = Form.useForm();
   const [form] = Form.useForm();
+  const [productList, setProductList] = useState<any>([]);
+  const [metaData, setMetaData] = useState<any>([]);
+  const [visible, setVisible] = useState<boolean>(false);
+
+  const getProductList = async () => {
+    const res = await service.getProductListNoPage({
+      terms: [{ column: 'accessProvider', value: 'edge-child-device' }],
+    });
+    if (res.status === 200) {
+      setProductList(res.result);
+    }
+  };
+
+  useEffect(() => {
+    // console.log(props.childData)
+    getProductList();
+    if (props.childData?.id) {
+      setVisible(true);
+    }
+  }, []);
+
+  useEffect(() => {
+    if (props.childData.id) {
+      const item = productList.filter((i: any) => i.id === props.childData.productId)[0];
+      console.log(props.childData, item);
+      // const metadata = JSON.parse(item.metadata|| []).properties?.map((item: any) => ({
+      //   metadataId: item.id,
+      //   metadataName: `${item.name}(${item.id})`,
+      //   metadataType: 'property',
+      // }));
+      // if (metadata && metadata.length !== 0) {
+      //   service
+      //     .getMap(props.data.id, {
+      //       deviceId: props.childData.id,
+      //       query: {},
+      //     })
+      //     .then((res) => {
+      //       if (res.status === 200) {
+      //         // console.log(res.result)
+      //         //合并物模型
+      //         const array = res.result[0]?.reduce((x: any, y: any) => {
+      //           const metadataId = metadata.find((item: any) => item.metadataId === y.metadataId);
+      //           if (metadataId) {
+      //             Object.assign(metadataId, y);
+      //           } else {
+      //             x.push(y);
+      //           }
+      //           return x;
+      //         }, metadata);
+      //         //删除物模型
+      //         const items = array.filter((item: any) => item.metadataName);
+      //         setMetaData(items);
+      //         const delList = array.filter((a: any) => !a.metadataName).map((b: any) => b.id);
+      //         //删除后解绑
+      //         if (delList && delList.length !== 0) {
+      //           service.removeMap(props.data.id, {
+      //             deviceId: props.childData.id,
+      //             idList: [...delList],
+      //           });
+      //         }
+      //       }
+      //     });
+      // }
+    }
+  }, [productList]);
+
   return (
   return (
     <>
     <>
       <TitleComponent
       <TitleComponent
@@ -25,13 +95,13 @@ const SaveChild = (props: Props) => {
           </>
           </>
         }
         }
       />
       />
-      <Form layout="vertical" form={form}>
+      <Form layout="vertical" form={form} initialValues={props.childData}>
         <Row gutter={[24, 24]}>
         <Row gutter={[24, 24]}>
           <Col span={12}>
           <Col span={12}>
             <Form.Item
             <Form.Item
               label="设备名称"
               label="设备名称"
-              name="username"
-              rules={[{ required: true, message: 'Please input your username!' }]}
+              name="name"
+              rules={[{ required: true, message: '请输入设备名称' }]}
             >
             >
               <Input />
               <Input />
             </Form.Item>
             </Form.Item>
@@ -39,16 +109,48 @@ const SaveChild = (props: Props) => {
           <Col span={12}>
           <Col span={12}>
             <Form.Item
             <Form.Item
               label="产品名称"
               label="产品名称"
-              name="username"
-              rules={[{ required: true, message: 'Please input your username!' }]}
+              name="productId"
+              rules={[{ required: true, message: '请选择产品名称' }]}
             >
             >
-              <Input />
+              <Select
+                onChange={(e) => {
+                  if (e) {
+                    setVisible(true);
+                  }
+                  const item = productList.filter((i: any) => i.id === e)[0];
+                  const array = JSON.parse(item.metadata || [])?.properties?.map((i: any) => ({
+                    metadataType: 'property',
+                    metadataName: `${i.name}(${i.id})`,
+                    metadataId: i.id,
+                  }));
+                  setMetaData(array);
+                  console.log(array);
+                }}
+              >
+                {productList.map((item: any) => (
+                  <Select.Option key={item.id} value={item.id}>
+                    {item.name}
+                  </Select.Option>
+                ))}
+              </Select>
             </Form.Item>
             </Form.Item>
           </Col>
           </Col>
         </Row>
         </Row>
-        <Row>
-          <MapTable metaData={[]} deviceId={''} title={'点位映射'} ref={form} />
-        </Row>
+        {visible && (
+          <Row>
+            <MapTable
+              metaData={metaData}
+              edgeId={props.data.id}
+              deviceId={props.childData.id}
+              title={'点位映射'}
+              productList={productList}
+              close={() => {
+                props.close();
+              }}
+              formRef={form}
+            />
+          </Row>
+        )}
       </Form>
       </Form>
     </>
     </>
   );
   );

+ 20 - 2
src/pages/device/Instance/Detail/ChildDevice/index.tsx

@@ -2,7 +2,7 @@ import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import type { LogItem } from '@/pages/device/Instance/Detail/Log/typings';
 import type { LogItem } from '@/pages/device/Instance/Detail/Log/typings';
 import { Badge, Button, Card, Popconfirm, Tooltip } from 'antd';
 import { Badge, Button, Card, Popconfirm, Tooltip } from 'antd';
-import { DisconnectOutlined, SearchOutlined } from '@ant-design/icons';
+import { DisconnectOutlined, EditOutlined, SearchOutlined } from '@ant-design/icons';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { InstanceModel, service } from '@/pages/device/Instance';
 import { InstanceModel, service } from '@/pages/device/Instance';
 import { useRef, useState } from 'react';
 import { useRef, useState } from 'react';
@@ -20,13 +20,18 @@ statusMap.set('online', 'success');
 statusMap.set('offline', 'error');
 statusMap.set('offline', 'error');
 statusMap.set('notActive', 'warning');
 statusMap.set('notActive', 'warning');
 
 
-const ChildDevice = () => {
+interface Props {
+  data: any;
+}
+
+const ChildDevice = (props: Props) => {
   const intl = useIntl();
   const intl = useIntl();
   const [visible, setVisible] = useState<boolean>(false);
   const [visible, setVisible] = useState<boolean>(false);
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
   const [searchParams, setSearchParams] = useState<any>({});
   const [searchParams, setSearchParams] = useState<any>({});
   const [bindKeys, setBindKeys] = useState<any[]>([]);
   const [bindKeys, setBindKeys] = useState<any[]>([]);
   const [childVisible, setChildVisible] = useState<boolean>(false);
   const [childVisible, setChildVisible] = useState<boolean>(false);
+  const [current, setCurrent] = useState<any>({});
 
 
   const { minHeight } = useDomFullHeight(`.device-detail-childDevice`);
   const { minHeight } = useDomFullHeight(`.device-detail-childDevice`);
 
 
@@ -133,6 +138,16 @@ const ChildDevice = () => {
             </Tooltip>
             </Tooltip>
           </Popconfirm>
           </Popconfirm>
         </a>,
         </a>,
+        <a
+          onClick={() => {
+            setCurrent(record);
+            setChildVisible(true);
+          }}
+        >
+          <Tooltip title={'编辑'} key={'edit'}>
+            <EditOutlined />
+          </Tooltip>
+        </a>,
       ],
       ],
     },
     },
   ];
   ];
@@ -141,6 +156,8 @@ const ChildDevice = () => {
     <Card className={'device-detail-childDevice'} style={{ minHeight }}>
     <Card className={'device-detail-childDevice'} style={{ minHeight }}>
       {childVisible ? (
       {childVisible ? (
         <SaveChild
         <SaveChild
+          data={props.data}
+          childData={current}
           close={() => {
           close={() => {
             setChildVisible(false);
             setChildVisible(false);
           }}
           }}
@@ -184,6 +201,7 @@ const ChildDevice = () => {
               <Button
               <Button
                 onClick={() => {
                 onClick={() => {
                   // actionRef.current?.reset?.();
                   // actionRef.current?.reset?.();
+                  setCurrent({});
                   setChildVisible(true);
                   setChildVisible(true);
                 }}
                 }}
                 key="save"
                 key="save"

+ 59 - 17
src/pages/device/Instance/Detail/EdgeMap/mapTable/index.tsx

@@ -15,15 +15,17 @@ import { onlyMessage } from '@/utils/util';
 
 
 interface Props {
 interface Props {
   metaData: Record<string, string>[];
   metaData: Record<string, string>[];
-  deviceId: string;
+  deviceId?: string;
   edgeId: string;
   edgeId: string;
   reload?: any;
   reload?: any;
+  close?: any;
   title?: string;
   title?: string;
-  form?: any;
+  formRef?: any;
+  productList?: any;
 }
 }
 
 
 const MapTable = (props: Props) => {
 const MapTable = (props: Props) => {
-  const { metaData, deviceId, reload, edgeId } = props;
+  const { metaData, deviceId, reload, edgeId, productList } = props;
   const [visible, setVisible] = useState<boolean>(false);
   const [visible, setVisible] = useState<boolean>(false);
   const [channelList, setChannelList] = useState<any>([]);
   const [channelList, setChannelList] = useState<any>([]);
 
 
@@ -34,7 +36,11 @@ const MapTable = (props: Props) => {
     });
     });
     if (res.status === 200) {
     if (res.status === 200) {
       onlyMessage('解绑成功');
       onlyMessage('解绑成功');
-      reload('remove');
+      if (props.formRef) {
+        props.close();
+      } else {
+        reload('save');
+      }
     }
     }
   };
   };
 
 
@@ -148,7 +154,11 @@ const MapTable = (props: Props) => {
     const res = await service.saveMap(edgeId, item);
     const res = await service.saveMap(edgeId, item);
     if (res.status === 200) {
     if (res.status === 200) {
       onlyMessage('保存成功');
       onlyMessage('保存成功');
-      reload('save');
+      if (props.formRef) {
+        props.close();
+      } else {
+        reload('save');
+      }
     }
     }
   };
   };
 
 
@@ -202,6 +212,35 @@ const MapTable = (props: Props) => {
       });
       });
     },
     },
   });
   });
+  const add = async () => {
+    const value = await props.formRef.validateFields();
+    const mapValue: any = await form.submit();
+    // console.log(value)
+    if (value && mapValue) {
+      if (mapValue.requestList.length === 0) {
+        onlyMessage('请配置物模型', 'warning');
+      } else {
+        const formData = {
+          ...value,
+          productName: productList.find((item: any) => item.id === value.productId).name,
+          parentId: edgeId,
+          id: deviceId ? deviceId : undefined,
+        };
+        console.log(formData);
+        const res = await service.addDevice(formData);
+        if (res.status === 200) {
+          const array = mapValue.requestList.filter((item: any) => item.channelId);
+          const submitData = {
+            deviceId: res.result.id,
+            provider: array?.[0]?.provider,
+            requestList: array,
+          };
+          save(submitData);
+        }
+      }
+      console.log(value, mapValue);
+    }
+  };
 
 
   const schema = {
   const schema = {
     type: 'object',
     type: 'object',
@@ -394,17 +433,18 @@ const MapTable = (props: Props) => {
         <Button
         <Button
           type="primary"
           type="primary"
           onClick={async () => {
           onClick={async () => {
-            // const formData = await props.ref?.validateFields();
-            // console.log(formData, props.ref);
-            const value: any = await form.submit();
-            const array = value.requestList.filter((item: any) => item.channelId);
-            const submitData = {
-              deviceId: deviceId,
-              provider: array[0].provider,
-              requestList: array,
-            };
-            save(submitData);
-            console.log(submitData);
+            if (props.formRef) {
+              add();
+            } else {
+              const value: any = await form.submit();
+              const array = value.requestList.filter((item: any) => item.channelId);
+              const submitData = {
+                deviceId: deviceId,
+                provider: array[0].provider,
+                requestList: array,
+              };
+              save(submitData);
+            }
           }}
           }}
         >
         >
           保存
           保存
@@ -419,9 +459,11 @@ const MapTable = (props: Props) => {
         <MapTree
         <MapTree
           close={() => {
           close={() => {
             setVisible(false);
             setVisible(false);
+            reload('map');
           }}
           }}
-          deviceId={deviceId}
+          deviceId={deviceId || ''}
           edgeId={edgeId}
           edgeId={edgeId}
+          metaData={metaData}
         />
         />
       )}
       )}
     </div>
     </div>

+ 38 - 41
src/pages/device/Instance/Detail/EdgeMap/mapTree/index.tsx

@@ -1,3 +1,4 @@
+import { onlyMessage } from '@/utils/util';
 import { DeleteOutlined } from '@ant-design/icons';
 import { DeleteOutlined } from '@ant-design/icons';
 import { Button, Card, Modal, Tree, List, Popconfirm } from 'antd';
 import { Button, Card, Modal, Tree, List, Popconfirm } from 'antd';
 import { useEffect, useRef, useState } from 'react';
 import { useEffect, useRef, useState } from 'react';
@@ -8,50 +9,17 @@ interface Props {
   close: any;
   close: any;
   deviceId: string;
   deviceId: string;
   edgeId: string;
   edgeId: string;
+  metaData: any;
 }
 }
 
 
 const MapTree = (props: Props) => {
 const MapTree = (props: Props) => {
-  const { deviceId, edgeId, close } = props;
+  const { deviceId, edgeId, close, metaData } = props;
   const [data, setData] = useState<any>([]);
   const [data, setData] = useState<any>([]);
   const [checked, setChecked] = useState<any>([]);
   const [checked, setChecked] = useState<any>([]);
   const filterRef = useRef<any>([]);
   const filterRef = useRef<any>([]);
   const [expandedKey, setExpandedKey] = useState<any>();
   const [expandedKey, setExpandedKey] = useState<any>();
   const [list, setList] = useState<any>([]);
   const [list, setList] = useState<any>([]);
 
 
-  const treeData = [
-    {
-      name: '通道1',
-      id: '1',
-      collectors: [
-        {
-          name: '设备1',
-          id: '1-1',
-          parentId: '1',
-          points: [
-            {
-              name: '点位1',
-              id: '1-1-1',
-            },
-            {
-              name: '点位2',
-              id: '1-1-2',
-            },
-          ],
-        },
-        {
-          name: '设备2',
-          id: '1-2',
-          parentId: '1',
-        },
-      ],
-    },
-    {
-      name: '通道2',
-      id: '2',
-      collectors: [],
-    },
-  ];
-
   const filterTree = (nodes: any[], lists: any[]) => {
   const filterTree = (nodes: any[], lists: any[]) => {
     if (!nodes?.length) {
     if (!nodes?.length) {
       return nodes;
       return nodes;
@@ -59,7 +27,7 @@ const MapTree = (props: Props) => {
     return nodes.filter((item) => {
     return nodes.filter((item) => {
       if (lists.indexOf(item.id) > -1) {
       if (lists.indexOf(item.id) > -1) {
         filterRef.current.push(item);
         filterRef.current.push(item);
-        console.log(filterRef.current, 'filterRef.current');
+        // console.log(filterRef.current, 'filterRef.current');
         return false;
         return false;
       }
       }
       // 符合条件的保留,并且需要递归处理其子节点
       // 符合条件的保留,并且需要递归处理其子节点
@@ -79,15 +47,43 @@ const MapTree = (props: Props) => {
     filterRef.current = filterRef.current.filter((element: any) => element.id !== node.id);
     filterRef.current = filterRef.current.filter((element: any) => element.id !== node.id);
   };
   };
 
 
+  const save = async () => {
+    // console.log(list,'list')
+    const params: any[] = [];
+    const metadataId = metaData.map((item: any) => item.metadataId);
+    list.forEach((item: any) => {
+      const array = item.points.map((element: any) => ({
+        channelId: item.parentId,
+        collectorId: element.collectorId,
+        pointId: element.id,
+        metadataType: 'property',
+        metadataId: metadataId.find((i: any) => i === element.id),
+        provider: data.find((it: any) => it.id === item.parentId).provider,
+      }));
+      params.push(...array);
+    });
+
+    // console.log(params)
+    const res = await service.saveMap(edgeId, {
+      deviceId: deviceId,
+      provider: params[0].provider,
+      requestList: params,
+    });
+    if (res.status === 200) {
+      onlyMessage('保存成功');
+      close();
+    }
+  };
+
   useEffect(() => {
   useEffect(() => {
-    console.log(close, deviceId);
+    console.log(metaData);
     service.treeMap(edgeId).then((res) => {
     service.treeMap(edgeId).then((res) => {
       if (res.status === 200) {
       if (res.status === 200) {
+        console.log(res.result?.[0], 'data');
         setData(res.result?.[0]);
         setData(res.result?.[0]);
+        setExpandedKey([res.result?.[0].id]);
       }
       }
     });
     });
-    // setData(treeData);
-    setExpandedKey([treeData?.[0].id]);
   }, []);
   }, []);
 
 
   useEffect(() => {
   useEffect(() => {
@@ -99,10 +95,11 @@ const MapTree = (props: Props) => {
       title="批量映射"
       title="批量映射"
       visible
       visible
       onCancel={() => {
       onCancel={() => {
-        props.close();
+        close();
       }}
       }}
       onOk={() => {
       onOk={() => {
-        props.close();
+        //  close();
+        save();
       }}
       }}
       width="900px"
       width="900px"
     >
     >

+ 10 - 0
src/pages/device/Instance/Detail/EdgeMap/service.ts

@@ -55,6 +55,16 @@ class Service extends BaseService<any> {
       method: 'POST',
       method: 'POST',
       data,
       data,
     });
     });
+  getProductListNoPage = (params?: any) =>
+    request(`/${SystemConst.API_BASE}/device/product/_query/no-paging?paging=false`, {
+      method: 'POST',
+      data: params,
+    });
+  addDevice = (params: any) =>
+    request(`/${SystemConst.API_BASE}/device-instance`, {
+      method: 'PATCH',
+      data: params,
+    });
 }
 }
 
 
 export default Service;
 export default Service;

+ 1 - 1
src/pages/device/Instance/Detail/index.tsx

@@ -211,7 +211,7 @@ const InstanceDetail = observer(() => {
         datalist.push({
         datalist.push({
           key: 'child-device',
           key: 'child-device',
           tab: '子设备',
           tab: '子设备',
-          component: <ChildDevice />,
+          component: <ChildDevice data={InstanceModel.detail} />,
         });
         });
       }
       }
       if (response.result.accessProvider === 'edge-child-device' && response.result.parentId) {
       if (response.result.accessProvider === 'edge-child-device' && response.result.parentId) {

+ 5 - 0
src/pages/device/Instance/service.ts

@@ -14,6 +14,11 @@ class Service extends BaseService<DeviceInstance> {
       method: 'GET',
       method: 'GET',
       params,
       params,
     });
     });
+  public getProductListNoPage = (params?: any) =>
+    request(`/${SystemConst.API_BASE}/device/product/_query/no-paging?paging=false`, {
+      method: 'POST',
+      data: params,
+    });
 
 
   // 批量删除设备
   // 批量删除设备
   public batchDeleteDevice = (params: any) =>
   public batchDeleteDevice = (params: any) =>