lind 3 лет назад
Родитель
Сommit
97caae2416
32 измененных файлов с 411 добавлено и 250 удалено
  1. 4 4
      src/components/ProTableCard/CardItems/protocol.tsx
  2. 25 14
      src/components/SearchComponent/index.tsx
  3. 4 4
      src/hooks/route/useHistory.tsx
  4. 3 3
      src/hooks/route/useLocation.tsx
  5. 36 11
      src/pages/Log/Access/index.tsx
  6. 11 11
      src/pages/device/Product/Detail/Access/index.tsx
  7. 7 7
      src/pages/device/Product/Detail/BaseInfo/index.tsx
  8. 11 11
      src/pages/device/Product/Detail/index.tsx
  9. 13 13
      src/pages/device/Product/index.tsx
  10. 20 7
      src/pages/link/AccessConfig/Detail/Access/index.tsx
  11. 10 10
      src/pages/link/AccessConfig/Detail/Media/index.tsx
  12. 5 5
      src/pages/link/AccessConfig/Detail/index.tsx
  13. 9 9
      src/pages/link/Certificate/index.tsx
  14. 12 12
      src/pages/link/Gateway/index.tsx
  15. 25 8
      src/pages/link/Protocol/index.tsx
  16. 9 9
      src/pages/link/Protocol/save/index.tsx
  17. 3 2
      src/pages/link/Type/Detail/index.tsx
  18. 30 0
      src/pages/link/Type/index.tsx
  19. 11 0
      src/pages/media/Cascade/Channel/index.tsx
  20. 23 10
      src/pages/media/Device/Channel/index.tsx
  21. 8 8
      src/pages/media/Device/Save/ProviderSelect.tsx
  22. 4 4
      src/pages/media/Device/Save/SaveProduct.tsx
  23. 8 8
      src/pages/media/Device/Save/index.tsx
  24. 10 9
      src/pages/media/Device/index.tsx
  25. 7 1
      src/pages/notice/Config/Debug/index.tsx
  26. 8 4
      src/pages/notice/Template/Debug/index.tsx
  27. 13 1
      src/pages/notice/Template/Detail/index.tsx
  28. 17 12
      src/pages/system/Menu/index.tsx
  29. 17 11
      src/pages/system/Permission/index.tsx
  30. 12 12
      src/pages/system/Role/index.tsx
  31. 10 10
      src/pages/system/Tenant/index.tsx
  32. 26 20
      src/pages/system/User/index.tsx

+ 4 - 4
src/components/ProTableCard/CardItems/protocol.tsx

@@ -1,10 +1,10 @@
 import React from 'react';
-import type {ProtocolItem} from '@/pages/link/Protocol/typings';
-import {StatusColorEnum} from '@/components/BadgeStatus';
-import {TableCard} from '@/components';
+import type { ProtocolItem } from '@/pages/link/Protocol/typings';
+import { StatusColorEnum } from '@/components/BadgeStatus';
+import { TableCard } from '@/components';
 import '@/style/common.less';
 import '../index.less';
-import {Col, Row, Tooltip} from 'antd';
+import { Col, Row, Tooltip } from 'antd';
 
 export interface ProcotolCardProps extends ProtocolItem {
   detail?: React.ReactNode;

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

@@ -1,5 +1,5 @@
-import type {ISchema} from '@formily/json-schema';
-import {createSchemaField} from '@formily/react';
+import type { ISchema } from '@formily/json-schema';
+import { createSchemaField } from '@formily/react';
 import {
   ArrayItems,
   DatePicker,
@@ -13,20 +13,26 @@ import {
   Select,
   Space,
 } from '@formily/antd';
-import type {Field, FieldDataSource} from '@formily/core';
-import {createForm, onFieldReact} from '@formily/core';
+import type { Field, FieldDataSource } from '@formily/core';
+import { createForm, onFieldReact } from '@formily/core';
 import GroupNameControl from '@/components/SearchComponent/GroupNameControl';
-import {DeleteOutlined, DoubleRightOutlined, ReloadOutlined, SaveOutlined, SearchOutlined,} from '@ant-design/icons';
-import {Button, Card, Dropdown, Empty, Menu, message, Popover, Typography} from 'antd';
-import {useEffect, useMemo, useRef, useState} from 'react';
-import type {ProColumns} from '@jetlinks/pro-table';
-import type {EnumData} from '@/utils/typings';
+import {
+  DeleteOutlined,
+  DoubleRightOutlined,
+  ReloadOutlined,
+  SaveOutlined,
+  SearchOutlined,
+} from '@ant-design/icons';
+import { Button, Card, Dropdown, Empty, Menu, message, Popover, Typography } from 'antd';
+import { useEffect, useMemo, useRef, useState } from 'react';
+import type { ProColumns } from '@jetlinks/pro-table';
+import type { EnumData } from '@/utils/typings';
 import styles from './index.less';
 import Service from '@/components/SearchComponent/service';
 import _ from 'lodash';
-import {useIntl} from '@@/plugin-locale/localeExports';
+import { useIntl } from '@@/plugin-locale/localeExports';
 import classnames from 'classnames';
-import {randomString} from '@/utils/util';
+import { randomString } from '@/utils/util';
 
 const ui2Server = (source: SearchTermsUI): SearchTermsServer => [
   { terms: source.terms1 },
@@ -192,13 +198,18 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
                 state.componentProps = { showTime: true };
               });
               f.setFieldState(typeFiled.query('.termType'), async (state) => {
-                state.value = 'gt';
+                state.value = 'gte';
               });
             } else {
               f.setFieldState(typeFiled.query('.value'), async (state) => {
                 state.componentType = 'Input';
               });
             }
+            if (_column === 'id') {
+              f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                state.value = 'eq';
+              });
+            }
           });
         },
       }),
