Browse Source

refactor(device): device -> Metadata

Lind 4 years atrás
parent
commit
0dd373b0af

+ 0 - 134
src/pages/device/Instance/Detail/Metadata/ItemDetail/index.tsx

@@ -1,134 +0,0 @@
-import { InstanceModel } from '@/pages/device/Instance';
-
-import { createForm } from '@formily/core';
-import { createSchemaField } from '@formily/react';
-import {
-  Form,
-  FormItem,
-  FormLayout,
-  Input,
-  Select,
-  Cascader,
-  DatePicker,
-  FormGrid,
-  ArrayItems,
-  Editable,
-  Radio,
-} from '@formily/antd';
-import type { MetadataItem } from '@/pages/device/Product/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-const ItemDetail = () => {
-  const intl = useIntl();
-  const form = createForm<MetadataItem>({
-    validateFirst: true,
-    initialValues: InstanceModel.metadataItem,
-  });
-  const SchemaField = createSchemaField({
-    components: {
-      FormItem,
-      FormGrid,
-      FormLayout,
-      Input,
-      DatePicker,
-      Cascader,
-      Select,
-      ArrayItems,
-      Editable,
-      Radio,
-    },
-  });
-
-  const schema = {
-    type: 'object',
-    properties: {
-      id: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.logotype',
-          defaultMessage: '',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      name: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.attributeName',
-          defaultMessage: '属性名称',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      dataType: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.dataType',
-          defaultMessage: '数据类型',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Select',
-        enum: [
-          { label: 'int(整数型)', value: 'int' },
-          { label: 'long(长整数型)', value: 'long' },
-          { label: 'double(双精度浮点数)', value: 'double' },
-          { label: 'float(单精度浮点数)', value: 'float' },
-          { label: 'text(字符串)', value: 'string' },
-          { label: 'bool(布尔型)', value: 'boolean' },
-          { label: 'date(时间型)', value: 'date' },
-          { label: 'enum(枚举)', value: 'enum' },
-          { label: 'array(数组)', value: 'array' },
-          { label: 'object(结构体)', value: 'object' },
-          { label: 'geoPoint(地理位置)', value: 'geoPoint' },
-        ],
-      },
-      readOnly: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.readOnly',
-          defaultMessage: '只读',
-        }),
-        enum: [
-          {
-            label: intl.formatMessage({
-              id: 'pages.device.instanceDetail.metadata.readOnly.yes',
-              defaultMessage: '是',
-            }),
-            value: 1,
-          },
-          {
-            label: intl.formatMessage({
-              id: 'pages.device.instanceDetail.metadata.readOnly.no',
-              defaultMessage: '否',
-            }),
-            value: 2,
-          },
-        ],
-        'x-decorator': 'FormItem',
-        'x-component': 'Radio.Group',
-      },
-      description: {
-        type: 'string',
-        required: true,
-        title: intl.formatMessage({
-          id: 'pages.table.describe',
-          defaultMessage: '描述',
-        }),
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
-      },
-    },
-  };
-  return (
-    <>
-      <Form form={form} labelCol={8} wrapperCol={16} onAutoSubmit={console.log} size="small">
-        <SchemaField schema={schema} />
-      </Form>
-    </>
-  );
-};
-
-export default ItemDetail;

+ 0 - 53
src/pages/device/Instance/Detail/Metadata/ItemList/index.tsx

@@ -1,53 +0,0 @@
-import type { MetadataItem } from '@/pages/device/Product/typings';
-import { InstanceModel } from '@/pages/device/Instance';
-import { Popconfirm, Tooltip } from 'antd';
-import { CloseCircleOutlined } from '@ant-design/icons';
-import ProList from '@jetlinks/pro-list';
-
-interface Props {
-  metadata: Partial<MetadataItem>;
-}
-
-const ItemList = (props: Props) => {
-  const { metadata } = props;
-  return (
-    <ProList
-      rowKey="id"
-      bordered={true}
-      showActions="hover"
-      onRow={(record: MetadataItem) => {
-        return {
-          onClick: () => {
-            InstanceModel.metadataItem = record;
-          },
-        };
-      }}
-      dataSource={metadata.properties}
-      metas={{
-        title: {
-          dataIndex: 'name',
-        },
-        id: {
-          dataIndex: 'id',
-        },
-        actions: {
-          render: (text, row) => [
-            <Popconfirm
-              onConfirm={() => {
-                console.log(row);
-              }}
-              title="确认删除?"
-            >
-              <Tooltip title="删除">
-                <a>
-                  <CloseCircleOutlined />
-                </a>
-              </Tooltip>
-            </Popconfirm>,
-          ],
-        },
-      }}
-    ></ProList>
-  );
-};
-export default ItemList;

