97 lines
32 KiB
JavaScript
97 lines
32 KiB
JavaScript
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 "7.3 富文本处理""></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 "处理流程图""></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>│ ├─ 解析 <img> 标签的 src │</span></span>
|
||
<span class="line"><span>│ ├─ 解析 <video>/<source>/<embed> 标签的 src │</span></span>
|
||
<span class="line"><span>│ ├─ 解析 <a> 标签的文件 href │</span></span>
|
||
<span class="line"><span>│ │ │</span></span>
|
||
<span class="line"><span>│ ▼ │</span></span>
|
||
<span class="line"><span>│ save_content(&$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 "在 Service 中配置""></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;">'</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">content</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</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 "为什么使用占位符?""></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 "处理范围""></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><img></code></td><td><code>src</code></td><td>图片</td></tr><tr><td><code><video></code></td><td><code>src</code></td><td>视频</td></tr><tr><td><code><source></code></td><td><code>src</code></td><td>视频源</td></tr><tr><td><code><embed></code></td><td><code>src</code></td><td>嵌入内容</td></tr><tr><td><code><a></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 "代码示例""></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;"> &</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;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">article</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</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;">'</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">file</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</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;">'</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">domain_url</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</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;"> ''</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> '</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">/</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">'</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. 匹配 <img> 标签的 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;"> '/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;"><img</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^></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;">"\\'</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;">^"\\'>\\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'</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. 匹配 <video>/<source>/<embed> 标签的 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;"> '/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;"><(?:video|source|embed)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^></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;">"\\'</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;">^"\\'>\\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'</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. 匹配 <a> 标签的 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;"> '/</span><span style="--shiki-dark:#E7EE98;--shiki-light:#AB5E3F;"><a</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">^></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;">"\\'</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;">^"\\'>\\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;">"\\'</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'</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 "注意事项""></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};
|