批量复制改为弧度和距离复制

图例增加曲线隐藏
This commit is contained in:
yyy 2025-06-25 16:55:11 +08:00
parent 24dde0807c
commit b1fbcb09f2
4 changed files with 105 additions and 91 deletions

View File

@ -8,25 +8,27 @@
@close="dialogClose" @close="dialogClose"
> >
<el-form :model="batchCopyingForm" label-width="120" ref="BatchCopyingFormRef" :rules="rules"> <el-form :model="batchCopyingForm" label-width="120" ref="BatchCopyingFormRef" :rules="rules">
<el-form-item label="X轴偏移量(实际点位)" prop="x" required> <el-form-item label="方向(弧度)" prop="radian" required>
<el-input-number <el-input-number
v-model="batchCopyingForm.x" v-model="batchCopyingForm.radian"
placeholder="请输入" placeholder="请输入弧度"
controls-position="right" controls-position="right"
style="width: 100%" style="width: 100%"
precision="2" :min="-Math.PI"
:max="Math.PI"
:step="0.01"
precision="4"
/> />
<el-text type="info" size="small">X轴往左为负值往右为正值</el-text>
</el-form-item> </el-form-item>
<el-form-item label="Y轴偏移量(实际点位)" prop="y" required> <el-form-item label="偏移距离(米)" prop="distance" required>
<el-input-number <el-input-number
v-model="batchCopyingForm.y" v-model="batchCopyingForm.distance"
placeholder="请输入" placeholder="请输入距离"
controls-position="right" controls-position="right"
style="width: 100%" style="width: 100%"
:min="0"
precision="2" precision="2"
/> />
<el-text type="info" size="small">Y轴往上为负值往下为正值</el-text>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -39,7 +41,7 @@
</template> </template>
<script setup> <script setup>
import { reactive, ref } from 'vue' import { reactive, ref, watch } from 'vue'
import * as MapApi from '@/api/map/map' import * as MapApi from '@/api/map/map'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
@ -52,6 +54,8 @@ const props = defineProps({
}) })
// //
const batchCopyingForm = ref({ const batchCopyingForm = ref({
radian: 0,
distance: 0,
x: 0, x: 0,
y: 0 y: 0
}) })
@ -59,44 +63,30 @@ const boundaryValue = ref()
const BatchCopyingFormRef = ref() const BatchCopyingFormRef = ref()
const dialogFormVisible = ref(false) // const dialogFormVisible = ref(false) //
const validateXValue = (rule, value, callback) => { const roundToThree = (num) => Math.round(Number(num) * 1000) / 1000
const { resolution, width } = props.imgBgObj
let maxLeft = -(Number(boundaryValue.value.left) / Number(resolution)) watch(
let maxRight = (Number(width) - Number(boundaryValue.value.right)) / Number(resolution) () => [batchCopyingForm.value.radian, batchCopyingForm.value.distance],
if (value < maxLeft || value > maxRight) { ([newRadian, newDistance]) => {
callback(new Error(`不能超出地图宽度,可偏移范围为${maxLeft}${maxRight}`)) // xy
} else { // Ysin
callback() const x = newDistance * Math.cos(newRadian)
} const y = -1 * newDistance * Math.sin(newRadian)
} batchCopyingForm.value.x = roundToThree(x)
const validateYValue = (rule, value, callback) => { batchCopyingForm.value.y = roundToThree(y)
const { resolution, height } = props.imgBgObj },
{ immediate: true }
let maxTop = -(Number(boundaryValue.value.top) / Number(resolution)) )
let maxBottom = (Number(height) - Number(boundaryValue.value.bottom)) / Number(resolution)
if (value < maxTop || value > maxBottom) {
callback(new Error(`不能超出地图宽度,可偏移范围为${maxTop}${maxBottom}`))
} else {
callback()
}
}
const rules = reactive({ const rules = reactive({
x: [ radian: [{ required: true, message: '请输入方向弧度', trigger: 'blur' }],
{ required: true, message: '请输入X轴偏移量', trigger: 'blur' }, distance: [{ required: true, message: '请输入偏移距离', trigger: 'blur' }]
{ validator: validateXValue, trigger: 'blur' }
],
y: [
{ required: true, message: '请输入Y轴偏移量', trigger: 'blur' },
{ validator: validateYValue, trigger: 'blur' }
]
}) })
const open = (boundaryObj) => { const open = (boundaryObj) => {
boundaryValue.value = boundaryObj boundaryValue.value = boundaryObj
batchCopyingForm.value.x = 0 batchCopyingForm.value.radian = 0
batchCopyingForm.value.y = 0 batchCopyingForm.value.distance = 0
dialogFormVisible.value = true dialogFormVisible.value = true
} }
@ -115,6 +105,7 @@ const submitLineLibraryForm = async () => {
const y = roundToThree( const y = roundToThree(
safeNumber(batchCopyingForm.value.y) / safeNumber(props.imgBgObj.resolution) safeNumber(batchCopyingForm.value.y) / safeNumber(props.imgBgObj.resolution)
) )
emit('submitBatchCopyingFormSuccess', { emit('submitBatchCopyingFormSuccess', {
x: x, x: x,
y: y y: y
@ -124,7 +115,6 @@ const submitLineLibraryForm = async () => {
} }
const safeNumber = (value) => Number(value || 0) const safeNumber = (value) => Number(value || 0)
const roundToThree = (num) => Math.round(Number(num) * 1000) / 1000
defineExpose({ open }) // open defineExpose({ open }) // open
</script> </script>

View File

@ -134,7 +134,7 @@
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="库位类型" required prop="locationTypeId"> <el-form-item label="库位类型" required prop="locationTypeId" v-if="form.type === 2">
<el-select <el-select
class="!w-300px" class="!w-300px"
v-model="form.locationTypeId" v-model="form.locationTypeId"
@ -474,6 +474,7 @@ const typeChange = (type) => {
form.value.dataJson = null form.value.dataJson = null
form.value.dataObj = {} form.value.dataObj = {}
form.value.dataList = [] form.value.dataList = []
form.value.locationTypeId = null
if (type === 1) { if (type === 1) {
form.value.layersNumber = null form.value.layersNumber = null
form.value.direction = null form.value.direction = null

View File

@ -22,19 +22,28 @@ const emit = defineEmits(['layerSelectionSuccess'])
const list = ref([ const list = ref([
{ {
category: 'node',
type: 2, type: 2,
name: '库位点', name: '库位点',
isShow: true isShow: true
}, },
{ {
category: 'node',
type: 1, type: 1,
name: '路径点', name: '路径点',
isShow: true isShow: true
}, },
{ {
category: 'node',
type: 3, type: 3,
name: '设备点', name: '设备点',
isShow: true isShow: true
},
{
category: 'curve',
type: 4,
name: '曲线',
isShow: true
} }
]) ])
@ -44,9 +53,13 @@ const changeUnfold = () => {
isUnfold.value = !isUnfold.value isUnfold.value = !isUnfold.value
} }
const changeSelectList = (item) => { const changeSelectList = (item) => {
if (item.category === 'node') {
const types = list.value.filter((item) => !item.isShow).map((item) => item.type)
emit('layerSelectionSuccess', types)
} else {
emit('isCurveDisplayChange')
}
item.isShow = !item.isShow item.isShow = !item.isShow
const types = list.value.filter((item) => !item.isShow).map((item) => item.type)
emit('layerSelectionSuccess', types)
} }
const open = (item) => {} const open = (item) => {}
@ -59,8 +72,8 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
z-index: 999; z-index: 999;
background-color: #fff; background-color: #fff;
position: absolute; position: absolute;
bottom: 22px; bottom: 0px;
left: 18px; left: 0px;
width: 144px; width: 144px;
cursor: pointer; cursor: pointer;

View File

@ -715,49 +715,51 @@
</template> </template>
<template v-else> <template v-else>
<path <template v-if="state.isCurveDisplay">
id="curvePath" <path
:d="getCurvePath(curve)" id="curvePath"
:stroke="curve.isSelected ? '#f48924' : '#2d72d9'" :d="getCurvePath(curve)"
:stroke-width="state.routeWidthForm.routeWidth" :stroke="curve.isSelected ? '#f48924' : '#2d72d9'"
fill="none" :stroke-width="state.routeWidthForm.routeWidth"
@click="handleChooseRoute(curve, index)" fill="none"
/> @click="handleChooseRoute(curve, index)"
<text />
style="user-select: none" <text
:x="computedCurveTextX(curve)" style="user-select: none"
:y="computedCurveTextY(curve)" :x="computedCurveTextX(curve)"
font-size="11" :y="computedCurveTextY(curve)"
text-anchor="middle" font-size="11"
fill="black" text-anchor="middle"
v-if="curve.isSelected" fill="black"
@click="handleChooseRoute(curve, index)" v-if="curve.isSelected"
> @click="handleChooseRoute(curve, index)"
{{ calculateRouteLength(curve, 'curve') }} >
</text> {{ calculateRouteLength(curve, 'curve') }}
</text>
<!-- 第一条控制线 --> <!-- 第一条控制线 -->
<line <line
v-if="state.currentDragTarget.index == index" v-if="state.currentDragTarget.index == index"
:x1="Number(curve.startPointX)" :x1="Number(curve.startPointX)"
:y1="Number(curve.startPointY)" :y1="Number(curve.startPointY)"
:x2="curve.beginControlX" :x2="curve.beginControlX"
:y2="curve.beginControlY" :y2="curve.beginControlY"
:stroke="curve.isSelected ? '#f48924' : '#2d72d9'" :stroke="curve.isSelected ? '#f48924' : '#2d72d9'"
stroke-dasharray="4" stroke-dasharray="4"
stroke-width="2" stroke-width="2"
/> />
<!-- 第二条控制线 --> <!-- 第二条控制线 -->
<line <line
v-if="state.currentDragTarget.index == index" v-if="state.currentDragTarget.index == index"
:x1="Number(curve.endPointX)" :x1="Number(curve.endPointX)"
:y1="Number(curve.endPointY)" :y1="Number(curve.endPointY)"
:x2="curve.endControlX" :x2="curve.endControlX"
:y2="curve.endControlY" :y2="curve.endControlY"
:stroke="curve.isSelected ? '#f48924' : '#2d72d9'" :stroke="curve.isSelected ? '#f48924' : '#2d72d9'"
stroke-dasharray="4" stroke-dasharray="4"
stroke-width="2" stroke-width="2"
/> />
</template>
<!-- 控制点circle已移至SVG末尾 --> <!-- 控制点circle已移至SVG末尾 -->
</template> </template>
</template> </template>
@ -898,6 +900,7 @@
v-if="state.isShowLayer" v-if="state.isShowLayer"
ref="layerSelectionToolDialogRef" ref="layerSelectionToolDialogRef"
@layer-selection-success="layerSelectionSuccess" @layer-selection-success="layerSelectionSuccess"
@is-curve-display-change="isCurveDisplayChange"
/> />
<!-- 设备弹窗选择 --> <!-- 设备弹窗选择 -->
<equipmentToolDialog <equipmentToolDialog
@ -1712,7 +1715,8 @@ const state = reactive({
routeDirection: 2, //12 routeDirection: 2, //12
vLine: [], vLine: [],
hLine: [], hLine: [],
svgRouteZIndex: 9 svgRouteZIndex: 9,
isCurveDisplay: true
}) })
const getRefLineParams = (params) => { const getRefLineParams = (params) => {
@ -3847,6 +3851,11 @@ const layerSelectionSuccess = (typeList) => {
} }
}) })
} }
//线
const isCurveDisplayChange = () => {
state.isCurveDisplay = !state.isCurveDisplay
}
// //
const disposeEventPoints = (event) => { const disposeEventPoints = (event) => {
const rect = mapBackgroundRef.value.getBoundingClientRect() const rect = mapBackgroundRef.value.getBoundingClientRect()
@ -4196,7 +4205,7 @@ const findClosestPoint = (x, y) => {
padding: 0 0 0 4px; padding: 0 0 0 4px;
.top-tool-list { .top-tool-list {
max-width: calc(100vw - 260px); max-width: calc(100% - 200px);
overflow-x: auto; overflow-x: auto;
display: flex; display: flex;
align-items: center; align-items: center;
@ -4352,6 +4361,7 @@ const findClosestPoint = (x, y) => {
} }
.search-select { .search-select {
padding-right: 20px;
.search-icon { .search-icon {
widows: 20px; widows: 20px;
height: 20px; height: 20px;