From cbf9b21b96950b778924e2e84bd52d9febc651c0 Mon Sep 17 00:00:00 2001 From: augushong Date: Thu, 30 Apr 2026 12:17:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(api):=20=E5=A2=9E=E5=BC=BA=E6=96=87?= =?UTF-8?q?=E7=AB=A0API=E5=8A=9F=E8=83=BD=E5=B9=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为文章创建和更新接口添加 `publish_time` 字段支持 - 升级 Markdown 解析器以支持表格扩展 - 增加数据库字段默认值设置,避免严格模式错误 - 禁止客户端设置 `create_time` 和 `update_time` 字段 - 更新 API 文档以反映上述更改 - 将临时文件和工具目录添加到 .gitignore --- .gitignore | 5 +- app/api/controller/Articles.php | 83 ++++++++++++++++++++++++++++++--- view/index/api_doc/index.html | 8 +++- 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 8178be2..9a1b986 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,7 @@ public/upload/* /public/.well-known /public/.user.ini .well-known -/runtime \ No newline at end of file +/runtime +/.sisyphus +/.trae +/token-usage-output.txt \ No newline at end of file diff --git a/app/api/controller/Articles.php b/app/api/controller/Articles.php index e454520..3baefd7 100644 --- a/app/api/controller/Articles.php +++ b/app/api/controller/Articles.php @@ -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); diff --git a/view/index/api_doc/index.html b/view/index/api_doc/index.html index a18e6f5..a0ceb03 100644 --- a/view/index/api_doc/index.html +++ b/view/index/api_doc/index.html @@ -270,11 +270,13 @@ X-API-Key: {api_key} posterstring否封面图 URL typestring否文章类型,默认 "1" statusint否状态,默认 0(草稿) - content_typestring否内容类型: "html"(默认) 或 "markdown" + content_typestring否内容类型: "html"(默认) 或 "markdown"
当为 "markdown" 时,系统会自动将 content 转换为 HTML 存储到 content_html 字段 categorysarray否分类 ID 数组,如 [1, 2] tagsarray否标签 ID 数组,如 [1, 2] + publish_timestring否发布时间,格式为 Y-m-d H:i:s,如 2024-01-15 14:30:00 +

注:create_timeupdate_time 由系统自动生成,客户端无需设置也无法修改。

请求示例(HTML)

curl -X POST \ @@ -337,11 +339,13 @@ X-API-Key: {api_key}
descstring否文章摘要 posterstring否封面图 URL statusint否状态 - content_typestring否内容类型: "html"(默认) 或 "markdown" + content_typestring否内容类型: "html"(默认) 或 "markdown"
当为 "markdown" 时,系统会自动将 content 转换为 HTML 存储到 content_html 字段 categorysarray否分类 ID 数组(全量覆盖) tagsarray否标签 ID 数组(全量覆盖) + publish_timestring否发布时间,格式为 Y-m-d H:i:s,如 2024-01-15 14:30:00 +

注:create_timeupdate_time 由系统自动生成,客户端无需设置也无法修改。

请求示例

curl -X POST \