mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 14:52:48 +08:00
feat(content-type): add content_type field, markdown auto-conversion, and API doc updates
- Add content_type column to ul_post via migration - Install league/commonmark for markdown->HTML conversion - Add Post model accessors/setters for content_type and content - Update API Articles controller save/update with content_type support - Update API docs with content_type parameter and markdown example Closes content-type-support plan
This commit is contained in:
@@ -8,6 +8,7 @@ use app\BaseController;
|
||||
use app\model\Post;
|
||||
use app\model\PostCategory;
|
||||
use app\model\PostTag;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use think\Request;
|
||||
|
||||
class Articles extends BaseController
|
||||
@@ -105,6 +106,21 @@ class Articles extends BaseController
|
||||
if (!isset($post_data['status'])) {
|
||||
$post_data['status'] = 0;
|
||||
}
|
||||
if (!isset($post_data['content_type'])) {
|
||||
$post_data['content_type'] = 'html';
|
||||
}
|
||||
|
||||
// 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 自动转换
|
||||
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']);
|
||||
}
|
||||
|
||||
$model_post = Post::create($post_data);
|
||||
|
||||
@@ -201,6 +217,12 @@ class Articles extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
// 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']);
|
||||
}
|
||||
|
||||
$model_post->save($post_data);
|
||||
|
||||
return json_message([], 0, '更新成功');
|
||||
|
||||
@@ -156,6 +156,30 @@ class Post extends Base
|
||||
return trim($value);
|
||||
}
|
||||
|
||||
public function getContentTypeAttr($value)
|
||||
{
|
||||
return $value ?: 'html';
|
||||
}
|
||||
|
||||
public function setContentTypeAttr($value)
|
||||
{
|
||||
if (!in_array($value, ['html', 'markdown'], true)) {
|
||||
throw new \InvalidArgumentException('Invalid content_type: ' . $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function setContentAttr($value)
|
||||
{
|
||||
return trim($value);
|
||||
}
|
||||
|
||||
public function getContentAttr($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getContentMarkdownAttr()
|
||||
{
|
||||
$content_html = $this->getAttr('content_html');
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
"topthink/think-filesystem": "^2.0",
|
||||
"mibe/feedwriter": "^1.1",
|
||||
"matomo/device-detector": "^6.1",
|
||||
"intervention/image": "^2.7"
|
||||
"intervention/image": "^2.7",
|
||||
"league/commonmark": "^2.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^4.2"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use think\migration\Migrator;
|
||||
use think\migration\db\Column;
|
||||
|
||||
class AddContentTypeToPost extends Migrator
|
||||
{
|
||||
/**
|
||||
* Change Method.
|
||||
*
|
||||
* Write your reversible migrations using this method.
|
||||
*
|
||||
* More information on writing migrations is available here:
|
||||
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
|
||||
*
|
||||
* The following commands can be used in this method and Phinx will
|
||||
* automatically reverse them when rolling back:
|
||||
*
|
||||
* createTable
|
||||
* renameTable
|
||||
* addColumn
|
||||
* renameColumn
|
||||
* addIndex
|
||||
* addForeignKey
|
||||
*
|
||||
* Remember to call "create()" or "update()" and NOT "save()" when working
|
||||
* with the Table class.
|
||||
*/
|
||||
public function change()
|
||||
{
|
||||
$this->table('post')->addColumn(
|
||||
Column::make('content_type', 'string', ['limit' => 20, 'default' => 'html', 'comment' => '内容类型: html/markdown'])
|
||||
)->update();
|
||||
}
|
||||
}
|
||||
@@ -196,6 +196,7 @@ X-API-Key: {api_key}</div>
|
||||
"id": 1,
|
||||
"title": "文章标题",
|
||||
"content": "文章内容",
|
||||
"content_type": "html",
|
||||
"type": "1",
|
||||
"status": 1,
|
||||
"source": "api",
|
||||
@@ -238,6 +239,7 @@ X-API-Key: {api_key}</div>
|
||||
"title": "文章标题",
|
||||
"content": "文章内容",
|
||||
"content_html": "<p>HTML内容</p>",
|
||||
"content_type": "html",
|
||||
"desc": "摘要",
|
||||
"poster": "/uploads/poster.jpg",
|
||||
"type": "1",
|
||||
@@ -268,12 +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>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>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>请求示例</h4>
|
||||
<h4>请求示例(HTML)</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/articles/save" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
@@ -286,6 +289,21 @@ X-API-Key: {api_key}</div>
|
||||
"tags": [3]
|
||||
}'</div>
|
||||
|
||||
<h4>请求示例(Markdown)</h4>
|
||||
<div class="api-code">curl -X POST \
|
||||
"https://example.com/index.php/api/articles/save" \
|
||||
-H "Authorization: Bearer your_api_key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"title": "Markdown 文章",
|
||||
"content": "# 标题\n\n段落内容",
|
||||
"content_type": "markdown",
|
||||
"type": "1",
|
||||
"status": 1,
|
||||
"categorys": [1, 2],
|
||||
"tags": [3]
|
||||
}'</div>
|
||||
|
||||
<h4>返回示例</h4>
|
||||
<div class="api-code">{
|
||||
"code": 0,
|
||||
@@ -319,6 +337,7 @@ 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>categorys</td><td>array</td><td>否</td><td>分类 ID 数组(全量覆盖)</td></tr>
|
||||
<tr><td>tags</td><td>array</td><td>否</td><td>标签 ID 数组(全量覆盖)</td></tr>
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user