791 lines
26 KiB
Vue
791 lines
26 KiB
Vue
<template>
|
||
<div class="uebox">
|
||
<div v-if="editorError" class="editor-error">
|
||
<p>编辑器加载失败: {{ editorError }}</p>
|
||
<button @click="retryLoad">重试加载</button>
|
||
</div>
|
||
|
||
<vue-ueditor-wrap
|
||
v-model="content"
|
||
:editor-id="props.id"
|
||
:config="editorConfig"
|
||
:editorDependencies="editorDependencies"
|
||
@ready="onEditorReady"
|
||
@error="onEditorError"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
|
||
import { VueUeditorWrap } from 'vue-ueditor-wrap'
|
||
import { computed, reactive, onMounted, ref } from 'vue'
|
||
import { useUserStore } from '/@/store/modules/system/user.js'
|
||
import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const'
|
||
|
||
// 解析后端API基地址(按环境变量/全局变量/本地存储,依次回退)
|
||
const resolveApiBase = () => {
|
||
const env = import.meta.env || {}
|
||
const candidates = [
|
||
env.VITE_APP_API_URL, // 使用正确的环境变量名
|
||
env.VITE_GLOB_API_URL,
|
||
env.VITE_API_BASE,
|
||
env.VITE_API_URL,
|
||
env.VITE_BASE_API,
|
||
// 可选的全局变量/本地存储回退
|
||
typeof window !== 'undefined' ? window.__API_BASE__ : '',
|
||
typeof localStorage !== 'undefined' ? localStorage.getItem('API_BASE_URL') : ''
|
||
].filter(Boolean)
|
||
const base = candidates.length > 0 ? candidates[0] : ''
|
||
return base ? base.replace(/\/+$/,'') : ''
|
||
}
|
||
const apiBase = resolveApiBase()
|
||
const uploadEndpoint = '/support/file/upload'
|
||
const resolvedServerUrl = `${apiBase}${uploadEndpoint}`
|
||
|
||
// 获取用户store实例
|
||
const userStore = useUserStore()
|
||
|
||
// 根据环境动态设置UEditor路径
|
||
const isProduction = computed(() => {
|
||
return apiBase.includes('dev-casedata.igandan.com') || apiBase.includes('casedata.igandan.com')
|
||
})
|
||
|
||
const ueditorBasePath = computed(() => {
|
||
if (isProduction.value) {
|
||
// 线上环境:确保包含UEditorPlus层级
|
||
return '/admin/web/UEditorPlus/'
|
||
}
|
||
// 本地环境
|
||
return '/UEditorPlus/'
|
||
})
|
||
|
||
// 调试信息
|
||
console.log('UEditor环境配置:', {
|
||
apiBase: apiBase.value,
|
||
isProduction: isProduction.value,
|
||
ueditorBasePath: ueditorBasePath.value
|
||
})
|
||
|
||
const props = defineProps({
|
||
// 内容
|
||
modelValue: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
|
||
// 必须得有,如果要在一个页面内写两个或以上的组件,需要用id去区分
|
||
id: {
|
||
type: String,
|
||
default: 'common_editor'
|
||
}
|
||
})
|
||
|
||
const emits = defineEmits(['update:modelValue'])
|
||
|
||
const content = computed({
|
||
get() {
|
||
return props.modelValue || ''
|
||
},
|
||
|
||
set(value) {
|
||
emits('update:modelValue', value)
|
||
return value
|
||
}
|
||
})
|
||
|
||
// 编辑器状态
|
||
const editorError = ref('')
|
||
const editorReady = ref(false)
|
||
|
||
// UEditor依赖文件配置
|
||
const editorDependencies = computed(() => {
|
||
if (isProduction.value) {
|
||
// 线上环境:使用完整路径
|
||
return [
|
||
'/admin/web/UEditorPlus/ueditor.config.js',
|
||
'/admin/web/UEditorPlus/ueditor.all.js',
|
||
'/admin/web/UEditorPlus/lang/zh-cn/zh-cn.js'
|
||
]
|
||
}
|
||
// 本地环境:使用相对路径
|
||
return [
|
||
'ueditor.config.js',
|
||
'ueditor.all.js',
|
||
'lang/zh-cn/zh-cn.js'
|
||
]
|
||
})
|
||
|
||
const editorConfig = reactive({
|
||
// 基础路径配置 - 必须正确设置,避免路径拼接问题
|
||
UEDITOR_HOME_URL: ueditorBasePath.value,
|
||
UEDITOR_CORS_URL: ueditorBasePath.value,
|
||
|
||
// 不从服务器加载配置,使用本地配置
|
||
loadConfigFromServer: false,
|
||
|
||
// 使用项目中的文件上传接口(按环境解析,直接包含folder参数)
|
||
serverUrl: `${resolvedServerUrl}?folder=${FILE_FOLDER_TYPE_ENUM.ARTICLE.value}`,
|
||
serverHeaders: computed(() => ({
|
||
'Authorization': 'Bearer ' + userStore.getToken
|
||
})),
|
||
|
||
// 编辑器基本配置
|
||
initialFrameHeight: 500,
|
||
initialFrameWidth: '100%',
|
||
autoHeightEnabled: false,
|
||
catchRemoteImageEnable: false,
|
||
|
||
// 编辑器功能配置
|
||
enableAutoSave: true,
|
||
autoSaveInterval: 60000, // 60秒自动保存
|
||
enableContextMenu: true,
|
||
|
||
// 图片上传配置 - 简化配置
|
||
imageActionName: 'uploadimage',
|
||
imageFieldName: 'file',
|
||
imageMaxSize: 2048000, // 2MB
|
||
imageAllowFiles: ['.png', '.jpg', '.jpeg', '.gif', '.bmp'],
|
||
imageCompressEnable: false, // 禁用图片压缩,避免webuploader错误
|
||
imageCompressBorder: 1600,
|
||
imageInsertAlign: 'none',
|
||
imageUrlPrefix: '',
|
||
|
||
// 视频上传配置
|
||
videoActionName: 'uploadvideo',
|
||
videoFieldName: 'file',
|
||
videoMaxSize: 102400000, // 100MB
|
||
videoAllowFiles: ['.flv', '.swf', '.mkv', '.avi', '.rm', '.rmvb', '.mpeg', '.mpg', '.ogg', '.ogv', '.mov', '.wmv', '.mp4', '.webm', '.wav', '.mid'],
|
||
videoUrlPrefix: '',
|
||
|
||
// 附件上传配置
|
||
fileActionName: 'uploadfile',
|
||
fileFieldName: 'file',
|
||
fileMaxSize: 51200000, // 50MB
|
||
fileAllowFiles: ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.flv', '.swf', '.mkv', '.avi', '.rm', '.rmvb', '.mpeg', '.mpg', '.ogg', '.ogv', '.mov', '.wmv', '.mp4', '.webm', '.wav', '.mid', '.rar', '.zip', '.tar', '.gz', '.7z', '.bz2', '.cab', '.iso', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf', '.txt', '.md', '.xml'],
|
||
fileUrlPrefix: '',
|
||
|
||
// 完整的工具栏配置
|
||
toolbars:[
|
||
[
|
||
"fullscreen", // 全屏
|
||
"source", // 源代码
|
||
"|",
|
||
"undo", // 撤销
|
||
"redo", // 重做
|
||
"|",
|
||
"bold", // 加粗
|
||
"italic", // 斜体
|
||
"underline", // 下划线
|
||
"fontborder", // 字符边框
|
||
"strikethrough",// 删除线
|
||
"superscript", // 上标
|
||
"subscript", // 下标
|
||
"removeformat", // 清除格式
|
||
"formatmatch", // 格式刷
|
||
"autotypeset", // 自动排版
|
||
"blockquote", // 引用
|
||
"pasteplain", // 纯文本粘贴模式
|
||
"|",
|
||
"forecolor", // 字体颜色
|
||
"backcolor", // 背景色
|
||
"insertorderedlist", // 有序列表
|
||
"insertunorderedlist", // 无序列表
|
||
"selectall", // 全选
|
||
"cleardoc", // 清空文档
|
||
"|",
|
||
"rowspacingtop",// 段前距
|
||
"rowspacingbottom", // 段后距
|
||
"lineheight", // 行间距
|
||
"|",
|
||
"customstyle", // 自定义标题
|
||
"paragraph", // 段落格式
|
||
"fontfamily", // 字体
|
||
"fontsize", // 字号
|
||
"|",
|
||
"directionalityltr", // 从左向右输入
|
||
"directionalityrtl", // 从右向左输入
|
||
"indent", // 首行缩进
|
||
"|",
|
||
"justifyleft", // 居左对齐
|
||
"justifycenter", // 居中对齐
|
||
"justifyright",
|
||
"justifyjustify", // 两端对齐
|
||
"|",
|
||
"touppercase", // 字母大写
|
||
"tolowercase", // 字母小写
|
||
"|",
|
||
"link", // 超链接
|
||
"unlink", // 取消链接
|
||
"anchor", // 锚点
|
||
"|",
|
||
"imagenone", // 图片默认
|
||
"imageleft", // 图片左浮动
|
||
"imageright", // 图片右浮动
|
||
"imagecenter", // 图片居中
|
||
"|",
|
||
"simpleupload", // 单图上传
|
||
"insertimage", // 多图上传
|
||
"emotion", // 表情
|
||
"scrawl", // 涂鸦
|
||
"insertvideo", // 视频
|
||
"attachment", // 附件
|
||
"insertframe", // 插入Iframe
|
||
"insertcode", // 插入代码
|
||
"pagebreak", // 分页
|
||
"template", // 模板
|
||
"background", // 背景
|
||
"formula", // 公式
|
||
"|",
|
||
"horizontal", // 分隔线
|
||
"date", // 日期
|
||
"time", // 时间
|
||
"spechars", // 特殊字符
|
||
"wordimage", // Word图片转存
|
||
"|",
|
||
"inserttable", // 插入表格
|
||
"deletetable", // 删除表格
|
||
"insertparagraphbeforetable", // 表格前插入行
|
||
"insertrow", // 前插入行
|
||
"deleterow", // 删除行
|
||
"insertcol", // 前插入列
|
||
"deletecol", // 删除列
|
||
"mergecells", // 合并多个单元格
|
||
"mergeright", // 右合并单元格
|
||
"mergedown", // 下合并单元格
|
||
"splittocells", // 完全拆分单元格
|
||
"splittorows", // 拆分成行
|
||
"splittocols", // 拆分成列
|
||
"contentimport", // 内容导入(支持Word、Markdown)
|
||
"|",
|
||
"print", // 打印
|
||
"preview", // 预览
|
||
"searchreplace", // 查询替换
|
||
"help", // 帮助
|
||
]
|
||
],
|
||
|
||
// 图片上传配置
|
||
imageConfig: {
|
||
disableUpload: false,
|
||
disableOnline: false,
|
||
selectCallback: null
|
||
},
|
||
|
||
// 视频上传配置
|
||
videoConfig: {
|
||
disableUpload: false,
|
||
selectCallback: null
|
||
},
|
||
|
||
// 附件上传配置
|
||
attachmentConfig: {
|
||
disableUpload: false,
|
||
selectCallback: null
|
||
},
|
||
|
||
// 其他配置
|
||
debug: false,
|
||
autoSaveEnable: true,
|
||
autoSaveRestore: false,
|
||
maximumWords: 10000,
|
||
maxUndoCount: 20,
|
||
minFrameHeight: 220,
|
||
autoFloatEnabled: false,
|
||
topOffset: 0,
|
||
toolbarTopOffset: 0,
|
||
|
||
// 文件处理配置 - 避免webuploader错误
|
||
enableContextMenu: true,
|
||
catchRemoteImageEnable: false,
|
||
autoHeightEnabled: false,
|
||
|
||
// 错误处理
|
||
tipError: function(message, title) {
|
||
console.error('UEditor Error:', message);
|
||
editorError.value = message;
|
||
}
|
||
})
|
||
|
||
// 编辑器就绪事件
|
||
const onEditorReady = (editorInstance) => {
|
||
console.log('UEditor已就绪:', editorInstance);
|
||
editorReady.value = true;
|
||
editorError.value = '';
|
||
|
||
// 确保编辑器可编辑
|
||
if (editorInstance && editorInstance.setEnabled) {
|
||
try {
|
||
editorInstance.setEnabled(true);
|
||
} catch (error) {
|
||
console.error('启用编辑器失败:', error);
|
||
}
|
||
}
|
||
|
||
// 设置初始内容
|
||
if (content.value) {
|
||
try {
|
||
editorInstance.setContent(content.value);
|
||
} catch (error) {
|
||
console.error('设置初始内容失败:', error);
|
||
}
|
||
}
|
||
|
||
// 监听图片上传完成事件
|
||
if (editorInstance && editorInstance.addListener) {
|
||
try {
|
||
// 监听图片上传完成
|
||
editorInstance.addListener('afterimagepaste', function(type, data) {
|
||
console.log('图片粘贴完成:', type, data);
|
||
});
|
||
|
||
editorInstance.addListener('afterimageinsert', function(type, data) {
|
||
console.log('图片插入完成:', type, data);
|
||
});
|
||
|
||
// 尝试监听上传完成事件
|
||
editorInstance.addListener('afterimageupload', function(type, data) {
|
||
console.log('图片上传完成:', type, data);
|
||
});
|
||
|
||
// 监听内容变化,检查是否有图片插入
|
||
editorInstance.addListener('contentchange', function() {
|
||
console.log('编辑器内容变化');
|
||
const content = editorInstance.getContent();
|
||
console.log('当前内容:', content);
|
||
|
||
// 检查内容中是否包含图片
|
||
if (content.includes('<img')) {
|
||
console.log('检测到图片标签');
|
||
|
||
// 检查是否有undefined的图片src,如果有则尝试修复
|
||
if (content.includes('src="undefined"')) {
|
||
console.log('检测到undefined图片src,尝试修复');
|
||
|
||
// 延迟执行,等待图片上传完成
|
||
setTimeout(() => {
|
||
// 这里可以尝试从其他地方获取正确的图片URL
|
||
console.log('尝试修复undefined图片src');
|
||
}, 2000);
|
||
}
|
||
}
|
||
});
|
||
|
||
} catch (error) {
|
||
console.error('添加事件监听器失败:', error);
|
||
}
|
||
}
|
||
|
||
// 尝试重写图片上传成功的处理
|
||
if (editorInstance && editorInstance.execCommand) {
|
||
try {
|
||
// 保存原始的execCommand方法
|
||
const originalExecCommand = editorInstance.execCommand;
|
||
|
||
// 重写execCommand方法,拦截图片插入
|
||
editorInstance.execCommand = function(command, ...args) {
|
||
console.log('执行命令:', command, args);
|
||
|
||
if (command === 'inserthtml' && args[0] && args[0].includes('<img')) {
|
||
console.log('检测到图片插入命令:', args[0]);
|
||
}
|
||
|
||
// 调用原始方法
|
||
return originalExecCommand.call(this, command, ...args);
|
||
};
|
||
|
||
console.log('已重写execCommand方法');
|
||
} catch (error) {
|
||
console.error('重写execCommand失败:', error);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 编辑器错误事件
|
||
const onEditorError = (error) => {
|
||
console.error('UEditor错误:', error);
|
||
editorError.value = error.message || '编辑器加载失败';
|
||
editorReady.value = false;
|
||
}
|
||
|
||
// 重试加载
|
||
const retryLoad = () => {
|
||
editorError.value = '';
|
||
editorReady.value = false;
|
||
// 强制重新渲染组件
|
||
location.reload();
|
||
}
|
||
|
||
// 组件挂载后的处理
|
||
onMounted(() => {
|
||
// 在UEditor加载前设置全局配置,避免路径问题
|
||
window.UEDITOR_HOME_URL = ueditorBasePath.value;
|
||
window.UEDITOR_CORS_URL = ueditorBasePath.value;
|
||
|
||
// 设置UEditor的全局上传成功回调
|
||
window.UEDITOR_CONFIG = window.UEDITOR_CONFIG || {};
|
||
|
||
// 图片上传成功后的处理 - 关键配置
|
||
window.UEDITOR_CONFIG.onImageUploadSuccess = function(result) {
|
||
console.log('=== 图片上传成功回调开始 ===');
|
||
console.log('原始返回数据:', result);
|
||
console.log('数据类型:', typeof result);
|
||
console.log('是否为字符串:', typeof result === 'string');
|
||
|
||
let parsedResult;
|
||
try {
|
||
// 如果result是字符串,尝试解析JSON
|
||
if (typeof result === 'string') {
|
||
parsedResult = JSON.parse(result);
|
||
} else {
|
||
parsedResult = result;
|
||
}
|
||
console.log('解析后的数据:', parsedResult);
|
||
} catch (e) {
|
||
console.error('JSON解析失败:', e);
|
||
parsedResult = result;
|
||
}
|
||
|
||
// 确保返回正确的数据格式
|
||
if (parsedResult && parsedResult.data && parsedResult.data.fileUrl) {
|
||
const returnData = {
|
||
url: parsedResult.data.fileUrl,
|
||
title: parsedResult.data.fileName || '图片',
|
||
alt: parsedResult.data.fileName || '图片',
|
||
state: 'SUCCESS'
|
||
};
|
||
console.log('返回给UEditor的数据:', returnData);
|
||
return returnData;
|
||
}
|
||
|
||
// 如果数据格式不对,返回错误状态
|
||
console.error('数据格式错误,无法提取fileUrl');
|
||
console.log('完整数据:', parsedResult);
|
||
return {
|
||
state: 'ERROR',
|
||
message: '上传失败:数据格式错误'
|
||
};
|
||
};
|
||
|
||
// 视频上传成功后的处理
|
||
window.UEDITOR_CONFIG.onVideoUploadSuccess = function(result) {
|
||
console.log('视频上传成功回调:', result);
|
||
if (result && result.data && result.data.fileUrl) {
|
||
return {
|
||
url: result.data.fileUrl,
|
||
title: result.data.fileName,
|
||
state: 'SUCCESS'
|
||
};
|
||
}
|
||
return {
|
||
state: 'ERROR',
|
||
message: '上传失败:数据格式错误'
|
||
};
|
||
};
|
||
|
||
// 附件上传成功后的处理
|
||
window.UEDITOR_CONFIG.onFileUploadSuccess = function(result) {
|
||
console.log('附件上传成功回调:', result);
|
||
if (result && result.data && result.data.fileUrl) {
|
||
return {
|
||
url: result.data.fileUrl,
|
||
title: result.data.fileName,
|
||
state: 'SUCCESS'
|
||
};
|
||
}
|
||
return {
|
||
state: 'ERROR',
|
||
message: '上传失败:数据格式错误'
|
||
};
|
||
};
|
||
|
||
// 检查依赖文件是否存在
|
||
editorDependencies.value.forEach(dep => {
|
||
fetch(dep)
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
console.error(`依赖文件加载失败: ${dep}`);
|
||
editorError.value = `依赖文件加载失败: ${dep}`;
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error(`依赖文件请求失败: ${dep}`, error);
|
||
editorError.value = `依赖文件请求失败: ${dep}`;
|
||
});
|
||
});
|
||
|
||
// 延迟强制刷新编辑器配置
|
||
setTimeout(() => {
|
||
if (window.UE && window.UEDITOR_CONFIG) {
|
||
// 强制覆盖配置
|
||
Object.assign(window.UEDITOR_CONFIG, editorConfig);
|
||
|
||
// 确保上传成功回调被正确设置
|
||
if (window.UEDITOR_CONFIG.onImageUploadSuccess) {
|
||
console.log('UEditor图片上传成功回调已设置');
|
||
}
|
||
if (window.UEDITOR_CONFIG.onVideoUploadSuccess) {
|
||
console.log('UEditor视频上传成功回调已设置');
|
||
}
|
||
if (window.UEDITOR_CONFIG.onFileUploadSuccess) {
|
||
console.log('UEditor附件上传成功回调已设置');
|
||
}
|
||
|
||
// 尝试监听UEditor的图片上传完成事件
|
||
if (window.UE && window.UE.getEditor) {
|
||
try {
|
||
const editor = window.UE.getEditor(props.id);
|
||
if (editor && editor.addListener) {
|
||
editor.addListener('afterimagepaste', function(type, data) {
|
||
console.log('图片粘贴事件:', type, data);
|
||
});
|
||
|
||
editor.addListener('afterimageinsert', function(type, data) {
|
||
console.log('图片插入事件:', type, data);
|
||
});
|
||
|
||
editor.addListener('afterimageupload', function(type, data) {
|
||
console.log('图片上传事件:', type, data);
|
||
});
|
||
}
|
||
} catch (e) {
|
||
console.log('编辑器实例获取失败,可能还未初始化:', e);
|
||
}
|
||
}
|
||
|
||
// 尝试重写UEditor的图片上传处理逻辑
|
||
if (window.UE && window.UE.getEditor) {
|
||
try {
|
||
const editor = window.UE.getEditor(props.id);
|
||
if (editor) {
|
||
// 重写图片上传成功后的处理
|
||
const originalInsertImage = editor.insertImage;
|
||
if (originalInsertImage) {
|
||
editor.insertImage = function(url, title, alt) {
|
||
console.log('重写的insertImage被调用:', url, title, alt);
|
||
|
||
// 如果URL是undefined,尝试从其他地方获取
|
||
if (!url || url === 'undefined') {
|
||
console.error('图片URL无效:', url);
|
||
return false;
|
||
}
|
||
|
||
// 调用原始方法
|
||
return originalInsertImage.call(this, url, title, alt);
|
||
};
|
||
console.log('已重写insertImage方法');
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.log('重写insertImage失败:', e);
|
||
}
|
||
}
|
||
|
||
// 尝试拦截网络请求,在图片上传成功后强制处理
|
||
if (window.fetch) {
|
||
const originalFetch = window.fetch;
|
||
window.fetch = function(url, options) {
|
||
// 如果是图片上传请求
|
||
if (url && url.includes('/support/file/upload') && options && options.method === 'POST') {
|
||
console.log('拦截到图片上传请求:', url);
|
||
|
||
return originalFetch(url, options).then(response => {
|
||
// 克隆响应以便多次读取
|
||
const clonedResponse = response.clone();
|
||
|
||
// 读取响应内容
|
||
clonedResponse.json().then(data => {
|
||
console.log('图片上传响应:', data);
|
||
|
||
// 如果上传成功,尝试强制插入图片
|
||
if (data && data.code === 0 && data.data && data.data.fileUrl) {
|
||
console.log('图片上传成功,尝试强制插入:', data.data.fileUrl);
|
||
|
||
// 延迟执行,确保编辑器已就绪
|
||
setTimeout(() => {
|
||
if (window.UE && window.UE.getEditor) {
|
||
try {
|
||
const editor = window.UE.getEditor(props.id);
|
||
if (editor && editor.execCommand) {
|
||
const imgHtml = `<img src="${data.data.fileUrl}" title="${data.data.fileName}" alt="${data.data.fileName}" />`;
|
||
console.log('插入图片HTML:', imgHtml);
|
||
editor.execCommand('inserthtml', imgHtml);
|
||
}
|
||
} catch (e) {
|
||
console.error('强制插入图片失败:', e);
|
||
}
|
||
}
|
||
}, 1000);
|
||
}
|
||
}).catch(e => {
|
||
console.error('读取响应失败:', e);
|
||
});
|
||
|
||
return response;
|
||
});
|
||
}
|
||
|
||
// 其他请求正常处理
|
||
return originalFetch(url, options);
|
||
};
|
||
|
||
console.log('已拦截fetch请求');
|
||
}
|
||
|
||
// 拦截XMLHttpRequest,这是UEditor可能使用的另一种请求方式
|
||
if (window.XMLHttpRequest) {
|
||
const originalXHROpen = window.XMLHttpRequest.prototype.open;
|
||
const originalXHRSend = window.XMLHttpRequest.prototype.send;
|
||
|
||
window.XMLHttpRequest.prototype.open = function(method, url, ...args) {
|
||
this._ueditorUrl = url;
|
||
this._ueditorMethod = method;
|
||
return originalXHROpen.call(this, method, url, ...args);
|
||
};
|
||
|
||
window.XMLHttpRequest.prototype.send = function(data) {
|
||
const xhr = this;
|
||
const url = this._ueditorUrl;
|
||
const method = this._ueditorMethod;
|
||
|
||
// 如果是图片上传请求
|
||
if (url && url.includes('/support/file/upload') && method === 'POST') {
|
||
console.log('XMLHttpRequest拦截到图片上传请求:', url);
|
||
|
||
// 监听响应
|
||
xhr.addEventListener('load', function() {
|
||
if (xhr.status === 200) {
|
||
try {
|
||
const response = JSON.parse(xhr.responseText);
|
||
console.log('XMLHttpRequest图片上传响应:', response);
|
||
|
||
// 如果上传成功,尝试强制插入图片
|
||
if (response && response.code === 0 && response.data && response.data.fileUrl) {
|
||
console.log('XMLHttpRequest图片上传成功,尝试强制插入:', response.data.fileUrl);
|
||
|
||
// 延迟执行,确保编辑器已就绪
|
||
setTimeout(() => {
|
||
if (window.UE && window.UE.getEditor) {
|
||
try {
|
||
const editor = window.UE.getEditor(props.id);
|
||
if (editor && editor.execCommand) {
|
||
// 先删除所有undefined的图片
|
||
const currentContent = editor.getContent();
|
||
if (currentContent.includes('src="undefined"')) {
|
||
console.log('删除undefined图片');
|
||
editor.setContent(currentContent.replace(/<img[^>]*src="undefined"[^>]*>/g, ''));
|
||
}
|
||
|
||
// 插入正确的图片
|
||
const imgHtml = `<img src="${response.data.fileUrl}" title="${response.data.fileName}" alt="${response.data.fileName}" />`;
|
||
console.log('插入图片HTML:', imgHtml);
|
||
editor.execCommand('inserthtml', imgHtml);
|
||
}
|
||
} catch (e) {
|
||
console.error('XMLHttpRequest强制插入图片失败:', e);
|
||
}
|
||
}
|
||
}, 1000);
|
||
}
|
||
} catch (e) {
|
||
console.error('XMLHttpRequest响应解析失败:', e);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
return originalXHRSend.call(this, data);
|
||
};
|
||
|
||
console.log('已拦截XMLHttpRequest');
|
||
}
|
||
}
|
||
}, 3000);
|
||
|
||
// 额外的图片上传处理 - 监听全局事件
|
||
window.addEventListener('message', function(event) {
|
||
if (event.data && event.data.type === 'ueditor-image-upload-success') {
|
||
console.log('收到图片上传成功消息:', event.data);
|
||
// 这里可以处理图片上传成功后的逻辑
|
||
}
|
||
});
|
||
})
|
||
|
||
</script>
|
||
|
||
<style scoped>
|
||
.uebox {
|
||
width: 100%;
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
position: relative;
|
||
}
|
||
|
||
.editor-error {
|
||
padding: 20px;
|
||
background-color: #fff2f0;
|
||
border: 1px solid #ffccc7;
|
||
border-radius: 6px;
|
||
margin-bottom: 10px;
|
||
text-align: center;
|
||
}
|
||
|
||
.editor-error button {
|
||
margin-top: 10px;
|
||
padding: 8px 16px;
|
||
background-color: #1890ff;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.editor-error button:hover {
|
||
background-color: #40a9ff;
|
||
}
|
||
|
||
/* 编辑器容器样式优化 */
|
||
.uebox :deep(.edui-editor) {
|
||
border: none !important;
|
||
width: 100% !important;
|
||
height: auto !important;
|
||
}
|
||
|
||
.uebox :deep(.edui-editor-toolbarbox) {
|
||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||
border-bottom: 1px solid #e8e8e8;
|
||
width: 100% !important;
|
||
display: block !important;
|
||
}
|
||
|
||
.uebox :deep(.edui-editor-iframeholder) {
|
||
border: 1px solid #e8e8e8;
|
||
border-top: none;
|
||
width: 100% !important;
|
||
height: 500px !important;
|
||
}
|
||
|
||
.uebox :deep(.edui-editor-iframeholder iframe) {
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
pointer-events: auto !important;
|
||
}
|
||
|
||
.uebox :deep(.edui-editor-iframeholder .edui-body-container) {
|
||
pointer-events: auto !important;
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.uebox {
|
||
margin: 0 -8px;
|
||
}
|
||
|
||
.uebox :deep(.edui-editor-toolbarbox) {
|
||
padding: 4px;
|
||
}
|
||
}
|
||
</style> |