Merge remote-tracking branch 'origin/lichang' into lichang

This commit is contained in:
zhongzm
2024-10-11 18:05:32 +08:00
8 changed files with 254 additions and 229 deletions

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -2112,7 +2112,7 @@ export default {
realTimeStop:"Stop",
realTime:"Real Time Speed",
pid:"PID",
name:"APP Name",
name:"Program name",
username:"User Name",
runTime:"Run Time",
numThreads:"Thread",
@@ -2121,13 +2121,11 @@ export default {
diskWrite:"Disk Write",
},
net:{
PID:"PID",
name:"name",
localAddr:"localAddr",
remoteAddr:"remoteAddr",
status:"status",
type:"type",
port:"port",
localAddr:"Local Address",
remoteAddr:"Foreign Address",
status:"State",
proto:"Proto",
port:"Port",
},
},
},

View File

@@ -2121,13 +2121,11 @@ export default {
diskWrite:"磁盘写入",
},
net:{
PID:"PID",
name:"名称",
localAddr:"localAddr",
remoteAddr:"remoteAddr",
localAddr:"本地地址",
remoteAddr:"远程地址",
status:"状态",
type:"类型",
port:"口",
proto:"协议",
port:"口",
},
},
},

View File

@@ -70,6 +70,7 @@ let fromState = ref({
nef_ip: '172.16.5.210',
mme_ip: '172.16.5.220',
n3iwf_ip: '172.16.5.230',
smsc_ip: '172.16.5.240',
},
});

View File

@@ -102,6 +102,9 @@ export function usePara5G() {
case 'N3IWF':
state.from.sbi.n3iwf_ip = item.ip;
break;
case 'SMSC':
state.from.sbi.smsc_ip = item.ip;
break;
}
}
}

View File

@@ -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 { SizeType } from 'ant-design-vue/lib/config-provider';
import { ColumnsType } 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:"",
name: '',
port: undefined,
flag: false,
changeTime:5000,
});
//临时缓存:用于搜索后清除筛选条件
let bufferParams = reactive({
/**状态对象 */
let state = reactive({
/**调度器 */
interval: null as any,
/**刷新周期 */
intervalTime: 5_000,
/**查询参数 */
query: {
pid: undefined,
name:"",
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)//设置定时器
},
});
/**查询按钮**/
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 wsMessage(res: Record<string, any>) {
const { code, requestId, data } = res;
if (code === RESULT_CODE_ERROR) {
console.warn(res.msg);
return;
}
/**重置按钮**/
function queryReset(){
queryParams.flag = false
bufferParams.flag = false
// 建联时发送请求
if (!requestId && data.clientId) {
fnGetList();
return;
}
let s:any = null
/**定时器**/
function queryReset2(c:boolean){
if(c){
clearInterval(s)//清理旧定时器
ws.close();//断开原来的wb连接
fnRealTime();//建立新的实时数据连接
// 收到消息数据
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(reLink: boolean) {
if (reLink) {
ws.close();
}
/**
* 实时数据
*/
function fnRealTime() {
const options: OptionsType = {
url: '/ws',
onmessage: wsMessage,
onerror: wsError,
onerror: (ev: any) => {
// 接收数据后回调
console.error(ev);
},
};
//建立连接
ws.connect(options);
}
/**接收数据后回调(失败) */
function wsError(ev: any) {
// 接收数据后回调
console.error(ev);
}
/**接收数据后回调(成功) */
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[]=[];
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 };
});
} 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 fnIntervalChange(v: any) {
clearInterval(state.interval);
const timer = parseInt(v);
if (timer > 1_000) {
state.intervalTime = v;
fnGetList();
}
}
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 }
/**查询列表 */
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);
}
//发送请求
/**查询参数传入 */
function fnQuery() {
state.query = JSON.parse(JSON.stringify(queryParams));
nextTick(() => {
ws.send({
'requestId': 'dxxx',
'type': 'net',
'data': data,
requestId: `net_${state.interval}`,
type: 'net',
data: state.query,
});
});
}
/**查询参数重置 */
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,122 +225,95 @@ 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-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>
</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-form-item>
</a-col>
<a-col :lg="4" :md="12" :xs="24">
<a-form-item>
<a-button type="primary" @click='queryTime()'>
<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="queryReset()" style='left: 20px;'>
<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-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.intervalTime"
: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"
@@ -298,11 +321,13 @@ const tableColumns: ColumnsType<any> = [
:pagination="tablePagination"
:loading="tableState.loading"
:data-source="tableState.data"
:size="tableState.size"
size="small"
:scroll="{ x: tableColumns.length * 120 }"
></a-table>
</a-card>
</PageContainer>
</template>
<style lang="less" scoped>
.table :deep(.ant-pagination) {
padding: 0 24px;

View File

@@ -50,6 +50,9 @@ function wsMessage(res: Record<string, any>) {
if (requestId.startsWith('ps_')) {
// 将数据填入表格
if (Array.isArray(data)) {
if (tableState.loading) {
tableState.loading = false;
}
tableState.data = data;
} else {
tableState.data = [];
@@ -97,10 +100,9 @@ function fnGetList() {
ws.send(msg);
// 定时刷新数据
state.interval = setInterval(() => {
msg.data = state.query;
msg.data = JSON.parse(JSON.stringify(state.query));
ws.send(msg);
}, state.intervalTime);
tableState.loading = false;
}
/**查询参数传入 */
@@ -320,8 +322,6 @@ onBeforeUnmount(() => {
</a-col>
</a-row>
</a-form>
<div>{{ state.query }}</div>
<div>{{ queryParams }}</div>
</a-card>
<a-card :bordered="false" :body-style="{ padding: '0px' }">

View File

@@ -19,7 +19,6 @@ import {
packetStop,
packetFilter,
} from '@/api/trace/packet';
import { s } from 'vite/dist/node/types.d-aGj9QkWt';
const ws = new WS();
const { t } = useI18n();
@@ -366,6 +365,7 @@ onBeforeUnmount(() => {
type="primary"
:loading="downLoading"
@click.prevent="fnDownloadPCAP()"
v-if="state.task.outputPCAP"
>
<template #icon><DownloadOutlined /></template>
{{ t('common.downloadText') }}
@@ -378,7 +378,7 @@ onBeforeUnmount(() => {
</a-tag>
</a-space>
<a-space :size="8" class="toolbar-info">
<a-space :size="8" class="toolbar-info" v-show="state.initialized">
<span>
{{ t('views.traceManage.task.traceId') }}:&nbsp;
<strong>{{ state.task.taskNo }}</strong>