vue使用md编辑器和打印 egg使用ctx.getFileStream进行文件上传

vue2使用markdown编辑器

安装

npm install mavon-editor --save

全局引入(main)

import mavonEditor from 'mavon-editor'     //引入mavon-editor组件
import 'mavon-editor/dist/css/index.css'       //引入组件的样式
Vue.use(mavonEditor)

vue2 使用打印功能

安装

npm install vue-print-nb --save

全局引入(main)

//引入打印机插件
import Print from 'vue-print-nb'
//注册
Vue.use(Print); //注册

组件应用

<template>
	<div class="bg-white p-5">
			 <!-- 给要打印的区块添加一个id,这时候给点击打印的按钮添加一个指令v-print,指定为要打印的区域id即可 -->
			 <div class="flex justify-end">
			 	<el-button  v-print="printObj" size="mini" type="primary">打印</el-button>
			 </div>
			    <div id="printTest" >
			<h3 style="text-align: center;">虚惊轻微事故调查表</h3>
			
			<div class="mt-5"  >
				<table style="width: 100%;">
					<tr>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故等级</td>
						<td class="border p" style="text-align: center;">虚惊/轻微</td>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故类别</td>
						<td class="border p" style="text-align: center;">物体打击</td>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故时间</td>
						<td class="border p" style="text-align: center;">2023-04-14</td>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故地点</td>
						<td class="border p" style="text-align: center;">上海</td>
					</tr>
					<tr>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故所属Bu</td>
						<td class="border p" style="text-align: center;">BU1</td>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故部门</td>
						<td class="border p" style="text-align: center;"></td>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">事故区域负责人</td>
						<td class="border p" style="text-align: center;"></td>
						<td class="border p printcolor" style="text-align: center;background-color: #E7F3FC;">电话</td>
						<td class="border p" style="text-align: center;">19822773234</td>
					</tr>
					<tr>
						<td class="border p printcolor"  colspan="8" style="background-color: #E7F3FC;">1.事故状况描述:(时间、地点、人物、受伤经过)</td>
					</tr>
					<tr>
						<td class="border p" style="height: 100px;"  colspan="8">
							
							<mavon-editor ref="md" v-model="content" :ishljs="true" @imgAdd="imgAdd"/>
						
							
						</td>
					</tr>
					<tr>
						<td class="border p printcolor"  colspan="8" style="background-color: #E7F3FC;">2.事故图片:</td>
					</tr>
					<tr>
						<td class="border p" style="height: 100px;"  colspan="8">
							<!-- 预览 -->
						 <mavon-editor  class="md"  :value="content"  :subfield="false"  :defaultOpen="'preview'"  :toolbarsFlag="false"  :editable="false"  :scrollStyle="true"  :ishljs="true" />
							
						
						</td>
					</tr>
					<tr>
						<td class="border p printcolor"  colspan="8" style="background-color: #E7F3FC;">3.事故处理情况(事故现场处理措施与状况、伤员处理情况等)</td>
					</tr>
					<tr>
						<td class="border p" style="height: 100px;"  colspan="8">
							
							 

						</td>
					</tr>
					<tr>
						<td class="border p printcolor"  colspan="8" style="background-color: #E7F3FC;">4、事故直接损失统计</td>
					</tr>
					<tr>
						<td class="border p"  colspan="8">□无损失       □轻微损失(说明):</td>
					</tr>
					<tr>
						<td class="border p printcolor"  colspan="8" style="background-color: #E7F3FC;">5、原因分析与改善方案</td>
					</tr>
					<tr>
						<td class="border p"  colspan="8" style="height: 100px;" >
						
						</td>
					</tr>
					<tr>
						<td class="border p printcolor"  colspan="8" style="background-color: #E7F3FC;">6、预防改善对策:</td>
					</tr>
					<tr style="background-color: #E7F3FC;text-align: center;">
						<td class="border p printcolor"  colspan="3"  >改善对策</td>
						<td class="border p printcolor"   >完成时间</td>
						<td class="border p printcolor"   >佐证资料<el-button @click="drawer3 = true" type="text"  style="margin-left: 16px">描述</el-button></td>
						<td class="border p printcolor"   >责任人</td>
						<td class="border p printcolor"   >核实结果</td>
						<td class="border p printcolor"   >核实人员</td>
					</tr>
					<tr style="text-align: center;height: 30px;">
						<td class="border p"  colspan="3"  ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
					</tr>
					<tr style="text-align: center;height: 30px;">
						<td class="border p"  colspan="3"  ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
						<td class="border p"   ></td>
					</tr>
				</table>
			</div>
		<el-drawer title="佐证资料" :visible.sync="drawer3" direction="rtl" :close-on-press-escape='false'
			:wrapperClosable='false' destroy-on-close size='50%'>
			<div style="font-size: 10px;  padding: 10px;overflow-y: auto;" :style="{ height: (h + 'px') }" v-html>
				可根据具体对策提供相关佐证资料:<br/>
				改善现场照片、管理培训记录、书面培训教材、培训会议签到表、培训会议照片、制定相关管理要求文件等
				 </div>
		</el-drawer>
	</div>

	</div>
