feat: 🚀 切换站点清空语言
This commit is contained in:
@@ -239,6 +239,7 @@ const options = reactive({
|
|||||||
const options1 = reactive({
|
const options1 = reactive({
|
||||||
theme: "snow",
|
theme: "snow",
|
||||||
debug: "warn",
|
debug: "warn",
|
||||||
|
strict: false,
|
||||||
modules: {
|
modules: {
|
||||||
toolbar: {
|
toolbar: {
|
||||||
container: [
|
container: [
|
||||||
@@ -377,6 +378,7 @@ const handleHttpUpload = async options => {
|
|||||||
fileItem.path = data.path;
|
fileItem.path = data.path;
|
||||||
}
|
}
|
||||||
const allFilesUploaded = imageListDb.value.every(item => item.path);
|
const allFilesUploaded = imageListDb.value.every(item => item.path);
|
||||||
|
console.log(allFilesUploaded, "=allFilesUploaded=");
|
||||||
if (allFilesUploaded) {
|
if (allFilesUploaded) {
|
||||||
let rawQuillEditor = "";
|
let rawQuillEditor = "";
|
||||||
let quill = "";
|
let quill = "";
|
||||||
@@ -395,10 +397,13 @@ const handleHttpUpload = async options => {
|
|||||||
const insertPosition = selection ? selection.index : quill.getLength();
|
const insertPosition = selection ? selection.index : quill.getLength();
|
||||||
imageListDb?.value?.forEach(item => {
|
imageListDb?.value?.forEach(item => {
|
||||||
// 使用光标位置插入图片
|
// 使用光标位置插入图片
|
||||||
quill.insertEmbed(insertPosition, "customImage", {
|
setTimeout(() => {
|
||||||
url: item.path,
|
quill.insertEmbed(insertPosition, "customImage", {
|
||||||
id: item.serverImgId || generateUUID()
|
url: item.path,
|
||||||
});
|
id: item.serverImgId || generateUUID()
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
// 插入后光标后移一位(避免多张图片重叠插入)
|
// 插入后光标后移一位(避免多张图片重叠插入)
|
||||||
quill.setSelection(insertPosition + 1);
|
quill.setSelection(insertPosition + 1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -123,17 +123,35 @@ import { useRouter } from "vue-router";
|
|||||||
import { useMsg } from "@/hooks/useMsg";
|
import { useMsg } from "@/hooks/useMsg";
|
||||||
// 字体配置
|
// 字体配置
|
||||||
let fontSizeStyle = Quill.import("attributors/style/size");
|
let fontSizeStyle = Quill.import("attributors/style/size");
|
||||||
fontSizeStyle.whitelist = ["12px", "14px", "16px", "18px", "20px", "22px", "24px", "26px", "28px", "30px", "32px"];
|
fontSizeStyle.whitelist = [
|
||||||
|
"12px",
|
||||||
|
"14px",
|
||||||
|
"16px",
|
||||||
|
"18px",
|
||||||
|
"20px",
|
||||||
|
"22px",
|
||||||
|
"24px",
|
||||||
|
"26px",
|
||||||
|
"28px",
|
||||||
|
"30px",
|
||||||
|
"32px",
|
||||||
|
"34px",
|
||||||
|
"36px",
|
||||||
|
"38px",
|
||||||
|
"40px",
|
||||||
|
"42px"
|
||||||
|
];
|
||||||
Quill.register(fontSizeStyle, true);
|
Quill.register(fontSizeStyle, true);
|
||||||
|
|
||||||
// 自定义Blot
|
// 自定义Blot
|
||||||
import ImageBlot from "./quill-image";
|
import ImageBlot from "./quill-image";
|
||||||
import Video from "./quill-video";
|
import Video from "./quill-video";
|
||||||
import TabsBlot from "./quill-tabs";
|
import TabsBlot from "./quill-tabs";
|
||||||
|
import DynamicDivBlot from "./quill-detail-div";
|
||||||
Quill.register(Video);
|
Quill.register(Video);
|
||||||
Quill.register(ImageBlot);
|
Quill.register(ImageBlot);
|
||||||
Quill.register(TabsBlot);
|
Quill.register(TabsBlot);
|
||||||
|
Quill.register(DynamicDivBlot);
|
||||||
// 基础变量
|
// 基础变量
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
const emit = defineEmits(["update:content", "handleRichTextContentChange"]);
|
const emit = defineEmits(["update:content", "handleRichTextContentChange"]);
|
||||||
@@ -164,7 +182,10 @@ const props = defineProps({
|
|||||||
|
|
||||||
// 主编辑器内容双向绑定
|
// 主编辑器内容双向绑定
|
||||||
const editorContent = computed({
|
const editorContent = computed({
|
||||||
get: () => props.content,
|
get: () => {
|
||||||
|
if (!props.content) return "";
|
||||||
|
return props.content;
|
||||||
|
},
|
||||||
set: val => {
|
set: val => {
|
||||||
emit("update:content", val);
|
emit("update:content", val);
|
||||||
}
|
}
|
||||||
@@ -175,6 +196,7 @@ const myQuillEditor = ref(null); // 主编辑器ref
|
|||||||
const options = reactive({
|
const options = reactive({
|
||||||
theme: "snow",
|
theme: "snow",
|
||||||
debug: "warn",
|
debug: "warn",
|
||||||
|
strict: false,
|
||||||
modules: {
|
modules: {
|
||||||
toolbar: {
|
toolbar: {
|
||||||
container: [
|
container: [
|
||||||
@@ -208,6 +230,7 @@ const options = reactive({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
placeholder: "请输入内容...",
|
placeholder: "请输入内容...",
|
||||||
readOnly: props.readOnly
|
readOnly: props.readOnly
|
||||||
});
|
});
|
||||||
@@ -271,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 = "";
|
||||||
@@ -305,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 = [];
|
||||||
@@ -329,33 +419,127 @@ const handleHttpUpload = async options => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 视频上传(保持不变)
|
// 视频上传(保持不变)
|
||||||
|
// const handleVideoUpload = async evt => {
|
||||||
|
// if (evt.target.files.length === 0) return;
|
||||||
|
// const formData = new FormData();
|
||||||
|
// formData.append("video", evt.target.files[0]);
|
||||||
|
// try {
|
||||||
|
// 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();
|
||||||
|
// }
|
||||||
|
// let length = quill.selection.savedRange.index;
|
||||||
|
// const { data } = await uploadVideo(formData);
|
||||||
|
// quill.insertEmbed(length, "customVideo", {
|
||||||
|
// url: data.path,
|
||||||
|
// id: generateUUID()
|
||||||
|
// });
|
||||||
|
// uploadFileVideo.value.value = "";
|
||||||
|
// } catch (error) {
|
||||||
|
// console.log(error);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// 在<script setup>中替换handleVideoUpload方法
|
||||||
const handleVideoUpload = async evt => {
|
const handleVideoUpload = async evt => {
|
||||||
if (evt.target.files.length === 0) return;
|
if (evt.target.files.length === 0) return;
|
||||||
const formData = new FormData();
|
const file = evt.target.files[0];
|
||||||
formData.append("video", evt.target.files[0]);
|
|
||||||
try {
|
// 1. 校验视频文件
|
||||||
let rawQuillEditor = "";
|
const maxSize = props.fileSizeLimit * 1024 * 1024 * 15;
|
||||||
let quill = "";
|
if (file.size > maxSize) {
|
||||||
if (activeEditor.value === "main") {
|
ElNotification({
|
||||||
rawQuillEditor = toRaw(myQuillEditor.value);
|
title: "文件过大",
|
||||||
quill = rawQuillEditor.getQuill();
|
message: `视频大小不能超过 ${props.fileSizeLimit}MB`,
|
||||||
} else {
|
type: "warning"
|
||||||
const tabIndex = parseInt(activeEditor.value.split("-")[1]);
|
|
||||||
rawQuillEditor = toRaw(tabEditors.value[tabIndex]);
|
|
||||||
quill = rawQuillEditor.getQuill();
|
|
||||||
}
|
|
||||||
let length = quill.selection.savedRange.index;
|
|
||||||
const { data } = await uploadVideo(formData);
|
|
||||||
quill.insertEmbed(length, "customVideo", {
|
|
||||||
url: data.path,
|
|
||||||
id: generateUUID()
|
|
||||||
});
|
});
|
||||||
uploadFileVideo.value.value = "";
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 生成视频本地URL(用于生成封面,不上传)
|
||||||
|
const localVideoUrl = URL.createObjectURL(file);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 4. 并行处理:上传视频 + 生成并上传封面
|
||||||
|
// 4.1 上传视频到视频服务器
|
||||||
|
const videoFormData = new FormData();
|
||||||
|
videoFormData.append("video", file);
|
||||||
|
const videoRes = await uploadVideo(videoFormData); // 视频上传接口
|
||||||
|
|
||||||
|
// 校验视频上传结果(根据你的接口返回格式调整)
|
||||||
|
if (videoRes?.code !== 0) {
|
||||||
|
throw new Error(`视频上传失败: ${videoRes?.message || "未知错误"}`);
|
||||||
|
}
|
||||||
|
const videoUrl = videoRes.data.path; // 服务器返回的视频URL
|
||||||
|
console.log(localVideoUrl, "=localVideoUrl=");
|
||||||
|
// 4.2 生成封面图并上传到图片服务器
|
||||||
|
const frameBlob = await Video.captureVideoFrame(localVideoUrl);
|
||||||
|
console.log(frameBlob, "============frameBlob===========");
|
||||||
|
let coverUrl = "";
|
||||||
|
if (!frameBlob) return;
|
||||||
|
|
||||||
|
// 复用图片上传接口(与图片上传逻辑一致)
|
||||||
|
const coverFormData = new FormData();
|
||||||
|
const coverUid = generateUUID(); // 生成唯一ID
|
||||||
|
// formData.append("image", options.file);
|
||||||
|
coverFormData.append("image", frameBlob, `cover-${coverUid}.jpg`);
|
||||||
|
console.log(coverFormData, "=coverFormData=");
|
||||||
|
// 调用图片上传接口(和普通图片上传用同一个接口)
|
||||||
|
const coverRes = await uploadImg(coverFormData, routerName.value, coverUid);
|
||||||
|
|
||||||
|
// 校验封面上传结果
|
||||||
|
if (coverRes?.data?.code === 0) {
|
||||||
|
coverUrl = coverRes.data.data.path; // 服务器返回的封面URL
|
||||||
|
} else {
|
||||||
|
console.warn("封面上传失败,使用默认封面");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 将带封面的视频插入编辑器
|
||||||
|
insertVideoToEditor(videoUrl, coverUrl);
|
||||||
|
|
||||||
|
// 6. 上传成功提示
|
||||||
|
// loading.close();
|
||||||
|
// ElNotification({
|
||||||
|
// title: "上传成功",
|
||||||
|
// message: "视频已添加到编辑器",
|
||||||
|
// type: "success"
|
||||||
|
// });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error, "==============");
|
||||||
|
} finally {
|
||||||
|
console.log("======12323232========");
|
||||||
|
// 清理资源
|
||||||
|
URL.revokeObjectURL(localVideoUrl); // 释放本地视频URL
|
||||||
|
evt.target.value = ""; // 重置文件输入框
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 辅助方法:插入视频到编辑器
|
||||||
|
const insertVideoToEditor = (videoUrl, coverUrl) => {
|
||||||
|
// 获取当前活跃的编辑器(主编辑器或标签页编辑器)
|
||||||
|
let quill;
|
||||||
|
if (activeEditor.value === "main") {
|
||||||
|
quill = toRaw(myQuillEditor.value)?.getQuill();
|
||||||
|
} else {
|
||||||
|
const tabIndex = parseInt(activeEditor.value.split("-")[1]);
|
||||||
|
quill = toRaw(tabEditors.value[tabIndex])?.getQuill();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quill) {
|
||||||
|
const range = quill.getSelection() || { index: 0 };
|
||||||
|
// 插入自定义视频组件,携带服务器返回的视频URL和封面URL
|
||||||
|
quill.insertEmbed(range.index, "customVideo", {
|
||||||
|
url: videoUrl,
|
||||||
|
poster: coverUrl // 这里使用图片服务器返回的封面URL
|
||||||
|
});
|
||||||
|
quill.setSelection(range.index + 1); // 移动光标到视频后
|
||||||
|
}
|
||||||
|
};
|
||||||
// 标签页切换事件(基于key切换)
|
// 标签页切换事件(基于key切换)
|
||||||
const handleTabChange = key => {
|
const handleTabChange = key => {
|
||||||
const tabIndex = tabsData.value.findIndex(item => item.key === key);
|
const tabIndex = tabsData.value.findIndex(item => item.key === key);
|
||||||
@@ -514,20 +698,49 @@ const loadTabsDataToEditor = tabs => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const cleanEmptyTags = container => {
|
||||||
|
// if (!container) return;
|
||||||
|
|
||||||
|
// // 获取所有 <p> 标签
|
||||||
|
// const pTags = container.querySelectorAll("p");
|
||||||
|
|
||||||
|
// // 只清理真正的空标签(不含任何内容,包括<br>)
|
||||||
|
// Array.from(pTags).forEach(pTag => {
|
||||||
|
// // 判断标准:
|
||||||
|
// // 1. 完全没有子节点
|
||||||
|
// // 2. 或innerHTML为空字符串
|
||||||
|
// const isCompletelyEmpty = pTag.childNodes.length === 0 || pTag.innerHTML.trim() === "";
|
||||||
|
|
||||||
|
// if (isCompletelyEmpty) {
|
||||||
|
// // 特殊处理:保留首尾空标签,避免编辑器异常
|
||||||
|
// const isFirstOrLast = pTag === container.firstElementChild || pTag === container.lastElementChild;
|
||||||
|
|
||||||
|
// if (isFirstOrLast) {
|
||||||
|
// pTag.innerHTML = ""; // 清空内容
|
||||||
|
// } else {
|
||||||
|
// pTag.remove(); // 移除中间的纯空标签
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// // 触发清理的函数(针对所有编辑器)
|
||||||
|
// const handleCleanEmptyTags = () => {
|
||||||
|
// // 处理主编辑器
|
||||||
|
// const mainEditor = document.querySelector("#mainEditor .ql-editor");
|
||||||
|
// console.log(mainEditor, "=mainEditor=");
|
||||||
|
// if (mainEditor) cleanEmptyTags(mainEditor);
|
||||||
|
// };
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initTitle();
|
initTitle();
|
||||||
// 监听编辑按钮点击事件
|
// 监听编辑按钮点击事件
|
||||||
const editorEl = document.querySelector(".ql-editor");
|
const editorEl = document.querySelector(".ql-editor");
|
||||||
if (editorEl) {
|
if (editorEl) {
|
||||||
editorEl.addEventListener("edit-tabs", e => {
|
editorEl.addEventListener("edit-tabs", e => {
|
||||||
console.log(1232, "测试");
|
|
||||||
console.log(e.detail.blot, "=e.detail=");
|
|
||||||
const tabsData = TabsBlot.value(e.detail.blot.domNode);
|
const tabsData = TabsBlot.value(e.detail.blot.domNode);
|
||||||
console.log(tabsData, "=tabsData=");
|
|
||||||
if (tabsData.length > 0) {
|
if (tabsData.length > 0) {
|
||||||
// 保存当前编辑的标签页引用
|
// 保存当前编辑的标签页引用
|
||||||
currentEditingTabsRef.value = e.detail.blot;
|
currentEditingTabsRef.value = e.detail.blot;
|
||||||
console.log(currentEditingTabsRef.value, "=currentEditingTabsRef.value =");
|
|
||||||
// 加载数据到弹窗
|
// 加载数据到弹窗
|
||||||
loadTabsDataToEditor(tabsData);
|
loadTabsDataToEditor(tabsData);
|
||||||
// 显示弹窗
|
// 显示弹窗
|
||||||
@@ -535,8 +748,15 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 等待编辑器首次渲染完成
|
||||||
|
// setTimeout(handleCleanEmptyTags, 300);
|
||||||
});
|
});
|
||||||
|
// 监听内容变化,重新清理空标签
|
||||||
|
// watch(editorContent, () => {
|
||||||
|
// nextTick(() => {
|
||||||
|
// setTimeout(handleCleanEmptyTags, 100); // 延迟确保 Quill 已重新渲染
|
||||||
|
// });
|
||||||
|
// });
|
||||||
defineExpose({
|
defineExpose({
|
||||||
clearEditor: () => {
|
clearEditor: () => {
|
||||||
const quill = toRaw(myQuillEditor.value)?.getQuill();
|
const quill = toRaw(myQuillEditor.value)?.getQuill();
|
||||||
@@ -574,5 +794,89 @@ defineExpose({
|
|||||||
width: 100px;
|
width: 100px;
|
||||||
margin: -2px 0; /* 与标签对齐 */
|
margin: -2px 0; /* 与标签对齐 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 详情样式 */
|
||||||
|
.o_detail_all {
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.o_detail_title {
|
||||||
|
margin-top: 2vw;
|
||||||
|
margin-bottom: 1.25vw;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 2.25em;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2em;
|
||||||
|
color: #101010;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.o_detail_small {
|
||||||
|
margin-bottom: 0.7vw;
|
||||||
|
font-size: 1.5em;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.o_detail_text {
|
||||||
|
width: 80%;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-bottom: 0.7vw;
|
||||||
|
margin-left: auto;
|
||||||
|
font-size: 1.125em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
color: #737373;
|
||||||
|
}
|
||||||
|
.products_des {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
.products_des img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.de_t_n {
|
||||||
|
font-size: 1.5em;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.detail_title {
|
||||||
|
padding: 2% 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.detail_title p {
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
.detail_con_a {
|
||||||
|
margin: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.lj_detail_text,
|
||||||
|
.lj_detail_texts {
|
||||||
|
font-size: 0.875em;
|
||||||
|
}
|
||||||
|
.lj_detail_text p {
|
||||||
|
padding: 0.5% 0;
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* seo-pro */
|
||||||
|
.seo-pro h3 {
|
||||||
|
margin: 2% 0 1%;
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: #333333;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.seo-pro p {
|
||||||
|
margin: 0 0 11px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.seo-pro a {
|
||||||
|
color: #333333;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.sa_blue,
|
||||||
|
.sa_blue a,
|
||||||
|
.seo-pro a:hover {
|
||||||
|
color: #009fdf;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
./quill-image1111
|
|
||||||
|
|||||||
@@ -44,9 +44,16 @@ import { useMsg } from "@/hooks/useMsg";
|
|||||||
import { useUserStore } from "@/stores/modules/user";
|
import { useUserStore } from "@/stores/modules/user";
|
||||||
import { ElMessageBox } from "element-plus";
|
import { ElMessageBox } from "element-plus";
|
||||||
import { outLogin } from "@/utils/outLogin";
|
import { outLogin } from "@/utils/outLogin";
|
||||||
|
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
|
||||||
import { getLanguageListApi, getLanguageCutoverApi } from "@/api/modules/global";
|
import { getLanguageListApi, getLanguageCutoverApi } from "@/api/modules/global";
|
||||||
|
// import { HOME_URL } from "@/config";
|
||||||
|
// import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
import { useTabsStore } from "@/stores/modules/tabs";
|
||||||
|
const tabStore = useTabsStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
// const router = useRouter();
|
||||||
|
const keepAliveStore = useKeepAliveStore();
|
||||||
document.cookie = `lang=zh_cn`;
|
document.cookie = `lang=zh_cn`;
|
||||||
const langs = ref<any>([]);
|
const langs = ref<any>([]);
|
||||||
const name = ref("");
|
const name = ref("");
|
||||||
@@ -58,13 +65,13 @@ const getLanguageList = async () => {
|
|||||||
const { data } = result;
|
const { data } = result;
|
||||||
langs.value = data;
|
langs.value = data;
|
||||||
let id = userStore?.languageType ? userStore?.languageType : data[0]?.id;
|
let id = userStore?.languageType ? userStore?.languageType : data[0]?.id;
|
||||||
getLanguageCutover(id);
|
getLanguageCutover(id, "noCLick");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
getLanguageList();
|
getLanguageList();
|
||||||
|
|
||||||
// 站点切换接口
|
// 站点切换接口
|
||||||
const getLanguageCutover = async (id: any) => {
|
const getLanguageCutover = async (id: any, type: any) => {
|
||||||
const result = await getLanguageCutoverApi(id);
|
const result = await getLanguageCutoverApi(id);
|
||||||
if (result?.code === 0) {
|
if (result?.code === 0) {
|
||||||
userStore.setLanguageType(id);
|
userStore.setLanguageType(id);
|
||||||
@@ -72,12 +79,33 @@ const getLanguageCutover = async (id: any) => {
|
|||||||
return item.id === id;
|
return item.id === id;
|
||||||
});
|
});
|
||||||
name.value = names[0]?.country_name;
|
name.value = names[0]?.country_name;
|
||||||
|
if (type === "click") {
|
||||||
|
tabStore.closeMultipleTab("/admin/index");
|
||||||
|
keepAliveStore.setKeepAliveName();
|
||||||
|
router.push(HOME_URL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 站点切换事件
|
// 站点切换事件
|
||||||
const handleCommand = (val: string) => {
|
const handleCommand = (val: string) => {
|
||||||
getLanguageCutover(val);
|
//切换语言将清空所有标签页面
|
||||||
|
|
||||||
|
ElMessageBox.confirm("切换语言将清空所有标签页面?", "温馨提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
}).then(async () => {
|
||||||
|
await getLanguageCutover(val, "click");
|
||||||
|
// // // 1. 退出登录
|
||||||
|
// // const result: any = await logoutApi();
|
||||||
|
// // if (result?.code === 0) {
|
||||||
|
// // getLanguageCutover(val);
|
||||||
|
// // // outLogin();
|
||||||
|
// // } else {
|
||||||
|
// // useMsg("error", result.message);
|
||||||
|
// // }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 退出登录
|
// 退出登录
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import MoreButton from "./components/MoreButton.vue";
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const tabStore = useTabsStore();
|
const tabStore = useTabsStore();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
// const globalStore = useGlobalStore();
|
// const globalStore = useGlobalStore();
|
||||||
|
|||||||
@@ -30,12 +30,13 @@ export const useTabsStore = defineStore({
|
|||||||
},
|
},
|
||||||
// Close MultipleTab
|
// Close MultipleTab
|
||||||
async closeMultipleTab(tabsMenuValue?: string) {
|
async closeMultipleTab(tabsMenuValue?: string) {
|
||||||
this.tabsMenuList = this.tabsMenuList.filter(item => {
|
this.tabsMenuList = this.tabsMenuList.filter((item: any) => {
|
||||||
return item.path === tabsMenuValue || !item.close;
|
return item.path === tabsMenuValue || !item.hidden;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// Set Tabs
|
// Set Tabs
|
||||||
async setTabs(tabsMenuList: any[]) {
|
async setTabs(tabsMenuList: any[]) {
|
||||||
|
console.log(tabsMenuList, "=tabsMenuList=");
|
||||||
this.tabsMenuList = tabsMenuList;
|
this.tabsMenuList = tabsMenuList;
|
||||||
},
|
},
|
||||||
// Set Tabs Title
|
// Set Tabs Title
|
||||||
|
|||||||
Reference in New Issue
Block a user