ref: 统一ftp操作功能,备份文件查看下载删除功能

This commit is contained in:
TsMask
2025-04-25 16:16:09 +08:00
parent 71b4943816
commit 204d198819
8 changed files with 473 additions and 609 deletions

View File

@@ -1,38 +1,57 @@
<script setup lang="ts">
import { reactive, ref, onMounted, toRaw } from 'vue';
import { reactive, ref, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import { ProModal } from 'antdv-pro-modal';
import { SizeType } from 'ant-design-vue/es/config-provider';
import { ColumnsType } from 'ant-design-vue/es/table';
import { Form, Modal, message } from 'ant-design-vue/es';
import { Modal, message } from 'ant-design-vue/es';
import BackupModal from '@/views/ne/neConfigBackup/components/BackupModal.vue';
import { parseDateToStr } from '@/utils/date-utils';
import {
getBakFile,
getBakFileList,
downFile,
delFile,
updateFTPInfo,
getFTPInfo,
putFTPInfo,
} from '@/api/logManage/exportFile';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import useI18n from '@/hooks/useI18n';
import saveAs from 'file-saver';
import { regExpIPv4 } from '@/utils/regular-utils';
import { delFile, getFile, listFile } from '@/api/tool/file';
import { parseSizeFromFile } from '@/utils/parse-utils';
import { pushBackupFTP } from '@/api/neData/backup';
const { t } = useI18n();
/**网元参数 */
let logSelect = ref<string[]>([]);
/**文件列表 */
let fileList = ref<any>([]);
/**文件来源 */
let sourceState = reactive({
/**文件列表 */
list: [
{
value: '/log/operate_log',
label: t('views.logManage.exportFile.operateLog'),
path: '/usr/local/omc/backup',
},
{
value: '/cdr/ims_cdr',
label: t('views.logManage.exportFile.cdrIMS'),
path: '/usr/local/omc/backup',
},
{
value: '/cdr/smf_cdr',
label: t('views.logManage.exportFile.cdrSMF'),
path: '/usr/local/omc/backup',
},
{
value: '/cdr/smsc_cdr',
label: t('views.logManage.exportFile.cdrSMSC'),
path: '/usr/local/omc/backup',
},
{
value: '/cdr/sgwc_cdr',
label: t('views.logManage.exportFile.cdrSGWC'),
path: '/usr/local/omc/backup',
},
],
/**选择value */
value: undefined,
});
/**查询参数 */
let queryParams = reactive({
/**读取路径 */
path: '',
/**表名 */
tableName: '',
/**当前页数 */
pageNum: 1,
/**每页条数 */
@@ -80,6 +99,9 @@ let tableColumns: ColumnsType = [
title: t('views.logManage.neFile.size'),
dataIndex: 'size',
align: 'left',
customRender(opt) {
return parseSizeFromFile(opt.value);
},
width: 100,
},
{
@@ -88,9 +110,9 @@ let tableColumns: ColumnsType = [
align: 'left',
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value * 1000);
return parseDateToStr(opt.value);
},
width: 150,
width: 200,
},
{
title: t('views.logManage.neFile.fileName'),
@@ -135,10 +157,6 @@ let tablePagination = reactive({
/**下载触发等待 */
let downLoading = ref<boolean>(false);
/**删除触发等待 */
let delLoading = ref<boolean>(false);
/**信息文件下载 */
function fnDownloadFile(row: Record<string, any>) {
if (downLoading.value) return;
@@ -150,10 +168,7 @@ function fnDownloadFile(row: Record<string, any>) {
onOk() {
downLoading.value = true;
const hide = message.loading(t('common.loading'), 0);
downFile({
path: queryParams.path,
fileName: row.fileName,
})
getFile(queryParams.path, row.fileName)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
@@ -178,6 +193,9 @@ function fnDownloadFile(row: Record<string, any>) {
});
}
/**删除触发等待 */
let delLoading = ref<boolean>(false);
/**信息文件删除 */
function fnRecordDelete(row: Record<string, any>) {
if (delLoading.value) return;
Modal.confirm({
@@ -186,30 +204,27 @@ function fnRecordDelete(row: Record<string, any>) {
fileName: row.fileName,
}),
onOk() {
const key = 'delFile';
delLoading.value = true;
message.loading({ content: t('common.loading'), key });
delFile({
fileName: row.fileName,
path: queryParams.path,
})
const hide = message.loading(t('common.loading'), 0);
delFile(queryParams.path, row.fileName)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: t('views.system.user.delSuss'),
key,
content: t('common.msgSuccess', {
msg: t('common.deleteText'),
}),
duration: 2,
});
fnGetList();
} else {
message.error({
content: `${res.msg}`,
key: key,
content: t('views.logManage.exportFile.deleteTipErr'),
duration: 2,
});
}
})
.finally(() => {
hide();
delLoading.value = false;
});
},
@@ -217,17 +232,18 @@ function fnRecordDelete(row: Record<string, any>) {
}
/**网元类型选择对应修改 */
function fnNeChange(keys: any, opt: any) {
queryParams.tableName = keys;
queryParams.path = opt.path;
function fnNeChange(_: any, opt: any) {
queryParams.path = `${opt.path}${opt.value}`;
ftpInfo.path = queryParams.path;
ftpInfo.tag = opt.value;
fnGetList(1);
}
/**查询备份信息列表, pageNum初始页数 */
function fnGetList(pageNum?: number) {
if (queryParams.tableName === '') {
if (queryParams.path === '') {
message.warning({
content: t('views.logManage.exportFile.selectTip'),
content: t('views.logManage.exportFile.fileSourcePlease'),
duration: 2,
});
return;
@@ -237,7 +253,7 @@ function fnGetList(pageNum?: number) {
if (pageNum) {
queryParams.pageNum = pageNum;
}
getBakFileList(toRaw(queryParams)).then(res => {
listFile(toRaw(queryParams)).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
const { total, rows } = res.data;
tablePagination.total = total;
@@ -259,147 +275,34 @@ function fnGetList(pageNum?: number) {
});
}
onMounted(() => {
getBakFile().then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
res.data.forEach((item: any) => {
fileList.value.push({
value: item.tableName,
label: item.tableDisplay,
path: item.filePath,
});
});
}
});
// .finally(() => {
// fnGetList();
// });
});
/**打开FTP配置窗口 */
const openFTPModal = ref<boolean>(false);
function fnFTPModalOpen() {
openFTPModal.value = !openFTPModal.value;
}
/**对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
openByEdit: boolean;
/**标题 */
title: string;
/**表单数据 */
from: Record<string, any>;
/**确定按钮 loading */
confirmLoading: boolean;
type FTPInfoType = {
path: string;
tag: string;
fileName: string;
};
/**FTP日志对象信息状态 */
let modalState: ModalStateType = reactive({
openByEdit: false,
title: '设置远程备份配置',
from: {
username: '',
password: '',
toIp: '',
toPort: 22,
enable: false,
dir: '',
},
confirmLoading: false,
const ftpInfo = reactive<FTPInfoType>({
path: '',
tag: '',
fileName: '',
});
/**FTP日志对象信息内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
modalState.from,
reactive({
toIp: [
{
required: true,
pattern: regExpIPv4,
message: 'Please enter the service login IP',
},
],
username: [
{
required: true,
trigger: 'blur',
message: 'Please enter the service login user name',
},
],
dir: [
{
required: true,
trigger: 'blur',
message: 'Please enter the service address target file directory',
},
],
})
);
/**
* 对话框弹出显示为 新增或者修改
* @param configId 参数编号id, 不传为新增
*/
function fnModalVisibleByEdit() {
if (modalState.confirmLoading) return;
const hide = message.loading(t('common.loading'), 0);
modalState.confirmLoading = true;
getFTPInfo().then(res => {
modalState.confirmLoading = false;
hide();
if (res.code === RESULT_CODE_SUCCESS && res.data) {
modalState.from = Object.assign(modalState.from, res.data);
modalState.title = 'Setting Remote Backup';
modalState.openByEdit = true;
/**同步文件到FTP */
function fnSyncFileToFTP(fileName: string) {
ftpInfo.fileName = fileName;
pushBackupFTP(toRaw(ftpInfo)).then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success(t('common.operateOk'), 3);
} else {
message.error(res.msg, 3);
modalState.title = 'Setting Remote Backup';
modalState.openByEdit = false;
message.warning(res.msg, 3);
}
});
}
/**FTP对象保存 */
function fnModalOk() {
modalStateFrom.validate().then(() => {
modalState.confirmLoading = true;
const from = toRaw(modalState.from);
updateFTPInfo(from)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success(`Configuration saved successfully`, 3);
fnModalCancel();
} else {
message.warning(`Configuration save exception`, 3);
}
})
.finally(() => {
modalState.confirmLoading = false;
});
});
}
/**
* 对话框弹出关闭执行函数
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.openByEdit = false;
modalStateFrom.resetFields();
}
/**
* 同步文件到FTP
* @param row
*/
function fnSyncFileToFTP(row: Record<string, any>) {
putFTPInfo(row.filePath, row.fileName)
.then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success(t('common.operateOk'), 3);
} else {
message.warning(res.msg, 3);
}
})
.finally(() => {
modalState.confirmLoading = false;
});
}
</script>
<template>
@@ -410,12 +313,14 @@ function fnSyncFileToFTP(row: Record<string, any>) {
<a-form :model="queryParams" name="queryParams" layout="horizontal">
<a-row :gutter="16" align="middle">
<a-col>
<span>{{ t('views.logManage.exportFile.fileName') }}:</span>&nbsp;
<span>{{ t('views.logManage.exportFile.fileSource') }}:</span
>&nbsp;
<a-select
v-model:value="logSelect"
:options="fileList"
v-model:value="sourceState.value"
:options="sourceState.list"
@change="fnNeChange"
:allow-clear="false"
:placeholder="t('common.selectPlease')"
style="width: 200px"
/>
</a-col>
@@ -436,9 +341,11 @@ function fnSyncFileToFTP(row: Record<string, any>) {
<!-- 插槽-卡片右侧 -->
<template #extra>
<a-space :size="8" align="center">
<a-tooltip>
<template #title>Setting Remote Backup</template>
<a-button type="text" @click.prevent="fnModalVisibleByEdit()">
<a-tooltip placement="topRight">
<template #title>
{{ t('views.ne.neConfigBackup.backupModal.title') }}
</template>
<a-button type="text" @click.prevent="fnFTPModalOpen()">
<template #icon><DeliveredProcedureOutlined /></template>
</a-button>
</a-tooltip>
@@ -465,135 +372,45 @@ function fnSyncFileToFTP(row: Record<string, any>) {
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'fileName'">
<a-space :size="8" align="center">
<a-button
type="link"
:loading="downLoading"
@click.prevent="fnSyncFileToFTP(record)"
v-if="record.fileType === 'file'"
>
<template #icon><CloudServerOutlined /></template>
</a-button>
<a-button
type="link"
:loading="downLoading"
@click.prevent="fnDownloadFile(record)"
v-if="record.fileType === 'file'"
>
<template #icon><DownloadOutlined /></template>
</a-button>
<a-button
type="link"
:loading="delLoading"
@click.prevent="fnRecordDelete(record)"
v-if="record.fileType === 'file'"
>
<template #icon><DeleteOutlined /></template>
</a-button>
<a-tooltip placement="topRight" v-if="record.fileType === 'file'">
<template #title>
{{ t('views.ne.neConfigBackup.backupModal.pushFileOper') }}
</template>
<a-button
type="link"
@click.prevent="fnSyncFileToFTP(record.fileName)"
>
<template #icon><CloudServerOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip placement="topRight" v-if="record.fileType === 'file'">
<template #title>{{ t('common.downloadText') }}</template>
<a-button
type="link"
:loading="downLoading"
@click.prevent="fnDownloadFile(record)"
>
<template #icon><DownloadOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip placement="topRight" v-if="record.fileType === 'file'">
<template #title>{{ t('common.deleteText') }}</template>
<a-button
type="link"
:loading="delLoading"
@click.prevent="fnRecordDelete(record)"
>
<template #icon><DeleteOutlined /></template>
</a-button>
</a-tooltip>
</a-space>
</template>
</template>
</a-table>
</a-card>
<!-- 新增框或修改框 -->
<ProModal
:drag="true"
:width="800"
:destroyOnClose="true"
:keyboard="false"
:mask-closable="false"
:open="modalState.openByEdit"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:label-wrap="true"
>
<a-form-item label="Enable" name="enable" :label-col="{ span: 3 }">
<a-switch
v-model:checked="modalState.from.enable"
:checked-children="t('common.switch.open')"
:un-checked-children="t('common.switch.shut')"
/>
</a-form-item>
<template v-if="modalState.from.enable">
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="Service IP"
name="toIp"
v-bind="modalStateFrom.validateInfos.toIp"
>
<a-input
v-model:value="modalState.from.toIp"
allow-clear
:placeholder="t('common.inputPlease')"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="Service Port"
name="toPort"
v-bind="modalStateFrom.validateInfos.toPort"
>
<a-input-number
v-model:value="modalState.from.toPort"
allow-clear
:placeholder="t('common.inputPlease')"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="UserName"
name="username"
v-bind="modalStateFrom.validateInfos.username"
>
<a-input
v-model:value="modalState.from.username"
allow-clear
:placeholder="t('common.inputPlease')"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="Password"
name="password"
v-bind="modalStateFrom.validateInfos.password"
>
<a-input-password
v-model:value="modalState.from.password"
allow-clear
:placeholder="t('common.inputPlease')"
></a-input-password>
</a-form-item>
</a-col>
</a-row>
<a-form-item
label="Save Dir"
name="dir"
v-bind="modalStateFrom.validateInfos.dir"
:label-col="{ span: 3 }"
>
<a-input
v-model:value="modalState.from.dir"
allow-clear
:placeholder="t('common.inputPlease')"
></a-input>
</a-form-item>
</template>
</a-form>
</ProModal>
<!-- FTP配置窗口 -->
<BackupModal v-model:open="openFTPModal"></BackupModal>
</PageContainer>
</template>