@@ -1,155 +1,205 @@
< script setup lang = "ts" >
import { reactive , toRaw , onMounted } from 'vue' ;
import { reactive , onMounted, onBeforeUnmount , nextTick } from 'vue' ;
import { PageContainer } from 'antdv-pro-layout' ;
import { Size Type } from 'ant-design-vue/lib/config-provider ' ;
import { ColumnsType } from 'ant-design-vue/lib/table' ;
import { Columns Type } from 'ant-design-vue/lib/table ' ;
import useI18n from '@/hooks/useI18n' ;
import { OptionsType , WS } from '@/plugins/ws-websocket' ;
import {
RESULT _CODE _ERROR
} from '@/constants/result-constants' ;
import { RESULT _CODE _ERROR } from '@/constants/result-constants' ;
const { t } = useI18n ( ) ;
const ws = new WS ( ) ;
//查询数据
/**表单查询参数 */
let queryParams = reactive ( {
pid : undefined ,
name : "" ,
port : undefined ,
flag : false ,
changeTime : 5000 ,
name : '' ,
port : undefined ,
} ) ;
//临时缓存:用于搜索后清除筛选条件
let bufferParams = reactive ( {
pid : undefined ,
name : "" ,
port : undefined ,
flag : false ,
changeTime : 5000 ,
} )
//时间粒度
let timeOptions = [
{ label : t ( 'views.tool.ps.realTimeHigh' ) , value : 3000 },
{ label : t ( 'views.tool.ps.realTimeRegular' ) , value : 5000 } ,
{ label : t ( 'views.tool.ps.realTimeLow' ) , value : 10000 } ,
] ;
/**钩子函数,界面打开初始化*/
onMounted ( ( ) => {
fnRealTime ( ) //建立连接
extracted ( ) //先立刻发送请求获取第一次的数据
queryReset2 ( false ) //设置定时器
/**状态对象 */
let state = reactive ( {
/**调度器 */
interval : null as any ,
/**刷新周期 */
intervalTime : 5 _000 ,
/**查询参数 */
query : {
pid : undefined ,
name : '' ,
port : undefined ,
} ,
} ) ;
/**查询按钮* */
function queryTime ( ) { //将表单中的数据传递给缓存数据(缓存数据自动同步请求信息中)
bufferParams . pid = queryParams . pid ;
bufferParams . port = queryParams . port ;
bufferParams . name = queryParams . name ;
bufferParams . flag = true
queryParams . pid = undefined ;
queryParams . name = "" ;
queryParams . port = undefined ;
}
/**重置按钮**/
function queryReset ( ) {
queryParams . flag = false
bufferParams . flag = false
}
let s : any = null
/**定时器**/
function queryReset2 ( c : boolean ) {
if ( c ) {
clearInterval ( s ) //清理旧定时器
ws . close ( ) ; //断开原来的wb连接
fnRealTime ( ) ; //建立新的实时数据连接
/**接收数据后回调(成功) */
function wsMessage ( res : Record < string , any > ) {
const { code , requestId , data } = res ;
if ( code === RESULT _CODE _ERROR ) {
console . warn ( res . msg ) ;
return ;
}
// 建联时发送请求
if ( ! requestId && data . clientId ) {
fnGetList ( ) ;
return ;
}
// 收到消息数据
if ( requestId . startsWith ( 'net_' ) ) {
// 将数据填入表格
if ( Array . isArray ( data ) ) {
if ( tableState . loading ) {
tableState . loading = false ;
}
tableState . data = data ;
} else {
tableState . data = [ ] ;
}
}
s = setInterval ( ( ) => { //设置新的定时器s
extracted ( ) ;
} , queryParams . changeTime )
}
/**刷新频率改变* */
function fnRealTime2 ( ) { //时间粒度改变时触发
queryReset2 ( true ) //改变定时器
}
/**
* 实时数据
*/
function fnRealTime ( ) {
/**实时数据 */
function fnRealTime ( reLink : boolean ) {
if ( reLink ) {
ws . close ( ) ;
}
const options : OptionsType = {
url : '/ws' ,
onmessage : wsMessage ,
onerror : wsError ,
onerror : ( ev : any ) => {
// 接收数据后回调
console . error ( ev ) ;
} ,
} ;
//建立连接
ws . connect ( options ) ;
}
/**接收数据后回调(失败) */
function wsError ( e v: any ) {
// 接收数据后回调
console . error ( e v) ;
/**调度器周期变更 */
function fnIntervalChange ( v : any ) {
clearInterval ( state . interval ) ;
const timer = parseInt ( v ) ;
if ( timer > 1 _000 ) {
state . intervalTime = v ;
fnGetList ( ) ;
}
}
/**接收数据后回调(成功) */
function wsMessage ( res : Record < string , any > ) {
const { code , requestId , data } = res ; //获取数据
if ( code === RESULT _CODE _ERROR ) {
console . warn ( res . msg ) ;
return ;
}
// 处理数据, 组成ip : port
let processedData : any [ ] = [ ] ;
/**查询列表 */
function fnGetList ( ) {
if ( tableState . loading || ws . state ( ) === - 1 ) return ;
tableState . loading = true ;
const msg = {
requestId : ` net_ ${ state . interval } ` ,
type : 'net' ,
data : state . query ,
} ;
// 首发
ws . send ( msg ) ;
// 定时刷新数据
state . interval = setInterval ( ( ) => {
msg . data = JSON . parse ( JSON . stringify ( state . query ) ) ;
ws . send ( msg ) ;
} , state . intervalTime ) ;
}
if ( Array . isArray ( data ) ) {
processedData = data . map ( ( item : any ) => {
const localAddr = ` ${ item . localaddr ? . ip || '' } : ${ item . localaddr ? . port || '' } ` ;
const remoteAddr = ` ${ item . remoteaddr ? . ip || '' } : ${ item . remoteaddr ? . port || '' } ` ;
return { ... item , localAddr , remoteAddr } ;
/**查询参数传入 */
function fnQuery ( ) {
state . query = JSON . parse ( JSON . stringify ( queryParams ) ) ;
nextTick ( ( ) => {
ws . send ( {
requestId : ` net_ ${ state . interval } ` ,
type : 'net' ,
data : state . query ,
} ) ;
} else if ( typeof data === 'object' && data !== null ) {
// 如果data是单个对象, 将其包装在数组中
const localAddr = ` ${ data . localaddr ? . ip || '' } : ${ data . localaddr ? . port || '' } ` ;
const remoteAddr = ` ${ data . remoteaddr ? . ip || '' } : ${ data . remoteaddr ? . port || '' } ` ;
processedData = [ { ... data , localAddr , remoteAddr } ] ;
} else {
console . warn ( '收到意外的数据格式:' , data ) ;
}
if ( requestId ) {
tableState . data = processedData ; // 将数据填入表格
}
}
function extracted ( ) { //将表单各条件值取出, 并打包在data中发送请求
const { pid , name , port , flag } = toRaw ( bufferParams ) //从queryParams中取出各属性值
let data = { } // { 'PID': PID, 'name': name, 'port': port }
if ( flag ) { //若flag为真则把值封装进data
data = { 'pid' : pid , 'name' : name , 'port' : port }
}
//发送请求
ws . send ( {
'requestId' : 'dxxx' ,
'type' : 'net' ,
'data' : data ,
} ) ;
}
/**查询参数重置 */
function fnQueryReset ( ) {
Object . assign ( queryParams , {
pid : undefined ,
name : '' ,
port : undefined ,
} ) ;
tablePagination . current = 1 ;
tablePagination . pageSize = 20 ;
// 重置查询条件
Object . assign ( state . query , {
pid : undefined ,
name : '' ,
port : undefined ,
} ) ;
}
/**表格状态类型 */
type TableStateType = {
/**加载等待 */
loading : boolean ;
/**记录数据 */
data : object [ ] ;
} ;
/**表格状态 */
let tableState : TableStateType = reactive ( {
loading : false ,
size : 'large' ,
data : [ ] ,
} ) ;
/**表格字段列 */
const tableColumns : ColumnsType < any > = [
{
title : t ( 'views.tool.ps.pid' ) ,
dataIndex : 'pid' ,
align : 'right' ,
width : 100 ,
sorter : {
compare : ( a : any , b : any ) => a . pid - b . pid ,
multiple : 3 ,
} ,
} ,
{
title : t ( 'views.tool.net.proto' ) ,
dataIndex : 'type' ,
align : 'left' ,
width : 100 ,
customRender ( opt ) {
return ` ${ opt . value } ` . toUpperCase ( ) ;
} ,
} ,
{
title : t ( 'views.tool.net.localAddr' ) ,
dataIndex : 'localAddr' ,
align : 'left' ,
width : 150 ,
customRender ( opt ) {
const { ip , port } = opt . value ;
return port !== 0 ? ` ${ ip } : ${ port } ` : ` ${ ip } ` ;
} ,
} ,
{
title : t ( 'views.tool.net.remoteAddr' ) ,
dataIndex : 'remoteAddr' ,
align : 'left' ,
width : 150 ,
customRender ( opt ) {
const { ip , port } = opt . value ;
return port !== 0 ? ` ${ ip } : ${ port } ` : ` ${ ip } ` ;
} ,
} ,
{
title : t ( 'views.tool.net.status' ) ,
dataIndex : 'status' ,
align : 'left' ,
width : 120 ,
} ,
{
title : t ( 'views.tool.ps.name' ) ,
dataIndex : 'name' ,
align : 'left' ,
} ,
] ;
/**表格分页器参数 */
let tablePagination = reactive ( {
/**当前页数 */
@@ -175,134 +225,109 @@ let tablePagination = reactive({
} ,
} ) ;
/**表格状态类型 */
type TableStateType = {
/**加载等待 */
loading : boolean ;
/**紧凑型 */
size : SizeType ;
/**记录数据 */
data : object [ ] ;
} ;
/**表格字段列 */
const tableColumns : ColumnsType < any > = [
{
title : t ( 'views.tool.net.PID' ) ,
dataIndex : 'pid' ,
align : 'center' ,
width : 50 ,
sorter : { //PID排序
compare : ( a : any , b : any ) => a . pid - b . pid ,
multiple : 1 ,
}
} ,
{
title : t ( 'views.tool.net.name' ) ,
dataIndex : 'name' ,
align : 'center' ,
width : 100 ,
} ,
{
title : t ( 'views.tool.net.localAddr' ) ,
dataIndex : 'localAddr' ,
align : 'center' ,
width : 70 ,
} ,
{
title : t ( 'views.tool.net.remoteAddr' ) ,
dataIndex : 'remoteAddr' ,
align : 'center' ,
width : 100 ,
} ,
{
title : t ( 'views.tool.net.status' ) ,
dataIndex : 'status' ,
align : 'center' ,
width : 70 ,
} ,
{
title : t ( 'views.tool.net.type' ) ,
dataIndex : 'type' ,
align : 'center' ,
width : 100 ,
} ,
] ;
/**钩子函数,界面打开初始化 */
onMounted ( ( ) => {
fnRealTime ( false ) ;
} ) ;
/**钩子函数,界面关闭*/
onBeforeUnmount ( ( ) => {
ws . close ( ) ;
} ) ;
< / script >
< template >
< PageContainer >
< a-card
:bordered = "false"
: body -style = " { marginBottom : ' 24px ' , paddingBottom : 0 } "
>
< a-form :model = "queryParams" name = "formParams" layout = "horizontal" >
<!-- 表格搜索栏 -- >
< a-form :model = "queryParams" name = "queryParams" layout = "horizontal" >
< a-row :gutter = "16" >
< a-col :lg = "4" :md = "6" :xs = "12" >
< a-form-item :label = "t('views.tool.ps.realTime ')" name = "changeTime " >
< a-select
v -model :value = "queryParams.changeTime"
:options = "timeOptions"
:placeholder = "t('common.selectPlease')"
@ change = 'fnRealTime2'
style = 'width: 100%'
/ >
< / a-form-item > < / a-col >
< a-col :lg = "3" :md = "6" :xs = "12" >
< a-form-item :label = "t('views.tool.ps.pid')" name = "pid" >
< a-form-item :label = "t('views.tool.ps.pid ')" name = "pid " >
< a-input-number
v -model :value = "queryParams.pid"
allow -clear
:placeholder = "t('common.inputPlease')"
style = ' width: 100%'
style = " width: 100%"
> < / a-input-number >
< / a-form-item > < / a-col >
< / a-form-item >
< / a-col >
< a-col :lg = "6" :md = "12" :xs = "24" >
< a-form-item :label = "t('views.tool.net .name')" name = "name" >
< a-form-item :label = "t('views.tool.ps .name')" name = "name" >
< a-input
v -model :value = "queryParams.name"
allow -clear
:placeholder = "t('common.inputPlease')"
> < / a-input >
< / a-form-item > < / a-col >
< a-col :lg = "5" :md = "10" :xs = "20" >
< a-form-item :label = "t('views.tool.net.port')" name = "port " >
< / a-form-item >
< / a-col >
< a-col :lg = "6" :md = "12" :xs = "24 " >
< a-form-item :label = "t('views.tool.net.port')" name = "port" >
< a-input-number
v -model :value = "queryParams.port"
allow -clear
:placeholder = "t('common.inputPlease')"
style = ' width: 100%'
style = " width: 100%"
> < / a-input-number >
< / a-form-item > < / a-col >
< a-col :lg = "4" :md = "12" :xs = "24" >
< a-form-item >
< a-button type = "primary" @ click = 'queryTime()' >
< template # icon > < SearchOutlined / > < / template >
{ { t ( 'common.search' ) } }
< / a-button >
< a-button type = "default" @click.prevent ="queryReset()" style = 'left: 20px;' >
< template # icon > < ClearOutlined / > < / template >
{ { t ( 'common.reset' ) } }
< / a-button >
< / a-form-item >
< / a-col >
< a-col :lg = "4" :md = "12" :xs = "24" >
< a-form-item >
< a-space :size = "8" >
< a-button type = "primary" @click.prevent ="fnQuery()" >
< template # icon > < SearchOutlined / > < / template >
{ { t ( 'common.search' ) } }
< / a-button >
< a-button type = "default" @click.prevent ="fnQueryReset" >
< template # icon > < ClearOutlined / > < / template >
{ { t ( 'common.reset' ) } }
< / a-button >
< / a-space >
< / a-form-item >
< / a-col >
< / a-row >
< / a-form >
< / a-card >
< a-table
class = "table"
row -key = " id "
:columns = "tableColumns"
:pagination = "tablePagination"
:loading = "tableState.loading"
:data-source = "tableState.data"
:size = "tableState.siz e"
: scroll = "{ x: tableColumns.length * 120 }"
> < / a-table >
< a-card :bordered = "false" : body -style = " { padding : ' 0px ' } " >
<!-- 插槽 - 卡片左侧侧 -- >
< template # title >
< a-form layout = "inline" >
< a-form-item :label = "t('views.tool.ps.realTime')" name = "realTime" >
< a-select
v -model :value = "state.intervalTim e"
: options = "[
{ label: t('views.tool.ps.realTimeHigh'), value: 3_000 },
{ label: t('views.tool.ps.realTimeRegular'), value: 5_000 },
{ label: t('views.tool.ps.realTimeLow'), value: 10_000 },
{ label: t('views.tool.ps.realTimeStop'), value: -1 },
]"
:placeholder = "t('common.selectPlease')"
@change ="fnIntervalChange"
style = "width: 100px"
/ >
< / a-form-item >
< / a-form >
< / template >
<!-- 表格列表 -- >
< a-table
class = "table"
row -key = " id "
:columns = "tableColumns"
:pagination = "tablePagination"
:loading = "tableState.loading"
:data-source = "tableState.data"
size = "small"
: scroll = "{ x: tableColumns.length * 120 }"
> < / a-table >
< / a-card >
< / PageContainer >
< / template >
< style lang = "less" scoped >
. table : deep ( . ant - pagination ) {
padding : 0 24 px ;