初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
<?php
namespace app\install\controller;
use app\Controller;
use think\facade\Cache;
class BaseInstall extends Controller
{
public $replace;
public $lock_file;
public $lang;
public $init_data;
public function __construct()
{
parent::__construct();
$this->replace = [
'INSTALL_CSS' => __ROOT__ . '/app/install/view/public/css',
'INSTALL_IMG' => __ROOT__ . '/app/install/view/public/img',
'INSTALL_JS' => __ROOT__ . '/app/install/view/public/js',
];
$this->lock_file = './install.lock';//锁定文件
$root_url = __ROOT__;
$this->assign("root_url", $root_url);
}
/**
* 操作成功返回值函数
* @param string $data
* @param string $code_var
* @return array
*/
public function returnSuccess($data = '', $code_var = 'SUCCESS')
{
$lang_array = $this->getLang();
$lang_var = $lang_array[$code_var] ?? $code_var;
if ($code_var == 'SUCCESS') {
$code_var = 0;
} else {
$code_array = array_keys($lang_array);
$code_index = array_search($code_var, $code_array);
if ($code_index != false) {
$code_var = 10000 + $code_index;
}
}
return success($code_var, $lang_var, $data);
}
/**
* 操作失败返回值函数
* @param string $data
* @param string $code_var
* @return array
*/
public function returnError($data = '', $code_var = 'FAIL')
{
$lang_array = $this->getLang();
if (isset($lang_array[ $code_var ])) {
$lang_var = $lang_array[ $code_var ];
} else {
$lang_var = $code_var;
$code_var = 'FAIL';
}
$code_array = array_keys($lang_array);
$code_index = array_search($code_var, $code_array);
if ($code_index != false) {
$code_var = -10000 - $code_index;
}
return error($code_var, $lang_var, $data);
}
/**
* 获取语言包数组
* @return Ambigous <multitype:, unknown>
*/
public function getLang()
{
$default_lang = config("lang.default_lang");
$cache_common = Cache::get("lang_app/lang/" . $default_lang . '/model.php');
if (empty($cache_common)) {
$cache_common = include 'app/lang/' . $default_lang . '/model.php';
Cache::tag("lang")->set("lang_app/lang/" . $default_lang, $cache_common);
}
$lang_path = $this->lang ?? '';
if (!empty($lang_path)) {
$cache_path = Cache::get("lang_" . $lang_path . "/" . $default_lang . '/model.php');
if (empty($cache_path)) {
$cache_path = include $lang_path . "/" . $default_lang . '/model.php';
Cache::tag("lang")->set("lang_" . $lang_path . "/" . $default_lang, $cache_path);
}
$lang = array_merge($cache_common, $cache_path);
} else {
$lang = $cache_common;
}
return $lang;
}
}

608
app/install/controller/Index.php Executable file
View File

