feat: 网元日志文件获取查看,抓包单独查看
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { request } from '@/plugins/http-fetch';
|
import { request } from '@/plugins/http-fetch';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询文件列表列表
|
* 查询网元端文件列表
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
@@ -14,7 +14,7 @@ export function listNeFiles(query: Record<string, any>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从网元端获取文件
|
* 从网元到本地获取文件
|
||||||
* @param query 查询参数
|
* @param query 查询参数
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
@@ -27,3 +27,24 @@ export function getNeFile(query: Record<string, any>) {
|
|||||||
timeout: 180_000,
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -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标准版内部抓包
|
// UPF标准版内部抓包
|
||||||
export function traceUPF(data: Record<string, string>) {
|
export function traceUPF(data: Record<string, string>) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -1110,8 +1110,8 @@ export default {
|
|||||||
fileUPFTip: 'UPF internal packet capture and analysis packet',
|
fileUPFTip: 'UPF internal packet capture and analysis packet',
|
||||||
textStart: "Start",
|
textStart: "Start",
|
||||||
textStop: "Stop",
|
textStop: "Stop",
|
||||||
textLog: "Log",
|
textLog: "LogFile",
|
||||||
textLogMsg: "Log Info",
|
textLogMsg: "LogFile Info",
|
||||||
textDown: "Download",
|
textDown: "Download",
|
||||||
downTip: "Are you sure you want to download the {title} capture data file?",
|
downTip: "Are you sure you want to download the {title} capture data file?",
|
||||||
downOk: "{title} file download complete",
|
downOk: "{title} file download complete",
|
||||||
|
|||||||
@@ -1110,8 +1110,8 @@ export default {
|
|||||||
fileUPFTip: 'UPF内部抓包分析包',
|
fileUPFTip: 'UPF内部抓包分析包',
|
||||||
textStart: "开始",
|
textStart: "开始",
|
||||||
textStop: "停止",
|
textStop: "停止",
|
||||||
textLog: "日志",
|
textLog: "日志文件",
|
||||||
textLogMsg: "日志信息",
|
textLogMsg: "日志文件信息",
|
||||||
textDown: "下载",
|
textDown: "下载",
|
||||||
downTip: "确认要下载 {title} 抓包数据文件吗?",
|
downTip: "确认要下载 {title} 抓包数据文件吗?",
|
||||||
downOk: "{title} 文件下载完成",
|
downOk: "{title} 文件下载完成",
|
||||||
|
|||||||
@@ -204,11 +204,13 @@ function fnDirCD(dir: string, index?: number) {
|
|||||||
|
|
||||||
/**网元类型选择对应修改 */
|
/**网元类型选择对应修改 */
|
||||||
function fnNeChange(keys: any, _: any) {
|
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]) {
|
if (queryParams.neType !== neType || queryParams.neId !== neId) {
|
||||||
const neType = keys[0];
|
|
||||||
queryParams.neType = neType;
|
queryParams.neType = neType;
|
||||||
queryParams.neId = keys[1];
|
queryParams.neId = neId;
|
||||||
if (neType === 'IMS') {
|
if (neType === 'IMS') {
|
||||||
nePathArr.value = ['/var/log/ims'];
|
nePathArr.value = ['/var/log/ims'];
|
||||||
queryParams.search = '';
|
queryParams.search = '';
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Modal, message } from 'ant-design-vue/lib';
|
|||||||
import { parseDateToStr } from '@/utils/date-utils';
|
import { parseDateToStr } from '@/utils/date-utils';
|
||||||
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
|
import { getNeFile, listNeFiles } from '@/api/tool/neFile';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
|
import ViewDrawer from '@/views/logManage/neFile/components/ViewDrawer.vue';
|
||||||
import useNeInfoStore from '@/store/modules/neinfo';
|
import useNeInfoStore from '@/store/modules/neinfo';
|
||||||
import useTabsStore from '@/store/modules/tabs';
|
import useTabsStore from '@/store/modules/tabs';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
@@ -218,16 +219,18 @@ function fnDirCD(dir: string, index?: number) {
|
|||||||
|
|
||||||
/**网元类型选择对应修改 */
|
/**网元类型选择对应修改 */
|
||||||
function fnNeChange(keys: any, _: any) {
|
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]) {
|
if (queryParams.neType !== neType || queryParams.neId !== neId) {
|
||||||
const neType = keys[0];
|
|
||||||
queryParams.neType = neType;
|
queryParams.neType = neType;
|
||||||
queryParams.neId = keys[1];
|
queryParams.neId = neId;
|
||||||
if (neType === 'UPF' && tmp.value) {
|
if (neType === 'UPF' && tmp.value) {
|
||||||
nePathArr.value = ['/tmp'];
|
nePathArr.value = ['/tmp'];
|
||||||
queryParams.search = `${neType}_${keys[1]}`;
|
queryParams.search = `${neType}_${neId}`;
|
||||||
} else {
|
} else {
|
||||||
nePathArr.value = [`/tmp/omc/tcpdump/${neType.toLowerCase()}/${keys[1]}`];
|
nePathArr.value = [`/tmp/omc/tcpdump/${neType.toLowerCase()}/${neId}`];
|
||||||
queryParams.search = '';
|
queryParams.search = '';
|
||||||
}
|
}
|
||||||
fnGetList(1);
|
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(() => {
|
onMounted(() => {
|
||||||
// 获取网元网元列表
|
// 获取网元网元列表
|
||||||
neInfoStore.fnNelist().then(res => {
|
neInfoStore.fnNelist().then(res => {
|
||||||
@@ -375,6 +397,16 @@ onMounted(() => {
|
|||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'fileName'">
|
<template v-if="column.key === 'fileName'">
|
||||||
<a-space :size="8" align="center">
|
<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
|
<a-button
|
||||||
type="link"
|
type="link"
|
||||||
:loading="downLoading"
|
:loading="downLoading"
|
||||||
@@ -398,6 +430,14 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 文件内容查看抽屉 -->
|
||||||
|
<ViewDrawer
|
||||||
|
v-model:visible="viewDrawerState.visible"
|
||||||
|
:file-path="viewDrawerState.filePath"
|
||||||
|
:ne-type="viewDrawerState.neType"
|
||||||
|
:ne-id="viewDrawerState.neId"
|
||||||
|
></ViewDrawer>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { useRoute, useRouter } from 'vue-router';
|
|||||||
import { message, Modal } from 'ant-design-vue/lib';
|
import { message, Modal } from 'ant-design-vue/lib';
|
||||||
import { ColumnsType } from 'ant-design-vue/lib/table';
|
import { ColumnsType } from 'ant-design-vue/lib/table';
|
||||||
import { PageContainer } from 'antdv-pro-layout';
|
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 { 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 saveAs from 'file-saver';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
@@ -31,7 +31,7 @@ type ModalStateType = {
|
|||||||
/**任务编号 */
|
/**任务编号 */
|
||||||
taskCode: string;
|
taskCode: string;
|
||||||
/**任务日志,upf标准版为空字符串 */
|
/**任务日志,upf标准版为空字符串 */
|
||||||
logMsg: string;
|
taskFiles: string[];
|
||||||
/**提交表单参数 */
|
/**提交表单参数 */
|
||||||
data: {
|
data: {
|
||||||
neType: string;
|
neType: string;
|
||||||
@@ -65,7 +65,14 @@ type ModalStateType = {
|
|||||||
/**详情框是否显示 */
|
/**详情框是否显示 */
|
||||||
visibleByView: boolean;
|
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,
|
visibleByView: false,
|
||||||
logMsg: '',
|
viewFrom: {
|
||||||
|
neType: '',
|
||||||
|
neId: '',
|
||||||
|
path: '',
|
||||||
|
action: '',
|
||||||
|
files: [],
|
||||||
|
content: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**表格状态类型 */
|
/**表格状态类型 */
|
||||||
@@ -194,7 +208,7 @@ function fnGetList() {
|
|||||||
cmdStart: start,
|
cmdStart: start,
|
||||||
cmdStop: stop,
|
cmdStop: stop,
|
||||||
taskCode: '',
|
taskCode: '',
|
||||||
logMsg: '',
|
taskFiles: [],
|
||||||
data: {
|
data: {
|
||||||
neType: item.neType,
|
neType: item.neType,
|
||||||
neId: item.neId,
|
neId: item.neId,
|
||||||
@@ -218,7 +232,7 @@ function fnSelectCmd(id: any, option: any) {
|
|||||||
modalState.from[id].cmdStop = option.stop;
|
modalState.from[id].cmdStop = option.stop;
|
||||||
// 重置任务
|
// 重置任务
|
||||||
modalState.from[id].taskCode = '';
|
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') {
|
if (res.status === 'fulfilled') {
|
||||||
const resV = res.value;
|
const resV = res.value;
|
||||||
fromArr[idx].loading = false;
|
fromArr[idx].loading = false;
|
||||||
fromArr[idx].logMsg = '';
|
fromArr[idx].taskFiles = [];
|
||||||
if (fromArr[idx].cmdStop) {
|
if (fromArr[idx].cmdStop) {
|
||||||
fromArr[idx].taskCode = '';
|
fromArr[idx].taskCode = '';
|
||||||
}
|
}
|
||||||
@@ -350,7 +364,7 @@ function fnRecordStop(row?: Record<string, any>) {
|
|||||||
if (fromArr[idx].cmdStop) {
|
if (fromArr[idx].cmdStop) {
|
||||||
fromArr[idx].taskCode = resV.data;
|
fromArr[idx].taskCode = resV.data;
|
||||||
} else {
|
} else {
|
||||||
fromArr[idx].logMsg = resV.msg;
|
fromArr[idx].taskFiles = resV.data;
|
||||||
}
|
}
|
||||||
message.success({
|
message.success({
|
||||||
content: t('views.traceManage.pcap.stopOk', { title }),
|
content: t('views.traceManage.pcap.stopOk', { title }),
|
||||||
@@ -422,10 +436,15 @@ function fnDownPCAP(row?: Record<string, any>) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
const { neType, neId } = from.data;
|
||||||
|
const path = `/tmp/omc/tcpdump/${neType.toLowerCase()}/${neId}/${taskCode}`;
|
||||||
reqArr.push(
|
reqArr.push(
|
||||||
dumpDownload(
|
getNeDirZip({
|
||||||
Object.assign({ taskCode: taskCode, delTemp: true }, from.data)
|
neType,
|
||||||
)
|
neId,
|
||||||
|
path,
|
||||||
|
delTemp: true,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,8 +516,42 @@ function fnBatchOper(key: string) {
|
|||||||
function fnModalVisibleByVive(id: string | number) {
|
function fnModalVisibleByVive(id: string | number) {
|
||||||
const from = modalState.from[id];
|
const from = modalState.from[id];
|
||||||
if (!from) return;
|
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.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() {
|
function fnModalCancel() {
|
||||||
modalState.visibleByView = false;
|
modalState.visibleByView = false;
|
||||||
modalState.logMsg = '';
|
modalState.viewFrom.action = '';
|
||||||
|
modalState.viewFrom.files = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**跳转文件数据页面 */
|
/**跳转文件数据页面 */
|
||||||
@@ -651,7 +705,7 @@ onMounted(() => {
|
|||||||
placement="topRight"
|
placement="topRight"
|
||||||
v-if="
|
v-if="
|
||||||
!modalState.from[record.id].loading &&
|
!modalState.from[record.id].loading &&
|
||||||
!!modalState.from[record.id].logMsg
|
modalState.from[record.id].taskFiles.length > 0
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
@@ -694,21 +748,39 @@ onMounted(() => {
|
|||||||
<!-- 日志信息框 -->
|
<!-- 日志信息框 -->
|
||||||
<ProModal
|
<ProModal
|
||||||
:drag="true"
|
:drag="true"
|
||||||
|
:fullscreen="true"
|
||||||
|
:borderDraw="true"
|
||||||
:width="800"
|
:width="800"
|
||||||
:visible="modalState.visibleByView"
|
:visible="modalState.visibleByView"
|
||||||
:footer="false"
|
:footer="false"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:body-style="{ padding: '12px' }"
|
:body-style="{ padding: '0 12px 12px' }"
|
||||||
:title="t('views.traceManage.pcap.textLogMsg')"
|
:title="t('views.traceManage.pcap.textLogMsg')"
|
||||||
@cancel="fnModalCancel"
|
@cancel="fnModalCancel"
|
||||||
>
|
>
|
||||||
<a-textarea
|
<a-tabs
|
||||||
v-model:value="modalState.logMsg"
|
v-model:activeKey="modalState.viewFrom.action"
|
||||||
:auto-size="{ minRows: 2, maxRows: 18 }"
|
tab-position="top"
|
||||||
:disabled="true"
|
size="small"
|
||||||
style="color: rgba(0, 0, 0, 0.85)"
|
@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>
|
</ProModal>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user