mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 16:02:48 +08:00
refactor(phone-image): 配置字段对齐,架构文档更新
- PHP getConfigFields 移除 template/font,新增 pageAlignments - validateConfig 字段与 getConfigFields 一致 - 架构文档更新数据流、配置体系、已知问题、修复记录章节
This commit is contained in:
@@ -53,7 +53,44 @@ PhoneImageEngine.render() -- L129: 管线入口,带并发
|
||||
|
||||
## 2. 数据流
|
||||
|
||||
### 2.1 HTML内容的三个来源(三源问题)
|
||||
### 2.1 修复后的单一数据源模型(当前状态)
|
||||
|
||||
修复后,引擎闭包变量 `postData.content_html` 成为唯一的权威数据源,所有读写操作统一通过引擎 API 进行。
|
||||
|
||||
**权威数据源**:闭包 `postData.content_html`(`phone-image.js:32`),通过以下两个 API 对外暴露:
|
||||
|
||||
| API | 位置 | 用途 |
|
||||
|-----|------|------|
|
||||
| `getContentHtml()` | `phone-image.js:1485-1487` | 返回 `postData.content_html`,外部获取内容的唯一标准接口 |
|
||||
| `updateConfig(newConfig)` | `phone-image.js:1488-1492` | 使用 `$.extend(config, newConfig)` 更新配置,**不重置** `postData` |
|
||||
|
||||
**DOM `#post-content-html` 的角色降级**:仅作为初始化数据源和显示层,不再被保存操作读取。保存后主动同步 `$('#post-content-html').html(PhoneImageEngine.getContentHtml())`(`phone_image.html:271`, `phone_image.html:295`),保持显示层与权威源一致。
|
||||
|
||||
**各操作的数据流**:
|
||||
|
||||
```
|
||||
保存配置 (#btn-save):
|
||||
content_html 取自 PhoneImageEngine.getContentHtml() -- L268
|
||||
保存后同步: $('#post-content-html').html(getContentHtml()) -- L271
|
||||
|
||||
生成并保存 (#btn-generate):
|
||||
content_html 取自 PhoneImageEngine.getContentHtml() -- L290
|
||||
保存后同步: $('#post-content-html').html(getContentHtml()) -- L295
|
||||
|
||||
重新排版 (doRender):
|
||||
用 PhoneImageEngine.updateConfig(newConfig) -- L239
|
||||
不再调用 init(),不重置 postData.content_html
|
||||
|
||||
加载历史 (loadFromHistory):
|
||||
PhoneImageEngine.init(postData, historyConfig) -- L414 (全量初始化)
|
||||
PhoneImageEngine.render() -- L416
|
||||
```
|
||||
|
||||
**分页标记操作**仍然直接修改闭包内的 `postData.content_html`(`insertPageBreak` L1223, `removePageBreak` L1261),但保存时通过 `getContentHtml()` 读取,确保标记不会丢失。
|
||||
|
||||
### 2.2 修复前的三源问题(历史记录)
|
||||
|
||||
> 以下记录修复前的问题状态,保留作为设计决策参考。
|
||||
|
||||
文章HTML内容在运行时存在于三个独立位置,彼此之间没有同步机制:
|
||||
|
||||
@@ -74,9 +111,9 @@ PhoneImageEngine.render() -- L129: 管线入口,带并发
|
||||
-> 闭包 postData.content_html = options.contentHtml (phone-image.js:85)
|
||||
```
|
||||
|
||||
**问题**:分页标记操作(`insertPageBreak`/`removePageBreak`)只更新闭包内的 `postData.content_html`(`phone-image.js:1223`, `phone-image.js:1261`),不更新 DOM `#post-content-html` 和模板局部的 `postData.contentHtml`。而保存操作(`#btn-save`, `#btn-generate`)读取的是 `$('#post-content-html').html()`(`phone_image.html:267`, `phone_image.html:288`),这意味着分页标记在保存时会丢失。
|
||||
**问题(已修复)**:分页标记操作(`insertPageBreak`/`removePageBreak`)只更新闭包内的 `postData.content_html`(`phone-image.js:1223`, `phone-image.js:1261`),不更新 DOM `#post-content-html` 和模板局部的 `postData.contentHtml`。而保存操作(`#btn-save`, `#btn-generate`)原来读取的是 `$('#post-content-html').html()`,这意味着分页标记在保存时会丢失。此问题已通过将保存操作改为读取 `getContentHtml()` 修复。
|
||||
|
||||
### 2.2 完整数据流图
|
||||
### 2.3 完整数据流图(修复后)
|
||||
|
||||
```
|
||||
[数据库 Post.content_html]
|
||||
@@ -98,15 +135,16 @@ phone_image.html 模板渲染
|
||||
|
|
||||
v
|
||||
渲染管线 (phone-image.js render())
|
||||
- 读取 postData.content_html
|
||||
- 读取 postData.content_html (唯一权威源)
|
||||
- 生成 pages 数组
|
||||
- 截图显示缩略图
|
||||
|
|
||||
v
|
||||
用户交互
|
||||
- 分页标记 -> 修改 postData.content_html (闭包内)
|
||||
- 保存配置 -> POST savePostOutputConfig (content_html 取自 DOM)
|
||||
- 生成保存 -> POST savePostOutput (content_html 取自 DOM)
|
||||
- 保存配置 -> POST savePostOutputConfig (content_html 取自 getContentHtml())
|
||||
- 生成保存 -> POST savePostOutput (content_html 取自 getContentHtml())
|
||||
- 重新排版 -> updateConfig() + render() (不重置 postData)
|
||||
|
|
||||
v
|
||||
后端存储
|
||||
@@ -114,18 +152,18 @@ phone_image.html 模板渲染
|
||||
- PostOutputFile (每页图片文件记录)
|
||||
```
|
||||
|
||||
### 2.3 历史记录加载流
|
||||
### 2.4 历史记录加载流(修复后)
|
||||
|
||||
```
|
||||
loadFromHistory(outputId) (phone_image.html:371)
|
||||
loadFromHistory(outputId) (phone_image.html:374)
|
||||
-> GET loadPostOutputConfig?id=XXX
|
||||
-> 更新表单控件 (size/fontSize/watermark)
|
||||
-> 更新 postData.contentHtml (模板局部变量)
|
||||
-> 更新 DOM #post-content-html
|
||||
-> doRender(renderConfig) (含 pageAlignments)
|
||||
-> PhoneImageEngine.init(postData, historyConfig) (全量初始化, L414)
|
||||
-> PhoneImageEngine.render() (L416)
|
||||
```
|
||||
|
||||
注意:`loadFromHistory` 更新的是模板局部的 `postData.contentHtml` 和 DOM,但没有直接更新闭包内的 `postData.content_html`。它依赖 `doRender -> init()` 的间接传递来同步。
|
||||
修复后 `loadFromHistory` 使用 `init + render` 全量初始化引擎,直接将历史内容传入闭包,不再依赖 `doRender` 的间接传递。
|
||||
|
||||
## 3. 存储模型
|
||||
|
||||
@@ -182,17 +220,20 @@ loadFromHistory(outputId) (phone_image.html:371)
|
||||
|
||||
## 4. 配置体系
|
||||
|
||||
### 4.1 PHP 端配置字段定义
|
||||
### 4.1 PHP 端配置字段定义(对齐后)
|
||||
|
||||
`PhoneImage::getConfigFields()` (L15-23) 定义了5个字段:
|
||||
`PhoneImage::getConfigFields()` (L15-23) 定义了4个字段,已与 JS 端对齐:
|
||||
|
||||
| 字段 | 类型 | 选项/范围 | 默认值 |
|
||||
|------|------|-----------|--------|
|
||||
| `template` | select | minimal/magazine/mixed | minimal |
|
||||
| `size` | select | xiaohongshu/douyin | xiaohongshu |
|
||||
| `font` | select | source-han-sans/alibaba-puhuiti/lxgw-wenkai | source-han-sans |
|
||||
| `fontSize` | number | 10-24 | 14 |
|
||||
| `watermark` | text | - | '' |
|
||||
| `pageAlignments` | json | - | '{}' |
|
||||
|
||||
**已移除的字段**:`template`(3个模板选项 minimal/magazine/mixed)和 `font`(3个字体选项 source-han-sans/alibaba-puhuiti/lxgw-wenkai)已从 `getConfigFields()` 中移除,因为 JS 端无对应的模板/字体切换逻辑。
|
||||
|
||||
**新增的字段**:`pageAlignments` 已新增到 `getConfigFields()`,类型为 `json`,默认值 `'{}'`,与 JS 端的逐页对齐功能对齐。
|
||||
|
||||
### 4.2 JS 端实际使用的配置
|
||||
|
||||
@@ -209,52 +250,63 @@ config = {
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 PHP/JS 字段不对齐
|
||||
### 4.3 PHP/JS 字段对齐状态(修复后)
|
||||
|
||||
两端存在明显的字段定义差异:
|
||||
修复后两端字段已基本对齐:
|
||||
|
||||
| 问题 | PHP 定义 | JS 实际使用 |
|
||||
|------|----------|-------------|
|
||||
| `template` | PHP有定义 (3个模板选项) | JS完全不使用,无任何模板切换逻辑 |
|
||||
| `font` | PHP有定义 (3个字体选项) | JS不使用,字体通过CSS引入,无切换机制 |
|
||||
| `pageAlignments` | PHP未定义 | JS核心功能,保存在config中 |
|
||||
| `contentPadding` | PHP未定义 | JS硬编码为20 (L23) |
|
||||
| 字段 | PHP 定义 | JS 使用 | 状态 |
|
||||
|------|----------|---------|------|
|
||||
| `size` | select, 2个选项 | 核心功能 | 已对齐 |
|
||||
| `fontSize` | number, 10-24 | 核心功能 | 已对齐 |
|
||||
| `watermark` | text | 核心功能 | 已对齐 |
|
||||
| `pageAlignments` | json | 核心功能 | 已对齐 |
|
||||
| `contentPadding` | 未定义 | 硬编码为20 (L23) | 仍为 JS 内部常量,无需 PHP 定义 |
|
||||
|
||||
`validateConfig()` (L29-50) 验证 `template`/`size`/`font`/`fontSize`,但 `pageAlignments` 不在验证范围内。前端发送的配置比PHP定义的字段多,PHP不做字段白名单过滤,全部存入JSON。
|
||||
`validateConfig()` (L28-50) 验证 `size`/`fontSize`,`pageAlignments` 为 JSON 类型不做严格校验。前端发送的配置比 PHP 定义的字段多(如 `content_html`、`sizes`、`contentPadding`),PHP 不做字段白名单过滤,全部存入 JSON config 字段。
|
||||
|
||||
> **修复前的字段不对齐记录**:`template`(PHP 有定义但 JS 不使用)和 `font`(PHP 有定义但 JS 不使用)已从 PHP 端移除;`pageAlignments`(JS 核心功能但 PHP 未定义)已新增到 PHP 端。
|
||||
|
||||
## 5. 已知问题
|
||||
|
||||
### 5.1 分页标记丢失(根因分析)
|
||||
### 5.1 已修复
|
||||
|
||||
#### 5.1.1 分页标记丢失(已修复)
|
||||
|
||||
**现象**:用户通过中间栏的 "+" 按钮插入分页标记后,点击"保存"或"生成并保存",重新加载页面时分页标记消失。
|
||||
|
||||
**根因**:数据源不一致。
|
||||
**根因**:数据源不一致。分页标记写入闭包 `postData.content_html`,但保存时读取的是 DOM `#post-content-html`(不含标记)。
|
||||
|
||||
分页标记的插入流程 (`insertPageBreak`, L1198-1227):
|
||||
1. 从闭包 `postData.content_html` 读取内容
|
||||
2. 在目标位置插入 `<hr>` 标签
|
||||
3. 写回闭包 `postData.content_html`(L1223)
|
||||
**修复方案**:保存操作改用 `PhoneImageEngine.getContentHtml()` 读取闭包内的权威数据源(`phone_image.html:268`, `phone_image.html:290`),保存后主动同步 DOM(`phone_image.html:271`, `phone_image.html:295`)。
|
||||
|
||||
保存操作的配置构建 (`phone_image.html:262-268`, `284-289`):
|
||||
```javascript
|
||||
content_html: $('#post-content-html').html() // 读取的是DOM元素
|
||||
```
|
||||
#### 5.1.2 双数据源不一致(已修复)
|
||||
|
||||
DOM `#post-content-html` 的内容在页面初始化后从未被 `insertPageBreak` 更新。因此保存时发送的 `content_html` 是初始值,不含 `<hr>` 分页标记。下次加载页面时,服务端用这个无标记的内容渲染,标记丢失。
|
||||
**现象**:`doRender` 调用 `init()` 重置 `postData.content_html`,导致分页标记在重新排版时丢失。
|
||||
|
||||
### 5.2 保存数据量限制
|
||||
**根因**:`doRender` 通过 `init()` 传递配置,`init()` 会用 DOM 内容覆盖闭包变量。
|
||||
|
||||
**修复方案**:`doRender` 改用 `PhoneImageEngine.updateConfig(newConfig)`(`phone_image.html:239`),仅更新配置不重置 `postData`。
|
||||
|
||||
#### 5.1.3 PHP/JS 字段不对齐(已修复)
|
||||
|
||||
**现象**:PHP 定义了 JS 不使用的 `template`/`font` 字段,缺少 JS 核心使用的 `pageAlignments` 字段。
|
||||
|
||||
**修复方案**:PHP `getConfigFields()` 移除 `template`/`font`,新增 `pageAlignments`(`PhoneImage.php:17-22`)。
|
||||
|
||||
### 5.2 仍存在的问题
|
||||
|
||||
#### 5.2.1 保存数据量限制
|
||||
|
||||
`saveImages()` 有16MB的客户端检查(`phone-image.js:1317-1320`),但服务端没有对应的分块接收机制。大文章(超过约30页)的base64数据可能超出 PHP `post_max_size` 配置。
|
||||
|
||||
### 5.3 目录权限 0777
|
||||
#### 5.2.2 目录权限 0777
|
||||
|
||||
`PhoneImage.php:95` 和 `:140` 中 `mkdir` 使用 0777 权限,与项目其他位置的 anti-pattern 一致。
|
||||
|
||||
### 5.4 接口 `PostOutputManagerInterface` 未被充分利用
|
||||
#### 5.2.3 接口 `PostOutputManagerInterface` 未被充分利用
|
||||
|
||||
`PhoneImage` 实现了 `process()` 和 `getPreview()` 方法,但两者都返回空值(`PhoneImage.php:56-67`)。实际业务完全在控制器中直接调用 `PhoneImage` 的其他方法,绕过了接口定义的流程。接口仅作为类型约束存在。
|
||||
|
||||
### 5.5 `saveConfigOnly` 是静态方法但 `createOutput` 是实例方法
|
||||
#### 5.2.4 `saveConfigOnly` 是静态方法但 `createOutput` 是实例方法
|
||||
|
||||
`PhoneImage::saveConfigOnly()` 是 static 方法(L223),而同类的 `createOutput()` 是实例方法(L193)。两者的实现几乎相同(都是 `PostOutput::create()`),但调用方式不同。控制器中 `savePostOutput` 通过实例调用 `createOutput`,`savePostOutputConfig` 通过静态调用 `saveConfigOnly`,风格不统一。
|
||||
|
||||
@@ -305,11 +357,40 @@ DOM `#post-content-html` 的内容在页面初始化后从未被 `insertPageBrea
|
||||
|
||||
---
|
||||
|
||||
## 7. 修复记录
|
||||
|
||||
### 7.1 数据源统一修复
|
||||
|
||||
**修复日期**:2026-05-11
|
||||
|
||||
**核心原理**:将三个独立的数据源(DOM、闭包变量、模板局部变量)统一为单一权威数据源——引擎闭包变量 `postData.content_html`,通过新增的引擎 API 对外暴露。
|
||||
|
||||
**变更清单**:
|
||||
|
||||
| 变更 | 文件 | 说明 |
|
||||
|------|------|------|
|
||||
| 新增 `getContentHtml()` | `phone-image.js:1485-1487` | 返回闭包内 `postData.content_html`,外部获取内容的唯一接口 |
|
||||
| 新增 `updateConfig(newConfig)` | `phone-image.js:1488-1492` | 使用 `$.extend(config, newConfig)` 更新配置,不重置 `postData` |
|
||||
| 保存按钮改用 `getContentHtml()` | `phone_image.html:268` | `#btn-save` 的 `content_html` 取自引擎 API 而非 DOM |
|
||||
| 生成按钮改用 `getContentHtml()` | `phone_image.html:290` | `#btn-generate` 的 `content_html` 取自引擎 API 而非 DOM |
|
||||
| 保存后同步 DOM | `phone_image.html:271,295` | 保存成功后 `$('#post-content-html').html(getContentHtml())` |
|
||||
| `doRender` 改用 `updateConfig()` | `phone_image.html:239` | 替代 `init()` 调用,避免重置 `postData.content_html` |
|
||||
| `loadFromHistory` 改用 `init + render` | `phone_image.html:414-416` | 全量初始化引擎,直接传入历史内容 |
|
||||
| PHP `getConfigFields` 移除 `template`/`font` | `PhoneImage.php:17-22` | 移除 JS 端不使用的字段定义 |
|
||||
| PHP `getConfigFields` 新增 `pageAlignments` | `PhoneImage.php:21` | 与 JS 端逐页对齐功能对齐 |
|
||||
|
||||
**修复效果**:
|
||||
- 分页标记在保存和重新排版后不再丢失
|
||||
- 历史记录加载正确恢复内容和配置
|
||||
- PHP/JS 端配置字段定义一致
|
||||
|
||||
---
|
||||
|
||||
*文档基于以下源文件的完整阅读:*
|
||||
- `public/static/js/phone-image.js` (1487行)
|
||||
- `view/admin/post/phone_image.html` (425行)
|
||||
- `public/static/js/phone-image.js` (1495行)
|
||||
- `view/admin/post/phone_image.html` (436行)
|
||||
- `app/admin/controller/Post.php` (L350-579)
|
||||
- `app/common/tools/PhoneImage.php` (234行)
|
||||
- `app/common/tools/PhoneImage.php` (229行)
|
||||
- `app/common/tools/PostOutputManagerInterface.php` (28行)
|
||||
- `app/model/PostOutput.php` (62行)
|
||||
- `app/model/PostOutputFile.php` (26行)
|
||||
|
||||
Reference in New Issue
Block a user