文件同步管理
This commit is contained in:
parent
8317b543cd
commit
ff1e18aee9
@ -63,6 +63,13 @@ export function automaticFileBackup(params:any) {
|
||||
params:params,
|
||||
});
|
||||
}
|
||||
export function automaticFileBackupByIds(params:any) {
|
||||
return request({
|
||||
url: '/experimentalData/ts-files/automaticFileBackupByIds',
|
||||
method: 'post',
|
||||
params:params,
|
||||
});
|
||||
}
|
||||
//获取url
|
||||
export function obtainUrl(params:any) {
|
||||
return request({
|
||||
@ -95,3 +102,27 @@ export function compareMinio(params:any) {
|
||||
params:params,
|
||||
});
|
||||
}
|
||||
//文件差异-新增全部
|
||||
export function compareLocalList(params:any) {
|
||||
return request({
|
||||
url: '/experimentalData/ts-files/compareLocalList',
|
||||
method: 'post',
|
||||
params:params,
|
||||
});
|
||||
}
|
||||
//文件差异变更全部
|
||||
export function compareMd5List(params:any) {
|
||||
return request({
|
||||
url: '/experimentalData/ts-files/compareMd5List',
|
||||
method: 'post',
|
||||
params:params,
|
||||
});
|
||||
}
|
||||
//文件差异-缺失全部
|
||||
export function compareMinioList(params:any) {
|
||||
return request({
|
||||
url: '/experimentalData/ts-files/compareMinioList',
|
||||
method: 'post',
|
||||
params:params,
|
||||
});
|
||||
}
|
||||
|
@ -1,139 +1,296 @@
|
||||
<template>
|
||||
<!-- 地图容器 -->
|
||||
<div id="map" style="height: 800px; width: 100%"></div>
|
||||
<div ref="mapContainer" class="map-container" :class="{ 'fullscreen': isFullscreen }">
|
||||
<button class="fullscreen-btn" @click="toggleFullscreen">
|
||||
{{ isFullscreen ? '退出全屏' : '全屏' }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch, nextTick, onUnmounted } from 'vue'
|
||||
import L from 'leaflet'
|
||||
import 'leaflet/dist/leaflet.css'
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
const userStore = useUserStore();
|
||||
const url = userStore.mapUrl;
|
||||
// 类型定义
|
||||
interface PointProp {
|
||||
points?: Array<[number, number]>;
|
||||
}
|
||||
<script setup>
|
||||
import { ref, onMounted, watch, defineEmits, onBeforeUnmount } from 'vue'
|
||||
import * as d3 from 'd3'
|
||||
import chinaData from './newJson.json'
|
||||
|
||||
// 地图配置常量
|
||||
const MAP_CONFIG = {
|
||||
center: [39.9042, 116.4074] as [number, number], // 初始中心坐标(北京)
|
||||
zoom: 4, // 初始缩放级别
|
||||
minZoom: 0, // 最小缩放级别
|
||||
maxZoom: 11, // 最大缩放级别
|
||||
zoomControl: true // 缩放控件
|
||||
}
|
||||
// ==================== 常量与类型定义 ====================
|
||||
const DEFAULT_MAP_SIZE = { width: 800, height: 600 }
|
||||
const PROJECTION_CENTER = [104, 37] // 中国地理中心近似坐标
|
||||
const SCALE_FACTORS = { normal: 600, fullscreen: 1000 }
|
||||
|
||||
// 轨迹线样式配置
|
||||
const POLYLINE_STYLE = {
|
||||
color: 'blue', // 轨迹线颜色
|
||||
weight: 3, // 线宽
|
||||
lineJoin: 'round' as const // 连接处样式
|
||||
}
|
||||
|
||||
// 响应式props定义
|
||||
const props = withDefaults(defineProps<PointProp>(), {
|
||||
points: () => []
|
||||
})
|
||||
|
||||
// 地图实例引用
|
||||
let map: L.Map | null = null
|
||||
// 轨迹线实例
|
||||
let polyline: L.Polyline | null = null
|
||||
// 标记点数组
|
||||
let markers: L.Marker[] = []
|
||||
|
||||
/**
|
||||
* 初始化地图实例
|
||||
*/
|
||||
function initMap() {
|
||||
map = L.map('map', MAP_CONFIG)
|
||||
addTileLayer()
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加离线瓦片图层
|
||||
*/
|
||||
function addTileLayer() {
|
||||
L.tileLayer(url+'/{z}/{y}/{x}.jpg', {
|
||||
attribution: 'Offline Map',
|
||||
tileSize: 256,
|
||||
noWrap: true
|
||||
}).addTo(map!)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有轨迹元素
|
||||
*/
|
||||
function clearLayers() {
|
||||
// 移除轨迹线
|
||||
polyline?.remove()
|
||||
// 批量移除标记点
|
||||
markers.forEach(marker => marker.remove())
|
||||
markers = []
|
||||
}
|
||||
|
||||
/**
|
||||
* 将坐标转换为Leaflet的LatLng对象
|
||||
* @param point 原始坐标数组
|
||||
* @returns Leaflet坐标对象
|
||||
*/
|
||||
const convertToLatLng = (point: [number, number]) => L.latLng(point[0], point[1])
|
||||
|
||||
/**
|
||||
* 绘制轨迹线
|
||||
* @param latlngs 坐标点数组
|
||||
*/
|
||||
function createPolyline(latlngs: L.LatLng[]) {
|
||||
polyline = L.polyline(latlngs, POLYLINE_STYLE).addTo(map!)
|
||||
// 自动适配视图(按需启用)
|
||||
// map?.fitBounds(polyline.getBounds())
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建标记点
|
||||
* @param latlngs 坐标点数组
|
||||
* @returns 标记实例数组
|
||||
*/
|
||||
function createMarkers(latlngs: L.LatLng[]) {
|
||||
return latlngs.map(latlng =>
|
||||
L.marker(latlng).addTo(map!)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 主绘制函数
|
||||
* @param points 原始坐标数组
|
||||
*/
|
||||
function drawTrajectory(points: Array<[number, number]>) {
|
||||
if (!map) return
|
||||
|
||||
// 始终执行清理(无论是否有新坐标)
|
||||
clearLayers()
|
||||
|
||||
// 仅在有有效坐标时创建新元素
|
||||
if (points?.length > 0) {
|
||||
const latlngs = points.map(convertToLatLng)
|
||||
createPolyline(latlngs)
|
||||
markers = createMarkers(latlngs)
|
||||
// ==================== 组件Props/Emits ====================
|
||||
const props = defineProps({
|
||||
coordinates: {
|
||||
type: Array,
|
||||
default: () => [
|
||||
[116.405285, 39.904989], // 北京
|
||||
[121.472644, 31.231706] // 上海
|
||||
],
|
||||
validator: value => value.every(coord =>
|
||||
Array.isArray(coord) && coord.length === 2 &&
|
||||
typeof coord[0] === 'number' && typeof coord[1] === 'number'
|
||||
)
|
||||
},
|
||||
qvehuan: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['qvehuan1'])
|
||||
|
||||
// ==================== 响应式状态 ====================
|
||||
const mapContainer = ref(null)
|
||||
const isFullscreen = ref(false)
|
||||
const isRouteInitialized = ref(false) // 原initqie,重命名以明确含义
|
||||
|
||||
// ==================== D3相关变量 ====================
|
||||
let svgInstance = null
|
||||
let mapGroup = null
|
||||
let markersGroup = null
|
||||
let zoomBehavior = null
|
||||
|
||||
// ==================== 地图核心逻辑 ====================
|
||||
/**
|
||||
* 创建地理投影配置
|
||||
* @returns {d3.GeoProjection} D3地理投影实例
|
||||
*/
|
||||
const createProjection = () => {
|
||||
const { width, height } = getContainerSize()
|
||||
return d3.geoMercator()
|
||||
.center(PROJECTION_CENTER)
|
||||
.scale(isFullscreen.value ? SCALE_FACTORS.fullscreen : SCALE_FACTORS.normal)
|
||||
.translate([width / 2, height / 2])
|
||||
}
|
||||
|
||||
// 组件挂载时初始化地图
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
initMap()
|
||||
/**
|
||||
* 初始化地图基础结构
|
||||
*/
|
||||
const initializeMap = () => {
|
||||
// 清理旧实例
|
||||
if (svgInstance) svgInstance.remove()
|
||||
|
||||
const { width, height } = getContainerSize()
|
||||
const projection = createProjection()
|
||||
const pathGenerator = d3.geoPath().projection(projection)
|
||||
|
||||
// 创建SVG容器
|
||||
svgInstance = d3.select(mapContainer.value)
|
||||
.append('svg')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
|
||||
// 创建分层结构
|
||||
const mainGroup = svgInstance.append('g')
|
||||
mapGroup = mainGroup.append('g').attr('class', 'map-layer')
|
||||
markersGroup = mainGroup.append('g').attr('class', 'markers-layer')
|
||||
|
||||
// 绘制中国地图
|
||||
renderChinaMap(pathGenerator)
|
||||
|
||||
// 初始化缩放行为
|
||||
initializeZoomBehavior(mainGroup)
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染中国地图路径和文字
|
||||
* @param {d3.GeoPath} path - 路径生成器
|
||||
*/
|
||||
const renderChinaMap = (path) => {
|
||||
// 绘制省份路径
|
||||
mapGroup.append('g')
|
||||
.selectAll('path')
|
||||
.data(chinaData.features)
|
||||
.enter()
|
||||
.append('path')
|
||||
.attr('d', path)
|
||||
.attr('fill', '#e7e7e7')
|
||||
.attr('stroke', '#fff')
|
||||
|
||||
// 添加省份名称
|
||||
mapGroup.append('g')
|
||||
.selectAll('text')
|
||||
.data(chinaData.features)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('transform', d => `translate(${path.centroid(d)})`)
|
||||
.text(d => d.properties.name || '')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dominant-baseline', 'central')
|
||||
.style('font', '12px Arial')
|
||||
.attr('fill', '#333')
|
||||
.style('pointer-events', 'none')
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化缩放行为
|
||||
* @param {d3.Selection} group - 需要应用缩放的分组
|
||||
*/
|
||||
const initializeZoomBehavior = (group) => {
|
||||
zoomBehavior = d3.zoom()
|
||||
.scaleExtent([0.2, 68])
|
||||
.on('zoom', ({ transform }) => {
|
||||
group.attr('transform', transform)
|
||||
})
|
||||
svgInstance.call(zoomBehavior)
|
||||
}
|
||||
|
||||
// ==================== 路线相关逻辑 ====================
|
||||
/**
|
||||
* 更新路线和标记点
|
||||
*/
|
||||
const updateRoute = () => {
|
||||
if (!props.coordinates?.length) return
|
||||
if (!mapGroup) initializeMap()
|
||||
const projection = createProjection()
|
||||
const pathGenerator = d3.geoPath().projection(projection)
|
||||
|
||||
// 清理旧数据
|
||||
if (isRouteInitialized.value) {
|
||||
mapGroup.selectAll('.route-path').remove()
|
||||
markersGroup.selectAll('*').remove()
|
||||
isRouteInitialized.value = false
|
||||
emit('qvehuan1', isRouteInitialized.value)
|
||||
}
|
||||
|
||||
// 绘制新路线
|
||||
renderRoutePath(pathGenerator)
|
||||
renderMarkers(projection)
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制路径动画
|
||||
* @param {d3.GeoPath} path - 路径生成器
|
||||
*/
|
||||
const renderRoutePath = (path) => {
|
||||
const routeData = {
|
||||
type: "LineString",
|
||||
coordinates: props.coordinates
|
||||
}
|
||||
|
||||
mapGroup.append('path')
|
||||
.datum(routeData)
|
||||
.attr('class', 'route-path')
|
||||
.attr('d', path)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', '#f00')
|
||||
.attr('stroke-width', 0.1)
|
||||
.attr('stroke-dasharray', function() {
|
||||
return this.getTotalLength()
|
||||
})
|
||||
.attr('stroke-dashoffset', function() {
|
||||
return this.getTotalLength()
|
||||
})
|
||||
.transition()
|
||||
.duration(2000)
|
||||
.attr('stroke-dashoffset', 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制位置标记点
|
||||
* @param {d3.GeoProjection} projection - 地理投影实例
|
||||
*/
|
||||
const renderMarkers = (projection) => {
|
||||
props.coordinates.forEach(coord => {
|
||||
if (!isValidCoordinate(coord)) return
|
||||
|
||||
const [x, y] = projection(coord)
|
||||
markersGroup.append('circle')
|
||||
.attr('cx', x)
|
||||
.attr('cy', y)
|
||||
.attr('r', 0.3)
|
||||
.attr('fill', '#ff4757')
|
||||
.attr('stroke', 'white')
|
||||
.attr('stroke-width', 0)
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
const getContainerSize = () => ({
|
||||
width: mapContainer.value?.clientWidth || DEFAULT_MAP_SIZE.width,
|
||||
height: mapContainer.value?.clientHeight || DEFAULT_MAP_SIZE.height
|
||||
})
|
||||
|
||||
// 组件卸载时清理地图
|
||||
onUnmounted(() => {
|
||||
map?.remove()
|
||||
map = null
|
||||
const isValidCoordinate = (coord) =>
|
||||
Array.isArray(coord) && coord.length === 2 &&
|
||||
!isNaN(coord[0]) && !isNaN(coord[1])
|
||||
|
||||
// ==================== 全屏处理 ====================
|
||||
const handleWindowResize = () => {
|
||||
if (!isFullscreen.value) return
|
||||
initializeMap()
|
||||
updateRoute()
|
||||
}
|
||||
|
||||
const toggleFullscreen = () => {
|
||||
isFullscreen.value = !isFullscreen.value
|
||||
setTimeout(() => {
|
||||
initializeMap()
|
||||
updateRoute()
|
||||
}, 100) // 等待DOM更新
|
||||
}
|
||||
|
||||
// ==================== 生命周期钩子 ====================
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', handleWindowResize)
|
||||
// 强制初始化地图基础结构
|
||||
initializeMap() // [!code ++]
|
||||
// 仅在coordinates存在时更新路线
|
||||
if (props.coordinates?.length) { // [!code ++]
|
||||
updateRoute() // [!code ++]
|
||||
} // [!code ++]
|
||||
})
|
||||
|
||||
// 监听points变化自动绘制轨迹
|
||||
watch(() => props.points, (newPoints) => {
|
||||
drawTrajectory(newPoints || [])
|
||||
}, { deep: true, immediate: true })
|
||||
</script>
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', handleWindowResize)
|
||||
})
|
||||
|
||||
// ==================== 响应式监听 ====================
|
||||
watch(() => props.qvehuan, (newVal) => {
|
||||
isRouteInitialized.value = newVal
|
||||
updateRoute()
|
||||
})
|
||||
|
||||
watch(() => props.coordinates, () => {
|
||||
updateRoute()
|
||||
}, { deep: true })
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.map-container {
|
||||
position: relative;
|
||||
background-color: #f0f8ff;
|
||||
margin: 20px;
|
||||
overflow: hidden;
|
||||
touch-action: none;
|
||||
transition: all 0.3s ease;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.fullscreen {
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0 !important;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.fullscreen-btn {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 25px;
|
||||
z-index: 1001;
|
||||
padding: 8px 16px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.fullscreen-btn:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
@ -89,16 +89,16 @@ function gettreedata() {
|
||||
getNodesTree(treeForm.value).then((res: any) => {
|
||||
treedata.value = res.data
|
||||
treeloading.value = false
|
||||
if( treedata.value[0]){
|
||||
if (treedata.value[0]) {
|
||||
pathid.value = treedata.value[0].id
|
||||
nextTick(() => {
|
||||
treeRef.value?.setCurrentKey(pathid.value);
|
||||
});
|
||||
getdata()
|
||||
}else{
|
||||
nextTick(() => {
|
||||
treeRef.value?.setCurrentKey(pathid.value);
|
||||
});
|
||||
getdata()
|
||||
} else {
|
||||
tableData.value.length = 0
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
const pathid = ref()
|
||||
@ -589,7 +589,23 @@ 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) == 'xls' || getFileExtension(row.fileName) == 'docx' || getFileExtension(row.fileName) == 'doc' || getFileExtension(row.fileName) == 'bin') {
|
||||
console.log(row)
|
||||
// if(row.fileSize > '2'){
|
||||
// ElMessageBox.confirm(
|
||||
// '此文件内存过大无法预览,是否立即下载该文件?',
|
||||
// '警告',
|
||||
// {
|
||||
// confirmButtonText: '确定',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning',
|
||||
// }
|
||||
// )
|
||||
// .then(() => {
|
||||
// window.open(row.url);
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
if (getFileExtension(row.fileName) == 'pdf' || getFileExtension(row.fileName) == 'xlsx' || getFileExtension(row.fileName) == 'xls' || getFileExtension(row.fileName) == 'docx' || getFileExtension(row.fileName) == 'doc' || getFileExtension(row.fileName) == 'bin') {
|
||||
title1.value = row.fileName
|
||||
ViewfileUrl.value = row.url
|
||||
isViewfile.value = true
|
||||
@ -669,7 +685,7 @@ const FILE_ICONS = {
|
||||
txt: TextImg
|
||||
};
|
||||
// 获取文件图标
|
||||
const fileIcon = (row:any) => {
|
||||
const fileIcon = (row: any) => {
|
||||
const ext = row.fileName.split('.').pop()?.toLowerCase() || 'unknown';
|
||||
return FILE_ICONS[ext as keyof typeof FILE_ICONS] || (row.type == 'ZIP' ? ZipImg : TextImg);
|
||||
};
|
||||
@ -754,21 +770,20 @@ const fileIcon = (row:any) => {
|
||||
<el-table-column prop="fileName" label="预览" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="preview-icon">
|
||||
<img :src="fileIcon(row)" alt="file icon" class="file-icon"
|
||||
@click=" openPreview(row)">
|
||||
<img :src="fileIcon(row)" alt="file icon" class="file-icon" @click=" openPreview(row)">
|
||||
</div>
|
||||
</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 label="操作" width="100" align="center">
|
||||
<el-table-column 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/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_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;">
|
||||
<img src="@/assets/MenuIcon/xia1.png" alt="" @click="xiafile(scope.row)" title="下载"
|
||||
@ -807,23 +822,22 @@ const fileIcon = (row:any) => {
|
||||
<el-button @click="openUploadFolderDialog" type="primary">上传文件夹</el-button> -->
|
||||
<ZUpload />
|
||||
</el-form-item>
|
||||
<el-form-item v-else prop="fileName" label="文件名称:">
|
||||
<el-form-item v-else prop="fileName" label="文件名称:">
|
||||
<el-input v-model="fileObj.fileName" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="judge" label="关键字:" prop="taskName">
|
||||
<el-input v-model="fileObj.keywords" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="judge" label="描述:">
|
||||
<el-input v-model="fileObj.description" :rows="2" type="textarea" maxlength="400" show-word-limit />
|
||||
</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-input v-model="fileObj.description" :rows="2" type="textarea" maxlength="400"
|
||||
show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<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-dialog>
|
||||
<!-- 组件预览 -->
|
||||
@ -991,6 +1005,7 @@ const fileIcon = (row:any) => {
|
||||
padding: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
15
web/src/views/testdata/datamanagement/index.vue
vendored
15
web/src/views/testdata/datamanagement/index.vue
vendored
@ -1687,14 +1687,13 @@ function texexceltClose() {
|
||||
<el-form-item v-if="judge" label="描述:">
|
||||
<el-input v-model="fileObj.description" :rows="2" type="textarea" maxlength="400" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="width: 100%;display: flex;justify-content: end;">
|
||||
|
||||
</el-form>
|
||||
</el-scrollbar>
|
||||
<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>
|
||||
@ -1901,7 +1900,7 @@ function texexceltClose() {
|
||||
|
||||
</el-dialog>
|
||||
<!-- 轨迹地图 -->
|
||||
<el-dialog title="轨迹地图/图表" v-model="mapTrajectory" :before-close="mapClose" top="30px" draggable
|
||||
<el-dialog title="轨迹地图/图表" v-model="mapTrajectory" :close-on-click-modal="false" :before-close="mapClose" top="30px" draggable
|
||||
destroy-on-close>
|
||||
<div style="margin:0px 0px 15px 0px ;">
|
||||
<span>设定采样频率:</span>
|
||||
@ -1916,7 +1915,7 @@ function texexceltClose() {
|
||||
<div @click="tabbas = '1'" :class="tabbas == '1' ? 'mapbox_border' : 'mapbox_border1'">载体运动轨迹</div>
|
||||
<div @click="tabbas = '2'" :class="tabbas == '2' ? 'mapbox_border' : 'mapbox_border1'">高程变化动态图</div>
|
||||
</div>
|
||||
<div v-show="tabbas == '1'" style="width:100%;height:600px;overflow: hidden;margin-top: 20px;">
|
||||
<div v-show="tabbas == '1'" style="width:800px;height:600px;overflow: hidden;margin-top: 20px;">
|
||||
<MapChart :points="dynamicCoordinates" />
|
||||
</div>
|
||||
<div v-show="tabbas == '2'" style="width: 800px;height:600px;overflow: hidden;">
|
||||
@ -1926,7 +1925,7 @@ function texexceltClose() {
|
||||
</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>
|
||||
<!-- 文本编辑器 -->
|
||||
|
214
web/src/views/testdata/fileSynchronization/index.vue
vendored
214
web/src/views/testdata/fileSynchronization/index.vue
vendored
@ -9,7 +9,7 @@ import { ref, onMounted, nextTick, defineAsyncComponent, onBeforeUnmount } from
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox, ElMessage } from "element-plus";
|
||||
import { tstaskList, getTsNodesTree, tsFilesPage, deleteTsFilesByIds } from "@/api/datamanagement";
|
||||
import { listLocalAndBackup, compare, compareLocal, compareMd5, compareMinio, uploadToBackup, downloadToLocal, deleteTsFilesById, automaticFileBackup, obtainUrl, listBackupTree, listLocalTree } from "@/api/fileSynchronization";
|
||||
import { listLocalAndBackup, compare, compareLocalList,automaticFileBackupByIds, compareMd5List, compareMinioList, compareLocal, compareMd5, compareMinio, uploadToBackup, downloadToLocal, deleteTsFilesById, automaticFileBackup, obtainUrl, listBackupTree, listLocalTree } from "@/api/fileSynchronization";
|
||||
import { debounce } from 'lodash-es';
|
||||
import Page from '@/components/Pagination/page.vue';
|
||||
//text文件编辑功能
|
||||
@ -68,10 +68,25 @@ function diffFile() {
|
||||
});
|
||||
tabs.value = 1
|
||||
differential.value = true
|
||||
diffSure()
|
||||
diffChange()
|
||||
diffMiss()
|
||||
diffSure(false)
|
||||
diffChange(false)
|
||||
diffMiss(false)
|
||||
}
|
||||
|
||||
function diffFile2() {
|
||||
const seen = new Set();
|
||||
comparearr.value = comparearr.value.filter(item => {
|
||||
return seen.has(item.id) ? false : seen.add(item.id);
|
||||
});
|
||||
getchayi()
|
||||
}
|
||||
|
||||
//两棵树
|
||||
function gettreeTwo() {
|
||||
getlocaltree()
|
||||
getminiotree()
|
||||
}
|
||||
|
||||
function backups() {
|
||||
ElMessageBox.confirm(
|
||||
'您确定要将文件/文件夹自动备份到备份空间吗?',
|
||||
@ -85,16 +100,73 @@ function backups() {
|
||||
.then(() => {
|
||||
worktree.value = true
|
||||
worktree1.value = true
|
||||
automaticFileBackup({ nodeId: pathid.value, taskId: projectId.value }).then((res: any) => {
|
||||
const seen = new Set();
|
||||
comparearr.value = comparearr.value.filter(item => {
|
||||
return seen.has(item.id) ? false : seen.add(item.id);
|
||||
});
|
||||
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
|
||||
}
|
||||
if(ids.length > 0){
|
||||
automaticFileBackupByIds(params).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success(res.msg)
|
||||
getlocaltree()
|
||||
getminiotree()
|
||||
}
|
||||
})
|
||||
}else{
|
||||
automaticFileBackup(params).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success(res.msg)
|
||||
getlocaltree()
|
||||
getminiotree()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
////////////
|
||||
function getchayi() {
|
||||
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
|
||||
}
|
||||
compareLocalList(params).then((res: any) => {
|
||||
// debugger
|
||||
localOnlyFiles.value = res.data
|
||||
gettreeTwo()
|
||||
})
|
||||
compareMd5List(params).then((res: any) => {
|
||||
md5MismatchedFiles.value = res.data
|
||||
gettreeTwo()
|
||||
})
|
||||
compareMinioList(params).then((res: any) => {
|
||||
minioOnlyFiles.value = res.data
|
||||
gettreeTwo()
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//文件差异性对比结果
|
||||
const comparearr: any = ref([])
|
||||
const localOnlyFiles: any = ref([])
|
||||
@ -107,7 +179,7 @@ const loading3 = ref(false)
|
||||
const sureSize = ref(10)
|
||||
const sureTotal = ref()
|
||||
const sureCurrent = ref(1)
|
||||
function diffSure() {
|
||||
function diffSure(row: any) {
|
||||
loading1.value = true
|
||||
const ids = []
|
||||
const params: any = {}
|
||||
@ -134,7 +206,7 @@ function diffSure() {
|
||||
const ChangeSize = ref(10)
|
||||
const ChangeTotal = ref()
|
||||
const ChangeCurrent = ref(1)
|
||||
function diffChange() {
|
||||
function diffChange(row: any) {
|
||||
loading2.value = true
|
||||
const ids = []
|
||||
const params: any = {}
|
||||
@ -155,13 +227,14 @@ function diffChange() {
|
||||
ChangeSize.value = res.data.size
|
||||
ChangeTotal.value = res.data.total
|
||||
ChangeCurrent.value = res.data.current
|
||||
|
||||
})
|
||||
}
|
||||
//文件对比-缺失内容
|
||||
const MisseSize = ref(10)
|
||||
const MissTotal = ref()
|
||||
const MissCurrent = ref(1)
|
||||
function diffMiss() {
|
||||
function diffMiss(row: any) {
|
||||
loading3.value = true
|
||||
const ids = []
|
||||
const params: any = {}
|
||||
@ -182,6 +255,7 @@ function diffMiss() {
|
||||
MisseSize.value = res.data.size
|
||||
MissTotal.value = res.data.total
|
||||
MissCurrent.value = res.data.current
|
||||
|
||||
})
|
||||
}
|
||||
//差异染色
|
||||
@ -189,7 +263,6 @@ function diffMiss() {
|
||||
function diffColor() {
|
||||
// 1. 使用Map优化查找性能
|
||||
const createMap = (arr: any[]) => new Map(arr.map(item => [item.id, item]));
|
||||
|
||||
const localMap = createMap(localOnlyFiles.value);
|
||||
const md5Map = createMap(md5MismatchedFiles.value);
|
||||
const minioMap = createMap(minioOnlyFiles.value);
|
||||
@ -303,8 +376,8 @@ const handleCheckChange = (
|
||||
// 使用防抖优化批量操作
|
||||
const updateCompare = debounce(() => {
|
||||
//
|
||||
comparearr.value = getclickdata(workall.value);
|
||||
const comparearrval = getclickdata(workall.value);
|
||||
comparearr.value = getclickdata(workall.value);
|
||||
const comparearrval = getclickdata(workall.value);
|
||||
// 转换节点格式
|
||||
const checkedKeys = comparearrval
|
||||
.map(node => node.id)
|
||||
@ -453,8 +526,8 @@ const backupsChange = (
|
||||
|
||||
const updateCompare = debounce(() => {
|
||||
// comparearr.value.length = 0
|
||||
comparearr.value = getclickdata(workall.value);
|
||||
const comparearrval = getclickdata(workall.value);
|
||||
comparearr.value = getclickdata(workall.value);
|
||||
const comparearrval = getclickdata(workall.value);
|
||||
// 转换节点格式
|
||||
const checkedKeys = comparearrval
|
||||
.map(node => node.id)
|
||||
@ -598,8 +671,8 @@ function tableBeifen(row: any) {
|
||||
uploadToBackup({ parameterLists: params }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
ElMessage.success("上传成功")
|
||||
diffSure()
|
||||
diffChange()
|
||||
diffSure(false)
|
||||
diffChange(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -630,8 +703,8 @@ function moretableBeifen() {
|
||||
loading2.value = true
|
||||
uploadToBackup({ parameterLists: beifenArr3 }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
diffSure()
|
||||
diffChange()
|
||||
diffSure(false)
|
||||
diffChange(false)
|
||||
ElMessage.success("上传成功")
|
||||
}
|
||||
})
|
||||
@ -662,8 +735,8 @@ function tablerestore(row: any) {
|
||||
downloadToLocal({ parameterLists: params }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
ElMessage.success("恢复成功")
|
||||
diffChange()
|
||||
diffMiss()
|
||||
diffChange(false)
|
||||
diffMiss(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -694,8 +767,8 @@ function moretablerestore() {
|
||||
downloadToLocal({ parameterLists: restoreArr3 }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
ElMessage.success("恢复成功")
|
||||
diffChange()
|
||||
diffMiss()
|
||||
diffChange(false)
|
||||
diffMiss(false)
|
||||
}
|
||||
})
|
||||
|
||||
@ -720,7 +793,7 @@ function delhuifu() {
|
||||
deleteTsFilesByIds({ ids: ids.value.join(','), type: 'minio' }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
ElMessage.success("删除成功")
|
||||
diffMiss()
|
||||
diffMiss(false)
|
||||
}
|
||||
})
|
||||
|
||||
@ -759,7 +832,7 @@ function bfclick(type: any) {
|
||||
uploadToBackup({ parameterLists: beifenArr3 }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
ElMessage.success("上传成功")
|
||||
diffChange()
|
||||
diffChange(false)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -771,7 +844,7 @@ function bfclick(type: any) {
|
||||
downloadToLocal({ parameterLists: restoreArr3 }).then((res: any) => {
|
||||
if (res.code == '0') {
|
||||
ElMessage.success("恢复成功")
|
||||
diffChange()
|
||||
diffChange(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -966,12 +1039,28 @@ const tabs = ref(1)
|
||||
</div>
|
||||
</aside>
|
||||
<section class="silderRight">
|
||||
<div class="tree_button">
|
||||
<el-button type="primary" :disabled="worktree && worktree1" @click="backups()">文件自动备份</el-button>
|
||||
<el-button type="primary" :disabled="worktree && worktree1" @click="diffFile()">文件差异性对比</el-button>
|
||||
<el-button type="primary" :disabled="worktree && worktree1"
|
||||
@click="differential = true">查看本次差异性对比</el-button>
|
||||
<div style="display: flex;justify-content: space-between;align-items: center;">
|
||||
<div class="legend">
|
||||
<div class="legend_box">
|
||||
<div class="legend_color1"></div>
|
||||
<div class="legend_text">工作空间新增文件</div>
|
||||
</div>
|
||||
<div class="legend_box">
|
||||
<div class="legend_color2"></div>
|
||||
<div class="legend_text">工作空间已删除文件</div>
|
||||
</div>
|
||||
<div class="legend_box">
|
||||
<div class="legend_color3"></div>
|
||||
<div class="legend_text">工作空间内容变动文件</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tree_button">
|
||||
<el-button type="primary" :disabled="worktree && worktree1" @click="backups()">文件备份</el-button>
|
||||
<el-button type="primary" :disabled="worktree && worktree1" @click="diffFile2()">差异检测</el-button>
|
||||
<el-button type="primary" :disabled="worktree && worktree1" @click="diffFile()">差异批量处理</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tree_box">
|
||||
<div class="tree_left">
|
||||
<div class="tree_title">工作空间:</div>
|
||||
@ -987,9 +1076,9 @@ const tabs = ref(1)
|
||||
<span class="text">
|
||||
{{ data.fileName }}({{ data.isFile == 'FOLDER' ? data.children.length :
|
||||
data.fileSize + 'MB' }})
|
||||
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
||||
<!-- <span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
||||
(data.station
|
||||
== '2' ? '已变更' : '已删除') }})</span>
|
||||
== '2' ? '已变更' : '已删除') }})</span> -->
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
@ -1022,9 +1111,9 @@ const tabs = ref(1)
|
||||
<span class="text">{{ data.fileName }}({{ data.isFile == 'FOLDER' ?
|
||||
data.children.length :
|
||||
data.fileSize + 'MB' }})</span>
|
||||
<span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
||||
<!-- <span v-if="data.station != '0'">({{ data.station == '1' ? '新增' :
|
||||
(data.station
|
||||
== '2' ? '已变更' : '已删除') }})</span>
|
||||
== '2' ? '已变更' : '已删除') }})</span> -->
|
||||
</span>
|
||||
</template>
|
||||
</el-tree-v2>
|
||||
@ -1042,12 +1131,12 @@ const tabs = ref(1)
|
||||
</div>
|
||||
</div>
|
||||
<!-- 文件差异性对比 -->
|
||||
<el-dialog title="文件差异性对比" v-model="differential" width="50%" :before-close="diffClose" top="30px"
|
||||
<el-dialog title="差异批量处理" v-model="differential" width="50%" :before-close="diffClose" top="30px"
|
||||
draggable destroy-on-close>
|
||||
<div class="tabbs_all">
|
||||
<div @click="tabs = 1" :class="tabs == 1 ? 'tabbs_box1' : 'tabbs_box'">新增内容</div>
|
||||
<div @click="tabs = 2" :class="tabs == 2 ? 'tabbs_box1' : 'tabbs_box'">变更内容</div>
|
||||
<div @click="tabs = 3" :class="tabs == 3 ? 'tabbs_box1' : 'tabbs_box'">缺失内容</div>
|
||||
<div @click="tabs = 1" :class="tabs == 1 ? 'tabbs_box1' : 'tabbs_box'">新增文件</div>
|
||||
<div @click="tabs = 2" :class="tabs == 2 ? 'tabbs_box1' : 'tabbs_box'">修改文件</div>
|
||||
<div @click="tabs = 3" :class="tabs == 3 ? 'tabbs_box1' : 'tabbs_box'">删除文件</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- <el-scrollbar height="400px"> -->
|
||||
@ -1086,7 +1175,7 @@ const tabs = ref(1)
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<Page :total="sureTotal" v-model:size="sureSize" v-model:current="sureCurrent"
|
||||
@pagination="diffSure()">
|
||||
@pagination="diffSure(false)">
|
||||
</Page>
|
||||
</div>
|
||||
<div class="newContent" v-if="tabs == 2">
|
||||
@ -1129,7 +1218,7 @@ const tabs = ref(1)
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<Page :total="ChangeTotal" v-model:size="ChangeSize" v-model:current="ChangeCurrent"
|
||||
@pagination="diffChange()">
|
||||
@pagination="diffChange(false)">
|
||||
</Page>
|
||||
</div>
|
||||
<div class="newContent" v-if="tabs == 3">
|
||||
@ -1171,7 +1260,7 @@ const tabs = ref(1)
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<Page :total="MissTotal" v-model:size="MisseSize" v-model:current="MissCurrent"
|
||||
@pagination="diffMiss()">
|
||||
@pagination="diffMiss(false)">
|
||||
</Page>
|
||||
</div>
|
||||
<!-- </el-scrollbar> -->
|
||||
@ -1306,7 +1395,7 @@ const tabs = ref(1)
|
||||
|
||||
.tree_left {
|
||||
width: 49%;
|
||||
height: calc(78vh);
|
||||
height: calc(77vh);
|
||||
|
||||
|
||||
.tree_title {
|
||||
@ -1327,7 +1416,7 @@ const tabs = ref(1)
|
||||
padding: 5px;
|
||||
background-color: green;
|
||||
color: #fff;
|
||||
margin-bottom: 5px !important;
|
||||
// margin-bottom: 5px !important;
|
||||
}
|
||||
|
||||
.custom-tree-node2 {
|
||||
@ -1468,4 +1557,45 @@ const tabs = ref(1)
|
||||
border-bottom: 3px solid #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
.legend {
|
||||
width: 40%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #409eff;
|
||||
padding: 5px 8px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
|
||||
.legend_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.legend_color1 {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.legend_color2 {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.legend_color3 {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.legend_text {
|
||||
font-size: 14px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user