Forráskód Böngészése

Merge pull request #603 from jetlinks/next-wzy

fix: opc
孙超 3 éve
szülő
commit
9bc8b5ba0b
30 módosított fájl, 183 hozzáadás és 203 törlés
  1. 3 1
      src/components/DashBoard/echarts.tsx
  2. 1 1
      src/components/FUpload/index.tsx
  3. 1 1
      src/pages/Log/Access/index.tsx
  4. 2 2
      src/pages/Log/System/index.tsx
  5. 1 1
      src/pages/Northbound/AliCloud/index.tsx
  6. 1 1
      src/pages/Northbound/DuerOS/index.tsx
  7. 1 1
      src/pages/device/Instance/Detail/ChildDevice/index.tsx
  8. 2 1
      src/pages/device/Instance/Detail/Diagnose/Status/ManualInspection.tsx
  9. 9 115
      src/pages/device/Instance/Detail/Opcua/index.tsx
  10. 1 1
      src/pages/device/components/Metadata/Base/index.tsx
  11. 4 4
      src/pages/init-home/components/basis.tsx
  12. 47 2
      src/pages/link/AccessConfig/Detail/Provider/index.tsx
  13. 1 1
      src/pages/link/Channel/Modbus/index.tsx
  14. 23 7
      src/pages/link/Channel/Opcua/index.tsx
  15. 9 9
      src/pages/link/Channel/Opcua/savePoint.tsx
  16. 23 30
      src/pages/link/Channel/Opcua/service.ts
  17. 1 2
      src/pages/link/DashBoard/service.ts
  18. 1 1
      src/pages/link/Protocol/FileUpload/index.tsx
  19. 1 1
      src/pages/media/Cascade/index.tsx
  20. 1 1
      src/pages/media/Device/Channel/index.tsx
  21. 20 1
      src/pages/media/Device/index.tsx
  22. 6 0
      src/pages/media/Device/service.ts
  23. 1 1
      src/pages/rule-engine/Instance/index.tsx
  24. 1 1
      src/pages/rule-engine/Scene/index.tsx
  25. 7 4
      src/pages/system/Basis/index.tsx
  26. 2 1
      src/pages/system/Menu/index.tsx
  27. 1 1
      src/pages/system/Platforms/index.tsx
  28. 1 1
      src/pages/system/Relationship/index.tsx
  29. 8 2
      src/pages/user/Login/index.less
  30. 3 8
      src/pages/user/Login/index.tsx

+ 3 - 1
src/components/DashBoard/echarts.tsx

