فهرست منبع

feat(device): status->property actions

Lind 4 سال پیش
والد
کامیت
ce8d912c66

+ 67 - 0
src/pages/device/Instance/Detail/PropertyList/index.tsx

@@ -0,0 +1,67 @@
+import type { ProColumns } from '@jetlinks/pro-table';
+import ProTable from '@jetlinks/pro-table';
+import { service } from '@/pages/device/Instance';
+import { useParams } from 'umi';
+import { Drawer } from 'antd';
+import encodeQuery from '@/utils/encodeQuery';
+import moment from 'moment';
+import type { PropertyMetadata } from '@/pages/device/Product/typings';
+
+type PropertyData = {
+  data: string;
+  date: string;
+};
+
+interface Props {
+  property: string;
+  visible: boolean;
+  close: () => void;
+  data: Partial<PropertyMetadata>;
+}
+
+const PropertyList = (props: Props) => {
+  const params = useParams<{ id: string }>();
+  const { property, visible, close, data } = props;
+  const columns: ProColumns<PropertyData>[] = [
+    {
+      dataIndex: 'index',
+      valueType: 'indexBorder',
+      width: 48,
+    },
+    {
+      dataIndex: 'timestamp',
+      title: '时间',
+      sorter: true,
+      width: 200,
+      renderText: (text: string) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
+    },
+    {
+      dataIndex: 'formatValue',
+      title: '数据',
+      copyable: true,
+    },
+  ];
+  return (
+    <Drawer title={data.name} visible={visible} onClose={() => close()} width="45vw">
+      <ProTable
+        size="small"
+        toolBarRender={false}
+        request={async (param) =>
+          service.getPropertyData(
+            params.id,
+            encodeQuery({
+              ...param,
+              terms: { property: property },
+              sorts: { timestamp: 'desc' },
+            }),
+          )
+        }
+        pagination={{
+          pageSize: 15,
+        }}
+        columns={columns}
+      />
+    </Drawer>
+  );
+};
+export default PropertyList;

+ 64 - 12
src/pages/device/Instance/Detail/Running/Property.tsx

@@ -1,11 +1,12 @@
-import { EditOutlined, SyncOutlined } from '@ant-design/icons';
-import { Divider, message, Spin } from 'antd';
+import { EditOutlined, SyncOutlined, UnorderedListOutlined } from '@ant-design/icons';
+import { Button, Divider, Input, message, Popover, Spin, Tooltip } from 'antd';
 import ProCard from '@ant-design/pro-card';
 import type { ObserverMetadata, PropertyMetadata } from '@/pages/device/Product/typings';
 import { Line } from '@ant-design/charts';
 import { useCallback, useEffect, useRef, useState } from 'react';
 import { service } from '@/pages/device/Instance';
 import { useParams } from 'umi';
+import PropertyList from '@/pages/device/Instance/Detail/PropertyList';
 
 interface Props {
   data: Partial<PropertyMetadata> & ObserverMetadata;
@@ -86,20 +87,65 @@ const Property = (props: Props) => {
       message.success('操作成功');
     }
   };
+
+  const [propertyValue, setPropertyValue] = useState<string>();
+  const [visible, setVisible] = useState<boolean>(false);
+  const handleSetPropertyValue = async () => {
+    const resp = await service.setProperty(params.id, { [`${data.id}`]: propertyValue });
+    if (resp.status === 200) {
+      message.success('操作成功');
+    }
+  };
+
+  const renderSetProperty = () => {
+    if (data.expands?.readOnly === false || data.expands?.readOnly === 'false') {
+      return (
+        <Popover
+          trigger="click"
+          title={
+            <div
+              style={{
+                display: 'flex',
+                justifyContent: 'space-between',
+              }}
+            >
+              <span>设置属性</span>
+              <Button size="small" type="primary" onClick={handleSetPropertyValue}>
+                设置
+              </Button>
+            </div>
+          }
+          content={
+            <Input value={propertyValue} onChange={(e) => setPropertyValue(e.target.value)} />
+          }
+        >
+          <Tooltip placement="top" title="设置属性至设备">
+            <EditOutlined />
+          </Tooltip>
+          <Divider type="vertical" />
+        </Popover>
+      );
+    } else {
+      return null;
+    }
+  };
   return (
     <ProCard
       title={`${data?.name} ${title}`}
       extra={
         <>
-          <EditOutlined
-            onClick={async () => {
-              message.success('设置属性');
-            }}
-          />
-          <Divider type="vertical" />
-          <SyncOutlined onClick={refreshProperty} />
+          {renderSetProperty()}
+          <Tooltip placement="top" title="获取最新属性值">
+            <SyncOutlined onClick={refreshProperty} />
+          </Tooltip>
           <Divider type="vertical" />
-          <EditOutlined onClick={refreshProperty} />
+          <Tooltip placement="top" title="详情">
+            <UnorderedListOutlined
+              onClick={() => {
+                setVisible(true);
+              }}
+            />
+          </Tooltip>
         </>
       }
       layout="center"
@@ -107,9 +153,15 @@ const Property = (props: Props) => {
       headerBordered
       colSpan={{ xs: 12, sm: 8, md: 6, lg: 6, xl: 6 }}
     >
-      <Spin spinning={loading} style={{ height: 60 }}>
-        {chart()}
+      <Spin spinning={loading}>
+        <div style={{ height: 60 }}>{chart()}</div>
       </Spin>
+      <PropertyList
+        data={data}
+        property={data.id!}
+        visible={visible}
+        close={() => setVisible(false)}
+      />
     </ProCard>
   );
 };

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

@@ -43,6 +43,18 @@ class Service extends BaseService<DeviceInstance> {
     request(`/${SystemConst.API_BASE}/device/standard/${id}/property/${type}`, {
       method: 'GET',
     });
+
+  public setProperty = (deviceId: string, data: Record<string, unknown>) =>
+    request(`/${SystemConst.API_BASE}/device/instance/${deviceId}/property`, {
+      method: 'PUT',
+      data,
+    });
+
+  public getPropertyData = (deviceId: string, params: Record<string, unknown>) =>
+    request(`/${SystemConst.API_BASE}/device-instance/${deviceId}/properties/_query`, {
+      method: 'GET',
+      params,
+    });
 }
 
 export default Service;