ソースを参照

Merge wzy

Next wzy
XieYongHong 3 年 前
コミット
cabfdcb59b

+ 4 - 4
config/proxy.ts

@@ -12,11 +12,11 @@ export default {
       // target: 'http://192.168.32.28:8844/',
       // ws: 'ws://192.168.32.28:8844/',
       // 开发环境
-      // target: 'http://120.79.18.123:8844/',
-      // ws: 'ws://120.79.18.123:8844/',
+      target: 'http://120.79.18.123:8844/',
+      ws: 'ws://120.79.18.123:8844/',
       // 测试环境
-      target: 'http://120.77.179.54:8844/',
-      ws: 'ws://120.77.179.54:8844/',
+      // target: 'http://120.77.179.54:8844/',
+      // ws: 'ws://120.77.179.54:8844/',
       // target: 'http://192.168.66.5:8844/',
       // ws: 'ws://192.168.66.5:8844/',
       // ws: 'ws://demo.jetlinks.cn/jetlinks',

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

@@ -376,7 +376,7 @@ export default (props: Props) => {
                 title: (
                   <>
                     点位名称
-                    <Tooltip title="名称(从站ID/地址/功能码))">
+                    <Tooltip title="名称(从站ID/地址/功能码)">
                       <QuestionCircleOutlined />
                     </Tooltip>
                   </>
@@ -505,7 +505,7 @@ export default (props: Props) => {
   return (
     <Card className="modbus" style={{ minHeight }}>
       {empty ? (
-        <Empty description={'暂无数据,请配置物模型'} />
+        <Empty description={'暂无数据,请配置物模型'} style={{ marginTop: '10%' }} />
       ) : (
         <>
           <div className="edit-top">

+ 16 - 14
src/pages/home/ops/index.tsx

@@ -1,6 +1,5 @@
 import { Col, message, Row, Tooltip } from 'antd';
 import Guide from '../components/Guide';
-import { PermissionButton } from '@/components';
 import Statistics from '../components/Statistics';
 import Pie from '@/pages/home/components/Pie';
 import { getMenuPathByCode, MENUS_CODE } from '@/utils/menu';
@@ -16,10 +15,9 @@ const Ops = () => {
   const [subscribeTopic] = useSendWebsocketMessage();
   const history = useHistory();
 
-  const productPermission = PermissionButton.usePermission('device/Product').permission;
-  const devicePermission = PermissionButton.usePermission('device/Instance').permission;
-  const rulePermission = PermissionButton.usePermission('rule-engine/Instance').permission;
-
+  const accessPermission = getMenuPathByCode(MENUS_CODE['link/AccessConfig']);
+  const logPermission = getMenuPathByCode(MENUS_CODE['Log']);
+  const linkPermission = getMenuPathByCode(MENUS_CODE['link/DashBoard']);
   const [cpuValue, setCpuValue] = useState<number>(0);
   const [jvmValue, setJvmValue] = useState<number>(0);
 
@@ -57,30 +55,34 @@ const Ops = () => {
       jvmRealTime?.unsubscribe();
     };
   }, []);
+
   const guideOpsList: any[] = [
     {
       key: 'product',
       name: '设备接入配置',
       english: 'STEP1',
-      auth: !!productPermission.add,
-      url: 'device/Product',
-      param: '?save=true',
+      auth: !!accessPermission,
+      url: accessPermission,
     },
     {
       key: 'device',
       name: '日志排查',
       english: 'STEP2',
-      auth: !!devicePermission.add,
-      url: 'device/Instance',
-      param: '?save=true',
+      auth: !!logPermission,
+      url: logPermission,
+      param: {
+        key: 'system',
+      },
     },
     {
       key: 'rule-engine',
       name: '实时监控',
       english: 'STEP3',
-      auth: !!rulePermission.add,
-      url: 'rule-engine/Instance',
-      param: '?save=true',
+      auth: !!linkPermission,
+      url: linkPermission,
+      param: {
+        save: true,
+      },
     },
   ];
   return (

+ 0 - 278
src/pages/link/Channel/Modbus/Access/addPoint/index.tsx

@@ -1,278 +0,0 @@
-import { Col, Form, Input, InputNumber, Modal, Row, Select } from 'antd';
-import { useEffect, useState } from 'react';
-import { service } from '@/pages/link/Channel/Modbus';
-import { onlyMessage } from '@/utils/util';
-
-interface Props {
-  data: any;
-  deviceId: string;
-  opcUaId: string;
-  close: Function;
-}
-
-const AddPoint = (props: Props) => {
-  const { opcUaId, deviceId, data } = props;
-  const [form] = Form.useForm();
-  const [property, setProperty] = useState<any>([]);
-
-  const handleSave = async () => {
-    const formData = await form.validateFields();
-    service
-      .saveMetadataConfig(opcUaId, deviceId, {
-        ...data,
-        ...formData,
-        metadataType: 'property',
-        codec: 'number',
-      })
-      .then((res: any) => {
-        if (res.status === 200) {
-          onlyMessage('操作成功!');
-          props.close();
-        }
-      });
-  };
-
-  useEffect(() => {
-    console.log(props.data);
-    service.deviceDetail(props.deviceId).then((res: any) => {
-      if (res.result.metadata) {
-        const item = JSON.parse(res.result?.metadata);
-        setProperty(item.properties);
-      }
-    });
-  }, []);
-  return (
-    <Modal
-      title={props.data.id ? '编辑' : '新增'}
-      visible
-      width="40vw"
-      destroyOnClose
-      onOk={handleSave}
-      onCancel={() => {
-        props.close();
-      }}
-    >
-      <Form
-        form={form}
-        layout="vertical"
-        initialValues={{
-          ...props.data,
-          codecConfig: {
-            ...props.data?.codecConfig,
-            readIndex: props.data?.codecConfig?.readIndex || 0,
-            scaleFactor: props.data?.codecConfig?.scaleFactor || 1,
-            revertBytes: props.data?.codecConfig?.revertBytes || false,
-          },
-        }}
-      >
-        <Row gutter={[24, 24]}>
-          <Col span={12}>
-            <Form.Item
-              label="属性"
-              name="metadataId"
-              required
-              rules={[{ required: true, message: '属性必选' }]}
-            >
-              <Select placeholder="请选择属性">
-                {property.map((item: any) => (
-                  <Select.Option value={item.id} key={item.id}>
-                    {item.name}
-                  </Select.Option>
-                ))}
-              </Select>
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item
-              label="功能码"
-              name="function"
-              required
-              rules={[{ required: true, message: '功能码必选' }]}
-            >
-              <Select placeholder="请选择">
-                <Select.Option value={'Coils'}>线圈寄存器</Select.Option>
-                <Select.Option value={'HoldingRegisters'}>保存寄存器</Select.Option>
-                <Select.Option value={'InputRegisters'}>输入寄存器</Select.Option>
-              </Select>
-            </Form.Item>
-          </Col>
-        </Row>
-        <Row gutter={[24, 24]}>
-          <Col span={24}>
-            <Form.Item
-              label="从站ID"
-              name="unitId"
-              required
-              rules={[
-                { required: true, message: '从站ID' },
-                ({}) => ({
-                  validator(_, value) {
-                    if (value !== 0 || /(^[1-9]\d*$)/.test(value)) {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('请输入非0正整数'));
-                  },
-                }),
-              ]}
-            >
-              <InputNumber style={{ width: '100%' }} placeholder="请输入" min={0} />
-            </Form.Item>
-          </Col>
-        </Row>
-        <Row gutter={[24, 24]}>
-          <Col span={12}>
-            <Form.Item
-              label="读取起始位置"
-              name={['codecConfig', 'readIndex']}
-              required
-              rules={[
-                { required: true, message: '请输入读取起始位置' },
-                ({}) => ({
-                  validator(_, value) {
-                    if (/(^[0-9]\d*$)/.test(value)) {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('请输入正整数'));
-                  },
-                }),
-              ]}
-            >
-              <InputNumber style={{ width: '100%' }} placeholder="请输入" min={0} />
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item label="读取长度" name={['codecConfig', 'readLength']} required>
-              <Select placeholder="请选择">
-                <Select.Option value={1}>1</Select.Option>
-                <Select.Option value={2}>2</Select.Option>
-                <Select.Option value={3}>3</Select.Option>
-                <Select.Option value={4}>4</Select.Option>
-                <Select.Option value={8}>8</Select.Option>
-              </Select>
-            </Form.Item>
-          </Col>
-        </Row>
-        <Row gutter={[24, 24]}>
-          <Col span={12}>
-            <Form.Item
-              label="地址"
-              name="address"
-              tooltip="要获取的对象地址"
-              rules={[
-                { required: true, message: '请输入读取长度' },
-                ({}) => ({
-                  validator(_, value) {
-                    if (value > 1 && value < 255) {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('请输入1~255之间的数字'));
-                  },
-                }),
-              ]}
-            >
-              <InputNumber style={{ width: '100%' }} placeholder="请输入" min={1} />
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item
-              label="寄存器数量"
-              name="quantity"
-              rules={[
-                { required: true, message: '请输入寄存器数量' },
-                ({}) => ({
-                  validator(_, value) {
-                    if (/(^[0-9]\d*$)/.test(value)) {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('请输入正整数'));
-                  },
-                }),
-              ]}
-            >
-              <InputNumber style={{ width: '100%' }} placeholder="请输入" min={1} />
-            </Form.Item>
-          </Col>
-        </Row>
-        <Row gutter={[24, 24]}>
-          <Col span={12}>
-            <Form.Item
-              label="变换器寄存器高低字节"
-              name={['codecConfig', 'revertBytes']}
-              required
-              rules={[{ required: true, message: '变换器寄存器高低字节必填' }]}
-            >
-              <Select placeholder="请选择">
-                <Select.Option value={false}>否</Select.Option>
-                <Select.Option value={true}>是</Select.Option>
-              </Select>
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item
-              label="缩放因子"
-              name={['codecConfig', 'scaleFactor']}
-              required
-              tooltip="基于原始数据按比例进行数据缩放。默认比例为1,不能为0"
-              rules={[
-                { required: true, message: '请输入缩放因子' },
-                ({}) => ({
-                  validator(_, value) {
-                    if (value !== 0) {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('请输入正整数'));
-                  },
-                }),
-              ]}
-            >
-              <InputNumber style={{ width: '100%' }} placeholder="请输入" />
-            </Form.Item>
-          </Col>
-        </Row>
-        <Row gutter={[24, 24]}>
-          <Col span={12}>
-            <Form.Item
-              label="数据格式"
-              name={['codecConfig', 'format']}
-              required
-              rules={[{ required: true, message: '数据格式必选' }]}
-            >
-              <Select placeholder="请选择">
-                <Select.Option value={'unsigned'}>无符号数字</Select.Option>
-                <Select.Option value={'signed'}>有符号数字</Select.Option>
-                <Select.Option value={'ieee754'}>IEEE754</Select.Option>
-              </Select>
-            </Form.Item>
-          </Col>
-          <Col span={12}>
-            <Form.Item
-              label="读取数据周期"
-              name="interval"
-              tooltip="若不填写表示不定时拉取数据"
-              rules={[
-                ({}) => ({
-                  validator(_, value) {
-                    if (value !== 0 || /(^[1-9]\d*$)/.test(value)) {
-                      return Promise.resolve();
-                    }
-                    return Promise.reject(new Error('请输入正整数'));
-                  },
-                }),
-              ]}
-            >
-              <InputNumber style={{ width: '100%' }} placeholder="请输入" addonAfter={<>ms</>} />
-            </Form.Item>
-          </Col>
-        </Row>
-        <Row gutter={[24, 24]}>
-          <Col span={24}>
-            <Form.Item label="说明" name="description">
-              <Input.TextArea maxLength={200} placeholder="请输入说明" />
-            </Form.Item>
-          </Col>
-        </Row>
-      </Form>
-    </Modal>
-  );
-};
-export default AddPoint;

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

@@ -1,139 +0,0 @@
-import { Modal } from '@/components';
-import SearchComponent from '@/components/SearchComponent';
-import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Badge } from 'antd';
-import { useRef, useState } from 'react';
-import { service } from '@/pages/link/Channel/Modbus';
-import moment from 'moment';
-import { onlyMessage } from '@/utils/util';
-
-interface Props {
-  id: string;
-  close: () => void;
-}
-
-const BindDevice = (props: Props) => {
-  const actionRef = useRef<ActionType>();
-  const [param, setParam] = useState({});
-  const [keys, setKeys] = useState<any>([]);
-
-  const statusMap = new Map();
-  statusMap.set('在线', 'success');
-  statusMap.set('离线', 'error');
-  statusMap.set('禁用', 'processing');
-  statusMap.set('online', 'success');
-  statusMap.set('offline', 'error');
-  statusMap.set('notActive', 'processing');
-
-  const columns: ProColumns<any>[] = [
-    {
-      title: '设备ID',
-      dataIndex: 'id',
-      width: 200,
-      ellipsis: true,
-    },
-    {
-      title: '设备名称',
-      dataIndex: 'name',
-      width: 200,
-      ellipsis: true,
-    },
-    {
-      title: '产品名称',
-      dataIndex: 'productName',
-      width: 200,
-      ellipsis: true,
-    },
-    {
-      title: '注册时间',
-      // dataIndex: 'registryTime',
-      render: (_, record) => (
-        <>{record.registryTime ? moment(record.registryTime).format('YYYY-MM-DD HH:mm:ss') : '-'}</>
-      ),
-    },
-    {
-      title: '状态',
-      dataIndex: 'state',
-      renderText: (state) => <Badge text={state?.text} status={statusMap.get(state.value)} />,
-      valueType: 'select',
-      valueEnum: {
-        online: {
-          text: '在线',
-          status: 'disabled',
-        },
-        offline: {
-          text: '离线',
-          status: 'offline',
-        },
-        notActive: {
-          text: '禁用',
-          status: 'notActive',
-        },
-      },
-    },
-  ];
-
-  const save = () => {
-    if (keys && keys.length !== 0) {
-      service.bind(keys, props.id).then((res) => {
-        if (res.status === 200) {
-          onlyMessage('绑定成功');
-          props.close();
-        }
-      });
-    } else {
-      onlyMessage('请勾选数据', 'error');
-    }
-  };
-
-  return (
-    <Modal
-      title={'绑定设备'}
-      maskClosable={false}
-      visible
-      onCancel={props.close}
-      onOk={() => {
-        save();
-      }}
-      width={1300}
-      permissionCode={'device/Instance'}
-      permission={['edit', 'view']}
-    >
-      <SearchComponent
-        field={columns}
-        model={'simple'}
-        target="bindDevice"
-        defaultParam={[
-          { column: 'id$modbus-master$not', value: props.id },
-          { column: 'productId$dev-protocol', value: 'modbus-tcp' },
-        ]}
-        onSearch={(data) => {
-          // 重置分页数据
-          actionRef.current?.reset?.();
-          setParam(data);
-        }}
-      />
-      <ProTable
-        actionRef={actionRef}
-        params={param}
-        columns={columns}
-        rowKey="id"
-        columnEmptyText={''}
-        search={false}
-        request={async (params) =>
-          service.getDevice({
-            ...params,
-            sorts: [{ name: 'createTime', order: 'desc' }],
-          })
-        }
-        rowSelection={{
-          selectedRowKeys: keys,
-          onChange: (selectedRowKeys) => {
-            setKeys(selectedRowKeys);
-          },
-        }}
-      />
-    </Modal>
-  );
-};
-export default BindDevice;

+ 0 - 44
src/pages/link/Channel/Modbus/Access/index.less

@@ -1,44 +0,0 @@
-.list {
-  :global {
-    .ant-tabs-tab.ant-tabs-tab-active {
-      background-color: #fafafa;
-    }
-    .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
-      color: #1d39c4;
-      text-shadow: none;
-    }
-
-    .ant-tabs-content-holder {
-      width: 1px;
-    }
-
-    .ant-tabs > .ant-tabs-nav .ant-tabs-nav-more,
-    .ant-tabs > div > .ant-tabs-nav .ant-tabs-nav-more {
-      display: none;
-    }
-  }
-}
-
-.left {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  width: 200px;
-  .text {
-    width: 130px;
-    overflow: hidden;
-    white-space: nowrap;
-    text-align: left;
-    text-overflow: ellipsis;
-    word-break: break-all;
-  }
-  .icon {
-    display: none;
-  }
-}
-
-.left:hover {
-  .icon {
-    display: block;
-  }
-}

+ 0 - 434
src/pages/link/Channel/Modbus/Access/index.tsx

@@ -1,434 +0,0 @@
-import PermissionButton from '@/components/PermissionButton';
-import { PageContainer } from '@ant-design/pro-layout';
-import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
-import { Badge, Card, Empty, Input, Popconfirm, Tabs, Tooltip } from 'antd';
-import { useIntl, useLocation } from 'umi';
-import { useEffect, useRef, useState } from 'react';
-import {
-  DeleteOutlined,
-  DisconnectOutlined,
-  EditOutlined,
-  PlayCircleOutlined,
-  PlusOutlined,
-  StopOutlined,
-} from '@ant-design/icons';
-import BindDevice from '@/pages/link/Channel/Modbus/Access/bindDevice';
-import { service } from '@/pages/link/Channel/Modbus';
-import encodeQuery from '@/utils/encodeQuery';
-import styles from './index.less';
-import AddPoint from './addPoint';
-import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
-import { map } from 'rxjs/operators';
-import { useDomFullHeight } from '@/hooks';
-import { onlyMessage } from '@/utils/util';
-
-const Access = () => {
-  const intl = useIntl();
-  const actionRef = useRef<ActionType>();
-  const location = useLocation<string>();
-  const [param, setParam] = useState<any>({});
-  const [opcUaId, setOpcUaId] = useState<any>('');
-  const { permission } = PermissionButton.usePermission('link/Channel/Modbus');
-  const [deviceVisiable, setDeviceVisiable] = useState<boolean>(false);
-  const [pointVisiable, setPointVisiable] = useState<boolean>(false);
-  const [bindList, setBindList] = useState<any>([]);
-  const [deviceId, setDeviceId] = useState<string>('');
-  const [productId, setProductId] = useState<string>('');
-  const [current, setCurrent] = useState<any>({});
-  const [data, setData] = useState<any>([]);
-  const [subscribeTopic] = useSendWebsocketMessage();
-  const [propertyValue, setPropertyValue] = useState<any>({});
-  const wsRef = useRef<any>();
-  const [filterList, setFilterList] = useState([]);
-  const { minHeight } = useDomFullHeight(`.modbusAccess`, 26);
-
-  const columns: ProColumns<any>[] = [
-    {
-      title: '属性ID',
-      dataIndex: 'metadataId',
-      ellipsis: true,
-    },
-    {
-      title: '功能码',
-      render: (record: any) => <>{record.function?.text}</>,
-    },
-    {
-      title: '读取起始位置',
-      render: (record: any) => <>{record.codecConfig?.readIndex}</>,
-    },
-    {
-      title: '读取长度',
-      render: (record: any) => <>{record.codecConfig?.readLength}</>,
-    },
-    {
-      title: '值',
-      width: 100,
-      render: (record: any) => <>{propertyValue[record?.metadataId] || '-'}</>,
-    },
-    {
-      title: '状态',
-      dataIndex: 'state',
-      renderText: (state) => (
-        <Badge text={state?.text} status={state?.value === 'disabled' ? 'error' : 'success'} />
-      ),
-    },
-    {
-      title: '操作',
-      valueType: 'option',
-      align: 'center',
-      width: 200,
-      render: (text, record) => [
-        <PermissionButton
-          isPermission={permission.update}
-          key="edit"
-          onClick={() => {
-            setPointVisiable(true);
-            setCurrent(record);
-          }}
-          type={'link'}
-          style={{ padding: 0 }}
-          tooltip={{
-            title: intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            }),
-          }}
-        >
-          <EditOutlined />
-        </PermissionButton>,
-        <PermissionButton
-          type="link"
-          key={'action'}
-          style={{ padding: 0 }}
-          popConfirm={{
-            title: intl.formatMessage({
-              id: `pages.data.option.${
-                record.state?.value !== 'disabled' ? 'disabled' : 'enabled'
-              }.tips`,
-              defaultMessage: '确认禁用?',
-            }),
-            onConfirm: async () => {
-              const item = {
-                ...record,
-                state: record.state?.value === 'enabled' ? 'disabled' : 'enabled',
-              };
-              await service.saveMetadataConfig(opcUaId, deviceId, item);
-              onlyMessage(
-                intl.formatMessage({
-                  id: 'pages.data.option.success',
-                  defaultMessage: '操作成功!',
-                }),
-              );
-              actionRef.current?.reload();
-            },
-          }}
-          isPermission={permission.action}
-          tooltip={{
-            title: intl.formatMessage({
-              id: `pages.data.option.${record.state.value !== 'disabled' ? 'disabled' : 'enabled'}`,
-              defaultMessage: record.state?.value !== 'disabled' ? '禁用' : '启用',
-            }),
-          }}
-        >
-          {record.state?.value !== 'disabled' ? <StopOutlined /> : <PlayCircleOutlined />}
-        </PermissionButton>,
-        <PermissionButton
-          isPermission={permission.delete}
-          style={{ padding: 0 }}
-          disabled={record.state?.value === 'enabled'}
-          tooltip={{
-            title:
-              record.state?.value === 'disabled'
-                ? intl.formatMessage({
-                    id: 'pages.data.option.remove',
-                    defaultMessage: '删除',
-                  })
-                : '请先禁用该点位,再删除。',
-          }}
-          popConfirm={{
-            title: '确认删除',
-            disabled: record.state.value === 'enabled',
-            onConfirm: async () => {
-              const resp: any = await service.removeMetadataConfig(record.id);
-              if (resp.status === 200) {
-                onlyMessage(
-                  intl.formatMessage({
-                    id: 'pages.data.option.success',
-                    defaultMessage: '操作成功!',
-                  }),
-                );
-                actionRef.current?.reload();
-              }
-            },
-          }}
-          key="delete"
-          type="link"
-        >
-          <DeleteOutlined />
-        </PermissionButton>,
-      ],
-    },
-  ];
-
-  const getBindList = (masterId: any) => {
-    service
-      .bindDevice(
-        encodeQuery({
-          terms: {
-            'id$modbus-master': masterId,
-          },
-        }),
-      )
-      .then((res: any) => {
-        if (res.status === 200) {
-          if (res.result && res.result !== 0) {
-            setDeviceId(res.result[0]?.id);
-            setProductId(res.result[0]?.productId);
-            setBindList(res.result);
-            setFilterList(res.result);
-            setParam({
-              deviceId: res.result[0]?.id,
-              // terms: [{ column: 'deviceId', value: res.result[0]?.deviceId }],
-            });
-          }
-        }
-      });
-  };
-
-  useEffect(() => {
-    const item = new URLSearchParams(location.search);
-    const id = item.get('id');
-    if (id) {
-      setOpcUaId(id);
-      getBindList(id);
-    }
-  }, []);
-
-  useEffect(() => {
-    if (productId && deviceId) {
-      const point = data.map((item: any) => item.metadataId);
-      const id = `instance-info-property-${deviceId}-${productId}-${point.join('-')}`;
-      const topic = `/dashboard/device/${productId}/properties/realTime`;
-      wsRef.current = subscribeTopic?.(id, topic, {
-        deviceId: deviceId,
-        properties: data.map((item: any) => item.metadataId),
-        history: 1,
-      })
-        ?.pipe(map((res) => res.payload))
-        .subscribe((payload: any) => {
-          const { value } = payload;
-          propertyValue[value.property] = value.formatValue;
-          setPropertyValue({ ...propertyValue });
-          // console.log(propertyValue)
-        });
-    }
-    return () => wsRef.current && wsRef.current?.unsubscribe();
-  }, [data]);
-
-  // useEffect(() => {
-  //   console.log(deviceId);
-  // }, [deviceId]);
-
-  return (
-    <PageContainer>
-      <Card className={styles.list}>
-        <div className="modbusAccess" style={{ display: 'flex', minHeight }}>
-          <div>
-            <div style={{ width: '250px', marginTop: 15 }}>
-              <Input.Search
-                placeholder="请输入绑定设备名称"
-                allowClear
-                onSearch={(value) => {
-                  if (value) {
-                    const items = bindList.filter((item: any) => item.name.match(value));
-                    setFilterList(items);
-                    setFilterList(items);
-                    if (items.length === 0) {
-                      setParam({
-                        deviceId: undefined,
-                      });
-                    } else {
-                      setParam({
-                        deviceId: items[0]?.id,
-                        // terms: [{ column: 'deviceId', value: items[0]?.deviceId }],
-                      });
-                      setDeviceId(items[0]?.id);
-                    }
-                  } else {
-                    setFilterList(bindList);
-                    if (deviceId) {
-                      setParam({
-                        deviceId: deviceId,
-                      });
-                    } else {
-                      setParam({
-                        deviceId: undefined,
-                      });
-                    }
-                  }
-                }}
-              />
-              <PermissionButton
-                onClick={() => {
-                  setDeviceVisiable(true);
-                }}
-                isPermission={permission.add}
-                key="add"
-                icon={<PlusOutlined />}
-                type="dashed"
-                style={{ width: '100%', margin: '16px 0 18px 0' }}
-              >
-                绑定设备
-              </PermissionButton>
-            </div>
-            {filterList.length > 0 ? (
-              <Tabs
-                style={{ height: 600 }}
-                tabPosition={'left'}
-                activeKey={deviceId}
-                onChange={(e) => {
-                  setDeviceId(e);
-                  const items = bindList.find((item: any) => item.id === e);
-                  setProductId(items?.productId);
-                  setParam({
-                    deviceId: e,
-                  });
-                }}
-              >
-                {filterList.map((item: any) => (
-                  <Tabs.TabPane
-                    key={item.id}
-                    tab={
-                      <div className={styles.left}>
-                        <Tooltip title={item.name}>
-                          <div className={styles.text}>{item.name}</div>
-                        </Tooltip>
-                        <Popconfirm
-                          title="确认解绑该设备嘛?"
-                          onConfirm={() => {
-                            service.unbind([item.id], opcUaId).then((res: any) => {
-                              if (res.status === 200) {
-                                onlyMessage('解绑成功');
-                                getBindList(opcUaId);
-                              }
-                            });
-                          }}
-                          okText="是"
-                          cancelText="否"
-                        >
-                          <DisconnectOutlined className={styles.icon} />
-                        </Popconfirm>
-                      </div>
-                    }
-                  ></Tabs.TabPane>
-                ))}
-              </Tabs>
-            ) : (
-              <Empty description={<>暂无绑定设备</>} />
-            )}
-          </div>
-          <div style={{ width: '100%' }}>
-            <ProTable
-              actionRef={actionRef}
-              params={param}
-              columns={columns}
-              rowKey="id"
-              columnEmptyText={''}
-              search={false}
-              headerTitle={
-                <>
-                  <PermissionButton
-                    onClick={() => {
-                      setPointVisiable(true);
-                      setCurrent({});
-                    }}
-                    isPermission={permission.add}
-                    key="add"
-                    icon={<PlusOutlined />}
-                    type="primary"
-                  >
-                    {intl.formatMessage({
-                      id: 'pages.data.option.add',
-                      defaultMessage: '新增',
-                    })}
-                  </PermissionButton>
-                  <div style={{ marginLeft: 10 }}>
-                    <Input.Search
-                      placeholder="请输入属性ID"
-                      allowClear
-                      onSearch={(value) => {
-                        console.log(value);
-                        if (value) {
-                          setParam({
-                            terms: [
-                              { column: 'metadataId', value: `%${value}%`, termType: 'like' },
-                            ],
-                          });
-                        } else {
-                          setParam({
-                            deviceId: deviceId,
-                            // terms: [{ column: 'deviceId', value: deviceId }],
-                          });
-                        }
-                      }}
-                    />
-                  </div>
-                </>
-              }
-              request={async (params) => {
-                if (!params.deviceId) {
-                  return {
-                    code: 200,
-                    result: {
-                      data: [],
-                      pageIndex: 0,
-                      pageSize: 0,
-                      total: 0,
-                    },
-                    status: 200,
-                  };
-                }
-                const res = await service.queryMetadataConfig(opcUaId, params.deviceId, {
-                  ...params.terms,
-                  sorts: [{ name: 'createTime', order: 'desc' }],
-                });
-                setData(res.result.data);
-                return {
-                  code: res.message,
-                  result: {
-                    data: res.result.data,
-                    pageIndex: res.result.pageIndex,
-                    pageSize: res.result.pageSize,
-                    total: res.result.total,
-                  },
-                  status: res.status,
-                };
-              }}
-            />
-          </div>
-        </div>
-      </Card>
-      {deviceVisiable && (
-        <BindDevice
-          id={opcUaId}
-          close={() => {
-            setDeviceVisiable(false);
-            getBindList(opcUaId);
-          }}
-        />
-      )}
-      {pointVisiable && (
-        <AddPoint
-          deviceId={deviceId}
-          opcUaId={opcUaId}
-          data={current}
-          close={() => {
-            setPointVisiable(false);
-            actionRef.current?.reload();
-          }}
-        />
-      )}
-    </PageContainer>
-  );
-};
-export default Access;

+ 5 - 1
src/pages/link/Channel/Modbus/Export/index.tsx

@@ -11,7 +11,7 @@ import { downloadFile } from '@/utils/util';
 interface Props {
   visible: boolean;
   close: () => void;
-  masterId?: any;
+  data: any;
 }
 
 const Export = (props: Props) => {
@@ -94,9 +94,13 @@ const Export = (props: Props) => {
   };
   const downloadTemplate = async () => {
     const values = (await form.submit()) as any;
+    const masterName = props.data.find((item: any) => item.id === values.masterId)?.name;
     if (values) {
       downloadFile(
         `/${SystemConst.API_BASE}/modbus/point/${values.masterId}/export.${values.fileType}`,
+        {
+          masterName: masterName,
+        },
       );
       close();
     }

+ 0 - 190
src/pages/link/Channel/Modbus/Save/index.tsx

@@ -1,190 +0,0 @@
-import { useIntl } from 'umi';
-import { createForm } from '@formily/core';
-import { createSchemaField } from '@formily/react';
-import { Form, FormGrid, FormItem, Input, NumberPicker, Select } from '@formily/antd';
-import type { ISchema } from '@formily/json-schema';
-import { service } from '@/pages/link/Channel/Modbus';
-import { Modal } from '@/components';
-import { useEffect } from 'react';
-import { onlyMessage } from '@/utils/util';
-
-interface Props {
-  data: any;
-  close: () => void;
-  device?: any;
-}
-
-const Save = (props: Props) => {
-  const intl = useIntl();
-
-  const form = createForm({
-    validateFirst: true,
-    initialValues: props.data,
-  });
-
-  const SchemaField = createSchemaField({
-    components: {
-      FormItem,
-      Input,
-      Select,
-      FormGrid,
-      NumberPicker,
-    },
-  });
-
-  const schema: ISchema = {
-    type: 'object',
-    properties: {
-      layout: {
-        type: 'void',
-        'x-decorator': 'FormGrid',
-        'x-decorator-props': {
-          maxColumns: 2,
-          minColumns: 2,
-          columnGap: 24,
-        },
-        properties: {
-          name: {
-            title: '名称',
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-decorator-props': {
-              gridSpan: 2,
-            },
-            'x-component-props': {
-              placeholder: '请输入名称',
-            },
-            name: 'name',
-            'x-validator': [
-              {
-                max: 64,
-                message: '最多可输入64个字符',
-              },
-              {
-                required: true,
-                message: '请输入名称',
-              },
-            ],
-          },
-          host: {
-            title: 'IP',
-            'x-decorator-props': {
-              gridSpan: 2,
-            },
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input',
-            'x-component-props': {
-              placeholder: '请输入IP',
-            },
-            'x-validator': ['ipv4'],
-            name: 'host',
-            required: true,
-          },
-          port: {
-            title: '端口',
-            'x-decorator-props': {
-              gridSpan: 2,
-            },
-            type: 'string',
-            'x-decorator': 'FormItem',
-            'x-component': 'NumberPicker',
-            'x-component-props': {
-              placeholder: '请输入端口',
-            },
-            default: 502,
-            'x-validator': [
-              {
-                min: 1,
-                max: 65535,
-                message: '请输入1~65535之间的正整数',
-              },
-            ],
-            name: 'host',
-            required: true,
-          },
-          description: {
-            title: '说明',
-            'x-decorator': 'FormItem',
-            'x-component': 'Input.TextArea',
-            'x-component-props': {
-              rows: 5,
-              placeholder: '请输入说明',
-            },
-            'x-decorator-props': {
-              gridSpan: 2,
-            },
-            'x-validator': [
-              {
-                max: 200,
-                message: '最多可输入200个字符',
-              },
-            ],
-          },
-        },
-      },
-    },
-  };
-
-  const save = async () => {
-    const value = await form.submit<any>();
-    if (props.data.id) {
-      service
-        .edit({
-          ...value,
-          id: props.data.id,
-        })
-        .then((res: any) => {
-          if (res.status === 200) {
-            onlyMessage('保存成功');
-            props.close();
-          }
-        });
-    } else {
-      if (props.device) {
-        service.save(value).then((res: any) => {
-          if (res.status === 200) {
-            service.bind([props.device.id], res.result.id).then((resp: any) => {
-              if (resp.status === 200) {
-                onlyMessage('保存成功');
-                props.close();
-              }
-            });
-          }
-        });
-      } else {
-        service.save(value).then((res: any) => {
-          if (res.status === 200) {
-            onlyMessage('保存成功');
-            props.close();
-          }
-        });
-      }
-    }
-  };
-
-  useEffect(() => {
-    console.log(props.data.id);
-  }, []);
-  return (
-    <Modal
-      title={intl.formatMessage({
-        id: `pages.data.option.${props.data.id ? 'edit' : 'add'}`,
-        defaultMessage: '编辑',
-      })}
-      maskClosable={false}
-      visible
-      onCancel={props.close}
-      onOk={save}
-      width="35vw"
-      permissionCode={'link/Channel/Modbus'}
-      permission={['add', 'edit']}
-    >
-      <Form form={form} layout="vertical">
-        <SchemaField schema={schema} />
-      </Form>
-    </Modal>
-  );
-};
-export default Save;

+ 23 - 3
src/pages/link/Channel/Modbus/import/index.tsx

@@ -15,10 +15,10 @@ interface Props {
   masterId: any;
 }
 const FileFormat = (props: any) => {
-  const [data, setData] = useState<{ autoDeploy: boolean; fileType: 'xlsx' | 'csv' }>({
-    autoDeploy: false,
+  const [data, setData] = useState<{ fileType: 'xlsx' | 'csv' }>({
     fileType: 'xlsx',
   });
+
   return (
     <Space>
       <Radio.Group
@@ -47,6 +47,7 @@ const NormalUpload = (props: any) => {
   const [count, setCount] = useState<number>(0);
   const [errMessage, setErrMessage] = useState<string>('');
   const [errorUrl, setErrorUrl] = useState<string>('');
+  const [fileName, setFileName] = useState<any>('');
 
   const submitData = async (fileUrl: string) => {
     setErrorUrl(fileUrl);
@@ -92,6 +93,10 @@ const NormalUpload = (props: any) => {
           }}
           onChange={async (info) => {
             if (info.file.status === 'done') {
+              console.log(info.file);
+              const name = info.file.name.split('.')?.[0];
+              setFileName(name);
+              console.log(name);
               const resp: any = info.file.response || { result: '' };
               await submitData(resp?.result || '');
             }
@@ -135,7 +140,22 @@ const NormalUpload = (props: any) => {
               <>
                 <Badge status="error" text="失败" />
                 <span style={{ marginLeft: 15 }}>{errMessage}</span>
-                <a href={errorUrl} style={{ marginLeft: 15 }}>
+                <a
+                  style={{ marginLeft: 15 }}
+                  onClick={() => {
+                    const parms = new XMLHttpRequest();
+                    parms.open('GET', errorUrl, true);
+                    parms.responseType = 'blob';
+                    parms.onload = () => {
+                      const url = window.URL.createObjectURL(parms.response);
+                      const a = document.createElement('a');
+                      a.href = url;
+                      a.download = `${fileName}-${errMessage}`;
+                      a.click();
+                    };
+                    parms.send();
+                  }}
+                >
                   下载
                 </a>
               </>

+ 0 - 26
src/pages/link/Channel/Modbus/index.less

@@ -1,26 +0,0 @@
-.topCard {
-  display: flex;
-  align-items: center;
-  width: 100%;
-
-  .text {
-    margin-left: 10px;
-    .p1 {
-      min-width: 130px;
-      height: 22px;
-      margin-bottom: 7px;
-      font-weight: 700;
-      font-size: 18px;
-      line-height: 22px;
-    }
-
-    .p2 {
-      min-width: 130px;
-      height: 20px;
-      color: rgba(0, 0, 0, 0.75);
-      font-weight: 400;
-      font-size: 12px;
-      line-height: 20px;
-    }
-  }
-}

+ 75 - 76
src/pages/link/Channel/Modbus/index.tsx

@@ -1,6 +1,6 @@
 import { Badge, Button, Card, Divider, Dropdown, Input, Menu, Modal } from 'antd';
 import { useDomFullHeight } from '@/hooks';
-import './index.less';
+import '../index.less';
 import SearchComponent from '@/components/SearchComponent';
 import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
 import PermissionButton from '@/components/PermissionButton';
@@ -136,7 +136,7 @@ const NewModbus = () => {
             }
           }}
         >
-          <Ellipsis title={currentData[record?.id] || '-'} />
+          <Ellipsis title={currentData[record?.id] || ''} />
         </a>
       ),
     },
@@ -146,7 +146,7 @@ const NewModbus = () => {
       render: (record: any) => (
         <>
           {record.state.value === 'disabled' ? (
-            '-'
+            ''
           ) : (
             <>
               <Badge
@@ -304,7 +304,6 @@ const NewModbus = () => {
           setFilterList(res.result);
           setActiveKey(res.result?.[0]?.id);
           masterId.current = res.result?.[0]?.id;
-          console.log(masterId.current);
         }
       });
   };
@@ -348,7 +347,6 @@ const NewModbus = () => {
         const { pointId, hex } = payload;
         current[pointId] = hex;
         setCurrentData({ ...current });
-        console.log(current);
       });
     return () => wsRef.current && wsRef.current?.unsubscribe();
   }, [pointList]);
@@ -381,7 +379,7 @@ const NewModbus = () => {
                 isPermission={permission.add}
                 key="add"
                 icon={<PlusOutlined />}
-                type="default"
+                type="primary"
                 style={{ width: '100%', marginTop: 16, marginBottom: 16 }}
               >
                 新增
@@ -466,76 +464,77 @@ const NewModbus = () => {
             </div>
           </div>
           <div className="item-right">
-            <SearchComponent<any>
-              field={columns}
-              target="modbus"
-              onSearch={(value) => {
-                actionRef.current?.reset?.();
-                setParam(value);
-              }}
-            />
-            <ProTable
-              actionRef={actionRef}
-              params={param}
-              columns={columns}
-              rowKey="id"
-              // dataSource={dataSoure}
-              scroll={{ x: 200 }}
-              search={false}
-              headerTitle={
-                <>
-                  <PermissionButton
-                    onClick={() => {
-                      setPointDetail({});
-                      setVisiblePoint(true);
-                    }}
-                    isPermission={permission.add}
-                    key="add"
-                    icon={<PlusOutlined />}
-                    type="primary"
-                    style={{ marginRight: 10 }}
-                  >
-                    {intl.formatMessage({
-                      id: 'pages.data.option.add',
-                      defaultMessage: '新增',
-                    })}
-                  </PermissionButton>
-                  <Dropdown key={'more'} overlay={menu} placement="bottom">
-                    <Button>批量操作</Button>
-                  </Dropdown>
-                </>
-              }
-              request={async (params) => {
-                if (masterId.current) {
-                  const res = await service.queryPoint(masterId.current, {
-                    ...params,
-                    sorts: [{ name: 'createTime', order: 'desc' }],
-                  });
-                  setPointList(res.result.data);
-                  return {
-                    code: res.message,
-                    result: {
-                      data: res.result.data,
-                      pageIndex: res.result.pageIndex,
-                      pageSize: res.result.pageSize,
-                      total: res.result.total,
-                    },
-                    status: res.status,
-                  };
-                } else {
-                  return {
-                    code: 200,
-                    result: {
-                      data: [],
-                      pageIndex: 0,
-                      pageSize: 0,
-                      total: 0,
-                    },
-                    status: 200,
-                  };
+            <div style={{ width: '100%' }}>
+              <SearchComponent<any>
+                field={columns}
+                target="modbus"
+                onSearch={(value) => {
+                  actionRef.current?.reset?.();
+                  setParam(value);
+                }}
+              />
+              <ProTable
+                actionRef={actionRef}
+                params={param}
+                columns={columns}
+                rowKey="id"
+                scroll={{ x: 1000 }}
+                search={false}
+                headerTitle={
+                  <>
+                    <PermissionButton
+                      onClick={() => {
+                        setPointDetail({});
+                        setVisiblePoint(true);
+                      }}
+                      isPermission={permission.add}
+                      key="add"
+                      icon={<PlusOutlined />}
+                      type="primary"
+                      style={{ marginRight: 10 }}
+                    >
+                      {intl.formatMessage({
+                        id: 'pages.data.option.add',
+                        defaultMessage: '新增',
+                      })}
+                    </PermissionButton>
+                    <Dropdown key={'more'} overlay={menu} placement="bottom">
+                      <Button>批量操作</Button>
+                    </Dropdown>
+                  </>
                 }
-              }}
-            />
+                request={async (params) => {
+                  if (masterId.current) {
+                    const res = await service.queryPoint(masterId.current, {
+                      ...params,
+                      sorts: [{ name: 'createTime', order: 'desc' }],
+                    });
+                    setPointList(res.result.data);
+                    return {
+                      code: res.message,
+                      result: {
+                        data: res.result.data,
+                        pageIndex: res.result.pageIndex,
+                        pageSize: res.result.pageSize,
+                        total: res.result.total,
+                      },
+                      status: res.status,
+                    };
+                  } else {
+                    return {
+                      code: 200,
+                      result: {
+                        data: [],
+                        pageIndex: 0,
+                        pageSize: 0,
+                        total: 0,
+                      },
+                      status: 200,
+                    };
+                  }
+                }}
+              />
+            </div>
           </div>
         </div>
       </Card>
@@ -568,7 +567,7 @@ const NewModbus = () => {
         visible={importVisible}
       />
       <Export
-        masterId={activeKey}
+        data={masterList}
         close={() => {
           setExportVisible(false);
           actionRef.current?.reload();

+ 0 - 5
src/pages/link/Channel/Modbus/saveChannel.tsx

@@ -4,9 +4,7 @@ import { Form, FormGrid, FormItem, Input, NumberPicker, Select } from '@formily/
 import type { ISchema } from '@formily/json-schema';
 import { service } from '@/pages/link/Channel/Modbus';
 import { Modal } from '@/components';
-import { useEffect } from 'react';
 import { onlyMessage } from '@/utils/util';
-// import { onlyMessage } from '@/utils/util';
 
 interface Props {
   data: any;
@@ -143,9 +141,6 @@ const SaveChannel = (props: Props) => {
     }
   };
 
-  useEffect(() => {
-    console.log(props.data.id);
-  }, []);
   return (
     <Modal
       title={props.data.id ? '编辑通道' : '新增通道'}

+ 7 - 4
src/pages/link/Channel/Modbus/savePoint.tsx

@@ -44,7 +44,7 @@ const SavePoint = (props: Props) => {
 
   return (
     <Modal
-      title={props.data.id ? '编辑点' : '新增点'}
+      title={props.data.id ? '编辑数据点' : '新增数据点'}
       visible
       width="40vw"
       destroyOnClose
@@ -66,7 +66,10 @@ const SavePoint = (props: Props) => {
               label="名称"
               name="name"
               required
-              rules={[{ required: true, message: '名称必填' }]}
+              rules={[
+                { required: true, message: '名称必填' },
+                { max: 64, message: '最多可输入64个字符' },
+              ]}
             >
               <Input placeholder="请输入名称" />
             </Form.Item>
@@ -93,7 +96,7 @@ const SavePoint = (props: Props) => {
               name="unitId"
               required
               rules={[
-                { required: true, message: '从站ID' },
+                { required: true, message: '从站ID必填' },
                 ({}) => ({
                   validator(_, value) {
                     if (value !== 0 || /(^[1-9]\d*$)/.test(value)) {
@@ -134,7 +137,7 @@ const SavePoint = (props: Props) => {
             <Form.Item
               label="地址"
               name="address"
-              tooltip="要获取的对象地址"
+              tooltip="范围在0x0-0xFFFF"
               rules={[
                 { required: true, message: '请输入读取长度' },
                 ({}) => ({

+ 1 - 1
src/pages/link/Channel/index.less

@@ -26,7 +26,7 @@
   }
 
   .item-right {
-    width: 100%;
+    width: calc(100% - 230px);
     .ant-card-body {
       padding-top: 0;
       padding-left: 0;