mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 14:42:48 +08:00
- 新增手机图片排版功能,支持小红书/抖音尺寸输出 - 新增AI智能排版顾问,支持内容分析与优化推荐 - 新增AI供应商管理,支持多渠道配置与同步 - 新增文章输出管理页面,支持图片预览与批量下载 - 新增字体文件与排版样式配置
216 lines
6.5 KiB
PHP
216 lines
6.5 KiB
PHP
<?php
|
||
|
||
namespace app\common\tools;
|
||
|
||
use app\model\Post;
|
||
use app\model\PostOutput;
|
||
use app\model\PostOutputFile;
|
||
use think\facade\App;
|
||
|
||
class PhoneImage implements PostOutputManagerInterface
|
||
{
|
||
/**
|
||
* 返回配置字段定义
|
||
*/
|
||
public function getConfigFields(): array
|
||
{
|
||
return [
|
||
'template' => ['type' => 'select', 'options' => ['minimal', 'magazine', 'mixed'], 'default' => 'minimal'],
|
||
'size' => ['type' => 'select', 'options' => ['xiaohongshu', 'douyin'], 'default' => 'xiaohongshu'],
|
||
'font' => ['type' => 'select', 'options' => ['source-han-sans', 'alibaba-puhuiti', 'lxgw-wenkai'], 'default' => 'source-han-sans'],
|
||
'font_size' => ['type' => 'number', 'default' => 14, 'min' => 10, 'max' => 24],
|
||
'watermark' => ['type' => 'text', 'default' => ''],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 验证配置合法性
|
||
*/
|
||
public function validateConfig(array $config): bool
|
||
{
|
||
$fields = $this->getConfigFields();
|
||
|
||
if (isset($config['template']) && !in_array($config['template'], $fields['template']['options'])) {
|
||
return false;
|
||
}
|
||
if (isset($config['size']) && !in_array($config['size'], $fields['size']['options'])) {
|
||
return false;
|
||
}
|
||
if (isset($config['font']) && !in_array($config['font'], $fields['font']['options'])) {
|
||
return false;
|
||
}
|
||
if (isset($config['font_size'])) {
|
||
$size = intval($config['font_size']);
|
||
if ($size < $fields['font_size']['min'] || $size > $fields['font_size']['max']) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 执行输出处理 - 服务端接收base64数据,保存文件,创建记录
|
||
* 注意:HTML渲染在前端完成(html2canvas),服务端只做文件保存和记录创建
|
||
*/
|
||
public function process(Post $post, array $config): array
|
||
{
|
||
return [];
|
||
}
|
||
|
||
/**
|
||
* 返回预览HTML - 预览在前端完成,服务端返回空
|
||
*/
|
||
public function getPreview(Post $post, array $config): string
|
||
{
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* 保存单页图片
|
||
* @param int $outputId 输出记录ID
|
||
* @param int $page 页码(从1开始)
|
||
* @param string $imageData base64编码的图片数据
|
||
* @return PostOutputFile|false
|
||
*/
|
||
public function savePageImage(int $outputId, int $page, string $imageData)
|
||
{
|
||
$imageData = str_replace('data:image/jpeg;base64,', '', $imageData);
|
||
$imageData = str_replace('data:image/png;base64,', '', $imageData);
|
||
$imageData = str_replace(' ', '+', $imageData);
|
||
$decoded = base64_decode($imageData);
|
||
|
||
if ($decoded === false) {
|
||
return false;
|
||
}
|
||
|
||
$dateDir = date('Ymd');
|
||
$relativeDir = '/upload/post_output/' . $dateDir;
|
||
$fileName = $outputId . '_' . $page . '.jpg';
|
||
$relativePath = $relativeDir . '/' . $fileName;
|
||
$fullDir = App::getRootPath() . '/public' . $relativeDir;
|
||
$fullPath = $fullDir . '/' . $fileName;
|
||
|
||
if (!is_dir($fullDir)) {
|
||
mkdir($fullDir, 0777, true);
|
||
}
|
||
|
||
file_put_contents($fullPath, $decoded);
|
||
|
||
$imageInfo = getimagesize($fullPath);
|
||
$width = $imageInfo[0] ?? 0;
|
||
$height = $imageInfo[1] ?? 0;
|
||
|
||
$fileRecord = PostOutputFile::create([
|
||
'output_id' => $outputId,
|
||
'page' => $page,
|
||
'file_path' => $relativePath,
|
||
'file_url' => $relativePath,
|
||
'file_size' => strlen($decoded),
|
||
'width' => $width,
|
||
'height' => $height,
|
||
]);
|
||
|
||
return $fileRecord;
|
||
}
|
||
|
||
/**
|
||
* 打包某条输出记录的所有图片为ZIP
|
||
* @param int $outputId
|
||
* @return string ZIP文件路径
|
||
* @throws \Exception
|
||
*/
|
||
public function createZip(int $outputId): string
|
||
{
|
||
$output = PostOutput::find($outputId);
|
||
if (!$output) {
|
||
throw new \Exception('输出记录不存在');
|
||
}
|
||
|
||
$files = PostOutputFile::where('output_id', $outputId)
|
||
->order('page', 'asc')
|
||
->select();
|
||
|
||
if ($files->isEmpty()) {
|
||
throw new \Exception('没有可下载的文件');
|
||
}
|
||
|
||
$tempDir = App::getRuntimePath() . 'temp';
|
||
if (!is_dir($tempDir)) {
|
||
mkdir($tempDir, 0777, true);
|
||
}
|
||
|
||
$zipFileName = 'post_output_' . $outputId . '.zip';
|
||
$zipPath = $tempDir . '/' . $zipFileName;
|
||
|
||
$zip = new \ZipArchive();
|
||
if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) {
|
||
throw new \Exception('无法创建ZIP文件');
|
||
}
|
||
|
||
foreach ($files as $file) {
|
||
$filePath = App::getRootPath() . '/public' . $file->file_path;
|
||
if (file_exists($filePath)) {
|
||
$pageName = str_pad((string) $file->page, 2, '0', STR_PAD_LEFT) . '.jpg';
|
||
$zip->addFile($filePath, $pageName);
|
||
}
|
||
}
|
||
|
||
$zip->close();
|
||
|
||
return $zipPath;
|
||
}
|
||
|
||
/**
|
||
* 删除输出记录及所有关联文件
|
||
* @param int $outputId
|
||
* @return bool
|
||
*/
|
||
public function deleteOutput(int $outputId): bool
|
||
{
|
||
$files = PostOutputFile::where('output_id', $outputId)->select();
|
||
|
||
foreach ($files as $file) {
|
||
$filePath = App::getRootPath() . '/public' . $file->file_path;
|
||
if (file_exists($filePath)) {
|
||
@unlink($filePath);
|
||
}
|
||
}
|
||
|
||
PostOutputFile::where('output_id', $outputId)->delete();
|
||
PostOutput::destroy($outputId);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 创建输出记录
|
||
* @param int $postId 文章ID
|
||
* @param array $config 配置
|
||
* @param int $adminId 管理员ID
|
||
* @return PostOutput
|
||
*/
|
||
public function createOutput(int $postId, array $config, int $adminId): PostOutput
|
||
{
|
||
return PostOutput::create([
|
||
'post_id' => $postId,
|
||
'output_type' => 'phone_image',
|
||
'config' => $config,
|
||
'status' => PostOutput::STATUS_PROCESSING,
|
||
'page_count' => 0,
|
||
'admin_id' => $adminId,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 完成输出记录 - 更新状态和页数
|
||
*/
|
||
public function completeOutput(int $outputId, int $pageCount): bool
|
||
{
|
||
return PostOutput::where('id', $outputId)->update([
|
||
'status' => PostOutput::STATUS_COMPLETED,
|
||
'page_count' => $pageCount,
|
||
]) > 0;
|
||
}
|
||
}
|