feat(api): 增强文章API功能并更新文档

- 为文章创建和更新接口添加 `publish_time` 字段支持
- 升级 Markdown 解析器以支持表格扩展
- 增加数据库字段默认值设置,避免严格模式错误
- 禁止客户端设置 `create_time` 和 `update_time` 字段
- 更新 API 文档以反映上述更改
- 将临时文件和工具目录添加到 .gitignore
This commit is contained in:
augushong
2026-04-30 12:17:50 +08:00
parent 6f332467df
commit cbf9b21b96
3 changed files with 86 additions and 10 deletions

3
.gitignore vendored
View File

@@ -10,3 +10,6 @@ public/upload/*
/public/.user.ini
.well-known
/runtime
/.sisyphus
/.trae
/token-usage-output.txt

View File

@@ -8,7 +8,10 @@ use app\BaseController;
use app\model\Post;
use app\model\PostCategory;
use app\model\PostTag;
use League\CommonMark\CommonMarkConverter;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\MarkdownConverter;
use think\Request;
class Articles extends BaseController
@@ -95,6 +98,9 @@ class Articles extends BaseController
unset($post_data['tags']);
}
// 禁止客户端设置的时间字段
unset($post_data['create_time'], $post_data['update_time']);
$post_data['uid'] = uniqid();
$post_data['source'] = 'api';
$post_data['create_time'] = time();
@@ -110,16 +116,46 @@ class Articles extends BaseController
$post_data['content_type'] = 'html';
}
// 校验 publish_time 格式(必须是 Y-m-d H:i:s
if (isset($post_data['publish_time']) && !empty($post_data['publish_time'])) {
if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $post_data['publish_time'])) {
return json_message('publish_time 格式错误,应为 Y-m-d H:i:s如 2024-01-15 14:30:00');
}
}
// content_type 白名单校验
$allowed_content_types = ['html', 'markdown'];
if (!in_array($post_data['content_type'], $allowed_content_types)) {
return json_message('无效的content_type', 500);
}
// Markdown→HTML 自动转换
// Markdown→HTML 自动转换(启用表格扩展)
if ($post_data['content_type'] === 'markdown' && !empty($post_data['content'])) {
$converter = new CommonMarkConverter(['html_input' => 'strip', 'allow_unsafe_links' => false]);
$post_data['content_html'] = $converter->convert($post_data['content']);
$environment = Environment::createCommonMarkEnvironment();
$environment->addExtension(new TableExtension());
$converter = new MarkdownConverter($environment);
$post_data['content_html'] = $converter->convert($post_data['content'])->getContent();
}
// 提供字段默认值,避免数据库严格模式报错
$default_fields = [
'jump_to_btn_title' => '',
'jump_to_url' => '',
'jump_to_url_status' => 0,
'poster' => '',
'desc' => '',
'author_name' => '',
'hits' => 0,
'is_top' => 0,
'sort' => 0,
'files' => '',
'pictures' => '',
'tpl_name' => '',
];
foreach ($default_fields as $field => $default) {
if (!isset($post_data[$field])) {
$post_data[$field] = $default;
}
}
$model_post = Post::create($post_data);
@@ -169,6 +205,16 @@ class Articles extends BaseController
$post_data = $request->post();
unset($post_data['id']);
// 禁止客户端设置的时间字段
unset($post_data['create_time'], $post_data['update_time']);
// 校验 publish_time 格式(必须是 Y-m-d H:i:s
if (isset($post_data['publish_time']) && !empty($post_data['publish_time'])) {
if (!preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $post_data['publish_time'])) {
return json_message('publish_time 格式错误,应为 Y-m-d H:i:s如 2024-01-15 14:30:00');
}
}
// categorys diff update
if (isset($post_data['categorys'])) {
$categorys = $post_data['categorys'];
@@ -217,10 +263,33 @@ class Articles extends BaseController
}
}
// Markdown→HTML 自动转换
// Markdown→HTML 自动转换(启用表格扩展)
if (isset($post_data['content_type']) && $post_data['content_type'] === 'markdown' && !empty($post_data['content'])) {
$converter = new CommonMarkConverter(['html_input' => 'strip', 'allow_unsafe_links' => false]);
$post_data['content_html'] = $converter->convert($post_data['content']);
$environment = Environment::createCommonMarkEnvironment();
$environment->addExtension(new TableExtension());
$converter = new MarkdownConverter($environment);
$post_data['content_html'] = $converter->convert($post_data['content'])->getContent();
}
// 提供字段默认值,避免数据库严格模式报错
$default_fields = [
'jump_to_btn_title' => '',
'jump_to_url' => '',
'jump_to_url_status' => 0,
'poster' => '',
'desc' => '',
'author_name' => '',
'hits' => 0,
'is_top' => 0,
'sort' => 0,
'files' => '',
'pictures' => '',
'tpl_name' => '',
];
foreach ($default_fields as $field => $default) {
if (!isset($post_data[$field])) {
$post_data[$field] = $default;
}
}
$model_post->save($post_data);

View File

@@ -270,11 +270,13 @@ X-API-Key: {api_key}</div>
<tr><td>poster</td><td>string</td><td></td><td>封面图 URL</td></tr>
<tr><td>type</td><td>string</td><td></td><td>文章类型,默认 "1"</td></tr>
<tr><td>status</td><td>int</td><td></td><td>状态,默认 0草稿</td></tr>
<tr><td>content_type</td><td>string</td><td></td><td>内容类型: "html"(默认) 或 "markdown"</td></tr>
<tr><td>content_type</td><td>string</td><td></td><td>内容类型: "html"(默认) 或 "markdown"<br/>当为 "markdown" 时,系统会自动将 content 转换为 HTML 存储到 content_html 字段</td></tr>
<tr><td>categorys</td><td>array</td><td></td><td>分类 ID 数组,如 [1, 2]</td></tr>
<tr><td>tags</td><td>array</td><td></td><td>标签 ID 数组,如 [1, 2]</td></tr>
<tr><td>publish_time</td><td>string</td><td></td><td>发布时间,格式为 Y-m-d H:i:s如 2024-01-15 14:30:00</td></tr>
</tbody>
</table>
<p style="color:#888;margin-top:8px;"><strong>注:</strong><code>create_time</code><code>update_time</code> 由系统自动生成,客户端无需设置也无法修改。</p>
<h4>请求示例HTML</h4>
<div class="api-code">curl -X POST \
@@ -337,11 +339,13 @@ X-API-Key: {api_key}</div>
<tr><td>desc</td><td>string</td><td></td><td>文章摘要</td></tr>
<tr><td>poster</td><td>string</td><td></td><td>封面图 URL</td></tr>
<tr><td>status</td><td>int</td><td></td><td>状态</td></tr>
<tr><td>content_type</td><td>string</td><td></td><td>内容类型: "html"(默认) 或 "markdown"</td></tr>
<tr><td>content_type</td><td>string</td><td></td><td>内容类型: "html"(默认) 或 "markdown"<br/>当为 "markdown" 时,系统会自动将 content 转换为 HTML 存储到 content_html 字段</td></tr>
<tr><td>categorys</td><td>array</td><td></td><td>分类 ID 数组(全量覆盖)</td></tr>
<tr><td>tags</td><td>array</td><td></td><td>标签 ID 数组(全量覆盖)</td></tr>
<tr><td>publish_time</td><td>string</td><td></td><td>发布时间,格式为 Y-m-d H:i:s如 2024-01-15 14:30:00</td></tr>
</tbody>
</table>
<p style="color:#888;margin-top:8px;"><strong>注:</strong><code>create_time</code><code>update_time</code> 由系统自动生成,客户端无需设置也无法修改。</p>
<h4>请求示例</h4>
<div class="api-code">curl -X POST \