feat: 网元日志文件获取查看,抓包单独查看

This commit is contained in:
TsMask
2024-10-15 14:55:41 +08:00
parent 405842bc0b
commit 6e11d2b16a
7 changed files with 171 additions and 47 deletions

View File

@@ -1,7 +1,7 @@
import { request } from '@/plugins/http-fetch';
/**
* 查询文件列表列表
* 查询网元端文件列表
* @param query 查询参数
* @returns object
*/
@@ -14,7 +14,7 @@ export function listNeFiles(query: Record<string, any>) {
}
/**
* 从网元获取文件
* 从网元到本地获取文件
* @param query 查询参数
* @returns object
*/
@@ -27,3 +27,24 @@ export function getNeFile(query: Record<string, any>) {
timeout: 180_000,
});
}
// 从网元到本地获取目录压缩为ZIP
export function getNeDirZip(data: Record<string, any>) {
return request({
url: '/ne/action/pullDirZip',
method: 'get',
params: data,
responseType: 'blob',
timeout: 60_000,
});
}
// 查看网元端文件内容
export function getNeViewFile(data: Record<string, any>) {
return request({
url: '/ne/action/viewFile',
method: 'get',
params: data,
timeout: 60_000,
});
}

View File

@@ -20,17 +20,6 @@ export function dumpStop(data: Record<string, string>) {
});
}
// 网元抓包PACP 下载
export function dumpDownload(data: Record<string, any>) {
return request({
url: '/trace/tcpdump/download',
method: 'get',
params: data,
responseType: 'blob',
timeout: 60_000,
});
}
// UPF标准版内部抓包
export function traceUPF(data: Record<string, string>) {
return request({

View File

@@ -1110,8 +1110,8 @@ export default {
fileUPFTip: 'UPF internal packet capture and analysis packet',
textStart: "Start",
textStop: "Stop",
textLog: "Log",
textLogMsg: "Log Info",
textLog: "LogFile",
textLogMsg: "LogFile Info",
textDown: "Download",
downTip: "Are you sure you want to download the {title} capture data file?",
downOk: "{title} file download complete",

View File

@@ -1110,8 +1110,8 @@ export default {
fileUPFTip: 'UPF内部抓包分析包',
textStart: "开始",
textStop: "停止",
textLog: "日志",
textLogMsg: "日志信息",
textLog: "日志文件",
textLogMsg: "日志文件信息",
textDown: "下载",
downTip: "确认要下载 {title} 抓包数据文件吗?",
downOk: "{title} 文件下载完成",

View File

@@ -204,11 +204,13 @@ function fnDirCD(dir: string, index?: number) {
/**网元类型选择对应修改 */
function fnNeChange(keys: any, _: any) {
if (!Array.isArray(keys)) return;
const neType = keys[0];
const neId = keys[1];
// 不是同类型时需要重新加载
if (Array.isArray(keys) && queryParams.neType !== keys[0]) {
const neType = keys[0];
if (queryParams.neType !== neType || queryParams.neId !== neId) {
queryParams.neType = neType;
queryParams.neId = keys[1];
queryParams.neId = neId;
if (neType === 'IMS') {
nePathArr.value = ['/var/log/ims'];
queryParams.search = '';

View File

@@ -7,6 +7,7 @@ import { Modal, message } from 'ant-design-vue/lib';
import { parseDateToStr } from '@/utils/date-utils';
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import ViewDrawer from '@/views/logManage/neFile/components/ViewDrawer.vue';
import useNeInfoStore from '@/store/modules/neinfo';
import useTabsStore from '@/store/modules/tabs';
import useI18n from '@/hooks/useI18n';
@@ -218,16 +219,18 @@ function fnDirCD(dir: string, index?: number) {
/**网元类型选择对应修改 */
function fnNeChange(keys: any, _: any) {
if (!Array.isArray(keys)) return;
const neType = keys[0];
const neId = keys[1];
// 不是同类型时需要重新加载
if (Array.isArray(keys) && queryParams.neType !== keys[0]) {
const neType = keys[0];
if (queryParams.neType !== neType || queryParams.neId !== neId) {
queryParams.neType = neType;
queryParams.neId = keys[1];
queryParams.neId = neId;
if (neType === 'UPF' && tmp.value) {
nePathArr.value = ['/tmp'];
queryParams.search = `${neType}_${keys[1]}`;
queryParams.search = `${neType}_${neId}`;
} else {
nePathArr.value = [`/tmp/omc/tcpdump/${neType.toLowerCase()}/${keys[1]}`];
nePathArr.value = [`/tmp/omc/tcpdump/${neType.toLowerCase()}/${neId}`];
queryParams.search = '';
}
fnGetList(1);
@@ -270,6 +273,25 @@ function fnGetList(pageNum?: number) {
});
}
/**抽屉状态 */
const viewDrawerState = reactive({
visible: false,
/**文件路径 /var/log/amf.log */
filePath: '',
/**网元类型 */
neType: '',
/**网元ID */
neId: '',
});
/**打开抽屉查看 */
function fnDrawerOpen(row: Record<string, any>) {
viewDrawerState.filePath = [...nePathArr.value, row.fileName].join('/');
viewDrawerState.neType = neTypeSelect.value[0];
viewDrawerState.neId = neTypeSelect.value[1];
viewDrawerState.visible = !viewDrawerState.visible;
}
onMounted(() => {
// 获取网元网元列表
neInfoStore.fnNelist().then(res => {
@@ -375,6 +397,16 @@ onMounted(() => {
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'fileName'">
<a-space :size="8" align="center">
<a-tooltip
v-if="
record.fileType === 'file' && record.fileName.endsWith('.log')
"
>
<template #title>{{ t('common.viewText') }}</template>
<a-button type="link" @click.prevent="fnDrawerOpen(record)">
<template #icon><ProfileOutlined /></template>
</a-button>
</a-tooltip>
<a-button
type="link"
:loading="downLoading"
@@ -398,6 +430,14 @@ onMounted(() => {
</template>
</a-table>
</a-card>
<!-- 文件内容查看抽屉 -->
<ViewDrawer
v-model:visible="viewDrawerState.visible"
:file-path="viewDrawerState.filePath"
:ne-type="viewDrawerState.neType"
:ne-id="viewDrawerState.neId"
></ViewDrawer>
</PageContainer>
</template>

View File

@@ -4,9 +4,9 @@ import { useRoute, useRouter } from 'vue-router';
import { message, Modal } from 'ant-design-vue/lib';
import { ColumnsType } from 'ant-design-vue/lib/table';
import { PageContainer } from 'antdv-pro-layout';
import { dumpStart, dumpStop, dumpDownload, traceUPF } from '@/api/trace/pcap';
import { dumpStart, dumpStop, traceUPF } from '@/api/trace/pcap';
import { listAllNeInfo } from '@/api/ne/neInfo';
import { getNeFile } from '@/api/tool/neFile';
import { getNeDirZip, getNeFile, getNeViewFile } from '@/api/tool/neFile';
import saveAs from 'file-saver';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
@@ -31,7 +31,7 @@ type ModalStateType = {
/**任务编号 */
taskCode: string;
/**任务日志,upf标准版为空字符串 */
logMsg: string;
taskFiles: string[];
/**提交表单参数 */
data: {
neType: string;
@@ -65,7 +65,14 @@ type ModalStateType = {
/**详情框是否显示 */
visibleByView: boolean;
/**详情框内容 */
logMsg: string;
viewFrom: {
neType: string;
neId: string;
path: string;
action: string;
files: string[];
content: string;
};
};
/**对话框对象信息状态 */
@@ -106,7 +113,14 @@ let modalState: ModalStateType = reactive({
},
],
visibleByView: false,
logMsg: '',
viewFrom: {
neType: '',
neId: '',
path: '',
action: '',
files: [],
content: '',
},
});
/**表格状态类型 */
@@ -194,7 +208,7 @@ function fnGetList() {
cmdStart: start,
cmdStop: stop,
taskCode: '',
logMsg: '',
taskFiles: [],
data: {
neType: item.neType,
neId: item.neId,
@@ -218,7 +232,7 @@ function fnSelectCmd(id: any, option: any) {
modalState.from[id].cmdStop = option.stop;
// 重置任务
modalState.from[id].taskCode = '';
modalState.from[id].logMsg = '';
modalState.from[id].taskFiles = [];
}
/**
@@ -341,7 +355,7 @@ function fnRecordStop(row?: Record<string, any>) {
if (res.status === 'fulfilled') {
const resV = res.value;
fromArr[idx].loading = false;
fromArr[idx].logMsg = '';
fromArr[idx].taskFiles = [];
if (fromArr[idx].cmdStop) {
fromArr[idx].taskCode = '';
}
@@ -350,7 +364,7 @@ function fnRecordStop(row?: Record<string, any>) {
if (fromArr[idx].cmdStop) {
fromArr[idx].taskCode = resV.data;
} else {
fromArr[idx].logMsg = resV.msg;
fromArr[idx].taskFiles = resV.data;
}
message.success({
content: t('views.traceManage.pcap.stopOk', { title }),
@@ -422,10 +436,15 @@ function fnDownPCAP(row?: Record<string, any>) {
)
);
} else {
const { neType, neId } = from.data;
const path = `/tmp/omc/tcpdump/${neType.toLowerCase()}/${neId}/${taskCode}`;
reqArr.push(
dumpDownload(
Object.assign({ taskCode: taskCode, delTemp: true }, from.data)
)
getNeDirZip({
neType,
neId,
path,
delTemp: true,
})
);
}
}
@@ -497,8 +516,42 @@ function fnBatchOper(key: string) {
function fnModalVisibleByVive(id: string | number) {
const from = modalState.from[id];
if (!from) return;
const { neType, neId } = from.data;
const path = `/tmp/omc/tcpdump/${neType.toLowerCase()}/${neId}/${
from.taskCode
}`;
const files = from.taskFiles.filter(f => f.endsWith('log'));
modalState.viewFrom.neType = neType;
modalState.viewFrom.neId = neId;
modalState.viewFrom.path = path;
modalState.viewFrom.files = [...files];
fnViveTab(files[0]);
modalState.visibleByView = true;
modalState.logMsg = from.logMsg;
}
/**对话框tab查看 */
function fnViveTab(action: any) {
console.log('fnViveTab', action);
if (modalState.viewFrom.action === action) return;
modalState.viewFrom.action = action;
modalState.viewFrom.content = '';
const { neType, neId, path } = modalState.viewFrom;
getNeViewFile({
neId,
neType,
path,
fileName: action,
}).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
modalState.viewFrom.content = res.data;
} else {
modalState.viewFrom.content = '';
message.warning({
content: `${res.msg}`,
duration: 3,
});
}
});
}
/**
@@ -507,7 +560,8 @@ function fnModalVisibleByVive(id: string | number) {
*/
function fnModalCancel() {
modalState.visibleByView = false;
modalState.logMsg = '';
modalState.viewFrom.action = '';
modalState.viewFrom.files = [];
}
/**跳转文件数据页面 */
@@ -651,7 +705,7 @@ onMounted(() => {
placement="topRight"
v-if="
!modalState.from[record.id].loading &&
!!modalState.from[record.id].logMsg
modalState.from[record.id].taskFiles.length > 0
"
>
<template #title>
@@ -694,21 +748,39 @@ onMounted(() => {
<!-- 日志信息框 -->
<ProModal
:drag="true"
:fullscreen="true"
:borderDraw="true"
:width="800"
:visible="modalState.visibleByView"
:footer="false"
:maskClosable="false"
:keyboard="false"
:body-style="{ padding: '12px' }"
:body-style="{ padding: '0 12px 12px' }"
:title="t('views.traceManage.pcap.textLogMsg')"
@cancel="fnModalCancel"
>
<a-textarea
v-model:value="modalState.logMsg"
:auto-size="{ minRows: 2, maxRows: 18 }"
:disabled="true"
style="color: rgba(0, 0, 0, 0.85)"
/>
<a-tabs
v-model:activeKey="modalState.viewFrom.action"
tab-position="top"
size="small"
@tabClick="fnViveTab"
>
<a-tab-pane
v-for="fileName in modalState.viewFrom.files"
:key="fileName"
:tab="fileName"
:destroyInactiveTabPane="false"
>
<a-spin :spinning="!modalState.viewFrom.content">
<a-textarea
:value="modalState.viewFrom.content"
:auto-size="{ minRows: 2 }"
:disabled="true"
style="color: rgba(0, 0, 0, 0.85)"
/>
</a-spin>
</a-tab-pane>
</a-tabs>
</ProModal>
</PageContainer>
</template>