index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. <template>
  2. <div id="container" ref="container"></div>
  3. </template>
  4. <script>
  5. import Konva from 'konva'
  6. import {
  7. selectIsIsolationPointById,
  8. getIsIsolationPointPage
  9. } from '@/api/mes/spm/segregationPoint'
  10. import { mapGetters } from 'vuex'
  11. export default {
  12. name: 'KonvaExample',
  13. props: {
  14. points: {
  15. type: Object,
  16. default: null
  17. }
  18. },
  19. data() {
  20. return {
  21. stage: null,
  22. layer: null,
  23. selectedStates: [], // 用于存储每个元素的选中状态
  24. selectedText: [], // 用于存储未选中的元素文本
  25. rects: [], //白色rect合集
  26. texts: [], //白色text合集
  27. redrects: [], //红色rect合集
  28. redtexts: [] //白色text合集
  29. }
  30. },
  31. watch: {
  32. 'getMapData': {
  33. handler(newval) {
  34. if (newval) {
  35. this.$nextTick(()=>{
  36. this.initKonva()
  37. })
  38. }
  39. }
  40. }
  41. },
  42. mounted() {
  43. this.initKonva()
  44. console.log(this.points, 'points')
  45. console.log(this.getMapData, 'Mapdata')
  46. console.log(
  47. this.getSelectSopPoints,
  48. this.getSopEdit,
  49. this.getSopLook,
  50. 'getSopEdit - getSelectSopPoints'
  51. )
  52. },
  53. computed: {
  54. ...mapGetters('sopSelectPoints', [
  55. 'getSelectSopPoints',
  56. 'getSopEdit',
  57. 'getSopLook',
  58. 'getMapData'
  59. ])
  60. },
  61. methods: {
  62. initKonva() {
  63. // 创建舞台
  64. this.stage = new Konva.Stage({
  65. container: this.$refs.container, // 容器元素
  66. width: 1270,
  67. height: 830
  68. })
  69. // 创建图层
  70. this.layer = new Konva.Layer()
  71. // 创建底图
  72. const bgImage = new Image()
  73. bgImage.src = require('@/assets/images/table.png')
  74. bgImage.onload = () => {
  75. const knovaImage = new Konva.Image({
  76. x: 330,
  77. y: 10,
  78. image: bgImage,
  79. width: 500,
  80. height: 790,
  81. draggable: false
  82. })
  83. this.layer.add(knovaImage)
  84. this.layer.draw()
  85. }
  86. // 绘制无限网格
  87. this.drawGrid(50, 50, '#e0e0e0') // 每个单元格50x50,浅灰色网格
  88. // 渲染数据
  89. const imageSrc = require('@/assets/images/localSetIcon.jpg') // 图片路径
  90. this.renderGrid(imageSrc, 6, 3, 450, 100, 120, 100, 50, 50, 60, 25)
  91. // 将图层添加到舞台
  92. this.stage.add(this.layer)
  93. this.layer.draw()
  94. // 禁止舞台拖拽
  95. this.stage.draggable(false)
  96. },
  97. // 绘制无限网格
  98. drawGrid(cellWidth, cellHeight, gridColor) {
  99. const width = 1270
  100. const height = 830
  101. // 绘制竖线
  102. for (let i = 0; i <= width; i += cellWidth) {
  103. const verticalLine = new Konva.Line({
  104. points: [i, 0, i, height],
  105. stroke: gridColor,
  106. strokeWidth: 1
  107. })
  108. this.layer.add(verticalLine)
  109. }
  110. // 绘制横线
  111. for (let j = 0; j <= height; j += cellHeight) {
  112. const horizontalLine = new Konva.Line({
  113. points: [0, j, width, j],
  114. stroke: gridColor,
  115. strokeWidth: 1
  116. })
  117. this.layer.add(horizontalLine)
  118. }
  119. this.layer.draw()
  120. },
  121. renderGrid(imageSrc) {
  122. this.selectedStates = {} // 用对象来存储选中状态,键为文字内容
  123. this.rects = {}
  124. this.texts = {}
  125. this.redrects = {}
  126. this.redtexts = {}
  127. this.selectedText = []
  128. // const positions = JSON.parse(this.points.map);
  129. const positions = this.getMapData
  130. console.log(positions, 'positions')
  131. // 检查 this.getSelectSopPoints 是否有内容
  132. const isLocked = this.getSelectSopPoints.length > 0
  133. // 添加或移除全局点击事件监听器 this.getSopEdit这是vuex里判断是否可以选择隔离点的操作
  134. if (isLocked && this.getSopEdit == true) {
  135. this.layer.on('click', (e) => {
  136. e.cancelBubble = true // 阻止事件冒泡
  137. // e.stopPropagation(); // 阻止事件传播
  138. })
  139. } else {
  140. this.layer.off('click') // 移除全局点击事件监听器
  141. }
  142. positions.forEach((pos, index) => {
  143. const x = pos.col * 50 // 每个单元格宽度为50
  144. const y = pos.row * 50 // 每个单元格高度为50
  145. const labelText = pos.pointName // 对应的文字
  146. const point = new Image()
  147. point.src = pos.pointIcon
  148. // point.src = imageSrc;
  149. point.onload = () => {
  150. const knovaImage = new Konva.Image({
  151. x: x,
  152. y: y,
  153. image: point,
  154. width: 50,
  155. height: 50,
  156. draggable: false
  157. })
  158. // 添加点击事件,仅当 getSopEdit 为 true 时才允许点击a
  159. if (this.getSopEdit == true && this.getSopLook == false) {
  160. knovaImage.on('click', () => {
  161. // 切换选中状态,基于文本内容
  162. this.selectedStates[labelText] = !this.selectedStates[labelText]
  163. if (this.selectedStates[labelText]) {
  164. // 选中状态,显示红色矩形和文字,切换为选中的图片
  165. this.rects[labelText].visible(false)
  166. this.texts[labelText].visible(false)
  167. this.redrects[labelText].visible(true)
  168. this.redtexts[labelText].visible(true)
  169. const selectedImage = new Image()
  170. selectedImage.src = require('@/assets/images/localSetSelect.jpg')
  171. selectedImage.onload = () => {
  172. knovaImage.image(selectedImage) // 更新图像
  173. this.layer.draw() // 更新图层
  174. }
  175. // 获取隔离点信息,并将选中的 labelText 推入数组
  176. this.$nextTick(() => {
  177. if (
  178. this.$route.query.sopId !== null ||
  179. this.$route.query.ticketId !== null
  180. ) {
  181. this.selectedText.push({
  182. pointName: pos.pointName,
  183. pointId: pos.pointId,
  184. pointType: pos.pointTypeName,
  185. powerType: pos.powerTypeName
  186. })
  187. this.$emit('selection-changed', this.selectedText)
  188. // selectIsIsolationPointById(pos.pointId).then((res) => {
  189. // this.selectedText.push({
  190. // pointName: res.data.pointName,
  191. // pointId: res.data.pointId,
  192. // pointType: res.data.pointType,
  193. // powerType: res.data.powerType,
  194. // });
  195. // console.log(this.selectedText, "$emit");
  196. // this.$emit("selection-changed", this.selectedText);
  197. // });
  198. }
  199. })
  200. } else {
  201. // 取消选中状态,恢复普通矩形和文字,切换为未选中的图片
  202. this.rects[labelText].visible(true)
  203. this.texts[labelText].visible(true)
  204. this.redrects[labelText].visible(false)
  205. this.redtexts[labelText].visible(false)
  206. const normalImage = new Image()
  207. normalImage.src = pos.pointIcon
  208. // normalImage.src = imageSrc; // 未选中的默认图片路径
  209. normalImage.onload = () => {
  210. knovaImage.image(normalImage) // 更新图像
  211. this.layer.draw() // 更新图层
  212. }
  213. // 从选中数组中移除该项
  214. this.selectedText = this.selectedText.filter(
  215. (item) => item.pointName !== labelText
  216. )
  217. }
  218. // 确保图层重新渲染
  219. this.layer.draw()
  220. this.$emit('selection-changed', this.selectedText)
  221. })
  222. }
  223. this.layer.add(knovaImage)
  224. // 普通矩形
  225. const rect = new Konva.Rect({
  226. x: x - 3,
  227. y: y + 55,
  228. width: 60,
  229. height: 25,
  230. cornerRadius: 10,
  231. stroke: 'red',
  232. strokeWidth: 2,
  233. fill: 'white'
  234. })
  235. this.layer.add(rect)
  236. this.rects[labelText] = rect // 用文字作为键存储
  237. // 普通文字
  238. const text = new Konva.Text({
  239. x: x + 12,
  240. y: y + 60,
  241. fontSize: 20,
  242. text: labelText,
  243. fontFamily: 'Calibri',
  244. fill: 'red'
  245. })
  246. this.layer.add(text)
  247. this.texts[labelText] = text // 用文字作为键存储
  248. // 红色矩形(初始隐藏)
  249. const redrect = new Konva.Rect({
  250. x: x - 3,
  251. y: y + 55,
  252. width: 60,
  253. height: 25,
  254. cornerRadius: 10,
  255. stroke: 'red',
  256. strokeWidth: 2,
  257. fill: 'red',
  258. visible: false
  259. })
  260. this.layer.add(redrect)
  261. this.redrects[labelText] = redrect // 用文字作为键存储
  262. // 红色文字(初始隐藏)
  263. const redtext = new Konva.Text({
  264. x: x + 12,
  265. y: y + 60,
  266. fontSize: 20,
  267. text: labelText,
  268. fontFamily: 'Calibri',
  269. fill: 'white',
  270. visible: false
  271. })
  272. this.layer.add(redtext)
  273. this.redtexts[labelText] = redtext // 用文字作为键存储
  274. // 检查 this.getSelectSopPoints 是否包含当前点的 pointId
  275. if (pos.state) {
  276. // 设置为选中状态
  277. this.selectedStates[labelText] = true
  278. this.rects[labelText].visible(false)
  279. this.texts[labelText].visible(false)
  280. this.redrects[labelText].visible(true)
  281. this.redtexts[labelText].visible(true)
  282. // 切换图片为选中状态的图片
  283. const selectedImage = new Image()
  284. selectedImage.src = require('@/assets/images/localSetSelect.jpg') // 选中的图片路径
  285. selectedImage.onload = () => {
  286. knovaImage.image(selectedImage) // 更新图像
  287. this.layer.draw() // 更新图层
  288. }
  289. // 将选中的 labelText 推入数组
  290. this.selectedText.push({
  291. pointName: pos.pointName,
  292. pointId: pos.pointId,
  293. pointType: pos.pointTypeName,
  294. powerType: pos.powerTypeName
  295. })
  296. } else {
  297. // 设置为未选中状态
  298. this.selectedStates[labelText] = false
  299. this.rects[labelText].visible(true)
  300. this.texts[labelText].visible(true)
  301. this.redrects[labelText].visible(false)
  302. this.redtexts[labelText].visible(false)
  303. }
  304. // 触发父组件的 selection-changed 事件
  305. this.$emit('selection-changed', this.selectedText)
  306. // if (this.getSelectSopPoints.includes(pos.pointId.toString())) {
  307. // // 设置为选中状态
  308. // this.selectedStates[labelText] = true;
  309. // this.rects[labelText].visible(false);
  310. // this.texts[labelText].visible(false);
  311. // this.redrects[labelText].visible(true);
  312. // this.redtexts[labelText].visible(true);
  313. //
  314. // // 切换图片为选中状态的图片
  315. // const selectedImage = new Image();
  316. // selectedImage.src = require("@/assets/images/localSetSelect.jpg"); // 选中的图片路径
  317. // selectedImage.onload = () => {
  318. // knovaImage.image(selectedImage); // 更新图像
  319. // this.layer.draw(); // 更新图层
  320. // };
  321. // // 将选中的 labelText 推入数组
  322. // this.$nextTick(() => {
  323. // getIsIsolationPointPage({ current: 1, size: 100 })
  324. // .then((res) => {
  325. // const allPoints = res.data.records; // 假设返回的数据结构是 { records: [点数据] }
  326. //
  327. // // 根据 pos.pointId 查找对应的 pointType 和 powerType
  328. // const pointInfo = allPoints.find(
  329. // (point) => point.pointId == pos.pointId
  330. // );
  331. //
  332. // if (pointInfo) {
  333. // this.selectedText.push({
  334. // pointName: labelText,
  335. // pointId: pos.pointId,
  336. // pointType: pointInfo.pointType,
  337. // powerType: pointInfo.powerType,
  338. // });
  339. // } else {
  340. // // 如果没有找到对应的点信息,可以处理这种情况
  341. // console.warn(`未找到 pointId 为 ${pos.pointId} 的点信息`);
  342. // this.selectedText.push({
  343. // pointName: labelText,
  344. // pointId: pos.pointId,
  345. // pointType: "",
  346. // powerType: "",
  347. // });
  348. // }
  349. // // console.log(this.selectedText,'默认拿到的points')
  350. // // 触发父组件的 selection-changed 事件
  351. // this.$emit("selection-changed", this.selectedText);
  352. // })
  353. // .catch((error) => {
  354. // console.error("获取隔离点信息失败", error);
  355. // });
  356. // });
  357. // }
  358. this.layer.draw()
  359. }
  360. })
  361. }
  362. // methods结束
  363. }
  364. }
  365. </script>
  366. <style scoped lang="scss">
  367. #container {
  368. width: 100%;
  369. height: 100%;
  370. }
  371. </style>