ElementPropEdit.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <el-dialog
  3. class="element-prop-edit edit-dialog"
  4. :visible.sync="openElementEditDialog"
  5. :title="title"
  6. top="10vh"
  7. width="640px"
  8. :close-on-click-modal="false"
  9. :close-on-press-escape="false"
  10. :before-close="cancel"
  11. append-to-body
  12. >
  13. <component
  14. v-if="openElementEditDialog"
  15. ref="ElementPropEditComp"
  16. :is="curEditComponent"
  17. :instance="curElement"
  18. :key="curElement.id"
  19. @modified="modified"
  20. ></component>
  21. <div slot="footer">
  22. <el-button type="primary" :disabled="loading" @click="submit"
  23. >确认</el-button
  24. >
  25. <el-button @click="cancel">取消</el-button>
  26. </div>
  27. </el-dialog>
  28. </template>
  29. <script>
  30. import { mapState, mapMutations, mapActions } from "vuex";
  31. import { getElementName, getFillQuestionName } from "../elementModel";
  32. import EditComposition from "../elements/composition/EditComposition";
  33. import EditExplain from "../elements/explain/EditExplain";
  34. import EditFillLine from "../elements/fill-line/EditFillLine";
  35. import EditFillQuestion from "../elements/fill-question/EditFillQuestion";
  36. import EditText from "../elements/text/EditText";
  37. import EditImage from "../elements/image/EditImage";
  38. import EditLine from "../elements/line/EditLine";
  39. import EditLines from "../elements/lines/EditLines";
  40. import EditGrids from "../elements/grids/EditGrids";
  41. export default {
  42. name: "element-prop-edit",
  43. components: {
  44. EditComposition,
  45. EditExplain,
  46. EditFillLine,
  47. EditFillQuestion,
  48. EditText,
  49. EditImage,
  50. EditLine,
  51. EditLines,
  52. EditGrids,
  53. },
  54. data() {
  55. return { loading: false };
  56. },
  57. computed: {
  58. ...mapState("card", ["curElement", "topics", "openElementEditDialog"]),
  59. title() {
  60. if (this.curElement.type === "FILL_QUESTION")
  61. return getFillQuestionName(this.curElement);
  62. return this.curElement.type
  63. ? getElementName(this.curElement.type)
  64. : "属性编辑";
  65. },
  66. curEditComponent() {
  67. if (!this.curElement.type) return;
  68. let type = this.curElement.type.toLowerCase().replace("_", "-");
  69. if (type.indexOf("line-") === 0) type = "line";
  70. return `edit-${type}`;
  71. },
  72. },
  73. methods: {
  74. ...mapMutations("card", ["setOpenElementEditDialog"]),
  75. ...mapActions("card", [
  76. "addElement",
  77. "modifyElement",
  78. "modifyElementChild",
  79. "rebuildPages",
  80. "scrollToElementPage",
  81. ]),
  82. cancel() {
  83. this.setOpenElementEditDialog(false);
  84. },
  85. open() {
  86. this.setOpenElementEditDialog(true);
  87. },
  88. submit() {
  89. if (this.loading) return;
  90. this.loading = true;
  91. setTimeout(() => {
  92. this.loading = false;
  93. }, 500);
  94. this.$refs.ElementPropEditComp.submit();
  95. },
  96. equalTopicType(topic1, topic2) {
  97. if (topic1.type === topic2.type) {
  98. if (topic1.type !== "FILL_QUESTION") {
  99. return true;
  100. }
  101. return (
  102. topic1.isBoolean === topic2.isBoolean &&
  103. topic1.isMultiply === topic2.isMultiply
  104. );
  105. }
  106. return false;
  107. },
  108. checkTopicType(element) {
  109. const relateTopics = this.topics.filter(
  110. (item) =>
  111. item.topicNo === element.topicNo &&
  112. item.parent &&
  113. item.parent.id !== element.id
  114. );
  115. if (!relateTopics.length) return true;
  116. return !relateTopics.some(
  117. (topic) => !this.equalTopicType(element, topic)
  118. );
  119. },
  120. checkTopicNo(element) {
  121. if (element.type === "COMPOSITION") return true;
  122. const relateTopics = this.topics.filter(
  123. (item) =>
  124. item.topicNo === element.topicNo &&
  125. item.parent &&
  126. item.parent.id !== element.id
  127. );
  128. if (!relateTopics.length) return true;
  129. let er = [
  130. element.startNumber,
  131. element.startNumber + element.questionsCount - 1,
  132. ];
  133. const unvalid = relateTopics.some((item) => {
  134. const topic = item.type === "EXPLAIN" ? item.parent : item;
  135. const tr = [
  136. topic.startNumber,
  137. topic.startNumber + topic.questionsCount - 1,
  138. ];
  139. return (
  140. (er[0] <= tr[0] && er[1] >= tr[0]) ||
  141. (er[0] <= tr[1] && er[1] >= tr[1]) ||
  142. (er[0] >= tr[0] && er[1] <= tr[1])
  143. );
  144. });
  145. return !unvalid;
  146. },
  147. modified(element) {
  148. if (!element["container"]) {
  149. if (!this.checkTopicType(element)) {
  150. this.$message.error("同一大题号的所有试题题型必须相同");
  151. return;
  152. }
  153. // 在不校验大题号重复的情况下,需要校验小题号重复
  154. if (!this.checkTopicNo(element)) {
  155. this.$message.error("小题号重复,请重新设置小题号");
  156. return;
  157. }
  158. }
  159. // 编辑试题
  160. // 属性存在的条件:parent:大题的小题,container:题目内的子元素
  161. if (this.curElement["_edit"]) {
  162. if (element["container"]) {
  163. this.modifyElementChild(element);
  164. } else {
  165. this.modifyElement(element);
  166. }
  167. } else {
  168. this.addElement(element);
  169. }
  170. this.cancel();
  171. this.$nextTick(() => {
  172. this.rebuildPages();
  173. this.$nextTick(() => {
  174. this.scrollToElementPage(element);
  175. });
  176. });
  177. },
  178. },
  179. };
  180. </script>