This commit is contained in:
BianLzhaoMin 2025-08-12 09:56:01 +08:00
parent f865c765fb
commit bc65a8ceae
7 changed files with 343 additions and 78 deletions

View File

@ -89,6 +89,8 @@ service.interceptors.response.use(
setTimeout(() => {
message.error('登录已经失效,请重新登录')
// 清除所有localStorage
localStorage.clear()
window.location.href = 'http://sgwpdm.ah.sgcc.com.cn/iws/#/unified/'
}, 500)
return Promise.reject(data)

View File

@ -86,6 +86,8 @@ service.interceptors.response.use(
// modelShow = false
// }
message.error('登录已经失效,请重新登录')
// 清除所有localStorage
localStorage.clear()
setTimeout(() => {
window.location.href = 'http://sgwpdm.ah.sgcc.com.cn/iws/#/unified/'
}, 500)

View File

@ -134,4 +134,8 @@
.n-radio .n-radio__dot {
background-color: #1d3861;
}
.n-input.n-input--disabled {
background-color: #1d3861;
}

View File

@ -424,6 +424,7 @@ const audioMimeTypes = ref(
'.pcm,.wav,.aac,audio/wav,audio/x-wav,audio/x-aiff,audio/aac,audio/x-aac',
)
//
const audioOptions = ref([
{
label: '播放',

View File

@ -7,11 +7,13 @@
>
<div class="add-or-edit-marker-form">
<n-form
ref="addOrEditFormRef"
size="small"
label-placement="left"
style="margin-top: 10px"
label-width="140"
label-placement="left"
ref="addOrEditFormRef"
style="margin-top: 10px"
require-mark-placement="left"
:rules="addOrEditMarkerFormRules"
>
<n-grid x-gap="24" :cols="24">
<n-gi :span="24">
@ -24,7 +26,7 @@
</n-grid>
<n-grid x-gap="24" :cols="24">
<n-gi :span="24">
<n-form-item label="点位名称:" prop="markerName">
<n-form-item label="点位名称:" path="markerName">
<n-input
v-model:value="markerParams.markerName"
placeholder="点位名称"
@ -65,9 +67,10 @@
<n-gi :span="24">
<n-form-item label="角度:" prop="markerAngle">
<n-input
v-model:value="markerParams.markerAngle"
placeholder="角度"
disabled
clearable
placeholder="角度"
v-model:value="markerParams.markerAngle"
/>
</n-form-item>
</n-gi>
@ -153,9 +156,13 @@ const message = useMessage()
const deviceToken = ref('')
const deviceInfo = ref(null)
const isCurrentPosition = ref(null)
const addOrEditFormRef = ref(null)
const dialog = useDialog()
const emits = defineEmits(['onHandleCloseAddMarkerModal', 'onHandleConfirm'])
const addOrEditMarkerFormRules = ref({
markerName: [{ required: true, message: '请输入点位名称' }],
})
const cameraNode = ref({
token: '',
puid: '',
@ -295,54 +302,58 @@ const addOrEditMarker = async (isCurrentPosition) => {
const onHandleConfirm = () => {
// emits('onHandleConfirm', markerParams.value)
handleRobotActionApi({
puId: deviceInfo.value?.puId,
type: '2',
}).then(async (res) => {
const { Robot_x, Robot_y, PTZ_x, PTZ_y, PTZ_zoom, Robot_theta } = res?.data.data
addOrEditFormRef.value.validate().then(async (valid) => {
if (valid) {
handleRobotActionApi({
puId: deviceInfo.value?.puId,
type: '2',
}).then(async (res) => {
const { Robot_x, Robot_y, PTZ_x, PTZ_y, PTZ_zoom, Robot_theta } = res?.data.data
const isCurrentPosition = {
Robot_x,
Robot_y,
PTZ_x,
PTZ_y,
PTZ_zoom,
Robot_theta,
}
const isCurrentPosition = {
Robot_x,
Robot_y,
PTZ_x,
PTZ_y,
PTZ_zoom,
Robot_theta,
}
//
if (
Math.abs(Robot_x - markerParams.value.xCount) > 2 ||
Math.abs(Robot_y - markerParams.value.yCount) > 2
) {
if (markerParams.value.type === '修改') {
dialog.warning({
title: '温馨提示',
content:
'机器人当前位置与预置点位不一致,您可以点击前往点位按钮,也可以选择继续修改?',
positiveText: '前往点位',
negativeText: '继续修改',
onPositiveClick: () => {
onHandleGoToPoint()
},
onNegativeClick: async () => {
addOrEditMarker(isCurrentPosition)
},
})
} else {
dialog.warning({
title: '温馨提示',
content: '机器人当前位置与预置点位不一致,确定新增吗?',
positiveText: '确定新增',
negativeText: '取消',
onPositiveClick: async () => {
addOrEditMarker(isCurrentPosition)
},
onNegativeClick: () => {},
})
}
} else {
addOrEditMarker(isCurrentPosition)
//
if (
Math.abs(Robot_x - markerParams.value.xCount) > 2 ||
Math.abs(Robot_y - markerParams.value.yCount) > 2
) {
if (markerParams.value.type === '修改') {
dialog.warning({
title: '温馨提示',
content:
'机器人当前位置与预置点位不一致,您可以点击前往点位按钮,也可以选择继续修改?',
positiveText: '前往点位',
negativeText: '继续修改',
onPositiveClick: () => {
onHandleGoToPoint()
},
onNegativeClick: async () => {
addOrEditMarker(isCurrentPosition)
},
})
} else {
dialog.warning({
title: '温馨提示',
content: '机器人当前位置与预置点位不一致,确定新增吗?',
positiveText: '确定新增',
negativeText: '取消',
onPositiveClick: async () => {
addOrEditMarker(isCurrentPosition)
},
onNegativeClick: () => {},
})
}
} else {
addOrEditMarker(isCurrentPosition)
}
})
}
})
}
@ -390,7 +401,7 @@ watch(
onMounted(async () => {
deviceToken.value = await getRobotTokenFn()
deviceInfo.value = await getRobotDeviceListFn()
const mapInfo = await getRobotMapInfoFn(deviceInfo?.puId)
const mapInfo = await getRobotMapInfoFn(deviceInfo.value?.puId)
markerParams.value.mapId = mapInfo?.mapId
cameraNode.value.puid = deviceInfo.value?.puId
cameraNode.value.token = deviceToken.value

View File

@ -37,7 +37,7 @@
<!-- 中间的按钮 -->
<div class="row-3-item-1-center" @click="handleStopCamera">
<img alt="" class="center-icon" :src="!isStopLeft ? startImg : stopImg" />
<img alt="" class="center-icon" :src="isStopLeft ? startImg : stopImg" />
</div>
<!-- 描述文字 -->
@ -132,7 +132,7 @@ const message = useMessage()
const isStopLeft = ref(false)
const isStopRight = ref(false)
const isZoom = ref(false)
const robotBaseInfo = ref({})
const robotBaseInfo = ref({ type: '' })
const props = defineProps({
deviceToken: {
@ -148,7 +148,7 @@ const props = defineProps({
//
const getRobotBaseInfo = async () => {
const { data: res } = await handleRobotActionApi({
puId: deviceInfo.value?.puId,
puId: props.deviceInfo.value?.puId,
type: '1',
})

View File

@ -10,18 +10,18 @@
<div
class="plane-map-container"
ref="planeMapContainer"
:class="{ 'can-drag': canDrag() }"
:style="{ height: INITIAL_HEIGHT + 'px' }"
style="min-height: 70vh"
@mousemove="handleMouseMove"
:class="{ 'can-drag': canDrag() }"
:style="{ height: INITIAL_HEIGHT + 'px' }"
>
<svg
ref="svgMapRef"
class="svg-map-container"
:width="svgWidth"
:height="svgHeight"
@wheel.passive="handleWheel"
@click="handleMapClick"
class="svg-map-container"
@wheel.passive="handleWheel"
:style="{ transform: `translate(${offsetX}px, ${offsetY}px)` }"
>
<!-- 图片宽高 100% 跟随 SVG -->
@ -44,11 +44,59 @@
:ref="(el) => setItemRef(el, index)"
@contextmenu.prevent="handlePointRightClick($event, point, index)"
/>
<!-- 方向指示器 -->
<g v-if="showDirectionIndicator">
<!-- 圆环 -->
<circle
:cx="selectedPoint.x * scale + offsetX / scale"
:cy="selectedPoint.y * scale + offsetY / scale"
r="20"
fill="none"
stroke="#5c96fa"
stroke-width="1"
/>
<!-- 箭头线 -->
<line
:x1="selectedPoint.x * scale + offsetX / scale"
:y1="selectedPoint.y * scale + offsetY / scale"
:x2="arrowEndX"
:y2="arrowEndY"
stroke="#5c96fa"
stroke-width="2"
marker-end="url(#arrowhead)"
@click="handlePointClickCircle()"
/>
<!-- 角度显示 -->
<!-- <text
:x="selectedPoint.x * scale + offsetX / scale + 30"
:y="selectedPoint.y * scale + offsetY / scale - 30"
fill="#5c96fa"
font-size="12"
>
{{ Math.round(currentAngle) }}°
</text> -->
</g>
<!-- 箭头标记定义 -->
<defs>
<marker
id="arrowhead"
markerWidth="10"
markerHeight="7"
refX="0"
refY="3.5"
orient="auto"
>
<polygon points="0 0, 10 3.5, 0 7" fill="#5c96fa" />
</marker>
</defs>
</svg>
<div v-if="showTooltip && mousePosition" class="coord-tooltip" :style="tooltipStyle">
<!-- 数据向下取整 -->
X: {{ Math.floor(mousePosition.x) * 2 }}, Y: {{ Math.floor(mousePosition.y) * 2 }}
X: {{ Math.floor(mousePosition.x) * 2 }}, Y:{{ Math.floor(mousePosition.y) * 2 }},
角度{{ Math.round(currentAngle) }}°
</div>
<div v-if="showContextMenu" class="context-menu" :style="contextMenuStyle" @click.stop>
@ -86,6 +134,7 @@ import { AddCircleOutline, RemoveCircleOutline } from '@vicons/ionicons5'
import { getRobotDeviceListFn, getRobotMapInfoFn } from '@/utils/getRobotInfo'
import { getMarkerListAllApi, deleteMarkerApi } from '@/api/home'
import { useMessage } from 'naive-ui'
import demoImg from '@/assets/demo.png'
const modalTitle = ref('预置位配置') //
const mousePosition = ref(null) //
@ -94,8 +143,8 @@ const isPointClickStatus = ref(true) // 是否点击点位
const mapInfo = ref({}) //
// SVG
const INITIAL_WIDTH = ref(0)
const INITIAL_HEIGHT = ref(0)
const INITIAL_WIDTH = ref(400)
const INITIAL_HEIGHT = ref(400)
// SVG
const svgWidth = ref(INITIAL_WIDTH.value)
@ -133,6 +182,13 @@ const emits = defineEmits(['onHandleCloseModal', 'onHandleAddMarker']) // 定义
const message = useMessage()
//
const showDirectionIndicator = ref(false) //
const selectedPoint = ref({ x: 0, y: 0 }) //
const currentAngle = ref(0) //
const arrowEndX = ref(0) // X
const arrowEndY = ref(0) // Y
// props
const props = defineProps({
markerInfoNew: {
@ -321,7 +377,26 @@ const showTooltip = ref(false)
//
const handleMouseMove = throttle((e) => {
// if (!svgMapRef.value) return
// // SVG
// const svgRect = svgMapRef.value.getBoundingClientRect()
// const isInside =
// e.clientX >= svgRect.left &&
// e.clientX <= svgRect.right &&
// e.clientY >= svgRect.top &&
// e.clientY <= svgRect.bottom
// showTooltip.value = isInside
// if (isInside) {
// mousePosition.value = getLogicalPosition(e.clientX, e.clientY)
// tooltipStyle.value = {
// left: `${e.clientX}px`,
// top: `${e.clientY}px`,
// }
// }
if (!svgMapRef.value) return
// SVG
const svgRect = svgMapRef.value.getBoundingClientRect()
const isInside =
@ -337,13 +412,69 @@ const handleMouseMove = throttle((e) => {
left: `${e.clientX}px`,
top: `${e.clientY}px`,
}
//
if (showDirectionIndicator.value) {
const centerX = selectedPoint.value.x * scale.value + offsetX.value / scale.value
const centerY = selectedPoint.value.y * scale.value + offsetY.value / scale.value
// SVG
const mouseX = (e.clientX - svgRect.left - offsetX.value) / scale.value
const mouseY = (e.clientY - svgRect.top - offsetY.value) / scale.value
//
const dx = mouseX - selectedPoint.value.x
const dy = selectedPoint.value.y - mouseY // Y
// 0-360
let angle = (Math.atan2(dy, dx) * 180) / Math.PI
if (angle < 0) angle += 360
currentAngle.value = angle
updateArrowPosition(angle)
//
if (selectedPoint.value.index !== undefined) {
devicePoints.value[selectedPoint.value.index].markerAngle = Math.round(angle)
}
}
}
}, 30)
//
const handleMapClick = (e) => {
// isPointClickStatus.value = false
// if (!svgMapRef.value || isDragging.value) return //
// //
// const isPointClick = devicePoints.value.some((point, index) => {
// const pointRect = itemRefs.value[index].getBoundingClientRect()
// return (
// e.clientX >= pointRect.left &&
// e.clientX <= pointRect.right &&
// e.clientY >= pointRect.top &&
// e.clientY <= pointRect.bottom
// )
// })
// if (isPointClick) {
// return
// }
// const svgRect = svgMapRef.value.getBoundingClientRect()
// const isInside =
// e.clientX >= svgRect.left &&
// e.clientX <= svgRect.right &&
// e.clientY >= svgRect.top &&
// e.clientY <= svgRect.bottom
// if (isInside) {
// const pos = getLogicalPosition(e.clientX, e.clientY)
// addDevicePoint(pos.x, pos.y, pos.y1)
// }
isPointClickStatus.value = false
if (!svgMapRef.value || isDragging.value) return //
if (!svgMapRef.value || isDragging.value) return
//
const isPointClick = devicePoints.value.some((point, index) => {
const pointRect = itemRefs.value[index].getBoundingClientRect()
@ -355,20 +486,24 @@ const handleMapClick = (e) => {
)
})
if (isPointClick) {
return
//
if (!isPointClick) {
showDirectionIndicator.value = false
}
const svgRect = svgMapRef.value.getBoundingClientRect()
const isInside =
e.clientX >= svgRect.left &&
e.clientX <= svgRect.right &&
e.clientY >= svgRect.top &&
e.clientY <= svgRect.bottom
if (!isPointClick) {
const svgRect = svgMapRef.value.getBoundingClientRect()
const isInside =
e.clientX >= svgRect.left &&
e.clientX <= svgRect.right &&
e.clientY >= svgRect.top &&
e.clientY <= svgRect.bottom
if (isInside) {
const pos = getLogicalPosition(e.clientX, e.clientY)
addDevicePoint(pos.x, pos.y, pos.y1)
if (isInside) {
const pos = getLogicalPosition(e.clientX, e.clientY)
addDevicePoint(pos.x, pos.y, pos.y1)
console.log(pos, 'pos')
}
}
}
@ -376,6 +511,7 @@ const handleMapClick = (e) => {
const handlePointRightClick = (e, point, index) => {
e.preventDefault()
selectedPointIndex.value = index
showDirectionIndicator.value = false //
//
const containerRect = planeMapContainer.value.getBoundingClientRect()
@ -467,22 +603,121 @@ const addDevicePoint = (x, y, y1) => {
})
}
//
const updateArrowPosition = (angle) => {
const radius = 20 // 20
const centerX = selectedPoint.value.x * scale.value + offsetX.value / scale.value
const centerY = selectedPoint.value.y * scale.value + offsetY.value / scale.value
// SVGY
arrowEndX.value = centerX + radius * Math.cos((angle * Math.PI) / 180)
arrowEndY.value = centerY - radius * Math.sin((angle * Math.PI) / 180)
}
//
const handlePointClick = (point, index) => {
if (point.id) {
message.warning('点位已存在,无需新增,可右击修改或删除')
return
}
// const markerInfo = {
// type: '',
// xCount: point.xCount, //
// yCount: point.yCount, //
// markerIndex: index,
// markerX: point.markerX,
// markerY: point.markerY,
// markerY1: point.markerY1,
// markerName: point.markerName,
// markerAngle: point.markerAngle,
// markerPreset: point.markerPreset,
// isAdd: point.isAdd,
// }
// emits('onHandleAddMarker', markerInfo)
// if (point.id) {
// message.warning('')
// return
// }
//
selectedPoint.value = {
x: point.markerX,
y: point.markerY1,
index,
point,
}
currentAngle.value = 0
updateArrowPosition(0) // 0
showDirectionIndicator.value = true
// const markerInfo = {
// type: '',
// xCount: point.xCount, //
// yCount: point.yCount, //
// markerIndex: index,
// markerX: point.markerX,
// markerY: point.markerY,
// markerY1: point.markerY1,
// markerName: point.markerName,
// markerAngle: point.markerAngle,
// markerPreset: point.markerPreset,
// isAdd: point.isAdd,
// }
// emits('onHandleAddMarker', markerInfo)
//
// if (showDirectionIndicator.value && selectedPoint.value.index === index) {
// //
// if (currentAngle.value !== undefined && currentAngle.value !== null) {
// //
// point.markerAngle = Math.round(currentAngle.value)
// const markerInfo = {
// type: '',
// xCount: point.xCount,
// yCount: point.yCount,
// markerIndex: index,
// markerX: point.markerX,
// markerY: point.markerY,
// markerY1: point.markerY1,
// markerName: point.markerName,
// markerAngle: point.markerAngle,
// markerPreset: point.markerPreset,
// isAdd: point.isAdd,
// }
// emits('onHandleAddMarker', markerInfo)
// }
// showDirectionIndicator.value = false //
// } else {
// //
// selectedPoint.value = {
// x: point.markerX,
// y: point.markerY1,
// index,
// point,
// }
// currentAngle.value = point.markerAngle || 0 // 使0
// updateArrowPosition(currentAngle.value)
// showDirectionIndicator.value = true
// }
}
// 线
const handlePointClickCircle = () => {
const point = devicePoints.value.find((item) => item.markerY1 == selectedPoint.value.y)
const index = devicePoints.value.findIndex((item) => item.markerY1 == selectedPoint.value.y)
const markerInfo = {
type: '新增',
xCount: point.xCount, //
yCount: point.yCount, //
xCount: point.xCount,
yCount: point.yCount,
markerIndex: index,
markerX: point.markerX,
markerY: point.markerY,
markerY1: point.markerY1,
markerName: point.markerName,
markerAngle: point.markerAngle,
markerAngle: point.markerAngle * 1,
markerPreset: point.markerPreset,
isAdd: point.isAdd,
}
@ -691,4 +926,14 @@ watch(
}
}
}
/* 新增的样式 */
.angle-display {
position: absolute;
background: rgba(255, 255, 255, 0.8);
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
pointer-events: none;
}
</style>