@@ -449,10 +460,10 @@ const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
   };
 
   useEffect(() => {
-    if (defaultParam) {
+    if (defaultParam || initParam) {
       handleSearch();
     }
-  }, []);
+  }, [defaultParam, initParam]);
 
   const handleSaveLog = async () => {
     const value = await form.submit<SearchTermsUI>();

+ 4 - 4
src/hooks/route/useHistory.tsx

@@ -1,7 +1,7 @@
-import {useHistory} from 'umi';
-import {useEffect, useState} from 'react';
-import type {LocationDescriptor, LocationState, Path} from 'history';
-import {model} from '@formily/reactive';
+import { useHistory } from 'umi';
+import { useEffect, useState } from 'react';
+import type { LocationDescriptor, LocationState, Path } from 'history';
+import { model } from '@formily/reactive';
 
 export const historyStateModel = model<{ state: any }>({ state: {} });
 

+ 3 - 3
src/hooks/route/useLocation.tsx

@@ -1,6 +1,6 @@
-import {useLocation} from 'umi';
-import {useEffect, useState} from 'react';
-import {historyStateModel} from '@/hooks/route/useHistory';
+import { useLocation } from 'umi';
+import { useEffect, useState } from 'react';
+import { historyStateModel } from '@/hooks/route/useHistory';
 
 const useLocations = () => {
   const umiLocation = useLocation();

+ 36 - 11
src/pages/Log/Access/index.tsx

@@ -37,17 +37,30 @@ const Access = () => {
       title: '请求方法',
       dataIndex: 'httpMethod',
       ellipsis: true,
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.description',
-        defaultMessage: '说明',
-      }),
-      dataIndex: 'describe',
-      ellipsis: true,
-      // render: (text, record) => {
-      //   return `${record.action}-${record.describe}`;
-      // },
+      valueType: 'select',
+      width: 80,
+      valueEnum: {
+        POST: {
+          text: 'POST',
+          status: 'POST',
+        },
+        GET: {
+          text: 'GET',
+          status: 'GET',
+        },
+        PATCH: {
+          text: 'PATCH',
+          status: 'PATCH',
+        },
+        DELETE: {
+          text: 'DELETE',
+          status: 'DELETE',
+        },
+        PUT: {
+          text: 'PUT',
+          status: 'PUT',
+        },
+      },
     },
     {
       title: intl.formatMessage({
@@ -67,6 +80,7 @@ const Access = () => {
         id: 'pages.log.access.requestTimeConsuming',
         defaultMessage: '请求耗时',
       }),
+      width: 80,
       renderText: (record: AccessLogItem) => (
         <Tag color="purple">{record.responseTime - record.requestTime}ms</Tag>
       ),
@@ -83,6 +97,17 @@ const Access = () => {
     },
     {
       title: intl.formatMessage({
+        id: 'pages.table.description',
+        defaultMessage: '说明',
+      }),
+      dataIndex: 'describe',
+      ellipsis: true,
+      // render: (text, record) => {
+      //   return `${record.action}-${record.describe}`;
+      // },
+    },
+    {
+      title: intl.formatMessage({
         id: 'pages.data.option',
         defaultMessage: '操作',
       }),

+ 11 - 11
src/pages/device/Product/Detail/Access/index.tsx

@@ -1,17 +1,17 @@
-import {Badge, Button, Col, Empty, message, Row, Table, Tooltip} from 'antd';
-import {service} from '@/pages/link/AccessConfig';
-import {productModel, service as productService} from '@/pages/device/Product';
+import { Badge, Button, Col, Empty, message, Row, Table, Tooltip } from 'antd';
+import { service } from '@/pages/link/AccessConfig';
+import { productModel, service as productService } from '@/pages/device/Product';
 import styles from './index.less';
-import type {SetStateAction} from 'react';
-import {useEffect, useState} from 'react';
+import type { SetStateAction } from 'react';
+import { useEffect, useState } from 'react';
 import AccessConfig from './AccessConfig';
 import ReactMarkdown from 'react-markdown';
-import {Form, FormGrid, FormItem, FormLayout, Input, Password, PreviewText} from '@formily/antd';
-import type {ISchema} from '@formily/json-schema';
-import type {ConfigProperty} from '@/pages/device/Product/typings';
-import {createSchemaField} from '@formily/react';
-import {createForm} from '@formily/core';
-import {QuestionCircleOutlined} from '@ant-design/icons';
+import { Form, FormGrid, FormItem, FormLayout, Input, Password, PreviewText } from '@formily/antd';
+import type { ISchema } from '@formily/json-schema';
+import type { ConfigProperty } from '@/pages/device/Product/typings';
+import { createSchemaField } from '@formily/react';
+import { createForm } from '@formily/core';
+import { QuestionCircleOutlined } from '@ant-design/icons';
 import TitleComponent from '@/components/TitleComponent';
 import usePermissions from '@/hooks/permission';
 

+ 7 - 7
src/pages/device/Product/Detail/BaseInfo/index.tsx

@@ -1,11 +1,11 @@
-import {productModel, service} from '@/pages/device/Product';
-import {Descriptions} from 'antd';
-import {useState} from 'react';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import {EditOutlined} from '@ant-design/icons';
-import {getDateFormat} from '@/utils/util';
+import { productModel, service } from '@/pages/device/Product';
+import { Descriptions } from 'antd';
+import { useState } from 'react';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import { EditOutlined } from '@ant-design/icons';
+import { getDateFormat } from '@/utils/util';
 import Save from '@/pages/device/Product/Save';
-import {PermissionButton} from '@/components';
+import { PermissionButton } from '@/components';
 
 // const componentMap = {
 //   string: 'Input',

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

@@ -1,21 +1,21 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import {useIntl, useLocation, useParams} from 'umi';
-import {Badge, Card, Descriptions, message, Popconfirm, Space, Spin, Switch, Tooltip} from 'antd';
+import { PageContainer } from '@ant-design/pro-layout';
+import { useIntl, useLocation, useParams } from 'umi';
+import { Badge, Card, Descriptions, message, Popconfirm, Space, Spin, Switch, Tooltip } from 'antd';
 import BaseInfo from '@/pages/device/Product/Detail/BaseInfo';
-import {observer} from '@formily/react';
-import {productModel, service} from '@/pages/device/Product';
-import {useCallback, useEffect, useState} from 'react';
-import {useHistory} from '@/hooks';
+import { observer } from '@formily/react';
+import { productModel, service } from '@/pages/device/Product';
+import { useCallback, useEffect, useState } from 'react';
+import { useHistory } from '@/hooks';
 import Metadata from '@/pages/device/components/Metadata';
 import Access from '@/pages/device/Product/Detail/Access';
-import type {DeviceMetadata} from '@/pages/device/Product/typings';
-import {Store} from 'jetlinks-store';
+import type { DeviceMetadata } from '@/pages/device/Product/typings';
+import { Store } from 'jetlinks-store';
 import MetadataAction from '@/pages/device/components/Metadata/DataBaseAction';
-import {getMenuPathByCode, MENUS_CODE} from '@/utils/menu';
+import { getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
 import encodeQuery from '@/utils/encodeQuery';
 import MetadataMap from '@/pages/device/Instance/Detail/MetadataMap';
 import SystemConst from '@/utils/const';
-import {PermissionButton} from '@/components';
+import { PermissionButton } from '@/components';
 
 export const ModelEnum = {
   base: 'base',

+ 13 - 13
src/pages/device/Product/index.tsx

@@ -1,6 +1,6 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import {Badge, Button, message, Space, Tooltip, Upload} from 'antd';
-import type {ProductItem} from '@/pages/device/Product/typings';
+import { PageContainer } from '@ant-design/pro-layout';
+import { Badge, Button, message, Space, Tooltip, Upload } from 'antd';
+import type { ProductItem } from '@/pages/device/Product/typings';
 import {
   DeleteOutlined,
   DownloadOutlined,
@@ -10,18 +10,18 @@ import {
   StopOutlined,
 } from '@ant-design/icons';
 import Service from '@/pages/device/Product/service';
-import {observer} from '@formily/react';
-import {model} from '@formily/reactive';
-import {useHistory} from 'umi';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
-import {useEffect, useRef, useState} from 'react';
+import { observer } from '@formily/react';
+import { model } from '@formily/reactive';
+import { useHistory } from 'umi';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { useEffect, useRef, useState } from 'react';
 import Save from '@/pages/device/Product/Save';
 import SearchComponent from '@/components/SearchComponent';
-import {getMenuPathByParams, MENUS_CODE} from '@/utils/menu';
-import {AIcon, PermissionButton, ProTableCard} from '@/components';
+import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { AIcon, PermissionButton, ProTableCard } from '@/components';
 import ProductCard from '@/components/ProTableCard/CardItems/product';
-import {downloadObject} from '@/utils/util';
+import { downloadObject } from '@/utils/util';
 
 export const service = new Service('device-product');
 export const statusMap = {
@@ -295,7 +295,7 @@ const Product = observer(() => {
         id: 'pages.system.description',
         defaultMessage: '说明',
       }),
-      hideInSearch: true,
+      // hideInSearch: true,
     },
     {
       title: intl.formatMessage({

+ 20 - 7
src/pages/link/AccessConfig/Detail/Access/index.tsx

@@ -1,14 +1,27 @@
-import {Badge, Button, Card, Col, Empty, Form, Input, message, Row, Steps, Table, Tooltip,} from 'antd';
-import {useEffect, useState} from 'react';
+import {
+  Badge,
+  Button,
+  Card,
+  Col,
+  Empty,
+  Form,
+  Input,
+  message,
+  Row,
+  Steps,
+  Table,
+  Tooltip,
+} from 'antd';
+import { useEffect, useState } from 'react';
 import styles from './index.less';
-import {service} from '@/pages/link/AccessConfig';
+import { service } from '@/pages/link/AccessConfig';
 import encodeQuery from '@/utils/encodeQuery';
-import {useHistory} from 'umi';
+import { useHistory } from 'umi';
 import ReactMarkdown from 'react-markdown';
-import {getButtonPermission, getMenuPathByCode, MENUS_CODE} from '@/utils/menu';
-import {ExclamationCircleFilled} from '@ant-design/icons';
+import { getButtonPermission, getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
+import { ExclamationCircleFilled } from '@ant-design/icons';
 import TitleComponent from '@/components/TitleComponent';
-import {PermissionButton} from '@/components';
+import { PermissionButton } from '@/components';
 
 interface Props {
   change: () => void;

+ 10 - 10
src/pages/link/AccessConfig/Detail/Media/index.tsx

@@ -1,5 +1,5 @@
-import {Button, Card, Col, Form, Input, message, Row, Steps} from 'antd';
-import {useEffect, useState} from 'react';
+import { Button, Card, Col, Form, Input, message, Row, Steps } from 'antd';
+import { useEffect, useState } from 'react';
 import styles from './index.less';
 import {
   ArrayCollapse,
@@ -12,16 +12,16 @@ import {
   Radio,
   Select,
 } from '@formily/antd';
-import {createSchemaField} from '@formily/react';
-import type {ISchema} from '@formily/json-schema';
-import {createForm, registerValidateRules} from '@formily/core';
-import {service} from '@/pages/link/AccessConfig';
-import {useLocation} from 'umi';
+import { createSchemaField } from '@formily/react';
+import type { ISchema } from '@formily/json-schema';
+import { createForm, registerValidateRules } from '@formily/core';
+import { service } from '@/pages/link/AccessConfig';
+import { useLocation } from 'umi';
 import SipComponent from '@/components/SipComponent';
 import TitleComponent from '@/components/TitleComponent';
-import {ExclamationCircleFilled} from '@ant-design/icons';
-import {testIP} from '@/utils/util';
-import {getButtonPermission} from '@/utils/menu';
+import { ExclamationCircleFilled } from '@ant-design/icons';
+import { testIP } from '@/utils/util';
+import { getButtonPermission } from '@/utils/menu';
 
 type LocationType = {
   id?: string;

+ 5 - 5
src/pages/link/AccessConfig/Detail/index.tsx

@@ -1,11 +1,11 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import {useEffect, useState} from 'react';
-import {useLocation} from 'umi';
+import { PageContainer } from '@ant-design/pro-layout';
+import { useEffect, useState } from 'react';
+import { useLocation } from 'umi';
 import Access from './Access';
 import Provider from './Provider';
 import Media from './Media';
-import {service} from '@/pages/link/AccessConfig';
-import {Spin} from 'antd';
+import { service } from '@/pages/link/AccessConfig';
+import { Spin } from 'antd';
 
 type LocationType = {
   id?: string;

+ 9 - 9
src/pages/link/Certificate/index.tsx

@@ -1,14 +1,14 @@
-import {PageContainer} from '@ant-design/pro-layout';
+import { PageContainer } from '@ant-design/pro-layout';
 import BaseService from '@/utils/BaseService';
-import type {CertificateItem} from '@/pages/link/Certificate/typings';
-import {useRef} from 'react';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
-import {message, Popconfirm, Tooltip} from 'antd';
-import {EditOutlined, MinusOutlined} from '@ant-design/icons';
+import type { CertificateItem } from '@/pages/link/Certificate/typings';
+import { useRef } from 'react';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { message, Popconfirm, Tooltip } from 'antd';
+import { EditOutlined, MinusOutlined } from '@ant-design/icons';
 import BaseCrud from '@/components/BaseCrud';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import type {ISchema} from '@formily/json-schema';
-import {CurdModel} from '@/components/BaseCrud/model';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import type { ISchema } from '@formily/json-schema';
+import { CurdModel } from '@/components/BaseCrud/model';
 
 export const service = new BaseService<CertificateItem>('network/certificate');
 const Certificate = () => {

+ 12 - 12
src/pages/link/Gateway/index.tsx

@@ -1,8 +1,8 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import type {GatewayItem} from '@/pages/link/Gateway/typings';
-import {useRef} from 'react';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
-import {message, Popconfirm, Tooltip} from 'antd';
+import { PageContainer } from '@ant-design/pro-layout';
+import type { GatewayItem } from '@/pages/link/Gateway/typings';
+import { useRef } from 'react';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { message, Popconfirm, Tooltip } from 'antd';
 import {
   EditOutlined,
   MinusOutlined,
@@ -12,14 +12,14 @@ import {
   StopOutlined,
 } from '@ant-design/icons';
 import BaseCrud from '@/components/BaseCrud';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import type {ISchema} from '@formily/json-schema';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import type { ISchema } from '@formily/json-schema';
 import Service from '@/pages/link/Gateway/service';
-import {CurdModel} from '@/components/BaseCrud/model';
-import type {Field, FormPathPattern} from '@formily/core';
-import {onFieldReact, onFieldValueChange} from '@formily/core';
-import {action} from '@formily/reactive';
-import {useAsyncDataSource} from '@/utils/util';
+import { CurdModel } from '@/components/BaseCrud/model';
+import type { Field, FormPathPattern } from '@formily/core';
+import { onFieldReact, onFieldValueChange } from '@formily/core';
+import { action } from '@formily/reactive';
+import { useAsyncDataSource } from '@/utils/util';
 
 export const service = new Service('gateway/device');
 

+ 25 - 8
src/pages/link/Protocol/index.tsx

@@ -1,13 +1,19 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
-import type {ProtocolItem} from '@/pages/link/Protocol/typings';
-import {Badge, message} from 'antd';
-import {useRef, useState} from 'react';
-import {CheckCircleOutlined, DeleteOutlined, EditOutlined, PlusOutlined, StopOutlined,} from '@ant-design/icons';
+import { PageContainer } from '@ant-design/pro-layout';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import type { ProtocolItem } from '@/pages/link/Protocol/typings';
+import { Badge, message } from 'antd';
+import { useRef, useState } from 'react';
+import {
+  CheckCircleOutlined,
+  DeleteOutlined,
+  EditOutlined,
+  PlusOutlined,
+  StopOutlined,
+} from '@ant-design/icons';
 import Service from '@/pages/link/Protocol/service';
-import {useIntl} from 'umi';
+import { useIntl } from 'umi';
 import SearchComponent from '@/components/SearchComponent';
-import {PermissionButton, ProTableCard} from '@/components';
+import { PermissionButton, ProTableCard } from '@/components';
 import ProcotolCard from '@/components/ProTableCard/CardItems/protocol';
 import Save from './save';
 
@@ -51,6 +57,17 @@ const Protocol = () => {
       dataIndex: 'type',
       title: '类型',
       ellipsis: true,
+      valueType: 'select',
+      valueEnum: {
+        jar: {
+          text: 'jar',
+          status: 'jar',
+        },
+        local: {
+          text: 'local',
+          status: 'local',
+        },
+      },
     },
     {
       dataIndex: 'state',

+ 9 - 9
src/pages/link/Protocol/save/index.tsx

@@ -1,14 +1,14 @@
-import {Button, message} from 'antd';
-import {createForm, registerValidateRules} from '@formily/core';
-import {createSchemaField} from '@formily/react';
-import React, {useEffect, useState} from 'react';
+import { Button, message } from 'antd';
+import { createForm, registerValidateRules } from '@formily/core';
+import { createSchemaField } from '@formily/react';
+import React, { useEffect, useState } from 'react';
 import * as ICONS from '@ant-design/icons';
-import {Form, FormGrid, FormItem, Input, Select} from '@formily/antd';
-import type {ISchema} from '@formily/json-schema';
-import {service} from '@/pages/link/Protocol';
-import {Modal} from '@/components';
+import { Form, FormGrid, FormItem, Input, Select } from '@formily/antd';
+import type { ISchema } from '@formily/json-schema';
+import { service } from '@/pages/link/Protocol';
+import { Modal } from '@/components';
 import FileUpload from '../FileUpload';
-import type {ProtocolItem} from '@/pages/link/Protocol/typings';
+import type { ProtocolItem } from '@/pages/link/Protocol/typings';
 
 interface Props {
   data: ProtocolItem | undefined;

+ 3 - 2
src/pages/link/Type/Detail/index.tsx

@@ -755,7 +755,8 @@ const Save = observer(() => {
     },
   };
 
-  const handleSave = async (data: any) => {
+  const handleSave = async () => {
+    const data: any = await form.submit();
     if (data.shareCluster === false) {
       data.cluster = data.cluster?.map((item: any) => ({
         serverId: item.serverId,
@@ -791,7 +792,7 @@ const Save = observer(() => {
               <PermissionButton
                 type="primary"
                 isPermission={getOtherPermission(['add', 'update'])}
-                onClick={handleSave}
+                onClick={() => handleSave()}
               >
                 保存
               </PermissionButton>

+ 30 - 0
src/pages/link/Type/index.tsx

@@ -61,11 +61,30 @@ const Network = () => {
         id: 'pages.link.type',
         defaultMessage: '类型',
       }),
+      valueType: 'select',
+      request: () =>
+        service.getSupports().then((resp) =>
+          resp.result.map((item: any) => ({
+            label: item.name,
+            value: item.id,
+          })),
+        ),
     },
     {
       dataIndex: 'shareCluster',
       title: '集群',
       renderText: (text) => (text ? '共享配置' : '独立配置'),
+      valueType: 'select',
+      valueEnum: {
+        true: {
+          text: '共享配置',
+          status: true,
+        },
+        false: {
+          text: '独立配置',
+          status: false,
+        },
+      },
     },
     {
       dataIndex: 'configuration',
@@ -102,6 +121,17 @@ const Network = () => {
         id: 'pages.searchTable.titleStatus',
         defaultMessage: '状态',
       }),
+      valueType: 'select',
+      valueEnum: {
+        disabled: {
+          text: '已停止',
+          status: 'disabled',
+        },
+        enabled: {
+          text: '已启动',
+          status: 'enabled',
+        },
+      },
       render: (text, record) => {
         if (record.state.value === 'enabled') {
           return <Badge color="lime" text="正常" />;

+ 11 - 0
src/pages/media/Cascade/Channel/index.tsx

@@ -107,6 +107,17 @@ const Channel = () => {
     {
       dataIndex: 'status',
       title: '在线状态',
+      valueType: 'select',
+      valueEnum: {
+        online: {
+          text: '已连接',
+          status: 'online',
+        },
+        offline: {
+          text: '离线',
+          status: 'offline',
+        },
+      },
       render: (text: any, record: any) => (
         <BadgeStatus
           status={record.status?.value}

+ 23 - 10
src/pages/media/Device/Channel/index.tsx

@@ -1,14 +1,14 @@
 // 视频设备通道列表
-import {PageContainer} from '@ant-design/pro-layout';
-import ProTable, {ActionType, ProColumns} from '@jetlinks/pro-table';
+import { PageContainer } from '@ant-design/pro-layout';
+import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
 import SearchComponent from '@/components/SearchComponent';
 import './index.less';
-import {useEffect, useRef, useState} from 'react';
-import {ChannelItem} from '@/pages/media/Device/Channel/typings';
-import {useHistory, useIntl, useLocation} from 'umi';
-import {BadgeStatus} from '@/components';
-import {StatusColorEnum} from '@/components/BadgeStatus';
-import {Button, message, Popconfirm, Tooltip} from 'antd';
+import { useEffect, useRef, useState } from 'react';
+import { ChannelItem } from '@/pages/media/Device/Channel/typings';
+import { useHistory, useIntl, useLocation } from 'umi';
+import { BadgeStatus } from '@/components';
+import { StatusColorEnum } from '@/components/BadgeStatus';
+import { Button, message, Popconfirm, Tooltip } from 'antd';
 import {
   DeleteOutlined,
   EditOutlined,
@@ -18,9 +18,9 @@ import {
 } from '@ant-design/icons';
 import Save from './Save';
 import Service from './service';
-import {ProviderValue} from '../index';
+import { ProviderValue } from '../index';
 import Live from './Live';
-import {getButtonPermission, getMenuPathByCode, MENUS_CODE} from '@/utils/menu';
+import { getButtonPermission, getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
 import Tree from './Tree';
 
 export const service = new Service('media');
@@ -100,6 +100,17 @@ export default () => {
         id: 'pages.searchTable.titleStatus',
         defaultMessage: '状态',
       }),
+      valueType: 'select',
+      valueEnum: {
+        online: {
+          text: '已连接',
+          status: 'online',
+        },
+        offline: {
+          text: '离线',
+          status: 'offline',
+        },
+      },
       render: (_, record) => (
         <BadgeStatus
           status={record.status.value}
@@ -129,6 +140,8 @@ export default () => {
           })}
         >
           <Button
+            style={{ padding: 0 }}
+            type="link"
             onClick={() => {
               setCurrent(record);
               setVisible(true);

+ 8 - 8
src/pages/media/Device/Save/ProviderSelect.tsx

@@ -1,15 +1,15 @@
 import classNames from 'classnames';
-import {Badge, Button, Empty} from 'antd';
-import {StatusColorEnum} from '@/components/BadgeStatus';
+import { Badge, Button, Empty } from 'antd';
+import { StatusColorEnum } from '@/components/BadgeStatus';
 import styles from '@/pages/link/AccessConfig/index.less';
-import {TableCard} from '@/components';
+import { TableCard } from '@/components';
 import './providerSelect.less';
 import usePermissions from '@/hooks/permission';
-import {useIntl} from 'umi';
-import {providerType, service} from '@/pages/media/Device';
-import {useCallback, useEffect, useRef, useState} from 'react';
-import {getMenuPathByCode, MENUS_CODE} from '@/utils/menu';
-import {useRequest} from '@@/plugin-request/request';
+import { useIntl } from 'umi';
+import { providerType, service } from '@/pages/media/Device';
+import { useCallback, useEffect, useRef, useState } from 'react';
+import { getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
+import { useRequest } from '@@/plugin-request/request';
 
 interface ProviderProps {
   value?: string;

+ 4 - 4
src/pages/media/Device/Save/SaveProduct.tsx

@@ -1,7 +1,7 @@
-import {useEffect, useState} from 'react';
-import {service} from '../index';
-import {useRequest} from 'umi';
-import {Form, Input, message, Modal} from 'antd';
+import { useEffect, useState } from 'react';
+import { service } from '../index';
+import { useRequest } from 'umi';
+import { Form, Input, message, Modal } from 'antd';
 import ProviderItem from './ProviderSelect';
 
 interface SaveProps {

+ 8 - 8
src/pages/media/Device/Save/index.tsx

@@ -1,12 +1,12 @@
-import {useCallback, useEffect, useState} from 'react';
-import {Button, Col, Form, Input, message, Modal, Radio, Row, Select, Tooltip} from 'antd';
-import {useIntl} from 'umi';
-import {RadioCard, UploadImage} from '@/components';
-import {PlusOutlined} from '@ant-design/icons';
-import {service} from '../index';
+import { useCallback, useEffect, useState } from 'react';
+import { Button, Col, Form, Input, message, Modal, Radio, Row, Select, Tooltip } from 'antd';
+import { useIntl } from 'umi';
+import { RadioCard, UploadImage } from '@/components';
+import { PlusOutlined } from '@ant-design/icons';
+import { service } from '../index';
 import SaveProductModal from './SaveProduct';
-import type {DeviceItem} from '../typings';
-import {getButtonPermission} from '@/utils/menu';
+import type { DeviceItem } from '../typings';
+import { getButtonPermission } from '@/utils/menu';
 
 interface SaveProps {
   visible: boolean;

+ 10 - 9
src/pages/media/Device/index.tsx

@@ -1,8 +1,8 @@
 // 视频设备列表
-import {PageContainer} from '@ant-design/pro-layout';
-import {useRef, useState} from 'react';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
-import {Button, message, Tooltip} from 'antd';
+import { PageContainer } from '@ant-design/pro-layout';
+import { useRef, useState } from 'react';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import { Button, message, Tooltip } from 'antd';
 import {
   DeleteOutlined,
   EditOutlined,
@@ -11,13 +11,13 @@ import {
   PlusOutlined,
   SyncOutlined,
 } from '@ant-design/icons';
-import type {DeviceItem} from '@/pages/media/Device/typings';
-import {useHistory, useIntl} from 'umi';
-import {BadgeStatus, PermissionButton, ProTableCard} from '@/components';
-import {StatusColorEnum} from '@/components/BadgeStatus';
+import type { DeviceItem } from '@/pages/media/Device/typings';
+import { useHistory, useIntl } from 'umi';
+import { BadgeStatus, PermissionButton, ProTableCard } from '@/components';
+import { StatusColorEnum } from '@/components/BadgeStatus';
 import SearchComponent from '@/components/SearchComponent';
 import MediaDevice from '@/components/ProTableCard/CardItems/mediaDevice';
-import {getMenuPathByCode, getMenuPathByParams, MENUS_CODE} from '@/utils/menu';
+import { getMenuPathByCode, getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import Service from './service';
 import Save from './Save';
 
@@ -115,6 +115,7 @@ const Device = () => {
         defaultMessage: '通道数量',
       }),
       valueType: 'digit',
+      hideInSearch: true,
     },
     {
       dataIndex: 'manufacturer',

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

@@ -34,7 +34,12 @@ const Debug = observer(() => {
             const list = Store.get('notice-template-list');
 
             const _template = list.find((item: any) => item.id === value);
-            form1.setValuesIn('variableDefinitions', _template.variableDefinitions);
+            if (_template?.variableDefinitions?.length > 0) {
+              form1.setFieldState('variableDefinitions', (_state) => {
+                _state.visible = true;
+                _state.value = _template.variableDefinitions;
+              });
+            }
           });
           onFieldReact('variableDefinitions.*.type', (field) => {
             const value = (field as Field).value;
@@ -109,6 +114,7 @@ const Debug = observer(() => {
           pagination: { pageSize: 9999 },
           scroll: { x: '100%' },
         },
+        'x-visible': false,
         items: {
           type: 'object',
           properties: {

+ 8 - 4
src/pages/notice/Template/Debug/index.tsx

@@ -36,10 +36,8 @@ const Debug = observer(() => {
             if (target && target.variableDefinitions) {
               form1.setValuesIn('variableDefinitions', target.variableDefinitions);
             }
-            //
-            // 获取 变量列表
-            // 然后set 值
           });
+
           onFieldReact('variableDefinitions.*.type', (field) => {
             const value = (field as Field).value;
             const format = field.query('.value').take() as any;
@@ -70,7 +68,12 @@ const Debug = observer(() => {
 
   useEffect(() => {
     const data = state.current;
-    form.setValuesIn('variableDefinitions', data?.variableDefinitions);
+    if (data?.variableDefinitions?.length > 0) {
+      form.setFieldState('variableDefinitions', (state1) => {
+        state1.visible = true;
+        state1.value = data?.variableDefinitions;
+      });
+    }
   }, [state.current]);
 
   const SchemaField = createSchemaField({
@@ -121,6 +124,7 @@ const Debug = observer(() => {
           pagination: { pageSize: 9999 },
           scroll: { x: '100%' },
         },
+        'x-visible': false,
         items: {
           type: 'object',
           properties: {

+ 13 - 1
src/pages/notice/Template/Detail/index.tsx

@@ -216,6 +216,11 @@ const Detail = observer(() => {
                 ?.match(pattern)
                 ?.filter((i: string) => i)
                 .map((item: string) => ({ id: item, type: 'string', format: '--' }));
+            if (idList && idList.length > 0) {
+              form1.setFieldState('variableDefinitions', (state1) => {
+                state1.visible = true;
+              });
+            }
             if (form1.modified) {
               form1.setValuesIn('variableDefinitions', idList);
             }
@@ -343,6 +348,9 @@ const Detail = observer(() => {
         type: 'string',
         'x-decorator': 'FormItem',
         'x-component': 'Input',
+        'x-component-props': {
+          placeholder: '请输入名称',
+        },
         name: 'name',
         'x-validator': [
           {
@@ -913,6 +921,9 @@ const Detail = observer(() => {
                 'x-decorator-props': {
                   tip: '多个收件人用换行分隔 \n最大支持1000个号码',
                 },
+                'x-component-props': {
+                  placeholder: '请输入收件人邮箱,多个收件人用换行分隔',
+                },
               },
               attachments: {
                 type: 'array',
@@ -944,7 +955,7 @@ const Detail = observer(() => {
                       'x-component-props': {
                         type: 'file',
                         display: 'name',
-                        placeholder: '请上传文件',
+                        placeholder: '请上传文件或输入文件名称',
                       },
                     },
                     remove: {
@@ -999,6 +1010,7 @@ const Detail = observer(() => {
           pagination: { pageSize: 9999 },
           scroll: { x: '100%' },
         },
+        'x-visible': false,
         items: {
           type: 'object',
           properties: {

+ 17 - 12
src/pages/system/Menu/index.tsx

@@ -1,20 +1,25 @@
 // 菜单管理
-import {PageContainer} from '@ant-design/pro-layout';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
+import { PageContainer } from '@ant-design/pro-layout';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
-import {useRef, useState} from 'react';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import {Button, message, Tooltip} from 'antd';
-import {DeleteOutlined, PlusCircleOutlined, PlusOutlined, SearchOutlined,} from '@ant-design/icons';
-import {observer} from '@formily/react';
-import {model} from '@formily/reactive';
-import {useHistory} from 'umi';
+import { useRef, useState } from 'react';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import { Button, message, Tooltip } from 'antd';
+import {
+  DeleteOutlined,
+  PlusCircleOutlined,
+  PlusOutlined,
+  SearchOutlined,
+} from '@ant-design/icons';
+import { observer } from '@formily/react';
+import { model } from '@formily/reactive';
+import { useHistory } from 'umi';
 import SearchComponent from '@/components/SearchComponent';
 import Service from './service';
-import type {MenuItem} from './typing';
+import type { MenuItem } from './typing';
 import moment from 'moment';
-import {getMenuPathByParams, MENUS_CODE} from '@/utils/menu';
-import {PermissionButton} from '@/components';
+import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { PermissionButton } from '@/components';
 
 export const service = new Service('menu');
 

+ 17 - 11
src/pages/system/Permission/index.tsx

@@ -1,20 +1,26 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import React, {useRef, useState} from 'react';
-import {CloseCircleOutlined, DeleteOutlined, EditOutlined, PlayCircleOutlined, PlusOutlined,} from '@ant-design/icons';
-import {Badge, Button, Dropdown, Menu, message, Popconfirm, Space, Tooltip, Upload} from 'antd';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
+import { PageContainer } from '@ant-design/pro-layout';
+import React, { useRef, useState } from 'react';
+import {
+  CloseCircleOutlined,
+  DeleteOutlined,
+  EditOutlined,
+  PlayCircleOutlined,
+  PlusOutlined,
+} from '@ant-design/icons';
+import { Badge, Button, Dropdown, Menu, message, Popconfirm, Space, Tooltip, Upload } from 'antd';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import type {PermissionItem} from '@/pages/system/Permission/typings';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import type { PermissionItem } from '@/pages/system/Permission/typings';
 import Service from '@/pages/system/Permission/service';
-import {observer} from '@formily/react';
+import { observer } from '@formily/react';
 import SearchComponent from '@/components/SearchComponent';
 import Save from './Save';
 import SystemConst from '@/utils/const';
-import {downloadObject} from '@/utils/util';
+import { downloadObject } from '@/utils/util';
 import Token from '@/utils/token';
-import {getButtonPermission} from '@/utils/menu';
-import {PermissionButton} from '@/components';
+import { getButtonPermission } from '@/utils/menu';
+import { PermissionButton } from '@/components';
 
 export const service = new Service('permission');
 const Permission: React.FC = observer(() => {

+ 12 - 12
src/pages/system/Role/index.tsx

@@ -1,18 +1,18 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import React, {useEffect, useRef} from 'react';
-import {DeleteOutlined, EditOutlined} from '@ant-design/icons';
-import {message} from 'antd';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
+import { PageContainer } from '@ant-design/pro-layout';
+import React, { useEffect, useRef } from 'react';
+import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
+import { message } from 'antd';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import BaseCrud from '@/components/BaseCrud';
 import Service from './service';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import {observer} from '@formily/react';
-import {history, useLocation} from 'umi';
-import {Store} from 'jetlinks-store';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import { observer } from '@formily/react';
+import { history, useLocation } from 'umi';
+import { Store } from 'jetlinks-store';
 import SystemConst from '@/utils/const';
-import {CurdModel} from '@/components/BaseCrud/model';
-import {getButtonPermission, getMenuPathByParams, MENUS_CODE} from '@/utils/menu';
-import {PermissionButton} from '@/components';
+import { CurdModel } from '@/components/BaseCrud/model';
+import { getButtonPermission, getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
+import { PermissionButton } from '@/components';
 
 export const service = new Service('role');
 

+ 10 - 10
src/pages/system/Tenant/index.tsx

@@ -1,19 +1,19 @@
-import {PageContainer} from '@ant-design/pro-layout';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
-import type {TenantDetail, TenantItem} from '@/pages/system/Tenant/typings';
+import { PageContainer } from '@ant-design/pro-layout';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
+import type { TenantDetail, TenantItem } from '@/pages/system/Tenant/typings';
 import BaseCrud from '@/components/BaseCrud';
-import {useRef} from 'react';
-import {Avatar, Drawer, Tooltip} from 'antd';
+import { useRef } from 'react';
+import { Avatar, Drawer, Tooltip } from 'antd';
 import Service from '@/pages/system/Tenant/service';
-import {EyeOutlined, KeyOutlined} from '@ant-design/icons';
-import {useIntl} from '@@/plugin-locale/localeExports';
+import { EyeOutlined, KeyOutlined } from '@ant-design/icons';
+import { useIntl } from '@@/plugin-locale/localeExports';
 import moment from 'moment';
-import {Link} from 'umi';
+import { Link } from 'umi';
 import TenantModel from '@/pages/system/Tenant/model';
-import type {ISchema} from '@formily/json-schema';
+import type { ISchema } from '@formily/json-schema';
 import autzModel from '@/components/Authorization/autz';
 import Authorization from '@/components/Authorization';
-import {observer} from '@formily/react';
+import { observer } from '@formily/react';
 
 export const service = new Service('tenant');
 

+ 26 - 20
src/pages/system/User/index.tsx

@@ -1,15 +1,21 @@
 import Service from '@/pages/system/User/serivce';
-import {PageContainer} from '@ant-design/pro-layout';
+import { PageContainer } from '@ant-design/pro-layout';
 import SearchComponent from '@/components/SearchComponent';
-import type {ActionType, ProColumns} from '@jetlinks/pro-table';
+import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
-import {Badge, message, Popconfirm} from 'antd';
-import {CloseCircleOutlined, DeleteOutlined, EditOutlined, PlayCircleOutlined, PlusOutlined,} from '@ant-design/icons';
-import {useIntl} from '@@/plugin-locale/localeExports';
-import {useRef, useState} from 'react';
+import { Badge, message, Popconfirm } from 'antd';
+import {
+  CloseCircleOutlined,
+  DeleteOutlined,
+  EditOutlined,
+  PlayCircleOutlined,
+  PlusOutlined,
+} from '@ant-design/icons';
+import { useIntl } from '@@/plugin-locale/localeExports';
+import { useRef, useState } from 'react';
 import Save from './Save';
-import {observer} from '@formily/react';
-import {PermissionButton} from '@/components';
+import { observer } from '@formily/react';
+import { PermissionButton } from '@/components';
 import usePermissions from '@/hooks/permission';
 
 export const service = new Service('user');
@@ -18,7 +24,7 @@ const User = observer(() => {
   const intl = useIntl();
   const actionRef = useRef<ActionType>();
 
-  const {permission: userPermission} = usePermissions('system/User');
+  const { permission: userPermission } = usePermissions('system/User');
   const [model, setMode] = useState<'add' | 'edit' | 'query'>('query');
   const [current, setCurrent] = useState<Partial<UserItem>>({});
   const edit = async (record: UserItem) => {
@@ -98,7 +104,7 @@ const User = observer(() => {
         },
       },
       render: (text, record) => (
-        <Badge status={record.status === 1 ? 'success' : 'error'} text={text}/>
+        <Badge status={record.status === 1 ? 'success' : 'error'} text={text} />
       ),
     },
     {
@@ -110,7 +116,7 @@ const User = observer(() => {
       width: 200,
       render: (text, record) => [
         <PermissionButton
-          style={{padding: 0}}
+          style={{ padding: 0 }}
           type="link"
           isPermission={userPermission.update}
           key="editable"
@@ -119,13 +125,13 @@ const User = observer(() => {
             title: intl.formatMessage({
               id: 'pages.data.option.edit',
               defaultMessage: '编辑',
-            })
+            }),
           }}
         >
-          <EditOutlined/>
+          <EditOutlined />
         </PermissionButton>,
         <PermissionButton
-          style={{padding: 0}}
+          style={{ padding: 0 }}
           isPermission={userPermission.action}
           type="link"
           key="changeState"
@@ -155,15 +161,15 @@ const User = observer(() => {
             }),
           }}
         >
-          {record.status ? <CloseCircleOutlined/> : <PlayCircleOutlined/>}
+          {record.status ? <CloseCircleOutlined /> : <PlayCircleOutlined />}
         </PermissionButton>,
         <PermissionButton
           type="link"
           key="delete"
-          style={{padding: 0}}
+          style={{ padding: 0 }}
           isPermission={userPermission.delete}
           disabled={record.status === 1}
-          tooltip={{title: record.status === 0 ? '删除' : '请先禁用该用户,再删除。'}}
+          tooltip={{ title: record.status === 0 ? '删除' : '请先禁用该用户,再删除。' }}
         >
           <Popconfirm
             onConfirm={async () => {
@@ -172,7 +178,7 @@ const User = observer(() => {
             }}
             title="确认删除?"
           >
-            <DeleteOutlined/>
+            <DeleteOutlined />
           </Popconfirm>
         </PermissionButton>,
       ],
@@ -204,7 +210,7 @@ const User = observer(() => {
             }}
             isPermission={userPermission.add}
             key="button"
-            icon={<PlusOutlined/>}
+            icon={<PlusOutlined />}
             type="primary"
           >
             {intl.formatMessage({
@@ -214,7 +220,7 @@ const User = observer(() => {
           </PermissionButton>
         }
         request={async (params) =>
-          service.query({...params, sorts: [{name: 'createTime', order: 'desc'}]})
+          service.query({ ...params, sorts: [{ name: 'createTime', order: 'desc' }] })
         }
       />
       <Save