refactor(cmsArticle): 统一文章编辑器为单一 WangEditor 富文本模式

- 删除原有 TinyMCE 富文本和 MdEditor Markdown 双模式切换及相关逻辑
- 替换文章编辑弹窗内容详情为 RichTextEditor 组件
- 新增图片库和视频库选择按钮,支持插入图片和视频 HTML 标签
- 实现一键排版和首行缩进按钮,直接操作内容 HTML 字符串
- 回显时 Markdown 内容转换为 HTML,保存时固定 editor 类型为 1
- 移除无用的配置和样式,简化代码逻辑,提升编辑体验
- 留下文章编辑器类型设置字段待后续清理,展示端保持一致 HTML 渲染方式
This commit is contained in:
2026-08-11 21:58:09 +08:00
parent cf7d065379
commit 07add26fe6
2 changed files with 70 additions and 546 deletions
+15
View File
@@ -113,3 +113,18 @@
- **潜在坑**:若 HTML content 里含裸 `.jpg` 链接(非 `<img>` 包裹,如 `<a href="https://x/x.jpg">`),`parseContent` 的兜底会把该 URL 误转成 `<img>` 破坏链接。WangEditor 产出的图片都是 `<img>`,正常商品详情极少触发,低概率。 - **潜在坑**:若 HTML content 里含裸 `.jpg` 链接(非 `<img>` 包裹,如 `<a href="https://x/x.jpg">`),`parseContent` 的兜底会把该 URL 误转成 `<img>` 破坏链接。WangEditor 产出的图片都是 `<img>`,正常商品详情极少触发,低概率。
- `uploadFile` 返回的 `url` 是否为小程序域名白名单内完整 URL 需上线后在真机确认(影响商品详情页图片显示)。 - `uploadFile` 返回的 `url` 是否为小程序域名白名单内完整 URL 需上线后在真机确认(影响商品详情页图片显示)。
- 老商品仅在「重新编辑」时转 HTML;从未编辑过的老 Markdown 商品保持 Markdown,仍由小程序正确渲染。 - 老商品仅在「重新编辑」时转 HTML;从未编辑过的老 Markdown 商品保持 Markdown,仍由小程序正确渲染。
## 文章管理编辑弹窗:统一换成 WangEditor 富文本(双模式→单模式)
- 用户要求文章模块编辑器"也换了",与商品模块一致。经确认采用「统一 WangEditor 单模式」,**删除原有的 TinyMCE 富文本 + MdEditor Markdown 双模式切换**。
- 改动文件:`src/views/cms/cmsArticle/components/articleEdit.vue`(复用已建的 `src/components/RichTextEditor.vue`)。
- 删除:双模式 `v-if="editor==1/2"` 渲染分支、`editor` ref、`onEditorTypeChange/performEditorSwitch/convertContentFormat/onEditor` 切换逻辑、`markdownToolbars``onMarkdownUploadImg``openMarkdownImageSelector/openMarkdownVideoSelector``insertMarkdownText`、TinyMCE `config`(含 custom_image_selector/quick_upload/auto_format/toggle_indent 等自定义按钮 setup)、`.mce-content-body` 样式、`uploadOss` import(仅在删块中使用)。
- 新增/改写:
- 内容详情改用 `<RichTextEditor ref="editorRef" v-model="content" :height="500">`
- 编辑器下方按钮区:`📷从图片库选择`/`🎬从视频库选择`(调 `editorRef.value.insertHtml` 插入 img/video,复用 SelectData 弹窗)、`🎨一键排版`/`📐首行缩进`(直接操作 `content.value` HTML 字符串,底层 smartFormatContent/addIndent/removeIndent 纯函数保留)。
- `md = markdownit()` + `toEditorContent(raw)`:回显时 Markdown→HTML,已是 HTML 原样返回。
- `save()` 固定 `editor: 1`(统一 HTML)。
- 验证:`pnpm build` 通过(exit 0)。
- 风险/待办:
- `src/views/cms/cmsWebsiteSettingEdit.vue` 仍有"编辑器类型 1 md-editor-v3, 2 tinymce-editor"设置字段,文章编辑已不再读取,**该设置现在对文章编辑无效**,建议后续清理(改动涉及系统设置暂未动)。
- 展示端 `guilixu-taro/src/pages/index/article-detail.tsx` 用 Taro `RichText` 渲染 HTML(目前是占位页),统一 HTML 安全。
- `uploadFile` 的 url 域名白名单同商品模块,需真机确认。
@@ -80,58 +80,22 @@
/> />
</a-form-item> </a-form-item>
<a-form-item label="内容详情" name="content"> <a-form-item label="内容详情" name="content">
<!-- 富文本编辑器 --> <RichTextEditor
<div v-if="editor == 1">
<tinymce-editor
ref="editorRef" ref="editorRef"
class="editor-content"
v-model:value="content"
:disabled="disabled"
:init="config"
placeholder="支持直接粘贴或拖拽图片,也可点击工具栏图片按钮从文件库选择"
/>
<div class="file-selector-tip">
💡
提示工具栏"图片"按钮从图片库选择"上传"按钮快速上传图片"视频"按钮从视频库选择"上传视频"按钮快速上传视频"一键排版"按钮自动优化文章格式"首行缩进"按钮切换段落缩进
</div>
</div>
<!-- Markdown编辑器 -->
<div v-if="editor == 2">
<!-- 📝 Markdown编辑器工具栏扩展 -->
<div class="markdown-toolbar-extension">
<a-button
type="primary"
size="small"
@click="openMarkdownImageSelector"
style="margin-right: 8px"
>
📷 从图片库选择
</a-button>
<a-button
type="default"
size="small"
@click="openMarkdownVideoSelector"
style="margin-right: 8px"
>
🎬 从视频库选择
</a-button>
</div>
<MdEditor
v-model="content" v-model="content"
:disabled="disabled" :disabled="disabled"
height="500px" :height="500"
:placeholder="'请输入Markdown内容...'" placeholder="支持直接粘贴或拖拽图片,也可点击下方按钮从图片库选择"
:toolbars="markdownToolbars"
:onUploadImg="onMarkdownUploadImg"
/> />
<div class="file-selector-tip"> <div class="file-selector-tip">
💡 💡 提示支持直接粘贴/拖拽上传图片点击下方按钮从图片库/视频库选择或使用排版首行缩进优化文章
提示支持Markdown语法可以使用工具栏按钮从文件库选择图片/视频也可以直接拖拽上传文件
</div> </div>
</div> <a-space class="editor-toolbar-ext mt-2" wrap>
<a-button size="small" @click="openImageSelector">📷 从图片库选择</a-button>
<a-button size="small" @click="openVideoSelector">🎬 从视频库选择</a-button>
<a-button size="small" @click="handleAutoFormat">🎨 一键排版</a-button>
<a-button size="small" @click="toggleParagraphIndent">📐 首行缩进</a-button>
</a-space>
<a-space <a-space
class="py-2 flex items-center text-gray-400" class="py-2 flex items-center text-gray-400"
v-if="lang == 'zh_CN'" v-if="lang == 'zh_CN'"
@@ -317,11 +281,8 @@
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types'; import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FormInstance, RuleObject } from 'ant-design-vue/es/form'; import { FormInstance, RuleObject } from 'ant-design-vue/es/form';
import { FileRecord } from '@/api/system/file/model'; import { FileRecord } from '@/api/system/file/model';
import TinymceEditor from '@/components/TinymceEditor/index.vue'; import RichTextEditor from '@/components/RichTextEditor.vue';
import { MdEditor } from 'md-editor-v3'; import markdownit from 'markdown-it';
import 'md-editor-v3/lib/style.css';
import 'md-editor-v3/lib/preview.css';
import { uploadOss } from '@/api/system/file';
import { CmsArticleCategory } from '@/api/cms/cmsArticleCategory/model'; import { CmsArticleCategory } from '@/api/cms/cmsArticleCategory/model';
import { CmsNavigation } from '@/api/cms/cmsNavigation/model'; import { CmsNavigation } from '@/api/cms/cmsNavigation/model';
import SourceSelect from '@/views/cms/cmsArticle/dictionary/source-select.vue'; import SourceSelect from '@/views/cms/cmsArticle/dictionary/source-select.vue';
@@ -335,8 +296,6 @@
const useForm = Form.useForm; const useForm = Form.useForm;
const setting = useWebsiteSettingStore(); const setting = useWebsiteSettingStore();
const { locale } = useI18n(); const { locale } = useI18n();
const editor = ref<number>(1);
// 是否开启响应式布局 // 是否开启响应式布局
const themeStore = useThemeStore(); const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore); const { styleResponsive } = storeToRefs(themeStore);
@@ -486,138 +445,6 @@
} }
}; };
// 📝 编辑器类型切换处理
const onEditorTypeChange = (e: any) => {
const newEditorType = e.target.value;
const oldEditorType = editor.value;
// 如果编辑器类型没有变化,直接返回
if (newEditorType === oldEditorType) {
return;
}
// 如果当前有内容,提示用户确认切换
if (
content.value &&
content.value.trim() !== '' &&
content.value !== '<p><br></p>'
) {
Modal.confirm({
title: '🔄 切换编辑器类型',
content: '切换编辑器类型可能会影响内容格式,是否继续?',
okText: '确认切换',
cancelText: '取消',
onOk: () => {
performEditorSwitch(newEditorType, oldEditorType);
},
onCancel: () => {
// 恢复原来的编辑器类型
editor.value = oldEditorType;
}
});
} else {
// 没有内容直接切换
performEditorSwitch(newEditorType, oldEditorType);
}
};
// 执行编辑器切换
const performEditorSwitch = (newType: number, oldType: number) => {
try {
editor.value = newType;
// 保存编辑器类型偏好到本地存储
localStorage.setItem('cms_article_editor_preference', newType.toString());
// 显示切换成功提示
const editorName = newType === 1 ? '富文本编辑器' : 'Markdown编辑器';
message.success({
content: `✅ 已切换到${editorName}`,
duration: 2
});
// 如果有内容,尝试进行格式转换
if (content.value && content.value.trim() !== '') {
convertContentFormat(oldType, newType);
}
} catch (error) {
console.error('编辑器切换失败:', error);
message.error('编辑器切换失败,请重试');
// 恢复原来的编辑器类型
editor.value = oldType;
}
};
// 内容格式转换
const convertContentFormat = (fromType: number, toType: number) => {
if (!content.value) return;
try {
if (fromType === 1 && toType === 2) {
// 富文本转Markdown(简单转换)
let markdownContent = content.value
.replace(/<h1[^>]*>(.*?)<\/h1>/gi, '# $1\n\n')
.replace(/<h2[^>]*>(.*?)<\/h2>/gi, '## $1\n\n')
.replace(/<h3[^>]*>(.*?)<\/h3>/gi, '### $1\n\n')
.replace(/<h4[^>]*>(.*?)<\/h4>/gi, '#### $1\n\n')
.replace(/<h5[^>]*>(.*?)<\/h5>/gi, '##### $1\n\n')
.replace(/<h6[^>]*>(.*?)<\/h6>/gi, '###### $1\n\n')
.replace(/<strong[^>]*>(.*?)<\/strong>/gi, '**$1**')
.replace(/<b[^>]*>(.*?)<\/b>/gi, '**$1**')
.replace(/<em[^>]*>(.*?)<\/em>/gi, '*$1*')
.replace(/<i[^>]*>(.*?)<\/i>/gi, '*$1*')
.replace(/<code[^>]*>(.*?)<\/code>/gi, '`$1`')
.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '[$2]($1)')
.replace(
/<img[^>]*src="([^"]*)"[^>]*alt="([^"]*)"[^>]*>/gi,
'![$2]($1)'
)
.replace(/<img[^>]*src="([^"]*)"[^>]*>/gi, '![图片]($1)')
.replace(/<p[^>]*>(.*?)<\/p>/gi, '$1\n\n')
.replace(/<br[^>]*>/gi, '\n')
.replace(/<[^>]+>/g, '') // 移除其他HTML标签
.replace(/\n{3,}/g, '\n\n') // 清理多余换行
.trim();
content.value = markdownContent;
message.info('已尝试将富文本内容转换为Markdown格式');
} else if (fromType === 2 && toType === 1) {
// Markdown转富文本(基本转换)
let htmlContent = content.value
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
.replace(/^#### (.*$)/gim, '<h4>$1</h4>')
.replace(/^##### (.*$)/gim, '<h5>$1</h5>')
.replace(/^###### (.*$)/gim, '<h6>$1</h6>')
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/`(.*?)`/g, '<code>$1</code>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>')
.replace(
/!\[([^\]]*)\]\(([^)]+)\)/g,
'<img src="$2" alt="$1" style="max-width: 100%;" />'
)
.replace(/\n\n/g, '</p><p>')
.replace(/\n/g, '<br>');
// 包装在段落标签中
if (htmlContent && !htmlContent.startsWith('<')) {
htmlContent = '<p>' + htmlContent + '</p>';
}
content.value = htmlContent;
message.info('已尝试将Markdown内容转换为富文本格式');
}
} catch (error) {
console.error('内容格式转换失败:', error);
message.warning('内容格式转换失败,请手动调整内容格式');
}
};
const onEditor = (value: any) => {
editor.value = value.target.value;
};
const onComments = () => { const onComments = () => {
if (form.comments == undefined) { if (form.comments == undefined) {
@@ -737,7 +564,16 @@
}); });
}; };
const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null); const editorRef = ref<any>(null);
// markdown-it 实例:编辑回显时把老 Markdown 内容转成 HTML 喂给富文本编辑器
const md = markdownit();
const toEditorContent = (val: string): string => {
if (!val) return '';
// 已是 HTML(含标签)则原样返回,否则用 markdown-it 转 HTML
if (/<[a-z][\s\S]*>/i.test(val)) return val;
return md.render(val);
};
// 文件库选择弹窗状态 // 文件库选择弹窗状态
const showFileSelector = ref(false); const showFileSelector = ref(false);
@@ -747,324 +583,6 @@
const showVideoSelector = ref(false); const showVideoSelector = ref(false);
const videoSelectCallback = ref<((url: string) => void) | null>(null); const videoSelectCallback = ref<((url: string) => void) | null>(null);
// 📝 Markdown编辑器配置
const markdownToolbars = [
'bold',
'underline',
'italic',
'-',
'title',
'strikeThrough',
'sub',
'sup',
'quote',
'unorderedList',
'orderedList',
'task',
'-',
'codeRow',
'code',
'link',
'image',
'table',
'mermaid',
'katex',
'-',
'revoke',
'next',
'save',
'=',
'pageFullscreen',
'fullscreen',
'preview',
'previewOnly',
'htmlPreview',
'catalog'
] as any;
// 📝 Markdown编辑器图片上传处理
const onMarkdownUploadImg = async (
files: File[],
callback: (urls: string[]) => void
) => {
try {
const uploadPromises = files.map(async (file) => {
// 检查文件大小(限制为10MB
if (file.size > 10 * 1024 * 1024) {
message.error(`图片 ${file.name} 大小超过10MB,请选择更小的文件`);
return null;
}
// 检查文件类型
if (!file.type.startsWith('image/')) {
message.error(`文件 ${file.name} 不是有效的图片格式`);
return null;
}
try {
const result = await uploadOss(file);
return result.url || result.path;
} catch (error) {
console.error('图片上传失败:', error);
message.error(`图片 ${file.name} 上传失败`);
return null;
}
});
const results = await Promise.all(uploadPromises);
const successUrls = results.filter((url) => url !== null) as string[];
if (successUrls.length > 0) {
callback(successUrls);
message.success(`成功上传 ${successUrls.length} 张图片`);
}
} catch (error) {
console.error('批量上传失败:', error);
message.error('图片上传失败,请重试');
}
};
// 📝 Markdown编辑器图片选择器
const openMarkdownImageSelector = () => {
fileSelectCallback.value = (url: string) => {
// 在当前光标位置插入Markdown图片语法
const imageMarkdown = `![图片](${url})`;
insertMarkdownText(imageMarkdown);
};
showFileSelector.value = true;
};
// 📝 Markdown编辑器视频选择器
const openMarkdownVideoSelector = () => {
videoSelectCallback.value = (url: string) => {
// 在当前光标位置插入Markdown视频语法(使用HTML标签)
const videoMarkdown = `<video controls style="max-width: 100%; height: auto;">
<source src="${url}" type="video/mp4">
您的浏览器不支持视频播放。
</video>`;
insertMarkdownText(videoMarkdown);
};
showVideoSelector.value = true;
};
// 📝 在Markdown编辑器中插入文本
const insertMarkdownText = (text: string) => {
// 简单的文本插入,在内容末尾添加
if (content.value) {
content.value += '\n\n' + text;
} else {
content.value = text;
}
};
const config = ref({
height: 420,
paste_data_images: true,
automatic_uploads: true,
// 自定义工具栏,移除默认的image和media按钮,添加自定义按钮 (视频、上传视频按钮 custom_video_selector quick_video_upload)(首行缩进
toolbar: [
'fullscreen preview code codesample emoticons auto_format custom_image_selector quick_upload',
'undo redo | forecolor backcolor',
'bold italic underline strikethrough',
'alignleft aligncenter alignright alignjustify',
'outdent indent | numlist bullist',
'formatselect fontselect fontsizeselect',
'link charmap anchor pagebreak | ltr rtl'
].join(' | '),
// 图片上传处理器 - 支持拖拽和粘贴上传
images_upload_handler: (blobInfo, success, error) => {
const file = blobInfo.blob();
// 检查文件大小(限制为10MB
if (file.size > 10 * 1024 * 1024) {
error('图片大小不能超过10MB');
return;
}
// 检查文件类型
if (!file.type.startsWith('image/')) {
error('只能上传图片文件');
return;
}
// 显示上传进度提示
const loadingMsg = message.loading('图片上传中...', 0);
uploadOss(file)
.then((res) => {
loadingMsg();
success(res.url || res.path);
message.success('图片上传成功');
})
.catch((msg) => {
loadingMsg();
error(msg || '图片上传失败');
message.error('图片上传失败:' + msg);
});
},
// 图片工具栏
image_toolbar:
'alignleft aligncenter alignright | rotateleft rotateright | imageoptions',
// 图片标题
image_title: true,
// 图片描述
image_description: true,
// 图片尺寸
image_dimensions: true,
// 图片类别
image_class_list: [
{ title: '无样式', value: '' },
{ title: '响应式图片', value: 'img-responsive' },
{ title: '圆角图片', value: 'img-rounded' },
{ title: '圆形图片', value: 'img-circle' }
],
// 自定义按钮设置
setup: (editor: any) => {
// 添加自定义图片选择按钮
editor.ui.registry.addButton('custom_image_selector', {
text: '图片',
icon: 'image',
tooltip: '插入图片(从文件库选择或上传)',
onAction: () => {
// 打开文件库选择弹窗
fileSelectCallback.value = (url: string) => {
editor.insertContent(
`<img src="${url}" alt="图片" style="max-width: 100%;" />`
);
};
showFileSelector.value = true;
}
});
// 添加快速上传按钮
editor.ui.registry.addButton('quick_upload', {
text: '上传',
icon: 'upload',
tooltip: '快速上传图片',
onAction: () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = (e: any) => {
const file = e.target.files[0];
if (file) {
// 检查文件大小
if (file.size > 10 * 1024 * 1024) {
message.error('图片大小不能超过10MB');
return;
}
const loadingMsg = message.loading('图片上传中...', 0);
uploadOss(file)
.then((res) => {
loadingMsg();
const imageUrl = res.url || res.path;
editor.insertContent(
`<img src="${imageUrl}" alt="${file.name}" style="max-width: 100%;" />`
);
message.success('图片上传成功');
})
.catch((msg) => {
loadingMsg();
message.error('图片上传失败:' + msg);
});
}
};
input.click();
}
});
// 添加自定义视频选择按钮
editor.ui.registry.addButton('custom_video_selector', {
text: '视频',
icon: 'embed',
tooltip: '插入视频(从视频库选择)',
onAction: () => {
// 打开视频库选择弹窗
videoSelectCallback.value = (url: string) => {
// 插入视频标签,使用HTML5 video元素
editor.insertContent(`
<video controls style="max-width: 100%; height: auto;">
<source src="${url}" type="video/mp4">
您的浏览器不支持视频播放。
</video>
`);
};
showVideoSelector.value = true;
}
});
// 添加快速视频上传按钮
editor.ui.registry.addButton('quick_video_upload', {
text: '上传视频',
icon: 'upload',
tooltip: '快速上传视频',
onAction: () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = 'video/*';
input.onchange = (e: any) => {
const file = e.target.files[0];
if (file) {
// 检查文件大小(限制为100MB)
if (file.size > 100 * 1024 * 1024) {
message.error('视频大小不能超过100MB');
return;
}
const loadingMsg = message.loading('视频上传中...', 0);
uploadOss(file)
.then((res) => {
loadingMsg();
const videoUrl = res.path || res.downloadUrl;
editor.insertContent(`
<video controls style="max-width: 100%; height: auto;">
<source src="${videoUrl}" type="video/mp4">
您的浏览器不支持视频播放。
</video>
`);
message.success('视频上传成功');
})
.catch((msg) => {
loadingMsg();
message.error('视频上传失败:' + msg);
});
}
};
input.click();
}
});
// 添加一键排版按钮
editor.ui.registry.addButton('auto_format', {
text: '排版',
icon: 'template',
tooltip: '智能优化文章格式和排版',
onAction: () => {
// 直接在这里处理排版,因为此时编辑器肯定已经初始化完成
handleAutoFormat(editor);
}
});
// 添加段落首行缩进切换按钮
editor.ui.registry.addButton('toggle_indent', {
icon: 'indent',
tooltip: '切换段落首行缩进(适合中文排版)',
onAction: () => {
toggleParagraphIndent(editor);
}
});
}
});
// 从文件库选择图片的回调 // 从文件库选择图片的回调
const onFileSelected = (data: FileRecord) => { const onFileSelected = (data: FileRecord) => {
if (fileSelectCallback.value) { if (fileSelectCallback.value) {
@@ -1093,11 +611,31 @@
showVideoSelector.value = false; showVideoSelector.value = false;
}; };
// 从图片库选择图片:插入到 WangEditor 当前光标处
const openImageSelector = () => {
fileSelectCallback.value = (url: string) => {
editorRef.value?.insertHtml(
`<img src="${url}" alt="图片" style="max-width:100%;"/>`
);
};
showFileSelector.value = true;
};
// 从视频库选择视频:插入到 WangEditor 当前光标处
const openVideoSelector = () => {
videoSelectCallback.value = (url: string) => {
editorRef.value?.insertHtml(
`<video controls style="max-width:100%;height:auto;"><source src="${url}" type="video/mp4"></video>`
);
};
showVideoSelector.value = true;
};
// 🎨 智能一键排版 - 人性化设计 // 🎨 智能一键排版 - 人性化设计
const handleAutoFormat = (editor: any) => { const handleAutoFormat = () => {
try { try {
// 1. 检查内容 // 1. 检查内容
const content = editor.getContent(); const content = content.value;
if ( if (
!content || !content ||
content.trim() === '' || content.trim() === '' ||
@@ -1121,7 +659,7 @@
setTimeout(() => { setTimeout(() => {
try { try {
const optimizedContent = smartFormatContent(content); const optimizedContent = smartFormatContent(content);
editor.setContent(optimizedContent); content.value = optimizedContent;
loadingMsg(); loadingMsg();
@@ -1316,9 +854,9 @@
}; };
// 🔄 段落首行缩进切换功能 // 🔄 段落首行缩进切换功能
const toggleParagraphIndent = (editor: any) => { const toggleParagraphIndent = () => {
try { try {
const content = editor.getContent(); const content = content.value;
if ( if (
!content || !content ||
@@ -1351,7 +889,7 @@
actionText = '已添加段落首行缩进'; actionText = '已添加段落首行缩进';
} }
editor.setContent(newContent); content.value = newContent;
message.success({ message.success({
content: `📐 ${actionText}`, content: `📐 ${actionText}`,
@@ -1449,7 +987,7 @@
} }
const formData = { const formData = {
...form, ...form,
editor: editor.value || 1, editor: 1,
status: setting.setting?.articleReview ? 1 : 0, status: setting.setting?.articleReview ? 1 : 0,
content: content.value content: content.value
}; };
@@ -1480,12 +1018,6 @@
watch( watch(
() => props.visible, () => props.visible,
(visible) => { (visible) => {
if (localStorage.getItem('Editor')) {
editor.value = Number(localStorage.getItem('Editor'));
} else {
editor.value = 1;
}
if (visible) { if (visible) {
images.value = []; images.value = [];
category.value = []; category.value = [];
@@ -1499,7 +1031,7 @@
// 文章详情 // 文章详情
assignObject(form, data); assignObject(form, data);
if (data.content) { if (data.content) {
content.value = data.content; content.value = toEditorContent(data.content);
} }
if (!data.source) { if (!data.source) {
form.source = undefined; form.source = undefined;
@@ -1509,9 +1041,6 @@
} else { } else {
form.tags = undefined; form.tags = undefined;
} }
if (data.editor) {
editor.value = data.editor;
}
if (data.files) { if (data.files) {
const arr = JSON.parse(data.files); const arr = JSON.parse(data.files);
arr.map((url: string) => { arr.map((url: string) => {
@@ -1561,26 +1090,6 @@
border-radius: 6px; border-radius: 6px;
} }
// 编辑器内图片样式
:deep(.mce-content-body) {
img {
max-width: 100%;
height: auto;
&.img-responsive {
width: 100%;
height: auto;
}
&.img-rounded {
border-radius: 8px;
}
&.img-circle {
border-radius: 50%;
}
}
}
} }
// 文件选择提示 // 文件选择提示