+ 0 - 219
src/pages/device/Instance/Detail/Metadata/ItemParam/index.tsx

@@ -1,219 +0,0 @@
-import { createSchemaField } from '@formily/react';
-import type { IFieldState } from '@formily/core';
-import { createForm, onFieldValueChange } from '@formily/core';
-import {
-  FormItem,
-  Form,
-  FormGrid,
-  FormLayout,
-  Input,
-  DatePicker,
-  Cascader,
-  Select,
-  ArrayItems,
-  Editable,
-  Radio,
-  PreviewText,
-} from '@formily/antd';
-import { InstanceModel, service } from '@/pages/device/Instance';
-import type { Unit } from '@/pages/device/Instance/typings';
-import type { ISchema } from '@formily/json-schema';
-import ProCard from '@ant-design/pro-card';
-import { useState } from 'react';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-const ItemParam = () => {
-  const intl = useIntl();
-  const [cardId, setCardId] = useState<string>('');
-  const form = createForm({
-    validateFirst: true,
-    readPretty: InstanceModel.active === cardId,
-    effects() {
-      onFieldValueChange('type', (field) => {
-        const type = field.query('type').value();
-        const id = field.query('id').value();
-        setCardId(`${id}-$${InstanceModel.params.size}`);
-        const temp = Array.from(InstanceModel.params).map((item) => item.split('-$')[0]);
-        const includes = new Set(temp).has(id);
-        if (includes && type !== 'object') {
-          InstanceModel.params.delete(`${id}-$${InstanceModel.params.size - 1}`);
-        } else if (id && type === 'object') {
-          InstanceModel.active = `${id}-$${InstanceModel.params.size}`;
-          InstanceModel.params.add(`${id}-$${InstanceModel.params.size}`);
-        }
-      });
-    },
-  });
-
-  const SchemaField = createSchemaField({
-    components: {
-      FormItem,
-      FormGrid,
-      FormLayout,
-      Input,
-      DatePicker,
-      Cascader,
-      Select,
-      ArrayItems,
-      Editable,
-      Radio,
-    },
-    scope: {
-      fetchUnits: async (field: IFieldState) => {
-        const unit = await service.getUnits();
-        // eslint-disable-next-line no-param-reassign
-        field.dataSource = unit.result?.map((item: Unit) => ({
-          label: item.text,
-          value: item.id,
-        }));
-      },
-    },
-  });
-
-  const schema: ISchema = {
-    type: 'object',
-    properties: {
-      id: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.logotype',
-          defaultMessage: '属性标识',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      name: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.parameterName',
-          defaultMessage: '参数名称',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-      },
-      type: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.dataType',
-          defaultMessage: '数据类型',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Select',
-        enum: [
-          { label: 'int(整数型)', value: 'int' },
-          { label: 'long(长整数型)', value: 'long' },
-          { label: 'double(双精度浮点数)', value: 'double' },
-          { label: 'float(单精度浮点数)', value: 'float' },
-          { label: 'text(字符串)', value: 'string' },
-          { label: 'bool(布尔型)', value: 'boolean' },
-          { label: 'date(时间型)', value: 'date' },
-          { label: 'enum(枚举)', value: 'enum' },
-          { label: 'array(数组)', value: 'array' },
-          { label: 'object(结构体)', value: 'object' },
-          { label: 'geoPoint(地理位置)', value: 'geoPoint' },
-        ],
-      },
-      scale: {
-        type: 'string',
-        title: '精度',
-        'x-display': 'none',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-reactions': {
-          dependencies: ['type'],
-          fulfill: {
-            state: {
-              display: '{{($deps[0]==="float"||$deps[0]==="double")?"visible":"none"}}',
-            },
-          },
-        },
-      },
-      maxLength: {
-        type: 'number',
-        title: '最大长度',
-        'x-display': 'none',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-reactions': {
-          dependencies: ['type'],
-          fulfill: {
-            state: {
-              display: '{{($deps[0]==="string")?"visible":"none"}}',
-            },
-          },
-        },
-      },
-      format: {
-        type: 'string',
-        title: '时间格式',
-        'x-display': 'none',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-component-props': {
-          placeholder: '默认格式:String类型的UTC时间戳 (毫秒)',
-        },
-        'x-reactions': {
-          dependencies: ['type'],
-          fulfill: {
-            state: {
-              display: '{{($deps[0]==="date")?"visible":"none"}}',
-            },
-          },
-        },
-      },
-      unit: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.device.instanceDetail.metadata.unit',
-          defaultMessage: '单位',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Select',
-        'x-reactions': '{{fetchUnits}}',
-      },
-      description: {
-        type: 'string',
-        title: intl.formatMessage({
-          id: 'pages.table.describe',
-          defaultMessage: '描述',
-        }),
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
-      },
-    },
-  };
-
-  const saveParam = async () => {
-    console.log(cardId, InstanceModel.params);
-    const values = await form.submit();
-    console.log(values, 'vv');
-    InstanceModel.params.delete(cardId);
-  };
-  return (
-    <ProCard
-      extra={
-        <a onClick={saveParam}>
-          {intl.formatMessage({
-            id: 'pages.device.instanceDetail.save',
-            defaultMessage: '保存',
-          })}
-        </a>
-      }
-      bordered={true}
-      colSpan={500}
-      style={{ height: '40vh', marginRight: 10 }}
-    >
-      <PreviewText.Placeholder value="-">
-        <Form form={form} labelCol={8} wrapperCol={13} size="small">
-          <SchemaField schema={schema} />
-        </Form>
-      </PreviewText.Placeholder>
-    </ProCard>
-  );
-};
-export default ItemParam;

