2025-02-20 20:44:31 +08:00

288 lines
7.7 KiB
Vue

<script setup>
import { ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { markRaw } from 'vue';
import { Upload, Download, Refresh } from "@element-plus/icons-vue";
// 模拟备份记录数据
const backupRecords = ref([
{
id: 1,
name: "系统完整备份_20240320",
size: "256MB",
type: "完整备份",
status: "成功",
createTime: "2024-03-20 00:00:00",
},
{
id: 2,
name: "监测数据备份_20240320",
size: "128MB",
type: "数据备份",
status: "成功",
createTime: "2024-03-20 12:00:00",
},
]);
// 数据导入上传配置
const uploadConfig = {
action: "/api/upload",
multiple: true,
accept: ".xlsx,.csv",
beforeUpload: (file) => {
const isValidType = [
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"text/csv",
].includes(file.type);
if (!isValidType) {
ElMessage.error("只能上传 Excel 或 CSV 文件!");
return false;
}
return true;
},
onSuccess: () => {
ElMessage.success("导入成功");
},
onError: () => {
ElMessage.error("导入失败");
},
};
// 备份配置
const backupConfig = ref({
autoBackup: true,
backupTime: "00:00",
backupType: "full", // full: 完整备份, data: 数据备份
retention: 30, // 保留天数
});
// 开始备份
const handleBackup = () => {
ElMessageBox.confirm("确认开始备份?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
ElMessage.success("备份任务已启动");
const newBackup = {
id: Date.now(),
name: `系统备份_${new Date().toISOString().split("T")[0].replace(/-/g, "")}`,
size: "处理中",
type: backupConfig.value.backupType === "full" ? "完整备份" : "数据备份",
status: "进行中",
createTime: new Date().toLocaleString(),
};
backupRecords.value.unshift(newBackup);
// 模拟备份完成
setTimeout(() => {
const index = backupRecords.value.findIndex((item) => item.id === newBackup.id);
if (index !== -1) {
backupRecords.value[index].status = "成功";
backupRecords.value[index].size = "128MB";
}
}, 3000);
});
};
// 恢复备份
const handleRestore = (record) => {
if (record.status !== "成功") {
ElMessage.warning("只能恢复成功的备份");
return;
}
ElMessageBox.confirm("确认恢复该备份?此操作将覆盖当前数据!", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
ElMessage.success("恢复任务已启动");
});
};
// 删除备份
const handleDelete = (record) => {
ElMessageBox.confirm("确认删除该备份?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(() => {
const index = backupRecords.value.findIndex((item) => item.id === record.id);
if (index !== -1) {
backupRecords.value.splice(index, 1);
ElMessage.success("删除成功");
}
});
};
// 导出数据
const handleExport = () => {
ElMessage.success("正在导出数据,请稍候...");
};
const icons = {
Upload: markRaw(Upload),
Download: markRaw(Download),
Refresh: markRaw(Refresh)
};
</script>
<template>
<div class="data-container">
<!-- 数据导入导出 -->
<el-card class="mb-20">
<template #header>
<div class="card-header">
<span>数据导入导出</span>
<div class="header-btns">
<el-upload v-bind="uploadConfig" class="upload-btn">
<el-button type="primary">
<el-icon><component :is="icons.Upload" /></el-icon>
导入数据
</el-button>
</el-upload>
<el-button type="success" @click="handleExport">
<el-icon><component :is="icons.Download" /></el-icon>
导出数据
</el-button>
</div>
</div>
</template>
<el-alert
title="支持导入导出的数据类型:监测数据、设备数据、巡护记录等"
type="info"
:closable="false"
class="mb-20"
/>
<el-form label-width="120px">
<el-form-item label="导入说明">
<ol class="import-tips">
<li>支持 Excel CSV 格式的文件</li>
<li>文件大小不超过 10MB</li>
<li>请严格按照模板格式填写数据</li>
<li>导入前请注意备份现有数据</li>
</ol>
</el-form-item>
</el-form>
</el-card>
<!-- 数据备份 -->
<el-card>
<template #header>
<div class="card-header">
<span>数据备份</span>
<el-button type="primary" @click="handleBackup">立即备份</el-button>
</div>
</template>
<!-- 备份配置 -->
<el-form :model="backupConfig" label-width="120px" class="mb-20">
<el-form-item label="自动备份">
<el-switch v-model="backupConfig.autoBackup" />
</el-form-item>
<el-form-item label="备份时间">
<el-time-picker
v-model="backupConfig.backupTime"
format="HH:mm"
placeholder="选择时间"
:disabled="!backupConfig.autoBackup"
/>
</el-form-item>
<el-form-item label="备份类型">
<el-radio-group v-model="backupConfig.backupType">
<el-radio label="full">完整备份</el-radio>
<el-radio label="data">数据备份</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="保留时间">
<el-input-number v-model="backupConfig.retention" :min="7" :max="365" :step="1" />
<span class="ml-10"></span>
</el-form-item>
</el-form>
<!-- 备份记录 -->
<el-table :data="backupRecords" style="width: 100%">
<el-table-column prop="name" label="备份名称" min-width="200" />
<el-table-column prop="size" label="大小" width="100" />
<el-table-column prop="type" label="类型" width="120" />
<el-table-column prop="status" label="状态" width="100">
<template #default="{ row }">
<el-tag :type="row.status === '成功' ? 'success' : 'warning'">
{{ row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="180" />
<el-table-column label="操作" width="200" fixed="right">
<template #default="{ row }">
<el-button
type="primary"
size="small"
:disabled="row.status !== '成功'"
@click="handleRestore(row)"
>
恢复
</el-button>
<el-button type="danger" size="small" @click="handleDelete(row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<style lang="scss" scoped>
@use "./styles/variables" as v;
.data-container {
.mb-20 {
margin-bottom: 20px;
}
.ml-10 {
margin-left: 10px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 16px;
font-weight: 500;
color: $text-primary;
}
.header-btns {
display: flex;
gap: 12px;
}
}
.import-tips {
margin: 0;
padding-left: 20px;
color: $text-regular;
line-height: 1.8;
}
:deep(.el-card) {
border: none;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
:deep(.upload-btn) {
.el-upload {
width: auto;
}
}
}
</style>