@@ -0,0 +1,608 @@
<?php
namespace app\install\controller;
use app\model\shop\Shop;
use app\model\system\Addon;
use app\model\system\Api;
use app\model\system\Group;
use app\model\system\H5;
use app\model\system\Menu;
use app\model\system\Site;
use app\model\system\User;
use think\facade\Cache;
use think\facade\Event;
class Index extends BaseInstall
{
public function __construct()
{
//执行父类构造函数
parent::__construct();
}
/**
*安装
*/
public function index()
{
if (file_exists($this->lock_file)) {
$this->redirect(__ROOT__);
}
$step = input("step", 1);
if ($step == 1) {
return $this->fetch('index/step-1', [], $this->replace);
} elseif ($step == 2) {
//系统变量
$system_variables = [];
$phpv = phpversion();
$os = PHP_OS;
$server = $_SERVER[ 'SERVER_SOFTWARE' ];
$host = ( empty($_SERVER[ 'REMOTE_ADDR' ]) ? $_SERVER[ 'REMOTE_HOST' ] : $_SERVER[ 'REMOTE_ADDR' ] );
$name = $_SERVER[ 'SERVER_NAME' ];
$verison = !( version_compare(PHP_VERSION, '7.1.0') == -1 );
//pdo
$pdo = extension_loaded('pdo') && extension_loaded('pdo_mysql');
$system_variables[] = [ "name" => "pdo", "need" => "开启", "status" => $pdo ];
//curl
$curl = extension_loaded('curl') && function_exists('curl_init');
$system_variables[] = [ "name" => "curl", "need" => "开启", "status" => $curl ];
//openssl
$openssl = extension_loaded('openssl');
$system_variables[] = [ "name" => "openssl", "need" => "开启", "status" => $openssl ];
//gd
$gd = extension_loaded('gd');
$system_variables[] = [ "name" => "GD库", "need" => "开启", "status" => $gd ];
//fileinfo
$fileinfo = extension_loaded('fileinfo');
$system_variables[] = [ "name" => "fileinfo", "need" => "开启", "status" => $fileinfo ];
$root_path = str_replace("\\", DIRECTORY_SEPARATOR, dirname(__FILE__, 4));
$root_path = str_replace("/", DIRECTORY_SEPARATOR, $root_path);
$dirs_list = [
[ "path" => $root_path, "path_name" => "/", "name" => "整目录" ],
[ "path" => $root_path . DIRECTORY_SEPARATOR . "public", "path_name" => "public", "name" => "public" ],
[ "path" => $root_path . DIRECTORY_SEPARATOR . "config", "path_name" => "config", "name" => "config" ],
[ "path" => $root_path . DIRECTORY_SEPARATOR . 'runtime', "path_name" => "runtime", "name" => "runtime" ],
[ "path" => $root_path . DIRECTORY_SEPARATOR . 'app/install', "path_name" => "app/install", "name" => "安装目录" ]
];
//目录 可读 可写检测
$is_dir = true;
foreach ($dirs_list as $k => $v) {
$is_readable = is_readable($v[ "path" ]);
$is_write = is_write($v[ "path" ]);
$dirs_list[ $k ][ "is_readable" ] = $is_readable;
$dirs_list[ $k ][ "is_write" ] = $is_write;
if ($is_readable == false || $is_write == false) {
$is_dir = false;
}
}
$this->assign("root_path", $root_path);
$this->assign("system_variables", $system_variables);
$this->assign("phpv", $phpv);
$this->assign("server", $server);
$this->assign("host", $host);
$this->assign("os", $os);
$this->assign("name", $name);
$this->assign("verison", $verison);
$this->assign("dirs_list", $dirs_list);
if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir) {
$continue = true;
} else {
$continue = false;
}
$this->assign("continue", $continue);
return $this->fetch('index/step-2', [], $this->replace);
} elseif ($step == 3) {
return $this->fetch('index/step-3', [], $this->replace);
} elseif ($step == 4) {
set_time_limit(300);
$source_file = "./app/install/source/database.php";//源配置文件
$target_dir = "./config";
$target_file = "database.php";
$file_name = "./app/install/source/database.sql";//数据文件
//数据库
$dbport = input("dbport", "3306");
$dbhost = input("dbhost", "localhost");
$dbuser = input("dbuser", "root");
$dbpwd = input("dbpwd", "root");
$dbname = input("dbname", "niushop_b2c_v5");//数据库名称
$dbprefix = input("dbprefix", "");//前缀
//平台
$site_name = input('site_name', "");
$username = input('username', "");
$password = input('password', "");
$password2 = input('password2', "");
$yanshi = input('yanshi', "");// 演示数据开关
if ($dbhost == '' || $dbuser == '') {
return $this->returnError([], '数据库链接配置信息丢失!');
}
// if ($dbprefix == '') {
// return $this->returnError('数据表前缀为空!');
// }
//可写测试
$write_result = is_write($target_dir);
if (!$write_result) {
//判断是否有可写的权限linux操作系统要注意这一点windows不必注意。
return $this->returnError([], '配置文件不可写,权限不够!');
}
//数据库连接测试
$conn = @mysqli_connect($dbhost, $dbuser, $dbpwd, "", $dbport);
if (!$conn) {
return $this->returnError([], '连接数据库失败!请检查连接参数!');
}
//平台
if ($site_name == '' || $username == '' || $password == '') {
return $this->returnError([], '平台信息不能为空!');
}
if ($password != $password2) {
return $this->returnError([], '两次密码输入不一样,请重新输入');
}
//数据库可写和是否存在测试
$empty_db = mysqli_select_db($conn, $dbname);
if ($empty_db) {
$sql = "DROP DATABASE `$dbname`";
$retval = mysqli_query($conn, $sql);
if (!$retval) {
return $this->returnError([], '删除数据库失败: ' . mysqli_error($conn));
}
}
//如果数据库不存在,我们就进行创建。
$dbsql = "CREATE DATABASE `$dbname`";
$db_create = mysqli_query($conn, $dbsql);
if (!$db_create) {
return $this->returnError([], '创建数据库失败,请确认是否有足够的权限!');
}
//链接数据库
@mysqli_select_db($conn, $dbname);
//修改配置文件
$fp = fopen($source_file, "r");
$configStr = fread($fp, filesize($source_file));
fclose($fp);
$configStr = str_replace('model_hostname', $dbhost, $configStr);
$configStr = str_replace('model_database', $dbname, $configStr);
$configStr = str_replace("model_username", $dbuser, $configStr);
$configStr = str_replace("model_password", $dbpwd, $configStr);
$configStr = str_replace("model_port", $dbport, $configStr);
$configStr = str_replace("model_prefix", $dbprefix, $configStr);
$fp = fopen($target_dir . DIRECTORY_SEPARATOR . $target_file, "w");
if ($fp == false) {
return $this->returnError([], '写入配置失败,请检查' . $target_dir . '/' . $target_file . '是否可写入!');
}
fwrite($fp, $configStr);
fclose($fp);
//导入SQL并执行。
$get_sql_data = file_get_contents($file_name);
$sql_query = $this->getSqlQuery($get_sql_data);
@mysqli_query($conn, "SET NAMES utf8");
$query_count = count($sql_query);
for ($i = 0; $i < $query_count; $i++) {
$sql = trim($sql_query[ $i ]);
if (strstr($sql, 'CREATE TABLE')) {
$match_item = preg_match('/CREATE TABLE [`]?(\\w+)[`]?/is', $sql, $match_data);
} elseif (strstr($sql, 'ALTER TABLE')) {
$match_item = preg_match('/ALTER TABLE [`]?(\\w+)[`]?/is', $sql, $match_data);
} elseif (strstr($sql, 'INSERT INTO')) {
$match_item = preg_match('/INSERT INTO [`]?(\\w+)[`]?/is', $sql, $match_data);
} else {
$match_item = 0;
}
if ($match_item > 0) {
try {
$table_name = $match_data[ "1" ];
$new_table_name = $dbprefix . $table_name;
$sql_item = $this->str_replace_first($table_name, $new_table_name, $sql);
@mysqli_query($conn, $sql_item);
} catch (\Exception $e) {
return $this->returnError([], '数据库解析失败' . $e->getMessage());
}
}
}
@mysqli_close($conn);
$database_config = include $target_dir . DIRECTORY_SEPARATOR . $target_file;
\think\facade\Config::set($database_config, "database");
//gateway配置
$this->initGatewayConfig();
//安装菜单
$menu = new Menu();
$shop_menu_res = $menu->refreshMenu('shop', '');
if ($shop_menu_res[ "code" ] < 0) {
return $this->returnError([], '店铺菜单失败!');
}
//安装插件
$addon_model = new Addon();
$addon_result = $addon_model->installAllAddon();
if ($addon_result[ "code" ] < 0) {
return $this->returnError([], $addon_result[ "message" ]);
}
$this->init_data = include "./app/install/source/init.php";//源配置文件
$initdata_result = $this->initData(input());
if ($initdata_result[ "code" ] < 0) {
return $this->returnError([], '默认数据添加失败!');
}
// H5端刷新
$h5 = new H5();
$h5_res = $h5->refresh();
if ($h5_res[ 'code' ] < 0) {
return $this->returnError([], 'h5部署失败');
}
//添加店铺
$site_data = [
'site_type' => 'shop',
'create_time' => time(),
'site_name' => $site_name,
'username' => $username
];
$site_model = new Site();
$site_result = $site_model->addSite($site_data);
if ($site_result[ 'code' ] < 0) {
return $this->returnError([], '默认站点添加失败!');
}
$site_id = $site_result[ 'data' ];
$shop_data = [
'site_id' => $site_id,
'shop_status' => 1
];
$shop_model = new Shop();
$shop_result = $shop_model->addShop($shop_data);
if ($shop_result[ 'code' ] < 0) {
return $this->returnError([], '默认店铺添加失败!');
}
// 添加默认数据
$default_result = $this->defaultData($site_id);
if ($default_result[ 'code' ] < 0) {
return $default_result;
}
//添加系统用户组
$group_model = new Group();
$group_data = array (
"site_id" => $site_id,
"app_module" => "shop",
"group_name" => "系统管理员",
"group_status" => 1,
"is_system" => 1,
"menu_array" => "",
"desc" => "",
);
$group_result = $group_model->addGroup($group_data);
if ($group_result[ "code" ] < 0) {
return $this->returnError([], '后台管理员权限组添加失败!');
}
$group_id = $group_result[ "data" ];
$user_model = new User();
$user_data = array (
"app_module" => "shop",
"app_group" => 0,
"is_admin" => 1,
"site_id" => $site_id,
"group_id" => $group_id,
"username" => $username,
"password" => $password
);
$user_result = $user_model->addUser($user_data);
if ($user_result[ "code" ] < 0) {
return $this->returnError([], '后台管理员添加失败!');
}
if ($yanshi) {
// 演示数据
$yanshi_data_result = $this->yanShiData($site_id);
if ($yanshi_data_result[ "code" ] < 0) {
return $this->returnError([], '演示数据添加失败!');
}
}
$fp = fopen($this->lock_file, "w");
if ($fp == false) {
return $this->returnError([], "写入失败,请检查目录" . dirname(__FILE__, 2) . "是否可写入!'");
}
fwrite($fp, '已安装');
fclose($fp);
return $this->returnSuccess([], "安装成功");
}
}
public function installSuccess()
{
return $this->fetch('index/step-4', [], $this->replace);
}
/**
* 测试数据库
*/
public function testDb($dbhost = '', $dbport = '', $dbuser = '', $dbpwd = '', $dbname = '')
{
$dbport = input("dbport", "");
$dbhost = input("dbhost", "");
$dbuser = input("dbuser", "");
$dbpwd = input("dbpwd", "");
$dbname = input("dbname", "");
try {
if ($dbport != "" && $dbhost != "") {
$dbhost = $dbport != '3306' ? $dbhost . ':' . $dbport : $dbhost;
}
if ($dbhost == '' || $dbuser == '') {
return $this->returnError([
"status" => -1,
"message" => "数据库账号或密码不能为空"
]);
}
if (!function_exists("mysqli_connect")) {
return $this->returnError([
"status" => -1,
"message" => "mysqli扩展类必须开启"
]);
}
$conn = @mysqli_connect($dbhost, $dbuser, $dbpwd);
if ($conn) {
if (empty($dbname)) {
$result = [
"status" => 1,
"message" => "数据库连接成功"
];
} else {
if (@mysqli_select_db($conn, $dbname)) {
$result = [
"status" => 2,
"message" => "数据库存在,系统将覆盖数据库"
];
} else {
$result = [
"status" => 1,
"message" => "数据库不存在,系统将自动创建"
];
}
}
} else {
$result = [
"status" => -1,
"message" => "数据库连接失败!"
];
}
@mysqli_close($conn);
return $this->returnSuccess($result);
} catch (\Exception $e) {
$result = [
"status" => -1,
"message" => $e->getMessage()
];
return $this->returnSuccess($result);
}
}
/**
* @param sql文件 $sql_data
* @return array
*/
public function getSqlQuery($sql_data)
{
$sql_data = preg_replace("/TYPE=(InnoDB|MyISAM|MEMORY)( DEFAULT CHARSET=[^; ]+)?/", "ENGINE=\\1 DEFAULT CHARSET=utf8", $sql_data);
$sql_data = str_replace("\r", "\n", $sql_data);
$sql_query = [];
$num = 0;
$sql_arr = explode(";\n", trim($sql_data));
unset($sql);
foreach ($sql_arr as $sql) {
$sql_query[ $num ] = '';
$sqls = explode("\n", trim($sql));
$sqls = array_filter($sqls);
foreach ($sqls as $query) {
$str1 = substr($query, 0, 1);
if ($str1 != '#' && $str1 != '-')
$sql_query[ $num ] .= $query;
}
$num++;
}
return $sql_query;
}
/**
* 初始化平台数据
*/
private function initData($param)
{
$init_event_result = $this->initEvent();
if ($init_event_result[ 'code' ] < 0) {
return $init_event_result;
}
// 初始化自定义组件、链接
$diyview_result = $this->initDiyView();
if ($diyview_result[ 'code' ] < 0) {
return $this->returnError([], '自定义组件初始化失败!');
}
$api_model = new Api();
$data = array (
"public_key" => $this->init_data[ 'api' ][ 'public_key' ],
"private_key" => $this->init_data[ 'api' ][ 'private_key' ],
);
$api_result = $api_model->setApiConfig($data, 1);
if ($api_result[ 'code' ] < 0) {
return $this->returnError([], 'api秘钥配置失败');
}
return $this->returnSuccess();
}
/**
* 添加店铺默认数据
*/
private function defaultData($site_id)
{
// 添加店铺相册默认分组
model("album")->add([ 'site_id' => $site_id, 'type' => 'video', 'album_name' => "默认分组", 'update_time' => time(), 'is_default' => 1, 'level' => 1 ]);
$result = model("album")->add([ 'site_id' => $site_id, 'type' => 'img', 'album_name' => "默认分组", 'update_time' => time(), 'is_default' => 1, 'level' => 1 ]);
if ($result === false) {
return $this->returnError([], '默认相册创建失败!');
}
//执行事件
$add_site_result = event("AddSite", [ 'site_id' => $site_id ]);
if (!empty($add_site_result)) {
foreach ($add_site_result as $site_item) {
if (!empty($site_item) && $site_item[ 'code' ] < 0) {
return $this->returnError([], $site_item[ 'message' ]);
}
}
}
return $this->returnSuccess();
}
/**
* 演示数据
* @param $sys_uid
* @return array
*/
private function yanShiData($site_id)
{
$result_array = event("AddYanshiData", [ 'site_id' => $site_id ]);
if (!empty($result_array)) {
foreach ($result_array as $item) {
if (!empty($item) && $item[ 'code' ] < 0) {
return $this->returnError([], $item[ 'message' ]);
}
}
}
return $this->returnSuccess();
}
/**
* 初始化自定义组件、链接
* @return array
*/
private function initDiyView()
{
$addon = new Addon();
$menu = new Menu();
$menu->truncateDiyView();
$res = $addon->refreshDiyView('');
$addon_list = $addon->getAddonList([], 'name')[ 'data' ];
foreach ($addon_list as $k => $v) {
$addon->refreshDiyView($v[ 'name' ]);
}
return $res;
}
/**
* 初始化插件
*/
private function initEvent()
{
try {
$cache = Cache::get("addon_event_list");
if (empty($cache)) {
$addon_model = new Addon();
$addon_data = $addon_model->getAddonList([], 'name');
$listen_array = [];
foreach ($addon_data[ 'data' ] as $k => $v) {
$addon_event = require_once 'addon/' . $v[ 'name' ] . '/config/event.php';
$listen = $addon_event[ 'listen' ] ?? [];
if (!empty($listen)) {
$listen_array[] = $listen;
}
}
Cache::tag("addon")->set("addon_event_list", $listen_array);
} else {
$listen_array = $cache;
}
if (!empty($listen_array)) {
foreach ($listen_array as $k => $listen) {
if (!empty($listen)) {
Event::listenEvents($listen);
}
}
}
return $this->returnSuccess();
} catch (\Exception $e) {
return $this->returnError('', $e->getMessage());
}
}
function str_replace_first($search, $replace, $subject)
{
return implode($replace, explode($search, $subject, 2));
}
/**
* 初始化gateway配置
*/
protected function initGatewayConfig()
{
$source_file = './app/install/source/gateway.php';
$target_file = './config/gateway.php';
// 读取配置文件
$fp = fopen($source_file, 'r');
$config = fread($fp, filesize($source_file));
fclose($fp);
// 替换内容
$database_config = config('database');
$config = str_replace('model_hostname', $database_config['connections']['mysql']['hostname'], $config);
$config = str_replace('model_database', $database_config['connections']['mysql']['database'], $config);
$config = str_replace('model_username', $database_config['connections']['mysql']['username'], $config);
$config = str_replace('model_password', $database_config['connections']['mysql']['password'], $config);
$config = str_replace('model_port', $database_config['connections']['mysql']['hostport'], $config);
$config = str_replace('model_prefix', $database_config['connections']['mysql']['prefix'], $config);
// 检测文件是否可写
$fp = fopen($target_file, 'w');
if (!$fp) {
return error(-1, '写入配置失败,请检查' . $target_file . '是否可写入!');
}
fwrite($fp, $config);
fclose($fp);
}
}

