| <template> | 
|   <div ref="container"> | 
|     <el-container class="designer-container"> | 
|       <el-aside width="300px"> | 
|         <left-aside ref="left-aside" :basic-components="basicComponents" :module-node.sync="moduleNode" :detail-fields.sync="detailFields" :widget-form-data.sync="widgetFormData" :reset-do-list="resetDoList"></left-aside> | 
|       </el-aside> | 
|   | 
|       <el-container class="designer-center-container" direction="vertical"> | 
|         <div class="content"> | 
|           <div class="right-tools" @mousedown.stop> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-baocun" @click="handleGenerateJson">保存</el-button> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-reset" @click="handleReset">重置</el-button> | 
|             <el-button type="text" size="medium" icon="el-icon-view" @click="handlePreview">预览</el-button> | 
|             <i class="el-icon-yrt-vertical_line"></i> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-undo" @click.native="toolActionUndo()">撤销</el-button> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-redo" @click.native="toolActionRedo()">恢复</el-button> | 
|             <i class="el-icon-yrt-vertical_line"></i> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-zuoduiqi" @click.native="toolAction('left')">左对齐</el-button> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-youduiqi" @click.native="toolAction('right')">右对齐</el-button> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-shangduiqi" @click.native="toolAction('top')">上对齐</el-button> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-xiaduiqi" @click.native="toolAction('bottom')">下对齐</el-button> | 
|             <i class="el-icon-yrt-vertical_line"></i> | 
|             <el-button type="text" size="medium" icon="el-icon-yrt-settings2" @click.native="toolActionSetting">设置</el-button> | 
|           </div> | 
|   | 
|           <widget-form ref="widgetForm" :data="widgetFormData" :select.sync="widgetFormSelect" :config-type.sync="configType" :detail-fields.sync="detailFields" :add-do-list="addDoList"></widget-form> | 
|         </div> | 
|       </el-container> | 
|   | 
|       <!--属性窗口--> | 
|       <el-dialog v-dialogDrag :modal="false" :visible.sync="settingVisible" :append-to-body="true" :modal-append-to-body="true" width="300px" top="5vh" title="属性设置" class="attribute-config-container"> | 
|         <el-tabs value="widget" @tab-click="(tab, event)=>{handleConfigSelect(tab, event)}"> | 
|           <el-tab-pane label="字段属性" name="widget"> | 
|             <el-scrollbar :noresize="false" :native="false" wrap-class="config scrollbar-wrap"> | 
|               <component v-show="configTab=='widget'" :is="configType" :data="widgetFormSelect" :basic-components="basicComponents"></component> | 
|             </el-scrollbar> | 
|           </el-tab-pane> | 
|           <el-tab-pane label="表单属性" name="form"> | 
|             <el-scrollbar :noresize="false" :native="false" wrap-class="config scrollbar-wrap"> | 
|               <form-config v-show="configTab=='form'" :data-options="widgetFormData.dataOptions"></form-config> | 
|             </el-scrollbar> | 
|           </el-tab-pane> | 
|         </el-tabs> | 
|       </el-dialog> | 
|   | 
|       <cus-dialog ref="widgetPreview" :visible="previewVisible" title="UI预览" width="1000px" form @on-close="previewVisible = false" @on-submit="handlePagePreview"> | 
|       </cus-dialog> | 
|   | 
|       <cus-dialog ref="jsonPreview" :visible="jsonVisible" width="800px" form title="生成JSON并保存Vue文件" @on-close="jsonVisible = false"> | 
|         <div id="jsoneditor" style="height: 400px;width: 100%;">{{ vueData }}</div> | 
|         <template slot="action"> | 
|           <el-button data-clipboard-target=".ace_text-input" @dblclick.native="$message.success('复制成功');">双击复制</el-button> | 
|           <el-button :loading="createLoading" type="primary" data-clipboard-target=".ace_text-input" @click.native="createBaseVue">保存</el-button> | 
|         </template> | 
|       </cus-dialog> | 
|     </el-container> | 
|   </div> | 
| </template> | 
|   | 
| <script> | 
| import Draggable from "vuedraggable"; | 
| import WidgetConfig from "./WidgetConfig"; | 
| import FormConfig from "./FormConfig"; | 
| import WidgetForm from "./WidgetForm"; | 
| import CusDialog from "./CusDialog"; | 
| import { basicComponents } from "./componentsConfig.js"; | 
| import { loadJs } from "./util/index.js"; | 
| import { generateMixinCode, generateMainCode } from "./generateMixinCode.js"; | 
| import LeftAside from "./components/leftAside"; | 
|   | 
| export default { | 
|   name: "sys-dev-tools-print-designer", | 
|   components: { | 
|     Draggable, | 
|     WidgetConfig, | 
|     FormConfig, | 
|     WidgetForm, | 
|     CusDialog, | 
|     LeftAside | 
|   }, | 
|   data() { | 
|     return { | 
|       basicComponents, | 
|   | 
|       // 明细字段 | 
|       detailFields: [], | 
|   | 
|       // 当前配置参数设置组件 | 
|       configType: "WidgetConfig", | 
|   | 
|       // 模块字段信息 | 
|       moduleNode: { | 
|         projectName: null, | 
|         cnName: "【请选择模块】", | 
|         table_Id: 0, | 
|         tableName: null, | 
|         tableView: null, | 
|         dBServer: null, | 
|         dBServerReadOnly: null, | 
|         parentId: null, | 
|         detailName: null, | 
|         idField: null, | 
|         codeRegular: null, | 
|         linkColumn: null, | 
|         sortName: null | 
|       }, | 
|   | 
|       // 设计器数据结构 | 
|       widgetFormData: { | 
|         // 数据加载及保存参数 | 
|         dataOptions: { | 
|           menu_Id: null, | 
|           projectName: "BasicInfo", | 
|           tableView: "", | 
|           idField: "", | 
|           router: "/sys/table", | 
|           title: "", | 
|           paddingTop: 5, | 
|           paddingBottom: 5, | 
|           paddingLeft: 5, | 
|           paddingRight: 5, | 
|           width: 210, | 
|           height: 148, | 
|           templateType: "常规模板" | 
|         }, | 
|         // 字段集合 | 
|         fields: [] | 
|       }, | 
|       // 撤销、恢复 | 
|       undoList: [], | 
|       redoList: [], | 
|       // undo、redo操作,不在记录历史 | 
|       isDoAction: false, | 
|       // 时间戳 | 
|       currentTimeStamp: 0, | 
|   | 
|       // 设计器默认数据结构 | 
|       widgetFormDataDefault: { | 
|         // 数据加载及保存参数 | 
|         dataOptions: { | 
|           projectName: "BasicInfo", | 
|           tableView: "", | 
|           idField: "", | 
|           router: "", | 
|           title: "", | 
|           paddingTop: 30, | 
|           paddingRight: 30, | 
|           paddingBottom: 30, | 
|           paddingLeft: 30, | 
|           templateType: "常规模板" | 
|         }, | 
|         // 字段集合 | 
|         fields: [] | 
|       }, | 
|       // 设计器类型:管理页面、编辑页面 | 
|       editRegionTab: "WidgetConfig", | 
|       configTab: "widget", | 
|       widgetFormSelect: null, // 选中项 | 
|       previewVisible: false, | 
|       jsonVisible: false, | 
|       codeVisible: false, | 
|       blank: "", | 
|       vueData: "", // 创建混入文件内容 | 
|       mainCode: "", // 创建主文件内容 | 
|       createLoading: false, // 创建页面loading | 
|       // 参数设置窗口显示 | 
|       settingVisible: true | 
|     }; | 
|   }, | 
|   watch: { | 
|     widgetFormData: { | 
|       deep: true, | 
|       handler: function(val) { | 
|         this.addDoList(); | 
|       } | 
|     }, | 
|     configType: function(val) {}, | 
|     widgetFormSelect: { | 
|       handler(val) {}, | 
|       deep: true | 
|     } | 
|   }, | 
|   mounted() { | 
|     loadJs("lib/ace/src/ace.js"); | 
|   }, | 
|   deactivated() { | 
|     this.settingVisible = false; | 
|   }, | 
|   activated() { | 
|     this.settingVisible = true; | 
|     // SaaS模块权限 | 
|     this.common.hasSaaSAuth("打印模板设置", this.$refs.container); | 
|   }, | 
|   methods: { | 
|     handleConfigSelect(tab, event) { | 
|       this.configTab = tab.name; | 
|     }, | 
|     // 预览设计 | 
|     handlePreview() { | 
|       this.previewVisible = true; | 
|     }, | 
|     // 重置,重新开始设计 | 
|     handleReset() { | 
|       if (!this.moduleNode.tableView) { | 
|         this.$message.error("请选择需要设计的模块!"); | 
|         return; | 
|       } | 
|       this.$confirm("确定要重置设计,将重新开始设计, 是否继续?", "重置提示", { | 
|         confirmButtonText: "确定", | 
|         cancelButtonText: "取消", | 
|         type: "warning" | 
|       }) | 
|         .then(() => { | 
|           this.reset(); | 
|           this.$message({ | 
|             type: "success", | 
|             message: "重置成功!" | 
|           }); | 
|         }) | 
|         .catch(() => { | 
|           this.$message({ | 
|             type: "info", | 
|             message: "已取消重置" | 
|           }); | 
|         }); | 
|     }, | 
|     // 重置 | 
|     reset() { | 
|       var data = this.moduleNode; | 
|       this.widgetFormData = Object.assign({}, this.widgetFormDataDefault, { | 
|         dataOptions: { | 
|           projectName: data.projectName, | 
|           tableView: data.tableView, | 
|           idField: data.idField, | 
|           router: "/api/common/loadEditData", | 
|           idValue: 0, | 
|           codeRegular: data.codeRegular, // 自动编码字段 | 
|           linkColumn: data.linkColumn, // 链接到弹出编辑窗口的字段 | 
|           menu_Id: null, | 
|           pageIndex: 1, | 
|           pageSize: 15, | 
|           total: 0, | 
|           sortName: data.sortName | 
|         } | 
|       }); | 
|       this.widgetFormSelect = null; // 编辑页面选中项 | 
|     }, | 
|     // 预览页面 | 
|     handlePagePreview() {}, | 
|     // 生成JSON | 
|     handleGenerateJson() { | 
|       var title = this.widgetFormData.dataOptions.title; | 
|       var router = this.widgetFormData.dataOptions.router; | 
|       var tableView = this.widgetFormData.dataOptions.tableView; | 
|       if (!title || !router || !tableView) { | 
|         this.$message.error("请在表单属性里面填写必填属性"); | 
|         return; | 
|       } | 
|   | 
|       this.jsonVisible = true; | 
|       var last = router.lastIndexOf("/"); | 
|       if (last === router.length - 1) { | 
|         router = router.substring(0, router.length - 1); | 
|         this.widgetFormData.dataOptions.router = router; | 
|       } | 
|   | 
|       this.mainCode = generateMainCode(router); | 
|       this.vueData = generateMixinCode(this.widgetFormData); | 
|   | 
|       this.$nextTick(() => { | 
|         // eslint-disable-next-line | 
|         const editor = ace.edit("jsoneditor"); | 
|         // eslint-disable-next-line | 
|         editor.session.setMode("ace/mode/jsx"); | 
|       }); | 
|     }, | 
|   | 
|     // 生成文件 | 
|     createBaseVue() { | 
|       var the = this; | 
|       if (this.widgetFormData.dataOptions.menu_Id === "") { | 
|         this.$message.error("关联模块ID不能为空!"); | 
|         return; | 
|       } | 
|       if (!this.widgetFormData.dataOptions.title) { | 
|         this.$message.error("模板名称不能为空!"); | 
|         return; | 
|       } | 
|       if (!this.widgetFormData.dataOptions.router) { | 
|         this.$message.error("API地址不能为空!"); | 
|         return; | 
|       } | 
|       if (!this.widgetFormData.dataOptions.tableView) { | 
|         this.$message.error("关联表名不能为空!"); | 
|         return; | 
|       } | 
|       // eslint-disable-next-line | 
|       const editor = ace.edit("jsoneditor"); | 
|       var selectText = editor.getSelectedText(); | 
|   | 
|       // UI布局参数 | 
|       var vueData = selectText; | 
|       if (!vueData) { | 
|         vueData = JSON.stringify(this.widgetFormData, null, 2); | 
|       } else { | 
|         this.widgetFormData = JSON.parse(vueData); | 
|       } | 
|       if (!this.vueData) { | 
|         this.$message.error("没有可保存的数据!"); | 
|         return; | 
|       } | 
|       var node = this.$refs["left-aside"].getCurrentNode(); | 
|       var printTemplate_Id = node.printTemplate_Id; | 
|       // 更新节点数据 | 
|       node.vueData = vueData; | 
|   | 
|       the.createLoading = true; | 
|       var url = "/api/sys/printTemplate/savePrintTemplate"; | 
|       var params = { | 
|         menu_Id: this.widgetFormData.dataOptions.menu_Id, | 
|         printTemplate_Id: printTemplate_Id, | 
|         templateName: this.widgetFormData.dataOptions.title, | 
|         templateType: this.widgetFormData.dataOptions.templateType, | 
|         vueData: vueData, | 
|         noDataSign: true // 数据不参与加密 | 
|       }; | 
|   | 
|       the.common.ajax( | 
|         url, | 
|         params, | 
|         res => { | 
|           this.common.showMsg(res); | 
|           if (res.result) { | 
|             this.moduleNode.vueData = vueData; // 保存数下拉框中的VueData | 
|             this.jsonVisible = false; | 
|             this.resetDoList(); | 
|           } | 
|           the.createLoading = false; | 
|         }, | 
|         true | 
|       ); | 
|     }, | 
|   | 
|     // 工具栏事件操作 | 
|     toolAction(action) { | 
|       var topItem = null; | 
|       var fields = this.widgetFormData.fields; | 
|       document.querySelectorAll(".resable-item.selected").forEach(item => { | 
|         if (!topItem || topItem.offsetY > item.offsetY) { | 
|           topItem = item; | 
|         } | 
|       }); | 
|       if (!topItem) return; | 
|   | 
|       document.querySelectorAll(".resable-item.selected").forEach(item => { | 
|         const key = item.attributes["data-key"].value; | 
|         const field = fields.find(item => { | 
|           return item.key === key; | 
|         }); | 
|   | 
|         let bottom, y, right, x; | 
|         switch (action) { | 
|           case "top": | 
|             field.options.y = topItem.offsetTop; | 
|             break; | 
|           case "bottom": | 
|             bottom = topItem.offsetTop + topItem.offsetHeight; | 
|             y = bottom - item.offsetHeight; | 
|             field.options.y = y; | 
|             break; | 
|           case "left": | 
|             field.options.x = topItem.offsetLeft; | 
|             break; | 
|           case "right": { | 
|             right = topItem.offsetLeft + topItem.offsetWidth; | 
|             x = right - item.offsetWidth; | 
|             field.options.x = x; | 
|             break; | 
|           } | 
|         } | 
|       }); | 
|     }, | 
|     // 设计动作记录add do list | 
|     addDoList() { | 
|       if (this.isDoAction) { | 
|         this.isDoAction = false; | 
|         return; | 
|       } | 
|       var currStamp = new Date().valueOf(); | 
|       var span = currStamp - this.currentTimeStamp; | 
|       var newItem = JSON.parse(JSON.stringify(this.widgetFormData)); | 
|       if (this.undoList.length) { | 
|         var lastItem = this.undoList[this.undoList.length - 1]; | 
|         var newItemJson = JSON.stringify(this.widgetFormData); | 
|   | 
|         if (newItemJson !== lastItem) { | 
|           if (span < 150) { | 
|             this.undoList[this.undoList.length - 1] = newItem; | 
|           } else { | 
|             this.undoList.push(newItem); | 
|           } | 
|         } | 
|       } else { | 
|         this.undoList.push(newItem); | 
|       } | 
|       this.redoList = []; | 
|       this.currentTimeStamp = currStamp; | 
|     }, | 
|     // undo | 
|     toolActionUndo() { | 
|       this.isDoAction = true; | 
|       if (this.undoList.length >= 1) { | 
|         var item = this.undoList.pop(); | 
|         var newItem = JSON.parse(JSON.stringify(item)); | 
|         this.redoList.push(newItem); | 
|         var lastItem = this.undoList[this.undoList.length - 1]; | 
|         newItem = JSON.parse(JSON.stringify(lastItem)); | 
|         this.widgetFormData = newItem; | 
|       } else { | 
|         this.$message.error("没有可撤销的步骤了!"); | 
|       } | 
|     }, | 
|     // redo | 
|     toolActionRedo() { | 
|       this.isDoAction = true; | 
|       if (this.redoList.length) { | 
|         var item = this.redoList.pop(); | 
|         var newItem = JSON.parse(JSON.stringify(item)); | 
|         this.undoList.push(newItem); | 
|         newItem = JSON.parse(JSON.stringify(item)); | 
|         this.widgetFormData = newItem; | 
|       } else { | 
|         this.$message.error("没有可恢复的步骤了!"); | 
|       } | 
|     }, | 
|     // todo、redo reset | 
|     resetDoList() { | 
|       this.redoList = []; | 
|       this.undoList = []; | 
|     }, | 
|     toolActionSetting() { | 
|       this.settingVisible = !this.settingVisible; | 
|     } | 
|   } | 
| }; | 
| </script> | 
|   | 
| <style lang="scss" scoped> | 
| @import "./styles/index.scss"; | 
|   | 
| .el-container { | 
|   height: 100% !important; | 
| } | 
|   | 
| .el-radio + .el-radio { | 
|   margin-left: 0 !important; | 
| } | 
| .el-radio { | 
|   margin-right: 30px; | 
|   line-height: 32px; | 
| } | 
| .el-checkbox + .el-checkbox { | 
|   margin-left: 0 !important; | 
| } | 
| .el-checkbox { | 
|   margin-right: 30px; | 
| } | 
|   | 
| .attribute-config-container { | 
|   .el-tabs__header { | 
|     margin: 0; | 
|   } | 
| } | 
| </style> |