Kaynağa Gözat

Merge xyh

Next xyh
XieYongHong 3 yıl önce
ebeveyn
işleme
8276bb61a8
77 değiştirilmiş dosya ile 438 ekleme ve 6479 silme
  1. 0 11
      package.json
  2. 11 11
      src/app.tsx
  3. 0 73
      src/components/AMapComponent/index.tsx
  4. 14 9
      src/components/SearchComponent/index.tsx
  5. 1 1
      src/hooks/websocket/useSendWebsocketMessage.ts
  6. 1 0
      src/hooks/websocket/useWebSocket.ts
  7. 0 45
      src/pages/Analysis/CPU/index.tsx
  8. 0 192
      src/pages/Analysis/DeviceChart/index.tsx
  9. 0 188
      src/pages/Analysis/DeviceMessage/index.tsx
  10. 0 45
      src/pages/Analysis/Jvm/index.tsx
  11. 0 128
      src/pages/Analysis/MessageChart/index.tsx
  12. 0 59
      src/pages/Analysis/index.tsx
  13. 0 19
      src/pages/Analysis/service.ts
  14. 0 140
      src/pages/cloud/Aliyun/index.tsx
  15. 0 22
      src/pages/cloud/Aliyun/typings.d.ts
  16. 0 124
      src/pages/cloud/Ctwing/index.tsx
  17. 0 9
      src/pages/cloud/Ctwing/typings.d.ts
  18. 0 11
      src/pages/cloud/DuerOS/Save/index.tsx
  19. 0 158
      src/pages/cloud/DuerOS/index.tsx
  20. 0 45
      src/pages/cloud/DuerOS/typings.d.ts
  21. 0 136
      src/pages/cloud/Onenet/index.tsx
  22. 0 10
      src/pages/cloud/Onenet/typings.d.ts
  23. 0 42
      src/pages/device/Command/cat/index.tsx
  24. 0 260
      src/pages/device/Command/create/index.tsx
  25. 0 219
      src/pages/device/Command/index.tsx
  26. 0 23
      src/pages/device/Command/service.ts
  27. 0 28
      src/pages/device/Command/typings.d.ts
  28. 0 508
      src/pages/device/Instance/Detail/MetadataLog/Property/index copy.tsx
  29. 15 0
      src/pages/device/Instance/index.tsx
  30. 0 11
      src/pages/device/Location/index.tsx
  31. 0 118
      src/pages/edge/Device/index.tsx
  32. 0 14
      src/pages/edge/Device/typings.d.ts
  33. 0 113
      src/pages/edge/Product/index.tsx
  34. 0 9
      src/pages/edge/Product/typings.d.ts
  35. 2 3
      src/pages/init-home/components/basis.tsx
  36. 1 1
      src/pages/init-home/index.less
  37. 1 1
      src/pages/init-home/index.tsx
  38. 0 6
      src/pages/media/Config/index.tsx
  39. 0 4
      src/pages/media/Config/typings.d.ts
  40. 0 6
      src/pages/media/Reveal/index.tsx
  41. 0 4
      src/pages/media/Reveal/typings.d.ts
  42. 2 1
      src/pages/notice/Config/Debug/index.tsx
  43. 2 2
      src/pages/notice/Config/SyncUser/index.tsx
  44. 13 10
      src/pages/notice/Template/Detail/doc/DingTalk.tsx
  45. 2 2
      src/pages/notice/Template/Detail/doc/DingTalkRebot.tsx
  46. 1 1
      src/pages/rule-engine/DashBoard/index.tsx
  47. 1 1
      src/pages/rule-engine/Instance/index.tsx
  48. 0 150
      src/pages/rule-engine/SQLRule/index.tsx
  49. 0 3
      src/pages/rule-engine/SQLRule/typings.d.ts
  50. 6 3
      src/pages/rule-engine/Scene/Save/components/TimingTrigger/index.tsx
  51. 8 5
      src/pages/rule-engine/Scene/Save/components/TimingTrigger/refactor.tsx
  52. 21 0
      src/pages/rule-engine/Scene/Save/index.less
  53. 7 19
      src/pages/rule-engine/Scene/Save/index.tsx
  54. 13 11
      src/pages/rule-engine/Scene/Save/trigger/index.tsx
  55. 0 115
      src/pages/simulator/Device/index.tsx
  56. 0 9
      src/pages/simulator/Device/typings.d.ts
  57. 0 90
      src/pages/system/Basis/init.tsx
  58. 0 4
      src/pages/system/Config/index.tsx
  59. 0 6
      src/pages/system/Config/service.ts
  60. 1 1
      src/pages/system/Department/Assets/deivce/index.tsx
  61. 1 1
      src/pages/system/Department/Member/index.tsx
  62. 95 92
      src/pages/system/Menu/Detail/buttons.tsx
  63. 60 11
      src/pages/system/Menu/Setting/baseMenu.ts
  64. 16 2
      src/pages/system/Menu/Setting/index.tsx
  65. 37 4
      src/pages/system/Menu/Setting/tree.tsx
  66. 2 2
      src/pages/system/Menu/index.tsx
  67. 0 355
      src/pages/system/OpenAPI/index.tsx
  68. 0 16
      src/pages/system/OpenAPI/typings.d.ts
  69. 51 33
      src/pages/user/Login/index.tsx
  70. 4 0
      src/pages/user/Login/service.ts
  71. 0 104
      src/pages/visualization/Category/index.tsx
  72. 0 10
      src/pages/visualization/Category/typings.d.ts
  73. 0 142
      src/pages/visualization/Configuration/index.tsx
  74. 0 3
      src/pages/visualization/Configuration/typings.d.ts
  75. 0 144
      src/pages/visualization/Screen/index.tsx
  76. 0 9
      src/pages/visualization/Screen/typings.d.ts
  77. 49 2312
      yarn.lock

+ 0 - 11
package.json

@@ -54,10 +54,6 @@
     "not ie <= 10"
   ],
   "dependencies": {
-    "@ahooksjs/use-url-state": "^3.5.0",
-    "@amap/amap-jsapi-loader": "^1.0.1",
-    "@amap/amap-jsapi-types": "^0.0.8",
-    "@ant-design/charts": "^1.3.1",
     "@ant-design/icons": "^4.5.0",
     "@ant-design/pro-card": "^1.16.2",
     "@ant-design/pro-descriptions": "^1.6.8",
@@ -74,18 +70,15 @@
     "@jetlinks/pro-list": "^1.10.8",
     "@jetlinks/pro-table": "^2.63.11",
     "@liveqing/liveplayer": "^2.6.4",
-    "@types/react-syntax-highlighter": "^13.5.2",
     "@umijs/route-utils": "^1.0.36",
     "ahooks": "^2.10.9",
     "antd": "4.19.5",
-    "bizcharts": "^4.1.16",
     "braft-editor": "^2.3.9",
     "classnames": "^2.3.1",
     "dexie": "^3.0.3",
     "driver.js": "^0.9.8",
     "echarts": "^5.3.2",
     "event-source-polyfill": "^1.0.25",
-    "isomorphic-form-data": "^2.0.0",
     "jetlinks-store": "^0.0.3",
     "lodash": "^4.17.11",
     "moment": "^2.29.3",
@@ -94,7 +87,6 @@
     "omit.js": "^2.0.2",
     "react": "^17.0.0",
     "react-amap": "^1.2.8",
-    "react-beautiful-dnd": "^13.1.0",
     "react-custom-scrollbars": "^4.2.1",
     "react-dev-inspector": "^1.1.1",
     "react-dnd": "^16.0.1",
@@ -104,9 +96,6 @@
     "react-json-view": "^1.21.3",
     "react-markdown": "^8.0.0",
     "react-monaco-editor": "^0.46.0",
-    "react-syntax-highlighter": "^15.4.5",
-    "reconnecting-websocket": "^4.4.0",
-    "remark-gfm": "^3.0.1",
     "rxjs": "^7.2.0",
     "rxjs-websockets": "8",
     "umi": "^3.5.0",

+ 11 - 11
src/app.tsx

@@ -10,7 +10,7 @@ import Service from '@/pages/user/Login/service';
 // import { service as SystemConfigService } from '@/pages/system/Config';
 import Token from '@/utils/token';
 import type { RequestOptionsInit } from 'umi-request';
-import ReconnectingWebSocket from 'reconnecting-websocket';
+// import ReconnectingWebSocket from 'reconnecting-websocket';
 import SystemConst from '@/utils/const';
 import { service as MenuService } from '@/pages/system/Menu';
 import getRoutes, {
@@ -82,16 +82,16 @@ export async function getInitialState(): Promise<{
     };
   }
   // 链接websocket
-  const url = `${document.location.protocol.replace('http', 'ws')}//${document.location.host}/${
-    SystemConst.API_BASE
-  }/messaging/${Token.get()}?:X_Access_Token=${Token.get()}`;
-
-  const ws = new ReconnectingWebSocket(url);
-
-  // ws.send('sss');
-  ws.onerror = () => {
-    console.log('链接错误。ws');
-  };
+  // const url = `${document.location.protocol.replace('http', 'ws')}//${document.location.host}/${
+  //   SystemConst.API_BASE
+  // }/messaging/${Token.get()}?:X_Access_Token=${Token.get()}`;
+  //
+  // const ws = new ReconnectingWebSocket(url);
+  //
+  // // ws.send('sss');
+  // ws.onerror = () => {
+  //   console.log('链接错误。ws');
+  // };
 
   return {
     fetchUserInfo,

+ 0 - 73
src/components/AMapComponent/index.tsx

@@ -1,73 +0,0 @@
-import { useEffect, useRef, useState } from 'react';
-import AMapLoader from '@amap/amap-jsapi-loader';
-import classNames from 'classnames';
-import { LeftOutlined } from '@ant-design/icons';
-import './index.less';
-
-const AMapComponent = () => {
-  const mapRef = useRef({});
-
-  useEffect(() => {
-    AMapLoader.load({
-      key: '4a8929c85e2a1a8a1eae4ebc7d519ba4',
-      version: '2.0',
-      plugins: ['AMap.ToolBar', 'AMap.Driving'],
-      AMapUI: {
-        version: '1.1',
-        plugins: [],
-      },
-      Loca: {
-        version: '2.0.0',
-      },
-    })
-      .then((AMap) => {
-        const map = new AMap.Map('map-container', {
-          viewMode: '3D',
-          zoom: 5,
-          zooms: [2, 22],
-          center: [105.602725, 37.076636],
-        });
-        const positionArr = [
-          [113.357224, 34.977186],
-          [114.555528, 37.727903],
-          [112.106257, 36.962733],
-          [109.830097, 31.859027],
-          [116.449181, 39.98614],
-        ];
-        for (const item of positionArr) {
-          const marker = new AMap.Marker({
-            position: [item[0], item[1]],
-          });
-          map.add(marker);
-        }
-        mapRef.current = map;
-      })
-      .catch((e) => {
-        console.log(e);
-      });
-  }, []);
-  const [show, setShow] = useState<boolean>(false);
-  return (
-    <div className="home">
-      <div id="map-container" className="map" style={{ height: '600px' }} />
-      <div className="draw">
-        <div
-          className={classNames('draw-warp', {
-            show: show,
-          })}
-        >
-          <div
-            className={classNames('draw-button')}
-            onClick={() => {
-              setShow(!show);
-            }}
-          >
-            <LeftOutlined className={classNames('draw-button-icon', { active: show })} />
-          </div>
-          <div className="draw-content">....内容信息</div>
-        </div>
-      </div>
-    </div>
-  );
-};
-export default AMapComponent;

+ 14 - 9
src/components/SearchComponent/index.tsx

@@ -290,6 +290,7 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
                     state.componentType = 'DatePicker';
                     state.componentProps = { showTime: true, allowClear: true };
                   });
