作者 Karson

优化安装脚本

优化SelectPage编辑时按顺序显示
优化分类、省市联动列表接口逻辑
... ... @@ -20,14 +20,15 @@ FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架。
* 强大的插件扩展功能,在线安装卸载升级插件
* 通用的会员模块和API模块
* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
* 二级域名部署支持,同时域名支持绑定到插件
* 二级域名部署支持,同时域名支持绑定到应用插件
* 多语言支持,服务端及客户端支持
* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩
* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)[博客](https://www.fastadmin.net/store/blog.html)[知识付费问答](https://www.fastadmin.net/store/ask.html)[在线投票系统](https://www.fastadmin.net/store/vote.html)[商城系统](https://www.fastadmin.net/store/shopro.html))
* 支持表格固定列、固定表头、跨页选择、Excel导出、模板渲染等功能
* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)[博客](https://www.fastadmin.net/store/blog.html)[知识付费问答](https://www.fastadmin.net/store/ask.html)[在线投票系统](https://www.fastadmin.net/store/vote.html)[B2C商城](https://www.fastadmin.net/store/shopro.html)[B2B2C商城](https://www.fastadmin.net/store/wanlshop.html))
* 支持CMS、博客、知识付费问答无缝整合[Xunsearch全文搜索](https://www.fastadmin.net/store/xunsearch.html)
* 第三方小程序支持([预订小程序](https://www.fastadmin.net/store/ball.html)[问答小程序](https://www.fastadmin.net/store/questions.html)[活动报名小程序](https://www.fastadmin.net/store/huodong.html)[商城小程序](https://www.fastadmin.net/store/xshop.html)[博客小程序](https://www.fastadmin.net/store/blog.html))
* 第三方小程序支持([CMS小程序](https://www.fastadmin.net/store/cms.html)[预订小程序](https://www.fastadmin.net/store/ball.html)[问答小程序](https://www.fastadmin.net/store/ask.html)[点餐小程序](https://www.fastadmin.net/store/unidrink.html)[B2C小程序](https://www.fastadmin.net/store/shopro.html)[B2B2C小程序](https://www.fastadmin.net/store/wanlshop.html)[博客小程序](https://www.fastadmin.net/store/blog.html))
* 整合第三方短信接口(阿里云、腾讯云短信)
* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能
* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能,支持云储存分片上传
* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)
* 第三方登录(QQ、微信、微博)整合
* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
... ... @@ -48,7 +49,7 @@ https://demo.fastadmin.net
提 示:演示站数据无法进行修改,请下载源码安装体验全部功能
## 界面截图
![控制台](https://gitee.com/uploads/images/2017/0411/113717_e99ff3e7_10933.png "控制台")
![控制台](https://images.gitee.com/uploads/images/2020/0929/202947_8db2d281_10933.gif "控制台")
## 问题反馈
... ...
... ... @@ -90,7 +90,10 @@ class Install extends Command
$this->request = Request::instance();
define('INSTALL_PATH', APP_PATH . 'admin' . DS . 'command' . DS . 'Install' . DS);
Lang::load(INSTALL_PATH . $this->request->langset() . '.php');
$langSet = $this->request->langset();
if ($langSet === 'zh-cn') {
Lang::load(INSTALL_PATH . $langSet . '.php');
}
$installLockFile = INSTALL_PATH . "install.lock";
... ... @@ -196,23 +199,19 @@ class Install extends Command
// 后台入口文件
$adminFile = ROOT_PATH . 'public' . DS . 'admin.php';
// 数据库配置文件
$dbConfigFile = APP_PATH . 'database.php';
$config = @file_get_contents($dbConfigFile);
// 生成数据库Env配置文件
$envFile = ROOT_PATH . '.env.sample';
$envStr = @file_get_contents($envFile);
$callback = function ($matches) use ($mysqlHostname, $mysqlHostport, $mysqlUsername, $mysqlPassword, $mysqlDatabase, $mysqlPrefix) {
$field = "mysql" . ucfirst($matches[1]);
$replace = $$field;
if ($matches[1] == 'hostport' && $mysqlHostport == 3306) {
$replace = '';
}
return "'{$matches[1]}'{$matches[2]}=>{$matches[3]}Env::get('database.{$matches[1]}', '{$replace}'),";
return "{$matches[1]} = {$replace}" . PHP_EOL;
};
$config = preg_replace_callback("/'(hostname|database|username|password|hostport|prefix)'(\s+)=>(\s+)Env::get\((.*)\)\,/", $callback, $config);
$envConf = preg_replace_callback('/(hostname|database|username|password|hostport|prefix)\s*=\s*(.*?)\n/', $callback, $envStr);
// 检测能否成功写入数据库配置
$result = @file_put_contents($dbConfigFile, $config);
$result = @file_put_contents(ROOT_PATH . '.env', $envConf);
if (!$result) {
throw new Exception(__('The current permissions are insufficient to write the file %s', 'application/database.php'));
throw new Exception(__('The current permissions are insufficient to write the file %s', '.env'));
}
// 变更默认管理员密码
... ... @@ -222,6 +221,12 @@ class Install extends Command
$newPassword = md5(md5($adminPassword) . $newSalt);
$data = ['username' => $adminUsername, 'email' => $adminEmail, 'password' => $newPassword, 'salt' => $newSalt];
$instance->name('admin')->where('username', 'admin')->update($data);
// 变更前台默认用户的密码,随机生成
$newSalt = substr(md5(uniqid(true)), 0, 6);
$newPassword = md5(md5(Random::alnum(8)) . $newSalt);
$instance->name('user')->where('username', 'admin')->update(['password' => $newPassword, 'salt' => $newSalt]);
// 修改后台入口
$adminName = '';
if (is_file($adminFile)) {
... ... @@ -230,9 +235,9 @@ class Install extends Command
}
//修改站点名称
if ($siteName != __('My Website')) {
if ($siteName != config('site.name')) {
$instance->name('config')->where('name', 'name')->update(['value' => $siteName]);
$configFile = APP_PATH . 'extra' . DS . 'site.php';
$configFile = CONF_PATH . 'extra' . DS . 'site.php';
$config = include $configFile;
$configList = $instance->name("config")->select();
foreach ($configList as $k => $value) {
... ... @@ -270,17 +275,15 @@ class Install extends Command
'public' . DS . 'assets' . DS . 'libs'
];
//数据库配置文件
$dbConfigFile = APP_PATH . 'database.php';
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
throw new Exception(__("The current version %s is too low, please use PHP 5.5 or higher", PHP_VERSION));
if (version_compare(PHP_VERSION, '7.0.0', '<')) {
throw new Exception(__("The current version %s is too low, please use PHP 7.0 or higher", PHP_VERSION));
}
if (!extension_loaded("PDO")) {
throw new Exception(__("PDO is not currently installed and cannot be installed"));
}
if (!is_really_writable($dbConfigFile)) {
throw new Exception(__('The current permissions are insufficient to write the configuration file application/database.php'));
$envConfFile = ROOT_PATH . '.env';
if (is_file($envConfFile) && !is_really_writable($envConfFile)) {
throw new Exception(__('The current permissions are insufficient to write the file %s', '.env'));
}
foreach ($checkDirs as $k => $v) {
if (!is_dir(ROOT_PATH . $v)) {
... ...
... ... @@ -8,10 +8,10 @@ return [
'Mysql Password' => 'MySQL 密码',
'Mysql Prefix' => 'MySQL 数据表前缀',
'Mysql Hostport' => 'MySQL 端口号',
'Admin Username' => '管理者用户名',
'Admin Email' => '管理者Email',
'Admin Password' => '管理者密码',
'Repeat Password' => '重复密码',
'Admin Username' => '管理员用户名',
'Admin Email' => '管理员Email',
'Admin Password' => '管理员密码',
'Repeat Password' => '重复管理员密码',
'Website' => '网站名称',
'My Website' => '我的网站',
'Install now' => '点击安装',
... ... @@ -26,9 +26,9 @@ return [
'Please input correct password' => '密码长度必须在6-16位之间,不能包含空格',
'The two passwords you entered did not match' => '两次输入的密码不一致',
'Please input correct website' => '网站名称输入不正确',
'The current version %s is too low, please use PHP 5.5 or higher' => '当前版本%s过低,请使用PHP5.5以上版本',
'The current version %s is too low, please use PHP 7.0 or higher' => '当前版本%s过低,请使用PHP7.0以上版本',
'PDO is not currently installed and cannot be installed' => '当前未开启PDO,无法进行安装',
'The current permissions are insufficient to write the file %s' => '当前权限不足,无法写入文件%s',
'Please go to the official website to download the full package or resource package and try to install' => '当前代码仅包含核心代码,请前往官网下载完整包或资源包覆盖后再尝试安装',
'The system has been installed. If you need to reinstall, please remove %s first' => '当前已经安装成功,如果需要重新安装,请手动移除%s文件',
];
\ No newline at end of file
];
... ...
... ... @@ -29,7 +29,7 @@ class Ajax extends Backend
parent::_initialize();
//设置过滤方法
$this->request->filter(['strip_tags', 'htmlspecialchars']);
$this->request->filter(['trim', 'strip_tags', 'htmlspecialchars']);
}
/**
... ... @@ -138,8 +138,8 @@ class Ajax extends Backend
$orderway = $orderway == 'asc' ? 'ASC' : 'DESC';
$sour = $weighdata = [];
$ids = explode(',', $ids);
$prikey = $pk ? $pk : (Db::name($table)->getPk() ?: 'id');
$pid = $this->request->post("pid");
$prikey = $pk && preg_match("/^[a-z0-9\-_]+$/i", $pk) ? $pk : (Db::name($table)->getPk() ?: 'id');
$pid = $this->request->post("pid", "");
//限制更新的字段
$field = in_array($field, ['weigh']) ? $field : 'weigh';
... ... @@ -217,20 +217,20 @@ class Ajax extends Backend
*/
public function category()
{
$type = $this->request->get('type');
$pid = $this->request->get('pid');
$type = $this->request->get('type', '');
$pid = $this->request->get('pid', '');
$where = ['status' => 'normal'];
$categorylist = null;
$categorylist = null;
if ($pid || $pid === '0') {
$where['pid'] = $pid;
}
if ($type) {
$where['type'] = $type;
}
$categorylist = Db::name('category')->where($where)->field('id as value,name')->order('weigh desc,id desc')->select();
$this->success('', null, $categorylist);
$this->success('', '', $categorylist);
}
/**
... ... @@ -241,27 +241,23 @@ class Ajax extends Backend
$params = $this->request->get("row/a");
if (!empty($params)) {
$province = isset($params['province']) ? $params['province'] : '';
$city = isset($params['city']) ? $params['city'] : null;
$city = isset($params['city']) ? $params['city'] : '';
} else {
$province = $this->request->get('province');
$city = $this->request->get('city');
$province = $this->request->get('province', '');
$city = $this->request->get('city', '');
}
$where = ['pid' => 0, 'level' => 1];
$provincelist = null;
if ($province !== '') {
if ($province) {
$where['pid'] = $province;
$where['level'] = 2;
}
$where['pid'] = $province;
$where['level'] = 2;
if ($city !== '') {
if ($city) {
$where['pid'] = $city;
$where['level'] = 3;
}
$provincelist = Db::name('area')->where($where)->field('id as value,name')->select();
$where['pid'] = $city;
$where['level'] = 3;
}
}
$this->success('', null, $provincelist);
$provincelist = Db::name('area')->where($where)->field('id as value,name')->select();
$this->success('', '', $provincelist);
}
/**
... ...
... ... @@ -189,7 +189,7 @@ class Config extends Backend
$config[$value['name']] = $value['value'];
}
file_put_contents(
APP_PATH . 'extra' . DS . 'site.php',
CONF_PATH . 'extra' . DS . 'site.php',
'<?php' . "\n\nreturn " . var_export_short($config) . ";\n"
);
}
... ...
... ... @@ -112,7 +112,6 @@
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
margin-right: 10px;
}
.stat .value {
... ...
... ... @@ -535,25 +535,22 @@ class Backend extends Controller
}
$fields = is_array($this->selectpageFields) ? $this->selectpageFields : ($this->selectpageFields && $this->selectpageFields != '*' ? explode(',', $this->selectpageFields) : []);
//如果有primaryvalue,说明当前是初始化传值,按照选择顺序排序
if ($primaryvalue !== null) {
if ($primaryvalue !== null && preg_match("/^[a-z0-9_\-]+$/i", $primarykey)) {
$primaryvalue = array_unique(is_array($primaryvalue) ? $primaryvalue : explode(',', $primaryvalue));
$primaryvalue = implode(',', array_map([$this->model->getConnection(), 'quote'], $primaryvalue));
$datalist = $this->model->where($where)
->orderRaw("FIELD(`{$primarykey}`, {$primaryvalue})")
->page($page, $pagesize)
->field($this->selectpageFields)
->select();
$primaryvalue = implode(',', $primaryvalue);
$this->model->orderRaw("FIELD(`{$primarykey}`, {$primaryvalue})");
} else {
$datalist = $this->model->where($where)
->order($order)
->page($page, $pagesize)
->field($this->selectpageFields)
->select();
$this->model->order($order);
}
$datalist = $this->model->where($where)
->page($page, $pagesize)
->field($this->selectpageFields)
->select();
foreach ($datalist as $index => $item) {
unset($item['password'], $item['salt']);
if ($this->selectpageFields == '*') {
... ...
... ... @@ -57,7 +57,7 @@
<p style="color:#adb9e0;line-height:30px;">网站(Website)是指在因特网上根据一定的规则,使用HTML(标准通用标记语言)等工具制作的用于展示特定内容相关网页的集合。简单地说,网站是一种沟通工具,人们可以通过网站来发布自己想要公开的资讯,或者利用网站来提供相关的网络服务。</p>
<div>
<a href="{:url('index/user/index')}" class="btn bg-primary btn-xl btn-round-lg">会员中心</a>
<a href="{:url('index/user/index')}" class="btn bg-primary btn-xl btn-round-lg">{:__('Member center')}</a>
</div>
</div>
</div>
... ...
... ... @@ -26,7 +26,8 @@
"nelexa/zip": "^3.3",
"symfony/var-exporter": "^4.4.13",
"ext-json": "*",
"ext-curl": "*"
"ext-curl": "*",
"ext-pdo": "*"
},
"config": {
"preferred-install": "dist"
... ...