288 lines
7.7 KiB
Vue
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>
|