@@ -60,7 +60,7 @@ export default (props: EchartsProps) => {
 
   const initEcharts = (dom: HTMLDivElement) => {
     chartsRef.current = chartsRef.current || echarts.init(dom);
-
+    // chartsRef.current.clear()
     if (props.options) {
       chartsRef.current.setOption(props.options);
     } else {
@@ -80,6 +80,7 @@ export default (props: EchartsProps) => {
     return () => {
       (window as Window).removeEventListener('resize', updateSize);
       if (chartsRef.current) {
+        // chartsRef.current.clear();
         chartsRef.current.dispose();
         chartsRef.current = null;
       }
@@ -88,6 +89,7 @@ export default (props: EchartsProps) => {
 
   useEffect(() => {
     if (chartsRef.current && props.options) {
+      // chartsRef.current.clear()
       chartsRef.current.setOption(props.options);
     }
   }, [props.options, chartsRef.current]);

+ 1 - 1
src/components/FUpload/index.tsx

@@ -23,7 +23,7 @@ const FUpload = connect((props: Props) => {
       const api = await service.querySystemApi(['paths']);
       const f = {
         ...result,
-        url: `${api?.result[0]?.properties?.basePath}/file/${result?.id}?accessKey=${result?.others?.accessKey}`,
+        url: `${api?.result[0]?.properties['base-path']}/file/${result?.id}?accessKey=${result?.others?.accessKey}`,
       };
       setUrl(f.url);
       props.onChange(f);

+ 1 - 1
src/pages/Log/Access/index.tsx

@@ -102,7 +102,7 @@ const Access = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       fixed: 'right',
       render: (text, record) => [
         <a

+ 2 - 2
src/pages/Log/System/index.tsx

@@ -101,8 +101,8 @@ const System = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
-      width: 200,
+      align: 'left',
+      width: 100,
       fixed: 'right',
       render: (text, record) => [
         <a

+ 1 - 1
src/pages/Northbound/AliCloud/index.tsx

@@ -187,7 +187,7 @@ const AliCloud = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => Tools(record, 'table'),

+ 1 - 1
src/pages/Northbound/DuerOS/index.tsx

@@ -230,7 +230,7 @@ export default () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => Tools(record, 'table'),

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

@@ -102,7 +102,7 @@ const ChildDevice = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => [

+ 2 - 1
src/pages/device/Instance/Detail/Diagnose/Status/ManualInspection.tsx

@@ -15,6 +15,7 @@ interface Props {
 const ManualInspection = (props: Props) => {
   const { data } = props;
   const { permission } = PermissionButton.usePermission('device/Product');
+  const { update } = PermissionButton.usePermission('device/Instance').permission;
 
   const history = useHistory<Record<string, string>>();
 
@@ -214,7 +215,7 @@ const ManualInspection = (props: Props) => {
       width={900}
       footer={[
         <PermissionButton
-          isPermission={permission.update}
+          isPermission={data.type === 'product' ? permission.update : update}
           // type={'link'}
           key="back"
           style={{ marginRight: 10 }}

+ 9 - 115
src/pages/device/Instance/Detail/Opcua/index.tsx

@@ -1,5 +1,5 @@
 import { FormItem, ArrayTable, Editable, Select, NumberPicker } from '@formily/antd';
-import { createForm, Field, onFieldReact, FormPath, onFieldChange } from '@formily/core';
+import { createForm, Field, onFieldReact, FormPath } from '@formily/core';
 import { FormProvider, createSchemaField } from '@formily/react';
 import { Badge, Card, Empty, Input, Tooltip } from 'antd';
 import { action } from '@formily/reactive';
@@ -7,7 +7,7 @@ import type { Response } from '@/utils/typings';
 import './index.less';
 import { useDomFullHeight } from '@/hooks';
 import PermissionButton from '@/components/PermissionButton';
-import { service } from '@/pages/link/Channel/Modbus';
+import { service } from '@/pages/link/Channel/Opcua';
 import { useEffect, useState } from 'react';
 import { DisconnectOutlined, QuestionCircleOutlined } from '@ant-design/icons';
 import { onlyMessage } from '@/utils/util';
@@ -19,23 +19,14 @@ interface Props {
 export default (props: Props) => {
   const { data } = props;
   const { minHeight } = useDomFullHeight('.modbus');
-  const { permission } = PermissionButton.usePermission('link/Channel/Modbus');
+  const { permission } = PermissionButton.usePermission('link/Channel/Opcua');
   const [properties, setProperties] = useState<any>([]);
   const [filterList, setFilterList] = useState<any>([]);
   const [masterList, setMasterList] = useState<any>([]);
-  const [typeList, setTypeList] = useState<any>([]);
   const [reload, setReload] = useState<string>('');
   const [empty, setEmpty] = useState<boolean>(false);
 
   //数据类型长度
-  const lengthMap = new Map();
-  lengthMap.set('int8', 1);
-  lengthMap.set('int16', 2);
-  lengthMap.set('int32', 4);
-  lengthMap.set('int64', 8);
-  lengthMap.set('ieee754_float', 4);
-  lengthMap.set('ieee754_double', 8);
-  lengthMap.set('hex', 1);
 
   const Render = (propsText: any) => {
     const text = properties.find((item: any) => item.metadataId === propsText.value);
@@ -84,7 +75,7 @@ export default (props: Props) => {
 
   //异步数据源
   const getMaster = () =>
-    service.queryMaster({
+    service.noPagingOpcua({
       paging: false,
       sorts: [
         {
@@ -112,70 +103,19 @@ export default (props: Props) => {
       ],
       terms: [
         {
-          column: 'masterId',
+          column: 'opcUaId',
           value: collectorId,
         },
       ],
     });
   };
 
-  const getQuantity = async (field: any) => {
-    const path = FormPath.transform(
-      field.path,
-      /\d+/,
-      (index) => `array.${parseInt(index)}.collectorId`,
-    );
-    const path1 = FormPath.transform(
-      field.path,
-      /\d+/,
-      (index) => `array.${parseInt(index)}.pointId`,
-    );
-    const collectorId = field.query(path).get('value');
-    const pointId = field.query(path1).get('value');
-    if (collectorId && pointId) {
-      return service.getPoint({
-        paging: false,
-        sorts: [
-          {
-            name: 'createTime',
-            order: 'desc',
-          },
-        ],
-        terms: [
-          {
-            column: 'masterId',
-            value: collectorId,
-          },
-          {
-            column: 'id',
-            value: pointId,
-          },
-        ],
-      });
-    } else {
-      return [];
-    }
-  };
-  const useAsync = (api: any) => (field: Field) => {
-    field.loading = true;
-    api(field).then(
-      action.bound!((resp: Response<any>) => {
-        const value = resp.result?.[0].parameter.quantity || '';
-        field.dataSource = [...new Array(value * 2).keys()].map((item: any) => ({
-          label: item,
-          value: item,
-        }));
-        field.loading = false;
-      }),
-    );
-  };
-
   const useAsyncDataSource = (api: any) => (field: Field) => {
     field.loading = true;
     api(field).then(
       action.bound!((resp: Response<any>) => {
         field.dataSource = resp.result?.map((item: any) => ({
-          label: `${item.name}(${item.unitId}/${item.address}/${item.function.text})`,
+          label: `${item.name}(${item.opcPointId}/${item.dataMode?.text})`,
           value: item.id,
         }));
         field.loading = false;
@@ -193,7 +133,7 @@ export default (props: Props) => {
 
   useEffect(() => {
     service
-      .queryMaster({
+      .noPagingOpcua({
         paging: false,
         sorts: [
           {
@@ -211,18 +151,8 @@ export default (props: Props) => {
           setMasterList(list);
         }
       });
-    service.dataType().then((res) => {
-      if (res.status === 200) {
-        const items = res.result.map((item: any) => ({
-          label: item.name,
-          value: item.id,
-        }));
-        setTypeList(items);
-      }
-    });
   }, []);
   useEffect(() => {
-    console.log(typeList);
     const metadata = JSON.parse(data.metadata).properties?.map((item: any) => ({
       metadataId: item.id,
       metadataName: `${item.name}(${item.id})`,
@@ -282,11 +212,6 @@ export default (props: Props) => {
           /\d+/,
           (index) => `array.${parseInt(index)}.pointId`,
         );
-        const path1 = FormPath.transform(
-          field.path,
-          /\d+/,
-          (index) => `array.${parseInt(index)}.codec`,
-        );
         f.setFieldState(path, (state) => {
           if (value) {
             state.required = true;
@@ -296,34 +221,6 @@ export default (props: Props) => {
             form.validate();
           }
         });
-        f.setFieldState(path1, (state) => {
-          if (value) {
-            state.required = true;
-            form.validate();
-          } else {
-            state.required = false;
-            form.validate();
-          }
-        });
-      });
-      onFieldChange('array.*.codec', (field: any) => {
-        const value = (field as Field).value;
-        const path = FormPath.transform(
-          field.path,
-          /\d+/,
-          (index) => `array.${parseInt(index)}.codecConfiguration.readIndex`,
-        );
-        if ((field as Field).modified) {
-          const readIndex = field.query(path).get('value');
-          const dataLength = field.query(path).get('dataSource')?.length - 1;
-          const length = lengthMap.get(value) + readIndex;
-          console.log(length, dataLength);
-          if (length > dataLength) {
-            field.selfErrors = '数据类型对应的长度和起始位置加起来不能超过数据长度';
-          } else {
-            field.selfErrors = '';
-          }
-        }
       });
     },
   });
@@ -384,7 +281,7 @@ export default (props: Props) => {
                 title: (
                   <>
                     点位名称
-                    <Tooltip title="名称(从站ID/地址/功能码)">
+                    <Tooltip title="名称(点位ID/数据模式)">
                       <QuestionCircleOutlined />
                     </Tooltip>
                   </>
@@ -487,10 +384,7 @@ export default (props: Props) => {
           </div>
           <div className="edit-table">
             <FormProvider form={form}>
-              <SchemaField
-                schema={schema}
-                scope={{ useAsyncDataSource, getName, getMaster, getQuantity, useAsync }}
-              />
+              <SchemaField schema={schema} scope={{ useAsyncDataSource, getName, getMaster }} />
             </FormProvider>
           </div>
         </>

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

@@ -74,7 +74,7 @@ const BaseMetadata = observer((props: Props) => {
     {
       title: '操作',
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       render: (_: unknown, record: MetadataItem) => [
         <PermissionButton

+ 4 - 4
src/pages/init-home/components/basis.tsx

@@ -24,7 +24,7 @@ const Basis = forwardRef((props: Props, ref) => {
             properties: {
               ...formData,
               apikey: '',
-              basePath: '',
+              'base-path': '',
             },
           },
           {
@@ -36,7 +36,7 @@ const Basis = forwardRef((props: Props, ref) => {
           {
             scope: 'paths',
             properties: {
-              basePath: formData.basePath,
+              'base-path': formData['base-path'],
             },
           },
         ];
@@ -83,7 +83,7 @@ const Basis = forwardRef((props: Props, ref) => {
         ico: require('/public/favicon.ico'),
         backgroud: require('/public/images/login.png'),
         apikey: '',
-        basePath: `${window.location.origin}/api`,
+        'base-path': `${window.location.origin}/api`,
       }}
     >
       <Row gutter={[24, 24]}>
@@ -115,7 +115,7 @@ const Basis = forwardRef((props: Props, ref) => {
           </Form.Item>
           <Form.Item
             label="base-path"
-            name="basePath"
+            name="base-path"
             tooltip="系统后台访问的url"
             required
             rules={[{ required: true, message: 'base-path必填' }]}

+ 47 - 2
src/pages/link/AccessConfig/Detail/Provider/index.tsx

@@ -12,6 +12,7 @@ const Provider = (props: Props) => {
   const [dataSource, setDataSource] = useState<any[]>([]);
 
   useEffect(() => {
+    console.log(props.data);
     const media: any[] = [];
     const network: any[] = [];
     const cloud: any[] = [];
@@ -70,7 +71,7 @@ const Provider = (props: Props) => {
 
   return (
     <div>
-      {dataSource.map((i) => (
+      {/* {dataSource.map((i) => (
         <Card key={i.type} style={{ marginTop: 20 }}>
           <TitleComponent data={i.title} />
           <Row gutter={[24, 24]}>
@@ -107,7 +108,51 @@ const Provider = (props: Props) => {
             ))}
           </Row>
         </Card>
-      ))}
+      ))} */}
+      {dataSource.map((i) => {
+        if (i.list && i.list.length !== 0) {
+          return (
+            <Card key={i.type} style={{ marginTop: 20 }}>
+              <TitleComponent data={i.title} />
+              <Row gutter={[24, 24]}>
+                {(i?.list || []).map((item: any) => (
+                  <Col key={item.name} span={12}>
+                    <div className={styles.provider}>
+                      <div className={styles.box}>
+                        <div className={styles.left}>
+                          <div className={styles.images}>
+                            <img src={backMap.get(item.id)} />
+                          </div>
+                          <div className={styles.context}>
+                            <div style={{ fontWeight: 600 }}>{item.name}</div>
+                            <div className={styles.desc}>
+                              <Tooltip title={item?.description || ''}>
+                                {item?.description || ''}
+                              </Tooltip>
+                            </div>
+                          </div>
+                        </div>
+                        <div style={{ width: '70px' }}>
+                          <Button
+                            type="primary"
+                            onClick={() => {
+                              props.change(item, i.type);
+                            }}
+                          >
+                            接入
+                          </Button>
+                        </div>
+                      </div>
+                    </div>
+                  </Col>
+                ))}
+              </Row>
+            </Card>
+          );
+        } else {
+          return <></>;
+        }
+      })}
     </div>
   );
 };

+ 1 - 1
src/pages/link/Channel/Modbus/index.tsx

@@ -201,7 +201,7 @@ const NewModbus = () => {
     {
       title: '操作',
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 120,
       fixed: 'right',
       render: (text, record) => [

+ 23 - 7
src/pages/link/Channel/Opcua/index.tsx

@@ -21,10 +21,11 @@ import { PageContainer } from '@ant-design/pro-layout';
 import Service from './service';
 import SaveChannel from './saveChannel';
 import SavePoint from './savePoint';
-// import Import from './import';
 import { onlyMessage } from '@/utils/util';
 import Export from './Export';
 import Import from './import';
+import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
+import { map } from 'rxjs/operators';
 
 export const service = new Service('opc/client');
 
@@ -39,13 +40,15 @@ const NewOpc = () => {
   const [visiblePoint, setVisiblePoint] = useState<boolean>(false);
   const [current, setCurrent] = useState<any>({});
   const [pointDetail, setPointDetail] = useState<any>({});
-  // const [importVisible, setImportVisible] = useState<boolean>(false);
   const [opcList, setOpcList] = useState<any>([]);
   const [filterList, setFilterList] = useState([]);
   const opcId = useRef<string>('');
   const [pointList, setPointList] = useState<any>([]);
   const [exportVisible, setExportVisible] = useState<boolean>(false);
   const [importVisible, setImportVisible] = useState<boolean>(false);
+  const [subscribeTopic] = useSendWebsocketMessage();
+  const wsRef = useRef<any>();
+  const [currentData, setCurrentData] = useState<any>({});
 
   const collectMap = new Map();
   collectMap.set('good', 'success');
@@ -101,7 +104,7 @@ const NewOpc = () => {
     {
       title: '当前数据',
       search: false,
-      render: (record: any) => <>{record.parameter?.quantity}</>,
+      render: (record: any) => <>{currentData[record?.id] || ''}</>,
     },
     {
       title: '采集状态',
@@ -157,7 +160,7 @@ const NewOpc = () => {
     {
       title: '操作',
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 120,
       fixed: 'right',
       render: (text, record) => [
@@ -299,6 +302,22 @@ const NewOpc = () => {
     });
   };
 
+  useEffect(() => {
+    if (pointList && activeKey) {
+      const id = `collector-data-opcua`;
+      const topic = `/collector/OPC_UA/${activeKey}/data`;
+      wsRef.current = subscribeTopic?.(id, topic, {
+        pointId: pointList.map((item: any) => item.id),
+      })
+        ?.pipe(map((res: any) => res.payload))
+        .subscribe((payload: any) => {
+          const { pointId, parseData } = payload;
+          current[pointId] = parseData;
+          setCurrentData({ ...current });
+        });
+    }
+    return () => wsRef.current && wsRef.current?.unsubscribe();
+  }, [pointList]);
   const masterMemo = useMemo(
     () => (
       <Export
@@ -319,9 +338,6 @@ const NewOpc = () => {
   useEffect(() => {
     getOpc();
   }, []);
-  useEffect(() => {
-    console.log(pointList);
-  }, []);
 
   return (
     <PageContainer>

+ 9 - 9
src/pages/link/Channel/Opcua/savePoint.tsx

@@ -87,15 +87,15 @@ const SavePoint = (props: Props) => {
               required
               rules={[
                 { required: true, message: '点位ID必填' },
-                ({}) => ({
-                  validator(_, value) {
-                    const item = value.substring(0, 2);
-                    if (item === 'i=' || item === 's=' || item === 'g=' || item === 'b=') {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('前两个字符必须为i=、s=、g=、b=中的一个'));
-                  },
-                }),
+                // ({}) => ({
+                //   validator(_, value) {
+                //     const item = value.substring(0, 2);
+                //     if (item === 'i=' || item === 's=' || item === 'g=' || item === 'b=') {
+                //       return Promise.resolve();
+                //     }
+                //     return Promise.reject(new Error('前两个字符必须为i=、s=、g=、b=中的一个'));
+                //   },
+                // }),
               ]}
             >
               <Input placeholder="请输入点位ID" />

+ 23 - 30
src/pages/link/Channel/Opcua/service.ts

@@ -31,31 +31,7 @@ class Service extends BaseService<OpaUa> {
       method: 'GET',
       params,
     });
-  getDevice = (params?: any) =>
-    request(`/${SystemConst.API_BASE}/device-instance/_query`, {
-      method: 'POST',
-      data: params,
-    });
-  //绑定设备
-  bind = (params: any) =>
-    request(`/${SystemConst.API_BASE}/opc/device-bind/batch/_create`, {
-      method: 'POST',
-      data: params,
-    });
-  getBindList = (params: any) =>
-    request(`/${SystemConst.API_BASE}/opc/device-bind/device-details/_query/no-paging`, {
-      method: 'GET',
-      params,
-    });
-  unbind = (params: any, opcUaId: string) =>
-    request(`${SystemConst.API_BASE}/opc/device-bind/batch/${opcUaId}/_delete`, {
-      method: 'POST',
-      data: params,
-    });
-  deviceDetail = (id: any) =>
-    request(`${SystemConst.API_BASE}/device-instance/${id}/detail`, {
-      method: 'GET',
-    });
+
   addPoint = (params: any) =>
     request(`${SystemConst.API_BASE}/opc/point`, {
       method: 'POST',
@@ -66,6 +42,11 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data: params,
     });
+  getPoint = (params: any) =>
+    request(`${SystemConst.API_BASE}/opc/point/_query/no-paging`, {
+      method: 'POST',
+      data: params,
+    });
   editPoint = (id: string, params: any) =>
     request(`/${SystemConst.API_BASE}/opc/point/${id}`, {
       method: 'PUT',
@@ -80,11 +61,6 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data,
     });
-  stopPoint = (bindDeviceId: string, data: any) =>
-    request(`/${SystemConst.API_BASE}/opc/device-bind/points/${bindDeviceId}/_stop`, {
-      method: 'POST',
-      data,
-    });
   noPagingOpcua = (data: any) =>
     request(`/${SystemConst.API_BASE}/opc/client/_query/no-paging`, {
       method: 'POST',
@@ -95,6 +71,23 @@ class Service extends BaseService<OpaUa> {
       method: 'POST',
       data,
     });
+  removeDevicePoint = (deviceId: string, data: any) =>
+    request(`/${SystemConst.API_BASE}/things/collector/device/${deviceId}/_delete`, {
+      method: 'POST',
+      data,
+    });
+  //查询设备点位映射配置
+  getDevicePoint = (deviceId: string, param?: string) =>
+    request(`/${SystemConst.API_BASE}/things/collector/device/${deviceId}/_query`, {
+      method: 'GET',
+      param,
+    });
+  //保存设备绑定点位映射配置
+  saveDevicePoint = (deviceId: string, data: any) =>
+    request(`/${SystemConst.API_BASE}/things/collector/device/${deviceId}/OPC_UA`, {
+      method: 'PATCH',
+      data,
+    });
 }
 
 export default Service;

+ 1 - 2
src/pages/link/DashBoard/service.ts

@@ -3,8 +3,7 @@ import SystemConst from '@/utils/const';
 import { request } from 'umi';
 
 class Service extends BaseService<any> {
-  serverNode = () =>
-    request(`/${SystemConst.API_BASE}/network/resources/clusters`, { method: 'GET' });
+  serverNode = () => request(`/${SystemConst.API_BASE}/dashboard/cluster/nodes`, { method: 'GET' });
 
   /**
    * echarts数据

+ 1 - 1
src/pages/link/Protocol/FileUpload/index.tsx

@@ -23,7 +23,7 @@ const FileUpload = connect((props: Props) => {
       onlyMessage('上传成功!');
       const result = info.file.response?.result;
       const api = await service.querySystemApi(['paths']);
-      const f = `${api?.result[0]?.properties?.basePath}/file/${result?.id}?accessKey=${result?.others?.accessKey}`;
+      const f = `${api?.result[0]?.properties['base-path']}/file/${result?.id}?accessKey=${result?.others?.accessKey}`;
       setUrl(f);
       setLoading(false);
       props.onChange(f);

+ 1 - 1
src/pages/media/Cascade/index.tsx

@@ -207,7 +207,7 @@ const Cascade = () => {
       ellipsis: true,
       fixed: 'right',
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       render: (text, record) => [
         <PermissionButton
           isPermission={permission.update}

+ 1 - 1
src/pages/media/Device/Channel/index.tsx

@@ -138,7 +138,7 @@ export default () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       render: (_, record) => [
         <Tooltip

+ 20 - 1
src/pages/media/Device/index.tsx

@@ -126,6 +126,25 @@ const Device = () => {
         defaultMessage: '设备厂家',
       }),
     },
+    {
+      title: intl.formatMessage({
+        id: 'pages.table.productName',
+        defaultMessage: '产品名称',
+      }),
+      dataIndex: 'productId',
+      ellipsis: true,
+      valueType: 'select',
+      hideInTable: false,
+      request: async () => {
+        const res = await service.getProductList();
+        if (res.status === 200) {
+          return res.result.map((pItem: any) => ({ label: pItem.name, value: pItem.id }));
+        }
+        return [];
+      },
+      // render: (_, row) => row.productName,
+      filterMultiple: true,
+    },
     // {
     //   dataIndex: 'model',
     //   title: intl.formatMessage({
@@ -189,7 +208,7 @@ const Device = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => [

+ 6 - 0
src/pages/media/Device/service.ts

@@ -30,6 +30,12 @@ class Service extends BaseService<DeviceItem> {
     request(`/${SystemConst.API_BASE}/gateway/device/detail/_query`, { method: 'POST', data });
   //视频设备详情
   getDetail = (id: string) => request(`${this.uri}/${id}`, { method: 'GET' });
+  // 查询产品列表
+  getProductList = (params?: any) =>
+    request(`/${SystemConst.API_BASE}/device/product/_query/no-paging?paging=false`, {
+      method: 'GET',
+      params,
+    });
 }
 
 export default Service;

+ 1 - 1
src/pages/rule-engine/Instance/index.tsx

@@ -159,7 +159,7 @@ const Instance = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => [

+ 1 - 1
src/pages/rule-engine/Scene/index.tsx

@@ -295,7 +295,7 @@ const Scene = () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => Tools(record, 'table'),

+ 7 - 4
src/pages/system/Basis/index.tsx

@@ -27,7 +27,7 @@ const Basis = () => {
       form.setFieldsValue({
         ...basis[0].properties,
         apikey: api[0].properties.api,
-        basePath: basePath[0].properties.basePath,
+        'base-path': basePath[0].properties['base-path'],
       });
       setInitialState({
         ...initialState,
@@ -46,7 +46,7 @@ const Basis = () => {
           properties: {
             ...formData,
             apikey: '',
-            basePath: '',
+            'base-path': '',
           },
         },
         {
@@ -58,8 +58,11 @@ const Basis = () => {
         {
           scope: 'paths',
           properties: {
-            basePath: formData.basePath,
+            'base-path': formData['base-path'],
           },
+          // properties: {
+          //   basePath: formData.basePath,
+          // },
         },
       ];
       const res = await service.save(item);
@@ -109,7 +112,7 @@ const Basis = () => {
               </Form.Item>
               <Form.Item
                 label="base-path"
-                name="basePath"
+                name="base-path"
                 tooltip="访问后台服务器的url"
                 required
                 rules={[{ required: true, message: 'base-path必填' }]}

+ 2 - 1
src/pages/system/Menu/index.tsx

@@ -140,7 +140,8 @@ export default observer(() => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      width: 240,
+      width: 140,
+      align: 'left',
       fixed: 'right',
       render: (_, record) => [
         <Button

+ 1 - 1
src/pages/system/Platforms/index.tsx

@@ -113,7 +113,7 @@ export default () => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 250,
       fixed: 'right',
       render: (_, record: any) => [

+ 1 - 1
src/pages/system/Relationship/index.tsx

@@ -57,7 +57,7 @@ const Relationship = () => {
     {
       title: '操作',
       valueType: 'option',
-      align: 'center',
+      align: 'left',
       width: 200,
       fixed: 'right',
       render: (text, record) => [

+ 8 - 2
src/pages/user/Login/index.less

@@ -65,13 +65,17 @@
         .desc {
           margin-top: 12px;
           margin-bottom: 40px;
-          color: @text-color-secondary;
-          font-size: @font-size-base;
+          // color: @heading-color;
+          color: rgb(0 0 0 / 70%);
+          font-weight: 600;
+          font-size: 22px;
+          font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif;
         }
 
         .main {
           width: 70%;
           margin: 60px auto 0;
+
           @media screen and (max-width: @screen-sm) {
             width: 95%;
             max-width: 328px;
@@ -82,10 +86,12 @@
               margin: auto;
               font-size: 16px;
             }
+
             .ant-formily-item-size-large .ant-formily-item-help {
               text-align: left;
             }
           }
+
           .icon {
             margin-left: 16px;
             color: rgba(0, 0, 0, 0.2);

+ 3 - 8
src/pages/user/Login/index.tsx

@@ -95,6 +95,7 @@ const Login: React.FC = () => {
         const ico: any = document.querySelector('link[rel="icon"]');
         ico.href = res.result.ico;
         setBasis(res.result);
+        console.log(res.result);
         if (res.result.title) {
           document.title = res.result.title;
         } else {
@@ -232,16 +233,10 @@ const Login: React.FC = () => {
             <div className={styles.top}>
               <div className={styles.header}>
                 <Link to="/">
-                  <img alt="logo" className={styles.logo} src="/logo.svg" />
-                  {/*<span className={styles.title}>{SystemConst.SYSTEM_NAME}</span>*/}
+                  <img alt="logo" className={styles.logo} src={basis.logo || '/logo.svg'} />
                 </Link>
               </div>
-              <div className={styles.desc}>
-                {intl.formatMessage({
-                  id: 'pages.layouts.userLayout.title',
-                  defaultMessage: 'Jetlinks',
-                })}
-              </div>
+              <div className={styles.desc}>{basis.title || SystemConst.SYSTEM_NAME}</div>
               <div className={styles.main}>
                 <Form form={loginForm} layout="horizontal" size="large" onAutoSubmit={doLogin}>
                   <SchemaField schema={schema} />