+                  console.log(isModified);
                   if (isModified) {
                     f.setFieldState(typeFiled.query('.termType'), async (state) => {
                       state.value = 'gte';
@@ -625,22 +626,26 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
     onSearch({ terms: newTemp });
   };
 
-  useEffect(() => {
+  const handleLocation = async (l: any, tar?: string) => {
     // 防止页面下多个TabsTabPane中的查询组件共享路由中的参数
-    const params = new URLSearchParams(_location.search);
+    const params = new URLSearchParams(l.search);
     const q = params.get('q');
     const _target = params.get('target');
-    if (q && props.model !== 'simple') {
-      if (_target) {
-        if (props.target && _target === props.target) {
-          form.setValues(JSON.parse(q));
-          handleSearch(false);
-        }
+    const value = await form.submit<SearchTermsUI>();
+    if (q && props.model !== 'simple' && value && !value.terms1?.[0].value && !value.terms2) {
+      // 表单有值的情况下,不改变表单
+      if (_target && tar && _target === tar) {
+        form.setInitialValues(JSON.parse(q));
+        handleSearch(false);
         return;
       }
-      form.setValues(JSON.parse(q));
+      form.setInitialValues(JSON.parse(q));
       handleSearch(false);
     }
+  };
+
+  useEffect(() => {
+    handleLocation(_location, props.target);
   }, [_location, props.target]);
 
   useEffect(() => {

+ 1 - 1
src/hooks/websocket/useSendWebsocketMessage.ts

@@ -47,7 +47,7 @@ export const useSendWebsocketMessage = () => {
     // reconnectInterval: 1000,
     // reconnectLimit: 1,
     onClose: () => console.error('websocket 链接关闭'),
-    onOpen: (event) => console.log('打开链接', event),
+    // onOpen: (event) => console.log('打开链接', event),
     onError: (event) => console.log('报错了', event),
     onReconnect: () => {
       if (Object.keys(messageCache).length && sendMessage) {

+ 1 - 0
src/hooks/websocket/useWebSocket.ts

@@ -78,6 +78,7 @@ export default function useWebSocket(socketUrl: string, options: Options = {}):
           if (isReconnect.current && onReconnect) {
             // 是否为重连
             onReconnect();
+            return
           }
           onOpen?.(event);
           reconnectTimesRef.current = 0;

+ 0 - 45
src/pages/Analysis/CPU/index.tsx

@@ -1,45 +0,0 @@
-import { Gauge } from '@ant-design/charts';
-import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
-import WebsocketTopic from '@/utils/topic';
-import { useEffect, useState } from 'react';
-import type { WebsocketPayload } from '@/hooks/websocket/typings';
-
-const CPU = () => {
-  const [subscribeTopic] = useSendWebsocketMessage();
-  const [value, setValue] = useState<number>(0);
-  useEffect(() => {
-    const cpuRealTime = subscribeTopic?.(
-      WebsocketTopic.CPURealTime.id,
-      WebsocketTopic.CPURealTime.topic,
-      { params: { history: 1 } },
-    )?.subscribe((data: WebsocketPayload) => {
-      // +0.01为了解决0.00图表异常
-      setValue(((data.payload.value as number) + 0.01) / 100);
-    });
-    return () => cpuRealTime?.unsubscribe();
-  }, []);
-  const config = {
-    width: 200,
-    height: 200,
-
-    range: {
-      ticks: [0, 1 / 3, 2 / 3, 1],
-      color: ['#F4664A', '#FAAD14', '#30BF78'],
-    },
-    indicator: {
-      pointer: { style: { stroke: '#D0D0D0' } },
-      pin: { style: { stroke: '#D0D0D0' } },
-    },
-    statistic: {
-      content: {
-        style: {
-          fontSize: '36px',
-          lineHeight: '36px',
-        },
-      },
-    },
-  };
-  return <Gauge {...config} percent={value} />;
-};
-
-export default CPU;

+ 0 - 192
src/pages/Analysis/DeviceChart/index.tsx

@@ -1,192 +0,0 @@
-import { StatisticCard } from '@ant-design/pro-card';
-import { service } from '@/pages/Analysis';
-import { useEffect } from 'react';
-import { groupBy, map } from 'rxjs/operators';
-import { mergeMap, of, toArray, zip } from 'rxjs';
-import moment from 'moment';
-import { model } from '@formily/reactive';
-import { observer } from '@formily/react';
-import { Column } from '@ant-design/charts';
-import { Badge, Col, Row } from 'antd';
-import { SyncOutlined } from '@ant-design/icons';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-type DeviceChartType = {
-  deviceOnline: number;
-  aggOnline: Record<string, any>[];
-  deviceCount: number;
-  deviceNotActive: number;
-};
-const DeviceChartModel = model<DeviceChartType>({
-  deviceCount: 0,
-  aggOnline: [],
-  deviceOnline: 0,
-  deviceNotActive: 0,
-});
-const DeviceChart = observer(() => {
-  const intl = useIntl();
-  const getDeviceData = () => {
-    const requestParams = [
-      // 设备状态信息-在线
-      {
-        dashboard: 'device',
-        object: 'status',
-        measurement: 'record',
-        dimension: 'current',
-        group: 'deviceOnline',
-        params: {
-          state: 'online',
-        },
-      }, // 设备状态信息-总数
-      {
-        dashboard: 'device',
-        object: 'status',
-        measurement: 'record',
-        dimension: 'current',
-        group: 'deviceCount',
-      }, // 设备状态信息-未激活
-      {
-        dashboard: 'device',
-        object: 'status',
-        measurement: 'record',
-        dimension: 'current',
-        group: 'deviceNotActive',
-        params: {
-          state: 'notActive',
-        },
-      }, // 设备状态信息-历史在线
-      {
-        dashboard: 'device',
-        object: 'status',
-        measurement: 'record',
-        dimension: 'aggOnline',
-        group: 'aggOnline',
-        params: {
-          limit: 20,
-          time: '1d',
-          format: 'yyyy-MM-dd',
-        },
-      },
-    ];
-    service
-      .getMulti(requestParams)
-      .pipe(
-        mergeMap(
-          (item) =>
-            item.result as {
-              group: string;
-              data: Record<string, any>;
-              formatData?: { x: unknown; y: unknown };
-            }[],
-        ),
-        groupBy((item) => item.group),
-        mergeMap((group$) =>
-          zip(
-            of(group$.key),
-            group$.pipe(
-              map((item) =>
-                item.group === 'aggOnline'
-                  ? {
-                      x: moment(new Date(item.data.timeString)).format('YYYY-MM-DD'),
-                      y: Number(item.data.value),
-                    }
-                  : item.data.value,
-              ),
-              toArray(),
-            ),
-          ),
-        ),
-        map((item) =>
-          item[0] === 'aggOnline' ? [item[0], item[1].reverse()] : [item[0], ...item[1]],
-        ),
-      )
-      .subscribe((data) => {
-        // eslint-disable-next-line prefer-destructuring
-        DeviceChartModel[data[0]] = data[1];
-      });
-  };
-
-  useEffect(() => {
-    getDeviceData();
-  }, []);
-
-  return (
-    <StatisticCard
-      title={intl.formatMessage({
-        id: 'pages.analysis.deviceStatistics',
-        defaultMessage: '设备统计',
-      })}
-      extra={<SyncOutlined onClick={() => getDeviceData()} />}
-      chart={
-        <Column
-          width={200}
-          height={180}
-          xField="x"
-          yField="y"
-          label={{
-            position: 'middle',
-            style: {
-              fill: '#FFFFFF',
-              opacity: 0.6,
-            },
-          }}
-          xAxis={{
-            label: {
-              autoHide: true,
-              autoRotate: false,
-            },
-          }}
-          meta={{
-            x: { alias: '日期' },
-            y: { alias: '数量' },
-          }}
-          data={DeviceChartModel.aggOnline}
-        />
-      }
-      footer={
-        <Row>
-          <Col span={8}>
-            <>
-              {' '}
-              <Badge
-                status="warning"
-                text={intl.formatMessage({
-                  id: 'pages.analysis.cpu',
-                  defaultMessage: '未激活',
-                })}
-              />
-              {DeviceChartModel.deviceNotActive}
-            </>
-          </Col>
-          <Col span={8}>
-            <>
-              {' '}
-              <Badge
-                status="processing"
-                text={intl.formatMessage({
-                  id: 'pages.analysis.deviceStatistics.total',
-                  defaultMessage: '总数',
-                })}
-              />
-              · {DeviceChartModel.deviceCount}
-            </>
-          </Col>
-          <Col span={8}>
-            <>
-              <Badge
-                status="success"
-                text={intl.formatMessage({
-                  id: 'pages.analysis.deviceStatistics.online',
-                  defaultMessage: '在线',
-                })}
-              />
-              {DeviceChartModel.deviceOnline}
-            </>
-          </Col>
-        </Row>
-      }
-    />
-  );
-});
-
-export default DeviceChart;

+ 0 - 188
src/pages/Analysis/DeviceMessage/index.tsx

@@ -1,188 +0,0 @@
-import { Area } from '@ant-design/charts';
-import { service } from '@/pages/Analysis';
-import { useEffect } from 'react';
-import { groupBy, map, mergeMap } from 'rxjs/operators';
-import { of, toArray, zip } from 'rxjs';
-import { model } from '@formily/reactive';
-import { observer } from '@formily/react';
-import { StatisticCard } from '@ant-design/pro-card';
-import { Radio } from 'antd';
-import type { DurationInputArg1, DurationInputArg2 } from 'moment';
-import moment from 'moment';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-type DeviceMessage = {
-  chartData: any[];
-  startDate: string;
-  endDate: string;
-  timeType: string;
-  dateType: '1d' | '1h' | '7d' | '30d';
-};
-const DateFormat = 'YYYY-MM-DD HH:mm:ss';
-
-const DeviceMessageModel = model<DeviceMessage>({
-  chartData: [],
-  startDate: moment(new Date()).format(DateFormat),
-  endDate: moment(new Date()).format(DateFormat),
-  timeType: '1m',
-  dateType: '1h',
-});
-
-const DeviceMessageChart = observer(() => {
-  const intl = useIntl();
-  const gatewayMonitor = (from: string, to: string, time: string) => {
-    const params = [
-      {
-        dashboard: 'gatewayMonitor',
-        object: 'deviceGateway',
-        measurement: 'received_message',
-        dimension: 'agg',
-        group: 'sameDay',
-        params: {
-          time,
-          limit: 60,
-          format: 'HH时mm分',
-          from,
-          to,
-        },
-      },
-    ];
-
-    service
-      .getMulti(params)
-      .pipe(
-        mergeMap(
-          (item) =>
-            item.result as {
-              group: string;
-              data: {
-                value: number;
-                timeString: string;
-                timestamp: number;
-              };
-            }[],
-        ),
-        groupBy((item) => item.group),
-        mergeMap((group$) =>
-          zip(
-            of(group$.key),
-            group$.pipe(
-              map((item) => ({
-                type: '消息量',
-                year: item.data.timeString,
-                value: item.data.value,
-              })),
-              toArray(),
-            ),
-          ),
-        ),
-      )
-      .subscribe((data) => {
-        // eslint-disable-next-line prefer-destructuring
-        DeviceMessageModel.chartData = data[1];
-      });
-  };
-
-  const SubtractDate = (startDate: string, amount: DurationInputArg1, unit: DurationInputArg2) =>
-    moment(startDate).subtract(amount, unit).format(DateFormat);
-
-  const onDateTypeChange = (type: '1d' | '1h' | '7d' | '30d') => {
-    DeviceMessageModel.dateType = type;
-    const to = moment(new Date()).format(DateFormat);
-    switch (type) {
-      case '1h':
-        DeviceMessageModel.startDate = SubtractDate(to, 1, 'hours');
-        DeviceMessageModel.timeType = '1m';
-        break;
-      case '1d':
-        DeviceMessageModel.startDate = SubtractDate(to, 1, 'days');
-        DeviceMessageModel.timeType = '24m';
-        break;
-      case '7d':
-        DeviceMessageModel.startDate = SubtractDate(to, 7, 'days');
-        DeviceMessageModel.timeType = '168m';
-        break;
-      case '30d':
-        DeviceMessageModel.startDate = SubtractDate(to, 30, 'days');
-        DeviceMessageModel.timeType = '12h';
-        break;
-      default:
-        break;
-    }
-    gatewayMonitor(
-      DeviceMessageModel.startDate,
-      DeviceMessageModel.endDate,
-      DeviceMessageModel.timeType,
-    );
-  };
-  useEffect(() => {
-    onDateTypeChange('1h');
-  }, []);
-
-  const config = {
-    data: DeviceMessageModel.chartData,
-    xField: 'year',
-    yField: 'value',
-    xAxis: {
-      range: [0, 1],
-      tickCount: 5,
-    },
-    slider: {
-      start: 0.1,
-      end: 0.9,
-      trendCfg: { isArea: true },
-    },
-    areaStyle: function areaStyle() {
-      return { fill: 'l(270) 0:#ffffff 0.5:#7ec2f3 1:#1890ff' };
-    },
-  };
-  const options = [
-    {
-      label: intl.formatMessage({
-        id: 'pages.analysis.deviceMessage.1hour',
-        defaultMessage: '1小时',
-      }),
-      value: '1h',
-    },
-    {
-      label: intl.formatMessage({
-        id: 'pages.analysis.deviceMessage.1day',
-        defaultMessage: '1天',
-      }),
-      value: '1d',
-    },
-    {
-      label: intl.formatMessage({
-        id: 'pages.analysis.deviceMessage.7days',
-        defaultMessage: '7天',
-      }),
-      value: '7d',
-    },
-    {
-      label: intl.formatMessage({
-        id: 'pages.analysis.deviceMessage.30days',
-        defaultMessage: '30天',
-      }),
-      value: '30d',
-    },
-  ];
-  return (
-    <StatisticCard
-      title={intl.formatMessage({
-        id: 'pages.analysis.deviceMessage',
-        defaultMessage: '设备消息',
-      })}
-      extra={
-        <Radio.Group
-          options={options}
-          optionType="button"
-          size="small"
-          value={DeviceMessageModel.dateType}
-          onChange={(e) => onDateTypeChange(e.target.value)}
-        />
-      }
-      chart={<Area {...config} />}
-    />
-  );
-});
-export default DeviceMessageChart;

+ 0 - 45
src/pages/Analysis/Jvm/index.tsx

@@ -1,45 +0,0 @@
-import { Gauge } from '@ant-design/charts';
-import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
-import WebsocketTopic from '@/utils/topic';
-import { useEffect, useState } from 'react';
-import type { WebsocketPayload } from '@/hooks/websocket/typings';
-
-const Jvm = () => {
-  const [subscribeTopic] = useSendWebsocketMessage();
-  const [value, setValue] = useState<number>(0);
-  useEffect(() => {
-    const JvmRealTime = subscribeTopic?.(
-      WebsocketTopic.JVMRealTime.id,
-      WebsocketTopic.JVMRealTime.topic,
-      { params: { history: 1 } },
-    )?.subscribe((data: WebsocketPayload) => {
-      // +0.01为了解决0.00图表异常
-      setValue((((data.payload.value as Record<string, any>).usage as number) + 0.01) / 100);
-    });
-    return () => JvmRealTime?.unsubscribe();
-  }, []);
-  const config = {
-    width: 200,
-    height: 200,
-
-    range: {
-      ticks: [0, 1 / 3, 2 / 3, 1],
-      color: ['#F4664A', '#FAAD14', '#30BF78'],
-    },
-    indicator: {
-      pointer: { style: { stroke: '#D0D0D0' } },
-      pin: { style: { stroke: '#D0D0D0' } },
-    },
-    statistic: {
-      content: {
-        style: {
-          fontSize: '36px',
-          lineHeight: '36px',
-        },
-      },
-    },
-  };
-  return <Gauge {...config} percent={value} />;
-};
-
-export default Jvm;

+ 0 - 128
src/pages/Analysis/MessageChart/index.tsx

@@ -1,128 +0,0 @@
-import { Column } from '@ant-design/charts';
-import moment from 'moment';
-import { useEffect } from 'react';
-import { service } from '@/pages/Analysis';
-import type { ColumnConfig } from '@ant-design/plots/es/components/column';
-
-const calculationDate = () => {
-  const dd = new Date();
-  dd.setDate(dd.getDate() - 30);
-  const y = dd.getFullYear();
-  const m = dd.getMonth() + 1 < 10 ? `0${dd.getMonth() + 1}` : dd.getMonth() + 1;
-  const d = dd.getDate() < 10 ? `0${dd.getDate()}` : dd.getDate();
-  return `${y}-${m}-${d} 00:00:00`;
-};
-
-const MessageChart = () => {
-  const list = [
-    {
-      dashboard: 'device',
-      object: 'message',
-      measurement: 'quantity',
-      dimension: 'agg',
-      group: 'sameDay',
-      params: {
-        time: '1d',
-        format: 'yyyy-MM-dd',
-      },
-    },
-    {
-      dashboard: 'device',
-      object: 'message',
-      measurement: 'quantity',
-      dimension: 'agg',
-      group: 'sameMonth',
-      params: {
-        limit: 30,
-        time: '1d',
-        format: 'yyyy-MM-dd',
-        from: calculationDate(),
-        to: `${moment(new Date()).format('YYYY-MM-DD')} 23:59:59`,
-      },
-    },
-    {
-      dashboard: 'device',
-      object: 'message',
-      measurement: 'quantity',
-      dimension: 'agg',
-      group: 'month',
-      params: {
-        time: '1M',
-        format: 'yyyy-MM-dd',
-        from: calculationDate(),
-        to: `${moment(new Date()).format('YYYY-MM-DD')} 23:59:59`,
-      },
-    },
-  ];
-
-  useEffect(() => {
-    service.getMulti(list).subscribe((data) => {
-      console.log(data);
-    });
-  }, []);
-
-  const data = [
-    {
-      type: '1-3秒',
-      value: 0.16,
-    },
-    {
-      type: '4-10秒',
-      value: 0.125,
-    },
-    {
-      type: '11-30秒',
-      value: 0.24,
-    },
-    {
-      type: '31-60秒',
-      value: 0.19,
-    },
-    {
-      type: '1-3分',
-      value: 0.22,
-    },
-    {
-      type: '3-10分',
-      value: 0.05,
-    },
-    {
-      type: '10-30分',
-      value: 0.01,
-    },
-    {
-      type: '30+分',
-      value: 0.015,
-    },
-  ];
-
-  const paletteSemanticRed = '#F4664A';
-  const brandColor = '#5B8FF9';
-  const config: ColumnConfig = {
-    data,
-    xField: 'type',
-    yField: 'value',
-    seriesField: '',
-    color: function color(_ref: any) {
-      const { type } = _ref;
-      if (type === '10-30分' || type === '30+分') {
-        return paletteSemanticRed;
-      }
-      return brandColor;
-    },
-    width: 200,
-    height: 200,
-    label: {
-      offset: 10,
-    },
-    legend: false,
-    xAxis: {
-      label: {
-        autoHide: true,
-        autoRotate: false,
-      },
-    },
-  };
-  return <Column {...config} />;
-};
-export default MessageChart;

+ 0 - 59
src/pages/Analysis/index.tsx

@@ -1,59 +0,0 @@
-import { StatisticCard } from '@ant-design/pro-card';
-import RcResizeObserver from 'rc-resize-observer';
-import { useState } from 'react';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import CPU from '@/pages/Analysis/CPU';
-import Jvm from '@/pages/Analysis/Jvm';
-import DeviceMessageChart from '@/pages/Analysis/DeviceMessage';
-import DeviceChart from '@/pages/Analysis/DeviceChart';
-import MessageChart from '@/pages/Analysis/MessageChart';
-import Service from '@/pages/Analysis/service';
-
-const { Divider } = StatisticCard;
-
-export const service = new Service();
-const Analysis = () => {
-  const [responsive, setResponsive] = useState(false);
-  const intl = useIntl();
-
-  return (
-    <RcResizeObserver
-      key="resize-observer"
-      onResize={(offset) => {
-        setResponsive(offset.width < 596);
-      }}
-    >
-      <StatisticCard.Group direction={responsive ? 'column' : 'row'}>
-        <StatisticCard
-          title={intl.formatMessage({
-            id: 'pages.analysis.cpu',
-            defaultMessage: 'CPU使用率',
-          })}
-          chart={<CPU />}
-        />
-        <Divider type={responsive ? 'horizontal' : 'vertical'} />
-        <StatisticCard
-          title={intl.formatMessage({
-            id: 'pages.analysis.jvm',
-            defaultMessage: 'JVM内存',
-          })}
-          chart={<Jvm />}
-        />
-        <Divider type={responsive ? 'horizontal' : 'vertical'} />
-        <StatisticCard
-          title={intl.formatMessage({
-            id: 'pages.analysis.volume',
-            defaultMessage: '今日设备消息量',
-          })}
-          chart={<MessageChart />}
-        />
-        <Divider type={responsive ? 'horizontal' : 'vertical'} />
-        <DeviceChart />
-      </StatisticCard.Group>
-      <Divider type={responsive ? 'horizontal' : 'vertical'} />
-
-      <DeviceMessageChart />
-    </RcResizeObserver>
-  );
-};
-export default Analysis;

+ 0 - 19
src/pages/Analysis/service.ts

@@ -1,19 +0,0 @@
-import BaseService from '@/utils/BaseService';
-import { request } from 'umi';
-import SystemConst from '@/utils/const';
-import Token from '@/utils/token';
-import { defer, from } from 'rxjs';
-
-class Service extends BaseService<unknown> {
-  public getMulti = (data: unknown) =>
-    defer(() =>
-      from(
-        request(`${SystemConst.API_BASE}/dashboard/_multi?:X_Access_Token=${Token.get()}`, {
-          method: 'POST',
-          data,
-        }),
-      ),
-    );
-}
-
-export default Service;

+ 0 - 140
src/pages/cloud/Aliyun/index.tsx

@@ -1,140 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import BaseCrud from '@/components/BaseCrud';
-import { Popconfirm, Tooltip } from 'antd';
-import {
-  CloseCircleOutlined,
-  EditOutlined,
-  EyeOutlined,
-  PlayCircleOutlined,
-} from '@ant-design/icons';
-import { CurdModel } from '@/components/BaseCrud/model';
-import type { AliyunItem } from '@/pages/cloud/Aliyun/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import { onlyMessage } from '@/utils/util';
-
-export const service = new BaseService<AliyunItem>('device/aliyun/bridge');
-
-const stateIconMap = {
-  enabled: <CloseCircleOutlined />,
-  disabled: <PlayCircleOutlined />,
-};
-
-const Aliyun = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-  const columns: ProColumns<AliyunItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-      align: 'center',
-      dataIndex: 'name',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.description',
-        defaultMessage: '说明',
-      }),
-      align: 'center',
-      dataIndex: 'description',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      dataIndex: 'state',
-      render: (value: any) => value.text,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.detail',
-              defaultMessage: '查看',
-            })}
-            key={'detail'}
-          >
-            <EyeOutlined />
-          </Tooltip>
-        </a>,
-        <a key="editable" onClick={() => CurdModel.update(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a key="status">
-          <Popconfirm
-            title={intl.formatMessage({
-              id: `pages.data.option.${
-                record.state.value === 'disabled' ? 'enabled' : 'disabled'
-              }.tips`,
-              defaultMessage: `确认${record.state.value === 'disabled' ? '启' : '禁'}用?`,
-            })}
-            onConfirm={async () => {
-              // const state = record.state.value === 'disabled' ? 'enable' : 'disable';
-              // await service.changeStatus(record.id, state);
-              onlyMessage(
-                intl.formatMessage({
-                  id: 'pages.data.option.success',
-                  defaultMessage: '操作成功!',
-                }),
-              );
-              actionRef.current?.reload();
-            }}
-          >
-            <Tooltip
-              title={intl.formatMessage({
-                id: `pages.data.option.${
-                  record.state.value === 'enabled' ? 'disabled' : 'enabled'
-                }`,
-                defaultMessage: record.state.text,
-              })}
-            >
-              {stateIconMap[record.state.value]}
-            </Tooltip>
-          </Popconfirm>
-        </a>,
-      ],
-    },
-  ];
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud<AliyunItem>
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.cloud.aliyun',
-          defaultMessage: '阿里云',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Aliyun;

+ 0 - 22
src/pages/cloud/Aliyun/typings.d.ts

@@ -1,22 +0,0 @@
-import type { BaseItem, State } from '@/utils/typings';
-
-type AliyunItem = {
-  accessConfig: {
-    bridgeDeviceName: string;
-    bridgeDeviceSecret: string;
-    bridgeProductKey: string;
-    http2Endpoint: string;
-    serverId: string;
-  };
-  bridgeConfigs: {
-    accessKeyId: string;
-    accessSecret: string;
-    apiEndpoint: string;
-    authEndpoint: string;
-    productKey: string;
-    regionId: string;
-  };
-  codecProtocol: string;
-  createTime: number;
-  state: State;
-} & BaseItem;

+ 0 - 124
src/pages/cloud/Ctwing/index.tsx

@@ -1,124 +0,0 @@
-import BaseCrud from '@/components/BaseCrud';
-import { CurdModel } from '@/components/BaseCrud/model';
-import BaseService from '@/utils/BaseService';
-import { CloseCircleOutlined, EditOutlined, PlayCircleOutlined } from '@ant-design/icons';
-import { PageContainer } from '@ant-design/pro-layout';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Popconfirm, Tooltip } from 'antd';
-import { useRef } from 'react';
-import type { CtwingItem } from '@/pages/cloud/Ctwing/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import { onlyMessage } from '@/utils/util';
-
-export const service = new BaseService<CtwingItem>('ctwing/product');
-
-const stateIconMap = {
-  enabled: <CloseCircleOutlined />,
-  disabled: <PlayCircleOutlined />,
-};
-
-const Ctwing = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-  const columns: ProColumns<CtwingItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-      align: 'center',
-      dataIndex: 'name',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      dataIndex: 'state',
-      render: (value: any) => value.text,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.description',
-        defaultMessage: '说明',
-      }),
-      align: 'center',
-      dataIndex: 'description',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a key="editable" onClick={() => CurdModel.update(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a key="status">
-          <Popconfirm
-            title={intl.formatMessage({
-              id: `pages.data.option.${
-                record.state.value === 'disabled' ? 'enabled' : 'disabled'
-              }.tips`,
-              defaultMessage: `确认${record.state.value === 'disabled' ? '启' : '禁'}用?`,
-            })}
-            onConfirm={async () => {
-              // const state = record.state.value === 'disabled' ? 'enable' : 'disable';
-              // await service.changeStatus(record.id, state);
-              onlyMessage(
-                intl.formatMessage({
-                  id: 'pages.data.option.success',
-                  defaultMessage: '操作成功!',
-                }),
-              );
-              actionRef.current?.reload();
-            }}
-          >
-            <Tooltip
-              title={intl.formatMessage({
-                id: `pages.data.option.${
-                  record.state.value === 'enabled' ? 'disabled' : 'enabled'
-                }`,
-                defaultMessage: record.state.text,
-              })}
-            >
-              {stateIconMap[record.state.value]}
-            </Tooltip>
-          </Popconfirm>
-        </a>,
-      ],
-    },
-  ];
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud<CtwingItem>
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.cloud.ctwing',
-          defaultMessage: 'ctwing',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Ctwing;

+ 0 - 9
src/pages/cloud/Ctwing/typings.d.ts

@@ -1,9 +0,0 @@
-import type { BaseItem, State } from '@/utils/typings';
-
-type CtwingItem = {
-  apiAddress: string;
-  appKey: string;
-  appSecret: string;
-  masterKey: string;
-  state: State;
-} & BaseItem;

+ 0 - 11
src/pages/cloud/DuerOS/Save/index.tsx

@@ -1,11 +0,0 @@
-import { Modal } from 'antd';
-
-const Save = () => {
-  return (
-    <Modal title="新增" visible>
-      。。。
-    </Modal>
-  );
-};
-
-export default Save;

+ 0 - 158
src/pages/cloud/DuerOS/index.tsx

@@ -1,158 +0,0 @@
-import BaseService from '@/utils/BaseService';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { PageContainer } from '@ant-design/pro-layout';
-import { useRef, useState } from 'react';
-import { Space, Tooltip } from 'antd';
-import { DeleteOutlined, EditOutlined, MinusOutlined, PlusOutlined } from '@ant-design/icons';
-import type { DuerOSItem } from '@/pages/cloud/DuerOS/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import SearchComponent from '@/components/SearchComponent';
-import { PermissionButton, ProTableCard } from '@/components';
-import DuerOSCard from '@/components/ProTableCard/CardItems/duerOs';
-
-export const service = new BaseService<DuerOSItem>('dueros/product');
-const DuerOS = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-  const columns: ProColumns<DuerOSItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-      dataIndex: 'name',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.cloud.duerOS.applianceType',
-        defaultMessage: '设备类型',
-      }),
-      dataIndex: 'applianceType',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.cloud.duerOS.manufacturerName',
-        defaultMessage: '厂家名称',
-      }),
-      dataIndex: 'manufacturerName',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.cloud.duerOS.version',
-        defaultMessage: '动作数量',
-      }),
-      dataIndex: 'version',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a
-          onClick={() => {
-            console.log(record);
-          }}
-        >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-  // const schema = {};
-
-  const [param, setParam] = useState({});
-  return (
-    <PageContainer>
-      <SearchComponent
-        field={columns}
-        onSearch={(data) => {
-          actionRef.current?.reset?.();
-          setParam(data);
-        }}
-      />
-      <ProTableCard<any>
-        actionRef={actionRef}
-        rowKey="id"
-        search={false}
-        params={param}
-        columns={columns}
-        columnEmptyText={''}
-        request={(params) =>
-          service.query({ ...params, sorts: [{ name: 'createTime', order: 'desc' }] })
-        }
-        cardRender={(record) => (
-          <DuerOSCard
-            {...record}
-            action={[
-              <PermissionButton>
-                <EditOutlined />
-                编辑
-              </PermissionButton>,
-              <PermissionButton
-                type="link"
-                popConfirm={{
-                  disabled: record.state?.value !== 'disabled',
-                  title: '确认删除?',
-                  onConfirm: async () => {
-                    await service.remove(record.id);
-                    actionRef.current?.reset?.();
-                  },
-                }}
-                isPermission={true}
-                key="delete"
-              >
-                <DeleteOutlined />
-              </PermissionButton>,
-            ]}
-          />
-        )}
-        headerTitle={
-          <Space>
-            <PermissionButton
-              isPermission={true}
-              onClick={() => {
-                // setCurrent(undefined);
-                // setVisible(true);
-              }}
-              key="button"
-              icon={<PlusOutlined />}
-              type="primary"
-            >
-              {intl.formatMessage({
-                id: 'pages.data.option.add',
-                defaultMessage: '新增',
-              })}
-            </PermissionButton>
-          </Space>
-        }
-      />
-    </PageContainer>
-  );
-};
-export default DuerOS;