+ 0 - 110
src/pages/device/Instance/Detail/Metadata/index.tsx

@@ -1,110 +0,0 @@
-import ProCard from '@ant-design/pro-card';
-import { Col, Input, Row } from 'antd';
-import { InstanceModel } from '@/pages/device/Instance';
-import type { DeviceMetadata } from '@/pages/device/Product/typings';
-import ItemList from '@/pages/device/Instance/Detail/Metadata/ItemList';
-import ItemDetail from '@/pages/device/Instance/Detail/Metadata/ItemDetail';
-import ItemParam from '@/pages/device/Instance/Detail/Metadata/ItemParam';
-import { useEffect } from 'react';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-const Metadata = () => {
-  const intl = useIntl();
-  const metadata = JSON.parse(InstanceModel.detail.metadata as string) as DeviceMetadata;
-  useEffect(() => {
-    InstanceModel.params = new Set<string>(['test']);
-  }, []);
-  return (
-    <ProCard
-      tabs={{
-        tabPosition: 'left',
-      }}
-    >
-      <ProCard.TabPane
-        tab={intl.formatMessage({
-          id: 'pages.device.instanceDetail.property',
-          defaultMessage: '属性',
-        })}
-        key="property"
-        style={{ overflowX: 'auto' }}
-      >
-        <Row gutter={[16, 16]} style={{ height: '50vh' }} wrap={false}>
-          <Col span={6}>
-            <ProCard
-              bordered={true}
-              extra={
-                <Row>
-                  <Col span={18}>
-                    <Input.Search size="small" />
-                  </Col>
-                  <Col span={2} />
-                  <Col span={4} style={{ alignItems: 'center' }}>
-                    <a>
-                      {intl.formatMessage({
-                        id: 'pages.data.option.add',
-                        defaultMessage: '新增',
-                      })}
-                    </a>
-                  </Col>
-                </Row>
-              }
-              style={{ height: '40vh', marginRight: 10 }}
-            >
-              <ItemList metadata={metadata} />
-            </ProCard>
-          </Col>
-          <Col span={5}>
-            <ProCard
-              extra={
-                <a>
-                  {intl.formatMessage({
-                    id: 'pages.device.instanceDetail.save',
-                    defaultMessage: '保存',
-                  })}
-                </a>
-              }
-              bordered={true}
-              style={{ height: '40vh', marginRight: 10 }}
-            >
-              <ItemDetail />
-            </ProCard>
-          </Col>
-
-          {Array.from(InstanceModel.params).map((item, index) => (
-            <Col span={5} key={index}>
-              <ItemParam />
-            </Col>
-          ))}
-        </Row>
-      </ProCard.TabPane>
-      <ProCard.TabPane
-        tab={intl.formatMessage({
-          id: 'pages.device.instanceDetail.events',
-          defaultMessage: '事件',
-        })}
-        key="events"
-      >
-        事件
-      </ProCard.TabPane>
-      <ProCard.TabPane
-        tab={intl.formatMessage({
-          id: 'pages.device.instanceDetail.function',
-          defaultMessage: '功能',
-        })}
-        key="functions"
-      >
-        功能
-      </ProCard.TabPane>
-      <ProCard.TabPane
-        tab={intl.formatMessage({
-          id: 'pages.device.instanceDetail.tags',
-          defaultMessage: '标签',
-        })}
-        key="tags"
-      >
-        标签
-      </ProCard.TabPane>
-    </ProCard>
-  );
-};
-export default Metadata;