</template>

<script>
	import {mapState} from 'vuex'
	const windowHeight = window.innerHeight || document.body.clientHeight
	export default {
		data() {
			return {
				drawer3: false,
			
				 printObj:{
					id:'printTest',//打印的id
					popTitle:'智能综合管理',//打印的标题
			   },
			
				content:'',
			
			}
		},
		computed: {
			...mapState({
		
				h: state => {
					let a = windowHeight - 64 - 44 
					return state.screenHeight ? state.screenHeight : a
				}
			}),
		},
		mounted() {
			document.addEventListener('visibilitychange', this.handleVisiable)  
			document.body.onblur=()=>{
				this.outNumber++;
				console.log(this.outNumber)
				//alert(`请回到考试页面,你已离开${this.outNumber}次`)
			}
		},
		destroyed() {
		  document.removeEventListener('visibilitychange', this.handleVisiable)  
		}, 
		methods:{
			 // 绑定@imgAdd event
			    imgAdd(pos, $file) {
					console.log(pos, $file)
			      let $vm = this.$refs.md
			      // 第一步.将图片上传到服务器.
			      const formData = new FormData();
				
				  formData.append("withc",'还发快手看');
				  formData.append("hegidnh",'和立铠四大皆空福建省');
				 
			      formData.append('file', $file);
			      axios({
			        url: 'http://localhost:9090/file/upload',
			        method: 'post',
			        data: formData,
			        headers: {'Content-Type': 'multipart/form-data'},
			      }).then((res) => {
			        // 第二步.将返回的url替换到文本原位置![...](./0) -> ![...](url)
			        $vm.$img2Url(pos, res.data);
			      })
			    },
		
				handleVisiable(e) {
				  switch(e.target.visibilityState) {
				    case 'prerender':
				      console.log('网页预渲染,内容不可见')
				      break;
				    case 'hidden':
				      console.log('内容不可见,处理后台、最小化、锁屏状态')
				      //alert('警告!你已经离开当前答题页面');
				      break;
				    case 'visible':
				      console.log('处于正常打开')
				      break;
				  }
				},
			  
				
		
		}
	}
</script>

<style>
	
	/* 给要打印的背景的元素添加样式 */
	.printcolor{
		-webkit-print-color-adjust: exact;
	}
</style>

eggjs开启流模式

配置 config/config.default.js
eggjs文档

config.multipart = {
  fileSize: '50mb',
  mode: 'stream', //'file' 可以配置文件模式  https://www.eggjs.org/zh-CN/basics/controller  官方文档  'stream' 配置流模式  配置的模式不一样 接收的方法方式就不一样
  fileExtensions: ['.xlsx', '.txt', '.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.jpeg', '.JPEG','.apk'], // 扩展几种上传的文件格式
};

controller/shigu.js

'use strict';

const Controller = require('egg').Controller;
// 引入
const fs = require('fs');
const path = require('path');
//故名思意 异步二进制 写入流
const awaitWriteStream = require('await-stream-ready').write;
//管道读入一个虫洞。
const sendToWormhole = require('stream-wormhole');
const dayjs = require('dayjs');
class ShiguController extends Controller {
  async shuguuploade() {
    let { ctx, app } = this;
   
    const stream = await ctx.getFileStream();
    
    console.log(stream.fields)
    console.log(stream.filename)
    
    ctx.apiSuccess('ok');
  }
}

module.exports = ShiguController;

egg后台打印结果 vue前端 劫持图片上传,自定义图片上传
在这里插入图片描述
注意:
只支持上传一个文件。
上传文件必须在所有其他的 fields 后面,否则在拿到文件流时可能还获取不到 fields。

vue3使用富文本

引入tinymce富文本编辑器

npm i tinymce
npm i @tinymce/tinymce-vue

node_modules/tinymce引入 语音包下载
在这里插入图片描述

中文语言包zh-Hans.js下载地址
在这里插入图片描述
新建组件src/components/Editor.vue

<template>
    <editor v-model="content" tag-name="div" :init="init" />
    <ChooseImage :preview="false" ref="ChooseImageRef" :limit="9" />
