系统升级需要校验本地的文件是否被修改过,系统默认每次检验1千个文件,一般来说需要分四到五页来处理,如下图所示。
![](https://img.kancloud.cn/28/1c/281cf01028c03ab48c4257d1831e6969_779x573.png)
如果你的服务器性能太差的话,就需要手工把数值调小。把下面的代码复制出来。进入后台数据库管理工具那里执行一下,导入数据库。然后就可以在后台核心设置那里修改数值
~~~
INSERT INTO `qb_config` (`id`, `type`, `title`, `c_key`, `c_value`, `form_type`, `options`, `ifsys`, `htmlcode`, `c_descrip`, `list`, `sys_id`) VALUES(0, 1, '系统升级每次核对文件数', 'sys_update_filenum', '10', 'number', '', 1, '', '留空则默认是1000,如果你的空间性能太差,就手工调为50甚至10', 0, 0);
~~~
导入数据库后,需要在下面那里做设置,如下图
![](https://img.kancloud.cn/72/04/7204fc2c177616ab79bcea12de95ac12_1287x315.png)
把数值相应调小,测试看看能否正常升级。
复制下面的代码修改两个文件后,将会实现如下图的效果.
![](https://img.kancloud.cn/7b/60/7b609728423159f721564bf8ae116d6c_1171x758.gif)
要实现分页检验文件的话,需要修改两个文件.
> 复制下面的代码替换`\application\admin\controller\Upgrade.php`中的内容
~~~
<?php
namespace app\admin\controller;
use app\common\controller\AdminBase;
use app\common\model\Module;
use app\common\model\Plugin;
use app\common\model\Hook_plugin;
use app\common\model\Market as MarketModel;
use app\common\model\Timedtask AS TaskModel;
class Upgrade extends AdminBase
{
public function _initialize(){
parent::_initialize();
if(config('client_upgrade_edition')==''){
config('client_upgrade_edition',RUNTIME_PATH . '/client_upgrade_edition.php');
}
}
public function index()
{
$this->clean_cache();
$array = @include(config('client_upgrade_edition'));
$this->assign('upgrade',$array);
return $this->fetch('index');
}
/**
* 清除相关缓存
*/
protected function clean_cache(){
cache('timed_task',null);
cache('cache_modules_config',null);
cache('cache_plugins_config',null);
cache('hook_plugins',null);
}
/**
* 更新升级日志
* @param string $upgrade_edition
* @return boolean|string
*/
private function writelog($upgrade_edition=''){
$data = $this->request->post();
if($data['m']){
$array = modules_config();
foreach ($array AS $rs){
$de = $data['m'][$rs['keywords']];
if($de){
$vs = $de['time']."\t".$de['md5'];
Module::update(['id'=>$rs['id'],'version'=>$vs]);
}
}
}
if($data['p']){
$array = plugins_config();
foreach ($array AS $rs){
$de = $data['p'][$rs['keywords']];
if($de){
$vs = $de['time']."\t".$de['md5'];
Plugin::update(['id'=>$rs['id'],'version'=>$vs]);
}
}
}
if($data['h']){
$array = cache('hook_plugins');
foreach ($array AS $rs){
$de = $data['h'][$rs['version_id']];
if($de){
$vs = $de['time']."\t".$de['md5'];
Hook_plugin::update(['id'=>$rs['id'],'version'=>$vs]);
}
}
}
if($data['t']){
$array = cache('timed_task');
foreach ($array AS $rs){
$de = $data['t'][$rs['version_id']];
if($de){
$vs = $de['time']."\t".$de['md5'];
TaskModel::update(['id'=>$rs['id'],'version'=>$vs]);
}
}
}
$this->upgrade_mark($data['admin_style'],'admin_style');
$this->upgrade_mark($data['index_style'],'index_style');
$this->upgrade_mark($data['member_style'],'member_style');
$this->upgrade_mark($data['qun_style'],'qun_style');
$this->upgrade_mark($data['haibao_style'],'haibao_style');
$this->upgrade_mark($data['model_style'],'model_style');
$this->upgrade_mark($data['packet'],'packet');
$this->clean_cache();
if( file_put_contents(config('client_upgrade_edition'), '<?php return ["md5"=>"'.$upgrade_edition.'","time"=>"'.date('Y-m-d H:i').'",];') ){
return true;
}else{
return '权限不足,日志写入失败';
}
}
/**
* 应用市场,比如风格更新升级日志
* @param array $data
* @param string $type 比如admin_style index_style member_style
*/
private function upgrade_mark($data=[],$type=''){
if($data){
$array = MarketModel::get_list(['type'=>$type]);
foreach ($array AS $rs){
$de = $data[$rs['version_id']];
if($de){
$vs = $de['time']."\t".$de['md5'];
MarketModel::update(['id'=>$rs['id'],'version'=>$vs]);
}
}
}
}
/**
* 更新前,先备份一下文件
* @param string $filename
*/
private function bakfile($filename=''){
$bakpath = RUNTIME_PATH.'bakfile/';
if(!is_dir($bakpath)){
mkdir($bakpath);
}
$new_name = $bakpath.date('Y_m_d-H_i--').str_replace(['/','\\'], '--', $filename);
copy(ROOT_PATH.$filename,$new_name);
}
/**
* 升级数据库
* @param string $filename
*/
private function up_sql($filename=''){
if(preg_match('/\/upgrade\/([\w]+)\.sql$/', $filename)){
//if(preg_match('/^\/application\/common\/upgrade\/([\w]+)\.sql/', $filename)){
into_sql(ROOT_PATH.$filename,true,0);
}
}
/**
* 执行更多复杂的逻辑性的升级
* @param string $filename
*/
private function up_run($filename=''){
if(preg_match('/^\/application\/common\/upgrade\/([\w]+)\.php$/', $filename)){
$classname = "app\\common\\upgrade\\".ucfirst(substr(basename($filename), 0,-4));
}elseif( preg_match('/(application|plugins)\/([\w]+)\/upgrade\/([\w]+)\.php$/',$filename,$array) ){ //实际已包含了上面的
$m_p = $array[1]=='application'?'app':'plugins';
$model = $array[2];
$file = $array[3];
$classname = "$m_p\\$model\\upgrade\\".ucfirst($file);
}else{
return;
}
if( class_exists($classname) && method_exists($classname, 'up') ){
$obj = new $classname;
try {
$obj->up();
} catch(\Exception $e) {
//echo $e;
}
}
}
/**
* 正式执行开始升级,一个一个的文件升级替换
*/
public function sysup($filename='',$upgrade_edition=''){
if($upgrade_edition){ //升级完毕,写入升级信息日志
$result = $this->writelog($upgrade_edition);
if( $result===true ){
return $this->ok_js([],'升级成功');
}else{
return $this->err_js($result);
}
}
list($filename,$id) = explode(',',$filename);
if($filename==''){
return $this->err_js('文件不存在!');
}
$str = $this->get_server_file($filename,$id);
if($str){
$filename = $this->format_filename($filename); //针对模块或插件的升级做替换处理
$this->bakfile($filename);
makepath(dirname(ROOT_PATH.$filename)); //检查并生成目录
if( file_put_contents(ROOT_PATH.$filename, $str) ){
$this->up_sql($filename);
$this->up_run($filename);
return $this->ok_js([],'文件升级成功');
}else{
return $this->err_js('目录权限不足,文件写入失败');
}
}else{
return $this->err_js('获取云端数据失败,请确认服务器DNS是否正常,能否访问外网?');
}
}
/**
* 升级前,可以查看任何一个文件的源代码
* @param string $filename
*/
public function view_file($filename='',$id=0,$oldfile=''){
$str = $this->get_server_file($filename,$id);
if ( preg_match("/(\.jpg|\.png|\.jpeg|\.gif)$/i", $filename) ) {
//header('Content-type:image/'.substr($filename,strripos($filename,'.')+1));echo $str;
if (is_file(ROOT_PATH.$oldfile)) {
echo "<img style='max-width:200px;' src='".request()->domain().'/'.$oldfile."'><br>";
}
$temp_file = "uploads/images/temp.".substr($filename,strripos($filename,'.')+1);
file_put_contents(PUBLIC_PATH.$temp_file, $str);
echo "<br><br><img style='max-width:200px;' src='".tempdir($temp_file)."?".time()."'>";
exit;
}
$this->assign('new_code',str_replace(['<','>'], ['<','>'], $str));
$this->assign('old_code', str_replace(['<','>'], ['<','>'], file_get_contents(str_replace('//', '/', ROOT_PATH.$oldfile)) ) );
return $this->fetch();
}
/**
* 针对要升级的模块与插件的文件名特别处理, 替换后,// 双斜杠开头的文件就是插件或模块升级的文件
* @param string $filename
* @return string|mixed
*/
protected function format_filename($filename=''){
if(strstr($filename,'/../../')){
$filename = str_replace(['/../../template/','/../../plugin/','/../../hook/'], '/../../', $filename);
$filename = preg_replace('/^\/..\/..\/([\w]+)/','/',$filename);
}
return $filename;
}
/**
* 核对需要升级文件,展示出来给用户挑选哪些不想升级
* 这里的升级文件列表,即有系统的,也有频道插件与风格的
* @param string $upgrade_edition
* @param string $page 分页检验需要升级的文件.一次处理的话,有的服务器可能吃不消
* @return string|mixed
*/
public function check_files($upgrade_edition='',$page=0,$rows=1000){
if ($this->webdb['sys_update_filenum']>0) {
$rows = $this->webdb['sys_update_filenum'];
}
set_time_limit(0); //防止超时
$array = $this->getfile($page);
if(empty($array)){
$str = http_curl("https://x1.php168.com/appstore/upgrade/get_version.html?id=46");
if (!strstr($str,'md5')) {
return $this->err_js('你的服务器无法访问齐博官网,请检查你的服务器DNS是否配置正确,或者是否设置了防火墙不能访问外网');
}
return $this->err_js('获取云端文件列表数据失败,请晚点再偿试');
}
$totalpage = ceil(count($array)/$rows);
if (!$page) {
set_cookie('need_update',0);
return $this->ok_js($totalpage);
}
$data = [];
$min = ($page-1)*$rows;
for($i=$min;$i<$min+$rows;$i++){
$rs = $array[$i];
if (!$rs) {
break;
}
// }
// foreach($array AS $rs){
$showfile = $this->format_filename($rs['file']);
$file = ROOT_PATH.$showfile;
if (is_file($file.'.lock') && file_get_contents($file.'.lock')=='hide') {
continue; //用户不想升级的文件,也不想提示升级
}
$ispic = false;
$change = false;
$md5_size = '';
if (!is_file($file)) {
$change = true;
}elseif( ($md5_size=md5_file($file)) != $rs['md5'] ){
$change = true;
if ( preg_match("/(\.jpg|\.png|\.jpeg|\.gif)$/i", $file) ) {
$ispic = true;
}elseif ( check_bom($file,true) ) {
file_put_contents($file, check_bom($file));
if (md5_file($file)==$rs['md5']) {
$change = false;
}//elseif(preg_match("/(\/|\\\)upgrade(\/|\\\)([\w]+)(\.sql|\.php)$/i", $file)){
//$change = false;
//}
}
}
if($change){
$data[]=[
'file'=>$rs['file'],
'showfile'=>$showfile,
'md5'=>$md5_size,
'id'=>$rs['id'],
'islock'=>(is_file($file.'.lock')||(is_file($file)&&preg_match("/(\/|\\\)upgrade(\/|\\\)([\w]+)(\.sql|\.php)$/i", $file)))?1:0,
'ctime'=>is_file($file)?date('Y-m-d H:i',filemtime($file)):'缺失的文件',
'time'=>date('Y-m-d H:i',$rs['time']),
];
}
}
$array_sql = $array_php = [];
foreach ($data AS $key=>$rs){
if( preg_match("/\/upgrade\/([\w]+\.sql)/i",$rs['file']) ){
unset($data[$key]);
$array_sql[$rs['file']] = $rs;
}elseif( preg_match("/\/upgrade\/([\w]+\.php)/i",$rs['file']) ){
unset($data[$key]);
$array_php[$rs['file']] = $rs;
}
}
ksort($array_php);
ksort($array_sql);
$data = array_values(array_merge($data,$array_sql,$array_php));
$need_update = get_cookie('need_update')+count($data);
set_cookie('need_update',$need_update);
if ($page==$totalpage) {
unlink(RUNTIME_PATH.'updatelist.txt');
}
if($page==$totalpage && $need_update<1){
$upgrade_edition && $reustl = $this->writelog($upgrade_edition);
return $this->err_js($reustl!==true?$reustl:'没有可更新文件');
}else{
return $this->ok_js($data?:[]);
}
}
/**
* 获取云端的某个最新文件
* @param string $filename 升级的文件名
* @param number $id 对应云端的插件ID
* @return string|mixed
*/
protected function get_server_file($filename='',$id=0){
@set_time_limit(600); //防止超时
$str = http_curl('https://x1.php168.com/appstore/upgrade/make_client_file.html?filename='.$filename.'&id='.$id.'&appkey='.urlencode($this->webdb['mymd5']).'&domain='.urlencode($this->request->domain()));
if(substr($str,0,2)=='QB'){ //文件核对,防止网络故障,抓取一些出错信息
$str = substr($str,2);
}else{
$str='';
}
return $str;
}
/**
* 获取云端的最新文件列表
* @return string|mixed
*/
protected function getfile($page=0){
if (!$page) {
$str = http_curl('https://x1.php168.com/appstore/upgrade/get_list_file.html?typeid='.$this->webdb['typeid'].'&appkey='.urlencode($this->webdb['mymd5']).'&domain='.urlencode($this->request->domain()),['app_edition'=>fun('upgrade@local_edition')]);
file_put_contents(RUNTIME_PATH.'updatelist.txt', $str);
}else{
$str = file_get_contents(RUNTIME_PATH.'updatelist.txt');
}
return $str ? json_decode($str,true) : '';
}
}
?>
~~~
> 复制下面的代码替换`\template\admin_style\default\admin\upgrade\index.htm`中的内容
~~~
{extend name="index:layout" /}
{block name="menu"}{/block}
{block name="content"}
<link rel="stylesheet" href="/public/static/layui/css/layui.css" media="all">
<script src="__STATIC__/js/core/vue.js"></script>
<script type="text/javascript">
<!--
if (navigator.userAgent.indexOf("MSIE") >= 0) {
alert("请使用谷歌或火狐访问.其它浏览器无法操作与使用");
}
//-->
</script>
<style type="text/css">
.locktr td,.locktr td a{
color:orange;
}
.progress_warp{
position:fixed;
top:65%;
z-index:9999999999;
width:100%;
display:none;
}
.progress_warp .layui-progress{
margin:0 200px;
}
</style>
<form name="formlist" method="post" action="" class="up_files">
<div class="MainContainers">
<div class="Header"><span class="tag">在线升级</span><span class="more">>></span></div>
<div class="Conter">
<table class="ListTable" id="upgradeTR">
<tr>
<th width='8%'>选中升级</th>
<th>文件名称</th>
<th width='17%'>升级前时间</th>
<th width='21%'>更新时间</th>
<th width='19%'>对比差异</th>
</tr>
<tr id="contents">
<td colspan=5 height=30 style="background:#eee;">
<div align="center" style="color:red;" class="upgrade_msg">正在获取云端数据信息,请稍候...</div>
</td>
</tr>
<tr v-for="rs in listdb" :class="rs.islock?'locktr':''">
<td class="b red">
<input v-if="rs.islock==1||rs.md5!=''" :data-islock="rs.islock" :data-showfile="rs.showfile" :data-md5="rs.md5" type="checkbox" name="filedb[]" :value="rs.file+','+rs.id" onclick="if($(this).is(':checked'))layer.alert('你修改过当前文件,你确认要升级覆盖现有的文件吗?')" />
<input v-else type="checkbox" name="filedb[]" :value="rs.file+','+rs.id" checked /> {{rs.i}}
</td>
<td class="Left listfile" :data-id="rs.id">{{rs.showfile}}</td>
<td>
<div align="center">{{rs.ctime}}</div>
</td>
<td>{{rs.time}}</td>
<td><a :href="'{:urls('view_file')}?filename='+rs.file+'&oldfile='+rs.showfile+'&id='+rs.id" target="_blank">对比差异</a>
</td>
</tr>
<tr bgcolor='#FFFFFF' align="center" class="up_btn" style="display:none;">
<td colspan='5'>
<div class='submits'>
<!--<input type='button' onclick="CheckAll(this.form)" name='Submit' value='全选'>-->
<input type='button' style="background:red;" onclick="sys_upgrade();" name='Submit' value='立刻升级'>
</div>
</td>
</tr>
</table>
</div>
</div>
</form>
<div class="MainContainers">
<div class="Header"><span class="tag">升级说明</span></div>
<div class="Conter">
<ul class="notes">
<li>1、你可以选择哪些文件不升级,不过你最好是在程序目录,把不想升级的文件,做个标志,比如“index.htm”不想升级,就在对应的目录创建一个文件“index.htm.lock”,这样每次升级,文件就处于非选中状态,而不会升级。</li>
<li>2、如果网络故障,一次升级不成功,可反复升级</li>
<li>3、如果因为升级文件被替换了,请进目录/runtime/bakfile/找回来</li>
<li>4、系统默认每次校验文件数是1千个,如果你的空间性能太差的话,<a href="https://www.kancloud.cn/php168/x1_of_qibo/2059526" target="_blank">请点击查看教程进行设置</a></li>
</ul>
</div>
</div>
<div class="progress_warp">
<div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="progressId">
<div class="layui-progress-bar" lay-percent="1%"></div>
</div>
</div>
<script src="__STATIC__/layui/layui.js"></script>
<script type="text/javascript">
var element;
$(function(){
layui.use('element', function(){
element = layui.element;
})
//element.progress('progressId', i+'%');
})
</script>
<script language=JavaScript>
var upgrade_edition = '';
var upgrade_data = {};
//检查版本更新
function check_upgrade(){
var now_edition = "{$upgrade.md5}";
$.post("https://x1.php168.com/appstore/upgrade/get_edition.html?typeid={$webdb.typeid}&"+Math.random(),{
app_edition:"{:fun('upgrade@local_edition')}",
sys_edition:now_edition,
domin:'{:request()->domain()}',
appkey:'{$webdb.mymd5}'
}).success( function(res){
if(res.code==0){
upgrade_data = res.data;
if(res.data.md5!=now_edition||typeof(res.data.upgrade_msg) != "undefined"){
if(typeof(res.data.time) == "undefined"){
return ;
}
upgrade_edition = res.data.md5;
var msg = typeof(res.data.upgrade_msg) != "undefined" ? res.data.upgrade_msg : '你的系统需要升级<br>云端更新日期:'+res.data.time;
$(".upgrade_msg").html(msg);
layer.confirm(msg, {
btn : [ '查看需要升级的文件', '晚点再升级' ]
}, function(index) {
down_file_list();
});
}else{
$(".upgrade_msg").html('已经是最新了,无须升级');
}
}else{
layer.alert(res.msg,{time:5500});
}
}).fail(function (res) {
//layer.alert('网络故障,请晚点再偿试升级!!');
//layer.closeAll();
layer.open({title: '网络故障,请晚点再偿试升级!!',area:['90%','90%'],content: res.responseText});
});
}
check_upgrade();
var app_ids = {};
var vues = new Vue({
el: '#upgradeTR',
data: {
listdb: [],
},
watch:{
listdb: function() {
this.$nextTick(function(){ //数据渲染完毕才执行
var time = 100;
$("input[data-islock=0]:not(:checked)").each(function(){
time += 200;
var that = $(this);
var url = "https://x1.php168.com/appstore/upgrade/check_md5.html?path="+that.attr('data-showfile')+"&md5="+that.attr('data-md5');
setTimeout(function(){
$.get(url,function(res){
if(res.code==0){
that.attr('checked',true);
}
});
},time);
});
var times = 500;
$(".listfile").each(function(){
var that = $(this);
if(that.attr("data-id")){
var id = that.attr("data-id");
if(app_ids[id]==undefined){
app_ids[id] = {};
times += 500;
setTimeout(function(){
$.get("https://x1.php168.com/appstore/wxapp.show/index.html?id="+id,function(res){
if(res.code==0){
//app_ids[id] = res.data;
$(".listfile[data-id="+id+"]").append(" <a href='https://x1.php168.com/appstore/content/show/id/"+id+".html' target='_blank'>"+res.data.title+"</a>");
}
});
},times);
}
}
});
$(".up_btn").show();
layer.alert('需要升级的文件列表如下,你可以有选择性的升级');
});
}
},
methods: {
add_data:function(array){
$("#contents").remove();
array.forEach((rs,i)=>{
rs.i = i+1;
this.listdb.push(rs);
});
}
}
});
var need_update_file = [];
function check_need_update(totalpage,page){
if(page==1)layer.load(1,{shade: [0.7, '#393D49']}, {shadeClose: true}); //0代表加载的风格,支持0-2
layer.msg('正在核对需要升级的文件, <b style="color:red;">'+page+'</b> / '+totalpage+' 页,<br>需要一点时间,请耐心等候!',{icon:1,time:30000, shift: 1});
$.post("{:urls('check_files')}?upgrade_edition="+upgrade_edition+"&page="+page,upgrade_data,function(res){
if(res.code==0){
res.data.forEach((rs)=>{
need_update_file.push(rs);
});
if(page<totalpage){
page++;
check_need_update(totalpage,page);
}else{
layer.closeAll();
vues.add_data(need_update_file);
}
}else{
layer.alert(res.msg);
}
});
}
//下载文件列表,核对需要哪些更新
function down_file_list(){
layer.alert('正在从云端下载升级文件列表,请稍候!');
var index = layer.load(1,{shade: [0.7, '#393D49']}, {shadeClose: true}); //0代表加载的风格,支持0-2
$.post("{:urls('check_files')}?upgrade_edition="+upgrade_edition,upgrade_data).success(function(res){
layer.closeAll();
if(res.code==0){
//vues.add_data(res.data);
check_need_update(res.data,1);
/*
var str = '';
res.data.forEach(function(rs){
var ck = rs.islock?" onclick='layer.alert(\"当前文件已锁定,你确认要升级吗?\")' ":' checked ';
var style = rs.islock?" class='locktr' ":' ';
str +='<tr '+style+'>'+
'<td class="b red"> <input type="checkbox" name="filedb[]" value="'+rs.file+','+rs.id+'" '+ck+'></td>'+
'<td class="Left">'+rs.showfile+'</td>'+
'<td><div align="center">'+rs.ctime+'</div></td>'+
'<td>'+rs.time+'</td>'+
'<td><a href="{:urls("view_file")}?filename='+rs.file+'&id='+rs.id+'" target="_blank">查看</a></td>'+
'</tr>';
});
document.getElementById('contents').outerHTML=str;
*/
}else{
layer.alert(res.msg,{time:5500});
}
}).fail(function (res) {
layer.closeAll();
//layer.alert('通信失败,可能你的后台权限不足'); )
var parsedJson = $.parseJSON(res.responseText.substr(res.responseText.indexOf('{'))); //用户程序中有UTF8 +BOM文件导致的
if( typeof(parsedJson) == 'object' && parsedJson.code==0){
//vues.add_data(parsedJson.data);
check_need_update(res.data,1);
/*
var str = '';
parsedJson.data.forEach(function(rs){
var ck = rs.islock?" onclick='layer.alert(\"当前文件已锁定,你确认要升级吗?\")' ":' checked ';
var style = rs.islock?" class='locktr' ":' ';
str +='<tr '+style+'>'+
'<td class="b red"> <input type="checkbox" name="filedb[]" value="'+rs.file+','+rs.id+'" '+ck+'></td>'+
'<td class="Left">'+rs.showfile+'</td>'+
'<td><div align="center">'+rs.ctime+'</div></td>'+
'<td>'+rs.time+'</td>'+
'<td><a href="{:urls("view_file")}?filename='+rs.file+'&id='+rs.id+'" target="_blank">查看</a></td>'+
'</tr>';
});
document.getElementById('contents').outerHTML=str;
*/
//$(".up_btn").show();
//layer.alert('需要升级的文件列表如下,你可以有选择性的升级<br>特别提醒:你的系统中有错误的UTF8 +BOM 代码文件,一般情况是新装的风格导致的,请仔细排查!');
return ;
}else if( typeof(parsedJson) == 'object' && parsedJson.code==1){
layer.alert(parsedJson.msg+"<br><br>特别提醒:你的系统中有错误的UTF8 +BOM 代码文件,一般情况是新装的风格导致的,请仔细排查!",{time:5500});
return ;
}
layer.confirm('通信失败,你是否要新开窗口查看一下详情?'+JSON.stringify(res), {
btn : [ '查看详情', '取消' ]
}, function(index) {
window.open("{:urls('check_files')}?upgrade_edition="+upgrade_edition);
});
});
}
//开始升级文件
function sys_upgrade(){
$(".up_files input[type='checkbox']").each(function(i){
if($(this).is(':checked')==true){
ckfile_num++;
}
});
layer.alert('正在升级文件,请耐心稍候...');
var index = layer.load(1,{shade: [0.7, '#393D49']}, {shadeClose: true}); //0代表加载的风格,支持0-2
$(".progress_warp").show();
var time = 0;
$(".up_files input[type='checkbox']").each(function(i){
if($(this).is(':checked')==true){
var file_name = $(this).val();
var obj = $(this).parent().next();
if( file_name.indexOf('/upgrade/')>0 ){
time += 3000;
}else{
time += 500;
}
setTimeout(function(){
upgrade_file(file_name,obj);
},time);
}
});
}
//全部升级完毕
function end_up(){
layer.msg('全部文件升级成功');
$.post("{:urls('sysup')}?upgrade_edition="+upgrade_edition,upgrade_data).success(function(res){
if(res.code==0){
layer.alert('本次升级完毕,'+ok_num+'个文件升级成功!');
}else{
layer.alert('升级信息写入失败');
}
}).fail(function (res) {
layer.open({title: '网络故障,请晚点再偿试升级!!',area:['90%','90%'],content: res.responseText});
});
}
var ckfile_num = 0; //选中的升级文件个数
var ok_num = 0; //成功升级文件个数
//一个一个的文件升级
function upgrade_file(filename,obj){
$.post("{:urls('sysup')}?filename="+filename,upgrade_data).success(function(res){
if(res.code==0){
//layer.msg('文件:'+filename+' 升级成功');
var str = obj.html()+' <font color="red">升级成功</font>';
obj.html(str);
ok_num++;
if(ok_num==ckfile_num){ //全部升级完毕
layer.closeAll();
end_up();
$(".progress_warp").hide();
}
element.progress('progressId', parseInt(ok_num*100/ckfile_num)+'%'); //升级进度
}else{
//layer.msg('文件:'+filename+' 升级失败:'+ res.msg,{time:2500});
var str = obj.html()+' <font color="blue">升级失败:'+res.msg+'</font>';
obj.html(str);
}
}).fail(function (res) {
//layer.alert('通信失败,可能你的后台权限不足');
layer.open({title: '网络故障,请晚点再偿试升级!!',area:['90%','90%'],content: res.responseText});
});
}
function CheckAll(form){
for (var i=0;i<form.elements.length;i++){
var e = form.elements[i];
e.checked == true ? e.checked = false : e.checked = true;
}
}
</script>
{/block}
~~~
- 新手快速入门教程
- AI智能积分体系的开发
- 二次开发教程
- mysql数据表简介
- CMS文章与论坛的数据表简介视频教程
- 钩子模块插件数据表讲解
- 数据表参数设置讲解
- 数据表后台的所有参数设置
- 表单自动生成器
- 表单器新增与修改
- 不同的选项联动触发不同的表单项
- 万能字段自定义字段的特别讲解
- 如何给二维多维数组定义描述
- 商城判断是否购买过
- 在线支付接口的使用
- 支付视频教程
- 程序中快速激活当前页面在线支付付款充值
- JS网页快速接入支付功能
- 模块后期要加参数的方法
- 自定义字段下拉菜单关联其它数据表
- 自定义字段表单默认调用会员资料
- 频道插件如何对接圈子
- 频道的二次开发入门讲解
- 模块安装文件讲解
- 表单快速启用城市地区功能
- 前台后台地址跳转的处理
- 会员中心菜单权限显示
- 动态改变标签调用不同频道的数据
- 自定义字段关联其它字段的隐藏显示
- 齐博首创钩子的使用方法
- 模型里边钩子的创建与使用
- 钩子自动添加频道参数变量
- 如何增加会员中心及后台菜单
- 暴力吸粉,强制关注公众号,再引导进入相关页面
- 如何发布方案
- 发布方案几个要点注意事项
- 表单字段如何获取当前地址
- 快速增加下拉菜单
- 系统与频道插件的参数配置讲解
- 下订单与付款后的信息通知开关
- 查询某个时间段内的数据
- 二开小技巧
- 如何自动增加模块参数
- 新增内容想关闭窗口或者继续提交相关数据
- 耗时的功能异步启用子进程
- 增强版缓存cache2
- php操作redis的常用方法
- 后台自定义搜索
- 如何给会员中心菜单及后台菜单传更多的参数
- 如何让class类标签增加更多的设置选项
- 程序中如何激活当前页面在线充值
- 表单只显示部分字段
- 群聊模块二次开发
- JS及框架接口的说明
- 几个重要的方法函数
- JS文件共有4个关键类
- 内容重新渲染,使聊天内容更炫
- 如何使用定时群发消息
- 自定义字段下拉框选择数据表字段
- 表单相关视频
- 表单入门视频
- 如何调用上传文件的接口
- 如何新增加系统表单字段输入选项
- 如何创建各种类型的填写表单
- 在模板中快速添加下拉菜单
- 在程序中快速添加下拉菜单
- 圈主自定义用户组的处理
- 模块插件安装程序制作的视频教程
- 模块插件安装程序制作的图文教程
- 钩子BUG冲突部分钩子不生效
- 如何重定义改写自动表单中的某个字段
- 列表项菜单自定义匿名函数
- 如何新增自定义字段
- 如何添加滑动验证码
- 登录页及注册页增加滑动验证码
- 增加系统参数的几种方法
- 如何定义微信模板消息
- 风格模板教程
- 栏目名称调用详解
- where实现条件筛选与数据关联
- 调用多个圈子同时调用贴子
- 调用多个圈子同时调用相关会员
- 内页调用本栏目其它内容
- 万能数据统计之fun函数
- 背景图如何设置标签
- 圈子黄页风格制作说明
- 同一个标签要更换不同模块的数据
- 标签如何调用论坛内容
- 标签设置取组图不存在就取内容中的图片
- 用异步加载,可加快网页打开速度
- 显示购物车数量与商品
- 登录提醒判断处理
- 如何使用不同的头部风格
- 辅栏目字段跨频道调用
- 给频道内容生成不同的海报
- 如何调用论坛内容里的图片
- 父栏目的调用判断
- 根据用户uid调用圈子信息
- 循环列出某个子分类同时调取对应分类下的内容
- 底部头部菜单如何设置高亮
- 滑动门+下滑加载更多
- 圈子切换按钮调用不同频道的数据
- 如何调用显示地区
- 内容太多如何分屏显示
- 向上滚动特效
- 调用栏目分类的字段
- 如何调用系统自定义字段
- 开发者如何展示某套风格
- 如何调用评论
- 如何进入某人的圈子
- 包含碎版模板include的用法
- 圈子风格制作讲解
- 圈子频道风格的目录讲解
- 圈子频道程序的目录讲解
- 圈子完整一套风格目录
- 圈子风格实现独立的头尾全局布局风格
- 专题标签调用详解
- 频道内容页圈子专属模板说明
- 如何列出所有万能表单
- 添加标签注意事项
- 制作幻灯片标签教程
- 万能数据统计调用方法
- 重新定义微信分享的标题图片及链接
- 网站当天当月积分余额消费收入统计
- 如何生成二维码
- 如何查询某个时间段内的数据
- 如何弹出客服会话窗口
- 在当前文章内页调出所有辅栏目的名称
- 导航菜单高亮设置
- 标签调取关注我的粉丝
- 调用当前页面的小程序码与普通二维码
- 使用缩略图功能加快列表页打开速度
- 如何调用视频播放器
- 另一种单页,创建模板就能实现单页
- 标签中如何获取编辑器里的视频地址
- 自动添加自定义模板字段的方法
- 自定义模板字段的添加规则
- 把内容评论改造成即时聊天
- 任何页面加入即时聊天功能
- 标签如何动态调用不同频道的数据
- qb:tag万能标签的使用
- 如何统计用户不同时间段的收益支出
- 小程序关注公众号的方法
- 引用布局模板注意事项
- 如何对自定义字段做特殊显示处理
- 如何在内容页或列表页及主页调用关联的圈子信息
- 风格模块碎片教程
- 风格模块碎片是什么?
- 模块碎片入门
- qb:tag与qb:hy的主要区别
- 公共碎片模板与私有碎片模板
- 碎片子模板高级配置
- 自定义表单参数对照表
- 碎片模板高级技巧
- 碎片模板注意事项
- 风格碎片视频教程
- 第一集,入门基础篇
- 第二集,进阶篇
- 第三集,巩固篇
- 第四集,实战篇,万能数据统计碎片
- 第五集,碎片深入开发
- 第六集,涉及表单碎片的制作开发
- 开发及上架公共碎片注意事项
- 碎片如何获取主模板的变量值
- 标签设置中的个性模板配置
- 站内引用主题使用公共碎片的方法
- 碎片如何增加展示选择预览图片
- 飘浮碎片如何定位标签层
- 标签碎片中如何做复杂的数据DEMO演示
- 飘浮的标签元素如何添加占位符
- 标签变量如何传到外面使用
- 标签中如何实现条件筛选过滤查询
- 标签或碎片的一些注意事项
- 碎片模板文件后缀名设置为php可防盗
- 模板代码如何混淆加密
- 常用文件目录说明
- 风格目录文件说明
- 模板文件调用的优先级
- 新风格要注意问题
- 几个关键模板文件要熟知
- 安装云市场应用注意事项
- 标签快速入门
- 标签进阶之幻灯片制作
- 标签之无刷新显示更多
- 异步加载标签数据
- 做风格常用的变量名
- 标签动态调用数据
- 文本代码标签的使用
- 多张组图的标签调用
- 一张图片展示X1目录结构简介
- 如何强制进后台
- 单张图片标签的使用
- 后台网站参数配置修改与添加
- 简单的模块制作说明(随风编写)
- 钩子简单制作-tag加连接解说版(随风编写)
- 模板中常用的TP标签数据处理
- 做模板组图单图无图混排的处理
- 列表页制作及无滚动加载内容
- 如何对接公众号
- 微信支付授权目录详细讲解
- 公众号发送关键字没反应的原因
- 公众号模板消息字段名的设置
- 对接小程序设置
- 商家圈子小程序的配置
- IIS服务器注意事项
- 会员中心如何加标签
- 再强调严禁用记事本改任何文件
- 支付宝对接收款配置
- 标签的嵌套用法,调用聚合数据
- 阿里云短信配置
- 内容评论的风格制作
- 二次开发的灵魂fun函数
- 自定义字段多文件多图的显示处理
- 内容中下一页上一页的标签
- 标签动态变量查询
- 相关栏目名称的调用
- 辅栏目(专题)的使用说明
- 换服务器如何转移网站
- block模板的分块替换
- 模板包含文件
- 后台打不开,空间不支持pathinfo的解决方法
- X1微信小程序的介绍
- 隐藏index.php的方法
- 新做风格路径注意事项
- 添加公众号模板消息
- 公众号菜单跳转到小程序
- 重复安装应用导致重复执行的问题
- 如何配置定时任务
- 万能通用短信接口的配置
- 小技巧
- 重新定义主题的星级名称
- 如何增加VIP价格
- 如何恢复后台超管权限
- 频道二级域名的配置方法
- (频道菜单)用户组设置TAG标志的作用
- 如何给内容页自定义个性模板
- 如何显示新消息数目
- 启用redis缓存,让网站更快
- URL美化伪静态设置方法
- 标签缓存时间设置
- 自定义提交PHP相关危险关键字
- 如何对CMS等频道内容进行数据分表进行文本储值
- 两个网站共用一个认证服务号
- 关注公众号自动注册帐号
- 如何重建模块数据索引
- 任意页面生成小程序码或普通二维码
- 列表及内容页模板的优先级顺序
- APP配置教程及签名工具下载
- APP之QQ登录配置
- 关于APP使用原生微信支付的说明
- 改版后的QQ登录配置
- APP之QQ登录接口关联配置
- APP几个重要接口在模板中的调用
- 直播及APP相关教程
- 如何上传与编译手机可安装的文件
- app如何加模块
- 如何静默修复热更新
- 如何获取签名
- 用SVN导出差异文件做热修复
- 视频直播接口设置
- 用第三方直播APP推流
- 如何配置圈子群聊直播APP
- 直播要设置回调地址才能播放
- 直播录制为点播的配置
- 自建流媒体RTMP直播服务器
- 自建流媒体如何录制视频
- 如何录制阿里等第三方直播流
- APP要实现直播的关键两步
- 直播神器聊天小插件
- 直播相关视频教程
- 第一集阿里云及腾讯接口配置
- 注意事项
- 如何取消某个标签的缓存时间
- 商业模块仅限一个国际域名使用
- 页面报数据表错误如何修复
- 页面不直接报错,如何排查
- 如何取消禁止跨城市密码登录限制
- 非正常修改后台入口admin.php导致的问题
- 服务器性能太差,调整系统升级每次校验的文件数
- 如何开启自定义标签模板功能
- 客服系统显示客户在哪个页面
- 给表单某个字段设置初始值
- 如果把万能表单直接插入到内容中去
- 工单碎片模板制作教程
- 小程序与公众号长期永久订阅消息的申请方法
- 小程序集群微信开放平台配置教程
- 关于小程序个性源代码的说明
- 小程序风格模板设置
- 开通第三方平台服务商组件
- 微信公众号及小程序订阅模板消息的配置
- 主题内容如何群发给圈子成员
- 如何限制圈子内搜索内容