/** * 后台富文本清洗(协议、公告等静态内容) * * 背景:html 表里的正文是 Word / 旧编辑器导出的,直接渲染有两类问题: * 1. 大量 `

 

` 空段落,叠加段间距后出现大片空白; * 2. 几乎每个 span 都带内联 `font-family:宋体;font-size:14px;color:#000`, * 内联样式优先级最高,会盖掉页面样式,暗色模式下黑字配深底完全不可读。 * * 处理方式:删掉空段落,剥掉会影响排版与主题的内联属性,保留加粗、下划线等语义样式。 * 与 ai_uniapp_v2/utils/richtext.js 保持同一套规则(两个仓库独立,无法共享模块)。 */ const DROP_STYLE_PROPS = [ 'font-family', 'font-size', 'color', 'background', 'background-color', 'line-height', 'margin', 'margin-top', 'margin-bottom', 'margin-left', 'margin-right', 'padding', 'padding-top', 'padding-bottom', 'width', 'height', ] /** 判断一段 html 是否只有空白内容(空格、 、
、空标签) */ function isBlankFragment(html) { const text = String(html || '') .replace(//gi, '') .replace(/<[^>]+>/g, '') .replace(/ | |\u00a0/gi, '') .replace(/\s/g, '') return text.length === 0 } function cleanStyleValue(style) { return String(style || '') .split(';') .map(item => item.trim()) .filter(Boolean) .filter((item) => { const prop = item.split(':')[0].trim().toLowerCase() return prop && !DROP_STYLE_PROPS.includes(prop) }) .join('; ') } /** * @param {string} html 后台返回的富文本 * @return {string} 清洗后的富文本 */ export function cleanRichText(html) { if (!html) return '' let text = String(html) // Word 导出的无用标签与内嵌样式表 text = text .replace(/<\/?o:p[^>]*>/gi, '') .replace(//g, '') .replace(/]*>/gi, '') .replace(//gi, '') .replace(//gi, '') // 剥掉内联的字体/颜色/间距声明,style 清空后连属性一起去掉 text = text.replace(/\sstyle\s*=\s*"([^"]*)"/gi, (match, style) => { const kept = cleanStyleValue(style) return kept ? ` style="${kept}"` : '' }) text = text.replace(/\sstyle\s*=\s*'([^']*)'/gi, (match, style) => { const kept = cleanStyleValue(style) return kept ? ` style="${kept}"` : '' }) text = text.replace(/<\/?font[^>]*>/gi, '') text = text.replace(/\sclass\s*=\s*"(?:Mso|xl)[^"]*"/gi, '') // 只剩空白的段落 / 标题直接删掉 text = text.replace(/<(p|div|h[1-6])\b[^>]*>([\s\S]*?)<\/\1>/gi, (match, tag, inner) => { return isBlankFragment(inner) ? '' : match }) // 连续
压缩为一个 text = text.replace(/(?:\s*){2,}/gi, '
') return text.trim() } export default cleanRichText