初始版本

This commit is contained in:
贾祥聪
2025-08-19 14:16:51 +08:00
commit f937a1f9b9
4373 changed files with 359728 additions and 0 deletions

View File

@@ -0,0 +1,493 @@
<?php
// +----------------------------------------------------------------------
// | likeshop100%开源免费商用商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | 商业版本务必购买商业授权,以免引起法律纠纷
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshopTeam
// +----------------------------------------------------------------------
namespace app\adminapi\logic\setting\system;
use app\common\logic\BaseLogic;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Log;
use WpOrg\Requests\Requests;
/**
* 升级逻辑
* Class UpgradeLogic
* @package app\adminapi\logic\settings\system
*/
class UpgradeLogic extends BaseLogic
{
const BASE_URL = 'https://server.likeshop.cn';
/**
* @notes 格式化列表数据
* @param $lists
* @return array
* @author 段誉
* @date 2021/8/14 17:18
*/
public static function formatLists($lists, $pageNo)
{
$localData = local_version();
$localVersion = $localData['version'];
foreach ($lists as $k => $item) {
//版本描述
$lists[$k]['version_str'] = '';
$lists[$k]['able_update'] = 0;
if ($localVersion == $item['version_no']) {
$lists[$k]['version_str'] = '您的系统当前处于此版本';
}
if ($localVersion < $item['version_no']) {
$lists[$k]['version_str'] = '系统可更新至此版本';
$lists[$k]['able_update'] = 1;
}
//最新的版本号标志
$lists[$k]['new_version'] = 0;
//注意,是否需要重新发布描述
$lists[$k]['notice'] = [];
if ($item['uniapp_publish'] == 1) {
$lists[$k]['notice'][] = '更新至当前版本后需重新发布前端商城';
}
if ($item['pc_admin_publish'] == 1) {
$lists[$k]['notice'][] = '更新至当前版本后需重新发布PC管理后台';
}
if ($item['pc_shop_publish'] == 1) {
$lists[$k]['notice'][] = '更新至当前版本后需重新发布PC商城端';
}
//处理更新内容信息
$contents = $item['update_content'];
$add = [];
$optimize = [];
$repair = [];
$contentDesc = [];
if (!empty($contents)) {
foreach ($contents as $content) {
if ($content['type'] == 1) {
$add[] = '新增:' . $content['update_function'];
}
if ($content['type'] == 2) {
$optimize[] = '优化:' . $content['update_function'];
}
if ($content['type'] == 3) {
$repair[] = '修复:' . $content['update_function'];
}
}
$contentDesc = array_merge($add, $optimize, $repair);
}
$lists[$k]['add'] = $add;
$lists[$k]['optimize'] = $optimize;
$lists[$k]['repair'] = $repair;
$lists[$k]['content_desc'] = $contentDesc;
unset($lists[$k]['update_content']);
}
$lists[0]['new_version'] = ($pageNo == 1) ? 1 : 0;
return $lists;
}
/**
* @notes 更新操作
* @param $params
* @return bool|string
* @author 段誉
* @date 2021/8/14 17:19
*/
public static function upgrade($params)
{
$openBasedir = ini_get('open_basedir');
if(strpos($openBasedir, "server") !== false) {
self::$error = '请临时关闭服务器本站点的跨域攻击设置,并重启 nginx、PHP具体参考相关升级文档';
return false;
}
// 授权验证
$params['link'] = "package_link";
$result = self::verify($params);
if (!$result['has_permission']) {
self::$error = !empty($result['msg']) ? $result['msg'] : '请先联系客服获取授权';
// 写日志
self::addlog($params['id'], $params['update_type'], false);
return false;
}
// 本地更新包路径
$localUpgradeDir = ROOT_PATH . '/upgrade/';
// 本地更新临时文件
$tempDir = ROOT_PATH . '/upgrade/temp/';
// 更新成功或失败的标识
$flag = true;
Db::startTrans();
try {
// 远程下载链接
$remoteUrl = $result['link'];
if (!is_dir($localUpgradeDir)) {
mkdir(iconv("UTF-8", "GBK", $localUpgradeDir), 0777, true);
}
//下载更新压缩包保存到本地
$remoteData = self::downFile($remoteUrl, $localUpgradeDir);
if (false === $remoteData) {
throw new \Exception('获取文件错误');
}
//解压缩
if (false === unzip($remoteData['save_path'], $tempDir)) {
throw new \Exception('解压文件错误');
}
//更新sql->更新数据类型
if (false === self::upgradeSql($tempDir . 'sql/data/')) {
throw new \Exception('更新数据库数据失败');
}
//更新文件
if (false === self::upgradeFile($tempDir . 'project/server/', self::getProjectPath())) {
throw new \Exception('更新文件失败');
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
//错误日志
$params['error'] = $e->getMessage();
// 标识更新失败
$flag = false;
}
if ($flag) {
try {
//更新sql->更新数据结构
if (false === self::upgradeSql($tempDir . 'sql/structure/')) {
throw new \Exception('更新数据库结构失败');
}
} catch (\Exception $e) {
self::$error = $e->getMessage();
//错误日志
$params['error'] = $e->getMessage();
// 标识更新失败
$flag = false;
}
}
//删除临时文件(压缩包不删除,删除解压的文件)
if ($flag && false === del_target_dir($tempDir, true)) {
Log::write('删除系统更新临时文件失败');
}
// 增加日志
self::addlog($params['id'], $params['update_type'], $flag);
return $flag;
}
/**
* @notes 授权验证
* @param $params
* @author Tab
* @date 2021/10/26 17:12
*/
public static function verify($params)
{
$domain = $_SERVER['SERVER_NAME'];
$remoteUrl = self::BASE_URL . "/api/version/verify?domain=".$domain."&product_id=19&type=2&version_id=".$params['id']."&link=".$params['link'];
$result = Requests::get($remoteUrl);
$result = json_decode($result->body, true);
$result = $result['data'] ?? ['has_permission' => false, 'link' => '', 'msg' => ''];
return $result;
}
/**
* @notes 获取远程版本数据
* @param null $pageNo
* @param null $pageSize
* @return array|mixed
* @author 段誉
* @date 2021/8/14 17:20
*/
public static function getRemoteVersion($pageNo = null, $pageSize = null)
{
$cacheVersion = Cache::get('version_lists' . $pageNo);
if (!empty($cacheVersion)) {
return $cacheVersion;
}
if (empty($pageNo) || empty($pageSize)) {
$remoteUrl = self::BASE_URL . "/api/version/lists?product_id=19&type=2&page=1";
} else {
$remoteUrl = self::BASE_URL . "/api/version/lists?product_id=19&type=2&page_no=$pageNo&page_size=$pageSize&page=1";
}
$result = Requests::get($remoteUrl);
$result = json_decode($result->body, true);
$result = $result['data'] ?? [];
Cache::set('version_lists' . $pageNo, $result, 1800);
return $result;
}
/**
* @notes 更新包下载链接
* @param $params
* @return array|false
* @author 段誉
* @date 2022/3/25 17:50
*/
public static function getPkgLine($params)
{
$map = [
1 => 'package_link', //一键更新类型 : 服務端更新包
2 => 'package_link', //服務端更新包
3 => 'pc_package_link', //pc端更新包
4 => 'uniapp_package_link', //uniapp更新包
5 => 'web_package_link', //后台前端更新包
6 => 'integral_package_link', //完整包
8 => 'kefu_package_link', //客服更新包
];
$params['link'] = $map[$params['update_type']] ?? '未知类型';
// 授权验证
$result = self::verify($params);
if (!$result['has_permission']) {
self::$error = !empty($result['msg']) ? $result['msg'] : '请先联系客服获取授权';
// 写日志
self::addlog($params['id'], $params['update_type'], false);
return false;
}
//增加日志记录
self::addlog($params['id'], $params['update_type']);
//更新包下载链接
return ['line' => $result['link']];
}
/**
* @notes 添加日志
* @param $versionId //版本id
* @param $updateType //更新类型
* @param bool $status //更新状态
* @return bool|\Requests_Response
* @author 段誉
* @date 2021/10/9 14:48
*/
public static function addlog($versionId, $updateType, $status = true)
{
//版本信息
$versionData = self::getVersionDataById($versionId);
$domain = $_SERVER['SERVER_NAME'];
try {
$paramsData = [
'version_id' => $versionData['id'],
'version_no' => $versionData['version_no'],
'domain' => $domain,
'type' => 2,//付费版
'product_id' => 19,//上门按摩
'update_type' => $updateType,
'status' => $status ? 1 : 0,
'error' => empty(self::$error) ? '' : self::$error,
];
$requestUrl = self::BASE_URL . '/api/version/log';
$result = Requests::post($requestUrl, [], $paramsData);
return $result;
} catch (\Exception $e) {
Log::write('更新日志:' . '更新失败' . $e->getMessage());
return false;
}
}
/**
* @notes 通过版本记录id获取版本信息
* @param $id
* @return array
* @author 段誉
* @date 2021/10/9 11:40
*/
public static function getVersionDataById($id)
{
$cacheVersion = self::getRemoteVersion()['lists'] ?? [];
if (!empty($cacheVersion)) {
$versionColumn = array_column($cacheVersion, null, 'id');
if (!empty($versionColumn[$id])) {
return $versionColumn[$id];
}
}
return [];
}
/**
* @notes 下载远程文件
* @param $url
* @param string $savePath
* @return array|false
* @author 段誉
* @date 2021/8/14 17:20
*/
public static function downFile($url, $savePath = './upgrade/')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$header = '';
$body = '';
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
}
curl_close($ch);
//文件名
$fullName = basename($url);
//文件保存完整路径
$savePath = $savePath . $fullName;
//创建目录并设置权限
$basePath = dirname($savePath);
if (!file_exists($basePath)) {
@mkdir($basePath, 0777, true);
@chmod($basePath, 0777);
}
if (file_put_contents($savePath, $body)) {
return [
'save_path' => $savePath,
'file_name' => $fullName,
];
}
return false;
}
/**
* @notes 获取项目路径
* @return string
* @author 段誉
* @date 2021/8/14 17:20
*/
public static function getProjectPath()
{
$path = dirname(ROOT_PATH);
if(substr($path, -1) != '/') {
$path = $path . '/';
}
return $path;
}
/**
* @notes 更新sql
* @param $dir
* @return bool
* @author 段誉
* @date 2021/8/14 17:20
*/
public static function upgradeSql($dir)
{
//没有sql文件时无需更新
if (!file_exists($dir)) {
return true;
}
//遍历指定目录下的指定后缀文件
$sqlFiles = get_scandir($dir, '', 'sql');
if (false === $sqlFiles) {
return false;
}
//当前数据库前缀
$sqlPrefix = config('database.connections.mysql.prefix');
foreach ($sqlFiles as $k => $item) {
if (get_extension($item) != 'sql') {
continue;
}
$sqlContent = file_get_contents($dir . $item);
if (empty($sqlContent)) {
continue;
}
$sqls = explode(';', $sqlContent);
//执行sql
foreach ($sqls as $sql) {
$sql = trim($sql);
if (!empty($sql)) {
$sql = str_replace('`ls_', '`' . $sqlPrefix, $sql) . ';';
Db::execute($sql);
}
}
}
return true;
}
/**
* @notes 更新文件
* @param $tempFile
* @param $oldFile
* @return bool
* @author 段誉
* @date 2021/8/14 17:21
*/
public static function upgradeFile($tempFile, $oldFile)
{
if (empty(trim($tempFile)) || empty(trim($oldFile))) {
return false;
}
// 目录不存在就新建
if (!is_dir($oldFile)) {
mkdir($oldFile, 0777, true);
}
foreach (glob($tempFile . '*') as $fileName) {
// 要处理的是目录时,递归处理文件目录。
if (is_dir($fileName)) {
self::upgradeFile($fileName . '/', $oldFile . basename($fileName) . '/');
}
// 要处理的是文件时,判断是否存在 或者 与原来文件不一致 则覆盖
if (is_file($fileName)) {
if (!file_exists($oldFile . basename($fileName))
|| md5(file_get_contents($fileName)) != md5(file_get_contents($oldFile . basename($fileName)))
) {
copy($fileName, $oldFile . basename($fileName));
}
}
}
return true;
}
}