| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361 |
- <template>
- <div class="mapdata">
- <div id="container" ref="container" style="width: 1200px"></div>
- <div class="left">
- <el-card class="box-card">
- <div slot="header" class="clearfix">
- <span style="font-size: 18px">地图预览</span>
- </div>
- <div style="height: 100%; padding-bottom: 10px">
- <el-input v-model="value" type="textarea" :rows="34"></el-input>
- </div>
- <div
- class="bottombtn"
- style="width: 100%; height: 35px; padding: 10px 0 0;"
- >
- <el-button
- v-no-more-click
- @click="close"
- type="primary"
- icon="el-icon-close"
- style="float: right; height: 33px; line-height: 2px;margin: 0 10px"
- >关闭
- </el-button>
- <el-button
- v-no-more-click
- @click="save"
- type="primary"
- icon="el-icon-check"
- style="float: right; height: 33px; line-height: 2px; margin: 0 10px"
- >保存
- </el-button>
- <el-button
- v-no-more-click
- @click="reset"
- type="primary"
- icon="el-icon-setting"
- style="float: right; height: 33px; line-height: 2px; margin: 0 5px"
- >重置
- </el-button>
- <!-- <el-button-->
- <!-- v-no-more-click-->
- <!-- @click="view"-->
- <!-- type="primary"-->
- <!-- icon="el-icon-refresh"-->
- <!-- style="float: right; height: 33px; line-height: 2px"-->
- <!-- >刷新-->
- <!-- </el-button>-->
- </div>
- </el-card>
- </div>
- </div>
- </template>
- <script>
- import Konva from 'konva'
- import {
- getLotoMapInfo,
- getLotoInfo,
- updateLoto,
- unbundlePointPage
- } from '@/api/mes/lotoStation/lotoStation'
- import { getIsIsolationPointPage } from '@/api/mes/spm/segregationPoint'
- export default {
- name: 'KonvaExample',
- data() {
- return {
- stage: null,
- layer: null,
- selectedStates: [], // 用于存储每个元素的选中状态
- selectedText: [], // 用于存储未选中的元素文本
- rects: [], // 白色rect合集
- texts: [], // 白色text合集
- redrects: [], // 红色rect合集
- redtexts: [], // 白色text合集
- value: '',
- form: {}, //拿到单个数据
- originData: null, //原始数据
- filterData: null, //用来过滤掉已经渲染出来的隔离点
- leftPoints: [], //绑定的但未指定位置的集合
- orgLeftPoints: [],//原始左边数据
- rightPoints: [], //解绑的数据集合
- orgRightPoints: [],//原始右边数据
- groups: [], //组移动数据
- bindingPointIds: [], //存放从未绑定中放入物资柜的数据 id集合
- unbindPointIds: [], //解绑的数据接口参数 id集合
- isSave:false
- }
- },
- created() {
- this.getIsIsolationPointPage()
- },
- beforeRouteEnter(to, from, next) {
- next((vm) => {
- vm.getIsIsolationPointPage()
- vm.addPointsToRightPointsBox()
- })
- },
- mounted() {
- this.$nextTick(() => {
- this.getIsIsolationPointPage()
- this.getInfo()
- this.addPointsToRightPointsBox()
- })
- console.log(this.$route.query.lotoId, 'lotoId')
- },
- methods: {
- getInfo() {
- const lotoId = this.$route.query.lotoId
- const sopId = ''
- const ticketId = ''
- getLotoInfo(lotoId).then((response) => {
- console.log(response, '作业区域信息')
- this.form = response.data
- })
- // 获取map-json
- getLotoMapInfo(lotoId, sopId, ticketId).then((response) => {
- console.log(response, '作业区域预览接口调用')
- this.form.map = response.data
- this.filterData = response.data
- const data = {
- current: 1,
- size: -1,
- lotoId: this.$route.query.lotoId
- }
- getIsIsolationPointPage(data).then((res) => {
- const data1 = res.data.records
- const data2 = this.filterData
- console.log(data1, data2, '隔离点获取左侧列表啊哈哈哈哈')
- // 创建一个 Set 来存储 data2 中的 pointId
- const data2PointIds = new Set(data2.map(item => item.pointId))
- const filterData = data1.filter(item => !data2PointIds.has(item.pointId))
- this.leftPoints = filterData.map((item) => {
- return {
- pointId: item.pointId,
- pointName: item.pointName,
- remark: item.remark,
- prePointId: item.prePointId,
- pointType: item.pointType,
- pointTypeName: item.pointTypeName,
- powerType: item.powerType,
- powerTypeName: item.powerTypeName,
- pointIcon: item.pointIcon,
- status: false,
- pointPicture: item.pointPicture,
- mapImg: null
- }
- })
- this.addPointsToLeftPointsBox(filterData)
- this.orgLeftPoints = res.data.records.map((item) => {
- return {
- pointId: item.pointId,
- pointName: item.pointName,
- remark: item.remark,
- prePointId: item.prePointId,
- pointType: item.pointType,
- pointTypeName: item.pointTypeName,
- powerType: item.powerType,
- powerTypeName: item.powerTypeName,
- pointIcon: item.pointIcon,
- status: false,
- pointPicture: item.pointPicture,
- mapImg: null
- }
- })
- })
- if (response.data) {
- try {
- this.value = JSON.stringify(response.data, null, 4)
- this.originData = this.value
- } catch (err) {
- }
- }
- this.initKonva()
- })
- },
- // 获取所有隔离点
- getIsIsolationPointPage() {
- // 拿到解绑的隔离点数据
- const data1 = {
- current: 1,
- size: -1,
- lotoId: 0
- }
- getIsIsolationPointPage(data1).then((res) => {
- this.rightPoints = res.data.records.map((item) => {
- return {
- pointId: item.pointId,
- pointName: item.pointName,
- remark: item.remark,
- prePointId: item.prePointId,
- pointType: item.pointType,
- pointTypeName: item.pointTypeName,
- powerType: item.powerType,
- powerTypeName: item.powerTypeName,
- pointIcon: item.pointIcon,
- status: false,
- pointPicture: item.pointPicture,
- mapImg: null
- }
- })
- this.orgRightPoints = res.data.records.map((item) => {
- return {
- pointId: item.pointId,
- pointName: item.pointName,
- remark: item.remark,
- prePointId: item.prePointId,
- pointType: item.pointType,
- pointTypeName: item.pointTypeName,
- powerType: item.powerType,
- powerTypeName: item.powerTypeName,
- pointIcon: item.pointIcon,
- status: false,
- pointPicture: item.pointPicture,
- mapImg: null
- }
- })
- })
- },
- // 重置
- reset() {
- this.value = this.originData
- // 清空并重新赋值
- this.rightPoints = JSON.parse(JSON.stringify(this.orgRightPoints)) // 深拷贝
- this.leftPoints = JSON.parse(JSON.stringify(this.orgLeftPoints)) // 深拷贝
- this.initKonva() // 重新初始化 Konva
- },
- // 刷新
- // view() {
- // if (this.isJson(this.value)) {
- // this.form.map = this.value
- // this.initKonva()
- // this.getIsIsolationPointPage()
- // // this.addPointsToLeftPointsBox();
- // this.addPointsToRightPointsBox()
- // } else {
- // this.$message({
- // type: 'error',
- // message: '地图数据格式不正确,请输入有效的 JSON 格式!'
- // })
- // }
- // },
- close() {
- this.$router.push('/mes/dv/lotoStation')
- },
- save() {
- this.$confirm('请确认是否保存修改内容', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
- .then(() => {
- // 校验 this.value 是否为有效的 JSON
- if (this.isJson(this.value)) {
- const mapData =
- typeof this.value === 'string'
- ? this.value
- : JSON.stringify(this.value)
- const formData = {
- ...this.form,
- map: mapData
- }
- console.log(formData, 'map')
- updateLoto(formData).then((response) => {
- console.log(response, '修改车间区域地图')
- this.$message({
- type: 'success',
- message: '保存成功!'
- })
- })
- const data = {
- bindingPointIds: this.bindingPointIds,
- lotoId: this.$route.query.lotoId,
- unbindPointIds: this.unbindPointIds
- }
- console.log(data, '解绑与绑定数据参数')
- unbundlePointPage(data).then((res) => {
- console.log(res, '解绑接口返回值')
- this.bindingPointIds = []
- this.unbindPointIds = []
- })
- } else {
- this.$message({
- type: 'error',
- message: '地图数据格式不正确,请输入有效的 JSON 格式!'
- })
- }
- })
- .catch(() => {
- // 取消操作
- })
- },
- // 校验字符串是否为有效的 JSON
- isJson(str) {
- try {
- JSON.parse(str)
- return true
- } catch (e) {
- return false
- }
- },
- initKonva() {
- // 创建舞台
- this.stage = new Konva.Stage({
- container: this.$refs.container, // 容器元素
- width: 1250,
- height: 860
- })
- // 创建图层
- this.layer = new Konva.Layer()
- // 绘制隔离点等其他内容
- this.drawGrid(50, 50, '#e0e0e0') // 每个单元格50x50,浅灰色网格
- // 创建物资柜底图
- const bgImage = new Image()
- bgImage.src = require('@/assets/images/table.png')
- bgImage.onload = () => {
- // 创建背景图并添加到图层
- const knovaImage = new Konva.Image({
- x: 330,
- y: 10,
- image: bgImage,
- width: 500,
- height: 790,
- draggable: false
- })
- this.layer.add(knovaImage)
- // 创建所有隔离点父盒子 放置于网格线上
- const rightPointsBox = new Konva.Rect({
- x: 990,
- y: 15,
- width: 200,
- height: 800,
- cornerRadius: 5,
- stroke: 'black',
- strokeWidth: 2,
- fill: 'white'
- })
- const rightnoLoto = new Konva.Text({
- x: 1000, // 调整位置以适应网格
- y: 20, // 调整位置以适应网格
- text: '未绑定锁定站的隔离点数据',
- fontSize: 15,
- fill: 'black'
- })
- this.layer.add(rightPointsBox)
- this.layer.add(rightnoLoto)
- // 将隔离点添加到 rightPointsBox
- this.addPointsToRightPointsBox(rightPointsBox)
- // 渲染数据
- const imageSrc = require('@/assets/images/localSetIcon.jpg') // 图片路径
- this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25)
- // 将图层添加到舞台
- this.stage.add(this.layer)
- this.layer.draw()
- }
- // 禁止舞台拖拽
- this.stage.draggable(false)
- },
- // 绘制无限网格
- drawGrid(cellWidth, cellHeight, gridColor) {
- const width = 1200
- const height = 860
- // 绘制竖线
- for (let i = 0; i <= width; i += cellWidth) {
- const verticalLine = new Konva.Line({
- points: [i, 0, i, height],
- stroke: gridColor,
- strokeWidth: 1
- })
- this.layer.add(verticalLine)
- }
- // 绘制横线
- for (let j = 0; j <= height; j += cellHeight) {
- const horizontalLine = new Konva.Line({
- points: [0, j, width, j],
- stroke: gridColor,
- strokeWidth: 1
- })
- this.layer.add(horizontalLine)
- }
- // 添加网格坐标文本
- // for (let row = 0; row < height / cellHeight; row++) {
- // for (let col = 0; col < width / cellWidth; col++) {
- // const text = new Konva.Text({
- // x: col * cellWidth + 5, // 调整位置以适应网格
- // y: row * cellHeight + 5, // 调整位置以适应网格
- // text: `(${col},${row})`,
- // fontSize: 10,
- // fill: 'gray',
- // });
- // this.layer.add(text);
- // }
- // }
- this.layer.draw()
- },
- renderGrid(imageSrc) {
- this.selectedStates = [] // 用数组来存储选中状态
- this.rects = []
- this.texts = []
- this.bgrects = {}
- this.redrects = []
- this.redtexts = []
- this.selectedText = []
- const positions = JSON.parse(this.value)
- positions.forEach((pos, index) => {
- const x = pos.col * 50 // 每个单元格宽度为50
- const y = pos.row * 50 // 每个单元格高度为50
- const labelText = pos.pointName // 对应的文字
- const point = new Image()
- point.src = pos.pointIcon
- point.onload = () => {
- // 创建一个新的Group来包含整个隔离点
- const group = new Konva.Group({
- x: x,
- y: y,
- draggable: true // 设置为可拖拽
- })
- // 底部白色背景
- const bgrect = new Konva.Rect({
- x: -6,
- y: -5,
- width: 62,
- height: 80,
- cornerRadius: 5,
- stroke: 'white',
- strokeWidth: 2,
- fill: 'white'
- })
- // 普通矩形
- const rect = new Konva.Rect({
- x: 0,
- y: -1,
- width: 50,
- height: 72,
- cornerRadius: 5,
- stroke: 'red',
- strokeWidth: 2,
- fill: 'white'
- })
- // 图片
- const knovaImage = new Konva.Image({
- x: 0,
- y: 0,
- image: point,
- width: 50,
- height: 50
- })
- // 文字
- const text = new Konva.Text({
- x: 8,
- y: 50,
- fontSize: 17,
- text: labelText,
- fontFamily: 'Calibri',
- fill: 'red'
- })
- // 将所有元素添加到group中
- group.add(bgrect)
- group.add(rect)
- group.add(knovaImage)
- group.add(text)
- // 将group添加到layer
- this.layer.add(group)
- // 定义右侧盒子的范围
- const rightBoxBounds = {
- x: 990,
- y: 15,
- width: 200,
- height: 800
- }
- // 定义物资柜的范围
- const cabinetBounds = {
- x: 330, // 物资柜的 x 坐标
- y: 10, // 物资柜的 y 坐标
- width: 500, // 物资柜的宽度
- height: 790 // 物资柜的高度
- }
- group.on('dragend', () => {
- // 获取拖拽的内容对应的点名称
- const labelText = group.findOne('Text').text()
- // 获取 group 的位置
- const groupPos = group.getAbsolutePosition()
- // 检查是否仍在物资柜范围内
- const isInCabinet =
- groupPos.x >= cabinetBounds.x &&
- groupPos.x <= cabinetBounds.x + cabinetBounds.width &&
- groupPos.y >= cabinetBounds.y &&
- groupPos.y <= cabinetBounds.y + cabinetBounds.height
- // 检查是否在右侧盒子范围内
- const isInRightBox =
- groupPos.x >= rightBoxBounds.x &&
- groupPos.x <= rightBoxBounds.x + rightBoxBounds.width &&
- groupPos.y >= rightBoxBounds.y &&
- groupPos.y <= rightBoxBounds.y + rightBoxBounds.height
- // 查找并删除对应的点数据
- const indexToRemove = positions.findIndex(
- (item) => item.pointName === labelText
- )
- if (indexToRemove !== -1) {
- // 从 positions 中移除并获取移动的点
- const movedPoint = positions.splice(indexToRemove, 1)[0]
- if (movedPoint) {
- // 如果点位在物资柜外但不在右侧列表中,进行位置更新
- if (!isInCabinet && !isInRightBox) {
- // 更新位置为新的列和行
- const newCol = Math.round(groupPos.x / 50) // 四舍五入到最近的列
- const newRow = Math.round(groupPos.y / 50) // 四舍五入到最近的行
- // 限制列和行的范围,防止超出网格边界
- const maxCols = Math.floor(1200 / 50) - 1 // 最大列索引
- const maxRows = Math.floor(860 / 50) - 1 // 最大行索引
- const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
- const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
- // 更新点位数据
- const updatedPosition = {
- ...movedPoint,
- col: boundedCol,
- row: boundedRow
- }
- // 更新 positions 数组中的点位
- positions[indexToRemove] = updatedPosition
- this.value = JSON.stringify(positions, null, 4)
- }
- // 如果从物资柜外移动到右侧列表
- else if (isInRightBox) {
- // 确保点位没有被重复添加到 rightPoints 中
- if (
- !this.rightPoints.find(
- (point) => point.pointName === movedPoint.pointName
- )
- ) {
- // 从 positions 中删除该点
- const updatedPositions = positions.filter(
- (item) => item.pointName !== movedPoint.pointName
- )
- this.value = JSON.stringify(updatedPositions, null, 4)
- // 将 movedPoint 添加到 rightPoints 数组
- this.rightPoints.push(movedPoint)
- // 将 pointId 添加到 unbindPointIds 数组
- this.unbindPointIds.push(movedPoint.pointId)
- }
- }
- // 如果是从物资柜内拿出来并移到柜外但不进入右侧列表
- else if (isInCabinet && !isInRightBox) {
- // 更新位置并保存
- const newCol = Math.round(groupPos.x / 50) // 四舍五入到最近的列
- const newRow = Math.round(groupPos.y / 50) // 四舍五入到最近的行
- // 限制列和行的范围,防止超出网格边界
- const maxCols = Math.floor(1200 / 50) - 1 // 最大列索引
- const maxRows = Math.floor(860 / 50) - 1 // 最大行索引
- const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
- const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
- // 更新点位数据
- const updatedPosition = {
- ...movedPoint,
- col: boundedCol,
- row: boundedRow
- }
- // 更新 positions 数组中的点位
- positions[indexToRemove] = updatedPosition
- this.value = JSON.stringify(positions, null, 4)
- }
- }
- } else {
- // 如果点不在 positions 中,可能是从右侧列表移动回来
- const rightIndex = this.rightPoints.findIndex(
- (item) => item.pointName === labelText
- )
- if (rightIndex !== -1) {
- // 从右侧拖拽到物资柜外或物资柜内
- const movedPoint = this.rightPoints.splice(rightIndex, 1)[0]
- // 如果点不在右侧列表中且不在物资柜中,更新位置
- if (!isInRightBox && !isInCabinet) {
- // 更新位置为新的列和行
- const newCol = Math.round(groupPos.x / 50) // 四舍五入到最近的列
- const newRow = Math.round(groupPos.y / 50) // 四舍五入到最近的行
- // 限制列和行的范围,防止超出网格边界
- const maxCols = Math.floor(1200 / 50) - 1 // 最大列索引
- const maxRows = Math.floor(860 / 50) - 1 // 最大行索引
- const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
- const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
- // 更新点位数据
- const updatedPosition = {
- ...movedPoint,
- col: boundedCol,
- row: boundedRow
- }
- // 更新 positions 数组中的点位
- positions.push(updatedPosition)
- this.value = JSON.stringify(positions, null, 4)
- }
- // 如果点从右侧拖拽到物资柜内
- if (isInCabinet) {
- // 更新位置为新的列和行
- const newCol = Math.round(groupPos.x / 50) // 四舍五入到最近的列
- const newRow = Math.round(groupPos.y / 50) // 四舍五入到最近的行
- // 限制列和行的范围,防止超出网格边界
- const maxCols = Math.floor(1200 / 50) - 1 // 最大列索引
- const maxRows = Math.floor(860 / 50) - 1 // 最大行索引
- const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
- const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
- // 更新点位数据
- const updatedPosition = {
- ...movedPoint,
- col: boundedCol,
- row: boundedRow
- }
- // 更新 positions 数组中的点位
- positions.push(updatedPosition)
- this.value = JSON.stringify(positions, null, 4)
- // 确保点位没有被重复添加到 leftPoints 中
- if (
- !this.leftPoints.find(
- (point) => point.pointName === movedPoint.pointName
- )
- ) {
- this.leftPoints.push(movedPoint)
- }
- }
- }
- }
- // 清理 undefined 数据
- this.rightPoints = this.rightPoints.filter(Boolean)
- // 打印调试信息
- console.log('Updated positions:', positions)
- console.log('Right Points:', this.rightPoints)
- console.log('Left Points:', this.leftPoints)
- // 重新绘制图层
- this.layer.draw()
- })
- }
- })
- },
- // renderGrid(imageSrc) {
- // this.selectedStates = [] // 用数组来存储选中状态
- // this.rects = []
- // this.texts = []
- // this.bgrects = {}
- // this.redrects = []
- // this.redtexts = []
- // this.selectedText = []
- //
- // const positions = JSON.parse(this.value)
- //
- // positions.forEach((pos, index) => {
- // const x = pos.col * 50 // 每个单元格宽度为50
- // const y = pos.row * 50 // 每个单元格高度为50
- // const labelText = pos.pointName // 对应的文字
- //
- // const point = new Image()
- // point.src = pos.pointIcon
- //
- // point.onload = () => {
- // // 创建一个新的Group来包含整个隔离点
- // const group = new Konva.Group({
- // x: x,
- // y: y,
- // draggable: true // 设置为可拖拽
- // })
- //
- // // 底部白色背景
- // const bgrect = new Konva.Rect({
- // x: -6,
- // y: -5,
- // width: 62,
- // height: 80,
- // cornerRadius: 5,
- // stroke: 'white',
- // strokeWidth: 2,
- // fill: 'white'
- // })
- //
- // // 普通矩形
- // const rect = new Konva.Rect({
- // x: 0,
- // y: -1,
- // width: 50,
- // height: 72,
- // cornerRadius: 5,
- // stroke: 'red',
- // strokeWidth: 2,
- // fill: 'white'
- // })
- //
- // // 图片
- // const knovaImage = new Konva.Image({
- // x: 0,
- // y: 0,
- // image: point,
- // width: 50,
- // height: 50
- // })
- //
- // // 文字
- // const text = new Konva.Text({
- // x: 8,
- // y: 50,
- // fontSize: 17,
- // text: labelText,
- // fontFamily: 'Calibri',
- // fill: 'red'
- // })
- //
- // // 将所有元素添加到group中
- // group.add(bgrect)
- // group.add(rect)
- // group.add(knovaImage)
- // group.add(text)
- //
- // // 将group添加到layer
- // this.layer.add(group)
- // // 定义右侧盒子的范围
- // const rightBoxBounds = {
- // x: 990,
- // y: 15,
- // width: 200,
- // height: 800
- // }
- // // 定义物资柜的范围
- // const cabinetBounds = {
- // x: 330, // 物资柜的 x 坐标
- // y: 10, // 物资柜的 y 坐标
- // width: 500, // 物资柜的宽度
- // height: 790 // 物资柜的高度
- // }
- //
- // // 定义是否已经在物资柜中的状态
- //
- // group.on('dragend', () => {
- // // 获取拖拽的内容对应的点名称
- // const labelText = group.findOne('Text').text()
- //
- // // 获取 group 的位置
- // const groupPos = group.getAbsolutePosition()
- //
- // // 检查是否仍在物资柜范围内
- // const isInCabinet =
- // groupPos.x >= cabinetBounds.x &&
- // groupPos.x <= cabinetBounds.x + cabinetBounds.width &&
- // groupPos.y >= cabinetBounds.y &&
- // groupPos.y <= cabinetBounds.y + cabinetBounds.height
- //
- // // 检查是否在右侧盒子范围内
- // const isInRightBox =
- // groupPos.x >= rightBoxBounds.x &&
- // groupPos.x <= rightBoxBounds.x + rightBoxBounds.width &&
- // groupPos.y >= rightBoxBounds.y &&
- // groupPos.y <= rightBoxBounds.y + rightBoxBounds.height
- //
- // // 查找并删除对应的点数据
- // const indexToRemove = positions.findIndex(
- // (item) => item.pointName === labelText
- // )
- //
- // if (indexToRemove !== -1) {
- // // 从 positions 中移除并获取移动的点
- // const movedPoint = positions.splice(indexToRemove, 1)[0]
- //
- // if (movedPoint) {
- // // 如果点位在物资柜外但不在右侧列表中,进行位置更新
- // if (!isInCabinet && !isInRightBox) {
- // // 更新位置为新的列和行
- // const newCol = Math.round(groupPos.x / 50) // 四舍五入到最近的列
- // const newRow = Math.round(groupPos.y / 50) // 四舍五入到最近的行
- //
- // // 限制列和行的范围,防止超出网格边界
- // const maxCols = Math.floor(1200 / 50) - 1 // 最大列索引
- // const maxRows = Math.floor(860 / 50) - 1 // 最大行索引
- //
- // const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
- // const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
- //
- // // 更新点位数据
- // const updatedPosition = {
- // ...movedPoint,
- // col: boundedCol,
- // row: boundedRow
- // }
- //
- // // 更新 positions 数组中的点位
- // positions[indexToRemove] = updatedPosition
- // this.value = JSON.stringify(positions, null, 4)
- // }
- //
- // // 如果从物资柜外移动到右侧列表
- // else if (isInRightBox) {
- // // 确保点位没有被重复添加到 rightPoints 中
- // if (
- // !this.rightPoints.find(
- // (point) => point.pointName === movedPoint.pointName
- // )
- // ) {
- // // 从 positions 中删除该点
- // const updatedPositions = positions.filter(
- // (item) => item.pointName !== movedPoint.pointName
- // )
- // this.value = JSON.stringify(updatedPositions, null, 4)
- //
- // // 将 movedPoint 添加到 rightPoints 数组
- // this.rightPoints.push(movedPoint)
- //
- // // 将 pointId 添加到 unbindPointIds 数组
- // this.unbindPointIds.push(movedPoint.pointId)
- // }
- // }
- // // 如果是从物资柜内拿出来并移到柜外但不进入右侧列表
- // else if (isInCabinet && !isInRightBox) {
- // // 更新位置并保存
- // const newCol = Math.round(groupPos.x / 50) // 四舍五入到最近的列
- // const newRow = Math.round(groupPos.y / 50) // 四舍五入到最近的行
- //
- // // 限制列和行的范围,防止超出网格边界
- // const maxCols = Math.floor(1200 / 50) - 1 // 最大列索引
- // const maxRows = Math.floor(860 / 50) - 1 // 最大行索引
- //
- // const boundedCol = Math.max(0, Math.min(newCol, maxCols)) // 限制列范围
- // const boundedRow = Math.max(0, Math.min(newRow, maxRows)) // 限制行范围
- //
- // // 更新点位数据
- // const updatedPosition = {
- // ...movedPoint,
- // col: boundedCol,
- // row: boundedRow
- // }
- //
- // // 更新 positions 数组中的点位
- // positions[indexToRemove] = updatedPosition
- // this.value = JSON.stringify(positions, null, 4)
- // }
- // }
- // } else {
- // // 如果点不在 positions 中,可能是从右侧列表移动回来
- // const rightIndex = this.rightPoints.findIndex(
- // (item) => item.pointName === labelText
- // )
- //
- // if (rightIndex !== -1 && !isInRightBox && !isInCabinet) {
- // // 从右侧拖拽到物资柜外
- // const movedPoint = this.rightPoints.splice(rightIndex, 1)[0]
- // if (
- // !this.leftPoints.find(
- // (point) => point.pointName === movedPoint.pointName
- // )
- // ) {
- // this.leftPoints.push(movedPoint)
- // }
- // }
- // }
- //
- // // 清理 undefined 数据
- // this.rightPoints = this.rightPoints.filter(Boolean)
- //
- // // 打印调试信息
- // console.log('Updated positions:', positions)
- // console.log('Right Points:', this.rightPoints)
- // })
- //
- // this.layer.draw()
- // }
- // })
- // },
- // 左侧的列表
- addPointsToLeftPointsBox(filterData) {
- // 获取接口返回的 leftPoints 数据
- const pointsData = filterData
- let row = 1 // 当前行
- let col = 1 // 当前列
- // 遍历 pointsData 并根据是否存在于 this.value 中来决定位置
- pointsData.forEach((point) => {
- const existingPoint = JSON.parse(this.value).find(
- (item) => item.pointId === point.pointId
- )
- // 如果该点在 this.value 中,使用它的原始位置
- if (existingPoint) {
- point.row = existingPoint.row
- point.col = existingPoint.col
- } else {
- // 否则,按顺序从 (0, 0) 位置开始,每行三个点
- point.row = row
- point.col = col
- // 每行最多三个点,换行处理
- col++
- if (col >= 3) {
- col = 0
- row++
- }
- }
- // 渲染该点
- this.renderPoint(point)
- })
- },
- // 渲染每个点
- renderPoint(point) {
- const x = point.col * 50 // 每个单元格宽度为50
- const y = point.row * 50 // 每个单元格高度为50
- const labelText = point.pointName // 对应的文字
- const pointImage = new Image()
- pointImage.src = point.pointIcon
- pointImage.onload = () => {
- // 创建一个新的 Group 来包含整个隔离点
- const group = new Konva.Group({
- x: x,
- y: y,
- draggable: true // 设置为可拖拽
- })
- // 背景矩形
- const bgrect = new Konva.Rect({
- x: -6,
- y: -5,
- width: 62,
- height: 80,
- cornerRadius: 5,
- stroke: 'white',
- strokeWidth: 2,
- fill: 'white'
- })
- // 普通矩形
- const rect = new Konva.Rect({
- x: 0,
- y: -1,
- width: 50,
- height: 72,
- cornerRadius: 5,
- stroke: 'red',
- strokeWidth: 2,
- fill: 'white'
- })
- // 图片
- const knovaImage = new Konva.Image({
- x: 0,
- y: 0,
- image: pointImage,
- width: 50,
- height: 50
- })
- // 文字
- const text = new Konva.Text({
- x: 8,
- y: 50,
- fontSize: 17,
- text: labelText,
- fontFamily: 'Calibri',
- fill: 'red'
- })
- // 将所有元素添加到 group 中
- group.add(bgrect)
- group.add(rect)
- group.add(knovaImage)
- group.add(text)
- // 将 group 添加到 layer
- this.layer.add(group)
- // 定义右侧盒子的范围
- const rightBoxBounds = {
- x: 990,
- y: 15,
- width: 200,
- height: 800
- }
- // 定义物资柜的范围
- const cabinetBounds = {
- x: 330,
- y: 10,
- width: 500,
- height: 790
- }
- // 处理拖拽事件
- group.on('dragend', () => {
- const groupPos = group.getAbsolutePosition()
- const isInRightBox =
- groupPos.x >= rightBoxBounds.x &&
- groupPos.x <= rightBoxBounds.x + rightBoxBounds.width &&
- groupPos.y >= rightBoxBounds.y &&
- groupPos.y <= rightBoxBounds.y + rightBoxBounds.height
- const isInCabinet =
- groupPos.x >= cabinetBounds.x &&
- groupPos.x <= cabinetBounds.x + cabinetBounds.width &&
- groupPos.y >= cabinetBounds.y &&
- groupPos.y <= cabinetBounds.y + cabinetBounds.height
- // 如果点进入右侧列表,执行删除操作
- if (isInRightBox) {
- this.removePointFromJson(point)
- } else if (isInCabinet) {
- // 如果点回到物资柜,执行更新操作
- this.updatePointInJson(point, groupPos)
- } else if (!isInCabinet && !isInRightBox) {
- // 如果点位在物资柜外但不在右侧列表中,进行位置更新
- this.updatePointInJson(point, groupPos)
- }
- })
- this.layer.draw()
- }
- },
- // 从 json 删除对应的点
- removePointFromJson(point) {
- // 更新 leftPoints 和 rightPoints
- this.rightPoints.push(point)
- this.unbindPointIds.push(point.pointId) // 给接口传递需要解绑的数据Id
- // 删除 JSON 中对应的点
- const updatedData = JSON.parse(this.value).filter(
- (item) => item.pointId !== point.pointId
- )
- this.value = JSON.stringify(updatedData, null, 4)
- // console.log('Updated value after removal:', this.value)
- },
- // 更新 JSON 中对应点的位置
- updatePointInJson(point, groupPos) {
- // 计算新的位置
- const newCol = Math.round(groupPos.x / 50)
- const newRow = Math.round(groupPos.y / 50)
- // 更新 positions 数组中的点位
- const updatedPosition = {
- row: newRow,
- col: newCol,
- pointId: point.pointId,
- pointName: point.pointName,
- remark: point.remark,
- prePointId: point.prePointId,
- pointType: point.pointType,
- pointTypeName: point.pointTypeName,
- powerType: point.powerType,
- powerTypeName: point.powerTypeName,
- state: point.state,
- pointIcon: point.pointIcon,
- pointPicture: point.pointPicture,
- mapImg: point.mapImg
- }
- let positions = JSON.parse(this.value)
- const index = positions.findIndex((item) => item.pointId === point.pointId)
- if (index !== -1) {
- positions[index] = updatedPosition
- this.value = JSON.stringify(positions, null, 4)
- } else {
- // 如果点位不在 this.value 中,则重新插入
- positions.push(updatedPosition)
- this.value = JSON.stringify(positions, null, 4)
- }
- console.log('Updated value after update:', this.value)
- },
- addPointsToRightPointsBox(rightPointsBox) {
- if (this.rightPoints && this.rightPoints.length > 0) {
- const boxWidth = rightPointsBox.width();
- const boxHeight = rightPointsBox.height();
- const boxX = rightPointsBox.x();
- const boxY = rightPointsBox.y();
- const padding = 10; // 每个隔离点之间的间距
- const pointWidth = 50; // 每个隔离点的宽度
- const pointHeight = 70; // 每个隔离点的高度(包括图片和文字)
- let currentX = boxX + padding;
- let currentY = boxY + padding;
- const rightBoxBounds = {
- x: 990,
- y: 15,
- width: 200,
- height: 800,
- };
- const cabinetBounds = {
- x: 330,
- y: 10,
- width: 500,
- height: 790,
- };
- this.rightPoints.forEach((point) => {
- // 创建一个组来组合红色边框、图片和文字
- const group = new Konva.Group({
- x: currentX,
- y: currentY + 14,
- draggable: true, // 启用拖拽功能
- });
- // 创建红色边框
- const borderRect = new Konva.Rect({
- x: 0,
- y: 0,
- width: pointWidth,
- height: pointHeight,
- cornerRadius: 5,
- stroke: 'red',
- strokeWidth: 2,
- fill: 'white',
- });
- group.add(borderRect);
- // 创建图片
- const image = new Image();
- image.src = point.pointIcon;
- image.onload = () => {
- const knovaImage = new Konva.Image({
- x: 1, // 图片在组内的位置
- y: 5, // 图片在组内的位置
- image: image,
- width: 50, // 图片宽度
- height: 50, // 图片高度
- });
- group.add(knovaImage);
- // 创建文字
- const pointText = new Konva.Text({
- x: 12, // 文字在组内的位置
- y: 53, // 文字在组内的位置
- text: point.pointName,
- fontSize: 12,
- fill: 'red',
- });
- group.add(pointText);
- // 将组添加到图层
- this.layer.add(group);
- this.groups[point.pointName] = group; // 用文字作为键存储
- group.on('dragmove', () => {
- // 获取当前组的位置
- const groupPos = group.getAbsolutePosition();
- // 更新组的位置,无限制
- group.x(groupPos.x);
- group.y(groupPos.y);
- });
- // 监听组的拖拽结束事件
- group.on('dragend', () => {
- const gridX = 50; // 网格单元格宽度
- const gridY = 50; // 网格单元格高度
- // 计算最近的网格点位置
- const snappedX = Math.round(group.x() / gridX) * gridX;
- const snappedY = Math.round(group.y() / gridY) * gridY;
- // 设置组到最近的网格点位置
- group.x(snappedX);
- group.y(snappedY);
- // 计算网格坐标
- const row = Math.floor(snappedY / gridY);
- const col = Math.floor(snappedX / gridX);
- // 更新点位数据
- const updatedPointData = {
- row: row,
- col: col,
- pointId: point.pointId,
- pointName: point.pointName,
- remark: point.remark,
- prePointId: point.prePointId,
- pointType: point.pointType,
- pointTypeName: point.pointTypeName,
- powerType: point.powerType,
- powerTypeName: point.powerTypeName,
- state: point.status,
- pointIcon: point.pointIcon,
- pointPicture: point.pointPicture,
- mapImg: null,
- };
- // 解析 this.value 为数组
- let valueArray = [];
- try {
- valueArray = JSON.parse(this.value);
- } catch (e) {
- console.error('Failed to parse value:', e);
- }
- // 判断拖拽目标区域
- if (
- snappedX >= rightBoxBounds.x &&
- snappedX <= rightBoxBounds.x + rightBoxBounds.width &&
- snappedY >= rightBoxBounds.y &&
- snappedY <= rightBoxBounds.y + rightBoxBounds.height
- ) {
- // 进入右侧盒子区域
- console.log('进入右侧盒子区域');
- // 检查点是否已经存在于 valueArray 中
- // const index = valueArray.findIndex(item => item.pointId === point.pointId);
- // if (index !== -1) {
- // // 更新已有点位
- // valueArray[index] = updatedPointData;
- // } else {
- // // 如果点位不存在,则新增
- // valueArray.push(updatedPointData);
- // }
- //
- // this.value = JSON.stringify(valueArray, null, 4);
- // 如果点不在目标区域,从 valueArray 中移除
- this.value = JSON.stringify(valueArray.filter(item => item.pointId !== point.pointId), null, 4);
- // 从右侧盒子移除点
- this.rightPoints = this.rightPoints.filter(
- (item) => item.pointId !== point.pointId
- );
- } else if (
- snappedX >= cabinetBounds.x &&
- snappedX <= cabinetBounds.x + cabinetBounds.width &&
- snappedY >= cabinetBounds.y &&
- snappedY <= cabinetBounds.y + cabinetBounds.height
- ) {
- // 进入物资柜区域
- console.log('进入物资柜区域');
- // 检查点是否已经存在于 valueArray 中
- const index = valueArray.findIndex(item => item.pointId === point.pointId);
- if (index !== -1) {
- // 更新已有点位
- valueArray[index] = updatedPointData;
- } else {
- // 如果点位不存在,则新增
- valueArray.push(updatedPointData);
- }
- this.value = JSON.stringify(valueArray, null, 4);
- this.bindingPointIds.push(point.pointId);
- // 从右侧盒子移除点
- this.rightPoints = this.rightPoints.filter(
- (item) => item.pointId !== point.pointId
- );
- } else {
- console.log('未进入目标区域,保持原状态');
- // 如果点不在目标区域,从 valueArray 中移除
- this.value = JSON.stringify(valueArray.filter(item => item.pointId !== point.pointId), null, 4);
- // 如果点不在目标区域,重新添加到 rightPoints
- this.rightPoints.push(point);
- }
- // 重新绘制图层
- this.layer.draw();
- });
- // 重新绘制图层
- this.layer.draw();
- };
- // 更新下一个隔离点的位置
- currentX += pointWidth + padding;
- if (currentX + pointWidth > boxX + boxWidth) {
- currentX = boxX + padding;
- currentY += pointHeight + padding;
- }
- });
- }
- }
- }
- }
- </script>
- <style scoped lang="scss">
- #container {
- width: 100%;
- height: 100%;
- }
- .mapdata {
- width: 100%;
- height: 100%;
- display: flex;
- }
- .left {
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
- margin-bottom: 20px;
- }
- </style>
|