diff --git a/src/components/RightContent/index.less b/src/components/RightContent/index.less index fb2df6bc39bbc33b270f48e5ec74f30757316c25..7889db1e57264861de681ce162d5ded929d40e9b 100644 --- a/src/components/RightContent/index.less +++ b/src/components/RightContent/index.less @@ -17,6 +17,15 @@ height: 48px; margin-left: auto; overflow: hidden; + .help_document { + padding: 0 2px; + > a { color: rgba(0, 0, 0, 0.85); } + > a:hover { + color: #1890ff; + cursor: pointer; + } + } + .action { display: flex; align-items: center; diff --git a/src/pages/Agent/AgentList/HeartbeatBtn.tsx b/src/pages/Agent/AgentList/HeartbeatBtn.tsx new file mode 100644 index 0000000000000000000000000000000000000000..ffb748e5ed5b4d53bf1afbe9813105ee2d2372f5 --- /dev/null +++ b/src/pages/Agent/AgentList/HeartbeatBtn.tsx @@ -0,0 +1,32 @@ +import React, { useState, useEffect } from 'react'; +import { Popover, Tooltip, Space, Badge, message, Spin } from 'antd'; +import { FormattedMessage } from 'umi'; +import { agentHeartbeat } from '../service'; + +export default ({ callBack, record }) => { + const [heartbeatLoading, setHeartbeatLoading] = useState(false) + + const heartbeat = async (info)=> { + setHeartbeatLoading(true) + const res = await agentHeartbeat({ id: info.id}).catch(()=> setHeartbeatLoading(false)) + setHeartbeatLoading(false) + if (res?.code === 200) { + const reactNode = res?.data?.info?.split('\n')?.map((item: any)=>
{item}
) + if (res.data.heartbeat === 'ok') { + message.success(ok {reactNode}); + callBack('heartbeat', {}) + } else if (res.data.heartbeat === 'fail') { + message.error(fail {reactNode}); + } + } else { + message.error(res.msg || formatMessage({ id: 'request.data.failed'}) ); + } + } + + return ( + + heartbeat(record)}> + + ) + +} \ No newline at end of file diff --git a/src/pages/Agent/AgentList/index.tsx b/src/pages/Agent/AgentList/index.tsx index 717b9262518771299865c2a8c5fee557521fe3b7..dff1d673b2ec037fb31c164092769551a63c5876 100644 --- a/src/pages/Agent/AgentList/index.tsx +++ b/src/pages/Agent/AgentList/index.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Popover, Tooltip, Space, Badge, Popconfirm } from 'antd'; +import { Popover, Tooltip, Space, Badge, Popconfirm, Spin } from 'antd'; import { QuestionCircleOutlined, FilterFilled } from '@ant-design/icons' import { FormattedMessage, useIntl } from 'umi'; import CommonTable from '@/components/Public/CommonTable'; @@ -7,6 +7,7 @@ import { PopoverEllipsis, HearBeat } from '@/components/Public'; import SearchInput from '@/components/Public/SearchInput'; import SelectStatus from '@/components/Public/SelectStatus'; import { getLimitAuthority } from '@/utils/utilsHelp'; +import HeartbeatBtn from './HeartbeatBtn'; import styles from './style.less'; const ProductList = ({ data, loading, onChange, onRow, filterCallBack, editCallBack, rowSelectionCallBack= {} }:any) => { @@ -160,11 +161,12 @@ const ProductList = ({ data, loading, onChange, onRow, filterCallBack, editCallB columns = columns.concat([ { title: , - onCell: () => ({ style: { maxWidth: 100 } }), + onCell: () => ({ style: { minWidth: 160 } }), align: 'center', render: (text: any, record: any) => { return (
+ editCallBack('edit', record)}> { filterOption={(input, option:any) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 }> - {data.map((item: any) => ( - {item.version} - ))} + {data.map((item: any) => { + // const { is_new, is_stable } = record + const tagState = item.is_new ? 'new': (item.is_stable ? 'stable': null) + return ( + + {item.version}({item.os} | {item.arch}){tagState &&
{tagState}
} +
+ )} + )} diff --git a/src/pages/Agent/index.tsx b/src/pages/Agent/index.tsx index eec792d10e83e6d2dde636c683b2e652920f765f..35177f86af35212ca37ddec25231ece01bea4864 100644 --- a/src/pages/Agent/index.tsx +++ b/src/pages/Agent/index.tsx @@ -54,7 +54,7 @@ const List = (props: any) => { } // 新增机器 - const addOrEditCallBack = (type: string, info: any) => { + const addOrEditCallBack = async (type: string, info: any) => { // console.log('data:', type, info) if (type === 'add') { detailsModal.current?.show({ detailData: {} }); @@ -62,6 +62,8 @@ const List = (props: any) => { detailsModal.current?.show({ detailData: info }); } else if (type === 'delete') { deleteAgentClick(info) + } else if (type === 'heartbeat') { + getTableData({ page_num: data.page_num, page_size: data.page_size }) } } diff --git a/src/pages/Agent/locales/en-US.ts b/src/pages/Agent/locales/en-US.ts index 37000ad084f738056f05a3bb2ebdfbf4c31291c6..d37e06cb20b85c830c45ea78ddf51359c8660b9b 100644 --- a/src/pages/Agent/locales/en-US.ts +++ b/src/pages/Agent/locales/en-US.ts @@ -13,6 +13,7 @@ export default { 'agent.table.Heartbeat': 'Heartbeat', 'agent.table.Mode.Tooltip': 'ToneAgent operates in two modes, Active Mode and Passive Mode. Active mode refers to the mode in which the agent communicates with the server actively (similar to push mode), while passive mode refers to the mode in which the server communicates with the agent actively (similar to pull mode).', 'agent.table.description': 'Description', + 'agent.table.heartbeat.test': 'Heartbeat test', 'hearBeat.hours': ' hours', 'hearBeat.hours.ago': ' hours ago', 'hearBeat.minutes.ago': ' minutes ago', diff --git a/src/pages/Agent/locales/zh-CN.ts b/src/pages/Agent/locales/zh-CN.ts index 051a63e53fceb18040f9b6bc297c33e29c0f3c0f..27bbb423bd8307c3db70cd92f43be02e6be343d0 100644 --- a/src/pages/Agent/locales/zh-CN.ts +++ b/src/pages/Agent/locales/zh-CN.ts @@ -13,6 +13,7 @@ export default { 'agent.table.Heartbeat': '心跳', 'agent.table.Mode.Tooltip': 'ToneAgent分两种运行模式:主动模式(active)和被动模式(passive), 主动模式指的是agent主动连server进行通信的方式(类似push模式),被动模式指的是server主动连agent进行通信的模式(类似pull模式)。', 'agent.table.description': '描述', + 'agent.table.heartbeat.test': '心跳测试', 'hearBeat.hours': '小时', 'hearBeat.hours.ago': '小时之前', 'hearBeat.minutes.ago': '分钟之前', diff --git a/src/pages/Agent/service.ts b/src/pages/Agent/service.ts index 7c1e41245db83660e44121364e30b9164c5ff7be..84da456b4548f700e7732047f0123c3a86363d24 100644 --- a/src/pages/Agent/service.ts +++ b/src/pages/Agent/service.ts @@ -45,3 +45,11 @@ export async function agentDelete(params: any) { }, }); } + +// 心跳测试 +export async function agentHeartbeat(params: any) { + return request(`/v1/agent/heartbeat`, { + method: 'GET', + params, + }); +} diff --git a/src/pages/Token/Table/index.tsx b/src/pages/Token/Table/index.tsx index 84d32620572a3247baa78bfa4b92dadcebd13b16..e5633ebffcd0f7df9e7d43292c3f30b20b16910f 100644 --- a/src/pages/Token/Table/index.tsx +++ b/src/pages/Token/Table/index.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; -import { Popover, Tooltip, Space } from 'antd'; +import { Popover, Tooltip, Space, Popconfirm } from 'antd'; import { QuestionCircleOutlined, FilterFilled, EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons' -import { FormattedMessage } from 'umi'; +import { FormattedMessage, useIntl } from 'umi'; import CommonTable from '@/components/Public/CommonTable'; import PopoverEllipsis from '@/components/Public/PopoverEllipsis'; import SearchInput from '@/components/Public/SearchInput'; @@ -9,6 +9,7 @@ import SelectStatus from '@/components/Public/SelectStatus'; import styles from './style.less'; const ProductList = ({ data, loading, onChange, onRow, filterCallBack, editCallBack= ()=> {}, }:any) => { + const { formatMessage } = useIntl(); const [dataSource, setDataSource] = useState([]); // const [autoFocus, setFocus] = useState(true); @@ -122,7 +123,15 @@ const ProductList = ({ data, loading, onChange, onRow, filterCallBack, editCallB editCallBack('edit', record)}> editCallBack('reset', record)}> - editCallBack('delete', record)}> + editCallBack('delete', record)} + okText={formatMessage({ id: 'btn.ok' })} + cancelText={formatMessage({ id: 'btn.close' })} + > + + ) diff --git a/src/pages/Version/VersionList/index.tsx b/src/pages/Version/VersionList/index.tsx index 9767b0635d1dadfaf6a94ff3201793f86515b395..7c26abd473498d6f0311cbd08e9ff96385f72e9e 100644 --- a/src/pages/Version/VersionList/index.tsx +++ b/src/pages/Version/VersionList/index.tsx @@ -1,7 +1,7 @@ -import { FormattedMessage } from 'umi'; import React, { useState, useEffect } from 'react'; -import { Popover, Tooltip, Space } from 'antd'; +import { Popover, Tooltip, Space, Popconfirm } from 'antd'; import { FilterFilled, CopyOutlined } from '@ant-design/icons'; +import { FormattedMessage, useIntl } from 'umi'; import CommonTable from '@/components/Public/CommonTable'; import PopoverEllipsis from '@/components/Public/PopoverEllipsis'; import SearchInput from '@/components/Public/SearchInput'; @@ -11,7 +11,8 @@ import SelectStatus from '@/components/Public/SelectStatus'; import styles from './style.less'; const ProductList = ({ data, loading, onChange, filterCallBack, editCallBack= ()=> {}, onRow= ()=> {} }:any) => { - const [autoFocus, setFocus] = useState(true); + const { formatMessage } = useIntl(); + const [autoFocus, setFocus] = useState(true); const [version, setVersion] = useState(); const [arch, setArch] = useState(); // 权限 @@ -104,7 +105,15 @@ const ProductList = ({ data, loading, onChange, filterCallBack, editCallBack= ()
editCallBack('edit', record)}> - editCallBack('delete', record)}> + editCallBack('delete', record)} + okText={formatMessage({ id: 'btn.ok' })} + cancelText={formatMessage({ id: 'btn.close' })} + > + +
)