feat(editor): 集成富文本编辑器并优化响应式布局

1. 添加wangEditor富文本编辑器替换原有简易编辑器
2. 新增编辑器相关CSS样式和功能按钮
3. 优化详情页和编辑页的响应式布局
4. 调整评论区域样式结构
5. 添加移动端适配样式
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-11-25 19:12:29 +08:00
parent 73731fbbba
commit 460450c339
12 changed files with 24728 additions and 171 deletions

View File

@@ -15,9 +15,6 @@ const appSectionIndex = createApp({
setup() {
onMounted(() => {
getUserInfoWin();
setTimeout(() => {
SignInComponent.initComponent();
}, 3000);
});
let isLogin = ref(false);

View File

@@ -1,6 +1,8 @@
// 简单版本的论坛编辑器,确保图片插入功能正常
const { createApp, ref, computed, onMounted, nextTick, onUnmounted } = Vue;
import { headTop } from "../component/head-top/head-top.js";
const { createEditor, createToolbar } = window.wangEditor;
console.log("createEditor", createEditor);
const editApp = createApp({
setup() {
@@ -12,11 +14,9 @@ const editApp = createApp({
uniqid.value = params.uniqid || "";
getUserInfoWin();
checkWConfig();
cUpload();
init();
checkWConfig();
// 添加selectionchange事件监听当鼠标选中区域内容时更新lastSelection
document.addEventListener("selectionchange", handleSelectionChange);
@@ -107,6 +107,10 @@ const editApp = createApp({
ajaxGet(`/v2/api/config/upload?type=topic`).then((res) => {
const data = res.data;
uConfigData = data;
console.log("uConfigData", uConfigData);
init();
});
};
@@ -132,15 +136,153 @@ const editApp = createApp({
info.value = infoTarget;
token.value = data.token;
nextTick(() => {
judgeIsEmpty();
});
// nextTick(() => {
// judgeIsEmpty();
// });
initEditor();
})
.catch((err) => {
console.log("err", err);
});
};
let editor = null;
const initEditor = () => {
let infoTarget = info.value || {};
console.log("infoTarget", infoTarget);
const editorConfig = {
placeholder: "Type here...",
enabledMenus: [],
MENU_CONF: {
["emotion"]: {
emotions: optionEmoji.value,
},
["uploadImage"]: {
server: uConfigData.url,
// form-data fieldName ,默认值 'wangeditor-uploaded-image'
fieldName: uConfigData.requestName,
// 单个文件的最大体积限制,默认为 2M
maxFileSize: maxSize, // 1M
// 最多可上传几个文件,默认为 100
maxNumberOfFiles: imageLength,
// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
allowedFileTypes: ["image/*", ".png", ".jpg", ".jpeg"],
// 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
meta: { ...uConfigData.params },
// 将 meta 拼接到 url 参数中,默认 false
metaWithUrl: false,
// 自定义增加 http header
headers: { accept: "application/json, text/plain, */*", ...uConfigData.headers },
// 跨域是否传递 cookie ,默认为 false
withCredentials: true,
// 超时时间,默认为 10 秒
async customUpload(file, insertFn) {
try {
let config = uConfigData;
// 1. 构造 FormData包含你的接口所需字段
const formData = new FormData();
formData.append(config.requestName, file); // 文件数据
formData.append("name", file.name); // 文件名
formData.append("type", "image"); // 文件名
formData.append("data", config.params.data); // 文件名
ajax(config.url, formData).then((res) => {
const data = res.data;
insertFn(data.url); // 传入图片的可访问 URL
});
} catch (err) {
console.error("上传出错:", err);
}
},
},
},
// 4. 链接菜单:显式启用(默认启用,补充配置防止被过滤)
link: {
disabled: false, // 确保不禁用
showTarget: true, // 显示「是否新窗口打开」选项
showRel: true, // 显示「rel 属性」选项
},
// 5. 对齐菜单:显式启用(默认启用,兜底配置)
justify: {
disabled: false,
},
onChange(editor) {
const html = editor.getHtml();
console.log("editor content", html);
// 也可以同步到 <textarea>
},
};
editor = createEditor({
selector: "#editor-container",
html: "<p><br>555</p>",
config: editorConfig,
mode: "default",
});
setTimeout(() => {
console.log("editor", editor);
editor.addMark("bold", true); // 加粗
}, 1000);
// const toolbar = DomEditor.getToolbar(editor)
const toolbarConfig = {
// toolbarKeys: ["bold", "italic", "list"],
toolbarKeys: [
"headerSelect", // 标题
"bold", // 粗体
"italic", // 斜体
// "justify", // 对齐方式
{
key: "justifyCenter",
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"],
},
"emotion", // 表情
"insertLink", // 插入链接
"uploadImage", // 插入图片
"uploadVideo", // 插入视频
"undo", // 撤销
"redo", // 重做
"fullScreen", // 全屏
],
};
const toolbar = createToolbar({
editor,
selector: "#toolbar-container",
config: toolbarConfig,
mode: "default",
});
console.log("toolbar", toolbar);
// setTimeout(() => {
// const el = document.querySelector("#toolbar-container");
// if (el && el.children.length === 0) {
// createToolbar({ editor, selector: "#toolbar-container", config: toolbarConfig, mode: "default" });
// }
// }, 0);
};
const restoreHtml = (formattedText, attachments) => {
const imageList = attachments?.images || [];
@@ -196,7 +338,7 @@ const editApp = createApp({
html = html.replace(/(<span class="blue">[^<]+<\/span>)\s+/gi, '$1 <span class="fill"></span> ');
// 7. 清理多余的<br>标签
html = html.replace(/<br><br>/g, "<br>");
// html = html.replace(/<br><br>/g, "<br>");
imageList.forEach((element) => {
html += `<img src="${element.url}" data-aid="${element.aid}"><br/>`;
@@ -218,6 +360,7 @@ const editApp = createApp({
const editorRef = ref(null);
const focusLastNode = () => {
return;
const newRange = document.createRange();
const textNode = document.createTextNode("");
editorRef.value.appendChild(textNode);
@@ -408,6 +551,7 @@ const editApp = createApp({
// 处理选中文本变化的函数
const handleSelectionChange = () => {
return;
const selection = window.getSelection();
// 确保有选中内容且选中区域在编辑器内
if (selection.rangeCount > 0) {
@@ -560,7 +704,7 @@ const editApp = createApp({
html = html.replace(/<(?!(a\b|\/a\b))[^>]+>/gi, "");
// 8. 清理连续换行(最多保留两个空行,避免过多空行)
html = html.replace(/\n{3,}/g, "\n\n");
// html = html.replace(/\n{3,}/g, "\n\n");
// 去除首尾空白
html = html.trim();
@@ -745,7 +889,15 @@ const editApp = createApp({
const linkClick = () => {};
return { linkClick, insertVideo, insertLink, linkUrl, linkText, linkState, openLink, closeLink, handleClick, uniqid, userInfoWin, titleLength, submit, emojiState, openEmoji, closeEmoji, selectEmoji, optionEmoji, isPTitle, onEditorInput, onEditorFocus, onEditorBlur, paragraphTitle, info, tagList, token, cutAnonymity, editorRef, insertImage, judgeIsEmpty, isEmpty };
const overstriking = () => {
console.log("加粗");
editor.addMark("bold", true); // 加粗
editor.addMark("color", "#999"); // 文本颜色
console.log("editor", editor.addMark);
};
return { overstriking, linkClick, insertVideo, insertLink, linkUrl, linkText, linkState, openLink, closeLink, handleClick, uniqid, userInfoWin, titleLength, submit, emojiState, openEmoji, closeEmoji, selectEmoji, optionEmoji, isPTitle, onEditorInput, onEditorFocus, onEditorBlur, paragraphTitle, info, tagList, token, cutAnonymity, editorRef, insertImage, judgeIsEmpty, isEmpty };
},
});

24129
js/editor.js Normal file

File diff suppressed because one or more lines are too long