102
app/install/source/database.php Executable file
View File

@@ -0,0 +1,102 @@
<?php
use think\facade\Env;
return [
// 默认使用的数据库连接配置
'default' => 'mysql',
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段
// true为自动识别类型 false关闭
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 数据库连接配置信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => 'model_hostname',
// 数据库名
'database' => 'model_database',
// 用户名
'username' => 'model_username',
// 密码
'password' => 'model_password',
// 端口
'hostport' => 'model_port',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => 'model_prefix',
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => false,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => false,
// 开启字段缓存
'fields_cache' => true,
// 字段缓存路径
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
],
'v3' => [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '',
// 数据库名
'database' => '',
// 用户名
'username' => '',
// 密码
'password' => '',
// 端口
'hostport' => '3306',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => false,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => false,
// 开启字段缓存
'fields_cache' => true,
// 字段缓存路径
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
],
// 更多的数据库配置信息
],
];

11586
app/install/source/database.sql Executable file

File diff suppressed because it is too large Load Diff

47
app/install/source/gateway.php Executable file
View File

@@ -0,0 +1,47 @@
<?php
$name = 'b2c';//同一服务器不同站点名称不能相同
$register_port = 1342;//同一服务器不同站点注册端口不能相同
$gateway_port = 8283;//同一服务器不同站点gateway端口不能相同
return [
'database' => [
// 连接地址
'host' => 'model_hostname',
// 数据库名称
'dbname' => 'model_database',
// 用户名
'user' => 'model_username',
// 密码
'passwd' => 'model_password',
// 端口
'port' => 'model_port',
// 表前缀
'prefix' => 'model_prefix',
],
'register' => [
'name' => $name.'_register',
'socket_name' => 'text://0.0.0.0:'.$register_port,
],
'worker' => [
'name' => $name.'_worker',
'count' => 4,
'register_address' => '127.0.0.1:'.$register_port,
],
'gateway' => [
'name' => $name.'_gateway',
'count' => 4,
'register_address' => '127.0.0.1:'.$register_port,
'socket_name' => "websocket://0.0.0.0:".$gateway_port,
'lan_ip' => '127.0.0.1',
'start_port' => 4100,//同一服务器不同站点端口号不能相同且要相差最少4个数字如4104,4108,4200,4300
'ping_interval' => 60,
'ping_not_response_limit' => 1,
'ping_data' => '',
],
'ssl' => [
'cert' => 'server.pem', // 无需设置
'key' => 'server.key', // 无需设置
'enable' => false
],
];

72
app/install/source/init.php Executable file
View File

@@ -0,0 +1,72 @@
<?php
return [
'api' => [
'public_key' => '-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9J9Jesl0+vHuZf/kkK/4
fSiHF55aoGMcuGeWSsEurQnHasYUJnqDLS6VozF83o9eR/MFQMfWkJZAlOa7sznm
PGNOKhWvd7wGu7qoW75Lo3HIR/Uw6n7WDoeJedEcrQrsy9WtgRV5LeMnIiy++0SM
LYPlkvEfjsCrRR72s/HUP2xfQ/WzmgYQDU/27YUictak8S68lkXI5ZL+7OaiiFFD
IN8ecT8PTnQ7oZ4sEbxpBVGIxknCR1ldGTHeCp9nNeoo1zcoobXIoHqUtvJErap/
QElAfLG9OJW+E61LPSIRGepiMMDCt8hkZkYt7d3i/7qWM7Uxuin5qJb2+8fE1c/R
3tl/hV374mRbid3oFVX3vDGNbUSMLcgWR2QHKEcms7eF4iwJT6NxXzCNZ4qA0xcE
8RPl5LQviaxDowqij6bsQ9+AgSHru9k3fgB4XAGivZms7CSdb9fnvTWYw8Je+JMG
wDXgrRmE9z1MRfndniDvSDNVSL+lM4oEY3DET1AG0XWd9IqeAUR7bNVEr1WPoojv
zwuxwLLPZ+8nPwF8zbqoitzcghiepSxRo6toREYRbtK7huZnbrthQvVdLJQSLclC
54c99BCxXKhbABxKoFkh5RtqshbJLVnEVol4PFLgym25MfCoPsUEzOBtMogIiEtX
es7EzlKstlTvyik2t3ZVKXUCAwEAAQ==
-----END PUBLIC KEY-----',
'private_key' => '-----BEGIN PRIVATE KEY-----
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
qb4I+BQ4ywbjIpj15QjQ6LITfn77pCI=
-----END PRIVATE KEY-----'
]
];

146
app/install/view/base.html Executable file
View File

@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html>
<head>
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1" />
<title>安装程序 - 单商户V5版</title>
<link rel="icon" type="image/x-icon" href="__STATIC__/img/shop_bitbug_favicon.ico" />
<link rel="stylesheet" type="text/css" href="INSTALL_CSS/style.css" />
<link rel="stylesheet" type="text/css" href="__STATIC__/ext/layui/css/layui.css" />
<script src="__STATIC__/js/jquery-3.1.1.js"></script>
<script src="__STATIC__/ext/layui/layui.js"></script>
<script>
layui.use(['layer', 'upload', 'element'], function() {});
window.ns_url = {
baseUrl: "ROOT_URL/",
route: ['install', '{:request()->controller()}', '{:request()->action()}'],
};
window.regexp_config = {:json_encode(config('regexp'))};
</script>
<script src="INSTALL_JS/common.js"></script>
{block name="resources"}{/block}
</head>
<body>
<div class="head-block">
<div class="top">
<div class="top-logo"></div>
<div class="top-sub" style="flex:1;">单商户V5版</div>
<ul class="top-link">
<li><a href="https://www.niushop.com" target="_blank">官方网站</a></li>
<li><a href="https://bbs.niushop.com" target="_blank">技术论坛</a></li>
</ul>
</div>
</div>
<div class="step-content">
<div style="width:1000px;margin:0 auto;">
<!-- 标题进度条 start-->
<div class="content" style="margin:30px 0 0 0;width: 100%;">
<div class="processBar">
<div class="text" style="margin: 10px -25px;"><span class='poetry'>1.许可协议</span></div>
<div id="line0" class="bar">
<div id="point0" class="c-step c-select"></div>
</div>
</div>
<div class="processBar">
<div class="text" style="margin: 10px -30px;"><span class='poetry'>2.环境检测</span></div>
<div id="line1" class="bar">
<div id="point1" class="c-step"></div>
</div>
</div>
<div class="processBar">
<div class="text" style="margin: 10px -30px;"><span class='poetry'>3.参数配置</span></div>
<div id="line2" class="bar">
<div id="point2" class="c-step"></div>
</div>
</div>
<div class="processBar" style="width:10px;">
<div class="text" style="margin: 10px -39px;"><span class='poetry'>4.安装完成</span></div>
<div id="line3" class="bar" style="width: 0;">
<div id="point3" class="c-step"></div>
</div>
</div>
</div>
<!-- 标题进度条 end-->
<div style="clear: both;"></div>
</div>
</div>
<div class="install-content">
{block name='main'}{/block}
</div>
<script>
var index=0;
$(document).ready(function(){
$("#education").addClass('main-hide');
$("#work").addClass('main-hide');
$("#social").addClass('main-hide');
$('#previous_step').hide();
/*上一步*/
$('#previous_step').bind('click', function () {
index--;
ControlContent(index);
});
/*下一步*/
$('#next_step').bind('click', function () {
index++;
ControlContent(index);
});
});
function ControlContent(index) {
var stepContents = ["basicInfo","education","work","social"];
var key;//数组中元素的索引值
for (key in stepContents) {
var stepContent = stepContents[key];//获得元素的值
if (key == index) {
if(stepContent=='basicInfo'){
$('#previous_step').hide();
}else{
$('#previous_step').show();
}
if(stepContent=='social'){
$('#next_step').hide();
}else{
$('#next_step').show();
}
$('#'+stepContent).removeClass('main-hide');
$('#point'+key).addClass('c-select');
$('#line'+key).removeClass('b-select');
}else {
$('#'+stepContent).addClass('main-hide');
if(key>index){
$('#point'+key).removeClass('c-select');
$('#line'+key).removeClass('b-select');
}else if(key<index){
$('#point'+key).addClass('c-select');
$('#line'+key).addClass('b-select');
}
}
}
}
function success(message){
layer.alert(message, {
icon: 1,
skin: 'layer-ext-moon',
title:'提示'
})
}
function error(message){
layer.alert(message, {
icon: 2,
skin: 'layer-ext-moon',
title:'提示'
})
}
</script>
{block name="script"}{/block}
</body>
</html>

View File

