ElemExplainEdit.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <template>
  2. <div class="elem-explain elem-explain-edit">
  3. <div v-if="data.showTitle" ref="ElemTitle" class="elem-title">
  4. {{ data.parent.topicName }}
  5. </div>
  6. <div class="elem-body" :style="bodyStyle">
  7. <div
  8. v-if="data.parent.questionsCount > 1 && !data.isExtend"
  9. class="elem-explain-no"
  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. v-for="line in xLines"
  31. :key="`x-${line.top}`"
  32. class="guide-line guide-line-x"
  33. :style="line"
  34. ></div>
  35. <div
  36. v-for="line in yLines"
  37. :key="`y-${line.left}`"
  38. class="guide-line guide-line-y"
  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: "ElemExplainEdit",
  52. components: { ElemExplainElementEdit },
  53. mixins: [guideLinesMixins],
  54. props: {
  55. data: {
  56. type: Object,
  57. default() {
  58. return {};
  59. },
  60. },
  61. },
  62. data() {
  63. return {
  64. bodyStyle: {},
  65. };
  66. },
  67. computed: {
  68. ...mapState("card", ["curDragElement"]),
  69. },
  70. watch: {
  71. "data.parent": {
  72. handler() {
  73. this.modifyBodyStyle();
  74. },
  75. },
  76. },
  77. mounted() {
  78. this.modifyBodyStyle();
  79. },
  80. methods: {
  81. ...mapMutations("card", ["setCurDragElement", "setCurElement"]),
  82. ...mapActions("card", ["rebuildPages", "modifyElementChild"]),
  83. modifyBodyStyle() {
  84. this.$nextTick(() => {
  85. let height = this.data.h;
  86. if (this.data.showTitle) {
  87. height = this.data.h - this.$refs.ElemTitle.clientHeight;
  88. }
  89. this.bodyStyle = {
  90. height: height + "px",
  91. };
  92. });
  93. },
  94. dropInnerElement(e) {
  95. let { offsetX: x, offsetY: y } = e;
  96. const { offsetLeft, offsetTop } = this.getOffsetInfo(
  97. e.target || e.srcElement
  98. );
  99. // 解答题的子元素中会新增container字段
  100. const curElement = {
  101. ...this.curDragElement,
  102. x: x + offsetLeft,
  103. y: y + offsetTop,
  104. container: {
  105. id: this.data.id,
  106. type: this.data.type,
  107. },
  108. };
  109. this.elementResizeOver(curElement);
  110. this.setCurDragElement({});
  111. this.setCurElement(curElement);
  112. },
  113. getOffsetInfo(dom, endParentClass = "elem-explain-elements") {
  114. let parentNode = dom;
  115. let offsetTop = 0,
  116. offsetLeft = 0;
  117. while (!parentNode.className.includes(endParentClass)) {
  118. offsetTop += parentNode.offsetTop;
  119. offsetLeft += parentNode.offsetLeft;
  120. parentNode = parentNode.offsetParent;
  121. }
  122. return {
  123. offsetLeft,
  124. offsetTop,
  125. };
  126. },
  127. elementResizeOver(element) {
  128. this.clear();
  129. this.modifyElementChild(element);
  130. this.$nextTick(() => {
  131. this.rebuildPages();
  132. });
  133. },
  134. rebuildGuides(element, actionType) {
  135. return this.rebuild(this.data.elements, element, actionType);
  136. },
  137. },
  138. };
  139. </script>