123
This commit is contained in:
parent
27c69a9b6d
commit
66b28bbe72
|
|
@ -26,7 +26,7 @@
|
|||
</el-form-item>
|
||||
|
||||
<el-form-item label="内容" prop="content">
|
||||
<div v-if="dialogVisible" class="editor-container">
|
||||
<div v-if="editorReady" class="editor-container">
|
||||
<Toolbar
|
||||
:editor="editorRef"
|
||||
:defaultConfig="toolbarConfig"
|
||||
|
|
@ -34,13 +34,16 @@
|
|||
class="editor-toolbar"
|
||||
/>
|
||||
<Editor
|
||||
v-model="formData.content"
|
||||
:defaultConfig="editorConfig"
|
||||
:mode="mode"
|
||||
class="editor-content"
|
||||
@onCreated="handleCreated"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="dialogVisible" class="editor-loading">
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
<span>加载编辑器中...</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
|
|
@ -54,8 +57,9 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch, shallowRef, onBeforeUnmount } from 'vue'
|
||||
import { ref, reactive, computed, watch, shallowRef, onBeforeUnmount, nextTick } from 'vue'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import type { IDomEditor, IEditorConfig, IToolbarConfig } from '@wangeditor/editor'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
|
|
@ -84,6 +88,7 @@ const dialogVisible = computed({
|
|||
|
||||
// 编辑器实例
|
||||
const editorRef = shallowRef<IDomEditor>()
|
||||
const editorReady = ref(false)
|
||||
const mode = 'default'
|
||||
|
||||
// 工具栏配置
|
||||
|
|
@ -159,7 +164,7 @@ const formRules: FormRules = {
|
|||
|
||||
// 清理 HTML 内容,修复可能导致编辑器解析错误的格式问题
|
||||
const cleanHtmlContent = (html: string): string => {
|
||||
if (!html) return ''
|
||||
if (!html) return '<p></p>'
|
||||
|
||||
// 修复以分号开头的 style 属性(如 style=";font-family:宋体")
|
||||
let cleaned = html.replace(/style=";/g, 'style="')
|
||||
|
|
@ -173,109 +178,82 @@ const cleanHtmlContent = (html: string): string => {
|
|||
// 移除 style 属性开头的分号
|
||||
cleaned = cleaned.replace(/style=";\s*/g, 'style="')
|
||||
|
||||
return cleaned
|
||||
}
|
||||
// 移除可能导致问题的特殊字符
|
||||
cleaned = cleaned.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g, '')
|
||||
|
||||
// 安全地设置编辑器内容
|
||||
const safeSetEditorContent = (editor: IDomEditor, content: string) => {
|
||||
if (!editor || editor.isDestroyed) return
|
||||
|
||||
try {
|
||||
// 清理 HTML 内容
|
||||
const cleanedContent = cleanHtmlContent(content)
|
||||
|
||||
// 先清空编辑器
|
||||
editor.clear()
|
||||
|
||||
// 使用 setTimeout 确保 clear 操作完成
|
||||
setTimeout(() => {
|
||||
if (!editor.isDestroyed) {
|
||||
try {
|
||||
editor.setHtml(cleanedContent)
|
||||
} catch (e) {
|
||||
console.error('[DanyeFormDialog] Error setting HTML content:', e)
|
||||
// 如果设置失败,尝试设置纯文本
|
||||
try {
|
||||
// 提取纯文本内容
|
||||
const tempDiv = document.createElement('div')
|
||||
tempDiv.innerHTML = cleanedContent
|
||||
const textContent = tempDiv.textContent || tempDiv.innerText || ''
|
||||
editor.insertText(textContent)
|
||||
} catch (e2) {
|
||||
console.error('[DanyeFormDialog] Error setting text content:', e2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 50)
|
||||
} catch (e) {
|
||||
console.error('[DanyeFormDialog] Error in safeSetEditorContent:', e)
|
||||
}
|
||||
return cleaned || '<p></p>'
|
||||
}
|
||||
|
||||
// 编辑器创建完成
|
||||
const handleCreated = (editor: IDomEditor) => {
|
||||
console.log('[DanyeFormDialog] handleCreated called, editor:', editor)
|
||||
console.log('[DanyeFormDialog] editor.isDestroyed:', editor.isDestroyed)
|
||||
console.log('[DanyeFormDialog] handleCreated called')
|
||||
editorRef.value = editor
|
||||
|
||||
// 如果有内容,设置到编辑器
|
||||
if (formData.content) {
|
||||
console.log('[DanyeFormDialog] Setting initial content to editor:', formData.content.substring(0, 100))
|
||||
safeSetEditorContent(editor, formData.content)
|
||||
// 延迟设置内容,确保编辑器完全初始化
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (editor && !editor.isDestroyed && formData.content) {
|
||||
try {
|
||||
const cleanedContent = cleanHtmlContent(formData.content)
|
||||
console.log('[DanyeFormDialog] Setting cleaned content')
|
||||
editor.setHtml(cleanedContent)
|
||||
} catch (e) {
|
||||
console.error('[DanyeFormDialog] Error setting content:', e)
|
||||
// 如果设置失败,尝试设置为空
|
||||
try {
|
||||
editor.setHtml('<p></p>')
|
||||
} catch (e2) {
|
||||
console.error('[DanyeFormDialog] Error setting empty content:', e2)
|
||||
}
|
||||
}
|
||||
}
|
||||
editorReady.value = true
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 监听弹窗打开,初始化数据
|
||||
watch(() => props.modelValue, (visible) => {
|
||||
console.log('[DanyeFormDialog] modelValue changed:', visible, 'danye:', props.danye?.id)
|
||||
console.log('[DanyeFormDialog] modelValue changed:', visible)
|
||||
if (visible && props.danye) {
|
||||
formData.title = props.danye.title
|
||||
formData.content = props.danye.content || ''
|
||||
console.log('[DanyeFormDialog] formData.content set to:', formData.content.substring(0, 100))
|
||||
console.log('[DanyeFormDialog] editorRef.value:', editorRef.value)
|
||||
console.log('[DanyeFormDialog] editorRef.value?.isDestroyed:', editorRef.value?.isDestroyed)
|
||||
|
||||
// 如果编辑器已存在且未销毁,直接设置内容
|
||||
if (editorRef.value && !editorRef.value.isDestroyed) {
|
||||
safeSetEditorContent(editorRef.value, formData.content)
|
||||
}
|
||||
editorReady.value = false
|
||||
}
|
||||
})
|
||||
|
||||
// 监听 dialogVisible 变化
|
||||
watch(dialogVisible, (visible) => {
|
||||
console.log('[DanyeFormDialog] dialogVisible changed:', visible)
|
||||
if (!visible) {
|
||||
editorReady.value = false
|
||||
}
|
||||
})
|
||||
|
||||
// 组件销毁时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
console.log('[DanyeFormDialog] onBeforeUnmount called')
|
||||
const editor = editorRef.value
|
||||
if (editor) {
|
||||
console.log('[DanyeFormDialog] Destroying editor in onBeforeUnmount')
|
||||
if (editor && !editor.isDestroyed) {
|
||||
editor.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
console.log('[DanyeFormDialog] resetForm called')
|
||||
formData.title = ''
|
||||
formData.content = ''
|
||||
editorReady.value = false
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
console.log('[DanyeFormDialog] handleClose called')
|
||||
console.log('[DanyeFormDialog] editorRef.value before destroy:', editorRef.value)
|
||||
// 先销毁编辑器实例
|
||||
if (editorRef.value) {
|
||||
console.log('[DanyeFormDialog] Destroying editor, isDestroyed:', editorRef.value.isDestroyed)
|
||||
if (editorRef.value && !editorRef.value.isDestroyed) {
|
||||
editorRef.value.destroy()
|
||||
editorRef.value = undefined
|
||||
console.log('[DanyeFormDialog] Editor destroyed and set to undefined')
|
||||
}
|
||||
editorReady.value = false
|
||||
dialogVisible.value = false
|
||||
resetForm()
|
||||
}
|
||||
|
|
@ -290,6 +268,11 @@ const handleSubmit = async () => {
|
|||
return
|
||||
}
|
||||
|
||||
// 从编辑器获取最新内容
|
||||
if (editorRef.value && !editorRef.value.isDestroyed) {
|
||||
formData.content = editorRef.value.getHtml()
|
||||
}
|
||||
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const submitData: DanyeUpdateRequest = {
|
||||
|
|
@ -312,6 +295,10 @@ const handleSubmit = async () => {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
width: 100%;
|
||||
border: 1px solid #dcdfe6;
|
||||
|
|
@ -329,6 +316,17 @@ const handleSubmit = async () => {
|
|||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.editor-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 400px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
color: #909399;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user