|
@@ -1,67 +1,208 @@
|
|
|
import PermissionButton from '@/components/PermissionButton';
|
|
import PermissionButton from '@/components/PermissionButton';
|
|
|
import { PageContainer } from '@ant-design/pro-layout';
|
|
import { PageContainer } from '@ant-design/pro-layout';
|
|
|
import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
|
|
import ProTable, { ActionType, ProColumns } from '@jetlinks/pro-table';
|
|
|
-import { Badge, Card, Popconfirm, message, Tabs, Empty } from 'antd';
|
|
|
|
|
|
|
+import { Badge, Card, Popconfirm, message, Tabs, Empty, Input } from 'antd';
|
|
|
import { useIntl, useLocation } from 'umi';
|
|
import { useIntl, useLocation } from 'umi';
|
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
|
-import { DisconnectOutlined, PlusOutlined } from '@ant-design/icons';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ DeleteOutlined,
|
|
|
|
|
+ DisconnectOutlined,
|
|
|
|
|
+ EditOutlined,
|
|
|
|
|
+ PlayCircleOutlined,
|
|
|
|
|
+ PlusOutlined,
|
|
|
|
|
+ StopOutlined,
|
|
|
|
|
+} from '@ant-design/icons';
|
|
|
import BindDevice from '@/pages/link/Channel/Opcua/Access/bindDevice';
|
|
import BindDevice from '@/pages/link/Channel/Opcua/Access/bindDevice';
|
|
|
import { service } from '@/pages/link/Channel/Opcua';
|
|
import { service } from '@/pages/link/Channel/Opcua';
|
|
|
import encodeQuery from '@/utils/encodeQuery';
|
|
import encodeQuery from '@/utils/encodeQuery';
|
|
|
import styles from './index.less';
|
|
import styles from './index.less';
|
|
|
import AddPoint from './addPoint';
|
|
import AddPoint from './addPoint';
|
|
|
|
|
+import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
|
|
|
|
|
+import { map } from 'rxjs/operators';
|
|
|
|
|
|
|
|
const Access = () => {
|
|
const Access = () => {
|
|
|
const intl = useIntl();
|
|
const intl = useIntl();
|
|
|
const actionRef = useRef<ActionType>();
|
|
const actionRef = useRef<ActionType>();
|
|
|
const location = useLocation<string>();
|
|
const location = useLocation<string>();
|
|
|
- // const [param, setParam] = useState({});
|
|
|
|
|
|
|
+ const [param, setParam] = useState({});
|
|
|
const [opcUaId, setOpcUaId] = useState<any>('');
|
|
const [opcUaId, setOpcUaId] = useState<any>('');
|
|
|
const { permission } = PermissionButton.usePermission('link/Channel/Opcua');
|
|
const { permission } = PermissionButton.usePermission('link/Channel/Opcua');
|
|
|
const [deviceVisiable, setDeviceVisiable] = useState<boolean>(false);
|
|
const [deviceVisiable, setDeviceVisiable] = useState<boolean>(false);
|
|
|
const [pointVisiable, setPointVisiable] = useState<boolean>(false);
|
|
const [pointVisiable, setPointVisiable] = useState<boolean>(false);
|
|
|
const [bindList, setBindList] = useState<any>([]);
|
|
const [bindList, setBindList] = useState<any>([]);
|
|
|
const [deviceId, setDeviceId] = useState<string>('');
|
|
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 columns: ProColumns<OpaUa>[] = [
|
|
|
|
|
|
|
+ const columns: ProColumns<any>[] = [
|
|
|
{
|
|
{
|
|
|
title: '属性ID',
|
|
title: '属性ID',
|
|
|
- dataIndex: 'name',
|
|
|
|
|
|
|
+ dataIndex: 'property',
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '功能码',
|
|
|
|
|
- dataIndex: '1',
|
|
|
|
|
|
|
+ title: '名称',
|
|
|
|
|
+ dataIndex: 'name',
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '读取起始位置',
|
|
|
|
|
- dataIndex: '2',
|
|
|
|
|
|
|
+ title: 'OPC点位ID',
|
|
|
|
|
+ dataIndex: 'opcPointId',
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- title: '读取长度',
|
|
|
|
|
- dataIndex: '3',
|
|
|
|
|
|
|
+ title: '数据类型',
|
|
|
|
|
+ dataIndex: 'dataType',
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
title: '值',
|
|
title: '值',
|
|
|
- dataIndex: '4',
|
|
|
|
|
|
|
+ // dataIndex: '4',
|
|
|
|
|
+ render: (record: any) => <>{propertyValue[record.property]}</>,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
title: '状态',
|
|
title: '状态',
|
|
|
dataIndex: 'state',
|
|
dataIndex: 'state',
|
|
|
renderText: (state) => (
|
|
renderText: (state) => (
|
|
|
- <Badge text={state?.text} status={state?.value === 'disabled' ? 'error' : 'success'} />
|
|
|
|
|
|
|
+ <Badge text={state?.text} status={state?.value === 'disable' ? '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 !== 'disable' ? 'disable' : 'good'}.tips`,
|
|
|
|
|
+ defaultMessage: '确认禁用?',
|
|
|
|
|
+ }),
|
|
|
|
|
+ onConfirm: async () => {
|
|
|
|
|
+ if (record.state.value === 'disable') {
|
|
|
|
|
+ await service.enablePoint(record.deviceId, [record.id]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await service.stopPoint(record.deviceId, [record.id]);
|
|
|
|
|
+ }
|
|
|
|
|
+ message.success(
|
|
|
|
|
+ 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 !== 'disable' ? 'disable' : 'good'}`,
|
|
|
|
|
+ defaultMessage: record.state.value !== 'disable' ? '禁用' : '启用',
|
|
|
|
|
+ }),
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {record.state.value !== 'disable' ? <StopOutlined /> : <PlayCircleOutlined />}
|
|
|
|
|
+ </PermissionButton>,
|
|
|
|
|
+ <PermissionButton
|
|
|
|
|
+ isPermission={permission.delete}
|
|
|
|
|
+ style={{ padding: 0 }}
|
|
|
|
|
+ disabled={record.state.value === 'good'}
|
|
|
|
|
+ tooltip={{
|
|
|
|
|
+ title:
|
|
|
|
|
+ record.state.value === 'disable'
|
|
|
|
|
+ ? intl.formatMessage({
|
|
|
|
|
+ id: 'pages.data.option.remove',
|
|
|
|
|
+ defaultMessage: '删除',
|
|
|
|
|
+ })
|
|
|
|
|
+ : '请先禁用该组件,再删除。',
|
|
|
|
|
+ }}
|
|
|
|
|
+ popConfirm={{
|
|
|
|
|
+ title: '确认删除',
|
|
|
|
|
+ onConfirm: async () => {
|
|
|
|
|
+ console.log(111);
|
|
|
|
|
+ const resp: any = await service.deletePoint(record.id);
|
|
|
|
|
+ if (resp.status === 200) {
|
|
|
|
|
+ message.success(
|
|
|
|
|
+ intl.formatMessage({
|
|
|
|
|
+ id: 'pages.data.option.success',
|
|
|
|
|
+ defaultMessage: '操作成功!',
|
|
|
|
|
+ }),
|
|
|
|
|
+ );
|
|
|
|
|
+ actionRef.current?.reload();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ }}
|
|
|
|
|
+ key="delete"
|
|
|
|
|
+ type="link"
|
|
|
|
|
+ >
|
|
|
|
|
+ <DeleteOutlined />
|
|
|
|
|
+ </PermissionButton>,
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
|
|
+ const pointWs = () => {
|
|
|
|
|
+ if (productId && deviceId) {
|
|
|
|
|
+ const id = `instance-info-property-${deviceId}-${productId}-opc-point`;
|
|
|
|
|
+ const topic = `/dashboard/device/${productId}/properties/realTime`;
|
|
|
|
|
+ subscribeTopic!(id, topic, {
|
|
|
|
|
+ deviceId: deviceId,
|
|
|
|
|
+ properties: data.map((item: any) => item.property),
|
|
|
|
|
+ history: 0,
|
|
|
|
|
+ })
|
|
|
|
|
+ ?.pipe(map((res) => res.patload))
|
|
|
|
|
+ .subscribe((payload: any) => {
|
|
|
|
|
+ const { value } = payload;
|
|
|
|
|
+ console.log(value);
|
|
|
|
|
+ propertyValue[value.property] = { ...payload, ...value };
|
|
|
|
|
+ setPropertyValue({ ...propertyValue });
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const getBindList = (params: any) => {
|
|
const getBindList = (params: any) => {
|
|
|
service.getBindList(params).then((res) => {
|
|
service.getBindList(params).then((res) => {
|
|
|
|
|
+ console.log(res.result);
|
|
|
if (res.status === 200) {
|
|
if (res.status === 200) {
|
|
|
setDeviceId(res.result[0]?.deviceId);
|
|
setDeviceId(res.result[0]?.deviceId);
|
|
|
|
|
+ setProductId(res.result[0]?.productId);
|
|
|
|
|
+ setParam({
|
|
|
|
|
+ terms: [{ column: 'deviceId', value: res.result[0]?.deviceId }],
|
|
|
|
|
+ });
|
|
|
setBindList(res.result);
|
|
setBindList(res.result);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // useEffect(() => {
|
|
|
|
|
+ // pointWs();
|
|
|
|
|
+ // }, [deviceId, productId])
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ pointWs();
|
|
|
|
|
+ }, [data]);
|
|
|
|
|
+
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
const item = new URLSearchParams(location.search);
|
|
const item = new URLSearchParams(location.search);
|
|
|
const id = item.get('id');
|
|
const id = item.get('id');
|
|
@@ -98,6 +239,11 @@ const Access = () => {
|
|
|
defaultActiveKey={deviceId}
|
|
defaultActiveKey={deviceId}
|
|
|
onChange={(e) => {
|
|
onChange={(e) => {
|
|
|
setDeviceId(e);
|
|
setDeviceId(e);
|
|
|
|
|
+ const items = bindList.find((item: any) => item.deviceId === e);
|
|
|
|
|
+ setProductId(items[0].productId);
|
|
|
|
|
+ setParam({
|
|
|
|
|
+ terms: [{ column: 'deviceId', value: e }],
|
|
|
|
|
+ });
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
{bindList.map((item: any) => (
|
|
{bindList.map((item: any) => (
|
|
@@ -130,34 +276,69 @@ const Access = () => {
|
|
|
</div>
|
|
</div>
|
|
|
}
|
|
}
|
|
|
>
|
|
>
|
|
|
- <ProTable<OpaUa>
|
|
|
|
|
|
|
+ <ProTable
|
|
|
actionRef={actionRef}
|
|
actionRef={actionRef}
|
|
|
- // params={param}
|
|
|
|
|
|
|
+ params={param}
|
|
|
columns={columns}
|
|
columns={columns}
|
|
|
rowKey="id"
|
|
rowKey="id"
|
|
|
search={false}
|
|
search={false}
|
|
|
headerTitle={
|
|
headerTitle={
|
|
|
- <PermissionButton
|
|
|
|
|
- onClick={() => {
|
|
|
|
|
- setPointVisiable(true);
|
|
|
|
|
- // setMode('add');
|
|
|
|
|
- // setVisible(true);
|
|
|
|
|
- // setCurrent({});
|
|
|
|
|
- }}
|
|
|
|
|
- isPermission={permission.add}
|
|
|
|
|
- key="add"
|
|
|
|
|
- icon={<PlusOutlined />}
|
|
|
|
|
- type="primary"
|
|
|
|
|
- >
|
|
|
|
|
- {intl.formatMessage({
|
|
|
|
|
- id: 'pages.data.option.add',
|
|
|
|
|
- defaultMessage: '新增',
|
|
|
|
|
- })}
|
|
|
|
|
- </PermissionButton>
|
|
|
|
|
|
|
+ <>
|
|
|
|
|
+ <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="请输入属性"
|
|
|
|
|
+ allowClear
|
|
|
|
|
+ onSearch={(value) => {
|
|
|
|
|
+ console.log(value);
|
|
|
|
|
+ if (value) {
|
|
|
|
|
+ setParam({
|
|
|
|
|
+ terms: [
|
|
|
|
|
+ { column: 'deviceId', value: deviceId },
|
|
|
|
|
+ { column: 'property', value: `%${value}%`, termType: 'like' },
|
|
|
|
|
+ ],
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ setParam({
|
|
|
|
|
+ terms: [{ column: 'deviceId', value: deviceId }],
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </>
|
|
|
}
|
|
}
|
|
|
- // request={async (params) =>
|
|
|
|
|
- // service.query({ ...params, sorts: [{ name: 'createTime', order: 'desc' }] })
|
|
|
|
|
- // }
|
|
|
|
|
|
|
+ request={async (params) => {
|
|
|
|
|
+ const res = await service.PointList({
|
|
|
|
|
+ ...params,
|
|
|
|
|
+ sorts: [{ name: 'createTime', order: 'desc' }],
|
|
|
|
|
+ });
|
|
|
|
|
+ setData(res.result.data);
|
|
|
|
|
+ return {
|
|
|
|
|
+ code: res.message,
|
|
|
|
|
+ result: {
|
|
|
|
|
+ data: res.result.data,
|
|
|
|
|
+ pageIndex: 0,
|
|
|
|
|
+ pageSize: 0,
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+ },
|
|
|
|
|
+ status: res.status,
|
|
|
|
|
+ };
|
|
|
|
|
+ }}
|
|
|
/>
|
|
/>
|
|
|
</Tabs.TabPane>
|
|
</Tabs.TabPane>
|
|
|
))}
|
|
))}
|
|
@@ -184,9 +365,11 @@ const Access = () => {
|
|
|
{pointVisiable && (
|
|
{pointVisiable && (
|
|
|
<AddPoint
|
|
<AddPoint
|
|
|
deviceId={deviceId}
|
|
deviceId={deviceId}
|
|
|
- data={{}}
|
|
|
|
|
|
|
+ opcUaId={opcUaId}
|
|
|
|
|
+ data={current}
|
|
|
close={() => {
|
|
close={() => {
|
|
|
setPointVisiable(false);
|
|
setPointVisiable(false);
|
|
|
|
|
+ actionRef.current?.reload();
|
|
|
}}
|
|
}}
|
|
|
/>
|
|
/>
|
|
|
)}
|
|
)}
|