shopxo/app/service/DesignService.php

649 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\service;
use think\facade\Db;
use app\service\ResourcesService;
/**
* 页面设计服务层
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-02-14
* @desc description
*/
class DesignService
{
/**
* 列表
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-06-16
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignList($params = [])
{
$where = empty($params['where']) ? [] : $params['where'];
$field = empty($params['field']) ? '*' : $params['field'];
$order_by = empty($params['order_by']) ? 'id desc' : $params['order_by'];
$m = isset($params['m']) ? intval($params['m']) : 0;
$n = isset($params['n']) ? intval($params['n']) : 10;
// 获取数据
$data = Db::name('Design')->where($where)->limit($m, $n)->order($order_by)->select()->toArray();
return DataReturn(MyLang('common.handle_success'), 0, self::DesignListHandle($data, $params));
}
/**
* 列表数据处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-01
* @desc description
* @param [array] $data [数据列表]
* @param [array] $params [输入参数]
*/
public static function DesignListHandle($data, $params = [])
{
if(!empty($data))
{
foreach($data as &$v)
{
// logo
if(array_key_exists('logo', $v))
{
$v['logo'] = ResourcesService::AttachmentPathViewHandle($v['logo']);
}
// 时间
if(array_key_exists('add_time', $v))
{
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
}
if(array_key_exists('upd_time', $v))
{
$v['upd_time'] = date('Y-m-d H:i:s', $v['upd_time']);
}
}
}
return $data;
}
/**
* 保存
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-06-16
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignSave($params = [])
{
// 附件
$data_fields = ['logo'];
$attachment = ResourcesService::AttachmentParams($params, $data_fields);
// 配置信息
$config = empty($params['config']) ? '' : (is_array($params['config']) ? json_encode($params['config'], JSON_UNESCAPED_UNICODE) : htmlspecialchars_decode($params['config'])) ;
// 数据
$data = [
'name' => empty($params['name']) ? '默认页面'.date('mdHi') : $params['name'],
'logo' => $attachment['data']['logo'],
'config' => $config,
'seo_title' => empty($params['seo_title']) ? '' : $params['seo_title'],
'seo_keywords' => empty($params['seo_keywords']) ? '' : $params['seo_keywords'],
'seo_desc' => empty($params['seo_desc']) ? '' : $params['seo_desc'],
'is_enable' => isset($params['is_enable']) ? intval($params['is_enable']) : 1,
'is_header' => isset($params['is_header']) ? intval($params['is_header']) : 1,
'is_footer' => isset($params['is_footer']) ? intval($params['is_footer']) : 1,
];
if(empty($params['id']))
{
$data['add_time'] = time();
$data_id = Db::name('Design')->insertGetId($data);
if($data_id <= 0)
{
return DataReturn(MyLang('common.insert_fail'), -1);
}
} else {
$data_id = intval($params['id']);
$data['upd_time'] = time();
if(Db::name('Design')->where(['id'=>$data_id])->update($data) === false)
{
return DataReturn(MyLang('common.update_fail'), -1);
}
}
return DataReturn(MyLang('common.operate_success'), 0, $data_id);
}
/**
* 状态更新
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-06-23
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignStatusUpdate($params = [])
{
// 请求参数
$p = [
[
'checked_type' => 'empty',
'key_name' => 'id',
'error_msg' => '操作id有误',
],
[
'checked_type' => 'empty',
'key_name' => 'field',
'error_msg' => '字段有误',
],
[
'checked_type' => 'in',
'key_name' => 'state',
'checked_data' => [0,1],
'error_msg' => '状态有误',
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 数据更新
if(Db::name('Design')->where(['id'=>intval($params['id'])])->update([$params['field']=>intval($params['state']), 'upd_time'=>time()]))
{
return DataReturn(MyLang('common.operate_success'), 0);
}
return DataReturn(MyLang('common.operate_fail'), -100);
}
/**
* 删除
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-18
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignDelete($params = [])
{
// 请求参数
$p = [
[
'checked_type' => 'empty',
'key_name' => 'ids',
'error_msg' => '操作id有误',
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 是否数组
if(!is_array($params['ids']))
{
$params['ids'] = explode(',', $params['ids']);
}
// 删除操作
if(Db::name('Design')->where(['id'=>$params['ids']])->delete())
{
// 删除数据库附件
foreach($params['ids'] as $v)
{
ResourcesService::AttachmentPathTypeDelete(self::AttachmentPathTypeValue($v));
}
return DataReturn(MyLang('common.delete_success'), 0);
}
return DataReturn(MyLang('common.delete_fail'), -100);
}
/**
* 页面访问统计加1
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-10-15
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignAccessCountInc($params = [])
{
if(!empty($params['design_id']))
{
return Db::name('Design')->where(['id'=>intval($params['design_id'])])->inc('access_count')->update();
}
return false;
}
/**
* 附件标识
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-06-23
* @desc description
* @param [int] $data_id [数据 id]
*/
public static function AttachmentPathTypeValue($data_id)
{
return 'design-'.$data_id;
}
/**
* 同步到首页
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-04-19
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignSync($params = [])
{
// 请求参数
$p = [
[
'checked_type' => 'empty',
'key_name' => 'id',
'error_msg' => '操作id有误',
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 获取数据
$data = Db::name('Design')->where(['id'=>intval($params['id'])])->field('config')->find();
if(empty($data))
{
return DataReturn('数据不存在', -1);
}
return LayoutService::LayoutConfigSave('home', $data);
}
/**
* 下载
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-04-17
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignDownload($params = [])
{
// 请求参数
$p = [
[
'checked_type' => 'empty',
'key_name' => 'id',
'error_msg' => '操作id有误',
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 获取数据
$data = Db::name('Design')->where(['id'=>intval($params['id'])])->find();
if(empty($data))
{
return DataReturn('数据不存在', -1);
}
// 目录不存在则创建
$dir = ROOT.'runtime'.DS.'data'.DS.'design'.DS.$data['id'];
\base\FileUtil::CreateDir($dir);
// 临时数据id
$data_id = GetNumberCode(6).time().GetNumberCode(6);
// 解析下载数据
$config = self::ConfigDownloadHandle($data_id, $data['config'], $dir);
// 基础信息
$base = [
'data_id' => $data_id,
'name' => $data['name'],
'logo' => self::FileSave($data_id, $data['logo'], 'images', $dir),
'is_header' => $data['is_header'],
'is_footer' => $data['is_footer'],
'config' => $config,
];
if(@file_put_contents($dir.DS.'config.json', JsonFormat($base)) === false)
{
return DataReturn('配置文件生成失败', -1);
}
// 生成压缩包
$dir_zip = $dir.'.zip';
$zip = new \base\ZipFolder();
if(!$zip->zip($dir_zip, $dir))
{
return DataReturn('压缩包生成失败', -2);
}
// 生成成功删除目录
\base\FileUtil::UnlinkDir($dir);
// 开始下载
if(\base\FileUtil::DownloadFile($dir_zip, $data['name'].'_v'.date('YmdHis').'.zip'))
{
// 删除文件
@unlink($dir_zip);
} else {
return DataReturn('下载失败', -100);
}
return DataReturn('下载成功', 0);
}
/**
* 配置数据下载处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-04-17
* @desc description
* @param [int] $data_id [数据id]
* @param [array] $config [配置数据]
* @param [string] $dir [存储目录]
*/
public static function ConfigDownloadHandle($data_id, $config, $dir)
{
if(!empty($config))
{
// 非数组则解析
if(!is_array($config))
{
$config = json_decode($config, true);
}
// 开始处理数据
foreach($config as &$v)
{
if(empty($v['children']))
{
continue;
}
foreach($v['children'] as &$vs)
{
if(empty($vs['children']))
{
continue;
}
foreach($vs['children'] as &$vss)
{
if(empty($vss['config']))
{
continue;
}
switch($vss['value'])
{
// 单图
case 'images' :
$vss['config']['content_images'] = self::FileSave($data_id, $vss['config']['content_images'], 'images', $dir);
break;
// 多图
case 'many-images' :
if(!empty($vss['config']['data_list']))
{
foreach($vss['config']['data_list'] as &$iv)
{
$iv['images'] = self::FileSave($data_id, $iv['images'], 'images', $dir);
}
}
break;
// 视频
case 'video' :
$vss['config']['content_video'] = self::FileSave($data_id, $vss['config']['content_video'], 'video', $dir);
break;
}
}
}
}
}
return $config;
}
/**
* 文件保存
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-04-18
* @desc description
* @param [int] $data_id [数据id]
* @param [string] $file [文件地址]
* @param [string] $type [类型]
* @param [string] $dir [存储路径]
*/
public static function FileSave($data_id, $file, $type, $dir)
{
if(!empty($file))
{
$arr = explode('/', $file);
$path = 'static'.DS.'upload'.DS.$type.DS.'design'.DS.$data_id.DS.date('Y/m/d');
$filename = $path.DS.$arr[count($arr)-1];
\base\FileUtil::CreateDir($dir.DS.$path);
$status = false;
if(substr($file, 0, 4) == 'http')
{
$temp = ResourcesService::AttachmentPathHandle($file);
if(substr($temp, 0, 4) == 'http' || !file_exists(ROOT.'public'.$temp))
{
// 远程下载
$temp_data = RequestGet($file);
if(!empty($temp_data))
{
file_put_contents($dir.DS.$filename, $temp_data);
$status = true;
}
} else {
$file = $temp;
}
}
if(!$status)
{
\base\FileUtil::CopyFile(ROOT.'public'.$file, $dir.DS.$filename);
}
return DS.$filename;
}
return '';
}
/**
* 导入
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-04-19
* @desc description
* @param [array] $params [输入参数]
*/
public static function DesignUpload($params = [])
{
// 文件上传校验
$error = FileUploadError('file');
if($error !== true)
{
return DataReturn($error, -1);
}
// 文件格式化校验
$type = ResourcesService::ZipExtTypeList();
if(!in_array($_FILES['file']['type'], $type))
{
return DataReturn('文件格式有误请上传zip压缩包', -2);
}
// 上传处理
return self::DesignUploadHandle($_FILES['file']['tmp_name'], $params);
}
/**
* 导入处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-04-19
* @desc description
* @param [string] $package_file [软件包地址]
* @param [array] $params [输入参数]
*/
public static function DesignUploadHandle($package_file, $params = [])
{
// 应用upload目录权限校验
$app_upload_dir = ROOT.'public'.DS.'static'.DS.'upload';
if(!is_writable($app_upload_dir))
{
return DataReturn('应用upload目录没有操作权限'.'['.$app_upload_dir.']', -3);
}
// 开始解压文件
$zip = new \ZipArchive();
$resource = $zip->open($package_file);
if($resource != true)
{
return DataReturn('压缩包打开失败['.$resource.']', -11);
}
// 文件处理
$config = [];
$data_id = 0;
$success = 0;
for($i=0; $i<$zip->numFiles; $i++)
{
// 资源文件
$file = $zip->getNameIndex($i);
// 排除临时文件和临时目录
if(strpos($file, '/.') === false && strpos($file, '__') === false)
{
// 去除第一个目录为原始数据的id
$temp_file = substr($file, strpos($file, '/')+1);
if(empty($temp_file) || in_array($temp_file, ['static/', 'static/upload/']))
{
continue;
}
// 是否配置文件
if($temp_file == 'config.json')
{
$stream = $zip->getStream($file);
if($stream === false)
{
$zip->close();
return DataReturn('配置信息读取失败', -1);
}
// 获取配置信息并解析
$file_content = stream_get_contents($stream);
$config = empty($file_content) ? [] : json_decode($file_content, true);
if(empty($config) || empty($config['data_id']) || empty($config['name']))
{
$zip->close();
return DataReturn('配置信息为空或有误', -1);
}
// 数据添加
$data = [
'name' => $config['name'],
'is_header' => (isset($config['is_header']) && $config['is_header'] == 1) ? 1 : 0,
'is_footer' => (isset($config['is_footer']) && $config['is_footer'] == 1) ? 1 : 0,
'add_time' => time(),
];
$data_id = Db::name('Design')->insertGetId($data);
if($data_id <= 0)
{
$zip->close();
return DataReturn('数据添加失败', -1);
}
// 更新配置信息和logo
if(!empty($config['config']) || !empty($config['logo']))
{
$upd_data = [
'logo' => empty($config['logo']) ? '' : str_replace($config['data_id'], $data_id, $config['logo']),
'config' => empty($config['config']) ? '' : str_replace($config['data_id'], $data_id, json_encode($config['config'], JSON_UNESCAPED_UNICODE)),
'upd_time' => time(),
];
if(!Db::name('Design')->where(['id'=>$data_id])->update($upd_data))
{
$zip->close();
return DataReturn('数据更新失败', -1);
}
}
continue;
}
// 配置信息和新的数据id必须存在
if(!empty($config) && !empty($data_id))
{
// 截取文件路径
$new_file = ROOT.'public'.DS.str_replace($config['data_id'], $data_id, $temp_file);
$file_path = substr($new_file, 0, strrpos($new_file, '/'));
// 路径不存在则创建
\base\FileUtil::CreateDir($file_path);
// 如果不是目录则写入文件
if(!is_dir($new_file))
{
// 读取这个文件
$stream = $zip->getStream($file);
if($stream !== false)
{
$file_content = stream_get_contents($stream);
if($file_content !== false)
{
if(file_put_contents($new_file, $file_content))
{
$success++;
}
}
fclose($stream);
}
}
}
}
}
// 关闭zip
$zip->close();
// 附件同步到数据库
ResourcesService::AttachmentDiskFilesToDb('design', self::AttachmentPathTypeValue($data_id));
return DataReturn('导入成功');
}
}
?>