u
This commit is contained in:
1 parent
62550b8182
commit
3e172a1d53
26 files changed
+4820
-413
No files matched your search
@@ -0,0 +1,236 @@
|
||||
<script setup>
|
||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import {
|
||||
computed,
|
||||
defineExpose,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
ref,
|
||||
shallowRef,
|
||||
watch,
|
||||
} from "vue";
|
||||
|
||||
import { uploadFile, uploadImage, uploadVideo } from "@/utils/file";
|
||||
import { registerPreviewMenu, toolbarConfig } from "./config";
|
||||
import Direcotry from "./modules/directory.vue";
|
||||
import Preview from "./modules/preview.vue";
|
||||
import "@wangeditor/editor/dist/css/style.css";
|
||||
|
||||
const props = defineProps({
|
||||
displayMode: {
|
||||
type: String,
|
||||
default: "edit", // edit / view
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
showDirecotry: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
moduleId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
father: {
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const previewHtml = ref("");
|
||||
const showPreview = ref(false);
|
||||
|
||||
// 内容
|
||||
const valueHtml = ref("");
|
||||
|
||||
onMounted(() => {
|
||||
registerPreviewMenu(() => {
|
||||
previewHtml.value = valueHtml.value;
|
||||
showPreview.value = true;
|
||||
});
|
||||
});
|
||||
|
||||
// 编辑器实例
|
||||
const editorRef = shallowRef();
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
valueHtml.value = val;
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
const toolbarClass = computed(() =>
|
||||
props.displayMode === "view" ? "toolbar-view" : "toolbar-edit",
|
||||
);
|
||||
|
||||
const editorClass = computed(() => (props.displayMode === "view" ? "editor-view" : "editor-edit"));
|
||||
|
||||
defineExpose({
|
||||
getText: () => {
|
||||
return editorRef.value ? editorRef.value.getText() : "";
|
||||
},
|
||||
});
|
||||
|
||||
function handleChange() {
|
||||
emit("update:modelValue", valueHtml.value);
|
||||
}
|
||||
|
||||
// ================= 编辑器配置 =================
|
||||
const editorConfig = {
|
||||
placeholder: props.displayMode === "edit" ? "请输入内容..." : "",
|
||||
readOnly: props.displayMode === "view",
|
||||
MENU_CONF: {},
|
||||
};
|
||||
|
||||
// 图片上传
|
||||
editorConfig.MENU_CONF.uploadImage = {
|
||||
async customBrowseAndUpload(insertFn) {
|
||||
try {
|
||||
const data = await uploadImage();
|
||||
if (!data) return;
|
||||
|
||||
const res = await uploadFile(
|
||||
data.blob,
|
||||
data.fileName,
|
||||
data.fileExt,
|
||||
data.fileSize,
|
||||
0,
|
||||
props.moduleId,
|
||||
props.father,
|
||||
"",
|
||||
);
|
||||
insertFn(res.mx_mapfilename, res.mx_filename, "");
|
||||
} catch (e) {
|
||||
ElMessage.error("图片上传失败");
|
||||
console.log(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 视频上传
|
||||
editorConfig.MENU_CONF.uploadVideo = {
|
||||
async customBrowseAndUpload(insertFn) {
|
||||
try {
|
||||
const data = await uploadVideo();
|
||||
if (!data) return;
|
||||
|
||||
const res = await uploadFile(
|
||||
data.blob,
|
||||
data.fileName,
|
||||
data.fileExt,
|
||||
data.fileSize,
|
||||
0,
|
||||
props.moduleId,
|
||||
props.father,
|
||||
"",
|
||||
);
|
||||
insertFn(res.mx_mapfilename, res.mx_filename, "");
|
||||
} catch (e) {
|
||||
ElMessage.error("视频上传失败");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// 销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value;
|
||||
if (editor) editor.destroy();
|
||||
});
|
||||
|
||||
function handleCreated(editor) {
|
||||
editorRef.value = editor;
|
||||
nextTick(() => {});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-loading="false" class="w-full h-full editor-container">
|
||||
<div class="main">
|
||||
<Toolbar
|
||||
v-if="props.displayMode === 'edit'"
|
||||
class="toolbar"
|
||||
:class="toolbarClass"
|
||||
:editor="editorRef"
|
||||
:default-config="toolbarConfig"
|
||||
/>
|
||||
<Editor
|
||||
key="main"
|
||||
v-model="valueHtml"
|
||||
class="editor"
|
||||
:class="editorClass"
|
||||
:default-config="editorConfig"
|
||||
@on-change="handleChange"
|
||||
@on-created="handleCreated"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Direcotry v-if="showDirecotry" v-model:content="valueHtml" class="directory" />
|
||||
</div>
|
||||
|
||||
<Preview v-model:visible="showPreview" :content="previewHtml" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.toolbar {
|
||||
}
|
||||
|
||||
.toolbar-view {
|
||||
}
|
||||
|
||||
.toolbar-edit {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.editor {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
/* 原来 .editor 内嵌的 :deep */
|
||||
.editor :deep(.w-e-text-container video) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.editor-view {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* 原来 .editor-view 内嵌的 :deep */
|
||||
.editor-view :deep(.w-e-text-container) {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.editor-view :deep(.w-e-text-container .w-e-scroll [data-slate-editor]) {
|
||||
overflow-y: auto;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.editor-edit {
|
||||
height: 500px !important;
|
||||
border: 1px solid #ccc;
|
||||
border-top: transparent;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
display: flex;
|
||||
gap: 44px;
|
||||
}
|
||||
|
||||
/* 原来 .editor-container 内嵌的 .directory */
|
||||
.editor-container .directory {
|
||||
width: 200px;
|
||||
height: 450px;
|
||||
}
|
||||
|
||||
/* 原来 .editor-container 内嵌的 .main */
|
||||
.editor-container .main {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user