Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_EleVue/.vitepress/dist/assets/zh_tools_rich-text.md.DyBRDKc5.js
T
2026-10-25 18:52:36 +08:00

97 lines
32 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{_ as i,o as a,c as n,a2 as p}from"./chunks/framework.B-QBKwc1.js";const c=JSON.parse('{"title":"富文本处理","description":"富文本(如文章内容)中的图片/视频链接同样需要处理。","frontmatter":{},"headers":[],"relativePath":"zh/tools/rich-text.md","filePath":"zh/tools/rich-text.md"}'),l={name:"zh/tools/rich-text.md"};function t(h,s,e,k,d,F){return a(),n("div",null,[...s[0]||(s[0]=[p(`<h1 id="_7-3-富文本处理" tabindex="-1">7.3 富文本处理 <a class="header-anchor" href="#_7-3-富文本处理" aria-label="Permalink to &quot;7.3 富文本处理&quot;">​</a></h1><div class="tip custom-block"><p class="custom-block-title">概述</p><p>富文本(如文章内容)中的图片/视频链接同样需要处理。项目采用 <code>[IMG_URL]</code> 占位符机制:入库时迁移临时文件并把域名替换为占位符,读取时再还原为当前配置的域名——支持域名变更场景。</p></div><h2 id="处理流程图" tabindex="-1">处理流程图 <a class="header-anchor" href="#处理流程图" aria-label="Permalink to &quot;处理流程图&quot;">​</a></h2><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 写入流程(add/update) │</span></span>
<span class="line"><span>├─────────────────────────────────────────────────────────────────┤</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ 前端编辑器插入图片 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ 上传到临时目录(uploadFile 接口) │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ 提交 HTML 内容到后端 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ Service(use HasFileProcessing) │</span></span>
<span class="line"><span>│ processContentFieldsOnSave() │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ├─ 解析 &lt;img&gt; 标签的 src │</span></span>
<span class="line"><span>│ ├─ 解析 &lt;video&gt;/&lt;source&gt;/&lt;embed&gt; 标签的 src │</span></span>
<span class="line"><span>│ ├─ 解析 &lt;a&gt; 标签的文件 href │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ save_content(&amp;$content, $saveDir) ← 引用传递,原地修改 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ├─ 站内临时文件 → save_file() 迁移至正式目录 │</span></span>
<span class="line"><span>│ ├─ 正式文件 → 去掉域名 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ 替换为 [IMG_URL]/相对路径 占位符 │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ 数据库存储含占位符的 HTML │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>└─────────────────────────────────────────────────────────────────┘</span></span>
<span class="line"><span></span></span>
<span class="line"><span>┌─────────────────────────────────────────────────────────────────┐</span></span>
<span class="line"><span>│ 读取流程(detail/pageList) │</span></span>
<span class="line"><span>├─────────────────────────────────────────────────────────────────┤</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>│ 数据库读取含占位符的 HTML │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ Service.processContentFieldsOnRead() │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ├─ 替换 [IMG_URL] 为 config/file.php 的 domain_url │</span></span>
<span class="line"><span>│ │ 如 https://cdn.example.com │</span></span>
<span class="line"><span>│ │ │</span></span>
<span class="line"><span>│ ▼ │</span></span>
<span class="line"><span>│ 返回完整 URL 的 HTML 给前端 │</span></span>
<span class="line"><span>│ │</span></span>
<span class="line"><span>└─────────────────────────────────────────────────────────────────┘</span></span></code></pre></div><h2 id="在-Service-中配置" tabindex="-1">在 Service 中配置 <a class="header-anchor" href="#在-Service-中配置" aria-label="Permalink to &quot;在 Service 中配置&quot;">​</a></h2><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">class</span><span style="--shiki-dark:#97E1F1;--shiki-light:#2E8F82;"> ArticleService</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> extends</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#59873A;--shiki-light-font-style:inherit;"> BaseTenantService</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 必须 use HasFileProcessing(否则占位实现直接透传,不处理)</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> use</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#998418;--shiki-light-font-style:inherit;"> HasFileProcessing</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /* 其他 Trait */</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 富文本字段</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@var</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> protected</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> array</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">contentFields</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">content</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">];</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><p>配置后自动处理:</p><ul><li><strong>add/update</strong>:<code>processContentFieldsOnSave()</code> → <code>save_content()</code> 处理临时文件与占位符</li><li><strong>detail/pageList/allList</strong>:<code>processContentFieldsOnRead()</code> / <code>...ReadList()</code> 还原占位符</li></ul><div class="warning custom-block"><p class="custom-block-title">未启用 Trait 不生效</p><p><code>BaseService</code> 中的 <code>processContentFieldsOnSave</code> 是<strong>占位实现</strong>(直接返回原数据)。子类必须 <code>use HasFileProcessing</code> 真实实现才会处理——声明了 <code>contentFields</code> 却不 <code>use</code>,富文本将原样入库。</p></div><h2 id="为什么使用占位符-" tabindex="-1">为什么使用占位符? <a class="header-anchor" href="#为什么使用占位符-" aria-label="Permalink to &quot;为什么使用占位符?&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">域名变更场景</p><p>假设初始配置 <code>FILE_DOMAIN_URL=https://cdn.example.com</code>,文章内容中图片 URL 为:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>https://cdn.example.com/uploads/article/20261002/abc.jpg</span></span></code></pre></div><p>存储时替换为:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span>[IMG_URL]/uploads/article/20261002/abc.jpg</span></span></code></pre></div><p>如果后续域名变更为 <code>https://cdn2.example.com</code>,只需修改 <code>.env</code> 中的 <code>FILE_DOMAIN_URL</code>,<strong>已存储的内容无需逐条更新</strong>,读取时自动替换为新域名。</p></div><h2 id="处理范围" tabindex="-1">处理范围 <a class="header-anchor" href="#处理范围" aria-label="Permalink to &quot;处理范围&quot;">​</a></h2><p><code>save_content()</code> 函数处理以下 HTML 标签:</p><table tabindex="0"><thead><tr><th>标签</th><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>&lt;img&gt;</code></td><td><code>src</code></td><td>图片</td></tr><tr><td><code>&lt;video&gt;</code></td><td><code>src</code></td><td>视频</td></tr><tr><td><code>&lt;source&gt;</code></td><td><code>src</code></td><td>视频源</td></tr><tr><td><code>&lt;embed&gt;</code></td><td><code>src</code></td><td>嵌入内容</td></tr><tr><td><code>&lt;a&gt;</code></td><td><code>href</code></td><td>文件链接(仅处理带扩展名的链接)</td></tr></tbody></table><h2 id="代码示例" tabindex="-1">代码示例 <a class="header-anchor" href="#代码示例" aria-label="Permalink to &quot;代码示例&quot;">​</a></h2><div class="language-php vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">php</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// app/Helpers/helpers.php 中的 save_content(来自项目实际代码的函数签名)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">/**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 处理富文本内容:站内临时文件转正、正式文件去掉域名,最终替换为 [IMG_URL] 占位。</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> *</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@param</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> $content 富文本 HTML(引用传递,原地修改)</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@param</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> $saveDir 正式保存子目录</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * </span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">@return</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> bool</span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> 是否发生替换</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> save_content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">string</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> &amp;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">$</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> string</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">saveDir</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">article</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">:</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> bool</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">config</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> config</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">file</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">domainUrl</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> rtrim</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">config</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">domain_url</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ??</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">/</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">empty</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">domainUrl</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ||</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> empty</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">))</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;"> false</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 1. 匹配 &lt;img&gt; 标签的 src</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> save_content_match</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;"> &#39;/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">&lt;img</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">src=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&quot;\\&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">?(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^&quot;\\&#39;&gt;\\s</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">)</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">/i&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">domainUrl</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">saveDir</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 2. 匹配 &lt;video&gt;/&lt;source&gt;/&lt;embed&gt; 标签的 src</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> save_content_match</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;"> &#39;/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">&lt;(?:video|source|embed)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">src=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&quot;\\&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">?(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^&quot;\\&#39;&gt;\\s</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">)</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">/i&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">domainUrl</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">saveDir</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 3. 匹配 &lt;a&gt; 标签的 href(指向文件的情况)</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> save_content_match</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;"> &#39;/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">&lt;a</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">href=</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&quot;\\&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">?(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^&quot;\\&#39;&gt;\\s</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">+</span><span style="--shiki-dark:#F286C4;--shiki-light:#BDA437;">\\.\\w</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">2,5</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">&quot;\\&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">]</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;">?</span><span style="--shiki-dark:#EE6666;--shiki-light:#B5695977;">/i&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">domainUrl</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">saveDir</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> // 批量替换</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">!</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> empty</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">))</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> str_replace</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">array_keys</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">),</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;"> array_values</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">($</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">urlMap</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">),</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> $</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">content</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;"> true</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><p><strong>处理规则(来自 <code>save_content</code> 实现注释):</strong></p><ul><li>站内临时文件 → 迁移到正式目录后记为 <code>[IMG_URL]</code> 占位</li><li>正式文件 → 去掉域名后记录为 <code>[IMG_URL]</code> 占位</li><li>外部 URL → 不处理(保持原样)</li></ul><h2 id="注意事项" tabindex="-1">注意事项 <a class="header-anchor" href="#注意事项" aria-label="Permalink to &quot;注意事项&quot;">​</a></h2><div class="warning custom-block"><p class="custom-block-title">富文本安全</p><ul><li>富文本内容可能包含 XSS 攻击代码,建议在前端使用编辑器的安全模式(粘贴过滤)</li><li><code>save_content</code> 只处理本站域名下的 URL,外部 URL 不做处理</li><li>图片标签的 <code>src</code> 必须是完整 URL(包含域名),否则无法识别</li><li>响应统一 <code>Content-Type: application/json</code>(ForceJsonResponse 中间件),内容不会被浏览器按 HTML 渲染</li></ul></div><div class="tip custom-block"><p class="custom-block-title">与文件字段的分工</p><ul><li><strong>单文件/多文件字段</strong>(<code>fileFields</code>/<code>multiFileFields</code>)→ 结构化字段,见 <a href="/zh/tools/upload.html">7.1 文件上传全流程</a></li><li><strong>富文本字段</strong>(<code>contentFields</code>)→ HTML 内嵌资源,本页说明</li><li><strong>配置项的 value</strong>(按 <code>type</code> 分派,富文本类型为 <code>ueditor</code>)→ <code>HasConfigValueProcessing</code> Trait,见 <a href="/zh/core/config.html">5.12 系统配置管理</a></li></ul><p>前两者由 <code>HasFileProcessing</code> Trait 提供,按属性声明分别启用;配置项不声明字段列表,而是由记录自身的 <code>type</code> 决定处理方式。</p></div>`,21)])])}const g=i(l,[["render",t]]);export{c as __pageData,g as default};