|
|
@@ -0,0 +1,618 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace app\api\controller;
|
|
|
+use app\common\controller\Api;
|
|
|
+use app\service\AIGatewayService;
|
|
|
+use think\Db;
|
|
|
+use think\Exception;
|
|
|
+
|
|
|
+class Material extends Api
|
|
|
+{
|
|
|
+ protected $noNeedLogin = ['*'];
|
|
|
+ protected $noNeedRight = ['*'];
|
|
|
+ public function index()
|
|
|
+ {
|
|
|
+ $this->success('Material');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取素材库列表接口
|
|
|
+ */
|
|
|
+ public function Material_List(){
|
|
|
+ $params = $this->request->param();
|
|
|
+ $search = input('search', '');
|
|
|
+ $where = [];
|
|
|
+ if (!empty($search)) {
|
|
|
+ $where['type'] = ['like', '%' . $search . '%'];
|
|
|
+ }
|
|
|
+ $res = Db::name('template_material')->where($where)->order('id desc')->select();
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '',
|
|
|
+ 'data' => $res,
|
|
|
+ 'count' => count($res)
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 模板关联素材查询
|
|
|
+ */
|
|
|
+ public function Template_Material_Relation(){
|
|
|
+ $params = $this->request->param();
|
|
|
+ $res = Db::name('template_material_relation')->alias('a')
|
|
|
+ ->field('a.*, b.material_url,c.canvasWidth,c.canvasHeight,c.size')
|
|
|
+ ->join('template_material b', 'a.material_id = b.id', 'left')
|
|
|
+ ->join('product_template c', 'a.template_id = c.id', 'left')
|
|
|
+ ->where('a.template_id',$params['id'])->select();
|
|
|
+
|
|
|
+ // 处理null值,转换为空字符串
|
|
|
+ if($res){
|
|
|
+ foreach($res as &$item){
|
|
|
+ foreach($item as $key => &$value){
|
|
|
+ if($value === null){
|
|
|
+ $value = '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '',
|
|
|
+ 'data' => $res,
|
|
|
+ 'count' => count($res)
|
|
|
+ ]);
|
|
|
+ }else{
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '此模版暂无作品',
|
|
|
+ 'data' => '',
|
|
|
+ 'count' => 0
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 新增模版(生成模版)
|
|
|
+ */
|
|
|
+ public function Template_Material_Add(){
|
|
|
+ $params = $this->request->param();
|
|
|
+// echo "<pre>";
|
|
|
+// print_r($params);
|
|
|
+// echo "<pre>";die;
|
|
|
+ // 处理 uploaded_materials:保存素材图片到 uploads/material/ 并写入 template_material 表
|
|
|
+ $layerIdToMaterial = []; // layer_id => ['id'=>material_id, 'url'=>material_url]
|
|
|
+ if (!empty($params['uploaded_materials'])) {
|
|
|
+ $materialSavePath = str_replace('\\', '/', ROOT_PATH . 'public/uploads/material/' . date('Y-m-d') . '/');
|
|
|
+ if (!is_dir($materialSavePath)) {
|
|
|
+ mkdir($materialSavePath, 0755, true);
|
|
|
+ }
|
|
|
+ foreach ($params['uploaded_materials'] as $item) {
|
|
|
+ $base64Data = $item['data'] ?? '';
|
|
|
+ if (empty($base64Data) || !preg_match('/data:image\/(png|jpg|jpeg);base64,([A-Za-z0-9+\/=]+)/i', $base64Data, $m)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $imageType = strtolower($m[1]);
|
|
|
+ $imageData = base64_decode($m[2]);
|
|
|
+ if ($imageData === false || strlen($imageData) < 100) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $ext = ($imageType === 'jpeg') ? 'jpg' : $imageType;
|
|
|
+ $fileName = uniqid() . '_' . date('YmdHis') . '.' . $ext;
|
|
|
+ $fullPath = $materialSavePath . $fileName;
|
|
|
+ if (!file_put_contents($fullPath, $imageData)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $materialUrl = 'uploads/material/' . date('Y-m-d') . '/' . $fileName;
|
|
|
+ $materialRecord = [
|
|
|
+ 'sys_id' => $params['sys_id'] ?? '',
|
|
|
+ 'material_url' => $materialUrl,
|
|
|
+ 'type' => $item['type'] ?? '',
|
|
|
+ 'create_time' => date('Y-m-d H:i:s'),
|
|
|
+ 'count' => 1
|
|
|
+ ];
|
|
|
+ $materialId = Db::name('template_material')->insertGetId($materialRecord);
|
|
|
+ if ($materialId && isset($item['layer_id'])) {
|
|
|
+ $layerIdToMaterial[$item['layer_id']] = ['id' => $materialId, 'url' => $materialUrl];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $save_path = ROOT_PATH . 'public' . '/' . 'uploads' . '/' . 'template' .'/'. date('Y-m-d') . '/';
|
|
|
+ // 移除ROOT_PATH中可能存在的反斜杠,确保统一使用正斜杠
|
|
|
+ $save_path = str_replace('\\', '/', $save_path);
|
|
|
+ // 自动创建文件夹(如果不存在)
|
|
|
+ if (!is_dir($save_path)) {
|
|
|
+ mkdir($save_path, 0755, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取base64图片数据
|
|
|
+ $previewImage = $params['previewImage'];
|
|
|
+ // 匹配base64图片数据
|
|
|
+ preg_match('/data:image\/(png|jpg|jpeg);base64,([^"]+)/', $previewImage, $matches);
|
|
|
+ if (empty($matches)) {
|
|
|
+ return '未找到图片数据';
|
|
|
+ }
|
|
|
+ $image_type = $matches[1];
|
|
|
+ $base64_data = $matches[2];
|
|
|
+ // 解码base64数据
|
|
|
+ $image_data = base64_decode($base64_data);
|
|
|
+ if ($image_data === false) {
|
|
|
+ return '图片解码失败';
|
|
|
+ }
|
|
|
+ // 生成唯一文件名(包含正确的扩展名)
|
|
|
+ $file_name = uniqid() . '_' . date('YmdHis') . '.' . $image_type;
|
|
|
+ $full_file_path = $save_path . $file_name;
|
|
|
+
|
|
|
+// 保存图片到文件系统
|
|
|
+ if (!file_put_contents($full_file_path, $image_data)) {
|
|
|
+ return '图片保存失败';
|
|
|
+ }
|
|
|
+ // 生成数据库存储路径(使用正斜杠格式)
|
|
|
+ $db_img_path = '/uploads/template/'. date('Y-m-d') .'/' . $file_name;
|
|
|
+
|
|
|
+ // 生成缩略图
|
|
|
+ $thumbnail_path = $this->generateThumbnail($full_file_path, $save_path, $file_name);
|
|
|
+ $db_thumbnail_path = '/uploads/template/'.date('Y-m-d') .'/' . $thumbnail_path;
|
|
|
+
|
|
|
+ //新增到模版表(product_template)
|
|
|
+ $record['toexamine'] = '审核通过';
|
|
|
+
|
|
|
+ $record['sys_id'] = $params['sys_id'];
|
|
|
+ $record['canvasWidth'] = $params['canvasWidth'];
|
|
|
+ $record['canvasHeight'] = $params['canvasHeight'];
|
|
|
+ $record['size'] = $params['canvasRatio'];
|
|
|
+ $record['template_image_url'] = $db_img_path;//原图
|
|
|
+ $record['thumbnail_image'] = $db_thumbnail_path;//缩略图
|
|
|
+
|
|
|
+ $record['sys_rq'] = date('Y-m-d');
|
|
|
+ $record['create_time'] = date('Y-m-d H:i:s');
|
|
|
+
|
|
|
+ // 插入模板记录并获取ID
|
|
|
+ $templateId = Db::name('product_template')->insertGetId($record);
|
|
|
+
|
|
|
+ if (!$templateId) {
|
|
|
+ // 如果数据库插入失败,删除已保存的图片
|
|
|
+ if (file_exists($full_file_path)) {
|
|
|
+ unlink($full_file_path);
|
|
|
+ }
|
|
|
+ return '数据库插入失败';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理layers数据,插入到模版-素材表(template_material_relation)
|
|
|
+ if (!empty($params['layers'])) {
|
|
|
+ $layers = $params['layers'];
|
|
|
+ foreach ($layers as $layer) {
|
|
|
+ $materialId = $layer['material_id'] ?? null;
|
|
|
+ $materialUrl = isset($layer['url']) ? $layer['url'] : '';
|
|
|
+ if (isset($layer['id']) && isset($layerIdToMaterial[$layer['id']])) {
|
|
|
+ $materialId = $layerIdToMaterial[$layer['id']]['id'];
|
|
|
+ $materialUrl = $layerIdToMaterial[$layer['id']]['url'];
|
|
|
+ }
|
|
|
+ $relationData = [
|
|
|
+ 'template_id' => $templateId,//模版ID
|
|
|
+ 'sys_id' => $params['sys_id'],//用户名
|
|
|
+ 'material_id' => $materialId,//素材ID
|
|
|
+ 'z_index' => $layer['id'],//层级
|
|
|
+ 'layer_name' => $layer['name'],//图层名称
|
|
|
+ 'layer_type' => $layer['type'],//类型
|
|
|
+ 'material_url' => $materialUrl,//素材图片
|
|
|
+ 'position_x' => $layer['x'],
|
|
|
+ 'position_y' => $layer['y'],
|
|
|
+ 'width' => $layer['width'],
|
|
|
+ 'height' => $layer['height'],
|
|
|
+ 'rotation' => $layer['rotation'],//素材旋转角度
|
|
|
+ 'opacity' => $layer['opacity'],//素材透明度
|
|
|
+ 'visible' => $layer['visible'],//图层是否显示
|
|
|
+ 'locked' => isset($layer['locked']) && $layer['locked'] ? 1 : 0,//图层是否锁住
|
|
|
+ //文字部分参数
|
|
|
+ 'text_content' => isset($layer['text']) ? $layer['text'] : '',//文字内容
|
|
|
+ 'font_family' => isset($layer['fontFamily']) ? $layer['fontFamily'] : '',//字体(如 Arial)
|
|
|
+ 'font_size' => isset($layer['fontSize']) ? $layer['fontSize'] : '',//字号大小
|
|
|
+ 'font_color' => isset($layer['color']) ? $layer['color'] : '',//文字颜色
|
|
|
+ 'background_border_radius' => isset($layer['background_border_radius']) ? $layer['background_border_radius'] : '',//背景圆角
|
|
|
+ 'background_color' => isset($layer['backgroundColor']) ? $layer['backgroundColor'] : '',//文字背景颜色
|
|
|
+ 'text_align' => isset($layer['textAlign']) ? $layer['textAlign'] : '',//对齐方式
|
|
|
+ 'font_weight' => isset($layer['fontWeight']) ? $layer['fontWeight'] : '',//加粗
|
|
|
+ 'font_style' => isset($layer['fontStyle']) ? $layer['fontStyle'] : '',//斜体
|
|
|
+ 'font_underline' => isset($layer['textDecoration']) ? $layer['textDecoration'] : '',//下划线
|
|
|
+ 'line_height' => isset($layer['lineHeight']) ? $layer['lineHeight'] : '',//行高
|
|
|
+ 'letter_spacing' => isset($layer['letterSpacing']) ? $layer['letterSpacing'] : '',//字距
|
|
|
+ //形状与线条
|
|
|
+ 'shape_type' => $layer['shape_type'] ?? $layer['shapeType'] ?? '',//形状类型 rect/circle/ellipse/line
|
|
|
+ 'fill_mode' => $layer['fill_mode'] ?? $layer['fillMode'] ?? '',//填充模式 solid/none
|
|
|
+ 'fill_color' => $layer['fill_color'] ?? $layer['fillColor'] ?? '',//填充色
|
|
|
+ 'stroke_color' => $layer['stroke_color'] ?? $layer['strokeColor'] ?? '',//描边色
|
|
|
+ 'stroke_width' => isset($layer['stroke_width']) ? floatval($layer['stroke_width']) : (isset($layer['strokeWidth']) ? floatval($layer['strokeWidth']) : 0),//描边宽度
|
|
|
+ 'create_time' => date('Y-m-d H:i:s')
|
|
|
+
|
|
|
+
|
|
|
+ ];
|
|
|
+ // 插入关联记录
|
|
|
+ Db::name('template_material_relation')->insert($relationData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '',
|
|
|
+ 'data' => '',
|
|
|
+ 'template_id' => $templateId,
|
|
|
+ 'template_image_url' => $db_img_path,
|
|
|
+ 'template_image' => $db_thumbnail_path
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 修改模版
|
|
|
+ */
|
|
|
+ public function Template_Material_Update(){
|
|
|
+ $params = $this->request->param();
|
|
|
+// echo "<pre>";
|
|
|
+// print_r($params);
|
|
|
+// echo "<pre>";die;
|
|
|
+ // 验证模板ID
|
|
|
+ if (empty($params['template_id'])) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '模板ID不能为空',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $templateId = $params['template_id'];
|
|
|
+
|
|
|
+ // 检查模板是否存在
|
|
|
+ $template = Db::name('product_template')->where('id', $templateId)->find();
|
|
|
+ if (!$template) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '模板不存在',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理 uploaded_materials:修改时会有新的素材图上传,保存到 uploads/material/ 并写入 template_material 表(参考新增模版)
|
|
|
+ $layerIdToMaterial = [];
|
|
|
+ if (!empty($params['uploaded_materials'])) {
|
|
|
+ $materialSavePath = str_replace('\\', '/', ROOT_PATH . 'public/uploads/material/' . date('Y-m-d') . '/');
|
|
|
+ if (!is_dir($materialSavePath)) {
|
|
|
+ mkdir($materialSavePath, 0755, true);
|
|
|
+ }
|
|
|
+ foreach ($params['uploaded_materials'] as $item) {
|
|
|
+ $base64Data = $item['data'] ?? '';
|
|
|
+ if (empty($base64Data) || !preg_match('/data:image\/(png|jpg|jpeg);base64,([A-Za-z0-9+\/=]+)/i', $base64Data, $m)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $imageType = strtolower($m[1]);
|
|
|
+ $imageData = base64_decode($m[2]);
|
|
|
+ if ($imageData === false || strlen($imageData) < 100) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $ext = ($imageType === 'jpeg') ? 'jpg' : $imageType;
|
|
|
+ $fileName = uniqid() . '_' . date('YmdHis') . '.' . $ext;
|
|
|
+ $fullPath = $materialSavePath . $fileName;
|
|
|
+ if (!file_put_contents($fullPath, $imageData)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $materialUrl = 'uploads/material/' . date('Y-m-d') . '/' . $fileName;
|
|
|
+ $materialRecord = [
|
|
|
+ 'sys_id' => $params['sys_id'] ?? '',
|
|
|
+ 'material_url' => $materialUrl,
|
|
|
+ 'type' => $item['type'] ?? '',
|
|
|
+ 'create_time' => date('Y-m-d H:i:s'),
|
|
|
+ 'count' => 1
|
|
|
+ ];
|
|
|
+ $materialId = Db::name('template_material')->insertGetId($materialRecord);
|
|
|
+ if ($materialId && isset($item['layer_id'])) {
|
|
|
+ $layerIdToMaterial[$item['layer_id']] = ['id' => $materialId, 'url' => $materialUrl];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理图片更新
|
|
|
+ $db_img_path = $template['template_image_url'];
|
|
|
+ $db_thumbnail_path = $template['thumbnail_image'];
|
|
|
+
|
|
|
+ if (!empty($params['previewImage'])) {
|
|
|
+ $save_path = ROOT_PATH . 'public' . '/' . 'uploads' . '/' . 'template' .'/'. date('Y-m-d') . '/';
|
|
|
+ // 移除ROOT_PATH中可能存在的反斜杠,确保统一使用正斜杠
|
|
|
+ $save_path = str_replace('\\', '/', $save_path);
|
|
|
+ // 自动创建文件夹(如果不存在)
|
|
|
+ if (!is_dir($save_path)) {
|
|
|
+ mkdir($save_path, 0755, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取base64图片数据
|
|
|
+ $previewImage = $params['previewImage'];
|
|
|
+ // 匹配base64图片数据
|
|
|
+ preg_match('/data:image\/(png|jpg|jpeg);base64,([^"]+)/', $previewImage, $matches);
|
|
|
+ if (empty($matches)) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '未找到图片数据',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ $image_type = $matches[1];
|
|
|
+ $base64_data = $matches[2];
|
|
|
+ // 解码base64数据
|
|
|
+ $image_data = base64_decode($base64_data);
|
|
|
+ if ($image_data === false) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '图片解码失败',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ // 生成唯一文件名(包含正确的扩展名)
|
|
|
+ $file_name = uniqid() . '_' . date('YmdHis') . '.' . $image_type;
|
|
|
+ $full_file_path = $save_path . $file_name;
|
|
|
+
|
|
|
+ // 保存图片到文件系统
|
|
|
+ if (!file_put_contents($full_file_path, $image_data)) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '图片保存失败',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ // 生成数据库存储路径(使用正斜杠格式)
|
|
|
+ $db_img_path = '/uploads/template/'. date('Y-m-d') .'/' . $file_name;
|
|
|
+
|
|
|
+ // 生成缩略图
|
|
|
+ $thumbnail_path = $this->generateThumbnail($full_file_path, $save_path, $file_name);
|
|
|
+ $db_thumbnail_path = '/uploads/template/'.date('Y-m-d') .'/' . $thumbnail_path;
|
|
|
+
|
|
|
+ // 删除旧图片
|
|
|
+ if (!empty($template['template_image_url'])) {
|
|
|
+ $oldImagePath = ROOT_PATH . 'public' . $template['template_image_url'];
|
|
|
+ if (file_exists($oldImagePath)) {
|
|
|
+ unlink($oldImagePath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!empty($template['thumbnail_image'])) {
|
|
|
+ $oldThumbnailPath = ROOT_PATH . 'public' . $template['thumbnail_image'];
|
|
|
+ if (file_exists($oldThumbnailPath)) {
|
|
|
+ unlink($oldThumbnailPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新模版表(product_template)
|
|
|
+ $record['canvasWidth'] = $params['canvasWidth'];
|
|
|
+ $record['canvasHeight'] = $params['canvasHeight'];
|
|
|
+ $record['size'] = $params['canvasRatio'];
|
|
|
+ if (!empty($db_img_path)) {
|
|
|
+ $record['template_image_url'] = $db_img_path;//原图
|
|
|
+ $record['thumbnail_image'] = $db_thumbnail_path;//缩略图
|
|
|
+ }
|
|
|
+
|
|
|
+ $record['sys_rq'] = date('Y-m-d');
|
|
|
+ $record['template_name'] = $params['template_name'];
|
|
|
+ $record['update_time'] = date('Y-m-d H:i:s');
|
|
|
+
|
|
|
+ // 更新模板记录
|
|
|
+ $res = Db::name('product_template')->where('id', $templateId)->update($record);
|
|
|
+
|
|
|
+ if (!$res) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '数据库更新失败',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理layers数据,更新模版-素材表(template_material_relation)
|
|
|
+ if (!empty($params['layers'])) {
|
|
|
+ // 删除旧的关联记录
|
|
|
+ Db::name('template_material_relation')->where('template_id', $templateId)->delete();
|
|
|
+
|
|
|
+ $layers = $params['layers'];
|
|
|
+ foreach ($layers as $layer) {
|
|
|
+ $materialId = $layer['material_id'] ?? null;
|
|
|
+ $materialUrl = isset($layer['url']) ? $layer['url'] : '';
|
|
|
+ if (isset($layer['id']) && isset($layerIdToMaterial[$layer['id']])) {
|
|
|
+ $materialId = $layerIdToMaterial[$layer['id']]['id'];
|
|
|
+ $materialUrl = $layerIdToMaterial[$layer['id']]['url'];
|
|
|
+ }
|
|
|
+ $relationData = [
|
|
|
+ 'template_id' => $templateId,//模版ID
|
|
|
+ 'sys_id' => $params['sys_id'] ?? '',//用户名
|
|
|
+ 'material_id' => $materialId,//素材ID
|
|
|
+ 'z_index' => $layer['id'],//层级
|
|
|
+ 'layer_name' => $layer['name'],//图层名称
|
|
|
+ 'layer_type' => $layer['type'],//类型
|
|
|
+ 'material_url' => $materialUrl,//素材图片
|
|
|
+ 'position_x' => $layer['x'],
|
|
|
+ 'position_y' => $layer['y'],
|
|
|
+ 'width' => $layer['width'],
|
|
|
+ 'height' => $layer['height'],
|
|
|
+ 'rotation' => $layer['rotation'],//素材旋转角度
|
|
|
+ 'opacity' => $layer['opacity'],//素材透明度
|
|
|
+ 'visible' => $layer['visible'],//图层是否显示
|
|
|
+ 'locked' => isset($layer['locked']) && $layer['locked'] ? 1 : 0,//图层是否锁住
|
|
|
+ //文字部分参数
|
|
|
+ 'text_content' => isset($layer['text']) ? $layer['text'] : '',//文字内容
|
|
|
+ 'font_family' => isset($layer['fontFamily']) ? $layer['fontFamily'] : '',//字体(如 Arial)
|
|
|
+ 'font_size' => isset($layer['fontSize']) ? $layer['fontSize'] : '',//字号大小
|
|
|
+ 'font_color' => isset($layer['color']) ? $layer['color'] : '',//文字颜色
|
|
|
+ 'background_color' => isset($layer['backgroundColor']) ? $layer['backgroundColor'] : '',//文字背景颜色
|
|
|
+ 'background_border_radius' => isset($layer['background_border_radius']) ? $layer['background_border_radius'] : '',//背景圆角
|
|
|
+ 'text_align' => isset($layer['textAlign']) ? $layer['textAlign'] : '',//对齐方式
|
|
|
+ 'font_weight' => isset($layer['fontWeight']) ? $layer['fontWeight'] : '',//加粗
|
|
|
+ 'font_style' => isset($layer['fontStyle']) ? $layer['fontStyle'] : '',//斜体
|
|
|
+ 'font_underline' => isset($layer['textDecoration']) ? $layer['textDecoration'] : '',//下划线
|
|
|
+ 'line_height' => isset($layer['lineHeight']) ? $layer['lineHeight'] : '',//行高
|
|
|
+ 'letter_spacing' => isset($layer['letterSpacing']) ? $layer['letterSpacing'] : '',//字距
|
|
|
+ //形状与线条
|
|
|
+ 'shape_type' => $layer['shape_type'] ?? $layer['shapeType'] ?? '',//形状类型 rect/circle/ellipse/line
|
|
|
+ 'fill_mode' => $layer['fill_mode'] ?? $layer['fillMode'] ?? '',//填充模式 solid/none
|
|
|
+ 'fill_color' => $layer['fill_color'] ?? $layer['fillColor'] ?? '',//填充色
|
|
|
+ 'stroke_color' => $layer['stroke_color'] ?? $layer['strokeColor'] ?? '',//描边色
|
|
|
+ 'stroke_width' => isset($layer['stroke_width']) ? floatval($layer['stroke_width']) : (isset($layer['strokeWidth']) ? floatval($layer['strokeWidth']) : 0),//描边宽度
|
|
|
+ 'create_time' => date('Y-m-d H:i:s')
|
|
|
+
|
|
|
+ ];
|
|
|
+ // 插入关联记录
|
|
|
+ Db::name('template_material_relation')->insert($relationData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '修改成功',
|
|
|
+ 'data' => '',
|
|
|
+ 'template_id' => $templateId,
|
|
|
+ 'template_image_url' => $db_img_path,
|
|
|
+ 'template_image' => $db_thumbnail_path
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成缩略图(高质量)
|
|
|
+ * @param string $originalPath 原图路径
|
|
|
+ * @param string $savePath 保存目录
|
|
|
+ * @param string $fileName 原文件名
|
|
|
+ * @return string 缩略图文件名
|
|
|
+ */
|
|
|
+ private function generateThumbnail($originalPath, $savePath, $fileName) {
|
|
|
+ // 获取图片信息
|
|
|
+ $imageInfo = getimagesize($originalPath);
|
|
|
+ if (!$imageInfo) {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
+ $width = $imageInfo[0];
|
|
|
+ $height = $imageInfo[1];
|
|
|
+
|
|
|
+ // 计算缩略图尺寸(保持比例,最大宽度400)
|
|
|
+ $maxWidth = 400;
|
|
|
+ $maxHeight = 400;
|
|
|
+
|
|
|
+ if ($width > $maxWidth || $height > $maxHeight) {
|
|
|
+ $ratio = min($maxWidth / $width, $maxHeight / $height);
|
|
|
+ $thumbWidth = round($width * $ratio);
|
|
|
+ $thumbHeight = round($height * $ratio);
|
|
|
+ } else {
|
|
|
+ $thumbWidth = $width;
|
|
|
+ $thumbHeight = $height;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建缩略图画布
|
|
|
+ $thumbnail = imagecreatetruecolor($thumbWidth, $thumbHeight);
|
|
|
+
|
|
|
+ // 根据图片类型创建图像资源
|
|
|
+ switch ($imageInfo[2]) {
|
|
|
+ case IMAGETYPE_JPEG:
|
|
|
+ $source = imagecreatefromjpeg($originalPath);
|
|
|
+ break;
|
|
|
+ case IMAGETYPE_PNG:
|
|
|
+ $source = imagecreatefrompng($originalPath);
|
|
|
+ // 处理PNG透明
|
|
|
+ imagealphablending($thumbnail, false);
|
|
|
+ imagesavealpha($thumbnail, true);
|
|
|
+ $transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127);
|
|
|
+ imagefilledrectangle($thumbnail, 0, 0, $thumbWidth, $thumbHeight, $transparent);
|
|
|
+ break;
|
|
|
+ case IMAGETYPE_GIF:
|
|
|
+ $source = imagecreatefromgif($originalPath);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$source) {
|
|
|
+ return '';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调整图片大小(使用高质量缩放)
|
|
|
+ imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
|
|
|
+
|
|
|
+ // 生成缩略图文件名
|
|
|
+ $pathInfo = pathinfo($fileName);
|
|
|
+ $thumbnailName = $pathInfo['filename'] . '_thumb.' . $pathInfo['extension'];
|
|
|
+ $thumbnailPath = $savePath . $thumbnailName;
|
|
|
+
|
|
|
+ // 保存缩略图(使用高质量设置)
|
|
|
+ switch ($imageInfo[2]) {
|
|
|
+ case IMAGETYPE_JPEG:
|
|
|
+ imagejpeg($thumbnail, $thumbnailPath, 95); // 95% 质量,接近原图
|
|
|
+ break;
|
|
|
+ case IMAGETYPE_PNG:
|
|
|
+ imagepng($thumbnail, $thumbnailPath, 3); // 压缩级别 3,保持较高质量
|
|
|
+ break;
|
|
|
+ case IMAGETYPE_GIF:
|
|
|
+ imagegif($thumbnail, $thumbnailPath);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 释放资源
|
|
|
+ imagedestroy($source);
|
|
|
+ imagedestroy($thumbnail);
|
|
|
+
|
|
|
+ return $thumbnailName;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发布模版(release=1)
|
|
|
+ */
|
|
|
+ public function Template_Material_Publish(){
|
|
|
+ $params = $this->request->param();
|
|
|
+
|
|
|
+ $record['release'] = 1;
|
|
|
+ $record['update_time'] = date('Y-m-d H:i:s');
|
|
|
+ $res = Db::name('product_template')->where('id', $params['template_id'])->update($record);
|
|
|
+ if (!$res) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '发布失败',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '发布成功'
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取消发布模版(release=0)
|
|
|
+ */
|
|
|
+ public function Template_Material_Unpublish(){
|
|
|
+ $params = $this->request->param();
|
|
|
+ $record['release'] = 0;
|
|
|
+ $record['update_time'] = date('Y-m-d H:i:s');
|
|
|
+ $res = Db::name('product_template')->where('id', $params['template_id'])->update($record);
|
|
|
+ if (!$res) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '发布失败',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '发布成功'
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除模版
|
|
|
+ */
|
|
|
+ public function Template_Material_Delete(){
|
|
|
+ $params = $this->request->param();
|
|
|
+ $record['mod_rq'] = date('Y-m-d H:i:s');
|
|
|
+ $res = Db::name('product_template')->where('id', $params['template_id'])->update($record);
|
|
|
+ if (!$res) {
|
|
|
+ return json([
|
|
|
+ 'code' => 1,
|
|
|
+ 'msg' => '模版删除失败',
|
|
|
+ 'data' => ''
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ return json([
|
|
|
+ 'code' => 0,
|
|
|
+ 'msg' => '模版删除成功'
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|