1、安装文件更新

2、内核更新
This commit is contained in:
2016-07-31 14:17:51 +08:00
parent 9da53fc969
commit 762b280d21
30 changed files with 1082 additions and 181 deletions
+275
View File
@@ -0,0 +1,275 @@
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
// 检测环境是否支持可写
define('IS_WRITE', true);
define('INSTALL_APP_PATH', BASE_PATH . '/');
/**
* 系统环境检测
* @return array 系统环境数据
*/
function check_env(){
$items = array(
'os' => array('操作系统', '不限制', '类Unix', PHP_OS, 'success'),
'php' => array('PHP版本', '5.4.0', '5.3+', PHP_VERSION, 'success'),
'upload' => array('附件上传', '不限制', '2M+', '未知', 'success'),
'gd' => array('GD库', '2.0', '2.0+', '未知', 'success'),
'disk' => array('磁盘空间', '5M', '不限制', '未知', 'success'),
);
//PHP环境检测
if($items['php'][3] < $items['php'][1]){
$items['php'][4] = 'error';
session('error', true);
}
//附件上传检测
if(@ini_get('file_uploads'))
$items['upload'][3] = ini_get('upload_max_filesize');
//GD库检测
$tmp = function_exists('gd_info') ? gd_info() : array();
if(empty($tmp['GD Version'])){
$items['gd'][3] = '未安装';
$items['gd'][4] = 'error';
session('error', true);
} else {
$items['gd'][3] = $tmp['GD Version'];
}
unset($tmp);
//磁盘空间检测
if(function_exists('disk_free_space')) {
$items['disk'][3] = floor(disk_free_space(INSTALL_APP_PATH) / (1024*1024)).'M';
}
return $items;
}
/**
* 目录,文件读写检测
* @return array 检测数据
*/
function check_dirfile(){
$items = array(
array('dir', '可写', 'success', 'uploads/attachment/'),
array('dir', '可写', 'success', 'uploads/avatar/'),
array('dir', '可写', 'success', 'uploads/download/'),
array('dir', '可写', 'success', 'uploads/picture/'),
array('dir', '可写', 'success', 'uploads/editor/'),
);
foreach ($items as &$val) {
$item = INSTALL_APP_PATH . $val[3];
if('dir' == $val[0]){
if(!is_writable($item)) {
if(is_dir($item)) {
$val[1] = '可读';
$val[2] = 'error';
session('error', true);
} else {
$val[1] = '不存在';
$val[2] = 'error';
session('error', true);
}
}
} else {
if(file_exists($item)) {
if(!is_writable($item)) {
$val[1] = '不可写';
$val[2] = 'error';
session('error', true);
}
} else {
if(!is_writable(dirname($item))) {
$val[1] = '不存在';
$val[2] = 'error';
session('error', true);
}
}
}
}
return $items;
}
/**
* 函数检测
* @return array 检测数据
*/
function check_func(){
$items = array(
array('pdo','支持','success','类'),
array('pdo_mysql','支持','success','模块'),
array('file_get_contents', '支持', 'success','函数'),
array('mb_strlen', '支持', 'success','函数'),
);
foreach ($items as &$val) {
if(('类'==$val[3] && !class_exists($val[0]))
|| ('模块'==$val[3] && !extension_loaded($val[0]))
|| ('函数'==$val[3] && !function_exists($val[0]))
){
$val[1] = '不支持';
$val[2] = 'error';
session('error', true);
}
}
return $items;
}
/**
* 写入配置文件
* @param array $config 配置信息
*/
function write_config($config){
if(is_array($config)){
//读取配置内容
$conf = file_get_contents(BASE_PATH . './data/db.tpl');
//替换配置项
foreach ($config as $name => $value) {
$conf = str_replace("[{$name}]", $value, $conf);
}
file_put_contents(APP_PATH . 'install.lock', 'ok');
//写入应用配置文件
if(file_put_contents(APP_PATH . 'database.php', $conf)){
show_msg('配置文件写入成功');
} else {
show_msg('配置文件写入失败!', 'error');
session('error', true);
}
return '';
}
}
/**
* 创建数据表
* @param resource $db 数据库连接资源
*/
function create_tables($db, $prefix = ''){
//读取SQL文件
$sql = file_get_contents(BASE_PATH . './data/sql.sql');
$sql = str_replace("\r", "\n", $sql);
$sql = explode(";\n", $sql);
//替换表前缀
$orginal = 'sent_';
$sql = str_replace(" `{$orginal}", " `{$prefix}", $sql);
//开始安装
show_msg('开始安装数据库...');
foreach ($sql as $value) {
$value = trim($value);
if(empty($value)) continue;
if(substr($value, 0, 12) == 'CREATE TABLE') {
$name = preg_replace("/^CREATE TABLE `(\w+)` .*/s", "\\1", $value);
$msg = "创建数据表{$name}";
if(false !== $db->execute($value)){
show_msg($msg . '...成功');
} else {
show_msg($msg . '...失败!', 'error');
session('error', true);
}
} else {
$db->execute($value);
}
}
}
function register_administrator($db, $prefix, $admin){
show_msg('开始注册创始人帐号...');
$salt = rand_string();
$password = md5($admin['password'].$salt);
$sql = "INSERT INTO `[PREFIX]member` (`uid`,`username`,`password`,`nickname`,`email`, `sex`,`birthday`,`qq`,`score`,`salt`,`login`,`reg_ip`,`reg_time`,`last_login_ip`,`last_login_time`,`status`) VALUES ".
"('1', '[NAME]', '[PASS]', '[NAME]', '[EMAIL]', '0', '0000-00-00', '', '0','[SALT]', '1', '0', '[TIME]', '[IP]', '[TIME]', '1');";
$sql = str_replace(
array('[PREFIX]', '[NAME]','[PASS]','[EMAIL]','[SALT]', '[TIME]', '[IP]'),
array($prefix, $admin['username'],$password, $admin['email'],$salt, time(), get_client_ip(1)),
$sql);
$db->execute($sql);
show_msg('创始人帐号注册完成!');
}
/**
* 更新数据表
* @param resource $db 数据库连接资源
* @author lyq <605415184@qq.com>
*/
function update_tables($db, $prefix = ''){
//读取SQL文件
$sql = file_get_contents(MODULE_PATH . 'Data/update.sql');
$sql = str_replace("\r", "\n", $sql);
$sql = explode(";\n", $sql);
//替换表前缀
$sql = str_replace(" `sent_", " `{$prefix}", $sql);
//开始安装
show_msg('开始升级数据库...');
foreach ($sql as $value) {
$value = trim($value);
if(empty($value)) continue;
if(substr($value, 0, 12) == 'CREATE TABLE') {
$name = preg_replace("/^CREATE TABLE `(\w+)` .*/s", "\\1", $value);
$msg = "创建数据表{$name}";
if(false !== $db->execute($value)){
show_msg($msg . '...成功');
} else {
show_msg($msg . '...失败!', 'error');
session('error', true);
}
} else {
if(substr($value, 0, 8) == 'UPDATE `') {
$name = preg_replace("/^UPDATE `(\w+)` .*/s", "\\1", $value);
$msg = "更新数据表{$name}";
} else if(substr($value, 0, 11) == 'ALTER TABLE'){
$name = preg_replace("/^ALTER TABLE `(\w+)` .*/s", "\\1", $value);
$msg = "修改数据表{$name}";
} else if(substr($value, 0, 11) == 'INSERT INTO'){
$name = preg_replace("/^INSERT INTO `(\w+)` .*/s", "\\1", $value);
$msg = "写入数据表{$name}";
}
if(($db->execute($value)) !== false){
show_msg($msg . '...成功');
} else{
show_msg($msg . '...失败!', 'error');
session('error', true);
}
}
}
}
/**
* 及时显示提示信息
* @param string $msg 提示信息
*/
function show_msg($msg, $class = 'primary'){
echo "<script type=\"text/javascript\">showmsg(\"{$msg}\", \"{$class}\")</script>";
flush();
ob_flush();
}
/**
* 生成系统AUTH_KEY
* @author 麦当苗儿 <zuojiazi@vip.qq.com>
*/
function build_auth_key(){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$chars .= '`~!@#$%^&*()_+-=[]{};:"|,.<>/?';
$chars = str_shuffle($chars);
return substr($chars, 0, 40);
}
+16
View File
@@ -0,0 +1,16 @@
<?php
return array(
'view_replace_str' => array(
'__ADDONS__' => BASE_PATH . '/addons',
'__PUBLIC__' => BASE_PATH . '/public',
'__STATIC__' => BASE_PATH . '/application/admin/static',
'__IMG__' => BASE_PATH . '/application/admin/static/images',
'__CSS__' => BASE_PATH . '/application/admin/static/css',
'__JS__' => BASE_PATH . '/application/admin/static/js',
'__COMPANY__' => '南昌腾速科技有限公司',
'__NAME__' => 'SentCMS网站管理系统',
'__COMPANY_WEBSITE__' => 'www.tensent.cn',
'__WEBSITE__' => 'www.sentcms.cn',
),
);
+150
View File
@@ -0,0 +1,150 @@
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace app\install\controller;
class Index extends \think\Controller {
protected $status;
public function _initialize() {
$this->status = array(
'index' => 'info',
'check' => 'info',
'config' => 'info',
'sql' => 'info',
'complete' => 'info',
);
if (request()->action() != 'complete' && is_file(APP_PATH . 'database.php') && is_file(APP_PATH . 'install.lock')) {
return $this->redirect('index/index/index');
}
}
public function index() {
$this->status['index'] = 'primary';
$this->assign('status', $this->status);
return $this->fetch();
}
public function check() {
session('error', false);
//环境检测
$env = check_env();
//目录文件读写检测
if (IS_WRITE) {
$dirfile = check_dirfile();
$this->assign('dirfile', $dirfile);
}
//函数检测
$func = check_func();
session('step', 1);
$this->assign('env', $env);
$this->assign('func', $func);
$this->status['index'] = 'success';
$this->status['check'] = 'primary';
$this->assign('status', $this->status);
return $this->fetch();
}
public function config($db = null, $admin = null) {
if (request()->IsPost()) {
//检测管理员信息
if (!is_array($admin) || empty($admin[0]) || empty($admin[1]) || empty($admin[3])) {
return $this->error('请填写完整管理员信息');
} else if ($admin[1] != $admin[2]) {
return $this->error('确认密码和密码不一致');
} else {
$info = array();
list($info['username'], $info['password'], $info['repassword'], $info['email'])
= $admin;
//缓存管理员信息
session('admin_info', $info);
}
//检测数据库配置
if (!is_array($db) || empty($db[0]) || empty($db[1]) || empty($db[2]) || empty($db[3])) {
return $this->error('请填写完整的数据库配置');
} else {
$DB = array();
list($DB['type'], $DB['hostname'], $DB['database'], $DB['username'], $DB['password'],
$DB['hostport'], $DB['prefix']) = $db;
//缓存数据库配置
session('db_config', $DB);
//创建数据库
$dbname = $DB['database'];
unset($DB['database']);
$db = \think\Db::connect($DB);
$sql = "CREATE DATABASE IF NOT EXISTS `{$dbname}` DEFAULT CHARACTER SET utf8";
if (!$db->execute($sql)) {
return $this->error($db->getError());
} else {
return $this->redirect('install/index/sql');
}
}
} else {
$this->status['index'] = 'success';
$this->status['check'] = 'success';
$this->status['config'] = 'primary';
$this->assign('status', $this->status);
return $this->fetch();
}
}
public function sql() {
session('error', false);
$this->status['index'] = 'success';
$this->status['check'] = 'success';
$this->status['config'] = 'success';
$this->status['sql'] = 'primary';
$this->assign('status', $this->status);
echo $this->fetch();
if (session('update')) {
$db = \think\Db::connect();
//更新数据表
update_tables($db, config('prefix'));
} else {
//连接数据库
$dbconfig = session('db_config');
$db = \think\Db::connect($dbconfig);
//创建数据表
create_tables($db, $dbconfig['prefix']);
//注册创始人帐号
$admin = session('admin_info');
register_administrator($db, $dbconfig['prefix'], $admin);
//创建配置文件
$conf = write_config($dbconfig);
session('config_file', $conf);
}
if (session('error')) {
show_msg('失败');
} else {
echo '<script type="text/javascript">location.href = "'.url('install/index/complete').'";</script>';
}
}
public function complete() {
$this->status['index'] = 'success';
$this->status['check'] = 'success';
$this->status['config'] = 'success';
$this->status['sql'] = 'success';
$this->status['complete'] = 'primary';
$this->assign('status', $this->status);
$this->assign('status', $this->status);
return $this->fetch();
}
}
+67
View File
@@ -0,0 +1,67 @@
{extend name="public/base"/}
{block name="body"}
<h1>环境检测</h1>
<table class="table table-hover">
<caption><h2>运行环境检查</h2></caption>
<thead>
<tr>
<th>项目</th>
<th>所需配置</th>
<th>当前配置</th>
</tr>
</thead>
<tbody>
{volist name="env" id="item"}
<tr>
<td>{$item[0]}</td>
<td>{$item[1]}</td>
<td><i class="icon icon-{$item[4]}">&nbsp;</i>{$item[3]}</td>
</tr>
{/volist}
</tbody>
</table>
{present name="dirfile"}
<table class="table table-hover">
<caption><h2>目录、文件权限检查</h2></caption>
<thead>
<tr>
<th>目录/文件</th>
<th>所需状态</th>
<th>当前状态</th>
</tr>
</thead>
<tbody>
{volist name="dirfile" id="item"}
<tr>
<td>{$item[3]}</td>
<td><i class="icon icon-ok">&nbsp;</i>可写</td>
<td><i class="icon icon-{$item[2]}">&nbsp;</i>{$item[1]}</td>
</tr>
{/volist}
</tbody>
</table>
{/present}
<table class="table table-hover">
<caption><h2>函数依赖性检查</h2></caption>
<thead>
<tr>
<th>函数名称</th>
<th>检查结果</th>
</tr>
</thead>
<tbody>
{volist name="func" id="item"}
<tr>
<td>{$item[0]}()</td>
<td><i class="icon icon-{$item[2]}">&nbsp;</i>{$item[1]}</td>
</tr>
{/volist}
</tbody>
</table>
{/block}
{block name="footer"}
<div class="text-center">
<a class="btn btn-primary" href="{:url('install/index/config')}">下一步</a>
<a class="btn btn-default" href="{:url('install/index/index')}">上一步</a>
</div>
{/block}
@@ -0,0 +1,26 @@
{extend name="public/base"/}
{block name="body"}
<h1 class="text-center">完成</h1>
<div class="row">
<div class="col-sm-6">
<ul class="list-group">
<li class="list-group-item"><a href="http://www.tensent.cn" target="_blank">南昌腾速科技有限公司</a></li>
<li class="list-group-item"><a href="http://git.oschina.net/sentcms/sentcms" target="_blank">SentCMS3.0版本库</a></li>
<li class="list-group-item"><a href="http://wpa.qq.com/msgrd?v=3&uin=707479167&site=qq&menu=yes" target="_blank">系统定制</a></li>
</ul>
</div>
<div class="col-sm-6">
<ul class="list-group">
<li class="list-group-item"><a href="http://doc.sentcms.com" target="_blank">SentCMS3.0开发文档</a></li>
<li class="list-group-item"><a href="http://bbs.sentcms.com" target="_blank">SentCMS讨论社区</a></li>
<li class="list-group-item"><a href="http://jq.qq.com/?_wv=1027&k=2GgKNPQ" target="_blank">开发交流群</a></li>
</ul>
</div>
</div>
{/block}
{block name="footer"}
<div class="text-center">
<a class="btn btn-primary" target="_blank" href="/admin">登录后台</a>
<a class="btn btn-success" target="_blank" href="/">访问首页</a>
</div>
{/block}
+163
View File
@@ -0,0 +1,163 @@
{extend name="public/base"/}
{block name="body"}
<h2 class="text-center">
创建数据库
</h2>
<form method="post" target="_self">
<div class="create-database">
<h2>
数据库连接信息
</h2>
<table class="table-hover table">
<tr>
<td>
<select class="form-control" name="db[]">
<option>
mysql
</option>
<option>
mysqli
</option>
</select>
</td>
<td>
数据库连接类型,服务器支持的情况下建议使用mysql
</td>
</tr>
<tr>
<td>
<input class="form-control" name="db[]" type="text" value="127.0.0.1">
</input>
</td>
<td>
<span>
数据库服务器,数据库服务器IP,一般为127.0.0.1,使用localhost可能导致网站速度变慢
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="db[]" type="text" value="">
</input>
</td>
<td>
<span>
数据库名
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="db[]" type="text" value="">
</input>
</td>
<td>
<span>
数据库用户名
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="db[]" type="password" value="">
</input>
</td>
<td>
<span>
数据库密码
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="db[]" type="text" value="3306">
</input>
</td>
<td>
<span>
数据库端口,数据库服务连接端口,一般为3306
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="db[]" type="text" value="sent_" class="form-control">
</input>
</td>
<td>
<span>
数据表前缀,同一个数据库运行多个系统时请修改为不同的前缀
</span>
</td>
</tr>
</table>
</div>
<div class="create-database">
<h2>
创始人帐号信息
</h2>
<table class="table-hover table">
<tr>
<td>
<input class="form-control" name="admin[]" type="text" value="admin">
</input>
</td>
<td>
<span>
用户名(
<span class="text-danger">
英文+数字,严禁中文与特殊字符
</span>
)
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="admin[]" type="password" value="">
</input>
</td>
<td>
<span>
密码
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="admin[]" type="password" value="">
</input>
</td>
<td>
<span>
确认密码
</span>
</td>
</tr>
<tr>
<td>
<input class="form-control" name="admin[]" type="text" value="admin@admin.com">
</input>
</td>
<td>
<span>
邮箱,请填写正确的邮箱便于收取提醒邮件
</span>
</td>
</tr>
</table>
<div>
</div>
</div>
</form>
{/block}
{block name="footer"}
<div class="text-center">
<button class="btn btn-primary" id="submit" onclick="$('form').submit();return false;" type="button">
下一步
</button>
<a class="btn btn-default" href="{:url('install/index/check')}">
上一步
</a>
</div>
{/block}
+50
View File
@@ -0,0 +1,50 @@
{extend name="public/base"/}
{block name="body"}
<div class="margin-top">
<header>
<h2 class="text-center">__NAME__ 安装协议</h2>
<section class="text-center abstract">版权所有 (c) 2014-2015__COMPANY__保留所有权利。</section>
</header>
<section class="article-content" style="text-indent: 2em">
<p>
__NAME__基于
<a target="_blank" href="http://www.thinkphp.cn">ThinkPHP</a>框架
的开发产品。感谢顶想公司为__NAME__提供内核支持。
</p>
<p>
感谢您选择__NAME__,希望我们的努力可以为您创造价值。公司网址为
<a href="http://__COMPANY_WEBSITE__" target="_blank">http://__COMPANY_WEBSITE__</a>
,产品官方网站网址为
<a href="http://__WEBSITE__" target="_blank">http://__WEBSITE__</a>
</p>
<p>
用户须知:本协议是您于__COMPANY__关于__NAME__产品使用的法律协议。无论您是个人或组织、盈利与否、用途如何(包括以学习和研究为目的),均需仔细阅读本协议,包括免除或者限制__COMPANY__责任的免责条款及对您的权利限制。请您审阅并接受或不接受本服务条款。如您不同意本服务条款及或__COMPANY__随时对其的修改,您应不使用或主动取消__NAME__产品。否则,您的任何对__NAME__的相关服务的注册、登陆、下载、查看等使用行为将被视为您对本服务条款全部的完全接受,包括接受__COMPANY__对服务条款随时所做的任何修改。
</p>
<p>
本服务条款一旦发生变更,__COMPANY__将在产品官网上公布修改内容。修改后的服务条款一旦在网站公布即有效代替原来的服务条款。您可随时登陆官网查阅最新版服务条款。如果您选择接受本条款,即表示您同意接受协议各项条件的约束。如果您不同意本服务条款,则不能获得使用本服务的权利。您若有违反本条款规定,__COMPANY__有权随时中止或终止您对__NAME__产品的使用资格并保留追究相关法律责任的权利。
</p>
<p>
在理解、同意、并遵守本协议的全部条款后,方可开始使用__NAME__产品。您也可能与__COMPANY__直接签订另一书面协议,以补充或者取代本协议的全部或者任何部分。
</p>
<p>
__COMPANY__拥有__NAME__的知识产权,包括商标和著作权。本软件只供许可协议,并非出售。想天只允许您在遵守本协议各项条款的情况下复制、下载、安装、使用或者以其他方式受益于本软件的功能或者知识产权。
</p>
</section>
</div>
{/block}
{block name="footer"}
<div class="text-center">
<a class="btn btn-primary" href="{:url('Install/index/check')}">同意安装协议</a>
<a class="btn btn-default" style="background: white;" href="http://__WEBSITE__">不同意</a>
</div>
{/block}
+21
View File
@@ -0,0 +1,21 @@
{extend name="public/base"/}
{block name="body"}
<h1 class="text-center">安装数据库</h1>
<div id="show-list" class="install-database list-group" style="height:450px; overflow-y:auto; ">
</div>
<script type="text/javascript">
var list = document.getElementById('show-list');
function showmsg(msg, classname){
var li = document.createElement('p');
li.innerHTML = msg;
classname && li.setAttribute('class', 'list-group-item text-' + classname);
list.appendChild(li);
document.scrollTop += 30;
}
</script>
{/block}
{block name="footer"}
<div class="text-center">
<button class="btn btn-warning disabled">正在安装,请稍候...</button>
</div>
{/block}
+60
View File
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SentCMS系统安装</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<!-- zui -->
<link href="__PUBLIC__/css/bootstrap/bootstrap.min.css" rel="stylesheet">
<script src="__PUBLIC__/js/jquery.js"></script>
<style>
body{font-family: "Microsoft Yahei",'新宋体';}
.container{background: #ffffff; margin: 50px auto; padding: 20px 0; width: 1024px;}
.header-title{border-bottom: 1px solid #dedede; margin-bottom: 10px;}
.progress-tool{padding: 10px;}
.progress{height: 30px;}
.progress-bar{line-height: 30px; font-size: 14px;}
.article{padding: 0 20px;}
h1{font-size: 18px; color: #333333; font-weight: bold;}
h2{font-size: 16px; color: #333333; font-weight: bold;}
</style>
</head>
<body style="background: rgb(230, 234, 234)">
<div class="container">
<div class="margin">
<div class="text-center header-title margin-top">
<h1>SentCMS系统{if session('update')}升级{else/}安装{/if}</h1>
</div>
<div class="progress-tool">
<div class="progress">
<div class="progress-bar progress-bar-{$status['index']} progress-bar-striped" style="width: 20%">
<span>系统安装</span>
</div>
<div class="progress-bar progress-bar-{$status['check']} progress-bar-striped" style="width: 20%">
<span>环境检查</span>
</div>
<div class="progress-bar progress-bar-{$status['config']} progress-bar-striped" style="width: 20%">
<span>系统配置</span>
</div>
<div class="progress-bar progress-bar-{$status['sql']} progress-bar-striped" style="width: 20%">
<span>数据库安装</span>
</div>
<div class="progress-bar progress-bar-{$status['complete']} progress-bar-striped" style="width: 20%">
<span>安装完成</span>
</div>
</div>
</div>
<div class="article margin-top">
{block name="body"}{/block}
<div class="margin-top">
{block name="footer"}{/block}
</div>
</div>
</div>
</div>
</body>
</html>