引导安装,升级程序优化

This commit is contained in:
taoser 2022-11-26 20:32:21 +08:00
parent 8ddee45e5f
commit 6cf239b1cf
15 changed files with 144 additions and 120 deletions

View File

@ -50,15 +50,15 @@ class Addons extends AdminController
}
$res['col'] = [
['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field' => 'name','title'=> '插件', 'width'=> 120],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 60],
['field' => 'author','title'=> '作者', 'width'=> 80],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'show','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '到期时间', 'width'=> 150],
['title' => '操作', 'width'=> 220, 'align'=>'center', 'toolbar'=> '#addons-installed-tool']
['field' => 'ctime','title'=> '到期时间', 'width'=> 100],
['title' => '操作', 'width'=> 200, 'align'=>'center', 'toolbar'=> '#addons-installed-tool']
];
} else {
$res = ['code'=>-1,'msg'=>'没有安装任何插件'];
@ -81,7 +81,7 @@ class Addons extends AdminController
['field' => 'downloads','title'=> '下载', 'width'=> 70],
['field' => 'version','title'=> '版本', 'width'=> 70],
['field' => 'status','title'=> '状态', 'width'=> 70],
['title' => '操作', 'width'=> 180, 'align'=>'center', 'toolbar'=> '#addons-tool']
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool']
];
} else {
$res = ['code'=>-1,'msg'=>'未获取到服务器信息'];
@ -167,6 +167,17 @@ class Addons extends AdminController
return json($res);
}
/**
* 上传接口
*
* @return void
*/
public function uploads()
{
$type = Request::param('type');
return $this->uploadFiles($type);
}
//安装插件
public function install()
{

View File

@ -98,8 +98,7 @@ class Index extends AdminController
$verCheck = Api::urlPost($this->sys['upcheck_url'],['pn'=>$this->pn,'ver'=>$this->sys_version]);
if($verCheck->code !== -1){
$versions = $verCheck->code ? "<span style='color:red'>有{$verCheck->up_num}个版本需更新,当前可更新至{$verCheck->version}</span>" : $verCheck->msg;
return $versions;
return $verCheck->code ? "<span style='color:red'>有{$verCheck->up_num}个版本需更新,当前可更新至{$verCheck->version}</span>" : $verCheck->msg;
} else {
return lang('No new messages');
}

View File

@ -102,41 +102,24 @@ class Upgrade extends AdminController
Db::name('system')->cache('system')->update(['clevel'=>$cy->level,'id'=>1]);
}
$versions = Api::urlPost($this->sys['upcheck_url'],['pn'=>$this->pn,'ver'=>$this->sys_version]);
//判断服务器状态
// 判断服务器状态
$version_code = $versions->code;
if($version_code == -1){
$res = json(['code'=>$version_code,'msg'=>$versions->msg]);
}
if($version_code == 1){
$res = json(['code'=>$versions->code,'msg'=>$versions->msg,'version'=>$versions->version,'upnum'=>$versions->up_num,'info'=>$versions->info]);
$res = json(['code'=>$version_code,'msg'=>$versions->msg,'data'=>['version'=>$versions->version,'upnum'=>$versions->up_num,'info'=>$versions->info]]);
}
if($version_code == 0){
$res = json(['code'=>$versions->code,'msg'=>$versions->msg]);
$res = json(['code'=>$version_code,'msg'=>$versions->msg]);
}
return $res;
}
/**
* 备份
* @param string $dir
* @param string $backDir
* @param array $ex
* @return \think\response\Json
*/
public function backFile(string $dir,string $backDir,array $ex)
{
$backRes = Files::copydirs($dir, $backDir, $ex);
$backData = $backRes->getData();
if($backData['code'] == -1){
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'error','progress'=>'25%','msg'=>'备份失败!']);
return json(['code'=>-1,'msg'=>$backRes['msg']]);
}
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'30%','msg'=>'执行文件备份成功!']);
}
/**
* 在线更新
* 1.提交接口2.下载数据包3.备份4升级
*/
public function upload()
{
@ -158,21 +141,20 @@ class Upgrade extends AdminController
if(!isset($header[0]) && (strpos($header[0], '200') || strpos($header[0], '304'))){
return json(['code'=>-1,'msg'=>'获取远程文件失败']);
}
//把远程文件放入本地
$upload_dir = Files::getDirPath($this->upload_dir); //拼接路径
$upload_dir = Files::getDirPath($this->upload_dir); //拼接升级文件暂存路径
Files::mkdirs($upload_dir);
$package_file = $upload_dir.'taoler_'.$version_num.'.zip'; //升级的压缩包文件
$cpfile = copy($file_url,$package_file);
$package_file = $upload_dir.'taoler_'.$version_num.'.zip'; //本地zip文件
$cpfile = copy($file_url,$package_file); //把远程文件放入本地
if(!$cpfile) {
return json(['code'=>-1,'msg'=>'下载升级文件失败']);
}
//记录下日志
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'20%','msg'=>'上传升级包'.$version_num.'成功!']);
//升级前备份代码
$ex = array('.git','.idea','runtime','data','addons','config','extend','mysql','public','vendor','view'); // 排除备份文件夹
$ex = array('.git','.idea','runtime','data','addons','config','extend','mysql','public','vendor','view'); // 排除备份目录
$this->backFile($this->root_dir,$this->backup_dir,$ex);
//执行升级
@ -186,7 +168,7 @@ class Upgrade extends AdminController
Files::delDirAndFile($this->upload_dir);
Files::delDirAndFile($this->backup_dir);
//清除无用目录和文件
//清除废弃目录和文件
$delFiles = '../runtime/remove.txt';
if(file_exists($delFiles)){
$str = file_get_contents($delFiles); //将整个文件内容读入到一个字符串中
@ -206,9 +188,9 @@ class Upgrade extends AdminController
unlink($delFiles);
}
//清理缓存
$this->clearSysCache();
//更新系统的版本号了
//更新php的版本号了(应该跟svngit的版本号一致)
//更新数据库的版本号了(应该跟svngit的版本号一致)
$value = [
'version' => $version_num
];
@ -216,7 +198,9 @@ class Upgrade extends AdminController
if(!$res){
return json(['code'=>-1,'msg'=>'代码更新成功,但版本写入失败']);
}
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'100%','msg'=>'升级成功!']);
//清理缓存
$this->clearSysCache();
return json(['code'=>0,'msg'=>'升级成功']);
}
@ -229,7 +213,7 @@ class Upgrade extends AdminController
*/
private function execute_update(string $package_file)
{
//解压 zip文件有密码的话需要解密
// 1.解压 zip文件有密码的话需要解密
$zip = new Zip;
$zipDir = strstr($package_file, '.zip',true); //返回文件名后缀前的字符串
$zipPath = Files::getDirPath($zipDir); //转换为带/的路径 压缩文件解压到的路径
@ -243,16 +227,21 @@ class Upgrade extends AdminController
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'50%','msg'=>'升级文件解压成功!']);
//升级sql操作
// 2.升级sql操作
$upSql = $zipPath.'runtime/update.sql';
if(file_exists($upSql)) {
try{
SqlFile::dbExecute($upSql);
} catch (\Exception $e){
return json(['code'=>-1,'msg'=>$e->getMessage()]);
}
//删除sql语句
unlink($upSql);
}
//升级PHP
// 3.升级PHP
if(is_dir($zipPath)) {
//升级前的写入文件权限检查
$allUpdateFiles = Files::getAllFile($zipPath);
@ -293,13 +282,6 @@ class Upgrade extends AdminController
}
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'100%','msg'=>'升级成功!']);
//更新系统的版本号了
//更新php的版本号了(应该跟svngit的版本号一致)
//更新数据库的版本号了(应该跟svngit的版本号一致)
return json(['code'=>0,'msg'=>'升级文件执行成功']);
}
@ -359,5 +341,23 @@ class Upgrade extends AdminController
return json(['code'=>0,'msg'=>'升级成功']);
}
/**
* 备份
* @param string $dir
* @param string $backDir
* @param array $ex
* @return \think\response\Json
*/
public function backFile(string $dir,string $backDir,array $ex)
{
$backRes = Files::copydirs($dir, $backDir, $ex);
$backData = $backRes->getData();
if($backData['code'] == -1){
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'error','progress'=>'25%','msg'=>'备份失败!']);
return json(['code'=>-1,'msg'=>$backRes['msg']]);
}
Log::channel('update')->info('update:{type} {progress} {msg}',['type'=>'success','progress'=>'30%','msg'=>'执行文件备份成功!']);
}
}

