数通互联化工云平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

195 lines
7.2 KiB

<!--
@ 作者: 秦东
@ 时间: 2023-09-19 13:09:24
@ 备注:
-->
<script lang='ts' setup>
import { onMounted, watch, ref, computed, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { newUploadFileApi } from '@/api/file/index'
const props = withDefaults(
defineProps<{
modelValue: string
placeholder?: string
width?: string
height?: string
blobUrl?: string
imgUrl?: string
config?: any
}>(),
{
modelValue: '',
placeholder: '请输入内容',
width: '100%',
height: '300px',
blobUrl: '',
imgUrl: '',
config: () => {
return {}
}
}
)
const emits = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
const contentValue = ref(props.modelValue)
// 参数自定义初始化
// eslint-disable-next-line max-len
const buttonPlugins ='preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media code codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave '
// 导入工具栏
// eslint-disable-next-line max-len
const toolbar ='fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor table image | alignleft aligncenter alignright alignjustify outdent indent | styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | media charmap emoticons pagebreak insertdatetime print preview | code selectall searchreplace visualblocks | indent2em lineheight formatpainter axupimgs'
const toolbarSimple ='undo cut copy paste pastetext |forecolor backcolor bold italic underline strikethrough|alignleft aligncenter alignright alignjustify|'
const commInit = {
selector: '#myTextarea',
cleanup: true,
language: 'zh_CN', // 语言类型
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px', // 字体大小
lineheight_formats: '0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5', // 行高配置,也可配置成"12px 14px 16px 20px"这种形式
branding: false, // tiny技术支持信息是否显示
resize: false, // 编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
// statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
elementpath: false, // 元素路径是否显示
height: props.height, // 允许外界传进来高度和placeholder
width: props.width,
placeholder: props.placeholder,
init_instance_callback: (editor: any) => {
// editor.setContent('')
editor.on('NodeChange Change KeyUp SetContent', () => {
contentValue.value = editor.getContent()
emits('update:modelValue', editor.getContent())
})
}
}
// 图片上传
const imgUploadFn = (blobInfo: any, progress: number) =>
new Promise((resolve, reject) => {
// https://www.tiny.cloud/docs/tinymce/6/file-image-upload/#images_upload_handler
// console.log("图片上传",progress)
const params = new FormData()
params.append('file', blobInfo.blob())
params.append('type',"1")
let options = {}
if (props.imgUrl) {
options = {
url: props.imgUrl
}
}
newUploadFileApi(params)
.then(res =>{
// console.log("上传图片",res.data)
resolve(res.data.url)
})
.catch(()=>{
reject('上传出错,请查看你上传的文件是否符合要求!')
})
})
const fileUpload = (callback: any, value: string, meta: any) => {
const filetype ='.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4'
//后端接收上传文件的地址
const input = document.createElement('input') //创建文件选择
input.setAttribute('type', 'file')
input.setAttribute('accept', filetype)
input.click()
input.onchange = () => {
const file = input?.files && input.files[0] //获取文件信息
let attr = {}
if (meta.filetype === 'file') {
attr = { text: file?.name }
}
if (meta.filetype === 'image') {
attr = { alt: file?.name }
}
if (meta.filetype === 'media') {
// attr={source2: 'alt.ogg', poster: 'image.jpg'}
}
const params = new FormData()
params.append('file', file as any)
let options = {}
if (props.blobUrl) {
options = {
url: props.blobUrl
}
}
newUploadFileApi(params)
.then(res =>{
// console.log("后端接收上传文件的地址",res.data)
callback(res.data.url, attr)
})
.catch(res => {
ElMessage.error(res.data?.msg)
})
}
}
const defaultInit = {
plugins: buttonPlugins, // 插件配置
toolbar: toolbar, // 工具栏配置,设为false则隐藏
menubar: false, // 菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
//emoticons_database_url: './tinymce/emoticons/js/emojis.js',
// eslint-disable-next-line max-len
font_formats:'微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;', // 字体样式 微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif, 宋体=simsun,serif,仿宋体=FangSong,黑体=SimHei,Arial=arial,
// content_style: 'p {margin-block-start: 0; margin-block-end: 0; color: #606D81; font-size: 14px;}; table { border: 1px}', // 直接自定义可编辑区域的css样式
content_css: false, // 以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入
paste_data_images: true, // 图片是否可粘贴
// 允许外界传进来高度和placeholder
// 粘贴图片 自动处理 base64
urlconverter_callback: (url: string, node: string) => {
if (node === 'img' && url.startsWith('blob:')) {
// @ts-ignore
tinymce.activeEditor && tinymce.activeEditor.uploadImages()
}
return url
},
// 图片上传
images_upload_handler: imgUploadFn,
file_picker_types: 'file image media', //分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数
file_picker_callback: fileUpload
}
const simpleInit = {
plugins: '', // 插件配置
toolbar: toolbarSimple, // 工具栏配置,设为false则隐藏
menubar: false, // 菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看
font_formats: '',
paste_data_images: false // 图片是否可粘贴
}
const myInit = computed(() => {
const styleType =
props.config?.style === 'simple' ? simpleInit : defaultInit
return Object.assign(commInit, styleType)
})
onMounted(() => {
// @ts-ignore
tinymce.init(myInit.value)
})
onUnmounted(() => {
// @ts-ignore
tinymce.remove()
})
// 侦听默认值 外界第一次传进来一个 v-model 就赋值给 contentValue
watch(
() => props.modelValue,
(n: any) => {
if (n && n !== contentValue.value) {
contentValue.value = n
}
}
)
</script>
<template>
<textarea id="myTextarea" v-model="contentValue"></textarea>
</template>
<style lang='scss' scoped>
.tox-tinymce-aux {
z-index: 99999 !important; /*el-dialog层为2014,默认时在el弹出层显示不了编辑器里的弹窗*/
z-index: 99999;
}
</style>