| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- <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 { getLotoMapInfo, getLotoInfo, updateLoto } from '@/api/mes/lotoStation/lotoStation'
- import { getTechnologyInfo, saveMachineryPoints } from '@/api/system/machinery'
- export default {
- name: 'KonvaExample',
- props: {
- machineryId: {
- type: String,
- default: ''
- }
- },
- data() {
- return {
- stage: null,
- layer: null,
- selectedStates: [], // 用于存储每个元素的选中状态
- selectedText: [], // 用于存储未选中的元素文本
- rects: [], // 白色r ect合集
- texts: [], // 白色text合集
- redrects: [], // 红色rect合集
- redtexts: [], // 白色text合集
- value: '',
- form: {},//拿到单个数据
- orignData: null,//原始数据
- pointIdList: [],//选中的隔离点
- selectPoints: []//回显之前选中的隔离点
- }
- },
- mounted() {
- this.$nextTick(() => {
- this.getLoToInfo()
- })
- },
- methods: {
- goBack() {
- this.$router.push('/technology/technologyList')
- },
- close() {
- this.$router.push('/technology/technologyList')
- },
- getLoToInfo() {
- const machineryId = this.machineryId
- getTechnologyInfo(machineryId).then((response) => {
- const lotoId = response.data.lotoId
- const sopId = ''
- const ticketId = ''
- getLotoInfo(lotoId).then((response) => {
- console.log(response, '电柜信息')
- this.form = response.data
- })
- getLotoMapInfo(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
- } catch (err) {
- }
- }
- this.initKonva()
- })
- })
- // 设备工艺详情
- getTechnologyInfo(this.$route.query.machineryId).then(response => {
- console.log(response, '设备/工艺详情')
- this.selectPoints = response.data.pointIdList
- })
- },
- // 重置
- 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.layer = new Konva.Layer()
- // 创建底图
- 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)
- this.layer.draw()
- }
- // 绘制无限网格
- this.drawGrid(50, 50, '#e0e0e0') // 每个单元格50x50,浅灰色网格
- // 渲染数据
- 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)
- }
- this.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)
- 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 = () => {
- 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.pointId) // 移除ID
- } else {
- // 如果当前未选中,则选中
- this.redrects[labelText].visible(true)
- this.redtexts[labelText].visible(true)
- this.pointIdList.push(pos.pointId) // 添加ID
- }
- this.layer.batchDraw() // 更新图层显示
- })
- // 底部白色背景
- const bgrect = new Konva.Rect({
- x: x - 6,
- y: y - 5,
- width: 62,
- height: 80,
- cornerRadius: 5,
- stroke: 'white',
- strokeWidth: 2,
- fill: 'white'
- })
- this.layer.add(bgrect)
- this.bgrects[labelText] = bgrect // 用文字作为键存储
- // 普通矩形
- const rect = new Konva.Rect({
- x: x + 0,
- y: y - 1,
- width: 50,
- height: 72,
- 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: 20,
- text: labelText,
- fontFamily: 'Calibri',
- fill: 'red'
- })
- this.layer.add(text)
- this.texts[labelText] = text // 用文字作为键存储
- // 覆盖层(表示选中状态)
- const redrect = new Konva.Rect({
- x: x - 7,
- y: y - 6,
- width: 64.1,
- height: 82,
- 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 - 5 + 42 / 2, // 水平居中
- y: y + 62 / 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.pointId)) {
- // 设置选中状态
- this.redrects[labelText].visible(true)
- this.redtexts[labelText].visible(true)
- this.pointIdList.push(pos.pointId) // 添加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>
|