| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263 |
- <template>
- <div class="mapdata">
- <div id="container" ref="container" style="width: 1600px"></div>
- <div class="left">
- <div
- class="bottombtn"
- style="width: 100%; height: 35px; padding: 10px;display: flex;flex-direction: column;"
- >
- <!-- <el-button-->
- <!-- v-no-more-click-->
- <!-- @click="close"-->
- <!-- type="primary"-->
- <!-- icon="el-icon-close"-->
- <!-- style="align-self: flex-end;margin-top: 10px"-->
- <!-- >关闭-->
- <!-- </el-button>-->
- <!-- <el-button-->
- <!-- v-no-more-click-->
- <!-- @click="save"-->
- <!-- type="primary"-->
- <!-- icon="el-icon-check"-->
- <!-- style="align-self: flex-end;margin-top: 10px"-->
- <!-- >保存-->
- <!-- </el-button>-->
- <!-- <el-button-->
- <!-- v-no-more-click-->
- <!-- @click="reset"-->
- <!-- type="primary"-->
- <!-- icon="el-icon-setting"-->
- <!-- style="align-self: flex-end;margin-top: 10px"-->
- <!-- >重置-->
- <!-- </el-button>-->
- </div>
- </div>
- </div>
- </template>
- <script>
- import Konva from 'konva'
- import {
- selectLotoMapById,
- selectIsLotoSwitchMapById,
- updateIsLotoSwitchMap,
- updatePointsBindingSwitchMap
- } from '@/api/mes/switchmanagement/switchmanagement'
- import {getIsIsolationPointPage} from '@/api/mes/spm/segregationPoint'
- import {getIsMapPointPage, selectIsMapPointById, updateMapPointList} from '@/api/system/mappoint'
- import {selectIsMapById} from '@/api/system/mapconfig'
- 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: true,
- isInitialized: false, // 添加初始化标志
- imageUrl: '',//获取底图
- width: '',//底图宽
- height: '',//底图高
- x: '',//底图横坐标
- y: '',//底图纵坐标
- mapId: null,//地图Id
- mapType: 2,//地图类型
- pointList: null,//接口给的所有点位数据
- bindingPoints: [],//给地图点位界面更新的绑定隔离点
- movePoints: [],//给地图点位界面更新位置
- unbindingPoints: [],//给地图点位界面更新解绑数据
- blinkLights : [], // 所有需要闪烁的 light 节点
- globalBlinkTimer : null
- }
- },
- // watch: {
- // bindingPointIds(newVal, oldVal) {
- // if (newVal) {
- // this.isSave = false;
- // }
- // },
- // unbindPointIds(newVal, oldVal) {
- // if (newVal) {
- // this.isSave = false;
- // }
- // },
- // // value: {
- // // handler(newVal, oldVal) {
- // // if (this.isInitialized && newVal) {
- // // // 只有在初始化后才监听 value 变化
- // // const parsedValue = JSON.parse(newVal);
- // // console.log(parsedValue, "deep watch for value");
- // // this.isSave = false;
- // // }
- // // },
- // // deep: true,
- // // },
- // },
- created() {
- // this.getIsIsolationPointPage()
- this.isInitialized = true
- },
- beforeRouteEnter(to, from, next) {
- next((vm) => {
- // vm.getIsIsolationPointPage()
- vm.addPointsToRightPointsBox()
- })
- },
- mounted() {
- this.$nextTick(() => {
- this.getInfo()
- this.getIsIsolationPointPage()
- this.addPointsToRightPointsBox()
- })
- console.log(this.$route.query.switchMapId, 'switchMapId')
- },
- methods: {
- getInfo() {
- const switchMapId = this.$route.query.switchMapId
- selectIsLotoSwitchMapById(switchMapId).then((response) => {
- console.log(response, '作业区域信息')
- this.form = response.data
- this.mapId = response.data.mapId
- // 获取不同底图 如地图或者柜子
- selectIsMapById(response.data.mapId).then((response) => {
- console.log(response, '获取底图')
- if (response.data) {
- try {
- this.value = JSON.stringify(response.data.pointList, null, 4)
- this.originData = this.value
- } catch (err) {
- console.error(err)
- }
- }
- this.imageUrl = response.data.imageUrl
- this.width = response.data.width
- this.height = response.data.height
- this.x = response.data.x
- this.y = response.data.y
- this.pointList = response.data.pointList
- const data = {
- current: 1,
- size: -1,
- switchMapId: this.$route.query.switchMapId
- }
- getIsIsolationPointPage(data).then((res) => {
- const data1 = res.data.records // 该柜子或地图所有点
- const data2 = this.pointList // 该柜子里 json 拿到的点位(已渲染)
- console.log(data1, '该柜子或地图所有点')
- console.log(data2, '柜子里json拿到的点位')
- // 当前柜子已经存在的点位 id
- const pointListIds = new Set(this.pointList.map((item) => item.pointId))
- // 过滤掉已经在 pointList 里的点
- const filterData = data1.filter(item => !pointListIds.has(item.pointId))
- console.log([...pointListIds], '已有点位 ID')
- console.log(filterData, 'filterData-需要显示在左侧的数据')
- // 左侧需要显示的数据
- // this.leftPoints = filterData.map((item) => {
- // return {
- // pointId: item.pointId,
- // entityId: item.pointId,
- // entityName: item.pointName,
- // 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,
- // mapId:this.form.mapId,
- // mapType: 2,
- // mapName:'你好4',
- // x: 0,
- // y: 0,
- // }
- // })
- // 调用你已有的渲染逻辑
- // this.addPointsToLeftPointsBox(filterData)
- // 保存完整数据
- this.orgLeftPoints = res.data.records.map((item) => {
- return {
- pointId: item.pointId,
- entityId: item.pointId,
- entityName: item.pointName,
- 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,
- mapId:this.form.mapId,
- mapType: this.form.mapType,
- }
- })
- })
- this.initKonva()
- })
- })
- },
- // 获取未绑定的所有隔离点
- getIsIsolationPointPage() {
- // 拿到解绑的隔离点数据
- const data1 = {
- current: 1,
- size: -1,
- switchMapId: 0
- }
- getIsIsolationPointPage(data1).then((res) => {
- this.rightPoints = res.data.records.map((item) => {
- return {
- entityId: item.pointId,
- entityName: item.pointName,
- 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,
- mapId: this.mapId,
- mapType: this.mapType
- }
- })
- this.orgRightPoints = res.data.records.map((item) => {
- return {
- entityId: item.pointId,
- entityName: item.pointName,
- 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,
- mapId: this.mapId,
- mapType: this.mapType
- }
- })
- })
- },
- // 重置
- reset() {
- this.value = this.originData
- // 清空并重新赋值
- this.rightPoints = JSON.parse(JSON.stringify(this.orgRightPoints)) // 深拷贝
- this.leftPoints = JSON.parse(JSON.stringify(this.orgLeftPoints)) // 深拷贝
- this.initKonva() // 重新初始化 Konva
- },
- close() {
- // this.$router.push('/mes/dv/lotoStation')
- this.getInfo()
- // this.initKonva()
- },
- 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')
- updateIsLotoSwitchMap(formData).then((response) => {
- console.log(response, '修改车间区域地图')
- this.$message({
- type: 'success',
- message: '保存成功!'
- })
- })
- let dataMap = {
- bindingPoints: this.leftPoints,
- movePoints: this.movePoints,
- unbindingPoints: this.rightPoints
- }
- console.log(dataMap, '先拿到数据看看再说')
- updateMapPointList(dataMap).then((res) => {
- console.log(res, '拿到的新绑定数据')
- })
- const data = {
- bindingPointIds: this.bindingPointIds,
- switchMapId: this.$route.query.switchMapId,
- unbindPointIds: this.unbindPointIds
- }
- console.log(data, '解绑与绑定数据参数')
- updatePointsBindingSwitchMap(data).then((res) => {
- console.log(res, '解绑接口返回值')
- this.bindingPointIds = []
- this.unbindPointIds = []
- })
- // this.close()
- } 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: 1600,
- height: 860
- })
- // 创建图层
- this.layer = new Konva.Layer()
- // 绘制隔离点等其他内容
- this.drawGrid(50, 50, '#e0e0e0') // 每个单元格50x50,浅灰色网格
- // 创建物资柜底图
- const bgImage = new Image()
- const imageConfig = {
- x: this.x,
- y: this.y,
- width: this.width,
- height: this.height,
- draggable: false
- }
- bgImage.src = this.imageUrl
- bgImage.onload = () => {
- const knovaImage = new Konva.Image({
- ...imageConfig,
- image: bgImage
- })
- this.layer.add(knovaImage)
- // 创建背景图并添加到图层
- // 创建所有隔离点父盒子 放置于网格线上
- // const rightPointsBox = new Konva.Rect({
- // x: 1100,
- // y: 15,
- // width: 200,
- // height: 800,
- // cornerRadius: 5,
- // stroke: 'black',
- // strokeWidth: 2,
- // fill: 'white'
- // })
- // const rightnoLoto = new Konva.Text({
- // x: 1110, // 调整位置以适应网格
- // 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 = 1600
- 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 = []
- // ✅ 每次渲染前清空
- this.rightPoints = []
- this.leftPoints = []
- this.bindingPointIds = []
- this.unbindPointIds = []
- this.movePoints = []
- // 点位数据
- const positions = (this.pointList || []).map(item => ({
- row: item.x,
- col: item.y,
- id: item.id,
- pointId: item.entityId,
- pointName: item.entityName,
- entityId: item.entityId,
- entityName: item.entityName,
- mapId: item.mapId,
- mapType: parseInt(item.mapType),
- x: item.x,
- y: item.y,
- remark: item.remark,
- pointIcon: item.pointIcon,
- pointPicture: item.pointPicture,
- pointSerialNumber:item.pointSerialNumber,
- switchStatus: item.switchStatus,
- switchLastUpdateTime:item.switchLastUpdateTime
- }))
- console.log(positions, 'positions')
- positions.forEach((pos) => {
- const x = pos.x * 50
- const y = pos.y * 50
- const labelText = pos.entityName
- const point = new Image()
- point.src = pos.pointIcon
- point.onload = () => {
- const group = new Konva.Group({
- x: x,
- y: y,
- draggable: true
- })
- const bgrect = new Konva.Rect({
- x: -1,
- y: -5,
- width: 50,
- height: 78,
- cornerRadius: 5,
- stroke: 'white',
- strokeWidth: 2,
- fill: 'white'
- })
- const rect = new Konva.Rect({
- x: 1,
- y: -1,
- width: 45,
- height: 70,
- cornerRadius: 5,
- stroke: 'red',
- strokeWidth: 2,
- fill: 'white'
- })
- // 确定灯的颜色
- let lightColor, shadowColor, stroke;
- console.log(pos,'点位')
- if (pos.switchStatus == "0") {
- // lightColor = '#ff000d'; // Red
- // shadowColor = '#ffcae8';
- // stroke = '#ffcae8';
- lightColor = '#e0e0e0'; // Gray (unknown)
- shadowColor = '#e0e0e0';
- stroke = '#e0e0e0';
- } else if (pos.switchStatus == "1") {
- lightColor = '#0ea562'; // Green
- shadowColor = '#3ab890';
- stroke = '#3ab890';
- } else {
- lightColor = 'white';
- shadowColor="white";
- stroke="white"
- // lightColor = '#e0e0e0'; // Gray (unknown)
- // shadowColor = '#e0e0e0';
- // stroke = '#e0e0e0';
- }
- const isRed = pos.switchStatus == "0";
- const isGrey = pos.switchStatus == null;
- // Create the light
- const light = new Konva.Circle({
- x: 22.5, // Circle center position
- y: 25, // Circle center position
- radius: 12,
- fill: lightColor,
- stroke: stroke,
- strokeWidth: 2,
- shadow: {
- color: shadowColor,
- blur: 5,
- offset: {x: 0, y: 0},
- opacity: 0.8
- }
- });
- // const knovaImage = new Konva.Image({
- // x: 1,
- // y: 0,
- // image: point,
- // width: 45,
- // height: 45
- // })
- const text = new Konva.Text({
- x: 8,
- y: 50,
- fontSize: 17,
- text: labelText,
- fontFamily: 'Calibri',
- fill: 'red'
- })
- group.add(bgrect)
- group.add(rect)
- // group.add(knovaImage)
- // 添加灯闪
- group.add(light)
- group.add(text)
- this.layer.add(group)
- // 定义右侧盒子的范围
- // const rightBoxBounds = { x: 1100, y: 15, width: 200, height: 800 }
- // group.on('dragend', () => {
- // const groupPos = group.getAbsolutePosition()
- // const movedLabel = labelText
- //
- // 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 ? positions.findIndex(item => item.entityName === movedLabel) : -1
- //
- // if (indexToRemove !== -1) {
- // const movedPoint = positions[indexToRemove]
- // if (isInRightBox) {
- // // 移动到右侧
- // positions.splice(indexToRemove, 1)
- // if (!this.rightPoints.some(p => p.entityName === movedPoint.entityName)) {
- // this.rightPoints.push(movedPoint)
- // this.unbindPointIds.push(movedPoint.entityId)
- // this.bindingPointIds = this.bindingPointIds.filter(id => id !== movedPoint.entityId)
- // }
- // } else {
- // // 在柜子内/外更新位置
- // const newCol = Math.round(groupPos.y / 50)
- // const newRow = Math.round(groupPos.x / 50)
- //
- // const boundedCol = Math.max(0, Math.min(newCol, Math.floor(860 / 50) - 1))
- // const boundedRow = Math.max(0, Math.min(newRow, Math.floor(1200 / 50) - 1))
- //
- // const updatedPoint = {
- // ...movedPoint,
- // row: boundedRow,
- // col: boundedCol,
- // x: boundedRow,
- // y: boundedCol,
- // mapId: this.form.mapId,
- // mapType: this.form.mapType,
- // }
- //
- // positions[indexToRemove] = updatedPoint
- //
- // // ✅ 只有位置不为 0 才加入 movePoints
- // if (!(updatedPoint.row == 0 && updatedPoint.col == 0 && updatedPoint.x == 0 && updatedPoint.y == 0)) {
- // if (!this.movePoints) this.movePoints = []
- // // 防止重复 push,先找一下
- // const existIdx = this.movePoints.findIndex(p => p.pointId === updatedPoint.pointId)
- // if (existIdx !== -1) {
- // this.movePoints.splice(existIdx, 1, updatedPoint) // 覆盖旧的
- // } else {
- // this.movePoints.push(updatedPoint)
- // }
- // }
- // }
- // } else {
- // // movedLabel 不在 positions,可能是从右侧拖出来
- // const rightIndex = this.rightPoints.findIndex(item => item.entityName === movedLabel)
- // if (rightIndex !== -1) {
- // const movedPoint = this.rightPoints.splice(rightIndex, 1)[0]
- // const newCol = Math.round(groupPos.y / 50)
- // const newRow = Math.round(groupPos.x / 50)
- // const boundedCol = Math.max(0, Math.min(newCol, Math.floor(860 / 50) - 1))
- // const boundedRow = Math.max(0, Math.min(newRow, Math.floor(1200 / 50) - 1))
- //
- // const newPoint = {
- // ...movedPoint,
- // row: boundedRow,
- // col: boundedCol,
- // x: boundedRow,
- // y: boundedCol,
- // mapId: this.form.mapId,
- // mapType: this.form.mapType,
- // }
- //
- // positions.push(newPoint)
- //
- // if (!this.leftPoints.some(p => p.entityName === movedPoint.entityName)) {
- // this.leftPoints.push(movedPoint)
- // }
- // this.bindingPointIds.push(movedPoint.entityId)
- // this.unbindPointIds = this.unbindPointIds.filter(id => id !== movedPoint.entityId)
- //
- // // ✅ 判断 row/col/x/y 不为 0 再 push
- // if (!(newPoint.row == 0 && newPoint.col == 0 && newPoint.x == 0 && newPoint.y == 0)) {
- // if (!this.movePoints) this.movePoints = []
- // const existIdx = this.movePoints.findIndex(p => p.pointId === newPoint.pointId)
- // if (existIdx !== -1) {
- // this.movePoints.splice(existIdx, 1, newPoint)
- // } else {
- // this.movePoints.push(newPoint)
- // }
- // }
- // }
- // }
- //
- // // 清理无效数据
- // this.rightPoints = (this.rightPoints || []).filter(Boolean)
- // this.leftPoints = (this.leftPoints || []).filter(Boolean)
- //
- // this.value = JSON.stringify(positions, null, 4)
- // this.layer.draw()
- //
- // console.log('Updated positions:', positions)
- // console.log('MovePoints:', this.movePoints)
- // })
- // 添加绿灯或红灯闪烁动画
- this.addBlinkAnimation(light, isRed,isGrey);
- }
- })
- },
- // 全局控制闪烁频率同步函数
- startGlobalBlinkTimer() {
- if (this.globalBlinkTimer) return; // 已经启动了
- this.globalBlinkTimer = setInterval(() => {
- const currentSecond = Math.floor(Date.now() / 200) % 2;
- const isOn = currentSecond === 1;
- this.blinkLights.forEach(light => {
- light.opacity(isOn ? 1 : 0.6);
- light.scale({ x: isOn ? 1 : 1.1, y: isOn ? 1 : 1.1 });
- });
- if (this.blinkLights.length > 0) {
- this.blinkLights[0].getLayer().batchDraw(); // 统一刷新一次就行
- }
- }, 50);
- },
- // 绿灯动画
- addBlinkAnimation(light, isRed, isGrey) {
- if (!isGrey&&!isRed) {
- if (!this.blinkLights.includes(light)) {
- this.blinkLights.push(light);
- }
- this.startGlobalBlinkTimer();
- }
- },
- // 左侧的列表 现在左侧列表通过地图点位接口获取pointList里直接有左侧的数据 不用再去隔离点管理接口拿数据
- 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 = 0
- point.col = 0
- }
- // 渲染该点
- 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: 1100,
- 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)
- console.log('removePointFromJson', updatedData)
- },
- // 更新 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,
- x: newRow,
- y: newCol,
- pointId: point.pointId,
- pointName: point.pointName,
- entityId: point.pointId,
- entityName: 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,
- mapId: this.form.mapId,
- mapType: this.form.mapType,
- mapName:'你好5'
- }
- 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);
- const updatedPositionCopy = JSON.parse(JSON.stringify(updatedPosition))
- positions[index] = updatedPositionCopy
- console.log(updatedPositionCopy, positions[index], 'updatedPosition-1')
- 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: 1100,
- 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,
- entityId: point.entityId,
- entityName: point.entityName,
- 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,
- mapId: point.mapId,
- mapName:'你好6',
- mapType: point.mapType,
- }
- // 解析 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('进入右侧盒子区域')
- // 更新 point 对象的 col 和 row 值
- point.row = col
- point.col = row
- point.x = col
- point.y = row
- // 如果之前已在右侧区域,需要移除值,并更新绑定点ID
- const index = valueArray.findIndex(
- (item) => item.pointId === point.pointId
- )
- if (index !== -1) {
- valueArray.splice(index, 1) // 从 valueArray 中删除该点
- }
- this.value = JSON.stringify(valueArray, null, 4)
- // 删除绑定点
- this.bindingPointIds = this.bindingPointIds.filter(
- (id) => id !== point.pointId
- )
- // 将该点加入解绑点ID
- this.unbindPointIds.push(point.pointId)
- // 将点重新添加到 rightPoints
- this.rightPoints.push(point)
- }
- // 这里的if判断是为了 移动在物资柜内部才做的操作 现在我只要离开右侧 就做这个操作
- // if (
- // snappedX >= cabinetBounds.x &&
- // snappedX <= cabinetBounds.x + cabinetBounds.width &&
- // snappedY >= cabinetBounds.y &&
- // snappedY <= cabinetBounds.y + cabinetBounds.height
- // )
- else if (snappedX < rightBoxBounds.x ||
- snappedX > rightBoxBounds.x + rightBoxBounds.width ||
- snappedY < rightBoxBounds.y ||
- snappedY > rightBoxBounds.y + rightBoxBounds.height
- ) {
- // 进入物资柜区域
- console.log('进入物资柜区域')
- // 更新 point 对象的 col 和 row 值
- point.row = col
- point.col = row
- point.x = col
- point.y = row
- // 检查点是否已经存在于 valueArray 中
- const index = valueArray.findIndex(
- (item) => item.pointId === point.pointId
- )
- if (index === -1) {
- // 如果点位不存在,则新增
- valueArray.push(updatedPointData)
- this.value = JSON.stringify(valueArray, null, 4)
- }
- // 添加到绑定点ID数组
- this.bindingPointIds.push(point.pointId)
- // 从右侧盒子移除点
- this.rightPoints = this.rightPoints.filter(
- (item) => item.pointId !== point.pointId
- )
- this.leftPoints.push(point)
- console.log(point, '进入左侧区域进行隔离点绑定操作!')
- } else {
- // 未进入任何目标区域,保持原状态
- console.log('未进入目标区域,保持原状态')
- // 更新 point 对象的 col 和 row 值
- point.row = col
- point.col = row
- point.x = col
- point.y = row
- // 如果点不在目标区域,从 valueArray 中移除
- // this.value = JSON.stringify(
- // valueArray.filter((item) => item.pointId !== point.pointId),
- // null,
- // 4
- // );
- // 检查点是否已经存在于 valueArray 中
- const index = valueArray.findIndex(
- (item) => item.pointId === point.pointId
- )
- if (index === -1) {
- // 如果点位不存在,则新增
- valueArray.push(updatedPointData)
- this.value = JSON.stringify(valueArray, null, 4)
- }
- // 添加到绑定点ID数组
- this.bindingPointIds.push(point.pointId)
- // 从右侧盒子移除点
- this.rightPoints = this.rightPoints.filter(
- (item) => item.pointId !== point.pointId
- )
- // 如果点不在目标区域,重新添加到 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-start;
- margin-bottom: 20px;
- }
- </style>
|