no message
This commit is contained in:
5
css/textbus.min.css
vendored
5
css/textbus.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -1,12 +1,9 @@
|
||||
// 简单版本的论坛编辑器,确保图片插入功能正常
|
||||
const { createApp, ref, computed, onMounted, nextTick, onUnmounted } = Vue;
|
||||
const { createEditor, createToolbar, SlateTransforms, Boot, SlateEditor } = window.wangEditor;
|
||||
|
||||
const editApp = createApp({
|
||||
setup() {
|
||||
const E = window.wangEditor;
|
||||
const LANG = location.href.indexOf("lang=en") > 0 ? "en" : "zh-CN";
|
||||
E.i18nChangeLanguage(LANG);
|
||||
|
||||
const title = ref("");
|
||||
const saveStatus = ref("");
|
||||
@@ -14,7 +11,6 @@ const editApp = createApp({
|
||||
const info = ref({});
|
||||
const token = ref("");
|
||||
let editor = null;
|
||||
let toolbar = null;
|
||||
|
||||
const draftKey = "publish_admin_draft";
|
||||
let uConfigData = {};
|
||||
@@ -79,11 +75,24 @@ const editApp = createApp({
|
||||
// 提交
|
||||
const submit = (status) => {
|
||||
const infoTarget = { ...info.value } || {};
|
||||
let content = editor.getHtml();
|
||||
|
||||
// 获取 TextBus 内容
|
||||
// TextBus 1.0: editor.getContents().content
|
||||
// Fallback to generic HTML retrieval if needed
|
||||
let content = "";
|
||||
if (editor && typeof editor.getContents === 'function') {
|
||||
const contents = editor.getContents();
|
||||
content = (typeof contents === 'string') ? contents : (contents.content || "");
|
||||
} else if (editor && typeof editor.getHTML === 'function') {
|
||||
content = editor.getHTML();
|
||||
}
|
||||
|
||||
const editorDom = document.getElementById("editor-text-area");
|
||||
const images = extractImages(editorDom);
|
||||
const videos = extractVideos(editorDom);
|
||||
// 临时创建一个 div 来解析 content 中的图片和视频
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = content;
|
||||
|
||||
const images = extractImages(tempDiv);
|
||||
const videos = extractVideos(tempDiv);
|
||||
|
||||
infoTarget.attachments = infoTarget.attachments || {};
|
||||
infoTarget.attachments.images = images;
|
||||
@@ -222,178 +231,249 @@ const editApp = createApp({
|
||||
};
|
||||
|
||||
const initEditor = () => {
|
||||
const maxSize = 1 * 1024 * 1024; // 1M
|
||||
if (!window.textbus) {
|
||||
console.error("TextBus is not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
const editorConfig = {
|
||||
// 自定义 HTML 处理规则
|
||||
htmlFilter: {
|
||||
// 保留 img 标签(核心)
|
||||
tags: {
|
||||
img: true, // true 表示不过滤该标签,也可配置具体属性白名单
|
||||
},
|
||||
// 更精细控制:指定 img 允许的属性(避免过滤关键属性)
|
||||
attrs: {
|
||||
img: ["src", "alt", "width", "height", "data-id", "class"], // 按需添加自定义属性
|
||||
},
|
||||
},
|
||||
// 关闭「粘贴/插入 HTML 时自动清理空标签」(若 img 暂未赋值 src 可能触发)
|
||||
autoFormatAfterInit: false,
|
||||
autoFormatOnEditable: false,
|
||||
placeholder: "输入正文",
|
||||
// scroll: true, // 禁止编辑器滚动
|
||||
MENU_CONF: {
|
||||
["emotion"]: {
|
||||
emotions: ["😀", "😁", "😆", "😅", "😂", "😉", "😍", "🥰", "😘", "🤥", "😪", "😵💫", "🤓", "🥺", "😋", "😜", "🤪", "😎", "🤩", "🥳", "😔", "🙁", "😭", "😡", "😳", "🤗", "🤔", "🤭", "🤫", "😯", "😵", "🙄", "🥴", "🤢", "🤑", "🤠", "👌", "✌️", "🤟", "🤘", "🤙", "👍", "👎", "✊", "👏", "🤝", "🙏", "💪", "❎️", "✳️", "✴️", "❇️", "#️⃣", "*️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟", "🆗", "🈶", "🉐", "🉑", "🌹", "🥀", "🌸", "🌺", "🌷", "🌲", "☘️", "🍀", "🍁", "🌙", "⭐", "🌍", "☀️", "⭐️", "🌟", "☁️", "🌈", "☂️", "❄️", "☃️", "☄️", "🔥", "💧", "🍎", "🍐", "🍊", "🍉", "🍓", "🍑", "🍔", "🍟", "🍕", "🥪", "🍜", "🍡", "🍨", "🍦", "🎂", "🍰", "🍭", "🍿", "🍩", "🧃", "🍹", "🍒", "🥝", "🥒", "🥦", "🥨", "🌭", "🥘", "🍱", "🍢", "🥮", "🍩", "🍪", "🧁", "🍵", "🍶", "🍻", "🥂", "🧋", "🎉", "🎁", "🧧", "🎃", "🎄", "🧨", "✨️", "🎈", "🎊", "🎋", "🎍", "🎀", "🎖️", "🏆️", "🏅", "💌", "📬", "🚗", "🚕", "🚲", "🛵", "🚀", "🚁", "⛵", "🚢", "🔮", "🧸", "🀄️"],
|
||||
},
|
||||
content: info.value?.content || "",
|
||||
// 配置工具栏:去除音频、源码、组件库、插入段落
|
||||
// 根据 TextBus 文档,配置 providers.provide 可以在一定程度上控制工具栏,
|
||||
// 但对于标准版 @textbus/editor,最直接的方式是使用 toolbar 配置项(如果支持)
|
||||
// 或者通过 CSS 隐藏不需要的按钮(作为兜底方案,因为 CDN 版本配置灵活性有限)
|
||||
|
||||
// 尝试配置工具栏项,仅保留需要的
|
||||
// 注意:TextBus 的工具栏配置键名可能需要根据具体版本调整
|
||||
// 下面是一个常见的 TextBus 工具栏配置示例
|
||||
toolbar: [
|
||||
['undo', 'redo'],
|
||||
['bold', 'italic', 'underline', 'strikeThrough'],
|
||||
['heading'],
|
||||
['ol', 'ul'],
|
||||
['fontSize', 'fontFamily', 'color', 'backgroundColor'],
|
||||
['image'], // 先放图片
|
||||
['video'], // 再放视频
|
||||
['link', 'unlink'],
|
||||
['textAlign', 'textIndent'],
|
||||
['table'],
|
||||
// ['clean'], // 去掉清除格式
|
||||
// ['source'], // 去掉源码
|
||||
// ['audio'], // 去掉音频 (TextBus 默认可能有也可能没有,这里显式不加)
|
||||
// ['block'], // 去掉插入段落/组件库
|
||||
],
|
||||
|
||||
["insertImage"]: {
|
||||
onInsertedImage(imageNode) {
|
||||
const { src, alt, url, href } = imageNode;
|
||||
},
|
||||
uploader: function (type) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 1. 数量限制检查
|
||||
let content = "";
|
||||
if (editor && typeof editor.getContents === 'function') {
|
||||
const contents = editor.getContents();
|
||||
content = (typeof contents === 'string') ? contents : (contents.content || "");
|
||||
} else if (editor && typeof editor.getHTML === 'function') {
|
||||
content = editor.getHTML();
|
||||
}
|
||||
|
||||
async parseImageSrc(src) {
|
||||
console.log("parseImageSrc");
|
||||
// 如果图片链接中已经包含了 ?aid= ,则说明是本站图片,直接返回,无需处理
|
||||
if (src.includes("?aid=")) return src;
|
||||
console.log("parseImageSrc");
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = content;
|
||||
|
||||
// 对于不含 ?aid= 的外部图片,执行上传转换
|
||||
console.log("uConfigData", uConfigData);
|
||||
if (type === 'image') {
|
||||
const currentImages = tempDiv.querySelectorAll('img').length;
|
||||
if (currentImages >= imageLength) {
|
||||
creationAlertBox("error", `最多只能上传 ${imageLength} 张图片`);
|
||||
return;
|
||||
}
|
||||
} else if (type === 'video') {
|
||||
const currentVideos = tempDiv.querySelectorAll('video').length;
|
||||
if (currentVideos >= videoLength) {
|
||||
creationAlertBox("error", `最多只能上传 ${videoLength} 个视频`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 视频上传逻辑
|
||||
if (type === 'video') {
|
||||
const fileInput = document.createElement("input");
|
||||
fileInput.setAttribute("type", "file");
|
||||
fileInput.setAttribute("accept", "video/*");
|
||||
fileInput.style.cssText = "position: absolute; left: -9999px; top: -9999px; opacity: 0";
|
||||
|
||||
document.body.appendChild(fileInput);
|
||||
|
||||
fileInput.onchange = async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
if (!uConfigData || !uConfigData.url) return src;
|
||||
console.log("parseImageSrc");
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append("uploadType", "url");
|
||||
formData.append("url", src);
|
||||
if (uConfigData.params && uConfigData.params.data) {
|
||||
formData.append("data", uConfigData.params.data);
|
||||
// 大小限制检查 (视频通常允许更大,这里暂时统一限制,如需单独限制请调整)
|
||||
const maxSize = 1 * 1024 * 1024; // 1M
|
||||
if (file.size > maxSize) {
|
||||
creationAlertBox("error", "文件大小不能超过 1MB");
|
||||
document.body.removeChild(fileInput);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await ajax(uConfigData.url, formData);
|
||||
if (res.code == 200 && res.data) return `${res.data.url}?aid=${res.data.aid}`;
|
||||
else {
|
||||
creationAlertBox("error", res.message || "操作失败");
|
||||
return "";
|
||||
|
||||
try {
|
||||
// 1. 上传视频文件
|
||||
const res = await uploading(file, file.name, "video");
|
||||
const videoUrl = res.url + (res.aid ? `?aid=${res.aid}` : '');
|
||||
|
||||
// 2. 尝试获取封面 (可选)
|
||||
// TextBus 插入视频通常只需要 URL,或者 { src, poster }
|
||||
// 由于 uploading 返回的是 URL,我们直接返回
|
||||
resolve(videoUrl);
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
document.body.removeChild(fileInput);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Transform network image failed", e);
|
||||
return "";
|
||||
}
|
||||
},
|
||||
checkImage: (src, alt, url) => {
|
||||
if (src.indexOf("http") !== 0) {
|
||||
return "图片网址必须以 http/https 开头";
|
||||
}
|
||||
return true;
|
||||
}, // 也支持 async 函数
|
||||
},
|
||||
};
|
||||
|
||||
fileInput.click();
|
||||
return;
|
||||
}
|
||||
|
||||
["uploadImage"]: {
|
||||
server: uConfigData.url,
|
||||
fieldName: uConfigData.requestName,
|
||||
maxFileSize: maxSize, // 1M
|
||||
maxNumberOfFiles: imageLength,
|
||||
allowedFileTypes: ["image/png", "image/jpeg", "image/jpg"], // .png, .jpg, .jpeg
|
||||
meta: { ...uConfigData.params },
|
||||
metaWithUrl: false,
|
||||
headers: { accept: "application/json, text/plain, */*", ...uConfigData.headers },
|
||||
withCredentials: true,
|
||||
timeout: 60 * 1000, // 15 秒
|
||||
async customUpload(file, insertFn) {
|
||||
const fileInput = document.createElement("input");
|
||||
fileInput.setAttribute("type", "file");
|
||||
fileInput.setAttribute("accept", "image/png, image/jpeg, image/jpg, image/gif");
|
||||
fileInput.style.cssText = "position: absolute; left: -9999px; top: -9999px; opacity: 0";
|
||||
|
||||
document.body.appendChild(fileInput);
|
||||
|
||||
fileInput.onchange = async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
// 2. 大小限制检查
|
||||
const maxSize = 1 * 1024 * 1024; // 1M
|
||||
if (file.size > maxSize) {
|
||||
creationAlertBox("error", "文件大小不能超过 1MB");
|
||||
document.body.removeChild(fileInput);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const img = await uploading(file, file.name, "image");
|
||||
console.log("img", img);
|
||||
|
||||
insertFn(`${img.url}?aid=${img.aid}`);
|
||||
const res = await uploading(file, file.name, "image");
|
||||
// TextBus 期望返回 URL
|
||||
resolve(res.url + (res.aid ? `?aid=${res.aid}` : ''));
|
||||
} catch (err) {
|
||||
console.error("上传出错:", err);
|
||||
console.error(err);
|
||||
// reject(err); // TextBus 可能会捕获错误并提示
|
||||
} finally {
|
||||
document.body.removeChild(fileInput);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
["uploadVideo"]: {
|
||||
server: uConfigData.url,
|
||||
fieldName: uConfigData.requestName,
|
||||
maxFileSize: maxSize, // 1M
|
||||
maxNumberOfFiles: videoLength,
|
||||
allowedFileTypes: ["video/flv", "video/mkv", "video/avi", "video/rm", "video/rmvb", "video/mpeg", "video/mpg", "video/ogg", "video/ogv", "video/mov", "video/wmv", "video/mp4", "video/webm", "video/m4v"],
|
||||
meta: { ...uConfigData.params },
|
||||
metaWithUrl: false,
|
||||
headers: { accept: "application/json, text/plain, */*", ...uConfigData.headers },
|
||||
withCredentials: true,
|
||||
timeout: 60 * 1000, // 15 秒
|
||||
async customUpload(file, insertFn) {
|
||||
try {
|
||||
const videoUploadRes = await uploading(file, file.name, "video");
|
||||
const coverFile = await getVideoFirstFrame(file);
|
||||
const coverUploadRes = await uploading(coverFile, coverFile.name, "image");
|
||||
insertFn(`${videoUploadRes.url}?aid=${videoUploadRes.aid}`, `${coverUploadRes.url}?aid=${coverUploadRes.aid}`);
|
||||
} catch (err) {
|
||||
console.error("上传出错:", err);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
onChange(editor) {
|
||||
// console.log(editor.getHtml());
|
||||
saveStatus.value = "有未保存的更改";
|
||||
},
|
||||
hoverbarKeys: { text: { menuKeys: [] }, video: { menuKeys: [] } },
|
||||
};
|
||||
|
||||
fileInput.click();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
editor = E.createEditor({
|
||||
selector: "#editor-text-area",
|
||||
// content: [],
|
||||
html: info.value?.content || "",
|
||||
// html: `<div style="text-align: center;"><img src="https://o.x-php.com/Zvt57TuJSUvkyhw-xG_Y2l-U_pstfX-G1NFX9ddrB_WbUGy8P79gQxdCR7TG75gV7NkzNDQyOQ~~?aid=1011800" /></div>`,
|
||||
config: editorConfig,
|
||||
});
|
||||
// 查找 createEditor 函数
|
||||
let createEditor = null;
|
||||
if (window.textbus && typeof window.textbus.createEditor === 'function') {
|
||||
createEditor = window.textbus.createEditor;
|
||||
} else if (window.textbus && window.textbus.editor && typeof window.textbus.editor.createEditor === 'function') {
|
||||
createEditor = window.textbus.editor.createEditor;
|
||||
} else if (window.textbus && window.textbus.default && typeof window.textbus.default.createEditor === 'function') {
|
||||
createEditor = window.textbus.default.createEditor;
|
||||
}
|
||||
|
||||
if (!createEditor) {
|
||||
console.error("TextBus createEditor not found", window.textbus);
|
||||
creationAlertBox("error", "TextBus 初始化失败: createEditor 未找到");
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化编辑器
|
||||
// 根据源码推测:createEditor(config) 返回 editor 实例,然后调用 mount(selector)
|
||||
editor = createEditor(editorConfig);
|
||||
|
||||
if (editor && typeof editor.mount === 'function') {
|
||||
editor.mount("#editor-text-area");
|
||||
|
||||
// 手动隐藏不需要的工具栏按钮 (JS 兜底方案)
|
||||
setTimeout(() => {
|
||||
const hideButtons = () => {
|
||||
const buttons = document.querySelectorAll('.textbus-toolbar-btn, .textbus-btn, button');
|
||||
const targets = ['音频', '插入音频', 'Audio', '源代码', '查看源码', 'Source', '组件库', 'Components', '段落', '插入段落', 'Paragraph', '清除格式', 'Clean', '格式化', 'Format', '格式刷', 'Brush'];
|
||||
|
||||
let imageBtn = null;
|
||||
let videoBtn = null;
|
||||
|
||||
buttons.forEach(btn => {
|
||||
const title = btn.getAttribute('title') || btn.getAttribute('aria-label') || '';
|
||||
if (targets.some(t => title.includes(t))) {
|
||||
btn.style.display = 'none';
|
||||
}
|
||||
// 备用:检查图标 class
|
||||
if (btn.querySelector('.textbus-icon-music') ||
|
||||
btn.querySelector('.textbus-icon-code') ||
|
||||
btn.querySelector('.textbus-icon-components') ||
|
||||
btn.querySelector('.textbus-icon-paragraph') ||
|
||||
btn.querySelector('.textbus-icon-clean') // 清除格式
|
||||
) {
|
||||
btn.style.display = 'none';
|
||||
}
|
||||
|
||||
// 单独处理格式刷图标(通常是刷子形状)
|
||||
if (btn.querySelector('.textbus-icon-brush')) {
|
||||
btn.style.display = 'none';
|
||||
}
|
||||
|
||||
// 查找图片和视频按钮
|
||||
if (title.includes('图片') || title.includes('Image') || btn.querySelector('.textbus-icon-image')) {
|
||||
imageBtn = btn;
|
||||
}
|
||||
if (title.includes('视频') || title.includes('Video') || btn.querySelector('.textbus-icon-video')) {
|
||||
videoBtn = btn;
|
||||
}
|
||||
});
|
||||
|
||||
// 强制调整顺序:视频放在图片后面
|
||||
if (imageBtn && videoBtn && imageBtn.parentNode === videoBtn.parentNode) {
|
||||
// 如果视频按钮不在图片按钮的紧邻后面,则移动
|
||||
if (imageBtn.nextElementSibling !== videoBtn) {
|
||||
imageBtn.parentNode.insertBefore(videoBtn, imageBtn.nextElementSibling);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
hideButtons();
|
||||
// 监听 DOM 变化以防重新渲染
|
||||
const observer = new MutationObserver(hideButtons);
|
||||
const toolbar = document.querySelector('.textbus-toolbar') || document.querySelector('.textbus-ui-top');
|
||||
if (toolbar) {
|
||||
observer.observe(toolbar, { childList: true, subtree: true });
|
||||
}
|
||||
}, 100);
|
||||
|
||||
} else {
|
||||
// 兼容旧版本或直接传入 selector 的情况
|
||||
// 如果 createEditor 返回的不是带有 mount 的对象,可能是旧版本
|
||||
console.warn("Editor instance does not have mount method, assuming auto-mount or different API");
|
||||
}
|
||||
|
||||
if (editor && editor.onChange) {
|
||||
editor.onChange.subscribe(() => {
|
||||
saveStatus.value = "有未保存的更改";
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
console.log("TextBus init error", error);
|
||||
creationAlertBox("error", "TextBus 初始化异常: " + error.message);
|
||||
}
|
||||
|
||||
// 如果有远程数据,使用远程数据
|
||||
// if (info.value && info.value.content) {
|
||||
// editor.setHtml(info.value.content);
|
||||
// } else {
|
||||
// // 恢复草稿 (仅在没有远程数据时)
|
||||
// const cache = localStorage.getItem(draftKey);
|
||||
// if (cache) {
|
||||
// try {
|
||||
// const data = JSON.parse(cache);
|
||||
// if (data && (data.title || data.content)) {
|
||||
// if (data.title) title.value = data.title;
|
||||
// if (data.content) editor.setHtml(data.content);
|
||||
// if (data.updatedAt) {
|
||||
// saveStatus.value = `已保存 ${formatTime(new Date(data.updatedAt))}`;
|
||||
// }
|
||||
// }
|
||||
// } catch (_) {}
|
||||
// 点击空白处 focus 编辑器 (TextBus 可能不需要这个,但保留逻辑以防万一)
|
||||
// document.getElementById("editor-text-area").addEventListener("click", (e) => {
|
||||
// if (e.target.id === "editor-text-area") {
|
||||
// // editor.focus();
|
||||
// }
|
||||
// }
|
||||
|
||||
const toolbarConfig = {
|
||||
excludeKeys: ["insertVideo", "fullScreen"],
|
||||
};
|
||||
|
||||
toolbar = E.createToolbar({
|
||||
editor,
|
||||
selector: "#editor-toolbar",
|
||||
config: toolbarConfig,
|
||||
});
|
||||
|
||||
// 点击空白处 focus 编辑器
|
||||
document.getElementById("editor-text-area").addEventListener("click", (e) => {
|
||||
if (e.target.id === "editor-text-area") {
|
||||
editor.blur();
|
||||
editor.focus(true); // focus 到末尾
|
||||
}
|
||||
});
|
||||
// });
|
||||
};
|
||||
|
||||
// 提取视频第一帧作为封面
|
||||
// 提取视频第一帧作为封面 (保留辅助函数)
|
||||
const getVideoFirstFrame = (file) => {
|
||||
return new Promise((resolve) => {
|
||||
const video = document.createElement("video");
|
||||
@@ -430,9 +510,10 @@ const editApp = createApp({
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (editor == null) return;
|
||||
editor.destroy();
|
||||
editor = null;
|
||||
if (editor && typeof editor.destroy === 'function') {
|
||||
editor.destroy();
|
||||
editor = null;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -446,3 +527,4 @@ const editApp = createApp({
|
||||
},
|
||||
});
|
||||
editApp.mount("#edit");
|
||||
|
||||
|
||||
@@ -8,11 +8,55 @@
|
||||
<title>发布主题</title>
|
||||
<link href="https://framework.x-php.com/gter/forum/css/normalize.min.css" rel="stylesheet">
|
||||
<link href="https://framework.x-php.com/gter/forum/css/editorStyle.css" rel="stylesheet">
|
||||
<script src="https://framework.x-php.com/gter/forum/js/vue.global.js"></script>
|
||||
<link rel="stylesheet" href="/css/textbus.min.css">
|
||||
<script src="https://framework.x-php.com/gter/forum/js/vue.global.js"></script>
|
||||
<script src="/js/textbus.min.js"></script>
|
||||
<!-- <link rel="stylesheet" href="https://unpkg.com/@textbus/editor/bundles/textbus.min.css"> -->
|
||||
<!-- <script src="https://unpkg.com/@textbus/editor/bundles/textbus.min.js"></script> -->
|
||||
|
||||
<style>
|
||||
/* 隐藏 TextBus 工具栏按钮 */
|
||||
/* 由于我们无法确定具体的 class 且 JS 配置可能未生效,我们尝试使用更通用的属性选择器 */
|
||||
|
||||
/* 音频 */
|
||||
.textbus-toolbar-btn[title="音频"],
|
||||
.textbus-toolbar-btn[title="插入音频"],
|
||||
.textbus-toolbar-btn:has(.textbus-icon-music) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 源代码 */
|
||||
.textbus-toolbar-btn[title="源代码"],
|
||||
.textbus-toolbar-btn[title="查看源码"],
|
||||
.textbus-toolbar-btn:has(.textbus-icon-code) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 组件库 */
|
||||
.textbus-toolbar-btn[title="组件库"],
|
||||
.textbus-toolbar-btn:has(.textbus-icon-components) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 插入段落/其他 */
|
||||
.textbus-toolbar-btn[title="插入段落"],
|
||||
.textbus-toolbar-btn:has(.textbus-icon-paragraph) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 清除格式 */
|
||||
.textbus-toolbar-btn[title="清除格式"],
|
||||
.textbus-toolbar-btn:has(.textbus-icon-clean) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 格式刷 */
|
||||
.textbus-toolbar-btn[title="格式刷"],
|
||||
.textbus-toolbar-btn:has(.textbus-icon-brush) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
html,
|
||||
body {
|
||||
background-color: #fff;
|
||||
@@ -50,7 +94,7 @@
|
||||
width: 100vh;
|
||||
margin: 20px auto 20px auto;
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
/* padding: 10px; */
|
||||
border: 1px solid #e8e8e8;
|
||||
box-shadow: 0 2px 10px rgb(0 0 0 / 12%);
|
||||
}
|
||||
@@ -66,18 +110,30 @@
|
||||
outline: none;
|
||||
width: 100%;
|
||||
line-height: 1;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.textbus-toolbar-wrapper {
|
||||
border-radius: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
#editor-text-area {
|
||||
margin-top: 20px;
|
||||
/* margin-top: 20px; */
|
||||
/* height: 500px; */
|
||||
/* max-height: 80vh; */
|
||||
height: calc(100vh - 370px);
|
||||
height: calc(100vh - 310px);
|
||||
font-size: 18px;
|
||||
line-height: 1.5;
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
|
||||
.textbus-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.bottom-bar {
|
||||
@@ -217,22 +273,24 @@
|
||||
|
||||
<div class="bottom-bar action-buttons flexacenter">
|
||||
<div class="left-section flexacenter" @click="cutAnonymity">
|
||||
<img v-if="info.anonymous == 1" class="icon-pitch" src="https://framework.x-php.com/gter/forum/img/tick-box.svg" />
|
||||
<img v-if="info.anonymous == 1" class="icon-pitch"
|
||||
src="https://framework.x-php.com/gter/forum/img/tick-box.svg" />
|
||||
<div v-else class="icon"></div>
|
||||
<div class="text">匿名发布</div>
|
||||
</div>
|
||||
|
||||
<div class="right-section flexcenter">
|
||||
<div class="draft-btn flexcenter" @click="submit(0)"><img class="icon" src="https://framework.x-php.com/gter/forum/img/draft-icon.png?v=iem44eqj4HfC"> 存草稿 </div>
|
||||
<div class="draft-btn flexcenter" @click="submit(0)"><img class="icon"
|
||||
src="https://framework.x-php.com/gter/forum/img/draft-icon.png?v=iem44eqj4HfC"> 存草稿 </div>
|
||||
<div id="save-btn" class="publish-btn flexcenter" @click="submit(1)">保存</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="https://framework.x-php.com/gter/forum/js/editor.js"></script>
|
||||
<!-- <script type="module" src="https://framework.x-php.com/gter/forum/js/editor.js"></script> -->
|
||||
<script src="https://framework.x-php.com/gter/forum/js/axios.min.js"></script>
|
||||
<script src="https://framework.x-php.com/gter/forum/js/public.js"></script>
|
||||
<script type="module" src="https://framework.x-php.com/gter/forum/js/publish_admin.js"></script>
|
||||
<script type="module" src="/js/publish_admin.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user