FileManage/web/src/views/testdata/datamanagement/index.vue
2025-02-28 16:00:19 +08:00

1947 lines
72 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts">
export default {
name: "datamanagement",//实验数据管理
};
</script>
<script setup lang="ts">
import { ref, onMounted, nextTick, defineAsyncComponent } from "vue";
import { Search } from '@element-plus/icons-vue'
import { useAppStore } from '@/store/modules/app';
import { ElMessageBox, ElMessage, ElMain } from "element-plus";
import Page from '@/components/Pagination/page.vue';
import AudioPlayer from '@/components/file/preview/AudioPlayer.vue';
import { batchDeleteReq } from "@/api/file-operator";
import { tstaskList, getTsNodesTree, addTsNodes, updateTsNodes, deleteTsNodesById, tsFilesPage, addTsFiles, updateTsFiles, deleteTsFilesById, listTsFiles, deleteTsFilesByIds, compress, Decompression, compare, downloadToLocal, uploadToBackup, addTsFile, list, moveFileFolder, copyFileFolder } from "@/api/datamanagement";
import ZUpload from '@/components/file/ZUpload.vue'
import useFileUpload from "@/components/file/file/useFileUpload";
import useHeaderStorageList from "@/components/header/useHeaderStorageList";
import useFileData from "@/components/file/file/useFileData";
// 文件预览相关
import Viewfile from '@/views/component/Viewfile.vue'
import useFilePreview from "@/components/file/file/useFilePreview";
import MarkdownViewerAsyncLoading from "@/components/file/preview/MarkdownViewerAsyncLoading.vue";
import VideoPlayerAsyncLoading from "@/components/file/preview/VideoPlayerAsyncLoading.vue";
import TextViewerAsyncLoading from "@/components/file/preview/TextViewerAsyncLoading.vue";
import MarkdownViewerDialogAsyncLoading from "@/components/file/preview/MarkdownViewerDialogAsyncLoading.vue";
import { display } from "html2canvas/dist/types/css/property-descriptors/display";
const { dialogVideoVisible, dialogTextVisible, dialogPdfVisible, dialogOfficeVisible, dialog3dVisible } = useFilePreview();
const { clearALlFinishedUploadFile } = useFileUpload();
const { currentStorageKey } = useHeaderStorageList();
const { openRow } = useFileData();
onMounted(() => {
getProject()
});
//拖动条
const vMove = {
mounted(el: any) {
el.onmousedown = function (e: any) {
var init = e.clientX;
var parent: any = document.getElementById("silderLeft");
const initWidth: any = parent.offsetWidth;
document.onmousemove = function (e) {
var end = e.clientX;
var newWidth = end - init + initWidth;
parent.style.width = newWidth + "px";
};
document.onmouseup = function () {
document.onmousemove = document.onmouseup = null;
};
};
}
}
//左侧树的选择框
const projectId = ref()
const projectArr = ref([])
//获取所有项目
function getProject() {
tstaskList().then((res: any) => {
projectArr.value = res.data
projectId.value = projectArr.value[0].id
gettreedata()
})
}
//左侧树配置
const treedata = ref([])
const treeloading = ref(false)
const defaultProps = {
children: "children",
label: "nodeName"
};
const treeForm = ref({
taskId: '',
nodeName: '',
})
//获取树数据
const treeRef = ref();
function gettreedata() {
treeloading.value = true
treeForm.value.taskId = projectId.value
getTsNodesTree(treeForm.value).then((res: any) => {
treedata.value = res.data
treeloading.value = false
pathid.value = treedata.value[0].nodeId
nextTick(() => {
treeRef.value?.setCurrentKey(pathid.value);
});
getdata()
})
}
const pathid = ref()
function handleNodeClick(data: any, node: any) {
pathid.value = data.nodeId
creatform.value.parentId = ''
patharr.value.length = 0
getdata()
}
//子项目配置
const frame = ref(false)
const title = ref()
const ruleFormRef = ref()
const projectForme: any = ref({
parentId: '',//所属项目id
taskId: "",//父节点id
// nodeType: "",//节点类型
nodeName: "",//节点名称
})
//用户弹窗规则定义
const moderules = ref({
nodeName: [{ required: true, message: "请输入节点名称", trigger: "blur" }],
});
//新增子项目
function addSubItem(row: any) {
frame.value = true
projectForme.value = {
parentId: '',//所属项目id
taskId: "",//父节点id
// nodeType: "",//节点类型
nodeName: "",//节点名称
}
projectForme.value.taskId = projectId.value
projectForme.value.parentId = row.nodeId
title.value = "添加子节点"
}
//修改子项目
function editSubItem(row: any) {
title.value = "修改子节点"
frame.value = true
if (row.subRegions) {
delete row.subRegions
}
if (row.createTime) {
delete row.createTime
}
projectForme.value = JSON.parse(JSON.stringify(row))
}
//表单确定
async function submitForm(formEl: any) {
if (!formEl) return
await formEl.validate((valid: any, fields: any) => {
if (valid) {
if (projectForme.value.nodeId) {
updateTsNodes(projectForme.value).then((res: any) => {
if (res.code == 0) {
gettreedata()
ElMessage.success("修改成功")
frame.value = false
}
})
} else {
addTsNodes(projectForme.value).then((res: any) => {
if (res.code == 0) {
gettreedata()
ElMessage.success("添加成功")
frame.value = false
}
})
}
}
})
}
//弹框关闭
function handleClose(formEl: any) {
// if (!formEl) return
// formEl.resetFields()
frame.value = false
}
//删除子节点
function delSubItem(row: any) {
ElMessageBox.confirm(
'您确定要删除该项目吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteTsNodesById({ id: row.nodeId }).then((res: any) => {
if (res.code == 0) {
gettreedata()
ElMessage({
type: 'success',
message: '删除成功',
})
}
})
})
}
//表格数据配置
const queryParams: any = ref({
current: 1,
size: 20,
fileName: '',
startDate: '',
endDate: '',
keywords: '',
nodeId: '',//节点ID
taskId: '',//项目Id
childNode: '1'
});
const dataarr = ref([])
//定义表格数据
const tableData: any = ref([]);
const total = ref(0);
// 表格加载
const loading = ref(false)
//获取表格数据
function getdata() {
loading.value = true
console.log(dataarr.value)
if (dataarr.value && dataarr.value.length > 0) {
queryParams.value.startDate = dataarr.value[0]
queryParams.value.endDate = dataarr.value[1]
} else {
queryParams.value.startDate = ''
queryParams.value.endDate = ''
}
queryParams.value.nodeId = pathid.value
queryParams.value.taskId = projectId.value
queryParams.value.id = creatform.value.parentId
tsFilesPage(queryParams.value).then((res: any) => {
queryParams.value.current = res.data.current
queryParams.value.size = res.data.size
total.value = res.data.total
loading.value = false
tableData.value = res.data.records
})
}
//新增文件对象
const fileObj: any = ref({
taskId: '', //所属项目ID
nodeId: '', //节点ID
fileName: '', //文件名称
filePath: '', //文件对象存储路径
keywords: '', //关键字
description: '', //文件描述
fileSize: '', //M
})
//上传组件
const upfile = ref(false)
function openFile() {
title.value = "上传文件"
localStorage.setItem('filepath', creatform.value.workPath ? creatform.value.workPath : '/');
localStorage.setItem('storageKey', JSON.stringify(['local']));
upfile.value = true
fileObj.value = {
taskId: '', //所属项目ID
nodeId: '', //节点ID
fileName: '', //文件名称
filePath: '', //文件对象存储路径
keywords: '', //关键字
description: '', //文件描述
fileSize: '', //M
}
judge.value = true
}
//修改文件
const judge = ref(false)
function editfile(row: any, item: any) {
if (item) {
title.value = "修改文件"
} else {
title.value = "重命名"
}
upfile.value = true
fileObj.value = JSON.parse(JSON.stringify(row))
judge.value = item
}
function fileClose() {
upfile.value = false
let fileArr = JSON.parse(localStorage.getItem('fileArr'))
fileArr.forEach((item: any) => {
delfileOne(item)
})
closeDialog()
}
//删除文件
function delfileOne(row: any) {
const parmas = {
deleteItems: [
{
name: row.name,
password: "",
path: creatform.value.workPath ? creatform.value.workPath : '/',
type: "FILE"
}
],
storageKey: "minio"
}
batchDeleteReq(JSON.stringify(parmas)).then((res) => {
})
}
//字节转mb
function bytesToMB(bytes: any) {
return bytes / Math.pow(1024, 2);
}
//上传确定
function submitfile() {
// console.log( )
if (fileObj.value.id) {
updateTsFiles(fileObj.value).then((res: any) => {
if (res.code == 0) {
closeDialog()
ElMessage.success('修改成功')
getdata()
upfile.value = false
}
})
} else {
let fileArr: any
if (localStorage.getItem('fileArr')) {
fileArr = JSON.parse(localStorage.getItem('fileArr'))
} else {
ElMessage.warning('请先选择文件')
return
}
let fileName = []
let fileSize = []
if (fileArr.length > 0) {
const uniqueArr = fileArr.filter((item: any, index: any) =>
fileArr.findIndex((i: any) => i.name === item.name) === index
);
uniqueArr.forEach((item: any) => {
fileName.push(item.name)
fileSize.push(bytesToMB(item.size))
})
}
fileObj.value.taskId = projectId.value
fileObj.value.nodeId = pathid.value
fileObj.value.workPath = creatform.value.workPath ? creatform.value.workPath : '/'
fileObj.value.fileName = fileName.join(',')
fileObj.value.fileSize = fileSize.join(',')
fileObj.value.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
fileObj.value.isFile = 'FILE'
addTsFiles(fileObj.value).then((res: any) => {
if (res.code == 0) {
closeDialog()
ElMessage.success('增加成功')
getdata()
upfile.value = false
localStorage.setItem('fileArr', '');
}
})
}
}
// 如果有上传完成的文件,关闭对话框时调用 close 方法刷新文件列表
const emit = defineEmits([])
const closeDialog = () => {
let deleteCount = clearALlFinishedUploadFile();
if (deleteCount > 0) {
emit('close');
}
}
//单个删除文件
function delfile(row: any) {
ElMessageBox.confirm(
'您确定要删除该文件吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteTsFilesById({ id: row.id }).then((res: any) => {
if (res.code == 0) {
getdata()
ElMessage({
type: 'success',
message: '删除成功',
})
}
})
})
}
//多个删除文件
//表格多选
const tableIdarr = ref([])
function handleSelectionChange(val: any) {
tableIdarr.value = val
}
//多选删除
function delprojectArr() {
const ids = []
tableIdarr.value.forEach((item: any) => {
ids.push(item.id)
})
ElMessageBox.confirm(
'您确定要删除这些项目吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteTsFilesByIds({ ids: ids.join(',') }).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '删除成功',
})
getdata()
}
})
})
}
//下载
function xiafile(row: any) {
ElMessageBox.confirm(
'您确定要下载该文件吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
window.open(row.url);
})
}
//多选下载
function xiafilemony() {
ElMessageBox.confirm(
'您确定要下载这些项目吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
tableIdarr.value.forEach((item: any) => {
if (item.url) {
downloadFileUseIframeMode(item.url);
}
})
})
}
/**
* 使用 iframe 模式下载文件
*
* @param url 下载文件 url
*/
const downloadFileUseIframeMode = (url: any) => {
const iframe: any = document.createElement("iframe");
iframe.style.display = "none"; // 防止影响页面
iframe.style.height = 0; // 防止影响页面
iframe.src = url;
document.body.appendChild(iframe);
setTimeout(() => {
iframe.remove();
}, 5 * 60 * 1000);
}
const jiezip: any = ref({})
function decompression(row: any) {
jiezip.value = row
zipzheng.value = false
title.value = '解压'
zipfiles.value = true
zipObj.value.compressedName = removeSuffix(row.fileName)
zipParentid.value = row.parentId
filetsobj.value.path = row.workPath
zipObj.value.compressedPath = row.workPath
zipType()
gettsfiles()
// ElMessageBox.confirm(
// '您确定要解压该文件吗?',
// '警告',
// {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning',
// }
// )
// .then(() => {
//
// )
// })
}
// markdown viewer 组件懒加载, 节约首屏打开时间
const VMdPreview = defineAsyncComponent({
loader: () => {
return new Promise((resolve, reject) => {
; (async function () {
try {
const res = await import('@kangc/v-md-editor/lib/preview')
import('@kangc/v-md-editor/lib/style/preview.css');
import('@kangc/v-md-editor/lib/theme/style/github.css');
const hljs = await import('highlight.js');
const githubTheme = await import('@kangc/v-md-editor/lib/theme/github.js');
res.use(githubTheme, {
Hljs: hljs,
});
resolve(res)
} catch (error) {
reject(error)
}
})()
})
},
loadingComponent: MarkdownViewerAsyncLoading
})
// 文件预览相关, 视频、音频、文本、图片
const VideoPlayer = defineAsyncComponent({
loader: () => import("@/components/file/preview/VideoPlayer.vue"),
loadingComponent: VideoPlayerAsyncLoading
})
const TextViewer = defineAsyncComponent({
loader: () => import("@/components/file/preview/TextViewer.vue"),
loadingComponent: TextViewerAsyncLoading
})
const MarkdownViewer = defineAsyncComponent({
loader: () => import("@/components/file/preview/MarkdownViewer.vue"),
loadingComponent: MarkdownViewerDialogAsyncLoading
})
const PdfViewer = defineAsyncComponent({
loader: () => import("@/components/file/preview/PdfViewer.vue"),
loadingComponent: MarkdownViewerDialogAsyncLoading
})
const OfficeViewer = defineAsyncComponent({
loader: () => import("@/components/file/preview/OfficeViewer.vue"),
loadingComponent: MarkdownViewerDialogAsyncLoading
})
const Three3dPreview = defineAsyncComponent({
loader: () => import("@/components/file/preview/Three3dPreview.vue"),
loadingComponent: MarkdownViewerDialogAsyncLoading
})
// const AudioPlayer = defineAsyncComponent({
// loader: () => import("@/components/file/preview/AudioPlayer.vue"),
// loadingComponent: MarkdownViewerDialogAsyncLoading
// })
const FileGallery = defineAsyncComponent(() => import("@/components/file/preview/FileGallery.vue"))
//单击预览
const filePreview: any = ref({})
const ViewfileUrl = ref("")
const title1 = ref('')
const isViewfile = ref(false)
const fileType = ref('')
function openPreview(row: any) {
if (getFileExtension(row.fileName) == 'pdf' || getFileExtension(row.fileName) == 'xlsx' || getFileExtension(row.fileName) == 'docx' || getFileExtension(row.fileName) == 'doc' || getFileExtension(row.fileName) == 'bin') {
title1.value = row.fileName
ViewfileUrl.value = row.url
isViewfile.value = true
fileType.value = getFileExtension(row.fileName)
} else {
row.fileType = getFileType(row.fileName)
filePreview.value = row
localStorage.setItem('videorow', JSON.stringify(row));
openRow(row)
}
}
function getFileExtension(filename: any) {
// 获取点号在文件名中的位置(从后往前查找)
const lastIndex = filename.lastIndexOf('.');
// 如果点号存在且不是文件名的第一个字符,则返回后缀名
if (lastIndex !== -1 && lastIndex !== 0) {
return filename.substring(lastIndex + 1);
} else {
// 如果没有找到点号,则返回空字符串或根据需要返回其他值
return '';
}
}
function CloseView() {
isViewfile.value = false
}
// 文件分类
const fileTypeMap = {
image: ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp', 'ico'],
video: ['mp4', 'webm', 'm3u8', 'rmvb', 'avi', 'swf', '3gp', 'mkv', 'flv'],
audio: ['mp3', 'wav', 'wma', 'ogg', 'aac', 'flac', 'm4a'],
text: ['scss', 'sass', 'kt', 'gitignore', 'bat', 'properties', 'yml', 'css', 'js', 'md', 'xml', 'txt', 'py', 'go', 'html', 'less', 'php', 'rb', 'rust', 'script', 'java', 'sh', 'sql'],
executable: ['exe', 'dll', 'com', 'vbs'],
archive: ['7z', 'zip', 'rar', 'tar', 'gz'],
pdf: ['pdf'],
office: ['doc', 'docx', 'csv', 'xls', 'xlsx', "ppt", 'pptx'],
three3d: ['dae', 'fbx', 'gltf', 'glb', 'obj', 'ply', 'stl'],
document: ['txt', 'pages', 'epub', 'numbers', 'keynote']
};
function getFileType(name: any) {
let fileType: any;
for (let key in fileTypeMap) {
let suffix = getFileSuffix(name);
if (fileTypeMap[key].indexOf(suffix) !== -1) {
fileType = key;
break;
}
}
return fileType;
}
function getFileSuffix(name: any) {
let lastIndex = name.lastIndexOf('.');
if (lastIndex === -1) {
return 'other';
}
return name.substring(lastIndex + 1).toLowerCase();
}
function openNode(row: any) {
loading.value = true
creatform.value.parentId = row.id
creatform.value.workPath = row.workPath + row.fileName + '/'
patharr.value.push({ fileName: row.fileName, id: row.id })
getdata()
}
//差异性对比
const difference = ref(false)
const minioselect = ref()
const loacalselect = ref()
const radio1 = ref()
const diffloding = ref(false)
const diffdata: any = ref({})
function opendifference(row: any) {
diffloding.value = true
compare({ localPath: creatform.value.workPath ? creatform.value.workPath : '/', minioPath: creatform.value.workPath ? creatform.value.workPath : '/' }).then((res: any) => {
if (res.code == 0) {
diffdata.value = res.data
diffloding.value = false
difference.value = true
}
})
minioselect.value = ''
loacalselect.value = ''
radio1.value = ''
}
function differenceClose() {
difference.value = false
}
function diffSureLocal() {
const namess = []
const paths = []
const sizes = []
console.log(diffdata.value.localOnlyFiles.length)
if (diffdata.value.localOnlyFiles.length == 0) {
ElMessage.warning('暂无内容,请重试')
return
}
diffdata.value.localOnlyFiles.forEach((item: any) => {
namess.push(item.name)
paths.push(item.path)
sizes.push(item.size)
})
uploadToBackup({ paths: paths.join(','), names: namess.join(','), sizes: sizes.join(',') }).then((res: any) => {
console.log(res)
if (res.code == 0) {
ElMessage.success('上传成功')
}
})
}
function diffSureMinio() {
const namess = []
const paths = []
const sizes = []
if (diffdata.value.minioOnlyFiles.length == 0) {
ElMessage.warning('暂无内容,请重试')
return
}
diffdata.value.minioOnlyFiles.forEach((item: any) => {
namess.push(item.name)
paths.push(item.path)
sizes.push(item.size)
})
downloadToLocal({ paths: paths.join(','), names: namess.join(','), sizes: sizes.join(',') }).then((res: any) => {
console.log(res)
if (res.code == 0) {
ElMessage.success('备份成功')
}
})
}
function diffSureOne() {
// 覆盖 备份空间中的文件
const namess = []
const paths = []
const sizes = []
if (diffdata.value.md5MismatchedFiles.length == 0) {
ElMessage.warning('暂无内容,请重试')
return
}
diffdata.value.md5MismatchedFiles.forEach((item: any) => {
namess.push(item.name)
paths.push(item.path)
sizes.push(item.size)
})
uploadToBackup({ paths: paths.join(','), names: namess.join(','), sizes: sizes.join(',') }).then((res: any) => {
console.log(res)
if (res.code == 0) {
ElMessage.success('备份成功')
}
})
}
function diffSureTwo() {
// 覆盖工作空间中的文件
const namess = []
const paths = []
const sizes = []
if (diffdata.value.md5MismatchedFiles.length == 0) {
ElMessage.warning('暂无内容,请重试')
return
}
diffdata.value.md5MismatchedFiles.forEach((item: any) => {
namess.push(item.name)
paths.push(item.path)
sizes.push(item.size)
})
downloadToLocal({ paths: paths.join(','), names: namess.join(','), sizes: sizes.join(',') }).then((res: any) => {
console.log(res)
if (res.code == 0) {
ElMessage.success('备份成功')
}
})
}
// 复制,移动,粘贴
const pasteing = ref(false)
const copyarr = ref([])
const copytable = ref([])
const copyjudge = ref(false)
const copytype = ref('')
function copyMove(type: any) {
pasteing.value = true
copyarr.value = JSON.parse(JSON.stringify(tableIdarr.value))
copytype.value = type //copy move
// tableIdarr.value
}
function paste() {
debugger
let norepeat = []
let repeatObj: any = {
newPath: '',
oldpaths: '',
parentId: '',
newFileName: [],
rename: '',
type: '',
}
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
repeatObj.type = '0'
copytable.value.length = 0
if (tableData.value.length > 0) {
tableData.value.forEach((item: any) => {
copyarr.value.forEach((items: any) => {
if (items.fileName == item.fileName) {
copytable.value.push(items)
copyjudge.value = true
}
})
})
} else {
//直接走覆盖方法
copyarr.value.forEach((items: any) => {
repeatObj.oldpaths = items.workPath
repeatObj.newFileName.push(items.fileName)
})
repeatObj.newFileName = repeatObj.newFileName.join(',')
if (copytype.value == 'move') {
moveFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('移动成功')
getdata()
pasteing.value = false
copyarr.value.length = 0
}
})
} else {
copyFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('复制成功')
getdata()
pasteing.value = false
copyarr.value.length = 0
}
})
}
}
if (!containsAll(tableData.value, copyarr.value)) {
//直接走覆盖方法
// 2. 更高效的Set方式推荐
const arr2Ids = new Set(copytable.value.map(item => item.id));
norepeat = copyarr.value.filter(item => !arr2Ids.has(item.id));
norepeat.forEach((items: any) => {
repeatObj.oldpaths = items.workPath
repeatObj.newFileName.push(items.fileName)
})
repeatObj.newFileName = repeatObj.newFileName.join(',')
if (copytype.value == "move") {
moveFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
// ElMessage.success('未重复文件移动成功')
getdata()
pasteing.value = false
copyarr.value.length = 0
}
})
} else {
copyFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
// ElMessage.success('未重复文件复制成功')
getdata()
pasteing.value = false
copyarr.value.length = 0
}
})
}
}
}
function containsAll(array1: any, array2: any) {
debugger
// 创建一个 Set 来存储 array1 中所有对象的 name 属性
const namesInArray1 = new Set(array1.map(item => item.fileName));
// 遍历 array2检查每个元素的 name 是否在 Set 中存在
for (const item of array2) {
if (!namesInArray1.has(item.fileName)) {
return false; // 如果 array2 中的元素的 name 不在 array1 的 name Set 中,返回 false
}
}
return true; // 如果 array2 中的所有元素的 name 都在 array1 的 name Set 中,返回 true
}
function removeItemsFromArray1(array1: any, array2: any, key: any) {
// 创建一个 Set 来存储 array2 中所有元素的 key 值
const keysToRemove = new Set(array2.map(item => item[key]));
// 使用 filter 方法保留 array1 中不在 keysToRemove 中的元素
return array1.filter(item => !keysToRemove.has(item[key]));
}
function copycover(row: any) {
ElMessageBox.confirm(
'您确定要覆盖该文件吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
let repeatObj: any = {
newPath: '',
oldpaths: '',
parentId: '',
newFileName: [],
rename: '',
type: '',
}
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
repeatObj.type = '0'
repeatObj.oldpaths = row.workPath
repeatObj.newFileName.push(row.fileName)
repeatObj.newFileName = repeatObj.newFileName.join(',')
if (copytype.value == "move") {
moveFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('移动成功')
getdata()
pasteing.value = false
copytable.value = removeItemsFromArray1(copytable.value, [row], 'id')
}
})
} else {
copyFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('复制成功')
getdata()
pasteing.value = false
copytable.value = removeItemsFromArray1(copytable.value, [row], 'id')
}
})
}
})
}
function copyClose() {
if (copytable.value.length > 0) {
ElMessageBox.confirm(
'退出后待操作文件将会被清空,您确定要退出吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
copyjudge.value = false
copyarr.value.length = 0
pasteing.value = false
getdata()
})
} else {
copyjudge.value = false
copyarr.value.length = 0
pasteing.value = false
getdata()
}
}
const copyhandArr = ref([])
function copyhand(row: any) {
copyhandArr.value = row
}
function copysomefile() {
ElMessageBox.confirm(
'您确定要覆盖这些文件吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
let repeatObj: any = {
newPath: '',
oldpaths: '',
parentId: '',
newFileName: [],
rename: '',
type: '',
}
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
repeatObj.type = '0'
copyhandArr.value.forEach((items: any) => {
repeatObj.oldpaths = items.workPath
repeatObj.newFileName.push(items.fileName)
})
repeatObj.newFileName = repeatObj.newFileName.join(',')
if (copytype.value == "move") {
moveFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('移动成功')
getdata()
pasteing.value = false
copytable.value = removeItemsFromArray1(copytable.value, copyhandArr.value, 'id')
}
})
} else {
copyFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('复制成功')
getdata()
pasteing.value = false
copytable.value = removeItemsFromArray1(copytable.value, copyhandArr.value, 'id')
}
})
}
})
}
//粘贴/复制重命名
const rename = ref(false)
const renameFormRef = ref()
const renameobj = ref({
fileName: ''
})
const renameRules = ref({
fileName: [{ required: true, message: "请输入文件名称", trigger: "blur" }],
});
const rowarr: any = ref()
function renames(row: any) {
rename.value = true
rowarr.value = row
}
function RenameClose() {
rename.value = false
}
async function submitrename(formEl: any) {
if (!formEl) return
await formEl.validate((valid: any, fields: any) => {
if (valid) {
//
let repeatObj: any = {
newPath: '',
oldpaths: '',
parentId: '',
newFileName: [],
rename: '',
type: '',
}
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
repeatObj.type = '1'
repeatObj.oldpaths = rowarr.value.workPath
repeatObj.rename = (renameobj.value.fileName)
repeatObj.newFileName.push(rowarr.value.fileName)
repeatObj.newFileName = repeatObj.newFileName.join(',')
if (copytype.value == "move") {
moveFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('移动成功')
getdata()
pasteing.value = false
copytable.value = removeItemsFromArray1(copytable.value, [rowarr.value], 'id')
rename.value = false
}
})
} else {
copyFileFolder(repeatObj).then((res: any) => {
if (res.code == 0) {
ElMessage.success('复制成功')
getdata()
pasteing.value = false
copytable.value = removeItemsFromArray1(copytable.value, [rowarr.value], 'id')
rename.value = false
}
})
}
}
})
}
//创建文件/文件夹
const creat = ref(false)
const creatFormRef = ref()
const creatObj = ref({
fileName: '',
isFile: 'FOLDER',
nodeId: '',//节点id
parentId: '',//父ID
taskId: '',//任务ID
workPath: '',//工作空间路径
})
const creatform = ref({
parentId: '',
workPath: ''
})
const creatrules = ref({
fileName: [{ required: true, message: "请输入文件/文件夹名称", trigger: "blur" }],
});
function creatFile() {
creat.value = true
creatObj.value.fileName = ''
creatObj.value.nodeId = 'FOLDER'
}
function creatClose() {
creat.value = false
}
async function submitcreat(formEl: any) {
if (!formEl) return
await formEl.validate((valid: any, fields: any) => {
if (valid) {
creatObj.value.nodeId = pathid.value
creatObj.value.taskId = projectId.value
if (creatform.value.parentId) {
creatObj.value.parentId = creatform.value.parentId
} else {
creatObj.value.parentId = '00'
}
if (creatform.value.workPath) {
creatObj.value.workPath = creatform.value.workPath
} else {
creatObj.value.workPath = '/'
}
addTsFile(creatObj.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success("创建成功")
getdata()
}
})
creat.value = false
}
})
}
//路径导航条
const patharr = ref([])
function pathclick(row: any, index: any) {
patharr.value.splice(index + 1)
creatform.value.parentId = row.id
creatform.value.workPath = convertArrayToPath(patharr.value)
getdata()
}
// 压缩文件
const zipfiles = ref(false)
const zipFormRef = ref()
const visible = ref(false)
const ziprules = ref({
ids: [{ required: true, message: "请选择文件", trigger: "blur" }],
compressedFormat: [{ required: true, message: "请选择压缩格式", trigger: "blur" }],
compressedName: [{ required: true, message: "请输入压缩文件名", trigger: "blur" }],
compressedPath: [{ required: true, message: "请输入压缩文件路径", trigger: "blur" }],
})
const ziptypearr = ref([])
const zipObj: any = ref({
ids: '',
compressedFormat: '',
compressedName: '',
compressedPath: '',
covered: '1'
})
const zipzheng = ref()
function zipFile(row: any) {
zipzheng.value = row
zipfiles.value = true
title.value = '压缩'
if (tableIdarr.value.length == 1) {
zipObj.value.compressedName = removeSuffix(tableIdarr.value[0].fileName)
} else {
zipObj.value.compressedName = generateRandomName()
}
zipParentid.value = tableIdarr.value[0].parentId
filetsobj.value.path = tableIdarr.value[0].workPath
zipObj.value.compressedPath = tableIdarr.value[0].workPath
zipType()
gettsfiles()
}
function zipType() {
list({ parentcode: 'compressType' }).then((res: any) => {
ziptypearr.value = res.data
zipObj.value.compressedFormat = res.data[0].dictname
})
}
//确定按钮
const zipParentid = ref()
async function submitzip(formEl: any) {
if (!formEl) return
await formEl.validate((valid: any, fields: any) => {
if (valid) {
if (zipzheng.value == true) {
let idsarr = []
tableIdarr.value.forEach((item: any) => {
idsarr.push(item.id)
})
zipObj.value.ids = idsarr.join(',')
zipObj.value.parentId = zipParentid.value
gettreedata()
getdata()
zipfiles.value = false
compress(zipObj.value).then((res: any) => {
if (res.code == 0) {
zipfiles.value = false
getdata()
ElMessage.success('压缩成功')
tableIdarr.value.length = 0
}
})
} else {
// loading.value = true
Decompression({ id: jiezip.value.id, parentId: jiezip.value.parentId, decompressionPath: jieFilearr.value.workPath }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('解压成功')
gettreedata()
getdata()
zipfiles.value = false
tableIdarr.value.length = 0
}
})
}
}
})
}
function zipClose() {
zipfiles.value = false
tableIdarr.value.length = 0
}
//查询文件夹
const listFilesarr = ref([])
const filetsobj = ref({
id: '',
path: '',
})
const multipleTableRef = ref()
const jieFilearr: any = ref({})
const jiepatharr: any = ref([])
function gettsfiles() {
listTsFiles(filetsobj.value).then((res: any) => {
listFilesarr.value = res.data
if (res.data[0]) {
jieFilearr.value = res.data[0]
jiepatharr.value = convertPathToArray(jieFilearr.value.workPath)
creatform.value.parentId = res.data[0].parentId
creatform.value.workPath = jieFilearr.value.workPath
}
})
}
function openfiles(row: any) {
filetsobj.value.path = row.workPath + row.fileName + '/'
jieFilearr.value.workPath = filetsobj.value.path
jiepatharr.value = convertPathToArray(jieFilearr.value.workPath)
creatform.value.workPath = jieFilearr.value.workPath
zipParentid.value = row.id
creatform.value.parentId = row.id
filetsobj.value.id = ''
gettsfiles()
}
function getdictname(dictarr: any, itemcode: any) {
let dictname = ''
dictarr.forEach((item: any) => {
if (item.itemcode == itemcode) {
dictname = item.dictname
}
})
return dictname
}
function fileSelection(row: any) {
if (row.length > 1) {
multipleTableRef.value!.toggleRowSelection(row[0], undefined, false)
row.shift()
}
jieFilearr.value = row[0]
}
function pathFile(index: any) {
jiepatharr.value.splice(index + 1)
filetsobj.value.path = convertArrayToPath(jiepatharr.value)
gettsfiles()
}
function pathqveding() {
zipObj.value.compressedPath = jieFilearr.value.workPath
creatform.value.parentId = ''
creatform.value.workPath = ''
visible.value = !visible.value
}
function pathqvxiao() {
creatform.value.parentId = ''
creatform.value.workPath = ''
visible.value = !visible.value
}
//随机生成名字
function generateRandomName() {
// 1. 确定数字数量0~2
const numCount = Math.floor(Math.random() * 3);
const positions = new Set();
// 2. 随机选取数字位置
while (positions.size < numCount) {
positions.add(Math.floor(Math.random() * 6));
}
// 3. 生成每个字符
let result = '';
for (let i = 0; i < 6; i++) {
if (positions.has(i)) {
// 生成数字
result += Math.floor(Math.random() * 10);
} else {
// 生成字母(大小写随机)
const charCode = Math.random() < 0.5
? 65 + Math.floor(Math.random() * 26) // 大写字母
: 97 + Math.floor(Math.random() * 26); // 小写字母
result += String.fromCharCode(charCode);
}
}
return result;
}
// 路径转换方法(支持多级路径和容错处理)
function convertPathToArray(fullPath: string): string[] {
// 1. 去除首尾斜杠
const trimmedPath = fullPath.replace(/^\/+|\/+$/g, '')
// 2. 拆分路径并过滤空值
return trimmedPath.split('/').filter(Boolean)
}
// 路径转换方法(数组转路径)
function convertArrayToPath(segments: string[]): string {
// 处理空数组返回根路径
if (segments.length === 0) return '/'
// 过滤空值并拼接路径
return '/' + segments.filter(Boolean).join('/') + '/'
}
function removeSuffix(filename: any) {
// 使用正则表达式匹配文件名中的后缀部分
// 这个正则表达式匹配从最后一个点开始到字符串末尾的所有字符
const suffixMatch = filename.match(/\.[^\.]+$/);
// 如果找到了后缀suffixMatch 不为 null则去掉它
if (suffixMatch) {
// 使用 slice 方法去掉后缀部分
// suffixMatch[0] 是匹配到的后缀(包括点),所以我们需要去掉它的长度
return filename.slice(0, -suffixMatch[0].length);
}
// 如果没有找到后缀,则返回原文件名
return filename;
}
</script>
<template>
<div class="faulttemplate-box">
<aside id="silderLeft">
<div>
<el-select v-model="projectId" placeholder="请选择项目" @change="gettreedata()">
<el-option v-for="item in projectArr" :key="item.id" :label="item.taskName" :value="item.id" />
</el-select>
<div class="tree_sou">
<el-input v-model="treeForm.nodeName" style="width:100%;margin:10px 9px 10px 0px;"
placeholder="节点名称" clearable :suffix-icon="Search" @change="gettreedata()" />
<img src="@/assets/images/addNew.png" style="cursor: pointer;" title="新增子项目"
@click="addSubItem({ nodeId: '00' })" alt="">
<!-- <el-input v-model="treeForm.nodeName" style="width:100%;margin:10px 9px 10px 0px;"
placeholder="节点名称" clearable />
<el-button type="primary" @click="gettreedata()">搜索</el-button>
<el-button type="primary" @click="addSubItem({ nodeId: '00' })">新增子项目</el-button> -->
</div>
<el-tree ref="treeRef" node-key="nodeId" :data="treedata" :highlight-current="true"
:props="defaultProps" v-loading="treeloading" @node-click="handleNodeClick"
class="silderLeft-default" style="height: calc(100vh - 280px); overflow: auto;margin-top: 10px;">
<template #default="{ data }">
<span class="custom-tree-node">
<span class="text">{{ data.nodeName }}</span>
<span class="img_tree">
<img src="@/assets/project/xiu.png" alt="" title="编辑" @click="editSubItem(data)">
<img src="@/assets/project/del.png" alt="" title="删除" @click="delSubItem(data)">
<img src="@/assets/images/chayi.png" alt="" title="差异性对比" @click="opendifference(data)">
<img src="@/assets/project/jia.png" alt="" title="添加子项目" @click="addSubItem(data)">
</span>
</span>
</template>
</el-tree>
</div>
<div class="moveBtn" v-move>
<div class="moveBtn-line"></div>
</div>
</aside>
<section class="silderRight">
<div class="path_click" style="display: flex;align-items: center;">
<div @click="pathclick({ id: '' }, -1)">数据管理:</div>
<div v-for="(item, index) in patharr" @click="pathclick(item, index)"><span v-if="index > 0">-</span>{{
item.fileName }}</div>
</div>
<div class="sou_title">
<div class="sou_title_left">
<el-input style="margin-right: 10px ;" v-model="queryParams.fileName" clearable @change="getdata()"
placeholder="文件名称"></el-input>
<el-input style="margin-right: 10px ;" v-model="queryParams.keywords" clearable @change="getdata()"
placeholder="关键字"></el-input>
<el-date-picker v-model="dataarr" type="daterange" @change="getdata()"
style="width: 150%;margin-right: 10px ;" start-placeholder="开始时间" end-placeholder="结束时间"
format="YYYY-MM-DD" value-format="YYYY-MM-DD" range-separator="至" />
<el-button type="primary" @click="getdata()">搜索</el-button>
<el-checkbox v-model="queryParams.childNode" true-label="0" false-label="1" label="含目录"
style="margin-left: 10px ;" @change="getdata()" />
</div>
<div>
<!-- :disabled="pathid.value" -->
<el-button type="primary" @click="creatFile">创建文件/文件夹</el-button>
<el-button type="primary" :disabled="!pathid" @click="openFile">上传</el-button>
<el-button type="primary" @click="delprojectArr()" :disabled="tableIdarr.length == 0">删除</el-button>
<el-button type="primary" @click="xiafilemony()" :disabled="tableIdarr.length == 0">下载</el-button>
</div>
</div>
<div style="margin-bottom: 10px;">
<el-button type="primary" v-if="pasteing" @click="paste()">粘贴({{ copyarr.length }})</el-button>
<el-button type="primary" :disabled="tableIdarr.length == 0" @click="copyMove('copy')">复制</el-button>
<el-button type="primary" :disabled="tableIdarr.length == 0" @click="copyMove('move')">移动</el-button>
<el-button type="primary" :disabled="tableIdarr.length == 0" @click="zipFile(true)">压缩</el-button>
</div>
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange"
:header-cell-style="{ background: 'rgb(250 250 250)', height: '50px' }"
style="width: 100%; height: calc(66vh);margin-bottom: 20px;" border>
<el-table-column type="selection" width="40" />
<!-- <el-table-column type="index" label="序号" width="70" align="center"></el-table-column> -->
<el-table-column prop="fileName" label="文件名称">
<template #default="scope">
<div class="tableweight" v-if="scope.row.isFile == 'FOLDER'">{{ scope.row.fileName }} <span
class="tableHover " @click="openNode(scope.row)">(点击进入文件夹)</span> </div>
<div v-else-if="scope.row.isFile == 'FILE'">{{ scope.row.fileName }} <span class="tableHover"
@click="openPreview(scope.row)">(点击预览)</span> </div>
</template>
</el-table-column>
<el-table-column prop="keywords" label="关键字"></el-table-column>
<el-table-column prop="workPath" label="路径"></el-table-column>
<el-table-column prop="fileName" label="预览" width="60px" align="center">
<template #default="scope">
<div style="display: flex;align-items: center;justify-content: center;">
<img v-if="getFileExtension(scope.row.fileName) == 'pdf' || getFileExtension(scope.row.fileName) == 'PDF'"
src="@/assets/fileimg/PDF.png" alt="" style="cursor: pointer;">
<img v-else-if="getFileExtension(scope.row.fileName) == 'mp4'"
src="@/assets/fileimg/mp4.png" alt="" style="cursor: pointer;">
<img v-else-if="scope.row.isFile == 'FOLDER'" src="@/assets/fileimg/wenjianjia.png" alt=""
style="cursor: pointer;">
<img v-else-if="getFileExtension(scope.row.fileName) == 'zip'"
src="@/assets/fileimg/zip.png" alt="" style="cursor: pointer;">
<img v-else-if="getFileExtension(scope.row.fileName) == 'mp3'"
src="@/assets/fileimg/mp3.png" alt="" style="cursor: pointer;">
<img v-else src="@/assets/fileimg/text_line.png" alt="" style="cursor: pointer;">
</div>
<!-- {{ getFileExtension(scope.row.fileName) }} -->
</template>
</el-table-column>
<el-table-column prop="uploader" width="80" label="上传人"></el-table-column>
<el-table-column prop="uploadTime" width="170" label="上传时间"></el-table-column>
<el-table-column fixed="right" label="操作" width="120" align="center">
<template #default="scope">
<span
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">
<img src="@/assets/project/chong.png" alt="" title="重命名" @click="editfile(scope.row, false)"
style="cursor: pointer;">
<img src="@/assets/MenuIcon/lbcz_xg.png" alt="" @click="editfile(scope.row, true)"
title="修改" style="cursor: pointer;">
<img v-if="scope.row.type == 'ZIP'" src="@/assets/images/jieyasuo.png" alt=""
@click="decompression(scope.row)" title="解压" style="cursor: pointer;">
<img src="@/assets/MenuIcon/xia1.png" alt="" @click="xiafile(scope.row)" title="下载"
style="cursor: pointer;">
<img src="@/assets/MenuIcon/lbcz_sc.png" alt="" @click="delfile(scope.row)" title="删除"
style="cursor: pointer;">
</span>
</template>
</el-table-column>
</el-table>
<Page :total="total" v-model:size="queryParams.size" v-model:current="queryParams.current"
@pagination="getdata()">
</Page>
</section>
<el-dialog :title="title" v-model="frame" width="30%" :before-close="handleClose" top="30px" draggable
destroy-on-close>
<el-form ref="ruleFormRef" style="max-width: 600px" :model="projectForme" :rules="moderules"
label-width="auto" class="demo-ruleForm" status-icon>
<el-form-item label="节点名称" prop="nodeName">
<el-input v-model="projectForme.nodeName" />
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button>
<el-button @click="handleClose(ruleFormRef)">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog :title="title" v-model="upfile" width="50%" :before-close="fileClose" top="30px" draggable
destroy-on-close>
<el-scrollbar :height="!fileObj.id ? '400px' : ''">
<el-form ref="ruleFormRef" style="max-width: 100%" :model="fileObj" :rules="moderules"
label-width="auto" class="demo-ruleForm" status-icon>
<el-form-item v-if="!fileObj.id" label="文件:" prop="taskCode">
<!-- <el-button @click="openUploadDialog" type="primary">上传文件</el-button>
<el-button @click="openUploadFolderDialog" type="primary">上传文件夹</el-button> -->
<ZUpload />
</el-form-item>
<el-form-item v-else label="文件名称:">
<el-input v-model="fileObj.fileName" />
</el-form-item>
<el-form-item v-if="judge" label="关键字:" prop="taskName">
<el-input v-model="fileObj.keywords" />
</el-form-item>
<el-form-item v-if="judge" label="描述:">
<el-input v-model="fileObj.description" :rows="2" type="textarea" />
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitfile">确定</el-button>
<el-button @click="fileClose">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-scrollbar>
</el-dialog>
<el-dialog title="创建文件/文件夹" v-model="creat" width="30%" :before-close="creatClose" top="30px" draggable
destroy-on-close>
<el-form ref="creatFormRef" style="max-width: 100%" :model="creatObj" :rules="creatrules" label-width="auto"
class="demo-ruleForm" status-icon>
<el-form-item label="文件/文件夹名称:" prop="fileName">
<el-input v-model="creatObj.fileName" />
</el-form-item>
<el-form-item label="类型:">
<el-radio-group v-model="creatObj.isFile">
<el-radio :value="'FILE'">文件</el-radio>
<el-radio :value="'FOLDER'">文件夹</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitcreat(creatFormRef)">确定</el-button>
<el-button @click="creatClose()">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<!-- 复制粘贴弹框 -->
<el-dialog title="重命名或覆盖" v-model="copyjudge" width="60%" :before-close="copyClose" top="30px" draggable
destroy-on-close>
<div style="display: flex;justify-content: end;"><el-button :disabled="copyhandArr.length == 0"
type="primary" style="margin-bottom: 20px;" @click="copysomefile">覆盖({{ copyhandArr.length
}})</el-button>
</div>
<el-table v-loading="loading" :data="copytable" @selection-change="copyhand"
:header-cell-style="{ background: 'rgb(250 250 250)', height: '50px' }"
style="width: 100%; height: calc(100vh - 275px);margin-bottom: 20px;" border>
<el-table-column type="selection" width="40" />
<!-- <el-table-column type="index" label="序号" width="70" align="center"></el-table-column> -->
<el-table-column prop="fileName" label="文件名称"></el-table-column>
<el-table-column prop="workPath" label="路径"></el-table-column>
<el-table-column fixed="right" label="操作" width="80" align="center">
<template #default="scope">
<span
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">
<img src="@/assets/project/chong.png" alt="" title="重命名" @click="renames(scope.row)"
style="cursor: pointer;">
<img src="@/assets/project/gai.png" alt="" @click="copycover(scope.row)" title="覆盖"
style="cursor: pointer;">
</span>
</template>
</el-table-column>
</el-table>
</el-dialog>
<el-dialog title="重命名" v-model="rename" width="30%" :before-close="RenameClose" top="30px" draggable
destroy-on-close>
<el-form ref="renameFormRef" style="max-width: 100%" :model="renameobj" :rules="renameRules"
label-width="auto" class="demo-ruleForm" status-icon>
<el-form-item label="文件名称:" prop="fileName">
<el-input v-model="renameobj.fileName" />
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitrename(renameFormRef)">确定</el-button>
<el-button @click="RenameClose">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog :title="title" v-model="zipfiles" width="30%" :before-close="zipClose" top="30px" draggable
destroy-on-close>
<el-form ref="zipFormRef" style="max-width: 100%" :model="zipObj" :rules="ziprules" label-width="auto"
class="demo-ruleForm" status-icon>
<el-form-item v-if="zipzheng" label="压缩格式:" prop="compressedFormat">
<el-select v-model="zipObj.compressedFormat">
<el-option v-for="item in ziptypearr" :key="item.itemcode" :label="item.dictname"
:value="item.dictname" />
</el-select>
</el-form-item>
<el-form-item label="名称:" prop="compressedName">
<el-input v-if="zipzheng" v-model="zipObj.compressedName">
<template #append>.{{ zipObj.compressedFormat }}</template>
</el-input>
<el-input v-else v-model="zipObj.compressedName" disabled></el-input>
</el-form-item>
<el-form-item label="压缩路径:" prop="compressedPath">
<el-input v-model="zipObj.compressedPath">
<template #prepend>
<el-popover :visible="visible" placement="right" :width="400" trigger="click">
<template #reference>
<el-icon style="cursor: pointer;" @click="visible = !visible">
<Folder />
</el-icon>
</template>
<div class="pover_title">文件列表</div>
<div class="path_click" style="display: flex;align-items: center;">
<div @click="pathFile(-1)">数据管理:</div>
<div v-for="(item, index) in jiepatharr" @click="pathFile(index)">
<span v-if="index > 0">-</span> {{ item }}
</div>
</div>
<div>
<el-button type="primary" @click="creatFile">创建文件/文件夹</el-button>
</div>
<div>
<el-table v-loading="loading" :data="listFilesarr" ref="multipleTableRef"
@selection-change="fileSelection" :header-cell-style="{ display: 'none' }"
style="width: 100%; height: calc(50vh);margin-bottom: 20px;" border>
<!-- <el-table-column type="selection" width="40" /> -->
<el-table-column prop="fileName" label="文件名称">
<template #default="scope">
<div class="tableweight tableHover" v-if="scope.row.isFile == 'FOLDER'"
@click="openfiles(scope.row)">
{{ scope.row.fileName }}
<!-- <span >(点击进入文件夹)</span> -->
</div>
</template>
</el-table-column>
</el-table>
</div>
<div v-if="jieFilearr">当前选中:{{ jieFilearr.workPath }}</div>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="pathqveding">确定</el-button>
<el-button @click="pathqvxiao">取消</el-button>
</div>
</el-popover>
</template>
</el-input>
</el-form-item>
<el-form-item label="" prop="covered">
<el-checkbox true-value="0" false-value="1" v-model="zipObj.covered" label="覆盖已存在文件"
style="margin-left: 82px;" />
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitzip(zipFormRef)">确定</el-button>
<el-button @click="zipClose">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<!-- 差异性对比 -->
<el-dialog title="差异性对比" v-model="difference" width="60%" :before-close="differenceClose" top="30px" draggable
destroy-on-close>
<div class="chabox" v-loading="diffloding">
<div class="chabox_border">
<div class="chabox_border_top">差异性检查结果</div>
<div class="chabox_border_top">备份策略确认</div>
</div>
<div class="chabox_border">
<div class="chabox_border_bottom">
<el-scrollbar height="150px">
<div style="font-size: 16px;">备份空间缺失的文件:</div>
<div v-for="item in diffdata.localOnlyFiles">{{ item.name + '(' + item.path + ')' }}</div>
<!-- {{ diffdata.minioOnlyFiles }} -->
</el-scrollbar>
</div>
<div class="chabox_border_bottom_select">
<!-- <el-checkbox v-model="minioselect" label="将文件从 工作空间 上传到 备份空间" /> -->
<el-button type="primary" @click="diffSureLocal">将文件从 工作空间 上传到 备份空间</el-button>
</div>
</div>
<div class="chabox_border">
<div class="chabox_border_bottom">
<el-scrollbar height="150px">
<div style="font-size: 16px;">工作空间缺失的文件:</div>
<div v-for="item in diffdata.minioOnlyFiles">{{ item.name + '(' + item.path + ')' }}</div>
</el-scrollbar>
</div>
<div class="chabox_border_bottom_select">
<!-- <el-checkbox v-model="loacalselect" label="将文件从 备份空间 下载到 工作空间" /> -->
<el-button type="primary" @click="diffSureMinio">将文件从 备份空间 下载到 工作空间</el-button>
</div>
</div>
<div class="chabox_border">
<div class="chabox_border_bottom">
<el-scrollbar height="150px">
<div v-if="diffdata.md5MismatchedFiles.length > 0"
v-for="item in diffdata.md5MismatchedFiles">
<div style="font-size: 16px;">MD5哈希值不一致的文件{{ item.name + '(' + item.path + ')' }}</div>
<div style="font-size: 16px;">本地 MD5{{ item.locatMd5 }}</div>
<div style="font-size: 16px;">minio MD5{{ item.minioMd5 }}</div>
</div>
<div v-else>
<div style="font-size: 16px;">MD5哈希值不一致的文件</div>
<div style="font-size: 16px;">本地 MD5</div>
<div style="font-size: 16px;">minio MD5</div>
</div>
</el-scrollbar>
</div>
<div class="chabox_border_bottom_select">
<!-- <el-radio-group v-model="radio1">
<el-radio value="1" size="large">覆盖 备份空间中的文件</el-radio>
<div></div>
<el-radio value="2" size="large">覆盖工作空间中的文件</el-radio>
</el-radio-group> -->
<div>
<el-button type="primary" @click="diffSureOne">覆盖 备份空间中的文件</el-button>
<div style="margin-top: 10px;"></div>
<el-button type="primary" @click="diffSureTwo">覆盖 工作空间中的文件</el-button>
</div>
</div>
</div>
</div>
</el-dialog>
<!-- 组件预览 -->
<!-- 视频播放器 -->
<el-dialog draggable class="zfile-video-dialog" :destroy-on-close="true" v-model="dialogVideoVisible">
<video-player v-if="dialogVideoVisible" ref="videoPlayer" />
</el-dialog>
<!-- 文本编辑器 -->
<el-dialog draggable class="zfile-text-dialog zfile-dialog-mini-close" :destroy-on-close="true"
:title="filePreview.fileName" v-model="dialogTextVisible">
<TextViewer :file-name="filePreview.fileName" :file-url="filePreview.url"
v-if="dialogTextVisible && filePreview.fileName.indexOf('.md') === -1" />
<MarkdownViewer :file-name="filePreview.fileName" :file-url="filePreview.url"
v-if="dialogTextVisible && filePreview.fileName.indexOf('.md') !== -1" />
</el-dialog>
<!-- pdf 在线预览 -->
<el-dialog draggable class="zfile-pdf-dialog" :title="filePreview.fileName" v-model="dialogPdfVisible">
<PdfViewer :file-name="filePreview.fileName" :file-url="filePreview.url" v-if="dialogPdfVisible" />
</el-dialog>
<!-- office 在线预览 -->
<el-dialog draggable class="zfile-office-dialog zfile-dialog-mini-close zfile-dialog-hidden-title"
:title="filePreview.fileName" v-model="dialogOfficeVisible">
<OfficeViewer :file-name="filePreview.fileName" :file-url="filePreview.url" v-if="dialogOfficeVisible" />
</el-dialog>
<!-- 3d 在线预览 -->
<el-dialog draggable class="zfile-3d-dialog" :title="filePreview.fileName" v-model="dialog3dVisible">
<Three3dPreview :file-name="filePreview.fileName" :file-url="filePreview.url" v-if="dialog3dVisible" />
</el-dialog>
<!-- 音频播放器 -->
<AudioPlayer></AudioPlayer>
<Viewfile v-if="isViewfile" :showTime="true" :title="title1" :url="ViewfileUrl" :type="fileType"
@update="CloseView" />
<!-- <audio-player></audio-player> -->
</div>
</template>
<style scoped lang="scss">
.faulttemplate-box {
height: 100%;
display: flex;
display: -webkit-flex;
background-color: #f2f4f9;
}
#silderLeft {
width: 300px;
padding: 10px;
box-sizing: border-box;
background: #fff;
border-radius: 3px;
position: relative;
.tree_sou {
display: flex;
align-items: center;
justify-content: space-between;
}
&:hover {
.moveBtn {
opacity: 1;
}
}
}
/* 拖动条 */
.moveBtn {
height: 100%;
width: 15px;
padding: 0 6px;
opacity: 0;
position: absolute;
right: -15px;
top: 0;
}
.moveBtn-line {
width: 100%;
height: 100%;
cursor: col-resize;
user-select: none;
background-color: #60bfff;
}
.silderRight {
flex: 1;
width: 100%;
height: calc(100vh - 130px);
overflow: auto;
background-color: rgba(255, 255, 255, 1);
border-radius: 3px;
padding: 15px;
padding-bottom: 0px;
box-sizing: border-box;
margin-left: 15px;
.sou_title {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.sou_title_left {
width: 65%;
display: flex;
align-items: center;
justify-content: space-between;
}
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding: 8px;
.img_tree {
display: flex;
width: 28%;
align-items: center;
justify-content: space-between;
img {
cursor: pointer;
}
}
}
.tableHover {
cursor: pointer;
}
.tableHover:hover {
color: #409eff;
}
.tableweight {
font-size: 16px;
background: #dbf500;
}
//差异性对比
.chabox {
width: 80%;
// height: 500px;
border-top: 2px solid #ccc;
border-left: 2px solid #ccc;
margin: auto;
.chabox_border {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.chabox_border_top {
width: 50%;
height: 50px;
border-bottom: 2px solid #ccc;
border-right: 2px solid #ccc;
text-align: center;
line-height: 50px;
background-color: #fafafa;
color: #909399;
}
.chabox_border_bottom {
width: 50%;
height: 150px;
border-bottom: 2px solid #ccc;
border-right: 2px solid #ccc;
text-align: left;
}
.chabox_border_bottom_select {
width: 50%;
height: 150px;
border-bottom: 2px solid #ccc;
border-right: 2px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding-left: 15px;
}
}
}
:deep() {
.el-radio-group {
display: block !important;
}
}
//文字换行处理
.text {
overflow-wrap: break-word;
word-break: break-all;
white-space: normal;
// line-height: 1.5;
max-width: 72%;
// border: 1px solid #000;
// padding: 10px;
}
:deep() {
.el-tree-node__content {
height: auto !important;
line-height: 20px !important;
// padding-left: 10px !important;
}
.el-tree-node__content>.el-tree-node__expand-icon {
padding: 0px !important;
}
}
.path_click {
display: flex;
align-items: center;
div {
cursor: pointer;
}
div:hover {
color: #409eff;
cursor: pointer;
}
}
.pover_title {
line-height: 1;
margin-bottom: 12px;
color: #303133;
font-size: 16px;
}
</style>