字典配置轨迹文件格式

This commit is contained in:
wangxk 2025-08-01 10:56:49 +08:00
parent d76271da24
commit 50462faaff
2 changed files with 44 additions and 30 deletions

View File

@ -4,14 +4,10 @@
<button class="fullscreen-btn" @click="toggleFullscreen"> <button class="fullscreen-btn" @click="toggleFullscreen">
{{ isFullscreen ? '退出全屏' : '全屏' }} {{ isFullscreen ? '退出全屏' : '全屏' }}
</button> </button>
<svg ref="svgRef" class="trajectory-svg" :width="svgWidth" :height="svgHeight"> <svg ref="svgRef" class="trajectory-svg" :width="svgWidth" :height="svgHeight">
<g class="zoom-container"> <g class="zoom-container">
<image <image :xlink:href="imageUrl" :width="svgWidth" :height="svgHeight" />
:xlink:href="imageUrl"
:width="svgWidth"
:height="svgHeight"
/>
</g> </g>
</svg> </svg>
</div> </div>
@ -24,17 +20,17 @@ import * as d3 from 'd3'
// === Props === // === Props ===
const props = defineProps({ const props = defineProps({
imageUrl: { type: String, required: true }, imageUrl: { type: String, required: true },
bounds: { bounds: {
type: Array, type: Array,
required: true, required: true,
default: () => [0, 0, 1, 1] // [minLng, minLat, maxLng, maxLat] default: () => [0, 0, 1, 1] // [minLng, minLat, maxLng, maxLat]
}, },
trajectory: { trajectory: {
type: Array, type: Array,
required: true, required: true,
default: () => [] default: () => []
}, },
qvehuan: { qvehuan: {
type: Boolean, type: Boolean,
default: false default: false
} }
@ -64,13 +60,13 @@ const initMap = () => {
svgWidth.value = container.clientWidth svgWidth.value = container.clientWidth
svgHeight.value = container.clientHeight svgHeight.value = container.clientHeight
} }
const [minLng, minLat, maxLng, maxLat] = props.bounds const [minLng, minLat, maxLng, maxLat] = props.bounds
xScale.value = d3.scaleLinear() xScale.value = d3.scaleLinear()
.domain([minLng, maxLng]) .domain([minLng, maxLng])
.range([0, svgWidth.value]) .range([0, svgWidth.value])
yScale.value = d3.scaleLinear() yScale.value = d3.scaleLinear()
.domain([minLat, maxLat]) .domain([minLat, maxLat])
.range([svgHeight.value, 0]) .range([svgHeight.value, 0])
@ -83,7 +79,7 @@ const initMap = () => {
const initZoom = () => { const initZoom = () => {
const mapZoom = d3.zoom() const mapZoom = d3.zoom()
.scaleExtent([0.5, 3]) // .scaleExtent([0.5, 3]) //
.translateExtent([[-svgWidth.value, -svgHeight.value], [2*svgWidth.value, 2*svgHeight.value]]) .translateExtent([[-svgWidth.value, -svgHeight.value], [2 * svgWidth.value, 2 * svgHeight.value]])
.on("zoom", (event) => { .on("zoom", (event) => {
d3.select(svgRef.value).select('.zoom-container') d3.select(svgRef.value).select('.zoom-container')
.attr("transform", event.transform) .attr("transform", event.transform)
@ -131,10 +127,10 @@ const renderTrajectoryPath = () => {
.attr('stroke', '#1890FF') .attr('stroke', '#1890FF')
.attr('stroke-width', 2.5) .attr('stroke-width', 2.5)
.attr('fill', 'none') .attr('fill', 'none')
.attr('stroke-dasharray', function() { .attr('stroke-dasharray', function () {
return this.getTotalLength() return this.getTotalLength()
}) })
.attr('stroke-dashoffset', function() { .attr('stroke-dashoffset', function () {
return this.getTotalLength() return this.getTotalLength()
}) })
.transition() .transition()
@ -152,7 +148,7 @@ const renderTrajectoryMarkers = () => {
props.trajectory.forEach(([lng, lat], index) => { props.trajectory.forEach(([lng, lat], index) => {
const x = xScale.value(lng) const x = xScale.value(lng)
const y = yScale.value(lat) const y = yScale.value(lat)
d3.select(svgRef.value).select('.zoom-container') d3.select(svgRef.value).select('.zoom-container')
.append('circle') .append('circle')
.attr('class', `marker-circle marker-${index}`) .attr('class', `marker-circle marker-${index}`)
@ -162,12 +158,12 @@ const renderTrajectoryMarkers = () => {
.attr('fill', '#FF4D4F') .attr('fill', '#FF4D4F')
.attr('stroke', '#fff') .attr('stroke', '#fff')
.attr('stroke-width', 0.8) .attr('stroke-width', 0.8)
.on('mouseover', function() { .on('mouseover', function () {
d3.select(this) d3.select(this)
.attr('r', 4) .attr('r', 4)
.attr('stroke-width', 1.2) .attr('stroke-width', 1.2)
}) })
.on('mouseout', function() { .on('mouseout', function () {
d3.select(this) d3.select(this)
.attr('r', 2.5) .attr('r', 2.5)
.attr('stroke-width', 0.8) .attr('stroke-width', 0.8)
@ -216,24 +212,26 @@ const toggleFullscreen = () => {
// === === // === ===
const handleFullscreenChange = () => { const handleFullscreenChange = () => {
isFullscreen.value = !!document.fullscreenElement isFullscreen.value = !!document.fullscreenElement
// //
clearOldElements() clearOldElements()
requestAnimationFrame(() => {
// DOM // DOM
setTimeout(() => { setTimeout(() => {
initMap() initMap()
updateTrajectory() updateTrajectory()
}, 500) }, 500)
})
} }
// === === // === ===
const handleResize = () => { const handleResize = () => {
if (resizeTimeout) clearTimeout(resizeTimeout) if (resizeTimeout) clearTimeout(resizeTimeout)
resizeTimeout = setTimeout(() => { resizeTimeout = setTimeout(() => {
clearOldElements()
initMap() initMap()
updateTrajectory() updateTrajectory()
}, 300) },500)
} }
// === === // === ===
@ -253,14 +251,14 @@ onMounted(() => {
// //
document.addEventListener('fullscreenchange', handleFullscreenChange) document.addEventListener('fullscreenchange', handleFullscreenChange)
window.addEventListener('resize', handleResize) window.addEventListener('resize', handleResize)
// SVG // SVG
const container = d3.select(svgRef.value).node() const container = d3.select(svgRef.value).node()
if (container) { if (container) {
svgWidth.value = container.clientWidth svgWidth.value = container.clientWidth
svgHeight.value = container.clientHeight svgHeight.value = container.clientHeight
} }
// //
const imageElement = d3.select(svgRef.value).select('image') const imageElement = d3.select(svgRef.value).select('image')
if (imageElement) { if (imageElement) {

View File

@ -44,6 +44,7 @@ import VideoPlayerAsyncLoading from "@/components/file/preview/VideoPlayerAsyncL
import TextViewerAsyncLoading from "@/components/file/preview/TextViewerAsyncLoading.vue"; import TextViewerAsyncLoading from "@/components/file/preview/TextViewerAsyncLoading.vue";
import MarkdownViewerDialogAsyncLoading from "@/components/file/preview/MarkdownViewerDialogAsyncLoading.vue"; import MarkdownViewerDialogAsyncLoading from "@/components/file/preview/MarkdownViewerDialogAsyncLoading.vue";
import { display } from "html2canvas/dist/types/css/property-descriptors/display"; import { display } from "html2canvas/dist/types/css/property-descriptors/display";
import { getDict } from '@/api/dict'
const { dialogVideoVisible, dialogTextVisible, dialogPdfVisible, dialogOfficeVisible, dialog3dVisible } = useFilePreview(); const { dialogVideoVisible, dialogTextVisible, dialogPdfVisible, dialogOfficeVisible, dialog3dVisible } = useFilePreview();
const { clearALlFinishedUploadFile } = useFileUpload(); const { clearALlFinishedUploadFile } = useFileUpload();
const { currentStorageKey } = useHeaderStorageList(); const { currentStorageKey } = useHeaderStorageList();
@ -51,6 +52,7 @@ const { openRow } = useFileData();
const userStore = useUserStore(); const userStore = useUserStore();
onMounted(() => { onMounted(() => {
getProject() getProject()
getDictOne()
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
@ -63,6 +65,15 @@ onBeforeUnmount(() => {
} }
}) })
const trackFileType = ref([])
function getDictOne() {
getDict({ dictcode: 'Trajectory_File_Key' }).then((res: any) => {
trackFileType.value = res.data
})
}
function iftrackFile(name: string): boolean {
return trackFileType.value.some((item: any) => name.includes(item.dictname));
}
// //
const vMove = { const vMove = {
mounted(el: any) { mounted(el: any) {
@ -1769,6 +1780,10 @@ function getSSELink() {
try { try {
const data = JSON.parse(e.data) const data = JSON.parse(e.data)
console.log('SSE消息:', data) console.log('SSE消息:', data)
if(data.message == '配置文件选择错误,请重新选择!'){
ElMessage.warning(data.message)
return
}
if (data) { if (data) {
dynamicCoordinates.value.push([data.lon, data.lat]) dynamicCoordinates.value.push([data.lon, data.lat])
if (dynamicCoordinates.value.length > 2) { if (dynamicCoordinates.value.length > 2) {
@ -1960,7 +1975,8 @@ const configradio: any = ref(null)
style="cursor: pointer;"> --> style="cursor: pointer;"> -->
<img src="@/assets/project/chong.png" alt="" title="重命名" @click="editfile(scope.row, false)" <img src="@/assets/project/chong.png" alt="" title="重命名" @click="editfile(scope.row, false)"
style="cursor: pointer;"> style="cursor: pointer;">
<img v-if="scope.row.fileName.includes('ins_img') || scope.row.fileName == 'VINS.csv'"
<img v-if="iftrackFile(scope.row.fileName)"
src="@/assets/MenuIcon/guiji.png" alt="" @click="openMap(scope.row)" title="轨迹预览图" src="@/assets/MenuIcon/guiji.png" alt="" @click="openMap(scope.row)" title="轨迹预览图"
style="cursor: pointer;"> style="cursor: pointer;">
<img src="@/assets/MenuIcon/lbcz_xg.png" alt="" @click="editfile(scope.row, true)" <img src="@/assets/MenuIcon/lbcz_xg.png" alt="" @click="editfile(scope.row, true)"
@ -2281,7 +2297,7 @@ const configradio: any = ref(null)
<el-button @click="">取消</el-button> <el-button @click="">取消</el-button>
</div> </div>
</div> </div>
<div style="width: 800px;height:600px;overflow: hidden;margin: auto;" v-else> <div style="width: 800px;height:600px;margin: auto;" v-else>
<Imggui :imageUrl="pngobj.pngurl" :bounds="pngobj.textcontent" :trajectory="imgarrdata" <Imggui :imageUrl="pngobj.pngurl" :bounds="pngobj.textcontent" :trajectory="imgarrdata"
:qvehuan="qvehuan" @qvehuan1="handleCustomEvent" /> :qvehuan="qvehuan" @qvehuan1="handleCustomEvent" />
</div> </div>