index.vue 11 KB

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