地图编辑
This commit is contained in:
parent
ce81a142a7
commit
2f8d31b63c
@ -18,7 +18,7 @@
|
||||
</el-select>
|
||||
</ElDialog>
|
||||
<div v-else class="custom-hover" @click.stop="showTopSearch = !showTopSearch">
|
||||
<Icon icon="ep:search" />
|
||||
<Icon icon="ep:search" color="var(--top-header-text-color)" />
|
||||
<el-select
|
||||
@click.stop
|
||||
filterable
|
||||
|
@ -59,7 +59,7 @@ export default defineComponent({
|
||||
|
||||
<Backtop></Backtop>
|
||||
|
||||
{<Setting></Setting>}
|
||||
{/* <Setting></Setting> */}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
@ -54,7 +54,13 @@ onMounted(() => {
|
||||
<ElPopover :width="400" placement="bottom" trigger="click">
|
||||
<template #reference>
|
||||
<ElBadge :is-dot="unreadCount > 0" class="item">
|
||||
<Icon :size="18" class="cursor-pointer" icon="ep:bell" @click="getList" />
|
||||
<Icon
|
||||
:size="18"
|
||||
class="cursor-pointer"
|
||||
icon="ep:bell"
|
||||
@click="getList"
|
||||
color="var(--top-header-text-color)"
|
||||
/>
|
||||
</ElBadge>
|
||||
</template>
|
||||
<ElTabs v-model="activeName">
|
||||
|
@ -297,6 +297,6 @@ $prefix-cls: #{$namespace}-setting;
|
||||
|
||||
.#{$prefix-cls} {
|
||||
border-radius: 6px 0 0 6px;
|
||||
z-index: 1200;/*修正没有z-index会被表格层覆盖,值不要超过4000*/
|
||||
z-index: 1200; /*修正没有z-index会被表格层覆盖,值不要超过4000*/
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="tsx">
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { Message } from '@/layout/components//Message'
|
||||
import { Message } from '@/layout/components/Message'
|
||||
import { Collapse } from '@/layout/components/Collapse'
|
||||
import { UserInfo } from '@/layout/components/UserInfo'
|
||||
import { Screenfull } from '@/layout/components/Screenfull'
|
||||
@ -52,7 +52,7 @@ export default defineComponent({
|
||||
'h-[var(--top-tool-height)] relative px-[var(--top-tool-p-x)] flex items-center justify-between',
|
||||
'dark:bg-[var(--el-bg-color)]'
|
||||
]}
|
||||
style="height:60px"
|
||||
style="height:61px"
|
||||
>
|
||||
{layout.value !== 'top' ? (
|
||||
<div class="h-full flex items-center">
|
||||
|
@ -55,7 +55,7 @@ export const useRenderLayout = () => {
|
||||
'w-[var(--left-menu-max-width)]': !appStore.getCollapse
|
||||
}
|
||||
]}
|
||||
style="transition: all var(--transition-time-02);height:59px;display: flex;
|
||||
style="transition: all var(--transition-time-02);height:60px;display: flex;
|
||||
align-items: center;"
|
||||
></Logo>
|
||||
) : undefined}
|
||||
|
@ -72,7 +72,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
},
|
||||
//地图
|
||||
{
|
||||
path: '/warehouse/map', // 商品中心
|
||||
path: '/warehouse/map',
|
||||
component: Layout,
|
||||
name: 'warehouseMap',
|
||||
meta: {
|
||||
|
@ -94,7 +94,7 @@ export const useAppStore = defineStore('app', {
|
||||
// 头部字体颜色
|
||||
topHeaderTextColor: '#ffffff',
|
||||
// 头部悬停颜色
|
||||
topHeaderHoverColor: '#f6f6f6',
|
||||
topHeaderHoverColor: '#215bd8',
|
||||
// 头部边框颜色
|
||||
topToolBorderColor: '#E2E7F5'
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
/* left menu end */
|
||||
|
||||
/* logo start */
|
||||
--logo-height: 50px;
|
||||
--logo-height: 40px;
|
||||
|
||||
--logo-title-text-color: #fff;
|
||||
/* logo end */
|
||||
@ -31,14 +31,14 @@
|
||||
|
||||
--top-header-text-color: 'inherit';
|
||||
|
||||
--top-header-hover-color: #f6f6f6;
|
||||
--top-header-hover-color: #215bd8;
|
||||
|
||||
--top-tool-height: var(--logo-height);
|
||||
|
||||
--top-tool-p-x: 0;
|
||||
|
||||
/* --tags-view-height: 35px; 开启面包屑时 */
|
||||
--tags-view-height: 8px;
|
||||
--tags-view-height: 16px;
|
||||
/* header start */
|
||||
|
||||
/* tab menu start */
|
||||
|
@ -21,7 +21,13 @@
|
||||
<el-form-item label="层数" prop="layersNumber" required v-if="form.type === 2">
|
||||
<el-input-number v-model="form.layersNumber" :min="1" :max="3" />
|
||||
</el-form-item>
|
||||
<el-form-item label="编号" prop="id" required v-if="form.type === 3">
|
||||
<el-form-item
|
||||
label="编号"
|
||||
prop="id"
|
||||
required
|
||||
v-if="form.type === 3"
|
||||
:rules="{ required: true, message: '请选择设备编号', trigger: 'change' }"
|
||||
>
|
||||
<div>
|
||||
<el-select
|
||||
v-model="deviceInfo.deviceType"
|
||||
@ -199,11 +205,12 @@ const directionChange = (e) => {
|
||||
|
||||
//获取设备信息
|
||||
const deviceInfo = ref({
|
||||
positionMapId: props.positionMapId,
|
||||
positionMapId: '',
|
||||
deviceType: ''
|
||||
})
|
||||
const deviceList = ref([])
|
||||
const getDeviceList = async () => {
|
||||
deviceInfo.value.positionMapId = props.positionMapId
|
||||
deviceList.value = await MapApi.getDeviceInformationList(deviceInfo.value)
|
||||
}
|
||||
const deviceTypeChange = () => {
|
||||
|
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogFormVisible" title="设备" width="600" class="text-form-dialog">
|
||||
<div> 11 </div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="formSubmit"> 确认 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const dialogFormVisible = ref(false)
|
||||
|
||||
const open = (item) => {
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
|
||||
const formSubmit = () => {}
|
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.text-form-dialog {
|
||||
.el-dialog__header {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
padding-bottom: 30px;
|
||||
border-top: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<div class="layer-select">
|
||||
<div class="top-list" v-if="isUnfold">
|
||||
<div class="item" v-for="(item, index) in list" :key="index" @click="changeSelectList(item)">
|
||||
<span class="name">{{ item.name }}</span>
|
||||
<el-icon v-if="item.isShow" color="#1677FF"><View /></el-icon>
|
||||
<el-icon v-else color="#444444"><Hide /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-button" @click="changeUnfold">
|
||||
<span class="title">图例</span>
|
||||
<el-icon v-if="isUnfold" color="#98A4BF"><CaretTop /></el-icon>
|
||||
<el-icon v-else color="#98A4BF"><CaretBottom /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const list = ref([
|
||||
{
|
||||
labelType: 'locationPoint',
|
||||
name: '库位点',
|
||||
isShow: true
|
||||
},
|
||||
{
|
||||
labelType: 'wayPoint',
|
||||
name: '路径点',
|
||||
isShow: true
|
||||
},
|
||||
{
|
||||
labelType: 'devicePoint',
|
||||
name: '设备点',
|
||||
isShow: true
|
||||
}
|
||||
])
|
||||
const isUnfold = ref(true)
|
||||
|
||||
const changeUnfold = () => {
|
||||
isUnfold.value = !isUnfold.value
|
||||
}
|
||||
const changeSelectList = (item) => {
|
||||
item.isShow = !item.isShow
|
||||
}
|
||||
|
||||
const open = (item) => {}
|
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.layer-select {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
width: 144px;
|
||||
cursor: pointer;
|
||||
|
||||
.top-list {
|
||||
.item {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 22px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.name {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 0;
|
||||
border: 1px solid #eeeeee;
|
||||
|
||||
.title {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
PingFang SC;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #98a4bf;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,8 +1,13 @@
|
||||
<template>
|
||||
<Dialog v-model="dialogFormVisible" title="文字设置" width="400" class="text-form-dialog">
|
||||
<el-form :model="form">
|
||||
<div class="text-form-dialog">
|
||||
<el-form :model="form" :inline="true">
|
||||
<el-form-item label="字体">
|
||||
<el-select v-model="form.fontType" placeholder="请选择">
|
||||
<el-select
|
||||
v-model="form.fontFamily"
|
||||
placeholder="请选择"
|
||||
class="!w-100px"
|
||||
@change="fontStyleChange()"
|
||||
>
|
||||
<el-option label="宋体" value="SimSun" />
|
||||
<el-option label="黑体" value="SimHei" />
|
||||
<el-option label="微软雅黑" value="Microsoft Yahei" />
|
||||
@ -11,8 +16,10 @@
|
||||
<el-option label="仿宋" value="FangSong" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="字号">
|
||||
<el-input-number
|
||||
@change="fontStyleChange()"
|
||||
v-model="form.fontSize"
|
||||
:step="1"
|
||||
:min="10"
|
||||
@ -21,45 +28,36 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="颜色">
|
||||
<el-color-picker v-model="form.fontColor" />
|
||||
<el-color-picker v-model="form.fontColor" @change="fontStyleChange()" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="dialogFormVisible = false"> 确认 </el-button>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const dialogFormVisible = ref(false)
|
||||
const formLabelWidth = '140px'
|
||||
|
||||
const form = reactive({
|
||||
fontType: 'SimSun',
|
||||
fontFamily: 'SimSun',
|
||||
fontSize: '14',
|
||||
fontColor: '#000000'
|
||||
})
|
||||
|
||||
const open = (item) => {
|
||||
dialogFormVisible.value = true
|
||||
const fontStyleChange = () => {
|
||||
emit('textFormSuccess', form)
|
||||
}
|
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
const emit = defineEmits(['textFormSuccess'])
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.text-form-dialog {
|
||||
.el-dialog__header {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
border-top: none !important;
|
||||
}
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
top: 76px;
|
||||
left: 30%;
|
||||
box-shadow: rgba(0, 0, 0, 0.05) 0px 0px 0px 1px;
|
||||
padding: 18px 20px 0 20px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="top-tool">
|
||||
<div class="top-tool-list">
|
||||
<div v-for="item in state.topToolList" :key="item.id" class="top-tool-item">
|
||||
<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.id === 5 || item.id === 6"
|
||||
:disabled="currentItemIndex === -1"
|
||||
v-if="item.switchType === 'move' || item.switchType === 'revolve'"
|
||||
:disabled="!currentItemIndex"
|
||||
>
|
||||
<template #reference>
|
||||
<div
|
||||
class="tool-item"
|
||||
:class="
|
||||
toolbarTypeIndex === item.id
|
||||
toolbarSwitchType === item.switchType
|
||||
? 'tool-active'
|
||||
: item.isActive
|
||||
? 'right-tool-active'
|
||||
@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<!-- 位置 -->
|
||||
<el-form :model="state.moveForm" v-if="item.id === 5">
|
||||
<el-form :model="state.moveForm" v-if="item.switchType === 'move'">
|
||||
<el-form-item label="X">
|
||||
<el-input v-model="state.moveForm.x" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
@ -38,7 +38,7 @@
|
||||
</div>
|
||||
</el-form>
|
||||
<!-- 旋转 -->
|
||||
<el-form :model="state.rotationForm" v-if="item.id === 6">
|
||||
<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>
|
||||
@ -47,7 +47,7 @@
|
||||
</div>
|
||||
</el-form>
|
||||
<!-- 字体 -->
|
||||
<el-form :model="state.rotationForm" v-if="item.id === 13">
|
||||
<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>
|
||||
@ -61,23 +61,38 @@
|
||||
v-else
|
||||
class="tool-item"
|
||||
:class="
|
||||
toolbarTypeIndex === item.id ? 'tool-active' : item.isActive ? 'right-tool-active' : ''
|
||||
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.id === 3 || item.id === 10 || item.id === 17"></div>
|
||||
<div
|
||||
class="line"
|
||||
v-if="
|
||||
item.switchType === 'saveAs' ||
|
||||
item.switchType === 'delete' ||
|
||||
item.switchType === 'ranging'
|
||||
"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-tool-list" v-if="state.isShowToolbar">
|
||||
<div
|
||||
v-for="item in state.rightToolList"
|
||||
:key="item.id"
|
||||
:key="item.switchType"
|
||||
class="tool-item"
|
||||
:class="
|
||||
toolbarTypeIndex === item.id ? 'tool-active' : item.isActive ? 'right-tool-active' : ''
|
||||
toolbarSwitchType === item.switchType
|
||||
? 'tool-active'
|
||||
: item.isActive
|
||||
? 'right-tool-active'
|
||||
: ''
|
||||
"
|
||||
@click="toolbarClick(item)"
|
||||
>
|
||||
@ -86,14 +101,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- @mousewheel.prevent="rollImg" -->
|
||||
<div
|
||||
class="map-box"
|
||||
ref="imgWrap"
|
||||
@mousewheel.prevent="rollImg"
|
||||
style="overflow: hidden"
|
||||
:style="{ cursor: state.cursorStyle }"
|
||||
>
|
||||
<div class="map-box-inner" ref="image" @mousedown.prevent="moveImg">
|
||||
<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"
|
||||
@ -119,7 +141,6 @@
|
||||
:resizable="item.resizable"
|
||||
:rotatable="item.rotatable"
|
||||
:lock-aspect-ratio="item.lockAspectRatio"
|
||||
:handles="['tl', 'tr', 'bl', 'br', 'rot']"
|
||||
style="border: none"
|
||||
>
|
||||
<div
|
||||
@ -138,10 +159,51 @@
|
||||
v-if="item.labelType === 'node'"
|
||||
style="width: 100%; height: 100%; background-color: #000; border-radius: 50%"
|
||||
></div>
|
||||
<div
|
||||
v-if="item.labelType === 'text'"
|
||||
: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.x + 'px',
|
||||
top: state.inputBoxStyle.y + 'px'
|
||||
}"
|
||||
class="input-box-class"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 节点编辑 -->
|
||||
@ -151,19 +213,32 @@
|
||||
@submitNodeSuccess="submitNodeSuccess"
|
||||
/>
|
||||
<!-- 文字输入弹窗 -->
|
||||
<textFormToolDialog ref="textFormToolDialogRef" />
|
||||
<textFormToolDialog
|
||||
ref="textFormToolDialogRef"
|
||||
v-if="state.textFormToolShow"
|
||||
@textFormSuccess="textFormSuccess"
|
||||
/>
|
||||
<!-- 图层选择 -->
|
||||
<layerSelectionToolDialog v-if="state.isShowLayer" ref="layerSelectionToolDialogRef" />
|
||||
<!-- 设备弹窗选择 -->
|
||||
<equipmentToolDialog ref="equipmentToolDialogRef" />
|
||||
</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)
|
||||
@ -241,10 +316,10 @@ const editNodePropertiesRef = ref()
|
||||
const activatedHandle = (item, index) => {
|
||||
// console.log('选中', item, index)
|
||||
currentItemIndex.value = index
|
||||
if (item.labelType === 'node') {
|
||||
if (toolbarTypeIndex.value === 23) {
|
||||
editNodePropertiesRef.value.open(item)
|
||||
}
|
||||
|
||||
//节点编辑
|
||||
if (toolbarSwitchType.value === 'editNode' && item.labelType === 'node') {
|
||||
editNodePropertiesRef.value.open(item)
|
||||
}
|
||||
}
|
||||
//非选中
|
||||
@ -290,7 +365,7 @@ const backNextStep = () => {
|
||||
|
||||
//地图点击
|
||||
const mapClick = (e) => {
|
||||
if (toolbarTypeIndex.value === 22) {
|
||||
if (toolbarSwitchType.value === 'drawNodes') {
|
||||
//绘制节点
|
||||
imgList.value.push({
|
||||
x: e.offsetX,
|
||||
@ -308,7 +383,59 @@ const mapClick = (e) => {
|
||||
currentIndex.value++
|
||||
allHistoryList.value.push(JSON.parse(JSON.stringify(imgList.value)))
|
||||
}
|
||||
//文字输入
|
||||
if (toolbarSwitchType.value === 'text') {
|
||||
state.showInputBox = true
|
||||
state.inputBoxStyle = {
|
||||
fontSize: state.textForm.fontSize,
|
||||
fontFamily: state.textForm.fontFamily,
|
||||
fontColor: state.textForm.fontColor,
|
||||
x: e.offsetX,
|
||||
y: 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
|
||||
imgList.value.push({
|
||||
labelType: 'text', //类型 节点
|
||||
mapId: '', //地图的id
|
||||
x: state.inputBoxStyle.x, //x
|
||||
y: state.inputBoxStyle.y, //y
|
||||
h: '', //h
|
||||
w: '', //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 () => {
|
||||
//节点的保存
|
||||
@ -346,131 +473,137 @@ const submitNodeSuccess = (item) => {
|
||||
}
|
||||
|
||||
//工具栏点击
|
||||
const toolbarTypeIndex = ref(0)
|
||||
const toolbarSwitchType = ref('')
|
||||
const state = reactive({
|
||||
topToolList: [
|
||||
{
|
||||
id: 1,
|
||||
switchType: 'open',
|
||||
name: '打开',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
switchType: 'save',
|
||||
name: '保存',
|
||||
icon: 'ep:folder-checked',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
switchType: 'saveAs',
|
||||
name: '另存为',
|
||||
icon: 'ep:folder-opened',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
switchType: 'choose',
|
||||
name: '选择',
|
||||
icon: 'ep:position',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
switchType: 'move',
|
||||
name: '移动',
|
||||
icon: 'ep:rank',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
switchType: 'revolve',
|
||||
name: '旋转',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
switchType: 'copy',
|
||||
name: '复制',
|
||||
icon: 'ep:document',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
switchType: 'paste',
|
||||
name: '粘贴',
|
||||
icon: 'ep:copy-document',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
switchType: 'delete',
|
||||
name: '删除',
|
||||
icon: 'ep:delete',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
switchType: 'tools',
|
||||
name: '工具',
|
||||
icon: 'ep:briefcase',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
switchType: 'lineLibrary',
|
||||
name: '线库',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
switchType: 'region',
|
||||
name: '区域',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
switchType: 'text',
|
||||
name: '文字',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
switchType: 'equipment',
|
||||
name: '设备',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
switchType: 'ranging',
|
||||
name: '测距',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
switchType: 'layer',
|
||||
name: '图层',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
switchType: 'marker',
|
||||
name: '标记',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
switchType: 'grid',
|
||||
name: '网格',
|
||||
icon: 'ep:folder-add',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
switchType: 'larger',
|
||||
name: '放大',
|
||||
icon: 'ep:zoom-in',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
switchType: 'smaller',
|
||||
name: '缩小',
|
||||
icon: 'ep:zoom-out',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
switchType: 'withdraw',
|
||||
name: '撤回',
|
||||
icon: 'ep:top-left',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
switchType: 'next',
|
||||
name: '重做',
|
||||
icon: 'ep:top-right',
|
||||
isActive: false
|
||||
@ -478,25 +611,25 @@ const state = reactive({
|
||||
],
|
||||
rightToolList: [
|
||||
{
|
||||
id: 22,
|
||||
switchType: 'drawNodes',
|
||||
name: '绘制节点',
|
||||
icon: 'ep:circle-plus-filled',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
switchType: 'editNode',
|
||||
name: '编辑节点',
|
||||
icon: 'ep:circle-plus-filled',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
switchType: 'drawRoute',
|
||||
name: '绘制路线',
|
||||
icon: 'ep:semi-select',
|
||||
isActive: false
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
switchType: 'editRoute',
|
||||
name: '编辑路线',
|
||||
icon: 'ep:semi-select',
|
||||
isActive: false
|
||||
@ -512,32 +645,59 @@ const state = reactive({
|
||||
angle: ''
|
||||
}, //旋转的表单
|
||||
copyMapItem: '', //复制的值
|
||||
cursorStyle: 'auto'
|
||||
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.id
|
||||
if (currentItemIndex.value === -1 && (type === 5 || type === 6 || type === 7 || type === 9)) {
|
||||
let type = item.switchType
|
||||
if (
|
||||
currentItemIndex.value &&
|
||||
(type === 'move' || type === 'revolve' || type === 'copy' || type === 'delete')
|
||||
) {
|
||||
message.warning('请先选择要操作的对象')
|
||||
return
|
||||
}
|
||||
if (type === 8 && !state.copyMapItem) {
|
||||
//粘贴
|
||||
if (type === 'paste' && !state.copyMapItem) {
|
||||
message.warning('请先复制对象')
|
||||
return
|
||||
}
|
||||
|
||||
if ((type === 10 || type === 13 || type === 17) && toolbarTypeIndex.value === type) {
|
||||
toolbarTypeIndex.value = 0
|
||||
if (
|
||||
(type === 'tools' || type === 'text' || type === 'layer' || type === 'grid') &&
|
||||
toolbarSwitchType.value === type
|
||||
) {
|
||||
toolbarSwitchType.value = ''
|
||||
} else {
|
||||
toolbarTypeIndex.value = type
|
||||
toolbarSwitchType.value = type
|
||||
}
|
||||
|
||||
if (toolbarSwitchType.value !== 'text') {
|
||||
state.cursorStyle = `auto`
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
case 'open':
|
||||
// 打开
|
||||
break
|
||||
case 2:
|
||||
case 'save':
|
||||
//保存
|
||||
saveMap()
|
||||
break
|
||||
case 3:
|
||||
case 'saveAs':
|
||||
//另存为 存为json文件 无法直接访问用户的文件系统 不能选择存在那个文件夹里面
|
||||
const jsonString = JSON.stringify(allHistoryList.value[currentIndex.value], null, 2)
|
||||
const blob = new Blob([jsonString], { type: 'application/json' })
|
||||
@ -553,59 +713,79 @@ const toolbarClick = (item) => {
|
||||
|
||||
message.success('下载成功')
|
||||
break
|
||||
case 4:
|
||||
case 'choose':
|
||||
//选择
|
||||
break
|
||||
case 5:
|
||||
case 'move':
|
||||
//移动
|
||||
break
|
||||
case 6:
|
||||
case 'revolve':
|
||||
break
|
||||
case 7:
|
||||
case 'copy':
|
||||
//复制
|
||||
state.copyMapItem = allHistoryList.value[currentIndex.value][currentItemIndex.value]
|
||||
break
|
||||
case 8:
|
||||
case 'paste':
|
||||
//粘贴
|
||||
let item = JSON.parse(JSON.stringify(state.copyMapItem))
|
||||
item.x = item.x + 50
|
||||
item.y = item.y + 50
|
||||
imgList.value.push(item)
|
||||
let copyObj = JSON.parse(JSON.stringify(state.copyMapItem))
|
||||
copyObj.x = copyObj.x + 50
|
||||
copyObj.y = copyObj.y + 50
|
||||
imgList.value.push(copyObj)
|
||||
addEditHistory()
|
||||
break
|
||||
case 9:
|
||||
case 'delete':
|
||||
//删除
|
||||
imgList.value.splice(currentItemIndex.value, 1)
|
||||
addEditHistory()
|
||||
break
|
||||
case 10:
|
||||
case 'tools':
|
||||
//工具
|
||||
if (toolbarTypeIndex.value === 10) {
|
||||
if (toolbarSwitchType.value === 'tools') {
|
||||
state.isShowToolbar = true
|
||||
item.isActive = true
|
||||
} else {
|
||||
state.isShowToolbar = false
|
||||
item.isActive = false
|
||||
}
|
||||
break
|
||||
case 11:
|
||||
case 'lineLibrary':
|
||||
// 线库
|
||||
break
|
||||
case 12:
|
||||
case 'region':
|
||||
// 区域
|
||||
break
|
||||
case 13:
|
||||
case 'text':
|
||||
//文字
|
||||
textFormToolDialogRef.value.open()
|
||||
// if (toolbarTypeIndex.value === 13) {
|
||||
// state.cursorStyle = `url('${cursorCollection.input}'),auto`
|
||||
// } else {
|
||||
// state.cursorStyle = `auto`
|
||||
// }
|
||||
if (toolbarSwitchType.value === 'text') {
|
||||
state.textFormToolShow = true
|
||||
state.cursorStyle = `url('${cursorCollection.input}'),auto`
|
||||
} else {
|
||||
state.textFormToolShow = false
|
||||
state.cursorStyle = `auto`
|
||||
state.textFormToolShow = false
|
||||
state.showInputBox = false
|
||||
state.inputBoxValue = ''
|
||||
}
|
||||
break
|
||||
case 14:
|
||||
case 'ranging':
|
||||
// 测距
|
||||
break
|
||||
case 15:
|
||||
case 'layer':
|
||||
//图层
|
||||
if (toolbarSwitchType.value === 'layer') {
|
||||
state.isShowLayer = true
|
||||
item.isActive = true
|
||||
} else {
|
||||
state.isShowLayer = false
|
||||
item.isActive = false
|
||||
}
|
||||
break
|
||||
case 16:
|
||||
case 'marker':
|
||||
// 标记
|
||||
break
|
||||
case 17:
|
||||
case 'grid':
|
||||
//网格
|
||||
if (toolbarTypeIndex.value === 17) {
|
||||
if (toolbarSwitchType.value === 'grid') {
|
||||
state.isShowGrid = true
|
||||
item.isActive = true
|
||||
} else {
|
||||
@ -613,26 +793,35 @@ const toolbarClick = (item) => {
|
||||
item.isActive = false
|
||||
}
|
||||
break
|
||||
case 18:
|
||||
case 'larger':
|
||||
//放大
|
||||
break
|
||||
case 19:
|
||||
case 'smaller':
|
||||
//缩小
|
||||
break
|
||||
case 20:
|
||||
case 'withdraw':
|
||||
//上一步
|
||||
backPreviousStep()
|
||||
break
|
||||
case 21:
|
||||
case 'next':
|
||||
//下一步
|
||||
backNextStep()
|
||||
break
|
||||
case 22:
|
||||
drawNodes()
|
||||
case 'drawNodes':
|
||||
//绘制节点
|
||||
break
|
||||
case 23:
|
||||
case 'editNode':
|
||||
// 编辑节点
|
||||
break
|
||||
case 24:
|
||||
case 'drawRoute':
|
||||
//绘制路线
|
||||
break
|
||||
case 25:
|
||||
case 'editRoute':
|
||||
// 编辑路线
|
||||
break
|
||||
case 'equipment':
|
||||
// 设备
|
||||
equipmentToolDialogRef.value.open()
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -647,6 +836,53 @@ 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, '选中的')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
imgList.value = [
|
||||
{
|
||||
@ -718,34 +954,66 @@ onMounted(() => {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.top-tool-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
margin-top: -20px;
|
||||
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 {
|
||||
.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;
|
||||
// cursor: url('https://api.znkjfw.com/admin-api/infra/file/4/get/输入_png_179_1738982726561.png'),
|
||||
// auto;
|
||||
width: 52px;
|
||||
height: 70px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
padding: 10px;
|
||||
.name {
|
||||
font-family:
|
||||
PingFangSC,
|
||||
@ -758,46 +1026,22 @@ onMounted(() => {
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
.line {
|
||||
margin: 0 14px;
|
||||
width: 1px;
|
||||
height: 47px;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-active {
|
||||
background: #ebf1ff;
|
||||
border-bottom: 2px solid #1677ff;
|
||||
}
|
||||
|
||||
.right-tool-active {
|
||||
background: #ebf1ff;
|
||||
}
|
||||
}
|
||||
|
||||
.right-tool-list {
|
||||
.input-box-class {
|
||||
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;
|
||||
border: 1px solid #00329f;
|
||||
padding: 4px;
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -705,7 +705,7 @@ const formData = ref({
|
||||
skuInfo: undefined, //物料信息
|
||||
skuBatch: undefined, // 物料批次号
|
||||
skuNumber: undefined, // 物料数量
|
||||
priority: undefined, // 优先级
|
||||
priority: 50, // 优先级
|
||||
otherMsg: undefined, // 其他信息
|
||||
doCycle: 0, //循环(0:不循环、1:循环)
|
||||
doMoveAll: 0, //是否搬空所选线库/区域(0:不搬空、1:搬空)
|
||||
@ -740,7 +740,7 @@ const resetFormData = () => {
|
||||
skuInfo: undefined, //物料信息
|
||||
skuBatch: undefined, // 物料批次号
|
||||
skuNumber: undefined, // 物料数量
|
||||
priority: undefined, // 优先级
|
||||
priority: 50, // 优先级
|
||||
otherMsg: undefined, // 其他信息
|
||||
doCycle: 0, //循环(0:不循环、1:循环)
|
||||
doMoveAll: 0, //是否搬空所选线库/区域(0:不搬空、1:搬空)
|
||||
|
Loading…
Reference in New Issue
Block a user