Quellcode durchsuchen

feat(device): extract downloadFile、updateMetadata

Lind vor 3 Jahren
Ursprung
Commit
3f144fedb4

+ 12 - 27
src/pages/device/Instance/Export/index.tsx

@@ -1,4 +1,4 @@
-import { FormItem, FormLayout, Select, Radio } from '@formily/antd';
+import { FormItem, FormLayout, Radio, Select } from '@formily/antd';
 import { createForm } from '@formily/core';
 import { createSchemaField, FormProvider } from '@formily/react';
 import { Alert, Modal } from 'antd';
@@ -7,8 +7,8 @@ import { useEffect, useState } from 'react';
 import { service } from '@/pages/device/Instance';
 import type { DeviceInstance } from '../typings';
 import SystemConst from '@/utils/const';
-import Token from '@/utils/token';
 import encodeQuery from '@/utils/encodeQuery';
+import { downloadFile } from '@/utils/util';
 
 interface Props {
   visible: boolean;
@@ -60,6 +60,9 @@ const Export = (props: Props) => {
             'x-decorator': 'FormItem',
             'x-component': 'Select',
             enum: [...productList],
+            'x-component-props': {
+              allowClear: true,
+            },
           },
           fileType: {
             title: '文件格式',
@@ -87,31 +90,15 @@ const Export = (props: Props) => {
   };
   const downloadTemplate = async () => {
     const values = (await form.submit()) as any;
-    const formElement = document.createElement('form');
-    formElement.style.display = 'display:none;';
-    formElement.method = 'GET';
+    const params = encodeQuery(props.data);
     if (values.product) {
-      formElement.action = `/${SystemConst.API_BASE}/device/instance/${values.product}/export.${values.fileType}`;
+      downloadFile(
+        `/${SystemConst.API_BASE}/device/instance/${values.product}/export.${values.fileType}`,
+        params,
+      );
     } else {
-      formElement.action = `/${SystemConst.API_BASE}/device/instance/export.${values.fileType}`;
+      downloadFile(`/${SystemConst.API_BASE}/device/instance/export.${values.fileType}`, params);
     }
-    const params = encodeQuery(props.data);
-    Object.keys(params).forEach((key: string) => {
-      const inputElement = document.createElement('input');
-      inputElement.type = 'hidden';
-      inputElement.name = key;
-      inputElement.value = params[key];
-      formElement.appendChild(inputElement);
-    });
-    const inputElement = document.createElement('input');
-    inputElement.type = 'hidden';
-    inputElement.name = ':X_Access_Token';
-    inputElement.value = Token.get();
-    formElement.appendChild(inputElement);
-
-    document.body.appendChild(formElement);
-    formElement.submit();
-    document.body.removeChild(formElement);
   };
   return (
     <Modal
@@ -119,9 +106,7 @@ const Export = (props: Props) => {
       onCancel={() => close()}
       width="35vw"
       title="导出"
-      onOk={() => {
-        downloadTemplate();
-      }}
+      onOk={downloadTemplate}
     >
       <Alert
         message="不勾选产品,默认导出所有设备的基础数据,勾选单个产品可导出下属的详细数据"

+ 10 - 20
src/pages/device/Instance/Import/index.tsx

@@ -11,6 +11,7 @@ import { UploadOutlined } from '@ant-design/icons';
 import SystemConst from '@/utils/const';
 import Token from '@/utils/token';
 import { EventSourcePolyfill } from 'event-source-polyfill';
+import { downloadFile } from '@/utils/util';
 
 interface Props {
   visible: boolean;
@@ -60,28 +61,13 @@ const FileFormat = (props: any) => {
   );
 };
 
-const downloadTemplate = (type: string, product: string) => {
-  const formElement = document.createElement('form');
-  formElement.style.display = 'display:none;';
-  formElement.method = 'GET';
-  formElement.action = `/${SystemConst.API_BASE}/device-instance/${product}/template.${type}`;
-  const inputElement = document.createElement('input');
-  inputElement.type = 'hidden';
-  inputElement.name = ':X_Access_Token';
-  inputElement.value = Token.get();
-  formElement.appendChild(inputElement);
-  document.body.appendChild(formElement);
-  formElement.submit();
-  document.body.removeChild(formElement);
-};
-
 const NormalUpload = (props: any) => {
   const [importLoading, setImportLoading] = useState(false);
   const [flag, setFlag] = useState<boolean>(true);
   const [count, setCount] = useState<number>(0);
   const [errMessage, setErrMessage] = useState<string>('');
 
-  const submitData = (fileUrl: string) => {
+  const submitData = async (fileUrl: string) => {
     if (!!fileUrl) {
       setCount(0);
       setErrMessage('');
@@ -123,11 +109,11 @@ const NormalUpload = (props: any) => {
           headers={{
             'X-Access-Token': Token.get(),
           }}
-          onChange={(info) => {
+          onChange={async (info) => {
             if (info.file.status === 'done') {
               message.success('上传成功');
               const resp: any = info.file.response || { result: '' };
-              submitData(resp?.result || '');
+              await submitData(resp?.result || '');
             }
           }}
           showUploadList={false}
@@ -139,7 +125,9 @@ const NormalUpload = (props: any) => {
           <a
             style={{ marginLeft: 10 }}
             onClick={() => {
-              downloadTemplate('xlsx', props.product);
+              const url = `/${SystemConst.API_BASE}/device-instance/${props.product}/template.xlsx`;
+              downloadFile(url);
+              // downloadTemplate('xlsx', props.product);
             }}
           >
             .xlsx
@@ -147,7 +135,9 @@ const NormalUpload = (props: any) => {
           <a
             style={{ marginLeft: 10 }}
             onClick={() => {
-              downloadTemplate('csv', props.product);
+              const url = `/${SystemConst.API_BASE}/device-instance/${props.product}/template.csv`;
+              downloadFile(url);
+              // downloadTemplate('csv', props.product);
             }}
           >
             .csv

+ 35 - 24
src/pages/device/Product/Detail/PropertyImport/index.tsx

@@ -1,35 +1,38 @@
-import { Modal } from 'antd';
+import { Button, message, Modal, Space, Upload } from 'antd';
 import MetadataModel from '@/pages/device/components/Metadata/Base/model';
 import { FormItem, FormLayout, Radio } from '@formily/antd';
 import { createForm, onFieldValueChange } from '@formily/core';
 import { createSchemaField, FormProvider } from '@formily/react';
-import { Button, message, Space, Upload } from 'antd';
 import 'antd/lib/tree-select/style/index.less';
 import { UploadOutlined } from '@ant-design/icons';
 import SystemConst from '@/utils/const';
 import Token from '@/utils/token';
 import { useParams } from 'umi';
-import { service } from '../..';
-
-const downloadTemplate = (type: string, productId: string) => {
-  const formElement = document.createElement('form');
-  formElement.style.display = 'display:none;';
-  formElement.method = 'GET';
-  formElement.action = `/${SystemConst.API_BASE}/device/product/${productId}/property-metadata/template.${type}`;
-  const inputElement = document.createElement('input');
-  inputElement.type = 'hidden';
-  inputElement.name = ':X_Access_Token';
-  inputElement.value = Token.get();
-  formElement.appendChild(inputElement);
-  document.body.appendChild(formElement);
-  formElement.submit();
-  document.body.removeChild(formElement);
-};
+import { productModel, service } from '../..';
+import { downloadFile } from '@/utils/util';
+import type { DeviceMetadata, ProductItem } from '@/pages/device/Product/typings';
+import { updateMetadata } from '@/utils/metadata';
 
 const NormalUpload = (props: any) => {
   const param = useParams<{ id: string }>();
   console.log(props?.fileType);
 
+  const mergeMetadata = async (url: string) => {
+    if (!url) return;
+    // 解析物模型
+    const r = await service.importProductProperty(param.id, url);
+    const _metadata = JSON.parse(r.result || '{}') as DeviceMetadata;
+
+    const product = productModel.current;
+
+    const _product = updateMetadata('properties', _metadata.properties, product!) as ProductItem;
+    const resp = await service.update(_product);
+    console.log(resp);
+    if (resp.status === 200) {
+      message.success('操作成功');
+    }
+  };
+
   return (
     <div>
       <Space>
@@ -39,13 +42,17 @@ const NormalUpload = (props: any) => {
           headers={{
             'X-Access-Token': Token.get(),
           }}
-          onChange={(info) => {
+          onChange={async (info) => {
             if (info.file.status === 'done') {
               message.success('上传成功');
               const resp: any = info.file.response || { result: '' };
-              service.importProductProperty(param.id, resp?.result).then(() => {
-                // 更新产品物模型属性信息
-              });
+              await mergeMetadata(resp?.result);
+              // service.importProductProperty(param.id, resp?.result).then((r) => {
+              //   console.log(r, 'resp');
+              //   const _metadata = JSON.parse(r.result || '{}') as DeviceMetadata;
+              //
+              //   // 更新产品物模型属性信息
+              // });
             }
           }}
           showUploadList={false}
@@ -57,7 +64,9 @@ const NormalUpload = (props: any) => {
           <a
             style={{ marginLeft: 10 }}
             onClick={() => {
-              downloadTemplate('xlsx', param?.id);
+              const url = `/${SystemConst.API_BASE}/device/product/${param?.id}/property-metadata/template.xlsx`;
+              downloadFile(url);
+              // downloadTemplate('xlsx', param?.id);
             }}
           >
             .xlsx
@@ -65,7 +74,9 @@ const NormalUpload = (props: any) => {
           <a
             style={{ marginLeft: 10 }}
             onClick={() => {
-              downloadTemplate('csv', param?.id);
+              const url = `/${SystemConst.API_BASE}/device/product/${param.id}/property-metadata/template.csv`;
+              // downloadTemplate('csv', param?.id);
+              downloadFile(url);
             }}
           >
             .csv

+ 43 - 0
src/utils/metadata.ts

@@ -0,0 +1,43 @@
+import type {
+  DeviceMetadata,
+  MetadataItem,
+  MetadataType,
+  ProductItem,
+} from '@/pages/device/Product/typings';
+import type { DeviceInstance } from '@/pages/device/Instance/typings';
+
+/**
+ *
+ * @param type 物模型类型 events
+ * @param item 物模型数据 【{a},{b},{c}】
+ // * @param target product、device
+ * @param data product 、device [{event:[1,2,3]]
+ * @param onEvent 数据更新回调:更新数据库、发送事件等操作
+ *
+ */
+export const updateMetadata = (
+  type: MetadataType,
+  item: MetadataItem[],
+  // target: 'product' | 'device',
+  data: ProductItem | DeviceInstance,
+  onEvent?: (type: 'update' | 'add', item: MetadataItem) => void,
+): ProductItem | DeviceInstance => {
+  const metadata = JSON.parse(data.metadata || '{}') as DeviceMetadata;
+  const config = (metadata[type] || []) as MetadataItem[];
+  if (item.length > 1) {
+    item.forEach((i) => {
+      const index = config.findIndex((c) => c.id === i.id);
+      if (index > -1) {
+        config[index] = i;
+        onEvent?.('update', i);
+      } else {
+        config.push(i);
+        onEvent?.('add', i);
+      }
+    });
+  }
+  // @ts-ignore
+  metadata[type] = config;
+  data.metadata = JSON.stringify(metadata);
+  return data;
+};

+ 30 - 0
src/utils/util.ts

@@ -1,8 +1,38 @@
 import moment from 'moment';
 import type { Field, FieldDataSource } from '@formily/core';
 import { action } from '@formily/reactive';
+import Token from '@/utils/token';
 
 /**
+ * 下载文件
+ * @param url 下载链接
+ * @param params 参数
+ */
+export const downloadFile = (url: string, params?: Record<string, any>) => {
+  const formElement = document.createElement('form');
+  formElement.style.display = 'display:none;';
+  formElement.method = 'GET';
+  formElement.action = url;
+  // 添加参数
+  if (params) {
+    Object.keys(params).forEach((key: string) => {
+      const inputElement = document.createElement('input');
+      inputElement.type = 'hidden';
+      inputElement.name = key;
+      inputElement.value = params[key];
+      formElement.appendChild(inputElement);
+    });
+  }
+  const inputElement = document.createElement('input');
+  inputElement.type = 'hidden';
+  inputElement.name = ':X_Access_Token';
+  inputElement.value = Token.get();
+  formElement.appendChild(inputElement);
+  document.body.appendChild(formElement);
+  formElement.submit();
+  document.body.removeChild(formElement);
+};
+/**
  * 把数据下载成JSON
  * @param record
  * @param fileName