文件加全屏

This commit is contained in:
wangxk 2025-03-07 10:43:38 +08:00
parent e09b4077d9
commit 814efa8abd
13 changed files with 993 additions and 225 deletions

View File

@ -7,8 +7,6 @@
<meta name="description" content="" />
<meta name="keywords" content="" />
<script type="text/javascript" type="module" src="./webconfig.js"></script>
<script src="/lib/pptxjs/pptxjs.js"></script>
<link rel="stylesheet" href="/lib/pptxjs/pptxjs.css">
<title>文档与数据管理系统</title>
</head>
<body>

View File

@ -47,6 +47,7 @@
"path-browserify": "^1.0.1",
"path-to-regexp": "^6.2.0",
"pinia": "^2.0.12",
"pptxgenjs": "^3.12.0",
"screenfull": "^6.0.0",
"sortablejs": "^1.14.0",
"tinymce": "^7.0.0",

View File

@ -0,0 +1,41 @@
import request from '@/utils/request';
//查询本地和备份空间结构树
export function listLocalAndBackup(params:any) {
return request({
url: '/experimentalData/ts-files/listLocalAndBackup',
method: 'post',
params:params,
});
}
//对比两个目录的文件差异
export function compare(params:any) {
return request({
url: '/experimentalData/ts-files/compare',
method: 'post',
params:params,
});
}
//将文件上传到备份空间
export function uploadToBackup(params:any) {
return request({
url: '/experimentalData/ts-files/uploadToBackup',
method: 'post',
data:params,
});
}
//从备份空间下载到工作空间
export function downloadToLocal(params:any) {
return request({
url: '/experimentalData/ts-files/downloadToLocal',
method: 'post',
data:params,
});
}
//根据ID删除试验数据管理文档内容
export function deleteTsFilesById(params:any) {
return request({
url: '/experimentalData/ts-files/deleteTsFilesById',
method: 'post',
params:params,
});
}

View File

@ -1,4 +1,4 @@
import {ElMessage} from "element-plus";
import {ElMessage,ElMessageBox} from "element-plus";
// import { ref,reactive,useTitle,computed } from 'vue';
import { ref,reactive,computed} from "vue";
import MessageBox from "@/components/file/messageBox/messageBox";
@ -184,10 +184,7 @@ export default function useFileData() {
case 'image': openImage(row); break;
case 'text': openText(); break;
case 'audio': openAudio(row); break;
case 'office': openOffice(row); break;
case 'pdf': openPdf(row); break;
case 'three3d': open3d(row); break;
default: batchDownloadFile(row);
default: tishi(row);
}
// clearSelection();
@ -205,6 +202,20 @@ export default function useFileData() {
}
}
}
function tishi(row){
ElMessageBox.confirm(
'此项目暂时无法预览,您是否要下载?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
window.open(row.url);
})
}
// ------------- loading start ------------

View File

@ -1,5 +1,13 @@
<template>
<div class="editor" id="zfile-monaco-editor"/>
<div class="editor-container" :class="{ 'fullscreen-editor': fullscreen }">
<div class="editor-controls">
<el-button circle @click="toggleFullscreen" class="fullscreen-btn">
<img v-if="!fullscreen" src="@/assets/images/qvan.png" alt="全屏">
<img v-else src="@/assets/images/tuiqvan.png" alt="退出全屏">
</el-button>
</div>
<div class="editor" id="zfile-monaco-editor"/>
</div>
</template>
<script setup>
@ -70,6 +78,7 @@ import { getFileTextReq, getFileTextFromServerReq } from "@/api/common";
//
onMounted(() => {
// window.addEventListener('keydown', handleKeydown)
let fileUrl = props.fileUrl;
getFileTextReq(fileUrl).then((res) => {
fileContent.value = res.data;
@ -91,6 +100,7 @@ onUnmounted(() => {
monaco.editor.getModels().forEach((item) => {
item.dispose();
})
// window.removeEventListener('keydown', handleKeydown)
})
import useCommon from "@/components/file/useCommon";
@ -122,6 +132,25 @@ let initMonaco = () => {
lineNumbers: isNotMobile.value ? 'on' : 'off'
});
};
//
const fullscreen = ref(false)
//
const toggleFullscreen = () => {
fullscreen.value = !fullscreen.value
//
setTimeout(() => {
window.dispatchEvent(new Event('resize'))
}, 100)
}
//
// const handleKeydown = (e) => {
// if (fullscreen.value && e.key === 'Escape') {
// toggleFullscreen()
// }
// }
</script>
<style lang="scss" scoped>
@ -132,4 +161,47 @@ let initMonaco = () => {
//
//}
}
.editor-container {
position: relative;
height: 80vh;
&.fullscreen-editor {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
width: 100vw !important;
height: 100vh !important;
background: white;
#zfile-monaco-editor {
height: calc(100vh - 40px);
}
}
}
.editor-controls {
position: absolute;
top: 0px;
right: 0px;
z-index: 1000;
.fullscreen-btn {
background: rgba(255, 255, 255, 0.8);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
&:hover {
background: rgba(255, 255, 255, 0.9);
}
img {
width: 16px !important;
height: 16px;
}
}
}
#zfile-monaco-editor {
transition: all 0.3s ease;
}
</style>

View File

