PaperTemplateDesign.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. <template>
  2. <div class="paper-template-design card-design paper-page">
  3. <!-- actions -->
  4. <div class="design-action">
  5. <div class="design-logo">
  6. <h1>
  7. <i class="el-icon-d-arrow-left" title="退出" @click="toExit"></i>
  8. 试卷模板制作
  9. </h1>
  10. </div>
  11. <div class="action-part">
  12. <div class="action-part-title"><h2>基本设置</h2></div>
  13. <div class="action-part-body">
  14. <page-prop-edit @init-page="initPageData"></page-prop-edit>
  15. </div>
  16. </div>
  17. <div class="action-part">
  18. <div class="action-part-title"><h2>编辑结构</h2></div>
  19. <div class="action-part-body">
  20. <div class="type-list">
  21. <div class="type-item">
  22. <el-button @click="addNewTopic('PANE_BOX')"
  23. ><i class="el-icon-plus"></i>编辑框</el-button
  24. >
  25. </div>
  26. </div>
  27. <p class="tips-info">提示:点击创建编辑框</p>
  28. </div>
  29. </div>
  30. <div class="action-part">
  31. <div class="action-part-title"><h2>插入元素</h2></div>
  32. <div class="action-part-body">
  33. <div class="type-list">
  34. <div
  35. v-for="(item, index) in ELEMENT_LIST"
  36. :key="index"
  37. class="type-item"
  38. draggable="true"
  39. @dragstart="dragstart(item)"
  40. >
  41. <el-button><i class="el-icon-plus"></i>{{ item.name }}</el-button>
  42. </div>
  43. </div>
  44. <p class="tips-info">提示:拖动插入元素</p>
  45. </div>
  46. </div>
  47. </div>
  48. <div class="design-main">
  49. <!-- menus -->
  50. <div class="design-control">
  51. <div class="control-left tab-btns">
  52. <el-button
  53. v-for="(page, pageNo) in pages"
  54. :key="pageNo"
  55. :type="curPageNo === pageNo ? 'primary' : 'default'"
  56. @click="swithPage(pageNo)"
  57. >{{ pageNo ? "正面" : "反面" }}</el-button
  58. >
  59. </div>
  60. <div class="control-right">
  61. <el-button
  62. type="success"
  63. :loading="isSubmit"
  64. :disabled="!pages.length"
  65. @click="toPreview"
  66. >预览</el-button
  67. >
  68. <el-button type="primary" :loading="isSubmit" @click="toSubmit"
  69. >提交</el-button
  70. >
  71. </div>
  72. </div>
  73. <!-- edit body -->
  74. <div class="design-body">
  75. <div
  76. v-if="curPage.id"
  77. :class="[
  78. 'page-box',
  79. `page-box-${curPage.pageSize}`,
  80. `page-box-${curPageNo % 2}`,
  81. ]"
  82. >
  83. <!-- inner edit area -->
  84. <div class="page-main-inner">
  85. <div
  86. :class="['page-main', `page-main-${curPage.columns.length}`]"
  87. :style="{ margin: `0 -${curPage.columnGap / 2}px` }"
  88. >
  89. <div
  90. v-for="(column, columnNo) in curPage.columns"
  91. :key="columnNo"
  92. class="page-column"
  93. :style="{ padding: `0 ${curPage.columnGap / 2}px` }"
  94. >
  95. <div
  96. :id="[`column-${curPageNo}-${columnNo}`]"
  97. class="page-column-main"
  98. >
  99. <div class="page-column-body">
  100. <topic-element-edit
  101. v-for="element in column.elements"
  102. :key="element.id"
  103. class="page-column-element"
  104. :data-h="element.h"
  105. :data="element"
  106. ></topic-element-edit>
  107. </div>
  108. </div>
  109. <page-number
  110. v-if="curPage.showPageNo"
  111. type="text"
  112. :total="pages.length * 2"
  113. :current="curPageNo * 2 + columnNo + 1"
  114. ></page-number>
  115. </div>
  116. </div>
  117. </div>
  118. <!-- side edit -->
  119. <paper-side-edit
  120. class="page-main-side"
  121. :data="curPage.sides"
  122. ></paper-side-edit>
  123. </div>
  124. </div>
  125. </div>
  126. <!-- all topics -->
  127. <div class="topic-list">
  128. <div :class="['page-box', `page-box-${curPage.pageSize}`]">
  129. <div class="page-main-inner">
  130. <div
  131. :class="['page-main', `page-main-${curPage.columnNumber}`]"
  132. :style="{ margin: `0 -${curPage.columnGap / 2}px` }"
  133. >
  134. <div
  135. class="page-column"
  136. :style="{ padding: `0 ${curPage.columnGap / 2}px` }"
  137. >
  138. <div id="topic-column" class="page-column-main">
  139. <div class="page-column-body">
  140. <!-- topic element -->
  141. <topic-element-preview
  142. v-for="element in topics"
  143. :key="element.id"
  144. class="page-column-element"
  145. :data="element"
  146. ></topic-element-preview>
  147. </div>
  148. </div>
  149. </div>
  150. </div>
  151. </div>
  152. </div>
  153. </div>
  154. <!-- element-prop-edit -->
  155. <element-prop-edit ref="ElementPropEdit"></element-prop-edit>
  156. <!-- right-click-menu -->
  157. <right-click-menu></right-click-menu>
  158. </div>
  159. </template>
  160. <script>
  161. import { mapState, mapMutations, mapActions } from "vuex";
  162. import { getElementModel, ELEMENT_LIST } from "../elementModel";
  163. import { getModel as getPageModel } from "../elements/page/model";
  164. import PagePropEdit from "./PagePropEdit";
  165. import ElementPropEdit from "./ElementPropEdit";
  166. import RightClickMenu from "./RightClickMenu";
  167. import PageNumber from "./PageNumber";
  168. import TopicElementEdit from "./TopicElementEdit.vue";
  169. import TopicElementPreview from "./TopicElementPreview.vue";
  170. import PaperSideEdit from "./PaperSideEdit.vue";
  171. export default {
  172. name: "PaperTemplateDesign",
  173. components: {
  174. PagePropEdit,
  175. ElementPropEdit,
  176. RightClickMenu,
  177. PageNumber,
  178. TopicElementEdit,
  179. TopicElementPreview,
  180. PaperSideEdit,
  181. },
  182. props: {
  183. content: {
  184. type: Object,
  185. default() {
  186. return {
  187. pages: [],
  188. };
  189. },
  190. },
  191. },
  192. data() {
  193. return {
  194. ELEMENT_LIST,
  195. isSubmit: false,
  196. };
  197. },
  198. computed: {
  199. ...mapState("paper-export", [
  200. "topics",
  201. "pages",
  202. "curElement",
  203. "curPage",
  204. "curPageNo",
  205. ]),
  206. },
  207. mounted() {
  208. this.initCard();
  209. },
  210. beforeDestroy() {
  211. this.initState();
  212. },
  213. methods: {
  214. ...mapMutations("paper-export", [
  215. "addPage",
  216. "setCurPage",
  217. "setCurElement",
  218. "setOpenElementEditDialog",
  219. "setCurDragElement",
  220. "setPages",
  221. "setTopics",
  222. "initState",
  223. ]),
  224. ...mapActions("paper-export", [
  225. "addElement",
  226. "modifyElement",
  227. "rebuildPages",
  228. "initTopicsFromPages",
  229. ]),
  230. initCard() {
  231. const { pages } = this.content;
  232. if (pages && pages.length) {
  233. this.setPages(pages);
  234. this.initTopicsFromPages();
  235. this.setCurPage(0);
  236. } else {
  237. this.initPageData();
  238. }
  239. },
  240. initPageData() {
  241. this.setPages([getPageModel(), getPageModel()]);
  242. this.setCurPage(0);
  243. },
  244. addNewTopic(type) {
  245. let element = getElementModel(type);
  246. element.w = document.getElementById("topic-column").offsetWidth;
  247. this.addElement(element);
  248. this.$nextTick(() => {
  249. this.rebuildPages();
  250. });
  251. },
  252. // 元件编辑
  253. dragstart(element) {
  254. this.setCurDragElement(getElementModel(element.type));
  255. },
  256. // 切换正反页
  257. swithPage(pindex) {
  258. if (this.curPageNo === pindex) return;
  259. this.setCurPage(pindex);
  260. this.setCurElement({});
  261. },
  262. getTemplateJson() {
  263. return new Promise((resolve) => {
  264. setTimeout(() => {
  265. const data = JSON.stringify(
  266. {
  267. pages: this.pages,
  268. },
  269. (k, v) => (k.startsWith("_") ? undefined : v)
  270. );
  271. resolve(data);
  272. }, 100);
  273. });
  274. },
  275. toPreview() {
  276. if (this.isSubmit) return;
  277. this.$emit("on-preview", {
  278. pages: this.pages,
  279. });
  280. },
  281. toSubmit() {
  282. if (this.isSubmit) return;
  283. this.$emit("on-submit", {
  284. pages: this.pages,
  285. });
  286. },
  287. toExit() {
  288. this.$emit("on-exit");
  289. },
  290. loading() {
  291. this.isSubmit = true;
  292. },
  293. unloading() {
  294. this.isSubmit = false;
  295. },
  296. },
  297. };
  298. </script>