View File

@ -61,30 +61,22 @@
base: '/static/admin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'upload'], function(){
var $ = layui.$,upload = layui.upload,form = layui.form;
}).use(['index', 'upload','notify'], function(){
var $ = layui.$,upload = layui.upload,form = layui.form,notify=layui.notify;
//上传头像
upload.render({
elem: '.upload-select'
,url: 'uploadImg'
,url: 'uploads'
,data: {type:'image'}
,accept: 'images'
,method: 'get'
,acceptMime: 'image/*'
,done: function(res){
$(this.item).prev("div").children("input").val(res.src);
if(res.code == 0){
layer.msg(res.msg,{
icon:6,
tiye:2000
});
$(this.item).prevAll("input").val(res.url);
if(res.status == 0){
notify.success(res.msg);
} else {
layer.open({
title:"上传失败",
content:res.msg,
icon:5,
anim:6
});
notify.error(res.msg);
}
}
});

View File

@ -19,6 +19,7 @@
<link rel="stylesheet" href="/static/admin/style/admin.css" media="all">
{block name="css"}{/block}
<script src="/static/layui/layui.js"></script>
<script src="/static/notify.js"></script>
</head>
<body class="{if($Request.url == url('index/index'))} layui-layout-body {/if}">
{block name="body"}内容{/block}

View File

@ -79,11 +79,12 @@
base: '/static/admin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index','layer','form','upload'], function(){
}).use(['index','notify','layer','form','upload'], function(){
var $ = layui.jquery
,layer = layui.layer
,form = layui.form
,upload = layui.upload;
var notify = layui.notify;
//检测并更新系统
$('#upload-check').on('click',function(){
@ -95,32 +96,21 @@
if (data.code == 0) {
//已件最新版本
layer.close(loading);
layer.msg(data.msg,{
icon:6,
time:2000
});
notify.info(data.msg);
} else if (data.code == 1) {
//可升级
layer.close(loading);
$('div#ver_nums').after('<div class="layui-input-inline layui-input-company">发现<span style="color:red">'+data.upnum+'</span>个新版本:<span style="color:red">可更新至v' + data.version + ' [!!!重要:' + data.info + ']</span></div>');
//$('div#ver_nums').after('<div class="layui-input-inline layui-input-company">发现<span style="color:red">'+data.upnum+'</span>个新版本:<span style="color:red">可更新至v'+data.version+'</span></div> <button class="layui-btn layui-btn-sm" lay-submit lay-filter="update_system" data-url="{$ver_num.upgrade_url}" id="update_system">确认升级</button>');
$('div#ver_nums').after('<div class="layui-input-inline layui-input-company">发现<span style="color:red">'+data.data.upnum+'</span>个新版本:<span style="color:red">可更新至v' + data.data.version + ' [!重要:' + data.data.info + ']</span></div>');
$('button#upload-check').hide();
//更新系统
layer.confirm('更新v' + data.version + ',升级说明:<span style="color:red">[!!!重要:' + data.info + ']</span><br>确定升级?',{icon: 3, title:'升级系统'}, function(index){
layer.confirm('更新v' + data.data.version + ',升级说明:<span style="color:red">[!重要:' + data.data.info + ']</span><br>确定升级?',{icon: 3, title:'升级系统'}, function(index){
uploads(); //更新
layer.close(index); //关闭load加载层
});
} else {
//服务器错误
layer.close(loading);
layer.open({
title:'服务错误',
content:data.msg,
icon:5,
anim:6
});
notify.error(data.msg);
}
}
);
@ -129,7 +119,7 @@
//更新
function uploads(){
var load = layer.load(); //loading
var load = layer.load();
$.get("{:url('upgrade/upload')}",function (data){
if (data.code == 0) {
layer.close(load);
@ -141,7 +131,7 @@
});
} else {
layer.close(load);
layer.alert(data.msg,{icon:5,title:'更新失败', area:['50%', '70%']});
notify.error(data.msg);
return false;
}
}

View File

@ -28,12 +28,9 @@ return [
// 应用映射(自动多应用模式有效)
'app_map' => [
//'bbs' => 'index'
],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [
//'www' => 'index',
//'adm' => 'admin'
],
// 禁止URL访问的应用列表自动多应用模式有效

View File

@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改
'appname' => 'TaoLer',
// 版本配置
'version' => '2.0.2',
'version' => '2.0.3',
// 加盐
'salt' => 'taoler',
// 数据库备份目录

View File

@ -37,7 +37,7 @@ class Api
$res = curl_exec($ch);
$httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpCode == '200'){
if($httpCode == 200){
return json_decode($res);
} else {
return json_decode('{"code":-1,"msg":"远程服务器失败,稍后重试"}'); //转换为对象
@ -54,7 +54,7 @@ class Api
$data = curl_exec($ch);
$httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpCode == '200'){
if($httpCode == 200){
return json_decode($data);
} else {
//$status ='{"code":-1,"msg":"远程服务器失败"}'; //字符串
@ -72,7 +72,7 @@ class Api
$data = curl_exec($ch);
$httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpCode == '200'){
if($httpCode == 200){
//return json_decode($data);
return json(['code'=>0, 'data'=>$data]);
} else {

View File

@ -118,7 +118,7 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
var field = data.field; //获取提交的字段
$.ajax({
type: "post",
url: addonsConfig,
url: url,
data: field,
daType: "json",
success: function (res) {
@ -141,23 +141,23 @@ layui.define(["table", "form", "upload","notify","hxNav"], function (exports) {
forms.on("click", "button", function (data) {
var even = this.getAttribute("lay-event");
var names = this.dataset.name;
if (even == "addInput") {
var html = '<div class="layui-form-item">\n' +
'<label class="layui-form-label"></label>\n' +
'<div class="layui-input-inline">\n' +
' <input type="text" name="'+ names +'[key][]" value="" placeholder="key" autocomplete="off" class="layui-input input-double-width">\n' +
'</div>\n' +
'<div class="layui-input-inline">\n' +
' <input type="text" name="'+ names +'[value][]" value="" placeholder="value" autocomplete="off" class="layui-input input-double-width">\n' +
'</div>\n' +
'<button data-name="'+ names +'" type="button" class="layui-btn layui-btn-danger layui-btn-sm removeInupt" lay-event="removeInupt">\n' +
' <i class="layui-icon"></i>\n' +
'</button>\n' +
'</div>';
$(this).parent().parent().append(html);
} else {
$(this).parent().remove();
}
// if (even == "addInput") {
// var html = '<div class="layui-form-item">\n' +
// '<label class="layui-form-label"></label>\n' +
// '<div class="layui-input-inline">\n' +
// ' <input type="text" name="'+ names +'[key][]" value="" placeholder="key" autocomplete="off" class="layui-input input-double-width">\n' +
// '</div>\n' +
// '<div class="layui-input-inline">\n' +
// ' <input type="text" name="'+ names +'[value][]" value="" placeholder="value" autocomplete="off" class="layui-input input-double-width">\n' +
// '</div>\n' +
// '<button data-name="'+ names +'" type="button" class="layui-btn layui-btn-danger layui-btn-sm removeInupt" lay-event="removeInupt">\n' +
// ' <i class="layui-icon"></i>\n' +
// '</button>\n' +
// '</div>';
// $(this).parent().parent().append(html);
// } else {
// $(this).parent().remove();
// }
});
},
});

View File

@ -0,0 +1,34 @@
body{background:#fff}
.cl{zoom:1}
.cl:after{content:'\20';display:block;height:0;clear:both;visibility:hidden}
.z{float:left}
.y{float:right}
.logo {height:37px;padding:10px 0 0 10px;}
.header{background:#009688;height:60px;width:100%;position:fixed;left:0;top:0;z-index:999}
.header a{font-size:18px;padding:0 30px 0 0;line-height:60px;font-weight:100;color:#fff}
.header h2{font-size:18px;padding:0 0 0 30px;line-height:60px;font-weight:100;color:#fff}
.header a:hover{color:#fff}
.inside{width:100%;min-width:1000px;height:65px;background:#393D49}
.inside h2 img{float:left;padding:0}
.inside ul{width:120px;height:65px;float:left;margin-left:68px}
.inside .innumber1{background:#FF5722!important;color:#fff!important}
.inside .innumber{margin-top:12px;width:40px;height:40px;line-height:40px;text-align:center;font-size:20px;border-radius:50%;background:#fff;float:left;color:#009688}
.inside .inword{width:80px;height:65px;float:left;line-height:65px;text-indent:10px;font-size:16px;color:#fff}
.inwp{width:1000px;margin:0 auto}
.inout1 a{float:left;border:1px solid #C9C9C9;background-color:#fff;color:#555;padding:8px 18px;border-radius:2px;margin-right:10px;margin-top:20px}
.inout2 a{float:left;color:#fff;padding:9px 18px;background:#009688;border-radius:2px;margin-top:20px}
.inout1 a:hover{color:#555;opacity:.8;filter:alpha(opacity=80)}
.inout2 a:hover{color:#fff;opacity:.8;filter:alpha(opacity=80)}
.inout2 input{float:left;color:#fff;padding:9px 18px;background:#009688;border-radius:2px;margin-top:20px;border:none}
.inout2 input:hover{color:#fff;opacity:.8;filter:alpha(opacity=80)}
.inside2 h2{font-size:20px;margin:20px 0}
.inside2 h3{font-size:16px;margin:20px 0 10px 0;color:#FF5722}
.inside2 p{font-size:14px;line-height:28px;margin-bottom:10px}
.inside2 tr{border:1px solid #EAEAEA}
.inside2 tr th{border-left:1px solid #EAEAEA;background:#F9F9F9;line-height:45px}
.inside2 tr td{border-left:1px solid #EAEAEA;line-height:40px;padding-left:20px}

View File

@ -3,7 +3,7 @@
'name' => 'taoser/taoler',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'ceb164391c3d212f1460cfbcbb7f4d7ad66f8ce9',
'reference' => '0c44db5a5d56d4f62656d0fdad68f82c27235469',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -367,7 +367,7 @@
'taoser/taoler' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => 'ceb164391c3d212f1460cfbcbb7f4d7ad66f8ce9',
'reference' => '0c44db5a5d56d4f62656d0fdad68f82c27235469',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

2
vendor/services.php vendored
View File

@ -1,5 +1,5 @@
<?php
// This file is automatically generated at:2022-10-09 21:18:22
// This file is automatically generated at:2022-10-10 16:42:53
declare (strict_types = 1);
return array (
0 => 'taoser\\addons\\Service',

View File

@ -10,7 +10,7 @@
</ul>
<div class="copyright">
<span class="layui-hide"> v{:config('taoler.version')}</span> {$sysInfo.showlist|raw}
<p>Copyright © {:date('Y')} {$sysInfo.copyright|raw} <a href="https://www.aieok.com" target="blank" title="TaoLerCMS" class="layui-hide-xs">TaoLerCMS驱动</a>
<p>Copyright © {:date('Y')} {$sysInfo.copyright|raw} <a href="https://www.aieok.com" target="blank" title="TaoLerCMS" class="layui-hide">TaoLerCMS</a>
<a href="https://beian.miit.gov.cn/" target="blank">{$sysInfo.icp}</a>
</p>
</div>
@ -21,13 +21,13 @@
<div class="footer-sns">
<a class="sns-wx" href="javascript:;" aria-label="icon">
<i class="layui-icon layui-icon-login-wechat sns-icon"></i>
<span style="background-image:url(https://www.aieok.com/static/home/img/wx.png);"></span>
<span style="background-image:url({:hook('qqKefu','wxqr')});"></span>
</a>
<a class="sns-wx" href="javascript:;" aria-label="icon">
<i class="layui-icon layui-icon-chat sns-icon"></i>
<span style="background-image:url(https://www.aieok.com/static/home/img/qq.png);"></span>
<span style="background-image:url({:hook('qqKefu','qqqr')});"></span>
</a>
<a href="{$Request.domain}" target="_blank" rel="nofollow noopener" aria-label="icon">
<a href="{:hook('qqKefu','qq')}" target="_blank" rel="nofollow noopener" aria-label="icon" title="点击跟我聊天">
<i class="layui-icon layui-icon-login-qq sns-icon"></i>
</a>
</div>