+ 16 - 4
src/pages/device/Instance/Detail/index.tsx

@@ -1,18 +1,20 @@
 import { PageContainer } from '@ant-design/pro-layout';
 import { InstanceModel, service } from '@/pages/device/Instance';
 import { history, useParams } from 'umi';
-import { Badge, Button, Divider } from 'antd';
+import { Badge, Button, Card, Divider } from 'antd';
 import { useEffect, useState } from 'react';
 import { statusMap } from '@/pages/device/Product';
 import { observer } from '@formily/react';
 import Config from '@/pages/device/Instance/Detail/Config';
-import Metadata from '@/pages/device/Instance/Detail/Metadata';
 import Log from '@/pages/device/Instance/Detail/Log';
 import Alarm from '@/pages/device/Instance/Detail/Alarm';
 import Info from '@/pages/device/Instance/Detail/Info';
 import Functions from '@/pages/device/Instance/Detail/Functions';
 import Running from '@/pages/device/Instance/Detail/Running';
 import { useIntl } from '@@/plugin-locale/localeExports';
+import Metadata from '../../components/Metadata';
+import { DeviceMetadata } from '@/pages/device/Product/typings';
+import MetadataAction from '@/pages/device/components/Metadata/DataBaseAction';
 
 export const deviceStatus = new Map();
 deviceStatus.set('online', <Badge status="success" text={'在线'} />);
