diff --git a/css/edit.css b/css/edit.css
index 7b41f19..bfb171a 100644
--- a/css/edit.css
+++ b/css/edit.css
@@ -86,7 +86,7 @@
padding-left: 25px;
position: sticky;
top: 0;
- z-index: 10;
+ z-index: 1;
}
#edit .edit-container #editor—wrapper .editor-toolbar .w-e-panel-content-emotion {
width: 490px;
@@ -118,7 +118,6 @@
color: #000000;
line-height: 23px;
margin-right: 40px;
- position: relative;
padding: 0;
}
#edit .edit-container #editor—wrapper .editor-toolbar .toolbar-item .icon {
diff --git a/css/edit.less b/css/edit.less
index 804a918..c9e541f 100644
--- a/css/edit.less
+++ b/css/edit.less
@@ -96,7 +96,8 @@
padding-left: 25px;
position: sticky;
top: 0;
- z-index: 10;
+ // z-index: 10;
+ z-index: 1;
.w-e-panel-content-emotion {
width: 490px;
}
@@ -139,7 +140,7 @@
color: #000000;
line-height: 23px;
margin-right: 40px;
- position: relative;
+ // position: relative;
padding: 0;
> button {
diff --git a/edit.html b/edit.html
index 98c764a..0c0e4fb 100644
--- a/edit.html
+++ b/edit.html
@@ -34,10 +34,11 @@
-
+
@@ -89,11 +90,12 @@
{{ emoji }}
-->
+
-
+
diff --git a/js/edit.js b/js/edit.js
index 5934fe5..5c566e7 100644
--- a/js/edit.js
+++ b/js/edit.js
@@ -1,9 +1,54 @@
// 简单版本的论坛编辑器,确保图片插入功能正常
const { createApp, ref, computed, onMounted, nextTick, onUnmounted } = Vue;
import { headTop } from "../component/head-top/head-top.js";
-const { createEditor, createToolbar } = window.wangEditor;
+const { createEditor, createToolbar, SlateTransforms, Boot, SlateEditor } = window.wangEditor;
console.log("createEditor", createEditor);
+
+class MyButtonMenu { // JS 语法
+ constructor() {
+ this.title = '居中' // 自定义菜单标题
+ // this.iconSvg = '' // 可选
+ this.tag = 'button'
+ }
+
+ // 获取菜单执行时的 value ,用不到则返回空 字符串或 false
+ getValue(editor) {
+ // console.log("getValue", editor);
+
+ // TS 语法
+ // getValue(editor) { // JS 语法
+ return ' hello '
+ }
+
+ // 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false
+ isActive(editor) {
+ console.log("isActive", editor.getFragment()?.[0]);
+ if (editor.getFragment()?.[0]?.textAlign == 'center') return true
+ return false
+ }
+
+ // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false
+ isDisabled(editor) {
+ // TS 语法
+ // isDisabled(editor) { // JS 语法
+ return false
+ }
+
+ // 点击菜单时触发的函数
+ exec(editor, value) {
+ // center
+ let align = this.isActive(editor) ? 'left' : 'center'
+ console.log("align", this.isActive(editor));
+
+ SlateTransforms.setNodes(editor, {
+ textAlign: align
+ },)
+ }
+}
+
+
+
const editApp = createApp({
setup() {
let titleLength = ref(200);
@@ -160,15 +205,6 @@ const editApp = createApp({
if (!src) {
return;
}
-
- // 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); // 文件名
-
await setTimeout(() => {
console.log("1111");
return true;
@@ -189,47 +225,26 @@ const editApp = createApp({
// 3. 返回 undefined(即没有任何返回),说明检查未通过,编辑器会阻止插入。但不会提示任何信息
}
- // 【新增】判断节点的对齐方式
- const getNodeAlign = (node) => {
- if (!node) return "left"; // 默认居左
- // 获取节点的text-align样式(优先内联样式,再取CSS计算样式)
- const inlineAlign = node.style.textAlign;
- if (inlineAlign) return inlineAlign;
+ // // 自定义转换视频
+ // const customParseVideoSrc = (src) => {
+ // console.log("customParseVideoSrc", this);
- const computedStyle = window.getComputedStyle(node);
- return computedStyle.textAlign || "left";
- };
+ // // TS 语法
+ // // function customParseVideoSrc(src) { // JS 语法
+ // if (src.includes('.bilibili.com')) {
+ // // 转换 bilibili url 为 iframe (仅作为示例,不保证代码正确和完整)
+ // const arr = location.pathname.split('/')
+ // const vid = arr[arr.length - 1]
+ // return ``
+ // }
+ // // return src
+ // return ``
- // 【新增】切换对齐方式(居中 ↔ 居左)
- const toggleAlign = () => {
- const editorInst = editor.value;
- if (!editorInst) return;
-
- // 禁用编辑器默认的居中命令
- editorInst.off("clickToolbar", "justifyCenter");
-
- // 获取当前选中的节点(优先段落/块级节点)
- const selectedNode = getSelectedNode(editorInst);
- const blockNode = DomEditor.getClosestBlock(selectedNode); // 获取块级节点(p/div等)
- if (!blockNode) return;
-
- // 判断当前对齐方式
- const currentAlign = getNodeAlign(blockNode);
-
- // 切换对齐:居中 → 居左;其他 → 居中
- const newAlign = currentAlign === "center" ? "left" : "center";
-
- // 设置节点对齐样式
- editorInst.restoreSelection(); // 恢复选区
- blockNode.style.textAlign = newAlign;
-
- // 触发编辑器更新
- editorInst.change();
- editorInst.focus(); // 保持焦点
- };
+ // // return ``;
+ // }
const editorConfig = {
- placeholder: "Type here...",
+ placeholder: "输入正文",
enabledMenus: [],
MENU_CONF: {
["emotion"]: {
@@ -293,7 +308,7 @@ const editApp = createApp({
ajax(config.url, formData).then((res) => {
const data = res.data;
console.log("上传成功:", data);
- insertFn(data.url); // 传入图片的可访问 URL
+ insertFn(`${data.url}?aid=${data.aid}`); // 传入图片的可访问 URL
});
} catch (err) {
console.error("上传出错:", err);
@@ -301,6 +316,19 @@ const editApp = createApp({
},
},
+ ['insertVideo']: {
+ onInsertedVideo(videoNode) {
+ // TS 语法
+ // onInsertedVideo(videoNode) { // JS 语法
+ if (videoNode == null) return
+
+ const { src } = videoNode
+ console.log('inserted video', src)
+ },
+ // checkVideo: customCheckVideoFn, // 也支持 async 函数
+ // parseVideoSrc: (src) => customParseVideoSrc(src), // 也支持 async 函数
+ },
+
["uploadVideo"]: {
server: uConfigData.url,
@@ -343,26 +371,14 @@ const editApp = createApp({
// 步骤3:再上传第一帧封面(type 传 'cover',按后端要求调整)
const coverUploadRes = await uploading(coverFile, coverFile.name, "image");
console.log("封面上传成功", coverUploadRes);
+ console.log(insertFn);
- insertFn(videoUploadRes.url, coverUploadRes.url);
+ insertFn(`${videoUploadRes.url}?aid=${videoUploadRes.aid}`, `${coverUploadRes.url}?aid=${coverUploadRes.aid}`);
} catch (err) {
console.error("上传出错:", err);
}
},
},
-
- ["justifyCenter"]: {
- onClick: (editor) => {
- console.log("editor", editor);
- toggleAlign(); // 替换为自定义切换逻辑
- },
- // 【可选】自定义居中按钮的激活状态(选中时高亮)
- isActive: (editor) => {
- const selectedNode = getSelectedNode(editor);
- const blockNode = DomEditor.getClosestBlock(selectedNode);
- return blockNode && getNodeAlign(blockNode) === "center";
- },
- },
},
onChange(editor) {
@@ -404,16 +420,34 @@ const editApp = createApp({
// "uploadVideo", // 插入视频
"insertLink", // 插入链接
"bold", // 粗体
- "justifyCenter",
+ // "justifyCenter",
],
};
+ const menu1Conf = {
+ key: 'customCenter', // 定义 menu key :要保证唯一、不重复(重要)
+ factory() {
+ return new MyButtonMenu() // 把 `YourMenuClass` 替换为你菜单的 class
+ },
+ }
+ Boot.registerMenu(menu1Conf)
+ console.log(toolbarConfig, "toolbarConfig");
+
+ toolbarConfig.insertKeys = {
+ index: 7, // 插入的位置,基于当前的 toolbarKeys
+ keys: ['customCenter'],
+ }
const toolbar = createToolbar({
editor,
selector: "#toolbar-container",
config: toolbarConfig,
mode: "default",
});
+
+
+
+
+
console.log("editor.commands", editor);
nextTick(() => {
@@ -447,10 +481,10 @@ const editApp = createApp({
boldItem.classList.add("toolbar-item", "flexacenter");
bold.innerHTML = '
粗体';
- const justifyCenter = toolbarRef.value.querySelector('[data-menu-key="justifyCenter"]');
- const justifyCenterItem = justifyCenter.parentElement;
- justifyCenterItem.classList.add("toolbar-item", "flexacenter");
- justifyCenter.innerHTML = '
居中';
+ const customCenter = toolbarRef.value.querySelector('[data-menu-key="customCenter"]');
+ const customCenterItem = customCenter.parentElement;
+ customCenterItem.classList.add("toolbar-item", "flexacenter");
+ customCenter.innerHTML = '
居中';
});
};
@@ -549,7 +583,7 @@ const editApp = createApp({
try {
const DomEditor = window.wangEditor && window.wangEditor.DomEditor;
if (DomEditor && editor) node = DomEditor.getSelectionNode(editor);
- } catch (e) {}
+ } catch (e) { }
if (!node) {
const sel = window.getSelection();
if (sel && sel.rangeCount) node = sel.getRangeAt(0).commonAncestorContainer;
@@ -844,7 +878,7 @@ const editApp = createApp({
let format = ref("");
const submit = (status) => {
const infoTarget = { ...info.value } || {};
- let content = editorRef.value.innerHTML;
+ let content = editor.getHtml()
const images = extractImages(editorRef.value);
const videos = extractVideos(editorRef.value);
@@ -925,14 +959,20 @@ const editApp = createApp({
const imgElements = dom.querySelectorAll("img");
imgElements.forEach((imgEl) => {
- const url = imgEl.getAttribute("src")?.trim() || "";
- const aid = imgEl.dataset.aid?.trim() || ""; // 用 dataset 简化自定义属性读取
+ let url = imgEl.getAttribute("src")?.trim() || "";
+ const urlObj = new URL(url);
+ const aid = urlObj.searchParams.get('aid');
+ const queryIndex = url.indexOf('?');
+ const cleanUrl = queryIndex !== -1 ? url.substring(0, queryIndex) : url;
images.push({
- url,
+ url: cleanUrl,
aid: Number(aid),
});
});
+
+ console.log("提取完成的图片列表:", images);
+
return images;
};
@@ -943,16 +983,27 @@ const editApp = createApp({
// 2. 遍历每个 video 节点,直接获取属性
videoElements.forEach((videoEl) => {
- const url = videoEl.getAttribute("src")?.trim() || ""; // 视频地址
- const posterurl = videoEl.getAttribute("poster")?.trim() || ""; // 封面图
- const aid = videoEl.getAttribute("aid")?.trim() || ""; // 视频 ID(自定义属性)
- const posterid = videoEl.getAttribute("posterid")?.trim() || ""; // 封面 ID(自定义属性)
+ const posterurl = videoEl.getAttribute("poster")?.trim() || ""; // 视频地址
+ // 1. 用 URL 构造函数解析链接(自动处理查询参数)
+ const urlObj = new URL(posterurl);
+ // 2. 获取 aid 参数(get 方法找不到时返回 null)
+ const posterid = urlObj.searchParams.get('aid');
+ const sourceEl = videoEl.querySelector('source');
+
+ const url = sourceEl.getAttribute('src') || null;
+ const obj = new URL(url);
+ // 2. 获取 aid 参数(get 方法找不到时返回 null)
+ const aid = obj.searchParams.get('aid');
+ const queryIndex = url.indexOf('?');
+ const cleanUrl = queryIndex !== -1 ? url.substring(0, queryIndex) : url;
+ const queryIndex2 = posterurl.indexOf('?');
+ const cleanPosterurl = queryIndex2 !== -1 ? posterurl.substring(0, queryIndex2) : posterurl;
result.push({
aid: Number(aid),
posterid: Number(posterid),
- url,
- posterurl,
+ url: cleanUrl,
+ posterurl: cleanPosterurl,
});
});
@@ -1094,14 +1145,21 @@ const editApp = createApp({
});
};
- const linkClick = () => {};
+ const linkClick = () => { };
const overstriking = () => {
console.log("加粗");
- editor.addMark("bold", true); // 加粗
+ // editor.addMark("bold", true); // 加粗
// editor.addMark("color", "#999"); // 文本颜色
- console.log("editor", editor.addMark);
+ // console.log("editor", editor.addMark);
+
+ // editor.addMark('justifyCenter', true) // 加粗
+ console.log(SlateTransforms.setNodes, editor);
+
+ SlateTransforms.setNodes(editor, {
+ textAlign: 'right'
+ },)
};
return { toolbarRef, overstriking, isH1, 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 };