瀏覽代碼

feat: merge

xieyonghong 3 年之前
父節點
當前提交
5d0466fb27
共有 37 個文件被更改,包括 310 次插入69 次删除
  1. 二進制
      public/images/home/content1.png
  2. 二進制
      public/images/home/home-blackground.png
  3. 1 1
      src/app.tsx
  4. 1 2
      src/components/DashBoard/echarts.tsx
  5. 5 1
      src/components/ProTableCard/CardItems/duerOs.tsx
  6. 1 1
      src/global.less
  7. 3 3
      src/pages/Northbound/DuerOS/Detail/Doc.tsx
  8. 69 2
      src/pages/device/DashBoard/index.tsx
  9. 1 1
      src/pages/device/Instance/Detail/Config/index.tsx
  10. 2 0
      src/pages/device/Instance/Detail/Functions/form.tsx
  11. 22 3
      src/pages/device/Instance/Detail/Functions/index.tsx
  12. 5 3
      src/pages/device/Instance/Detail/Info/index.tsx
  13. 3 1
      src/pages/device/Instance/Detail/Running/Property/PropertyCard.tsx
  14. 2 1
      src/pages/device/Instance/Detail/Running/Property/index.tsx
  15. 2 2
      src/pages/device/Instance/Detail/Tags/index.tsx
  16. 5 3
      src/pages/device/Instance/Detail/index.tsx
  17. 3 1
      src/pages/device/Instance/Export/index.tsx
  18. 1 1
      src/pages/device/Product/Detail/index.tsx
  19. 3 3
      src/pages/device/Product/Save/index.tsx
  20. 1 0
      src/pages/device/Product/index.tsx
  21. 3 2
      src/pages/device/components/Metadata/Import/index.tsx
  22. 1 1
      src/pages/home/components/GuideHome.tsx
  23. 1 1
      src/pages/home/components/index.less
  24. 5 1
      src/pages/home/comprehensive/index.tsx
  25. 3 3
      src/pages/home/device/index.tsx
  26. 2 2
      src/pages/link/Channel/Modbus/Access/bindDevice/index.tsx
  27. 2 2
      src/pages/link/Channel/Opcua/Access/bindDevice/index.tsx
  28. 107 10
      src/pages/link/Type/Detail/index.tsx
  29. 5 0
      src/pages/link/service.ts
  30. 3 3
      src/pages/media/Home/index.tsx
  31. 5 5
      src/pages/notice/Config/SyncUser/index.tsx
  32. 3 3
      src/pages/notice/Config/index.tsx
  33. 8 0
      src/pages/rule-engine/Alarm/Configuration/index.tsx
  34. 18 4
      src/pages/rule-engine/Alarm/Log/Detail/Info.tsx
  35. 12 2
      src/pages/rule-engine/Alarm/Log/TabComponent/index.tsx
  36. 1 1
      src/pages/user/Login/index.less
  37. 1 0
      src/utils/menu/router.ts

二進制
public/images/home/content1.png


二進制
public/images/home/home-blackground.png


+ 1 - 1
src/app.tsx

@@ -171,7 +171,7 @@ export const request: RequestConfig = {
       history.push('/user/login');
       return;
     }