+ 0 - 45
src/pages/cloud/DuerOS/typings.d.ts

@@ -1,45 +0,0 @@
-import type { BaseItem } from '@/utils/typings';
-
-// type Action = {
-//   arg: unknown[];
-// } & BaseItem;
-//
-// type Mode = BaseItem;
-//
-// type Property = BaseItem;
-
-// type DuerOSItem = {
-//   actions?: Action[];
-//   modes?: Mode[];
-//   properties?: Property[];
-// } & BaseItem;
-
-type PropertyMapping = {
-  source: string;
-  target: string[];
-};
-
-type ActionMapping = {
-  action: string;
-  actionType: string;
-  command: {
-    message: Record<string, any>;
-    messageType: string;
-  };
-};
-type DuerOSItem = {
-  productName?: string;
-  version: number;
-  manufacturerName: string;
-  autoReportProperty: boolean;
-  applianceType: {
-    text: string;
-    value: string;
-  };
-  state?: {
-    text: string;
-    value: string;
-  };
-  actionMappings: ActionMapping[];
-  propertyMappings: PropertyMapping[];
-} & BaseItem;

+ 0 - 136
src/pages/cloud/Onenet/index.tsx

@@ -1,136 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Popconfirm, Tooltip } from 'antd';
-import {
-  CloseCircleOutlined,
-  EditOutlined,
-  MinusOutlined,
-  PlayCircleOutlined,
-} from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import { CurdModel } from '@/components/BaseCrud/model';
-import type { OnenetItem } from '@/pages/cloud/Onenet/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import { onlyMessage } from '@/utils/util';
-
-export const service = new BaseService<OnenetItem>('one-net/product');
-
-const stateIconMap = {
-  enabled: <CloseCircleOutlined />,
-  disabled: <PlayCircleOutlined />,
-};
-
-const Onenet = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-  const columns: ProColumns<OnenetItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-      align: 'center',
-      dataIndex: 'name',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      align: 'center',
-      dataIndex: 'state.text',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.description',
-        defaultMessage: '说明',
-      }),
-      align: 'center',
-      dataIndex: 'description',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a key="editable" onClick={() => CurdModel.update(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a key="status">
-          <Popconfirm
-            title={intl.formatMessage({
-              id: `pages.data.option.${
-                record.state.value === 'disabled' ? 'enabled' : 'disabled'
-              }.tips`,
-              defaultMessage: `确认${record.state.value === 'disabled' ? '启' : '禁'}用?`,
-            })}
-            onConfirm={async () => {
-              onlyMessage(
-                intl.formatMessage({
-                  id: 'pages.data.option.success',
-                  defaultMessage: '操作成功!',
-                }),
-              );
-              actionRef.current?.reload();
-            }}
-          >
-            <Tooltip
-              title={intl.formatMessage({
-                id: `pages.data.option.${
-                  record.state.value === 'enabled' ? 'disabled' : 'enabled'
-                }`,
-                defaultMessage: record.state.text,
-              })}
-            >
-              {stateIconMap[record.state.value]}
-            </Tooltip>
-          </Popconfirm>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-  const schema = {};
-  return (
-    <PageContainer>
-      <BaseCrud<OnenetItem>
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.cloud.onenet',
-          defaultMessage: 'Onenet',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Onenet;

+ 0 - 10
src/pages/cloud/Onenet/typings.d.ts

@@ -1,10 +0,0 @@
-import type { BaseItem, State } from '@/utils/typings';
-
-type OnenetItem = {
-  aesKey: string;
-  apiAddress: string;
-  apiKey: string;
-  description: string;
-  state: State;
-  validateToken: string;
-} & BaseItem;

+ 0 - 42
src/pages/device/Command/cat/index.tsx

@@ -1,42 +0,0 @@
-import { Input, Modal } from 'antd';
-import type { CommandItem } from '@/pages/device/Command/typings';
-import MonacoEditor from 'react-monaco-editor';
-
-interface Props {
-  close: () => void;
-  data: CommandItem | undefined;
-  visible: boolean;
-}
-
-const Cat = (props: Props) => {
-  const { close, data, visible } = props;
-  return (
-    <Modal
-      maskClosable={false}
-      width="40vw"
-      visible={visible}
-      onCancel={() => close()}
-      footer={null}
-      title="查看指令"
-    >
-      下发指令:
-      <MonacoEditor
-        height={300}
-        language={'json'}
-        editorDidMount={(editor) => {
-          editor.getAction('editor.action.formatDocument').run();
-          editor.onDidContentSizeChange?.(() => {
-            editor.getAction('editor.action.formatDocument').run();
-            // .finally(() => {
-            //   editor.updateOptions({ readOnly: true });
-            // });
-          });
-        }}
-        value={JSON.stringify(data?.downstream)}
-      />
-      回复结果:
-      <Input.TextArea rows={3} />
-    </Modal>
-  );
-};
-export default Cat;

+ 0 - 260
src/pages/device/Command/create/index.tsx

@@ -1,260 +0,0 @@
-import type { Field } from '@formily/core';
-import { createForm, onFieldValueChange } from '@formily/core';
-import { createSchemaField } from '@formily/react';
-import { ArrayTable, Form, FormItem, Input, Select, Space } from '@formily/antd';
-import { action } from '@formily/reactive';
-import type { ISchema } from '@formily/json-schema';
-import { service } from '@/pages/device/Command';
-import { Modal } from 'antd';
-import FSelectDevices from '@/components/FSelectDevices';
-import { useRef } from 'react';
-import type { DeviceMetadata, ProductItem } from '@/pages/device/Product/typings';
-import { onlyMessage } from '@/utils/util';
-
-interface Props {
-  close: () => void;
-  visible: boolean;
-}
-
-const Create = (props: Props) => {
-  const { close, visible } = props;
-  const products = useRef<ProductItem[]>([]);
-
-  const metadataRef = useRef<DeviceMetadata>();
-  const form = createForm({
-    validateFirst: true,
-    initialValues: {},
-    effects() {
-      onFieldValueChange('productId', (field, f) => {
-        const value = (field as Field).value;
-        const product = products.current.find((item) => item.id === value);
-        const deviceId = field.query('deviceId').take();
-        deviceId.setComponentProps({
-          productId: value,
-        });
-
-        const metadata = JSON.parse(product?.metadata as string) as DeviceMetadata;
-        metadataRef.current = metadata;
-        f.setFieldState(field.query('message.properties.key'), (state) => {
-          state.dataSource = metadata?.properties.map((item) => ({
-            label: item.name,
-            value: item.id,
-          }));
-        });
-        f.setFieldState(field.query('message.functionId'), (state) => {
-          state.dataSource = metadata?.functions.map((item) => ({
-            label: item.name,
-            value: item.id,
-          }));
-        });
-      });
-      onFieldValueChange('message.functionId', (field, f1) => {
-        const value = (field as Field).value;
-        const func = metadataRef.current?.functions.find((item) => item.id === value)?.inputs;
-        f1.setFieldState(field.query('message.inputs'), (state) => {
-          state.value = func?.map((item) => ({
-            key: `${item.name}(${item.id})`,
-            value: null,
-            name: item.id,
-          }));
-        });
-      });
-    },
-  });
-
-  const SchemaField = createSchemaField({
-    components: {
-      FormItem,
-      Input,
-      Select,
-      FSelectDevices,
-      ArrayTable,
-      Space,
-    },
-  });
-
-  const useAsyncDataSource = (services: (arg0: Field) => Promise<any>) => (field: Field) => {
-    field.loading = true;
-    services(field).then(
-      action.bound!((data: any) => {
-        products.current = data.result;
-        field.dataSource = data.result.map((item: any) => ({ label: item.name, value: item.id }));
-        field.loading = false;
-      }),
-    );
-  };
-
-  const loadData = async () => service.queryProduct();
-
-  const schema: ISchema = {
-    type: 'object',
-    properties: {
-      productId: {
-        title: '产品',
-        'x-decorator': 'FormItem',
-        'x-component': 'Select',
-        'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
-      },
-      deviceId: {
-        title: '设备',
-        'x-decorator': 'FormItem',
-        'x-component': 'FSelectDevices',
-        'x-component-props': {
-          type: 'multi',
-        },
-      },
-      message: {
-        type: 'object',
-        properties: {
-          messageType: {
-            title: '指令',
-            'x-decorator': 'FormItem',
-            'x-component': 'Select',
-            enum: [
-              { label: '读取属性', value: 'READ_PROPERTY' },
-              { label: '设置属性', value: 'WRITE_PROPERTY' },
-              { label: '调用功能', value: 'INVOKE_FUNCTION' },
-            ],
-          },
-          properties: {
-            type: 'object',
-            properties: {
-              key: {
-                title: '属性',
-                'x-decorator': 'FormItem',
-                'x-component': 'Select',
-                enum: [],
-                'x-reactions': {
-                  dependencies: ['..messageType'],
-                  fulfill: {
-                    state: {
-                      visible: "{{['READ_PROPERTY','WRITE_PROPERTY'].includes($deps[0])}}",
-                      componentProps: {
-                        mode: "{{$deps[0]==='READ_PROPERTY'&&'multiple'}}",
-                      },
-                    },
-                  },
-                },
-                'x-visible': false,
-              },
-              value: {
-                title: '设置值',
-                'x-component': 'Input',
-                'x-decorator': 'FormItem',
-                'x-reactions': {
-                  dependencies: ['..messageType'],
-                  fulfill: {
-                    state: {
-                      visible: "{{['WRITE_PROPERTY'].includes($deps[0])}}",
-                    },
-                  },
-                },
-                'x-visible': false,
-              },
-            },
-          },
-          functionId: {
-            title: '功能',
-            'x-decorator': 'FormItem',
-            'x-component': 'Select',
-            enum: [],
-            'x-reactions': {
-              dependencies: ['.messageType'],
-              fulfill: {
-                state: {
-                  visible: "{{['INVOKE_FUNCTION'].includes($deps[0])}}",
-                },
-              },
-            },
-            'x-visible': false,
-          },
-          inputs: {
-            title: '参数',
-            'x-decorator': 'FormItem',
-            'x-component': 'ArrayTable',
-            type: 'array',
-            items: {
-              type: 'object',
-              properties: {
-                column1: {
-                  type: 'void',
-                  'x-component': 'ArrayTable.Column',
-                  'x-component-props': { title: '键' },
-                  properties: {
-                    key: {
-                      type: 'string',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'Input',
-                      'x-read-only': true,
-                    },
-                  },
-                },
-                column2: {
-                  type: 'void',
-                  'x-component': 'ArrayTable.Column',
-                  'x-component-props': { title: '值' },
-                  properties: {
-                    value: {
-                      type: 'string',
-                      'x-decorator': 'FormItem',
-                      'x-component': 'Input',
-                    },
-                  },
-                },
-              },
-            },
-            'x-reactions': {
-              dependencies: ['.messageType'],
-              fulfill: {
-                state: {
-                  visible: "{{['INVOKE_FUNCTION'].includes($deps[0])}}",
-                },
-              },
-            },
-            'x-visible': false,
-          },
-        },
-      },
-    },
-  };
-
-  const sendCommand = async () => {
-    const values: Record<string, any> = await form.submit();
-    const type = values.message?.messageType;
-    switch (type) {
-      case 'READ_PROPERTY':
-        const property = values.message.properties.key;
-        values.message.properties = property;
-        break;
-      case 'WRITE_PROPERTY':
-        const key = values.message.properties.key;
-        const value = values.message.properties.value;
-        values.message.properties = { [key]: value };
-        break;
-      default:
-        break;
-    }
-    const resp = await service.task(values);
-    if (resp.status === 200) {
-      onlyMessage('操作成功');
-    } else {
-      onlyMessage('操作失败', 'error');
-    }
-    close();
-  };
-  return (
-    <Modal
-      maskClosable={false}
-      onOk={sendCommand}
-      onCancel={() => close()}
-      width="50vw"
-      visible={visible}
-      title="下发指令"
-    >
-      <Form form={form} labelCol={5} wrapperCol={16}>
-        <SchemaField schema={schema} scope={{ useAsyncDataSource, loadData }} />
-      </Form>
-    </Modal>
-  );
-};
-export default Create;

+ 0 - 219
src/pages/device/Command/index.tsx

@@ -1,219 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import ProTable from '@jetlinks/pro-table';
-import type { CommandItem } from '@/pages/device/Command/typings';
-import { Button, Tooltip } from 'antd';
-import moment from 'moment';
-import { EyeOutlined, PlusOutlined, SyncOutlined } from '@ant-design/icons';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import Service from '@/pages/device/Command/service';
-import Create from '@/pages/device/Command/create';
-import encodeQuery from '@/utils/encodeQuery';
-import { model } from '@formily/reactive';
-import { observer } from '@formily/react';
-import Cat from '@/pages/device/Command/cat';
-import { onlyMessage } from '@/utils/util';
-
-export const service = new Service('device/message/task');
-
-export const state = model<{
-  visible: boolean;
-  cat: boolean;
-  data?: CommandItem;
-}>({
-  visible: false,
-  cat: false,
-});
-const Command = observer(() => {
-  const actionRef = useRef<ActionType>();
-  const intl = useIntl();
-
-  const columns: ProColumns<CommandItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.deviceId',
-        defaultMessage: '设备ID',
-      }),
-      dataIndex: 'deviceId',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.deviceName',
-        defaultMessage: '设备名称',
-      }),
-      dataIndex: 'deviceName',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.device.command.type',
-        defaultMessage: '指令类型',
-      }),
-      dataIndex: 'messageType',
-      filters: [
-        {
-          text: intl.formatMessage({
-            id: 'pages.device.command.type.readProperty',
-            defaultMessage: '读取属性',
-          }),
-          value: 'READ_PROPERTY',
-        },
-        {
-          text: intl.formatMessage({
-            id: 'pages.device.command.type.writeProperty',
-            defaultMessage: '设置属性',
-          }),
-          value: 'WRITE_PROPERTY',
-        },
-        {
-          text: intl.formatMessage({
-            id: 'pages.device.command.type.invokeFunction',
-            defaultMessage: '调用属性',
-          }),
-          value: 'INVOKE_FUNCTION',
-        },
-      ],
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      dataIndex: 'state',
-      filters: [
-        {
-          text: intl.formatMessage({
-            id: 'pages.device.command.status.wait',
-            defaultMessage: '等待中',
-          }),
-          value: 'wait',
-        },
-        {
-          text: intl.formatMessage({
-            id: 'pages.device.command.status.sendError',
-            defaultMessage: '发送失败',
-          }),
-          value: 'sendError',
-        },
-        {
-          text: intl.formatMessage({
-            id: 'pages.device.command.status.success',
-            defaultMessage: '发送成功',
-          }),
-          value: 'success',
-        },
-      ],
-      render: (value: any) => value.text,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.device.command.lastError',
-        defaultMessage: '错误信息',
-      }),
-      dataIndex: 'lastError',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.device.command.sendTime',
-        defaultMessage: '发送时间',
-      }),
-      dataIndex: 'sendTimestamp',
-      render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
-      sorter: true,
-      defaultSortOrder: 'descend',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a
-          key="cat"
-          onClick={() => {
-            state.cat = true;
-            state.data = record;
-          }}
-        >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.detail',
-              defaultMessage: '查看',
-            })}
-            key="detail"
-          >
-            <EyeOutlined />
-          </Tooltip>
-        </a>,
-        record.state.value !== 'wait' && (
-          <a
-            key="action"
-            onClick={async () => {
-              const resp = await service.resend(encodeQuery({ terms: { id: record.id } }));
-              if (resp.status === 200) {
-                onlyMessage('操作成功!');
-              } else {
-                onlyMessage('操作失败!', 'error');
-              }
-            }}
-          >
-            <Tooltip
-              title={intl.formatMessage({
-                id: 'pages.device.command.option.send',
-                defaultMessage: '重新发送',
-              })}
-            >
-              <SyncOutlined />
-            </Tooltip>
-          </a>
-        ),
-      ],
-    },
-  ];
-
-  return (
-    <PageContainer>
-      <ProTable<CommandItem>
-        toolBarRender={() => [
-          <Button
-            onClick={() => {
-              state.visible = true;
-            }}
-            key="button"
-            icon={<PlusOutlined />}
-            type="primary"
-          >
-            下发指令
-          </Button>,
-        ]}
-        request={async (params) => service.query(params)}
-        columns={columns}
-        actionRef={actionRef}
-        rowKey="id"
-        columnEmptyText={''}
-      />
-      <Create
-        visible={state.visible}
-        close={() => {
-          state.visible = false;
-        }}
-      />
-      <Cat
-        close={() => {
-          state.cat = false;
-        }}
-        data={state.data}
-        visible={state.cat}
-      />
-    </PageContainer>
-  );
-});
-export default Command;

