wzyyy 3 лет назад
Родитель
Сommit
9ffe1599be

+ 25 - 9
src/app.tsx

@@ -15,6 +15,7 @@ import SystemConst from '@/utils/const';
 import { service as MenuService } from '@/pages/system/Menu';
 import getRoutes, { extraRouteArr, getMenus, handleRoutes, saveMenusCache } from '@/utils/menu';
 import { AIcon } from '@/components';
+import React from 'react';
 
 const isDev = process.env.NODE_ENV === 'development';
 const loginPath = '/user/login';
@@ -198,6 +199,23 @@ export const request: RequestConfig = {
   requestInterceptors: [requestInterceptor],
 };
 
+const MenuItemIcon = (
+  menuItemProps: any,
+  defaultDom: React.ReactNode,
+  props: any,
+): React.ReactNode => {
+  if (defaultDom) {
+    // @ts-ignore
+    const menuItem = React.cloneElement(defaultDom, {
+      // @ts-ignore
+      children: [<AIcon type={menuItemProps.icon as string} />, defaultDom.props.children[1]],
+      ...props,
+    });
+    return menuItem;
+  }
+  return defaultDom;
+};
+
 // ProLayout 支持的api https://procomponents.ant.design/components/layout
 export const layout: RunTimeLayoutConfig = ({ initialState }) => {
   // console.log({ ...initialState });
@@ -224,15 +242,13 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
     menuDataRender: () => {
       return getMenus(extraRoutes);
     },
-    menuItemRender: (menuItemProps) => {
-      return (
-        <Link to={menuItemProps.path}>
-          <span className={`antd-pro-menu-item`}>
-            {menuItemProps.icon && <AIcon type={menuItemProps.icon as string} />}
-            <span className={`antd-pro-menu-item-title`}>{menuItemProps.name}</span>
-          </span>
-        </Link>
-      );
+    subMenuItemRender: MenuItemIcon,
+    menuItemRender: (menuItemProps, defaultDom) => {
+      return MenuItemIcon(menuItemProps, defaultDom, {
+        onClick: () => {
+          history.push(menuItemProps.path!);
+        },
+      });
     },
     links: isDev
       ? [

+ 6 - 0
src/global.less

@@ -109,3 +109,9 @@ ol {
     display: flex;
   }
 }
+
+.tabs-full-active {
+  .ant-tabs-tab-active {
+    background-color: @primary-1;
+  }
+}

+ 2 - 16
src/pages/Log/Access/index.tsx

@@ -72,7 +72,6 @@ const Access = () => {
       valueType: 'dateTime',
       defaultSortOrder: 'descend',
       ellipsis: true,
-      width: 200,
       renderText: (text: string) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
     },
     {
@@ -80,7 +79,7 @@ const Access = () => {
         id: 'pages.log.access.requestTimeConsuming',
         defaultMessage: '请求耗时',
       }),
-      width: 80,
+      width: 100,
       renderText: (record: AccessLogItem) => (
         <Tag color="purple">{record.responseTime - record.requestTime}ms</Tag>
       ),
@@ -91,20 +90,7 @@ const Access = () => {
         defaultMessage: '请求用户',
       }),
       dataIndex: 'username',
-      render: (text, record: any) => (
-        <Tag color="geekblue">{record?.context?.username || '--'}</Tag>
-      ),
-    },
-    {
-      title: intl.formatMessage({
-        id: 'pages.table.description',
-        defaultMessage: '说明',
-      }),
-      dataIndex: 'describe',
-      ellipsis: true,
-      // render: (text, record) => {
-      //   return `${record.action}-${record.describe}`;
-      // },
+      render: (text, record: any) => <Tag color="geekblue">{record?.context?.username || ''}</Tag>,
     },
     {
       title: intl.formatMessage({

+ 21 - 4
src/pages/account/NotificationSubscription/save/index.tsx

@@ -6,6 +6,7 @@ import type { ISchema } from '@formily/react';
 import { createSchemaField } from '@formily/react';
 import { useAsyncDataSource } from '@/utils/util';
 import { service } from '@/pages/account/NotificationSubscription';
+import _ from 'lodash';
 
 interface Props {
   data: Partial<NotifitionSubscriptionItem>;
@@ -14,11 +15,19 @@ interface Props {
 }
 
 const Save = (props: Props) => {
-  const [data, setDada] = useState<Partial<NotifitionSubscriptionItem>>(props.data || {});
+  const [data, setDada] = useState<any>(props.data || {});
   const [dataList, setDataList] = useState<any[]>([]);
 
   useEffect(() => {
-    setDada(props.data);
+    if (props.data?.topicConfig) {
+      setDada({
+        ...props.data,
+        topicConfig: {
+          alarmConfigId: props.data?.topicConfig?.alarmConfigId.split(','),
+          alarmConfigName: props.data?.topicConfig?.alarmConfigName.split(','),
+        },
+      });
+    }
   }, [props.data]);
 
   const form = useMemo(
@@ -97,6 +106,7 @@ const Save = (props: Props) => {
           },
           'topicConfig.alarmConfigId': {
             title: '告警规则',
+            type: 'array',
             'x-component': 'Select',
             'x-decorator': 'FormItem',
             required: true,
@@ -106,7 +116,11 @@ const Save = (props: Props) => {
               layout: 'vertical',
             },
             'x-component-props': {
+              mode: 'multiple',
+              showArrow: true,
               placeholder: '请选择告警规则',
+              filterOption: (input: string, option: any) =>
+                option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
             },
             'x-reactions': ['{{useAsyncDataSource(queryAlarmConfigList)}}'],
             'x-validator': [
@@ -168,13 +182,16 @@ const Save = (props: Props) => {
   const handleSave = async () => {
     let param: any = await form.submit();
     delete param.notice;
-    const config = dataList.find((item) => item?.value === param?.topicConfig?.alarmConfigId);
+    const config = dataList.filter((item) =>
+      param?.topicConfig?.alarmConfigId.includes(item?.value),
+    );
     param = {
       ...data,
       ...param,
       topicConfig: {
         ...param?.topicConfig,
-        alarmConfigName: config.label || '',
+        alarmConfigId: param?.topicConfig.alarmConfigId.join(','),
+        alarmConfigName: _.map(config, 'label').join(','),
       },
     };
     const response: any = await service.saveData(param);

+ 9 - 19
src/pages/device/Instance/Detail/Log/index.tsx

@@ -5,38 +5,28 @@ import { Card, Input, Modal, Tooltip } from 'antd';
 import { SearchOutlined } from '@ant-design/icons';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { InstanceModel, service } from '@/pages/device/Instance';
-import { useEffect, useRef, useState } from 'react';
+import { useRef, useState } from 'react';
 import SearchComponent from '@/components/SearchComponent';
 
 const Log = () => {
   const intl = useIntl();
 
-  const [type, setType] = useState<any>({});
   const actionRef = useRef<ActionType>();
   const [searchParams, setSearchParams] = useState<any>({});
 
-  useEffect(() => {
-    service.queryLogsType().then((resp) => {
-      if (resp.status === 200) {
-        const list = (resp.result as { text: string; value: string }[]).reduce(
-          (previousValue, currentValue) => {
-            previousValue[currentValue.value] = currentValue;
-            return previousValue;
-          },
-          {},
-        );
-        setType({ ...list });
-      }
-    });
-  }, []);
-
   const columns: ProColumns<LogItem>[] = [
     {
       title: '类型',
       dataIndex: 'type',
-      renderText: (text) => text.text,
+      renderText: (text) => text?.text,
       valueType: 'select',
-      valueEnum: { ...type },
+      request: () =>
+        service.queryLogsType().then((resp: any) =>
+          (resp?.result || []).map((item: any) => ({
+            label: item.text,
+            value: item.value,
+          })),
+        ),
     },
     {
       title: '时间',

+ 33 - 16
src/pages/device/Instance/Detail/Running/Property/index.tsx

@@ -1,4 +1,4 @@
-import { Col, Input, message, Pagination, Row, Space, Spin, Table } from 'antd';
+import { Col, Empty, Input, message, Pagination, Row, Space, Spin, Table } from 'antd';
 import CheckButton from '@/components/CheckButton';
 import { useCallback, useEffect, useRef, useState } from 'react';
 import type { PropertyMetadata } from '@/pages/device/Product/typings';
@@ -250,19 +250,24 @@ const Property = (props: Props) => {
             }}
           />
         </div>
-        <div style={{ marginTop: '20px' }}>
-          {check ? (
-            <Row gutter={[16, 16]}>
-              {dataSource.data.map((item: any) => (
-                <Col {...ColResponsiveProps} key={item.id}>
-                  <PropertyCard data={item} value={item?.id ? propertyValue[item?.id] : '--'} />
-                </Col>
-              ))}
-            </Row>
-          ) : (
-            <Table pagination={false} columns={columns} dataSource={dataSource.data} rowKey="id" />
-          )}
-          {dataSource.data.length > 0 && (
+        {dataSource.data?.length > 0 ? (
+          <div style={{ marginTop: '20px' }}>
+            {check ? (
+              <Row gutter={[16, 16]}>
+                {dataSource.data.map((item: any) => (
+                  <Col {...ColResponsiveProps} key={item.id}>
+                    <PropertyCard data={item} value={item?.id ? propertyValue[item?.id] : '--'} />
+                  </Col>
+                ))}
+              </Row>
+            ) : (
+              <Table
+                pagination={false}
+                columns={columns}
+                dataSource={dataSource.data}
+                rowKey="id"
+              />
+            )}
             <div
               style={{
                 marginTop: '20px',
@@ -288,8 +293,20 @@ const Property = (props: Props) => {
                 }}
               />
             </div>
-          )}
-        </div>
+          </div>
+        ) : (
+          <div
+            style={{
+              height: 400,
+              display: 'flex',
+              alignItems: 'center',
+              width: '100%',
+              justifyContent: 'center',
+            }}
+          >
+            <Empty />
+          </div>
+        )}
       </Spin>
       {visible && (
         <EditProperty

+ 32 - 16
src/pages/device/Instance/Detail/Running/index.tsx

@@ -1,5 +1,5 @@
 import { InstanceModel } from '@/pages/device/Instance';
-import { Card, Input, Tabs } from 'antd';
+import { Card, Empty, Input, Tabs } from 'antd';
 import type { DeviceMetadata } from '@/pages/device/Product/typings';
 import Property from '@/pages/device/Instance/Detail/Running/Property';
 import Event from '@/pages/device/Instance/Detail/Running/Event';
@@ -33,21 +33,37 @@ const Running = () => {
 
   return (
     <Card>
-      <Tabs
-        defaultActiveKey="1"
-        tabPosition="left"
-        style={{ minHeight: 600 }}
-        tabBarExtraContent={{ left: operations() }}
-      >
-        <Tabs.TabPane tab="属性" key="1">
-          <Property data={metadata?.properties || []} />
-        </Tabs.TabPane>
-        {list?.map((item) => (
-          <Tabs.TabPane tab={item.name} key={item.id}>
-            <Event data={item} />
-          </Tabs.TabPane>
-        ))}
-      </Tabs>
+      {list?.length === 0 && (metadata?.properties || [])?.length === 0 ? (
+        <div
+          style={{
+            height: 480,
+            display: 'flex',
+            alignItems: 'center',
+            width: '100%',
+            justifyContent: 'center',
+          }}
+        >
+          <Empty />
+        </div>
+      ) : (
+        <div className="tabs-full-active">
+          <Tabs
+            defaultActiveKey="1"
+            tabPosition="left"
+            style={{ minHeight: 600 }}
+            tabBarExtraContent={{ left: operations() }}
+          >
+            <Tabs.TabPane tab="属性" key="1">
+              <Property data={metadata?.properties || []} />
+            </Tabs.TabPane>
+            {list?.map((item) => (
+              <Tabs.TabPane tab={item.name} key={item.id}>
+                <Event data={item} />
+              </Tabs.TabPane>
+            ))}
+          </Tabs>
+        </div>
+      )}
     </Card>
   );
 };

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

@@ -25,6 +25,7 @@ const Access = () => {
   const [config, setConfig] = useState<any>();
   const [access, setAccess] = useState<any>();
   const { permission } = usePermissions('link/AccessConfig');
+  const [dataSource, setDataSource] = useState<any[]>([]);
 
   const MetworkTypeMapping = new Map();
   MetworkTypeMapping.set('websocket-server', 'WEB_SOCKET_SERVER');
@@ -204,6 +205,11 @@ const Access = () => {
         productModel.current?.messageProtocol || '',
         productModel.current?.transportProtocol || '',
       );
+      service.getProviders().then((resp) => {
+        if (resp.status === 200) {
+          setDataSource(resp.result);
+        }
+      });
     }
   }, [productModel.current]);
 
@@ -386,16 +392,19 @@ const Access = () => {
                     </span>
                   }
                 />
-                <div className={styles.context}>{access?.name || '--'}</div>
-                <div className={styles.context}>{access?.description || '--'}</div>
+                <div className={styles.context}>{access?.name}</div>
+                <div className={styles.context}>
+                  {access?.description ||
+                    dataSource.find((item) => item?.id === access?.provider)?.description}
+                </div>
               </div>
 
               <div className={styles.item}>
                 <TitleComponent data={'消息协议'} />
-                <div className={styles.context}>{access?.protocolDetail?.name || '--'}</div>
+                <div className={styles.context}>{access?.protocolDetail?.name}</div>
                 {config?.document && (
                   <div className={styles.context}>
-                    <ReactMarkdown>{config?.document || '--'}</ReactMarkdown>
+                    <ReactMarkdown>{config?.document}</ReactMarkdown>
                   </div>
                 )}
               </div>
@@ -404,11 +413,7 @@ const Access = () => {
                 {(access?.channelInfo?.addresses || []).length > 0
                   ? (access?.channelInfo?.addresses || []).map((item: any) => (
                       <div key={item.address}>
-                        <Badge
-                          color={item.health === -1 ? 'red' : 'green'}
-                          text={item.address}
-                          style={{ marginLeft: '20px' }}
-                        />
+                        <Badge color={item.health === -1 ? 'red' : 'green'} text={item.address} />
                       </div>
                     ))
                   : '暂无连接信息'}

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

@@ -120,7 +120,10 @@ const ProductDetail = observer(() => {
             }
           }
           productModel.current = item;
-          message.success('操作成功');
+          message.success({
+            key: 'metadata',
+            content: '操作成功!',
+          });
         },
         error: async () => {
           message.success('操作失败');
@@ -205,6 +208,10 @@ const ProductDetail = observer(() => {
   ];
 
   useEffect(() => {
+    const { state } = location;
+    if (state && state?.tab) {
+      setMode(state?.tab);
+    }
     if ((location as any).query?.key) {
       setMode((location as any).query?.key || 'base');
     }
@@ -215,13 +222,6 @@ const ProductDetail = observer(() => {
       }
     });
     return () => subscription.unsubscribe();
-  }, []);
-
-  useEffect(() => {
-    const { state } = location;
-    if (state && state?.tab) {
-      setMode(state?.tab);
-    }
   }, [location]);
 
   return (

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

@@ -1049,7 +1049,10 @@ const Edit = observer((props: Props) => {
         if (deploy) {
           Store.set('product-deploy', deploy);
         } else {
-          message.success('操作成功!');
+          message.success({
+            key: 'metadata',
+            content: '操作成功!',
+          });
         }
         MetadataModel.edit = false;
         MetadataModel.item = {};

+ 2 - 2
src/pages/home/components/Steps.tsx

@@ -17,8 +17,8 @@ interface StepsProps {
 const ItemDefaultImg = require('/public/images/home/bottom-1.png');
 const StepsItem = (props: StepItemProps) => {
   return (
-    <div className={'step-item step-bar arrow-1'} onClick={props.onClick}>
-      <div className={'step-item-title'}>
+    <div className={'step-item step-bar arrow-1'}>
+      <div className={'step-item-title'} onClick={props.onClick}>
         <div className={'step-item-img'}>
           <img src={props.url || ItemDefaultImg} />
         </div>

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

@@ -143,6 +143,7 @@
         font-weight: bold;
         font-size: 20px;
         background-color: #f8f9fd;
+        cursor: pointer;
 
         .step-item-img {
           position: absolute;

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

@@ -232,7 +232,7 @@ const Comprehensive = () => {
           title={
             <span>
               设备接入推荐步骤
-              <Tooltip title={'不同的设备因为通信协议的不,存在接入步骤的差异'}>
+              <Tooltip title={'不同的设备因为通信协议的不,存在接入步骤的差异'}>
                 <QuestionCircleOutlined style={{ paddingLeft: 12 }} />
               </Tooltip>
             </span>

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

@@ -129,7 +129,7 @@ const Device = () => {
           title={
             <span>
               设备接入推荐步骤
-              <Tooltip title={'不同的设备因为通信协议的不,存在接入步骤的差异'}>
+              <Tooltip title={'不同的设备因为通信协议的不,存在接入步骤的差异'}>
                 <QuestionCircleOutlined style={{ paddingLeft: 12 }} />
               </Tooltip>
             </span>

+ 26 - 0
src/pages/link/Certificate/Detail/index.less

@@ -0,0 +1,26 @@
+.doc {
+  height: 100%;
+  padding: 24px;
+  overflow-y: auto;
+  color: rgba(#000, 0.8);
+  font-size: 14px;
+  background-color: #fff;
+
+  h1 {
+    margin: 16px 0;
+    color: rgba(#000, 0.85);
+    font-weight: bold;
+    font-size: 14px;
+
+    &:first-child {
+      margin-top: 0;
+    }
+  }
+
+  h2 {
+    margin: 6px 10px;
+    color: rgba(0, 0, 0, 0.8);
+    font-weight: 400;
+    font-size: 14px;
+  }
+}

+ 19 - 0
src/pages/link/Certificate/Detail/index.tsx

@@ -11,6 +11,7 @@ import CertificateFile from './components/CertificateFile';
 import Standard from './components/Standard';
 import { service } from '@/pages/link/Certificate';
 import { useParams } from 'umi';
+import './index.less';
 
 const Detail = observer(() => {
   const params = useParams<{ id: string }>();
@@ -156,6 +157,24 @@ const Detail = observer(() => {
               </FormButtonGroup.Sticky>
             </Form>
           </Col>
+          <Col span={12}>
+            <div className="doc">
+              <h1>1. 概述</h1>
+              <div>
+                证书由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能,保障设备与平台间的数据传输安全。配置后可被网络组件引用。
+              </div>
+              <h1>2. 配置说明</h1>
+              <h2>1、证书文件</h2>
+              <div>
+                您可以使用文本编辑工具打开PEM或者CRT格式的证书文件,复制其中的内容并粘贴到该文本框,或者单击该文本框下的上传,并选择存储在本地计算机的证书文件,将文件内容上传到文本框。
+              </div>
+              <h2>2、证书私钥</h2>
+              <div>
+                填写证书私钥内容的PEM编码。
+                您可以使用文本编辑工具打开KEY格式的证书私钥文件,复制其中的内容并粘贴到该文本框,或者单击该文本框下的上传并选择存储在本地计算机的证书私钥文件,将文件内容上传到文本框。
+              </div>
+            </div>
+          </Col>
         </Row>
       </Card>
     </PageContainer>

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

@@ -141,7 +141,7 @@ export default () => {
             title={
               <span>
                 设备接入推荐步骤
-                <Tooltip title={'不同的设备因为通信协议的不,存在接入步骤的差异'}>
+                <Tooltip title={'不同的设备因为通信协议的不,存在接入步骤的差异'}>
                   <QuestionCircleOutlined style={{ paddingLeft: 12 }} />
                 </Tooltip>
               </span>

+ 94 - 108
src/pages/rule-engine/Alarm/Config/index.tsx

@@ -5,7 +5,7 @@ import { createSchemaField } from '@formily/react';
 import { ArrayItems, Form, FormButtonGroup, FormGrid, FormItem, Input } from '@formily/antd';
 import type { ISchema } from '@formily/json-schema';
 import { useMemo, useState } from 'react';
-import { createForm, onFieldReact, onFormInit } from '@formily/core';
+import { createForm, onFormInit } from '@formily/core';
 import FLevelInput from '@/components/FLevelInput';
 import type { IOConfigItem } from '@/pages/rule-engine/Alarm/Config/typing';
 import Service from '@/pages/rule-engine/Alarm/Config/service';
@@ -23,63 +23,54 @@ const Config = () => {
       name: '告警名称',
       type: 'string',
       desc: '推送的告警名称',
-      example: '烟感告警',
     },
     {
       key: 'id',
       name: '告警ID',
       type: 'string',
       desc: '告警唯一性标识',
-      example: '1515992841393119232',
     },
     {
       key: 'targetType',
       name: '告警类型',
       type: 'string',
       desc: '告警所属的业务类型,具体有产品、设备、部门、其他',
-      example: '产品',
     },
     {
       key: 'targetId',
       name: '告警目标ID',
       type: 'string',
       desc: '告警目标唯一性标识',
-      example: '运维部',
     },
     {
       key: 'targetName',
       name: '告警目标名称',
       type: 'string',
       desc: '告警目标实例名称',
-      example: '烟感告警',
     },
     {
       key: 'alarmDate',
       name: '最近告警时间',
       type: 'date',
       desc: '最近一次的告警触发时间',
-      example: '2021-01-01 09:00:00',
     },
     {
       key: 'level',
       name: '告警级别',
       type: 'int',
       desc: '告警严重程度指标',
-      example: '1',
     },
     {
       key: 'state',
       name: '告警状态',
       type: 'object',
       desc: 'value:告警状态 text:告警值',
-      example: '"text": "告警中", "value": "warning"',
     },
     {
       key: 'description',
       name: '告警说明',
       type: 'string',
       desc: '告警规则说明',
-      example: '1楼烟感统一告警规则设置',
     },
   ];
   const outputColumns = [
@@ -107,12 +98,6 @@ const Config = () => {
       key: 'desc',
       ellipsis: true,
     },
-    {
-      title: '示例值',
-      dataIndex: 'example',
-      key: 'example',
-      ellipsis: true,
-    },
   ];
 
   const subData = [
@@ -122,7 +107,6 @@ const Config = () => {
       type: 'string',
       require: '是',
       desc: '订阅的告警唯一性标识',
-      example: '1515992841393119232',
     },
     {
       key: 'describe',
@@ -130,7 +114,6 @@ const Config = () => {
       type: 'string',
       require: '是',
       desc: '告警处理内容详细描述说明',
-      example: '已联系第三方人员进行告警处理,现告警已恢复',
     },
     {
       key: 'state',
@@ -138,7 +121,6 @@ const Config = () => {
       type: 'string',
       require: '是',
       desc: '告警中, 无告警',
-      example: '告警中',
     },
     {
       key: 'handleTime',
@@ -146,7 +128,6 @@ const Config = () => {
       type: 'long',
       require: '否',
       desc: '告警处理时间,不填是默认为消息处理时间',
-      example: '1651233650840',
     },
   ];
 
@@ -179,20 +160,23 @@ const Config = () => {
               const _level = resp.result.levels.map(
                 (item: { level: number; title: string }) => item.title,
               );
+              while (_level.length < 5) {
+                _level.push('');
+              }
               form.setValuesIn('level', _level);
             }
           });
-          onFieldReact('level.0.remove', (state, f1) => {
-            state.setState({ display: 'none' });
-            f1.setFieldState('level.add', (state1) => {
-              const length = f1.values.level?.length;
-              if (length > 4) {
-                state1.display = 'none';
-              } else {
-                state1.display = 'visible';
-              }
-            });
-          });
+          // onFieldReact('level.0.remove', (state, f1) => {
+          //   state.setState({ display: 'none' });
+          //   f1.setFieldState('level.add', (state1) => {
+          //     const length = f1.values.level?.length;
+          //     if (length > 4) {
+          //       state1.display = 'none';
+          //     } else {
+          //       state1.display = 'visible';
+          //     }
+          //   });
+          // });
         },
       }),
     [],
@@ -256,27 +240,27 @@ const Config = () => {
                 gridSpan: 23,
               },
             },
-            remove: {
-              type: 'void',
-              title: <div style={{ width: '20px' }} />,
-              'x-decorator': 'FormItem',
-              'x-component': 'ArrayItems.Remove',
-              'x-decorator-props': {
-                gridSpan: 1,
-              },
-              'x-component-props': {
-                style: { marginTop: '40px' },
-              },
-            },
-          },
-        },
-        properties: {
-          add: {
-            type: 'void',
-            title: '添加级别',
-            'x-component': 'ArrayItems.Addition',
+            // remove: {
+            //   type: 'void',
+            //   title: <div style={{ width: '20px' }} />,
+            //   'x-decorator': 'FormItem',
+            //   'x-component': 'ArrayItems.Remove',
+            //   'x-decorator-props': {
+            //     gridSpan: 1,
+            //   },
+            //   'x-component-props': {
+            //     style: { marginTop: '40px' },
+            //   },
+            // },
           },
         },
+        // properties: {
+        //   add: {
+        //     type: 'void',
+        //     title: '添加级别',
+        //     'x-component': 'ArrayItems.Addition',
+        //   },
+        // },
       },
     },
   };
@@ -308,43 +292,43 @@ const Config = () => {
           placeholder: '请输入topic',
         },
       },
-      layout2: {
-        type: 'void',
-        'x-decorator': 'FormGrid',
-        'x-decorator-props': {
-          maxColumns: 2,
-          minColumns: 2,
-          columnGap: 24,
-        },
-        properties: {
-          username: {
-            title: '用户名',
-            type: 'string',
-            // required: true,
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-component-props': {
-              placeholder: '请输入用户名',
-            },
-            'x-decorator-props': {
-              gridSpan: 1,
-            },
-          },
-          password: {
-            title: '密码',
-            type: 'string',
-            // required: true,
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              gridSpan: 1,
-            },
-            'x-component-props': {
-              placeholder: '请输入密码',
-            },
-          },
-        },
-      },
+      // layout2: {
+      //   type: 'void',
+      //   'x-decorator': 'FormGrid',
+      //   'x-decorator-props': {
+      //     maxColumns: 2,
+      //     minColumns: 2,
+      //     columnGap: 24,
+      //   },
+      //   properties: {
+      //     username: {
+      //       title: '用户名',
+      //       type: 'string',
+      //       // required: true,
+      //       'x-decorator': 'FormItem',
+      //       'x-component': 'Input',
+      //       'x-component-props': {
+      //         placeholder: '请输入用户名',
+      //       },
+      //       'x-decorator-props': {
+      //         gridSpan: 1,
+      //       },
+      //     },
+      //     password: {
+      //       title: '密码',
+      //       type: 'string',
+      //       // required: true,
+      //       'x-decorator': 'FormItem',
+      //       'x-component': 'Input',
+      //       'x-decorator-props': {
+      //         gridSpan: 1,
+      //       },
+      //       'x-component-props': {
+      //         placeholder: '请输入密码',
+      //       },
+      //     },
+      //   },
+      // },
     },
   };
 
@@ -486,28 +470,30 @@ const Config = () => {
         </div>
       </Col>
       <Col span={10}>
-        <div style={{ marginLeft: 20 }} className={styles.doc}>
-          <h1>功能图示</h1>
-          <div className={styles.image}>
-            <Image width="100%" src={ioImg} />
-          </div>
-          <h1>功能说明</h1>
-          <div>
-            1、平台支持将告警数据输出到kafka,第三方系统可订阅kafka中的告警数据,进行业务处理。
-          </div>
-          <h2>输出参数</h2>
-          <div>
-            <Table dataSource={outputData} pagination={false} columns={outputColumns} />
-          </div>
-          <h2>示例</h2>
-          <ReactMarkdown className={styles.code}>{outputText}</ReactMarkdown>
-          <div>2、平台支持订阅kafka中告警处理数据,并更新告警记录状态。</div>
-          <h2>订阅参数</h2>
-          <div>
-            <Table dataSource={subData} pagination={false} columns={subColumns} />
+        <div style={{ height: 560, marginLeft: 20, paddingBottom: 24 }}>
+          <div className={styles.doc}>
+            <h1>功能图示</h1>
+            <div className={styles.image}>
+              <Image width="100%" src={ioImg} />
+            </div>
+            <h1>功能说明</h1>
+            <div>
+              1、平台支持将告警数据输出到kafka,第三方系统可订阅kafka中的告警数据,进行业务处理。
+            </div>
+            <h2>输出参数</h2>
+            <div>
+              <Table dataSource={outputData} pagination={false} columns={outputColumns} />
+            </div>
+            <h2>示例</h2>
+            <ReactMarkdown className={styles.code}>{outputText}</ReactMarkdown>
+            <div>2、平台支持订阅kafka中告警处理数据,并更新告警记录状态。</div>
+            <h2>订阅参数</h2>
+            <div>
+              <Table dataSource={subData} pagination={false} columns={subColumns} />
+            </div>
+            <h2>示例</h2>
+            <ReactMarkdown className={styles.code}>{subText}</ReactMarkdown>
           </div>
-          <h2>示例</h2>
-          <ReactMarkdown className={styles.code}>{subText}</ReactMarkdown>
         </div>
       </Col>
     </Row>

+ 1 - 1
src/pages/system/DataSource/Save/index.tsx

@@ -159,7 +159,7 @@ const Save = (props: Props) => {
               gridSpan: 2,
             },
             'x-component-props': {
-              placeholder: '请输入接地址,示例:localhost:5672',
+              placeholder: '请输入接地址,示例:localhost:5672',
             },
             'x-validator': [
               {

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

@@ -189,8 +189,16 @@ const DataSource = observer(() => {
         >
           <Popconfirm
             onConfirm={async () => {
-              await service.remove(record.id);
-              actionRef.current?.reload();
+              const resp: any = await service.remove(record.id);
+              if (resp.status === 200) {
+                message.success(
+                  intl.formatMessage({
+                    id: 'pages.data.option.success',
+                    defaultMessage: '操作成功!',
+                  }),
+                );
+                actionRef.current?.reload();
+              }
             }}
             title="确认删除?"
           >

+ 3 - 2
src/pages/system/Role/Detail/Permission/Allocate/MenuPermission.tsx

@@ -59,7 +59,7 @@ const MenuPermission = (props: Props) => {
           paddingLeft: (props?.level || 0) * 10,
           transition: 'background .3s',
           borderBottom: '1px solid #f0f0f0',
-          height: 50,
+          minHeight: 50,
         }}
         key={value?.id}
       >
@@ -118,7 +118,7 @@ const MenuPermission = (props: Props) => {
               {value?.name}
             </Checkbox>
           </div>
-          <div>
+          <div style={{ padding: 5 }}>
             {value.id === 'menu-permission' ? (
               <span style={{ fontWeight: value.id === 'menu-permission' ? 600 : 400 }}>
                 操作权限
@@ -156,6 +156,7 @@ const MenuPermission = (props: Props) => {
                   };
                   props.change(d);
                 }}
+                style={{ width: '100%' }}
                 options={(value?.buttons || []).map((i: any) => ({
                   label: i.name,
                   value: i.id,

+ 7 - 1
src/pages/system/User/Save/index.tsx

@@ -348,7 +348,7 @@ const Save = (props: Props) => {
             'x-component-props': {
               multiple: true,
               showArrow: true,
-              placeholder: '请选择角色',
+              placeholder: '请选择部门',
               showCheckedStrategy: ATreeSelect.SHOW_ALL,
               filterOption: (input: string, option: any) =>
                 option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
@@ -395,6 +395,9 @@ const Save = (props: Props) => {
             'x-decorator-props': {
               gridSpan: 1,
             },
+            'x-component-props': {
+              placeholder: '请输入手机号',
+            },
           },
           email: {
             title: '邮箱',
@@ -404,6 +407,9 @@ const Save = (props: Props) => {
             'x-decorator-props': {
               gridSpan: 1,
             },
+            'x-component-props': {
+              placeholder: '请输入邮箱',
+            },
           },
         },
       },