Files
workspace/code/email/Email-Vue/src/components/email-editor/index.vue
T
2026-01-08 17:25:31 +08:00

147 lines
4.4 KiB
Vue

<template>
<div>
<HugerteEditor ref="editorRef" :init="init" v-model="modelValue" />
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import HugerteEditor from "@/components/hugerte-editor/index";
import { uploadTempFile } from "@/service/email";
const editorRef = ref<any>(null);
const modelValue = defineModel();
const props = defineProps({
height: {
type: Number,
default: 600
},
placeholder: {
type: String,
default: "请输入内容..."
}
});
const emit = defineEmits(["upload-image"]);
function getPlainText() {
const editor = editorRef.value?.getEditor?.();
return editor?.getContent({ format: "text" }) ?? "";
}
function getHtml() {
const editor = editorRef.value?.getEditor?.();
return editor?.getContent() ?? "";
}
function clear() {
const editor = editorRef.value?.getEditor?.();
if (editor) {
editor.setContent(""); // 清空内容
}
}
defineExpose({
getHtml,
getPlainText,
clear
});
const init = {
language: "zh_CN",
height: props.height,
placeholder: props.placeholder,
menubar: false,
statusbar: false,
plugins: "accordion advlist anchor formatpainter fullscreen image link lists preview table searchreplace ",
font_size_formats: "12px 14px 16px 18px 20px 22px 24px 26px 28px 30px 32px",
font_family_formats:
"PingFang SC;微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,;sans-serif",
toolbar:
"undo redo formatpainter removeformat | " +
"blocks fontfamily fontsize | " +
"bold italic underline strikethrough superscript subscript | forecolor backcolor |hr blockquote | " +
"align lineheight | bullist numlist indent outdent table|" +
"link customImage| searchreplace preview fullscreen print",
formats: {
blockquote: {
block: "blockquote",
styles: {
"border-left": "2px solid #ccc",
margin: "1em 0",
"padding-left": "1em"
}
}
},
body_class: "my-editor-body",
toolbar_mode: "wrap",
setup: function (editor: any) {
function applyTableInlineStyles() {
const body = editor.getBody();
if (!body) return;
body.querySelectorAll("table").forEach((table: HTMLTableElement) => {
table.style.width = "100%";
table.style.borderCollapse = "collapse";
table.style.border = "1px solid #ccc";
});
body.querySelectorAll("th").forEach((th: HTMLTableElement) => {
th.style.border = "1px solid #ccc";
th.style.padding = "8px";
th.style.backgroundColor = "#f2f2f2";
th.style.textAlign = "left";
});
body.querySelectorAll("td").forEach((td: HTMLTableElement) => {
td.style.border = "1px solid #ccc";
td.style.padding = "8px";
td.style.wordBreak = "break-word"; // 更合理
td.style.whiteSpace = "normal";
});
}
// 只在执行“插入表格”命令时添加样式
editor.on("ExecCommand", (e: any) => {
if (e.command === "mceInsertTable") {
// 延迟一下让表格插入完毕
setTimeout(() => {
applyTableInlineStyles();
}, 0);
}
});
editor.ui.registry.addButton("customImage", {
icon: "image",
tooltip: "上传图片",
onAction: () => {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.click();
input.onchange = async () => {
const files = input.files;
if (!files || files.length === 0) return;
const file = files[0];
try {
const res = await uploadTempFile(file);
emit("upload-image", res.data);
editor.insertContent(`<img src="${res.data.fileUrl}" />`);
} catch (err) {
console.error("图片上传失败", err);
}
};
}
});
}
};
</script>
<style lang="scss" scoped>
.preview-iframe {
background-color: white;
}
</style>