@@ -24,6 +26,9 @@ const InstanceDetail = observer(() => {
   const getDetail = (id: string) => {
     service.detail(id).then((response) => {
       InstanceModel.detail = response?.result;
+      // 写入物模型数据
+      const metadata: DeviceMetadata = JSON.parse(response.result?.metadata);
+      MetadataAction.insert(metadata);
     });
   };
   const params = useParams<{ id: string }>();
@@ -33,7 +38,10 @@ const InstanceDetail = observer(() => {
     } else {
       getDetail(InstanceModel.current?.id || params.id);
     }
-  }, []);
+    return () => {
+      MetadataAction.clean();
+    };
+  }, [params.id]);
 
   const list = [
     {
@@ -58,7 +66,11 @@ const InstanceDetail = observer(() => {
         id: 'pages.device.instanceDetail.metadata',
         defaultMessage: '物模型',
       }),
-      component: <Metadata />,
+      component: (
+        <Card>
+          <Metadata />
+        </Card>
+      ),
     },
     {
       key: 'functions',

+ 3 - 23
src/pages/device/Product/Detail/index.tsx

@@ -9,9 +9,9 @@ import { useIntl } from '@@/plugin-locale/localeExports';
 import Metadata from '@/pages/device/components/Metadata';
 import Alarm from '@/pages/device/Product/Detail/Alarm';
 import type { DeviceMetadata } from '@/pages/device/Product/typings';
-import DB from '@/db';
 import { Link } from 'umi';
 import { Store } from 'jetlinks-store';
+import MetadataAction from '@/pages/device/components/Metadata/DataBaseAction';
 
 const ProductDetail = observer(() => {
   const intl = useIntl();
@@ -48,38 +48,18 @@ const ProductDetail = observer(() => {
   };
   const param = useParams<{ id: string }>();
 
-  const EventTable = DB.getDB().table(`events`);
-  const PropertyTable = DB.getDB().table(`properties`);
-  const FunctionTable = DB.getDB().table(`functions`);
-  const TagTable = DB.getDB().table(`tags`);
-
   useEffect(() => {
     if (!productModel.current) {
       history.goBack();
     } else {
       service.getProductDetail(param.id).subscribe((data) => {
         const metadata: DeviceMetadata = JSON.parse(data.metadata);
-
-        EventTable.clear().then(() => {
-          EventTable.bulkAdd(metadata.events || []);
-        });
-        PropertyTable.clear().then(() => {
-          PropertyTable.bulkAdd(metadata.properties || []);
-        });
-        FunctionTable.clear().then(() => {
-          FunctionTable.bulkAdd(metadata.functions || []);
-        });
-        TagTable.clear().then(() => {
-          TagTable.bulkAdd(metadata.tags || []);
-        });
+        MetadataAction.insert(metadata);
       });
     }
 
     return () => {
-      EventTable.clear();
-      PropertyTable.clear();
-      FunctionTable.clear();
-      TagTable.clear();
+      MetadataAction.clean();
     };
   }, [param.id]);
 

+ 0 - 3
src/pages/device/Product/Save/index.tsx

@@ -38,14 +38,11 @@ const Save = (props: Props) => {
   const { visible, close, data } = props;
   const handleData = () => {
     // 特殊处理deviceType字段
-    console.log(data, '处理钱');
     if (data) {
       if (typeof data.deviceType !== 'string') {
         data.deviceType = data.deviceType?.value;
       }
     }
-
-    console.log(data, '初始化数据');
     return data;
   };
   const form = createForm({

+ 19 - 1
src/pages/device/components/Metadata/Base/index.tsx

@@ -5,7 +5,7 @@ import { useParams } from 'umi';
 import DB from '@/db';
 import type { MetadataItem, MetadataType } from '@/pages/device/Product/typings';
 import MetadataMapping from './columns';
-import { Button, Popconfirm, Tooltip } from 'antd';
+import { Button, message, Popconfirm, Tooltip } from 'antd';
 import { EditOutlined, MinusOutlined, PlusOutlined } from '@ant-design/icons';
 import Edit from './Edit';
 import { observer } from '@formily/react';
@@ -83,6 +83,24 @@ const BaseMetadata = observer((props: Props) => {
         columns={MetadataMapping.get(type)!.concat(actions)}
         rowKey="id"
         search={false}
+        pagination={{
+          pageSize: 5,
+        }}
+        options={{
+          density: false,
+          fullScreen: false,
+          reload: false,
+          setting: false,
+          search: true,
+        }}
+        toolbar={{
+          search: {
+            onSearch: (value) => {
+              // Todo 物模型属性搜索
+              message.success(value);
+            },
+          },
+        }}
         toolBarRender={() => [
           <Button
             onClick={() => {

+ 31 - 0
src/pages/device/components/Metadata/DataBaseAction.ts

@@ -0,0 +1,31 @@
+import DB from '@/db';
+import type { DeviceMetadata } from '@/pages/device/Product/typings';
+
+const EventTable = DB.getDB().table(`events`);
+const PropertyTable = DB.getDB().table(`properties`);
+const FunctionTable = DB.getDB().table(`functions`);
+const TagTable = DB.getDB().table(`tags`);
+
+const MetadataAction = {
+  insert: (metadata: DeviceMetadata) => {
+    EventTable.clear().then(() => {
+      EventTable.bulkAdd(metadata.events || []);
+    });
+    PropertyTable.clear().then(() => {
+      PropertyTable.bulkAdd(metadata.properties || []);
+    });
+    FunctionTable.clear().then(() => {
+      FunctionTable.bulkAdd(metadata.functions || []);
+    });
+    TagTable.clear().then(() => {
+      TagTable.bulkAdd(metadata.tags || []);
+    });
+  },
+  clean: () => {
+    EventTable.clear();
+    PropertyTable.clear();
+    FunctionTable.clear();
+    TagTable.clear();
+  },
+};
+export default MetadataAction;