+ 0 - 23
src/pages/device/Command/service.ts

@@ -1,23 +0,0 @@
-import BaseService from '@/utils/BaseService';
-import { request } from '@@/plugin-request/request';
-import type { CommandItem } from '@/pages/device/Command/typings';
-import SystemConst from '@/utils/const';
-
-class Service extends BaseService<CommandItem> {
-  queryProduct = () =>
-    request(`/${SystemConst.API_BASE}/device/product/_query/no-paging?paging=false`);
-
-  task = (data: Record<string, unknown>) =>
-    request(`/${SystemConst.API_BASE}/device/message/task`, {
-      method: 'POST',
-      data,
-    });
-
-  resend = (data: Record<string, unknown>) =>
-    request(`/${SystemConst.API_BASE}/device/message/task/state/wait`, {
-      method: 'PUT',
-      data,
-    });
-}
-
-export default Service;

+ 0 - 28
src/pages/device/Command/typings.d.ts

@@ -1,28 +0,0 @@
-export type CommandItem = {
-  id: string;
-  deviceId: string;
-  deviceName: string;
-  lastError: string;
-  lastErrorCode: string;
-  maxRetryTimes: number;
-  messageId: string;
-  messageType: string;
-  productId: string;
-  replyTimestamp: number;
-  retryTimes: number;
-  sendTimestamp: number;
-  serverId: string;
-  state: {
-    text: string;
-    value: string;
-  };
-  downstream: {
-    deviceId: string;
-    functionId: string;
-    headers: Record<string, any>;
-    inputs: Record<string, any>[];
-    messageId: string;
-    messageType: string;
-    timestamp: number;
-  };
-};

+ 0 - 508
src/pages/device/Instance/Detail/MetadataLog/Property/index copy.tsx

@@ -1,508 +0,0 @@
-import { InstanceModel, service } from '@/pages/device/Instance';
-import { useParams } from 'umi';
-import { DatePicker, Modal, Radio, Select, Space, Table, Tabs, Tooltip as ATooltip } from 'antd';
-import type { PropertyMetadata } from '@/pages/device/Product/typings';
-import encodeQuery from '@/utils/encodeQuery';
-import { useEffect, useState } from 'react';
-import moment from 'moment';
-import { Axis, Chart, Legend, LineAdvance, Point, Slider, Tooltip } from 'bizcharts';
-import FileComponent from '../../Running/Property/FileComponent';
-import { DownloadOutlined, SearchOutlined } from '@ant-design/icons';
-import Detail from './Detail';
-import AMap from './AMap';
-
-interface Props {
-  close: () => void;
-  data: Partial<PropertyMetadata>;
-}
-
-const PropertyLog = (props: Props) => {
-  const params = useParams<{ id: string }>();
-  const { close, data } = props;
-  const list = ['int', 'float', 'double', 'long'];
-  const [dataSource, setDataSource] = useState<any>({});
-  const [start, setStart] = useState<number>(moment().startOf('day').valueOf());
-  const [end, setEnd] = useState<number>(new Date().getTime());
-  const [radioValue, setRadioValue] = useState<undefined | 'today' | 'week' | 'month'>('today');
-  const [dateValue, setDateValue] = useState<any>(undefined);
-  const [chartsList, setChartsList] = useState<any>([]);
-  const [cycle, setCycle] = useState<string>(
-    list.includes(data.valueType?.type || '') ? '*' : '1m',
-  );
-  const [agg, setAgg] = useState<string>('AVG');
-  const [tab, setTab] = useState<string>('table');
-  const [detailVisible, setDetailVisible] = useState<boolean>(false);
-  const [current, setCurrent] = useState<any>('');
-
-  const [geoList, setGeoList] = useState<any>({});
-
-  const columns = [
-    {
-      title: '时间',
-      dataIndex: 'timestamp',
-      key: 'timestamp',
-      ellipsis: true,
-      render: (text: any) => <span>{text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : ''}</span>,
-    },
-    {
-      title: <span>{data.valueType?.type !== 'file' ? '自定义属性' : '文件内容'}</span>,
-      dataIndex: 'value',
-      key: 'value',
-      ellipsis: true,
-      render: (text: any, record: any) => (
-        <FileComponent type="table" value={{ formatValue: record.value }} data={data} />
-      ),
-    },
-    {
-      title: '操作',
-      dataIndex: 'action',
-      key: 'action',
-      render: (text: any, record: any) => (
-        <a>
-          {data.valueType?.type === 'file' && data?.valueType?.fileType == 'url' ? (
-            <ATooltip title="下载">
-              <DownloadOutlined
-                onClick={() => {
-                  const type = (record?.value || '').split('.').pop();
-                  const downloadUrl = record.value;
-                  const downNode = document.createElement('a');
-                  downNode.href = downloadUrl;
-                  downNode.target = '_blank';
-                  downNode.download = `${InstanceModel.detail.name}-${data.name}${moment(
-                    new Date().getTime(),
-                  ).format('YYYY-MM-DD-HH-mm-ss')}.${type}`;
-                  downNode.style.display = 'none';
-                  document.body.appendChild(downNode);
-                  downNode.click();
-                  document.body.removeChild(downNode);
-                }}
-              />
-            </ATooltip>
-          ) : (
-            <SearchOutlined
-              onClick={() => {
-                setDetailVisible(true);
-                setCurrent(record.value);
-              }}
-            />
-          )}
-        </a>
-      ),
-    },
-  ];
-
-  const geoColumns = [
-    {
-      title: '时间',
-      dataIndex: 'timestamp',
-      key: 'timestamp',
-      render: (text: any) => <span>{text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : ''}</span>,
-    },
-    {
-      title: '位置',
-      dataIndex: 'value',
-      key: 'value',
-      render: (text: any, record: any) => (
-        <FileComponent type="table" value={{ formatValue: record.value }} data={data} />
-      ),
-    },
-  ];
-
-  const tabList = [
-    {
-      tab: '列表',
-      key: 'table',
-    },
-    {
-      tab: '图表',
-      key: 'charts',
-    },
-  ];
-
-  const handleSearch = (param: any, startTime?: number, endTime?: number) => {
-    service
-      .getPropertyData(
-        params.id,
-        encodeQuery({
-          ...param,
-          terms: {
-            property: data.id,
-            timestamp$BTW: startTime && endTime ? [startTime, endTime] : [],
-          },
-          sorts: { timestamp: 'desc' },
-        }),
-      )
-      .then((resp) => {
-        if (resp.status === 200) {
-          setDataSource(resp.result);
-        }
-      });
-  };
-
-  const queryChartsList = async (startTime?: number, endTime?: number) => {
-    const resp = await service.queryPropertieList(params.id, data.id || '', {
-      paging: false,
-      terms: [
-        {
-          column: 'timestamp$BTW',
-          value: startTime && endTime ? [startTime, endTime] : [],
-          type: 'and',
-        },
-      ],
-      sorts: [{ name: 'timestamp', order: 'asc' }],
-    });
-    if (resp.status === 200) {
-      const dataList: any[] = [];
-      resp.result.data.forEach((i: any) => {
-        dataList.push({
-          year: moment(i.timestamp).format('YYYY-MM-DD HH:mm:ss'),
-          value: i.value,
-          type: data?.name || '',
-        });
-      });
-      setChartsList(dataList);
-    }
-  };
-
-  const queryChartsAggList = async (datas: any) => {
-    const resp = await service.queryPropertieInfo(params.id, datas);
-    if (resp.status === 200) {
-      const dataList: any[] = [];
-      resp.result.forEach((i: any) => {
-        dataList.push({
-          ...i,
-          year: moment(i.time).format('YYYY-MM-DD HH:mm:ss'),
-          value: Number(i[data.id || '']),
-          type: data?.name || '',
-        });
-      });
-      setChartsList(dataList.reverse());
-    }
-  };
-
-  useEffect(() => {
-    setRadioValue('today');
-    setTab('table');
-    setStart(moment().startOf('day').valueOf());
-    setEnd(new Date().getTime());
-  }, []);
-
-  const scale = {
-    value: { min: 0 },
-    year: {
-      type: 'time',
-      mask: 'YYYY-MM-DD HH:mm:ss',
-      // max: end,
-      // min: start,
-    },
-  };
-
-  const renderComponent = (type: string) => {
-    switch (type) {
-      case 'table':
-        return (
-          <Table
-            size="small"
-            rowKey={'id'}
-            onChange={(page) => {
-              handleSearch(
-                {
-                  pageSize: page.pageSize,
-                  pageIndex: Number(page.current) - 1 || 0,
-                },
-                start,
-                end,
-              );
-            }}
-            dataSource={dataSource?.data || []}
-            columns={data?.valueType?.type === 'geoPoint' ? geoColumns : columns}
-            pagination={{
-              current: (dataSource?.pageIndex || 0) + 1,
-              pageSize: dataSource?.pageSize || 10,
-              showSizeChanger: true,
-              total: dataSource?.total || 0,
-            }}
-          />
-        );
-      case 'charts':
-        return (
-          <div>
-            <div style={{ margin: '10 0', display: 'flex' }}>
-              <div style={{ marginRight: 20 }}>
-                统计周期:
-                <Select
-                  value={cycle}
-                  style={{ width: 120 }}
-                  onChange={(value: string) => {
-                    setCycle(value);
-                    if (value === '*') {
-                      queryChartsList(start, end);
-                    } else {
-                      queryChartsAggList({
-                        columns: [
-                          {
-                            property: data.id,
-                            alias: data.id,
-                            agg: agg,
-                          },
-                        ],
-                        query: {
-                          interval: value,
-                          format: 'yyyy-MM-dd HH:mm:ss',
-                          from: start,
-                          to: end,
-                        },
-                      });
-                    }
-                  }}
-                >
-                  {list.includes(data.valueType?.type || '') && (
-                    <Select.Option value="*">实际值</Select.Option>
-                  )}
-                  <Select.Option value="1m">按分钟统计</Select.Option>
-                  <Select.Option value="1h">按小时统计</Select.Option>
-                  <Select.Option value="1d">按天统计</Select.Option>
-                  <Select.Option value="1w">按周统计</Select.Option>
-                  <Select.Option value="1M">按月统计</Select.Option>
-                </Select>
-              </div>
-              {cycle !== '*' && list.includes(data.valueType?.type || '') && (
-                <div>
-                  统计规则:
-                  <Select
-                    defaultValue="AVG"
-                    style={{ width: 120 }}
-                    onChange={(value: string) => {
-                      setAgg(value);
-                      queryChartsAggList({
-                        columns: [
-                          {
-                            property: data.id,
-                            alias: data.id,
-                            agg: value,
-                          },
-                        ],
-                        query: {
-                          interval: cycle,
-                          format: 'yyyy-MM-dd HH:mm:ss',
-                          from: start,
-                          to: end,
-                        },
-                      });
-                    }}
-                  >
-                    <Select.Option value="AVG">平均值</Select.Option>
-                    <Select.Option value="MAX">最大值</Select.Option>
-                    <Select.Option value="MIN">最小值</Select.Option>
-                    <Select.Option value="COUNT">总数</Select.Option>
-                  </Select>
-                </div>
-              )}
-            </div>
-            <div style={{ marginTop: 10 }}>
-              <Chart height={400} data={chartsList} scale={scale} padding="auto" autoFit>
-                <Legend />
-                <Axis name="year" />
-                <Axis
-                  name="value"
-                  label={{
-                    formatter: (val) => parseFloat(val).toLocaleString(),
-                  }}
-                />
-                <Tooltip shared />
-                <Point position="year*value" />
-                <LineAdvance position="year*value" shape="smooth" area />
-                <Slider />
-              </Chart>
-            </div>
-          </div>
-        );
-      default:
-        return null;
-    }
-  };
-
-  useEffect(() => {
-    if (tab === 'table') {
-      handleSearch(
-        {
-          pageSize: 10,
-          pageIndex: 0,
-        },
-        start,
-        end,
-      );
-    } else if (tab === 'charts') {
-      if (list.includes(data.valueType?.type || '')) {
-        queryChartsList(start, end);
-      } else {
-        queryChartsAggList({
-          columns: [
-            {
-              property: data.id,
-              alias: data.id,
-              agg,
-            },
-          ],
-          query: {
-            interval: cycle,
-            format: 'yyyy-MM-dd HH:mm:ss',
-            from: start,
-            to: end,
-          },
-        });
-      }
-    } else if (tab === 'geo') {
-      service
-        .getPropertyData(
-          params.id,
-          encodeQuery({
-            paging: false,
-            terms: { property: data?.id, timestamp$BTW: start && start ? [start, end] : [] },
-            sorts: { timestamp: 'asc' },
-          }),
-        )
-        .then((resp) => {
-          if (resp.status === 200) {
-            setGeoList(resp.result);
-          }
-        });
-    }
-    setDateValue([moment(start), moment(end)]);
-  }, [start, end]);
-
-  // @ts-ignore
-  return (
-    <Modal
-      maskClosable={false}
-      title="详情"
-      visible
-      onCancel={() => close()}
-      onOk={() => close()}
-      width="50vw"
-    >
-      <div style={{ marginBottom: '20px' }}>
-        <Space>
-          <Radio.Group
-            value={radioValue}
-            buttonStyle="solid"
-            onChange={(e) => {
-              const value = e.target.value;
-              setRadioValue(value);
-              let st: number = 0;
-              const et = new Date().getTime();
-              if (value === 'today') {
-                st = moment().startOf('day').valueOf();
-              } else if (value === 'week') {
-                st = moment().subtract(6, 'days').valueOf();
-              } else if (value === 'month') {
-                st = moment().subtract(29, 'days').valueOf();
-              }
-              setDateValue(undefined);
-              setStart(st);
-              setEnd(et);
-            }}
-            style={{ minWidth: 220 }}
-          >
-            <Radio.Button value="today">今日</Radio.Button>
-            <Radio.Button value="week">近一周</Radio.Button>
-            <Radio.Button value="month">近一月</Radio.Button>
-          </Radio.Group>
-          {
-            // @ts-ignore
-            <DatePicker.RangePicker
-              value={dateValue}
-              showTime
-              onChange={(dates: any) => {
-                if (dates) {
-                  setRadioValue(undefined);
-                  setDateValue(dates);
-                  const st = dates[0]?.valueOf();
-                  const et = dates[1]?.valueOf();
-                  setStart(st);
-                  setEnd(et);
-                }
-              }}
-            />
-          }
-        </Space>
-      </div>
-      <Tabs
-        activeKey={tab}
-        onChange={(key: string) => {
-          setTab(key);
-          if (key === 'charts' && !!data.valueType?.type) {
-            if (list.includes(data.valueType?.type)) {
-              queryChartsList(start, end);
-            } else {
-              setCycle('1m');
-              setAgg('COUNT');
-              queryChartsAggList({
-                columns: [
-                  {
-                    property: data.id,
-                    alias: data.id,
-                    agg: 'COUNT',
-                  },
-                ],
-                query: {
-                  interval: '1m',
-                  format: 'yyyy-MM-dd HH:mm:ss',
-                  from: start,
-                  to: end,
-                },
-              });
-            }
-          }
-          if (key === 'geo') {
-            service
-              .getPropertyData(
-                params.id,
-                encodeQuery({
-                  paging: false,
-                  terms: { property: data.id, timestamp$BTW: start && end ? [start, end] : [] },
-                  sorts: { timestamp: 'asc' },
-                }),
-              )
-              .then((resp) => {
-                if (resp.status === 200) {
-                  setGeoList(resp.result);
-                }
-              });
-          }
-          if (key === 'table') {
-            handleSearch(
-              {
-                pageSize: 10,
-                pageIndex: 0,
-              },
-              start,
-              end,
-            );
-          }
-        }}
-      >
-        {tabList.map((item) => (
-          <Tabs.TabPane tab={item.tab} key={item.key}>
-            {renderComponent(item.key)}
-          </Tabs.TabPane>
-        ))}
-        {data?.valueType?.type === 'geoPoint' && (
-          <Tabs.TabPane tab="轨迹" key="geo">
-            <AMap value={geoList} name={data?.name || ''} />
-          </Tabs.TabPane>
-        )}
-      </Tabs>
-      {detailVisible && (
-        <Detail
-          close={() => {
-            setDetailVisible(false);
-          }}
-          value={current}
-          type={data.valueType?.type || ''}
-        />
-      )}
-    </Modal>
-  );
-};
-export default PropertyLog;

