参考上一篇 知识开发的一个功能,制作一个打印模板的管理模块,如下(就是保存froala编辑后的html文本,其中包括Vue的Template,这样我们可以利用Vue的模板的优势来动态绑定一些数据源进行HTML的打印,基本上跟过去水晶报表做一个模板再绑定数据源的方法异曲同工)

在 main.js 里引用 froala 组件

// Import and use Vue Froala lib.
import VueFroala from 'vue-froala-wysiwyg'// 引入 Froala Editor js file.
require('froala-editor/js/froala_editor.pkgd.min')
// 引入中文语言包
require('froala-editor/js/languages/zh_cn')
// 引入 Froala Editor css files.
require('froala-editor/css/froala_editor.pkgd.min.css')
require('font-awesome/css/font-awesome.css')
require('froala-editor/css/froala_style.min.css')// 批量导入 froala-editor 插件文件
function importAll (r) {r.keys().forEach(r)
}
importAll(require.context('froala-editor/js/plugins/', false, /\.js$/))
importAll(require.context('froala-editor/css/plugins/', false, /\.css$/))Vue.use(VueFroala)

以上基本是引用了所有的插件,不然工具栏会有很多的按钮不出来

然后把 froala 文本编辑器封装成一个Vue组件,只暴露我们想要的功能