@@ -0,0 +1,75 @@
{extend name="base"/}
{block name="main"}
<div class="pright layui-form">
<h3 class="pr-title">阅读许可协议</h3>
<div class="pr-agreement">
<strong>版权所有 (c)2016Niushop开源商城团队保留所有权利。</strong>
<p>
感谢您选择Niushop开源商城以下简称NiuShopNiuShop基于 PHP + MySQL的技术开发全部源码开放。 <br/>
为了使你正确并合法的使用本软件,请你在使用前务必阅读清楚下面的协议条款:
</p>
<p>
<strong>一、本授权协议适用且仅适用于Niushop开源商城系统(以下简称Niushop)任何版本Niushop开源商城官方对本授权协议的最终解释权。</strong>
</p>
<p>
<strong>二、协议许可的权利 </strong>
<ol>
<li>非授权用户允许商用严禁去除Niushop相关的版权信息。</li>
<li>请尊重Niushop开发人员劳动成果严禁使用本系统转卖、销售或二次开发后转卖、销售等商业行为。</li>
<li>任何企业和个人不允许对程序代码以任何形式任何目的再发布。</li>
<li>您可以在协议规定的约束和限制范围内修改Niushop开源商城源代码或界面风格以适应您的网站要求。</li>
<li>您拥有使用本软件构建的网站全部内容所有权,并独立承担与这些内容的相关法律义务。</li>
<li>
获得商业授权之后,您可以将本软件应用于商业用途,同时依据所购买的授权类型中确定的技术支持内容,自购买时刻起,在技术支持期限内拥有通过指定的方式获得指定范围内的技术支持服务。商业授权用户享有反映和提出意见的权力,相关意见将被作为首要考虑,但没有一定被采纳的承诺或保证。
</li>
</ol>
</p>
<p>
<strong>三、协议规定的约束和限制 </strong>
<ol>
<li>未获商业授权之前允许您对Niushop应用于商业用途但严禁去除Niushop任何相关的版权信息。</li>
<li>未经官方许可,不得对本软件或与之关联的商业授权进行出租、出售、抵押或发放子许可证。</li>
<li>未经官方许可禁止在Niushop开源商城的整体或任何部分基础上以发展任何派生版本、修改版本或第三方版本用于重新分发。</li>
<li>如果您未能遵守本协议的条款,您的授权将被终止,所被许可的权利将被收回,并承担相应法律责任。</li>
</ol>
</p>
<p>
<strong>四、有限担保和免责声明 </strong>
<ol>
<li>本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的。</li>
<li>用户出于自愿而使用本软件,您必须了解使用本软件的风险,在尚未购买产品技术服务之前,我们不承诺对免费用户提供任何形式的技术支持、使用担保,也不承担任何因使用本软件而产生问题的相关责任。</li>
<li>电子文本形式的授权协议如同双方书面签署的协议一样,具有完全的和等同的法律效力。您一旦开始确认本协议并安装
Niushop即被视为完全理解并接受本协议的各项条款在享有上述条款授予的权力的同时受到相关的约束和限制。协议许可范围以外的行为将直接违反本授权协议并构成侵权我们有权随时终止授权责令停止损害并保留追究相关责任的权力。
</li>
<li>如果本软件带有其它软件的整合API示范例子包这些文件版权不属于本软件官方并且这些文件是没经过授权发布的请参考相关软件的使用许可合法的使用。</li>
</ol>
</p>
</div>
<div class="btn-box">
<div class="btn-box-text">
<div class="layui-form-item">
<input type="checkbox" name="readpact" id="readpact" title="我已经阅读并同意此协议" value="1" lay-skin="primary">
</div>
</div>
<button class="layui-btn" lay-submit lay-filter="go">继续</button>
</div>
</div>
{/block}
{block name="script"}
<script>
layui.use('form', function () {
var form = layui.form;
form.on('submit(go)', function (data) {
var readpact = data.field.readpact;
if (readpact == 1) {
window.location.href = '{$root_url}/install.php/index/index?step=2';
} else {
error('您必须同意软件许可协议才能安装!');
}
});
});
</script>
{/block}

View File

@@ -0,0 +1,89 @@
{extend name="base"/}
{block name="main"}
<div class="testing">
<div class="testing-item">
<h3>服务器信息</h3>
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox">
<tr>
<th width="30%" align="center"><strong>参数</strong></th>
<th width="70%"><strong></strong></th>
</tr>
<tr>
<td><strong>服务器域名</strong></td>
<td>{$name}</td>
</tr>
<tr>
<td><strong>服务器操作系统</strong></td>
<td>{$os}</td>
</tr>
<tr>
<td><strong>服务器解译引擎</strong></td>
<td>{$server}</td>
</tr>
<tr>
<td><strong>PHP版本</strong></td>
<td>{$phpv}</td>
</tr>
<tr>
<td><strong>系统安装目录</strong></td>
<td>{$root_path}</td>
</tr>
</table>
</div>
<div class="testing-item">
<h3>系统环境检测<span class="desc">系统环境要求必须满足下列所有条件,否则系统或系统部份功能将无法使用。</span></h3>
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox">
<tr>
<th width="30%" align="center"><strong>需开启的变量或函数</strong></th>
<th width="35%"><strong>要求</strong></th>
<th width="35%"><strong>实际状态及建议</strong></th>
</tr>
<tr>
<td>php版本</td>
<td style="color:#ff8143;">php7.4.0及以上 </td>
<td><font color={if $verison}#ff8143{else/}red{/if}>{$phpv}</font> </td>
</tr>
{foreach $system_variables as $variables_key => $variables_item}
<tr>
<td>{$variables_item.name}</td>
<td>{$variables_item.need}</td>
<td><img clsss="check-icon" src="{if $variables_item.status}INSTALL_IMG/success.png{else/}INSTALL_IMG/error.png{/if}"/></td>
</tr>
{/foreach}
</table>
</div>
<div class="testing-item">
<h3>目录权限检测<span class="desc">系统要求必须满足下列所有的目录权限全部可读写的需求才能使用,其它应用目录可安装后在管理后台检测。</span></h3>
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox">
<tr>
<th width="30%" align="center"><strong>目录名</strong></th>
<th width="35%"><strong>读取权限</strong></th>
<th width="35%"><strong>写入权限</strong></th>
</tr>
{foreach $dirs_list as $dirs_key => $dirs_item}
<tr>
<td>{$dirs_item.path_name}</td>
<td>
<img clsss="check-icon" src="{if $dirs_item.is_readable}INSTALL_IMG/success.png{else/}INSTALL_IMG/error.png{/if}"/>
</td>
<td>
<img clsss="check-icon" src="{if $dirs_item.is_write}INSTALL_IMG/success.png{else/}INSTALL_IMG/error.png{/if}"/>
</td>
</tr>
{/foreach}
</table>
</div>
<div class="btn-box">
<input type="button" class="btn-back" value="后退" onclick="window.location.href = '{$root_url}/install.php/index/index?step=1';" />
<input type="button" class="btn-next" value="继续" {if !$continue} style="background-color:#777;color:#FFF;" disabled="disabled"{/if} onclick="window.location.href = '{$root_url}/install.php/index/index?step=3';" />
</div>
</div>
{/block}
{block name="script"}
<script>
ControlContent(1);
</script>
{/block}

View File