+ 15 - 0
src/pages/device/Instance/index.tsx

@@ -117,6 +117,21 @@ const Instance = () => {
     </Button>,
     <PermissionButton
       type={'link'}
+      onClick={() => {
+        setCurrent(record);
+        setVisible(true);
+      }}
+      tooltip={{
+        title: '编辑',
+      }}
+      style={{ padding: 0 }}
+      key={'edit'}
+      isPermission={permission.update}
+    >
+      <EditOutlined />
+    </PermissionButton>,
+    <PermissionButton
+      type={'link'}
       key={'state'}
       style={{ padding: 0 }}
       popConfirm={{

+ 0 - 11
src/pages/device/Location/index.tsx

@@ -1,11 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import AMapComponent from '@/components/AMapComponent';
-
-const Location = () => {
-  return (
-    <PageContainer title="地理位置">
-      <AMapComponent />
-    </PageContainer>
-  );
-};
-export default Location;

+ 0 - 118
src/pages/edge/Device/index.tsx

@@ -1,118 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Tooltip } from 'antd';
-import { ArrowDownOutlined, BugOutlined, EditOutlined, MinusOutlined } from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import BaseService from '@/utils/BaseService';
-import type { DeviceItem } from '@/pages/edge/Device/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-export const service = new BaseService<DeviceItem>('device/instance');
-const Device = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<DeviceItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'id',
-      title: 'ID',
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
-    },
-    {
-      dataIndex: 'productName',
-      title: intl.formatMessage({
-        id: 'pages.table.productName',
-        defaultMessage: '产品名称',
-      }),
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
-            })}
-          >
-            <ArrowDownOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.notice.option.debug',
-              defaultMessage: '调试',
-            })}
-          >
-            <BugOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.edge.device',
-          defaultMessage: 'config',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Device;

+ 0 - 14
src/pages/edge/Device/typings.d.ts

@@ -1,14 +0,0 @@
-import type { BaseItem, State } from '@/utils/typings';
-
-type DeviceItem = {
-  productId: string;
-  productName: string;
-  registryTime: number;
-  state: State;
-  createTime: number;
-  creatorId: string;
-  creatorName: string;
-  deviceMetadata: string;
-  features: unknown[];
-  configuration: Record<string, any>;
-} & BaseItem;

+ 0 - 113
src/pages/edge/Product/index.tsx

@@ -1,113 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Tooltip } from 'antd';
-import { ArrowDownOutlined, BugOutlined, EditOutlined, MinusOutlined } from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import type { ProductItem } from '@/pages/edge/Product/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-export const service = new BaseService<ProductItem>('edge/product');
-const Product = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<ProductItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'model',
-      title: intl.formatMessage({
-        id: 'pages.media.device.model',
-        defaultMessage: '型号',
-      }),
-    },
-    {
-      dataIndex: 'manufacturer',
-      title: intl.formatMessage({
-        id: 'pages.media.device.manufacturer',
-        defaultMessage: '厂家',
-      }),
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
-            })}
-          >
-            <ArrowDownOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.notice.option.debug',
-              defaultMessage: '调试',
-            })}
-          >
-            <BugOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.edge.product',
-          defaultMessage: '产品',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Product;

+ 0 - 9
src/pages/edge/Product/typings.d.ts

@@ -1,9 +0,0 @@
-import type { BaseItem } from '@/utils/typings';
-
-type ProductItem = {
-  createTime: number;
-  description: string;
-  model: string;
-  version: string;
-  manufacturer: string;
-} & BaseItem;

+ 2 - 3
src/pages/init-home/components/basis.tsx

