mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 14:52:48 +08:00
refactor(phone-image): Wave 2 - form, controller, JS engine, API updates
T3: Add cover_text textarea to post edit form T4: Update Post controller - content copy + cover_text passing T5: Refactor JS engine - remove old APIs, add forced breaks, page numbers, per-page alignment T8: Add cover_text to API default_fields, apidoc (4 places), AGENTS.md
This commit is contained in:
@@ -73,6 +73,7 @@ AJAX请求 -> JSON; 普通请求 -> 模板页面(common@tpl/success|error)
|
||||
Post --(M:N)--> Category (通过 post_category)
|
||||
Post --(M:N)--> Tag (通过 post_tag)
|
||||
Post --(1:N)--> PostComment, PostVisit
|
||||
Post 字段含 cover_text: 封面文案,用于手机图片排版封面展示
|
||||
Admin --(N:1)--> AdminGroup --(权限列表)--> AdminPermission
|
||||
表前缀: ul_,时间戳: int(10),软删除: delete_time字段
|
||||
```
|
||||
|
||||
@@ -358,7 +358,24 @@ class Post extends Common
|
||||
if (empty($model_post)) {
|
||||
$this->error('文章不存在');
|
||||
}
|
||||
|
||||
// 查询已有的排版输出,获取排版内容副本
|
||||
$postOutput = \app\model\PostOutput::where('post_id', $id)
|
||||
->where('output_type', 'phone_image')
|
||||
->order('id', 'desc')
|
||||
->find();
|
||||
|
||||
// 排版内容副本:优先使用已保存的副本,否则使用原文
|
||||
$layoutContentHtml = $model_post->content_html;
|
||||
$layoutConfig = [];
|
||||
if ($postOutput && !empty($postOutput->config['content_html'])) {
|
||||
$layoutContentHtml = $postOutput->config['content_html'];
|
||||
$layoutConfig = $postOutput->config;
|
||||
}
|
||||
|
||||
View::assign('post', $model_post);
|
||||
View::assign('layoutContentHtml', $layoutContentHtml);
|
||||
View::assign('layoutConfig', $layoutConfig);
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
@@ -395,6 +412,10 @@ class Post extends Common
|
||||
}
|
||||
|
||||
$config = $data['config'] ?? [];
|
||||
// 确保排版内容副本被保存到 config
|
||||
if (isset($data['content_html']) && !isset($config['content_html'])) {
|
||||
$config['content_html'] = $data['content_html'];
|
||||
}
|
||||
$pages = $data['pages'] ?? [];
|
||||
|
||||
$admin_id = session('admin_id') ?? 0;
|
||||
|
||||
@@ -154,6 +154,7 @@ class Articles extends BaseController
|
||||
'jump_to_url_status' => 0,
|
||||
'poster' => '',
|
||||
'desc' => '',
|
||||
'cover_text' => '',
|
||||
'author_name' => '',
|
||||
'hits' => 0,
|
||||
'is_top' => 0,
|
||||
|
||||
@@ -12,23 +12,14 @@ var PhoneImageEngine = (function () {
|
||||
|
||||
// ===== 配置 =====
|
||||
var config = {
|
||||
template: 'minimal',
|
||||
size: 'xiaohongshu',
|
||||
font: 'source-han-sans',
|
||||
fontSize: 14,
|
||||
watermark: '',
|
||||
// 尺寸映射 (渲染尺寸, 实际输出是2倍)
|
||||
pageAlignments: {}, // key=页码(1-based), value='top'|'center'
|
||||
sizes: {
|
||||
xiaohongshu: { width: 540, height: 720 },
|
||||
douyin: { width: 540, height: 960 }
|
||||
},
|
||||
// 字体映射
|
||||
fonts: {
|
||||
'source-han-sans': "'Source Han Sans', 'SourceHanSans-Normal', sans-serif",
|
||||
'alibaba-puhuiti': "'AlibabaPuHuiTi', sans-serif",
|
||||
'lxgw-wenkai': "'LXGWWenKai', cursive"
|
||||
},
|
||||
// 页面内容边距
|
||||
contentPadding: 20
|
||||
};
|
||||
|
||||
@@ -37,6 +28,7 @@ var PhoneImageEngine = (function () {
|
||||
id: 0,
|
||||
title: '',
|
||||
desc: '',
|
||||
coverText: '', // 封面文案
|
||||
content_html: '',
|
||||
poster: '',
|
||||
author_name: '',
|
||||
@@ -47,18 +39,16 @@ var PhoneImageEngine = (function () {
|
||||
// ===== 分页结果 =====
|
||||
var pages = [];
|
||||
|
||||
// ===== DOM引用 =====
|
||||
var $container = null;
|
||||
|
||||
/**
|
||||
* 初始化引擎
|
||||
* @param {Object} options - {postId, title, desc, contentHtml, poster, authorName, createTime, categoryName}
|
||||
* @param {Object} userConfig - {template, size, font, fontSize, watermark}
|
||||
* @param {Object} options - {postId, title, desc, coverText, contentHtml, poster, authorName, createTime, categoryName}
|
||||
* @param {Object} userConfig - {size, fontSize, watermark}
|
||||
*/
|
||||
function init(options, userConfig) {
|
||||
postData.id = options.postId || 0;
|
||||
postData.title = options.title || '';
|
||||
postData.desc = options.desc || '';
|
||||
postData.coverText = options.coverText || '';
|
||||
postData.content_html = options.contentHtml || '';
|
||||
postData.poster = options.poster || '';
|
||||
postData.author_name = options.authorName || '';
|
||||
@@ -68,12 +58,11 @@ var PhoneImageEngine = (function () {
|
||||
if (userConfig) {
|
||||
$.extend(config, userConfig);
|
||||
}
|
||||
|
||||
$container = $('#phone-image-container');
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染排版预览 - 生成分页后的HTML
|
||||
* 两遍遍历: 先算总页数, 再带页码生成
|
||||
* @returns {Array} 页面数组,每项是 { type, html, pageNum }
|
||||
*/
|
||||
function render() {
|
||||
@@ -82,22 +71,31 @@ var PhoneImageEngine = (function () {
|
||||
var pageHeight = sizeConfig.height;
|
||||
var contentAreaHeight = pageHeight - (config.contentPadding * 2);
|
||||
|
||||
// 内容预处理
|
||||
var cleanHtml = preprocessContent(postData.content_html);
|
||||
|
||||
// 解析为块级元素
|
||||
var blocks = parseHtmlToBlocks(cleanHtml);
|
||||
|
||||
// 生成封面页
|
||||
// 封面页
|
||||
pages.push(generateCoverPage(sizeConfig));
|
||||
|
||||
// 内容分页
|
||||
var contentPages = paginateContent(blocks, contentAreaHeight, sizeConfig);
|
||||
pages = pages.concat(contentPages);
|
||||
|
||||
// 生成尾页
|
||||
// 尾页
|
||||
pages.push(generateSummaryPage(sizeConfig, pages.length));
|
||||
|
||||
// 两遍遍历: 现在知道了总页数, 给每页补上 N/M 页码
|
||||
var totalPages = pages.length;
|
||||
for (var i = 0; i < pages.length; i++) {
|
||||
if (pages[i].type === 'content') {
|
||||
// 在页脚中添加 N/M 格式页码
|
||||
pages[i].html = pages[i].html.replace(
|
||||
'<span>' + pages[i].pageNum + '</span>',
|
||||
'<span class="page-number-indicator">' + (i + 1) + '/' + totalPages + '</span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染到DOM
|
||||
renderToDOM(sizeConfig);
|
||||
|
||||
@@ -191,6 +189,11 @@ var PhoneImageEngine = (function () {
|
||||
};
|
||||
|
||||
switch (tagName) {
|
||||
case 'hr':
|
||||
block.type = 'page-break';
|
||||
block.html = '';
|
||||
block.estimatedHeight = 0;
|
||||
break;
|
||||
case 'h1':
|
||||
case 'h2':
|
||||
case 'h3':
|
||||
@@ -296,7 +299,7 @@ var PhoneImageEngine = (function () {
|
||||
|
||||
/**
|
||||
* 将块级元素按高度累加,超过可用高度时分页
|
||||
* 支持超大块拆分(超长文本拆成多段)
|
||||
* 支持 <hr> 强制分页和超大块拆分(超长文本拆成多段)
|
||||
*/
|
||||
function paginateContent(blocks, contentAreaHeight, sizeConfig) {
|
||||
var contentPages = [];
|
||||
@@ -307,6 +310,20 @@ var PhoneImageEngine = (function () {
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var block = blocks[i];
|
||||
|
||||
// 强制分页标记
|
||||
if (block.type === 'page-break') {
|
||||
// 结束当前页
|
||||
if (currentPageBlocks.length > 0) {
|
||||
contentPages.push(generateContentPage(
|
||||
currentPageBlocks, pageNumber, sizeConfig, false
|
||||
));
|
||||
currentPageBlocks = [];
|
||||
currentHeight = 0;
|
||||
pageNumber++;
|
||||
}
|
||||
continue; // 跳过这个 page-break 块本身
|
||||
}
|
||||
|
||||
// 超大块处理:单个块超过整页高度时需要拆分
|
||||
if (block.estimatedHeight > contentAreaHeight) {
|
||||
// 先把当前页已有的内容推出去
|
||||
@@ -449,6 +466,10 @@ var PhoneImageEngine = (function () {
|
||||
if (postData.desc) {
|
||||
html += '<div class="cover-subtitle">' + escapeHtml(postData.desc) + '</div>';
|
||||
}
|
||||
// 封面文案(有封面图)
|
||||
if (postData.coverText) {
|
||||
html += '<div style="font-size:14px;color:#1890ff;margin-top:8px;">' + escapeHtml(postData.coverText) + '</div>';
|
||||
}
|
||||
html += '<div class="cover-meta">';
|
||||
if (postData.category_name) {
|
||||
html += escapeHtml(postData.category_name) + ' | ';
|
||||
@@ -469,6 +490,10 @@ var PhoneImageEngine = (function () {
|
||||
if (postData.desc) {
|
||||
html += '<div class="cover-no-img-desc">' + escapeHtml(postData.desc) + '</div>';
|
||||
}
|
||||
// 封面文案(无封面图)
|
||||
if (postData.coverText) {
|
||||
html += '<div style="font-size:14px;color:#1890ff;margin-top:10px;padding:0 30px;word-break:break-word;">' + escapeHtml(postData.coverText) + '</div>';
|
||||
}
|
||||
html += '<div class="cover-no-img-meta">';
|
||||
if (postData.category_name) {
|
||||
html += '<span>' + escapeHtml(postData.category_name) + '</span>';
|
||||
@@ -490,13 +515,17 @@ var PhoneImageEngine = (function () {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成内容页HTML
|
||||
* 生成内容页HTML(含逐页对齐支持)
|
||||
*/
|
||||
function generateContentPage(blocks, pageNum, sizeConfig, isLast) {
|
||||
var html = '<div class="phone-image-page page-body" style="width:' +
|
||||
// 读取逐页对齐配置
|
||||
var alignment = (config.pageAlignments && config.pageAlignments[pageNum]) || 'top';
|
||||
var valignClass = alignment === 'center' ? ' valign-center' : '';
|
||||
|
||||
var html = '<div class="phone-image-page page-body' + valignClass + '" style="width:' +
|
||||
sizeConfig.width + 'px;height:' + sizeConfig.height + 'px;">';
|
||||
|
||||
// 页头(仅首页内容页显示标题)
|
||||
// 页头(仅第一页内容页显示标题)
|
||||
if (pageNum === 1) {
|
||||
html += '<div class="page-header">';
|
||||
html += '<div class="page-title">' + escapeHtml(postData.title) + '</div>';
|
||||
@@ -510,7 +539,7 @@ var PhoneImageEngine = (function () {
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
// 页脚
|
||||
// 页脚 - 占位,render() 中会替换页码
|
||||
html += '<div class="page-footer">';
|
||||
html += '<span>' + escapeHtml(postData.author_name || '') + '</span>';
|
||||
html += '<span>' + pageNum + '</span>';
|
||||
@@ -546,119 +575,46 @@ var PhoneImageEngine = (function () {
|
||||
|
||||
// ===== DOM渲染 =====
|
||||
|
||||
// 当前预览页码 (0-based)
|
||||
var currentPreviewPage = 0;
|
||||
|
||||
/**
|
||||
* 渲染分页结果到DOM
|
||||
* 全尺寸平铺渲染到 #paginated-preview
|
||||
*/
|
||||
function renderToDOM(sizeConfig) {
|
||||
if (!$container || !$container.length) return;
|
||||
var $preview = $('#paginated-preview');
|
||||
if (!$preview.length) return;
|
||||
|
||||
var containerClasses = [
|
||||
'phone-image-container',
|
||||
'tpl-' + config.template,
|
||||
'size-' + config.size,
|
||||
'font-' + config.font
|
||||
];
|
||||
|
||||
$container.attr('class', containerClasses.join(' '));
|
||||
$container.css({
|
||||
'font-family': config.fonts[config.font] || config.fonts['source-han-sans'],
|
||||
'font-size': config.fontSize + 'px'
|
||||
});
|
||||
|
||||
$container.empty();
|
||||
$preview.empty();
|
||||
for (var i = 0; i < pages.length; i++) {
|
||||
$container.append(pages[i].html);
|
||||
$preview.append(pages[i].html);
|
||||
}
|
||||
|
||||
// 确保当前页码有效
|
||||
if (currentPreviewPage >= pages.length) {
|
||||
currentPreviewPage = Math.max(0, pages.length - 1);
|
||||
}
|
||||
|
||||
// 显示当前页, 隐藏其他页
|
||||
showPreviewPage(currentPreviewPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示指定预览页
|
||||
* @param {number} index 页码(0-based)
|
||||
*/
|
||||
function showPreviewPage(index) {
|
||||
if (!$container || !$container.length) return;
|
||||
var $allPages = $container.find('.phone-image-page');
|
||||
$allPages.hide();
|
||||
if (index >= 0 && index < $allPages.length) {
|
||||
$allPages.eq(index).show();
|
||||
currentPreviewPage = index;
|
||||
}
|
||||
// 更新页码显示
|
||||
$container.trigger('pageChange', [currentPreviewPage, pages.length]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下一页
|
||||
*/
|
||||
function nextPage() {
|
||||
if (currentPreviewPage < pages.length - 1) {
|
||||
showPreviewPage(currentPreviewPage + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上一页
|
||||
*/
|
||||
function prevPage() {
|
||||
if (currentPreviewPage > 0) {
|
||||
showPreviewPage(currentPreviewPage - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前预览页码
|
||||
*/
|
||||
function getCurrentPageIndex() {
|
||||
return currentPreviewPage;
|
||||
}
|
||||
|
||||
// ===== 图片生成 =====
|
||||
|
||||
/**
|
||||
* 逐页截图生成图片
|
||||
* 逐页截图生成图片(简化版:所有页面已在DOM中可见)
|
||||
* @param {Function} [onProgress] 进度回调 function(currentIndex, totalPages, canvas)
|
||||
* @returns {Promise} jQuery Deferred, resolves with array of canvas objects
|
||||
*/
|
||||
function generateImages(onProgress) {
|
||||
var deferred = $.Deferred();
|
||||
var canvases = [];
|
||||
var $pages = $container.find('.phone-image-page');
|
||||
var $pages = $('#paginated-preview .phone-image-page');
|
||||
|
||||
if ($pages.length === 0) {
|
||||
deferred.reject('没有可渲染的页面');
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
// 截图时需要所有页面都显示
|
||||
$pages.show();
|
||||
|
||||
var index = 0;
|
||||
var total = $pages.length;
|
||||
|
||||
function captureNext() {
|
||||
if (index >= total) {
|
||||
if (onProgress) onProgress(total, total, null);
|
||||
// 恢复单页显示
|
||||
showPreviewPage(currentPreviewPage);
|
||||
deferred.resolve(canvases);
|
||||
return;
|
||||
}
|
||||
|
||||
// 隐藏其他页, 只显示当前要截图的页
|
||||
$pages.hide();
|
||||
$pages.eq(index).show();
|
||||
|
||||
html2canvas($pages.eq(index)[0], {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
@@ -672,8 +628,6 @@ var PhoneImageEngine = (function () {
|
||||
if (onProgress) onProgress(index, total, canvas);
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
// 恢复单页显示
|
||||
showPreviewPage(currentPreviewPage);
|
||||
deferred.reject('截图失败(第' + (index + 1) + '页): ' + err);
|
||||
});
|
||||
}
|
||||
@@ -748,16 +702,6 @@ var PhoneImageEngine = (function () {
|
||||
|
||||
// ===== 配置切换 =====
|
||||
|
||||
/**
|
||||
* 切换模板
|
||||
*/
|
||||
function switchTemplate(name) {
|
||||
config.template = name;
|
||||
if ($container) {
|
||||
$container.removeClass('tpl-minimal tpl-magazine tpl-mixed').addClass('tpl-' + name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换尺寸
|
||||
*/
|
||||
@@ -765,15 +709,18 @@ var PhoneImageEngine = (function () {
|
||||
config.size = name;
|
||||
}
|
||||
|
||||
// ===== 逐页对齐 =====
|
||||
|
||||
/**
|
||||
* 切换字体
|
||||
* 设置指定页的对齐方式
|
||||
* @param {number} pageNum 页码(1-based)
|
||||
* @param {string} align 'top'|'center'
|
||||
*/
|
||||
function switchFont(name) {
|
||||
config.font = name;
|
||||
if ($container) {
|
||||
$container.removeClass('font-source-han-sans font-alibaba-puhuiti font-lxgw-wenkai').addClass('font-' + name);
|
||||
$container.css('font-family', config.fonts[name] || config.fonts['source-han-sans']);
|
||||
function setPageAlignment(pageNum, align) {
|
||||
if (!config.pageAlignments) {
|
||||
config.pageAlignments = {};
|
||||
}
|
||||
config.pageAlignments[pageNum] = align;
|
||||
}
|
||||
|
||||
// ===== 工具方法 =====
|
||||
@@ -802,76 +749,16 @@ var PhoneImageEngine = (function () {
|
||||
return pages.slice();
|
||||
}
|
||||
|
||||
// ===== AI 智能排版 =====
|
||||
|
||||
/**
|
||||
* 应用AI推荐配置
|
||||
*/
|
||||
function applyAiRecommendation(recommendation) {
|
||||
if (recommendation.template) {
|
||||
switchTemplate(recommendation.template);
|
||||
$('.template-btn').removeClass('active');
|
||||
$('.template-btn[data-template="' + recommendation.template + '"]').addClass('active');
|
||||
$('[name="size"]').val(config.size);
|
||||
}
|
||||
if (recommendation.font) {
|
||||
switchFont(recommendation.font);
|
||||
$('[name="font"]').val(recommendation.font);
|
||||
}
|
||||
if (recommendation.font_size) {
|
||||
config.fontSize = parseInt(recommendation.font_size);
|
||||
$('[name="fontSize"]').val(config.fontSize);
|
||||
$('#fontSizeValue').text(config.fontSize + 'px');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用AI优化内容(替换预览用的内容)
|
||||
*/
|
||||
var originalContentHtml = '';
|
||||
function applyAiContent(optimizedContent) {
|
||||
if (!originalContentHtml) {
|
||||
originalContentHtml = postData.content_html;
|
||||
}
|
||||
if (optimizedContent.optimized_paragraphs) {
|
||||
var newHtml = '';
|
||||
for (var i = 0; i < optimizedContent.optimized_paragraphs.length; i++) {
|
||||
newHtml += '<p>' + optimizedContent.optimized_paragraphs[i] + '</p>';
|
||||
}
|
||||
postData.content_html = newHtml;
|
||||
postData.title = optimizedContent.optimized_title || postData.title;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复原始内容
|
||||
*/
|
||||
function restoreOriginalContent() {
|
||||
if (originalContentHtml) {
|
||||
postData.content_html = originalContentHtml;
|
||||
originalContentHtml = '';
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 公开API =====
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
paginate: render,
|
||||
generateImages: generateImages,
|
||||
saveImages: saveImages,
|
||||
showGeneratedThumbnails: showGeneratedThumbnails,
|
||||
switchTemplate: switchTemplate,
|
||||
switchSize: switchSize,
|
||||
switchFont: switchFont,
|
||||
getConfig: getConfig,
|
||||
getPages: getPages,
|
||||
applyAiRecommendation: applyAiRecommendation,
|
||||
applyAiContent: applyAiContent,
|
||||
restoreOriginalContent: restoreOriginalContent,
|
||||
nextPage: nextPage,
|
||||
prevPage: prevPage,
|
||||
showPreviewPage: showPreviewPage,
|
||||
getCurrentPageIndex: getCurrentPageIndex
|
||||
setPageAlignment: setPageAlignment
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -66,6 +66,15 @@
|
||||
</div>
|
||||
</div>
|
||||
{/notin}
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-form-label">
|
||||
封面文案
|
||||
<p class="layui-word-aux">用于手机图片排版封面展示</p>
|
||||
</div>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="cover_text" class="layui-textarea" placeholder="用于手机图片排版封面展示(可选)">{$post->getData('cover_text')}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-form-label">描述</div>
|
||||
<div class="layui-input-block">
|
||||
|
||||
@@ -200,6 +200,7 @@ X-API-Key: {api_key}</div>
|
||||
"type": "1",
|
||||
"status": 1,
|
||||
"source": "api",
|
||||
"cover_text": "",
|
||||
"create_time": 1700000000,
|
||||
"update_time": 1700000000,
|
||||
"categorys": [...],
|
||||
@@ -241,6 +242,7 @@ X-API-Key: {api_key}</div>
|
||||
"content_html": "<p>HTML内容</p>",
|
||||
"content_type": "html",
|
||||
"desc": "摘要",
|
||||
"cover_text": "封面文案内容示例",
|
||||
"poster": "/uploads/poster.jpg",
|
||||
"type": "1",
|
||||
"status": 1,
|
||||
@@ -267,6 +269,7 @@ X-API-Key: {api_key}</div>
|
||||
<tr><td>content</td><td>string</td><td>否</td><td>文章内容(Markdown)</td></tr>
|
||||
<tr><td>content_html</td><td>string</td><td>否</td><td>文章内容(HTML)</td></tr>
|
||||
<tr><td>desc</td><td>string</td><td>否</td><td>文章摘要</td></tr>
|
||||
<tr><td>cover_text</td><td>string</td><td>否</td><td>封面文案,用于手机图片排版封面展示</td></tr>
|
||||
<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>
|
||||
@@ -338,6 +341,7 @@ X-API-Key: {api_key}</div>
|
||||
<tr><td>content</td><td>string</td><td>否</td><td>文章内容(Markdown)</td></tr>
|
||||
<tr><td>content_html</td><td>string</td><td>否</td><td>文章内容(HTML)</td></tr>
|
||||
<tr><td>desc</td><td>string</td><td>否</td><td>文章摘要</td></tr>
|
||||
<tr><td>cover_text</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"<br/>当为 "markdown" 时,系统会自动将 content 转换为 HTML 存储到 content_html 字段</td></tr>
|
||||
|
||||
Reference in New Issue
Block a user