@@ -0,0 +1,244 @@
{extend name="base"/}
{block name="resources"}
<style>
.install-content-procedure .content-procedure-item:first-of-type{
background: url("INSTALL_IMG/complete_two.png") no-repeat center / contain;
color: #fff;
}
.install-content-procedure .content-procedure-item:nth-child(2){
background: url("INSTALL_IMG/complete_four.png") no-repeat center / contain;
color: #fff;
}
.install-content-procedure .content-procedure-item:nth-child(3){
background: url("INSTALL_IMG/conduct.png") no-repeat center / contain;
color: #fff;
}
</style>
{/block}
{block name="main"}
<div id='postloader' class='waitpage'></div>
<form class="layui-form" >
<div class="testing parameter">
<div class="testing-item">
<h3>数据库设定</h3>
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox">
<tr>
<td class="onetd"><span class="required">*</span>数据库主机:</td>
<td>
<input name="dbhost" id="dbhost" type="text" lay-verify="empty" placeholder="请输入数据库主机" value="" class="input-txt" onChange="testDb()" />
<small>一般为localhost</small>
</td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span>Mysql端口</td>
<td>
<input name="dbport" id="dbport" type="text" value="3306" class="input-txt" lay-verify="empty" placeholder="请输入Mysql端口"/>
<small>一般为3306</small>
</td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span>数据库用户:</td>
<td>
<input name="dbuser" id="dbuser" type="text" value="" class="input-txt" onChange="testDb()" lay-verify="empty" placeholder="请输入数据库用户"/>
<small>默认root</small>
</td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span>数据库密码:</td>
<td>
<div style='float:left;margin-right:3px;'>
<input name="dbpwd" id="dbpwd" type="text" class="input-txt" onChange="testDb()" lay-verify="empty" placeholder="请输入数据库密码" />
</div>
<div style='float:left' class="mysql-message" id='dbpwdsta'></div>
</td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span>数据库名称:</td>
<td>
<div style='float:left;margin-right:3px;'><input name="dbname" id="dbname" type="text" value="" class="input-txt" onChange="haveDB()" lay-verify="empty" placeholder="请输入数据库名称" /></div>
<div style='float:left' class="mysql-message" id='havedbsta'></div>
</td>
</tr>
<tr>
<td class="onetd">数据表前缀:</td>
<td>
<div style='float:left;margin-right:3px;'><input name="dbprefix" id="dbprefix" type="text" value="" class="input-txt" placeholder="请输入数据表前缀"/></div>
</td>
</tr>
<tr>
<td class="onetd">数据库编码:</td>
<td>
<label class="install-code">UTF8</label>
</td>
</tr>
</table>
</div>
<div class="testing-item">
<h3>网站设定</h3>
<table border="0" align="center" cellpadding="0" cellspacing="0" class="twbox">
<tr>
<td class="onetd"><span class="required">*</span><strong>网站标题:</strong></td>
<td><input name="site_name" id="site_name" type="text" value="" class="input-txt" lay-verify="empty" placeholder="请输入网站标题"/>
<small id="mess_site_name">网站标题 必填</small></td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span><strong>管理员用户名:</strong></td>
<td><input name="username" id="username" type="text" value="" class="input-txt" lay-verify="empty" placeholder="请输入平台用户名"/>
<small id="mess_username">管理员用户名 必填</small></td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span><strong>管理员密码:</strong></td>
<td><input name="password" id="password" type="password" value="" class="input-txt" lay-verify="empty" placeholder="请输入平台密码"/>
<small id="mess_password">密码 必填</small></td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span><strong>确认密码:</strong></td>
<td><input name="password2" id="password2" type="password" value="" class="input-txt" lay-verify="empty" placeholder="请输入平台确认密码"/>
<small id="mess_password2">确认密码 必填</small></td>
</tr>
<tr>
<td class="onetd"><strong>演示数据:</strong></td>
<td><input type="checkbox" name="yanshi" id="yanshi" title="" value="1" lay-skin="primary">
<small id="mess_yanshi" style="margin-left: 0;">勾选后将添加演示数据</small></td>
</tr>
</table>
</div>
<div class="btn-box"></div>
<div class="btn-box">
<input type="button" class="btn-back" value="后退" onclick="window.location.href='{$root_url}/install.php/index/index?step=2'" />
<input type="button" class="btn-next" lay-submit lay-filter="install" value="开始安装" id="form_submit">
</div>
</div>
</form>
{/block}
{block name='script'}
<script language="javascript" type="text/javascript">
ControlContent(2);
var is_existdb = 1;//数据库是否存在
var message = '数据库账号或密码不能为空';
var is_install = false;
function inputBoxPointer(id){
return document.getElementById(id);
}
layui.use('form', function(){
var form = layui.form;
form.verify({
empty: function(value, item){
if(value == ''){
var msg = $(item).attr("placeholder");
return msg;
}
}
});
form.on('submit(install)', function(data){
if(is_existdb == 2){
layer.confirm('数据库存在,系统将覆盖数据库!', {
btn: ['继续','取消'] //按钮
}, function(){
layer.closeAll(); //疯狂模式,关闭所有层
install(data.field);
}, function(){
layer.closeAll(); //疯狂模式,关闭所有层
return false;
});
}else{
install(data.field);
}
return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
});
function install(data){
if(is_install){
return false;
}
document.getElementById('form_submit').disabled= true;
$("#form_submit").val("正在安装...");
$("#form_submit").addClass("installimg-btn");
var index = layer.load(2);
is_install = true;
$.ajax({
url: "{$root_url}/install.php/index/index?step=4",
data: data,
dataType: 'json',
type: 'post',
success : function(data) {
layer.close(index);
if(data.code < 0){
error(data.message);
is_install = false;
document.getElementById('form_submit').disabled= false;
$("#form_submit").val("开始安装");
$("#form_submit").removeClass("installimg-btn");
}else{
window.location.href = '{$root_url}/install.php/index/installSuccess';
}
}
})
}
});
//数据库连接测试
function testDb()
{
var dbhost = inputBoxPointer('dbhost').value;
var dbuser = inputBoxPointer('dbuser').value;
var dbpwd = inputBoxPointer('dbpwd').value;
var dbport = inputBoxPointer('dbport').value;
inputBoxPointer('dbpwdsta').innerHTML='<img src="INSTALL_IMG/ajax-loader.gif">';
$.ajax({ //post也可
url: '{$root_url}/install.php/index/testdb',
data: { dbhost: dbhost, dbport : dbport, dbuser:dbuser, dbpwd:dbpwd},
type: "post",
dataType: 'json',
success: function(data){
if(data.code >= 0){
inputBoxPointer('dbpwdsta').innerHTML = data.data.message;
is_existdb = data.data.status;
message = data.data.message;
}else{
is_existdb = -1;
}
}
});
}
/**
*验证数据库是否存在
*/
function haveDB()
{
var dbhost = inputBoxPointer('dbhost').value;
var dbname = inputBoxPointer('dbname').value;
var dbuser = inputBoxPointer('dbuser').value;
var dbpwd = inputBoxPointer('dbpwd').value;
var dbport = inputBoxPointer('dbport').value;
inputBoxPointer('havedbsta').innerHTML='<img src="INSTALL_IMG/ajax-loader.gif">';
$.ajax({ //post也可
url: '{$root_url}/install.php/index/testdb',
data: { dbhost: dbhost, dbport : dbport, dbuser:dbuser, dbpwd:dbpwd,dbname:dbname},
type: "post",
dataType: 'json',
success: function(data){
if(data.code >= 0){
inputBoxPointer('havedbsta').innerHTML = data.data.message;
is_existdb = data.data.status;
message = data.data.message;
}else{
is_existdb = -1;
}
}
});
}
</script>
{/block}

View File

@@ -0,0 +1,57 @@
{extend name="base"/}
{block name="resources"}
<style>
.install-content-procedure .content-procedure-item:first-of-type{
background: url("INSTALL_IMG/complete_two.png") no-repeat center / contain;
color: #fff;
}
.install-content-procedure .content-procedure-item:nth-child(2), .install-content-procedure .content-procedure-item:nth-child(3){
background: url("INSTALL_IMG/complete_four.png") no-repeat center / contain;
color: #fff;
}
.install-content-procedure .content-procedure-item:nth-child(4){
background: url("INSTALL_IMG/complete_three.png") no-repeat center / contain;
color: #fff;
}
.install-content-procedure{border: none;}
</style>
{/block}
{block name="main"}
<div class="install-success">
<div class="install-success-box">
<img class="install-success-pic" src="INSTALL_IMG/install_complete.png" alt="">
<div class="install-success-text">
<p class="install-success-title">恭喜您已成功安装单商户V5版系统。</p>
<p class="install-success-desc">建议删除安装目录install后使用</p>
</div>
</div>
</div>
<div class="other-links">
<p class="other-links-title">您现在可以访问:</p>
<ul class="other-links-list">
<li class="other-links-item">
<div class="other-links-pic">
<img src="INSTALL_IMG/site_index.png" alt="">
</div>
<a href="{$root_url}/shop" class="other-links-text" target="_blank">网站后台</a>
</li>
<li class="other-links-item">
<div class="other-links-pic">
<img src="INSTALL_IMG/official_website.png" alt="">
</div>
<a href="http://www.niushop.com" class="other-links-text" target="_blank">NIUSHOP官方网站</a>
</li>
<li class="other-links-item">
<div class="other-links-pic">
<img src="INSTALL_IMG/forum.png" alt="">
</div>
<a href="http://bbs.niushop.com" class="other-links-text" target="_blank">NIUSHOP官方论坛</a>
</li>
</ul>
</div>
{/block}
{block name="script"}
<script>
ControlContent(3);
</script>
{/block}

