RightClickMenu.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <div class="right-click-menu">
  3. <div
  4. v-if="visible"
  5. ref="RightMenuBody"
  6. v-clickoutside="close"
  7. class="right-menu-body"
  8. :style="styles"
  9. >
  10. <ul v-if="isClickSide">
  11. <li @click="toEdit">
  12. <i class="el-icon-edit-outline"></i>
  13. 编辑元素
  14. </li>
  15. <li class="li-danger" @click="toDelete">
  16. <i class="el-icon-delete"></i>
  17. 删除元素
  18. </li>
  19. </ul>
  20. <ul v-else>
  21. <li @click="toEdit">
  22. <i class="el-icon-edit-outline"></i>
  23. {{ IS_CONTAINER_ELEMENT ? "编辑元素" : "编辑编辑框" }}
  24. </li>
  25. <li class="li-danger" @click="toDelete">
  26. <i class="el-icon-delete"></i>
  27. {{ IS_CONTAINER_ELEMENT ? "删除元素" : "删除编辑框" }}
  28. </li>
  29. <li v-if="IS_CONTAINER_ELEMENT" @click="toCopyElementChild">
  30. <i class="el-icon-copy-document"></i> 复制元素
  31. </li>
  32. <li v-if="IS_CONTAINER && curCopyElement" @click="toPasteElementChild">
  33. <i class="el-icon-document-copy"></i> 粘贴元素
  34. </li>
  35. </ul>
  36. </div>
  37. </div>
  38. </template>
  39. <script>
  40. import { mapState, mapMutations, mapActions } from "vuex";
  41. import { deepCopy } from "../../card/plugins/utils";
  42. import Clickoutside from "element-ui/src/utils/clickoutside";
  43. import { findElementById } from "../store";
  44. export default {
  45. name: "RightClickMenu",
  46. directives: { Clickoutside },
  47. data() {
  48. return {
  49. visible: false,
  50. curCopyElement: null,
  51. styles: {
  52. position: "fixed",
  53. zIndex: 3000,
  54. },
  55. isClickSide: false,
  56. };
  57. },
  58. computed: {
  59. ...mapState("paper-export", ["curElement", "topics", "curPage"]),
  60. IS_CONTAINER_ELEMENT() {
  61. return !!this.curElement.container;
  62. },
  63. IS_CONTAINER() {
  64. return (
  65. this.curElement.type === "CONTAINER" ||
  66. (this.curElement.container &&
  67. this.curElement.container.type === "CONTAINER")
  68. );
  69. },
  70. },
  71. mounted() {
  72. this.init();
  73. },
  74. beforeDestroy() {
  75. document.oncontextmenu = null;
  76. document.removeEventListener("mouseup", this.docMouseUp);
  77. },
  78. methods: {
  79. ...mapMutations("paper-export", [
  80. "setOpenElementEditDialog",
  81. "setCurElement",
  82. ]),
  83. ...mapActions("paper-export", [
  84. "removeElement",
  85. "removeElementChild",
  86. "removeSideElement",
  87. "pasteElementChild",
  88. "rebuildPages",
  89. ]),
  90. init() {
  91. // 注册自定义右键事件菜单
  92. document.oncontextmenu = function () {
  93. return false;
  94. };
  95. document.addEventListener("mouseup", this.docMouseUp);
  96. },
  97. close() {
  98. this.visible = false;
  99. },
  100. show() {
  101. this.visible = true;
  102. },
  103. docMouseUp(e) {
  104. if (e.button === 2) {
  105. this.rightClick(e);
  106. }
  107. },
  108. rightClick(e) {
  109. const id = this.getRelateElementId(e.target);
  110. if (!id) return;
  111. let curElement = findElementById(id, this.topics);
  112. if (!curElement) {
  113. curElement = this.curPage.sides.find((item) => item.id === id);
  114. if (curElement) {
  115. this.setCurElement(curElement);
  116. this.isClickSide = true;
  117. } else {
  118. this.isClickSide = false;
  119. return;
  120. }
  121. } else {
  122. this.isClickSide = false;
  123. }
  124. this.show();
  125. this.$nextTick(() => {
  126. const { x: clickLeft, y: clickTop } = e;
  127. const { offsetWidth: menuWidth, offsetHeight: menuHeight } =
  128. this.$refs.RightMenuBody;
  129. const { innerWidth: wWidth, innerHeight: wHeight } = window;
  130. let menuLeft = clickLeft,
  131. menuTop = clickTop;
  132. if (menuWidth + clickLeft > wWidth) {
  133. menuLeft = clickLeft - menuWidth;
  134. }
  135. if (menuHeight + clickTop > wHeight) {
  136. menuTop = clickTop - menuHeight;
  137. }
  138. this.styles = Object.assign({}, this.styles, {
  139. top: menuTop + "px",
  140. left: menuLeft + "px",
  141. });
  142. });
  143. },
  144. getRelateElementId(dom) {
  145. let parentNode = dom;
  146. while (
  147. !(
  148. (parentNode["id"] && parentNode["id"].includes("element-")) ||
  149. parentNode.className.includes("page-column-body") ||
  150. parentNode.className.includes("paper-template-design")
  151. )
  152. ) {
  153. parentNode = parentNode.parentNode;
  154. }
  155. const elementType = parentNode.getAttribute("data-type");
  156. return parentNode["id"] && elementType ? parentNode["id"] : null;
  157. },
  158. toEdit() {
  159. this.curElement._edit = true;
  160. this.curElement._side = this.isClickSide;
  161. this.close();
  162. this.setOpenElementEditDialog(true);
  163. },
  164. toDelete() {
  165. this.close();
  166. this.$confirm("确定要删除当前元素吗?", "提示", {
  167. type: "warning",
  168. })
  169. .then(() => {
  170. this.removeSelectElement();
  171. })
  172. .catch(() => {});
  173. },
  174. removeSelectElement() {
  175. if (this.isClickSide) {
  176. this.removeSideElement(this.curElement);
  177. return;
  178. }
  179. if (this.curElement["container"]) {
  180. this.removeElementChild(this.curElement);
  181. } else {
  182. this.removeElement(this.curElement);
  183. }
  184. this.toRebuildPages();
  185. },
  186. toCopyElementChild() {
  187. this.close();
  188. this.curCopyElement = deepCopy(this.curElement);
  189. },
  190. toPasteElementChild() {
  191. this.close();
  192. const id = this.curElement.container
  193. ? this.curElement.container.id
  194. : this.curElement.id;
  195. const pasteElement =
  196. this.curCopyElement.container.id === id
  197. ? Object.assign({}, this.curCopyElement, {
  198. y: this.curCopyElement.y + 20,
  199. })
  200. : this.curCopyElement;
  201. this.pasteElementChild({
  202. curElement: this.curElement,
  203. pasteElement,
  204. });
  205. this.toRebuildPages();
  206. },
  207. toRebuildPages() {
  208. this.$nextTick(() => {
  209. this.rebuildPages();
  210. });
  211. },
  212. },
  213. };
  214. </script>