| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- <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>
- <!-- <span-->
- <!-- style="-->
- <!-- float: right;-->
- <!-- padding: 1px 0;-->
- <!-- font-size: 22px;-->
- <!-- cursor: pointer;-->
- <!-- "-->
- <!-- type="text"-->
- <!-- @click="goBack"-->
- <!-- >×</span-->
- <!-- >-->
- </div>
- <div style="height: 100%;padding-bottom:10px">
- <el-input v-model="value" type="textarea" :rows="26" disabled></el-input>
- </div>
- <div class="bottombtn" style="width:100%;height: 35px;padding: 10px 0 0">
- <el-button v-no-more-click @click="save" type="primary" icon="el-icon-edit"
- style="float: left; height: 33px; line-height: 2px"
- >保存
- </el-button>
- <!-- <el-button v-no-more-click @click="close" type="primary" icon="el-icon-close"-->
- <!-- style="float: left; height: 33px; line-height: 2px;"-->
- <!-- >关闭-->
- <!-- </el-button>-->
- <!-- <el-button v-no-more-click @click="reset" type="primary" icon="el-icon-refresh"-->
- <!-- style="float: left; height: 33px; line-height: 2px;"-->
- <!-- >重置-->
- <!-- </el-button>-->
- <!-- <el-button v-no-more-click @click="view" type="primary" icon="el-icon-view"-->
- <!-- style="float: left; height: 33px; line-height: 2px"-->
- <!-- >预览-->
- <!-- </el-button>-->
- </div>
- </el-card>
- </div>
- </div>
- </template>
- <script>
- import Konva from 'konva'
- import { selectLotoMapById, selectIsLotoStationById, updateLoto } from '@/api/mes/lotoStation/lotoStation'
- import { getTechnologyInfo, saveMachineryPoints } from '@/api/system/machinery'
- import { selectIsMapById } from '@/api/system/mapconfig'
- export default {
- name: 'KonvaExample',
- props: {
- machineryId: {
- type: String,
- default: ''
- }
- },
- data() {
- return {
- stage: null,
- layer: null,
- backgroundLayer:null,//背景图层
- gridLayer:null,//网格图层
- selectedStates: [], // 用于存储每个元素的选中状态
- selectedText: [], // 用于存储未选中的元素文本
- rects: [], // 白色r ect合集
- texts: [], // 白色text合集
- redrects: [], // 红色rect合集
- redtexts: [], // 白色text合集
- value: '',
- form: {},//拿到单个数据
- orignData: null,//原始数据
- pointIdList: [],//选中的隔离点
- selectPoints: [],//回显之前选中的隔离点
- imageUrl: '',//获取底图
- width: '',//底图宽
- height: '',//底图高
- x: '',//底图横坐标
- y: '',//底图纵坐标
- pointList:null,//接口给的点位信息
- }
- },
- mounted() {
- this.$nextTick(() => {
- this.selectIsLotoStationById()
- })
- },
- methods: {
- goBack() {
- this.$router.push('/technology/technologyList')
- },
- close() {
- this.$router.push('/technology/technologyList')
- },
- selectIsLotoStationById() {
- const machineryId = this.machineryId
- getTechnologyInfo(machineryId).then((response) => {
- const lotoId = response.data.lotoId
- const sopId = ''
- const ticketId = ''
- selectLotoMapById(lotoId, sopId, ticketId).then(response => {
- console.log(response, '电柜预览接口调用')
- this.form.map = response.data
- if (response.data) {
- try {
- this.value = JSON.stringify(response.data, null, 4)
- this.orignData = this.value
- this.initKonva()
- } catch (err) {
- }
- }
- })
- selectIsLotoStationById(lotoId).then((response) => {
- console.log(response, '电柜信息')
- this.form = response.data
- // 获取不同底图 如地图或者柜子
- selectIsMapById(response.data.mapId).then((response) => {
- console.log(response, '获取底图')
- 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
- this.initKonva()
- })
- })
- })
- // 设备工艺详情
- getTechnologyInfo(this.$route.query.machineryId).then(response => {
- console.log(response, '设备/工艺详情')
- this.selectPoints = response.data.pointIdList
- this.initKonva()
- })
- },
- // 重置
- reset() {
- this.value = this.orignData
- this.initKonva() // 重新初始化 Konva
- },
- // 预览
- view() {
- if (this.isJson(this.value)) {
- this.form.map = this.value
- this.initKonva()
- } else {
- this.$message({
- type: 'error',
- message: '地图数据格式不正确,请输入有效的 JSON 格式!'
- })
- }
- },
- save() {
- this.$confirm('请确认是否保存修改内容', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- // 校验 this.value 是否为有效的 JSON
- if (this.isJson(this.value)) {
- const machineryId = this.$route.query.machineryId
- const formData = {
- machineryId: machineryId,
- pointIdList: this.pointIdList
- }
- console.log(this.form, formData, 'map')
- saveMachineryPoints(formData).then(response => {
- console.log(response, '修改设备/工艺地图')
- // this.$router.push('/technology/technologyList')
- this.$message({
- type: 'success',
- message: '保存成功!'
- })
- })
- } 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: 1200,
- height: 860
- });
- // 创建网格图层(最底层)
- this.gridLayer = new Konva.Layer();
- this.stage.add(this.gridLayer);
- // 先绘制网格(不变)
- this.drawGrid(50, 50, '#e0e0e0', this.gridLayer);
- // 创建底图图层(第二层)
- this.backgroundLayer = new Konva.Layer();
- this.stage.add(this.backgroundLayer);
- // 加载底图
- const bgImage = new Image();
- bgImage.src = this.imageUrl;
- bgImage.onload = () => {
- const konvaImage = new Konva.Image({
- x: this.x || 0,
- y: this.y || 0,
- image: bgImage,
- width: this.width || 1200,
- height: this.height || 860,
- draggable: false
- });
- // 添加底图到底图图层
- this.backgroundLayer.add(konvaImage);
- this.backgroundLayer.draw();
- };
- // 创建主图层(第三层)用于存放隔离点
- this.layer = new Konva.Layer();
- this.stage.add(this.layer);
- // 渲染隔离点等数据
- const imageSrc = require('@/assets/images/localSetIcon.jpg'); // 图片路径
- this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25);
- this.layer.draw();
- // 禁止舞台拖拽
- this.stage.draggable(false);
- },
- // 绘制无限网格
- drawGrid(cellWidth, cellHeight, gridColor, layer) {
- 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
- });
- 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
- });
- layer.add(horizontalLine);
- }
- layer.draw();
- },
- renderGrid(imageSrc) {
- this.selectedStates = [] // 用数组来存储选中状态
- this.rects = {}
- this.texts = {}
- this.bgrects = {}
- this.redrects = {}
- this.redtexts = {}
- this.selectedText = []
- this.pointIdList = [] // 初始化选中的点ID列表
- // const positions = JSON.parse(this.value)
- const positions=this.pointList
- positions.forEach((pos, index) => {
- const x = pos.x * 50 // 每个单元格宽度为50
- const y = pos.y * 50 // 每个单元格高度为50
- const labelText = pos.entityName // 对应的文字
- const point = new Image()
- point.src = pos.pointIcon
- point.onload = () => {
- const knovaImage = new Konva.Image({
- x: x,
- y: y,
- image: point,
- width: 50,
- height: 50,
- draggable: false
- })
- // 添加点击事件监听器
- knovaImage.on('click', () => {
- const isCurrentlySelected = this.redrects[labelText].visible()
- if (isCurrentlySelected) {
- // 如果当前已选中,则取消选中
- this.redrects[labelText].visible(false)
- this.redtexts[labelText].visible(false)
- this.pointIdList = this.pointIdList.filter(id => id !== pos.entityId) // 移除ID
- } else {
- // 如果当前未选中,则选中
- this.redrects[labelText].visible(true)
- this.redtexts[labelText].visible(true)
- this.pointIdList.push(pos.entityId) // 添加ID
- }
- this.layer.batchDraw() // 更新图层显示
- })
- // 底部白色背景
- const bgrect = new Konva.Rect({
- x: x - 2,
- y: y - 5,
- width: 50,
- height: 78,
- cornerRadius: 5,
- stroke: 'white',
- strokeWidth: 2,
- fill: 'white'
- })
- this.layer.add(bgrect)
- this.bgrects[labelText] = bgrect // 用文字作为键存储
- // 普通矩形红色边框
- const rect = new Konva.Rect({
- x: x + 1,
- y: y - 1,
- width: 45,
- height: 70,
- cornerRadius: 5,
- stroke: 'red',
- strokeWidth: 2,
- fill: 'white'
- })
- this.layer.add(rect)
- this.rects[labelText] = rect // 用文字作为键存储
- // 先加底部白色 再添加图片
- this.layer.add(knovaImage)
- // 普通文字
- const text = new Konva.Text({
- x: x + 8,
- y: y + 50,
- fontSize: 17,
- text: labelText,
- fontFamily: 'Calibri',
- fill: 'red'
- })
- this.layer.add(text)
- this.texts[labelText] = text // 用文字作为键存储
- // 覆盖层(表示选中状态)
- const redrect = new Konva.Rect({
- x: x - 3,
- y: y - 6,
- width: 51,
- height: 80,
- cornerRadius: 5,
- fill: 'rgba(97, 97, 97, 0.5)', // 半透明灰色
- visible: false, // 初始状态隐藏
- listening: false
- })
- this.layer.add(redrect)
- this.redrects[labelText] = redrect // 用文字作为键存储
- // 创建对号文本
- const redtext = new Konva.Text({
- x: x - 8 + 42 / 2, // 水平居中
- y: y + 50 / 2, // 垂直居中
- fontSize: 24, // 根据需要调整字体大小
- text: '✔',
- fontFamily: 'Arial',
- fill: 'white',
- align: 'center',
- verticalAlign: 'middle',
- visible: false, // 初始隐藏状态
- listening: false
- })
- this.layer.add(redtext)
- this.redtexts[labelText] = redtext // 用文字作为键存储
- // 检查 selectPoints 是否存在并且不为空
- if (Array.isArray(this.selectPoints) && this.selectPoints.length > 0) {
- if (this.selectPoints.includes(pos.entityId)) {
- // 设置选中状态
- this.redrects[labelText].visible(true)
- this.redtexts[labelText].visible(true)
- this.pointIdList.push(pos.entityId) // 添加ID
- }
- }
- this.layer.draw()
- }
- })
- }
- }
- }
- </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;
- }
- </style>
|