fix: 🧩 修復不能換行
This commit is contained in:
@@ -112,7 +112,7 @@
|
|||||||
<script setup name="Editor">
|
<script setup name="Editor">
|
||||||
import { QuillEditor, Quill } from "@vueup/vue-quill";
|
import { QuillEditor, Quill } from "@vueup/vue-quill";
|
||||||
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
import "@vueup/vue-quill/dist/vue-quill.snow.css";
|
||||||
import { getCurrentInstance, reactive, ref, toRaw, computed, onMounted, nextTick, watch } from "vue";
|
import { getCurrentInstance, reactive, ref, toRaw, computed, onMounted, nextTick } from "vue";
|
||||||
import { generateUUID } from "@/utils";
|
import { generateUUID } from "@/utils";
|
||||||
// import { h } from "@/utils/url";
|
// import { h } from "@/utils/url";
|
||||||
import { routerObj } from "./utils.js";
|
import { routerObj } from "./utils.js";
|
||||||
@@ -228,17 +228,9 @@ const options = reactive({
|
|||||||
outerVisible.value = value;
|
outerVisible.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
clipboard: {
|
|
||||||
matchVisual: false // 禁用视觉匹配(减少空标签)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formats: [
|
|
||||||
// ... 原有格式
|
|
||||||
"align",
|
|
||||||
"bold",
|
|
||||||
"italic" // 只保留必要格式,减少自动生成的空标签
|
|
||||||
],
|
|
||||||
placeholder: "请输入内容...",
|
placeholder: "请输入内容...",
|
||||||
readOnly: props.readOnly
|
readOnly: props.readOnly
|
||||||
});
|
});
|
||||||
@@ -302,27 +294,88 @@ const handleBeforeUpload = file => {
|
|||||||
imageListDb.value = imageListDb.value.filter(item => item.customUid !== file.customUid);
|
imageListDb.value = imageListDb.value.filter(item => item.customUid !== file.customUid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
console.log(imageListDb.value, "=================value==================");
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 图片上传(保持不变)
|
// // 图片上传(保持不变)
|
||||||
|
// const handleHttpUpload = async options => {
|
||||||
|
// let formData = new FormData();
|
||||||
|
// formData.append("image", options.file);
|
||||||
|
// imageList.value.push(options.file);
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// const result = await uploadImg(formData, routerName.value, options.file.customUid);
|
||||||
|
// if (result?.data?.code === 0) {
|
||||||
|
// const { data } = result.data;
|
||||||
|
// const { imgId } = result;
|
||||||
|
|
||||||
|
// const fileItem = imageListDb.value.find(item => item.customUid === imgId);
|
||||||
|
// if (fileItem) {
|
||||||
|
// fileItem.serverImgId = imgId;
|
||||||
|
// fileItem.path = data.path;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const allFilesUploaded = imageListDb.value.every(item => item.path);
|
||||||
|
// if (allFilesUploaded) {
|
||||||
|
// let rawQuillEditor = "";
|
||||||
|
// let quill = "";
|
||||||
|
// if (activeEditor.value === "main") {
|
||||||
|
// rawQuillEditor = toRaw(myQuillEditor.value);
|
||||||
|
// quill = rawQuillEditor.getQuill();
|
||||||
|
// } else {
|
||||||
|
// const tabIndex = parseInt(activeEditor.value.split("-")[1]);
|
||||||
|
// rawQuillEditor = toRaw(tabEditors.value[tabIndex]);
|
||||||
|
// quill = rawQuillEditor.getQuill();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// imageListDb.value.forEach(item => {
|
||||||
|
// const length = quill.getLength() - 1;
|
||||||
|
// quill.insertEmbed(length, "customImage", {
|
||||||
|
// url: item.path,
|
||||||
|
// id: item.serverImgId || generateUUID()
|
||||||
|
// });
|
||||||
|
// quill.setSelection(length + 1);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const finalLength = quill.getLength();
|
||||||
|
// quill.setSelection(finalLength);
|
||||||
|
|
||||||
|
// imageList.value = [];
|
||||||
|
// imageListDb.value = [];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("图片上传失败:", error);
|
||||||
|
// imageList.value = imageList.value.filter(item => item.customUid !== options.file.customUid);
|
||||||
|
// imageListDb.value = imageListDb.value.filter(item => item.customUid !== options.file.customUid);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 图片上传(修改插入位置逻辑)
|
||||||
const handleHttpUpload = async options => {
|
const handleHttpUpload = async options => {
|
||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
formData.append("image", options.file);
|
formData.append("image", options.file);
|
||||||
imageList.value.push(options.file);
|
// imageList.value.push(options.file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await uploadImg(formData, routerName.value, options.file.customUid);
|
const result = await uploadImg(formData, routerName.value, options.file.customUid);
|
||||||
if (result?.data?.code === 0) {
|
if (result?.data?.code === 0) {
|
||||||
const { data } = result.data;
|
const { data } = result.data;
|
||||||
const { imgId } = result;
|
const { imgId } = result;
|
||||||
|
// imageListDb.value.forEach(item => {
|
||||||
|
// if (item.customUid === imgId) {
|
||||||
|
// item.serverImgId = imgId;
|
||||||
|
// item.path = data.path;
|
||||||
|
// console.log(item.path, "================>");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
const fileItem = imageListDb.value.find(item => item.customUid === imgId);
|
const fileItem = imageListDb.value.find(item => item.customUid === imgId);
|
||||||
|
console.log(fileItem, "=fileItem=");
|
||||||
if (fileItem) {
|
if (fileItem) {
|
||||||
fileItem.serverImgId = imgId;
|
fileItem.serverImgId = imgId;
|
||||||
fileItem.path = data.path;
|
fileItem.path = data.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
const allFilesUploaded = imageListDb.value.every(item => item.path);
|
const allFilesUploaded = imageListDb.value.every(item => item.path);
|
||||||
if (allFilesUploaded) {
|
if (allFilesUploaded) {
|
||||||
let rawQuillEditor = "";
|
let rawQuillEditor = "";
|
||||||
@@ -336,17 +389,23 @@ const handleHttpUpload = async options => {
|
|||||||
quill = rawQuillEditor.getQuill();
|
quill = rawQuillEditor.getQuill();
|
||||||
}
|
}
|
||||||
|
|
||||||
imageListDb.value.forEach(item => {
|
// 关键修改:获取当前光标位置(选区起始索引)
|
||||||
const length = quill.getLength() - 1;
|
const selection = quill.getSelection();
|
||||||
quill.insertEmbed(length, "customImage", {
|
// 如果没有选区(光标未激活),默认插入到末尾
|
||||||
|
const insertPosition = selection ? selection.index : quill.getLength();
|
||||||
|
imageListDb?.value?.forEach(item => {
|
||||||
|
// 使用光标位置插入图片
|
||||||
|
quill.insertEmbed(insertPosition, "customImage", {
|
||||||
url: item.path,
|
url: item.path,
|
||||||
id: item.serverImgId || generateUUID()
|
id: item.serverImgId || generateUUID()
|
||||||
});
|
});
|
||||||
quill.setSelection(length + 1);
|
// 插入后光标后移一位(避免多张图片重叠插入)
|
||||||
|
quill.setSelection(insertPosition + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
const finalLength = quill.getLength();
|
// 最终光标定位到最后一张图片后面
|
||||||
quill.setSelection(finalLength);
|
const finalPosition = insertPosition + imageListDb.value.length;
|
||||||
|
quill.setSelection(finalPosition);
|
||||||
|
|
||||||
imageList.value = [];
|
imageList.value = [];
|
||||||
imageListDb.value = [];
|
imageListDb.value = [];
|
||||||
@@ -639,43 +698,38 @@ const loadTabsDataToEditor = tabs => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 清理空标签的专用函数(针对 Quill 生成的空 <p>)
|
// const cleanEmptyTags = container => {
|
||||||
const cleanEmptyTags = container => {
|
// if (!container) return;
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
// 1. 获取所有 <p> 标签
|
// // 获取所有 <p> 标签
|
||||||
const allPTags = container.querySelectorAll("p");
|
// const pTags = container.querySelectorAll("p");
|
||||||
if (allPTags.length === 0) return;
|
|
||||||
|
|
||||||
// 2. 手动判断标签是否为空(处理隐形字符)
|
// // 只清理真正的空标签(不含任何内容,包括<br>)
|
||||||
Array.from(allPTags).forEach(pTag => {
|
// Array.from(pTags).forEach(pTag => {
|
||||||
// 清除所有空白字符(包括 、换行、空格)
|
// // 判断标准:
|
||||||
const trimmedContent = pTag.innerHTML
|
// // 1. 完全没有子节点
|
||||||
.replace(/ /g, "") // 替换 HTML 空格实体
|
// // 2. 或innerHTML为空字符串
|
||||||
.replace(/\s+/g, "") // 替换所有空白字符(空格、换行等)
|
// const isCompletelyEmpty = pTag.childNodes.length === 0 || pTag.innerHTML.trim() === "";
|
||||||
.replace(/<br\s*\/?>/gi, ""); // 移除 <br> 标签
|
|
||||||
|
|
||||||
// 判断是否为空标签(清理后内容长度为 0)
|
// if (isCompletelyEmpty) {
|
||||||
const isEmpty = trimmedContent.length === 0;
|
// // 特殊处理:保留首尾空标签,避免编辑器异常
|
||||||
|
// const isFirstOrLast = pTag === container.firstElementChild || pTag === container.lastElementChild;
|
||||||
|
|
||||||
if (isEmpty) {
|
// if (isFirstOrLast) {
|
||||||
// 保留首尾空标签,避免编辑器异常
|
// pTag.innerHTML = ""; // 清空内容
|
||||||
const isFirstOrLast = pTag === container.firstElementChild || pTag === container.lastElementChild;
|
// } else {
|
||||||
if (!isFirstOrLast) {
|
// pTag.remove(); // 移除中间的纯空标签
|
||||||
pTag.remove();
|
// }
|
||||||
} else {
|
// }
|
||||||
pTag.innerHTML = ""; // 清空内容
|
// });
|
||||||
}
|
// };
|
||||||
}
|
// // 触发清理的函数(针对所有编辑器)
|
||||||
});
|
// const handleCleanEmptyTags = () => {
|
||||||
};
|
// // 处理主编辑器
|
||||||
// 触发清理的函数(针对所有编辑器)
|
// const mainEditor = document.querySelector("#mainEditor .ql-editor");
|
||||||
const handleCleanEmptyTags = () => {
|
// console.log(mainEditor, "=mainEditor=");
|
||||||
// 处理主编辑器
|
// if (mainEditor) cleanEmptyTags(mainEditor);
|
||||||
const mainEditor = document.querySelector("#mainEditor .ql-editor");
|
// };
|
||||||
console.log(mainEditor, "=mainEditor=");
|
|
||||||
if (mainEditor) cleanEmptyTags(mainEditor);
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTitle();
|
initTitle();
|
||||||
@@ -695,14 +749,14 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 等待编辑器首次渲染完成
|
// 等待编辑器首次渲染完成
|
||||||
setTimeout(handleCleanEmptyTags, 300);
|
// setTimeout(handleCleanEmptyTags, 300);
|
||||||
});
|
});
|
||||||
// 监听内容变化,重新清理空标签
|
// 监听内容变化,重新清理空标签
|
||||||
watch(editorContent, () => {
|
// watch(editorContent, () => {
|
||||||
nextTick(() => {
|
// nextTick(() => {
|
||||||
setTimeout(handleCleanEmptyTags, 100); // 延迟确保 Quill 已重新渲染
|
// setTimeout(handleCleanEmptyTags, 100); // 延迟确保 Quill 已重新渲染
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
defineExpose({
|
defineExpose({
|
||||||
clearEditor: () => {
|
clearEditor: () => {
|
||||||
const quill = toRaw(myQuillEditor.value)?.getQuill();
|
const quill = toRaw(myQuillEditor.value)?.getQuill();
|
||||||
@@ -740,52 +794,36 @@ defineExpose({
|
|||||||
width: 100px;
|
width: 100px;
|
||||||
margin: -2px 0; /* 与标签对齐 */
|
margin: -2px 0; /* 与标签对齐 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 详情样式 */
|
||||||
.o_detail_all {
|
.o_detail_all {
|
||||||
|
overflow: hidden;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
.o_detail_title {
|
.o_detail_title {
|
||||||
margin-top: 3.125vw;
|
margin-top: 2vw;
|
||||||
margin-bottom: 1.25vw;
|
margin-bottom: 1.25vw;
|
||||||
|
overflow: hidden;
|
||||||
font-size: 2.25em;
|
font-size: 2.25em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
color: #101010;
|
color: #101010;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
.o_detail_small {
|
.o_detail_small {
|
||||||
margin-bottom: 0.7vw;
|
margin-bottom: 0.7vw;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
.o_detail_text {
|
.o_detail_text {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-bottom: 0.7vw;
|
margin-bottom: 0.7vw;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
font-size: 1em;
|
|
||||||
line-height: 1.5em;
|
|
||||||
color: #737373;
|
|
||||||
}
|
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
.o_detail_title {
|
|
||||||
padding: 4% 0 2.8%;
|
|
||||||
font-size: 2.25em;
|
|
||||||
color: #101010;
|
|
||||||
}
|
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
.o_detail_small {
|
|
||||||
padding-bottom: 1.8%;
|
|
||||||
font-size: 1.5em;
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
.o_detail_text {
|
|
||||||
width: 80%;
|
|
||||||
padding: 0 0 1.8%;
|
|
||||||
margin: auto;
|
|
||||||
font-size: 1.125em;
|
font-size: 1.125em;
|
||||||
line-height: 1.875em;
|
line-height: 1.5em;
|
||||||
color: #737373;
|
color: #737373;
|
||||||
}
|
}
|
||||||
.products_des {
|
.products_des {
|
||||||
@@ -841,9 +879,4 @@ defineExpose({
|
|||||||
.seo-pro a:hover {
|
.seo-pro a:hover {
|
||||||
color: #009fdf;
|
color: #009fdf;
|
||||||
}
|
}
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
// .o_detail_all {
|
|
||||||
// text-align: center;
|
|
||||||
// }
|
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user