@@ -58,7 +58,7 @@ const Basis = forwardRef((props: Props, ref) => {
       <Row gutter={[24, 24]}>
         <Col span={10}>
           <Form.Item label="系统名称" name="title">
-            <Input />
+            <Input placeholder={'请输入系统名称'} />
           </Form.Item>
           <Form.Item
             label="主题色"
@@ -72,7 +72,7 @@ const Basis = forwardRef((props: Props, ref) => {
             </Select>
           </Form.Item>
           <Form.Item label="高德API Key" name="apikey" tooltip="配置后平台可调用高德地图GIS服务">
-            <Input />
+            <Input placeholder={'请输入高德API Key'} />
           </Form.Item>
           <Row gutter={[24, 24]}>
             <Col>
@@ -116,7 +116,6 @@ const Basis = forwardRef((props: Props, ref) => {
                 <div>建议尺寸1400x1080</div>
               </>
             }
-            rules={[{ required: true, message: '请上传背景图' }]}
           >
             <UploadImage size={4} style={{ width: 570, height: 415 }} />
           </Form.Item>

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

@@ -31,7 +31,7 @@
 
         .collapseTitle {
           display: flex;
-          font-size: 14px;
+          font-size: 15px;
           opacity: 0.85;
 
           .collapseDesc {

+ 1 - 1
src/pages/init-home/index.tsx

@@ -51,7 +51,7 @@ const InitHome = () => {
           {/*</div>*/}
           <div className={styles.right}>
             <Spin spinning={loadings}>
-              <Collapse defaultActiveKey={['1', '2', '3', '4']}>
+              <Collapse defaultActiveKey={['1']} accordion>
                 <Collapse.Panel
                   header={
                     <div className={styles.collapseTitle}>

+ 0 - 6
src/pages/media/Config/index.tsx

@@ -1,6 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-
-const Config = () => {
-  return <PageContainer>Config</PageContainer>;
-};
-export default Config;

+ 0 - 4
src/pages/media/Config/typings.d.ts

@@ -1,4 +0,0 @@
-type Item = {
-  id: string;
-  name: string;
-};

+ 0 - 6
src/pages/media/Reveal/index.tsx

@@ -1,6 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-
-const Reveal = () => {
-  return <PageContainer>Reveal</PageContainer>;
-};
-export default Reveal;

+ 0 - 4
src/pages/media/Reveal/typings.d.ts

@@ -1,4 +0,0 @@
-type Item = {
-  id: string;
-  name: string;
-};

+ 2 - 1
src/pages/notice/Config/Debug/index.tsx

@@ -57,8 +57,10 @@ const Debug = observer(() => {
             const value = (field as Field).value;
             const format = field.query('.value').take() as any;
             const _id = field.query('.id').take() as Field;
+
             switch (value) {
               case 'date':
+                // const a = variableRef.current?.find((i: any) => i.id === _id.value);
                 format.setComponent(DatePicker);
                 break;
               case 'string':
@@ -76,7 +78,6 @@ const Debug = observer(() => {
                 format.setComponent(Input);
                 break;
             }
-            console.log(variableRef.current);
             if (variableRef.current) {
               const a = variableRef.current?.find((i: any) => i.id === _id.value);
               const businessType = a?.expands?.businessType;

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

@@ -62,7 +62,7 @@ const SyncUser = observer(() => {
       dataIndex: 'action',
       title: '操作',
       render: (text: any, record: any) => [
-        <Tooltip title={'绑定用户'} key="bind">
+        <Tooltip title={'编辑'} key="bind">
           <Button
             type="link"
             onClick={() => {
@@ -73,7 +73,7 @@ const SyncUser = observer(() => {
             <EditOutlined />
           </Button>
         </Tooltip>,
-        <Tooltip title={'解绑用户'} key="unbind">
+        <Tooltip title={'解绑'} key="unbind">
           {record?.status === 1 && (
             <Button type="link">
               <Popconfirm

+ 13 - 10
src/pages/notice/Template/Detail/doc/DingTalk.tsx

@@ -3,8 +3,8 @@ import './index.less';
 
 const DingTalk = () => {
   const agentId = require('/public/images/notice/doc/template/dingTalk-message/01-Agentid.jpg');
-  const userId = require('/public/images/notice/doc/template/dingTalk-message/02-user-id.jpg');
-  const dept = require('/public/images/notice/doc/template/dingTalk-message/03-dept.jpg');
+  // const userId = require('/public/images/notice/doc/template/dingTalk-message/02-user-id.jpg');
+  // const dept = require('/public/images/notice/doc/template/dingTalk-message/03-dept.jpg');
   const a = '{name}';
   return (
     <div className="doc">
@@ -22,26 +22,29 @@ const DingTalk = () => {
       <h1>1. 概述</h1>
       <div>
         通知模板结合通知配置为告警消息通知提供支撑。通知模板只能调用同一类型的通知配置服务。
+        <div>
+          使用钉钉消息通知时需在钉钉开放平台中创建好对应的应用
+        </div>
       </div>
       <h1> 2.模板配置说明</h1>
       <h2> 1、绑定配置</h2>
       <div> 使用固定的通知配置发送此通知模板</div>
       <h2> 2、Agentid</h2>
       <div> 应用唯一标识</div>
+      <div> 获取路径:“钉钉开发平台”--“应用开发”--“查看应用”</div>
       <div className="image">
         <Image width="100%" src={agentId} />
       </div>
-      <div> 获取路径:“钉钉开发平台”--“应用开发”--“查看应用”</div>
       <h2> 3、收信人ID、收信部门ID</h2>
       <div>
-        接收通知的2种方式,2个字段若在此页面都没有填写,则在模板调试和配置告警通知时需要手动填写
-      </div>
-      <div> 收信人ID获取路径:“钉钉管理后台”--“通讯录”--“查看用户”</div>
-      <div> 收信部门ID获取路径:“钉钉管理后台”--“通讯录”--“编辑部门”</div>
-      <div className="image">
-        <Image width="100%" src={userId} />
-        <Image width="100%" src={dept} />
+        若不填写收信人,则在模板调试和配置告警通知时手动填写。
       </div>
+      {/*<div> 收信人ID获取路径:“钉钉管理后台”--“通讯录”--“查看用户”</div>*/}
+      {/*<div> 收信部门ID获取路径:“钉钉管理后台”--“通讯录”--“编辑部门”</div>*/}
+      {/*<div className="image">*/}
+      {/*  <Image width="100%" src={userId} />*/}
+      {/*  <Image width="100%" src={dept} />*/}
+      {/*</div>*/}
       <h2> 4、模板内容</h2>
       <div>
         支持填写带变量的动态模板。变量填写规范示例:${a}

+ 2 - 2
src/pages/notice/Template/Detail/doc/DingTalkRebot.tsx

@@ -6,8 +6,8 @@ const DingTalkRebot = () => {
     <div className="doc">
       <div className="url">
         钉钉管理后台:
-        <a href="https://www.dingtalk.com" target="_blank" rel="noopener noreferrer">
-          https://www.dingtalk.com
+        <a href="https://open-dev.dingtalk.com" target="_blank" rel="noopener noreferrer">
+          https://open-dev.dingtalk.com
         </a>
       </div>
       <h1>1. 概述</h1>

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

@@ -126,7 +126,7 @@ const Dashboard = observer(() => {
         series: [
           {
             name: '告警数',
-            data: fifteenData.map((item) => item.value),
+            data: fifteenData.sort((a,b) => b.timestamp - a.timestamp).map((item) => item.value),
             type: 'bar',
             itemStyle: {
               color: '#2F54EB',

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

@@ -231,7 +231,7 @@ const Instance = () => {
           style={{ padding: 0 }}
           disabled={record.state.value !== 'disable'}
           tooltip={{
-            title: record.state.value !== 'disable' ? '请先禁用,再删除' : '',
+            title: record.state.value !== 'disable' ? '请先禁用,再删除' : '删除',
           }}
           popConfirm={{
             title: '确认删除',

+ 0 - 150
src/pages/rule-engine/SQLRule/index.tsx

@@ -1,150 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import type { SQLRuleItem } from '@/pages/rule-engine/SQLRule/typings';
-import { Tooltip } from 'antd';
-import {
-  CaretRightOutlined,
-  DownloadOutlined,
-  EditOutlined,
-  MinusOutlined,
-  ReloadOutlined,
-  StopOutlined,
-} from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import { service } from '@/pages/rule-engine/Instance';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import { onlyMessage } from '@/utils/util';
-
-const SQLRule = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<SQLRuleItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'createTime',
-      title: intl.formatMessage({
-        id: 'pages.ruleEngine.sqlRule.time',
-        defaultMessage: '创建时间',
-      }),
-    },
-    {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.ruleEngine.option.start',
-              defaultMessage: '启动',
-            })}
-          >
-            <CaretRightOutlined />
-          </Tooltip>
-        </a>,
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.ruleEngine.option.restart',
-              defaultMessage: '重启',
-            })}
-          >
-            <ReloadOutlined />
-          </Tooltip>
-        </a>,
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.ruleEngine.option.stop',
-              defaultMessage: '停止',
-            })}
-          >
-            <StopOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-        <a key="download">
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
-            })}
-          >
-            <DownloadOutlined
-              onClick={() => {
-                onlyMessage(
-                  `${intl.formatMessage({
-                    id: 'pages.data.option.download',
-                    defaultMessage: '下载',
-                  })}`,
-                );
-              }}
-            />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-  return (
-    <PageContainer>
-      <BaseCrud
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.ruleEngine.sqlRule',
-          defaultMessage: '数据转发',
-        })}
-        schema={schema}
-        defaultParams={{ modelType: 'sql_rule' }}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default SQLRule;

+ 0 - 3
src/pages/rule-engine/SQLRule/typings.d.ts

@@ -1,3 +0,0 @@
-import type { InstanceItem } from '@/pages/rule-engine/Instance/typings';
-
-type SQLRuleItem = InstanceItem;

+ 6 - 3
src/pages/rule-engine/Scene/Save/components/TimingTrigger/index.tsx

@@ -124,7 +124,10 @@ export default (props: TimingTrigger) => {
 
   return (
     <Row gutter={24} className={props.className}>
-      <Col span={data.trigger !== TriggerEnum.cron ? 6 : 8}>
+      <Col
+        xxl={data.trigger !== TriggerEnum.cron ? 6 : 8}
+        xl={data.trigger !== TriggerEnum.cron ? 10 : 12}
+      >
         <ItemGroup>
           <Select
             options={[
@@ -179,7 +182,7 @@ export default (props: TimingTrigger) => {
       </Col>
       {data.trigger !== TriggerEnum.cron && (
         <>
-          <Col span={12}>
+          <Col xxl={12} xl={14}>
             <ItemGroup>
               <Select
                 options={[
@@ -228,7 +231,7 @@ export default (props: TimingTrigger) => {
               )}
             </ItemGroup>
           </Col>
-          <Col span={6}>
+          <Col xxl={6} xl={10}>
             <ItemGroup style={{ gap: 16 }}>
               {data.mod === PeriodModEnum.period ? (
                 <>

+ 8 - 5
src/pages/rule-engine/Scene/Save/components/TimingTrigger/refactor.tsx

@@ -69,7 +69,10 @@ export default (props: TimingTrigger) => {
 
   return (
     <Row gutter={24} className={props.className}>
-      <Col span={data?.trigger !== TriggerEnum.cron ? 6 : 8}>
+      <Col
+        xxl={data.trigger !== TriggerEnum.cron ? 6 : 8}
+        xl={data.trigger !== TriggerEnum.cron ? 10 : 12}
+      >
         <ItemGroup>
           <Form.Item
             name={[...name, 'timer', 'trigger']}
@@ -150,7 +153,7 @@ export default (props: TimingTrigger) => {
           )}
         </ItemGroup>
       </Col>
-      <Col span={11}>
+      <Col xxl={11} xl={14}>
         {data?.trigger !== TriggerEnum.cron && (
           <ItemGroup>
             <Form.Item
@@ -193,12 +196,12 @@ export default (props: TimingTrigger) => {
           </ItemGroup>
         )}
       </Col>
-      <Col span={7}>
+      <Col xxl={7} xl={10}>
         {data?.trigger !== TriggerEnum.cron && (
           <ItemGroup style={{ gap: 16 }}>
             {data?.mod === PeriodModEnum.period ? (
               <>
-                <div style={{ paddingBottom: 14 }}> 每 </div>
+                <div style={{ paddingBottom: 16 }}> 每 </div>
                 <Form.Item
                   name={[...name, 'timer', 'period', 'every']}
                   rules={[{ required: true, message: '请输入时间' }]}
@@ -220,7 +223,7 @@ export default (props: TimingTrigger) => {
                 </Form.Item>
               </>
             ) : null}
-            <div style={{ flex: 0, flexBasis: 64, paddingBottom: 14 }}> 执行一次 </div>
+            <div style={{ flex: 0, flexBasis: 64, paddingBottom: 16 }}> 执行一次 </div>
           </ItemGroup>
         )}
       </Col>

+ 21 - 0
src/pages/rule-engine/Scene/Save/index.less

@@ -45,3 +45,24 @@
   //  }
   //}
 }
+
+.scene-content {
+  position: relative;
+
+  .scene-content-left {
+    width: 66.66%;
+  }
+
+  .scene-content-right {
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: 33.33%;
+    height: 100%;
+
+    > div {
+      height: 100%;
+      overflow-y: auto;
+    }
+  }
+}

+ 7 - 19
src/pages/rule-engine/Scene/Save/index.tsx

@@ -1,17 +1,5 @@
 import { PageContainer } from '@ant-design/pro-layout';
-import {
-  Button,
-  Card,
-  Col,
-  Form,
-  Input,
-  InputNumber,
-  Radio,
-  Row,
-  Space,
-  Switch,
-  Tooltip,
-} from 'antd';
+import { Button, Card, Form, Input, InputNumber, Radio, Space, Switch, Tooltip } from 'antd';
 import { useHistory, useIntl, useLocation } from 'umi';
 import { useCallback, useEffect, useRef, useState } from 'react';
 import { PermissionButton, TitleComponent } from '@/components';
@@ -217,8 +205,8 @@ export default () => {
   return (
     <PageContainer>
       <Card>
-        <Row>
-          <Col span={16}>
+        <div className={'scene-content'}>
+          <div className={'scene-content-left'}>
             <Form
               scrollToFirstError={{
                 behavior: 'smooth',
@@ -426,11 +414,11 @@ export default () => {
                 保存
               </PermissionButton>
             </Form>
-          </Col>
-          <Col span={8}>
+          </div>
+          <div className={'scene-content-right'}>
             <Explanation type={triggerType} />
-          </Col>
-        </Row>
+          </div>
+        </div>
       </Card>
     </PageContainer>
   );

+ 13 - 11
src/pages/rule-engine/Scene/Save/trigger/index.tsx

@@ -224,17 +224,19 @@ export default observer((props: TriggerProps) => {
           </Col>
         )}
         <Col span={6}>
-          <Form.Item
-            name={['trigger', 'device', 'operation', 'operator']}
-            initialValue={undefined}
-            rules={[{ required: true, message: '请选择触发类型' }]}
-          >
-            <Select
-              placeholder={'请选择触发类型'}
-              options={operatorOptions}
-              style={{ width: '100%' }}
-            />
-          </Form.Item>
+          {productId && (
+            <Form.Item
+              name={['trigger', 'device', 'operation', 'operator']}
+              initialValue={undefined}
+              rules={[{ required: true, message: '请选择触发类型' }]}
+            >
+              <Select
+                placeholder={'请选择触发类型'}
+                options={operatorOptions}
+                style={{ width: '100%' }}
+              />
+            </Form.Item>
+          )}
         </Col>
       </Row>
       {FormModel.trigger?.device?.operation?.operator === OperatorEnum.invokeFunction ||

+ 0 - 115
src/pages/simulator/Device/index.tsx

@@ -1,115 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import type { DeviceItem } from '@/pages/simulator/Device/typings';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Tooltip } from 'antd';
-import { ArrowDownOutlined, BugOutlined, EditOutlined, MinusOutlined } from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-export const service = new BaseService<DeviceItem>('network/simulator');
-const Device = () => {
-  // todo 接口返回未分页
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<DeviceItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'networkType',
-      title: intl.formatMessage({
-        id: 'pages.table.type',
-        defaultMessage: '类型',
-      }),
-    },
-    {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
-            })}
-          >
-            <ArrowDownOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.notice.option.debug',
-              defaultMessage: '调试',
-            })}
-          >
-            <BugOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.simulator.device',
-          defaultMessage: '模拟测试',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Device;

+ 0 - 9
src/pages/simulator/Device/typings.d.ts

@@ -1,9 +0,0 @@
-import type { BaseItem, State } from '@/utils/typings';
-
-type DeviceItem = {
-  listeners: Record<string, any>[];
-  networkConfiguration: Record<string, any>;
-  networkType: string;
-  runner: Record<string, any>;
-  state: State;
-} & BaseItem;

+ 0 - 90
src/pages/system/Basis/init.tsx

@@ -1,90 +0,0 @@
-import { UploadImage } from '@/components';
-import { Card, Col, Form, Input, Row, Select } from 'antd';
-import { useEffect } from 'react';
-
-interface Props {
-  getData: Function;
-}
-
-const Init = (props: Props) => {
-  const [form] = Form.useForm();
-
-  useEffect(() => {
-    props.getData(form);
-  }, []);
-
-  return (
-    <Card>
-      <Form layout="vertical" form={form}>
-        <Row gutter={[24, 24]}>
-          <Col span={10}>
-            <Form.Item label="系统名称" name="title">
-              <Input />
-            </Form.Item>
-            <Form.Item
-              label="主题色"
-              name="headerTheme"
-              initialValue="light"
-              rules={[{ required: true, message: '请选择主题色' }]}
-            >
-              <Select>
-                <Select.Option value="light">白色</Select.Option>
-                <Select.Option value="dark">黑色</Select.Option>
-              </Select>
-            </Form.Item>
-            <Form.Item label="高德API Key" name="apikey" tooltip="配置后平台可调用高德地图GIS服务">
-              <Input />
-            </Form.Item>
-            <Row gutter={[24, 24]}>
-              <Col>
-                <Form.Item
-                  name={'logo'}
-                  label="系统logo"
-                  extra={
-                    <>
-                      <div>推荐尺寸200*200</div>
-                      <div>支持jpg,png</div>
-                    </>
-                  }
-                >
-                  <UploadImage />
-                </Form.Item>
-              </Col>
-              <Col>
-                <Form.Item
-                  name={'ico'}
-                  label="浏览器页签"
-                  tooltip="浏览器tab页中显示的图片元素"
-                  extra={
-                    <>
-                      <div>推荐尺寸64*64</div>
-                      <div>支持ico格式</div>
-                    </>
-                  }
-                >
-                  <UploadImage size={1} types={['image/x-icon']} backgroundSize={'inherit'} />
-                </Form.Item>
-              </Col>
-            </Row>
-          </Col>
-          <Col span={14}>
-            <Form.Item
-              name={'backgroud'}
-              label="登录背景图"
-              extra={
-                <>
-                  <div>支持4M以内的图片:支持jpg、png</div>
-                  <div>建议尺寸1400x1080</div>
-                </>
-              }
-              rules={[{ required: true, message: '请上传背景图' }]}
-            >
-              <UploadImage size={4} style={{ width: 570, height: 415 }} />
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    </Card>
-  );
-};
-export default Init;

+ 0 - 4
src/pages/system/Config/index.tsx

@@ -1,4 +0,0 @@
-import Service from '@/pages/system/Config/service';
-
-export const service = new Service('system');
-export default () => {};

+ 0 - 6
src/pages/system/Config/service.ts

@@ -1,6 +0,0 @@
-import BaseService from '@/utils/BaseService';
-import { request } from '@@/plugin-request/request';
-
-export default class Service extends BaseService<any> {
-  getAMapKey = () => request(`${this.uri}/config/amap`, { method: 'GET' });
-}

+ 1 - 1
src/pages/system/Department/Assets/deivce/index.tsx

@@ -218,7 +218,7 @@ export default observer((props: { parentId: string }) => {
             <Tooltip
               title={intl.formatMessage({
                 id: 'pages.system.role.option.unBindUser',
-                defaultMessage: '删除',
+                defaultMessage: '解绑',
               })}
             >
               <DisconnectOutlined />

+ 1 - 1
src/pages/system/Department/Member/index.tsx

@@ -140,7 +140,7 @@ const Member = observer((props: { parentId: string }) => {
             <Tooltip
               title={intl.formatMessage({
                 id: 'pages.system.role.option.unBindUser',
-                defaultMessage: '解',
+                defaultMessage: '解绑',
               })}
             >
               <DisconnectOutlined />

+ 95 - 92
src/pages/system/Menu/Detail/buttons.tsx

@@ -250,7 +250,7 @@ export default (props: ButtonsProps) => {
         search={false}
         columnEmptyText={''}
         pagination={false}
-        toolBarRender={() => [
+        headerTitle={[
           <PermissionButton
             onClick={() => {
               if (!props.data) {
@@ -272,102 +272,105 @@ export default (props: ButtonsProps) => {
           </PermissionButton>,
         ]}
       />
-      <Modal
-        maskClosable={false}
-        width={660}
-        visible={visible}
-        title={handleTitle()}
-        onOk={() => {
-          if (!disabled) {
-            saveData();
-          } else {
+      {
+        visible &&
+        <Modal
+          maskClosable={false}
+          width={660}
+          visible={visible}
+          title={handleTitle()}
+          onOk={() => {
+            if (!disabled) {
+              saveData();
+            } else {
+              resetForm();
+              setVisible(false);
+            }
+          }}
+          onCancel={() => {
             resetForm();
             setVisible(false);
-          }
-        }}
-        onCancel={() => {
-          resetForm();
-          setVisible(false);
-        }}
-        confirmLoading={loading}
-      >
-        <Form form={form} layout={'vertical'}>
-          <Form.Item
-            name="id"
-            label={intl.formatMessage({
-              id: 'pages.system.org.encoding',
-              defaultMessage: '编码',
-            })}
-            required={true}
-            rules={[
-              { required: true, message: '请输入编码' },
-              { max: 64, message: '最多可输入64个字符' },
-              {
-                pattern: /^[a-zA-Z0-9`!@#$%^&*()_+\-={}|\\\]\[;':",.\/<>?]+$/,
-                message: '请输入英文+数字+特殊字符(`!@#$%^&*()_+-={}|\\][;\':",./<>?)',
-              },
-              {
-                validator: (_, value, callback) => {
-                  if (!(!disabled && id) && buttonItems.some((item) => item.id === value)) {
-                    // 判断是否为新增
-                    callback('重复编码');
-                  }
-                  callback();
+          }}
+          confirmLoading={loading}
+        >
+          <Form form={form} layout={'vertical'}>
+            <Form.Item
+              name="id"
+              label={intl.formatMessage({
+                id: 'pages.system.org.encoding',
+                defaultMessage: '编码',
+              })}
+              required={true}
+              rules={[
+                { required: true, message: '请输入编码' },
+                { max: 64, message: '最多可输入64个字符' },
+                {
+                  pattern: /^[a-zA-Z0-9`!@#$%^&*()_+\-={}|\\\]\[;':",.\/<>?]+$/,
+                  message: '请输入英文+数字+特殊字符(`!@#$%^&*()_+-={}|\\][;\':",./<>?)',
                 },
-              },
-            ]}
-          >
-            <Input disabled={!!(disabled || id)} placeholder={'请输入编码'} />
-          </Form.Item>
-          <Form.Item
-            name="name"
-            label={intl.formatMessage({
-              id: 'pages.table.name',
-              defaultMessage: '名称',
-            })}
-            required={true}
-            rules={[
-              { required: true, message: '请输入名称' },
-              { max: 64, message: '最多可输入64个字符' },
-            ]}
-          >
-            <Input disabled={disabled} placeholder={'请输入名称'} />
-          </Form.Item>
-          <Form.Item
-            label={intl.formatMessage({
-              id: 'page.system.menu.permissions',
-              defaultMessage: '权限',
-            })}
-            required={true}
-          >
-            <Input
-              allowClear
-              onChange={debounce(filterThree, 500)}
-              style={{ width: 300, marginBottom: 12 }}
-              placeholder={'请输入权限名称'}
-            />
-            <Form.Item name="permissions" rules={[{ required: true, message: '请选择权限' }]}>
-              <Permission
-                title={intl.formatMessage({
-                  id: 'page.system.menu.permissions.operate',
-                  defaultMessage: '权限操作',
-                })}
-                disabled={disabled}
-                data={permissions}
+                {
+                  validator: (_, value, callback) => {
+                    if (!(!disabled && id) && buttonItems.some((item) => item.id === value)) {
+                      // 判断是否为新增
+                      callback('重复编码');
+                    }
+                    callback();
+                  },
+                },
+              ]}
+            >
+              <Input disabled={!!(disabled || id)} placeholder={'请输入编码'} />
+            </Form.Item>
+            <Form.Item
+              name="name"
+              label={intl.formatMessage({
+                id: 'pages.table.name',
+                defaultMessage: '名称',
+              })}
+              required={true}
+              rules={[
+                { required: true, message: '请输入名称' },
+                { max: 64, message: '最多可输入64个字符' },
+              ]}
+            >
+              <Input disabled={disabled} placeholder={'请输入名称'} />
+            </Form.Item>
+            <Form.Item
+              label={intl.formatMessage({
+                id: 'page.system.menu.permissions',
+                defaultMessage: '权限',
+              })}
+              required={true}
+            >
+              <Input
+                allowClear
+                onChange={debounce(filterThree, 500)}
+                style={{ width: 300, marginBottom: 12 }}
+                placeholder={'请输入权限名称'}
               />
+              <Form.Item name="permissions" rules={[{ required: true, message: '请选择权限' }]}>
+                <Permission
+                  title={intl.formatMessage({
+                    id: 'page.system.menu.permissions.operate',
+                    defaultMessage: '权限操作',
+                  })}
+                  disabled={disabled}
+                  data={permissions}
+                />
+              </Form.Item>
             </Form.Item>
-          </Form.Item>
-          <Form.Item
-            name="description"
-            label={intl.formatMessage({
-              id: 'pages.table.describe',
-              defaultMessage: '说明',
-            })}
-          >
-            <Input.TextArea disabled={disabled} placeholder={'请输入说明'} />
-          </Form.Item>
-        </Form>
-      </Modal>
+            <Form.Item
+              name="description"
+              label={intl.formatMessage({
+                id: 'pages.table.describe',
+                defaultMessage: '说明',
+              })}
+            >
+              <Input.TextArea disabled={disabled} placeholder={'请输入说明'} />
+            </Form.Item>
+          </Form>
+        </Modal>
+      }
     </>
   );
 };

+ 60 - 11
src/pages/system/Menu/Setting/baseMenu.ts

@@ -6,6 +6,7 @@ export default [
     id: '1',
     url: '/iot',
     icon: 'icon-wulianwang',
+    sortIndex: 1,
     permissions: [
       {
         actions: ['query', 'save', 'delete'],
@@ -20,6 +21,7 @@ export default [
         id: '1-1',
         url: '/iot/home',
         icon: 'icon-keshihua',
+        sortIndex: 1,
         permissions: [
           { permission: 'device-instance', actions: ['query'] },
           { permission: 'dashboard', actions: ['query'] },
@@ -33,6 +35,7 @@ export default [
         id: '1-2',
         url: '/iot/notice/Type',
         icon: 'icon-shebei',
+        sortIndex: 2,
         permissions: [
           { permission: 'template', actions: ['query', 'save', 'delete'] },
           { permission: 'user-third-party-manager', actions: ['query', 'save'] },
@@ -58,6 +61,7 @@ export default [
         id: '1-3',
         url: '/iot/device',
         icon: 'icon-shebei',
+        sortIndex: 3,
         permissions: [],
         children: [
           {
@@ -67,6 +71,7 @@ export default [
             id: '1-3-1',
             url: '/iot/device/DashBoard',
             icon: 'icon-keshihua',
+            sortIndex: 1,
             permissions: [
               { permission: 'device-product', actions: ['query'] },
               { permission: 'dashboard', actions: ['query'] },
@@ -81,6 +86,7 @@ export default [
             id: '1-3-2',
             url: '/iot/device/Product',
             icon: 'icon-chanpin',
+            sortIndex: 2,
             permissions: [
               { permission: 'device-mapping', actions: ['query', 'save'] },
               { permission: 'device-gateway', actions: ['query', 'save', 'delete'] },
@@ -153,6 +159,7 @@ export default [
             id: '1-3-3',
             url: '/iot/device/Instance',
             icon: 'icon-shebei',
+            sortIndex: 3,
             permissions: [
               { permission: 'transparent-codec', actions: ['query'] },
               { permission: 'device-api', actions: ['query-device-events'] },
@@ -224,6 +231,7 @@ export default [
             name: '产品分类',
             parentId: '1-3',
             id: '1-3-4',
+            sortIndex: 4,
             url: '/iot/device/Category',
             icon: 'icon-chanpinfenlei1',
             permissions: [{ permission: 'device-category', actions: ['query', 'save'] }],
@@ -261,12 +269,14 @@ export default [
         url: '/iot/link',
         icon: 'icon-yunweiguanli-1',
         permissions: [],
+        sortIndex: 4,
         children: [
           {
             code: 'link/DashBoard',
             name: '仪表盘',
             parentId: '1-4',
             id: '1-4-1',
+            sortIndex: 1,
             url: '/iot/link/dashboard',
             icon: 'icon-keshihua',
             permissions: [
@@ -279,6 +289,7 @@ export default [
             name: '设备接入网关',
             parentId: '1-4',
             id: '1-4-2',
+            sortIndex: 2,
             url: '/iot/link/accessConfig',
             icon: 'icon-wangguanzishebei',
             permissions: [
@@ -347,6 +358,7 @@ export default [
             name: '协议管理',
             parentId: '1-4',
             id: '1-4-3',
+            sortIndex: 3,
             url: '/iot/link/protocol',
             icon: 'icon-tongzhiguanli',
             permissions: [
@@ -400,6 +412,7 @@ export default [
             name: '日志管理',
             parentId: '1-4',
             id: '1-4-4',
+            sortIndex: 4,
             url: '/iot/link/Log',
             icon: 'icon-rizhifuwu',
             permissions: [
@@ -422,6 +435,7 @@ export default [
             name: '网络组件',
             parentId: '1-4',
             id: '1-4-5',
+            sortIndex: 5,
             url: '/iot/link/type',
             icon: 'icon-wangluozujian',
             permissions: [{ permission: 'network-config', actions: ['query', 'delete'] }],
@@ -460,6 +474,7 @@ export default [
             name: '证书管理',
             parentId: '1-4',
             id: '1-4-6',
+            sortIndex: 6,
             url: '/iot/link/Certificate',
             icon: 'icon-rizhifuwu',
             permissions: [],
@@ -486,6 +501,7 @@ export default [
             name: '流媒体服务',
             parentId: '1-4',
             id: '1-4-7',
+            sortIndex: 7,
             url: '/iot/link/Stream',
             icon: 'icon-xuanzetongdao1',
             permissions: [{ permission: 'media-server', actions: ['query', 'save', 'delete'] }],
@@ -517,6 +533,7 @@ export default [
             name: '通道配置',
             parentId: '1-4',
             id: '1-4-8',
+            sortIndex: 8,
             url: '/iot/link/Channel',
             icon: 'icon-zidingyiguize',
             permissions: [],
@@ -526,6 +543,7 @@ export default [
                 name: 'OPC UA',
                 parentId: '1-4-8',
                 id: '1-4-8-1',
+                sortIndex: 1,
                 url: '/iot/link/Channel/Opcua',
                 icon: 'icon-zhilianshebei',
                 permissions: [
@@ -585,6 +603,7 @@ export default [
                 name: 'Modbus',
                 parentId: '1-4-8',
                 id: '1-4-8-2',
+                sortIndex: 2,
                 url: '/iot/link/Channel/Modbus',
                 icon: 'icon-changjingliandong',
                 permissions: [],
@@ -623,6 +642,7 @@ export default [
             name: '远程升级',
             parentId: '1-4',
             id: '1-4-9',
+            sortIndex: 9,
             url: '/iot/link/firmware',
             icon: 'icon-wangluozujian',
             permissions: [
@@ -665,6 +685,7 @@ export default [
         name: '告警中心',
         parentId: '1',
         id: '1-5',
+        sortIndex: 1,
         url: '/iot/Alarm',
         icon: 'icon-zidingyiguize',
         permissions: [],
@@ -675,6 +696,7 @@ export default [
             name: '仪表盘',
             parentId: '1-5',
             id: '1-5-1',
+            sortIndex: 1,
             url: '/iot/Alarm/dashboard',
             icon: 'icon-shujumoni',
             permissions: [
@@ -689,6 +711,7 @@ export default [
             name: '基础配置',
             parentId: '1-5',
             id: '1-5-3',
+            sortIndex: 2,
             url: '/iot/Alarm/Config',
             icon: 'icon-chajianguanli',
             permissions: [{ permission: 'alarm-config', actions: ['query', 'save', 'delete'] }],
@@ -708,6 +731,7 @@ export default [
             name: '告警配置',
             parentId: '1-5',
             id: '1-5-2',
+            sortIndex: 3,
             url: '/iot/Alarm/Configuration',
             icon: 'icon-chajianguanli',
             permissions: [
@@ -755,6 +779,7 @@ export default [
             name: '告警记录',
             parentId: '1-5',
             id: '1-5-4',
+            sortIndex: 4,
             url: '/iot/Alarm/Log',
             icon: 'icon-changjingliandong',
             permissions: [{ permission: 'alarm-record', actions: ['query', 'save'] }],
@@ -779,6 +804,7 @@ export default [
         name: '北向输出',
         parentId: '1',
         id: '1-6',
+        sortIndex: 6,
         url: '/iot/northbound',
         icon: 'icon-yunyunjieru',
         permissions: [],
@@ -789,6 +815,7 @@ export default [
             name: 'DuerOS',
             parentId: '1-6',
             id: '1-6-1',
+            sortIndex: 1,
             url: '/iot/northbound/DuerOS',
             icon: 'icon-yunyunjieru',
             permissions: [],
@@ -822,6 +849,7 @@ export default [
             name: '阿里云',
             parentId: '1-6',
             id: '1-6-2',
+            sortIndex: 2,
             url: '/iot/northbound/AliCloud',
             icon: 'icon-yunyunjieru',
             permissions: [],
@@ -856,6 +884,7 @@ export default [
         name: '规则引擎',
         parentId: '1',
         id: '1-7',
+        sortIndex: 7,
         url: '/iot/rule-engine',
         icon: 'icon-zidingyiguize',
         permissions: [],
@@ -866,6 +895,7 @@ export default [
             name: '规则编排',
             parentId: '1-7',
             id: '1-7-1',
+            sortIndex: 1,
             url: '/iot/rule-engine/Instance',
             icon: 'icon-changjingliandong',
             permissions: [
@@ -917,6 +947,7 @@ export default [
             name: '场景联动',
             parentId: '1-7',
             id: '1-7-2',
+            sortIndex: 2,
             url: '/iot/rule-engine/scene',
             icon: 'icon-yunweiguanli-1',
             permissions: [{ permission: 'rule-scene', actions: ['query', 'save', 'delete'] }],
@@ -955,6 +986,7 @@ export default [
     id: '2',
     url: '/media',
     icon: 'icon-shipinwangguan',
+    sortIndex: 2,
     permissions: [],
     buttons: [],
     children: [
@@ -963,6 +995,7 @@ export default [
         name: '首页',
         parentId: '2',
         id: '2-1',
+        sortIndex: 1,
         url: '/media/home',
         icon: 'icon-zhihuishequ',
         permissions: [],
@@ -973,6 +1006,7 @@ export default [
         name: '仪表盘',
         parentId: '2',
         id: '2-2',
+        sortIndex: 2,
         url: '/media/dashboard',
         icon: 'icon-keshihua',
         permissions: [],
@@ -983,6 +1017,7 @@ export default [
         name: '视频设备',
         parentId: '2',
         id: '2-3',
+        sortIndex: 3,
         url: '/media/device',
         icon: 'icon-keshihua',
         permissions: [
@@ -1047,6 +1082,7 @@ export default [
         name: '分屏展示',
         parentId: '2',
         id: '2-4',
+        sortIndex: 4,
         url: '/media/SplitScreen',
         icon: 'icon-fenpingzhanshi1',
         permissions: [
@@ -1069,6 +1105,7 @@ export default [
         name: '国标级联',
         parentId: '2',
         id: '2-5',
+        sortIndex: 5,
         url: '/media/Cascade',
         icon: 'icon-guojijilian',
         permissions: [
@@ -1140,6 +1177,7 @@ export default [
     id: '3',
     url: '/system',
     icon: 'icon-xitongguanli1',
+    sortIndex: 3,
     permissions: [{ permission: 'menu', actions: ['query', 'save', 'grant', 'delete'] }],
     buttons: [],
     children: [
@@ -1148,6 +1186,7 @@ export default [
         name: '基础配置',
         parentId: '3',
         id: '3-1',
+        sortIndex: 1,
         url: '/system/Basis',
         icon: 'icon-shezhi',
         permissions: [
@@ -1167,6 +1206,7 @@ export default [
         name: '用户管理',
         parentId: '3',
         id: '3-2',
+        sortIndex: 2,
         url: '/system/user',
         icon: 'icon-yonghuguanli',
         permissions: [
@@ -1223,9 +1263,22 @@ export default [
         name: '部门管理',
         parentId: '3',
         id: '3-3',
+        sortIndex: 3,
         url: '/system/Department',
         icon: 'icon-bumenguanli',
         permissions: [
+
+          { permission: 'assets-bind', actions: ['bind', 'unbind', 'query', 'permission'] },
+          { permission: 'role', actions: ['query', 'save', 'delete'] },
+          { permission: 'device-category', actions: ['query', 'save', 'delete'] },
+          { permission: 'device-instance', actions: ['query', 'save', 'delete'] },
+          {
+            permission: 'user',
+            actions: ['query', 'save', 'update-self-info', 'update-self-pwd', 'delete'],
+          },
+          { permission: 'device-product', actions: ['query', 'save', 'delete'] },
+        ],
+        buttons: [
           {
             id: 'view',
             name: '查看',
@@ -1265,23 +1318,13 @@ export default [
             permissions: [{ permission: 'organization', actions: ['query', 'save'] }],
           },
         ],
-        buttons: [
-          { permission: 'assets-bind', actions: ['bind', 'unbind', 'query', 'permission'] },
-          { permission: 'role', actions: ['query', 'save', 'delete'] },
-          { permission: 'device-category', actions: ['query', 'save', 'delete'] },
-          { permission: 'device-instance', actions: ['query', 'save', 'delete'] },
-          {
-            permission: 'user',
-            actions: ['query', 'save', 'update-self-info', 'update-self-pwd', 'delete'],
-          },
-          { permission: 'device-product', actions: ['query', 'save', 'delete'] },
-        ],
       },
       {
         code: 'system/Role',
         name: '角色管理',
         parentId: '3',
         id: '3-4',
+        sortIndex: 4,
         url: '/system/Role',
         icon: 'icon-jiaoseguanli',
         permissions: [
@@ -1324,6 +1367,7 @@ export default [
         name: '菜单管理',
         parentId: '3',
         id: '3-5',
+        sortIndex: 5,
         url: '/system/Menu',
         icon: 'icon-caidanguanli',
         permissions: [
@@ -1376,6 +1420,7 @@ export default [
         name: '权限管理',
         parentId: '3',
         id: '3-6',
+        sortIndex: 6,
         url: '/system/Permission',
         icon: 'icon-quanxianguanli',
         permissions: [
@@ -1430,6 +1475,7 @@ export default [
         name: '第三方平台',
         parentId: '3',
         id: '3-7',
+        sortIndex: 7,
         url: '/system/platforms',
         icon: 'icon-xitongguanli1',
         permissions: [{ permission: 'open-api', actions: ['query', 'save', 'delete'] }],
@@ -1462,6 +1508,7 @@ export default [
         name: '关系配置',
         parentId: '3',
         id: '3-8',
+        sortIndex: 8,
         url: '/system/Relationship',
         icon: 'icon-renyuan',
         permissions: [{ permission: 'relation', actions: ['query', 'save', 'delete'] }],
@@ -1489,6 +1536,7 @@ export default [
         name: '数据源管理',
         parentId: '3',
         id: '3-9',
+        sortIndex: 9,
         url: '/system/DataSource',
         icon: 'icon-shebei',
         permissions: [],
@@ -1525,6 +1573,7 @@ export default [
         name: 'API配置',
         parentId: '3',
         id: '3-10',
+        sortIndex: 10,
         url: '/system/Api',
         icon: 'icon-rizhifuwu',
         permissions: [{ permission: 'open-api', actions: ['query'] }],

+ 16 - 2
src/pages/system/Menu/Setting/index.tsx

@@ -7,7 +7,7 @@ import {
 } from '@ant-design/icons';
 import Tree from './tree';
 import './index.less';
-import { Button, message, Tooltip } from 'antd';
+import {Button, message, Modal, Tooltip} from 'antd';
 import BaseTreeData from './baseMenu';
 import { useEffect, useState } from 'react';
 import { HTML5Backend } from 'react-dnd-html5-backend';
@@ -32,6 +32,7 @@ export default observer(() => {
   const { minHeight } = useDomFullHeight(`.menu-setting-warp`);
   const [baseMenu, setBaseMenu] = useState<any[]>(BaseTreeData);
   const [loading, setLoading] = useState(false);
+  const [visible, setVisible] = useState(false);
 
   const finedObject = (
     data: any[],
@@ -180,6 +181,19 @@ export default observer(() => {
 
   return (
     <PageContainer>
+      <Modal
+        title={'一键拷贝'}
+        visible={visible}
+        onOk={() => {
+          MenuSettingModel.menuData = cloneDeep(baseMenu);
+          setVisible(false)
+        }}
+        onCancel={() => {
+          setVisible(false)
+        }}
+      >
+        源数据将会覆盖当前的系统菜单数据,确定要一键拷贝吗?
+      </Modal>
       <div className={'menu-setting-warp'} style={{ minHeight }}>
         <div className={'menu-setting-tip'}>
           <ExclamationCircleOutlined />
@@ -199,7 +213,7 @@ export default observer(() => {
                   type={'primary'}
                   ghost
                   onClick={() => {
-                    MenuSettingModel.menuData = cloneDeep(baseMenu);
+                    setVisible(true)
                   }}
                 >
                   一键拷贝

+ 37 - 4
src/pages/system/Menu/Setting/tree.tsx

@@ -2,7 +2,7 @@ import { Input, Tree } from 'antd';
 import { SearchOutlined } from '@ant-design/icons';
 import DragItem from '@/pages/system/Menu/Setting/dragItem';
 import { useDrop } from 'react-dnd';
-import { useEffect, useState } from 'react';
+import {useEffect, useState} from 'react';
 import type { TreeProps } from 'antd';
 import { cloneDeep, debounce } from 'lodash';
 import './DragItem.less';
@@ -21,15 +21,24 @@ export const DragType = 'DragBox';
 
 const { TreeNode } = Tree;
 
+const defaultExpandedKeys = ['iot', 'media', 'system', 'device', 'link', 'link/Channel', 'rule-engine/Alarm', 'Northbound', 'rule-engine']
+
 export default (props: TreeBodyProps) => {
   const [newData, setNewData] = useState(props.treeData);
   const [searchKeys, setSearchKeys] = useState<(string | number)[]>([]);
   const [expandedKeys, setExpandedKeys] = useState<(string | number)[]>([]);
+  const [autoExpandParent, setAutoExpandParent] = useState(true);
 
   useEffect(() => {
     setNewData(cloneDeep(props.treeData));
   }, [props.treeData]);
 
+  useEffect(() => {
+    setTimeout(() => {
+      setExpandedKeys(defaultExpandedKeys)
+    }, 300)
+  }, [])
+
   const [, drop] = useDrop(() => ({
     accept: DragType,
     drop(item: any, monitor) {
@@ -91,6 +100,21 @@ export default (props: TreeBodyProps) => {
     });
   };
 
+  const getParentKey = (key: string | number, data: any): string => {
+    let parentKey: string;
+    data.forEach((item: any) => {
+      if (item.children) {
+        if (item.children.some((cItem: any) => cItem.code === key)) {
+          parentKey = item.code
+        } else if (!!getParentKey(key, item.children)) {
+          parentKey = getParentKey(key, item.children)
+        }
+      }
+    })
+    // @ts-ignore
+    return parentKey
+  }
+
   const findAllItem = (data: any[], value: string): string[] => {
     return data.reduce((pre, next) => {
       const childrenKeys = next.children ? findAllItem(next.children, value) : [];
@@ -104,12 +128,17 @@ export default (props: TreeBodyProps) => {
     const value = e.target.value;
 
     if (value) {
-      const sKeys = findAllItem(props.treeData, value);
-      setSearchKeys(sKeys);
-      setExpandedKeys(sKeys);
+
+      const newKeys = findAllItem(props.treeData, value);
+      const newExpandedKeys = newKeys.map(key => {
+        return getParentKey(key, props.treeData)
+      })
+      setSearchKeys(newKeys);
+      setExpandedKeys(newExpandedKeys);
     } else {
       setSearchKeys([]);
     }
+    setAutoExpandParent(true)
   };
 
   return (
@@ -128,7 +157,9 @@ export default (props: TreeBodyProps) => {
             expandedKeys={expandedKeys}
             onExpand={(_expandedKeys) => {
               setExpandedKeys(_expandedKeys);
+              setAutoExpandParent(false)
             }}
+            autoExpandParent={autoExpandParent}
           >
             {createTreeNode(newData, props.droppableId)}
           </Tree>
@@ -139,7 +170,9 @@ export default (props: TreeBodyProps) => {
             expandedKeys={expandedKeys}
             onExpand={(_expandedKeys) => {
               setExpandedKeys(_expandedKeys);
+              setAutoExpandParent(false)
             }}
+            autoExpandParent={autoExpandParent}
             draggable={{
               icon: false,
             }}

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

@@ -261,7 +261,7 @@ export default observer(() => {
         search={false}
         params={param}
         request={async (params) => {
-          const response = await service.queryMenuThree({ ...params, paging: false });
+          const response = await service.queryMenuThree({ ...params, sorts: [{ name: 'sortIndex', order: 'asc'}], paging: false });
           return {
             code: response.message,
             result: {
@@ -290,7 +290,7 @@ export default observer(() => {
           </PermissionButton>,
           <PermissionButton
             style={{ marginLeft: 12 }}
-            isPermission={permission.action}
+            isPermission={permission.add}
             onClick={() => {
               history.push(getMenuPathByCode('system/Menu/Setting'));
             }}

+ 0 - 355
src/pages/system/OpenAPI/index.tsx

@@ -1,355 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import React, { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import type { OpenApiItem } from '@/pages/system/OpenAPI/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import { CurdModel } from '@/components/BaseCrud/model';
-import { Drawer, Popconfirm, Tooltip } from 'antd';
-import {
-  CloseCircleOutlined,
-  EditOutlined,
-  KeyOutlined,
-  PlayCircleOutlined,
-} from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import BaseService from '@/utils/BaseService';
-import autzModel from '@/components/Authorization/autz';
-import Authorization from '@/components/Authorization';
-import { observer } from '@formily/react';
-import type { ISchema } from '@formily/json-schema';
-import _ from 'lodash';
-import { onlyMessage } from '@/utils/util';
-
-const service = new BaseService<OpenApiItem>('open-api');
-const OpenAPI: React.FC = observer(() => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<OpenApiItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      title: 'clientId',
-      dataIndex: 'id',
-      sorter: true,
-      defaultSortOrder: 'ascend',
-      width: 200,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-      dataIndex: 'clientName',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.system.openApi.username',
-        defaultMessage: '用户名',
-      }),
-      dataIndex: 'username',
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      dataIndex: 'status',
-      filters: true,
-      align: 'center',
-      renderText: (text: any) => text.text,
-      valueType: 'select',
-      hideInForm: true,
-      onFilter: true,
-      valueEnum: {
-        default: {
-          text: intl.formatMessage({
-            id: 'pages.searchTable.titleStatus.all',
-            defaultMessage: '全部',
-          }),
-          status: 'Default',
-        },
-        '1': {
-          text: intl.formatMessage({
-            id: 'pages.searchTable.titleStatus.normal',
-            defaultMessage: '正常',
-          }),
-          status: '1',
-        },
-        '0': {
-          text: intl.formatMessage({
-            id: 'pages.searchTable.titleStatus.disable',
-            defaultMessage: '禁用',
-          }),
-          status: '0',
-        },
-      },
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a
-          key="editable"
-          onClick={() => {
-            const temp = _.omit(record, ['createTime', 'creatorId', 'status']);
-            CurdModel.update(temp);
-          }}
-        >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a
-          key="auth"
-          onClick={() => {
-            autzModel.autzTarget.id = record.id;
-            autzModel.autzTarget.name = record.clientName;
-            autzModel.visible = true;
-          }}
-        >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.authorize',
-              defaultMessage: '授权',
-            })}
-          >
-            <KeyOutlined />
-          </Tooltip>
-        </a>,
-        <a key="state">
-          <Popconfirm
-            title={intl.formatMessage({
-              id: 'pages.data.option.disabled.tips',
-              defaultMessage: '确认禁用?',
-            })}
-            onConfirm={async () => {
-              await service.update({
-                id: record.id,
-                status: record.status ? 0 : 1,
-              });
-              onlyMessage(
-                intl.formatMessage({
-                  id: 'pages.data.option.success',
-                  defaultMessage: '操作成功!',
-                }),
-              );
-              actionRef.current?.reload();
-            }}
-          >
-            <Tooltip
-              title={intl.formatMessage({
-                id: `pages.data.option.${record.status ? 'disabled' : 'enabled'}`,
-                defaultMessage: record.status ? '禁用' : '启用',
-              })}
-            >
-              {record.status ? <CloseCircleOutlined /> : <PlayCircleOutlined />}
-            </Tooltip>
-          </Popconfirm>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema: ISchema = {
-    type: 'object',
-    properties: {
-      layout: {
-        type: 'void',
-        'x-component': 'FormGrid',
-        'x-component-props': {
-          maxColumns: 2,
-        },
-        properties: {
-          clientName: {
-            title: intl.formatMessage({
-              id: 'pages.table.name',
-              defaultMessage: '名称',
-            }),
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              labelCol: 6,
-              wrapperCol: 18,
-            },
-            name: 'clientName',
-          },
-          enableOAuth2: {
-            type: 'boolean',
-            title: 'OAuth2',
-            'x-decorator': 'FormItem',
-            'x-component': 'Switch',
-            'x-decorator-props': {
-              labelCol: 6,
-              wrapperCol: 18,
-            },
-            name: 'enableOAuth2',
-          },
-          id: {
-            title: 'clientId',
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              labelCol: 6,
-              wrapperCol: 18,
-            },
-            name: 'clientId',
-          },
-          secureKey: {
-            title: 'secureKey',
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              labelCol: 6,
-              wrapperCol: 18,
-            },
-            name: 'secureKey',
-          },
-          username: {
-            title: intl.formatMessage({
-              id: 'pages.system.openApi.username',
-              defaultMessage: '用户名',
-            }),
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              labelWrap: false,
-              wrapperWrap: false,
-              labelCol: 6,
-              wrapperCol: 18,
-            },
-            name: 'username',
-          },
-          password: {
-            title: intl.formatMessage({
-              id: 'pages.system.openApi.password',
-              defaultMessage: '密码',
-            }),
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              labelCol: 6,
-              wrapperCol: 18,
-            },
-            name: 'password',
-          },
-          redirectUrl: {
-            title: 'redirectUrl',
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-visible': false,
-            'x-decorator-props': {
-              fullness: false,
-              gridSpan: 2,
-              labelAlign: 'right',
-              wrapperAlign: 'left',
-              labelCol: 3,
-              wrapperCol: 21,
-            },
-            name: 'redirectUrl',
-            'x-reactions': {
-              dependencies: [
-                {
-                  property: 'value',
-                  source: '.enableOAuth2',
-                  name: 'enableOAuth2',
-                },
-              ],
-              fulfill: {
-                state: {
-                  visible: '{{$deps.enableOAuth2}}',
-                },
-              },
-            },
-          },
-        },
-      },
-      ipWhiteList: {
-        title: intl.formatMessage({
-          id: 'pages.system.openApi.ipWhileList',
-          defaultMessage: 'IP白名单',
-        }),
-        type: 'string',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
-        'x-component-props': {},
-        'x-decorator-props': {
-          labelCol: 3,
-          wrapperCol: 21,
-        },
-        name: 'ipWhiteList',
-      },
-      description: {
-        title: intl.formatMessage({
-          id: 'pages.table.describe',
-          defaultMessage: '描述',
-        }),
-        type: 'string',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
-        'x-component-props': {},
-        'x-decorator-props': {
-          labelCol: 3,
-          wrapperCol: 21,
-        },
-        name: 'description',
-      },
-    },
-  };
-
-  return (
-    <PageContainer>
-      <BaseCrud<OpenApiItem>
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.system.openApi',
-          defaultMessage: '第三方平台',
-        })}
-        schema={schema}
-        modelConfig={{ width: 900 }}
-        actionRef={actionRef}
-      />
-      <Drawer
-        maskClosable={false}
-        title={intl.formatMessage({
-          id: 'pages.data.option.authorize',
-          defaultMessage: '授权',
-        })}
-        width="70vw"
-        visible={autzModel.visible}
-        onClose={() => {
-          autzModel.visible = false;
-        }}
-      >
-        <Authorization
-          close={() => {
-            autzModel.visible = false;
-          }}
-          target={autzModel.autzTarget}
-        />
-      </Drawer>
-    </PageContainer>
-  );
-});
-
-export default OpenAPI;

+ 0 - 16
src/pages/system/OpenAPI/typings.d.ts

@@ -1,16 +0,0 @@
-export type OpenApiItem = {
-  id: string;
-  username?: string;
-  userId?: string;
-  password: string;
-  clientName: string;
-  createTime: number;
-  creatorId: string;
-  description: string;
-  ipWhiteList: string;
-  secureKey: string;
-  signature: string;
-  enableOAuth2: boolean;
-  redirectUrl: string;
-  status: number;
-};

+ 51 - 33
src/pages/user/Login/index.tsx

@@ -160,39 +160,57 @@ const Login: React.FC = () => {
 
   const doLogin = async (data: LoginParam) => {
     setLoading(true);
-    Service.login({ expires: loginRef.current.expires, verifyKey: captcha.key, ...data }).subscribe(
-      {
-        next: async (userInfo) => {
-          Token.set(userInfo.token);
-          const userRef: any = await fetchUserInfo();
-          if (userRef?.user?.username === 'admin') {
-            const initRef = await Service.initPage();
-            if (initRef.status === 200 && !initRef.result.length) {
-              window.location.href = '/#/init-home';
-              setLoading(false);
-              return;
-            }
-          }
-          // goto();
-          window.location.href = '/';
-          setLoading(false);
-        },
-        error: () => {
-          message.error(
-            intl.formatMessage({
-              id: 'pages.login.failure',
-              defaultMessage: '登录失败,请重试!',
-            }),
-          );
-          getCode();
-          // setLoading(false);
-        },
-        complete: () => {
-          // getCode();
-          // setLoading(false);
-        },
-      },
-    );
+    const res = await Service.login2({ expires: loginRef.current.expires, verifyKey: captcha.key, ...data })
+    setLoading(false)
+    if (res.status === 200) {
+      const userInfo = res.result
+      Token.set(userInfo.token);
+      const userRef: any = await fetchUserInfo();
+      if (userRef?.user?.username === 'admin') {
+        const initRef = await Service.initPage()
+        if (initRef.status === 200 && !initRef.result.length) {
+          window.location.href = '/#/init-home';
+          return
+        }
+      }
+      window.location.href = '/';
+    } else {
+      getCode();
+      setLoading(false);
+    }
+    // Service.login({ expires: loginRef.current.expires, verifyKey: captcha.key, ...data }).subscribe(
+    //   {
+    //     next: async (userInfo) => {
+    //       Token.set(userInfo.token);
+    //       const userRef: any = await fetchUserInfo();
+    //       if (userRef?.user?.username === 'admin') {
+    //         const initRef = await Service.initPage()
+    //         if (initRef.status === 200 && !initRef.result.length) {
+    //           window.location.href = '/#/init-home';
+    //           setLoading(false);
+    //           return
+    //         }
+    //       }
+    //       // goto();
+    //       window.location.href = '/';
+    //       setLoading(false);
+    //     },
+    //     error: () => {
+    //       message.error(
+    //         intl.formatMessage({
+    //           id: 'pages.login.failure',
+    //           defaultMessage: '登录失败,请重试!',
+    //         }),
+    //       );
+    //       getCode();
+    //       // setLoading(false);
+    //     },
+    //     complete: () => {
+    //       // getCode();
+    //       // setLoading(false);
+    //     },
+    //   },
+    // );
   };
   return (
     <Spin spinning={loading} delay={500}>

+ 4 - 0
src/pages/user/Login/service.ts

@@ -37,6 +37,10 @@ const Service = {
         map((resp) => resp.result),
       ),
     ),
+  login2: (data: LoginParam) => request(`/${SystemConst.API_BASE}/authorize/login`, {
+    method: 'POST',
+    data,
+  }),
 
   queryCurrent: () =>
     request(`/${SystemConst.API_BASE}/authorize/me`, {

+ 0 - 104
src/pages/visualization/Category/index.tsx

@@ -1,104 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import type { CategoryItem } from '@/pages/visualization/Category/typings';
-import { Tooltip } from 'antd';
-import { EditOutlined, MinusOutlined, PlusOutlined } from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-export const service = new BaseService<CategoryItem>('visualization/catalog');
-const Category = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<CategoryItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'id',
-      title: 'ID',
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'description',
-      title: intl.formatMessage({
-        id: 'pages.table.describe',
-        defaultMessage: '描述',
-      }),
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a
-          onClick={() => {
-            console.log(record);
-          }}
-        >
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.visualization.option.addClass',
-              defaultMessage: '添加子分类',
-            })}
-          >
-            <PlusOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.visualization.category',
-          defaultMessage: '分类管理',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Category;

+ 0 - 10
src/pages/visualization/Category/typings.d.ts

@@ -1,10 +0,0 @@
-import type { BaseItem } from '@/utils/typings';
-
-type CategoryItem = {
-  level: number;
-  parentId: string;
-  description: string;
-  path: string;
-  sortIndex: number;
-  children: CategoryItem[];
-} & BaseItem;

+ 0 - 142
src/pages/visualization/Configuration/index.tsx

@@ -1,142 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import type { ConfigurationItem } from '@/pages/visualization/Configuration/typings';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Tooltip } from 'antd';
-import {
-  ArrowDownOutlined,
-  BarsOutlined,
-  CopyOutlined,
-  EditOutlined,
-  EyeOutlined,
-  MinusOutlined,
-} from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-export const service = new BaseService<ConfigurationItem>('visualization');
-const Configuration = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<ConfigurationItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
-    },
-    {
-      dataIndex: 'description',
-      title: intl.formatMessage({
-        id: 'pages.table.describe',
-        defaultMessage: '描述',
-      }),
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.preview',
-              defaultMessage: '预览',
-            })}
-          >
-            <EyeOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
-            })}
-          >
-            <ArrowDownOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.visualization.option.copy',
-              defaultMessage: '复制',
-            })}
-          >
-            <CopyOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.record',
-              defaultMessage: '通知记录',
-            })}
-          >
-            <BarsOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud
-        defaultParams={{ type: 'vis_configuration' }}
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.visualization.configuration',
-          defaultMessage: '组态管理',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Configuration;

+ 0 - 3
src/pages/visualization/Configuration/typings.d.ts

@@ -1,3 +0,0 @@
-import type { ScreenItem } from '@/pages/visualization/Screen/typings';
-
-type ConfigurationItem = ScreenItem;

+ 0 - 144
src/pages/visualization/Screen/index.tsx

@@ -1,144 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import BaseService from '@/utils/BaseService';
-import type { ScreenItem } from '@/pages/visualization/Screen/typings';
-import { useRef } from 'react';
-import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import type { ConfigurationItem } from '@/pages/visualization/Configuration/typings';
-import { Tooltip } from 'antd';
-import {
-  ArrowDownOutlined,
-  BarsOutlined,
-  CopyOutlined,
-  EditOutlined,
-  EyeOutlined,
-  MinusOutlined,
-} from '@ant-design/icons';
-import BaseCrud from '@/components/BaseCrud';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-export const service = new BaseService<ScreenItem>('visualization');
-
-const Screen = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-
-  const columns: ProColumns<ConfigurationItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
-      dataIndex: 'name',
-      title: intl.formatMessage({
-        id: 'pages.table.name',
-        defaultMessage: '名称',
-      }),
-    },
-    {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
-    },
-    {
-      dataIndex: 'description',
-      title: intl.formatMessage({
-        id: 'pages.table.describe',
-        defaultMessage: '描述',
-      }),
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.data.option',
-        defaultMessage: '操作',
-      }),
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <a onClick={() => console.log(record)}>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          >
-            <EditOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.preview',
-              defaultMessage: '预览',
-            })}
-          >
-            <EyeOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.download',
-              defaultMessage: '下载配置',
-            })}
-          >
-            <ArrowDownOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.visualization.option.copy',
-              defaultMessage: '复制',
-            })}
-          >
-            <CopyOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.record',
-              defaultMessage: '通知记录',
-            })}
-          >
-            <BarsOutlined />
-          </Tooltip>
-        </a>,
-        <a>
-          <Tooltip
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          >
-            <MinusOutlined />
-          </Tooltip>
-        </a>,
-      ],
-    },
-  ];
-
-  const schema = {};
-
-  return (
-    <PageContainer>
-      <BaseCrud
-        defaultParams={{ type: 'big_screen' }}
-        columns={columns}
-        service={service}
-        title={intl.formatMessage({
-          id: 'pages.visualization.screen',
-          defaultMessage: '大屏管理',
-        })}
-        schema={schema}
-        actionRef={actionRef}
-      />
-    </PageContainer>
-  );
-};
-export default Screen;

+ 0 - 9
src/pages/visualization/Screen/typings.d.ts

@@ -1,9 +0,0 @@
-import type { BaseItem, State } from '@/utils/typings';
-
-type ScreenItem = {
-  catalogId: string;
-  metadata: string;
-  state: State;
-  target: string;
-  type: string;
-} & BaseItem;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 49 - 2312
yarn.lock