<template>
|
<div>
|
<div style="width: 100%; height: 220px; border: 1px solid #f2f2f2">
|
<Toolbar
|
style="border-bottom: 1px solid #ccc"
|
:editor="editorRef"
|
:defaultConfig="toolbarConfig"
|
:mode="mode"
|
/>
|
<Editor
|
style="height:170px; overflow-y: hidden"
|
v-model="valueHtml"
|
:defaultConfig="editorConfig"
|
:mode="mode"
|
@onCreated="handleCreated"
|
/>
|
</div>
|
</div>
|
</template>
|
<script lang="ts" setup>
|
import {
|
ElNotification,
|
ElMessage,
|
UploadRawFile,
|
UploadRequestOptions,
|
genFileId,
|
} from 'element-plus'
|
import type {
|
FormInstance,
|
FormRules,
|
UploadInstance,
|
UploadProps,
|
UploadUserFile,
|
} from 'element-plus'
|
import { Refresh } from '@element-plus/icons-vue'
|
import { IEditorConfig } from '@wangeditor/editor'
|
import { getImgFlowUrl, getImgFlowUrlT } from '@/utils/fileFlow'
|
import '@wangeditor/editor/dist/css/style.css'
|
import { useUserInfo } from '@/stores/modules/userInfo'
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
import optionService from '@/api/zhongjian/optionApi'
|
const userInfoStore = useUserInfo()
|
const state = reactive<any>({
|
btnLoading: false,
|
})
|
const emit = defineEmits(['updateDataFun','getCurrentData'])
|
|
// 父组件props传参
|
interface Props {
|
richTextValue?: any // 可选的父组件传参
|
indexData: any
|
modelData: any
|
currentData?: any // 循环使用时使用
|
currentIndex?: any // 循环使用时使用
|
placeholder?:string
|
}
|
|
const props = withDefaults(defineProps<Props>(), {
|
richTextValue: '',
|
indexData: '',
|
modelData: '',
|
currentData: '',
|
currentIndex: '',
|
placeholder:''
|
})
|
|
//---------------------------------------
|
const mode = 'simple'
|
// 编辑器实例,必须用 shallowRef
|
const editorRef = shallowRef()
|
// 内容 HTML
|
const valueHtml = ref('')
|
|
const toolbarConfig = {
|
toolbarKeys: [
|
"headerSelect", // 头部类型选择
|
"blockquote", // 引用块
|
'|',
|
"bold", // 字体加粗
|
"underline", // 字体下划线
|
"italic", // 字体斜体
|
{
|
key: 'group-font',
|
title: '...',
|
menuKeys: ['through', 'code', 'sub', 'clearStyle'], //字体处理的四种方式
|
},
|
|
"color", // 字体颜色
|
"bgColor", // 背景颜色
|
"fontSize", // 字体大小
|
"fontFamily", // 字体
|
|
"lineHeight", // 行间距
|
'|', // 分割线
|
"bulletedList", // 无序列表
|
"numberedList", // 有序列表
|
"todo", // 待办事项
|
{
|
key: 'group-justify',
|
title: '对齐',
|
iconSvg:
|
'<svg viewBox="0 0 1024 1024"><path d="M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z"></path></svg>',
|
menuKeys: ['justifyLeft', 'justifyRight', 'justifyCenter', 'justifyJustify'], // 对齐的四种方式
|
},
|
{
|
key: 'group-indent',
|
title: '缩进',
|
iconSvg:
|
'<svg viewBox="0 0 1024 1024"><path d="M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z"></path></svg>',
|
menuKeys: ['indent', 'delIndent'], // 缩进的两种方式
|
},
|
|
'|',
|
// {
|
// key: 'group-image',
|
// title: '上传图片',
|
// iconSvg:
|
// '<svg viewBox="0 0 1024 1024"><path d="M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z"></path></svg>',
|
// menuKeys: ['uploadImage', 'insertImage'], // 对齐的四种方式
|
// },
|
'uploadImage',//上传图片
|
"redo", // 重做
|
"undo", // 撤销
|
'|',
|
|
|
]
|
};
|
|
|
const editorConfig: Partial<IEditorConfig> = {
|
placeholder:props?.placeholder||'请输入内容...',
|
MENU_CONF: {},
|
}
|
// 组件销毁时,也及时销毁编辑器
|
// onBeforeUnmount(() => {
|
// const editor = editorRef.value;
|
// if (editor == null) return;
|
// editor.destroy();
|
// });
|
onBeforeMount(() => {
|
const Biurl = import.meta.env.VITE_BI_URL as any
|
const hearderData = ref('')
|
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'prodReplace'|| process.env.NODE_ENV === 'replace') {
|
hearderData.value = '/admin'
|
} else{
|
hearderData.value = '/api'
|
}
|
//上传图片
|
editorConfig.MENU_CONF['uploadImage'] = {
|
// server: '/admin/admin/common' + "/fileUpload",
|
server: `${hearderData.value}/admin/common/fileUpload`,
|
fieldName: 'file',
|
// headers: { Authorization: "Bearer " + userInfoStore.getAdminToken},
|
headers: {
|
// 'Content-Type': 'application/json;charset=UTF-8',
|
token: userInfoStore.getAdminToken,
|
},
|
maxFileSize: 10 * 1024 * 1024,
|
base64LimitSize: 5 * 1024,
|
maxNumberOfFiles: 1,
|
allowedFileTypes: ['image/*'],
|
customInsert(res, insertFn) {
|
optionService
|
.getPicUrlUrl({
|
fileId: res.data.fileId,
|
})
|
.then((res) => {
|
console.log('res------', res)
|
if (res.code == 200) {
|
const url = res.data.fileUrl
|
insertFn(url)
|
}
|
})
|
|
// // 预览图片
|
// getImgFlowUrlT(res.data.fileId || '').then((res: any) => {
|
// console.log("查看图片-----", res)
|
// // if (window.URL.createObjectURL != undefined) {
|
// // const myBlob = new window.Blob([res.data], {type: 'image/jpeg'})
|
// // const url = window.URL.createObjectURL(myBlob)
|
// //
|
// // console.log('pic---',url)
|
// //
|
// //
|
// // }
|
// })
|
},
|
// onBeforeUpload(file) {
|
// console.log("onBeforeUpload", file);
|
// return file; // will upload this file
|
// // return false // prevent upload
|
// },
|
// onProgress(progress) {
|
// console.log("onProgress", progress);
|
// },
|
// onSuccess(file, res) {
|
// console.log("onSuccess", file, res);
|
// },
|
// onFailed(file, res) {
|
// alert(res.message);
|
// console.log("onFailed", file, res);
|
// },
|
// onError(file, err, res) {
|
// console.error("onError", file, err.message, res);
|
// }
|
}
|
//插入视频
|
editorConfig.MENU_CONF['insertVideo'] = {
|
onInsertedVideo(videoNode) {
|
},
|
}
|
//上传视频
|
editorConfig.MENU_CONF['uploadVideo'] = {
|
// server: '/admin/admin/common' + "/fileUpload",
|
server: `${hearderData.value}/admin/common/fileUpload`,
|
fieldName: 'file',
|
allowedFileTypes: ['video/*'],
|
headers: {
|
// 'Content-Type': 'application/json;charset=UTF-8',
|
token: userInfoStore.getAdminToken,
|
},
|
maxFileSize: 100 * 1024 * 1024,
|
customInsert(res, insertFn) {
|
// const videoInfo = res.data[0] || {};
|
// const {url} = videoInfo;
|
// if (!url) throw new Error(`视频的url为空`);
|
// insertFn(url + "#dsffdsfsf");
|
|
optionService
|
.getPicUrlUrl({
|
fileId: res.data.fileId,
|
})
|
.then((res) => {
|
console.log('res------', res)
|
if (res.code == 200) {
|
const url = res.data.fileUrl
|
insertFn(url + '#dsffdsfsf')
|
}
|
})
|
},
|
// onBeforeUpload(file) {
|
// console.log("onBeforeUpload", file);
|
// return file; // will upload this file
|
// // return false // prevent upload
|
// },
|
// onProgress(progress) {
|
// console.log("onProgress", progress);
|
// },
|
// onSuccess(file, res) {
|
// console.log("onSuccess", file, res);
|
// },
|
// onFailed(file, res) {
|
// alert(res.message);
|
// console.log("onFailed", file, res);
|
// },
|
// onError(file, err, res) {
|
// alert(err.message);
|
// console.error("onError", file, err, res);
|
// }
|
}
|
})
|
const handleCreated = (editor) => {
|
editorRef.value = editor // 记录 editor 实例,重要!
|
// console.log("editorRef------", editorRef.value)
|
}
|
|
// 父级调用
|
const completeFun = () => {
|
alert('11')
|
}
|
|
// 监听父级传来的
|
watch(
|
() => props.modelData,
|
(val: string) => {
|
valueHtml.value = val
|
},
|
{
|
immediate: true,
|
}
|
)
|
|
// 监听传给父级的
|
watch(
|
() => valueHtml.value,
|
(val: string) => {
|
emit('updateDataFun', val, props.indexData)
|
emit('getCurrentData', props.currentData, props.currentIndex)
|
},
|
{
|
immediate: true,
|
}
|
)
|
watch(
|
() => props.curentData,
|
(val: string) => {
|
emit('getCurrentData', val, props.currentIndex)
|
},
|
{
|
immediate: true,
|
}
|
)
|
// 将方法暴露给父组件
|
defineExpose({
|
completeFun,
|
})
|
</script>
|
<style scoped lang="scss">
|
.w-e-textarea-video-container {
|
//background-color: #00a0e9 !important;
|
}
|
</style>
|