ElemExplainEdit.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <template>
  2. <div class="elem-explain elem-explain-edit">
  3. <div class="elem-title" v-if="data.showTitle" ref="ElemTitle">
  4. {{ data.parent.topicName }}
  5. </div>
  6. <div class="elem-body" :style="bodyStyle">
  7. <div
  8. class="elem-explain-no"
  9. v-if="data.parent.questionsCount > 1 && !data.isExtend"
  10. >
  11. {{ data.serialNumber }}、
  12. </div>
  13. <!-- 解答题子元件编辑区域 -->
  14. <div
  15. class="elem-explain-elements"
  16. @drop.prevent="dropInnerElement($event)"
  17. @dragover.prevent
  18. @dragleave.prevent
  19. >
  20. <elem-explain-element-edit
  21. v-for="element in data.elements"
  22. :key="element.id"
  23. :data="element"
  24. :transform-fit="rebuildGuides"
  25. @resize-over="elementResizeOver"
  26. ></elem-explain-element-edit>
  27. <!-- guide-lines -->
  28. <div class="element-guide-lines">
  29. <div
  30. class="guide-line guide-line-x"
  31. v-for="line in xLines"
  32. :key="`x-${line.top}`"
  33. :style="line"
  34. ></div>
  35. <div
  36. class="guide-line guide-line-y"
  37. v-for="line in yLines"
  38. :key="`y-${line.left}`"
  39. :style="line"
  40. ></div>
  41. </div>
  42. </div>
  43. </div>
  44. </div>
  45. </template>
  46. <script>
  47. import { mapState, mapMutations, mapActions } from "vuex";
  48. import ElemExplainElementEdit from "./ElemExplainElementEdit";
  49. import guideLinesMixins from "../../mixins/guideLines";
  50. export default {
  51. name: "elem-explain-edit",
  52. components: { ElemExplainElementEdit },
  53. mixins: [guideLinesMixins],
  54. props: {
  55. data: {
  56. type: Object
  57. }
  58. },
  59. data() {
  60. return {
  61. bodyStyle: {}
  62. };
  63. },
  64. computed: {
  65. ...mapState("card", ["curDragElement"])
  66. },
  67. watch: {
  68. "data.parent": {
  69. handler() {
  70. this.modifyBodyStyle();
  71. }
  72. }
  73. },
  74. mounted() {
  75. this.modifyBodyStyle();
  76. },
  77. methods: {
  78. ...mapMutations("card", ["setCurDragElement", "setCurElement"]),
  79. ...mapActions("card", ["rebuildPages", "modifyElementChild"]),
  80. modifyBodyStyle() {
  81. this.$nextTick(() => {
  82. let height = this.data.h;
  83. if (this.data.showTitle) {
  84. height = this.data.h - this.$refs.ElemTitle.clientHeight;
  85. }
  86. this.bodyStyle = {
  87. height: height + "px"
  88. };
  89. });
  90. },
  91. dropInnerElement(e) {
  92. let { layerX: x, layerY: y } = e;
  93. const { offsetLeft, offsetTop } = this.getOffsetInfo(e.target);
  94. // 解答题的子元素中会新增container字段
  95. const curElement = {
  96. ...this.curDragElement,
  97. x: x + offsetLeft,
  98. y: y + offsetTop,
  99. container: {
  100. id: this.data.id,
  101. type: this.data.type
  102. }
  103. };
  104. this.elementResizeOver(curElement);
  105. this.setCurDragElement({});
  106. this.setCurElement(curElement);
  107. },
  108. getOffsetInfo(dom, endParent = "elem-explain-elements") {
  109. let parentNode = dom;
  110. let offsetTop = 0,
  111. offsetLeft = 0;
  112. while (!parentNode.className.includes(endParent)) {
  113. offsetTop += parentNode.offsetTop;
  114. offsetLeft += parentNode.offsetLeft;
  115. parentNode = parentNode.offsetParent;
  116. }
  117. return {
  118. offsetLeft,
  119. offsetTop
  120. };
  121. },
  122. elementResizeOver(element) {
  123. this.clear();
  124. this.modifyElementChild(element);
  125. this.$nextTick(() => {
  126. this.rebuildPages();
  127. });
  128. },
  129. rebuildGuides(element, actionType) {
  130. return this.rebuild(this.data.elements, element, actionType);
  131. }
  132. }
  133. };
  134. </script>