vue3 markdown编辑器编辑,保存;后端存数据库(解析指定内容)并前端预览下载
话接上篇,搞出来pdf文档展示,然后跟产品演示
产品:不行,这根本没法用,我要目录生成,并且跳转到指定内容,并且能搜索,能复制;
ps:提需求的时候不说,做完了演示的时候说了 :)
我:那pdf做不了。。。。;
产品:那你自己想想其他方案吧,文档格式不限;
我:????最开始不是要pdf么;
话不多说,换新的方案,我第一个想到的就是之前搞过的docsify,支持生成目录跳转,展示,搜索,能复制,就是图片是个问题,搜前端组件的时候,搜到了v-md-editor,大概看了官方文档,普通用法和高级用法,感觉可行,开搞!
实现思路: 产品、运维使用编辑器编辑文档(测试环境),保存本地,然后上传到服务器,然后v-md-preview展示
主要的就是前端处理,后端都好弄(vue3+ts +springboot)
前端使用组件: v-md-editor
# 使用 npm
npm i @kangc/v-md-editor@next -S
# 使用 yarn
yarn add @kangc/v-md-editor@next
import { createApp } from 'vue';
import VueMarkdownEditor from '@kangc/v-md-editor';
import '@kangc/v-md-editor/lib/style/base-editor.css';
import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js';
import '@kangc/v-md-editor/lib/theme/style/vuepress.css';
import Prism from 'prismjs';
VueMarkdownEditor.use(vuepressTheme, {
Prism,
});
const app = createApp(/*...*/);
app.use(VueMarkdownEditor);
v-md-editor 编辑器实现线上编辑,然后写回调函数,增加v-md-editord的保存本地和上传本地图片的方法(组件支持的扩展)
v-md-editor 中添加@save=“mdEdit(text)” @upload-image=“handleUploadImage”
因为md文件上传到服务器的时候图片不会上传,只是携带者链接,所以转base64并将其放到md文件中,显示的会很乱,但是没办法(菜单都是固定一个文档,而且只有产品、运维上传操作,其他不开放权限,而且修改频率比较低,用户只是展示,文档还好,都不是很大)
代码如下:
function handleUploadImage(event: Event,insertImage:any, files:Array<File>){
if(files.length>1){
return;
}else if(files.length == 0){
return;
}else{
const file = files[0];
const rader = new FileReader();
reader.readAsDataURL(File);
reader.onload = (e:any)=>{
const base64 = e.target.result;
insertImage({
url:base64,
desc:''
});
}
}
}
代码如下:
const mdEdit = (text:any) =>{
const blob = new blob([text],{type:"text/plain;charset=utf-8"});
const fileName = "templare"+newData().getTime()+".md";
const link = window.URL.createObjectURL(blob);
//保存本地文件
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);//释放blob对象
}
代码如下:
空巷一人
// 获取导航
function getAnchors() {
const anchors = (preview.value.$el as Element).querySelectorAll('h1,h2,h3,h4,h5,h6')
const titles = Array.from(anchors).filter((title: any) => !!title.innerText.trim())
if (!titles.length) {
t.titles = []
return
}
const hTags = Array.from(new Set(titles.map((title) => title.tagName))).sort()
t.titles = titles.map((el: any) => ({
title: el.innerText,
lineIndex: el.getAttribute('data-v-md-line'),
indent: hTags.indexOf(el.tagName)
}))
console.log( t.titles);
}
// 点击导航
function handleAnchorClick(anchor: { title: string; lineIndex: string; indent: number }) {
const { lineIndex } = anchor
const heading = preview.value.$el.querySelector(`[data-v-md-line="${lineIndex}"]`)
if (heading) {
preview.value.scrollToTarget({
target: heading,
scrollContainer: window,
top: 60
})
}
}
获取导航vue代码:
官网上的跳转锚点怎么都不生效,后来在v-md-editor交流群(官网有)里有大神提供了方法,给preview单独加了个div,然后在此div中设置了样式overflow:auto,接着在点击导航的方法中将scrollContainer: window ----->替换为scrollContainer: scroll 解决了这个问题!感谢大佬!
最后还有一个下载,因为后端我是将文件以流的形式存的,展示返回给前端的时候,如果是流的花会有中文乱码,试了好多种的字符集解析都没有成功,后来发现在数据库里都能正常显示,然后就将后端返回由流转换为了字符串,很简单的处理
new String(byte[])
然后前端就正常展示了,也对应生成了目录,并且可以跳转,可以复制;
上传很简单就是浏览文件,上传,很简单,就不贴了,一搜多得是
下载也是后端返回的大字符串,因为可能存在流中文乱码,也是试过几种方法,都不可行,就懒得再弄了,也是后端返回的字符串
前端处理:因为不能保存为md文件(怕用户打不开文件),因此转换为html
//引入marked 自行安装
1.安装marked
npm install marked --save
复制
2.引用
var marked = require('marked')
复制
3.转换为html
var html = marked('### hello markdown') // hello markdown
前端代码:
const downloadFile = () =>{
axios({
url:xxx,
method:"get"
}).then(res ={
var marked = require('marked')
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true, //
tables: true,
breaks: false,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: false
});
const content = marked(res.data);
const blob = new Blob([content],{type:'text/plain;charset=utf-8'});
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
cosnt fileName = "xx.html";
link.href = url;
link.download = fileName;
document.body.appendChild(link);
link.click();
link.remove();
})
}
marked参数含义:
目前转换还是丢失了样式,还在解决中,大体能看。