diff --git a/seller/src/views/goods/goods-seller/goodsOperationSec.vue b/seller/src/views/goods/goods-seller/goodsOperationSec.vue index a76178f2..bd1fc728 100644 --- a/seller/src/views/goods/goods-seller/goodsOperationSec.vue +++ b/seller/src/views/goods/goods-seller/goodsOperationSec.vue @@ -1452,6 +1452,22 @@ export default { /** 查询商品参数 */ this.GET_GoodsParams(); + + this.$nextTick(() => { + this.$refs.editor?.setContent?.(this.baseInfoForm.intro); + this.$refs.introEditor?.setContent?.(this.baseInfoForm.mobileIntro); + }); + }, + /** TinyMCE 的 v-model 可能滞后,提交前从编辑器实例取最新 HTML */ + syncIntroFromEditors() { + const pcEditor = this.$refs.editor; + const mobileEditor = this.$refs.introEditor; + if (pcEditor?.getContent) { + this.baseInfoForm.intro = pcEditor.getContent() ?? ""; + } + if (mobileEditor?.getContent) { + this.baseInfoForm.mobileIntro = mobileEditor.getContent() ?? ""; + } }, // 渲染sku数据 renderGoodsDetailSku(skuList) { @@ -1522,8 +1538,8 @@ export default { }, // 将pc商品描述同步给移动端 promiseIntroEditor() { - const pcContent = this.$refs.editor?.getContent?.() ?? this.baseInfoForm.intro ?? ""; - this.baseInfoForm.intro = pcContent; + this.syncIntroFromEditors(); + const pcContent = this.baseInfoForm.intro ?? ""; this.baseInfoForm.mobileIntro = pcContent; this.$nextTick(() => { this.$refs.introEditor?.setContent?.(pcContent); @@ -2360,6 +2376,7 @@ export default { if (!this.$route.query.copyId) { this.baseInfoForm.goodsId = this.goodsId; } + this.syncIntroFromEditors(); let submit = JSON.parse(JSON.stringify(this.baseInfoForm)); if ( submit.goodsGalleryFiles && diff --git a/seller/src/views/lili-components/editor/index.vue b/seller/src/views/lili-components/editor/index.vue index 8210bca3..2cd87e62 100644 --- a/seller/src/views/lili-components/editor/index.vue +++ b/seller/src/views/lili-components/editor/index.vue @@ -36,6 +36,7 @@ export default { initEditor, hasChange: false, // 标记内容是否有更改 hasInit: false, // 标记编辑器是否已初始化 + pendingContent: null, // 编辑器未就绪时暂存待回填内容 tinymceId: "tinymce-" + +new Date() + ((Math.random() * 1000).toFixed(0) + ""), // 生成唯一的编辑器 ID fullscreen: false, // 标记编辑器是否处于全屏模式 @@ -43,9 +44,6 @@ export default { content: "", // 编辑器内容 }; }, - created() { - this.init(); - }, computed: { bindValue() { return this.modelValue ?? this.value ?? ""; @@ -54,40 +52,55 @@ export default { watch: { bindValue: { handler(val) { - if (!this.hasChange && this.hasInit) { - const editor = window.tinymce.get(this.tinymceId); - if (editor) { - this.$nextTick(() => editor.setContent(val || "")); - } + if (!this.hasChange) { + this.setContent(val || ""); } }, - deep: true, }, }, methods: { + emitContent(content) { + this.$emit("update:modelValue", content); + this.$emit("input", content); + }, + getEditor() { + return window.tinymce?.get(this.tinymceId); + }, + isEditorReady() { + const editor = this.getEditor(); + return !!(editor && editor.initialized && editor.dom); + }, // 数据返回并给富文本框插入图片 insertImage(arr){ - arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(``)) + const editor = this.getEditor(); + if (!editor || !this.isEditorReady()) { + return; + } + arr.forEach(v => editor.insertContent(``)) }, init() { // 初始化编辑器 this.initTinymce(); }, initTinymce() { + if (this.getEditor()) { + return; + } const _this = this; window.tinymce.init({ selector: `#${this.tinymceId}`, convert_urls: false, init_instance_callback: (editor) => { - if (_this.bindValue) { - _this.$nextTick(() => editor.setContent(_this.bindValue)); - } _this.hasInit = true; - editor.on("NodeChange Change KeyUp SetContent", () => { + const initial = _this.pendingContent ?? _this.bindValue; + _this.pendingContent = null; + if (initial) { + _this.applyContent(editor, initial); + } + // 不监听 NodeChange/SetContent:初始化或回填时会把空内容写回 v-model,覆盖已加载的商品描述 + editor.on("input change undo redo KeyUp", () => { _this.hasChange = true; - const content = editor.getContent(); - _this.$emit("update:modelValue", content); - _this.$emit("input", content); + _this.emitContent(editor.getContent()); }); }, setup(editor) { @@ -101,23 +114,38 @@ export default { height:this.height }); }, - setContent(value) { - const editor = window.tinymce.get(this.tinymceId); - if (!editor) { - return; + applyContent(editor, content) { + if (!editor || !editor.initialized || !editor.dom) { + return false; } + try { + editor.setContent(content); + return true; + } catch (e) { + console.warn("tinymce setContent failed", e); + return false; + } + }, + setContent(value) { const content = value || ""; this.hasChange = false; - editor.setContent(content); - this.$emit("update:modelValue", content); - this.$emit("input", content); + if (!this.isEditorReady()) { + this.pendingContent = content; + return; + } + this.pendingContent = null; + this.applyContent(this.getEditor(), content); + this.emitContent(content); }, getContent() { - // 获取编辑器的内容 - return window.tinymce.get(this.tinymceId).getContent(); + const editor = this.getEditor(); + if (!editor || !editor.initialized) { + return this.pendingContent ?? this.bindValue ?? ""; + } + return editor.getContent(); }, destroyTinymce() { - const tinymce = window.tinymce.get(this.tinymceId); + const tinymce = this.getEditor(); if (tinymce) { // 销毁编辑器实例