Procházet zdrojové kódy

feat(cloud):add cloud

crush před 4 roky
rodič
revize
6a8d63be8d

+ 67 - 67
config/routes.ts

@@ -235,10 +235,10 @@
     path: '/visualization',
     name: 'visualization',
     icon: 'crown',
-    routes:[
+    routes: [
       {
         path: '/visualization',
-        redirect: '/visualization/category'
+        redirect: '/visualization/category',
       },
       {
         path: '/visualization/category',
@@ -258,24 +258,24 @@
         icon: 'smile',
         component: './visualization/configuration',
       },
-    ]
+    ],
   },
   {
     path: '/simulator',
     name: 'simulator',
     icon: 'crown',
-    routes:[
+    routes: [
       {
-        path:'/simulator',
+        path: '/simulator',
         redirect: '/simulator/device',
       },
       {
-        path:'/simulator/device',
-        name:'device',
-        icon:'smile',
-        component: './simulator/Device'
-      }
-    ]
+        path: '/simulator/device',
+        name: 'device',
+        icon: 'smile',
+        component: './simulator/Device',
+      },
+    ],
   },
   {
     path: '/log',
@@ -301,97 +301,97 @@
     ],
   },
   {
-    path:'/cloud',
-    name:'cloud',
-    icon:"crown",
+    path: '/cloud',
+    name: 'cloud',
+    icon: 'crown',
     routes: [
       {
-        path:'/cloud',
-        redirect: '/cloud/duer'
+        path: '/cloud',
+        redirect: '/cloud/duer',
       },
       {
-        path:'/cloud/duer',
-        name:'DuerOS',
-        icon:'smile',
+        path: '/cloud/duer',
+        name: 'DuerOS',
+        icon: 'smile',
         component: './cloud/DuerOS',
       },
       {
-        path:'/cloud/aliyun',
-        name:'aliyun',
-        icon:'smile',
-        component: './cloud/Aliyun'
+        path: '/cloud/aliyun',
+        name: 'aliyun',
+        icon: 'smile',
+        component: './cloud/Aliyun',
       },
       {
-        path:'/cloud/ctwing',
-        name:'ctwing',
-        icon:'smile',
-        component: './cloud/Ctwing'
+        path: '/cloud/onenet',
+        name: 'onenet',
+        icon: 'smile',
+        component: './cloud/Onenet',
       },
       {
-        path:'/cloud/onenet',
-        name:'onenet',
-        icon:'smile',
-        component: './cloud/Onenet'
-      }
-    ]
+        path: '/cloud/ctwing',
+        name: 'ctwing',
+        icon: 'smile',
+        component: './cloud/Ctwing',
+      },
+    ],
   },
   {
-    path:'/media',
-    name:'media',
-    icon:'crown',
-    routes:[
+    path: '/media',
+    name: 'media',
+    icon: 'crown',
+    routes: [
       {
-        path:'/media',
+        path: '/media',
         redirect: '/media/config',
       },
       {
-        path:'/media/config',
-        name:'config',
-        icon:'smile',
+        path: '/media/config',
+        name: 'config',
+        icon: 'smile',
         component: './media/Config',
       },
       {
-        path:'/media/device',
-        name:'device',
-        icon:'smile',
-        component: './media/device'
+        path: '/media/device',
+        name: 'device',
+        icon: 'smile',
+        component: './media/device',
       },
       {
-        path:'/media/reveal',
-        name:'reveal',
-        icon:'smile',
+        path: '/media/reveal',
+        name: 'reveal',
+        icon: 'smile',
         component: './media/reveal',
       },
       {
-        path:'/media/cascade',
-        name:'cascade',
-        icon:'smile',
+        path: '/media/cascade',
+        name: 'cascade',
+        icon: 'smile',
         component: './media/Cascade',
-      }
-      ]
+      },
+    ],
   },
   {
-    path:'/edge',
-    name:'edge',
-    icon:"crown",
+    path: '/edge',
+    name: 'edge',
+    icon: 'crown',
     routes: [
       {
-        path:'/edge',
-        redirect: '/edge/product'
+        path: '/edge',
+        redirect: '/edge/product',
       },
       {
-        path:'/edge/product',
-        name:'product',
-        icon:'smile',
+        path: '/edge/product',
+        name: 'product',
+        icon: 'smile',
         component: './edge/Product',
       },
       {
-        path:'/edge/device',
-        name:'device',
-        icon:'smile',
-        component: './edge/Device'
-      }
-    ]
+        path: '/edge/device',
+        name: 'device',
+        icon: 'smile',
+        component: './edge/Device',
+      },
+    ],
   },
   {
     path: '/',

+ 124 - 2
src/pages/cloud/Aliyun/index.tsx

@@ -1,6 +1,128 @@
-import { PageContainer } from '@ant-design/pro-layout';
+import {PageContainer} from '@ant-design/pro-layout';
+import BaseService from '@/utils/BaseService';
+import {useRef} from 'react';
+import {ActionType, ProColumns} from '@jetlinks/pro-table';
+import {useIntl} from '@@/plugin-locale/localeExports';
+import BaseCrud from '@/components/BaseCrud';
+import {message,Popconfirm, Tooltip} from 'antd';
+import { CloseCircleOutlined, EditOutlined, EyeOutlined, MinusOutlined, PlayCircleOutlined } from '@ant-design/icons';
+import { CurdModel } from '@/components/BaseCrud/model';
+
+export const service = new BaseService<AliyunItem>('device/aliyun/bridge');
+
+
+const stateIconMap = {
+  enabled: <CloseCircleOutlined />,
+  disabled: <PlayCircleOutlined />,
+};
 
 const Aliyun = () => {
-  return <PageContainer>Aliyun</PageContainer>;
+  const intl = useIntl();
+  const actionRef = useRef<ActionType>();
+  const columns: ProColumns<AliyunItem>[] = [
+    {
+      dataIndex: 'index',
+      valueType: 'indexBorder',
+      width: 48,
+    },
+    {
+      title: '名称',
+      align: 'center',
+      dataIndex: 'name'
+    },
+    {
+      title: '说明',
+      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);
+              message.success(
+                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;

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

@@ -1,4 +1,25 @@
-type Item = {
+type AliyunItem = {
   id: string;
   name: string;
+  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: {
+    text: string;
+    value: string;
+  };
 };

+ 111 - 1
src/pages/cloud/Ctwing/index.tsx

@@ -1,6 +1,116 @@
+import BaseCrud from '@/components/BaseCrud';
+import { CurdModel } from '@/components/BaseCrud/model';
+import BaseService from '@/utils/BaseService';
+import { CloseCircleOutlined, EditOutlined, MinusOutlined, PlayCircleOutlined } from '@ant-design/icons';
 import { PageContainer } from '@ant-design/pro-layout';
+import { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { message, Popconfirm, Tooltip } from 'antd';
+import { useRef } from 'react';
+import { useIntl } from '@@/plugin-locale/localeExports';
+
+export const service = new BaseService<CtwingItem>('ctwing/product');
+
+const stateIconMap = {
+  enabled: <CloseCircleOutlined />,
+  disabled: <PlayCircleOutlined />,
+};
 
 const Ctwing = () => {
-  return <PageContainer>Ctwing</PageContainer>;
+  const intl = useIntl();
+  const actionRef = useRef<ActionType>();
+  const columns: ProColumns<CtwingItem>[] = [
+    {
+      dataIndex: 'index',
+      valueType: 'indexBorder',
+      width: 48,
+    },
+    {
+      title: '名称',
+      align: 'center',
+      dataIndex: 'name'
+  },
+  {
+    title: intl.formatMessage({
+      id: 'pages.searchTable.titleStatus',
+      defaultMessage: '状态',
+    }),
+    dataIndex: 'state',
+    render: (value: any) => value.text,
+  },
+  {
+      title: '说明',
+      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);
+            message.success(
+              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;

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

@@ -1,4 +1,12 @@
-type Item = {
+type CtwingItem = {
+  apiAddress: string;
+  appKey: string;
+  appSecret: string;
   id: string;
+  masterKey: string;
   name: string;
+  state: {
+    text: string;
+    value: string;
+  };
 };

+ 117 - 1
src/pages/cloud/Onenet/index.tsx

@@ -1,6 +1,122 @@
 import { PageContainer } from '@ant-design/pro-layout';
+import BaseService from '@/utils/BaseService';
+import {useIntl} from '@@/plugin-locale/localeExports';
+import {useRef} from 'react';
+import { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { message, Popconfirm, Tooltip } from 'antd';
+import { CloseCircleOutlined, EditOutlined, MinusOutlined, PlayCircleOutlined } from '@ant-design/icons';
+import BaseCrud from '@/components/BaseCrud';
+import { CurdModel } from '@/components/BaseCrud/model';
+
+export const service = new BaseService<OnenetItem>('one-net/product');
+
+const stateIconMap = {
+  enabled: <CloseCircleOutlined />,
+  disabled: <PlayCircleOutlined />,
+};
 
 const Onenet = () => {
-  return <PageContainer>Onenet</PageContainer>;
+  const intl = useIntl();
+  const actionRef = useRef<ActionType>();
+  const columns: ProColumns<OnenetItem>[] = [
+    {
+      dataIndex: 'index',
+      valueType: 'indexBorder',
+      width: 48,
+    },
+      {
+          title: '名称',
+          align: 'center',
+          dataIndex: 'name'
+      },
+      {
+          title: '状态',
+          align: 'center',
+          dataIndex: 'state.text',
+      },
+      {
+          title: '说明',
+          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);
+                message.success(
+                  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;

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

@@ -1,4 +1,13 @@
-type Item = {
+type OnenetItem = {
+  aesKey: string;
+  apiAddress: string;
+  apiKey: string;
+  description: string;
   id: string;
   name: string;
+  state: {
+    text: string;
+    value: string;
+  };
+  validateToken: string;
 };

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

@@ -74,7 +74,7 @@ const DataSource = () => {
     {
       title: intl.formatMessage({
         id: 'pages.searchTable.titleStatus',
-        defaultMessage: '说明',
+        defaultMessage: '状态',
       }),
       dataIndex: 'state',
       render: (value: any) => value.text,
@@ -82,7 +82,7 @@ const DataSource = () => {
     {
       title: intl.formatMessage({
         id:'pages.data.option',
-        defaultMessage: '说明',
+        defaultMessage: '操作',
       }),
       valueType: 'option',
       align: 'center',

+ 3 - 0
src/utils/BaseService.ts

@@ -10,6 +10,9 @@ interface IBaseService<T> {
 }
 
 class BaseService<T> implements IBaseService<T> {
+  changeStatus(id: string, state: string) {
+    throw new Error('Method not implemented.');
+  }
   protected uri: string;
 
   protected headers = {