Material.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use app\service\AIGatewayService;
  5. use think\Db;
  6. use think\Exception;
  7. class Material extends Api
  8. {
  9. protected $noNeedLogin = ['*'];
  10. protected $noNeedRight = ['*'];
  11. public function index()
  12. {
  13. $this->success('Material');
  14. }
  15. /**
  16. * 获取素材库列表接口
  17. */
  18. public function Material_List(){
  19. $params = $this->request->param();
  20. $search = input('search', '');
  21. $where = [];
  22. if (!empty($search)) {
  23. $where['type'] = ['like', '%' . $search . '%'];
  24. }
  25. $res = Db::name('template_material')->where($where)->order('id desc')->select();
  26. return json([
  27. 'code' => 0,
  28. 'msg' => '',
  29. 'data' => $res,
  30. 'count' => count($res)
  31. ]);
  32. }
  33. /**
  34. * 模板关联素材查询
  35. */
  36. public function Template_Material_Relation(){
  37. $params = $this->request->param();
  38. $res = Db::name('template_material_relation')->alias('a')
  39. ->field('a.*, b.material_url,c.canvasWidth,c.canvasHeight,c.size')
  40. ->join('template_material b', 'a.material_id = b.id', 'left')
  41. ->join('product_template c', 'a.template_id = c.id', 'left')
  42. ->where('a.template_id',$params['id'])->select();
  43. // 处理null值,转换为空字符串
  44. if($res){
  45. foreach($res as &$item){
  46. foreach($item as $key => &$value){
  47. if($value === null){
  48. $value = '';
  49. }
  50. }
  51. }
  52. return json([
  53. 'code' => 0,
  54. 'msg' => '',
  55. 'data' => $res,
  56. 'count' => count($res)
  57. ]);
  58. }else{
  59. return json([
  60. 'code' => 1,
  61. 'msg' => '此模版暂无作品',
  62. 'data' => '',
  63. 'count' => 0
  64. ]);
  65. }
  66. }
  67. /**
  68. * 新增模版(生成模版)
  69. */
  70. public function Template_Material_Add(){
  71. $params = $this->request->param();
  72. // echo "<pre>";
  73. // print_r($params);
  74. // echo "<pre>";die;
  75. // 处理 uploaded_materials:保存素材图片到 uploads/material/ 并写入 template_material 表
  76. $layerIdToMaterial = []; // layer_id => ['id'=>material_id, 'url'=>material_url]
  77. if (!empty($params['uploaded_materials'])) {
  78. $materialSavePath = str_replace('\\', '/', ROOT_PATH . 'public/uploads/material/' . date('Y-m-d') . '/');
  79. if (!is_dir($materialSavePath)) {
  80. mkdir($materialSavePath, 0755, true);
  81. }
  82. foreach ($params['uploaded_materials'] as $item) {
  83. $base64Data = $item['data'] ?? '';
  84. if (empty($base64Data) || !preg_match('/data:image\/(png|jpg|jpeg);base64,([A-Za-z0-9+\/=]+)/i', $base64Data, $m)) {
  85. continue;
  86. }
  87. $imageType = strtolower($m[1]);
  88. $imageData = base64_decode($m[2]);
  89. if ($imageData === false || strlen($imageData) < 100) {
  90. continue;
  91. }
  92. $ext = ($imageType === 'jpeg') ? 'jpg' : $imageType;
  93. $fileName = uniqid() . '_' . date('YmdHis') . '.' . $ext;
  94. $fullPath = $materialSavePath . $fileName;
  95. if (!file_put_contents($fullPath, $imageData)) {
  96. continue;
  97. }
  98. $materialUrl = 'uploads/material/' . date('Y-m-d') . '/' . $fileName;
  99. $materialRecord = [
  100. 'sys_id' => $params['sys_id'] ?? '',
  101. 'material_url' => $materialUrl,
  102. 'type' => $item['type'] ?? '',
  103. 'create_time' => date('Y-m-d H:i:s'),
  104. 'count' => 1
  105. ];
  106. $materialId = Db::name('template_material')->insertGetId($materialRecord);
  107. if ($materialId && isset($item['layer_id'])) {
  108. $layerIdToMaterial[$item['layer_id']] = ['id' => $materialId, 'url' => $materialUrl];
  109. }
  110. }
  111. }
  112. $save_path = ROOT_PATH . 'public' . '/' . 'uploads' . '/' . 'template' .'/'. date('Y-m-d') . '/';
  113. // 移除ROOT_PATH中可能存在的反斜杠,确保统一使用正斜杠
  114. $save_path = str_replace('\\', '/', $save_path);
  115. // 自动创建文件夹(如果不存在)
  116. if (!is_dir($save_path)) {
  117. mkdir($save_path, 0755, true);
  118. }
  119. // 提取base64图片数据
  120. $previewImage = $params['previewImage'];
  121. // 匹配base64图片数据
  122. preg_match('/data:image\/(png|jpg|jpeg);base64,([^"]+)/', $previewImage, $matches);
  123. if (empty($matches)) {
  124. return '未找到图片数据';
  125. }
  126. $image_type = $matches[1];
  127. $base64_data = $matches[2];
  128. // 解码base64数据
  129. $image_data = base64_decode($base64_data);
  130. if ($image_data === false) {
  131. return '图片解码失败';
  132. }
  133. // 生成唯一文件名(包含正确的扩展名)
  134. $file_name = uniqid() . '_' . date('YmdHis') . '.' . $image_type;
  135. $full_file_path = $save_path . $file_name;
  136. // 保存图片到文件系统
  137. if (!file_put_contents($full_file_path, $image_data)) {
  138. return '图片保存失败';
  139. }
  140. // 生成数据库存储路径(使用正斜杠格式)
  141. $db_img_path = '/uploads/template/'. date('Y-m-d') .'/' . $file_name;
  142. // 生成缩略图
  143. $thumbnail_path = $this->generateThumbnail($full_file_path, $save_path, $file_name);
  144. $db_thumbnail_path = '/uploads/template/'.date('Y-m-d') .'/' . $thumbnail_path;
  145. //新增到模版表(product_template)
  146. $record['toexamine'] = '审核通过';
  147. $record['sys_id'] = $params['sys_id'];
  148. $record['canvasWidth'] = $params['canvasWidth'];
  149. $record['canvasHeight'] = $params['canvasHeight'];
  150. $record['size'] = $params['canvasRatio'];
  151. $record['template_image_url'] = $db_img_path;//原图
  152. $record['thumbnail_image'] = $db_thumbnail_path;//缩略图
  153. $record['sys_rq'] = date('Y-m-d');
  154. $record['create_time'] = date('Y-m-d H:i:s');
  155. // 插入模板记录并获取ID
  156. $templateId = Db::name('product_template')->insertGetId($record);
  157. if (!$templateId) {
  158. // 如果数据库插入失败,删除已保存的图片
  159. if (file_exists($full_file_path)) {
  160. unlink($full_file_path);
  161. }
  162. return '数据库插入失败';
  163. }
  164. // 处理layers数据,插入到模版-素材表(template_material_relation)
  165. if (!empty($params['layers'])) {
  166. $layers = $params['layers'];
  167. foreach ($layers as $layer) {
  168. $materialId = $layer['material_id'] ?? null;
  169. $materialUrl = isset($layer['url']) ? $layer['url'] : '';
  170. if (isset($layer['id']) && isset($layerIdToMaterial[$layer['id']])) {
  171. $materialId = $layerIdToMaterial[$layer['id']]['id'];
  172. $materialUrl = $layerIdToMaterial[$layer['id']]['url'];
  173. }
  174. $relationData = [
  175. 'template_id' => $templateId,//模版ID
  176. 'sys_id' => $params['sys_id'],//用户名
  177. 'material_id' => $materialId,//素材ID
  178. 'z_index' => $layer['id'],//层级
  179. 'layer_name' => $layer['name'],//图层名称
  180. 'layer_type' => $layer['type'],//类型
  181. 'material_url' => $materialUrl,//素材图片
  182. 'position_x' => $layer['x'],
  183. 'position_y' => $layer['y'],
  184. 'width' => $layer['width'],
  185. 'height' => $layer['height'],
  186. 'rotation' => $layer['rotation'],//素材旋转角度
  187. 'opacity' => $layer['opacity'],//素材透明度
  188. 'visible' => $layer['visible'],//图层是否显示
  189. 'locked' => isset($layer['locked']) && $layer['locked'] ? 1 : 0,//图层是否锁住
  190. //文字部分参数
  191. 'text_content' => isset($layer['text']) ? $layer['text'] : '',//文字内容
  192. 'font_family' => isset($layer['fontFamily']) ? $layer['fontFamily'] : '',//字体(如 Arial)
  193. 'font_size' => isset($layer['fontSize']) ? $layer['fontSize'] : '',//字号大小
  194. 'font_color' => isset($layer['color']) ? $layer['color'] : '',//文字颜色
  195. 'background_border_radius' => isset($layer['background_border_radius']) ? $layer['background_border_radius'] : '',//背景圆角
  196. 'background_color' => isset($layer['backgroundColor']) ? $layer['backgroundColor'] : '',//文字背景颜色
  197. 'text_align' => isset($layer['textAlign']) ? $layer['textAlign'] : '',//对齐方式
  198. 'font_weight' => isset($layer['fontWeight']) ? $layer['fontWeight'] : '',//加粗
  199. 'font_style' => isset($layer['fontStyle']) ? $layer['fontStyle'] : '',//斜体
  200. 'font_underline' => isset($layer['textDecoration']) ? $layer['textDecoration'] : '',//下划线
  201. 'line_height' => isset($layer['lineHeight']) ? $layer['lineHeight'] : '',//行高
  202. 'letter_spacing' => isset($layer['letterSpacing']) ? $layer['letterSpacing'] : '',//字距
  203. //形状与线条
  204. 'shape_type' => $layer['shape_type'] ?? $layer['shapeType'] ?? '',//形状类型 rect/circle/ellipse/line
  205. 'fill_mode' => $layer['fill_mode'] ?? $layer['fillMode'] ?? '',//填充模式 solid/none
  206. 'fill_color' => $layer['fill_color'] ?? $layer['fillColor'] ?? '',//填充色
  207. 'stroke_color' => $layer['stroke_color'] ?? $layer['strokeColor'] ?? '',//描边色
  208. 'stroke_width' => isset($layer['stroke_width']) ? floatval($layer['stroke_width']) : (isset($layer['strokeWidth']) ? floatval($layer['strokeWidth']) : 0),//描边宽度
  209. 'create_time' => date('Y-m-d H:i:s')
  210. ];
  211. // 插入关联记录
  212. Db::name('template_material_relation')->insert($relationData);
  213. }
  214. }
  215. return json([
  216. 'code' => 0,
  217. 'msg' => '',
  218. 'data' => '',
  219. 'template_id' => $templateId,
  220. 'template_image_url' => $db_img_path,
  221. 'template_image' => $db_thumbnail_path
  222. ]);
  223. }
  224. /**
  225. * 修改模版
  226. */
  227. public function Template_Material_Update(){
  228. $params = $this->request->param();
  229. // echo "<pre>";
  230. // print_r($params);
  231. // echo "<pre>";die;
  232. // 验证模板ID
  233. if (empty($params['template_id'])) {
  234. return json([
  235. 'code' => 1,
  236. 'msg' => '模板ID不能为空',
  237. 'data' => ''
  238. ]);
  239. }
  240. $templateId = $params['template_id'];
  241. // 检查模板是否存在
  242. $template = Db::name('product_template')->where('id', $templateId)->find();
  243. if (!$template) {
  244. return json([
  245. 'code' => 1,
  246. 'msg' => '模板不存在',
  247. 'data' => ''
  248. ]);
  249. }
  250. // 处理 uploaded_materials:修改时会有新的素材图上传,保存到 uploads/material/ 并写入 template_material 表(参考新增模版)
  251. $layerIdToMaterial = [];
  252. if (!empty($params['uploaded_materials'])) {
  253. $materialSavePath = str_replace('\\', '/', ROOT_PATH . 'public/uploads/material/' . date('Y-m-d') . '/');
  254. if (!is_dir($materialSavePath)) {
  255. mkdir($materialSavePath, 0755, true);
  256. }
  257. foreach ($params['uploaded_materials'] as $item) {
  258. $base64Data = $item['data'] ?? '';
  259. if (empty($base64Data) || !preg_match('/data:image\/(png|jpg|jpeg);base64,([A-Za-z0-9+\/=]+)/i', $base64Data, $m)) {
  260. continue;
  261. }
  262. $imageType = strtolower($m[1]);
  263. $imageData = base64_decode($m[2]);
  264. if ($imageData === false || strlen($imageData) < 100) {
  265. continue;
  266. }
  267. $ext = ($imageType === 'jpeg') ? 'jpg' : $imageType;
  268. $fileName = uniqid() . '_' . date('YmdHis') . '.' . $ext;
  269. $fullPath = $materialSavePath . $fileName;
  270. if (!file_put_contents($fullPath, $imageData)) {
  271. continue;
  272. }
  273. $materialUrl = 'uploads/material/' . date('Y-m-d') . '/' . $fileName;
  274. $materialRecord = [
  275. 'sys_id' => $params['sys_id'] ?? '',
  276. 'material_url' => $materialUrl,
  277. 'type' => $item['type'] ?? '',
  278. 'create_time' => date('Y-m-d H:i:s'),
  279. 'count' => 1
  280. ];
  281. $materialId = Db::name('template_material')->insertGetId($materialRecord);
  282. if ($materialId && isset($item['layer_id'])) {
  283. $layerIdToMaterial[$item['layer_id']] = ['id' => $materialId, 'url' => $materialUrl];
  284. }
  285. }
  286. }
  287. // 处理图片更新
  288. $db_img_path = $template['template_image_url'];
  289. $db_thumbnail_path = $template['thumbnail_image'];
  290. if (!empty($params['previewImage'])) {
  291. $save_path = ROOT_PATH . 'public' . '/' . 'uploads' . '/' . 'template' .'/'. date('Y-m-d') . '/';
  292. // 移除ROOT_PATH中可能存在的反斜杠,确保统一使用正斜杠
  293. $save_path = str_replace('\\', '/', $save_path);
  294. // 自动创建文件夹(如果不存在)
  295. if (!is_dir($save_path)) {
  296. mkdir($save_path, 0755, true);
  297. }
  298. // 提取base64图片数据
  299. $previewImage = $params['previewImage'];
  300. // 匹配base64图片数据
  301. preg_match('/data:image\/(png|jpg|jpeg);base64,([^"]+)/', $previewImage, $matches);
  302. if (empty($matches)) {
  303. return json([
  304. 'code' => 1,
  305. 'msg' => '未找到图片数据',
  306. 'data' => ''
  307. ]);
  308. }
  309. $image_type = $matches[1];
  310. $base64_data = $matches[2];
  311. // 解码base64数据
  312. $image_data = base64_decode($base64_data);
  313. if ($image_data === false) {
  314. return json([
  315. 'code' => 1,
  316. 'msg' => '图片解码失败',
  317. 'data' => ''
  318. ]);
  319. }
  320. // 生成唯一文件名(包含正确的扩展名)
  321. $file_name = uniqid() . '_' . date('YmdHis') . '.' . $image_type;
  322. $full_file_path = $save_path . $file_name;
  323. // 保存图片到文件系统
  324. if (!file_put_contents($full_file_path, $image_data)) {
  325. return json([
  326. 'code' => 1,
  327. 'msg' => '图片保存失败',
  328. 'data' => ''
  329. ]);
  330. }
  331. // 生成数据库存储路径(使用正斜杠格式)
  332. $db_img_path = '/uploads/template/'. date('Y-m-d') .'/' . $file_name;
  333. // 生成缩略图
  334. $thumbnail_path = $this->generateThumbnail($full_file_path, $save_path, $file_name);
  335. $db_thumbnail_path = '/uploads/template/'.date('Y-m-d') .'/' . $thumbnail_path;
  336. // 删除旧图片
  337. if (!empty($template['template_image_url'])) {
  338. $oldImagePath = ROOT_PATH . 'public' . $template['template_image_url'];
  339. if (file_exists($oldImagePath)) {
  340. unlink($oldImagePath);
  341. }
  342. }
  343. if (!empty($template['thumbnail_image'])) {
  344. $oldThumbnailPath = ROOT_PATH . 'public' . $template['thumbnail_image'];
  345. if (file_exists($oldThumbnailPath)) {
  346. unlink($oldThumbnailPath);
  347. }
  348. }
  349. }
  350. // 更新模版表(product_template)
  351. $record['canvasWidth'] = $params['canvasWidth'];
  352. $record['canvasHeight'] = $params['canvasHeight'];
  353. $record['size'] = $params['canvasRatio'];
  354. if (!empty($db_img_path)) {
  355. $record['template_image_url'] = $db_img_path;//原图
  356. $record['thumbnail_image'] = $db_thumbnail_path;//缩略图
  357. }
  358. $record['sys_rq'] = date('Y-m-d');
  359. $record['template_name'] = $params['template_name'];
  360. $record['update_time'] = date('Y-m-d H:i:s');
  361. // 更新模板记录
  362. $res = Db::name('product_template')->where('id', $templateId)->update($record);
  363. if (!$res) {
  364. return json([
  365. 'code' => 1,
  366. 'msg' => '数据库更新失败',
  367. 'data' => ''
  368. ]);
  369. }
  370. // 处理layers数据,更新模版-素材表(template_material_relation)
  371. if (!empty($params['layers'])) {
  372. // 删除旧的关联记录
  373. Db::name('template_material_relation')->where('template_id', $templateId)->delete();
  374. $layers = $params['layers'];
  375. foreach ($layers as $layer) {
  376. $materialId = $layer['material_id'] ?? null;
  377. $materialUrl = isset($layer['url']) ? $layer['url'] : '';
  378. if (isset($layer['id']) && isset($layerIdToMaterial[$layer['id']])) {
  379. $materialId = $layerIdToMaterial[$layer['id']]['id'];
  380. $materialUrl = $layerIdToMaterial[$layer['id']]['url'];
  381. }
  382. $relationData = [
  383. 'template_id' => $templateId,//模版ID
  384. 'sys_id' => $params['sys_id'] ?? '',//用户名
  385. 'material_id' => $materialId,//素材ID
  386. 'z_index' => $layer['id'],//层级
  387. 'layer_name' => $layer['name'],//图层名称
  388. 'layer_type' => $layer['type'],//类型
  389. 'material_url' => $materialUrl,//素材图片
  390. 'position_x' => $layer['x'],
  391. 'position_y' => $layer['y'],
  392. 'width' => $layer['width'],
  393. 'height' => $layer['height'],
  394. 'rotation' => $layer['rotation'],//素材旋转角度
  395. 'opacity' => $layer['opacity'],//素材透明度
  396. 'visible' => $layer['visible'],//图层是否显示
  397. 'locked' => isset($layer['locked']) && $layer['locked'] ? 1 : 0,//图层是否锁住
  398. //文字部分参数
  399. 'text_content' => isset($layer['text']) ? $layer['text'] : '',//文字内容
  400. 'font_family' => isset($layer['fontFamily']) ? $layer['fontFamily'] : '',//字体(如 Arial)
  401. 'font_size' => isset($layer['fontSize']) ? $layer['fontSize'] : '',//字号大小
  402. 'font_color' => isset($layer['color']) ? $layer['color'] : '',//文字颜色
  403. 'background_color' => isset($layer['backgroundColor']) ? $layer['backgroundColor'] : '',//文字背景颜色
  404. 'background_border_radius' => isset($layer['background_border_radius']) ? $layer['background_border_radius'] : '',//背景圆角
  405. 'text_align' => isset($layer['textAlign']) ? $layer['textAlign'] : '',//对齐方式
  406. 'font_weight' => isset($layer['fontWeight']) ? $layer['fontWeight'] : '',//加粗
  407. 'font_style' => isset($layer['fontStyle']) ? $layer['fontStyle'] : '',//斜体
  408. 'font_underline' => isset($layer['textDecoration']) ? $layer['textDecoration'] : '',//下划线
  409. 'line_height' => isset($layer['lineHeight']) ? $layer['lineHeight'] : '',//行高
  410. 'letter_spacing' => isset($layer['letterSpacing']) ? $layer['letterSpacing'] : '',//字距
  411. //形状与线条
  412. 'shape_type' => $layer['shape_type'] ?? $layer['shapeType'] ?? '',//形状类型 rect/circle/ellipse/line
  413. 'fill_mode' => $layer['fill_mode'] ?? $layer['fillMode'] ?? '',//填充模式 solid/none
  414. 'fill_color' => $layer['fill_color'] ?? $layer['fillColor'] ?? '',//填充色
  415. 'stroke_color' => $layer['stroke_color'] ?? $layer['strokeColor'] ?? '',//描边色
  416. 'stroke_width' => isset($layer['stroke_width']) ? floatval($layer['stroke_width']) : (isset($layer['strokeWidth']) ? floatval($layer['strokeWidth']) : 0),//描边宽度
  417. 'create_time' => date('Y-m-d H:i:s')
  418. ];
  419. // 插入关联记录
  420. Db::name('template_material_relation')->insert($relationData);
  421. }
  422. }
  423. return json([
  424. 'code' => 0,
  425. 'msg' => '修改成功',
  426. 'data' => '',
  427. 'template_id' => $templateId,
  428. 'template_image_url' => $db_img_path,
  429. 'template_image' => $db_thumbnail_path
  430. ]);
  431. }
  432. /**
  433. * 生成缩略图(高质量)
  434. * @param string $originalPath 原图路径
  435. * @param string $savePath 保存目录
  436. * @param string $fileName 原文件名
  437. * @return string 缩略图文件名
  438. */
  439. private function generateThumbnail($originalPath, $savePath, $fileName) {
  440. // 获取图片信息
  441. $imageInfo = getimagesize($originalPath);
  442. if (!$imageInfo) {
  443. return '';
  444. }
  445. $width = $imageInfo[0];
  446. $height = $imageInfo[1];
  447. // 计算缩略图尺寸(保持比例,最大宽度400)
  448. $maxWidth = 400;
  449. $maxHeight = 400;
  450. if ($width > $maxWidth || $height > $maxHeight) {
  451. $ratio = min($maxWidth / $width, $maxHeight / $height);
  452. $thumbWidth = round($width * $ratio);
  453. $thumbHeight = round($height * $ratio);
  454. } else {
  455. $thumbWidth = $width;
  456. $thumbHeight = $height;
  457. }
  458. // 创建缩略图画布
  459. $thumbnail = imagecreatetruecolor($thumbWidth, $thumbHeight);
  460. // 根据图片类型创建图像资源
  461. switch ($imageInfo[2]) {
  462. case IMAGETYPE_JPEG:
  463. $source = imagecreatefromjpeg($originalPath);
  464. break;
  465. case IMAGETYPE_PNG:
  466. $source = imagecreatefrompng($originalPath);
  467. // 处理PNG透明
  468. imagealphablending($thumbnail, false);
  469. imagesavealpha($thumbnail, true);
  470. $transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127);
  471. imagefilledrectangle($thumbnail, 0, 0, $thumbWidth, $thumbHeight, $transparent);
  472. break;
  473. case IMAGETYPE_GIF:
  474. $source = imagecreatefromgif($originalPath);
  475. break;
  476. default:
  477. return '';
  478. }
  479. if (!$source) {
  480. return '';
  481. }
  482. // 调整图片大小(使用高质量缩放)
  483. imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
  484. // 生成缩略图文件名
  485. $pathInfo = pathinfo($fileName);
  486. $thumbnailName = $pathInfo['filename'] . '_thumb.' . $pathInfo['extension'];
  487. $thumbnailPath = $savePath . $thumbnailName;
  488. // 保存缩略图(使用高质量设置)
  489. switch ($imageInfo[2]) {
  490. case IMAGETYPE_JPEG:
  491. imagejpeg($thumbnail, $thumbnailPath, 95); // 95% 质量,接近原图
  492. break;
  493. case IMAGETYPE_PNG:
  494. imagepng($thumbnail, $thumbnailPath, 3); // 压缩级别 3,保持较高质量
  495. break;
  496. case IMAGETYPE_GIF:
  497. imagegif($thumbnail, $thumbnailPath);
  498. break;
  499. }
  500. // 释放资源
  501. imagedestroy($source);
  502. imagedestroy($thumbnail);
  503. return $thumbnailName;
  504. }
  505. /**
  506. * 发布模版(release=1)
  507. */
  508. public function Template_Material_Publish(){
  509. $params = $this->request->param();
  510. $record['release'] = 1;
  511. $record['update_time'] = date('Y-m-d H:i:s');
  512. $res = Db::name('product_template')->where('id', $params['template_id'])->update($record);
  513. if (!$res) {
  514. return json([
  515. 'code' => 1,
  516. 'msg' => '发布失败',
  517. 'data' => ''
  518. ]);
  519. }
  520. return json([
  521. 'code' => 0,
  522. 'msg' => '发布成功'
  523. ]);
  524. }
  525. /**
  526. * 取消发布模版(release=0)
  527. */
  528. public function Template_Material_Unpublish(){
  529. $params = $this->request->param();
  530. $record['release'] = 0;
  531. $record['update_time'] = date('Y-m-d H:i:s');
  532. $res = Db::name('product_template')->where('id', $params['template_id'])->update($record);
  533. if (!$res) {
  534. return json([
  535. 'code' => 1,
  536. 'msg' => '发布失败',
  537. 'data' => ''
  538. ]);
  539. }
  540. return json([
  541. 'code' => 0,
  542. 'msg' => '发布成功'
  543. ]);
  544. }
  545. /**
  546. * 删除模版
  547. */
  548. public function Template_Material_Delete(){
  549. $params = $this->request->param();
  550. $record['mod_rq'] = date('Y-m-d H:i:s');
  551. $res = Db::name('product_template')->where('id', $params['template_id'])->update($record);
  552. if (!$res) {
  553. return json([
  554. 'code' => 1,
  555. 'msg' => '模版删除失败',
  556. 'data' => ''
  557. ]);
  558. }
  559. return json([
  560. 'code' => 0,
  561. 'msg' => '模版删除成功'
  562. ]);
  563. }
  564. }