mirror of https://github.com/flucont/btcloud.git

14 changed files with 480 additions and 34 deletions
-
18.env
-
18.env.example
-
13README.md
-
81app/controller/Install.php
-
2app/lib/Btapi.php
-
2app/lib/Plugins.php
-
2app/middleware/AuthAdmin.php
-
10app/middleware/LoadConfig.php
-
76app/script/convert.sh
-
3app/view/admin/layout.html
-
11app/view/admin/set.html
-
268app/view/install/index.html
-
BINpublic/win/panel/panel_7.6.0.zip
-
2route/app.php
@ -1,18 +0,0 @@ |
|||
APP_DEBUG = false |
|||
|
|||
[APP] |
|||
DEFAULT_TIMEZONE = Asia/Shanghai |
|||
|
|||
[DATABASE] |
|||
TYPE = mysql |
|||
HOSTNAME = localhost |
|||
DATABASE = btcloud |
|||
USERNAME = btcloud |
|||
PASSWORD = 123456 |
|||
HOSTPORT = 3306 |
|||
CHARSET = utf8mb4 |
|||
PREFIX = cloud_ |
|||
DEBUG = false |
|||
|
|||
[LANG] |
|||
default_lang = zh-cn |
@ -0,0 +1,18 @@ |
|||
APP_DEBUG = false |
|||
|
|||
[APP] |
|||
DEFAULT_TIMEZONE = Asia/Shanghai |
|||
|
|||
[DATABASE] |
|||
TYPE = mysql |
|||
HOSTNAME = {dbhost} |
|||
DATABASE = {dbname} |
|||
USERNAME = {dbuser} |
|||
PASSWORD = {dbpwd} |
|||
HOSTPORT = {dbport} |
|||
CHARSET = utf8mb4 |
|||
PREFIX = {dbprefix} |
|||
DEBUG = false |
|||
|
|||
[LANG] |
|||
default_lang = zh-cn |
@ -0,0 +1,81 @@ |
|||
<?php |
|||
namespace app\controller; |
|||
|
|||
use PDO; |
|||
use Exception; |
|||
use app\BaseController; |
|||
use think\facade\View; |
|||
use think\facade\Cache; |
|||
|
|||
class Install extends BaseController |
|||
{ |
|||
public function index() |
|||
{ |
|||
if (file_exists(app()->getRootPath().'.env')){ |
|||
return '当前已经安装成功,如果需要重新安装,请手动删除根目录.env文件'; |
|||
} |
|||
if(request()->isPost()){ |
|||
$mysql_host = input('post.mysql_host', null, 'trim'); |
|||
$mysql_port = intval(input('post.mysql_port', '3306')); |
|||
$mysql_user = input('post.mysql_user', null, 'trim'); |
|||
$mysql_pwd = input('post.mysql_pwd', null, 'trim'); |
|||
$mysql_name = input('post.mysql_name', null, 'trim'); |
|||
$mysql_prefix = input('post.mysql_prefix', 'cloud_', 'trim'); |
|||
$admin_username = input('post.admin_username', null, 'trim'); |
|||
$admin_password = input('post.admin_password', null, 'trim'); |
|||
|
|||
if(!$mysql_host || !$mysql_user || !$mysql_pwd || !$mysql_name || !$admin_username || !$admin_password){ |
|||
return json(['code'=>0, 'msg'=>'必填项不能为空']); |
|||
} |
|||
|
|||
$configdata = file_get_contents(app()->getRootPath().'.env.example'); |
|||
$configdata = str_replace(['{dbhost}','{dbname}','{dbuser}','{dbpwd}','{dbport}','{dbprefix}'], [$mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configdata); |
|||
|
|||
try{ |
|||
$DB=new PDO("mysql:host=".$mysql_host.";dbname=".$mysql_name.";port=".$mysql_port,$mysql_user,$mysql_pwd); |
|||
}catch(Exception $e){ |
|||
if($e->getCode() == 2002){ |
|||
$errorMsg='连接数据库失败:数据库地址填写错误!'; |
|||
}elseif($e->getCode() == 1045){ |
|||
$errorMsg='连接数据库失败:数据库用户名或密码填写错误!'; |
|||
}elseif($e->getCode() == 1049){ |
|||
$errorMsg='连接数据库失败:数据库名不存在!'; |
|||
}else{ |
|||
$errorMsg='连接数据库失败:'.$e->getMessage(); |
|||
} |
|||
return json(['code'=>0, 'msg'=>$errorMsg]); |
|||
} |
|||
$DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); |
|||
$DB->exec("set sql_mode = ''"); |
|||
$DB->exec("set names utf8"); |
|||
|
|||
$sqls=file_get_contents(app()->getRootPath().'install.sql'); |
|||
$sqls=explode(';', $sqls); |
|||
$sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('syskey', '".random(16)."')"; |
|||
$success=0;$error=0;$errorMsg=null; |
|||
foreach ($sqls as $value) { |
|||
$value=trim($value); |
|||
if(empty($value))continue; |
|||
$value = str_replace('cloud_',$mysql_prefix,$value); |
|||
if($DB->exec($value)===false){ |
|||
$error++; |
|||
$dberror=$DB->errorInfo(); |
|||
$errorMsg.=$dberror[2]."\n"; |
|||
}else{ |
|||
$success++; |
|||
} |
|||
} |
|||
if(empty($errorMsg)){ |
|||
if(!file_put_contents(app()->getRootPath().'.env', $configdata)){ |
|||
return json(['code'=>0, 'msg'=>'保存失败,请确保网站根目录有写入权限']); |
|||
} |
|||
Cache::clear(); |
|||
return json(['code'=>1, 'msg'=>'安装完成!成功执行SQL语句'.$success.'条']); |
|||
}else{ |
|||
return json(['code'=>0, 'msg'=>$errorMsg]); |
|||
} |
|||
} |
|||
return view(); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,76 @@ |
|||
#!/bin/bash |
|||
|
|||
Linux_Version="7.9.3" |
|||
Windows_Version="7.6.0" |
|||
|
|||
FILES=( |
|||
public/install/src/panel6.zip |
|||
public/install/update/LinuxPanel-${Linux_Version}.zip |
|||
public/install/install_6.0.sh |
|||
public/install/update_panel.sh |
|||
public/install/update6.sh |
|||
public/win/install/panel_update.py |
|||
public/win/panel/panel_${Windows_Version}.zip |
|||
public/win/panel/data/api.py |
|||
public/win/panel/data/setup.py |
|||
) |
|||
|
|||
DIR=$1 |
|||
SITEURL=$2 |
|||
|
|||
if [ ! -d "$DIR" ]; then |
|||
echo "网站目录不存在" |
|||
exit 1 |
|||
fi |
|||
if [ "$SITEURL" = "" ]; then |
|||
echo "网站URL不正确" |
|||
exit 1 |
|||
fi |
|||
|
|||
function handleFile() |
|||
{ |
|||
Filename=$1 |
|||
if [ "${Filename##*.}" = "zip" ]; then |
|||
handleZipFile $Filename |
|||
else |
|||
handleTextFile $Filename |
|||
fi |
|||
} |
|||
|
|||
function handleZipFile() |
|||
{ |
|||
Filename=$1 |
|||
mkdir -p /tmp/package |
|||
unzip -o -q $Filename -d /tmp/package |
|||
grep -rl --include=\*.py --include=\*.sh --include=index.js 'http://www.example.com' /tmp/package | xargs -I @ sed -i "s|http://www.example.com|${SITEURL}|g" @ |
|||
Sprit_SITEURK=${SITEURL//\//\\\\\/} |
|||
grep -rl --include=\*.sh 'http:\\\/\\\/www.example.com' /tmp/package | xargs -I @ sed -i "s|http:\\\/\\\/www.example.com|${Sprit_SITEURK}|g" @ |
|||
rm -f $Filename |
|||
cd /tmp/package && zip -9 -q -r $Filename * && cd - |
|||
rm -rf /tmp/package |
|||
} |
|||
|
|||
function handleTextFile() |
|||
{ |
|||
sed -i "s|http://www.example.com|${SITEURL}|g" $1 |
|||
} |
|||
|
|||
|
|||
echo "==========================" |
|||
echo "正在处理中..." |
|||
echo "==========================" |
|||
|
|||
for File in ${FILES[@]} |
|||
do |
|||
Filename="${DIR}${File}" |
|||
if [ -f "$Filename" ]; then |
|||
handleFile $Filename |
|||
echo -e "成功处理文件:\033[32m${Filename}\033[0m" |
|||
else |
|||
echo -e "文件不存在:\033[33m${Filename}\033[0m" |
|||
fi |
|||
done |
|||
|
|||
echo "==========================" |
|||
echo "处理完成" |
|||
echo "==========================" |
@ -0,0 +1,268 @@ |
|||
<!doctype html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|||
<title>宝塔第三方云端 - 安装程序</title> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<meta name="renderer" content="webkit"> |
|||
<style> |
|||
body { |
|||
background: #f1f6fd; |
|||
margin: 0; |
|||
padding: 0; |
|||
line-height: 1.5; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
|
|||
body, input, button { |
|||
font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, 'Microsoft Yahei', Arial, sans-serif; |
|||
font-size: 14px; |
|||
color: #7E96B3; |
|||
} |
|||
|
|||
.container { |
|||
max-width: 480px; |
|||
margin: 0 auto; |
|||
padding: 20px; |
|||
text-align: center; |
|||
} |
|||
|
|||
a { |
|||
color: #4e73df; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
a:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
h1 { |
|||
margin-top: 0; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
h2 { |
|||
font-size: 28px; |
|||
font-weight: normal; |
|||
color: #3C5675; |
|||
margin-bottom: 0; |
|||
margin-top: 0; |
|||
} |
|||
|
|||
form { |
|||
margin-top: 40px; |
|||
} |
|||
|
|||
.form-group { |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.form-group .form-field:first-child input { |
|||
border-top-left-radius: 4px; |
|||
border-top-right-radius: 4px; |
|||
} |
|||
|
|||
.form-group .form-field:last-child input { |
|||
border-bottom-left-radius: 4px; |
|||
border-bottom-right-radius: 4px; |
|||
} |
|||
|
|||
.form-field input { |
|||
background: #fff; |
|||
margin: 0 0 2px; |
|||
border: 2px solid transparent; |
|||
transition: background 0.2s, border-color 0.2s, color 0.2s; |
|||
width: 100%; |
|||
padding: 15px 15px 15px 180px; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.form-field input:focus { |
|||
border-color: #4e73df; |
|||
background: #fff; |
|||
color: #444; |
|||
outline: none; |
|||
} |
|||
|
|||
.form-field label { |
|||
float: left; |
|||
width: 160px; |
|||
text-align: right; |
|||
margin-right: -160px; |
|||
position: relative; |
|||
margin-top: 15px; |
|||
font-size: 14px; |
|||
pointer-events: none; |
|||
opacity: 0.7; |
|||
} |
|||
|
|||
button, .btn { |
|||
background: #3C5675; |
|||
color: #fff; |
|||
border: 0; |
|||
font-weight: bold; |
|||
border-radius: 4px; |
|||
cursor: pointer; |
|||
padding: 15px 30px; |
|||
-webkit-appearance: none; |
|||
} |
|||
|
|||
button[disabled] { |
|||
opacity: 0.5; |
|||
} |
|||
|
|||
.form-buttons { |
|||
height: 52px; |
|||
line-height: 52px; |
|||
} |
|||
|
|||
.form-buttons .btn { |
|||
margin-right: 5px; |
|||
} |
|||
|
|||
#error, .error, #success, .success, #warmtips, .warmtips { |
|||
background: #D83E3E; |
|||
color: #fff; |
|||
padding: 15px 20px; |
|||
border-radius: 4px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
#success { |
|||
background: #3C5675; |
|||
} |
|||
|
|||
#error a, .error a { |
|||
color: white; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
#warmtips { |
|||
background: #fff; |
|||
font-size: 14px; |
|||
color: #3C5675; |
|||
border: 2px solid #4e73df; |
|||
text-align: left; |
|||
} |
|||
|
|||
</style> |
|||
</head> |
|||
|
|||
<body> |
|||
<div class="container"> |
|||
<h1> |
|||
<svg t="1660545699809" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4887" width="100px" height="100px"> |
|||
<path d="M811.4 418.7C765.6 297.9 648.9 212 512.2 212S258.8 297.8 213 418.6C127.3 441.1 64 519.1 64 612c0 110.5 89.5 200 199.9 200h496.2C870.5 812 960 722.5 960 612c0-92.7-63.1-170.7-148.6-193.3z m36.3 281c-23.4 23.4-54.5 36.3-87.6 36.3H263.9c-33.1 0-64.2-12.9-87.6-36.3-23.4-23.4-36.3-54.6-36.3-87.7 0-28 9.1-54.3 26.2-76.3 16.7-21.3 40.2-36.8 66.1-43.7l37.9-9.9 13.9-36.6c8.6-22.8 20.6-44.1 35.7-63.4 14.9-19.2 32.6-35.9 52.4-49.9 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.2c19.9 14 37.5 30.8 52.4 49.9 15.1 19.3 27.1 40.7 35.7 63.4l13.8 36.5 37.8 10c54.3 14.5 92.1 63.8 92.1 120 0 33.1-12.9 64.3-36.3 87.7z" p-id="4888" fill="#4e73df"></path> |
|||
</svg> |
|||
</h1> |
|||
<h2>宝塔第三方云端 - 安装程序</h2> |
|||
<div> |
|||
|
|||
<form method="post"> |
|||
<div id="error" style="display:none"></div> |
|||
<div id="success" style="display:none"></div> |
|||
<div id="warmtips" style="display:none"><p>安装完成后,你还需要进行以下操作:</p><p>1、在后台使用批量替换工具,执行命令一键替换压缩包与安装脚本中的域名。</p><p></p>2、在后台配置面板对接,同步插件列表与插件包。</p></div> |
|||
|
|||
<div class="form-group"> |
|||
<div class="form-field"> |
|||
<label>MySQL 数据库地址</label> |
|||
<input type="text" name="mysql_host" value="localhost" required=""> |
|||
</div> |
|||
|
|||
<div class="form-field"> |
|||
<label>MySQL 数据库端口</label> |
|||
<input type="number" name="mysql_port" value="3306"> |
|||
</div> |
|||
|
|||
<div class="form-field"> |
|||
<label>MySQL 用户名</label> |
|||
<input type="text" name="mysql_user" value="" required=""> |
|||
</div> |
|||
|
|||
<div class="form-field"> |
|||
<label>MySQL 密码</label> |
|||
<input type="text" name="mysql_pwd" value="" required=""> |
|||
</div> |
|||
|
|||
<div class="form-field"> |
|||
<label>MySQL 数据库名</label> |
|||
<input type="text" name="mysql_name" value="" required=""> |
|||
</div> |
|||
|
|||
<div class="form-field"> |
|||
<label>MySQL 数据表前缀</label> |
|||
<input type="text" name="mysql_prefix" value="cloud_"> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="form-group"> |
|||
<div class="form-field"> |
|||
<label>管理员用户名</label> |
|||
<input type="text" name="admin_username" value="admin" required=""/> |
|||
</div> |
|||
|
|||
<div class="form-field"> |
|||
<label>管理员密码</label> |
|||
<input type="text" name="admin_password" value="123456" required=""> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="form-buttons"> |
|||
<!--@formatter:off--> |
|||
<button type="submit" >点击安装</button> |
|||
<!--@formatter:on--> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
<script src="//cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script> |
|||
<script> |
|||
$(function () { |
|||
$('form').on('submit', function (e) { |
|||
e.preventDefault(); |
|||
var form = this; |
|||
var $error = $("#error"); |
|||
var $success = $("#success"); |
|||
var $button = $(this).find('button') |
|||
.text("安装中...") |
|||
.prop('disabled', true); |
|||
$.ajax({ |
|||
url: "", |
|||
type: "POST", |
|||
dataType: "json", |
|||
data: $(this).serialize(), |
|||
success: function (ret) { |
|||
if (ret.code == 1) { |
|||
$error.hide(); |
|||
$(".form-group", form).remove(); |
|||
$button.remove(); |
|||
$("#success").text(ret.msg).show(); |
|||
$("#warmtips").show(); |
|||
|
|||
$buttons = $(".form-buttons", form); |
|||
$('<a class="btn" href="/admin" style="background:#4e73df">进入后台</a>').appendTo($buttons); |
|||
|
|||
} else { |
|||
$error.show().text(ret.msg); |
|||
$button.prop('disabled', false).text("点击安装"); |
|||
$("html,body").animate({ |
|||
scrollTop: 0 |
|||
}, 500); |
|||
} |
|||
}, |
|||
error: function (xhr) { |
|||
$error.show().text(xhr.responseText); |
|||
$button.prop('disabled', false).text("点击安装"); |
|||
$("html,body").animate({ |
|||
scrollTop: 0 |
|||
}, 500); |
|||
} |
|||
}); |
|||
return false; |
|||
}); |
|||
}); |
|||
</script> |
|||
</body> |
|||
</html> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue