<?php
session_start();
// lock_file_guard();
if (file_exists("dpqb.lock")) {
    echo('为了安全，本文件每次运行成功后会被自动锁定，如果想再次运行，请删除 dpqb.lock 后重试。');
    exit(0);
}
set_time_limit(0);
error_reporting(E_ALL ^ E_WARNING);
define('PACKAGE_BASE', 'https://api.dpqb.com/');
$SCRIPT_NAME = basename(__FILE__);
$STEP = get_step();
$IS_NEXT = true;
$autoInstall = false;
if (__DIR__ == '/usr/dpqb/www') {
    $autoInstall = true;
}
$offset = 1024 * 1024 * 3;
if (!empty($_GET['api'])) {
    if (empty($_GET['api_uuid'])) exit(json_encode(['code' => 7881, 'msg' => '业务编号为空']));
    if (empty($_GET['api_pwd'])) exit(json_encode(['code' => 7882, 'msg' => '业务密码为空']));
    if (empty($_GET['savecount'])) exit(json_encode(['code' => 7883, 'msg' => '分片数量为空']));
    if (empty($_GET['webTitle'])) exit(json_encode(['code' => 7883, 'msg' => '网站标题为空']));
    if (empty($_GET['mysqlHost'])) exit(json_encode(['code' => 7883, 'msg' => '数据库地址为空']));
    if (empty($_GET['mysqlDatabase'])) exit(json_encode(['code' => 7883, 'msg' => '数据库为空']));
    if (empty($_GET['mysqlUsername'])) exit(json_encode(['code' => 7883, 'msg' => '数据库用户名为空']));
    if (empty($_GET['mysqlPassword'])) exit(json_encode(['code' => 7883, 'msg' => '数据库密码为空']));
    if (empty($_GET['adminPath'])) exit(json_encode(['code' => 7883, 'msg' => '后台路径为空']));
    if (empty($_GET['redisHost'])) exit(json_encode(['code' => 7883, 'msg' => 'redis地址为空']));
    if (empty($_GET['redisPassword'])) exit(json_encode(['code' => 7883, 'msg' => 'redis密码为空']));

    $res = check_mysql_database($_GET['mysqlHost'], $_GET['mysqlUsername'], $_GET['mysqlPassword'], $_GET['mysqlDatabase']);
    if ($res !== true) {
        exit(json_encode(['code' => 200, 'msg' => $res, 'data' => ['success' => false]], JSON_UNESCAPED_UNICODE));
    }

    if ($_GET['savecount'] == 1 || ($_SESSION['start_time'] && $_SESSION['start_time'] < time() - 24 * 3600) || empty($_SESSION['start_time'])) {
        $_SESSION = [];
    }
    if (empty($_SESSION['path'])) {
        $res = app_post($_GET['api_pwd'], $_GET['api_uuid']);
        if (!isset($res['success'])) {
            exit(json_encode(['code' => 788, 'msg' => $res['msg'], 'data' => []], JSON_UNESCAPED_UNICODE));
        }
        $_SESSION['path'] = $res['rows']['path'];
        $_SESSION['version'] = $res['rows']['version'];
        $_SESSION['bus_uuid'] = $res['rows']['bus_uuid'];
        $_SESSION['bus_pwd'] = $res['rows']['bus_pwd'];
        $_SESSION['file_size'] = getFileSize($_SESSION['path']);
        $_SESSION['start_time'] = time();
        $file_arr = explode('/', $_SESSION['path']);
        $file_name = end($file_arr);
        $_SESSION['file_name'] = $file_name;
        $_SESSION['count'] = ceil($_SESSION['file_size'] / $offset);
    }
    $savecount = $_GET['savecount'] - 1;
    $filesize = $_SESSION['file_size'];
    $path = $_SESSION['path'];
    $file_name = $_SESSION['file_name'];
    $count = ceil($_SESSION['file_size'] / $offset);
    $hasSize = $_GET['savecount'] * $offset;
    $start = $savecount == 0 ? 0 : $offset * $savecount;
    $offset = $_GET['savecount'] >= $count ? $filesize : $offset + $start - 1;
    if ($_GET['savecount'] <= $count) {
        api_http_download_to_str($path, $file_name . '_' . $_GET['savecount'], $start, $offset);
    }

    $success = false;
    $msg = '正在执行安装';
    $part = intval(($hasSize / $filesize) * 100);
    if ($hasSize >= $filesize) {
        $success = true;
        $msg = '安装完成';
        $part = 100;
        $shell = 'echo "* * * * * php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan command:TimedTask" >> /var/spool/cron/root && sed -i s:/usr/dpqb/www:/usr/dpqb/www/public:g /etc/nginx/nginx.conf && nginx -s reload && echo "' . $_SERVER['USER'] . ' ALL=(root) NOPASSWD:ALL" >> /etc/sudoers';
        $arr = ['code' => 200, 'msg' => $msg, 'data' => ['part' => $part, 'runshell' => $shell, 'success' => $success, 'savecount' => $_GET['savecount']]];
        $data['webTitle'] = $_GET['webTitle'];
        $data['mysqlHost'] = $_GET['mysqlHost'];
        $data['mysqlDatabase'] = $_GET['mysqlDatabase'];
        $data['mysqlUsername'] = $_GET['mysqlUsername'];
        $data['mysqlPassword'] = $_GET['mysqlPassword'];
        $data['adminUsername'] = $_GET['adminUsername'];
        $data['adminPassword'] = $_GET['adminPassword'];
        $data['adminPath'] = $_GET['adminPath'];
        $data['redisHost'] = $_GET['redisHost'];
        $data['redisPassword'] = $_GET['redisPassword'];
        $data['app_ver'] = $_SESSION['version'];
        $filenames = scandir('./', 2);
        $filenames = filesort($filenames, $file_name);
        foreach ($filenames as $name) {
            if ($name != '.' && $name != '..') {
                if (strpos($name, $file_name) !== false) {
                    $str = file_get_contents($name);
                    file_put_contents($file_name, $str, FILE_APPEND);
                    @unlink($name);
                }
            }
        }
        extract_zip($file_name, __DIR__);
        @unlink($file_name);
        create_env($data, 2);
        $_GET['bus_uuid'] = $_SESSION['bus_uuid'];
        $_GET['bus_pwd'] = $_SESSION['bus_pwd'];
        $_GET['appid'] = $_GET['api_uuid'];
        $_GET['app_secret'] = $_GET['api_pwd'];
        create_mysql($_GET);
    } else {
        $arr = ['code' => 200, 'msg' => $msg, 'data' => ['part' => $part, 'success' => $success, 'savecount' => ++$_GET['savecount']]];
    }
    exit(json_encode($arr, JSON_UNESCAPED_UNICODE));
}

function create_mysql($data)
{
    $mysql = check_mysql_connection($data['mysqlHost'], $data['mysqlUsername'], $data['mysqlPassword']);
    $mysql->exec("USE {$data['mysqlDatabase']}");
    $backup_sql = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'install.sql');
    $uuid = create_uuid();
    $role_uuid_json = '{"1": "", "2": ""}';
    $password = sha1(md5($data['adminPassword']));
    if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    $register_ip = $ip;
    $time = date('Y-m-d H:i:s');
    $email = '';
    $mobile = '';
    if (filter_var($data['adminUsername'], FILTER_VALIDATE_EMAIL)) {
        $email = $data['adminUsername'];
    }
    if (preg_match('/^1[3456789]{1}\d{9}/', $data['adminUsername'])) {
        $mobile = $data['adminUsername'];
    }
    $backup_sql .= "update la_configs set val='{$data['appid']}' where `key`='api_uuid';";
    $backup_sql .= "update la_configs set val='{$data['app_secret']}' where `key`='api_pwd';";
    $backup_sql .= "update la_configs set val='{$data['bus_uuid']}' where `key`='agent_uuid';";
    $backup_sql .= "update la_configs set val='{$data['bus_pwd']}' where `key`='agent_pwd';";
    $backup_sql .= "update la_configs set val='{$data['webTitle']}' where `key`='web_name';";
    $backup_sql .= "update la_configs set val='{$data['adminPath']}' where `key`='admin_path';";
    $backup_sql .= "update la_configs set val='" . get_server_url() . "' where `key`='domain_index';";
    $backup_sql .= "update la_configs set val='" . get_server_url() . "' where `key`='domain_api';";
    $backup_sql .= "update la_configs set val='" . get_server_url() . "' where `key`='domain_panel';";
    $backup_sql .= "insert into la_users(uuid,role_uuid_json,mobile,email,pwd,created_at,updated_at,deleted_at,register_ip) values ('{$uuid}','{$role_uuid_json}','{$mobile}','{$email}','{$password}','{$time}','{$time}',Null,'{$register_ip}');";
    // $mysql->query($backup_sql);
    $panel = ['index','admin','user'];
    foreach($panel as $v_panel){
        $menu_file = 'resources/views/template/'. $v_panel . '/default/menu.json';
        if (file_exists($menu_file)) {
            $menu = file_get_contents($menu_file);
            if ($menu) {
                $menu = json_decode($menu, true);
                // $dt = date("Y-m-d H:i:s");
                foreach ($menu as $v) {
                    $backup_sql .= "insert into la_menus(uuid,menu_uuid,access_uuid,name,title,keywords,description,url,icon,type,status,note,sort,created_at,updated_at,source) values ('{$v['uuid']}','{$v['menu_uuid']}','{$v['access_uuid']}','{$v['name']}','{$v['title']}','{$v['keywords']}','{$v['description']}','{$v['url']}','{$v['icon']}','{$v['type']}','{$v['status']}','{$v['note']}','{$v['sort']}','{$time}','{$time}',1);";
                }
            }
        }
    }
    $mysql->query($backup_sql);
}

function p($data)
{
    echo '<pre>';
    print_r($data);
    die;
}

function filesort($files, $filename)
{
    $arr = [];
    foreach ($files as $v) {
        if (strpos($v, $filename . '_') !== false) {
            $arr[] = $v;
        }
    }
    function sort_last_digit($a, $b)
    {
        $a_last = intval(substr($a, strrpos($a, "_") + 1));
        $b_last = intval(substr($b, strrpos($b, "_") + 1));
        return $a_last - $b_last;
    }

    usort($arr, 'sort_last_digit');
    return $arr;
}

if (!empty($_POST['ctype'])) {
    header('Content-Type:application/json;charset=utf-8');
    if ($_POST['ctype'] == 1) {
        $savecount = $_POST['savecount'] - 1;
        $filesize = $_SESSION['file_size'];
        $path = $_SESSION['path'];
        $file_name = $_SESSION['file_name'];
        $count = ceil($_SESSION['file_size'] / $offset);
        $hasSize = $_POST['savecount'] * $offset;
        $start = $savecount == 0 ? 0 : $offset * $savecount;
        $offset = $_POST['savecount'] >= $count ? $filesize : $offset + $start - 1;
        if ($_POST['savecount'] <= $count) {
            api_http_download_to_str($path, $file_name . '_' . $_POST['savecount'], $start, $offset);
        }
        $part = intval(($hasSize / $filesize) * 100);
        $success = false;
        $msg = '正在执行安装';
        if ($hasSize >= $filesize) {
            $success = true;
            $msg = '安装完成';
            $filenames = scandir('./', 2);
            $filenames = filesort($filenames, $file_name);
            foreach ($filenames as $name) {
                if ($name != '.' && $name != '..') {
                    if (strpos($name, $file_name) !== false) {
                        $str = file_get_contents($name);
                        file_put_contents($file_name, $str, FILE_APPEND);
                        @unlink($name);
                    }
                }
            }
        }
        exit(json_encode(['code' => 200, 'msg' => $msg, 'data' => ['part' => $part, 'success' => $success, 'savecount' => ++$_POST['savecount']]]));
    } elseif ($_POST['ctype'] == 2) {
        $size = $_POST['size'];
        $tmpfile = $_POST['tmpfile'];
        $part = 0;
        $code = 400;
        $msg = '正在执行安装';
        if (file_exists($tmpfile)) {
            $filesize = filesize($tmpfile);
            $part = round($filesize / $size, 2) * 100;
        }
        if ($part >= 100) {
            $code = 200;
            $msg = '安装完成';
        }
        exit(json_encode(['code' => $code, 'msg' => $msg, 'data' => $part]));
    }
}

