文件上传参数修改
This commit is contained in:
parent
7741240bc6
commit
88e0ce82cd
@ -16,6 +16,15 @@
|
||||
"@kangc/v-md-editor": "^2.3.15",
|
||||
"@soerenmartius/vue3-clipboard": "^0.1.2",
|
||||
"@tinymce/tinymce-vue": "^5.1.1",
|
||||
"@tiptap/extension-blockquote": "^2.11.5",
|
||||
"@tiptap/extension-code-block": "^2.11.5",
|
||||
"@tiptap/extension-document": "^2.11.5",
|
||||
"@tiptap/extension-paragraph": "^2.11.5",
|
||||
"@tiptap/extension-strike": "^2.11.5",
|
||||
"@tiptap/extension-text": "^2.11.5",
|
||||
"@tiptap/extension-underline": "^2.11.5",
|
||||
"@tiptap/starter-kit": "^2.11.5",
|
||||
"@tiptap/vue-3": "^2.11.5",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@vueuse/core": "^9.1.1",
|
||||
"@vueuse/integrations": "^9.13.0",
|
||||
@ -23,7 +32,7 @@
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"aplayer": "^1.10.1",
|
||||
"artplayer": "^4.6.1",
|
||||
"axios": "^1.2.0",
|
||||
"axios": "^1.8.4",
|
||||
"beautify-qrcode": "^1.0.3",
|
||||
"better-scroll": "^2.4.2",
|
||||
"d3": "^7.9.0",
|
||||
@ -61,6 +70,7 @@
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-pdf-embed": "^1.1.4",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue-virtual-scroller": "^2.0.0-beta.1",
|
||||
"vue3-print-nb": "^0.1.4",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"xlsx": "^0.18.5"
|
||||
|
@ -16,10 +16,6 @@ let common = useCommon();
|
||||
let route = useRoute();
|
||||
// import IconPrev from '~icons/custom/prev';
|
||||
// import IconNext from '~icons/custom/next';
|
||||
|
||||
|
||||
|
||||
|
||||
let currentVideo = ref(null);
|
||||
|
||||
const openTarget = (mode) => {
|
||||
|
147
web/src/components/textEditing/index.vue
Normal file
147
web/src/components/textEditing/index.vue
Normal file
@ -0,0 +1,147 @@
|
||||
<!-- src/components/RichTextEditor.vue -->
|
||||
<template>
|
||||
<div class="editor-wrapper">
|
||||
<!-- 工具栏 -->
|
||||
<div v-if="editor" class="toolbar">
|
||||
<button @click="editor.chain().focus().toggleBold().run()"
|
||||
:class="{ 'is-active': editor.isActive('bold') }">
|
||||
<strong>B</strong>
|
||||
</button>
|
||||
<button @click="editor.chain().focus().toggleItalic().run()"
|
||||
:class="{ 'is-active': editor.isActive('italic') }">
|
||||
<em>I</em>
|
||||
</button>
|
||||
<button @click="editor.chain().focus().toggleHeading({ level: 2 }).run()"
|
||||
:class="{ 'is-active': editor.isActive('heading') }">
|
||||
H2
|
||||
</button>
|
||||
</div>
|
||||
<el-scrollbar height="600px">
|
||||
<!-- 编辑器主体 -->
|
||||
<editor-content :editor="editor" class="editor-content" />
|
||||
</el-scrollbar>
|
||||
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="actions">
|
||||
<button @click="loadContent" class="btn-load">加载文件</button>
|
||||
<button @click="saveContent" class="btn-save">保存文件</button>
|
||||
</div>
|
||||
|
||||
<!-- 状态提示 -->
|
||||
<div v-if="statusMessage" class="status">
|
||||
{{ statusMessage }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { EditorContent, useEditor } from '@tiptap/vue-3'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import axios from 'axios'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const statusMessage = ref('')
|
||||
|
||||
// 初始化编辑器
|
||||
const editor = useEditor({
|
||||
content: '',
|
||||
extensions: [
|
||||
StarterKit.configure({
|
||||
heading: {
|
||||
levels: [2, 3],
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
// 加载文件内容
|
||||
const loadContent = async () => {
|
||||
try {
|
||||
// const response = await axios.get('/api/files', {
|
||||
// params: { filePath: 'demo.txt' }
|
||||
// })
|
||||
const data = "<p>124535</p><p>4554</p><p>4545ljgljk</p><p><strong>lk'k;'k;'l;k'</strong></p><h2><strong><em>;l'kl;'kl;'</em></strong></h2><h2><strong><em>;'kl;';kl'kl;'l;k'k;l'k';lk';';k'l;'k;'kl;</em></strong></h2>"
|
||||
editor.value.commands.setContent(data)
|
||||
// statusMessage.value = '内容加载成功'
|
||||
// setTimeout(() => statusMessage.value = '', 2000)
|
||||
} catch (error) {
|
||||
statusMessage.value = `加载失败: ${error.response?.data || error.message}`
|
||||
}
|
||||
}
|
||||
|
||||
// 保存文件内容
|
||||
const saveContent = async () => {
|
||||
try {
|
||||
const content = editor.value.getHTML()
|
||||
await axios.post('/api/files', {
|
||||
filePath: 'demo.txt',
|
||||
content: content
|
||||
})
|
||||
statusMessage.value = '保存成功'
|
||||
setTimeout(() => statusMessage.value = '', 2000)
|
||||
} catch (error) {
|
||||
statusMessage.value = `保存失败: ${error.response?.data || error.message}`
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor-wrapper {
|
||||
max-width: 100%;
|
||||
margin: 20px auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
margin-bottom: 10px;
|
||||
padding: 8px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.toolbar button {
|
||||
margin-right: 8px;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.toolbar button.is-active {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border-color: #007bff;
|
||||
}
|
||||
|
||||
.editor-content {
|
||||
min-height: 600px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-load {
|
||||
background: #17a2b8;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-top: 10px;
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
</style>
|
@ -1,112 +1,139 @@
|
||||
<template>
|
||||
<div ref="chartContainer" class="chart-container"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
const props = defineProps<{
|
||||
chartData: Array<{ x: number; y: number }>;
|
||||
}>();
|
||||
|
||||
const chartContainer = ref<HTMLElement | null>(null);
|
||||
let svg: d3.Selection<SVGSVGElement, unknown, null, undefined>;
|
||||
let xScale: d3.ScaleLinear<number, number>;
|
||||
let yScale: d3.ScaleLinear<number, number>;
|
||||
let line: d3.Line<{ x: number; y: number }>;
|
||||
|
||||
const initChart = () => {
|
||||
if (!chartContainer.value) return;
|
||||
|
||||
// 清除旧图表
|
||||
d3.select(chartContainer.value).select("svg").remove();
|
||||
|
||||
// 创建SVG容器
|
||||
svg = d3.select(chartContainer.value)
|
||||
.append('svg')
|
||||
.attr('width', '100%')
|
||||
.attr('height', '100%');
|
||||
|
||||
// 初始化比例尺
|
||||
xScale = d3.scaleLinear()
|
||||
.range([50, 750]);
|
||||
|
||||
yScale = d3.scaleLinear()
|
||||
.range([400, 50]);
|
||||
|
||||
// 初始化折线生成器
|
||||
line = d3.line<{ x: number; y: number }>()
|
||||
.x(d => xScale(d.x))
|
||||
.y(d => yScale(d.y));
|
||||
|
||||
// 添加坐标轴容器
|
||||
svg.append('g')
|
||||
.attr('class', 'x-axis')
|
||||
.attr('transform', 'translate(0, 400)');
|
||||
|
||||
svg.append('g')
|
||||
.attr('class', 'y-axis')
|
||||
.attr('transform', 'translate(50, 0)');
|
||||
|
||||
// 创建路径元素
|
||||
svg.append('path')
|
||||
.attr('class', 'line')
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', 'steelblue')
|
||||
.attr('stroke-width', 2);
|
||||
svg.append("text")
|
||||
<div ref="chartContainer" class="chart-container"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
const props = defineProps<{
|
||||
chartData: Array<{ x: number; y: number }>;
|
||||
}>();
|
||||
|
||||
const chartContainer = ref<HTMLElement | null>(null);
|
||||
let svg: d3.Selection<SVGSVGElement, unknown, null, undefined>;
|
||||
let xScale: d3.ScaleLinear<number, number>;
|
||||
let yScale: d3.ScaleLinear<number, number>;
|
||||
let line: d3.Line<{ x: number; y: number }>;
|
||||
|
||||
const initChart = () => {
|
||||
if (!chartContainer.value) return;
|
||||
|
||||
// 清除旧图表
|
||||
d3.select(chartContainer.value).select("svg").remove();
|
||||
|
||||
// 创建SVG容器
|
||||
svg = d3.select(chartContainer.value)
|
||||
.append('svg')
|
||||
.attr('width', '100%')
|
||||
.attr('height', '100%');
|
||||
|
||||
// 初始化比例尺
|
||||
xScale = d3.scaleLinear()
|
||||
.range([50, 750]);
|
||||
|
||||
yScale = d3.scaleLinear()
|
||||
.range([400, 50]);
|
||||
|
||||
// 初始化折线生成器
|
||||
line = d3.line<{ x: number; y: number }>()
|
||||
.x(d => xScale(d.x))
|
||||
.y(d => yScale(d.y));
|
||||
|
||||
// 添加坐标轴容器
|
||||
svg.append('g')
|
||||
.attr('class', 'x-axis')
|
||||
.attr('transform', 'translate(0, 400)');
|
||||
|
||||
svg.append('g')
|
||||
.attr('class', 'y-axis')
|
||||
.attr('transform', 'translate(50, 0)');
|
||||
|
||||
// 创建路径元素
|
||||
svg.append('path')
|
||||
.attr('class', 'line')
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', 'steelblue')
|
||||
.attr('stroke-width', 2);
|
||||
svg.append("text")
|
||||
.attr("class", "x-axis-label") // 修改为独立class
|
||||
.attr("transform", "translate(400,440)")
|
||||
.style("text-anchor", "middle")
|
||||
.text("时间 (s)");
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-axis-label")
|
||||
.attr("transform", "rotate(-90) translate(-220, 15)") // 调整定位参数
|
||||
.style("text-anchor", "middle")
|
||||
.text("高度 (m)");
|
||||
|
||||
// 首次绘制
|
||||
svg.append("text")
|
||||
.attr("class", "y-axis-label")
|
||||
.attr("transform", "rotate(-90) translate(-220, 15)") // 调整定位参数
|
||||
.style("text-anchor", "middle")
|
||||
.text("高度 (m)");
|
||||
svg.call(d3.zoom()
|
||||
.scaleExtent([1, 8])
|
||||
.on('zoom', (event) => {
|
||||
xScale.eventTransform.rescaleX(xScale);
|
||||
yScale.eventTransform.rescaleY(yScale);
|
||||
updateChart();
|
||||
};
|
||||
|
||||
const updateChart = () => {
|
||||
// 更新比例尺域
|
||||
xScale.domain(d3.extent(props.chartData, d => d.x) as [number, number]);
|
||||
yScale.domain([0, d3.max(props.chartData, d => d.y)!]);
|
||||
|
||||
// 更新折线
|
||||
svg.select('.line')
|
||||
.datum(props.chartData)
|
||||
.transition()
|
||||
.duration(500)
|
||||
.attr('d', line);
|
||||
|
||||
// 更新坐标轴
|
||||
svg.select('.x-axis')
|
||||
.transition()
|
||||
.duration(500)
|
||||
.call(d3.axisBottom(xScale));
|
||||
|
||||
svg.select('.y-axis')
|
||||
.transition()
|
||||
.duration(500)
|
||||
.call(d3.axisLeft(yScale));
|
||||
};
|
||||
|
||||
onMounted(initChart);
|
||||
watch(() => props.chartData, updateChart, { deep: true });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container {
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
border: 1px solid #eee;
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
}));
|
||||
// 首次绘制
|
||||
updateChart();
|
||||
};
|
||||
|
||||
const updateChart = () => {
|
||||
svg.attr('key', Date.now());
|
||||
// 更新前先移除旧坐标轴
|
||||
svg.select('.x-axis').remove();
|
||||
svg.select('.y-axis').remove();
|
||||
|
||||
// 重新创建坐标轴容器
|
||||
const xAxis = svg.append('g')
|
||||
.attr('class', 'x-axis')
|
||||
.attr('transform', `translate(0, ${yScale.range()[0]})`);
|
||||
|
||||
const yAxis = svg.append('g')
|
||||
.attr('class', 'y-axis')
|
||||
.attr('transform', `translate(${xScale.range()[0]}, 0)`);
|
||||
// 更新比例尺域
|
||||
const xDomain = props.chartData.length > 0 ?
|
||||
d3.extent(props.chartData, d => d.x) : [0, 1];
|
||||
xScale.domain(xDomain as [number, number]);
|
||||
yScale.domain([0, d3.max(props.chartData, d => d.y)!]);
|
||||
|
||||
// 更新折线
|
||||
svg.select('.line')
|
||||
.datum(props.chartData)
|
||||
.transition()
|
||||
.duration(500)
|
||||
.attr('d', line);
|
||||
|
||||
// 更新坐标轴
|
||||
svg.select('.x-axis')
|
||||
.transition()
|
||||
.duration(500)
|
||||
.call(d3.axisBottom(xScale));
|
||||
|
||||
svg.select('.y-axis')
|
||||
.transition()
|
||||
.duration(500)
|
||||
.call(d3.axisLeft(yScale));
|
||||
};
|
||||
|
||||
onMounted(initChart);
|
||||
watch(() => props.chartData, updateChart, { deep: true });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container {
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
border: 1px solid #eee;
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.x-axis text {
|
||||
font-size: 10px;
|
||||
transform: rotate(-45deg);
|
||||
text-anchor: end;
|
||||
}
|
||||
|
||||
.x-axis-label,
|
||||
.y-axis-label {
|
||||
@ -114,4 +141,4 @@
|
||||
fill: #666;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</style>
|
@ -22,7 +22,7 @@
|
||||
<!-- 预览文件的地方(用于渲染) -->
|
||||
<div ref="file" :class="{ 'fullscreen-doc': fullscreen }"></div>
|
||||
</div>
|
||||
<div v-if="props.type == 'xlsx' || props.type == 'xls' " v-loading="loading" element-loading-text="正在加载报告..."
|
||||
<div v-if="props.type == 'xlsx' || props.type == 'xls'" v-loading="loading" element-loading-text="正在加载报告..."
|
||||
element-loading-background="rgba(122, 122, 122, 0.8)" class="docWrap">
|
||||
<div class="tab">
|
||||
<el-radio-group size="small" v-model="excel.sheetNameActive" @change="getSheetNameTable">
|
||||
@ -35,13 +35,22 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="props.type == 'pdf'">
|
||||
|
||||
<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"
|
||||
:class="{ 'fullscreen-bin': fullscreen }">
|
||||
<pre>{{ hexContent }}</pre>
|
||||
<div class="scroller">
|
||||
<el-scrollbar :height="fullscreen?'90vh':'54vh'">
|
||||
<pre v-for="(item, index) in visibleChunks" :key="hexContent.currentChunk + '-' + index"
|
||||
class="hex-content">{{ item.content }}</pre>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="pagination-control">
|
||||
<el-pagination layout="prev, pager, next" :current-page="hexContent.currentChunk + 1"
|
||||
:page-size="hexContent.chunkSize" :total="hexContent.rawData.length" :pager-count="5"
|
||||
@current-change="handlePageChange" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="props.type === 'pptx'" v-loading="loading" class="ppt-container">
|
||||
<div class="ppt-controls">
|
||||
@ -58,11 +67,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, nextTick, onMounted, getCurrentInstance, reactive, toRefs } from 'vue'
|
||||
import { ref, nextTick, onMounted, getCurrentInstance, reactive, toRefs, onBeforeUnmount, computed } from 'vue'
|
||||
import * as docx from 'docx-preview'
|
||||
import * as XLSX from "xlsx";
|
||||
import PptxGenJS from 'pptxgenjs';
|
||||
import axios from 'axios';
|
||||
// import { RecycleScroller } from 'vue-virtual-scroller'
|
||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||
const props = defineProps({
|
||||
showTime: {
|
||||
type: Boolean,
|
||||
@ -92,7 +103,12 @@ const dialogVisible = ref(props.showTime);
|
||||
const emits = defineEmits();
|
||||
const emptyTips = ref('暂无内容');
|
||||
const fullscreen = ref(false);
|
||||
const hexContent = ref('');
|
||||
const hexContent = ref({
|
||||
rawData: new Uint8Array(0), // 初始化为空数组
|
||||
chunkSize: 1024,
|
||||
totalChunks: 0,
|
||||
currentChunk: 0
|
||||
});
|
||||
const data = reactive({
|
||||
excel: {
|
||||
// 数据
|
||||
@ -112,30 +128,56 @@ const currentSlide = ref(0);
|
||||
const totalSlides = ref(0);
|
||||
|
||||
const prevSlide = () => {
|
||||
if (currentSlide.value > 0) {
|
||||
currentSlide.value--;
|
||||
scrollToSlide();
|
||||
}
|
||||
if (currentSlide.value > 0) {
|
||||
currentSlide.value--;
|
||||
scrollToSlide();
|
||||
}
|
||||
};
|
||||
|
||||
const nextSlide = () => {
|
||||
if (currentSlide.value < totalSlides.value - 1) {
|
||||
currentSlide.value++;
|
||||
scrollToSlide();
|
||||
}
|
||||
if (currentSlide.value < totalSlides.value - 1) {
|
||||
currentSlide.value++;
|
||||
scrollToSlide();
|
||||
}
|
||||
};
|
||||
const visibleChunks = computed(() => {
|
||||
// debugger
|
||||
if (!hexContent.value.rawData?.length) {
|
||||
console.log('No raw data available');
|
||||
return [];
|
||||
}
|
||||
|
||||
const start = hexContent.value.currentChunk * hexContent.value.chunkSize;
|
||||
const end = start + hexContent.value.chunkSize;
|
||||
const chunkData = hexContent.value.rawData.subarray(start, end);
|
||||
const content = arrayBufferToHex(chunkData);
|
||||
return [{
|
||||
index: hexContent.value.currentChunk,
|
||||
content: content
|
||||
}];
|
||||
});
|
||||
const handlePageChange = (currentPage) => {
|
||||
hexContent.value.currentChunk = currentPage - 1;
|
||||
hexContent.value = { ...hexContent.value }; // 触发响应式更新
|
||||
};
|
||||
const scrollToSlide = () => {
|
||||
const slides = proxy.$refs.pptViewer.querySelectorAll('.slide-container');
|
||||
slides[currentSlide.value].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center'
|
||||
});
|
||||
const slides = proxy.$refs.pptViewer.querySelectorAll('.slide-container');
|
||||
slides[currentSlide.value].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center'
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
init(props.type);
|
||||
// if (buffer.length === 0) {
|
||||
// hexContent.value.rawData = new Uint8Array(0);
|
||||
// }
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
if (hexContent.value.rawData) {
|
||||
hexContent.value.rawData = null; // 释放内存
|
||||
}
|
||||
})
|
||||
|
||||
// 前一个页面调用的init 我在前一个页面根据文件名字后缀已经判断是什么类型的文件了
|
||||
function init(type) {
|
||||
typeName.value = type;
|
||||
@ -191,7 +233,7 @@ function init(type) {
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
} else if (type == "xlsx"|| type == "xls") {
|
||||
} else if (type == "xlsx" || type == "xls") {
|
||||
// //表格
|
||||
loading.value = true;
|
||||
axios.request({
|
||||
@ -245,6 +287,7 @@ function init(type) {
|
||||
loading.value = false;
|
||||
});
|
||||
} else if (type === "bin") {
|
||||
|
||||
loading.value = true;
|
||||
axios.request({
|
||||
method: "GET",
|
||||
@ -253,15 +296,16 @@ function init(type) {
|
||||
}).then((res) => {
|
||||
if (res.data) {
|
||||
const buffer = new Uint8Array(res.data);
|
||||
hexContent.value = arrayBufferToHex(buffer);
|
||||
hexContent.value.rawData = new Uint8Array(buffer); // 保持响应式引用
|
||||
hexContent.value.totalChunks = Math.ceil(buffer.length / 1024);
|
||||
hexContent.value.currentChunk = 0;
|
||||
loading.value = false;
|
||||
}
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
// 处理错误
|
||||
});
|
||||
} else if (type === "pptx") {
|
||||
debugger
|
||||
// debugger
|
||||
loading.value = true;
|
||||
axios.request({
|
||||
method: "GET",
|
||||
@ -322,12 +366,12 @@ function getSheetNameTable(sheetName) {
|
||||
}
|
||||
// 新增转换方法
|
||||
function arrayBufferToHex(buffer) {
|
||||
// debugger
|
||||
return Array.from(buffer)
|
||||
.map(byte => byte.toString(16).padStart(2, '0'))
|
||||
.join(' ')
|
||||
.replace(/([\da-f]{2} ){16}/g, '$&\n'); // 每16字节换行
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
emits('update', false)
|
||||
}
|
||||
@ -617,4 +661,35 @@ html body {
|
||||
background: white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.hex-container {
|
||||
.scroller {
|
||||
// height: calc(54vh);
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
|
||||
.hex-content {
|
||||
// font-family: 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
padding: 12px;
|
||||
background-color: #fafafa;
|
||||
counter-increment: line;
|
||||
color: #333;
|
||||
|
||||
&::before {
|
||||
content: counter(line, decimal-leading-zero) ": ";
|
||||
color: #666;
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-control {
|
||||
margin-top: 12px;
|
||||
padding: 8px;
|
||||
background: #fff;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -582,7 +582,6 @@ 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') {
|
||||
title1.value = row.fileName
|
||||
ViewfileUrl.value = row.url
|
||||
@ -667,14 +666,13 @@ 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);
|
||||
};
|
||||
// 判断是否可预览(基于文件图标映射表)
|
||||
const shouldPreview = (filename: string): boolean => {
|
||||
// 获取文件扩展名并转为小写,兼容无扩展名情况
|
||||
const fileExtension = filename.split('.').pop()?.toLowerCase() || '';
|
||||
|
||||
// 通过 keyof 类型保护确保类型安全
|
||||
return Object.keys(FILE_ICONS).includes(fileExtension);
|
||||
};
|
||||
// // 判断是否可预览(基于文件图标映射表)
|
||||
// const shouldPreview = (filename: string): boolean => {
|
||||
// // 获取文件扩展名并转为小写,兼容无扩展名情况
|
||||
// const fileExtension = filename.split('.').pop()?.toLowerCase() || '';
|
||||
// // 通过 keyof 类型保护确保类型安全
|
||||
// return Object.keys(FILE_ICONS).includes(fileExtension);
|
||||
// };
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -750,7 +748,7 @@ const shouldPreview = (filename: string): boolean => {
|
||||
<template #default="{ row }">
|
||||
<div class="preview-icon">
|
||||
<img :src="fileIcon(row)" alt="file icon" class="file-icon"
|
||||
@click="shouldPreview(row.fileName) && openPreview(row)">
|
||||
@click=" openPreview(row)">
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
105
web/src/views/testdata/datamanagement/index.vue
vendored
105
web/src/views/testdata/datamanagement/index.vue
vendored
@ -5,7 +5,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, nextTick, defineAsyncComponent,onUnmounted } from "vue";
|
||||
import { ref, onMounted, nextTick, defineAsyncComponent, onUnmounted } from "vue";
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
@ -18,6 +18,8 @@ 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";
|
||||
//text文件编辑功能
|
||||
import textEdit from '@/components/textEditing/index.vue'
|
||||
//轨迹图
|
||||
import MapChart from '@/components/trajectory/index.vue';
|
||||
import Echart from '@/components/trajectory/echarts.vue';
|
||||
@ -48,8 +50,8 @@ const userStore = useUserStore();
|
||||
onMounted(() => {
|
||||
getProject()
|
||||
});
|
||||
onUnmounted(()=>{
|
||||
closeSSE()
|
||||
onUnmounted(() => {
|
||||
closeSSE()
|
||||
})
|
||||
//拖动条
|
||||
const vMove = {
|
||||
@ -269,7 +271,7 @@ const fileObj: any = ref({
|
||||
const upfile = ref(false)
|
||||
function openFile() {
|
||||
title.value = "上传文件"
|
||||
localStorage.setItem('filepath', creatform.value.workPath ? creatform.value.workPath : '/');
|
||||
localStorage.setItem('filepath', creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/');
|
||||
localStorage.setItem('storageKey', JSON.stringify(['local']));
|
||||
upfile.value = true
|
||||
fileObj.value = {
|
||||
@ -312,7 +314,7 @@ function delfileOne(row: any) {
|
||||
{
|
||||
name: row.name,
|
||||
password: "",
|
||||
path: creatform.value.workPath ? creatform.value.workPath : '/',
|
||||
path: creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/',
|
||||
type: "FILE"
|
||||
}
|
||||
],
|
||||
@ -330,6 +332,7 @@ function submitfile() {
|
||||
// console.log( )
|
||||
|
||||
if (fileObj.value.id) {
|
||||
fileObj.value.workPath = '/' + pathid.value + fileObj.value.workPath
|
||||
updateTsFiles(fileObj.value).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
closeDialog()
|
||||
@ -360,7 +363,7 @@ function submitfile() {
|
||||
}
|
||||
fileObj.value.taskId = projectId.value
|
||||
fileObj.value.nodeId = pathid.value
|
||||
fileObj.value.workPath = creatform.value.workPath ? creatform.value.workPath : '/'
|
||||
fileObj.value.workPath = creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/'
|
||||
fileObj.value.fileName = fileName.join(',')
|
||||
fileObj.value.fileSize = fileSize.join(',')
|
||||
fileObj.value.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
|
||||
@ -587,7 +590,9 @@ const title1 = ref('')
|
||||
const isViewfile = ref(false)
|
||||
const fileType = ref('')
|
||||
function openPreview(row: any) {
|
||||
// debugger?
|
||||
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') {
|
||||
// debugger
|
||||
title1.value = row.fileName
|
||||
ViewfileUrl.value = row.url
|
||||
isViewfile.value = true
|
||||
@ -648,7 +653,7 @@ function getFileSuffix(name: any) {
|
||||
function openNode(row: any) {
|
||||
loading.value = true
|
||||
creatform.value.parentId = row.id
|
||||
creatform.value.workPath = row.workPath + row.fileName + '/'
|
||||
creatform.value.workPath = '/' + pathid.value + row.workPath + row.fileName + '/'
|
||||
patharr.value.push({ fileName: row.fileName, id: row.id })
|
||||
getdata()
|
||||
}
|
||||
@ -767,7 +772,7 @@ function paste() {
|
||||
rename: '',
|
||||
type: '',
|
||||
}
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/'
|
||||
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
|
||||
repeatObj.type = '0'
|
||||
|
||||
@ -816,7 +821,7 @@ function paste() {
|
||||
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.oldpaths = '/' + pathid.value + items.workPath
|
||||
repeatObj.newFileName.push(items.fileName)
|
||||
})
|
||||
repeatObj.newFileName = repeatObj.newFileName.join(',')
|
||||
@ -880,10 +885,10 @@ function copycover(row: any) {
|
||||
rename: '',
|
||||
type: '',
|
||||
}
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/'
|
||||
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
|
||||
repeatObj.type = '0'
|
||||
repeatObj.oldpaths = row.workPath
|
||||
repeatObj.oldpaths = '/' + pathid.value + row.workPath
|
||||
repeatObj.newFileName.push(row.fileName)
|
||||
repeatObj.newFileName = repeatObj.newFileName.join(',')
|
||||
if (copytype.value == "move") {
|
||||
@ -955,11 +960,11 @@ function copysomefile() {
|
||||
rename: '',
|
||||
type: '',
|
||||
}
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/'
|
||||
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
|
||||
repeatObj.type = '0'
|
||||
copyhandArr.value.forEach((items: any) => {
|
||||
repeatObj.oldpaths = items.workPath
|
||||
repeatObj.oldpaths = '/' + pathid.value + items.workPath
|
||||
repeatObj.newFileName.push(items.fileName)
|
||||
})
|
||||
repeatObj.newFileName = repeatObj.newFileName.join(',')
|
||||
@ -1019,10 +1024,10 @@ async function submitrename(formEl: any) {
|
||||
rename: '',
|
||||
type: '',
|
||||
}
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/'
|
||||
repeatObj.newPath = creatform.value.workPath ? creatform.value.workPath : '/' + pathid.value + '/'
|
||||
repeatObj.parentId = creatform.value.parentId ? creatform.value.parentId : '00'
|
||||
repeatObj.type = '1'
|
||||
repeatObj.oldpaths = rowarr.value.workPath
|
||||
repeatObj.oldpaths = '/' + pathid.value + rowarr.value.workPath
|
||||
repeatObj.rename = (renameobj.value.fileName)
|
||||
repeatObj.newFileName.push(rowarr.value.fileName)
|
||||
repeatObj.newFileName = repeatObj.newFileName.join(',')
|
||||
@ -1095,7 +1100,7 @@ async function submitcreat(formEl: any) {
|
||||
if (creatform.value.workPath) {
|
||||
creatObj.value.workPath = creatform.value.workPath
|
||||
} else {
|
||||
creatObj.value.workPath = '/'
|
||||
creatObj.value.workPath = '/' + pathid.value + '/'
|
||||
}
|
||||
addTsFile(creatObj.value).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
@ -1113,7 +1118,7 @@ function pathclick(row: any, index: any) {
|
||||
|
||||
patharr.value.splice(index + 1)
|
||||
creatform.value.parentId = row.id
|
||||
creatform.value.workPath = convertArrayToPath1(patharr.value)
|
||||
creatform.value.workPath = '/' + pathid.value + convertArrayToPath1(patharr.value)
|
||||
getdata()
|
||||
}
|
||||
// 压缩文件
|
||||
@ -1148,7 +1153,6 @@ function zipFile(row: any) {
|
||||
title.value = '压缩'
|
||||
if (tableIdarr.value.length == 1) {
|
||||
zipObj.value.compressedName = removeSuffix(tableIdarr.value[0].fileName)
|
||||
|
||||
} else {
|
||||
zipObj.value.compressedName = generateRandomName()
|
||||
}
|
||||
@ -1180,6 +1184,8 @@ async function submitzip(formEl: any) {
|
||||
// gettreedata()
|
||||
getdata()
|
||||
zipfiles.value = false
|
||||
// debugger
|
||||
zipObj.value.compressedPath= '/' + pathid.value +zipObj.value.compressedPath
|
||||
compress(zipObj.value).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
zipfiles.value = false
|
||||
@ -1191,7 +1197,7 @@ async function submitzip(formEl: any) {
|
||||
})
|
||||
} else {
|
||||
// loading.value = true
|
||||
Decompression({ id: jiezip.value.id, parentId: zipParentid.value, decompressionPath: jieFilearr.value.workPath ? jieFilearr.value.workPath : filetsobj.value.path }).then((res: any) => {
|
||||
Decompression({ id: jiezip.value.id, parentId: zipParentid.value, decompressionPath: jieFilearr.value.workPath ? '/' + pathid.value + jieFilearr.value.workPath : '/' + pathid.value + filetsobj.value.path }).then((res: any) => {
|
||||
if (res.code == 0) {
|
||||
ElMessage.success('解压成功')
|
||||
// // gettreedata()
|
||||
@ -1224,13 +1230,14 @@ const jiepatharr: any = ref([])
|
||||
function gettsfiles() {
|
||||
filetsobj.value.nodeId = pathid.value
|
||||
filetsobj.value.taskId = projectId.value
|
||||
// filetsobj.value.path ='/' + pathid.value + filetsobj.value.path
|
||||
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
|
||||
creatform.value.workPath = '/' + pathid.value + jieFilearr.value.workPath
|
||||
}
|
||||
|
||||
})
|
||||
@ -1239,7 +1246,7 @@ 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
|
||||
creatform.value.workPath = '/' + pathid.value + jieFilearr.value.workPath
|
||||
zipParentid.value = row.id
|
||||
creatform.value.parentId = row.id
|
||||
filetsobj.value.id = ''
|
||||
@ -1268,7 +1275,7 @@ function pathFile(index: any) {
|
||||
gettsfiles()
|
||||
}
|
||||
function pathqveding() {
|
||||
zipObj.value.compressedPath = jieFilearr.value.workPath
|
||||
zipObj.value.compressedPath = jieFilearr.value.workPath
|
||||
creatform.value.parentId = ''
|
||||
creatform.value.workPath = ''
|
||||
visible.value = !visible.value
|
||||
@ -1376,15 +1383,6 @@ 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);
|
||||
};
|
||||
// 判断是否可预览(基于文件图标映射表)
|
||||
const shouldPreview = (rwo: any): boolean => {
|
||||
// 获取文件扩展名并转为小写,兼容无扩展名情况
|
||||
const fileExtension = rwo.fileName.split('.').pop()?.toLowerCase() || '';
|
||||
|
||||
// 通过 keyof 类型保护确保类型安全
|
||||
return Object.keys(FILE_ICONS).includes(fileExtension);
|
||||
};
|
||||
|
||||
const mapTrajectory = ref(false)
|
||||
|
||||
const fredid = ref('')
|
||||
@ -1402,7 +1400,7 @@ function openMap(row: any) {
|
||||
}
|
||||
function mapClose() {
|
||||
mapTrajectory.value = false
|
||||
|
||||
|
||||
closeSSE()
|
||||
// index = 0
|
||||
}
|
||||
@ -1435,13 +1433,16 @@ const options = ref([
|
||||
])
|
||||
const maptime: any = ref(1)
|
||||
//频率
|
||||
const qvehuan = ref(false)
|
||||
const qvehuan: any = ref(false)
|
||||
const qvehuan1: any = ref(false)
|
||||
function frequency(row: any) {
|
||||
startSimpleNavi({ samTimes: maptime.value, id: fredid.value, token: userStore.userId }).then((res: any) => {
|
||||
if (res.code == '0' && row) {
|
||||
ElMessage.success("切换成功")
|
||||
getSSELink()
|
||||
qvehuan.value = true
|
||||
qvehuan1.value = true
|
||||
lineData.value.length = 0
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1449,14 +1450,14 @@ function frequency(row: any) {
|
||||
const eventSource = ref(null)
|
||||
let index = 0
|
||||
const dynamicCoordinates = ref([])
|
||||
function closeSSE(){
|
||||
function closeSSE() {
|
||||
dynamicCoordinates.value.length = 0
|
||||
// SSEclose :any
|
||||
let SSEclose = new EventSource(userStore.webApiBaseUrl + '/sse/disconnect/' + userStore.userId)
|
||||
eventSource.value?.close()
|
||||
let SSEclose = new EventSource(userStore.webApiBaseUrl + '/sse/disconnect/' + userStore.userId)
|
||||
eventSource.value?.close()
|
||||
}
|
||||
function getSSELink() {
|
||||
closeSSE()
|
||||
closeSSE()
|
||||
eventSource.value = new EventSource(userStore.webApiBaseUrl + '/sse/connect/' + userStore.userId)
|
||||
eventSource.value.addEventListener('open', () => {
|
||||
frequency(false)
|
||||
@ -1467,12 +1468,13 @@ function getSSELink() {
|
||||
try {
|
||||
const data = JSON.parse(e.data)
|
||||
console.log('SSE消息:', data)
|
||||
if(data){
|
||||
if (data) {
|
||||
dynamicCoordinates.value.push([data.lon, data.lat])
|
||||
if(dynamicCoordinates.value.length>2){
|
||||
if (dynamicCoordinates.value.length > 2) {
|
||||
dynamicCoordinates.value.shift()
|
||||
}
|
||||
lineData.value.push({x:data.UtcTime,y:data.alt})
|
||||
|
||||
lineData.value.push({ x: data.UtcTime, y: data.alt })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('消息解析失败:', err)
|
||||
@ -1485,11 +1487,20 @@ function getSSELink() {
|
||||
}
|
||||
}
|
||||
// 示例数据格式
|
||||
const lineData:any = ref([])
|
||||
const lineData: any = ref([])
|
||||
const tabbas = ref('1')
|
||||
function handleCustomEvent(row:any){
|
||||
function handleCustomEvent(row: any) {
|
||||
qvehuan.value = row
|
||||
}
|
||||
//编辑文本设置
|
||||
const textedit = ref(false)
|
||||
function testClick(row: any) {
|
||||
textedit.value = true
|
||||
title.value = '编辑 - ' + row.workPath + row.fileName
|
||||
}
|
||||
function textClose() {
|
||||
textedit.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -1583,7 +1594,7 @@ function handleCustomEvent(row:any){
|
||||
<img v-if="row.isFile == 'FOLDER'" src="@/assets/fileimg/wenjianjia.png" alt=""
|
||||
@click="openNode(row)" style="cursor: pointer;">
|
||||
<img v-else :src="fileIcon(row)" alt="file icon" class="file-icon"
|
||||
@click="shouldPreview(row) && openPreview(row)">
|
||||
@click=" openPreview(row)">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1594,6 +1605,8 @@ function handleCustomEvent(row:any){
|
||||
<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="testClick(scope.row)"
|
||||
style="cursor: pointer;">
|
||||
<img src="@/assets/project/chong.png" alt="" title="重命名" @click="editfile(scope.row, false)"
|
||||
style="cursor: pointer;">
|
||||
<img v-if="scope.row.fileName.includes('ins_img')" src="@/assets/MenuIcon/guiji.png" alt=""
|
||||
@ -1919,6 +1932,12 @@ function handleCustomEvent(row:any){
|
||||
<AudioPlayer></AudioPlayer>
|
||||
<Viewfile v-if="isViewfile" :showTime="true" :title="title1" :url="ViewfileUrl" :type="fileType"
|
||||
@update="CloseView" />
|
||||
<el-dialog :title="title" v-model="textedit" :before-close="textClose" top="30px" draggable width="60%"
|
||||
destroy-on-close>
|
||||
|
||||
<textEdit />
|
||||
<!-- </el-scrollbar> -->
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
Loading…
Reference in New Issue
Block a user