@ -98,7 +98,14 @@ svg{
background-color: #409eff !important;
color: #fff !important;
}
.tree_content{
.el-tree-node.is-current > .el-tree-node__content {
width: 100%;
height: 33px;
background-color: #f5f7fa !important;
color: #606266 !important;
}
}
.el-tree-node__content {
width: 100%;
height: 33px !important;

View File

@ -1,8 +1,16 @@
<template>
<div class="viewItemFile">
<!-- 预览文件 -->
<el-dialog width="61%" class="viewItemFileDialog" :title="title" v-model='dialogVisible' :before-close="handleClose"
<el-dialog width="80%" class="viewItemFileDialog" :title="title" v-model='dialogVisible' :before-close="handleClose"
:close-on-click-modal="false" :close-on-press-escape="false" draggable>
<div class="pdf-controls"
v-if="props.type == 'pdf' || props.type == 'docx' || props.type == 'doc' || props.type == 'xlsx' || props.type == 'bin'">
<el-button size="small" @click="toggleFullscreen" circle>
<img v-if="!fullscreen" src="@/assets/images/qvan.png" alt="">
<img v-else src="@/assets/images/tuiqvan.png" alt="">
</el-button>
</div>
<div class="image"
v-if="props.type == 'JPG' || props.type == 'jpg' || props.type == 'JPEG' || props.type == 'jpeg' || props.type == 'PNG' || props.type == 'png'">
<div>
@ -12,7 +20,7 @@
<div v-loading="loading" element-loading-text="正在加载报告..." element-loading-background="rgba(122, 122, 122, 0.8)"
class="docWrap" v-if="props.type == 'docx' || props.type == 'doc'">
<!-- 预览文件的地方用于渲染 -->
<div ref="file"></div>
<div ref="file" :class="{ 'fullscreen-doc': fullscreen }"></div>
</div>
<div v-if="props.type == 'xlsx'" v-loading="loading" element-loading-text="正在加载报告..."
element-loading-background="rgba(122, 122, 122, 0.8)" class="docWrap">
@ -21,17 +29,28 @@
<el-radio-button v-for="(item, index) in excel.sheetNames" :key="index" :label="item"></el-radio-button>
</el-radio-group>
</div>
<div style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;">
<div style="margin-top: 5px;border: 1px solid #a0a0a0;overflow:auto;"
:class="{ 'fullscreen-xlsx': fullscreen }">
<div v-html="excel.SheetActiveTable" style="padding: 10px 15px"></div>
</div>
</div>
<div v-if="props.type == 'pdf'">
<iframe :src="pdfurl" type="application/x-google-chrome-pdf" width="100%" height="800px" />
<iframe :src="pdfurl" :class="{ 'fullscreen-iframe': fullscreen }" type="application/x-google-chrome-pdf"
width="100%" :height="fullscreen ? 'calc(100vh - 55px)' : '800px'" />
</div>
<div v-if="props.type === 'bin'" v-loading="loading" class="hex-container">
<div v-if="props.type === 'bin'" v-loading="loading" class="hex-container"
:class="{ 'fullscreen-bin': fullscreen }">
<pre>{{ hexContent }}</pre>
</div>
<div v-if="props.type === 'pptx'" v-loading="loading" class="ppt-container">
<div class="ppt-controls">
<el-button-group>
<el-button size="small" @click="prevSlide">上一页</el-button>
<el-button size="small" @click="nextSlide">下一页</el-button>
<el-button size="small" @click="toggleFullscreen">全屏</el-button>
</el-button-group>
</div>
<div ref="pptViewer" class="ppt-viewer"></div>
</div>
</el-dialog>
@ -41,8 +60,8 @@
<script setup>
import { ref, nextTick, onMounted, getCurrentInstance, reactive, toRefs } from 'vue'
import * as docx from 'docx-preview'
import * as XLSX from "xlsx";
import PptxGenJS from 'pptxgenjs';
import axios from 'axios';
const props = defineProps({
showTime: {
@ -89,7 +108,30 @@ const data = reactive({
const { excel } = toRefs(data);
const currentSlide = ref(0);
const totalSlides = ref(0);
const prevSlide = () => {
if (currentSlide.value > 0) {
currentSlide.value--;
scrollToSlide();
}
};
const nextSlide = () => {
if (currentSlide.value < totalSlides.value - 1) {
currentSlide.value++;
scrollToSlide();
}
};
const scrollToSlide = () => {
const slides = proxy.$refs.pptViewer.querySelectorAll('.slide-container');
slides[currentSlide.value].scrollIntoView({
behavior: 'smooth',
block: 'center'
});
};
onMounted(() => {
init(props.type);
})
@ -219,35 +261,46 @@ function init(type) {
//
});
} else if (type === "pptx") {
loading.value = true;
(async () => { // async
try {
const response = await axios({
method: "GET",
url: props.url,
responseType: "arraybuffer"
});
const pptx = window.PPTXJS;
pptx.verbose = false;
const viewer = proxy.$refs.pptViewer;
viewer.innerHTML = '';
const pres = new pptx.Presentation(viewer, {
slideNumberFormat: pptx.SlideNumberFormat.SLIDE_NUMBER,
license: "YOUR_LICENSE_KEY"
});
await pres.load(response.data);
pres.render();
debugger
loading.value = true;
axios.request({
method: "GET",
url: props.url,
responseType: "arraybuffer",
}).then(async (res) => {
if (res.data) {
// PPTX
const pptx = new PptxGenJS();
// PPTX
await pptx.load(res.data);
//
const slides = pptx.getSlides();
//
proxy.$refs.pptViewer.innerHTML = '';
//
slides.forEach((slide, index) => {
const slideDiv = document.createElement('div');
slideDiv.className = 'slide-container';
slideDiv.innerHTML = `
<div class="slide-content">
${slide.getPageSVG()} <!-- 获取SVG内容 -->
<div class="slide-number">Page ${index + 1}/${slides.length}</div>
</div>
`;
proxy.$refs.pptViewer.appendChild(slideDiv);
});
loading.value = false;
}
}).catch(() => {
loading.value = false;
} catch (error) {
console.error('PPT加载失败:', error);
loading.value = false;
}
})(); //
}
ElMessage.error('PPT加载失败');
});
}
dialogVisible.value = true;
}
@ -278,6 +331,20 @@ function arrayBufferToHex(buffer) {
function handleClose() {
emits('update', false)
}
const toggleFullscreen = () => {
fullscreen.value = !fullscreen.value;
nextTick(() => {
if (fullscreen.value) {
document.documentElement.style.overflow = 'hidden';
if (props.type == 'pdf') {
pdfurl.value = pdfurl.value.split('#')[0] + '#zoom=fit';
}
} else {
document.documentElement.style.overflow = '';
}
});
};
</script>
<style lang="scss" scoped>
@ -435,50 +502,119 @@ html body {
color: #333;
}
}
/* 添加PPT预览样式 */
.ppt-container {
height: 700px;
overflow: auto;
background: #f0f0f0;
padding: 20px;
}
.ppt-viewer {
width: 80%;
margin: 0 auto;
max-width: 100%;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
/* 保持PPT原始比例 */
:deep(.slide-container) {
position: relative;
width: 100%;
height: 0;
padding-top: 75%; /* 默认4:3比例 */
&.widescreen {
padding-top: 56.25%; /* 16:9比例 */
}
background: white;
.slide-container {
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.slide-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
position: relative;
padding-top: 75%; // 4:3
svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
&.widescreen {
.slide-content {
padding-top: 56.25%; // 16:9
}
}
}
}
/* 适配PPT动画和布局 */
:deep(.shape-animation) {
animation-duration: 0.5s !important;
//docx
:deep(.docx-wrapper) {
padding: 10px !important;
}
:deep(.slide-number) {
position: absolute;
right: 10px;
bottom: 10px;
font-size: 14px;
color: #666;
:deep(.docx-wrapper>section.docx) {
width: 100% !important;
}
.fullscreen-doc {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
z-index: 9999;
background: white;
overflow: auto;
}
.docWrap {
height: calc(100vh - 150px);
overflow: auto;
}
.pdf-controls {
position: fixed;
right: 117px;
top: 12px;
z-index: 10000;
background: rgba(255, 255, 255, 0.8);
padding: 5px;
border-radius: 20px;
}
.fullscreen-iframe {
position: fixed !important;
top: 0 !important;
/* 调整为0 */
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
/* 调整为100vh */
z-index: 9999;
background: white;
border: none;
}
/* 调整对话框全屏样式 */
.viewItemFileDialog.fullscreen {
width: 100vw !important;
max-width: 100vw !important;
height: 100vh !important;
margin: 0 !important;
top: 0 !important;
.el-dialog__body {
height: 100vh !important;
/* 调整为100vh */
padding: 0 !important;
}
}
.fullscreen-xlsx {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
z-index: 9999;
background: white;
overflow: auto;
}
.fullscreen-bin {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
z-index: 9999;
background: white;
overflow: auto;
}
</style>

View File

@ -204,11 +204,12 @@ function handleLogin() {
.login(user)
.then(() => {
Cookies.set('username', user.username);
// debugger
if (remember.value == true) {
Cookies.set('password', user.password);
Cookies.set('rememberMe', String(remember.value));
}
router.push({ path: state.redirect || '/', query: state.otherQuery });
router.push({ path: '/dashboard' || '/', query: state.otherQuery });
state.loading = false;
})
.catch(() => {

View File

@ -284,11 +284,19 @@ function openFile() {
description: '', //
fileSize: '', //M
}
judge.value = true
}
//
function editfile(row: any) {
const judge = ref(false)
function editfile(row: any, item: any) {
upfile.value = true
fileObj.value = JSON.parse(JSON.stringify(row))
if (item) {
title.value = "修改文件"
} else {
title.value = "重命名"
}
judge.value = item
}
// close
const emit = defineEmits([])
@ -558,7 +566,7 @@ 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' || getFileExtension(row.fileName) == 'pptx') {
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
@ -684,20 +692,37 @@ function getFileSuffix(name: any) {
<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>{{ 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="description" 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'"
@click="openPreview(scope.row)" src="@/assets/fileimg/PDF.png" alt="" style="cursor: pointer;">
<img v-else-if="getFileExtension(scope.row.fileName) == 'docx'"
@click="openPreview(scope.row)" src="@/assets/fileimg/word.png" alt="" style="cursor: pointer;">
<img v-else-if="getFileExtension(scope.row.fileName) == 'mp4'"
@click="openPreview(scope.row)" src="@/assets/fileimg/mp4.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'"
@click="openPreview(scope.row)" src="@/assets/fileimg/mp3.png" alt="" style="cursor: pointer;">
<img v-else src="@/assets/fileimg/text_line.png" alt="" style="cursor: pointer;" @click="openPreview(scope.row)">
</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="80" align="center">
<el-table-column fixed="right" label="操作" width="100" align="center">
<template #default="scope">
<span
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">
<img src="@/assets/MenuIcon/lbcz_xg.png" alt="" @click="editfile(scope.row)" title="修改"
<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 src="@/assets/MenuIcon/lbcz_sc.png" alt="" @click="delfile(scope.row)" title="删除"
style="cursor: pointer;">
@ -729,7 +754,7 @@ function getFileSuffix(name: any) {
</el-dialog>
<el-dialog title="上传文件" v-model="upfile" width="50%" :before-close="fileClose" top="30px" draggable
destroy-on-close>
<el-scrollbar height="400px">
<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">
@ -740,10 +765,10 @@ function getFileSuffix(name: any) {
<el-form-item v-else label="文件名称:">
<el-input v-model="fileObj.fileName" />
</el-form-item>
<el-form-item label="关键字:" prop="taskName">
<el-form-item v-if="judge" label="关键字:" prop="taskName">
<el-input v-model="fileObj.keywords" />
</el-form-item>
<el-form-item label="描述:">
<el-form-item v-if="judge" label="描述:">
<el-input v-model="fileObj.description" :rows="2" type="textarea" />
</el-form-item>
<el-form-item>

View File

@ -448,8 +448,8 @@ onMounted(() => {
style="cursor: pointer; "> -->
<img src="@/assets/MenuIcon/lbcz_qx.png" alt="" title="权限分配" @click="assignment(scope.row)"
style="cursor: pointer; ">
<img src="@/assets/tableicon/region.png" alt="" title="区域权限分配" @click="regionClick(scope.row)"
style="cursor: pointer; ">
<!-- <img src="@/assets/tableicon/region.png" alt="" title="区域权限分配" @click="regionClick(scope.row)"
style="cursor: pointer; "> -->
<img v-hasPerm="['del:role']" src="@/assets/MenuIcon/lbcz_sc.png" alt="" title="删除"
@click="delrole(scope.row)" style="cursor: pointer; ">
</span>

View File

@ -55,12 +55,12 @@ function getTree() {
parentid: "0",
};
getTreelist(params).then((res: any) => {
// treedata.value = res
treedata.value = res
treeloading.value = false
orgId.value = res[0].childList[0].id
// nextTick(() => {
// treeRef.value?.setCurrentKey(orgId.value);
// });
nextTick(() => {
treeRef.value?.setCurrentKey(orgId.value);
});
getdata()
})
.catch((error: any) => {
@ -91,7 +91,7 @@ function handleNodeClick(data: Tree, node: any) {
const defaultProps = {
children: "childList",
label: "name"
label: "orgname"
};
//
@ -382,7 +382,7 @@ function dateFormat(row: any) {
const isRoles = ref(false)
onMounted(() => {
getTree();
getTreeInit();
// getTreeInit();
// getdata()
for (let i = 0; i < userStore.roles.length; i++) {
if (userStore.roles[i] == '医疗机构管理员') {
@ -452,33 +452,33 @@ function institutionClick(e: any) {
});
}
const queryName = ref('')
function getTreeInit() {
queryName.value = queryName.value.replace(/\s+/g, "");
let params = {
name: queryName.value
};
treeloading.value = true
treedata.value = []
queryVisionInstitutionNameList(params).then((res) => {
treedata.value = res.data
treedata.value.unshift({
id: '',
name: '全部机构'
})
// function getTreeInit() {
// queryName.value = queryName.value.replace(/\s+/g, "");
// let params = {
// name: queryName.value
// };
// treeloading.value = true
// treedata.value = []
// queryVisionInstitutionNameList(params).then((res) => {
// treedata.value = res.data
// treedata.value.unshift({
// id: '',
// name: ''
// })
treeloading.value = false
}).catch(() => {
treeloading.value = false
});
}
// treeloading.value = false
// }).catch(() => {
// treeloading.value = false
// });
// }
</script>
<template>
<div class="faulttemplate-box">
<aside id="silderLeft">
<el-input v-model="queryName" clearable @keydown.enter="getTreeInit" placeholder="机构名称搜索">
<el-input v-model="queryName" clearable @keydown.enter="getTree()" placeholder="组织名称">
<template #append>
<el-button type="primary" :icon="Search" @click="getTreeInit" />
<el-button type="primary" :icon="Search" @click="getTree()" />
</template>
</el-input>
<el-tree ref="treeRef" :class="useAppStore().size === 'default' ? 'silderLeft-large' : 'silderLeft-default'"

View File

@ -379,7 +379,7 @@ function delfile(row: any) {
}
)
.then(() => {
deleteTsFilesById({ id: row.id }).then((res: any) => {
deleteTsFilesById({ id: row.id,type:'local' }).then((res: any) => {
if (res.code == 0) {
getdata()
ElMessage({
@ -414,7 +414,7 @@ function delprojectArr() {
}
)
.then(() => {
deleteTsFilesByIds({ ids: ids.join(',') }).then((res: any) => {
deleteTsFilesByIds({ ids: ids.join(','),type:'local' }).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
@ -567,7 +567,7 @@ 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') {
if (getFileExtension(row.fileName) == 'pdf' || getFileExtension(row.fileName) == 'pptx' || 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
@ -1395,10 +1395,8 @@ function removeSuffix(filename: any) {
<!-- <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>
<div class="tableweight" v-if="scope.row.isFile == 'FOLDER'">{{ scope.row.fileName }} </div>
<div v-else-if="scope.row.isFile == 'FILE'">{{ scope.row.fileName }} </div>
</template>
</el-table-column>
<el-table-column prop="keywords" label="关键字"></el-table-column>
@ -1407,16 +1405,16 @@ function removeSuffix(filename: any) {
<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;">
@click="openPreview(scope.row)" 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=""
@click="openPreview(scope.row)" src="@/assets/fileimg/mp4.png" alt="" style="cursor: pointer;">
<img v-else-if="scope.row.isFile == 'FOLDER'" src="@/assets/fileimg/wenjianjia.png" alt="" @click="openNode(scope.row)"
style="cursor: pointer;">
<img v-else-if="getFileExtension(scope.row.fileName) == 'zip'"
src="@/assets/fileimg/zip.png" alt="" style="cursor: pointer;">
@click="openPreview(scope.row)" 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;">
@click="openPreview(scope.row)" src="@/assets/fileimg/mp3.png" alt="" style="cursor: pointer;">
<img v-else src="@/assets/fileimg/text_line.png" alt="" style="cursor: pointer;" @click="openPreview(scope.row)">
</div>
<!-- {{ getFileExtension(scope.row.fileName) }} -->

View File

@ -9,6 +9,7 @@ import { ref, onMounted, nextTick, defineAsyncComponent } from "vue";
import { Search } from '@element-plus/icons-vue'
import { ElMessageBox, ElMessage } from "element-plus";
import { tstaskList, getTsNodesTree, tsFilesPage } from "@/api/datamanagement";
import { listLocalAndBackup, compare, uploadToBackup, downloadToLocal, deleteTsFilesById } from "@/api/fileSynchronization";
//
import useFileUpload from "@/components/file/file/useFileUpload";
import useHeaderStorageList from "@/components/header/useHeaderStorageList";
@ -43,32 +44,93 @@ const treeForm = ref({
//
const props = {
label: 'fileName',
children: 'zones',
children: 'children',
}
const workloading = ref(false)
//
const queryParams: any = ref({
current: 1,
size: 20,
nodeId: '',//ID
taskId: '',//Id
childNode: '1'
});
const worktree = ref(false)
const workdata = ref([])
const workall = ref([])
const workref = ref()
//
const backupsdata = ref([])
//
const contextMenuVisible = ref(false)
const contextMenuVisible2 = ref(false)
const contextMenuPosition = ref({ x: 0, y: 0 })
const currentNode = ref<any>(null)
//
const differential = ref(false)
function diffFile(){
function diffFile() {
const seen = new Set();
comparearr.value = comparearr.value.filter(item => {
return seen.has(item.id) ? false : seen.add(item.id);
});
differential.value = true
getchayi()
}
//
const comparearr: any = ref([])
const localOnlyFiles: any = ref([])
const md5MismatchedFiles: any = ref([])
const minioOnlyFiles: any = ref([])
const loading = ref(false)
function getchayi() {
loading.value = true
const ids = []
const params: any = {}
if (comparearr.value.length > 0) {
comparearr.value.forEach((item: any) => {
ids.push(item.id)
})
params.id = ids.join(',')
} else {
params.nodeId = pathid.value
params.taskId = projectId.value
}
compare(params).then((res: any) => {
localOnlyFiles.value = res.data.localOnlyFiles
md5MismatchedFiles.value = res.data.md5MismatchedFiles
minioOnlyFiles.value = res.data.minioOnlyFiles
loading.value = false
diffColor()
})
}
//
function diffColor() {
if (workdata.value.length > 0 && localOnlyFiles.value.length > 0) {
workdata.value = changeColor(workdata.value, localOnlyFiles.value, '1')
}
if (workdata.value.length > 0 && md5MismatchedFiles.value.length > 0) {
workdata.value = changeColor(workdata.value, md5MismatchedFiles.value, '2')
backupsdata.value = changeColor(backupsdata.value, md5MismatchedFiles.value, '2')
}
if (backupsdata.value.length > 0 && minioOnlyFiles.value.length > 0) {
backupsdata.value = changeColor(backupsdata.value, minioOnlyFiles.value, '3')
}
workref.value!.setCheckedKeys([], false)
beifentree.value!.setCheckedKeys([], false)
}
//
function changeColor(data: any, data2: any, type: any) {
data.forEach((item: any) => {
data2.forEach((item2: any) => {
if (item.id == item2.id) {
item.station = type
}
if (item.children.length > 0) {
changeColor(item.children, data2, type)
}
})
})
return data
}
function diffClose() {
differential.value = false
getWorkData()
}
//
function getProject() {
@ -102,56 +164,170 @@ const handleCheckChange = (
checked: boolean,
indeterminate: boolean
) => {
console.log(data, checked)
if (checked == true && indeterminate == false) {
workall.value.push(data)
} else {
workall.value = workall.value.filter(item => item.id !== data.id);
}
comparearr.value = getclickdata(workall.value)
beifentree.value!.setCheckedNodes(comparearr.value, false)
}
//
function getclickdata(data: any) {
data.forEach((item: any) => {
if (item.isFile == "FOLDER") {
item.children.forEach((child: any) => {
data = data.filter((items: any) => items.id !== child.id);
if (child.children.length > 0) {
getclickdata(child.children)
}
})
}
});
return data
}
//
//
function getWorkData() {
// workloading.value = true
queryParams.value.nodeId = pathid.value
queryParams.value.taskId = projectId.value
tsFilesPage(queryParams.value).then((res: any) => {
// workloading.value = false
workdata.value = res.data.records
backupsdata.value = res.data.records
worktree.value = true
worktree.value = true
listLocalAndBackup({ taskId: projectId.value, nodeId: pathid.value }).then((res: any) => {
workdata.value = res.data.localTrees
backupsdata.value = res.data.minioTrees
if (workdata.value.length > 0) {
assignment(workdata.value, 'local')
}
if (backupsdata.value.length > 0) {
assignment(backupsdata.value, 'minio')
}
worktree.value = false
diffColor()
})
}
//
function assignment(data: any, difference: any) {
data.forEach((item: any) => {
item.location = difference
item.station = '0' //0123
if (item.children.length > 0) {
assignment(item.children, difference)
}
})
}
//
const beifentree = ref()
function backupsChange(
data: any,
checked: boolean,
indeterminate: boolean
) {
console.log(data, checked)
if (checked == true && indeterminate == false) {
workall.value.push(data)
} else {
workall.value = workall.value.filter(item => item.id !== data.id);
}
comparearr.value = getclickdata(workall.value)
workref.value!.setCheckedNodes(comparearr.value, false)
}
//
const handleRightClick = (event: Event, data: any, node: any) => {
console.log(data)
event.preventDefault()
currentNode.value = data
contextMenuVisible.value = true
contextMenuPosition.value = {
x: (event as MouseEvent).clientX + 10,
y: (event as MouseEvent).clientY
if (data.station != '0') {
event.preventDefault()
currentNode.value = data
if (data.location == 'local') {
contextMenuVisible.value = true
} else {
contextMenuVisible2.value = true
}
contextMenuPosition.value = {
x: (event as MouseEvent).clientX + 10,
y: (event as MouseEvent).clientY
}
} else {
contextMenuVisible.value = false
contextMenuVisible2.value = false
}
}
function workclick() {
contextMenuVisible.value = false
contextMenuVisible2.value = false
}
const handleMenuClick = (action: string, type: any) => {
contextMenuVisible.value = false
contextMenuVisible2.value = false
switch (action) {
case 'restore':
//
ElMessageBox.confirm(
'您确定要将该文件/文件夹恢复到工作空间吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
const params = [{
path: currentNode.value.path,
name: currentNode.value.fileName,
size: currentNode.value.fileSize,
type: currentNode.value.isFile
}]
downloadToLocal({ parameterLists: params }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("恢复成功")
minioOnlyFiles.value = minioOnlyFiles.value.filter((item: any) => item.id !== currentNode.value.id)
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== currentNode.value.id)
getWorkData()
}
})
})
break
case 'backups':
//
ElMessageBox.confirm(
'您确定要将该文件/文件夹上传到备份空间吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
const params = [{
path: currentNode.value.path,
name: currentNode.value.fileName,
size: currentNode.value.fileSize,
type: currentNode.value.isFile
}]
uploadToBackup({ parameterLists: params }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("上传成功")
localOnlyFiles.value = localOnlyFiles.value.filter((item: any) => item.id !== currentNode.value.id)
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== currentNode.value.id)
getWorkData()
// getchayi()
}
})
})
break
case 'delete':
//
deleteTsFilesById({ id: currentNode.value.id, type: type }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("删除成功")
getWorkData()
}
})
break
case 'preview':
//
openPreview(currentNode.value)
break
}
}
@ -159,7 +335,166 @@ const handleMenuClick = (action: string, type: any) => {
//
document.addEventListener('click', () => {
contextMenuVisible.value = false
contextMenuVisible2.value = false
})
//
function tableBeifen(row: any) {
ElMessageBox.confirm(
'您确定要将该文件/文件夹上传到备份空间吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
const params = [{
path: row.path,
name: row.name,
size: row.size,
type: row.type
}]
uploadToBackup({ parameterLists: params }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("上传成功")
localOnlyFiles.value = localOnlyFiles.value.filter((item: any) => item.id !== row.id)
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== row.id)
}
})
})
}
const beifenArr = ref([])
function bifenChange(row: any) {
beifenArr.value = row
}
function moretableBeifen() {
ElMessageBox.confirm(
'您确定要将这些文件/文件夹上传到备份空间吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
uploadToBackup({ parameterLists: beifenArr.value }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("上传成功")
beifenArr.value.forEach((items: any) => {
localOnlyFiles.value = localOnlyFiles.value.filter((item: any) => item.id !== items.id)
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id)
})
}
})
})
}
//
function tablerestore(row: any) {
ElMessageBox.confirm(
'您确定要将该文件/文件夹恢复到工作空间吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
const params = [{
path: row.path,
name: row.name,
size: row.size,
type: row.type
}]
downloadToLocal({ parameterLists: params }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("恢复成功")
minioOnlyFiles.value = minioOnlyFiles.value.filter((item: any) => item.id !== row.id)
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== row.id)
}
})
})
}
const restoreArr = ref([])
function restoreChange(row: any) {
restoreArr.value = row
}
function moretablerestore() {
ElMessageBox.confirm(
'您确定要将这些文件/文件夹恢复到工作空间吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
downloadToLocal({ parameterLists: restoreArr.value }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("恢复成功")
restoreArr.value.forEach((item: any) => {
minioOnlyFiles.value = minioOnlyFiles.value.filter((item: any) => item.id !== item.id)
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== item.id)
})
}
})
})
}
//
const changeclick = ref([])
function handleChange(row: any) {
changeclick.value = row
}
function bfclick(type: any) {
let tstitle = ''
if (type == 'bf') {
tstitle = '您确定要将这些文件/文件夹上传到备份空间吗?'
} else {
tstitle = '您确定要将这些文件/文件夹恢复到工作空间吗'
}
ElMessageBox.confirm(
tstitle,
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
if (type == 'bf') {
uploadToBackup({ parameterLists: changeclick.value }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("上传成功")
changeclick.value.forEach((items: any) => {
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id)
})
}
})
} else {
downloadToLocal({ parameterLists: changeclick.value }).then((res: any) => {
if (res.code == '0') {
ElMessage.success("恢复成功")
changeclick.value.forEach((items: any) => {
md5MismatchedFiles.value = md5MismatchedFiles.value.filter((item: any) => item.id !== items.id)
})
}
})
}
})
}
onMounted(() => {
getProject()
});
@ -207,6 +542,71 @@ const Three3dPreview = defineAsyncComponent({
loader: () => import("@/components/file/preview/Three3dPreview.vue"),
loadingComponent: MarkdownViewerDialogAsyncLoading
})
//
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 '';
}
}
//
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 CloseView() {
isViewfile.value = false
}
</script>
<template>
@ -220,7 +620,6 @@ const Three3dPreview = defineAsyncComponent({
<el-input v-model="treeForm.nodeName" style="width:100%;margin:10px 9px 10px 0px;"
placeholder="节点名称" clearable :suffix-icon="Search" @change="gettreedata()" />
</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;">
@ -236,20 +635,29 @@ const Three3dPreview = defineAsyncComponent({
</div>
</aside>
<section class="silderRight">
<div class="tree_button"><el-button type="primary" @click="diffFile()" >文件差异性对比</el-button></div>
<div class="tree_button">
<el-button type="primary" @click="diffFile()">文件差异性对比</el-button>
<el-button type="primary" @click="differential = true">查看本次差异性对比</el-button>
</div>
<div class="tree_box">
<div class="tree_left">
<div class="tree_title">工作空间:</div>
<div>
<div class="tree_content">
<el-scrollbar height="73vh">
<el-tree v-if="worktree" style="max-width: 600px" :props="props" :data="workdata"
@node-contextmenu="handleRightClick" :expand-on-click-node="false" show-checkbox
v-loading="workloading" @check-change="handleCheckChange">
<el-tree ref="workref" style="max-width: 600px" :props="props" :data="workdata"
@node-click="workclick" @node-contextmenu="handleRightClick" default-expand-all
:expand-on-click-node="false" show-checkbox node-key="id" v-loading="worktree"
@check-change="handleCheckChange">
<template #default="{ data }">
<span class="custom-tree-node">
<!-- data.children.length -->
<span class="text">{{ data.fileName }}({{ data.isFile == 'FOLDER' ? '0' :
data.fileSize + 'MB' }})</span>
<span
:class="data.station == '0' ? 'custom-tree-node' : (data.station == '1' ? 'custom-tree-node1' : (data.station == '2' ? 'custom-tree-node2' : 'custom-tree-node3'))">
<span class="text">
{{ data.fileName }}({{ data.isFile == 'FOLDER' ? data.children.length :
data.fileSize + 'MB' }})
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
(data.station
== '2' ? '已变更' : '已删除') }})</span>
</span>
</span>
</template>
</el-tree>
@ -267,20 +675,26 @@ const Three3dPreview = defineAsyncComponent({
</div>
<div class="tree_left">
<div class="tree_title">备份空间:</div>
<div>
<div class="tree_content">
<el-scrollbar height="73vh">
<el-tree v-if="worktree" style="max-width: 600px" :props="props" :data="backupsdata"
@node-contextmenu="handleRightClick" :expand-on-click-node="false" show-checkbox
v-loading="workloading" @check-change="backupsChange">
<el-tree ref="beifentree" style="max-width: 600px" :props="props" :data="backupsdata"
default-expand-all @node-click="workclick" @node-contextmenu="handleRightClick"
:expand-on-click-node="false" show-checkbox node-key="id" v-loading="worktree"
@check-change="backupsChange">
<template #default="{ data }">
<span class="custom-tree-node">
<span
:class="data.station == '0' ? 'custom-tree-node' : (data.station == '1' ? 'custom-tree-node1' : (data.station == '2' ? 'custom-tree-node2' : 'custom-tree-node3'))">
<!-- data.children.length -->
<span class="text">{{ data.fileName }}({{ data.isFile == 'FOLDER' ? '0' :
<span class="text">{{ data.fileName }}({{ data.isFile == 'FOLDER' ?
data.children.length :
data.fileSize + 'MB' }})</span>
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
(data.station
== '2' ? '已变更' : '已删除') }})</span>
</span>
</template>
</el-tree>
<div v-show="contextMenuVisible" class="context-menu" :style="{
<div v-show="contextMenuVisible2" class="context-menu" :style="{
left: `${contextMenuPosition.x}px`,
top: `${contextMenuPosition.y}px`
}">
@ -299,27 +713,33 @@ const Three3dPreview = defineAsyncComponent({
<el-scrollbar height="400px">
<div class="newContent">
<div class="newContent_title"><span class="newContent_title_text">新增内容</span>
<el-button type="primary">全部备份</el-button>
<el-button type="primary" :disabled="beifenArr.length == 0"
@click="moretableBeifen()">备份</el-button>
</div>
<el-table v-loading="loading" :data="tableData"
@selection-change="handleSelectionChange"
<el-table v-loading="loading" :data="localOnlyFiles" @selection-change="bifenChange"
:header-cell-style="{ background: 'rgb(250 250 250)', height: '50px' }"
style="width: 100%; height: calc(30vh);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="fileSize" label="文件大小">
<el-table-column prop="name" label="文件名称"></el-table-column>
<el-table-column prop="type" label="文件类型" width="90">
<template #default="scope">
{{ scope.row.fileSize + 'MB' }}
<span v-if="scope.row.type == 'FOLDER'">文件夹</span>
<span v-else>文件</span>
</template>
</el-table-column>
<el-table-column prop="workPath" label="路径"></el-table-column>
<el-table-column prop="updateTime" width="170" label="修改日期"></el-table-column>
<el-table-column fixed="right" label="操作" width="120" align="center">
<el-table-column prop="size" label="文件大小" width="100">
<template #default="scope">
<span
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">
<span v-if="scope.row.type != 'FOLDER'">{{ scope.row.size + 'MB' }}</span>
</template>
</el-table-column>
<el-table-column prop="path" label="路径"></el-table-column>
<el-table-column prop="time" width="170" label="修改日期"></el-table-column>
<el-table-column fixed="right" label="操作" width="60" align="center">
<template #default="scope">
<span style="display: flex;justify-content:center;">
<img @click="tableBeifen(scope.row)" style="cursor: pointer;" title="备份"
src="@/assets/images/beifen.png" alt="">
</span>
</template>
</el-table-column>
@ -327,54 +747,74 @@ const Three3dPreview = defineAsyncComponent({
</div>
<div class="newContent">
<div class="newContent_title"><span class="newContent_title_text">变更内容</span>
<el-button type="primary">全部备份</el-button>
<div>
<el-button type="primary" :disabled="changeclick.length == 0"
@click="bfclick('bei')">备份</el-button>
<el-button type="primary" :disabled="changeclick.length == 0"
@click="bfclick('hui')">恢复</el-button>
</div>
</div>
<el-table v-loading="loading" :data="tableData"
@selection-change="handleSelectionChange"
<el-table v-loading="loading" :data="md5MismatchedFiles"
@selection-change="handleChange"
:header-cell-style="{ background: 'rgb(250 250 250)', height: '50px' }"
style="width: 100%; height: calc(30vh);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="fileSize" label="文件大小">
<el-table-column prop="name" label="文件名称"></el-table-column>
<el-table-column prop="type" label="文件类型" width="90">
<template #default="scope">
{{ scope.row.fileSize + 'MB' }}
<span v-if="scope.row.type == 'FOLDER'">文件夹</span>
<span v-else>文件</span>
</template>
</el-table-column>
<el-table-column prop="workPath" label="路径"></el-table-column>
<el-table-column prop="updateTime" width="170" label="修改日期"></el-table-column>
<el-table-column fixed="right" label="操作" width="120" align="center">
<el-table-column prop="size" label="文件大小" width="100">
<template #default="scope">
<span
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">
{{ scope.row.size + 'MB' }}
</template>
</el-table-column>
<el-table-column prop="path" label="路径"></el-table-column>
<el-table-column prop="time" width="170" label="修改日期"></el-table-column>
<el-table-column label="操作" width="80" align="center">
<template #default="scope">
<span style="display: flex;justify-content:space-around;">
<img @click="tableBeifen(scope.row)" style="cursor: pointer;" title="备份"
src="@/assets/images/beifen.png" alt="">
<img @click="tablerestore(scope.row)" style="cursor: pointer;"
title="恢复" src="@/assets/images/huifu.png" alt="">
</span>
</template>
</el-table-column>
</el-table>
</div>
<div class="newContent">
<div class="newContent_title"><span class="newContent_title_text">缺失内容</span> <el-button
type="primary">全部恢复</el-button> </div>
<el-table v-loading="loading" :data="tableData"
@selection-change="handleSelectionChange"
<div class="newContent_title"><span class="newContent_title_text">缺失内容</span>
<el-button type="primary" :disabled="restoreArr.length == 0"
@click="moretablerestore()">恢复</el-button>
</div>
<el-table v-loading="loading" :data="minioOnlyFiles" @selection-change="restoreChange"
:header-cell-style="{ background: 'rgb(250 250 250)', height: '50px' }"
style="width: 100%; height: calc(30vh);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="fileSize" label="文件大小">
<el-table-column prop="name" label="文件名称"></el-table-column>
<el-table-column prop="type" label="文件类型" width="90">
<template #default="scope">
{{ scope.row.fileSize + 'MB' }}
<span v-if="scope.row.type == 'FOLDER'">文件夹</span>
<span v-else>文件</span>
</template>
</el-table-column>
<el-table-column prop="workPath" label="路径"></el-table-column>
<el-table-column prop="updateTime" width="170" label="修改日期"></el-table-column>
<el-table-column prop="size" label="文件大小" width="100">
<template #default="scope">
{{ scope.row.size + 'MB' }}
</template>
</el-table-column>
<el-table-column prop="path" label="路径"></el-table-column>
<el-table-column prop="time" 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; ">
<span style="display: flex;justify-content:center;">
<img @click="tablerestore(scope.row)" style="cursor: pointer;"
title="恢复" src="@/assets/images/huifu.png" alt="">
</span>
</template>
</el-table-column>
@ -386,41 +826,40 @@ const Three3dPreview = defineAsyncComponent({
</el-dialog>
<!-- 组件预览 -->
<!-- 视频播放器 -->
<!-- <el-dialog draggable class="zfile-video-dialog" :destroy-on-close="true" v-model="dialogVideoVisible">
<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>
<!-- 文本编辑器 -->
<!-- <el-dialog draggable class="zfile-text-dialog zfile-dialog-mini-close" :destroy-on-close="true"
<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> -->
</el-dialog>
<!-- pdf 在线预览 -->
<!-- <el-dialog draggable class="zfile-pdf-dialog" :title="filePreview.fileName" v-model="dialogPdfVisible">
<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> -->
</el-dialog>
<!-- office 在线预览 -->
<!-- <el-dialog draggable class="zfile-office-dialog zfile-dialog-mini-close zfile-dialog-hidden-title"
<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> -->
</el-dialog>
<!-- 3d 在线预览 -->
<!-- <el-dialog draggable class="zfile-3d-dialog" :title="filePreview.fileName" v-model="dialog3dVisible">
<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> -->
</el-dialog>
<!-- 音频播放器 -->
<!-- <AudioPlayer></AudioPlayer> -->
<!-- <Viewfile v-if="isViewfile" :showTime="true" :title="title1" :url="ViewfileUrl" :type="fileType"
@update="CloseView" /> -->
<AudioPlayer></AudioPlayer>
<Viewfile v-if="isViewfile" :showTime="true" :title="title1" :url="ViewfileUrl" :type="fileType"
@update="CloseView" />
</div>
</section>
@ -518,11 +957,41 @@ const Three3dPreview = defineAsyncComponent({
}
.custom-tree-node1 {
display: inline-block;
width: 100%;
font-size: 14px;
padding: 5px;
background-color: green;
color: #fff;
margin-bottom: 5px !important;
}
.custom-tree-node2 {
display: inline-block;
width: 100%;
font-size: 14px;
padding: 5px;
background-color: yellow;
color: #409eff;
}
.custom-tree-node3 {
display: inline-block;
width: 100%;
font-size: 14px;
padding: 5px;
background-color: red;
color: #fff;
margin-bottom: 5px !important;
}
.custom-tree-node {
display: inline-block;
width: 100%;
font-size: 14px;
padding: 5px;
// margin-bottom: 5px !important;
}
:deep() {
@ -555,6 +1024,15 @@ const Three3dPreview = defineAsyncComponent({
}
}
.tree_title {
:deep(.el-tree-node.is-current > .el-tree-node__content) {
background-color: #606266 !important;
color: #606266 !important;
}
}
.context-menu {
position: fixed;
background: #fff;