View File

@@ -0,0 +1,510 @@
*{
padding:0px;
margin:0px;
}
body{
font-family:Verdana, Arial, Helvetica, sans-serif;
font-size:12px;
color: #333;
background-color: #edf0f3;
}
ul{
list-style:none;
}
a{
color: #333;
text-decoration: none;
}
a:hover{
color:#FF6A00;
text-decoration:none;
}
input,button,select{
vertical-align:middle;
outline: none;
}
.fc-690{
color:#333;
}
.fs-14{
font-size:14px;
}
.layui-input, .layui-select, .input-text, .layui-btn{
height: 34px;
line-height: 34px;
font-size: 14px;
}
.layui-btn{
color: #fff;
padding: 0 16px;
background-color: #FF6A00 !important;
}
.btn-box .layui-form-checked[lay-skin=primary] i{
border-color: #FF6A00 !important;
background-color: #FF6A00 !important;
color: #fff !important;
}
.layui-form-checkbox[lay-skin=primary]:hover i{
border-color: #FF6A00 !important;
}
.layui-form-checked[lay-skin=primary] i{
border-color: #FF6A00 !important;
background-color: #FF6A00 !important;
}
.head-block{
margin-bottom: 20px;
background-color: #fff;
}
.top{
overflow:hidden;
display: flex;
justify-content: space-between;
align-items: center;
width: 1200px;
height: 80px;
margin: auto;
}
.top .top-logo{
overflow:hidden;
width:142px;
height: 100%;
background:url(../img/logo.png) no-repeat center;
}
.top-sub{
flex:1;
font-size:19px;
font-weight: bold;
margin-left:10px;
}
.top .top-logo h1{
font-size:0px;
line-height:1000%;
}
.top .top-link{
height:15px;
}
.top .top-link li{
display: inline-block;
margin-left: 15px;
line-height:14px;
font-size: 16px;
}
.install-content{
margin: 0 auto 50px;
width: 1200px;
background-color: #fff;
}
.install-content::after{
content:"";
display: block;
clear: both;
}
.install-content-procedure{
border: 1px solid #EDF0F3;
height: 116px;
}
.install-content-procedure .content-procedure-list{
width: 1000px;
margin: 15px auto;
display: flex;
position: relative;
top: 50%;
transform: translateY(-50%);
}
.install-content-procedure .content-procedure-item{
flex: 1;
height: 36px;
font-size: 14px;
line-height: 36px;
text-align: center;
background: url("../img/not_complete.png") no-repeat center / contain;
}
.install-content-procedure .content-procedure-item:first-of-type{
color: #fff;
background: url("../img/complete_one.png") no-repeat center / contain;
}
.install-content-procedure .content-procedure-item:last-of-type{
background: url("../img/not_complete_two.png") no-repeat center / contain;
}
/* 第一个页面 */
.pright{
margin: 0px auto 0;
padding-bottom: 40px;
width:1100px;
padding-top: 40px;
}
.pright .pr-title{
padding-left: 30px;
height: 50px;
font-size: 16px;
font-weight: bold;
line-height: 50px;
background-color: #e7e7e7;
}
.pr-agreement{
overflow-y:scroll;
padding: 10px 30px;
border:1px solid #ddd;
height:300px;
line-height:21px;
color:#666;
}
.pr-agreement::-webkit-scrollbar {
width: 6px;
background-color: #FFF;
}
.pr-agreement::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: #494E51;
}
.pr-agreement::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #F5F5F5;
}
.pr-agreement strong{
display:block;
color:#333;
line-height:27px;
margin-top:6px;
}
.pr-agreement p{
text-indent:30px;
}
.pr-agreement .describe{
text-indent: 0;
}
.btn-box{
margin-top: 30px;
text-align: right;
vertical-align: middle;
height: 34px;
line-height: 34px;
}
.btn-back, .btn-next{
width:100px;
height:34px;
border:none;
background-color:#ff8143;
color:#FFF;
cursor:pointer;
margin-left:10px;
overflow:hidden;
font-size: 14px;
border-radius:3px;
}
.btn-back{
border: 1px solid #C7C7C7;
color: #333;
background-color: #fff;
}
.btn-box-text{
position: relative;
display: inline-block;
height: 16px;
line-height: 16px;
}
#readpact{
position: relative;
height: 16px;
width: 16px;
vertical-align: bottom;
z-index: 8;
opacity: 0;
cursor: pointer;
}
.btn-box-selection{
position: absolute;
top: 0;
left: 0;
width: 16px;
height: 16px;
background: url("../img/no_agree.png") no-repeat center;
}
.btn-box .agreement{
font-size: 14px;
font-weight: bold;
}
/* 第二个页面 */
.testing{
padding: 25px 25px 35px;
}
.testing-item{
margin-bottom: 30px;
}
.testing-item:last-of-type{
margin-bottom: 0;
}
.testing-item h3{
height: 50px;
line-height: 50px;
font-size: 16px;
font-weight: bold;
}
.testing .testing-item .desc{
margin-left: 5px;
color: #666;
font-size: 12px;
font-weight: normal;
}
.testing .twbox{
width: 100%;
font-size: 14px;
border: 1px solid #e7e7e7;
}
.testing .twbox th{
height: 50px;
text-align: left;
background-color: #e7e7e7;
}
.testing .twbox td{
height: 50px;
border-top: 1px solid #e7e7e7;
}
.testing .twbox th:first-of-type, .testing .twbox td:first-of-type{
padding-left: 30px;
}
/* 第三个页面 */
.parameter .twbox{
border-top: 0;
}
.parameter .input-txt{
padding-left: 11px;
width: 180px;
height: 30px;
border:1px solid #c7c7c7;
font-size:12px;
color: #333;
outline: none;
}
.parameter .onetd{
padding: 0 !important;
width:120px;
font-weight: 400;
text-align:right;
line-height:25px;
}
.parameter small{
margin-left: 20px;
color: #999;
}
.waitpage {
top:0;
left:0;
filter:Alpha(opacity=70);
-moz-opacity:0.7;
position:absolute;
z-index:10000;
background:url(../img/loading1.gif) #ababab no-repeat center 200px;
width:100%;
height:2500px;
display:none;
}
.install-code{
height:27px;line-height:27px;
}
.installimg-btn{
background-color:#777;
}
/* 第四个页面 */
.install-success{
padding: 10px 0 50px;
margin-left: 50px;
margin-right: 50px;
border-bottom: 1px dashed #E7E7E7;
text-align: center;
padding-top: 50px;
}
.install-content .install-success-box{
display: inline-block;
align-self: center;
margin: auto;
}
.install-content .install-success-pic{
width: 45px;
height: 45px;
margin-right: 20px;
vertical-align: middle;
}
.install-content .install-success-text{
display: inline-block;
text-align: left;
vertical-align: middle;
}
.install-content .install-success-title{
margin-bottom: 5px;
font-size: 18px;
font-weight: bolder;
}
.install-content .install-success-desc{
color: #999;
font-size: 14px;
}
.install-content .other-links{
padding: 39px 50px 300px;
font-size: 14px;
}
.install-content .other-links-list{
display: flex;
margin-top: 60px;
justify-content: space-around;
}
.install-content .other-links-item{
display: flex;
align-self: center;
}
.install-content .other-links-pic{
margin-right: 20px;
width: 45px;
height: 45px;
line-height: 45px;
text-align: center;
}
.install-content .other-links-pic img{
display: block;
max_width: 100%;
max-height: 100%;
}
.install-content .other-links-text{
line-height: 45px;
}
.step-content{
margin: 0 auto 3px;
width: 1200px;
background-color: #fff;
padding-bottom:30px;
}
input{
vertical-align:middle;
margin-right:3px;
font-size:12px;
}
input.but{
height:26px;
padding-left:6px;
padding-right:6px;
line-height:26px;
font-weight:bold;
letter-spacing:1px;
color:#FFF;
background-color:#FC3;
}
/*步骤*/
.processBar{
float: left;
width: 329px;
margin-top: 15px;
}
.processBar .bar{
background: #fbeeea;
height: 3px;
position: relative;
width: 314px;
margin-left: 10px;
}
.processBar .b-select{
background: #ff8143;
}
.processBar .bar .c-step{
position: absolute;
width: 16px;
height: 16px;
border-radius: 50%;
background-image: url(../img/step_point.png);
left: -16px;
top: 50%;
margin-top: -8px;
}
.processBar .bar .c-select{
width: 16px;
height: 16px;
margin: -9px 1px;
background-image: url(../img/step_point_check.png);
}
.main-hide {
position: absolute;
top: -9999px;
left: -9999px;
}
.poetry{
color: #000;
font-size: 13px;
background-color: transparent;
font-weight: 800;
}
button{
width: 80px;
line-height: 30px;
font-size: 11px;
color: #ff8143;
text-align: center;
border-radius: 6px;
border: 1px solid #e2e2e2;
cursor: pointer;
background-color: #fff;
outline:none;
}
button:hover{
border: 1px solid #fbeeea;
}
.layui-form-item .layui-form-checkbox[lay-skin=primary]{
margin-top: 3px !important;
}
.mysql-message{
height: 32px;
line-height: 32px;
margin-left: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

View File

@@ -0,0 +1,166 @@
var ns = window.ns_url;
/* 基础对象检测 */
ns || $.error("js-ns_url基础配置没有正确加载");
/**
* 解析URL
* @param {string} url 被解析的URL
* @return {object} 解析后的数据
*/
ns.parse_url = function (url) {
var parse = url.match(/^(?:([a-z]+):\/\/)?([\w-]+(?:\.[\w-]+)+)?(?::(\d+))?([\w-\/]+)?(?:\?((?:\w+=[^#&=\/]*)?(?:&\w+=[^#&=\/]*)*))?(?:#([\w-]+))?$/i);
parse || $.error("url格式不正确");
return {
"scheme": parse[1],
"host": parse[2],
"port": parse[3],
"path": parse[4],
"query": parse[5],
"fragment": parse[6]
};
}
ns.parse_str = function (str) {
var value = str.split("&"), vars = {}, param;
for (val in value) {
param = value[val].split("=");
vars[param[0]] = param[1];
}
return vars;
}
ns.parse_name = function (name, type) {
if (type) {
/* 下划线转驼峰 */
name = name.replace(/_([a-z])/g, function ($0, $1) {
return $1.toUpperCase();
});
/* 首字母大写 */
name = name.replace(/[a-z]/, function ($0) {
return $0.toUpperCase();
});
} else {
/* 大写字母转小写 */
name = name.replace(/[A-Z]/g, function ($0) {
return "_" + $0.toLowerCase();
});
/* 去掉首字符的下划线 */
if (0 === name.indexOf("_")) {
name = name.substr(1);
}
}
return name;
}
//scheme://host:port/path?query#fragment
ns.url = function (url, vars, suffix) {
var info = this.parse_url(url), path = [], param = {}, reg;
/* 验证info */
info.path || $.error("url格式错误");
url = info.path;
/* 解析URL */
path = url.split("/");
path = [path.pop(), path.pop(), path.pop()].reverse();
path[1] = path[1] || this.route[1];
path[0] = path[0] || this.route[0];
// param[this.route[0]] = path[0];
// param[this.route[1]] = path[1];
// param[this.route[2]] = path[2].toLowerCase();
// url = param[this.route[0]] + '/' + param[this.route[1]] + '/' + param[this.route[2]];
param[this.route[2]] = path[0];
param[this.route[3]] = path[1];
param[this.route[4]] = path[2].toLowerCase();
url = param[this.route[2]] + '/' + param[this.route[3]] + '/' + param[this.route[4]];
/* 解析参数 */
if (typeof vars === "string") {
vars = this.parse_str(vars);
} else if (!$.isPlainObject(vars)) {
vars = {};
}
/* 添加伪静态后缀 */
if (false !== suffix) {
suffix = suffix || 'html';
if (suffix) {
url += "." + suffix;
}
}
/* 解析URL自带的参数 */
info.query && $.extend(vars, this.parse_str(info.query));
/* 判断站点id是否存在 */
var site = '';
if (vars.site_id) {
var site_id = vars.site_id;
delete vars.site_id;
site = 's' + parseInt(site_id) + '/';
} else {
var site_id = this.route[0];
site = site_id > 0 ? 's' + parseInt(site_id) + '/' : '';
}
var addon = '';
if (info.scheme != '' && info.scheme != undefined) {
addon = info.scheme + '/';
}
url = site + addon + url;
if (vars) {
var param_str = $.param(vars);
if ('' !== param_str) {
url += ((this.baseUrl + url).indexOf('?') !== -1 ? '&' : '?') + param_str;
}
}
url = this.baseUrl + url;
return url;
}
/**
* 处理图片路径
*/
ns.img = function (path, type = '') {
if (path.indexOf("http://") == -1 && path.indexOf("https://") == -1) {
var start = path.lastIndexOf('.');
type = type ? '_' + type : '';
var base_url = this.baseUrl.replace('/?s=', '');
var suffix = path.substring(start);
var path = path.substring(0, start);
var true_path = base_url + 'attachment/' + path + type + suffix;
} else {
var true_path = path;
}
return true_path;
}
/**
* 时间戳转时间
*
*/
ns.time_to_date = function (timeStamp) {
if (timeStamp > 0) {
var date = new Date();
date.setTime(timeStamp * 1000);
var y = date.getFullYear();
var m = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
var d = date.getDate();
d = d < 10 ? ('0' + d) : d;
var h = date.getHours();
h = h < 10 ? ('0' + h) : h;
var minute = date.getMinutes();
var second = date.getSeconds();
minute = minute < 10 ? ('0' + minute) : minute;
second = second < 10 ? ('0' + second) : second;
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
} else {
return "";
}
}
/**
* url 反转义
* @param url
*/
ns.urlReplace = function (url) {
var new_url = url.replace(/%2B/g, "+");//"+"转义
new_url = new_url.replace(/%26/g, "&");//"&"
new_url = new_url.replace(/%23/g, "#");//"#"
new_url = new_url.replace(/%20/g, " ");//" "
new_url = new_url.replace(/%3F/g, "?");//"#"
new_url = new_url.replace(/%25/g, "%");//"#"
new_url = new_url.replace(/&3D/g, "=");//"#"
new_url = new_url.replace(/%2F/g, "/");//"#"
return new_url;
}

9814
app/install/view/public/js/jquery-2.2.js vendored Executable file

File diff suppressed because it is too large Load Diff