-    if (response.status === 400 || response.status === 500) {
+    if (response.status === 400 || response.status === 500 || response.status === 404) {
       // 添加clone() 避免后续其它地方用response.text()时报错
       response
         .clone()

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

@@ -77,8 +77,7 @@ export default (props: EchartsProps) => {
   };
 
   useEffect(() => {
-    (window as Window).addEventListener('resize', updateSize);
-
+    setTimeout(() => (window as Window).addEventListener('resize', updateSize), 100);
     return () => {
       (window as Window).removeEventListener('resize', updateSize);
     };

+ 5 - 1
src/components/ProTableCard/CardItems/duerOs.tsx

@@ -34,7 +34,11 @@ export default (props: DuerOSProps) => {
         </div>
         <div className={'card-item-body'}>
           <div className={'card-item-header'}>
-            <span className={'card-item-header-name ellipsis'}>{props?.name}</span>
+            <span className={'card-item-header-name ellipsis'}>
+              <Tooltip title={props?.name} placement="topLeft">
+                {props?.name}
+              </Tooltip>
+            </span>
           </div>
           <div className={'card-item-content'}>
             <div>

+ 1 - 1
src/global.less

@@ -117,7 +117,7 @@ ol {
 }
 
 .ellipsis {
-  max-width: 100%;
+  width: 100%;
   overflow: hidden;
   white-space: nowrap;
   text-align: left;

+ 3 - 3
src/pages/Northbound/DuerOS/Detail/Doc.tsx

@@ -31,7 +31,7 @@ const Doc = () => {
         </div>
         <h1>授权地址</h1>
         <div>物联网平台的登录地址。注意需要为https。</div>
-        <div>请复制并填写: https://pro.baidu.cn/#/user/login</div>
+        <div>请复制并填写: https://{location.host}/#/user/login</div>
         <div className={'image'}>
           <Image width="100%" src={image1} />
         </div>
@@ -53,8 +53,8 @@ const Doc = () => {
           <Image width="100%" src={image3} />
         </div>
         <h1>Token地址</h1>
-        <div>请复制并填写:HTTPS://【IP:端口】/api/v1/token</div>
-        <h2>ClientSecret</h2>
+        <div>请复制并填写:HTTPS://{location.host}/api/v1/token</div>
+        <h1>ClientSecret</h1>
         <div>请复制物联网平台-第三方平台中的secureKey,填写到DuerOS平台。</div>
         <div></div>
         <h1>WebService</h1>

+ 69 - 2
src/pages/device/DashBoard/index.tsx

@@ -243,8 +243,7 @@ const DeviceBoard = () => {
 
   const getEcharts = async () => {
     const data = ref.current!.getValues();
-    if (data) {
-      // console.log(Math.ceil((data.time.end - data.time.start) / (1 * 24 * 3600 * 1000) + 1));
+    if (data && data.time.type !== 'today') {
       const res = await service.dashboard([
         {
           dashboard: 'device',
@@ -317,6 +316,74 @@ const DeviceBoard = () => {
           ],
         });
       }
+    } else {
+      const res = await service.dashboard([
+        {
+          dashboard: 'device',
+          object: 'message',
+          measurement: 'quantity',
+          dimension: 'agg',
+          group: 'device_msg',
+          params: {
+            time: '1h',
+            format: 'yyyy.MM.dd HH:MM:SS',
+            limit: 24,
+            from: data.time.start,
+            to: data.time.end,
+          },
+        },
+      ]);
+      if (res.status === 200) {
+        const x = res.result.map((item: any) => item.data.timeString).reverse();
+        const y = res.result.map((item: any) => item.data.value).reverse();
+        setOptions({
+          xAxis: {
+            type: 'category',
+            data: x,
+          },
+          yAxis: {
+            type: 'value',
+          },
+          tooltip: {
+            trigger: 'axis',
+          },
+          grid: {
+            top: '2%',
+            bottom: '5%',
+            left: '2%',
+            right: '2%',
+          },
+          series: [
+            {
+              name: '消息量',
+              data: y,
+              type: 'line',
+              smooth: true,
+              color: '#685DEB',
+              areaStyle: {
+                color: {
+                  type: 'linear',
+                  x: 0,
+                  y: 0,
+                  x2: 0,
+                  y2: 1,
+                  colorStops: [
+                    {
+                      offset: 0,
+                      color: '#685DEB', // 100% 处的颜色
+                    },
+                    {
+                      offset: 1,
+                      color: '#FFFFFF', //   0% 处的颜色
+                    },
+                  ],
+                  global: false, // 缺省为 false
+                },
+              },
+            },
+          ],
+        });
+      }
     }
   };
   //地图数据

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

@@ -74,7 +74,7 @@ const Config = () => {
         return (
           <div>
             <Tooltip title={config[item.property] || '--'} placement="topLeft">
-              <div className="ellipsis" style={{ width: 300 }}>
+              <div className="ellipsis" style={{ maxWidth: 300 }}>
                 {config[item.property] || '--'}
               </div>
             </Tooltip>

+ 2 - 0
src/pages/device/Instance/Detail/Functions/form.tsx

@@ -11,6 +11,7 @@ import moment from 'moment';
 import './index.less';
 import { GeoPoint, MetadataJsonInput } from '@/components';
 import { QuestionCircleOutlined } from '@ant-design/icons';
+import { onlyMessage } from '@/utils/util';
 
 type FunctionProps = {
   data: FunctionMetadata;
@@ -219,6 +220,7 @@ export default (props: FunctionProps) => {
       const res = await service.invokeFunction(id, props.data.id, data);
       if (res.status === 200) {
         setResult(res.result);
+        onlyMessage('操作成功');
       }
     }
   };

+ 22 - 3
src/pages/device/Instance/Detail/Functions/index.tsx

@@ -1,4 +1,4 @@
-import { Card, Tabs } from 'antd';
+import { Card, Tabs, Tooltip } from 'antd';
 import { InstanceModel } from '@/pages/device/Instance';
 import type { FunctionMetadata } from '@/pages/device/Product/typings';
 import FnForm from './form';
@@ -27,7 +27,17 @@ const Functions = () => {
                 {functionList &&
                   functionList.map((fn) => {
                     return (
-                      <Tabs.TabPane tab={fn.name} key={fn.id}>
+                      <Tabs.TabPane
+                        tab={
+                          <Tooltip placement="topLeft" title={fn.name}>
+                            <div className="ellipsis" style={{ width: 100 }}>
+                              {fn.name}
+                            </div>
+                          </Tooltip>
+                        }
+                        // tab={fn.name}
+                        key={fn.id}
+                      >
                         <FnForm data={fn} />
                       </Tabs.TabPane>
                     );
@@ -40,7 +50,16 @@ const Functions = () => {
               {functionList &&
                 functionList.map((fn) => {
                   return (
-                    <Tabs.TabPane tab={fn.name} key={fn.id}>
+                    <Tabs.TabPane
+                      tab={
+                        <Tooltip placement="topLeft" title={fn.name}>
+                          <div className="ellipsis" style={{ width: 100 }}>
+                            {fn.name}
+                          </div>
+                        </Tooltip>
+                      }
+                      key={fn.id}
+                    >
                       <AModel data={fn} />
                     </Tabs.TabPane>
                   );

+ 5 - 3
src/pages/device/Instance/Detail/Info/index.tsx

@@ -52,7 +52,7 @@ const Info = observer(() => {
             })}
           >
             <Tooltip placement="topLeft" title={InstanceModel.detail?.id}>
-              <div className="ellipsis" style={{ width: 300 }}>
+              <div className="ellipsis" style={{ maxWidth: 250 }}>
                 {InstanceModel.detail?.id}
               </div>
             </Tooltip>
@@ -64,7 +64,7 @@ const Info = observer(() => {
             })}
           >
             <Tooltip placement="topLeft" title={InstanceModel.detail?.productName}>
-              <div className="ellipsis" style={{ width: 300 }}>
+              <div className="ellipsis" style={{ maxWidth: 250 }}>
                 {InstanceModel.detail?.productName}
               </div>
             </Tooltip>
@@ -127,7 +127,9 @@ const Info = observer(() => {
             })}
           >
             <Tooltip placement="topLeft" title={InstanceModel.detail?.description}>
-              <div className="ellipsis">{InstanceModel.detail?.description}</div>
+              <div className="ellipsis" style={{ maxWidth: 250 }}>
+                {InstanceModel.detail?.description}
+              </div>
             </Tooltip>
           </Descriptions.Item>
         </Descriptions>

+ 3 - 1
src/pages/device/Instance/Detail/Running/Property/PropertyCard.tsx

@@ -47,7 +47,9 @@ const Property = (props: Props) => {
     return (
       <div className="card-title-box">
         <div className="card-title">
-          <Tooltip title={title}>{title}</Tooltip>
+          <Tooltip title={title} placement="topLeft">
+            {title}
+          </Tooltip>
         </div>
         <Space style={{ fontSize: 12 }}>
           {data.expands?.type?.includes('write') && (

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

@@ -285,7 +285,7 @@ const Property = (props: Props) => {
         {dataSource.data?.length > 0 ? (
           <div style={{ marginTop: '20px' }}>
             {check ? (
-              <Row gutter={[16, 16]}>
+              <Row gutter={[16, 16]} style={{ minHeight: 450 }}>
                 {dataSource.data.map((item: any) => (
                   <Col {...ColResponsiveProps} key={item.id}>
                     <PropertyCard data={item} value={item?.id ? propertyValue[item?.id] : '--'} />
@@ -298,6 +298,7 @@ const Property = (props: Props) => {
                 columns={columns}
                 dataSource={dataSource.data}
                 rowKey="id"
+                style={{ minHeight: 450 }}
               />
             )}
             <div

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

@@ -46,8 +46,8 @@ const Tags = () => {
         {(tags || [])?.map((item: any) => (
           <Descriptions.Item span={1} label={`${item.name}(${item.key})`} key={item.key}>
             <Tooltip title={item.value || '--'} placement="topLeft">
-              <div className="ellipsis" style={{ width: 300 }}>
-                {item.value || '--'}{' '}
+              <div className="ellipsis" style={{ maxWidth: 300 }}>
+                {item.value || '--'}
               </div>
             </Tooltip>
           </Descriptions.Item>

+ 5 - 3
src/pages/device/Instance/Detail/index.tsx

@@ -32,7 +32,7 @@ import { onlyMessage } from '@/utils/util';
 export const deviceStatus = new Map();
 deviceStatus.set('online', <Badge status="success" text={'在线'} />);
 deviceStatus.set('offline', <Badge status="error" text={'离线'} />);
-deviceStatus.set('notActive', <Badge status="processing" text={'未启用'} />);
+deviceStatus.set('notActive', <Badge status="processing" text={'用'} />);
 
 const InstanceDetail = observer(() => {
   const intl = useIntl();
@@ -285,7 +285,9 @@ const InstanceDetail = observer(() => {
         <Descriptions size="small" column={4}>
           <Descriptions.Item label={'ID'}>
             <Tooltip placement="topLeft" title={InstanceModel.detail?.id}>
-              <div className="ellipsis-70">{InstanceModel.detail?.id}</div>
+              <div className="ellipsis" style={{ maxWidth: 250 }}>
+                {InstanceModel.detail?.id}
+              </div>
             </Tooltip>
           </Descriptions.Item>
           <Descriptions.Item label={'所属产品'}>
@@ -316,7 +318,7 @@ const InstanceDetail = observer(() => {
       title={
         <div style={{ display: 'flex', alignItems: 'center' }}>
           <Tooltip placement="topLeft" title={InstanceModel.detail?.name}>
-            <div className="ellipsis" style={{ width: 250 }}>
+            <div className="ellipsis" style={{ maxWidth: 250 }}>
               {InstanceModel.detail?.name}
             </div>
           </Tooltip>

+ 3 - 1
src/pages/device/Instance/Export/index.tsx

@@ -9,6 +9,7 @@ import type { DeviceInstance } from '../typings';
 import SystemConst from '@/utils/const';
 import encodeQuery from '@/utils/encodeQuery';
 import { downloadFile } from '@/utils/util';
+import { ExclamationCircleOutlined } from '@ant-design/icons';
 
 interface Props {
   visible: boolean;
@@ -117,7 +118,8 @@ const Export = (props: Props) => {
     >
       <div style={{ background: 'rgb(236, 237, 238)' }}>
         <p style={{ padding: 10 }}>
-          选择单个产品时可导出其下属设备的详细数据,不选择产品时导出所有设备的基础数
+          <ExclamationCircleOutlined style={{ marginRight: 5 }} />
+          选择单个产品时可导出其下属设备的详细数据,不选择产品时导出所有设备的基础数量。
         </p>
       </div>
       <div style={{ marginTop: '20px' }}>

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

@@ -296,7 +296,7 @@ const ProductDetail = observer(() => {
       }
       title={
         <Tooltip placement="topLeft" title={productModel.current?.name}>
-          <div className="ellipsis" style={{ width: 250 }}>
+          <div className="ellipsis" style={{ maxWidth: 250 }}>
             {productModel.current?.name}
           </div>
         </Tooltip>

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

@@ -96,15 +96,15 @@ const Save = (props: Props) => {
           <div style={{ color: '#757575' }}>
             点击具体产品的查看按钮,进入“设备接入”tab页,并参照设备铭牌说明选择匹配的接入方式
           </div>
-          <div style={{ fontWeight: 600 }}>2、添加测试设备</div>
+          <div style={{ fontWeight: 600 }}>2、添加测试设备</div>
           <div style={{ color: '#757575' }}>
             进入设备列表,添加单个设备,用于验证产品模型是否配置正确
           </div>
-          <div style={{ fontWeight: 600 }}> 3、功能调试</div>
+          <div style={{ fontWeight: 600 }}> 3、功能调试</div>
           <div style={{ color: '#757575' }}>
             点击查看具体设备,进入“设备诊断”对添加的测试设备进行功能调试,验证能否连接到平台,设备功能是否配置正确
           </div>
-          <div style={{ fontWeight: 600 }}> 4、批量添加设备</div>
+          <div style={{ fontWeight: 600 }}> 4、批量添加设备</div>
           <div style={{ color: '#757575' }}>
             进入设备列表页面,点击批量导入设备,批量添加同一产品下的设备
           </div>

+ 1 - 0
src/pages/device/Product/index.tsx

@@ -260,6 +260,7 @@ const Product = observer(() => {
       title: '接入方式',
       dataIndex: 'accessId',
       width: 150,
+      ellipsis: true,
       valueType: 'select',
       render: (_, row) => {
         return row.protocolName;

+ 3 - 2
src/pages/device/components/Metadata/Import/index.tsx

@@ -11,6 +11,7 @@ import { useParams } from 'umi';
 import { Store } from 'jetlinks-store';
 import SystemConst from '@/utils/const';
 import { onlyMessage } from '@/utils/util';
+import { ExclamationCircleOutlined } from '@ant-design/icons';
 
 interface Props {
   visible: boolean;
@@ -213,8 +214,8 @@ const Import = (props: Props) => {
     >
       <div style={{ background: 'rgb(236, 237, 238)' }}>
         <p style={{ padding: 10 }}>
-          <span style={{ color: '#f5222d' }}>注</span>
-          导入的物模型会覆盖原来的属性、功能、事件、标签,请谨慎操作。
+          <ExclamationCircleOutlined style={{ marginRight: 5 }} />
+          导入的物模型会覆盖原来的属性、功能、事件、标签,请谨慎操作。
           {/* <br /> */}
           {/*物模型格式请参考文档:*/}
           {/*<a*/}

+ 1 - 1
src/pages/home/components/GuideHome.tsx

@@ -38,7 +38,7 @@ const GuideItem = (props: GuideItemProps) => {
 
   return (
     <div
-      className={'home-guide-item step-bar'}
+      className={'home-guide-item step-bar pointer'}
       onClick={jumpPage}
       style={{ marginTop: 12, padding: 10, border: '1px solid #eee' }}
     >

+ 1 - 1
src/pages/home/components/index.less

@@ -90,7 +90,7 @@
 .home-body {
   .home-base;
 
-  min-height: 440px;
+  min-height: 444px;
   margin-bottom: @margin;
   padding-bottom: 26.5%;
   overflow: hidden;

+ 5 - 1
src/pages/home/comprehensive/index.tsx

@@ -234,7 +234,11 @@ const Comprehensive = () => {
         </Row>
         <Row gutter={24}>
           <Col span={24} style={{ marginTop: 24 }}>
-            <Body title={'平台架构图'} english={'PLATFORM ARCHITECTURE DIAGRAM'} />
+            <Body
+              title={'平台架构图'}
+              english={'PLATFORM ARCHITECTURE DIAGRAM'}
+              url={require('/public/images/home/content1.png')}
+            />
           </Col>
         </Row>
       </Col>

+ 3 - 3
src/pages/home/device/index.tsx

@@ -48,7 +48,7 @@ const Device = () => {
     {
       key: 'product',
       name: '创建产品',
-      english: 'CREATE PRODUCT',
+      english: 'STP 1',
       auth: !!productPermission.add,
       url: 'device/Product',
       param: {
@@ -58,7 +58,7 @@ const Device = () => {
     {
       key: 'device',
       name: '创建设备',
-      english: 'CREATE DEVICE',
+      english: 'STP 2',
       auth: !!devicePermission.add,
       url: 'device/Instance',
       param: {
@@ -68,7 +68,7 @@ const Device = () => {
     {
       key: 'rule-engine',
       name: '规则引擎',
-      english: 'RULE ENGINE',
+      english: 'STP 3',
       auth: !!rulePermission.add,
       url: 'rule-engine/Instance',
       param: {

+ 2 - 2
src/pages/link/Channel/Modbus/Access/bindDevice/index.tsx

@@ -20,7 +20,7 @@ const BindDevice = (props: Props) => {
   const statusMap = new Map();
   statusMap.set('在线', 'success');
   statusMap.set('离线', 'error');
-  statusMap.set('未激活', 'processing');
+  statusMap.set('禁用', 'processing');
   statusMap.set('online', 'success');
   statusMap.set('offline', 'error');
   statusMap.set('notActive', 'processing');
@@ -66,7 +66,7 @@ const BindDevice = (props: Props) => {
           status: 'offline',
         },
         notActive: {
-          text: '未激活',
+          text: '禁用',
           status: 'notActive',
         },
       },

+ 2 - 2
src/pages/link/Channel/Opcua/Access/bindDevice/index.tsx

@@ -21,7 +21,7 @@ const BindDevice = (props: Props) => {
   const statusMap = new Map();
   statusMap.set('在线', 'success');
   statusMap.set('离线', 'error');
-  statusMap.set('未激活', 'processing');
+  statusMap.set('禁用', 'processing');
   statusMap.set('online', 'success');
   statusMap.set('offline', 'error');
   statusMap.set('notActive', 'processing');
@@ -65,7 +65,7 @@ const BindDevice = (props: Props) => {
           status: 'offline',
         },
         notActive: {
-          text: '未激活',
+          text: '禁用',
           status: 'notActive',
         },
       },

+ 107 - 10
src/pages/link/Type/Detail/index.tsx

@@ -15,7 +15,7 @@ import {
 } from '@formily/antd';
 import type { ISchema } from '@formily/json-schema';
 import { useEffect, useMemo, useRef } from 'react';
-import type { Field } from '@formily/core';
+import { Field, FieldDataSource } from '@formily/core';
 import { createForm, onFieldReact, onFieldValueChange } from '@formily/core';
 import { Card } from 'antd';
 import styles from './index.less';
@@ -26,6 +26,7 @@ import FAutoComplete from '@/components/FAutoComplete';
 import { Store } from 'jetlinks-store';
 import { PermissionButton } from '@/components';
 import usePermissions from '@/hooks/permission';
+import { action } from '@formily/reactive';
 
 /**
  *  根据类型过滤配置信息
@@ -65,6 +66,20 @@ const Save = observer(() => {
     });
   }, []);
 
+  const useAsyncData = (services: (arg0: Field) => Promise<FieldDataSource>) => (field: Field) => {
+    field.loading = true;
+    services(field).then(
+      action.bound!((resp: any) => {
+        const save = location.href.split('/');
+        if (save[save.length - 1] === ':id') {
+          field.value = resp[0].value;
+        }
+        field.dataSource = resp;
+        field.loading = false;
+      }),
+    );
+  };
+
   const getResourcesClusters = () => {
     // eslint-disable-next-line @typescript-eslint/no-use-before-define
     const checked = form.getValuesIn('cluster')?.map((i: any) => i?.serverId) || [];
@@ -84,17 +99,17 @@ const Save = observer(() => {
       });
     }
   };
+  const getCertificates = () =>
+    service.getCertificates().then((resp: any) =>
+      resp.result?.map((item: any) => ({
+        label: item.name,
+        value: item.id,
+      })),
+    );
 
   const getResourceById = (id: string, type: string) =>
     service.getResourceClustersById(id).then((resp) => filterConfigByType(resp.result, type));
 
-  // const getAllResources = () =>
-  //   service.getAllResources().then((resp) =>
-  //     resp.result?.map((item: any) => ({
-  //       label: item.clusterNodeId,
-  //       value: item.clusterNodeId,
-  //     })));
-
   const form = useMemo(
     () =>
       createForm({
@@ -103,6 +118,7 @@ const Save = observer(() => {
         effects() {
           onFieldValueChange('type', (field, f) => {
             const value = (field as Field).value;
+            // console.log(field)
             if (f.modified) {
               f.deleteValuesIn('configuration');
               f.deleteValuesIn('cluster');
@@ -538,6 +554,79 @@ const Save = observer(() => {
           },
         },
       },
+      secure: {
+        title: '开启DTLS',
+        'x-decorator': 'FormItem',
+        'x-component': 'Radio.Group',
+        'x-decorator-props': {
+          gridSpan: 1,
+          labelAlign: 'left',
+          layout: 'vertical',
+        },
+        required: true,
+        default: false,
+        enum: [
+          { label: '是', value: true },
+          { label: '否', value: false },
+        ],
+      },
+      certId: {
+        title: '证书',
+        'x-decorator': 'FormItem',
+        'x-component': 'Select',
+        'x-component-props': {
+          placeholder: '请选择证书',
+        },
+        'x-decorator-props': {
+          gridSpan: 1,
+          labelAlign: 'left',
+          layout: 'vertical',
+        },
+        required: true,
+        'x-reactions': [
+          '{{useAsyncDataSource(getCertificates)}}',
+          {
+            dependencies: ['..secure'],
+            fulfill: {
+              state: {
+                visible: '{{$deps[0]===true}}',
+              },
+            },
+          },
+        ],
+      },
+      privateKeyAlias: {
+        title: '私钥别名',
+        'x-decorator': 'FormItem',
+        'x-component': 'Input',
+        'x-component-props': {
+          placeholder: '请输入私钥别名',
+        },
+        'x-decorator-props': {
+          gridSpan: 1,
+          labelAlign: 'left',
+          layout: 'vertical',
+        },
+        required: true,
+        'x-validator': [
+          {
+            max: 64,
+            message: '最多可输入64个字符',
+          },
+          {
+            required: true,
+            message: '请输入私钥别名',
+          },
+        ],
+        'x-reactions': {
+          dependencies: ['..secure'],
+          fulfill: {
+            state: {
+              visible: '{{$deps[0]===true}}',
+            },
+          },
+        },
+      },
     },
   };
   const schema: ISchema = {
@@ -584,13 +673,14 @@ const Save = observer(() => {
             'x-component-props': {
               placeholder: '请选择类型',
             },
+            default: {},
             'x-validator': [
               {
                 required: true,
                 message: '请输入名称',
               },
             ],
-            'x-reactions': ['{{useAsyncDataSource(getSupports)}}'],
+            'x-reactions': ['{{useAsyncData(getSupports)}}'],
           },
           shareCluster: {
             title: '集群',
@@ -737,7 +827,14 @@ const Save = observer(() => {
         <Form form={form} layout="vertical" style={{ padding: 30 }}>
           <SchemaField
             schema={schema}
-            scope={{ formCollapse, useAsyncDataSource, getSupports, getResourcesClusters }}
+            scope={{
+              formCollapse,
+              useAsyncDataSource,
+              useAsyncData,
+              getSupports,
+              getResourcesClusters,
+              getCertificates,
+            }}
           />
           <FormButtonGroup.Sticky>
             <FormButtonGroup.FormItem>

+ 5 - 0
src/pages/link/service.ts

@@ -36,6 +36,11 @@ class Service extends BaseService<NetworkItem> {
 
   changeState = (id: string, status: 'start' | 'shutdown') =>
     request(`${SystemConst.API_BASE}/network/config/${id}/_${status}`, { method: 'POST' });
+
+  getCertificates = () =>
+    request(`/${SystemConst.API_BASE}/network/certificate/_query/no-paging?paging=false`, {
+      method: 'GET',
+    });
 }
 
 export default Service;

+ 3 - 3
src/pages/media/Home/index.tsx

@@ -68,7 +68,7 @@ export default () => {
     {
       key: 'EQUIPMENT',
       name: '添加视频设备',
-      english: 'ADD VIDEO EQUIPMENT',
+      english: 'STP 1',
       auth: !!devicePermission.add,
       url: deviceUrl,
       param: { save: true },
@@ -76,14 +76,14 @@ export default () => {
     {
       key: 'SCREEN',
       name: '分屏展示',
-      english: 'SPLIT SCREEN DISPLAY',
+      english: 'STP 2',
       auth: !!splitScreenUrl,
       url: splitScreenUrl,
     },
     {
       key: 'CASCADE',
       name: '国标级联',
-      english: 'GB CASCADE',
+      english: 'STP 3',
       auth: !!cascadeUrl,
       url: cascadeUrl,
     },

+ 5 - 5
src/pages/notice/Config/SyncUser/index.tsx

@@ -224,9 +224,9 @@ const SyncUser = observer(() => {
                     })
                 }
                 headerTitle={
-                  <Popconfirm
-                    title="确认保存"
-                    onConfirm={async () => {
+                  <Button
+                    type="primary"
+                    onClick={async () => {
                       const arr = list
                         .filter((item) => item.status === 0)
                         .map((i) => {
@@ -248,8 +248,8 @@ const SyncUser = observer(() => {
                       }
                     }}
                   >
-                    <Button type="primary">自动绑定</Button>
-                  </Popconfirm>
+                    自动绑定
+                  </Button>
                 }
               />
             ) : (

+ 3 - 3
src/pages/notice/Config/index.tsx

@@ -124,17 +124,17 @@ const Config = observer(() => {
         defaultMessage: '操作',
       }),
       valueType: 'option',
-      align: 'center',
       width: 200,
       fixed: 'right',
       render: (text, record) => [
-        (id === 'dingTalk' || id === 'weixin') && (
+        (record.provider === 'dingTalkMessage' || record.provider === 'corpMessage') && (
           <PermissionButton
             tooltip={{
               title: '同步用户',
             }}
             style={{ padding: 0 }}
             type="link"
+            isPermission={configPermission.bind}
             onClick={() => {
               state.syncUser = true;
               state.current = record;
@@ -431,7 +431,7 @@ const Config = observer(() => {
                       <Menu.Item key="syncUser">
                         <PermissionButton
                           key="syncUser"
-                          isPermission={true}
+                          isPermission={configPermission.bind}
                           type="link"
                           onClick={() => {
                             state.syncUser = true;

+ 8 - 0
src/pages/rule-engine/Alarm/Configuration/index.tsx

@@ -101,6 +101,14 @@ const Configuration = () => {
           </span>
         </PermissionButton>
       ),
+      valueType: 'select',
+      request: async () => {
+        const res = await service.getScene({});
+        if (res.status === 200) {
+          return res.result.map((item: any) => ({ label: item.name, value: item.name }));
+        }
+        return [];
+      },
     },
     {
       title: '状态',

+ 18 - 4
src/pages/rule-engine/Alarm/Log/Detail/Info.tsx

@@ -1,4 +1,4 @@
-import { Descriptions, Modal } from 'antd';
+import { Descriptions, Modal, Tooltip } from 'antd';
 import { useEffect, useState } from 'react';
 import moment from 'moment';
 import { Store } from 'jetlinks-store';
@@ -43,11 +43,25 @@ const Info = (props: Props) => {
           {moment(data?.alarmTime).format('YYYY-MM-DD HH:mm:ss')}
         </Descriptions.Item>
         <Descriptions.Item label="告警级别" span={1}>
-          {(Store.get('default-level') || []).find((item: any) => item?.level === data?.level)
-            ?.title || data?.level}
+          <Tooltip
+            placement="topLeft"
+            title={
+              (Store.get('default-level') || []).find((item: any) => item?.level === data?.level)
+                ?.title || data?.level
+            }
+          >
+            <div className="ellipsis" style={{ maxWidth: 100 }}>
+              {(Store.get('default-level') || []).find((item: any) => item?.level === data?.level)
+                ?.title || data?.level}
+            </div>
+          </Tooltip>
         </Descriptions.Item>
         <Descriptions.Item label="告警说明" span={1}>
-          {data?.description || '--'}
+          <Tooltip placement="topLeft" title={data?.description || '--'}>
+            <div className="ellipsis" style={{ maxWidth: 1 }}>
+              {data?.description || '--'}
+            </div>
+          </Tooltip>
         </Descriptions.Item>
         <Descriptions.Item label="告警流水" span={2}>
           {data?.alarmInfo || '--'}

+ 12 - 2
src/pages/rule-engine/Alarm/Log/TabComponent/index.tsx

@@ -255,8 +255,18 @@ const TabComponent = observer((props: Props) => {
                             style={{ backgroundColor: colorMap.get(item.level) }}
                           >
                             <div className={'card-state-content'}>
-                              {AlarmLogModel.defaultLevel.find((i) => i.level === item.level)
-                                ?.title || item.level}
+                              <Tooltip
+                                placement="topLeft"
+                                title={
+                                  AlarmLogModel.defaultLevel.find((i) => i.level === item.level)
+                                    ?.title || item.level
+                                }
+                              >
+                                <div className="ellipsis" style={{ maxWidth: 70 }}>
+                                  {AlarmLogModel.defaultLevel.find((i) => i.level === item.level)
+                                    ?.title || item.level}
+                                </div>
+                              </Tooltip>
                             </div>
                           </div>
                         </div>

+ 1 - 1
src/pages/user/Login/index.less

@@ -70,7 +70,7 @@
         }
 
         .main {
-          width: 328px;
+          width: 70%;
           margin: 60px auto 0;
           @media screen and (max-width: @screen-sm) {
             width: 95%;

+ 1 - 0
src/utils/menu/router.ts

@@ -156,6 +156,7 @@ export enum BUTTON_PERMISSION_ENUM {
   'log' = 'log',
   'tigger' = 'tigger',
   'empowerment' = 'empowerment',
+  'bind' = 'bind',
 }
 
 // 调试按钮、通知记录、批量导出、批量导入、选择通道、推送、分配资产、绑定用户对应的ID是啥