</template>
<script setup>
import tinymce from "tinymce/tinymce";
import Editor from "@tinymce/tinymce-vue";
import ChooseImage from '~/components/ChooseImage.vue'
import { ref, watch } from "vue"
import "tinymce/themes/silver/theme"; // 引用主题文件
import "tinymce/icons/default"; // 引用图标文件
import 'tinymce/models/dom'
// tinymce插件可按自己的需要进行导入
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
import "tinymce/plugins/advlist"
import "tinymce/plugins/anchor"
import "tinymce/plugins/autolink"
import "tinymce/plugins/autoresize"
import "tinymce/plugins/autosave"
import "tinymce/plugins/charmap" // 特殊字符
import "tinymce/plugins/code" // 查看源码
import "tinymce/plugins/codesample" // 插入代码
import "tinymce/plugins/directionality"
import "tinymce/plugins/emoticons"
import "tinymce/plugins/fullscreen" //全屏
import "tinymce/plugins/help"
import "tinymce/plugins/image" // 插入上传图片插件
import "tinymce/plugins/importcss" //图片工具
import "tinymce/plugins/insertdatetime" //时间插入
import "tinymce/plugins/link"
import "tinymce/plugins/lists" // 列表插件
import "tinymce/plugins/media" // 插入视频插件
import "tinymce/plugins/nonbreaking"
import "tinymce/plugins/pagebreak" //分页
import "tinymce/plugins/preview" // 预览
import "tinymce/plugins/quickbars"
import "tinymce/plugins/save" // 保存
import "tinymce/plugins/searchreplace" //查询替换
import "tinymce/plugins/table" // 插入表格插件
import "tinymce/plugins/template" //插入模板
import "tinymce/plugins/visualblocks"
import "tinymce/plugins/visualchars"
import "tinymce/plugins/wordcount" // 字数统计插件
// v-model
const props = defineProps({
    modelValue: String,
})
const emit = defineEmits(["update:modelValue"])

const ChooseImageRef=ref(null)
// 配置
const init = {
    language_url: '/tinymce/langs/zh-Hans.js', // 中文语言包路径
    language: "zh-Hans",
    skin_url: '/tinymce/skins/ui/oxide', // 编辑器皮肤样式
    content_css: "/tinymce/skins/content/default/content.min.css",
    menubar: false, // 隐藏菜单栏
    autoresize_bottom_margin: 50,
    max_height: 500,
    min_height: 400,
    // height: 320,
    toolbar_mode: "none",
    plugins:
        'wordcount visualchars visualblocks template searchreplace save quickbars preview pagebreak nonbreaking media insertdatetime importcss image help fullscreen directionality codesample code charmap link code table lists advlist anchor autolink autoresize autosave',
        //新增自定义按钮 这里需要注册如:imageUpload
    toolbar:
        "formats undo redo fontsizeselect fontselect ltr rtl searchreplace media imageUpload | outdent indent aligncenter alignleft alignright alignjustify lineheight underline quicklink h2 h3 blockquote numlist bullist table removeformat forecolor backcolor bold italic strikethrough hr link preview fullscreen help ",
    content_style: "p {margin: 5px 0; font-size: 14px}",
    fontsize_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px",
    font_formats: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方= PingFang SC, Microsoft YaHei, sans- serif; 宋体 = simsun, serif; 仿宋体 = FangSong, serif; 黑体 = SimHei, sans - serif; Arial = arial, helvetica, sans - serif;Arial Black = arial black, avant garde;Book Antiqua = book antiqua, palatino; ",
    branding: false,
    elementpath: false,
    resize: false, // 禁止改变大小
    statusbar: false, // 隐藏底部状态栏
    setup:(editor)=>{ //插入图片功能 自定义按钮imageUpload
        editor.ui.registry.addButton('imageUpload',{
            tooltip:'插入图片',//文字提示
            icon:'image',//内置图标
            onAction(){
                ChooseImageRef.value.open((data)=>{
                        data.forEach(url=>{
                            //插入内容 图片
                             editor.insertContent(`<img src='${url}' style='width:100%'/>`)
                        })
                })
             
            }
        })
    }
}
tinymce.init; // 初始化
const content = ref(props.modelValue)
watch(props, (newVal) => content.value = newVal.modelValue)
watch(content, (newVal) => emit("update:modelValue", newVal))
</script>
<style>
.tox-tinymce-aux {
    z-index: 9999 !important;
}
</style>


调用content.vue

<template>
    <FormDrawer ref="formDrawerRef" title="设置商品详情" @submit="submit" destroy-on-close>
         <el-form :model="form">
            <el-form-item >
                <Editor v-model="form.content"/>
            </el-form-item>
        </el-form>
    </FormDrawer>
</template>
<script setup>
import { reactive, ref } from 'vue';
import FormDrawer from '~/components/FormDrawer.vue';
import {readGoods,updateGoods} from '~/api/goods.js'
import Editor from '~/components/Editor.vue';
import { toast } from '~/composables/util';
const formDrawerRef=ref(null)
const form=reactive({
    content:''
})
const goodsId=ref(0)
const open=(row)=>{
    goodsId.value=row.id
    row.contentLoading=true
    readGoods(goodsId.value).then(res=>{
       form.content=res.content
        formDrawerRef.value.open()
    }).finally(()=>{
        row.contentLoading=false
    })
   
}
const emit=defineEmits(['reloadData'])

const submit=()=>{
    formDrawerRef.value.showLoading()
    updateGoods(goodsId.value,form)
    .then(res=>{
        toast('设置商品详情成功')
        formDrawerRef.value.close()
        emit('reloadData')
    })
    .finally(()=>{
        formDrawerRef.value.hideLoading()
    })
}
defineExpose({
    open
})
</script>

vue3使用打印功能

npm install vue3-print-nb --save

全局引入(main)

// 1. 全局挂载
import { createApp } from 'vue'
import App from './App.vue'
import print from 'vue3-print-nb'
const app = createApp(App)
app.use(print)
app.mount('#app')
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时光浅止

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值