<template> <div class="card-design card-free-design"> <div class="design-header"> <div class="design-header-cont box-justify"> <el-button class="btn-help" icon="el-icon-question" type="text" @click="showHelp" ></el-button> <div class="design-back" @click="toExit"> <i class="el-icon-d-arrow-left" title="退出"></i> 返回 </div> </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"> <div v-if="hasUnsubmitCont" class="tips-info tips-error"> <i class="el-icon-warning"></i>有未提交数据 </div> <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 ref="ShortcutKey" @sk-save="skSave" @sk-submit="skSubmit" @sk-preview="skPreview" ></shortcut-key> <!-- help-dialog --> <help-dialog ref="HelpDialog" @on-enable="shortcutEnableChange" ></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, hasUnsubmitCont: false, }; }, computed: { ...mapState("free", [ "cardConfig", "pages", "curElement", "curPage", "curPageNo", "curDragElement", "curColumnId", ]), }, mounted() { this.initCard(); }, beforeDestroy() { this.initState(); }, 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, pages: this.pages, }, (k, v) => (k.startsWith("_") ? undefined : v) ); resolve(data); }, 100); }); }, skSave() { this.toSave(); }, skSubmit() { this.toSubmit(); }, skPreview() { this.toPreview(); }, shortcutEnableChange(enable) { if (enable) { this.$refs.ShortcutKey.registShortcutKey(); } else { this.$refs.ShortcutKey.removeShortcutKey(); } }, toPreview() { this.$emit("on-preview", { cardConfig: this.cardConfig, pages: this.pages, }); }, async toSave() { 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, }); }, toExit() { this.$emit("on-exit"); }, showHelp() { this.$refs.HelpDialog.open(); }, loading() { this.isSubmit = true; }, unloading() { this.isSubmit = false; }, updateUnsubmitStatus(status) { this.hasUnsubmitCont = status; }, }, }; </script>