feat(post): 新增手机图片排版与AI智能排版功能

- 新增手机图片排版功能,支持小红书/抖音尺寸输出
- 新增AI智能排版顾问,支持内容分析与优化推荐
- 新增AI供应商管理,支持多渠道配置与同步
- 新增文章输出管理页面,支持图片预览与批量下载
- 新增字体文件与排版样式配置
This commit is contained in:
augushong
2026-05-01 12:23:17 +08:00
parent b4558b55fb
commit 83a2bd48a2
25 changed files with 4440 additions and 0 deletions

View File

@@ -348,4 +348,208 @@ class Post extends Common
return download($mardkown, $model_post->title . '.md', true);
}
/**
* 手机图片排版操作页
*/
public function phoneImage($id)
{
$model_post = ModelPost::find($id);
if (empty($model_post)) {
$this->error('文章不存在');
}
View::assign('post', $model_post);
return View::fetch();
}
/**
* 输出管理列表页
*/
public function postOutputList($id)
{
$model_post = ModelPost::find($id);
if (empty($model_post)) {
$this->error('文章不存在');
}
$output_list = \app\model\PostOutput::where('post_id', $id)
->order('id', 'desc')
->paginate(10);
View::assign('post', $model_post);
View::assign('list', $output_list);
return View::fetch('post_output/index');
}
/**
* 保存输出记录
*/
public function savePostOutput()
{
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['post_id'])) {
return json(['code' => 500, 'msg' => '缺少文章ID']);
}
$post = ModelPost::find($data['post_id']);
if (empty($post)) {
return json(['code' => 500, 'msg' => '文章不存在']);
}
$config = $data['config'] ?? [];
$pages = $data['pages'] ?? [];
$admin_id = session('admin_id') ?? 0;
$phoneImage = new \app\common\tools\PhoneImage();
$output = $phoneImage->createOutput((int) $data['post_id'], $config, (int) $admin_id);
foreach ($pages as $index => $pageData) {
$phoneImage->savePageImage($output->id, $index + 1, $pageData);
}
$phoneImage->completeOutput($output->id, count($pages));
return json(['code' => 0, 'msg' => '保存成功', 'data' => ['output_id' => $output->id]]);
}
/**
* 删除输出记录
*/
public function deletePostOutput()
{
$id = $this->request->param('id', 0);
if (empty($id)) {
return json(['code' => 500, 'msg' => '缺少ID']);
}
$phoneImage = new \app\common\tools\PhoneImage();
$phoneImage->deleteOutput((int) $id);
return json(['code' => 0, 'msg' => '删除成功']);
}
/**
* 重新生成(用相同配置)
*/
public function regeneratePostOutput()
{
$id = $this->request->param('id', 0);
if (empty($id)) {
return json(['code' => 500, 'msg' => '缺少ID']);
}
$output = \app\model\PostOutput::find($id);
if (empty($output)) {
return json(['code' => 500, 'msg' => '输出记录不存在']);
}
$phoneImage = new \app\common\tools\PhoneImage();
$phoneImage->deleteOutput((int) $id);
return json(['code' => 0, 'msg' => '请重新排版', 'data' => ['config' => $output->config]]);
}
/**
* 下载ZIP
*/
public function downloadPostOutputZip($id)
{
$phoneImage = new \app\common\tools\PhoneImage();
try {
$zipPath = $phoneImage->createZip((int) $id);
$output = \app\model\PostOutput::find($id);
if (empty($output)) {
throw new \Exception('输出记录不存在');
}
$post = ModelPost::find($output->post_id);
$fileName = ($post ? $post->title : 'output') . '_phone_image_' . date('Ymd') . '.zip';
// 请求结束后清理临时ZIP文件
$tempFile = $zipPath;
register_shutdown_function(function () use ($tempFile) {
if (file_exists($tempFile)) {
@unlink($tempFile);
}
});
return download($zipPath, $fileName);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
}
/**
* 获取输出文件列表(AJAX)
*/
public function getOutputFiles()
{
$outputId = $this->request->param('output_id', 0);
if (empty($outputId)) {
return json(['code' => 500, 'msg' => '缺少输出ID']);
}
$output = \app\model\PostOutput::find((int) $outputId);
if (empty($output)) {
return json(['code' => 500, 'msg' => '输出记录不存在']);
}
$files = \app\model\PostOutputFile::getByOutput((int) $outputId);
$result = [];
foreach ($files as $file) {
$result[] = [
'id' => $file->id,
'page' => $file->page,
'file_url' => $file->file_url,
'file_size' => $file->file_size,
'width' => $file->width,
'height' => $file->height,
];
}
return json(['code' => 0, 'data' => $result]);
}
/**
* AI智能排版推荐.
*/
public function aiRecommend()
{
$postId = $this->request->post('post_id', 0);
$post = ModelPost::find($postId);
if (empty($post)) {
return json(['code' => 500, 'msg' => '文章不存在']);
}
$advisor = new \app\common\tools\AiLayoutAdvisor();
$result = $advisor->analyzeAndRecommend($post);
if ($result['success']) {
return json(['code' => 0, 'data' => $result['data']]);
}
return json(['code' => 500, 'msg' => $result['msg']]);
}
/**
* AI内容优化.
*/
public function aiOptimizeContent()
{
$postId = $this->request->post('post_id', 0);
$post = ModelPost::find($postId);
if (empty($post)) {
return json(['code' => 500, 'msg' => '文章不存在']);
}
$advisor = new \app\common\tools\AiLayoutAdvisor();
$result = $advisor->optimizeContent($post);
if ($result['success']) {
return json(['code' => 0, 'data' => $result['data']]);
}
return json(['code' => 500, 'msg' => $result['msg']]);
}
}