<template><div class="editor-wrap"><froala:tag="'textarea'":config="config"v-model="body.innerHTML"/></div>
</template>
<script>
import FroalaEditor from 'froala-editor'
export default {props: {// 显示的工具列表placeholder: {type: String},height: {type: Number},value: {type: String,default: null},index: {type: Number,default: 1},buttons: {type: Array,default: () => ['undo','redo','clearFormatting','bold','italic','underline','strikeThrough','fontFamily','fontSize','textColor','color','backgroundColor','inlineStyle','paragraphFormat','align','formatOL','formatUL','outdent','indent','quote',// 'insertLink','insertImage',// 'insertVideo',// 'embedly',// 'insertFile','insertTable',// 'emoticons','specialCharacters','insertHR','selectAll','print','spellChecker','html','help','fullscreen','clear','save']}},data () {const that = thisreturn {editor: null,uploadImage: {loading: false,previewVisible: false,previewImage: '',imgFile: {},isSize: false,isType: false},fileList: [],body: {innerHTML: this.value,textLen: 0,leftoverLen: 99999999999,sumLen: 999999999,error_tip: '',error_show: false},config: {codeBeautifierOptions: {end_with_newline: true,indent_inner_html: true,extra_liners: "['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre', 'ul', 'ol', 'table', 'dl']",brace_style: 'expand',indent_char: ' ',indent_size: 4,wrap_line_length: 0},htmlAllowedAttrs: ['.*'],pasteAllowedStyleProps: ['.*'],// fullPage: true,useClasses: false,htmlRemoveTags: [],iframe: true,toolbarButtons: this.buttons,// theme: "dark", //主题placeholderText: this.placeholder || '编辑文本',language: 'zh_cn', // 国际化imageUploadURL: '', // 上传urlimageUploadParams: { token: '', i: '', ak: '', f: 9 },fileUploadURL: '',fileUploadParams: { token: '', i: '', ak: '', f: 9 },videoUploadURL: '',videoUploadParams: { token: '', i: '', ak: '', f: 9 },quickInsertButtons: ['image', 'table', 'ul', 'ol', 'hr'], // 快速插入项// toolbarVisibleWithoutSelection: true,//是否开启 不选中模式// disableRightClick: true,//是否屏蔽右击colorsHEXInput: true, // 关闭16进制色值toolbarSticky: false, // 操作栏是否自动吸顶,// Colors list.colorsBackground: ['#15E67F','#E3DE8C','#D8A076','#D83762','#76B6D8','REMOVE','#1C7A90','#249CB8','#4ABED9','#FBD75B','#FBE571','#FFFFFF'],colorsStep: 6,colorsText: ['#15E67F','#E3DE8C','#D8A076','#D83762','#76B6D8','REMOVE','#1C7A90','#249CB8','#4ABED9','#FBD75B','#FBE571','#FFFFFF'],zIndex: 2501,height: this.height || '250',// autofocus: true,events: {initialized: function () {that.editor = thisthat.body.innerHTML = that.valuethat.editorChange()},blur: () => {that.$emit('blur')},contentChanged: () => {that.editorChange()},'image.beforeUpload': function (images) {// 自定义上传图片that.beforeUpload(images[0])return false},'file.beforeUpload': function () {// Image was uploaded to the server.return true},'video.beforeUpload': function () {// Image was uploaded to the server.return true}}}}},watch: {value: {handler: function (news, old) {this.body.innerHTML = news},deep: true},'body.innerHTML': function (newVal, old) {if (old !== newVal) {let val = this.getSimpleText(this.editor.html.get(true))this.editor.html.set(newVal)}},label: function (newVal, old) {if (old !== newVal) {this.editor.html.set(newVal)}}},mounted () {// 自定义按钮***********************************************************************// 清理FroalaEditor.DefineIcon('clear', {NAME: 'remove', SVG_KEY: 'remove'})FroalaEditor.RegisterCommand('clear', {title: '清空',focus: false,undo: true,refreshAfterCallback: true,callback: function () {this.html.set(null)this.events.focus()}})// 保存FroalaEditor.DefineIconTemplate('material_design', '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="floppy-disk" class="svg-inline--fa fa-floppy-disk" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M433.1 129.1l-83.9-83.9C342.3 38.32 327.1 32 316.1 32H64C28.65 32 0 60.65 0 96v320c0 35.35 28.65 64 64 64h320c35.35 0 64-28.65 64-64V163.9C448 152.9 441.7 137.7 433.1 129.1zM224 416c-35.34 0-64-28.66-64-64s28.66-64 64-64s64 28.66 64 64S259.3 416 224 416zM320 208C320 216.8 312.8 224 304 224h-224C71.16 224 64 216.8 64 208v-96C64 103.2 71.16 96 80 96h224C312.8 96 320 103.2 320 112V208z"></path></svg>')FroalaEditor.DefineIcon('saveIcon', {NAME: 'save', template: 'material_design'})FroalaEditor.RegisterCommand('save', {title: '保存',icon: 'saveIcon',callback: () => {this.$emit('save', this.body.innerHTML)}})// **********************************************************************************setTimeout(() => {this.setIndex(this.index)}, 200)},methods: {saveHtml () {this.$emit('save', this.body.innerHTML)},// 更改富文本层级setIndex (val) {this.$nextTick(() => {let dv = document.getElementsByClassName('fr-box')for (let i in dv) {if (!dv[i].style) {return}dv[i].style.cssText = 'z-index:' + val}})},// 富文本中提取纯文本getSimpleText: html => {var re1 = new RegExp('<p data-f-id="pbf".+?</p>', 'g') // 匹配html标签的正则表达式,"g"是搜索匹配多个符合的内容var msg = html.replace(re1, '') // 执行替换成空字符return msg},editorChange () {if (this.editor == null) returnthis.$emit('change', this.body.innerHTML)},beforeUpload (file) {this.uploadImage.loading = trueconst formData = new FormData()formData.append('formFile', file)// this.$store//   .dispatch('UploadImg', formData)//   .then(res => {//     this.uploadImage.loading = false//     if (res.code === 200) {//       this.uploadImage.imgFile = JSON.parse(res.data)//       const url = this.uploadImage.imgFile.data//       // 插入图片//       this.editor.html.insert(//         '<img src=' + this.uploadImage.imgFile.data + '>', // HTML//         false // 在插入之前是否应清除HTML//       ) // 插入图片//     } else {//       this.fileList = []//       this.$message.error(res.msg)//     }//   })//   .catch(() => {//     this.uploadImage.loading = false//     this.$message.error('上传失败')//   })}}
}</script>
<style lang="less" scoped>
.editor-wrap {width: 100%;height: calc(100% - 30px);// 去掉底部工具栏logo/deep/ .fr-second-toolbar {height: 42.19px;#fr-logo >span {display: none;}#Layer_1 {display: none;}}/deep/ .fr-box {height: 100% !important;.fr-wrapper {height: calc(100% - 93px) !important;}}/deep/ .fr-code {height: 100% !important;}
}.fr-wrapper > div[style*="z-index:9999;"],
.fr-wrapper > div[style*="z-index: 9999;"] {height: 0;overflow: hidden;position: absolute;top: -1000000px;opacity: 0;
}
.fr-view{position: absolute;top: 0;
}
.fr-placeholder{margin-top: 0;
}
.fr-box .second-toolbar {display: none;
}
.fr-box .second-toolbar #logo {width: 0 !important;height: 0 !important;overflow: hidden;
}
.fr-box .fr-toolbar {border-radius: 4px 4px 0 0;border-color: #dcdfe6;
}
.fr-box .second-toolbar {border-radius: 0 0 4px 4px;border-color: #dcdfe6;
}
.fr-box .fr-wrapper {border-color: #dcdfe6 !important;
}
</style>
<style>
.fa-floppy-disk {width: 18px;height: 18px;
}
</style>

