<template> <div class="card-design card-free-design"> <div class="design-header"> <div class="design-header-cont box-justify"> <div></div> <el-button class="btn-help" icon="el-icon-question" type="text" @click="showHelp" ></el-button> </div> </div> <!-- actions --> <div class="design-action"> <div class="design-logo"> <h1> <i class="el-icon-d-arrow-left" @click="toExit" title="退出"></i> 答题卡制作 </h1> </div> <div class="action-part"> <div class="action-part-title"><h2>基本设置</h2></div> <div class="action-part-body"> <page-prop-edit></page-prop-edit> </div> </div> <div class="action-part"> <div class="action-part-title"><h2>当前页面设置</h2></div> <div class="action-part-body"> <edit-page></edit-page> </div> </div> <div class="action-part"> <div class="action-part-title"><h2>复杂元素</h2></div> <div class="action-part-body"> <div class="type-list"> <div class="type-item" v-for="(item, index) in TOPIC_LIST" :key="index" draggable="true" @dragstart="dragstart(item)" > <el-button><i class="el-icon-plus"></i>{{ item.name }}</el-button> </div> </div> <p class="tips-info">提示:拖动插入元素</p> </div> </div> <div class="action-part"> <div class="action-part-title"><h2>简单元素</h2></div> <div class="action-part-body"> <div class="type-list"> <div class="type-item" v-for="(item, index) in ELEMENT_LIST" :key="index" draggable="true" @dragstart="dragstart(item)" > <el-button><i class="el-icon-plus"></i>{{ item.name }}</el-button> </div> <p class="tips-info">提示:拖动插入元素</p> </div> </div> </div> <div class="action-part"> <div class="action-part-title"><h2>元素面板</h2></div> <div class="action-part-body"> <!-- element-tier-edit --> <element-tier-edit ref="ElementTierEdit"></element-tier-edit> </div> </div> </div> <div class="design-main"> <!-- menus --> <div class="design-control"> <div class="control-left tab-btns"> <el-button v-for="(page, pageNo) in pages" :key="pageNo" :type="curPageNo === pageNo ? 'primary' : 'default'" @click="swithPage(pageNo)" > <span>第{{ pageNo + 1 }}页</span> <span class="page-delete" @click.stop="toDeletePage(page)" ><i class="el-icon-error"></i ></span> </el-button> <el-button icon="el-icon-plus" @click="toAddPage"></el-button> </div> <div class="control-right"> <el-button type="success" :loading="isSubmit" :disabled="!pages.length" @click="toPreview" >预览</el-button > <el-button v-if="showSaveBtn" type="primary" :loading="isSubmit" :disabled="canSave || !pages.length" @click="toSave" >暂存</el-button > <el-button type="primary" :loading="isSubmit" @click="toSubmit" >提交</el-button > </div> </div> <!-- edit body --> <div class="design-body"> <div :class="[ 'page-box', `page-box-${curPage.pageSize}`, `page-box-${curPageNo % 2}`, { 'page-box-less': pages.length <= 2 } ]" v-if="curPage.id" > <!-- locator --> <div class="page-locator page-locator-top"> <div v-for="elem in curPage.locators.top" :key="elem.id" :id="elem.id" class="page-locator-item" ></div> </div> <div class="page-locator page-locator-bottom"> <div v-for="elem in curPage.locators.bottom" :key="elem.id" :id="elem.id" class="page-locator-item" ></div> </div> <!-- inner edit area --> <div class="page-main-inner"> <div :class="['page-main', `page-main-${curPage.columns.length}`]" :style="{ margin: `0 -${curPage.columnGap / 2}px` }" > <div class="page-column" v-for="(column, columnNo) in curPage.columns" :key="columnNo" :style="{ padding: `0 ${curPage.columnGap / 2}px` }" > <topic-column-edit class="page-column-main" :data="column" ></topic-column-edit> </div> </div> </div> <!-- outer edit area --> <div class="page-main-outer"> <page-number type="rect" :total="pages.length" :current="curPageNo + 1" ></page-number> <page-number type="text" :total="pages.length" :current="curPageNo + 1" ></page-number> </div> </div> </div> </div> <!-- element-prop-edit --> <element-prop-edit ref="ElementPropEdit"></element-prop-edit> <!-- right-click-menu --> <right-click-menu></right-click-menu> <!-- shortcut-key --> <shortcut-key @sk-save="skSave" @sk-submit="skSubmit" @sk-preview="skPreview" ></shortcut-key> <!-- help-dialog --> <help-dialog ref="HelpDialog"></help-dialog> </div> </template> <script> import { mapState, mapMutations, mapActions } from "vuex"; import { getElementModel, ELEMENT_LIST, TOPIC_LIST } from "../elements/model"; import { getModel as getPageModel } from "../../../elements/page/model"; import { CARD_VERSION } from "../../../enumerate"; import TopicColumnEdit from "../components/TopicColumnEdit"; import ElementPropEdit from "../components/ElementPropEdit"; import ElementTierEdit from "../components/ElementTierEdit"; import PagePropEdit from "../components/PagePropEdit"; import RightClickMenu from "../components/RightClickMenu"; import ShortcutKey from "../components/ShortcutKey"; import HelpDialog from "../components/HelpDialog"; import EditPage from "../../../elements/page/EditPage"; import PageNumber from "../../../components/PageNumber"; export default { name: "card-free-design", props: { content: { type: Object, default() { return { pages: [], cardConfig: {} }; } }, showSaveBtn: { type: Boolean, default: true } }, components: { TopicColumnEdit, PagePropEdit, EditPage, ElementPropEdit, ElementTierEdit, RightClickMenu, ShortcutKey, HelpDialog, PageNumber }, data() { return { ELEMENT_LIST, TOPIC_LIST, topicList: [], columnWidth: 0, isSubmit: false, canSave: false }; }, computed: { ...mapState("free", [ "cardConfig", "pages", "curElement", "curPage", "curPageNo", "curDragElement", "curColumnId" ]) }, mounted() { this.initCard(); }, methods: { ...mapMutations("free", [ "setCurPageNo", "setCurElement", "setCardConfig", "setOpenElementEditDialog", "setCurDragElement", "setPages", "initState" ]), ...mapActions("free", [ "addPage", "removePage", "addElement", "modifyElement" ]), async initCard() { const { cardConfig, pages } = this.content; this.setCardConfig(cardConfig); if (pages && pages.length) { this.setPages(pages); this.setCurPageNo(0); } else { this.initPageData(); } }, initPageData() { const page = getPageModel(this.cardConfig); this.addPage(page); this.setCurPageNo(0); }, toAddPage() { const page = getPageModel(this.cardConfig); this.addPage(page); }, addNewTopic(item) { let element = getElementModel(item.type); this.setCurElement(element); this.$refs.ElementPropEdit.open(); // to elementPropEdit/ElementPropEdit open topic edit dialog }, // 元件编辑 dragstart(element) { this.setCurDragElement(getElementModel(element.type)); }, // 操作 swithPage(pindex) { if (this.curPageNo === pindex) return; this.setCurPageNo(pindex); this.setCurElement({}); }, toDeletePage(page) { if (this.pages.length === 1) { this.$message.error("只剩最后一页,不能再删除了"); return; } this.removePage(page); }, // save getCardData(htmlContent = "", model = "") { let data = { title: this.cardConfig.cardTitle, content: model, htmlContent }; return data; }, getCardJson() { // 防止页面未渲染完成,各试题高度未及时更新,保存数据有误的问题 return new Promise(resolve => { setTimeout(() => { const data = JSON.stringify( { version: CARD_VERSION, cardType: "FREE", cardConfig: this.cardConfig, paperParams: this.paperParams, pages: this.pages }, (k, v) => (k.startsWith("_") ? undefined : v) ); resolve(data); }, 100); }); }, skSave() { this.toSave(); }, skSubmit() { this.toSubmit(); }, skPreview() { this.toPreview(); }, async toPreview() { if (this.isSubmit) return; this.isSubmit = true; const model = await this.getCardJson(); const datas = this.getCardData("", model); this.$emit("on-preview", datas); }, async toSave() { if (this.isSubmit) return; this.isSubmit = true; const model = await this.getCardJson(); const datas = this.getCardData("", model); this.$emit("on-save", datas); }, toSubmit() { if (this.isSubmit) return; if (this.pages.length % 2) { this.$message.error("请确保题卡页数是偶数"); return; } this.$emit("on-submit", { cardConfig: this.cardConfig, pages: this.pages, paperParams: this.paperParams }); }, toExit() { this.$emit("on-exit"); }, showHelp() { this.$refs.HelpDialog.open(); }, loading() { this.isSubmit = true; }, unloading() { this.isSubmit = false; } }, beforeDestroy() { this.initState(); } }; </script>