if ($STEP === FALSE) redirect("/" . $SCRIPT_NAME . "?step=0");
$STEPS = build_steps();

// header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
// header("Cache-Control: post-check=0, pre-check=0", false);
// header("Pragma: no-cache");

?>
<!DOCTYPE html>
<html class="u-forget">

<head>`
    <meta charset="UTF-8">
    <link rel="shortcut icon" href="https://www.dpqb.com/uploads/article/92c51e86-13ba-d444-c567-c25ab1740c1e.png">
    <title>安装向导 - 怪圈科技</title>
    <meta name="renderer" content="webkit"/>
    <meta name="format-detection" content="telephone=no"/>
    <link href="https://www.dpqb.com/static/install/layui.css" rel="stylesheet">
    <link href="https://www.dpqb.com/static/install/bootstrap.min.css" rel="stylesheet">
    <script src="https://www.dpqb.com/static/install/jquery.min.js"></script>
    <script src="https://www.dpqb.com/static/install/bootstrap.min.js"></script>
    <script src="https://www.dpqb.com/views/plugins/layer/layer.js"></script>
</head>
<style>
    html {
        font-size: 16px;
    }

    body {
        font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
        font-weight: 500
    }

    h1,h2,h3,h4,h5,h6 {
        margin-bottom: 0;
    }

    p {
        margin-top: 0.25em;
        margin-bottom: 0.25em;
    }

    .container {
        max-width: 960px;
        padding-top: 80px;
    }

    .navbar .in .nav li {
        display: block;
        float: none;
        width: 100%;
    }

    .hidden {
        display: none;
    }

    .pre-logs {
        max-height: 480px;
        overflow-y: auto;
        margin: 1em 1em 1em 1em;
    }

    .p {
        font-size: 15px;
        line-height: 30px;
        color: #333;
        padding: 20px;
        border: 10px solid #5298ff;
        border-radius: 5px;
    }

    .layui-container {
        width: 750px;
    }
</style>
<script>
    function next_step() {
        zhezhaoceng = layer.load(1, {shade: [0.5, '#000']})
        $('#button_next').addClass('disabled');
        //$('#spinner').removeClass('hidden');
        var check_form = $('#check_form');
        if (check_form.length !== 0) {
            check_form.submit();
            return;
        }
        var app_form = $('#appform');
        if (app_form.length !== 0) {
            app_form.submit();
            return;
        }
        var user_form = $('#userform');
        if (user_form.length !== 0) {
            user_form.submit();
            return;
        }
        layer.close(zhezhaoceng);
        window.location.href = "/<?= $SCRIPT_NAME ?>?step=<?= $STEP + 1 ?>";
    }
    
    function leart() {
        layer.alert('环境检测不通过，请按照提示修正后点击下一步。', {icon: 2});
    }
</script>

    <body>
        <div class="layui-container">
        <?php if ($STEP == 0) : ?>
            <h3 class="h3 m-5 text-center">安装协议- 怪圈科技</h3>
        <?php endif; ?>
        <?php if ($STEP == 1) : ?>
            <h3 class="h3 m-5 text-center">环境检测- 怪圈科技</h3>
        <?php endif; ?>
        
        <?php if ($STEP == 2) : ?>
            <h3 class="h3 m-5 text-center">授权信息- 怪圈科技</h3>
        <?php endif; ?>
        
        <?php if ($STEP == 3) : ?>
            <h3 class="h3 m-5 text-center">配置信息- 怪圈科技</h3>
        <?php endif; ?>
        
        <?php if ($STEP == 4) : ?>
            <h3 class="h3 m-5 text-center">正在安装- 怪圈科技</h3>
        <?php endif; ?>
        
        <?php if ($STEP == 5) : ?>
            <h3 class="h3 m-5 text-center">完成安装- 怪圈科技</h3>
        <?php endif; ?>
        <?php try {
            $func = $STEPS[$STEP];
            if ($func) {
                call_user_func($func);
            } else {
                redirect("/" . $SCRIPT_NAME . "?step=0");
            } 
            ?>
        
            <div class="d-flex justify-content-center">
                <div class="spinner-border hidden my-3" role="status" id="spinner">
                    <span class="sr-only">Loading...</span>
                </div>
            </div>
        
            <div class="row mb-3">
                <div class="col">
                    <?php if ($STEP > 0 and $STEP < 5) { ?>
                        <a class="btn btn-outline-secondary" href="javascript:history.back()">上一步</a>
                    <?php } ?>
                    <?php if ($STEP < 4) { ?>
                        <?php if ($STEP > 0) { ?>
                            <a class="btn btn-primary float-right" id="button_next"
                               <?php if ($IS_NEXT){ ?>href="javascript:next_step();"<?php } else { ?> style="color:#fff;" onclick="leart()" <?php } ?>>下一步</a>
                        <?php } else { ?>
                            <div style="margin-bottom: 10px;text-align:center; ">
                                <a class="btn btn-primary" id="button_next"
                                   href="javascript:next_step();">同意协议</a>
                            </div>
                        <?php } ?>
                    <?php } ?>
                </div>
            </div>
        <?php } catch (Exception $e) {
            if (trim($e->getMessage()) == 'There is no active transaction') {        //误报没有开启事务的话，刷新该页面即可
                header('location: ' . $_SERVER['HTTP_REFERER']);
            }
        ?>
            <div class="alert alert-danger" role="alert">
                <!-- <p>安装无法继续，请纠正以下错误。</p> -->
                <p><?= $e->getMessage() ?></p>
                <!-- <p>同时请关闭浏览器，重新进入该安装页面</p> -->
            </div>
            <div class="row mb-3">
                <div class="col">
                    <?php if ($STEP > 1) { ?>
                        <a class="btn btn-outline-secondary" href="javascript:history.back()">上一步</a>
                    <?php } ?>
                    <a class="btn btn-outline-primary float-right"
                       href="javascript:window.location.href=window.location.href">重试</a>
                </div>
            </div>
        <?php } ?>
        </div>
    </body>
</html>

<?php
//region 检查系统环境
function check_env()
{
    global $LANG;
    $env_check = array(
        'disable_function' => true,
        'php_version' => true,
        'php_cli_version' => true,
        'php_vs_version' => true,
        'https' => true,
        'www_dir' => true
    );
    $LANG['disable_function'] = 'PHP函数检测通过';
    $LANG['func_check'] = 'PHP函数检查';
    $LANG['php_version'] = 'PHP版本 > 8.0';
    $LANG['php_cli_version'] = 'PHP CLI版本 > 8.0';
    $LANG['php_vs_version'] = 'PHP版本与PHP CLI版本相等';
    $LANG['shell_exec_check'] = 'shell_exec检查';
    $dir = __DIR__;
    $LANG['www_dir'] = '检查当前目录' . $dir . '是否可写';
    $php_version = phpversion();
    //$php_cli_version = shell_exec('php -r "echo PHP_VERSION;"');

    if (strlen(ini_get('disable_functions')) > 0) {
        $env_check['disable_function'] = false;
        $LANG['disable_function'] = '请到php.ini搜索disable_functions并删除所有禁用函数。';
    }

    if (version_compare($php_version, '8.0.0', '<')) {
        $env_check['php_version'] = false;
        $LANG['php_version'] = '当前PHP版本' . $php_version . '低于8.0最低版本要求';
    }

    //$php_cli_version = $env_check['disable_function'] ? shell_exec('php -r "echo PHP_VERSION;"') : '';
    $php_cli_version = $env_check['disable_function'] ? shell_exec('php -r "echo PHP_VERSION;"') : false;

    if ($php_cli_version) {
        if (version_compare($php_cli_version, '8.0.0', '<')) {
            $env_check['php_cli_version'] = false;
            $LANG['php_cli_version'] = '当前PHP CLI命令行版本' . $php_cli_version . '低于8.0最低版本要求，当前PHP CLI命令行版本：' . $php_cli_version;
        }

        if ($php_version != $php_cli_version) {
            $env_check['php_vs_version'] = false;
            $LANG['php_vs_version'] = '当前站点PHP版本与服务器PHP CLI版本不一致，易导致各种问题，请改为一致版本，并且大于PHP8.0以上，当前PHP版本：' . $php_version;
        }
    } else {
        $env_check['php_cli_version'] = false;
        $LANG['php_cli_version'] = 'PHP CLI版本，依赖shell_exec函数，请删除禁用函数。';
        $env_check['php_vs_version'] = false;
        $LANG['php_vs_version'] = 'PHP版本与PHP CLI版本比对，依赖shell_exec函数，请删除禁用函数。';
    }

    if (!writable_check($dir)) {
        $env_check['www_dir'] = false;
        $LANG['www_dir'] = '权限检查失败，确认网站目录' . $dir . '是否可读写';
    }


    // $LANG['php_cli_version'] = 'PHP版本要求 8.0以上';


    // $LANG['php_vs_version'] = 'PHP版本要求 8.0以上';


    $ext_check = extension_check();
    $env_check = array_merge($ext_check, $env_check);

    $LANG['https'] = '站点推荐使用HTTPS';
    if (!is_https()) {
        $env_check['https'] = 'warn';
    }


    return $env_check;
}


/**
 * 检查扩展模块是否加载，并生成$LANG相关文字
 */
function extension_check()
{
    global $LANG;
    $ext_check = array();
    $needed_extensions = array(
        'bcmath', 'ctype', 'curl', 'dom', 'fileinfo', 'gd', 'json', 'mbstring', 'openssl', 'pdo', 'pdo_mysql', 'tokenizer', 'xml', 'zip', 'redis'
    );

    $all_passed = true;
    foreach ($needed_extensions as $ext) {
        if (!extension_loaded($ext)) {
            $all_passed = false;
            $ext_check['extension_' . $ext] = false;
            $LANG['extension_' . $ext] = "PHP扩展要求支持 " . $ext;
        }
    }
    if ($all_passed) {
        $ext_check['extension_all'] = true;
        $LANG['extension_all'] = "PHP扩展检查";
    }

    return $ext_check;
}


function writable_check($dir)
{
    $tmpfile = $dir . "/" . uniqid('test', true);
    if (file_put_contents($tmpfile, "hello") === FALSE) {
        return false;
    }
    if (!file_exists($tmpfile)) {
        return false;
    }
    return unlink($tmpfile);
}

function silent_self_update()
{ ?>
    <div class="jumbotron">
        <h1 class="display-6">怪圈云系统</h1>
        <p class="lead">怪圈云系统是一款免费、开源的企业服务管理系统，请仔细阅读服务协议，并感谢您的支持。</p>
        <hr class="my-4">
        <div style="height: 366px;overflow-y: auto;">
            <p>欢迎您使用怪圈科技服务！</p>
            <p><br></p>
            <p>
                本协议是怪圈科技与您，就您使用怪圈科技服务的相关事项签订的合同。为使用怪圈科技服务，您应当充分阅读、理解本协议，其中限制、免责条款或者其他涉及您重大权益的条款（如违约处罚、争议管辖等）可能会以加粗、加下划线等形式提示您重点注意。</p>
            <p><br></p>
            <p>
                除非您已充分阅读、理解并同意接受和遵守本协议，否则，请您不要使用怪圈科技服务。您通过网页确认或以其他任何方式明示或者默示表示接受本协议，或您以任何方式使用怪圈科技服务的，即视为您已阅读并同意接受本协议的约束，本协议即在您与怪圈科技之间产生法律效力。</p>
            <p><br></p>
            <p>使用怪圈科技服务应当遵守本协议及其服务规则。服务规则以怪圈科技官网或其他相关页面展示的内容为准，您应事先了解服务规则，并根据服务规则进行操作，以确保顺利使用。</p>
            <p><br></p>
            <p>第一条 通则</p>
            <p>1.1 怪圈科技服务指怪圈科技提供的各种产品、服务，您可以根据自己的需求选择使用一项或多项具体服务并遵守其服务规则。</p>
            <p><br></p>
            <p>1.2 涉及具体服务的服务内容、服务等级、技术规范、操作文档、计费标准等内容的服务条款、规则、说明、标准等（统称为“服务规则”），以怪圈科技官网或其他相关页面展示的内容为准。</p>
            <p><br></p>
            <p>1.3 怪圈科技是中立的技术服务提供者，依约向您提供各类技术产品和服务；您的网站、应用、软件、平台等任何产品、服务及相关内容等，由您自行运营并承担全部责任。</p>
            <p><br></p>
            <p>1.4 双方均保证已经依照国家相关规定获得了合法经营资质或政府审批等，有权依法运营其产品及服务。双方进一步保证，在本协议有效期内持续保持具备国家相关规定要求的经营资质或审批手续。</p>
            <p><br></p>
            <p>第二条 账号</p>
            <p>2.1 您应依法具备必要、适当的权利能力和行为能力，按照怪圈科技的要求完成注册、获得怪圈科技服务账号（以下简称“账号”）。</p>
            <p><br></p>
            <p>2.2 为保护账号的安全性和独立性，避免出现账号归属不清晰等不良后果，您应当使用您享有合法权益的微信号、QQ 号、邮箱和微信公众号等进行注册或登录，否则，可能导致您无法正常登录和使用怪圈科技服务。</p>
            <p><br></p>
            <p>2.3
                您应当按照怪圈科技服务流程填写、提交真实、合法、有效的资料（统称“客户资料”），包括但不限于名称、联系人、电子邮箱、联系电话、联系地址、工商登记证件等；如果客户资料发生变更的，您应及时书面通知怪圈科技或根据怪圈科技的规则自行进行更新。</p>
            <p><br></p>
            <p>2.4
                本协议效力适用于您名下全部账号。账号将作为您使用怪圈科技服务的身份识别依据，您应当对用户名、密码等信息采取必要、有效的保密和安全保护措施（包括但不限于：保管使用权限、设置高强度密码和定期更换措施等），否则，导致的后果由您自行承担。此外，您应为账号下的行为负责，所有账号下的操作行为均被视为您实施，且应由您承担全部法律后果。</p>
            <p><br></p>
            <p>2.5
                您需自行建立健全内部管理制度，规范对账号的使用与管理。为保障您的权益，账号应仅供您自行使用，若您基于自身经营需要等原因，将账号授权您的员工或他人管理的，须做好权限管控，并且在遇到人员变动时及时完成交接和账号安全保护（例如修改密码、变更登录方式、设置账号保护等）。</p>
            <p><br></p>
            <p>2.6 为保护账号和业务等的安全，您应依照国家相关规定及怪圈科技流程、制度进行实名认证。您同意授权怪圈科技通过第三方核实您提交的相关信息或资料。</p>
            <p><br></p>
            <p>2.7
                实名认证是对账号归属以及责任承担等进行判断的依据，在发生账号归属争议等纠纷时，怪圈科技有权认定该账号归属于实名认证主体；对于归属存在争议的账号，怪圈科技有权暂时对该账号进行冻结。您在进行认证时务必谨慎对待，给与足够的重视并确保认证主体与账号使用主体保持一致，避免将企业使用的账号认证在个人名下，或将本人使用的账号认证在他人名下等任何不当认证行为。</p>
            <p><br></p>
            <p>2.8
                若您发现有他人盗用您的账号及密码、或任何其他未经您合法授权的情形时，您应立即以有效方式通知怪圈科技并提供必要资料（如客户资料、情况说明、证明材料及诉求等，以便怪圈科技核实身份及事件）。怪圈科技收到您的有效通知并核实身份后，会依据法律法规及服务规则进行处理。怪圈科技依据本条进行处理产生的相关责任和后果由您承担。</p>
            <p>
                若您提供的资料存在瑕疵，导致怪圈科技无法核实您的身份或无法判断您的需求等，而导致怪圈科技未能及时处理，给您带来的损失，应由您自行承担。同时，您理解，怪圈科技对您的请求进行处理需要合理期限，对于怪圈科技采取措施前您已经产生的损失以及采取措施后因不可归责于怪圈科技的原因导致的损失，怪圈科技不承担任何责任。</p>
            <p><br></p>
            <p>第三条 服务</p>
            <p>3.1 服务开通</p>
            <p>3.1.1 您可根据自身需求，自行通过怪圈科技官网在线选购所需服务，购买前您需仔细阅读所购服务对应的服务规则并根据自身需求决定是否购买或使用。双方也可根据实际合作需要，另行签订协议等。</p>
            <p><br></p>
            <p>3.1.2 部分怪圈科技服务的开通可能需要双方另行签订单独的服务协议，单独的服务协议可能以电子文档形式展示，也可能是独立的纸质文档形式展示，您可以根据自身情况决定是否接受服务协议及开通服务。</p>
            <p><br></p>
            <p>3.1.3 您需在订单提交后及时完成支付。部分服务可能有时间限制、库存限制或者活动数量等限制，订单提交后，若发生您未及时付款、或付款期间出现数量不足或已达到限量等情况的，您将可能无法使用相关服务。</p>
            <p><br></p>
            <p>3.1.4
                怪圈科技可能因营销活动、产品推广等各种原因，在特定时期内推出“限时免费”、“限时优惠”、“限量优惠”、“充值优惠”以及赠送服务等优惠措施（以下统称“优惠措施”），您理解并同意，这些优惠措施可能是暂时性、阶段性或有数量限制的，也可能仅适用于满足特定条件的客户，您需要按照相应的规则购买、使用相应服务。除非另有书面明确说明，优惠措施不可同时叠加适用。</p>
            <p><br></p>
            <p>3.2 服务费用</p>
            <p>3.2.1
                怪圈科技服务的结算方式可能分为预付费和后付费等类型，为保证服务及时开通或持续提供，您应当遵守本协议及您使用的服务的服务规则并及时缴纳费用。部分怪圈科技服务开通后（例如云服务器、云数据库等），即使您未新增服务项目或资源，亦未进行新的操作，但由于该部分服务会持续占用资源，因此将持续产生扣费，您应当及时续费或关闭服务。</p>
            <p><br></p>
            <p>3.2.2
                优惠措施是基于特定条件设置，例如针对特定配置的产品的优惠措施、您需一次性使用特定期限或数量的产品方可享受的优惠措施等（如包年优惠），若您最终未符合特定条件，则无法享受相应的优惠（包括但不限于折扣、代金券赠与、优惠使用其他服务等），双方需按照购买时相应服务的官网原价进行费用结算。</p>
            <p><br></p>
            <p>3.2.3 您可以通过账号在线付款或充值续费，也可以通过银行转账方式向怪圈科技支付费用（为保证服务的持续性，若您选择线下支付费用的，应预留合理时间以便怪圈科技核实到账情况并完成您账号充值）。</p>
            <p><br></p>
            <p>3.2.4
                对于按自然月结算的服务，怪圈科技向您提供上一月的缴费账单后，您须在5个工作日内予以核对确认或提出异议。如怪圈科技未在5个工作日内收到您的确认或异议，视为您无异议；您如有异议，由双方友好协商解决，如协商不成以怪圈科技系统数据为准。怪圈科技根据双方最后确认的金额开具发票。您收到怪圈科技发票后在10个工作日内付费。您使用的服务对应的服务规则与本条约定不一致或双方另有约定的除外。</p>
            <p><br></p>
            <p>3.2.5
                本协议项下的业务发生销售折让、销售退回或其他按照国家规定需要开具红字发票或重新开票的情况，怪圈科技需按照国家税收规定向您开具红字发票或重新开票，您需按照国家税收规定退回怪圈科技已开具的发票或向税局递交需怪圈科技开具红字专用发票的有效证明。双方约定具体按以下政策执行：</p>
            <p>（1）如果退票发生在发票开具当月且您尚未进行税务认证抵扣的，您退回发票即可。</p>
            <p>（2）如果您已就该发票进行税务认证抵扣，或者退票时间已超过开票日期所在当月的，您应向怪圈科技提供开具红字发票的必要资料，如《开具红字增值税专用发票信息表》等。</p>
            <p>（3）对于怪圈科技尚未开具发票或已开具发票但尚未交付给您的退款申请，无需您提供发票相关资料。</p>
            <p>
                若无法满足上述条件，则无法办理退款，后果由您自行承担，怪圈科技不就此承担任何责任。在完成上述退票及开具红字发票流程后，怪圈科技将在次月内按照您实际消费数额重新开具发票，并将您账号内现金部分剩余款项进行退款。</p>
            <p><br></p>
            <p>3.3 服务支持</p>
            <p>3.3.1 怪圈科技向您提供售后服务，协助您解答、处理使用怪圈科技服务过程中遇到的问题。</p>
            <p><br></p>
            <p>3.3.2
                怪圈科技将依照法律法规要求对其系统、设备等采取基础的安全保护措施。若您对安全保护措施的要求高于前述基础的安全保护措施标准的，您有权根据自身需求购买配置更高的安全保护服务或另行配置其他安全防护软件、系统等。</p>
            <p><br></p>
            <p>3.3.3 您应自行对您使用的计算机信息系统、设备等采取必要的、有效的安全保护措施，因您未采取前述措施导致权益受损的，由您自行承担责任。</p>
            <p><br></p>
            <p>3.3.4 怪圈科技在服务规则约定内提供可用性保障。如果您对可用性的要求高于服务规则，则需要您主动对自身系统进行高可用性的设置，怪圈科技可给与必要的协助。如果需要怪圈科技配合做设计，由双方另行协商确认。</p>
            <p><br></p>
            <p>3.4 服务中止或终止</p>
            <p>3.4.1
                为了向您提供更加完善的服务，怪圈科技有权定期或不定期地对服务平台或相关设备、系统、软件等进行检修、维护、升级及优化等（统称“常规维护”），如因常规维护造成怪圈科技服务在合理时间内中断或暂停的，怪圈科技无需为此向您承担责任。但是，怪圈科技应当至少提前24小时，就常规维护事宜通知您。若因不可抗力、基础运营商过错等原因导致的非常规维护，怪圈科技应及时通知您。</p>
            <p><br></p>
            <p>3.4.2
                为保证服务的安全性和稳定性，怪圈科技可能进行机房迁移、设备更换等重大调整，前述情况可能导致怪圈科技服务在合理时间内中断或暂停，怪圈科技无需为此向您承担责任，但是，怪圈科技应提前30天通知您，您应予以配合；如您不配合进行调整，或者怪圈科技无法与您取得联系，由此产生的后果由您自行承担。</p>
            <p><br></p>
            <p>3.4.3
                如您购买的具体服务含有存储功能的，在该服务到期或终止后，对于您存储在该服务中的数据等任何信息，怪圈科技将根据该服务的服务规则为您保留相应期限。您应承担保留期限内产生的费用（若有），并按时结清费用、完成全部数据的迁移。保留期限届满后，您的前述信息将被删除。</p>
            <p><br></p>
            <p>3.4.4
                怪圈科技有权根据自身运营安排，随时调整、终止部分或全部服务（包括但不限于对服务进行下线、迭代、整合等）。但是，怪圈科技应提前至少30天通知您，以便您做好相关数据的转移备份以及业务调整等，以保护您的合法权益。</p>
            <p><br></p>
            <p>3.5
                基于网络服务的及时性、复杂性、高效性等特性及监管要求、政策调整等原因，您同意怪圈科技可以不时对本协议以及怪圈科技的相关服务规则进行调整，并通过网站公告、邮件通知、短信通知、系统消息、站内信等方式中的一种或多种予以公布；若您在调整后继续使用怪圈科技服务的，表示您已充分阅读、理解并接受修改后的内容，也将遵循修改后的内容。</p>
            <p><br></p>
            <p>3.6 若您选择使用中国大陆以外的服务，应当确保您符合中国大陆法律法规、政策等的要求，同时，也应当确保您的资质、能力以及使用行为等均符合当地法律法规、政策等的要求。</p>
            <p><br></p>
            <p>3.7 第三方产品或服务</p>
            <p>3.7.1 如果您通过怪圈科技平台获取、使用第三方提供的任何产品或服务（包括但不限于怪圈科技服务市场中由服务商等第三方提供的产品、服务），您应当自行评估该产品或服务是否符合您要求。</p>
            <p><br></p>
            <p>3.7.2 第三方产品或服务的开通，可能需要您与第三方另行签订单独的协议，单独的协议可能以电子文档形式展示，也可能是独立的纸质文档，您可以根据自身情况决定是否接受协议及使用产品或服务。</p>
            <p><br></p>
            <p>3.7.3 您因使用第三方产品或服务产生的纠纷由您与第三方自行解决。</p>
            <p><br></p>
            <p>第四条 客户权利义务</p>
            <p>4.1 您有权依照本协议约定使用怪圈科技服务并获得怪圈科技的技术支持和售后服务。</p>
            <p><br></p>
            <p>4.2 您在使用怪圈科技平台上的服务时须遵守相关法律法规及服务规则，并确保拥有法律法规要求的经营资质和能力，不得实施包括但不限于以下行为，也不得为任何违反法律法规的行为提供便利：</p>
            <p>4.2.1 反对宪法所规定的基本原则的。</p>
            <p>4.2.2 危害国家安全，泄露国家秘密，颠覆国家政权，破坏国家统一的。</p>
            <p>4.2.3 损害国家荣誉和利益的。</p>
            <p>4.2.4 煽动民族仇恨、民族歧视，破坏民族团结的。</p>
            <p>4.2.5 破坏国家宗教政策，宣扬邪教和封建迷信的。</p>
            <p>4.2.6 散布谣言，扰乱社会秩序，破坏社会稳定的。</p>
            <p>4.2.7 散布淫秽、色情、赌博、暴力、凶杀、恐怖或教唆犯罪的。</p>
            <p>4.2.8 侮辱或诽谤他人，侵害他人合法权益的。</p>
            <p>4.2.9 实施任何违背“七条底线”的行为。</p>
            <p>4.2.10 含有法律、行政法规禁止的其他内容的。</p>
            <p><br></p>
            <p>4.3 您在使用怪圈科技平台上的服务时须维护互联网秩序和安全，不得侵犯任何主体的合法权益，不得实施包括但不限于以下行为，也不得为其提供便利：</p>
            <p>4.3.1 实施诈欺、虚伪不实或误导行为，或实施侵害他人知识产权等任何合法权益的行为，如“私服”、“外挂”等。</p>
            <p>4.3.2 发布、传播垃圾邮件（SPAM）或包含危害国家秩序和安全、封建迷信、淫秽、色情、低俗等违法违规信息。</p>
            <p>4.3.3 违反与怪圈科技网络相联通之网络、设备或服务的操作规定；实施违法或未授权之接取、盗用、干扰或监测。</p>
            <p>4.3.4 实施任何破坏或试图破坏网络安全的行为，包括但不限于以病毒、木马、恶意代码、钓鱼等方式，对网站、服务器进行恶意扫描、非法侵入系统、非法获取数据等。</p>
            <p>4.3.5
                实施任何改变或试图改变怪圈科技服务提供的系统配置或破坏系统安全的行为；利用技术或其他手段破坏、扰乱怪圈科技服务的运营或他人对怪圈科技服务的使用；以任何方式干扰或企图干扰怪圈科技任何产品或任何部分、功能的正常运行，或者制作、发布、传播上述工具、方法等。</p>
            <p>4.3.6 因从事包括但不限于“DNS 解析”、“安全服务”、“域名代理”、“反向代理”等任何业务，导致您自己频繁遭受攻击（包括但不限于 DDoS
                攻击）且未及时更正行为，或未根据怪圈科技要求消除影响，从而对怪圈科技服务平台或他人产生影响的。</p>
            <p>4.3.7 实施其他破坏互联网秩序和安全的行为。</p>
            <p><br></p>
            <p>4.4 您应当按照服务规则及时、足额支付费用。若您未及时、足额支付费用的，怪圈科技有权拒绝开通服务或无需另行通知而中止、终止服务，同时可以采取以下一项或多项措施：</p>
            <p>4.4.1 要求您除应依约支付应付费用外，每逾期一天，还应按所欠费用1‰的标准向怪圈科技支付违约金，直至缴清全部费用为止。</p>
            <p>4.4.2 若您逾期付款超过15天，怪圈科技有权无需另行通知您即可随时采取包括但不限于提前单方解除协议的措施。</p>
            <p>4.4.3 若您逾期付款但您使用了预付费服务或您账号有未消耗的现金余额的，则怪圈科技有权无需另行通知您，而直接将预付费用和现金余额用于抵扣拖欠款项和违约金。</p>
            <p>4.4.4 删除您基于使用怪圈科技服务而存储或产生的部分或全部信息和数据。</p>
            <p><br></p>
            <p>第五条 怪圈科技权利义务</p>
            <p>5.1 怪圈科技应当依照本协议约定向您提供怪圈科技服务和售后支持。</p>
            <p><br></p>
            <p>5.2 怪圈科技仅对怪圈科技服务本身提供运营维护，您应当保证自身的网络、设备的安全性、稳定性，如发生以下情况，您应及时解决并避免对怪圈科技服务产生影响：</p>
            <p>5.2.1 您内部网络出现问题，包括但不限于超负荷等。</p>
            <p>5.2.2 您自有设备或您使用的第三方设备出现故障。</p>
            <p>5.2.3 您自行拆离设备或通过其他方式导致网络中断。</p>
            <p>5.2.4 其他您自身原因导致的任何故障、网络中断等。</p>
            <p><br></p>
            <p>5.3 若怪圈科技自行发现或根据相关部门的信息、权利人的投诉等发现您可能存在违反相关法律法规或本协议的行为的，怪圈科技有权根据一般人的认识自行独立判断，并随时单方采取以下措施中的一种或多种：</p>
            <p>5.3.1 要求您立即删除、修改相关内容。</p>
            <p>5.3.2 限制、暂停向您提供全部或部分怪圈科技服务（包括但不限于直接对您的部分服务进行下线并收回相关资源、对您账号采取操作限制/账号冻结等措施）。</p>
            <p>5.3.3 终止向您提供怪圈科技服务，终止协议（包括但不限于直接对您的全部服务进行下线并收回相关资源等）。</p>
            <p>5.3.4 怪圈科技根据本协议终止向您提供服务或终止协议的，您预缴的费用将作为违约金归怪圈科技所有。</p>
            <p>5.3.5 依法追究您的其他责任。</p>
            <p>
                怪圈科技依据本协议采取相应措施（包括但不限于暂停服务、扣除费用、终止协议等），不视为怪圈科技违约，若因此给您造成损失（包括但不限于业务暂停、数据清空等）的，均由您自行承担。因您违反本协议约定产生的责任和后果由您自行承担，若给怪圈科技或第三方造成损失的，您应当予以赔偿。</p>
            <p><br></p>
            <p>5.4
                为合理保护您、您的用户及权利人等各方的利益，怪圈科技有权制定专门的侵权、投诉流程制度，您应当予以遵守。如果怪圈科技接到第三方对您的投诉或举报，怪圈科技有权向第三方披露您相关资料（如您的主体资料及您就投诉或举报提交的反通知书、相关证据等全部资料），要求您与投诉方进行协商（包括但不限于建立包含您、怪圈科技以及投诉方的三方邮件组，供您、投诉方直接沟通、相互举证等，下同），若您投诉或举报其他怪圈科技客户的，怪圈科技也有权向被投诉方披露您相关资料（如您的主体资料及您就投诉或举报提交的通知书、相关证据等全部资料），要求您与被投诉方进行协商，以便及时解决投诉、纠纷，保护各方合法权益，您应当予以配合，否则，可能会影响您继续使用怪圈科技服务，由此造成您或他方损失的，您自行承担。</p>
            <p><br></p>
            <p>5.5 怪圈科技可将本协议部分或全部权利义务转让予第三方，但怪圈科技须提前90天书面通知您。为本款生效之需要，双方同意签订所有合理必要的文件及采取合理必要的措施。</p>
            <p><br></p>
            <p>5.6 您同意怪圈科技有权使用您的名称、品牌、商标标识等作为商业案例进行宣传、展示。</p>
            <p><br></p>
            <p>第六条 客户数据</p>
            <p>6.1 您保证，您存储、上传到怪圈科技服务中，或者利用怪圈科技服务以分析、分发等任何方式处理的数据，为您依法收集、获取或产生的数据，您不会也不曾以任何方式侵犯任何个人或实体的合法权利。</p>
            <p><br></p>
            <p>6.2
                您保证其有权使用怪圈科技服务对前述数据进行存储、上传、分析和分发等任何处理，且前述处理活动均符合相关法律法规的要求，不存在任何违法、侵权或违反其与第三方的合同约定的情形，不会将数据用于违法违规目的。</p>
            <p><br></p>
            <p>6.3 您有权自行使用怪圈科技服务对数据进行上传、分析、删除、更改等处理（具体以您使用的服务的服务规则为准），就数据的删除、更改等处理，您应谨慎操作并承担因该等操作所产生的后果。</p>
            <p><br></p>
            <p>6.4 除因您使用怪圈科技服务所需及法律法规另有规定外，未经您同意，怪圈科技不会接触或使用您的数据。</p>
            <p><br></p>
            <p>6.5 您应根据自身需求自行对数据进行备份，怪圈科技仅依据相关法律法规要求或服务规则约定提供数据备份服务，怪圈科技仅在法定或约定提供的数据备份服务的范围内承担责任。</p>
            <p><br></p>
            <p>6.6
                因您的数据的产生、收集、处理、使用等任何相关事项存在违反法律法规等情况而造成的全部结果及责任均由您自行承担，并且，怪圈科技有权随时全部或部分终止向您提供怪圈科技服务。您因此遭受的一切损失或承担的一切责任和费用，由您自行承担。</p>
            <p><br></p>
            <p>第七条 知识产权</p>
            <p>7.1 双方各自享有的商标权、著作权或者其他知识产权，均仍归各方单独享有，并不会因为双方签订或者履行本协议而转归对方享有，或者转归双方共同享有。</p>
            <p><br></p>
            <p>7.2 任何一方均应尊重相对方、第三方的知识产权，如有任何第三方就一方侵犯其知识产权等合法权益的原因向另一方提起诉讼、主张索赔的，责任方应当独立处理相关纠纷，赔偿另一方的直接经济损失，并使另一方免责。</p>
            <p><br></p>
            <p>第八条 保密信息</p>
            <p>8.1 双方为了本协议目的，已经或将会提供或透露某些保密信息。其中，披露保密信息的一方为“披露方”，而接受保密信息的一方为“接收方”。</p>
            <p><br></p>
            <p>8.2
                “保密信息”指由披露方持有的与其业务、经营、技术及权利等事项相关的，非公开的信息、资讯、数据、资料等，包括但不限于营业规划，商务资料，与技术有关之知识及信息、创意、设想、方案，提供的物品或厂商资料，用户信息，人事资料，商业计划，服务价格及折扣，财务状况等。</p>
            <p><br></p>
            <p>8.3
                接收方从披露方所获悉的信息，如有标明或可合理认知为属于披露方的保密信息的，接收方须对披露方的保密信息保密，未经披露方书面同意，不得以任何方式披露给第三方或用于本协议以外目的。接收方应以对待其自身保密信息相同的注意程度（且不得低于合理审慎义务）对待披露方的保密信息。</p>
            <p><br></p>
            <p>8.4 尽管有前述约定，符合下列情形之一的，相关信息不被视为保密信息：</p>
            <p>8.4.1 接收方在披露方向其披露之前已经通过合法的渠道或方式持有的信息。</p>
            <p>8.4.2 该信息已经属于公知领域，或该信息在非因接收方违反本协议的情况下而被公开。</p>
            <p>8.4.3 接收方合法自其他有权披露资料的第三方处知悉且不负有保密义务的信息。</p>
            <p>8.4.4 由接收方不使用或不参考任何披露方的保密信息而独立获得或开发的。</p>
            <p><br></p>
            <p>8.5
                如果接收方基于法律法规或监管机关的要求，需要依法披露披露方的保密信息的，不视为违反本协议，但接收方应当在法律许可的范围内尽快通知披露方，同时，接收方应当努力帮助披露方有效限制该保密信息的披露范围，保护披露方合法权益。</p>
            <p><br></p>
            <p>8.6 双方保密义务在本协议有效期限内及期限届满后持续有效，直至相关信息不再具有保密意义。</p>
            <p><br></p>
            <p>8.7 一旦发生保密信息泄露事件，双方应合作采取一切合理措施避免或者减轻损害后果的产生；如因接收方违反保密义务给披露方造成损失的，接收方应赔偿因此给披露方造成的直接经济损失。</p>
            <p><br></p>
            <p>8.8 怪圈科技会按照公布的《隐私声明》的规定保护您的相关信息。</p>
            <p><br></p>
            <p>第九条 出口管制与制裁法律合规</p>
            <p>
                各方承诺遵守所有适用的经济与贸易制裁以及出口管制法律法规，包括所有由联合国安全理事会、中国、美国及任何其他国家所制定并执行的制裁决议、法律与法规以及出口管制法律与法规（在前述文件适用于该方的范围内）（下称“适用出口管制法律”）。您承诺不会将怪圈科技提供的产品或服务用于适用出口管制法律所禁止的用途。非经相关主管机关许可，您及您授权使用怪圈科技提供的产品或服务的个人或实体不会通过怪圈科技提供的产品或服务向所适用出口管制法律所制裁或指定的个人或实体提供受控的技术、软件或服务，或以任何方式使得怪圈科技违反适用出口管制法律。</p>
            <p><br></p>
            <p>第十条 责任限制</p>
            <p>10.1 您理解并同意，在使用怪圈科技服务的过程中可能会遇到以下情况使服务发生中断。出现下述情况时，怪圈科技应及时与相关单位配合进行修复，但是由此给您造成的损失怪圈科技将予以免责。</p>
            <p>10.1.1 不可抗力，包括但不限于自然灾害、政府行为、法律法规颁布调整、罢工（任一方内部劳资纠纷除外）、动乱等不能预见、不能避免并不能克服的客观情况。</p>
            <p>10.1.2 基础运营商原因，包括但不限于电信部门技术调整、电信/电力线路被他人破坏、电信/电力部门对电信网络/电力资源进行安装、改造、维护。</p>
            <p>10.1.3 网络安全事故，如计算机病毒、木马或其他恶意程序、黑客攻击的破坏。</p>
            <p>10.1.4 您通过非怪圈科技授权的方式使用怪圈科技服务，您操作不当或您的电脑软件、系统、硬件和通信线路出现故障。</p>
            <p>10.1.5 其他非怪圈科技过错、怪圈科技无法控制或合理预见的情形。</p>
            <p><br></p>
            <p>10.2
                因不可抗力、基础运营商原因、网络安全事故或其他超出当事人可合理掌控范围的事件，造成本协议迟延履行或任何一方违约，双方均无需承担违约责任。但是，受影响一方应尽可能及时通知另一方。如前述事件妨碍协议履行达30天以上的，任一方可提前15天书面通知对方终止协议。因本条款终止协议的，任何一方均无须承担违约责任。</p>
            <p><br></p>
            <p>10.3
                您理解并同意，怪圈科技的服务是按照现有技术和条件所能达到的现状提供的。怪圈科技将尽最大努力确保服务的连贯性和安全性，但怪圈科技不能保证其所提供的服务毫无瑕疵，因此，即使怪圈科技提供的服务存在瑕疵，但若上述瑕疵是当时行业技术水平所无法避免的，其将不视为怪圈科技违约，怪圈科技也无需承担任何责任，双方应友好协作共同解决问题。</p>
            <p><br></p>
            <p>10.4
                于任何情形下，任一方均不对另一方之任何间接的、偶然的、特殊的或惩罚性的损害和损失（如利润损失、机会损失、向第三方支付的费用、声誉/商誉损失或损害等）承担责任，无论基于合同、保证、侵权或任何其他责任理论，不论任一方是否知道或应当知道上述损失或损害的可能性。</p>
            <p><br></p>
            <p>10.5
                于任何情形下，怪圈科技基于本协议及相关订单和怪圈科技服务向您所承担的赔偿责任（无论基于合同、侵权或任何其他责任理论）的总额，不超过您就造成您损失的怪圈科技服务已经向怪圈科技支付的费用总额；如果造成您损失的相应怪圈科技服务的服务期限超过12个月的，则怪圈科技的最大赔偿责任不超过损害发生前12个月，您就造成您损失的怪圈科技服务已经向怪圈科技支付的费用总额（为免歧义，本处费用指您就实际使用该服务的时长/数量等而实际已支付的现金，不包括代金券、预付但未实际消耗的费用等）。若本条款与双方其他约定或怪圈科技服务规则冲突或不一致的，以本条约定为准。</p>
            <p><br></p>
            <p>第十一条 通知和送达</p>
            <p>11.1
                您应当保证和维持客户资料（包括但不限于电话号码、电子邮箱等联系方式）的有效性，客户资料若存在虚假、无效等任何可能导致您无法及时获悉业务通知、服务提示、客户服务、技术支持、纠纷协调、违规处罚等信息的，由您自行承担相应责任。</p>
            <p><br></p>
            <p>11.2 您应当根据怪圈科技官网公布的怪圈科技的联系方式向怪圈科技发送通知，双方另有约定除外。</p>
            <p><br></p>
            <p>11.3
                怪圈科技可通过网页公告、系统通知、站内信、电子邮件、手机短信、即时通讯工具、函件等方式中的一种或多种向您发送与怪圈科技服务有关的业务通知、服务提示、验证消息、营销信息等各种信息（包括但不限于更新后的服务规则、服务升级、机房裁撤、广告等）。前述信息在以下情况下视为已送达：</p>
            <p>11.3.1 交专人递送的，在收件人签收时视为已送达。</p>
            <p>11.3.2 以网页公告等形式公布的，一经公布即生效（另有说明除外）。</p>
            <p>11.3.3 以电子形式（包括系统通知、站内信、电子邮件、手机短信、即时通讯工具等）发送的，在发送成功后视为已送达。</p>
            <p>11.3.4 以邮资预付的快递公司递送或以挂号信递送的，以投邮后的第3个自然日视为已送达。</p>
            <p>如果送达时间为法定节假日的，则以送达后首个工作日为送达日。</p>
            <p><br></p>
            <p>第十二条 法律适用及争议解决</p>
            <p>12.1 本协议的签订地为广东省深圳市南山区。</p>
            <p><br></p>
            <p>12.2 本协议的成立、生效、履行、解释及纠纷解决等，均适用中国大陆法律法规（不包括冲突法）。</p>
            <p><br></p>
            <p>12.3 因本协议产生之争议，双方应首先协商解决；双方未能协商解决的，任何一方均应将争议提交本协议签订地有管辖权的人民法院裁决。双方无争议的部分，应当继续履行。</p>
            <p><br></p>
            <p>第十三条 其他</p>
            <p>13.1 除非另有说明，本协议正文及其附件中所有的“天”均为自然日，结算货币均为人民币。</p>
            <p><br></p>
            <p>13.2 本协议的拟定、解释均以中文为准。除双方另有约定外，任何有关本协议的翻译不得作为解释本协议或判定双方当事人意图之依据。</p>
            <p><br></p>
            <p>13.3 服务规则为本协议的重要组成部分，与本协议正文具有同等法律效力，您应当予以遵守。（正文完）</p>
        </div>
    </div>
<?php }

function check_env_and_extension()
{
    global $SCRIPT_NAME, $STEP, $LANG, $IS_NEXT;
    // echo $SCRIPT_NAME;
    // echo $check_ready;
    // if(!$check_ready){
    //     header('"location:".$SCRIPT_NAME."?step=0"');
    // }
    $appid = get_var('appid');
    $app_secret = get_var('app_secret');
    $env_check = check_env();
    $check_all = true; ?>
    <form action="<?= $SCRIPT_NAME ?>?step=<?= $STEP + 1 ?>" id="check_form" method="post">
        <input type="hidden" id="appid" name="appid" value="<?= $appid ?>">
        <input type="hidden" id="app_secret" name="app_secret" value="<?= $app_secret ?>">
    </form>
    <ul class="list-group my-3">
        <?php foreach ($env_check as $chk => $result) {
            if (!$result) $check_all = false;
            ?>
            <li class="list-group-item d-flex justify-content-between align-items-center">
                <div> <?= $LANG[$chk] ?> </div>
                <?php if ($result === 'warn') { ?>
                    <span class="badge badge-warning">警告</span>
                <?php } else if ($result) { ?>
                    <span class="badge badge-primary">成功</span>
                <?php } else {
                    $IS_NEXT = false; ?>
                    <span class="badge badge-danger">失败</span>
                <?php } ?>
            </li>
        <?php } ?>
    </ul>
    <?php
    // if (!$check_all) throw new Exception('环境检查失败，请按要求确认PHP版本，启用PHP扩展与函数。');
}

function app_check()
{
global $SCRIPT_NAME, $STEP;

$action = get_var('action');
$appid = get_var('appid');
$app_secret = get_var('app_secret');
$appid_invalid = $action && !$appid;
$app_secret_invalid = $action && !$app_secret;
$app_invalid = false;
$check_ready = false;
$app_invalid_msg = '';

if ($action == 1 && !$appid_invalid && !$app_secret_invalid) {
    $app_check = app_post($app_secret, $appid);
    if ($app_check['code'] == 200) {
        $check_ready = true;
        // $check_ready ='222';
        // $STEP += 1;
        // auto_next_step();
    } else {
        $app_invalid = true;
        // $check_ready ='333';
        $app_invalid_msg = $app_check['msg'] ?? '未知错误，请咨询客服';
    }
}
if ($check_ready) {
    ?>
    <div class="alert alert-success" role="alert">
        <p>校验成功</p>
        <p>正在跳转进入安装过程</p>
    </div>
    <?php
    $STEP += 1;
    auto_next_step();
} else { ?>

<?php } ?>
<form action="<?= $SCRIPT_NAME ?>?step=<?= $STEP ?>" id="appform" method="post" class="layui-form layui-form-pane">
    <input type="hidden" name="action" value="<?= $check_ready ? 0 : 1 ?>"/>
    <div class="layui-form-item">
        <label class="layui-form-label" style="width:114px;">怪圈API编号</label>
        <div class="layui-input-block" style="margin-left:114px;">
            <input type="text" placeholder="填写www.dpqb.com的API信息"
                   class="layui-input <?= $appid_invalid ? "is-invalid" : "" ?>"
                   name="appid" value="<?= $appid ?>" required>
            <?php if ($action && !$appid) { ?>
                <div class="invalid-feedback">怪圈API编号不能为空</div>
            <?php } ?>
        </div>
    </div>
    <div class="layui-form-item">
        <label class="layui-form-label" style="width:114px;">怪圈API密码</label>
        <div class="layui-input-block" style="margin-left:114px;">
            <input type="text" placeholder="填写www.dpqb.com的API信息"
                   class="layui-input <?= $app_secret_invalid || $app_invalid ? "is-invalid" : "" ?>" name="app_secret"
                   value="<?= $app_secret ? $app_secret : "" ?>" required>
            <?php if ($action && !$app_secret) { ?>
                <div class="invalid-feedback">怪圈API密码不能为空</div>
            <?php } ?>
            <?php if ($app_invalid) { ?>
                <div class="invalid-feedback"><?= $app_invalid_msg; ?></div>
            <?php } ?>
        </div>
    </div>
    <?php
    }

    function show_init_form()
    {
        global $SCRIPT_NAME, $STEP;

        // $action == 1 表示是提交的表单
        $action = get_var('action');

        $webTitle = get_var('webTitle');
        $mysqlHost = get_var('mysqlHost');
        $mysqlDatabase = get_var('mysqlDatabase');
        $mysqlUsername = get_var('mysqlUsername');
        $mysqlPassword = get_var('mysqlPassword');
        $redisHost = get_var('redisHost');
        $redisPassword = get_var('redisPassword');
        $tablePrefix = get_var('tablePrefix');
        $adminUsername = get_var('adminUsername');
        $adminPassword = get_var('adminPassword');
        $adminPath = get_var('adminPath');
        $adminPasswordConfirmation = get_var('adminPasswordConfirmation');
        $appid = get_var('appid');
        $app_secret = get_var('app_secret');

        // 判断每个字段是否合法
        $webTitleInvalid = $action && !$webTitle;
        $mysqlHostInvalid = $action && !$mysqlHost;
        $mysqlDatabaseInvalid = $action && !$mysqlDatabase;
        $mysqlUsernameInvalid = $action && !$mysqlUsername;
        $mysqlPasswordInvalid = $action && !$mysqlPassword;
        $redisHostInvalid = $action && !$redisHost;
        $redisPasswordInvalid = $action && !$redisPassword;
        $tablePrefixInvalid = $action && $tablePrefix && !preg_match("/^\w+$/", $tablePrefix);
        $adminUsernameInvalid = $action && (!filter_var($adminUsername, FILTER_VALIDATE_EMAIL) && !preg_match('/^1[3456789]{1}\d{9}/', $adminUsername));
        $adminPasswordInvalid = $action && (!$adminPassword || !$adminPasswordConfirmation || ($adminPasswordConfirmation != $adminPassword));
        $adminPathInvalid = $action && !preg_match("/^[a-z0-9]+$/i", $adminPath);

        // 需要检查数据库连接
        $mysqlConnectCheck = $action && !$mysqlHostInvalid && !$mysqlUsernameInvalid && !$mysqlPasswordInvalid;
        $redisConnectCheck = $action && !$redisHostInvalid && !$redisPasswordInvalid;

        $mysqlVersionInvalid = true;
        $mysqlConnectInvalid = true;
        $mysqlUserPassInvalid = true;
        $mysqlDatabaseDbInvalid = true;
        $mysqlDatabaseDbInvalidMsg = "";
        $mysqlVersionInvalidMsg = "";

        if ($mysqlConnectCheck) {
            $r = check_mysql_connection($mysqlHost, $mysqlUsername, $mysqlPassword);
            $mysqlConnectInvalid = ($r === -1) || $r === false;
            $mysqlUserPassInvalid = ($r === -2);
            $mysqlHostInvalid = $mysqlHostInvalid || $mysqlConnectInvalid;

            if ($mysqlUserPassInvalid) {
                $mysqlUsernameInvalid = true;
                $mysqlPasswordInvalid = true;
            }

            if (!$mysqlConnectInvalid && !$mysqlUserPassInvalid) { // 如果数据库可连接
                $r = check_mysql_version($mysqlHost, $mysqlUsername, $mysqlPassword);
                if ($r !== true) { // 如果数据库版本错误，也标记mysqlHost字段不合法
                    $mysqlHostInvalid = true;
                    $mysqlVersionInvalid = true;
                    $mysqlVersionInvalidMsg = $r;
                } else {
                    $mysqlVersionInvalid = false;
                }
                if (!$mysqlDatabaseInvalid) { // 如果输入了数据库名称
                    $r = check_mysql_database($mysqlHost, $mysqlUsername, $mysqlPassword, $mysqlDatabase);
                    if ($r !== true) {
                        $mysqlDatabaseInvalid = true;
                        $mysqlDatabaseDbInvalidMsg = $r;
                        $mysqlDatabaseDbInvalid = true;
                    }
                }
            }
            $r = null;
        }

        if (strpos($mysqlDatabase, '-') !== false) {
            $mysqlDatabaseInvalid = true;
            $mysqlDatabaseDbInvalidMsg = "数据库名称中不能包含 - ";
        }

        $redisConnectInvalid = true;
        $redisConnectInvalidMsg = '';

        if ($redisConnectCheck) {
            $r = check_redis_connection($redisHost, $redisPassword);
            if (!isset($r['code']) or $r['code'] == 1) {
                // $redisConnectInvalidMsg = $r['msg'];
                $redisConnectInvalidMsg = 'Redis密码错误，请核对。';
                $redisHostInvalid = true;
                $redisPasswordInvalid = true;
            } else {
                $redisConnectInvalid = false;
            }
        }

        $ready_to_install = $action && !$webTitleInvalid && !$mysqlHostInvalid && !$mysqlDatabaseInvalid && !$mysqlUsernameInvalid
            && !$mysqlPasswordInvalid && !$tablePrefixInvalid && !$adminUsernameInvalid && !$adminPasswordInvalid && !$mysqlUserPassInvalid && !$redisConnectInvalid && !$adminPathInvalid;

        if ($ready_to_install) {
            if (true) {
                // 如果有初始化sql，则进入下一步，由本程序进行初始化，不通过POST到 http://localhost/install 进行初始化
                $STEP += 1;
                $ready_to_install = 0;
            } else {
                make_lock_file();
            }
            auto_next_step();
            ?>
            <div class="alert alert-success" role="alert">
                <p>安装信息配置完成</p>
                <p>所有测试都已完成，将自动完成安装！</p>
            </div>
            <div class="alert alert-danger hidden" id="errormsgdiv" role="alert">
                <p>安装错误</p>
                <p id="errormsg"></p>
            </div>
        <?php } else { ?>
            <div class="alert alert-primary" role="alert">
                <p>请填写以下信息，点击下一步测试是否可安装</p>
            </div>
        <?php } ?>
        <form action="<?= $SCRIPT_NAME ?>?step=<?= $STEP ?>" method="post"
              id="userform<?= $ready_to_install ? 'install' : '' ?>">
            <input type="hidden" name="action" value="1"/>
            <div class="form-group row">
                <label for="forum_title" class="col-sm-2 offset-sm-2 col-form-label">站点名称</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $webTitleInvalid ? "is-invalid" : "" ?>" id="forum_title"
                           name="webTitle" value="<?= $webTitle ?>" required>
                    <input type="hidden" id="appid" name="appid" value="<?= $appid ?>">
                    <input type="hidden" id="app_secret" name="app_secret" value="<?= $app_secret ?>">
                    <input type="hidden" id="table_prefix" name="tablePrefix" value="<?= $tablePrefix ?>">
                    <?php if ($action && !$webTitle) { ?>
                        <div class="invalid-feedback">站点名称不能为空</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="admin_ptah" class="col-sm-2 offset-sm-2 col-form-label">后台目录</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $adminPathInvalid ? "is-invalid" : "" ?>" id="admin_path"
                           name="adminPath" value="<?= $adminPath ?>" required>
                    <?php if ($action && $adminPathInvalid) { ?>
                        <div class="invalid-feedback">后台目录不能为空或符号，只能由字母数字组成。</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="mysql_host" class="col-sm-2 offset-sm-2 col-form-label">数据库地址</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $mysqlHostInvalid ? "is-invalid" : "" ?>" id="mysql_host"
                           name="mysqlHost" value="<?= $mysqlHost ? $mysqlHost : "127.0.0.1" ?>" required>
                    <?php if ($action && !$mysqlHost) { ?>
                        <div class="invalid-feedback">数据库地址不能为空</div>
                    <?php } ?>
                    <?php if ($mysqlConnectCheck && $mysqlConnectInvalid) { ?>
                        <div class="invalid-feedback">数据库服务器无法连接，请检查服务器的IP与端口(可用:指定端口号)</div>
                    <?php } ?>
                    <?php if ($mysqlConnectCheck && $mysqlVersionInvalid) { ?>
                        <div class="invalid-feedback"><?= $mysqlVersionInvalidMsg ?></div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="mysql_database" class="col-sm-2 offset-sm-2 col-form-label">数据库名称</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $mysqlDatabaseInvalid ? "is-invalid" : "" ?>"
                           id="mysql_database" name="mysqlDatabase" value="<?= $mysqlDatabase ?>" required>
                    <?php if ($action && !$mysqlDatabase) { ?>
                        <div class="invalid-feedback">数据库名称不能为空</div>
                    <?php } else if ($action && $mysqlDatabaseDbInvalid) { ?>
                        <div class="invalid-feedback"><?= $mysqlDatabaseDbInvalidMsg ?></div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="mysql_username" class="col-sm-2 offset-sm-2 col-form-label">数据库用户</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $mysqlUsernameInvalid ? "is-invalid" : "" ?>"
                           id="mysql_username" name="mysqlUsername" value="<?= $mysqlUsername ?>" required>
                    <?php if ($action && !$mysqlUsername) { ?>
                        <div class="invalid-feedback">数据库用户不能为空</div>
                    <?php } ?>
                    <?php if ($action && $mysqlUserPassInvalid) { ?>
                        <div class="invalid-feedback">使用您输入的 MySQL 用户名密码组合无法连接到数据库</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="mysql_password" class="col-sm-2 offset-sm-2 col-form-label">数据库密码</label>
                <div class="col-sm-6">
                    <input type="password" class="form-control <?= $mysqlPasswordInvalid ? "is-invalid" : "" ?>"
                           id="mysql_password" name="mysqlPassword" value="<?= $mysqlPassword ?>" required>
                    <?php if ($action && !$mysqlPassword) { ?>
                        <div class="invalid-feedback">数据库密码不能为空</div>
                    <?php } ?>
                    <?php if ($action && $mysqlUserPassInvalid) { ?>
                        <div class="invalid-feedback">使用您输入的 MySQL 用户名密码组合无法连接到数据库</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="redis_host" class="col-sm-2 offset-sm-2 col-form-label">Redis 地址</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $redisHostInvalid ? "is-invalid" : "" ?>" id="redis_host"
                           name="redisHost" value="<?= $redisHost ? $redisHost : "127.0.0.1" ?>" required>
                    <?php if ($action && !$redisHost) { ?>
                        <div class="invalid-feedback">Redis 服务器不能为空</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="redis_password" class="col-sm-2 offset-sm-2 col-form-label">Redis 密码</label>
                <div class="col-sm-6">
                    <input type="password" class="form-control <?= $redisPasswordInvalid ? "is-invalid" : "" ?>"
                           id="redis_password" name="redisPassword" value="<?= $redisPassword ?>" required>
                    <?php if ($action && !$redisPassword) { ?>
                        <div class="invalid-feedback">Redis 密码不能为空</div>
                    <?php } ?>
                    <?php if ($action && $redisConnectInvalid) { ?>
                        <div class="invalid-feedback"><?= $redisConnectInvalidMsg ?></div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="admin_username" class="col-sm-2 offset-sm-2 col-form-label">管理员用户名</label>
                <div class="col-sm-6">
                    <input type="text" class="form-control <?= $adminUsernameInvalid ? "is-invalid" : "" ?>"
                           id="admin_username" name="adminUsername" value="<?= $adminUsername ?>" required>
                    <?php if ($action && $adminUsernameInvalid) { ?>
                        <div class="invalid-feedback">管理员用户名必须为手机号或邮箱</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="admin_password" class="col-sm-2 offset-sm-2 col-form-label">管理员密码</label>
                <div class="col-sm-6">
                    <input type="password" class="form-control <?= $adminPasswordInvalid ? "is-invalid" : "" ?>"
                           id="admin_password" name="adminPassword" value="<?= $adminPassword ?>" required>
                    <?php if ($action && !$adminPassword) { ?>
                        <div class="invalid-feedback">管理员密码不能为空</div>
                    <?php } else if ($action && ($adminPassword != $adminPasswordConfirmation)) { ?>
                        <div class="invalid-feedback">管理员密码两次输入不一致</div>
                    <?php } ?>
                </div>
            </div>
            <div class="form-group row">
                <label for="admin_password2" class="col-sm-2 offset-sm-2 col-form-label">密码确认</label>
                <div class="col-sm-6">
                    <input type="password" class="form-control <?= $adminPasswordInvalid ? "is-invalid" : "" ?>"
                           id="admin_password2" name="adminPasswordConfirmation"
                           value="<?= $adminPasswordConfirmation ?>" required>
                    <?php if ($action && !$adminPasswordConfirmation) { ?>
                        <div class="invalid-feedback">管理员密码确认不能为空</div>
                    <?php } else if ($action && ($adminPassword != $adminPasswordConfirmation)) { ?>
                        <div class="invalid-feedback">管理员密码两次输入不一致</div>
                    <?php } ?>
                </div>
            </div>
        </form>
        <?php
    }

    function do_install()
    {
        $app_check = app_post(get_var('app_secret'), get_var('appid'));
        $app_secret = get_var('app_secret');
        $appid = get_var('appid');
        global $SCRIPT_NAME, $STEP;
        $action = get_var('action');
        if ($action == 1 && !empty($app_check['rows'])) {
            $data['webTitle'] = get_var('webTitle');
            $data['mysqlHost'] = get_var('mysqlHost');
            $data['mysqlDatabase'] = get_var('mysqlDatabase');
            $data['mysqlUsername'] = get_var('mysqlUsername');
            $data['mysqlPassword'] = get_var('mysqlPassword');
            $data['tablePrefix'] = get_var('tablePrefix');
            $data['adminUsername'] = get_var('adminUsername');
            $data['adminPassword'] = get_var('adminPassword');
            $data['adminPath'] = get_var('adminPath');
            $data['redisHost'] = get_var('redisHost');
            $data['redisPassword'] = get_var('redisPassword');
            $data['appid'] = $appid;
            $data['app_secret'] = $app_secret;
            $data['app_ver'] = $app_check['rows']['version'];
            $data['bus_uuid'] = $app_check['rows']['bus_uuid'];
            $data['bus_pwd'] = $app_check['rows']['bus_pwd'];
            $data = json_encode($data);
        } else {
            $data = get_var('data');
        }
    if (empty(json_decode(htmlspecialchars_decode($data)))) {
        ?>
        <div class="alert alert-danger" id="errormsgdiv" role="alert">
            <p>获取配置信息失败，请返回上一步重试！</p>
            <p id="errormsg"></p>
        </div>
        <?php
    } else {
        $install_step = get_var('install_step');
        if ($install_step === false) {
            $install_step = 1;
        } else {
            $install_step++;
            if ($install_step == 4) {
                $STEP++;
            }
        }
        $tmpfile = get_var('tmpfile');
        if (empty($tmpfile)) {
            $tmpfile = __DIR__ . DIRECTORY_SEPARATOR . uniqid('dpqb', true) . '.zip';
        }
        ?>
        <div class="alert alert-primary" role="alert">
            <p>正在执行安装，该过程时间较久，不会超过5分钟，请耐心等待。</p>
        </div>

        <form action="<?= $SCRIPT_NAME ?>?step=<?= $STEP ?>" id="install_form" method="post">
            <input type="hidden" name="install_step" value="<?= $install_step ?>">
            <input type="hidden" name="tmpfile" value="<?= $tmpfile ?>">
            <input type="hidden" name="data" value='<?= $data ?>'>
            <ul class="list-group my-3">
                <div id="process"
                     style="background:#eeebff;width: 100%;position: relative;left: 0%;top: 65%;height: 10px;">
                    <div style="background:red;width: 0%;height: 10px;"></div>
                </div>
                <li class="list-group-item d-flex justify-content-between align-items-center">
                    <div> 下载安装文件</div>
                    <?php
                    $data = json_decode(htmlspecialchars_decode($data), true);
                    if ($install_step == 1) {
                        $app_check = app_post($data['app_secret'], $data['appid']);
                    if (isset($app_check['success']) and $app_check['code'] == 200 and $app_check['success'] == true) {
                        $_SESSION['path'] = $app_check['rows']['path'];
                        $_SESSION['version'] = $app_check['rows']['version'];
                        $_SESSION['bus_uuid'] = $app_check['rows']['bus_uuid'];
                        $_SESSION['bus_pwd'] = $app_check['rows']['bus_pwd'];
                        $_SESSION['file_size'] = getFileSize($_SESSION['path']);
                        $_SESSION['start_time'] = time();
                        $file_arr = explode('/', $_SESSION['path']);
                        $file_name = end($file_arr);
                        $_SESSION['file_name'] = $file_name;
                        ?>
                        <script type="text/javascript">
                            var savecount = 0;

                            function download() {
                                savecount++
                                $.ajax({
                                    url: "<?=$SCRIPT_NAME?>",
                                    data: {
                                        ctype: 1,
                                        savecount: savecount,
                                    },
                                    /*接口域名地址*/
                                    type: 'post',
                                    success: function (res) {
                                        var part = res.data.part
                                        var html = '<div style="background:red;width: ' + part + '%;height: 10px;"></div>'
                                        $('#process').html(html);
                                        if (res.data.success == true && part >= 100) {
                                            $('#install_form').submit();
                                        } else {
                                            download();
                                        }
                                    },
                                });
                            }

                            download();
                        </script>
                    <?php
                    //                                http_download_to_str($app_check['rows']['path'], $tmpfile);
                    //                                return json_encode(['code'=>200,'msg'=>'文件下载中','data'=>['size'=>getFileSize($app_check['rows']['path']),'tmpfile'=>$tmpfile]]);
                    }
                    ?>
                        <div class="spinner-border" role="status" style="width: 1rem;height: 1rem;">
                            <span class="sr-only">Loading...</span>
                        </div>
                    <?php } elseif ($install_step == 2) {

                    }
                    if ($install_step > 1) {
                        ?>
                        <span class="badge badge-primary">成功</span>

                    <?php } ?>
                </li>
                <li class="list-group-item d-flex justify-content-between align-items-center">
                    <div> 进行安装网站</div>
                    <?php
                    if ($install_step == 2) {
                        ?>
                        <div class="spinner-border" role="status" style="width: 1rem;height: 1rem;">
                            <span class="sr-only">Loading...</span>
                        </div>
                    <?php } elseif ($install_step == 3) {
                        extract_zip($_SESSION['file_name'], __DIR__);
                        @unlink($_SESSION['file_name']);
                        create_env($data);
                    }
                    if ($install_step > 2) {
                        ?>
                        <span class="badge badge-primary">成功</span>
                    <?php } ?>
                </li>
                <li class="list-group-item d-flex justify-content-between align-items-center">
                    <div> 进行网站配置</div>
                    <?php
                    if ($install_step == 3) {
                        ?>
                        <div class="spinner-border" role="status" style="width: 1rem;height: 1rem;">
                            <span class="sr-only">Loading...</span>
                        </div>
                    <?php } elseif ($install_step == 4) {
                        create_mysql($data);
                    }
                    }
                    if ($install_step > 3) {
                        ?>
                        <span class="badge badge-primary">成功</span>
                    <?php } ?>
                </li>
            </ul>
        </form>
    <?php
    if ($install_step > 1) {
    ?>
        <script type="text/javascript">
            $('#install_form').submit();
        </script>
        <?php
    }
        ?>

        <?php
    }

    function complate_install()
    {
        $system = strtoupper(substr(PHP_OS, 0, 3));
        $data = get_var('data');
        $data = json_decode(htmlspecialchars_decode($data), true);
        make_lock_file();
        ?>
        <div class="alert alert-success" role="alert">
            <p>恭喜！系统安装配置完成，请不要将下述信息告知任何人！</p>
            <p>网站后台地址：http://<?= $_SERVER['HTTP_HOST']; ?>/<?= $data['adminPath'] ?></p>
            <p>管理员用户：<?= $data['adminUsername'] ?></p>
            <p>管理员密码：<?= $data['adminPassword'] ?></p>
            <?php
            if (__DIR__ == '/usr/dpqb/www') {
                if ($system == 'WIN') {
                    $cron = 'schtasks /create /sc minute /tn dpqb /tr "cmd.exe /c php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan command:TimedTask" /ru system';
                } else {
                    $cron = 'echo "* * * * * php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan command:TimedTask" >> /var/spool/cron/' . $_SERVER['USER'] . ' && sed -i s:/usr/dpqb/www:/usr/dpqb/www/public:g /etc/nginx/nginx.conf && nginx -s reload && echo "' . $_SERVER['USER'] . ' ALL=(root) NOPASSWD:ALL" >> /etc/sudoers';
                }
                ?>
                <p style="color:brown;font-weight:600">1、在Powshell或CMD执行命令，设置运行目录、定时任务：
                <div class="layui-card">
                    <div class="layui-card-body">
                        <div class="copycron"><span><?= $cron ?></span><a href="javascript:;">[点击复制]</a></div>
                    </div>
                </div>
                </p>
                <?php
            } else {
                if ($system == 'WIN') {
                    $cron = 'schtasks /create /sc minute /tn dpqb /tr "cmd.exe /c php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan command:TimedTask" /ru system';
                } else {
                    $cron = 'echo "* * * * * php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan command:TimedTask" >> /var/spool/cron/' . $_SERVER['USER'] . ' && echo "' . $_SERVER['USER'] . ' ALL=(root) NOPASSWD:ALL" >> /etc/sudoers';
                }
                ?>
                <p style="color:brown;font-weight:600">1、将网站运行目录修改为public目录。</p>
                <p style="color:brown;font-weight:600">2、在SSH执行Shell命令，设置定时任务：
                <div class="layui-card">
                    <div class="layui-card-body">
                        <div class="copycron"><span><?= $cron ?></span><a href="javascript:;">[点击复制]</a></div>
                    </div>
                </div>
                </p>
                <?php
            }
            ?>

            <p>如果您用的满意，希望您能分享下“怪圈云系统”给其他需要的人，共建怪圈！</p>
        </div>

        <?php
    }

    function auto_next_step()
    {
        ?>
        <script>
            setTimeout(function () {
                next_step();
            }, 1000);
        </script>
        <?php
    }

    function get_step()
    {
        return get_var('step');
    }

    function downloadLargeFile($sourceFileUrl, $targetFile, $size, $pieceSize)
    {
        if ($size === false) {
            return false;
        }

        $from = 0;
        $i = 0;
        $isSuccess = true;
        do {
            $to = min($from + $pieceSize - 1, $size);
            $partTargetFile = $targetFile . '_' . $i++;
            $partFiles[] = $partTargetFile;
            $r = downFileByPiece($sourceFileUrl, $partTargetFile, $from, $to);
            if ($r === false) {
                $isSuccess = false;
                break;
            }
            $from = $to + 1;
            if ($from > $size) {
                break;
            }
        } while (true);
        ob_end_flush();
        // 合并文件
        if ($isSuccess) {
            $combineCmd = "cat " . implode(' ', $partFiles) . " > " . $targetFile;
            exec($combineCmd, $o, $ret);
            if ($ret != 0) {
                $isSuccess = false;
            }
        }

        // 清理临时文件
        foreach ($partFiles as $partFile) {
            if (file_exists($partFile)) {
                @unlink($partFile);
            }
        }

        return $isSuccess;
    }

    function downFileByPiece($sourceFile, $savePath, $fromByte = 0, $toByte = -1)
    {
        if (file_exists($savePath)) {
            return true;
        }
        $cmd = "curl --range " . $fromByte . "-";
        if ($toByte > 0) {
            $cmd .= $toByte;
        }
        $cmd .= " -o " . $savePath . " '" . $sourceFile . "'";
        exec($cmd, $o, $ret);
        ob_end_clean();
        if ($ret != 0) {
            return false;
        }
        return true;
    }

    function api_http_download_to_str($url, $saveFile, $start, $size)
    {
//        $timestamp = time(); // 获取当前的秒级时间戳
//        $friendlyTime = date('Y-m-d H:i:s', $timestamp); // 转换为友好的时间格式

        // 准备要写入的数据
//        $data = [
//            'time' => $friendlyTime,
//            // 'method' => $method,
//            'url' => $url,
//            'saveFile' => $saveFile,
//            'start' => $start,
//            'size' => $size
            // 'headers' => $headers,
            // 'request_params' => $_REQUEST
//        ];

        // 将数组转化为可读的字符串
//        $dataString = print_r($data, true);

        // 写入文件
        //file_put_contents('down.txt', $dataString, FILE_APPEND);

        $h_curl = curl_init();
        $h_file = fopen($saveFile, 'w');
        if ($h_file === FALSE) {
            throw new Exception("无法创建文件 $saveFile , 请重新返回第一步，检查目录权限");
        }
        // 开启缓冲区
        ob_start();
        $header = [
            'Range: bytes=' . $start . "-" . $size
        ];
        curl_setopt($h_curl, CURLOPT_URL, $url);
        curl_setopt($h_curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($h_curl, CURLOPT_HEADER, false);
        curl_setopt($h_curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($h_curl, CURLOPT_TIMEOUT, 60);
        curl_setopt($h_curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($h_curl, CURLOPT_FILE, $h_file);
        curl_setopt($h_curl, CURLOPT_SSL_VERIFYPEER, false); // 阻止对证书的合法性的检查
        curl_setopt($h_curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
        $curl_success = curl_exec($h_curl);
        ob_flush();
        flush();
        ob_end_clean();
        curl_close($h_curl);
        fclose($h_file);
        return $curl_success;
    }

    function http_download_to_str($url, $saveFile, $start, $size)
    {
        $h_curl = curl_init();
        $h_file = fopen($saveFile, 'a+');
        if ($h_file === FALSE) {
            throw new Exception("无法创建文件 $saveFile , 请重新返回第一步，检查目录权限");
        }
        // 开启缓冲区
        ob_start();
        $header = [
            'Range: bytes=' . $start . "-" . $size
        ];
        curl_setopt($h_curl, CURLOPT_URL, $url);
        curl_setopt($h_curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($h_curl, CURLOPT_HEADER, false);
        curl_setopt($h_curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($h_curl, CURLOPT_TIMEOUT, 60);
        curl_setopt($h_curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($h_curl, CURLOPT_FILE, $h_file);
        curl_setopt($h_curl, CURLOPT_SSL_VERIFYPEER, false); // 阻止对证书的合法性的检查
        curl_setopt($h_curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
        $curl_success = curl_exec($h_curl);
        ob_flush();
        flush();
        ob_end_clean();
        curl_close($h_curl);
        fclose($h_file);
        return $curl_success;
    }

    function extract_zip($zipfile, $targetfolder)
    {
        $zip = new ZipArchive;
        $res = $zip->open($zipfile, ZipArchive::CREATE);
        if ($res === true) {
            if ($zip->extractTo($targetfolder) === FALSE) {
                throw new Exception("无法解压缩 $zipfile 到 $targetfolder ，
             请检查 $targetfolder 下是否有文件或目录的拥有者用户与 $zipfile 拥有者用户不同，
             若有不同则修改该目录或文件拥有者保持与$zipfile 拥有者相同，操作完后再次点击重试");
            }
            $zip->close();
        } else {
            file_put_contents('error.json', json_encode($res));
            throw new Exception("无法打开 $zipfile");
        }
    }

    function create_env($data, $type = 1)
    {
        $mysqlPort = 3306;
        if (strpos($data['mysqlHost'], ":") !== FALSE) {
            list($mysqlHost, $mysqlPort) = explode(":", $data['mysqlHost']);
        } else {
            $mysqlHost = $data['mysqlHost'];
        }
        $redisPort = 6379;
        if (strpos($data['redisHost'], ":") !== FALSE) {
            list($redisHost, $redisPort) = explode(":", $data['redisHost']);
        } else {
            $redisHost = $data['redisHost'];
        }

        $app_key = 'base64:' . base64_encode(md5(time()));
        $content = "APP_NAME=" . get_server_url() . "
APP_ENV=production
APP_KEY=" . $app_key . "
APP_DEBUG=false
APP_URL=" . get_server_url() . "
APP_DIR=" . __DIR__ . "
APP_VER={$data['app_ver']}

DB_CONNECTION=mysql
DB_HOST={$mysqlHost}
DB_PORT={$mysqlPort}
DB_DATABASE={$data['mysqlDatabase']}
DB_USERNAME={$data['mysqlUsername']}
DB_PASSWORD={$data['mysqlPassword']}

BROADCAST_DRIVER=redis
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120

REDIS_HOST={$redisHost}
REDIS_PASSWORD={$data['redisPassword']}
REDIS_PORT={$redisPort}
ADMIN_TPL=default
USER_TPL=default
INDEX_TPL=default
PANEL_TPL=default
ADMIN_PATH={$data['adminPath']}";
        file_put_contents(__DIR__ . DIRECTORY_SEPARATOR . '.env', $content);
        // shell_exec('php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan key:generate');
        shell_exec('php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan cache:clear');
        shell_exec('php ' . __DIR__ . DIRECTORY_SEPARATOR . 'artisan command:TimedTask');
        if ($type == 1) {
            echo '配置完成';
        }
    }

    function get_var($var)
    {
        if (!isset($_GET[$var])) {
            if (!isset($_POST[$var])) return false;
            $ret = $_POST[$var];
        } else {
            $ret = $_GET[$var];
        }
        return htmlspecialchars($ret);
    }

    function redirect($url)
    {
        header('Location: ' . $url);
        exit(0);
    }

    function build_steps()
    {
        global $STEP;
        $steps = NULL;

        $steps = array(
            0 => 'silent_self_update',
            1 => 'check_env_and_extension',
            2 => 'app_check',
            3 => 'show_init_form',
            4 => 'do_install',
            5 => 'complate_install'
        );

        // 在第0步的时候，不进行跨目录访问
        if ($STEP > 0) {
            $current_install_ver = existing_installation();
            if ($current_install_ver) {
                // 如果已有安装，则只保留steps到download_vendor
                $index = array_search('download_vendor', $steps);
                $steps = array_slice($steps, 0, $index + 1);
                // 后面加一个升级的步骤
                $steps[$index + 1] = 'upgrade_existing_installation';
            }
        }
        $steps[] = 'warp_up';
        return $steps;
    }

    function get_server_url()
    {
        $url = is_https() ? "https://" : "http://";
        $url .= $_SERVER['HTTP_HOST'];
        return $url;
    }

    function is_https()
    {
        if (isset($_SERVER["HTTPS"]) && strtolower($_SERVER["HTTPS"]) != "off") {
            return true;
        }
        if (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && strtolower($_SERVER["HTTP_X_FORWARDED_PROTO"]) == "https") {
            return true;
        }
        if (isset($_SERVER["HTTP_SCHEME"]) && strtolower($_SERVER["HTTP_SCHEME"]) == "https") {
            return true;
        }
        if (isset($_SERVER["HTTP_FROM_HTTPS"]) && strtolower($_SERVER["HTTP_FROM_HTTPS"]) != "off") {
            return true;
        }
        if (isset($_SERVER["SERVER_PORT"]) && $_SERVER["SERVER_PORT"] == 443) {
            return true;
        }
        return false;
    }


    function existing_installation()
    {
        $dir = __DIR__;
        if (file_exists($dir . "/../config/config.php") || file_exists($dir . "/../storage/install.lock")) {
            return extract_version_from_source();
        }
        return false;
    }

    function getFileSize($url)
    {
        $url = parse_url($url);
        if ($fp = @fsockopen($url['host'], empty($url['port']) ? 80 : $url['port'], $error)) {
            fputs($fp, "GET " . (empty($url['path']) ? '/' : $url['path']) . " HTTP/1.1\r\n");
            fputs($fp, "Host:$url[host]\r\n\r\n");
            while (!feof($fp)) {
                $tmp = fgets($fp);
                if (trim($tmp) == '') {
                    break;
                } else if (preg_match('/Content-Length:(.*)/si', $tmp, $arr)) {
                    return trim($arr[1]);
                }
            }
            return null;
        } else {
            return null;
        }
    }

    function app_post($app_secret, $appid)
    {
        if ($app_secret) {
            
            $app_secret = trim($app_secret);
            $appid = trim($appid);
            $time = time();
            $secret = md5(sha1($app_secret . $appid . $time));
            $url = PACKAGE_BASE . 'api/index/v2/bus/soft/install/1/' . $appid . '/' . $secret . '/' . $time . '?base_uuid=ad678392-b30b-6f90-ef33-45fedf7bbf15&use_api=1';
            // p($url);
            return json_decode(post_url($url, NULL), true);
        } else {
            return '请返回第一步重新安装';
        }
    }

    function post_url($url, $params)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        if (substr($url, 0, 5) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }


    function check_mysql_connection($host, $username, $password)
    {
        $port = 3306;
        if (strpos($host, ":") !== FALSE) {
            list($host, $port) = explode(":", $host);
        }
        try {
            $conn = "mysql:host=$host;port=$port;charset=utf8mb4";
            return new PDO($conn, $username, $password);
        } catch (PDOException $e) {
            if ($e->getCode() === 2002) {
                return -1; // -1 表示连接被拒绝
            }
            if ($e->getCode() === 1045) {
                return -2; // -2 表示用户名/密码错误
            }
            return false;
        }
    }

    function check_mysql_version($host, $username, $password)
    {
        $pdo = check_mysql_connection($host, $username, $password);
        if ($pdo === FALSE) {
            return "数据库无法连接";
        }
        if ($q = $pdo->query('SELECT VERSION()')) {
            $version = $q->fetchColumn();
            if (strpos($version, 'MariaDB') !== FALSE) {
                if (version_compare($version, '10.3.0', '>=')) {
                    return true;
                }
            } else {
                if (version_compare($version, '8.0.0', '>=')) {
                    return true;
                }
            }
        } else {
            return "无法查询数据库版本";
        }
        if ($q = $pdo->query("SELECT @@GLOBAL.innodb_default_row_format")) {
            $rowformat = $q->fetchColumn();
            if ($rowformat != "dynamic") {
                return "MySQL配置不正确，请确认innodb_default_row_format配置为dynamic";
            }
            $large_prefix = $pdo->query("SELECT @@GLOBAL.innodb_large_prefix")->fetchColumn();
            if ($large_prefix != 1) {
                return "MySQL配置不正确，请确认innodb_large_prefix配置为on";
            }
        } else {
            return "MySQL版本太低，请使用MySQL 8.0版本以上或MariaDB 10.2以上";
        }
        return true;
    }

    function check_mysql_database($host, $username, $password, $database)
    {
        $database = addslashes($database);
        $pdo = check_mysql_connection($host, $username, $password);
        if ($pdo === FALSE) {
            return "数据库无法连接";
        }
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
        if ($pdo->exec("USE `$database`") !== FALSE) {
            if ($pdo->query("SHOW TABLES")->rowCount() > 0) {
                return "数据库 $database 不为空，请清空后重试";
            }
            return true;
        } else {
            if ($q = $pdo->query("SHOW DATABASES LIKE '$database'")) {
                if ($q->rowCount() > 0) {
                    return "无法切换到数据库 $database";
                }
                if ($pdo->query("CREATE DATABASE $database DEFAULT CHARACTER SET = `utf8mb4` DEFAULT COLLATE = `utf8mb4_unicode_ci`") === FALSE) {
                    return "无法创建数据库 $database ，请检查用户权限";
                }
                return true;
            }
            return "无法获取数据库列表";
        }
    }

    function check_redis_connection($host, $password)
    {
        $port = 6379;
        if (strpos($host, ":") !== FALSE) {
            list($host, $port) = explode(":", $host);
        }
        try {
            $redis = new Redis();
            $redis->connect($host, $port);
            $redis->auth($password); //密码验证
            $redis->ping();
            return ['code' => 0];
        } catch (Exception $e) {
            return ['code' => 1, 'msg' => $e->getMessage()];
        }
    }

    function make_lock_file()
    {
        file_put_contents("dpqb.lock", "locked");
    }

    function create_uuid()
    {
        @mt_srand(microtime() * 10000);
        $charid = md5(uniqid(rand(), true));
        $hyphen = chr(45);
        $uuid = substr($charid, 0, 8) . $hyphen
            . substr($charid, 8, 4) . $hyphen
            . substr($charid, 12, 4) . $hyphen
            . substr($charid, 16, 4) . $hyphen
            . substr($charid, 20, 12);
        return $uuid;
    }

    function get_env($env)
    {
        $uriFile = __DIR__ . "/.env";
        if (file_exists($uriFile)) {
            $lines = @file($uriFile);
            foreach ($lines as $lineStr) {
                $lineStr = explode('=', $lineStr);
                if (count($lineStr) == 2 and $lineStr[0] == $env) {
                    return $lineStr[1];
                }
            }
        }
    }


    ?>
    <script>
        $(".copycron a").click(function () {
            var text = $(this).prev().text();
            var aux = document.createElement("input");
            aux.setAttribute("value", text);
            document.body.appendChild(aux);
            aux.select();
            document.execCommand("copy");
            document.body.removeChild(aux);
            layer.msg('复制成功')
        })

    </script>