具体的用法还要参详一下 froala 官方文档,这里不细表了

后端设计一张数据库表用来保存 html 文本

下面使用刚刚上面封装好的组件对html模板进行保存和更新

<template><div class="page"><SplitPane direction="column" :min="10" :max="90" :triggerLength="10" :paneLengthPercent.sync="paneLengthPercent"><template v-slot:one><div style="height:100%"><div style="height:calc(100% - 40px)"><el-tablestripeelement-loading-text="数据正在加载中"highlight-current-rowsize="small"ref="multipleTable"border:data="tableData"height="100%":cell-style="{ 'text-align': 'center' }":header-cell-style="{ 'text-align': 'center' }"v-on:select="handleSelectedRow" v-on:row-click="handleSelectedRow"@cell-click="cellClick"><el-table-column type="index" width="48"></el-table-column><el-table-column label="模板名称" width="350px" prop='template_name'><template slot-scope="scope"><el-input v-if="tableData.indexOf(scope.row)  === rowIndex && hearderTitle === '模板名称'"v-model="scope.row.template_name" placeholder="请填写模板名称"></el-input><span v-else>{{ scope.row.template_name }}</span></template></el-table-column><template  v-for="item in headerGroup"><el-table-column:key="item.label"v-if="item.show":label="item.label":prop="item.prop":width="item.width"></el-table-column></template><el-table-column label="操作" width="120" fixed="right"><template slot="header"><el-popoverplacement="top-start"width="30"trigger="hover"content="点击添加一行"><el-button size="mini" class='el-buttons' type="primary" icon="el-icon-plus" circle slot="reference" @click="renderAddRow"></el-button></el-popover></template><template slot-scope="scope"><el-popover width="160" :ref="`popover-${scope.$index}`" placement="top"><p>确定删除该项吗?</p><div style="text-align: right; margin: 0"><el-button type="text" size="mini" @click="scope._self.$refs[`popover-${scope.$index}`].doClose()">取消</el-button><el-button type="danger" size="mini" @click="deleteRow(scope.$index, scope.row, scope._self.$refs[`popover-${scope.$index}`])">确定</el-button></div><el-button type="danger" class='el-buttons' style="background-color:#F56C6C" slot="reference" icon="el-icon-delete" size="mini" circle></el-button></el-popover><el-popoverplacement="top-start"width="80px"trigger="hover"content="点击保存这一行"><el-button size="mini" class='el-buttons' style="background-color:#909399" type="info" icon="el-icon-edit" circle slot="reference" @click="addOrUpdateRow(scope.row)"></el-button></el-popover></template></el-table-column></el-table></div><div style="height:40px;padding:5px;"><el-paginationbackgroundlayout="total, sizes, prev, pager, next":total="GridPageRequest.PageTotal"@size-change="handleSizeChange"@current-change="handleCurrentChange":page-sizes="[20, 30, 50, 100]":page-size="GridPageRequest.PageSize":current-page.sync="GridPageRequest.PageIndex"></el-pagination></div></div></template><template v-slot:two><editor v-model="templateHtml" @save="saveTemplate" @change="changeTemplate"></editor></template></SplitPane></div>
</template>
<script>
import SplitPane from '@/components/draglayhorizontallayouter/SplitPane.vue'
import Editor from '@/components/print/editor.vue'
export default {components: { SplitPane, Editor },data () {return {templateName: null,rowIndex: 0,hearderTitle: '',paneLengthPercent: 40,// 表格tableData: [],// 表头headerGroup: [{ label: '主键ID', prop: 'id', show: false, width: '160px' },{ label: '创建人', prop: 'create_by_name', show: true, width: '160' },{ label: '创建人', prop: 'create_by', show: false, width: '160' },{ label: '创建时间', prop: 'create_time', show: true, width: '160' },{ label: '修改人', prop: 'update_by_name', show: true, width: '160' },{ label: '修改人', prop: 'update_by', show: false, width: '160' },{ label: '修改时间', prop: 'update_time', show: true, width: 'auto' }],// 分页GridPageRequest: {PageSize: 20,PageIndex: 0,PageTotal: 0},selectedRows: [],templateHtml: ''}},mounted () {this.$nextTick(async () => {this.onSearch()})},methods: {// 选择行handleSelectedRow (selection, row) {this.templateHtml = ''this.selectedRows = []if (Array.isArray(selection)) {for (let i = 0; i < selection.length; i++) {this.selectedRows.push(selection[i])}} else { this.selectedRows.push(selection) }this.templateHtml = this.selectedRows[0].template_html},cellClick (row, column, cell, event) {this.rowIndex = this.tableData.indexOf(row)this.hearderTitle = column.labelthis.templateHtml = ''this.selectedRows = []if (Array.isArray(row)) {for (let i = 0; i < row.length; i++) {this.selectedRows.push(row[i])}} else { this.selectedRows.push(row) }this.templateHtml = this.selectedRows[0].template_html},renderAddRow () {this.tableData.push({ template_name: null })},addOrUpdateRow (row) {if (!row.id) {row.create_by = localStorage.getItem('user')} else {row.update_by = localStorage.getItem('user')}if (!row.template_name || row.template_name.length === 0) {this.$message.error('请先填写模板名称!')return}this.axios.post('BasePrintTemplate/AddOrUpdate', row).then((response) => {this.$message.success('操作成功!')this.getTableData()}).catch((error) => {this.$message({message: error.response.data.Message,type: 'warning'})})},deleteRow (index, row, _self) {// 关闭气泡提示_self.doClose()if (!row.id) {this.tableData.splice(this.tableData.indexOf(row), 1)this.$message.success('操作成功!')return}this.axios.post('BasePrintTemplate/Delete', row).then((response) => {if (response.data.Data) {this.$message.success('操作成功!')this.tableData.splice(this.tableData.indexOf(row), 1)} else {this.$message.error('操作失败!')}}).catch((error) => {this.$message({message: error.response.data.Message,type: 'warning'})})},getTableData () {this.GridPageRequest.Filter = []if (this.templateName != null) {this.GridPageRequest.Filter.push({FieldName: 'template_name', ConditionalType: '15', FieldValue: this.templateName})}this.axios.post('BasePrintTemplate/QueryTake', this.GridPageRequest).then((response) => {this.tableData = response.data.Datathis.GridPageRequest.PageTotal = response.data.TotalRowsthis.radio = ''}).catch((error) => {this.$message({message: error.response.data.Message,type: 'warning'})})},onSearch () {this.getTableData()},handleSizeChange (val) {this.GridPageRequest.PageSize = valthis.onSearch()},handleCurrentChange (val) {this.GridPageRequest.PageIndex = valthis.onSearch()},changeTemplate (template) {this.templateHtml = template},saveTemplate () {if (this.selectedRows.length === 0) {this.$message({message: '请选择一行数据再保存!',type: 'warning'})return}this.selectedRows[0].template_html = this.templateHtmlthis.axios.post('BasePrintTemplate/AddOrUpdate', this.selectedRows[0]).then((response) => {this.$message.success('操作成功!')this.getTableData()}).catch((error) => {this.$message({message: error.response.data.Message,type: 'warning'})})}}
}</script>
<style lang="less" scoped>
.page {height: 100%;/deep/ .el-table .el-table__fixed-right .el-table__fixed-header-wrapper .el-table__cell {text-align: right !important;}
}
</style>
<style src='@/css/el-buttons.css' scoped>
</style>

绑定Vue的数据源,

<template><top-middle-bottom><template v-slot:header><el-row :gutter="20"><el-col :span="6"><el-buttonsize="medium"icon="el-icon-circle-plus-outline"type="success"v-on:click="onOpenAdd()">新 增</el-button><el-buttonicon="el-icon-bottom"type="info"size="medium"v-on:click="onImport()">批量导入</el-button><el-buttonicon="el-icon-printer"size="medium"v-on:click="onShowTemplate()">打印</el-button></el-col><el-col :span="18"><template><el-radio v-model="search.status" :label="1000">全部</el-radio><el-radio v-model="search.status" :label="1001">启用</el-radio><el-radio v-model="search.status" :label="1002">禁用</el-radio></template><el-inputsize="medium"v-model="search.name"placeholder="请输入单位名称"style="width: 300px; margin-right: 5px"clearablev-on:clear="clearSearchValue"></el-input><el-buttontype="primary"v-on:click="onSearch"icon="el-icon-search"size="medium">搜索</el-button></el-col></el-row></template><template v-slot:body><el-tableelement-loading-text="数据正在加载中"highlight-current-rowref="multipleTable"borderstripe:data="table.data":cell-style="{ 'text-align': 'center' }":header-cell-style="{ 'text-align': 'center' }"height="100%"><el-table-column type="index" label="序号" width="50"></el-table-column><el-table-columnprop="supplier_name"show-overflow-tooltiplabel="单位名称"width="220px"></el-table-column><el-table-columnprop="supplier_code"show-overflow-tooltiplabel="单位代码"width="220px"></el-table-column><el-table-column prop="supplier_type_text" label="类别" width="100px"></el-table-column><el-table-column label="状态" width="65"><template slot-scope="scope"><el-switchv-model="scope.row.bill_status"active-color="#13ce66"inactive-color="#ff4949":active-value="1001":inactive-value="1002"@change="onUpdateStatus(scope.row)"></el-switch></template></el-table-column><el-table-column prop="create_time" label="创建时间" width="180px"></el-table-column><el-table-column prop="context" label="联系人" width="100px"></el-table-column><el-table-column prop="phone" label="电话" width="180px"></el-table-column><el-table-column prop="email" label="邮箱" width="300px"></el-table-column><el-table-columnprop="address"show-overflow-tooltiplabel="地址"width="auto"></el-table-column><el-table-column fixed="right" width="180" label="操作" align="left"><template slot-scope="scope"><el-buttontype="text"size="small"icon="el-icon-edit"v-on:click="onOpenUpdate(scope.row)">修改</el-button><el-buttontype="text"size="small"icon="el-icon-delete"style="color: #f56c6c"v-on:click="onDelete(scope.row)">删除</el-button></template></el-table-column></el-table></template><template v-slot:footer><el-paginationref="pagination"v-on:size-change="onPageSizeChange"v-on:current-change="onPageCurrentChange":current-page.sync="GridPageRequest.PageIndex":page-sizes="[20, 50, 100, 200]":page-size="GridPageRequest.PageSize"layout="sizes, prev, pager, next, total":total="table.count"></el-pagination></template><template v-slot:dialog><el-dialog title="打印" append-to-body :close-on-press-escape="false":visible.sync = "showPrint":close-on-click-modal="false"width="50%"><div id="myPrint" v-html="templateHtml"></div></el-dialog><!-- 弹窗 新增 / 修改 --><el-dialog:title="form.id ? '修改' : '新增'":visible.sync="form.show":destroy-on-close="true":close-on-press-escape="false":close-on-click-modal="false"width="50%"><el-form ref="form" :model="form" label-width="100px" :rules="rules"><el-row><el-col :span="12"><el-form-item label="单位名称" prop="supplier_name"><el-inputv-model="form.supplier_name"style="width: 300px"></el-input></el-form-item></el-col><el-col :span="12"><el-form-item label="单位代码" prop="supplier_code"><el-inputv-model="form.supplier_code"style="width: 300px"></el-input></el-form-item></el-col></el-row><el-row><el-form-item label="地址"><el-input v-model="form.address"></el-input></el-form-item></el-row><el-row><el-col :span="12"><el-form-item label="联系人"><el-input v-model="form.context"></el-input> </el-form-item></el-col><el-col :span="12"><el-form-item label="电话"><el-input v-model="form.phone"></el-input> </el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="邮箱"><el-input v-model="form.email"></el-input></el-form-item></el-col><el-col :span="12"><el-form-item label="类别"><el-radio v-model="form.supplier_type" :label="1001">供应商</el-radio><el-radio v-model="form.supplier_type" :label="1002">客户</el-radio><el-radio v-model="form.supplier_type" :label="1003">制造商</el-radio><el-radio v-model="form.supplier_type" :label="1004">维保外委</el-radio></el-form-item></el-col></el-row><el-row><el-form-item label="备注"><el-inputtype="textarea":rows="3"placeholder="请输入备注内容"v-model="form.remarks"></el-input></el-form-item></el-row></el-form><div slot="footer" class="dialog-footer"><el-button size="medium" v-on:click="dialogClose()">取 消</el-button><el-button size="medium" type="primary" v-on:click="onFormSubmit()">确 定</el-button></div></el-dialog><!-- 导出组件 --><import-excel:visible="showExcelImport":upload-path="uploadPath":tempfile-url="tempfileUrl"tempfile-name="往来单位模板"v-on:close="closeExcelImport"></import-excel></template></top-middle-bottom>
</template>
<script>
import axios from 'axios'
import ImportExcel from '@/components/importexcel.vue'
import TopMiddleBottom from '@/components/uilayout/topmiddlebottom.vue'
import Vue from 'vue'
import printJS from 'print-js'
export default {components: { ImportExcel, TopMiddleBottom },data () {return {condition: [],templateHtml: null,tempfileUrl: process.env.ROOT + '/TemplateFiles/单位模板.xls',uploadPath: process.env.ROOT + '/api/Supplier/Import',showPrint: false,showExcelImport: false,// 搜索search: {name: '',status: 1000},// 表格table: {data: [],count: 0},// 分页GridPageRequest: {PageSize: 20,PageIndex: 0,PageTotal: 0},rules: {supplier_name: [{ required: true, message: '请输入单位名称', trigger: 'blur' }],supplier_code: [{ required: true, message: '请输入单位代码', trigger: 'blur' }]},form: {show: false,id: '',supplier_name: '',supplier_code: '',address: '',context: '',phone: '',supplier_type: 1001,bill_status: 1001,email: '',remarks: ''},styleNode: ''}},mounted () {this.$nextTick(() => {this.getTableData(this.search)})},methods: {// 搜索onSearch () {const search = this.searchthis.getTableData(search)},// 请求表格数据getTableData (data) {axios.get('Supplier/Query', {params: {name: data.name,status: data.status,pageIndex: this.GridPageRequest.PageIndex,pageSize: this.GridPageRequest.PageSize}}).then((response) => {if (response.data.Success === true) {this.table.data = response.data.Datathis.table.count = response.data.TotalRows} else {// 请求失败this.$message.error(response.data.Msg)}}).catch(function (error) {this.$message.error(error)})},// 修改分页大小onPageSizeChange (val) {this.GridPageRequest.PageSize = valthis.getTableData(this.search)},// 修改分页页数onPageCurrentChange (val) {this.GridPageRequest.PageIndex = valthis.getTableData(this.search)},// 打开新增onOpenAdd () {this.dialogClose()this.form.show = true},// 打开修改onOpenUpdate (row) {// 赋值form数据this.form.id = row.idthis.form.supplier_name = row.supplier_namethis.form.supplier_code = row.supplier_codethis.form.address = row.addressthis.form.context = row.contextthis.form.phone = row.phonethis.form.supplier_type = row.supplier_typethis.form.email = row.emailthis.form.remarks = row.remarksthis.form.bill_status = row.bill_statusthis.form.show = true},// 删除onDelete (row) {const supplierId = row.idthis.$confirm('此操作将删除该条记录, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {axios.post(`Supplier/IsDelete?supplierId=${supplierId}`).then((response) => {if (response.data.Success === true) {this.$message({type: 'success',message: '删除成功!'})this.getTableData(this.search)} else {this.$message({type: 'warning',message: `${response.data.Msg}`})}}).catch((error) => {this.$message.error(error)})}).catch(() => {})},// 清除搜索条件clearSearchValue () {this.search = {name: '',status: 1000}},// 启用/禁用onUpdateStatus (row) {// 保存点击之后v-modeld的值const flag = row.bill_status// 保持switch点击前的状态row.bill_status = row.bill_status === 1001 ? 1002 : 1001this.$confirm('是否确认此操作?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {const supplierId = row.idconst status = flagaxios.post(`Supplier/UpdateState?supplierId=${supplierId}&status=${status}`).then((response) => {this.getTableData(this.search)}).catch((error) => {this.$message.error(error)})}).catch(() => {})},// 表单提交确认onFormSubmit () {const form = { ...this.form }const userId = localStorage.getItem('user')axios.post('Supplier/AddOrEdit', {UserId: userId,Data: {id: form.id,supplier_name: form.supplier_name,supplier_code: form.supplier_code,address: form.address,context: form.context,phone: form.phone,supplier_type: form.supplier_type,bill_status: form.bill_status,email: form.email,remarks: form.remarks}}).then((response) => {if (response.data.Success === true) {this.dialogClose()this.getTableData(this.search)} else {this.$message.error(response.data.Msg)}}).catch((error) => {console.log(error)})},// 导入onImport () {this.showExcelImport = true},// 对话框关闭dialogClose () {// 初始化form数据this.form = {show: false,id: '',supplier_name: '',supplier_code: '',address: '',context: '',phone: '',supplier_type: 1001,bill_status: 1001,email: '',remarks: ''}},closeExcelImport () {this.showExcelImport = false},async onShowTemplate () {let findTemplate = nullthis.condition = []// 查询模板this.condition.push({FieldName: 'template_name', ConditionalType: '0', FieldValue: '供应商与客户'})await this.axios.post('BasePrintTemplate/QueryCondition', this.condition).then((response) => {if (Array.isArray(response.data.Data)) {findTemplate = response.data.Data[0].template_html}}).catch((error) => {this.$message({message: error.response.Message,type: 'warning'})})// 绑定模板if (findTemplate) {const printData = this.table.dataconst Component = Vue.extend({template: `<div>${findTemplate}</div>`,data () {return {printItems: printData}},methods: {}})const component = new Component().$mount()this.templateHtml = component.$el.innerHTMLthis.showPrint = true// 等待渲染完成后再调用打印方法this.$nextTick(() => {printJS({printable: 'myPrint',type: 'html',scanStyles: false,targetStyles: ['*'],// @media print 用来控制打印的样式,边距,横向/纵向,纸张大小等style: '@media print {@page {margin: 10px;size: portrait;} body {font-size: 10px;margin: 0px;}}'})this.showPrint = false})}}}
}
</script>

打印预览效果如下

Vue中使用froala富文本编辑器制作打印模板 + print.js 打印相关推荐

  1. Vue 中引入markdown富文本编辑器并根据md格式渲染

    Vue 中引入markdown富文本编辑器 在vue组件中,比较好用的是mavon-editor,github文档地址 https://github.com/hinesboy/mavonEditor ...

  2. Vue中使用vue-quil-editor富文本编辑器+el-upload实现带图片上传到SpringBoot后台接口

    场景 系统中经常会用到富文本编辑器,比如新增通知和公告功能,并且需要添加上传图片. vue-quill-editor官网: https://www.npmjs.com/package/vue-quil ...

  3. vue中使用wangeditor富文本编辑器(含图片上传和回显)

    最近在写vue的项目中,遇到一个需求,点击编辑,显示弹框,在弹框中的富文本编辑器中编辑自定义文本样式,可以上传图片并回显.编辑完成确定后显示在页面上. 首先先写一个editor.vue的页面.(建议单 ...

  4. vue中使用element-tiptap富文本编辑器

    element-tiptap富文本编辑器 npm安装 npm install element-tiptap --save yarn安装 yarn add element-tiptap 全局引入 imp ...

  5. 在Vue中使用CKEditor5富文本编辑器

    在项目中遇到富文本编辑器需要实现粘贴图片的功能,使用场景:如用户在其他地方截图可以直接在富文本编辑器内粘贴. 找了一圈市面上开源免费的富文本编辑器,最后选中CKEditor.ckeditor  doc ...

  6. 在Vue中使用Tinymce富文本编辑器+上传图片到七牛

    公司官网后台需要做一个上传新闻.公告的功能,自然而然就需要用到了富文本编辑器. UEditor.Simditor.wangEditor.CKEditor.TinyMCE.Quill,这是当前比较热门的 ...

  7. vue中使用quill富文本编辑器

    因为公司的需求,对比了线在很火的几款富文本编辑器,最终选定了quill,他够轻量,拓展性也比较高,除了文档是英文的阅读不方便之外,都很适合公司项目.故整理出来,也方便以后使用. 在网上找了一个中文文档 ...

  8. Vue 中使用 Tinymce 富文本编辑器

    参考链接:https://www.cnblogs.com/wisewrong/p/8985471.html Tinymce : 从 word 粘贴过来还能保持绝大部分格式的编辑器 一. 下载 npm ...

  9. 在vue3.0项目中使用tinymce富文本编辑器

    目录 一.安装 二.完整代码 三.事项说明 四.参考文档   之前看了好几篇关于 vue项目中使用 tinymce的文章, import引入大量 tinymce插件, /node_modules/ti ...

  10. Froala富文本编辑器

    Froala富文本编辑器 https://www.froala.com/wysiwyg-editor

最新文章

  1. 一种用XAML写Data Converter的方式
  2. 数据库-ADONET-使用强类型DataSet
  3. 【PAT乙级】1053 住房空置率 (20 分)
  4. python爬虫beautifulsoup爬当当网_Python爬虫包 BeautifulSoup 递归抓取实例详解_python_脚本之家...
  5. 0-1背包动态规划c语言,动态规划解决0-1背包问题程序看不懂,请大家看看帮忙解决下...
  6. 使用SparkJava和Graal的本机微服务
  7. 前端学习(507):垂直居中的第二种方式的优缺点
  8. JavaScript基本语法2
  9. 事件营销成功案例-引爆全网的优衣库事件
  10. 小儿持续高烧不退的护理办法和相关病理分析
  11. 【阿里巴巴Java编程规范学习 五】MySQL数据库规约
  12. ecshop index.php,ecshop  源码分析01 (index.php)
  13. Java自学教程!docker运行镜像无反应
  14. 学习OpenCV3:Cmake+MinGW编译OpenCV
  15. JAVA正则表达式,matcher.find()和 matcher.matches()的区别
  16. python关键词生成文章_如何生成关键词云图?
  17. 360n4s高通版卡刷包
  18. 基于SpringBoot的实习管理系统
  19. Python项目实战 1.1:项目准备.需求分析
  20. IBM陈剑:金融行业大数据解决方案实践

热门文章

  1. Maven 使用入门
  2. 摄影小白入门相机选择(个人出发)
  3. css 固定宽度超出部分换行,css怎么超出宽度换行
  4. Flash Builder 4 正式版破解注册方法(flex4)
  5. 单盘齿廓测量仪的设计
  6. Linux使用libmodbus源码开发,LibModbus源码分析
  7. windows10计算机策略,win10系统轻松玩转组策略的图文步骤
  8. LM358电压跟随器
  9. Python基于机器视觉的图像风格迁移
  10. CVPR 2021 论文大盘点-去雾去模糊篇