修改显示

main
suixy 3 months ago
parent 2c32efcebf
commit ec01f39fa0

@ -42,6 +42,7 @@
},
"dependencies": {
"@vitejs/plugin-basic-ssl": "^2.0.0",
"@vitejs/plugin-vue-jsx": "^5.1.1",
"axios": "^1.11.0",
"element-plus": "^2.10.4",
"vue": "^3.5.17",

@ -1,350 +1,357 @@
<template>
<!-- <div class="container" ref="containerRef" @wheel.prevent="onWheel">-->
<div class="container" ref="containerRef">
<!-- <div class="leftLine"></div>-->
<!-- 左侧竖向刻度尺 -->
<div class="ruler vertical" :style="{ backgroundColor: bgColor }">
<div class="ruler-content" :style="{ height: contentHeight + 'px' ,transform: 'rotate(180deg)'}">
<template v-for="tick in verticalTicks" :key="'v-' + tick.index">
<div
class="tick"
:class="{ major: tick.isMajor }"
:style="{
bottom: tick.pos + 'px',
width: tick.isMajor ? '15px' : '7px',
right: 0,
}"
>
<span
v-if="tick.isMajor"
class="label"
:style="{ right: '18px', bottom: '-6px',transform: 'rotate(180deg)' }"
>
{{ tick.label }}
</span>
</div>
</template>
</div>
</div>
<!-- 内容区 -->
<div ref="wrapperRef" class="map-wrapper">
<!-- 中心区域 -->
<div
class="content-area"
:style="{
width: contentWidth + 'px',
height: contentHeight + 'px',
backgroundColor: bgColor,
}"
class="map-content"
:style="{ transformOrigin: `${transformOriginX}px ${transformOriginY}px`,transform: ` scale(${scale}) translate(${0}px, ${0}px)` }"
>
<div class="map-area"></div>
<div
class="content-inner"
v-if="lineCoordinates"
class="connection-line"
:style="{
transform: `translate(${offsetX}px, ${offsetY}px) scale(${scale})`,
transformOrigin: 'top left',
}"
>
<div
v-if="props.boxPos.x && props.boxPos.y"
class="box"
:style="{
width: boxSize + 'px',
height: boxSize + 'px',
left: props.boxPos.x + 'px',
top: contentHeight - props.boxPos.y - boxSize + 'px',
transform: `rotate(${props.boxPos.rotate}deg)`
left: lineCoordinates.startX + 'px',
bottom: lineCoordinates.startY + 'px',
width: lineCoordinates.width + 'px',
transform: `translateY(50%) rotate(${lineCoordinates.angle}deg) scaleY(${1/scale})`,
transformOrigin: 'left center'
}"
></div>
<!-- Box元素直接用内容坐标不再额外 *scale/+translate -->
<div
v-if="boxPos"
class="box"
:style="{
left: boxContentX + 'px',
bottom: boxContentY + 'px',
transform: `translate(-50%, 50%) rotate(${boxPos.rotate}deg) scale(${1 / scale})`
}"
>
<div class="scan"></div>
</div>
<div class="dot"
v-for="i in dots"
:style="{
width: 10 + 'px',
height: 10 + 'px',
left: i.x + 'px',
top: contentHeight - i.y - 10 + 'px',
}">
>
<div class="scan"></div>
</div>
<div
v-for="(dot, index) in dots"
:key="index"
class="dot"
:style="{
left: `${lonToPixel(dot.lon)}px`,
bottom: `${latToPixel(dot.lat)}px`,
transform: `translate(-50%, 50%) scale(${1 / scale})`
}"
></div>
</div>
</div>
<div
v-if="lineStyle"
class="line"
:style="lineStyle"
></div>
<!-- 左侧刻度尺 -->
<div class="y-ruler">
<div
v-for="tick in yTicks"
:key="tick.value"
class="tick"
:style="{ bottom: tick.pixel + 'px' }"
>
<div class="line"></div>
<div class="label">{{ tick.display }}</div>
</div>
</div>
<!-- 下方横向刻度尺 -->
<div
class="ruler horizontal"
:style="{ backgroundColor: bgColor, width: contentWidth + 'px' }"
>
<div class="ruler-content" :style="{ width: contentWidth + 'px' }">
<template v-for="tick in horizontalTicks" :key="'h-' + tick.index">
<div
class="tick"
:class="{ major: tick.isMajor }"
:style="{
left: tick.pos + 'px',
height: tick.isMajor ? '15px' : '7px',
top: 0,
}"
>
<span
v-if="tick.isMajor"
class="label"
:style="{ top: '18px', left: '-6px' }"
>
{{ tick.label }}
</span>
</div>
</template>
<!-- 下方刻度尺 -->
<div class="x-ruler">
<div
v-for="tick in xTicks"
:key="tick.value"
class="tick"
:style="{ left: tick.pixel + 'px' }"
>
<div class="line"></div>
<div class="label">{{ tick.display }}</div>
</div>
</div>
</div>
</template>
<script setup>
import {ref, computed, onMounted, watch, watchEffect} from 'vue'
<script setup>
import {ref, computed, onMounted} from "vue"
const props = defineProps({
boxPos: {
type: Object,
default: () => ({x: 200, y: 300, rotate: -45}),
},
index: {type: Number, default: -1} //
minlon: Number,
maxlon: Number,
minlat: Number,
maxlat: Number,
boxPos: Object,// { x, y, rotate }
dots: Array,
dotIndex: Number
})
// const boxPos = ref({x: 200, y: 300, rotate: -45})
// setInterval(() => {
// props.boxPos.x += (-10 + (Math.random() * 20))
// props.boxPos.y += (-10 + (Math.random() * 20))
// props.boxPos.rotate += (-5 + (Math.random() * 10))
// }, 1000)
setInterval(() => {
props.boxPos.x += (-0.001 + (Math.random() * 0.002))
props.boxPos.y += (-0.001 + (Math.random() * 0.002))
props.boxPos.rotate += (-25 + (Math.random() * 50))
}, 1000)
const wrapperRef = ref(null)
const parentWidth = ref(0)
const parentHeight = ref(0)
const dots = ref([
// {
// x: 100,
// y: 100,
// },
// {
// x: 200,
// y: 200,
// }
])
const setDot = (dot, bol) => {
if (bol) {
dots.value = []
} else {
dots.value = [...dots.value, ...dot]
}
}
const lineStyle = ref(null)
watchEffect(() => {
if (props.index < 0 || !dots.value[props.index]) return
//
const rulerWidth = 40
const rulerHeight = 20
const dot = dots.value[props.index]
// box
const centerX = props.boxPos.x + boxSize / 2
const centerY = contentHeight.value - props.boxPos.y - boxSize / 2
// box
const rad = props.boxPos.rotate * Math.PI / 180
//
const dx0 = 0
const dy0 = -boxSize / 2
//
const dx = dx0 * Math.cos(rad) - dy0 * Math.sin(rad)
const dy = dx0 * Math.sin(rad) + dy0 * Math.cos(rad)
//
const boxTopX = centerX + dx
const boxTopY = centerY + dy
// dot
const dotX = dot.x + 5
const dotY = contentHeight.value - dot.y - 5
const dX = dotX - boxTopX
const dY = dotY - boxTopY
const length = Math.sqrt(dX * dX + dY * dY)
const angle = Math.atan2(dY, dX) * 180 / Math.PI
//
// if (lineStyle._timer) clearTimeout(lineStyle._timer)
// 1
lineStyle._timer = setTimeout(() => {
lineStyle.value = {
left: boxTopX + 'px',
top: boxTopY + 'px',
width: length + 'px',
transform: `rotate(${angle}deg)`,
transformOrigin: '0 0'
}
}, 1000)
})
defineExpose({
setDot
})
const boxSize = 30
const minScale = 1
const maxScale = 3
const scale = ref(1)
const offsetX = ref(0)
const offsetY = ref(0)
const containerRef = ref(null)
const rulerSize = 40
const containerWidth = ref(0)
const containerHeight = ref(0)
const contentWidth = computed(() => containerWidth.value - rulerSize)
const contentHeight = computed(() => containerHeight.value - rulerSize)
const bgColor = '#353741'
function updateContainerSize() {
if (containerRef.value) {
containerWidth.value = containerRef.value.clientWidth
containerHeight.value = containerRef.value.clientHeight
}
}
onMounted(() => {
updateContainerSize()
window.addEventListener('resize', updateContainerSize)
})
watch(
() => containerRef.value,
(el) => {
if (el) updateContainerSize()
}
//
const zoomLevel = ref(1)
const scale = computed(() =>
zoomLevel.value === 1 ? 1 : zoomLevel.value === 2 ? 10 : 100
)
const tickValue = computed(() =>
zoomLevel.value === 1 ? 100 : zoomLevel.value === 2 ? 10 : 1
)
// box
function getBoxCenterPos(s) {
const x = props.boxPos.x * s + (boxSize * s) / 2
const y = props.boxPos.y * s + (boxSize * s) / 2
return {x, y}
const translateX = ref(0)
const translateY = ref(0)
//
const updateSize = () => {
if (wrapperRef.value) {
const rect = wrapperRef.value.getBoundingClientRect()
parentWidth.value = rect.width
parentHeight.value = rect.height
}
}
//
function onWheel(e) {
const oldScale = scale.value
const direction = e.deltaY < 0 ? 1 : -1
const step = 0.1
let newScale = oldScale + direction * step
newScale = Math.max(minScale, Math.min(maxScale, newScale))
if (newScale === oldScale) return
onMounted(updateSize)
window.addEventListener("resize", updateSize)
// box
const oldCenter = getBoxCenterPos(oldScale)
// box
const newCenter = getBoxCenterPos(newScale)
//
const contentWidth = computed(() => parentWidth.value - rulerWidth)
const contentHeight = computed(() => parentHeight.value - rulerHeight)
// box
offsetX.value += oldCenter.x - newCenter.x
offsetY.value += oldCenter.y - newCenter.y
scale.value = newScale
//
function lonToPixel(lon) {
return ((lon - props.minlon) / (props.maxlon - props.minlon)) * contentWidth.value
}
function latToPixel(lat) {
return ((lat - props.minlat) / (props.maxlat - props.minlat)) * contentHeight.value
}
//
const baseMajorTickSize = 100
const baseMinorTicks = 10
const transformOriginX = ref(0)
const transformOriginY = ref(0)
const majorTickSpacing = computed(() => baseMajorTickSize * scale.value)
const minorTickSpacing = computed(() => majorTickSpacing.value / baseMinorTicks)
//
function setZoom(center, level) {
zoomLevel.value = level
function generateTicks(length, offset, isVertical = false) {
const spacing = minorTickSpacing.value
const contentX = lonToPixel(center.lon)
const contentY = latToPixel(center.lat)
const scaledX = (contentX + translateX.value) * scale.value
const scaledY = (contentY + translateY.value) * scale.value
transformOriginX.value = contentX
transformOriginY.value = contentHeight.value - contentY
const cx = lonToPixel(center.lon)
const cy = latToPixel(center.lat)
const targetX = contentWidth.value / 2
const targetY = contentHeight.value / 2
translateX.value = targetX - cx * scale.value
translateY.value = targetY - cy * scale.value
}
//
function formatTick(valueMeters) {
if (zoomLevel.value === 1) return Math.round(valueMeters / 100) * 100
if (zoomLevel.value === 2) return Math.round(valueMeters / 10) * 10
return Math.round(valueMeters)
}
// X
const xTicks = computed(() => {
const ticks = []
const pixelsPerLon = contentWidth.value / (props.maxlon - props.minlon)
const startLon = props.minlon - translateX.value / (pixelsPerLon * scale.value)
const startIndex = Math.floor(-offset / spacing)
const endIndex = Math.ceil((length - offset) / spacing)
for (let i = startIndex; i <= endIndex; i++) {
const rawPos = i * spacing + offset
const pos = isVertical ? length - rawPos : rawPos
const isMajor = i % baseMinorTicks === 0
let val = startLon
while (val <= props.maxlon) {
const contentX = lonToPixel(val)
const pixel = contentX * scale.value + translateX.value
ticks.push({
index: i,
pos,
isMajor,
label: isMajor ? i * (baseMajorTickSize / baseMinorTicks) : null,
value: val,
pixel,
display: formatTick((val - props.minlon) * 111000)
})
val += tickValue.value / 111000
}
return ticks
}
})
const horizontalTicks = computed(() =>
generateTicks(contentWidth.value, offsetX.value)
)
// Y
const yTicks = computed(() => {
const ticks = []
const pixelsPerLat = contentHeight.value / (props.maxlat - props.minlat)
const startLat = props.minlat - translateY.value / (pixelsPerLat * scale.value)
const verticalTicks = computed(() =>
generateTicks(contentHeight.value, offsetY.value, true)
)
let val = startLat
while (val <= props.maxlat) {
const contentY = latToPixel(val)
const pixel = contentY * scale.value + translateY.value
ticks.push({
value: val,
pixel,
display: formatTick((val - props.minlat) * 111000)
})
val += tickValue.value / 111000
}
return ticks
})
// Box/
const boxContentX = computed(() => {
if (!props.boxPos) return 0
return lonToPixel(props.boxPos.x)
})
const boxContentY = computed(() => {
if (!props.boxPos) return 0
return latToPixel(props.boxPos.y)
})
const lineCoordinates = computed(() => {
if (!props.boxPos || !props.dots || props.dotIndex === undefined) return null
const startDot = props.dots[props.dotIndex]
if (!startDot) return null
const startX = lonToPixel(startDot.lon)
const startY = latToPixel(startDot.lat)
const endX = lonToPixel(props.boxPos.x)
const endY = latToPixel(props.boxPos.y) + 15
const dx = endX - startX
const dy = endY - startY
const width = Math.hypot(dx, dy)
const angle = Math.atan2(dx, dy) * 180 / Math.PI - 90
return {startX, startY, width, angle}
})
defineExpose({setZoom})
//
// setTimeout(() => {
// setZoom({lon: 120.005, lat: 30.005}, 2)
// }, 3000)
// setTimeout(() => {
// setZoom({lon: 120.005, lat: 30.005}, 3)
// }, 5000)
// setTimeout(() => {
// setZoom({lon: 120.005, lat: 30.005}, 2)
// }, 8000)
// setTimeout(() => {
// setZoom({lon: 120.005, lat: 30.005}, 1)
// }, 10000)
</script>
<style scoped>
.container {
.map-wrapper {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
background: #353741;
user-select: none;
overflow: hidden;
color: white;
background: #000;
}
/* 竖向刻度尺 */
.ruler.vertical {
.map-content {
position: absolute;
left: 40px; /* 左侧刻度尺宽度 */
bottom: 20px; /* 下方刻度尺高度 */
width: calc(100% - 40px);
height: calc(100% - 20px);
transform-origin: 0 0;
}
.map-area {
width: 100%;
height: 100%;
background: #333;
}
/* 左侧刻度尺 */
.y-ruler {
position: absolute;
left: 0;
top: 0;
bottom: 20px;
width: 40px;
height: calc(100% - 40px);
position: relative;
border-right: 1px solid #666;
background: #000;
}
.ruler.horizontal {
height: 40px;
width: 100%;
.y-ruler .tick {
position: absolute;
width: 100%;
height: 1px;
}
.y-ruler .line {
position: absolute;
right: 0;
width: 10px;
height: 1px;
background: #fff;
}
.y-ruler .label {
position: absolute;
right: 12px;
top: -6px;
color: #fff;
font-size: 10px;
text-align: right;
}
/* 下方刻度尺 */
.x-ruler {
position: absolute;
bottom: 0;
left: 40px;
border-top: 1px solid #666;
right: 0;
bottom: 0;
height: 20px;
background: #000;
}
.content-area {
position: relative;
height: 100%;
overflow: hidden;
flex-shrink: 0;
border-left: 1px solid #666;
border-bottom: 1px solid #666;
}
.content-inner {
.x-ruler .tick {
position: absolute;
width: 100%;
height: 100%;
width: 1px;
}
.x-ruler .line {
position: absolute;
top: 0;
width: 1px;
height: 5px;
background: #fff;
}
.x-ruler .label {
position: absolute;
top: 5px;
left: -5px;
color: #fff;
font-size: 10px;
}
/* Box元素 */
.box {
position: absolute;
width: 30px;
height: 30px;
background-image: url("../assets/car.png");
background-repeat: no-repeat;
background-size: 100% 100%;
transition: top 1s ease, left 1s ease;
transform-origin: center;
}
.box .scan {
@ -356,73 +363,23 @@ const verticalTicks = computed(() =>
top: 50%;
right: 15px;
transform: translateY(-50%);
}
.dot {
width: 10px;
height: 10px;
position: absolute;
background: radial-gradient(circle at center,
#ea1212 0%, rgba(228, 116, 116, 0.2) 100%);
border-radius: 50%;
}
.tick {
position: absolute;
opacity: 0.4;
pointer-events: none;
}
.tick.major {
opacity: 1;
}
.ruler.vertical .tick {
border-top: 1px solid white;
}
.ruler.vertical .tick.major {
border-top: 2px solid white;
}
.ruler.vertical .label {
position: absolute;
font-size: 10px;
bottom: -6px;
right: 18px;
}
.ruler.horizontal .tick {
border-left: 1px solid white;
}
.ruler.horizontal .tick.major {
border-left: 2px solid white;
}
.ruler.horizontal .label {
position: absolute;
font-size: 10px;
top: 18px;
left: -6px;
}
.ruler-content {
position: relative;
}
.leftLine {
position: absolute;
top: 0;
left: 20%;
width: 1px;
height: calc(100% - 40px);
border-right: 3px dashed white;
z-index: 9999;
}
.line {
.connection-line {
position: absolute;
height: 2px;
background: yellow;
background-color: transparent; /* 背景透明 */
border-top: 1px dashed #fff; /* 虚线样式 */
transform-origin: left center;
z-index: 1;
}
</style>
</style>

@ -0,0 +1,427 @@
<template>
<!-- <div class="container" ref="containerRef" @wheel.prevent="onWheel">-->
<div class="container" ref="containerRef">
<!-- <div class="leftLine"></div>-->
<!-- 左侧竖向刻度尺 -->
<div class="ruler vertical" :style="{ backgroundColor: bgColor }">
<div class="ruler-content" :style="{ height: contentHeight + 'px' ,transform: 'rotate(180deg)'}">
<template v-for="tick in verticalTicks" :key="'v-' + tick.index">
<div
class="tick"
:class="{ major: tick.isMajor }"
:style="{
bottom: tick.pos + 'px',
width: tick.isMajor ? '15px' : '7px',
right: 0,
}"
>
<span
v-if="tick.isMajor"
class="label"
:style="{ right: '18px', bottom: '-6px',transform: 'rotate(180deg)' }"
>
{{ tick.label }}
</span>
</div>
</template>
</div>
</div>
<!-- 内容区 -->
<div
class="content-area"
:style="{
width: contentWidth + 'px',
height: contentHeight + 'px',
backgroundColor: bgColor,
}"
>
<div
class="content-inner"
:style="{
transform: `translate(${offsetX}px, ${offsetY}px) scale(${scale})`,
transformOrigin: 'top left',
}"
>
<div
v-if="props.boxPos.x && props.boxPos.y"
class="box"
:style="{
width: boxSize + 'px',
height: boxSize + 'px',
left: props.boxPos.x + 'px',
top: contentHeight - props.boxPos.y - boxSize + 'px',
transform: `rotate(${props.boxPos.rotate}deg)`
}"
>
<div class="scan"></div>
</div>
<div class="dot"
v-for="i in dots"
:style="{
width: 10 + 'px',
height: 10 + 'px',
left: i.x + 'px',
top: contentHeight - i.y - 10 + 'px',
}">
</div>
<div
v-if="lineStyle"
class="line"
:style="lineStyle"
></div>
</div>
</div>
<!-- 下方横向刻度尺 -->
<div
class="ruler horizontal"
:style="{ backgroundColor: bgColor, width: contentWidth + 'px' }"
>
<div class="ruler-content" :style="{ width: contentWidth + 'px' }">
<template v-for="tick in horizontalTicks" :key="'h-' + tick.index">
<div
class="tick"
:class="{ major: tick.isMajor }"
:style="{
left: tick.pos + 'px',
height: tick.isMajor ? '15px' : '7px',
top: 0,
}"
>
<span
v-if="tick.isMajor"
class="label"
:style="{ top: '18px', left: '-6px' }"
>
{{ tick.label }}
</span>
</div>
</template>
</div>
</div>
</div>
</template>
<script setup>
import {ref, computed, onMounted, watch, watchEffect} from 'vue'
const props = defineProps({
boxPos: {
type: Object,
default: () => ({x: 200, y: 300, rotate: -45}),
},
index: {type: Number, default: -1} //
})
// const boxPos = ref({x: 200, y: 300, rotate: -45})
// setInterval(() => {
// props.boxPos.x += (-10 + (Math.random() * 20))
// props.boxPos.y += (-10 + (Math.random() * 20))
// props.boxPos.rotate += (-5 + (Math.random() * 10))
// }, 1000)
const dots = ref([
// {
// x: 100,
// y: 100,
// },
// {
// x: 200,
// y: 200,
// }
])
const setDot = (dot, bol) => {
if (bol) {
dots.value = []
} else {
dots.value = [...dots.value, ...dot]
}
}
const lineStyle = ref(null)
watchEffect(() => {
if (props.index < 0 || !dots.value[props.index]) return
const dot = dots.value[props.index]
// box
const centerX = props.boxPos.x + boxSize / 2
const centerY = contentHeight.value - props.boxPos.y - boxSize / 2
// box
const rad = props.boxPos.rotate * Math.PI / 180
//
const dx0 = 0
const dy0 = -boxSize / 2
//
const dx = dx0 * Math.cos(rad) - dy0 * Math.sin(rad)
const dy = dx0 * Math.sin(rad) + dy0 * Math.cos(rad)
//
const boxTopX = centerX + dx
const boxTopY = centerY + dy
// dot
const dotX = dot.x + 5
const dotY = contentHeight.value - dot.y - 5
const dX = dotX - boxTopX
const dY = dotY - boxTopY
const length = Math.sqrt(dX * dX + dY * dY)
const angle = Math.atan2(dY, dX) * 180 / Math.PI
//
// if (lineStyle._timer) clearTimeout(lineStyle._timer)
// 1
lineStyle._timer = setTimeout(() => {
lineStyle.value = {
left: boxTopX + 'px',
top: boxTopY + 'px',
width: length + 'px',
transform: `rotate(${angle}deg)`,
transformOrigin: '0 0'
}
}, 1000)
})
defineExpose({
setDot
})
const boxSize = 30
const minScale = 1
const maxScale = 3
const scale = ref(1)
const offsetX = ref(0)
const offsetY = ref(0)
const containerRef = ref(null)
const rulerSize = 40
const containerWidth = ref(0)
const containerHeight = ref(0)
const contentWidth = computed(() => containerWidth.value - rulerSize)
const contentHeight = computed(() => containerHeight.value - rulerSize)
const bgColor = '#353741'
function updateContainerSize() {
if (containerRef.value) {
containerWidth.value = containerRef.value.clientWidth
containerHeight.value = containerRef.value.clientHeight
}
}
onMounted(() => {
updateContainerSize()
window.addEventListener('resize', updateContainerSize)
})
watch(
() => containerRef.value,
(el) => {
if (el) updateContainerSize()
}
)
// box
function getBoxCenterPos(s) {
const x = props.boxPos.x * s + (boxSize * s) / 2
const y = props.boxPos.y * s + (boxSize * s) / 2
return {x, y}
}
//
function onWheel(e) {
const oldScale = scale.value
const direction = e.deltaY < 0 ? 1 : -1
const step = 0.1
let newScale = oldScale + direction * step
newScale = Math.max(minScale, Math.min(maxScale, newScale))
if (newScale === oldScale) return
// box
const oldCenter = getBoxCenterPos(oldScale)
// box
const newCenter = getBoxCenterPos(newScale)
// box
offsetX.value += oldCenter.x - newCenter.x
offsetY.value += oldCenter.y - newCenter.y
scale.value = newScale
}
//
const baseMajorTickSize = 100
const baseMinorTicks = 10
const majorTickSpacing = computed(() => baseMajorTickSize * scale.value)
const minorTickSpacing = computed(() => majorTickSpacing.value / baseMinorTicks)
function generateTicks(length, offset, isVertical = false) {
const spacing = minorTickSpacing.value
const ticks = []
const startIndex = Math.floor(-offset / spacing)
const endIndex = Math.ceil((length - offset) / spacing)
for (let i = startIndex; i <= endIndex; i++) {
const rawPos = i * spacing + offset
const pos = isVertical ? length - rawPos : rawPos
const isMajor = i % baseMinorTicks === 0
ticks.push({
index: i,
pos,
isMajor,
label: isMajor ? i * (baseMajorTickSize / baseMinorTicks) : null,
})
}
return ticks
}
const horizontalTicks = computed(() =>
generateTicks(contentWidth.value, offsetX.value)
)
const verticalTicks = computed(() =>
generateTicks(contentHeight.value, offsetY.value, true)
)
</script>
<style scoped>
.container {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
background: #353741;
user-select: none;
overflow: hidden;
color: white;
}
/* 竖向刻度尺 */
.ruler.vertical {
width: 40px;
height: calc(100% - 40px);
position: relative;
border-right: 1px solid #666;
}
.ruler.horizontal {
height: 40px;
width: 100%;
position: absolute;
bottom: 0;
left: 40px;
border-top: 1px solid #666;
}
.content-area {
position: relative;
height: 100%;
overflow: hidden;
flex-shrink: 0;
border-left: 1px solid #666;
border-bottom: 1px solid #666;
}
.content-inner {
position: absolute;
width: 100%;
height: 100%;
}
.box {
position: absolute;
background-image: url("../assets/car.png");
background-repeat: no-repeat;
background-size: 100% 100%;
transition: top 1s ease, left 1s ease;
}
.box .scan {
position: absolute;
background-image: url("../assets/scan.gif");
background-size: 100% 100%;
width: 100px;
height: 100px;
top: 50%;
right: 15px;
transform: translateY(-50%);
}
.dot {
position: absolute;
background: radial-gradient(circle at center,
#ea1212 0%, rgba(228, 116, 116, 0.2) 100%);
border-radius: 50%;
}
.tick {
position: absolute;
opacity: 0.4;
pointer-events: none;
}
.tick.major {
opacity: 1;
}
.ruler.vertical .tick {
border-top: 1px solid white;
}
.ruler.vertical .tick.major {
border-top: 2px solid white;
}
.ruler.vertical .label {
position: absolute;
font-size: 10px;
bottom: -6px;
right: 18px;
}
.ruler.horizontal .tick {
border-left: 1px solid white;
}
.ruler.horizontal .tick.major {
border-left: 2px solid white;
}
.ruler.horizontal .label {
position: absolute;
font-size: 10px;
top: 18px;
left: -6px;
}
.ruler-content {
position: relative;
}
.leftLine {
position: absolute;
top: 0;
left: 20%;
width: 1px;
height: calc(100% - 40px);
border-right: 3px dashed white;
z-index: 9999;
}
.line {
position: absolute;
height: 2px;
background: yellow;
}
</style>

@ -62,9 +62,9 @@ button:focus-visible {
}
#app {
max-width: 1280px;
width: 1080px;
min-width: 1080px;
margin: 0 auto;
padding: 2rem;
}
@media (prefers-color-scheme: light) {

File diff suppressed because it is too large Load Diff

@ -1,5 +1,6 @@
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import path from 'path';
// https://vite.dev/config/
@ -14,8 +15,7 @@ export default defineConfig({
rewrite: (path) => path.replace(new RegExp('^' + '/dev-api'), '')
}
}
},
plugins: [vue()], resolve: {
}, plugins: [vue(), vueJsx()], resolve: {
alias: {
'~': path.resolve(__dirname, './'), '@': path.resolve(__dirname, 'src')
}, extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']

@ -7,6 +7,142 @@
resolved "https://registry.npmmirror.com/7zip-bin/-/7zip-bin-5.2.0.tgz#7a03314684dd6572b7dfa89e68ce31d60286854d"
integrity sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==
"@babel/code-frame@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be"
integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==
dependencies:
"@babel/helper-validator-identifier" "^7.27.1"
js-tokens "^4.0.0"
picocolors "^1.1.1"
"@babel/compat-data@^7.27.2":
version "7.28.4"
resolved "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.28.4.tgz#96fdf1af1b8859c8474ab39c295312bfb7c24b04"
integrity sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==
"@babel/core@^7.28.3":
version "7.28.4"
resolved "https://registry.npmmirror.com/@babel/core/-/core-7.28.4.tgz#12a550b8794452df4c8b084f95003bce1742d496"
integrity sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==
dependencies:
"@babel/code-frame" "^7.27.1"
"@babel/generator" "^7.28.3"
"@babel/helper-compilation-targets" "^7.27.2"
"@babel/helper-module-transforms" "^7.28.3"
"@babel/helpers" "^7.28.4"
"@babel/parser" "^7.28.4"
"@babel/template" "^7.27.2"
"@babel/traverse" "^7.28.4"
"@babel/types" "^7.28.4"
"@jridgewell/remapping" "^2.3.5"
convert-source-map "^2.0.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
json5 "^2.2.3"
semver "^6.3.1"
"@babel/generator@^7.28.3":
version "7.28.3"
resolved "https://registry.npmmirror.com/@babel/generator/-/generator-7.28.3.tgz#9626c1741c650cbac39121694a0f2d7451b8ef3e"
integrity sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==
dependencies:
"@babel/parser" "^7.28.3"
"@babel/types" "^7.28.2"
"@jridgewell/gen-mapping" "^0.3.12"
"@jridgewell/trace-mapping" "^0.3.28"
jsesc "^3.0.2"
"@babel/helper-annotate-as-pure@^7.27.3":
version "7.27.3"
resolved "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5"
integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==
dependencies:
"@babel/types" "^7.27.3"
"@babel/helper-compilation-targets@^7.27.2":
version "7.27.2"
resolved "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d"
integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==
dependencies:
"@babel/compat-data" "^7.27.2"
"@babel/helper-validator-option" "^7.27.1"
browserslist "^4.24.0"
lru-cache "^5.1.1"
semver "^6.3.1"
"@babel/helper-create-class-features-plugin@^7.27.1":
version "7.28.3"
resolved "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz#3e747434ea007910c320c4d39a6b46f20f371d46"
integrity sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.27.3"
"@babel/helper-member-expression-to-functions" "^7.27.1"
"@babel/helper-optimise-call-expression" "^7.27.1"
"@babel/helper-replace-supers" "^7.27.1"
"@babel/helper-skip-transparent-expression-wrappers" "^7.27.1"
"@babel/traverse" "^7.28.3"
semver "^6.3.1"
"@babel/helper-globals@^7.28.0":
version "7.28.0"
resolved "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674"
integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==
"@babel/helper-member-expression-to-functions@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44"
integrity sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==
dependencies:
"@babel/traverse" "^7.27.1"
"@babel/types" "^7.27.1"
"@babel/helper-module-imports@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204"
integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==
dependencies:
"@babel/traverse" "^7.27.1"
"@babel/types" "^7.27.1"
"@babel/helper-module-transforms@^7.28.3":
version "7.28.3"
resolved "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6"
integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==
dependencies:
"@babel/helper-module-imports" "^7.27.1"
"@babel/helper-validator-identifier" "^7.27.1"
"@babel/traverse" "^7.28.3"
"@babel/helper-optimise-call-expression@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200"
integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==
dependencies:
"@babel/types" "^7.27.1"
"@babel/helper-plugin-utils@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c"
integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==
"@babel/helper-replace-supers@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0"
integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==
dependencies:
"@babel/helper-member-expression-to-functions" "^7.27.1"
"@babel/helper-optimise-call-expression" "^7.27.1"
"@babel/traverse" "^7.27.1"
"@babel/helper-skip-transparent-expression-wrappers@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56"
integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==
dependencies:
"@babel/traverse" "^7.27.1"
"@babel/types" "^7.27.1"
"@babel/helper-string-parser@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
@ -17,6 +153,26 @@
resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8"
integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==
"@babel/helper-validator-option@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f"
integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==
"@babel/helpers@^7.28.4":
version "7.28.4"
resolved "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.4.tgz#fe07274742e95bdf7cf1443593eeb8926ab63827"
integrity sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==
dependencies:
"@babel/template" "^7.27.2"
"@babel/types" "^7.28.4"
"@babel/parser@^7.27.2", "@babel/parser@^7.28.3", "@babel/parser@^7.28.4":
version "7.28.4"
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.4.tgz#da25d4643532890932cc03f7705fe19637e03fa8"
integrity sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==
dependencies:
"@babel/types" "^7.28.4"
"@babel/parser@^7.28.0":
version "7.28.0"
resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e"
@ -24,6 +180,61 @@
dependencies:
"@babel/types" "^7.28.0"
"@babel/plugin-syntax-jsx@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c"
integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==
dependencies:
"@babel/helper-plugin-utils" "^7.27.1"
"@babel/plugin-syntax-typescript@^7.27.1":
version "7.27.1"
resolved "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18"
integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==
dependencies:
"@babel/helper-plugin-utils" "^7.27.1"
"@babel/plugin-transform-typescript@^7.28.0":
version "7.28.0"
resolved "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz#796cbd249ab56c18168b49e3e1d341b72af04a6b"
integrity sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.27.3"
"@babel/helper-create-class-features-plugin" "^7.27.1"
"@babel/helper-plugin-utils" "^7.27.1"
"@babel/helper-skip-transparent-expression-wrappers" "^7.27.1"
"@babel/plugin-syntax-typescript" "^7.27.1"
"@babel/template@^7.27.2":
version "7.27.2"
resolved "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d"
integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==
dependencies:
"@babel/code-frame" "^7.27.1"
"@babel/parser" "^7.27.2"
"@babel/types" "^7.27.1"
"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.0", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.4":
version "7.28.4"
resolved "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.28.4.tgz#8d456101b96ab175d487249f60680221692b958b"
integrity sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==
dependencies:
"@babel/code-frame" "^7.27.1"
"@babel/generator" "^7.28.3"
"@babel/helper-globals" "^7.28.0"
"@babel/parser" "^7.28.4"
"@babel/template" "^7.27.2"
"@babel/types" "^7.28.4"
debug "^4.3.1"
"@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.4":
version "7.28.4"
resolved "https://registry.npmmirror.com/@babel/types/-/types-7.28.4.tgz#0a4e618f4c60a7cd6c11cb2d48060e4dbe38ac3a"
integrity sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==
dependencies:
"@babel/helper-string-parser" "^7.27.1"
"@babel/helper-validator-identifier" "^7.27.1"
"@babel/types@^7.28.0":
version "7.28.2"
resolved "https://registry.npmmirror.com/@babel/types/-/types-7.28.2.tgz#da9db0856a9a88e0a13b019881d7513588cf712b"
@ -340,11 +551,45 @@
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5":
version "0.3.13"
resolved "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f"
integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
"@jridgewell/trace-mapping" "^0.3.24"
"@jridgewell/remapping@^2.3.5":
version "2.3.5"
resolved "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1"
integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==
dependencies:
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
"@jridgewell/resolve-uri@^3.1.0":
version "3.1.2"
resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.5":
version "1.5.5"
resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba"
integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==
"@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.4"
resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7"
integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28":
version "0.3.31"
resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0"
integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==
dependencies:
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@malept/cross-spawn-promise@^2.0.0":
version "2.0.0"
resolved "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz#d0772de1aa680a0bfb9ba2f32b4c828c7857cb9d"
@ -393,6 +638,11 @@
resolved "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz#f8fc9a8788757dccba0d3b7fee93183621773d4c"
integrity sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==
"@rolldown/pluginutils@^1.0.0-beta.34":
version "1.0.0-beta.37"
resolved "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.37.tgz#4d182db433f0ae1aff1984fc682d40a1fa37bb69"
integrity sha512-0taU1HpxFzrukvWIhLRI4YssJX2wOW5q1MxPXWztltsQ13TE51/larZIwhFdpyk7+K43TH7x6GJ8oEqAo+vDbA==
"@rollup/rollup-android-arm-eabi@4.46.1":
version "4.46.1"
resolved "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.1.tgz#c659481d5b15054d4636b3dd0c2f50ab3083d839"
@ -619,6 +869,17 @@
resolved "https://registry.npmmirror.com/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz#c70d2a922bc437f154089d7ef0505db4b383eb7b"
integrity sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA==
"@vitejs/plugin-vue-jsx@^5.1.1":
version "5.1.1"
resolved "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-5.1.1.tgz#36504c57c8ccfc73b2dbd1fc560a1a473cba6cb4"
integrity sha512-uQkfxzlF8SGHJJVH966lFTdjM/lGcwJGzwAHpVqAPDD/QcsqoUGa+q31ox1BrUfi+FLP2ChVp7uLXE3DkHyDdQ==
dependencies:
"@babel/core" "^7.28.3"
"@babel/plugin-syntax-typescript" "^7.27.1"
"@babel/plugin-transform-typescript" "^7.28.0"
"@rolldown/pluginutils" "^1.0.0-beta.34"
"@vue/babel-plugin-jsx" "^1.5.0"
"@vitejs/plugin-vue@^6.0.0":
version "6.0.1"
resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz#4c7f559621af104a22255c6ace5626e6d8349689"
@ -626,6 +887,37 @@
dependencies:
"@rolldown/pluginutils" "1.0.0-beta.29"
"@vue/babel-helper-vue-transform-on@1.5.0":
version "1.5.0"
resolved "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz#b7e99d37eeb144d7b9757d7a1f40cd977fde748a"
integrity sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==
"@vue/babel-plugin-jsx@^1.5.0":
version "1.5.0"
resolved "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz#1b988b497cb1f79725da94463e75cebe60b72e70"
integrity sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==
dependencies:
"@babel/helper-module-imports" "^7.27.1"
"@babel/helper-plugin-utils" "^7.27.1"
"@babel/plugin-syntax-jsx" "^7.27.1"
"@babel/template" "^7.27.2"
"@babel/traverse" "^7.28.0"
"@babel/types" "^7.28.2"
"@vue/babel-helper-vue-transform-on" "1.5.0"
"@vue/babel-plugin-resolve-type" "1.5.0"
"@vue/shared" "^3.5.18"
"@vue/babel-plugin-resolve-type@1.5.0":
version "1.5.0"
resolved "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz#6881d7b1478e9fc0ea4bb08aaad1f4d206655568"
integrity sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==
dependencies:
"@babel/code-frame" "^7.27.1"
"@babel/helper-module-imports" "^7.27.1"
"@babel/helper-plugin-utils" "^7.27.1"
"@babel/parser" "^7.28.0"
"@vue/compiler-sfc" "^3.5.18"
"@vue/compiler-core@3.5.18":
version "3.5.18"
resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.18.tgz#521a138cdd970d9bfd27e42168d12f77a04b2074"
@ -637,6 +929,17 @@
estree-walker "^2.0.2"
source-map-js "^1.2.1"
"@vue/compiler-core@3.5.21":
version "3.5.21"
resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.21.tgz#5915b19273f0492336f0beb227aba86813e2c8a8"
integrity sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==
dependencies:
"@babel/parser" "^7.28.3"
"@vue/shared" "3.5.21"
entities "^4.5.0"
estree-walker "^2.0.2"
source-map-js "^1.2.1"
"@vue/compiler-dom@3.5.18":
version "3.5.18"
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz#e13504492c3061ec5bbe6a2e789f15261d4f03a7"
@ -645,6 +948,14 @@
"@vue/compiler-core" "3.5.18"
"@vue/shared" "3.5.18"
"@vue/compiler-dom@3.5.21":
version "3.5.21"
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz#26126447fe1e1d16c8cbac45b26e66b3f7175f65"
integrity sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==
dependencies:
"@vue/compiler-core" "3.5.21"
"@vue/shared" "3.5.21"
"@vue/compiler-sfc@3.5.18":
version "3.5.18"
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz#ba1e849561337d809937994cdaf900539542eeca"
@ -660,6 +971,21 @@
postcss "^8.5.6"
source-map-js "^1.2.1"
"@vue/compiler-sfc@^3.5.18":
version "3.5.21"
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz#e48189ef3ffe334c864c2625389ebe3bb4fa41eb"
integrity sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==
dependencies:
"@babel/parser" "^7.28.3"
"@vue/compiler-core" "3.5.21"
"@vue/compiler-dom" "3.5.21"
"@vue/compiler-ssr" "3.5.21"
"@vue/shared" "3.5.21"
estree-walker "^2.0.2"
magic-string "^0.30.18"
postcss "^8.5.6"
source-map-js "^1.2.1"
"@vue/compiler-ssr@3.5.18":
version "3.5.18"
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz#aecde0b0bff268a9c9014ba66799307c4a784328"
@ -668,6 +994,14 @@
"@vue/compiler-dom" "3.5.18"
"@vue/shared" "3.5.18"
"@vue/compiler-ssr@3.5.21":
version "3.5.21"
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz#f351c27aa5c075faa609596b2269c53df0df3aa1"
integrity sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==
dependencies:
"@vue/compiler-dom" "3.5.21"
"@vue/shared" "3.5.21"
"@vue/devtools-api@^6.6.4":
version "6.6.4"
resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343"
@ -711,6 +1045,11 @@
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.18.tgz#529f24a88d3ed678d50fd5c07455841fbe8ac95e"
integrity sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==
"@vue/shared@3.5.21", "@vue/shared@^3.5.18":
version "3.5.21"
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.21.tgz#505edb122629d1979f70a2a65ca0bd4050dc2e54"
integrity sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==
"@vueuse/core@^9.1.0":
version "9.13.0"
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-9.13.0.tgz#2f69e66d1905c1e4eebc249a01759cf88ea00cf4"
@ -910,6 +1249,11 @@ base64-js@^1.3.1, base64-js@^1.5.1:
resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
baseline-browser-mapping@^2.8.2:
version "2.8.3"
resolved "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.3.tgz#e52e1d836fd242384ee152dce7b62952e4442619"
integrity sha512-mcE+Wr2CAhHNWxXN/DdTI+n4gsPc5QpXpWnyCQWiQYIYZX+ZMJ8juXZgjRa/0/YPJo/NSsgW15/YgmI4nbysYw==
bl@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
@ -939,6 +1283,17 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"
browserslist@^4.24.0:
version "4.26.0"
resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.26.0.tgz#035ca84b4ff312a3c6a7014a77beb83456a882dd"
integrity sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==
dependencies:
baseline-browser-mapping "^2.8.2"
caniuse-lite "^1.0.30001741"
electron-to-chromium "^1.5.218"
node-releases "^2.0.21"
update-browserslist-db "^1.1.3"
buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
@ -1038,6 +1393,11 @@ call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
es-errors "^1.3.0"
function-bind "^1.1.2"
caniuse-lite@^1.0.30001741:
version "1.0.30001741"
resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz#67fb92953edc536442f3c9da74320774aa523143"
integrity sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@ -1149,6 +1509,11 @@ config-file-ts@0.2.8-rc1:
glob "^10.3.12"
typescript "^5.4.3"
convert-source-map@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@ -1338,6 +1703,11 @@ electron-publish@26.0.11:
lazy-val "^1.0.5"
mime "^2.5.2"
electron-to-chromium@^1.5.218:
version "1.5.218"
resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz#921042a011a98a4620853c9d391ab62bcc124400"
integrity sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==
electron@^37.3.1:
version "37.3.1"
resolved "https://registry.npmmirror.com/electron/-/electron-37.3.1.tgz#92d0299593c4302dcdf3305af917c60dad69719f"
@ -1471,7 +1841,7 @@ esbuild@^0.25.0:
"@esbuild/win32-ia32" "0.25.8"
"@esbuild/win32-x64" "0.25.8"
escalade@^3.1.1:
escalade@^3.1.1, escalade@^3.2.0:
version "3.2.0"
resolved "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
@ -1624,6 +1994,11 @@ function-bind@^1.1.2:
resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@ -1946,6 +2321,11 @@ jake@^10.8.5:
filelist "^1.0.4"
picocolors "^1.1.1"
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@ -1953,6 +2333,11 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
jsesc@^3.0.2:
version "3.1.0"
resolved "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
@ -2034,6 +2419,13 @@ lru-cache@^10.2.0:
resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
lru-cache@^5.1.1:
version "5.1.1"
resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
dependencies:
yallist "^3.0.2"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@ -2053,6 +2445,13 @@ magic-string@^0.30.17:
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
magic-string@^0.30.18:
version "0.30.19"
resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.19.tgz#cebe9f104e565602e5d2098c5f2e79a77cc86da9"
integrity sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.5"
make-fetch-happen@^10.2.1:
version "10.2.1"
resolved "https://registry.npmmirror.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164"
@ -2260,6 +2659,11 @@ node-api-version@^0.2.0:
dependencies:
semver "^7.3.5"
node-releases@^2.0.21:
version "2.0.21"
resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.21.tgz#f59b018bc0048044be2d4c4c04e4c8b18160894c"
integrity sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==
nopt@^6.0.0:
version "6.0.0"
resolved "https://registry.npmmirror.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d"
@ -2570,7 +2974,7 @@ semver@^5.5.0:
resolved "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
semver@^6.2.0:
semver@^6.2.0, semver@^6.3.1:
version "6.3.1"
resolved "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
@ -2833,6 +3237,14 @@ universalify@^2.0.0:
resolved "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==
update-browserslist-db@^1.1.3:
version "1.1.3"
resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420"
integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==
dependencies:
escalade "^3.2.0"
picocolors "^1.1.1"
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
@ -2943,6 +3355,11 @@ y18n@^5.0.5:
resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yallist@^3.0.2:
version "3.1.1"
resolved "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"

Loading…
Cancel
Save