1055 lines
28 KiB
Vue
1055 lines
28 KiB
Vue
<template>
|
||
<div class="top-tool">
|
||
<div class="top-tool-list">
|
||
<div v-for="item in state.topToolList" :key="item.switchType" class="top-tool-item">
|
||
<el-popover
|
||
placement="bottom"
|
||
:width="80"
|
||
trigger="click"
|
||
v-if="item.switchType === 'move' || item.switchType === 'revolve'"
|
||
:disabled="currentItemIndex === -1"
|
||
>
|
||
<template #reference>
|
||
<div
|
||
class="tool-item"
|
||
:class="
|
||
toolbarSwitchType === item.switchType
|
||
? 'tool-active'
|
||
: item.isActive
|
||
? 'right-tool-active'
|
||
: ''
|
||
"
|
||
@click="toolbarClick(item)"
|
||
>
|
||
<Icon :icon="item.icon" :size="24" />
|
||
<div class="name"> {{ item.name }} </div>
|
||
</div>
|
||
</template>
|
||
<!-- 位置 -->
|
||
<el-form :model="state.moveForm" v-if="item.switchType === 'move'">
|
||
<el-form-item label="X">
|
||
<el-input v-model="state.moveForm.locationX" placeholder="请输入" />
|
||
</el-form-item>
|
||
<el-form-item label="Y">
|
||
<el-input v-model="state.moveForm.y" placeholder="请输入" />
|
||
</el-form-item>
|
||
<div style="text-align: right">
|
||
<el-button size="small" color="#00329F" @click="moveFormSubmit">确认</el-button>
|
||
</div>
|
||
</el-form>
|
||
<!-- 旋转 -->
|
||
<el-form :model="state.rotationForm" v-if="item.switchType === 'revolve'">
|
||
<el-form-item label="角度">
|
||
<el-input v-model="state.rotationForm.angle" placeholder="请输入" />
|
||
</el-form-item>
|
||
<div style="text-align: right">
|
||
<el-button size="small" color="#00329F" @click="rotationFormSubmit">确认</el-button>
|
||
</div>
|
||
</el-form>
|
||
<!-- 字体 -->
|
||
<el-form :model="state.rotationForm" v-if="item.switchType === 'text'">
|
||
<el-form-item label="角度">
|
||
<el-input v-model="state.rotationForm.angle" placeholder="请输入" />
|
||
</el-form-item>
|
||
<div style="text-align: right">
|
||
<el-button size="small" color="#00329F" @click="rotationFormSubmit">确认</el-button>
|
||
</div>
|
||
</el-form>
|
||
</el-popover>
|
||
|
||
<div
|
||
v-else
|
||
class="tool-item"
|
||
:class="
|
||
toolbarSwitchType === item.switchType
|
||
? 'tool-active'
|
||
: item.isActive
|
||
? 'right-tool-active'
|
||
: ''
|
||
"
|
||
@click="toolbarClick(item)"
|
||
>
|
||
<Icon :icon="item.icon" :size="24" />
|
||
<div class="name"> {{ item.name }} </div>
|
||
</div>
|
||
<div
|
||
class="line"
|
||
v-if="
|
||
item.switchType === 'saveAs' ||
|
||
item.switchType === 'delete' ||
|
||
item.switchType === 'grid'
|
||
"
|
||
></div>
|
||
</div>
|
||
</div>
|
||
<div class="right-tool-list" v-if="state.isShowToolbar">
|
||
<div
|
||
v-for="item in state.rightToolList"
|
||
:key="item.switchType"
|
||
class="tool-item"
|
||
:class="
|
||
toolbarSwitchType === item.switchType
|
||
? 'tool-active'
|
||
: item.isActive
|
||
? 'right-tool-active'
|
||
: ''
|
||
"
|
||
@click="toolbarClick(item)"
|
||
>
|
||
<Icon :icon="item.icon" :size="24" />
|
||
<div class="name"> {{ item.name }} </div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- @mousewheel.prevent="rollImg" -->
|
||
<div
|
||
class="map-box"
|
||
ref="imgWrap"
|
||
style="overflow: hidden"
|
||
:style="{ cursor: state.cursorStyle }"
|
||
>
|
||
<div
|
||
class="map-box-inner"
|
||
ref="image"
|
||
@mousedown.stop="startDrawSelection"
|
||
@mousemove.stop="updateDrawSelection"
|
||
@mouseup.stop="endDrawSelection"
|
||
>
|
||
<img :src="imgBgObj.imgUrl" class="map-box-img" id="mapBg" />
|
||
<div
|
||
class="map-box-inner-dot"
|
||
@click="mapClick"
|
||
:class="state.isShowGrid ? 'grid-show' : ''"
|
||
v-if="interfaceRefreshed"
|
||
>
|
||
<VueDragResizeRotate
|
||
v-for="(item, index) in allHistoryList[currentIndex]"
|
||
:key="index"
|
||
:parent="true"
|
||
:x="item.locationX"
|
||
:y="item.locationY"
|
||
:w="item.locationWide"
|
||
:h="item.locationDeep"
|
||
:r="item.angle"
|
||
@rotatestop="(degree) => rotateEnd(degree, item, index)"
|
||
@dragstop="(x, y) => dragEnd(x, y, item, index)"
|
||
@resizestop="(x, y, width, height) => resizeEnd(x, y, width, height, item, index)"
|
||
@activated="() => activatedHandle(item, index)"
|
||
@deactivated="deactivatedHandle"
|
||
:draggable="item.draggable"
|
||
:resizable="item.resizable"
|
||
:rotatable="item.rotatable"
|
||
:lock-aspect-ratio="item.lockAspectRatio"
|
||
style="border: none"
|
||
>
|
||
<div
|
||
class="sdiv"
|
||
:style="
|
||
currentItemIndex === index ? 'border: 1px dashed #000;box-sizing: border-box;' : ''
|
||
"
|
||
>
|
||
<!-- <img
|
||
:src="item.img"
|
||
alt=""
|
||
style="width: 100%; height: 100%"
|
||
/> -->
|
||
<div
|
||
v-if="item.type !== 7"
|
||
style="width: 100%; height: 100%; background-color: #000; border-radius: 50%"
|
||
></div>
|
||
<div
|
||
v-if="item.type === 7"
|
||
:style="{
|
||
fontSize: item.fontSize + 'px',
|
||
fontFamily: item.fontFamily,
|
||
color: item.fontColor
|
||
}"
|
||
>
|
||
{{ item.text }}
|
||
</div>
|
||
</div>
|
||
</VueDragResizeRotate>
|
||
<!-- 文档 https://github.com/a7650/vue3-draggable-resizable/blob/main/docs/document_zh.md#resizable -->
|
||
</div>
|
||
|
||
<!-- 绘制框选区域 -->
|
||
<div
|
||
v-if="state.drawSelectionArea"
|
||
:style="{
|
||
position: 'absolute',
|
||
left: `${state.drawSelectionAreaBox.x}px`,
|
||
top: `${state.drawSelectionAreaBox.y}px`,
|
||
width: `${state.drawSelectionAreaBox.width}px`,
|
||
height: `${state.drawSelectionAreaBox.height}px`,
|
||
border: '1px solid blue',
|
||
backgroundColor: 'rgba(0, 0, 255, 0.1)',
|
||
zIndex: 99999
|
||
}"
|
||
></div>
|
||
<!-- 文字输入区域 -->
|
||
<input
|
||
v-if="state.showInputBox"
|
||
ref="inputBoxRef"
|
||
v-model="state.inputBoxValue"
|
||
@keyup.enter="handleInputEnd"
|
||
@blur="handleInputEnd"
|
||
:style="{
|
||
fontSize: state.inputBoxStyle.fontSize + 'px',
|
||
fontFamily: state.inputBoxStyle.fontFamily,
|
||
color: state.inputBoxStyle.fontColor,
|
||
left: state.inputBoxStyle.locationX + 'px',
|
||
top: state.inputBoxStyle.locationY + 'px'
|
||
}"
|
||
class="input-box-class"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<!-- 节点编辑 -->
|
||
<editNodeProperties
|
||
ref="editNodePropertiesRef"
|
||
:positionMapId="imgBgObj.positionMapId"
|
||
@submitNodeSuccess="submitNodeSuccess"
|
||
/>
|
||
<!-- 文字输入弹窗 -->
|
||
<textFormToolDialog
|
||
ref="textFormToolDialogRef"
|
||
v-if="state.textFormToolShow"
|
||
@textFormSuccess="textFormSuccess"
|
||
/>
|
||
<!-- 图层选择 -->
|
||
<layerSelectionToolDialog v-if="state.isShowLayer" ref="layerSelectionToolDialogRef" />
|
||
<!-- 设备弹窗选择 -->
|
||
<equipmentToolDialog ref="equipmentToolDialogRef" :positionMapId="imgBgObj.positionMapId" />
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, defineComponent, reactive, nextTick, onMounted } from 'vue'
|
||
import editNodeProperties from './components-tool/editNodeProperties.vue'
|
||
import textFormToolDialog from './components-tool/textFormToolDialog.vue'
|
||
import equipmentToolDialog from './components-tool/equipmentToolDialog.vue'
|
||
import layerSelectionToolDialog from './components-tool/layerSelectionToolDialog.vue'
|
||
|
||
import * as MapApi from '@/api/map/map'
|
||
import cursorCollection from './cursorCollection'
|
||
|
||
defineOptions({ name: 'editMapPageRealTimeMap' })
|
||
|
||
const equipmentToolDialogRef = ref() //设备弹窗
|
||
const textFormToolDialogRef = ref() //文字输入弹窗
|
||
const inputBoxRef = ref() //文字输入框
|
||
|
||
const message = useMessage() // 消息弹窗
|
||
const formLoading = ref(false)
|
||
|
||
const allHistoryList = ref([]) //全部的历史记录
|
||
const currentIndex = ref(0) //用于记录是哪条历史记录的
|
||
const currentItemIndex = ref(-1) //用于记录是在编辑那个具体的节点、图标等
|
||
const allMapPointInfo = ref([]) //所有的图标的列表
|
||
|
||
// 缩放停止
|
||
const interfaceRefreshed = ref(true)
|
||
const resizeEnd = (x, y, w, h, item, index) => {
|
||
interfaceRefreshed.value = false
|
||
console.log('缩放', w, h)
|
||
nextTick(() => {
|
||
allMapPointInfo.value[index].locationX = x
|
||
allMapPointInfo.value[index].locationY = y
|
||
allMapPointInfo.value[index].locationWide = w
|
||
allMapPointInfo.value[index].locationDeep = h
|
||
addEditHistory()
|
||
})
|
||
}
|
||
// 拖拽停止
|
||
const dragEnd = (x, y, item, index) => {
|
||
console.log('拖拽')
|
||
if (x === item.locationX && y === item.locationY) return
|
||
allMapPointInfo.value[index].locationX = x
|
||
allMapPointInfo.value[index].locationY = y
|
||
addEditHistory()
|
||
}
|
||
// 旋转
|
||
const rotateEnd = (angle, item, index) => {
|
||
console.log('旋转')
|
||
allMapPointInfo.value[index].angle = angle
|
||
addEditHistory()
|
||
}
|
||
|
||
//选中
|
||
const editNodePropertiesRef = ref()
|
||
const activatedHandle = (item, index) => {
|
||
// console.log('选中', item, index)
|
||
currentItemIndex.value = index
|
||
|
||
//节点编辑
|
||
if (toolbarSwitchType.value === 'editNode' && item.type !== 7) {
|
||
editNodePropertiesRef.value.open(item)
|
||
}
|
||
}
|
||
//非选中
|
||
const deactivatedHandle = () => {
|
||
console.log('取消选中')
|
||
}
|
||
|
||
//添加历史记录
|
||
const addEditHistory = () => {
|
||
//要判断是不是在最新的记录上修改 如果不是 要把currentIndex之后的记录都删掉 保持当前修改是最新的
|
||
if (currentIndex.value !== allHistoryList.value.length - 1) {
|
||
allHistoryList.value = allHistoryList.value.splice(0, currentIndex.value)
|
||
currentIndex.value = allHistoryList.value.length
|
||
allHistoryList.value.push(JSON.parse(JSON.stringify(allMapPointInfo.value)))
|
||
} else {
|
||
allHistoryList.value.push(JSON.parse(JSON.stringify(allMapPointInfo.value)))
|
||
currentIndex.value++
|
||
}
|
||
interfaceRefreshed.value = true
|
||
console.log(allHistoryList.value, 'allHistoryList')
|
||
}
|
||
|
||
//上一步
|
||
const backPreviousStep = () => {
|
||
if (currentIndex.value > 0) {
|
||
currentIndex.value--
|
||
allMapPointInfo.value = allHistoryList.value[currentIndex.value]
|
||
console.log('撤销', allHistoryList.value[currentIndex.value])
|
||
} else {
|
||
message.warning('没了老铁')
|
||
}
|
||
}
|
||
//下一步
|
||
const backNextStep = () => {
|
||
if (currentIndex.value < allHistoryList.value.length - 1) {
|
||
currentIndex.value++
|
||
allMapPointInfo.value = allHistoryList.value[currentIndex.value]
|
||
console.log('重做', allHistoryList.value[currentIndex.value])
|
||
} else {
|
||
message.warning('没了老铁')
|
||
}
|
||
}
|
||
|
||
//地图点击
|
||
const mapClick = (e) => {
|
||
if (toolbarSwitchType.value === 'drawNodes') {
|
||
//绘制节点
|
||
allMapPointInfo.value.push({
|
||
locationX: e.offsetX,
|
||
locationY: e.offsetY,
|
||
locationDeep: 16,
|
||
locationWide: 16,
|
||
angle: 0,
|
||
draggable: false,
|
||
resizable: false,
|
||
rotatable: false,
|
||
lockAspectRatio: false, //横纵比
|
||
img: '',
|
||
type: 1 //默认类型1 路径节点
|
||
})
|
||
currentIndex.value++
|
||
allHistoryList.value.push(JSON.parse(JSON.stringify(allMapPointInfo.value)))
|
||
}
|
||
//文字输入
|
||
if (toolbarSwitchType.value === 'text') {
|
||
state.showInputBox = true
|
||
state.inputBoxStyle = {
|
||
fontSize: state.textForm.fontSize,
|
||
fontFamily: state.textForm.fontFamily,
|
||
fontColor: state.textForm.fontColor,
|
||
locationX: e.offsetX,
|
||
locationY: e.offsetY
|
||
}
|
||
|
||
// 聚焦输入框
|
||
setTimeout(() => {
|
||
inputBoxRef.value.focus()
|
||
}, 0)
|
||
}
|
||
}
|
||
//输入文字样式改变
|
||
const textFormSuccess = (form) => {
|
||
state.textForm = JSON.parse(JSON.stringify(form))
|
||
state.inputBoxStyle = {
|
||
fontSize: `${form.fontSize}`,
|
||
fontFamily: `${form.fontFamily}`,
|
||
fontColor: `${form.fontColor}`
|
||
}
|
||
}
|
||
//输入结束
|
||
const handleInputEnd = () => {
|
||
if (state.inputBoxValue) {
|
||
state.showInputBox = false
|
||
allMapPointInfo.value.push({
|
||
type: 7, //类型 7文字
|
||
mapId: '', //地图的id
|
||
locationX: state.inputBoxStyle.locationX, //x
|
||
locationY: state.inputBoxStyle.locationY, //y
|
||
locationDeep: '', //h
|
||
locationWide: '', //w
|
||
angle: 0, //旋转角度
|
||
draggable: true, //是否可以拖动
|
||
resizable: false, //是否可以调整大小
|
||
rotatable: false, //是否可以旋转
|
||
lockAspectRatio: true, //是否锁定比例
|
||
img: '', //图片
|
||
text: state.inputBoxValue, //文字内容
|
||
fontColor: state.inputBoxStyle.fontColor, //文字颜色
|
||
fontFamily: state.inputBoxStyle.fontFamily, //字体类型
|
||
fontSize: state.inputBoxStyle.fontSize
|
||
})
|
||
addEditHistory()
|
||
state.inputBoxValue = ''
|
||
}
|
||
}
|
||
|
||
//保存地图
|
||
const saveMap = async () => {
|
||
//节点的保存
|
||
await saveNodeList()
|
||
}
|
||
//节点的保存
|
||
const saveNodeList = async () => {
|
||
formLoading.value = true
|
||
|
||
let list = allHistoryList.value[currentIndex.value]
|
||
|
||
list.forEach((item, index) => {
|
||
item.locationX = item.locationX
|
||
item.locationY = item.locationY
|
||
item.type = item.type || 1
|
||
if (item.type === 1) {
|
||
item.dataJson = ''
|
||
} else {
|
||
item.dataJson = item.dataJson
|
||
}
|
||
})
|
||
|
||
try {
|
||
await MapApi.batchSaveOrEditOrDelMapItem(imgBgObj.positionMapId, list)
|
||
message.success('创建成功')
|
||
} finally {
|
||
formLoading.value = false
|
||
}
|
||
}
|
||
//编辑节点成功
|
||
const submitNodeSuccess = (item) => {
|
||
allHistoryList.value[currentIndex.value][currentItemIndex.value] = item
|
||
}
|
||
|
||
//工具栏点击
|
||
const toolbarSwitchType = ref('')
|
||
const state = reactive({
|
||
topToolList: [
|
||
{
|
||
switchType: 'open',
|
||
name: '打开',
|
||
icon: 'ep:folder-add',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'save',
|
||
name: '保存',
|
||
icon: 'ep:folder-checked',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'saveAs',
|
||
name: '另存为',
|
||
icon: 'ep:folder-opened',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'choose',
|
||
name: '选择',
|
||
icon: 'ep:position',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'move',
|
||
name: '移动',
|
||
icon: 'ep:rank',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'revolve',
|
||
name: '旋转',
|
||
icon: 'ep:refresh-right',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'copy',
|
||
name: '复制',
|
||
icon: 'ep:document',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'paste',
|
||
name: '粘贴',
|
||
icon: 'ep:copy-document',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'delete',
|
||
name: '删除',
|
||
icon: 'ep:delete',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'tools',
|
||
name: '工具',
|
||
icon: 'ep:briefcase',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'lineLibrary',
|
||
name: '线库',
|
||
icon: 'ep:message-box',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'region',
|
||
name: '区域',
|
||
icon: 'ep:full-screen',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'text',
|
||
name: '文字',
|
||
icon: 'ep:edit-pen',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'equipment',
|
||
name: '设备',
|
||
icon: 'ep:video-camera-filled',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'ranging',
|
||
name: '测距',
|
||
icon: 'ep:folder-add',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'layer',
|
||
name: '图层',
|
||
icon: 'ep:copy-document',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'marker',
|
||
name: '标记',
|
||
icon: 'ep:map-location',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'grid',
|
||
name: '网格',
|
||
icon: 'ep:grid',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'larger',
|
||
name: '放大',
|
||
icon: 'ep:zoom-in',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'smaller',
|
||
name: '缩小',
|
||
icon: 'ep:zoom-out',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'withdraw',
|
||
name: '撤回',
|
||
icon: 'ep:top-left',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'next',
|
||
name: '重做',
|
||
icon: 'ep:top-right',
|
||
isActive: false
|
||
}
|
||
],
|
||
rightToolList: [
|
||
{
|
||
switchType: 'drawNodes',
|
||
name: '绘制节点',
|
||
icon: 'ep:circle-plus-filled',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'editNode',
|
||
name: '编辑节点',
|
||
icon: 'ep:circle-plus-filled',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'drawRoute',
|
||
name: '绘制路线',
|
||
icon: 'ep:semi-select',
|
||
isActive: false
|
||
},
|
||
{
|
||
switchType: 'editRoute',
|
||
name: '编辑路线',
|
||
icon: 'ep:semi-select',
|
||
isActive: false
|
||
}
|
||
],
|
||
isShowToolbar: false, //工具栏展示隐藏
|
||
isShowGrid: false, //网格展示隐藏
|
||
moveForm: {
|
||
locationX: '',
|
||
locationY: ''
|
||
}, //移动的表单
|
||
rotationForm: {
|
||
angle: ''
|
||
}, //旋转的表单
|
||
copyMapItem: '', //复制的值
|
||
cursorStyle: 'auto',
|
||
drawSelectionArea: false, //绘制框选区域
|
||
drawSelectionAreaBox: { x: 0, y: 0, width: 0, height: 0 }, //绘制区域的位置,长宽
|
||
drawSelectionAreaStartPos: { x: 0, y: 0 }, //开始绘制的点位
|
||
drawSelectionAreaSelectedPoints: [], //绘制选中的list
|
||
textForm: {
|
||
fontFamily: 'SimSun',
|
||
fontSize: '14',
|
||
fontColor: '#000000'
|
||
}, //默认宋体,14,#000000
|
||
textFormToolShow: false, //文字表单显示隐藏
|
||
showInputBox: false, //输入框显示隐藏
|
||
inputBoxStyle: {}, //输入框的样式
|
||
inputBoxValue: '', //输入的值
|
||
isShowLayer: false //图层显示
|
||
})
|
||
const toolbarClick = (item) => {
|
||
let type = item.switchType
|
||
if (
|
||
currentItemIndex.value &&
|
||
(type === 'move' || type === 'revolve' || type === 'copy' || type === 'delete')
|
||
) {
|
||
message.warning('请先选择要操作的对象')
|
||
return
|
||
}
|
||
//粘贴
|
||
if (type === 'paste' && !state.copyMapItem) {
|
||
message.warning('请先复制对象')
|
||
return
|
||
}
|
||
|
||
if (
|
||
(type === 'tools' || type === 'text' || type === 'layer' || type === 'grid') &&
|
||
toolbarSwitchType.value === type
|
||
) {
|
||
toolbarSwitchType.value = ''
|
||
} else {
|
||
toolbarSwitchType.value = type
|
||
}
|
||
|
||
if (toolbarSwitchType.value !== 'text') {
|
||
state.cursorStyle = `auto`
|
||
state.textFormToolShow = false
|
||
state.showInputBox = false
|
||
state.inputBoxValue = ''
|
||
}
|
||
|
||
switch (type) {
|
||
case 'open':
|
||
// 打开
|
||
break
|
||
case 'save':
|
||
//保存
|
||
saveMap()
|
||
break
|
||
case 'saveAs':
|
||
//另存为 存为json文件 无法直接访问用户的文件系统 不能选择存在那个文件夹里面
|
||
const jsonString = JSON.stringify(allHistoryList.value[currentIndex.value], null, 2)
|
||
const blob = new Blob([jsonString], { type: 'application/json' })
|
||
const url = URL.createObjectURL(blob)
|
||
|
||
const a = document.createElement('a')
|
||
a.href = url
|
||
a.download = 'mapJson.json'
|
||
document.body.appendChild(a)
|
||
a.click()
|
||
document.body.removeChild(a)
|
||
URL.revokeObjectURL(url)
|
||
|
||
message.success('下载成功')
|
||
break
|
||
case 'choose':
|
||
//选择
|
||
break
|
||
case 'move':
|
||
//移动
|
||
break
|
||
case 'revolve':
|
||
break
|
||
case 'copy':
|
||
//复制
|
||
state.copyMapItem = allHistoryList.value[currentIndex.value][currentItemIndex.value]
|
||
break
|
||
case 'paste':
|
||
//粘贴
|
||
let copyObj = JSON.parse(JSON.stringify(state.copyMapItem))
|
||
copyObj.locationX = copyObj.locationX + 50
|
||
copyObj.locationY = copyObj.locationY + 50
|
||
allMapPointInfo.value.push(copyObj)
|
||
addEditHistory()
|
||
break
|
||
case 'delete':
|
||
//删除
|
||
allMapPointInfo.value.splice(currentItemIndex.value, 1)
|
||
addEditHistory()
|
||
break
|
||
case 'tools':
|
||
//工具
|
||
if (toolbarSwitchType.value === 'tools') {
|
||
state.isShowToolbar = true
|
||
item.isActive = true
|
||
} else {
|
||
state.isShowToolbar = false
|
||
item.isActive = false
|
||
}
|
||
break
|
||
case 'lineLibrary':
|
||
// 线库
|
||
break
|
||
case 'region':
|
||
// 区域
|
||
break
|
||
case 'text':
|
||
//文字
|
||
if (toolbarSwitchType.value === 'text') {
|
||
state.textFormToolShow = true
|
||
state.cursorStyle = `url('${cursorCollection.input}'),auto`
|
||
} else {
|
||
state.cursorStyle = `auto`
|
||
state.textFormToolShow = false
|
||
state.showInputBox = false
|
||
state.inputBoxValue = ''
|
||
}
|
||
break
|
||
case 'ranging':
|
||
// 测距
|
||
break
|
||
case 'layer':
|
||
//图层
|
||
if (toolbarSwitchType.value === 'layer') {
|
||
state.isShowLayer = true
|
||
item.isActive = true
|
||
} else {
|
||
state.isShowLayer = false
|
||
item.isActive = false
|
||
}
|
||
break
|
||
case 'marker':
|
||
// 标记
|
||
break
|
||
case 'grid':
|
||
//网格
|
||
if (toolbarSwitchType.value === 'grid') {
|
||
state.isShowGrid = true
|
||
item.isActive = true
|
||
} else {
|
||
state.isShowGrid = false
|
||
item.isActive = false
|
||
}
|
||
break
|
||
case 'larger':
|
||
//放大
|
||
break
|
||
case 'smaller':
|
||
//缩小
|
||
break
|
||
case 'withdraw':
|
||
//上一步
|
||
backPreviousStep()
|
||
break
|
||
case 'next':
|
||
//下一步
|
||
backNextStep()
|
||
break
|
||
case 'drawNodes':
|
||
//绘制节点
|
||
break
|
||
case 'editNode':
|
||
// 编辑节点
|
||
break
|
||
case 'drawRoute':
|
||
//绘制路线
|
||
break
|
||
case 'editRoute':
|
||
// 编辑路线
|
||
break
|
||
case 'equipment':
|
||
// 设备
|
||
equipmentToolDialogRef.value.open()
|
||
break
|
||
}
|
||
}
|
||
|
||
//移动工具表单提交
|
||
const moveFormSubmit = () => {
|
||
allHistoryList.value[currentIndex.value][currentItemIndex.value].locationX =
|
||
state.moveForm.locationX
|
||
allHistoryList.value[currentIndex.value][currentItemIndex.value].locationY =
|
||
state.moveForm.locationY
|
||
}
|
||
//旋转工具表单提交
|
||
const rotationFormSubmit = () => {
|
||
allHistoryList.value[currentIndex.value][currentItemIndex.value].angle = state.rotationForm.angle
|
||
}
|
||
|
||
//开始框选绘制
|
||
const startDrawSelection = (event) => {
|
||
if (toolbarSwitchType.value !== 'lineLibrary' && toolbarSwitchType.value !== 'region') return
|
||
state.drawSelectionArea = true
|
||
state.drawSelectionAreaStartPos = { x: event.offsetX, y: event.offsetY }
|
||
state.drawSelectionAreaBox = { x: event.offsetX, y: event.offsetY, width: 0, height: 0 }
|
||
}
|
||
|
||
const updateDrawSelection = (event) => {
|
||
if (toolbarSwitchType.value !== 'lineLibrary' && toolbarSwitchType.value !== 'region') return
|
||
if (state.drawSelectionArea) {
|
||
state.drawSelectionAreaBox.width = event.offsetX - state.drawSelectionAreaStartPos.x
|
||
state.drawSelectionAreaBox.height = event.offsetY - state.drawSelectionAreaStartPos.y
|
||
}
|
||
}
|
||
//结束框选绘制
|
||
const endDrawSelection = () => {
|
||
if (toolbarSwitchType.value !== 'lineLibrary' && toolbarSwitchType.value !== 'region') return
|
||
let points = allHistoryList.value[currentIndex.value]
|
||
state.drawSelectionArea = false
|
||
state.drawSelectionAreaSelectedPoints = points.filter((point) => {
|
||
return (
|
||
point.x >=
|
||
Math.min(
|
||
state.drawSelectionAreaStartPos.x,
|
||
state.drawSelectionAreaStartPos.x + state.drawSelectionAreaBox.width
|
||
) &&
|
||
point.x <=
|
||
Math.max(
|
||
state.drawSelectionAreaStartPos.x,
|
||
state.drawSelectionAreaStartPos.x + state.drawSelectionAreaBox.width
|
||
) &&
|
||
point.y >=
|
||
Math.min(
|
||
state.drawSelectionAreaStartPos.y,
|
||
state.drawSelectionAreaStartPos.y + state.drawSelectionAreaBox.height
|
||
) &&
|
||
point.y <=
|
||
Math.max(
|
||
state.drawSelectionAreaStartPos.y,
|
||
state.drawSelectionAreaStartPos.y + state.drawSelectionAreaBox.height
|
||
)
|
||
)
|
||
})
|
||
console.log(state.drawSelectionAreaSelectedPoints, '选中的')
|
||
}
|
||
|
||
//获取地图点位
|
||
const list = ref([])
|
||
const getMapList = async () => {
|
||
let data = await MapApi.getPositionMapGetMap()
|
||
let mapList = []
|
||
for (let key in data) {
|
||
mapList.push({
|
||
floor: key,
|
||
children: data[key]
|
||
})
|
||
}
|
||
list.value = mapList
|
||
|
||
//默认取第一个
|
||
if (data[1][0]) {
|
||
getMapData(data[1][0])
|
||
}
|
||
}
|
||
|
||
//获取扫描图
|
||
//地图背景
|
||
const imgBgObj = reactive({
|
||
imgUrl: '',
|
||
positionMapId: '',
|
||
width: '',
|
||
height: ''
|
||
})
|
||
const getMapData = async (item) => {
|
||
let data = await MapApi.getPositionMapdDwnloadPngBase64({
|
||
floor: item.floor,
|
||
area: item.area
|
||
})
|
||
|
||
imgBgObj.imgUrl = data
|
||
imgBgObj.positionMapId = item.id
|
||
|
||
const img = new Image()
|
||
img.src = imgBgObj.imgUrl
|
||
imgBgObj.width = img.naturalWidth
|
||
imgBgObj.height = img.naturalHeight
|
||
|
||
console.log(imgBgObj)
|
||
|
||
getAllNodeList()
|
||
}
|
||
|
||
//获取所有的点位
|
||
const getAllNodeList = async () => {
|
||
let list = await MapApi.getPositionMapItemList({
|
||
positionMapId: imgBgObj.positionMapId
|
||
})
|
||
list.forEach((item) => {
|
||
if (item.type === 2) {
|
||
//库位点
|
||
let obj = JSON.parse(item.dataJson)[0]
|
||
|
||
// allMapPointInfo.value.push()
|
||
}
|
||
})
|
||
|
||
// allMapPointInfo.value = list.map((item) => {
|
||
// return {
|
||
// ...JSON.parse(item.dataJson)
|
||
// }
|
||
// })
|
||
// allMapPointInfo.value = allMapPointInfo.value
|
||
// console.log(allMapPointInfo.value)
|
||
allHistoryList.value[0] = JSON.parse(JSON.stringify(allMapPointInfo.value))
|
||
console.log(allHistoryList.value[0])
|
||
}
|
||
|
||
onMounted(() => {
|
||
getMapList()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.map-box {
|
||
width: 100%;
|
||
position: relative;
|
||
.map-box-inner {
|
||
position: relative;
|
||
width: 100%;
|
||
|
||
.map-box-img {
|
||
width: 100%;
|
||
height: auto;
|
||
}
|
||
.map-box-inner-dot {
|
||
width: 100%;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
}
|
||
|
||
.grid-show {
|
||
background: linear-gradient(-90deg, rgba(0, 0, 0, 0.1) 1px, transparent 1px),
|
||
linear-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1px);
|
||
background-size:
|
||
10px 10px,
|
||
10px 10px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.sdiv {
|
||
width: 100%;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.top-tool {
|
||
.top-tool-list {
|
||
display: flex;
|
||
align-items: center;
|
||
text-align: center;
|
||
background-color: #fff;
|
||
margin-top: -15px;
|
||
margin-left: -20px;
|
||
margin-right: -20px;
|
||
padding: 0 14px;
|
||
margin-bottom: 20px;
|
||
box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 0px 1px;
|
||
height: 70px;
|
||
|
||
.top-tool-item {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.tool-item {
|
||
cursor: pointer;
|
||
width: 52px;
|
||
height: 70px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.name {
|
||
font-family:
|
||
PingFangSC,
|
||
PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
color: #0d162a;
|
||
line-height: 20px;
|
||
text-align: center;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
.line {
|
||
margin: 0 14px;
|
||
width: 1px;
|
||
height: 47px;
|
||
border: 1px solid #cccccc;
|
||
}
|
||
}
|
||
}
|
||
|
||
.right-tool-list {
|
||
position: absolute;
|
||
right: 0;
|
||
top: 94px;
|
||
background-color: #fff;
|
||
z-index: 999;
|
||
text-align: center;
|
||
box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 0px 1px;
|
||
|
||
.tool-item {
|
||
cursor: pointer;
|
||
padding: 10px;
|
||
.name {
|
||
font-family:
|
||
PingFangSC,
|
||
PingFang SC;
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
color: #0d162a;
|
||
line-height: 20px;
|
||
text-align: center;
|
||
font-style: normal;
|
||
}
|
||
}
|
||
}
|
||
|
||
.tool-active {
|
||
background: #ebf1ff;
|
||
border-bottom: 2px solid #1677ff;
|
||
}
|
||
|
||
.right-tool-active {
|
||
background: #ebf1ff;
|
||
}
|
||
}
|
||
|
||
.input-box-class {
|
||
position: absolute;
|
||
border: 1px solid #00329f;
|
||
padding: 4px;
|
||
outline: none;
|
||
}
|
||
</style>
|