pref: 增加服务类优化UI版面

This commit is contained in:
Ying
2023-06-19 14:32:30 +08:00
parent 27eda6f37f
commit 2b8f874450
148 changed files with 3933 additions and 9286 deletions

View File

@@ -67,6 +67,12 @@ class AdminController extends BaseController
*/ */
protected bool $dataLimit = false; protected bool $dataLimit = false;
/**
* 是否开启部门限制
* @var bool
*/
protected bool $departmentLimit = false;
/** /**
* 数据限制字段 * 数据限制字段
* @var string * @var string
@@ -108,7 +114,7 @@ class AdminController extends BaseController
/** /**
* 获取资源列表 * 获取资源列表
* @return Response|void * @return Response
*/ */
public function index() public function index()
{ {
@@ -117,7 +123,6 @@ class AdminController extends BaseController
$limit = (int)input('limit', 18); $limit = (int)input('limit', 18);
$where = $this->buildSelectParams(); $where = $this->buildSelectParams();
$count = $this->model->where($where)->count(); $count = $this->model->where($where)->count();
$limit = is_empty($limit) ? 10 : $limit;
$page = $count <= $limit ? 1 : $page; $page = $count <= $limit ? 1 : $page;
$fieldList = $this->model->getFields(); $fieldList = $this->model->getFields();
$order = !array_key_exists('sort', $fieldList) ? 'id' : 'sort'; $order = !array_key_exists('sort', $fieldList) ? 'id' : 'sort';
@@ -219,6 +224,7 @@ class AdminController extends BaseController
/** /**
* 删除资源 * 删除资源
* @return Response
*/ */
public function del() public function del()
{ {
@@ -362,14 +368,14 @@ class AdminController extends BaseController
/** /**
* 获取查询参数 * 获取查询参数
* @return array
*/ */
protected function buildSelectParams() protected function buildSelectParams(): array
{ {
$where = [];
$params = request()->all(); $params = request()->all();
if (!empty($params) && is_array($params)) { if (!empty($params) && is_array($params)) {
$where = [];
$this->tableFields = $this->model->getFields(); $this->tableFields = $this->model->getFields();
foreach ($params as $field => $value) { foreach ($params as $field => $value) {
@@ -413,23 +419,18 @@ class AdminController extends BaseController
case 'year': case 'year':
$value = str_replace(',', '-', $value); $value = str_replace(',', '-', $value);
if (strpos($value, '-')) { if (strpos($value, '-')) {
$arr = explode(' - ', $value); $arr = explode(' - ', $value);
if (empty($arr)) { if (empty($arr)) {
continue 2; continue 2;
} }
if (in_array($field, $this->converTime)) { if (in_array($field, $this->converTime)) {
if (isset($arr[0])) { if (isset($arr[0])) {
$arr[0] = strtotime($arr[0]); $arr[0] = strtotime($arr[0]);
} }
if (isset($arr[1])) { if (isset($arr[1])) {
$arr[1] = strtotime($arr[1]); $arr[1] = strtotime($arr[1]);
} }
} }
$exp = 'between'; $exp = 'between';
if ($arr[0] === '') { if ($arr[0] === '') {
$exp = '<='; $exp = '<=';
@@ -438,7 +439,6 @@ class AdminController extends BaseController
$exp = '>='; $exp = '>=';
$arr = $arr[0]; $arr = $arr[0];
} }
$where[] = [$field, $exp, $arr]; $where[] = [$field, $exp, $arr];
} else { } else {
$where[] = [$field, '=', $value]; $where[] = [$field, '=', $value];
@@ -484,17 +484,20 @@ class AdminController extends BaseController
} }
} }
// 限制数据字段 // 限制个人数据权限
if (!$this->auth->SuperAdmin() && $this->dataLimit) { $superAdmin = $this->auth->SuperAdmin();
if (!$superAdmin && $this->dataLimit) {
if (in_array($this->dataLimitField, $this->tableFields)) { if (in_array($this->dataLimitField, $this->tableFields)) {
$where[] = [$this->dataLimitField, '=', get_admin_id()]; $where[] = [$this->dataLimitField, '=', get_admin_id()];
} }
} // 限制部门数据权限
else if (!$superAdmin && $this->departmentLimit
&& in_array('department_id', $this->tableFields)) {
$where[] = ['department_id', 'in', get_admin_info('AdminLogin.department_id')];
} }
return $where;
} }
return false; return $where;
} }
/** /**

View File

@@ -11,7 +11,8 @@ declare (strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
namespace app; namespace app;
use app\common\library\Auth; use app\common\service\user\UserService;
use support\Response;
/** /**
* Api全局控制器基类 * Api全局控制器基类
@@ -27,6 +28,52 @@ class ApiController extends BaseController
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->auth = Auth::instance(); }
/**
* 操作成功跳转
* @access protected
* @param mixed $msg
* @param mixed $url
* @param mixed $data
* @param int $count
* @param int $code
* @param int $wait
* @param array $header
* @return Response
*/
protected function success(mixed $msg = '', mixed $url = '', mixed $data = '', int $count = 0, int $code = 200, int $wait = 3, array $header = []): Response
{
$msg = !empty($msg) ? __($msg) : __('操作成功!');
$result = ['code' => $code, 'msg' => $msg, 'data' => $data, 'count' => $count, 'url' => (string)$url, 'wait' => $wait];
return json($result);
}
/**
* 操作错误跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param mixed $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param int $code
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return Response
*/
protected function error(mixed $msg = '', mixed $url = '', mixed $data = '', int $code = 101, int $wait = 3, array $header = []): Response
{
$msg = !empty($msg) ? __($msg) : __('操作失败!');
$result = ['code' => $code, 'msg' => $msg, 'data' => $data, 'url' => (string)$url, 'wait' => $wait];
return json($result);
}
/**
* 退出登录
* @access public
*/
public function logOut(): Response
{
UserService::logout();
return $this->success('退出成功', '/');
} }
} }

View File

@@ -10,6 +10,7 @@ declare (strict_types=1);
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License // | Author: meystack <coolsec@foxmail.com> Apache 2.0 License
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
namespace app; namespace app;
use support\Log; use support\Log;
use support\Response; use support\Response;
use think\db\exception\BindParamException; use think\db\exception\BindParamException;
@@ -44,12 +45,6 @@ class BaseController
*/ */
public string $scene = ''; public string $scene = '';
/**
* 是否批量验证
* @var bool
*/
protected bool $batchValidate = false;
/** /**
* 获取访问来源 * 获取访问来源
* @var string * @var string
@@ -58,59 +53,7 @@ class BaseController
public function __construct() public function __construct()
{ {
$this->referer = \request()->header('referer'); $this->referer = \request()->header('referer', '/');
}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param $validate
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return bool
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false): bool
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
[$validate, $scene] = explode('.', $validate);
}
$class = str_contains($validate, '\\') ? $validate : $this->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch();
}
return $v->failException()->check($data);
}
/**
* 解析应用类的类名
* @access public
* @param string $layer 层名 controller model ...
* @param string $name 类名
* @return string
*/
protected function parseClass(string $layer, string $name): string
{
$name = str_replace(['/', '.'], '\\', $name);
$array = explode('\\', $name);
$class = Str::studly(array_pop($array));
$path = $array ? implode('\\', $array) . '\\' : '';
return 'app' . '\\' . $layer . '\\' . $path . $class;
} }
/** /**
@@ -204,8 +147,8 @@ class BaseController
*/ */
protected function getResponseType(): string protected function getResponseType(): string
{ {
$mask=request()->input('_ajax')==1 ||request()->input('_pjax')==1; $_ajax = request()->input('_ajax', input('_pjax'));
return request()->isAjax() || request()->acceptJson() || $mask ? 'json' : 'html'; return request()->isAjax() || request()->acceptJson() || $_ajax ? 'json' : 'html';
} }
/** /**

View File

@@ -12,7 +12,7 @@ declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
namespace app; namespace app;
use app\common\library\Auth; use app\common\service\user\UserService;
use Psr\SimpleCache\InvalidArgumentException; use Psr\SimpleCache\InvalidArgumentException;
use support\Response; use support\Response;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
@@ -45,12 +45,6 @@ class HomeController extends BaseController
*/ */
public string $errorText = ''; public string $errorText = '';
/**
* 接口权限
* @var object
*/
public object $auth;
/** /**
* 控制器登录鉴权 * 控制器登录鉴权
* @var bool * @var bool
@@ -67,13 +61,13 @@ class HomeController extends BaseController
* 非鉴权方法 * 非鉴权方法
* @var array * @var array
*/ */
public array $noNeedAuth = []; public array $noNeedLogin = [];
/** /**
* 跳转URL地址 * 跳转URL地址
* @var string * @var string
*/ */
public string $JumpUrl = '/user/index'; public string $JumpUrl = '/';
/** /**
* 初始化函数 * 初始化函数
@@ -82,7 +76,6 @@ class HomeController extends BaseController
{ {
// 获取权限实例 // 获取权限实例
parent::__construct(); parent::__construct();
$this->auth = Auth::instance();
} }
/** /**
@@ -92,9 +85,6 @@ class HomeController extends BaseController
* @param string $app * @param string $app
* @return Response * @return Response
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/ */
protected function view(string $template = '', array $argc = [], string $app = 'index'): \support\Response protected function view(string $template = '', array $argc = [], string $app = 'index'): \support\Response
{ {
@@ -113,4 +103,14 @@ class HomeController extends BaseController
return view($template, $argc, $app); return view($template, $argc, $app);
} }
/**
* 退出登录
* @access public
*/
public function logOut(): Response
{
UserService::logout();
return $this->success('退出成功', '/');
}
} }

View File

@@ -12,21 +12,19 @@ declare(strict_types=1);
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
namespace app\admin\controller; namespace app\admin\controller;
use app\common\service\notice\EmailService;
use app\common\service\utils\FtpService;
use Psr\SimpleCache\InvalidArgumentException; use Psr\SimpleCache\InvalidArgumentException;
use support\Response; use support\Response;
use think\db\exception\BindParamException; use think\db\exception\BindParamException;
use think\facade\Cache; use support\Cache;
use think\facade\Db; use think\facade\Db;
use Webman\Event\Event; use Webman\Event\Event;
use system\Random; use system\Random;
use think\cache\driver\Memcached;
use think\cache\driver\Redis;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use app\AdminController; use app\AdminController;
use app\common\library\Email;
use app\common\library\Ftp;
use app\common\model\system\AdminNotice; use app\common\model\system\AdminNotice;
use app\common\model\system\Attachment; use app\common\model\system\Attachment;
use app\common\model\system\Config; use app\common\model\system\Config;
@@ -389,7 +387,6 @@ class Index extends AdminController
(new Config())->saveAll($config); (new Config())->saveAll($config);
$env = base_path() . '/.env'; $env = base_path() . '/.env';
$parse = parse_ini_file($env, true); $parse = parse_ini_file($env, true);
$parse['CACHE_DRIVER'] = $post['cache_type'];
$parse['CACHE_HOSTNAME'] = $post['cache_host']; $parse['CACHE_HOSTNAME'] = $post['cache_host'];
$parse['CACHE_HOSTPORT'] = $post['cache_port']; $parse['CACHE_HOSTPORT'] = $post['cache_port'];
$parse['CACHE_SELECT'] = $post['cache_select']; $parse['CACHE_SELECT'] = $post['cache_select'];
@@ -401,7 +398,6 @@ class Index extends AdminController
} }
// 清理系统核心缓存 // 清理系统核心缓存
Cache::tag('core_system')->clear();
$configList = Cache::get('config_list'); $configList = Cache::get('config_list');
foreach ($configList as $item) { foreach ($configList as $item) {
Cache::delete($item); Cache::delete($item);
@@ -417,7 +413,7 @@ class Index extends AdminController
public function testFtp(): Response public function testFtp(): Response
{ {
if (request()->isPost()) { if (request()->isPost()) {
if (Ftp::instance()->ftpTest(request()->post())) { if (FtpService::ftpTest(request()->post())) {
return $this->success('上传测试成功!'); return $this->success('上传测试成功!');
} }
} }
@@ -427,51 +423,49 @@ class Index extends AdminController
/** /**
* 邮件测试 * 邮件测试
* @return Response
*/ */
public function testEmail() public function testEmail(): Response
{ {
if (request()->isPost()) { if (request()->isPost()) {
$info = Email::instance()->testEMail(request()->post()); try {
return $info === true ? $this->success('测试邮件发送成功!') : $this->error($info); EmailService::testEmail(request()->post());
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
} }
return $this->success('测试邮件发送成功!');
} }
/** /**
* 缓存测试 * 缓存测试
* @return Response
*/ */
public function testCache() public function testCache(): Response
{ {
if (request()->isPost()) { if (request()->isPost()) {
$param = request()->post(); $param = request()->post();
if (!isset($param['type']) || empty($param['host']) || empty($param['port'])) { if (empty($param['host']) || empty($param['port'])) {
return $this->error('参数错误!'); return $this->error('参数错误!');
} }
$options = [ if (!extension_loaded('redis')) {
'host' => $param['host'], return $this->error('请先安装redis扩展!');
'port' => (int)$param['port'], }
'username' => $param['user'],
'password' => $param['pass']
];
try { try {
if (strtolower($param['type']) == 'redis') { $redis = new \Redis();
$drive = new Redis($options); $redis->connect($param['host'], (int)$param['port']);
} else { $redis->auth($param['pass']);
$drive = new Memcached($options); $redis->select((int)$param['select']);
} $redis->set('key-test', time());
$redis->close();
} catch (\Throwable $th) { } catch (\Throwable $th) {
return $this->error($th->getMessage()); return $this->error($th->getMessage());
} }
if ($drive->set('test', 'cacheOK', 1000)) {
return $this->success('缓存测试成功!');
} else {
return $this->error('缓存测试失败!');
}
} }
return $this->success('缓存测试成功!');
return false;
} }
} }

View File

@@ -26,7 +26,7 @@ use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use think\Exception; use think\Exception;
use think\facade\Cache; use support\Cache;
use Webman\Http\Request; use Webman\Http\Request;
/** /**
@@ -155,14 +155,13 @@ class Admin extends AdminController
return $this->error('该用户名或邮箱已被注册!'); return $this->error('该用户名或邮箱已被注册!');
} }
// 管理员加密 // 管理员加密
$post['pwd'] = encryptPwd($post['pwd']); $post['pwd'] = encryptPwd($post['pwd']);
$post['create_ip'] = request()->getRealIp(); $post['create_ip'] = request()->getRealIp();
$data = $this->model->create($post); $data = $this->model->create($post);
if (!is_empty($data->id)) { if (!is_empty($data['id'])) {
$access['admin_id'] = $data->id; $access['admin_id'] = $data['id'];
$access['group_id'] = $data->group_id; $access['group_id'] = $data['group_id'];
AdminAccessModel::insert($access); AdminAccessModel::insert($access);
return $this->success('添加管理员成功!'); return $this->success('添加管理员成功!');
} else { } else {
@@ -182,95 +181,84 @@ class Admin extends AdminController
if (request()->isPost()) { if (request()->isPost()) {
$id = request()->input('id'); $id = request()->input('id');
if (!empty($id) && is_numeric($id)) { if (!empty($id) && is_numeric($id)) {
// 验证数据 // 验证数据
$post = request()->all(); $post = request()->all();
$post = request_validate_rules($post, get_class($this->model), 'edit'); $retError = request_validate_rules($post, get_class($this->model), 'edit');
if (!is_array($post)) { if (!is_array($retError)) {
return $this->error($post); return $this->error($retError);
} }
if (isset($post['pwd']) && !empty($post['pwd'])) {
if (!empty($post['pwd'])) {
$post['pwd'] = encryptPwd($post['pwd']); $post['pwd'] = encryptPwd($post['pwd']);
} else { } else {
// 清空避免被覆盖
unset($post['pwd']); unset($post['pwd']);
} }
if ($this->model->update($post)) { if ($this->model->update($post)) {
$access['group_id'] = $post['group_id']; $access['group_id'] = $post['group_id'];
AdminAccessModel::where('admin_id', $id)->update($access); AdminAccessModel::where('admin_id', $id)->update($access);
return $this->success('更新管理员成功!'); return $this->success('更新管理员成功!');
} else {
return $this->error('更新管理员失败');
} }
} }
} }
return $this->error('更新管理员失败');
} }
/** /**
* 编辑权限 * 编辑权限
* @return Response
*/ */
public function editRules() public function editRules(): Response
{ {
if (request()->isPost()) { return $this->updateRuleCates();
return $this->_update_RuleCates();
}
} }
/** /**
* 编辑栏目权限 * 编辑栏目权限
* @return Response
*/ */
public function editCates() public function editCates(): Response
{ {
return $this->_update_RuleCates(AUTH_CATE); return $this->updateRuleCates(AUTH_CATE);
} }
/** /**
* 更新权限函数 * 更新权限函数
* @access protected * @access protected
* @param string $type * @param string $type
* @return \support\Response|void * @return Response
*/ */
protected function _update_RuleCates(string $type = AUTH_RULES) protected function updateRuleCates(string $type = AUTH_RULES): Response
{ {
if (request()->isPost()) { $admin_id = input('admin_id');
$rules = request()->post($type) ?? [];
$access = $this->auth->getRulesNode($admin_id, $type);
$rules = array_diff($rules, $access[$this->auth->authGroup]);
$admin_id = input('admin_id'); // 权限验证
$rules = request()->post($type) ?? []; if (!$this->auth->checkRuleOrCateNodes($rules, $type, $this->auth->authPrivate)) {
return $this->error('没有权限!');
if (!empty($admin_id) && $admin_id > 0) {
$access = $this->auth->getRulesNode($admin_id, $type);
$rules = array_diff($rules, $access[$this->auth->authGroup]);
// 权限验证
if (!$this->auth->checkRuleOrCateNodes($rules, $type, $this->auth->authPrivate)) {
return $this->error('没有权限!');
}
// 获取个人节点
$differ = array_diff($access[$this->auth->authPrivate], $access[$this->auth->authGroup]);
$current = [];
if (!$this->auth->superAdmin()) {
$current = $this->auth->getRulesNode();
$current = array_diff($differ, $current[$this->auth->authPrivate]);
}
$rules = array_unique(array_merge($rules, $current));
$AdminAccessModel = new AdminAccessModel();
$data = [
"$type" => implode(',', $rules)
];
if ($AdminAccessModel->where('admin_id', $admin_id)->save($data)) {
return $this->success('更新权限成功!');
}
return $this->error('更新权限失败!');
}
} }
// 获取个人节点
$differ = array_diff($access[$this->auth->authPrivate], $access[$this->auth->authGroup]);
$current = [];
if (!$this->auth->superAdmin()) {
$current = $this->auth->getRulesNode();
$current = array_diff($differ, $current[$this->auth->authPrivate]);
}
$rules = array_unique(array_merge($rules, $current));
$AdminAccessModel = new AdminAccessModel();
$data = ["$type" => implode(',', $rules)];
if ($AdminAccessModel->update($data, ['admin_id' => $admin_id])) {
return $this->success('更新权限成功!');
}
return $this->error('更新权限失败!');
} }
/** /**
@@ -278,7 +266,7 @@ class Admin extends AdminController
* getAdminRules * getAdminRules
* @return mixed * @return mixed
*/ */
public function getPermissions() public function getPermissions(): mixed
{ {
$list = []; $list = [];
if (\request()->isAjax()) { if (\request()->isAjax()) {
@@ -666,7 +654,7 @@ class Admin extends AdminController
// 清理内容 // 清理内容
if ($type == 'all' || $type == 'content') { if ($type == 'all' || $type == 'content') {
$session = session(AdminSession); $session = session(AdminSession);
\think\facade\Cache::clear(); \support\Cache::clear();
request()->session()->set(AdminSession, $session); request()->session()->set(AdminSession, $session);
} }

View File

@@ -50,34 +50,14 @@ class AdminRules extends AdminController
} }
// 获取总数 // 获取总数
$total = $this->model->count(); $total = $this->model->where($where)->count();
$list = $this->model->where($where)->order('sort asc')->select()->toArray(); $list = $this->model->where($where)->order('sort asc')->select()->toArray();
foreach ($list as $key => $value) { foreach ($list as $key => $value) {
$list[$key]['title'] = __($value['title']); $list[$key]['title'] = __($value['title']);
} }
// 自定义查询 $rules = list_to_tree($list,'id','pid','children',0);
if (count($list) < $total) { return $this->success('获取成功', '/',$rules, $total);
$parentNode = []; // 查找父节点
foreach ($list as $key => $value) {
if ($value['pid'] !== 0 && !list_search($list,['id'=>$value['pid']])) {
$parentNode[] = $this->parentNode($value['pid']);
}
}
foreach ($parentNode as $key => $value) {
$list = array_merge($list,$value);
}
}
$rules = $this->model->getListTree();
return $this->success('获取成功', '',[
'item'=> $list,
'rules'=> $rules
],
count($list),0);
} }

View File

@@ -73,11 +73,7 @@ class Department extends AdminController
} }
$depart = $this->model->getListTree(); $depart = $this->model->getListTree();
return $this->success('获取成功', '',[ return $this->success('获取成功', '',$depart, $total);
'item'=> $list,
'depart'=> $depart
],
count($list));
} }
return view('system/department/index'); return view('system/department/index');

View File

@@ -81,7 +81,7 @@ class Plugin extends AdminController
return $this->error('请勿重复安装插件'); return $this->error('请勿重复安装插件');
} }
// try { try {
$pluginZip = self::downLoad($name, ['name' => $name, 'token' => input('token')]); $pluginZip = self::downLoad($name, ['name' => $name, 'token' => input('token')]);
ZipArchives::unzip($pluginZip, plugin_path(), '', true); ZipArchives::unzip($pluginZip, plugin_path(), '', true);
@@ -95,10 +95,10 @@ class Plugin extends AdminController
self::pluginMenu($name); self::pluginMenu($name);
self::executeSql($name); self::executeSql($name);
self::enabled($name); self::enabled($name);
// } catch (\Throwable $th) { } catch (\Throwable $th) {
// recursive_delete($pluginPath); recursive_delete($pluginPath);
// return $this->error($th->getMessage(), null, self::$ServerBody, $th->getCode()); return $this->error($th->getMessage(), null, self::$ServerBody, $th->getCode());
// } }
return $this->success('插件安装成功', null, get_plugin_config($name, true)); return $this->success('插件安装成功', null, get_plugin_config($name, true));
} }
@@ -295,17 +295,15 @@ class Plugin extends AdminController
if (request()->isPost()) { if (request()->isPost()) {
$post['extends'] = input('extends'); $post['extends'] = input('extends');
$post['rewrite'] = input('rewrite'); $post['rewrite'] = input('rewrite');
foreach ($post['rewrite'] as $kk=>$vv) foreach ($post['rewrite'] as $kk => $vv) {
{ if ($kk[0] != '/') return $this->error('伪静态变量名称“' . $kk . '" 必须以“/”开头');
if($kk[0]!='/')return $this->error('伪静态变量名称“'.$kk.'" 必须以“/”开头'); $post['rewrite'][$kk] = str_replace('\\', '/', trim($vv, '/\\'));
$post['rewrite'][$kk]=str_replace('\\','/',trim($vv,'/\\')); $value = explode('/', $post['rewrite'][$kk]);
$value=explode('/',$post['rewrite'][$kk]); if (count($value) < 2) {
if(count($value)<2){ return $this->error('伪静态不符合规则');
return $this->error('伪静态规则变量值,不符合规则');
} }
if(strtoupper($value[count($value)-2][0]) !== $value[count($value)-2][0]) if (strtoupper($value[count($value) - 2][0]) !== $value[count($value) - 2][0]) {
{ return $this->error('控制器首字母必须大写');
return $this->error('伪静态规则变量值中,控制器首字母必须大写哦');
} }
} }
$config = array_merge($config, $post); $config = array_merge($config, $post);

View File

@@ -21,7 +21,6 @@ use system\Random;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
use Webman\Http\Request;
/** /**
* 用户管理 * 用户管理

View File

@@ -1,8 +1,6 @@
<?php <?php
namespace app\admin\middleware\system; namespace app\admin\middleware\system;
use app\common\library\Auth;
use think\facade\Cache;
use Webman\Http\Request; use Webman\Http\Request;
use Webman\Http\Response; use Webman\Http\Response;
use Webman\MiddlewareInterface; use Webman\MiddlewareInterface;

View File

@@ -27,7 +27,7 @@ class AdminPermissions implements MiddlewareInterface
* 不需要鉴权的方法 * 不需要鉴权的方法
* @var array * @var array
*/ */
protected array $noNeedAuth = [ protected array $noNeedLogin = [
'/Index/index', '/Index/index',
'/Login/index', '/Login/index',
'/Login/logout', '/Login/logout',
@@ -56,12 +56,12 @@ class AdminPermissions implements MiddlewareInterface
// 获取权限列表 // 获取权限列表
$class = new \ReflectionClass($request->controller); $class = new \ReflectionClass($request->controller);
$properties = $class->getDefaultProperties(); $properties = $class->getDefaultProperties();
$this->noNeedAuth = $properties['noNeedAuth'] ?? $this->noNeedAuth; $this->noNeedLogin = $properties['noNeedLogin'] ?? $this->noNeedLogin;
// 控制器鉴权 // 控制器鉴权
$method = '/' . $controller . '/' . $action; $method = '/' . $controller . '/' . $action;
if (!in_array('*', $this->noNeedAuth) if (!in_array('*', $this->noNeedLogin)
&& !in_array(strtolower($method), array_map('strtolower', $this->noNeedAuth))) { && !in_array(strtolower($method), array_map('strtolower', $this->noNeedLogin))) {
if (!Auth::instance()->SuperAdmin() && !Auth::instance()->check($method, get_admin_id())) { if (!Auth::instance()->SuperAdmin() && !Auth::instance()->check($method, get_admin_id())) {
if (request()->isAjax()) { if (request()->isAjax()) {
return json(['code' => 101, 'msg' => '没有权限']); return json(['code' => 101, 'msg' => '没有权限']);

View File

@@ -2,7 +2,7 @@
<!-- 正文开始 --> <!-- 正文开始 -->
<div class="layui-fluid" id="LAY-component-grid-all"> <div class="layui-fluid" id="LAY-component-grid-all">
<div class="layui-row layui-col-space10"> <div class="layui-row layui-col-space10">
<div class="layui-col-xs6 layui-col-sm7 layui-col-md3"> <div class=" layui-col-sm7 layui-col-md3">
<!-- 填充内容 --> <!-- 填充内容 -->
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">总销售额<i class="layui-icon layui-icon-about layui-fr" lay-tips="指标说明" ></i></div> <div class="layui-card-header">总销售额<i class="layui-icon layui-icon-about layui-fr" lay-tips="指标说明" ></i></div>
@@ -19,7 +19,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-xs6 layui-col-sm5 layui-col-md3"> <div class=" layui-col-sm5 layui-col-md3">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">访问量 <span class="layui-badge layui-badge-green pull-right"></span></div> <div class="layui-card-header">访问量 <span class="layui-badge layui-badge-green pull-right"></span></div>
<div class="layui-card-body"> <div class="layui-card-body">
@@ -32,7 +32,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-xs6 layui-col-sm5 layui-col-md3"> <div class=" layui-col-sm5 layui-col-md3">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">支付笔数 <span class="layui-badge layui-badge-blue pull-right"></span></div> <div class="layui-card-header">支付笔数 <span class="layui-badge layui-badge-blue pull-right"></span></div>
<div class="layui-card-body"> <div class="layui-card-body">
@@ -45,7 +45,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-xs6 layui-col-sm7 layui-col-md3"> <div class=" layui-col-sm7 layui-col-md3">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">活动运营效果 <span class="layui-badge layui-badge-red pull-right"></span></div> <div class="layui-card-header">活动运营效果 <span class="layui-badge layui-badge-red pull-right"></span></div>
<div class="layui-card-body"> <div class="layui-card-body">
@@ -62,7 +62,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-xs6 layui-col-sm7 layui-col-md9"> <div class=" layui-col-sm7 layui-col-md9">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-header">用户地域分布</div> <div class="layui-card-header">用户地域分布</div>
<div class="layui-card-body"> <div class="layui-card-body">
@@ -70,7 +70,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-xs6 layui-col-sm5 layui-col-md3"> <div class=" layui-col-sm5 layui-col-md3">
<div class="layui-card" > <div class="layui-card" >
<div class="layui-card-header">在线人数</div> <div class="layui-card-header">在线人数</div>
<div class="layui-card-body"> <div class="layui-card-body">
@@ -78,7 +78,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="layui-col-xs6 layui-col-sm5 layui-col-md3"> <div class=" layui-col-sm5 layui-col-md3">
<div class="layui-card" > <div class="layui-card" >
<div class="layui-card-header">浏览器分布</div> <div class="layui-card-header">浏览器分布</div>
<div class="layui-card-body"> <div class="layui-card-body">

View File

@@ -162,8 +162,7 @@
<div class="layui-form-mid layui-word-aux">* {:__('是否开启手机版模式')}</div> <div class="layui-form-mid layui-word-aux">* {:__('是否开启手机版模式')}</div>
</div> </div>
<div class="mobile" <eq name="$config['site_state']" value="0"> style="display:none;" <div class="mobile" <eq name="$config['site_state']" value="0"> style="display:none;" </eq> >
</eq> >
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">{:__('手机版类型')}</label> <label class="layui-form-label">{:__('手机版类型')}</label>
@@ -328,88 +327,61 @@
<label class="layui-form-label">{:__('缓存开关')}</label> <label class="layui-form-label">{:__('缓存开关')}</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="radio" name="cache_status" data-display="cache_status" <input type="radio" name="cache_status" data-display="cache_status"
lay-filter="radioStatus" value="1" title="开启" <if lay-filter="radioStatus" value="1" title="开启" <if
condition="$config['cache_status'] eq 1 "> checked </if> > condition="$config['cache_status'] eq 1 "> checked </if> >
<input type="radio" name="cache_status" data-display="cache_status" <input type="radio" name="cache_status" data-display="cache_status"
lay-filter="radioStatus" value="0" title="关闭" <if lay-filter="radioStatus" value="0" title="关闭" <if
condition="$config['cache_status'] eq 0 "> checked </if>> condition="$config['cache_status'] eq 0 "> checked </if>>
</div> </div>
<div class="layui-form-mid layui-word-aux">* {:__('开启数据库缓存会提高网站性能!')}</div> <div class="layui-form-mid layui-word-aux">* {:__('开启数据库缓存会提高网站性能!')}</div>
</div> </div>
<div class="cache_status" <eq name="$config['cache_status']" value="0"> <div class="layui-form-item">
style="display:none;" </eq> > <label class="layui-form-label">{:__('服务器IP')}</label>
<div class="layui-form-item"> <div class="layui-input-inline">
<label class="layui-form-label">{:__('缓存方式')}</label> <input type="text" name="cache_host" placeholder="{:__('缓存服务器IP')}"
<div class="layui-input-inline"> value="{$config['cache_host']}" class="layui-input chost">
<select name="cache_type" data-display="cache_type" data-disable="file"
lay-filter="selectStatus" class="ctype">
<option value="file" <if condition="$config['cache_type'] eq 'file'">
selected</if> >file</option>
<option value="redis" <if condition="$config['cache_type'] eq 'redis'">
selected</if> >redis</option>
<option value="memcached" <if
condition="$config['cache_type'] eq 'memcached'">selected</if>
>memcached</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">
<i class="layui-icon layui-icon-about"
lay-tips="{:__('使用Redis缓存方式,出错会抛出Connection refused')}"></i>
</div>
</div> </div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label">{:__('缓存时间')}</label> <label class="layui-form-label">{:__('端 口')}</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="cache_time" autocomplete="off" <input type="text" name="cache_port" placeholder="{:__('缓存服务器端口')}"
value="{$config.cache_time}" class="layui-input"> value="{$config['cache_port']}" class="layui-input cport">
</div>
<div class="layui-form-mid layui-word-aux">* {:__('单位 /秒')}</div>
</div> </div>
</div>
<div class="cache_type" <if <div class="layui-form-item">
condition="$config['cache_type'] eq 'file' or $config['cache_type'] eq ''"> <label class="layui-form-label">{:__('缓存时间')}</label>
style="display:none;" </if> > <div class="layui-input-inline">
<div class="layui-form-item"> <input type="text" name="cache_time" autocomplete="off"
<label class="layui-form-label">{:__('服务器IP')}</label> value="{$config.cache_time}" class="layui-input">
<div class="layui-input-inline"> </div>
<input type="text" name="cache_host" placeholder="{:__('缓存服务器IP')}" <div class="layui-form-mid layui-word-aux">* {:__('单位 /秒')}</div>
value="{$config['cache_host']}" class="layui-input chost"> </div>
</div> <div class="layui-form-item">
</div> <label class="layui-form-label">{:__('数据库')}</label>
<div class="layui-form-item"> <div class="layui-input-inline">
<label class="layui-form-label">{:__('端 口')}</label> <input type="number" name="cache_select" min="1" max="16"
<div class="layui-input-inline"> placeholder="{:__('缓存服务redis库 1- 16')}"
<input type="text" name="cache_port" placeholder="{:__('缓存服务器端口')}" value="{$config['cache_select']}" class="layui-input cselect">
value="{$config['cache_port']}" class="layui-input cport"> </div>
</div> </div>
</div> <div class="layui-form-item">
<div class="layui-form-item"> <label class="layui-form-label">{:__('账 号')}</label>
<label class="layui-form-label">{:__('数据库')}</label> <div class="layui-input-inline">
<div class="layui-input-inline"> <input type="text" name="cache_user" placeholder="{:__('缓存服务账号,没有请留空')}"
<input type="number" name="cache_select" min="1" max="16" value="{$config['cache_user']}" class="layui-input cuser">
placeholder="{:__('缓存服务redis库 1- 16')}" </div>
value="{$config['cache_select']}" class="layui-input cuser"> </div>
</div> <div class="layui-form-item">
</div> <label class="layui-form-label">{:__('密 码')}</label>
<div class="layui-form-item"> <div class="layui-input-inline">
<label class="layui-form-label">{:__('账 号')}</label> <input type="text" name="cache_pass" placeholder="{:__('缓存服务密码,没有请留空')}"
<div class="layui-input-inline"> value="{$config['cache_pass']}" class="layui-input cpass">
<input type="text" name="cache_user" placeholder="{:__('缓存服务账号,没有请留空')}" </div>
value="{$config['cache_user']}" class="layui-input cuser"> <button type="button" class="layui-btn layui-btn-primary" lay-ajax=""
</div> data-url="{:url('/index/testCache')}"
</div> data-object="host:chost,port:cport,user:cuser,select:cselect,pass:cpass">{:__('测试连接')}</button>
<div class="layui-form-item">
<label class="layui-form-label">{:__('密 码')}</label>
<div class="layui-input-inline">
<input type="text" name="cache_pass" placeholder="{:__('缓存服务密码,没有请留空')}"
value="{$config['cache_pass']}" class="layui-input cpass">
</div>
<button type="button" class="layui-btn layui-btn-primary" lay-ajax=""
data-url="{:url('/Index/testCache')}"
data-object="type:ctype,host:chost,port:cport,user:cuser,pass:cpass">{:__('测试连接')}</button>
</div>
</div> </div>
</div> </div>
@@ -427,8 +399,7 @@
<div class="layui-form-item layui-col-md5"> <div class="layui-form-item layui-col-md5">
<label class="layui-form-label">{:__('提示信息')}</label> <label class="layui-form-label">{:__('提示信息')}</label>
<div class="layui-input-block"> <div class="layui-input-block">
<textarea id="site_notice" name="site_notice" lay-verify="siteClose" <textarea name="site_notice" lay-verify="siteClose" class="layui-textarea">{$config.site_notice}</textarea>
type="layui-textarea">{$config.site_notice}</textarea>
</div> </div>
</div> </div>
</div> </div>
@@ -1835,21 +1806,11 @@
<include file="/public/footer" /> <include file="/public/footer" />
<script> <script>
layui.use(['form', 'jquery', 'layedit', 'admin'], function () { layui.use(['form', 'jquery', 'admin'], function () {
var form = layui.form; var form = layui.form;
var admin = layui.admin; var admin = layui.admin;
var jquery = layui.jquery; var jquery = layui.jquery;
// 渲染富文本编辑器
var layedit = layui.layedit;
var layindex = layedit.build('site_notice', { height: 110, color: '#ffffff' });
// 异步验证表单
form.verify({
siteClose: function (value) {
return layedit.sync(layindex);
}
});
// 增加变量 // 增加变量
jquery('.layui-variable-add').on('click', function () { jquery('.layui-variable-add').on('click', function () {

View File

@@ -290,6 +290,7 @@
</div> </div>
</div> </div>
</div> </div>
<table class="layui-hide" id="ID-treeTable-demo"></table>
</div> </div>
<script src="__STATICADMIN__module/echarts/echarts.js"></script> <script src="__STATICADMIN__module/echarts/echarts.js"></script>
<script src="__STATICADMIN__module/echarts/echarts-wordcloud.js"></script> <script src="__STATICADMIN__module/echarts/echarts-wordcloud.js"></script>
@@ -298,10 +299,35 @@
<include file="/public/footer"/> <include file="/public/footer"/>
<script> <script>
layui.use(['jquery','layer'], function () { layui.use(['jquery','layer','treeTable'], function () {
let $ = layui.jquery; let $ = layui.jquery;
let layer = layui.layer; let layer = layui.layer;
let treeTable = layui.treeTable;
var inst = treeTable.render({
elem: '#ID-treeTable-demo',
url: '/static/demo-1.json?page=1&limit=10', // 此处为静态模拟数据,实际使用时需换成真实接口
tree: {
customName: {
icon: 'icon2',
name: 'title'
},
},
maxHeight: '501px',
toolbar: '#TPL-treeTable-demo',
cols: [[
{type: 'checkbox', fixed: 'left'},
{field: 'id', title: 'ID', width: 80, sort: true, fixed: 'left'},
{field: 'name', title: '用户名', width: 180, fixed: 'left'},
{field: 'experience', title: '积分', width: 90, sort: true},
{field: 'sex', title: '性别', width: 80, sort: true},
{field: 'score', title: '评分', width: 80, sort: true},
{field: 'city', title: '城市'},
{ fixed: "right", title: "操作", width: 181, align: "center", toolbar: "#TPL-treeTable-demo-tools"}
]],
page: true
});
/** /**
* 用户统计报表 * 用户统计报表

View File

@@ -10,7 +10,7 @@
<div class="layui-card-body"> <div class="layui-card-body">
<div class="layui-panel"> <div class="layui-panel">
<div class="layui-card-header"> <div class="layui-card-header">
<div class="title"><span class="titles"><img src="{$detail.face}" class="face" width="20"> </span>{$detail.nickname}</div> <div class="title"><span class="titles"><img src="{$detail.face|default=''}" class="face" width="20"> </span>{$detail.nickname|default='隐藏用户'}</div>
<div class="time"><span class="times">时间:</span>{$detail.create_time}</div> <div class="time"><span class="times">时间:</span>{$detail.create_time}</div>
</div> </div>
<div id="layui-info">{$detail.content|raw}</div> <div id="layui-info">{$detail.content|raw}</div>

View File

@@ -122,31 +122,37 @@
<include file="/public/footer" /> <include file="/public/footer" />
<script> <script>
layui.use(['admin','form','treetable','iconPicker'], function () { layui.use(['admin','form','treeTable','iconPicker'], function () {
var jquery = layui.jquery; var jquery = layui.jquery;
var admin = layui.admin; var admin = layui.admin;
var form = layui.form; var form = layui.form;
var table = layui.table; var table = layui.table;
var treetable = layui.treetable; var treeTable = layui.treeTable;
var iconPicker = layui.iconPicker; var iconPicker = layui.iconPicker;
var tableURL = "{:url('/system/AdminRules/index')}"; var tableURL = "{:url('/system/AdminRules/index')}";
// 渲染初始化表格 // 渲染初始化表格
var renderTable = function (tableURL) { var renderTable = function (tableURL) {
treetable.render({ treeTable.render({
elem: '#lay-tableList', elem: '#lay-tableList',
treeColIndex: 1,
treeSpid: 0,
treeIdName: 'id',
treePidName: 'pid',
url: tableURL, url: tableURL,
cellMinWidth: 100, tree: {
treeDefaultClose: true, customName: {
pid: 'pid',
icon: 'icon1',
},
view: {
iconClose: '', // 关闭时候的图标
iconOpen: '', // 打开时候的图标
iconLeaf: '', // 叶子节点的图标
}
},
cols: [[ cols: [[
{type: 'numbers'}, {type: 'numbers'},
{field: 'title', title: '{:__("菜单名称")}'}, {field: 'name', title: '{:__("菜单名称")}',templet: function(d) {
return '<i class="layui-icon '+d.icon+'"></i> '+d.title;
},},
{field: 'router', title: '{:__("路由地址")}'}, {field: 'router', title: '{:__("路由地址")}'},
{field: 'alias', title: '{:__("权限标识")}'}, {field: 'alias', title: '{:__("权限标识")}'},
{field: 'auth', width: 80,title: '{:__("鉴权")}',templet: function(d) { {field: 'auth', width: 80,title: '{:__("鉴权")}',templet: function(d) {
@@ -246,7 +252,7 @@
tips: '请选择上级菜单', tips: '请选择上级菜单',
name: 'pid', name: 'pid',
height: 'auto', height: 'auto',
data: table.cache['rules'], data: table.cache['lay-tableList'],
radio: true, radio: true,
clickClose: true, clickClose: true,
initValue: checkedId, initValue: checkedId,
@@ -314,9 +320,10 @@
var pageThat = jquery(this); var pageThat = jquery(this);
pageThat.attr("disabled",true); pageThat.attr("disabled",true);
// 获取提交地址 // 获取提交地址
if (typeof(tableThis) !== 'undefined') { var _pageUrl;
if (typeof (tableThis) !== 'undefined') {
_pageUrl = tableThis.event === 'edit' ? pageThat.attr('lay-edit') : pageThat.attr('lay-add'); _pageUrl = tableThis.event === 'edit' ? pageThat.attr('lay-edit') : pageThat.attr('lay-add');
}else { } else {
_pageUrl = pageThat.attr('lay-add'); _pageUrl = pageThat.attr('lay-add');
} }
@@ -328,7 +335,7 @@
// 开始POST提交数据 // 开始POST提交数据
jquery.post(_pageUrl, jquery.post(_pageUrl,
post.field, function(res){ post.field, function(res){
if (res.code == 200) { if (res.code === 200) {
layer.msg(res.msg); layer.msg(res.msg);
@@ -356,12 +363,12 @@
// 展开所有 // 展开所有
jquery('#expandAll').click(function(){ jquery('#expandAll').click(function(){
treetable.expandAll('#lay-tableList'); treeTable.expandAll('lay-tableList', true);
}) })
// 折叠所有 // 折叠所有
jquery('#foldAll').click(function () { jquery('#foldAll').click(function () {
treetable.foldAll('#lay-tableList'); treeTable.expandAll('lay-tableList',false);
}); });
// 执行初始化 // 执行初始化

View File

@@ -112,26 +112,35 @@
<include file="/public/footer" /> <include file="/public/footer" />
<script src="__STATICADMIN__module/xmselect/xmselect.js"></script> <script src="__STATICADMIN__module/xmselect/xmselect.js"></script>
<script> <script>
layui.use(['admin','form','treetable'], function () { layui.use(['admin','form','treeTable'], function () {
var jquery = layui.jquery; var jquery = layui.jquery;
var admin = layui.admin; var admin = layui.admin;
var form = layui.form; var form = layui.form;
var table = layui.table; var table = layui.table;
var treetable = layui.treetable; var treeTable = layui.treeTable;
var tableURL = "{:url('/system/Department/index')}"; var tableURL = "{:url('/system/Department/index')}";
// 渲染初始化表格 // 渲染初始化表格
var renderTable = function (tableURL) { var renderTable = function (tableURL) {
var ss = treetable.render({ treeTable.render({
elem: '#lay-tableList', elem: '#lay-tableList',
treeColIndex: 1,
treeSpid: 0,
treeIdName: 'id',
treePidName: 'pid',
url: tableURL, url: tableURL,
cellMinWidth: 100, tree: {
customName: {
name: 'title',
icon: 'icon1',
},
view: {
iconClose: '', // 关闭时候的图标
iconOpen: '', // 打开时候的图标
iconLeaf: '', // 叶子节点的图标
expandAllDefault: true,
}
},
// 默认展开
cols: [[ cols: [[
{type: 'numbers'}, {type: 'numbers'},
{field: 'title', title: '{:__("部门名称")}'}, {field: 'title', title: '{:__("部门名称")}'},
@@ -179,7 +188,7 @@
tips: '请选择上级部门', tips: '请选择上级部门',
name: 'pid', name: 'pid',
height: 'auto', height: 'auto',
data: table.cache.depart, data: table.cache['lay-tableList'],
radio: true, radio: true,
clickClose: true, clickClose: true,
initValue: checkedId, initValue: checkedId,
@@ -210,10 +219,11 @@
var pageThat = jquery(this); var pageThat = jquery(this);
pageThat.attr("disabled",true); pageThat.attr("disabled",true);
// 获取提交地址 // 获取提交地址
if (typeof(tableThis) !== 'undefined') { var _pageUrl;
if (typeof (tableThis) !== 'undefined') {
_pageUrl = tableThis.event === 'edit' ? pageThat.attr('lay-edit') : pageThat.attr('lay-add'); _pageUrl = tableThis.event === 'edit' ? pageThat.attr('lay-edit') : pageThat.attr('lay-add');
}else { } else {
_pageUrl = pageThat.attr('lay-add'); _pageUrl = pageThat.attr('lay-add');
} }
@@ -225,7 +235,7 @@
// 开始POST提交数据 // 开始POST提交数据
jquery.post(_pageUrl, jquery.post(_pageUrl,
post.field, function(res){ post.field, function(res){
if (res.code == 200) { if (res.code === 200) {
layer.msg(res.msg); layer.msg(res.msg);
// 更新列数据 // 更新列数据
if (typeof(tableThis) !== 'undefined') { if (typeof(tableThis) !== 'undefined') {

View File

@@ -108,6 +108,7 @@
let $ = layui.jquery; let $ = layui.jquery;
let table = layui.table; let table = layui.table;
let dropdown = layui.dropdown; let dropdown = layui.dropdown;
window.framework = "{:config('app.version')}";
window.plugins = {$plugin|raw}; window.plugins = {$plugin|raw};
/* /*
* 初始化表格 * 初始化表格

View File

@@ -4,11 +4,10 @@ declare (strict_types=1);
namespace app\api\controller; namespace app\api\controller;
use app\ApiController; use app\ApiController;
use app\common\exception\OperateException;
use app\common\library\Email; use app\common\service\notice\EmailService;
use app\common\library\Sms; use app\common\service\notice\SmsService;
use app\common\model\system\User; use Psr\SimpleCache\InvalidArgumentException;
use PHPMailer\PHPMailer\Exception;
use support\Response; use support\Response;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
@@ -19,87 +18,47 @@ use think\db\exception\ModelNotFoundException;
*/ */
class Ajax extends ApiController class Ajax extends ApiController
{ {
public bool $needLogin = true;
/** /**
* 发送短信 * 首页
* @return Response|void
* @throws DataNotFoundException
* @throws DbException
*/ */
public function smsSend() public function index(): Response
{ {
if (request()->isPost()) { return response('Hello swiftadmin!');
$mobile = input('mobile');
$event = input('event', 'register');
if (!is_mobile($mobile)) {
return $this->error('手机号码不正确');
}
$sms = Sms::instance();
$data = $sms->getLast($mobile);
if ($data && (time() - strtotime($data['create_time'])) < 60) {
return $this->error(__('发送频繁'));
}
$user = User::getByMobile($mobile);
if (in_array($event, ['register', 'changer']) && $user) {
return $this->error('当前手机号已被占用');
} else if ($event == 'forgot' && !$user) {
return $this->error('当前手机号未注册');
}
if ($sms->send($mobile, $event)) {
return $this->success("验证码发送成功!");
} else {
return $this->error($sms->getError());
}
}
return json(['msg' => 'success', 'data' => 'Hello']);
} }
/** /**
* 发送邮件 * 发送短信验证码
* @return Response|void * @return Response
* @throws InvalidArgumentException
* @throws DataNotFoundException * @throws DataNotFoundException
* @throws DbException * @throws DbException
* @throws ModelNotFoundException * @throws ModelNotFoundException
* @throws Exception
*/ */
public function emailSend() public function smsSend(): Response
{ {
if (request()->isPost()) { $mobile = input('mobile', '');
$event = input('event', 'register');
$email = input('email'); if (!SmsService::filterMobile($mobile)) {
$event = input('event', 'register'); return $this->error('手机号码不正确');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->error('邮件格式不正确');
}
$Ems = Email::instance();
$data = $Ems->getLast($email);
if ($data && (time() - strtotime($data['create_time'])) < 60) {
return $this->error(__('发送频繁'));
}
$user = User::getByEmail($email);
if (in_array($event, ['register', 'changer']) && $user) {
return $this->error('当前邮箱已被注册');
} else if ($event == 'forgot' && !$user) {
return $this->error('当前邮箱不存在');
}
if ($Ems->captcha($email, $event)->send()) {
return $this->success("验证码发送成功!");
} else {
return $this->error($Ems->getError());
}
} }
SmsService::send($mobile, $event);
return $this->success("验证码发送成功!");
}
/**
* 发送邮件验证码
* @return Response
* @throws InvalidArgumentException
* @throws OperateException
*/
public function emailSend(): Response
{
$email = input('email');
$event = input('event', 'register');
if (!EmailService::filterEmail($email)) {
return $this->error('邮件格式不正确');
}
EmailService::captcha($email, $event);
return $this->success("验证码发送成功!");
} }
} }

View File

@@ -4,10 +4,18 @@
namespace app\api\controller; namespace app\api\controller;
use app\ApiController; use app\ApiController;
use app\common\exception\OperateException;
use app\common\exception\user\UserException;
use app\common\library\ResultCode; use app\common\library\ResultCode;
use app\common\library\Sms;
use app\common\library\Upload; use app\common\library\Upload;
use app\common\model\system\User as UserModel;
use app\common\validate\system\User as UserValidate;
use app\common\service\user\UserService;
use PHPMailer\PHPMailer\Exception;
use Psr\SimpleCache\InvalidArgumentException; use Psr\SimpleCache\InvalidArgumentException;
use support\Request;
use support\Response;
use system\Random;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
@@ -21,82 +29,267 @@ class User extends ApiController
* 需要登录 * 需要登录
* @var bool * @var bool
*/ */
public bool $needLogin = true; public bool $needLogin = true;
/** /**
* 非鉴权方法 * 非鉴权方法
* @var array * @var array
*/ */
public array $noNeedAuth = ['register', 'login']; public array $noNeedLogin = ['register', 'login', 'mobileLogin', 'mnpLogin', 'forgot'];
/**
* 构造方法
*/
public function __construct()
{
parent::__construct();
$this->model = new UserModel();
}
/**
* 用户中心
* @param Request $request
* @return Response
*/
public function center(Request $request): Response
{
$fields = $this->model->getVisibleFields();
$userInfo = array_intersect_key($request->userInfo, array_flip($fields));
return $this->success('获取成功', '', $userInfo);
}
/**
* 修改用户资料
* @param Request $request
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws OperateException
*/
public function profile(Request $request): Response
{
$post = request()->post();
validate(UserValidate::class)->scene('nickname')->check($post);
UserService::editProfile($post, $request->userId);
return $this->success('修改成功', '/');
}
/** /**
* 用户注册 * 用户注册
* @return mixed|void * @return Response
* @throws DataNotFoundException
* @throws DbException * @throws DbException
* @throws ModelNotFoundException|InvalidArgumentException * @throws InvalidArgumentException
* @throws OperateException
*/ */
public function register() public function register(): Response
{ {
if (request()->isPost()) { $post = request()->post();
validate(UserValidate::class)->scene('register')->check($post);
// 获取参数 $result = UserService::register($post);
$post = input('post.'); return $this->success('注册成功', '/', ['token' => $result['token']]);
// 获取注册方式
$registerType = saenv('user_register');
if ($registerType == 'mobile') {
$mobile = input('mobile');
$captcha = input('captcha');
// 校验手机验证码
if (!Sms::instance()->check($mobile, $captcha, 'register')) {
return $this->error(Sms::instance()->getError());
}
}
$response = $this->auth->register($post);
if (!$response) {
return $this->error($this->auth->getError());
}
return $response->withBody(json_encode(ResultCode::REGISTERSUCCESS));
}
} }
/** /**
* 用户登录 * 用户登录
* @return mixed|void * @return Response
* @throws InvalidArgumentException
* @throws OperateException
*/ */
public function login() { public function login(): Response
{
if (request()->isPost()) { $nickname = input('nickname');
// 获取参数 $password = input('pwd');
$nickname = input('nickname'); if (!$nickname || !$password) {
$password = input('pwd'); return $this->error('请输入用户名或密码');
}
$response = $this->auth->login($nickname, $password); $result = UserService::accountLogin($nickname, $password);
if (!$response) { return $this->success('登录成功', '/', ['token' => $result['token']]);
return $this->error($this->auth->getError());
}
$response->withBody(json_encode(array_merge(ResultCode::LOGINSUCCESS, ['token' => $this->auth->token])));
return $response;
}
} }
/** /**
* 文件上传 * 手机号登录
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws InvalidArgumentException
* @throws ModelNotFoundException
* @throws OperateException
*/ */
public function upload() public function mobileLogin(): Response
{
$mobile = input('mobile');
$captcha = input('captcha');
$result = UserService::mobileLogin($mobile, $captcha);
return $this->success('登录成功', '/', ['token' => $result['token']]);
}
/**
* 修改密码
* @param Request $request
* @return Response
* @throws OperateException
*/
public function changePwd(Request $request): Response
{
$post = request()->post();
UserService::changePwd($post, $request->userId);
return $this->success('修改密码成功!');
}
/**
* 找回密码
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws OperateException
*/
public function forgot(): Response
{
$post = request()->post();
validate(UserValidate::class)->check($post);
UserService::forgotPwd($post);
return $this->success('修改密码成功!');
}
/**
* 获取消息列表
* @param Request $request
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function message(Request $request): Response
{
$page = input('page/d', 1);
$limit = input('limit/d', 1);
$status = input('status', 'all');
$where[] = ['user_id', '=', $request->userId];
if ($status !== 'all') {
$where[] = ['status', '=', $status];
}
list($list, $count) = UserService::listMessage($limit, $page, $where);
return $this->success('查询成功', "/", $list, $count);
}
/**
* 查看消息
* @param Request $request
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws OperateException
*/
public function viewMessage(Request $request): Response
{
$id = input('id/d', 0);
$result = UserService::viewMessage($id, $request->userId);
return $this->success('查询成功', "/", $result);
}
/**
* 批量操作消息
* @param Request $request
* @return Response
*/
public function batchMessage(Request $request): Response
{
$ids = input('id');
$type = input('type', 'del');
try {
UserService::batchMessage($ids, $type, $request->userId);
} catch (UserException $e) {
return $this->error($e->getMessage());
}
return $this->success('操作成功');
}
/**
* 申请APP_KEY
* @param Request $request
* @return Response
*/
public function appid(Request $request): Response
{
$data['id'] = $request->userId;
$data['app_id'] = 10000 + $request->userId;
$data['app_secret'] = Random::alpha(22);
if ($this->model->update($data)) {
return $this->success('申请成功!', '/', $data);
}
return $this->error('申请失败!');
}
/**
* 修改邮箱地址
* @param Request $request
* @return Response
* @throws Exception|UserException|OperateException
*/
public function changeEmail(Request $request): Response
{
$email = input('email');
$captcha = input('captcha');
$event = input('event');
UserService::changeEmail($email, $captcha, $event, $request->userId);
return $this->success('修改邮箱成功!');
}
/**
* 修改手机号
* @param Request $request
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws OperateException
* @throws UserException
*/
public function changeMobile(Request $request): Response
{
$mobile = input('mobile');
$captcha = input('captcha');
$event = input('event');
UserService::changeMobile($mobile, $captcha, $event, $request->userId);
return $this->success('修改手机号成功!');
}
/**
* 意见反馈
* @return Response
*/
public function feedback(): Response
{
$type = input('type', '');
$content = input('content');
if (empty($type) || empty($content)) {
return $this->error('参数错误');
}
return $this->success('反馈成功');
}
/**
* 文件上传函数
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws InvalidArgumentException
* @throws ModelNotFoundException
*/
public function upload(): Response
{ {
if (request()->isPost()) { if (request()->isPost()) {
$file = Upload::instance()->upload(); $response = Upload::instance()->upload();
if (!$file) { if (empty($response)) {
return $this->error(Upload::instance()->getError()); return $this->error(Upload::instance()->getError());
} }
return json($file); return json($response);
} }
return json(ResultCode::SUCCESS);
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
namespace app\api\middleware\system; namespace app\api\middleware\system;
use app\common\library\Auth;
use app\common\library\ResultCode; use app\common\library\ResultCode;
use app\common\service\user\UserTokenService;
use Psr\SimpleCache\InvalidArgumentException;
use Webman\Event\Event; use Webman\Event\Event;
use Webman\MiddlewareInterface; use Webman\MiddlewareInterface;
use Webman\Http\Response; use Webman\Http\Response;
@@ -28,42 +28,52 @@ class ApiPermissions implements MiddlewareInterface
*/ */
public bool $authWorkflow = true; public bool $authWorkflow = true;
/**
* 禁止登录重复
* @var array
*/
public array $repeatLogin = ['login', 'register'];
/** /**
* 非鉴权方法 * 非鉴权方法
* @var array * @var array
*/ */
public array $noNeedAuth = []; public array $noNeedLogin = [];
/** /**
* 校验权限 * 校验权限
* @param Request $request * @param \support\Request|Request $request
* @param callable $handler * @param callable $handler
* @return Response * @return Response
* @throws InvalidArgumentException
* @throws \ReflectionException * @throws \ReflectionException
*/ */
public function process(Request $request, callable $handler): Response public function process(\support\Request|Request $request, callable $handler): Response
{ {
$app = request()->getApp(); $app = request()->getApp();
$controller = request()->getController(); $controller = request()->getController();
$action = request()->getAction(); $action = request()->getAction();
$method = $controller . '/' . $action; $method = $controller . '/' . $action;
$refClass = new \ReflectionClass($request->controller); $refClass = new \ReflectionClass($request->controller);
$property = $refClass->getDefaultProperties(); $property = $refClass->getDefaultProperties();
$this->needLogin = $property['needLogin'] ?? $this->needLogin; $this->needLogin = $property['needLogin'] ?? $this->needLogin;
$this->noNeedAuth = $property['noNeedAuth'] ?? $this->noNeedAuth; $this->noNeedLogin = $property['noNeedLogin'] ?? $this->noNeedLogin;
$this->repeatLogin = $property['repeatLogin'] ?? $this->repeatLogin;
$auth = Auth::instance(); // 是否验证登录器
if ($auth->isLogin()) { $userInfo = UserTokenService::isLogin();
// 验证权限 if (!empty($userInfo)) {
$request->userId = $userInfo['id'];
$request->userInfo = $userInfo;
// 是否验证API权限
if ($this->authWorkflow && Event::hasListener('apiAuth')) { if ($this->authWorkflow && Event::hasListener('apiAuth')) {
$result = Event::emit('apiAuth', ['method' => $method, 'user_id' => $auth->user_id], true); $result = Event::emit('apiAuth', ['method' => $method, 'user_id' => $userInfo['id']], true);
if (isset($result['code']) && $result['code'] != 200) { if (isset($result['code']) && $result['code'] != 200) {
return json($result); return json($result);
} }
} }
} else { } else {
if ($this->needLogin && !in_array($action, $this->noNeedAuth)) { if ($this->needLogin && !in_array($action, $this->noNeedLogin)) {
return json(ResultCode::AUTH_ERROR); return json(ResultCode::AUTH_ERROR);
} }
} }

View File

@@ -6,8 +6,7 @@ use app\common\model\system\SystemLog;
use Psr\SimpleCache\InvalidArgumentException; use Psr\SimpleCache\InvalidArgumentException;
use support\exception\BusinessException; use support\exception\BusinessException;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\DbException; use think\exception\ValidateException;
use think\db\exception\ModelNotFoundException;
use Webman\Exception\ExceptionHandler; use Webman\Exception\ExceptionHandler;
use Webman\Http\Request; use Webman\Http\Request;
use Webman\Http\Response; use Webman\Http\Response;
@@ -17,44 +16,36 @@ class ExceptionHandle extends ExceptionHandler
{ {
public $dontReport = [ public $dontReport = [
BusinessException::class, BusinessException::class,
ValidateException::class,
DataNotFoundException::class,
OperateException::class,
DumpException::class,
]; ];
/** /**
* 异常日志记录 * 异常日志记录
* @param Throwable $exception * @param Throwable $exception
* @throws DataNotFoundException * @throws InvalidArgumentException
* @throws DbException
* @throws ModelNotFoundException
*/ */
public function report(Throwable $exception) public function report(Throwable $exception)
{ {
try { if (saenv('system_exception')
&& !$this->shouldntReport($exception)) {
if (saenv('system_exception') && !empty($exception->getMessage())) { $logs['module'] = request()->app;
$data = [ $logs['controller'] = request()->controller;
'module' => request()->app, $logs['action'] = request()->action;
'controller' => request()->controller, $logs['params'] = serialize(request()->all());
'action' => request()->action, $logs['method'] = request()->method();
'params' => serialize(request()->all()), $logs['url'] = request()->url();
'method' => request()->method(), $logs['ip'] = request()->getRealIp();
'url' => request()->url(), $logs['name'] = session('AdminLogin.name') ?? 'system';
'ip' => request()->getRealIp(), $logs['type'] = 1;
'name' => session('AdminLogin.name'), $logs['code'] = $exception->getCode();
]; $logs['file'] = $exception->getFile();
if (empty($data['name'])) { $logs['line'] = $exception->getLine();
$data['name'] = 'system'; $logs['error'] = $exception->getMessage();
} SystemLog::write($logs);
$data['type'] = 1;
$data['code'] = $exception->getCode();
$data['file'] = $exception->getFile();
$data['line'] = $exception->getLine();
$data['error'] = $exception->getMessage();
SystemLog::write($data);
}
} catch (InvalidArgumentException $e) {
} }
parent::report($exception);
} }
/** /**
@@ -64,12 +55,16 @@ class ExceptionHandle extends ExceptionHandler
*/ */
public function render(Request $request, Throwable $exception): Response public function render(Request $request, Throwable $exception): Response
{ {
if ($exception instanceof \RuntimeException) { switch (true) {
return \response($exception->getMessage()); case $exception instanceof OperateException:
} case $exception instanceof ValidateException:
if (!file_exists(root_path() . '.env')) { return json(['code' => $exception->getCode() ?? 101, 'msg' => $exception->getMessage()]);
return parent::render($request, $exception); case $exception instanceof DumpException:
return \response($exception->getMessage());
default:
break;
} }
return get_env('APP_DEBUG') ? parent::render($request, $exception) : view(config('app.exception_tpl'), ['trace' => $exception]); return get_env('APP_DEBUG') ? parent::render($request, $exception) : view(config('app.exception_tpl'), ['trace' => $exception]);
} }
} }

View File

@@ -1,336 +0,0 @@
<?php
declare(strict_types=1);
// +----------------------------------------------------------------------
// | swiftAdmin 极速开发框架 [基于WebMan开发]
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2030 http://www.swiftadmin.net
// +----------------------------------------------------------------------
// | swiftAdmin.net High Speed Development Framework
// +----------------------------------------------------------------------
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License
// +----------------------------------------------------------------------
namespace app\common\library;
use app\common\model\system\UserLog;
use Psr\SimpleCache\InvalidArgumentException;
use system\Random;
use support\Response;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Cache;
use app\common\model\system\User as UserModel;
use Webman\Event\Event;
class Auth
{
/**
* token令牌
* @var string
*/
public string $token;
/**
* 用户ID
*/
public mixed $user_id = 0;
/**
* 用户数据
* @var object|array
*/
public mixed $userInfo;
/**
* 保活时间
* @var int
*/
protected int $keepTime = 604800;
/**
* 错误信息
* @var string
*/
protected string $_error = '';
/**
* @var object 对象实例
*/
protected static $instance;
/**
* 类构造函数
* class constructor.
*/
public function __construct($config = [])
{
$this->keepTime = config('session.cookie_lifetime');
}
/**
* 初始化
* @access public
* @param array $options 参数
* @return object
*/
public static function instance(array $options = [])
{
if (is_null(self::$instance)) {
self::$instance = new static($options);
}
// 返回实例
return self::$instance;
}
/**
* 用户注册
* @param array $post
* @return false|Response
* @throws DataNotFoundException
* @throws DbException
* @throws InvalidArgumentException
* @throws ModelNotFoundException
*/
public function register(array $post)
{
if (!saenv('user_status')) {
$this->setError('暂未开放注册!');
return false;
}
// 禁止批量注册
$where[] = ['create_ip', '=', request()->getRealIp()];
$where[] = ['create_time', '>', linux_time(1)];
$totalMax = UserModel::where($where)->count();
if ($totalMax >= saenv('user_register_second')) {
$this->setError('当日注册量已达到上限');
return false;
}
// 过滤用户信息
if (isset($post['nickname']) && UserModel::getByNickname($post['nickname'])) {
$this->setError('当前用户名已被占用!');
return false;
}
if (isset($post['email']) && UserModel::getByEmail($post['email'])) {
$this->setError('当前邮箱已被占用!');
return false;
}
if (isset($post['mobile']) && UserModel::getByMobile($post['mobile'])) {
$this->setError('当前手机号已被占用!');
return false;
}
try {
/**
* 是否存在邀请注册
*/
$post['invite_id'] = $this->getToken('inviter');
if (isset($post['pwd']) && $post['pwd']) {
$post['salt'] = Random::alpha();
$post['pwd'] = encryptPwd($post['pwd'], $post['salt']);
}
$user = UserModel::create($post);
} catch (\Throwable $th) {
$this->setError($th->getMessage());
return false;
}
return $this->responseToken($user);
}
/**
* 用户检测登录
* @param string $nickname
* @param string $pwd
* @return false|Response
* @throws DataNotFoundException
* @throws DbException
* @throws InvalidArgumentException
* @throws ModelNotFoundException
*/
public function login(string $nickname = '', string $pwd = '')
{
// 支持邮箱或手机登录
if (filter_var($nickname, FILTER_VALIDATE_EMAIL)) {
$where[] = ['email', '=', htmlspecialchars(trim($nickname))];
} else {
$where[] = ['mobile', '=', htmlspecialchars(trim($nickname))];
}
$user = UserModel::where($where)->find();
if (!empty($user)) {
$uPwd = encryptPwd($pwd, $user['salt']);
if ($user['pwd'] !== $uPwd) {
$this->setError('用户名或密码错误');
UserLog::write($this->getError(), $user['nickname'], $user['id']);
return false;
}
if (!$user['status']) {
$this->setError('用户异常或未审核,请联系管理员');
UserLog::write($this->getError(), $user['nickname'], $user['id']);
return false;
}
// 更新登录数据
$update = [
'id' => $user['id'],
'login_time' => time(),
'login_ip' => request()->getRealIp(),
'login_count' => $user['login_count'] + 1,
];
if (UserModel::update($update)) {
Event::emit('userLoginSuccess', $user);
UserLog::write('登录成功', $user['nickname'], $user['id'], 1);
return $this->responseToken($user);
}
}
$this->setError('您登录的用户不存在');
return false;
}
/**
* 验证是否登录
* @return bool
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException|InvalidArgumentException
*/
public function isLogin(): bool
{
$token = $this->getToken();
if (!$token) {
return false;
}
// 验证token
$user = $this->checkToken($token);
if (isset($user['id'])) {
$this->userInfo = UserModel::with('group')->find($user['id']);
if (!empty($this->userInfo)) {
$this->token = $token;
$this->user_id = $user['id'];
$this->refreshUserInfo($token, $this->userInfo);
return true;
}
}
return false;
}
/**
* 获取用户信息
*/
public function getUserInfo()
{
$token = $this->getToken();
if (!$token) {
return false;
}
// 获取用户信息
return $this->checkToken($token);
}
/**
*
* 返回前端令牌
* @param $user
* @param bool $token
* @return Response
* @throws InvalidArgumentException
*/
public function responseToken($user, bool $token = false): Response
{
$this->token = $token ? $this->getToken() : $this->buildToken($user['id']);
$response = response();
$response->cookie('uid', $user['id'], $this->keepTime, '/');
$response->cookie('token', $this->token, $this->keepTime, '/');
$response->cookie('nickname', $user['nickname'], $this->keepTime, '/');
$this->refreshUserInfo($this->token, $user);
// 执行登录成功事件
Event::emit("userLoginSuccess", $user);
return $response;
}
/**
* 刷新用户信息
* @param $token
* @param $user
* @return void
* @throws InvalidArgumentException
*/
private function refreshUserInfo($token, $user): void
{
Cache::set($token, $user, $this->keepTime);
}
/**
* 生成token
* @access protected
* @param $id
* @return string
*/
protected function buildToken($id): string
{
return md5(Random::alpha(16) . $id);
}
/**
* 获取token
*/
public function getToken($token = 'token')
{
return request()->header($token, input($token, request()->cookie($token)));
}
/**
* 校验token
*/
public function checkToken($token)
{
return Cache::get($token);
}
/**
* 退出登录
* @return void
* @throws InvalidArgumentException
*/
public function logout()
{
Cache::delete($this->token);
}
/**
* 获取最后产生的错误
* @return string
*/
public function getError(): string
{
return $this->_error;
}
/**
* 设置错误
* @param string $error 信息信息
* @return void
*/
protected function setError(string $error): void
{
$this->_error = $error;
}
}

View File

@@ -1,358 +0,0 @@
<?php
declare(strict_types=1);
// +----------------------------------------------------------------------
// | swiftAdmin 极速开发框架 [基于WebMan开发]
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2030 http://www.swiftadmin.net
// +----------------------------------------------------------------------
// | swiftAdmin.net High Speed Development Framework
// +----------------------------------------------------------------------
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License
// +----------------------------------------------------------------------
namespace app\common\library;
use app\common\model\system\UserValidate;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
use Psr\SimpleCache\InvalidArgumentException;
use system\Random;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\Model;
/**
* 邮件发送类
*
*/
class Email
{
/**
* @var object 对象实例
*/
protected static $instance = null;
/**
* @PHPMailer 对象实例
*/
protected mixed $mail;
/**
* 验证码对象
* @var mixed
*/
private mixed $userVModel;
/**
* 验证码过期时间
* @var int
*/
private int $expireTime = 5; //验证码过期时间(分钟)
/**
* 错误信息
* @var string
*/
protected string $_error = '';
//默认配置
protected array $config = [
'smtp_debug' => false, // 是否调试
'smtp_host' => 'smtp.163.com', // 服务器地址
'smtp_port' => 587, // 服务器端口
'smtp_user' => 'yourname@163.com', // 邮件用户名
'smtp_pass' => '****', // 邮件密码
'smtp_name' => '管理员', // 发送邮件显示
];
/**
* 类构造函数
* class constructor.
* @throws Exception
* @throws InvalidArgumentException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function __construct()
{
// 此配置项为数组
if ($email = saenv('email')) {
$this->config = array_merge($this->config, $email);
}
// 创建PHPMailer对象实例
$this->mail = new PHPMailer();
$this->mail->CharSet = 'UTF-8';
$this->mail->IsSMTP();
/**
* 是否开启调试模式
*/
$this->mail->SMTPDebug = $this->config['smtp_debug'];
$this->mail->SMTPAuth = true;
$this->mail->SMTPSecure = 'ssl';
$this->mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$this->mail->Host = $this->config['smtp_host'];
$this->mail->Port = $this->config['smtp_port'];
$this->mail->Username = $this->config['smtp_user'];
$this->mail->Password = trim($this->config['smtp_pass']);
$this->mail->SetFrom($this->config['smtp_user'], $this->config['smtp_name']);
$this->userVModel = new UserValidate();
}
/**
* 初始化
* @access public
* @param array $options 参数
* @return EMAIL
* @throws DataNotFoundException
* @throws DbException
* @throws Exception
* @throws InvalidArgumentException
* @throws ModelNotFoundException
*/
public static function instance($options = [])
{
if (is_null(self::$instance)) {
self::$instance = new static($options);
}
// 返回实例
return self::$instance;
}
/**
* 设置邮件主题
* @param string $subject 邮件主题
* @return $this
*/
public function Subject(string $subject): Email
{
$this->mail->Subject = $subject;
return $this;
}
/**
* 设置发件人
* @param string $email 发件人邮箱
* @param string $name 发件人名称
* @return $this
* @throws \PHPMailer\PHPMailer\Exception
*/
public function from(string $email, string $name = ''): Email
{
$this->mail->setFrom($email, $name);
return $this;
}
/**
* 设置邮件内容
* @param $MsgHtml
* @param boolean $isHtml 是否HTML格式
* @return $this
* @throws \PHPMailer\PHPMailer\Exception
*/
public function MsgHTML($MsgHtml, bool $isHtml = true): Email
{
if ($isHtml) {
$this->mail->msgHTML($MsgHtml);
} else {
$this->mail->Body = $MsgHtml;
}
return $this;
}
/**
* 设置收件人
* @param $email
* @param string $name
* @return $this
* @throws Exception
*/
public function to($email, string $name = ''): Email
{
$emailArr = $this->buildAddress($email);
foreach ($emailArr as $address => $name) {
$this->mail->addAddress($address, $name);
}
return $this;
}
/**
* 添加附件
* @param string $path 附件路径
* @param string $name 附件名称
* @return Email
* @throws \PHPMailer\PHPMailer\Exception
*/
public function attachment(string $path, string $name = ''): Email
{
if (is_file($path)) {
$this->mail->addAttachment($path, $name);
}
return $this;
}
/**
* 构建Email地址
* @param $emails
* @return array
*/
protected function buildAddress($emails): array
{
$emails = is_array($emails) ? $emails : explode(',', str_replace(";", ",", $emails));
$result = [];
foreach ($emails as $key => $value) {
$email = is_numeric($key) ? $value : $key;
$result[$email] = is_numeric($key) ? "" : $value;
}
return $result;
}
/**
* 获取最后一条
* @param string $email
* @return mixed
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function getLast(string $email)
{
$sms = UserValidate::where('email', $email)->order('id', 'desc')->find();
return $sms ?: null;
}
/**
* 发送验证码
* @param string $email 收件人邮箱
* @param string $event
* @return Email
* @throws \PHPMailer\PHPMailer\Exception
*/
public function captcha(string $email = '', string $event = "default"): Email
{
$code = Random::number();
$array = [
'code' => $code,
'event' => $event,
'email' => $email,
'status' => 1,
];
$this->userVModel->create($array);
$content = read_file(base_path() . '/extend/conf/tpl/captcha.tpl');
$content = str_replace(['{code}', '{site_name}', '{time}'], [$code, saenv('site_name'), date('Y-m-d H:i:s')], $content);
$this->to($email)->Subject("验证码")->MsgHTML($content);
return $this;
}
/**
* 检查验证码
* @param string $email
* @param string $code
* @param string $event
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function check(string $email, string $code = '', string $event = "default"): bool
{
$result = $this->userVModel->where([
['event', '=', $event],
['email', '=', $email],
['status', '=', 1],
])->order("id", "desc")->find();
if (!empty($result) && $result->code == $code) {
// 设置已使用
$result->status = 0;
$result->save();
// 是否过期
$expires = time() - strtotime($result['create_time']);
if ($expires <= $this->expireTime * 60) {
return true;
}
$this->setError("当前验证码已过期!");
} else {
$this->setError("无效验证码");
}
return false;
}
/**
* 获取最后产生的错误
* @return string
*/
public function getError(): string
{
return $this->_error;
}
/**
* 设置错误
* @param string $error 信息信息
*/
protected function setError(string $error): void
{
$this->_error = $error;
}
/**
* 发送邮件
* @return boolean
*/
public function send(): bool
{
$result = false;
try {
$result = $this->mail->send();
} catch (\PHPMailer\PHPMailer\Exception $e) {
$this->setError($e->getMessage());
}
$this->setError($result ? '' : $this->mail->ErrorInfo);
return $result;
}
/**
* 测试发送邮件
*/
public function testEmail($config)
{
if (empty($config) || !is_array($config)) {
return '缺少必要的信息';
}
$this->config = array_merge($this->config, $config);
$this->mail->Host = $this->config['smtp_host'];
$this->mail->Port = $this->config['smtp_port'];
$this->mail->Username = $this->config['smtp_user'];
$this->mail->Password = trim($this->config['smtp_pass']);
$this->mail->SetFrom($this->config['smtp_user'], $this->config['smtp_name']);
return $this->to($config['smtp_test'])->Subject("测试邮件")->MsgHTML("如果您看到这封邮件,说明测试成功了!")->send();
}
}

View File

@@ -1,154 +0,0 @@
<?php
declare(strict_types=1);
// +----------------------------------------------------------------------
// | swiftAdmin 极速开发框架 [基于WebMan开发]
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2030 http://www.swiftadmin.net
// +----------------------------------------------------------------------
// | swiftAdmin.net High Speed Development Framework
// +----------------------------------------------------------------------
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License
// +----------------------------------------------------------------------
namespace app\common\library;
use support\Log;
use system\Random;
/**
* FTP上传类
*
*/
class Ftp
{
/**
* @var object 对象实例
*/
protected static $instance = null;
//默认配置
protected array $config = [
'upload_ftp_host' => '127.0.0.1', // 服务器地址
'upload_ftp_port' => 21, // 服务器端口
'upload_ftp_user' => 'username', // FTP用户名
'upload_ftp_pass' => 'password', // FTP密码
'upload_path' => 'upload', // 上传路径
];
/**
* 类构造函数
* class constructor.
*/
public function __construct()
{
if ($upload = saenv('upload', true)) {
$this->config = array_merge($this->config, $upload);
}
}
/**
* 初始化
* @access public
* @param array $options 参数
* @return Ftp
*/
public static function instance($options = [])
{
if (is_null(self::$instance)) {
self::$instance = new static($options);
}
// 返回实例
return self::$instance;
}
/**
* FTP上传函数
* @access public
* @param string $source 源文件
* @param string $filepath 文件路径
* @param string $filename 文件名称
* @return bool true|false
*/
public function ftpUpload(string $source, string $filepath, string $filename): bool
{
if (!empty($source) && !empty($filepath)) {
// 链接FTP
$connect = @ftp_connect($this->config['upload_ftp_host'], $this->config['upload_ftp_port']) or die('Could not connect');
if (!ftp_login($connect, $this->config['upload_ftp_user'], $this->config['upload_ftp_pass'])) {
return false;
}
// 开启被动模式
ftp_pasv($connect, TRUE);
$source = fopen($source, "r");
// 循环创建文件夹
$filepath = str_replace("\\", '/', $filepath);
$dirs = explode('/', $filepath);
foreach ($dirs as $val) {
if (@ftp_chdir($connect, $val) == false) {
if (!ftp_mkdir($connect, $val)) {
//创建失败
return false;
}
// 切换目录
@ftp_chdir($connect, $val);
}
}
if (!@ftp_fput($connect, $filename, $source, FTP_BINARY)) {
return false;
}
ftp_close($connect);
return true;
} else {
return false;
}
}
/**
* FTP测试函数
* @access public
* @param array $config 配置信息
* @return bool true|false
*/
public function ftpTest(array $config): bool
{
$connect = @ftp_connect($config['host'], (int)$config['port']) or die('Could not connect');
if (@ftp_login($connect, $config['user'], $config['pass'])) {
try {
// 开启被动模式
ftp_pasv($connect, TRUE);
$folder = Random::alpha(16);
if (ftp_mkdir($connect, $folder)) {
// 读取测试文件
$location = __DIR__;
$source = fopen($location, "r"); // 上传测试文件
$filename = $folder . "/target.txt";
ftp_fput($connect, $filename, $source, FTP_BINARY);
// 删除测试文件
ftp_delete($connect, $filename);
ftp_rmdir($connect, $folder);
ftp_close($connect);
return true;
}
} catch (\Throwable $th) {
Log::info('upload ftp ' . $th->getMessage());
return false;
}
}
return false;
}
}

View File

@@ -1,192 +0,0 @@
<?php
declare (strict_types=1);
// +----------------------------------------------------------------------
// | swiftAdmin 极速开发框架 [基于WebMan开发]
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2030 http://www.swiftadmin.net
// +----------------------------------------------------------------------
// | swiftAdmin.net High Speed Development Framework
// +----------------------------------------------------------------------
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License
// +----------------------------------------------------------------------
namespace app\common\library;
use app\common\model\system\UserValidate;
use Psr\SimpleCache\InvalidArgumentException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use Webman\Event\Event;
/**
* 短信息类
*
*/
class Sms
{
/**
* 默认配置
* @var array
*/
protected array $config = [];
/**
* 错误信息
* @var string
*/
protected string $_error = '';
/**
* 验证码对象
* @var mixed
*/
protected string $smsType = 'alisms';
/**
* 验证码过期时间
* @var int
*/
private int $expireTime = 5; //验证码过期时间(分钟)
/**
* @var object 对象实例
*/
protected static $instance = null;
/**
* 类构造函数
* class constructor.
* @throws InvalidArgumentException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function __construct()
{
// 此配置项为数组。
if ($this->smsType = saenv('smstype')) {
$this->config = array_merge($this->config, saenv($this->smsType));
}
}
/**
* 初始化
* @access public
* @param array $options 参数
* @return self
* @throws DataNotFoundException
* @throws DbException
* @throws InvalidArgumentException
* @throws ModelNotFoundException
*/
public static function instance($options = [])
{
if (is_null(self::$instance)) {
self::$instance = new static($options);
}
// 返回实例
return self::$instance;
}
/**
* 发送短信
* @param string $mobile
* @param string $event
* @return bool
*/
public function send(string $mobile, string $event = 'register'): bool
{
if (!Event::hasListener('smsMsgSend')) {
$this->setError('短信插件未安装');
return false;
}
$config = include(base_path() . "/extend/conf/sms/sms.php");
if (!isset($config[$this->smsType][$event]['template'])) {
$this->setError('短信模板错误');
return false;
}
$response = Event::emit('smsMsgSend', [
'mobile' => $mobile,
'event' => $event,
'template' => $config[$this->smsType][$event]['template']
],true);
if ($response['error']) {
$this->setError($response['msg']);
return false;
}
return true;
}
/**
* 获取最后一条
* @param string $mobile
* @return UserValidate|array|mixed|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getLast(string $mobile)
{
$mobile = str_replace(['+86', '-', ' ', '.'], '', $mobile);
$sms = UserValidate::where('mobile', $mobile)->order('id', 'desc')->find();
return $sms ?: null;
}
/**
* 检查验证码
*
* @param string $mobile
* @param string $code
* @param string $event
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function check(string $mobile, string $code, string $event = "default"): bool
{
$where = [
['event', '=', $event],
['mobile', '=', $mobile],
['status', '=', 1],
];
$result = UserValidate::where($where)->order("id", "desc")->find();
if (!empty($result) && $result->code === $code) {
$result->status = 0;
$result->save();
$expires = time() - strtotime($result['create_time']);
if ($expires <= $this->expireTime * 60) {
return true;
}
$this->setError("当前验证码已过期!");
} else {
$this->setError("无效验证码");
}
return false;
}
/**
* 获取最后产生的错误
* @return string
*/
public function getError(): string
{
return $this->_error;
}
/**
* 设置错误
* @param string $error 信息信息
*/
protected function setError(string $error): void
{
$this->_error = $error;
}
}

View File

@@ -1,6 +1,8 @@
<?php <?php
namespace app\common\logic; namespace app\common\logic\admin;
use app\common\service\BaseServiceLogic;
/** /**
* 管理员日志逻辑层 * 管理员日志逻辑层
@@ -9,7 +11,7 @@ namespace app\common\logic;
* @author meystack< * @author meystack<
* @version 1.0 * @version 1.0
*/ */
class AdminLogic extends \think\model class AdminLogic extends BaseServiceLogic
{ {
// TODO.. // TODO..
} }

View File

@@ -19,6 +19,10 @@ class User extends Model
// 定义时间戳字段名 // 定义时间戳字段名
protected $createTime = 'create_time'; protected $createTime = 'create_time';
protected $updateTime = 'update_time'; protected $updateTime = 'update_time';
/**
* @var array|string[] 可见字段
*/
protected array $visibleFields = ['id', 'nickname', 'heart', 'avatar', 'mobile', 'email', 'score', 'gender', 'create_time', 'update_time'];
/** /**
* 定义第三方登录 * 定义第三方登录
@@ -121,6 +125,25 @@ class User extends Model
return $value; return $value;
} }
/**
* 获取可见字段
* @return array|string[]
*/
public function getVisibleFields(): array
{
return $this->visibleFields;
}
/**
* 设置可见字段
* @param array $visibleFields
* @return void
*/
public function setVisibleFields(array $visibleFields): void
{
$this->visibleFields = $visibleFields;
}
/** /**
* 减少会员积分 * 减少会员积分
* *
@@ -128,7 +151,7 @@ class User extends Model
* @param integer $score * @param integer $score
* @return void * @return void
*/ */
public static function reduceScore(int $id = 0, int $score = 0) public static function reduceScore(int $id = 0, int $score = 0): void
{ {
try { try {
if ($score) { if ($score) {

View File

@@ -58,6 +58,8 @@ class SaLibs extends TagLib
if (isset($variable[$tags['name']])) { if (isset($variable[$tags['name']])) {
return $variable[$tags['name']]; return $variable[$tags['name']];
} }
return '';
} }
/** /**

View File

@@ -18,4 +18,15 @@ class Dictionary extends Validate
'name' => 'require', 'name' => 'require',
'value' => 'require', 'value' => 'require',
]; ];
/**
* 定义错误信息
* 格式:'字段名.规则名' => '错误信息'
*
* @var array
*/
protected $message = [
'name.require' => '字典名称不能为空',
'value.require' => '字典值不能为空',
];
} }

View File

@@ -19,9 +19,11 @@ class User extends Validate
* @var array * @var array
*/ */
protected $rule = [ protected $rule = [
'test_filed' => 'max:255', 'nickname' => 'require|min:5|max:32|checkName',
'nickname' => 'require|min:2|max:12|filters|chsAlphaNum', 'pwd|密码' => 'require|min:6|max:64',
'pwd|密码' => 'require|min:6|max:64', 'email' => 'require',
'mobile' => 'require|mobile',
'captcha' => 'require',
]; ];
/** /**
@@ -32,35 +34,54 @@ class User extends Validate
*/ */
protected $message = [ protected $message = [
'nickname.require' => '用户名不能为空', 'nickname.require' => '用户名不能为空',
'nickname.min' => '用户名不能少于2个字符', 'nickname.min' => '用户名不能少于5个字符',
'nickname.max' => '用户名不能超过12个字符', 'nickname.max' => '用户名不能超过32个字符',
'nickname.filters' => '用户名包含禁止注册字符', 'nickname.checkName' => '用户名包含禁止注册字符',
'nickname.chsAlphaNum' => '用户名只能是汉字、字母和数字', 'pwd.require' => '密码不能为空',
'test_filed.max' => '测试场景用', 'pwd.min' => '密码不能少于6个字符',
'pwd.max' => '密码不能超过64个字符',
'email.require' => '邮箱不能为空',
'mobile.require' => '手机号不能为空',
'mobile.mobile' => '手机号格式不正确',
'captcha.require' => '验证码不能为空',
]; ];
// 测试验证场景 // 测试验证场景
protected $scene = [ protected $scene = [
'test' => ['test_filed'],
'nickname' => ['nickname'], 'nickname' => ['nickname'],
'mobile' => ['mobile', 'captcha'],
'login' => ['nickname', 'pwd'],
]; ];
/** /**
* 自定义验证规则 * 自定义验证规则
* @param $value * @param $value
* @return bool * @return string|bool
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/ */
protected function filters($value): bool protected function checkName($value): string|bool
{ {
$notAllow = saenv('user_reg_notallow'); $notAllow = saenv('user_reg_notallow');
$notAllow = explode(',', $notAllow); $notAllow = explode(',', $notAllow);
if (in_array($value, $notAllow)) { if (in_array($value, $notAllow)) {
return false; return '用户名不合法!';
} }
return true; return true;
} }
public function sceneRegister(): User
{
return $this->only(['nickname', 'pwd']);
}
public function scenePwd(): User
{
return $this->only(['pwd'])->append('pwd', 'confirm');
}
public function sceneMobile(): User
{
return $this->only(['mobile', 'captcha']);
}
} }

View File

@@ -3,11 +3,10 @@
* 全局公共函数库 * 全局公共函数库
*/ */
use app\common\library\Auth;
use app\common\model\system\UserThird; use app\common\model\system\UserThird;
use think\facade\Cache;
use app\common\model\system\Config; use app\common\model\system\Config;
use think\helper\Str; use think\helper\Str;
use support\Cache;
// 权限常量 // 权限常量
const AUTH_CATE = 'cates'; const AUTH_CATE = 'cates';
@@ -113,31 +112,6 @@ if (!function_exists('token_field')) {
} }
} }
if (!function_exists('get_user_id')) {
/**
* 获取会员ID
*/
function get_user_id()
{
return get_user_info('id');
}
}
if (!function_exists('get_user_info')) {
/**
* 获取会员信息
*/
function get_user_info($field = '')
{
$data = Auth::instance()->getUserInfo();
if ($field && isset($data[$field])) {
return $data[$field];
}
return $data;
}
}
if (!function_exists('get_admin_id')) { if (!function_exists('get_admin_id')) {
/** /**
* 获取管理员ID * 获取管理员ID
@@ -660,15 +634,11 @@ if (!function_exists('saenv')) {
* @param bool $group * @param bool $group
* @return mixed * @return mixed
* @throws \Psr\SimpleCache\InvalidArgumentException * @throws \Psr\SimpleCache\InvalidArgumentException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/ */
function saenv(string $name, bool $group = false) function saenv(string $name, bool $group = false): mixed
{ {
$redis = 'config_' . $name; $redis = 'config_' . $name;
$config = Cache::get($redis); $config = Cache::get($redis);
try { try {
$configList = Cache::get('config_list') ?? []; $configList = Cache::get('config_list') ?? [];
if (is_array($config) ? empty($config) : is_empty($config)) { if (is_array($config) ? empty($config) : is_empty($config)) {
@@ -683,52 +653,11 @@ if (!function_exists('saenv')) {
Cache::set('config_list', $configList); Cache::set('config_list', $configList);
} }
} }
} catch (\Exception $e) {}
} catch (\Exception $e) {
}
return $config; return $config;
} }
} }
if (!function_exists('system_cache')) {
/**
* 全局缓存控制函数
* @param string $name
* @param mixed $value
* @param null $options
* @param null $tag
* @return mixed
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
function system_cache(string $name = '', mixed $value = '', $options = null, $tag = null)
{
if (is_null($name)) {
return [];
}
if ('' === $value) {
// 获取缓存
return str_starts_with($name, '?') ? Cache::has(substr($name, 1)) : Cache::get($name);
} elseif (is_null($value)) {
// 删除缓存
return Cache::delete($name);
}
// 缓存数据
if (is_array($options)) {
$expire = $options['expire'] ?? null;
} else {
$expire = $options;
}
if (is_null($tag)) {
return Cache::set($name, $value, $expire);
} else {
return Cache::tag($tag)->set($name, $value, $expire);
}
}
}
if (!function_exists('system_reload')) { if (!function_exists('system_reload')) {
/** /**
* 重载系统 * 重载系统
@@ -1096,6 +1025,71 @@ if (!function_exists('request_validate_rules')) {
} }
} }
if (!function_exists('validate')) {
/**
* 验证数据
* @access protected
* @param $validate
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @param bool $failException
* @return \think\Validate
*/
function validate($validate, array $message = [], bool $batch = false, bool $failException = true): \think\Validate
{
if (is_array($validate) || '' === $validate) {
$v = new \think\Validate();
if (is_array($validate)) {
$v->rule($validate);
}
} else {
if (strpos($validate, '.')) {
// 支持场景
[$validate, $scene] = explode('.', $validate);
}
$class = str_contains($validate, '\\') ? $validate : parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
return $v->message($message)->batch($batch)->failException($failException);
}
}
if (!function_exists('parseClass')) {
/**
* 解析应用类的类名
* @access public
* @param string $layer 层名 controller model ...
* @param string $name 类名
* @return string
*/
function parseClass(string $layer, string $name): string
{
$name = str_replace(['/', '.'], '\\', $name);
$array = explode('\\', $name);
$class = underline_to_hump(array_pop($array));
$path = $array ? implode('\\', $array) . '\\' : '';
return 'app' . '\\' . $layer . '\\' . $path . $class;
}
}
if (!function_exists('underline_to_hump')) {
/**
* 下划线转驼峰
* @param string $value
* @return string
*/
function underline_to_hump(string $value): string
{
$value = ucwords(str_replace(['-', '_'], ' ', $value));
return str_replace(' ', '', $value);
}
}
if (!function_exists('check_user_third')) { if (!function_exists('check_user_third')) {
/** /**
* 获取第三方登录 * 获取第三方登录
@@ -1336,7 +1330,7 @@ if (!function_exists('get_plugin_instance')) {
* @param string $class 当前类名 * @param string $class 当前类名
* @return mixed * @return mixed
*/ */
function get_plugin_instance(string $name, string $class = '') function get_plugin_instance(string $name, string $class = ''): mixed
{ {
$object = get_plugin_class($name, $class); $object = get_plugin_class($name, $class);
return $object ? new $object : ''; return $object ? new $object : '';
@@ -1370,7 +1364,7 @@ if (!function_exists('get_plugin_list')) {
$list = array_merge($list, $other); $list = array_merge($list, $other);
} }
return $list ?: []; return $list ?? [];
} }
} }
@@ -1434,21 +1428,18 @@ if (!function_exists('set_plugin_config')) {
if (!function_exists('get_plugin_menu_entry')) { if (!function_exists('get_plugin_menu_entry')) {
/** /**
* 获取插件快捷入口 * 获取插件快捷入口
* @param string $type
* @return void * @return void
*/ */
function get_plugin_menu_entry(string $type = 'menu') function get_plugin_menu_entry(string $type = 'menu'): void
{ {
$quickEntry = ''; $quickEntry = '';
$pluginList = get_plugin_list(); $pluginList = get_plugin_list();
foreach ($pluginList as $item) { foreach ($pluginList as $item) {
try { try {
if (!$item['status']) { if (!$item['status']) {
continue; continue;
} }
$file = plugin_path($item['name']) . 'data/' . $type . '.html'; $file = plugin_path($item['name']) . 'data/' . $type . '.html';
if (is_file($file)) { if (is_file($file)) {
$quickEntry .= file_get_contents($file) . PHP_EOL; $quickEntry .= file_get_contents($file) . PHP_EOL;
@@ -1457,7 +1448,6 @@ if (!function_exists('get_plugin_menu_entry')) {
continue; continue;
} }
} }
echo $quickEntry; echo $quickEntry;
} }
} }
@@ -1469,77 +1459,48 @@ if (!function_exists('plugin_refresh_hooks')) {
*/ */
function plugin_refresh_hooks(): bool function plugin_refresh_hooks(): bool
{ {
$pluginEvent = [];
$pluginList = get_plugin_list(); $pluginList = get_plugin_list();
$taglib = [];
$events = [];
$routeList = '';
$parseRules = '<?php' . PHP_EOL . 'return [array' . PHP_EOL . '];';
foreach ($pluginList as $item) { foreach ($pluginList as $item) {
if (!$item['status']) { if (!$item['status']) {
continue; continue;
} }
// 插件名称
$name = $item['name']; $name = $item['name'];
$rewrite = $item['rewrite'] ?: [];
foreach ($rewrite as $key => $route) {
$parse = explode('/', $route);
$action = end($parse);
array_pop($parse);
$path = implode('\\', $parse);
$controller = 'app\\index\\controller\\' . $path;
if (class_exists($controller) && method_exists($controller, $action)) {
$controller = preg_replace('#//#', '/', $controller);
$routeList .= PHP_EOL . " '$key'=>[$controller::class, '$action'],";
}
}
$namespace = '\\plugin\\' . $name . '\\' . ucfirst($name); $namespace = '\\plugin\\' . $name . '\\' . ucfirst($name);
$methods = get_class_methods($namespace); $methods = get_class_methods($namespace);
$diff_hooks = array_diff($methods, get_class_methods("\\app\\PluginController")); $diff_hooks = array_diff($methods, get_class_methods("\\app\\PluginController"));
foreach ($diff_hooks as $hook) { foreach ($diff_hooks as $hook) {
$hookName = $name . '.' . $hook; $hookName = $name . '.' . $hook;
$events[$hook][] = [$namespace, $hook]; $pluginEvent[$hook][] = [$namespace, $hook];
}
$taglibPath = plugin_path($name . DIRECTORY_SEPARATOR . 'taglib');
$tagList = glob($taglibPath . '*.php');
foreach ($tagList as $index => $tag) {
$tag = pathinfo($tag, PATHINFO_FILENAME);
$taglib[] = 'plugin\\' . $name . '\\taglib\\' . $tag;
} }
} }
arr2file(root_path('config') . 'taglib.php', $taglib); $eventPath = root_path('config') . 'event.php';
$routePath = root_path('config') . 'defineRoute.php'; $eventOrigin = include /** @lang text */
write_file($routePath, str_replace('array', $routeList, $parseRules)); $eventPath;
$hooks = include/** @lang text */ foreach ($eventOrigin as $key => $item) {
(root_path('config') . 'event.php');
foreach ($hooks as $key => $item) {
$separator = explode('.', $key); $separator = explode('.', $key);
if (current($separator) == 'system') { if (current($separator) == 'system') {
continue; continue;
} }
if (!array_key_exists($key, $events)) { if (!array_key_exists($key, $pluginEvent)) {
unset($hooks[$key]); unset($eventOrigin[$key]);
} }
} }
$eventList = ''; $eventChars = '';
$events = array_merge($hooks, array_diff_key($events, $hooks)); $eventLists = array_merge($eventOrigin, array_diff_key($pluginEvent, $eventOrigin));
foreach ($events as $key => $event) { foreach ($eventLists as $key => $event) {
$eventList .= PHP_EOL . " '$key'=> ["; $eventChars .= PHP_EOL . " '$key'=> [";
foreach ($event as $value) { foreach ($event as $value) {
$eventList .= PHP_EOL . " [" . $value[0] . "::class, '" . $value[1] . "']," . PHP_EOL; $eventChars .= PHP_EOL . " [" . $value[0] . "::class, '" . $value[1] . "']," . PHP_EOL;
} }
$eventChars .= ' ],';
$eventList .= ' ],';
} }
$eventPath = root_path('config') . 'event.php'; $parseEvents = '<?php' . PHP_EOL . 'return [array' . PHP_EOL . '];';
write_file($eventPath, str_replace('array', $eventList, $parseRules)); write_file($eventPath, str_replace('array', $eventChars, $parseEvents));
return system_reload(); return system_reload();
} }
} }

View File

@@ -12,17 +12,8 @@
namespace app\index\controller; namespace app\index\controller;
use app\common\library\Email;
use app\common\library\Sms;
use app\common\model\system\User;
use app\HomeController; use app\HomeController;
use PHPMailer\PHPMailer\Exception;
use Psr\SimpleCache\InvalidArgumentException;
use support\Response; use support\Response;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\response\Json;
/** /**
* Ajax控制器 * Ajax控制器
@@ -35,86 +26,6 @@ class Ajax extends HomeController
*/ */
public function index(): Response public function index(): Response
{ {
return \response('Hello SWIFT!', 200); return \response('Hello swiftadmin!', 200);
}
/**
* 发送短信验证码
* @throws DataNotFoundException
* @throws DbException
* @throws InvalidArgumentException
* @throws ModelNotFoundException
*/
public function smsSend()
{
if (request()->isPost()) {
$mobile = input('mobile');
$event = input('event', 'register');
if (!is_mobile($mobile)) {
return $this->error('手机号码不正确');
}
$sms = Sms::instance();
$data = $sms->getLast($mobile);
if ($data && (time() - strtotime($data['create_time'])) < 60) {
return $this->error(__('发送频繁'));
}
$user = User::getByMobile($mobile);
if (in_array($event, ['register', 'changer']) && $user) {
return $this->error('当前手机号已被占用');
} else if ($event == 'forgot' && !$user) {
return $this->error('当前手机号未注册');
}
if ($sms->send($mobile, $event)) {
return $this->success("验证码发送成功!");
} else {
return $this->error($sms->getError());
}
}
}
/**
* 发送邮件验证码
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws Exception
* @throws InvalidArgumentException
*/
public function emailSend()
{
if (request()->isPost()) {
$email = input('email');
$event = input('event', 'register');
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->error('邮件格式不正确');
}
$Ems = Email::instance();
$data = $Ems->getLast($email);
if ($data && (time() - strtotime($data['create_time'])) < 60) {
return $this->error(__('发送频繁'));
}
$user = User::getByEmail($email);
if (in_array($event, ['register', 'changer']) && $user) {
return $this->error('当前邮箱已被注册');
} else if ($event == 'forgot' && !$user) {
return $this->error('当前邮箱不存在');
}
if ($Ems->captcha($email, $event)->send()) {
return $this->success("验证码发送成功!");
} else {
return $this->error($Ems->getError());
}
}
} }
} }

View File

@@ -12,11 +12,8 @@ declare (strict_types=1);
namespace app\index\controller; namespace app\index\controller;
use app\HomeController; use app\HomeController;
use support\Response;
use Psr\SimpleCache\InvalidArgumentException; use Psr\SimpleCache\InvalidArgumentException;
use think\db\exception\DataNotFoundException; use support\Response;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
class Index extends HomeController class Index extends HomeController
{ {
@@ -24,19 +21,9 @@ class Index extends HomeController
* 前端首页 * 前端首页
* @return Response * @return Response
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/ */
public function index(): Response public function index(): Response
{ {
$data = [
'欢迎使用swiftAdmin极速开发框架',
__DIR__.'\Index.php 正在使用halt函数输出到浏览器',
'请在app\index\controller\Index.php中删除halt函数',
];
halt($data);
return $this->view('index/index', ['name' => 'meystack']); return $this->view('index/index', ['name' => 'meystack']);
} }
} }

View File

@@ -12,11 +12,13 @@ declare (strict_types=1);
namespace app\index\controller; namespace app\index\controller;
use app\common\library\Auth;
use app\common\library\ResultCode; use app\common\library\ResultCode;
use app\common\service\user\UserService;
use app\common\service\user\UserTokenService;
use app\HomeController; use app\HomeController;
use app\common\model\system\User; use app\common\model\system\User;
use app\common\model\system\UserThird; use app\common\model\system\UserThird;
use Psr\SimpleCache\InvalidArgumentException;
use support\Response; use support\Response;
use system\Random; use system\Random;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
@@ -87,10 +89,11 @@ class Third extends HomeController
/** /**
* 用户回调函数 * 用户回调函数
* @return mixed|void * @return Response
* @throws DataNotFoundException * @throws DataNotFoundException
* @throws DbException * @throws DbException
* @throws ModelNotFoundException * @throws ModelNotFoundException
* @throws InvalidArgumentException
*/ */
public function callback() public function callback()
{ {
@@ -100,9 +103,9 @@ class Third extends HomeController
return $this->error($e->getMessage()); return $this->error($e->getMessage());
} }
$user = $this->oauth->getUserInfo(); $user = $this->oauth->getUserInfo();
if (!empty($user) && !$this->auth->isLogin()) { if (!empty($user) && !UserTokenService::isLogin()) {
return $this->register($user, $this->type); return $this->register($user, $this->type);
} else if ($this->auth->isLogin()) { // 绑定用户 } else if (UserTokenService::isLogin()) { // 绑定用户
return $this->doBind($user, $this->type); return $this->doBind($user, $this->type);
} }
} }
@@ -123,31 +126,28 @@ class Third extends HomeController
$userInfo = UserThird::alias('th')->view('user', '*', 'user.id=th.user_id')->where(['openid' => $openid, 'type' => $type])->find(); $userInfo = UserThird::alias('th')->view('user', '*', 'user.id=th.user_id')->where(['openid' => $openid, 'type' => $type])->find();
if (!empty($userInfo)) { if (!empty($userInfo)) {
$array['id'] = $userInfo['id'];
$array['login_time'] = time(); $array['login_time'] = time();
$array['login_ip'] = request()->getRealIp(); $array['login_ip'] = request()->getRealIp();
$array['login_count'] = $userInfo['login_count'] + 1; $array['login_count'] = $userInfo['login_count'] + 1;
if (User::update($array, ['id' => $userInfo['user_id']])) {
if (User::update($array)) { UserService::createUserCookies($userInfo);
$response = $this->auth->responseToken($userInfo); return redirect(request()->cookie('redirectUrl', '/'));
$response->withBody(json_encode(ResultCode::LOGINSUCCESS))->redirect(request()->cookie('redirectUrl', '/'));
} }
} else { } else {
// 注册本地用户 // 注册本地用户
$data['nickname'] = $nickname; $post['nickname'] = $nickname;
$data['avatar'] = $info['userData']['avatar']; $post['avatar'] = $info['userData']['avatar'];
if (User::getByNickname($nickname)) { if (User::getByNickname($nickname)) {
$data['nickname'] .= Random::alpha(3); $post['nickname'] .= Random::alpha(3);
} }
$data['group_id'] = 1; $post['group_id'] = 1;
$data['create_ip'] = request()->getRealIp(); $post['create_ip'] = request()->getRealIp();
$result = $this->auth->register($data); $result = UserService::register($post);
// 封装第三方数据 // 封装第三方数据
if (!empty($result)) { if (!empty($result)) {
$userThird = [ $third = [
'type' => $this->type, 'type' => $this->type,
'user_id' => $result['id'], 'user_id' => $result['id'],
'openid' => $openid, 'openid' => $openid,
@@ -158,13 +158,10 @@ class Third extends HomeController
'login_time' => time(), 'login_time' => time(),
'expiretime' => time() + $info['expires_in'], 'expiretime' => time() + $info['expires_in'],
]; ];
}
// 注册第三方数据 if (UserThird::create($third)) {
if (isset($userThird) && is_array($userThird)) { UserService::createUserCookies($result);
if (UserThird::create($userThird)) { return redirect(request()->cookie('redirectUrl', '/'));
$response = $this->auth->responseToken($result);
$response->withBody(json_encode(ResultCode::LOGINSUCCESS))->redirect(request()->cookie('redirectUrl', '/'));
} }
} }
} }
@@ -175,17 +172,18 @@ class Third extends HomeController
/** /**
* 用户绑定操作 * 用户绑定操作
* @return Response * @return Response
* @throws InvalidArgumentException
*/ */
public function bind(): Response public function bind(): Response
{ {
if (Auth::instance()->isLogin()) { if (UserTokenService::isLogin()) {
$buildQuery = [ $buildQuery = [
'bind' => true, 'bind' => true,
'type' => input('type'), 'type' => input('type'),
'ref' => input('ref', request()->server('HTTP_REFERER', '/')), 'ref' => input('ref', request()->server('HTTP_REFERER', '/')),
]; ];
return $this->redirect("/third/login?" . http_build_query($buildQuery)); return $this->redirect("/third/login?" . http_build_query($buildQuery));
} }
return $this->error('请先登录'); return $this->error('请先登录');
@@ -193,7 +191,9 @@ class Third extends HomeController
/** /**
* 用户解除绑定 * 用户解除绑定
* @return Response
* @throws DbException * @throws DbException
* @throws InvalidArgumentException
*/ */
public function unbind(): Response public function unbind(): Response
{ {
@@ -202,23 +202,22 @@ class Third extends HomeController
} catch (\Exception $e) { } catch (\Exception $e) {
return $this->error($e->getMessage()); return $this->error($e->getMessage());
} }
if ($this->auth->isLogin()) {
$result = $this->auth->userInfo; $result = UserTokenService::isLogin();
if (!empty($result)) { if (!empty($result)) {
if (empty($result['email']) || empty($result['pwd'])) { if (empty($result['email']) || empty($result['pwd'])) {
return $this->error('解除绑定需要设置邮箱和密码!'); return $this->error('解除绑定需要设置邮箱和密码!');
} }
$where['type'] = $this->type; $where['type'] = $this->type;
$where['user_id'] = request()->cookie('uid'); $where['user_id'] = request()->cookie('uid');
if (UserThird::where($where)->delete()) { if (UserThird::where($where)->delete()) {
return $this->success('解除绑定成功!'); return $this->success('解除绑定成功!');
}
} }
} }
return $this->error(); return $this->error();
} }
@@ -233,10 +232,8 @@ class Third extends HomeController
*/ */
protected function doBind(array $info = [], string $type = null) protected function doBind(array $info = [], string $type = null)
{ {
$openid = $info['openid'] ?? $info['id']; $openid = $info['openid'] ?? $info['id'];
$nickname = $info['userData']['name'] ?? $info['userData']['nickname']; $nickname = $info['userData']['name'] ?? $info['userData']['nickname'];
// 查询是否被注册 // 查询是否被注册
$where['openid'] = $openid; $where['openid'] = $openid;
$where['type'] = $this->type; $where['type'] = $this->type;
@@ -277,7 +274,7 @@ class Third extends HomeController
$referer = '/'; $referer = '/';
} }
request()->cookie('redirectUrl', null,1); request()->cookie('redirectUrl', null, 1);
return $this->redirect($referer); return $this->redirect($referer);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,9 @@
namespace app\index\middleware\system; namespace app\index\middleware\system;
use app\common\library\Auth;
use app\common\library\ResultCode; use app\common\library\ResultCode;
use app\common\service\user\UserTokenService;
use Psr\SimpleCache\InvalidArgumentException;
use support\View; use support\View;
use Webman\MiddlewareInterface; use Webman\MiddlewareInterface;
use Webman\Http\Response; use Webman\Http\Response;
@@ -32,22 +33,23 @@ class IndexPermissions implements MiddlewareInterface
* 非鉴权方法 * 非鉴权方法
* @var array * @var array
*/ */
public array $noNeedAuth = []; public array $noNeedLogin = [];
/** /**
* 跳转URL地址 * 跳转URL地址
* @var string * @var string
*/ */
public string $JumpUrl = '/index/user/index'; public string $JumpUrl = '/index/';
/** /**
* 校验权限 * 校验权限
* @param Request $request * @param \support\Request|Request $request
* @param callable $handler * @param callable $handler
* @return Response * @return Response
* @throws InvalidArgumentException
* @throws \ReflectionException * @throws \ReflectionException
*/ */
public function process(Request $request, callable $handler): Response public function process(\support\Request|Request $request, callable $handler): Response
{ {
$app = request()->getApp(); $app = request()->getApp();
$controller = request()->getController(); $controller = request()->getController();
@@ -56,23 +58,23 @@ class IndexPermissions implements MiddlewareInterface
$refClass = new \ReflectionClass($request->controller); $refClass = new \ReflectionClass($request->controller);
$property = $refClass->getDefaultProperties(); $property = $refClass->getDefaultProperties();
$this->needLogin = $property['needLogin'] ?? false; $this->needLogin = $property['needLogin'] ?? false;
$this->noNeedAuth = $property['noNeedAuth'] ?? $this->noNeedAuth; $this->noNeedLogin = $property['noNeedLogin'] ?? $this->noNeedLogin;
$this->repeatLogin = $property['repeatLogin'] ?? $this->repeatLogin; $this->repeatLogin = $property['repeatLogin'] ?? $this->repeatLogin;
$this->JumpUrl = $property['JumpUrl'] ?? $this->JumpUrl; $this->JumpUrl = $property['JumpUrl'] ?? $this->JumpUrl;
// 是否验证登录器 // 是否验证登录器
$auth = Auth::instance(); $userInfo = UserTokenService::isLogin();
if ($auth->isLogin()) { if (!empty($userInfo)) {
// 禁止重复登录
if (in_array($action, $this->repeatLogin)) { if (in_array($action, $this->repeatLogin)) {
var_dump($this->JumpUrl);
return redirect($this->JumpUrl); return redirect($this->JumpUrl);
} }
View::assign('user', $auth->userInfo); $request->userId = $userInfo['id'];
$request->userInfo = $userInfo;
View::assign('user', $userInfo);
} else { } else {
if ($this->needLogin && !in_array($action, $this->noNeedLogin)) {
if ($this->needLogin && !in_array($action, $this->noNeedAuth)) {
if (\request()->isAjax()) { if (\request()->isAjax()) {
return json(ResultCode::PLEASELOGININ); return json(ResultCode::PLEASELOGININ);
} else { } else {

View File

@@ -15,7 +15,7 @@
<div class="layui-container"> <div class="layui-container">
<div class="layui-row"> <div class="layui-row">
<div class="layui-col-md6"> <div class="layui-col-md6">
<div class="layui-swift-box"> <div class="layui-swift-box">
<h1>SWIFTADMIN 极速开发框架</h1> <h1>SWIFTADMIN 极速开发框架</h1>
<h1 style="font-size: 26px; font-weight: 300">基于高性能WM框架性能在TP5 10倍以上</h1> <h1 style="font-size: 26px; font-weight: 300">基于高性能WM框架性能在TP5 10倍以上</h1>
<p>SwiftAdmin框架主张简单就是高效的原则在设计和运维上采用最精简最高效的做法去完成业务系统的需求并且基于ant Design的设计原则是一款优秀的前后台极速开发解决方案。相信你第一眼就有立刻想体验SwiftAdmin框架的冲动和热情</p> <p>SwiftAdmin框架主张简单就是高效的原则在设计和运维上采用最精简最高效的做法去完成业务系统的需求并且基于ant Design的设计原则是一款优秀的前后台极速开发解决方案。相信你第一眼就有立刻想体验SwiftAdmin框架的冲动和热情</p>

View File

@@ -7,7 +7,6 @@
<link rel="stylesheet" href="/static/js/layui/css/layui.css"> <link rel="stylesheet" href="/static/js/layui/css/layui.css">
<link rel="stylesheet" href="/static/css/style.css?v={:release()}"> <link rel="stylesheet" href="/static/css/style.css?v={:release()}">
<script src="/static/js/layui/layui.js"></script> <script src="/static/js/layui/layui.js"></script>
<script src="/static/js/common.js?v={:release()}"></script>
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script> <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script> <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>

View File

@@ -14,8 +14,30 @@
<div class="layui-nav layui-hide-xs fr" id="login"> <div class="layui-nav layui-hide-xs fr" id="login">
<notempty name="$user.id"> <li class="layui-nav-item"><a class="" href="/index/user/index" >会员中心</a></li> <else/> <notempty name="$user.id"> <li class="layui-nav-item"><a class="" href="/index/user/index" >会员中心</a></li> <else/>
<li class="layui-nav-item"><a href="javascript:;" lay-open data-title="用户注册" data-area="490px" data-url="/index/user/register" >注册</a></li> <li class="layui-nav-item"><a href="/index/user/register" target="_blank">注册</a></li>
<li class="layui-nav-item"><a href="javascript:;" lay-open data-title="用户登录" data-area="450px,420px" data-url="/index/user/login" >登录</a></li> <li class="layui-nav-item"><a href="/index/user/login" target="_blank">登录</a></li>
<li class="layui-nav-item"><a id="ajaxLogin" href="javascript:;" lay-open data-title="用户登录" data-area="450px,420px" data-url="/index/user/ajaxLogin" >Ajax登录</a></li>
</notempty> </notempty>
</div> </div>
</div> </div>
<script >
layui.use([], function(e) {
var $ = layui.jquery;
var layer = layui.layer;
//监听导航点击
$('#ajaxLogin').on('click', function() {
var url = $(this).attr('data-url');
var title = $(this).attr('data-title');
var area = $(this).attr('data-area');
layer.open({
type: 2,
title: title,
area: ['450px','420px'],
shadeClose: true, //点击遮罩关闭
content: url
});
});
})
</script>

View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{$site_name} 用户登录</title>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="applicable-device" content="pc,mobile">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<script src="/static/js/layui/layui.js"></script>
<link rel="stylesheet" type="text/css" href="/static/js/layui/css/font-awesome.css" />
<link rel="stylesheet" type="text/css" href="/static/js/layui/css/layui.css" />
<link rel="stylesheet" type="text/css" href="/static/css/login.css" />
<script src="/static/js/center.js?v={:release()}"></script>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/>
</head>
<body>
<div id="ajaxLogin" >
<div class="other-link">
<span class="other">第三方账号登录:</span>
<span>
<a href="{:url('/third/login',['type'=>'qq'])}&ref={$referer}" class="qq" target="_top"></a>
<a href="{:url('/third/login',['type'=>'weixin'])}&ref={$referer}" class="wx" target="_top"></a>
<a href="{:url('/third/login',['type'=>'weibo'])}&ref={$referer}" class="sina" target="_top"></a>
</span>
</div>
<form class="layui-form" action="/index/user/login" method="post" style="height: auto">
<input type="hidden" name="__token__" value="{:token()}"/>
<div class="layui-form-item">
<div class="item">
<label class="left-icon layui-icon layui-icon-username"></label>
<input type="text" id="nickname" name="nickname" lay-verify="required" placeholder="{:__('请输入账号或邮箱')}" class="layui-input" value="test@swiftadmin.net">
</div>
</div>
<div class="layui-form-item">
<div class="item">
<label class="left-icon layui-icon layui-icon-password"></label>
<input type="password" id="pwd" name="pwd" lay-verify="required" placeholder="{:__('密码')}" class="layui-input" value="admin888">
</div>
</div>
<div class="layui-form-item" style="margin-bottom: 20px;">
<div class="fl">
<input type="checkbox" name="remember" lay-skin="primary" title="{:__('记住密码')}" checked>
</div>
<a lay-open data-title="找回密码" data-area="500px,320px" data-object="top" data-url="/index/user/forgot"
class="forgot-link fr" style="margin-top: 7px;">{:__('忘记密码?')}</a>
</div>
<div class="layui-form-item">
<input type="submit" value="{:__('立即登录')}" lay-submit="" lay-filter="submitIframe" data-reload="top"
class="layui-btn layui-btn-login layui-btn-fluid layui-btn-normal">
</div>
</form>
</div>
</body>
</html>

View File

@@ -74,7 +74,7 @@
<div class="contract-title">手机</div> <div class="contract-title">手机</div>
<div class="contract-detail">+86 {$user.mobile|default='未绑定'} <div class="contract-detail">+86 {$user.mobile|default='未绑定'}
<i class="layui-icon fa-edit" title="编辑" lay-open data-title="修改手机" <i class="layui-icon fa-edit" title="编辑" lay-open data-title="修改手机"
data-url="/index/user/mobile" data-area="500px,300px"></i> data-url="/index/user/changeMobile" data-area="500px,300px"></i>
</div> </div>
</div> </div>
@@ -87,7 +87,7 @@
<div class="contract-title">办公室邮箱</div> <div class="contract-title">办公室邮箱</div>
<div class="contract-detail">{$user.email|default='member@domain.com'} <div class="contract-detail">{$user.email|default='member@domain.com'}
<i class="layui-icon fa-edit" title="编辑" lay-open data-title="修改邮箱" <i class="layui-icon fa-edit" title="编辑" lay-open data-title="修改邮箱"
data-url="/index/user/email" data-area="500px,300px"></i> data-url="/index/user/changeEmail" data-area="500px,300px"></i>
</div> </div>
</div> </div>
<div class="layui-col-md3"> <div class="layui-col-md3">
@@ -242,7 +242,7 @@
<li> <li>
<a title="{$vo.nickname}" href="#" target="_blank"> <a title="{$vo.nickname}" href="#" target="_blank">
<img class="media-object" src="{$vo.avatar}"></a> <img class="media-object" src="{$vo.avatar}"></a>
<a class="truncate" href="{$vo.url}" target="_blank">{$vo.nickname}</a> <a class="truncate" href="{$vo.url|default='#'}" target="_blank">{$vo.nickname}</a>
</li> </li>
</volist> </volist>
</ul> </ul>

View File

@@ -1,79 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>修改密码</title>
<include file="user:include"/>
</head>
<body>
<div class="layui-card-body">
<form action="/index/user/changePwd" class="layui-form layui-form-fixed">
<input type="text" name="nickname" value="{$user.nickname}" hidden="">
<div class="layui-form-item">
<label class="layui-form-label">原密码</label>
<div class="layui-input-block">
<input type="password" id="oldpwd" name="oldpwd" class="layui-input" >
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">新密码</label>
<div class="layui-input-block">
<input type="password" id="pwd" name="pwd" class="layui-input" >
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">确认密码</label>
<div class="layui-input-block">
<input type="password" id="repwd" name="repwd" class="layui-input" >
</div>
</div>
<div class="layui-form-item" style="margin-top: 22px;text-align: center;">
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
<button type="submit" class="layui-btn layui-btn-normal" lay-submit="" lay-filter="submit">立即提交</button>
</div>
</form>
</div>
<script>
layui.use(['jquery','form'],function(){
let $ = layui.jquery;
let form = layui.form;
//监听提交
form.on('submit(submit)', function(data){
if($("#pwd").val().length < 6){
layer.tips('请至少输入6个字符作为密码',"#pwd",{'tips':3});
return false;
}
if ($("#pwd").val() !== $("#repwd").val()) {
layer.tips('两次输入的密码不一样!',"#repwd",{'tips':3});
return false;
}
$.ajax({
url: $(this).attr('action'),
type: 'POST',
dataType: 'json',
timeout: 6000,
data: data.field,
success: function(res){
if (res.code === 200) {
top.layer.msg(res.msg);
}
else {
top.layer.msg(res.msg,'error');
}
}
});
return false;
});
})
</script>
</body>
</html>

View File

@@ -1,32 +0,0 @@
<layout name="layout:layout"/>
<!-- 内容主体区域 -->
<div id="content">
<div class="layui-fluid ">
<form class="layui-form layui-form-fixed" action="/index/user/email">
<div class="layui-form-item">
<label class="layui-form-label">{:__('邮箱地址')}</label>
<div class="layui-input-inline" style="width: 265px">
<input name="email" placeholder="{:__('请输入邮箱地址')}" type="text" class="layui-input email"
autocomplete="off" lay-verify="required|email"/>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">{:__('验证码')}</label>
<div class="layui-input-inline">
<input name="captcha" placeholder="{:__('请输入验证码')}" type="text" class="layui-input"
autocomplete="off" lay-verify="required" maxlength="10"/>
</div>
<button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-ajax data-url="/index/user/email"
data-object="email:email,event:event">{:__('获取')}
</button>
</div>
<input type="text" hidden name="event" class="event" value="change">
<div class="layui-footer layui-form-item layui-center">
<button class="layui-btn layui-btn-primary" type="button" sa-event="closeDialog">{:__('取消')}</button>
<button class="layui-btn layui-btn-normal" data-reload="parent" lay-filter="submitIframe" lay-submit>{:__('提交')}</button>
</div>
</form>
</div>
</div>

View File

@@ -1,86 +1,89 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-CN"> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>SwiftAdmin 用户登录</title> <title>{$site_name} 找回密码</title>
<include file="public:header"/> <meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="applicable-device" content="pc,mobile">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<script src="/static/js/layui/layui.js"></script>
<link rel="stylesheet" type="text/css" href="/static/js/layui/css/font-awesome.css" />
<link rel="stylesheet" type="text/css" href="/static/js/layui/css/layui.css" />
<link rel="stylesheet" type="text/css" href="/static/css/login.css" />
<script src="/static/js/center.js?v={:release()}"></script>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/>
</head> </head>
<body> <body>
<style>
.layui-form-checked[lay-skin="primary"] i {
border-color: #1890ff !important;
background-color: #1890ff;
color: #fff;
}
.layui-form-item {
margin-bottom: 25px;
}
.red {
color: red;
}
.layui-input:hover {
border: 1px solid #1890ff!important;
}
</style>
<div class="layui-fluid"> <div class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/index/user/forgot" method="post" > <form class="layui-form layui-form-fixed" action="/index/user/forgot" method="post">
<input type="hidden" name="__token__" value="{:token()}"/>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> {:__('手机/邮箱')}</label> <label class="layui-form-label"><span class="red">*</span> {:__('手机/邮箱')}</label>
<div class="layui-input-inline" style="width: 306px"> <div class="layui-input-inline" style="width: 306px">
<input id="string" name="mobile" placeholder="{:__('请输入邮箱或手机号')}" type="text" class="layui-input string" <input id="name" name="name" placeholder="{:__('请输入邮箱或手机号')}" type="text" class="layui-input"
autocomplete="off" lay-verify="required"/> lay-verify="required"/>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> {:__('验证码')}</label> <label class="layui-form-label"><span class="red">*</span> {:__('验证码')}</label>
<div class="layui-input-inline"> <div class="layui-input-inline" style="width: 226px">
<input name="captcha" placeholder="{:__('请输入验证码')}" type="text" class="layui-input" autocomplete="off" lay-verify="required" maxlength="10"/> <input name="captcha" placeholder="{:__('请输入验证码')}" type="text" class="layui-input"
autocomplete="off" lay-verify="required" maxlength="10"/>
</div> </div>
<button id="send" class="layui-btn layui-btn-normal" type="button" <button id="uCode" class="layui-btn layui-btn-normal" type="button">{:__('获取')}
lay-ajax data-url="/ajax/smsSend" data-object="mobile:string,event:event">{:__('获取')}
</button> </button>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> {:__('新密码')}</label> <label class="layui-form-label"><span class="red">*</span> {:__('新密码')}</label>
<div class="layui-input-inline" style="width: 306px"> <div class="layui-input-inline" style="width: 306px">
<input type="password" id="pwd" name="pwd" lay-verify="required" placeholder="{:__('密码')}" class="layui-input" > <input type="password" id="pwd" name="pwd" lay-verify="required" placeholder="{:__('密码')}"
class="layui-input">
</div> </div>
</div> </div>
<input type="text" hidden name="event" class="event" value="forgot">
<div class="layui-footer layui-form-item layui-center"> <div class="layui-footer layui-form-item layui-center">
<button class="layui-btn layui-btn-primary" type="button" sa-event="closeDialog">{:__('取消')}</button> <button class="layui-btn layui-btn-primary" type="button" sa-event="closeDialog">{:__('取消')}</button>
<button class="layui-btn layui-btn-normal" lay-filter="submitIframe" lay-submit>{:__('提交')}</button> <button class="layui-btn layui-btn-normal" lay-filter="submitIframe" lay-submit>{:__('提交')}</button>
</div> </div>
</form> </form>
</div> </div>
</body> </body>
<script> <script>
layui.use('jquery', function() { layui.use('jquery', function () {
let $ = layui.jquery; let $ = layui.jquery;
$('#uCode').click(function (e) {
$('#string').on('keyup',function (e) { let name = $('#name').val();
if (name === '') {
let val = $(this).val(); layer.msg('请输入邮箱或手机号', 'info');
let string = $('#string'); return false;
let send = $('#send');
let regx = /^[1][3,4,5,6.7,8,9][0-9]{9}$/
if (regx.test(val)) {
string.attr('name','mobile');
send.attr('data-object','mobile:string,event:event');
send.attr('data-url','/ajax/smsSend');
} else {
string.attr('name','email');
send.attr('data-object','email:string,event:event');
send.attr('data-url','/ajax/emailsend');
} }
}) let regUrl = '/api/ajax/smsSend';
let data = { mobile: name };
let regxEmail = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/;
if (regxEmail.test(name)) {
regUrl = '/api/ajax/emailSend';
data = { email: name };
}
data.event = 'forgot';
$(this).attr('disabled', true);
$.ajax({
url: regUrl,
type: 'post',
data: data,
dataType: 'json',
success: function (res) {
if (res.code === 200) {
layer.msg(res.msg, 'success');
} else {
layer.msg(res.msg, 'error');
}
}
});
setTimeout(function () {
$('#uCode').attr('disabled', false);
}, 10000);
});
}) })
</script> </script>
</html> </html>

View File

@@ -1,40 +0,0 @@
<div class="layui-header">
<div class="layui-logo layui-hide-xs layui-bg-black">
<span class="logo-text">SAPHP <span style="font-size: medium ">用户后台</span></span>
</div>
<!-- 头部区域可配合layui 已有的水平导航) -->
<ul class="layui-nav layui-layout-left">
<!-- 移动端显示 -->
<li class="layui-nav-item layui-show-xs-inline-block" lay-header-event="menuLeft">
<i class="layui-icon layui-icon-spread-left"></i>
</li>
</ul>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item" lay-unselect="">
<a href="{$site_http}" lay-text="主页">
<i class="layui-icon layui-icon-website"></i>
</a>
</li>
<li class="layui-nav-item" lay-unselect="">
<a href="javascript:;" sa-event="message" lay-text="消息中心" data-url="/admin.php/system.admin/message">
<i class="layui-icon fa-bell-o"></i>
<!-- 如果有新消息,则显示小圆点 -->
<span class="layui-badge-dot"></span>
</a>
</li>
<li class="layui-nav-item layui-hide layui-show-md-inline-block">
<a href="javascript:;"><img src="{$user.avatar}" alt="{$user.nickname}" class="layui-nav-img">{$user.nickname}</a>
<dl class="layui-nav-child">
<dd><a lay-open lay-title="修改密码" lay-url="/index/user/changepwd" lay-area="470px,330px" href="javascript:;">修改密码</a>
</dd>
<dd><a href="/index/user/logout" >退出</a></dd>
</dl>
</li>
<li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
<a href="javascript:;"><i class="layui-icon layui-icon-more-vertical"></i></a>
</li>
</ul>
</div>

View File

@@ -9,7 +9,7 @@
<link href="/static/js/layui/css/font-awesome.css?v={:config('app.version')}" rel="stylesheet" type="text/css" /> <link href="/static/js/layui/css/font-awesome.css?v={:config('app.version')}" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="/static/css/center.css?v={:release()}"> <link rel="stylesheet" href="/static/css/center.css?v={:release()}">
<script src="/static/js/layui/layui.js"></script> <script src="/static/js/layui/layui.js"></script>
<script src="/static/js/common.js?v={:release()}"></script> <script src="/static/js/center.js?v={:release()}"></script>
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script> <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script> <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>

View File

@@ -1,62 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SwiftAdmin 用户登录</title>
<include file="public:header"/>
</head>
<body>
<style>
.layui-form-checked[lay-skin="primary"] i {
border-color: #1890ff !important;
background-color: #1890ff;
color: #fff;
}
.forget-link {
margin-top: 7px;
color: #1890ff;
}
</style>
<div id="userLogin" class="layui-fluid">
<div class="login-link">
<span class="other">第三方账号登录:</span>
<span>
<a href="{:url('/third/login',['type'=>'qq'])}&ref={$referer}" class="qq" target="_top"></a>
<a href="{:url('/third/login',['type'=>'weixin'])}&ref={$referer}" class="wx" target="_top"></a>
<a href="{:url('/third/login',['type'=>'weibo'])}&ref={$referer}" class="sina" target="_top"></a>
</span>
</div>
<form class="layui-form" action="/index/user/login" method="post" style="height: auto">
<input type="hidden" name="__token__" value="{:token()}"/>
<div class="layui-form-item">
<div class="item">
<label class="user-login-icon layui-icon layui-icon-username"></label>
<input type="text" id="nickname" name="nickname" lay-verify="required|email"
placeholder="{:__('请输入邮箱或手机号')}" class="layui-input" value="test@swiftadmin.net">
</div>
</div>
<div class="layui-form-item">
<div class="item">
<label class="user-login-icon layui-icon layui-icon-password"></label>
<input type="password" id="pwd" name="pwd" lay-verify="required" placeholder="{:__('密码')}"
class="layui-input" value="admin888">
</div>
</div>
<div class="layui-form-item" style="margin-bottom: 20px;">
<div class="fl">
<input type="checkbox" name="remember" lay-skin="primary" title="{:__('记住密码')}" checked>
</div>
<a lay-open data-title="找回密码" data-area="510px,360px" data-object="top" data-url="/index/user/forgot" class="forget-link fr" style="margin-top: 7px;">{:__('忘记密码?')}</a>
</div>
<div class="layui-form-item">
<input type="submit" value="{:__('立即登录')}" lay-submit="" lay-filter="submitIframe" data-reload="top"
class="layui-btn layui-btn-fluid layui-btn-normal">
</div>
</form>
</div>
</body>
</html>

View File

@@ -19,7 +19,7 @@
*/ */
var isTable = table.render({ var isTable = table.render({
elem: "#lay-tableList" elem: "#lay-tableList"
, url: "{:url('/user/login_log')}" , url: "{:url('/user/loginLog')}"
, page: true , page: true
, limit: 20 , limit: 20
, cols: [[ , cols: [[

View File

@@ -17,8 +17,8 @@
<button class="layui-btn layui-btn-normal layui-btn-sm layui-btn-post" data-status="all" >{:__('全部消息')}</button> <button class="layui-btn layui-btn-normal layui-btn-sm layui-btn-post" data-status="all" >{:__('全部消息')}</button>
<button class="layui-btn layui-btn-primary layui-btn-sm layui-btn-post" data-status="1">{:__('已读消息')}</button> <button class="layui-btn layui-btn-primary layui-btn-sm layui-btn-post" data-status="1">{:__('已读消息')}</button>
<button class="layui-btn layui-btn-primary layui-btn-sm layui-btn-post" data-status="0">{:__('未读消息')}</button> <button class="layui-btn layui-btn-primary layui-btn-sm layui-btn-post" data-status="0">{:__('未读消息')}</button>
<button class="layui-btn layui-btn-danger layui-btn-sm" lay-batch data-table="lay-tableList" data-url="/index/user/dermessage?type=del" >{:__('删除消息')}</button> <button class="layui-btn layui-btn-danger layui-btn-sm" lay-batch data-table="lay-tableList" data-url="/index/user/batchMessage?type=del" >{:__('删除消息')}</button>
<button class="layui-btn layui-btn-checked layui-btn-sm" lay-batch data-table="lay-tableList" data-url="/index/user/dermessage?type=read" >{:__('标记已读')}</button> <button class="layui-btn layui-btn-checked layui-btn-sm" lay-batch data-table="lay-tableList" data-url="/index/user/batchMessage?type=read" >{:__('标记已读')}</button>
</div> </div>
</div> </div>
</div> </div>
@@ -45,14 +45,14 @@
, page: true , page: true
, limit: 20 , limit: 20
, cols: [[ , cols: [[
{type: 'checkbox', width: 45}, {type: 'checkbox', width: 60},
{ {
field: 'title', align: 'left', templet: function (e) { field: 'title', align: 'left', templet: function (e) {
let title = '<a class="layui-table-text'; let title = '<a class="layui-table-text';
if (e.status === 0) { if (e.status === 0) {
title += ' layui-table-text-red'; title += ' layui-table-text-red';
} }
title += '" lay-open data-title="查看消息" data-url="/index/user/viewmessage?id=' + e.id + '" data-area="600px, 390px" >'; title += '" lay-open data-title="查看消息" data-url="/index/user/viewMessage?id=' + e.id + '" data-area="600px, 390px" >';
if (e.status === 0) { if (e.status === 0) {
title += '<i class="layui-icon fa-envelope"></i> '; title += '<i class="layui-icon fa-envelope"></i> ';
} else { } else {

View File

@@ -1,30 +0,0 @@
<layout name="layout:layout"/>
<!-- 内容主体区域 -->
<div id="content">
<div class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/index/user/mobile">
<div class="layui-form-item">
<label class="layui-form-label">{:__('手机号')}</label>
<div class="layui-input-inline" style="width: 265px">
<input name="mobile" placeholder="{:__('请输入号码')}" type="text" class="layui-input mobile"
autocomplete="off" lay-verify="required|phone"/>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">{:__('验证码')}</label>
<div class="layui-input-inline">
<input name="captcha" placeholder="{:__('请输入验证码')}" type="text" class="layui-input"
autocomplete="off" lay-verify="required" maxlength="10"/>
</div>
<button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-ajax data-url="/index/user/mobile"
data-object="mobile:mobile,event:event">{:__('获取')}
</button>
</div>
<input type="text" hidden name="event" class="event" value="change">
<div class="layui-footer layui-form-item layui-center">
<button class="layui-btn layui-btn-primary" type="button" sa-event="closeDialog">{:__('取消')}</button>
<button class="layui-btn layui-btn-normal" data-reload="parent" lay-filter="submitIframe" lay-submit>{:__('提交')}</button>
</div>
</form>
</div>
</div>

View File

@@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>消息管理 | {$site_name}</title>
<include file="user:include" />
</head>
<body>
<div class="layui-layout layui-layout-admin">
<include file="user:header" />
<div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<!-- 左侧导航区域可配合layui已有的垂直导航 -->
<include file="user:userNav" />
</div>
</div>
<div class="layui-body">
<!-- 内容主体区域 -->
<div id="content">
<h1>消息 示例页面</h1>
</div>
</div>
<include file="user:footer"/>
</div>
</body>
</html>
</body>
</html>

View File

@@ -2,85 +2,125 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>SwiftAdmin 用户注册</title> <title>{$site_name} 用户注册</title>
<include file="public:header"/> <meta http-equiv="Cache-Control" content="no-transform"/>
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<meta name="applicable-device" content="pc,mobile">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<script src="/static/js/layui/layui.js"></script>
<link rel="stylesheet" type="text/css" href="/static/js/layui/css/font-awesome.css"/>
<link rel="stylesheet" type="text/css" href="/static/js/layui/css/layui.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/login.css"/>
<script src="/static/js/center.js?v={:release()}"></script>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/>
</head> </head>
<body> <body>
<style> <div id="content" class="userLogin layui-fluid">
.layui-form-item { <div class="form-header">
margin-bottom: 15px; <i class="layui-icon fa-user-plus"></i>
} <h6>用户注册</h6>
</div>
<div class="formLogin active">
.red { <form class="layui-form mobileLogin" action="/index/user/register" method="post">
color: red; <div class="layui-form-item item-input">
} <input type="text" id="nickname" name="nickname" lay-verify="required" data-title="账号"
placeholder="{:__('请输入登录账号')}" class="inputStyle" value="">
.layui-input:hover {
border: 1px solid #1890ff !important;
}
</style>
<div id="register" class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/index/user/register" method="post">
<div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> 用户帐号</label>
<div class="layui-input-block">
<input type="text" name="nickname" placeholder="请输入帐号" class="layui-input">
</div> </div>
</div> <div class="layui-form-item item-input">
<div class="layui-form-item"> <input type="password" id="pwd" name="pwd" lay-verify="required" data-title="密码" maxlength="32"
<label class="layui-form-label"><span class="red">*</span> 密码</label> placeholder="{:__('请输入密码')}" class="inputStyle" value="">
<div class="layui-input-block"> <span class="fr-icon visiblePwd"><i class="layui-icon fa-eye-slash"></i></span>
<input type="password" id="pwd" name="pwd" placeholder="请输入密码" class="layui-input">
</div> </div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> 确认密码</label>
<div class="layui-input-block">
<input type="password" id="repwd" name="repwd" placeholder="请输入确认密码" class="layui-input">
</div>
</div>
<eq name="style" value="mobile"> <div class="layui-form-item item-input">
<input type="password" id="pwd2" lay-verify="required" data-title="密码" maxlength="32"
placeholder="{:__('请输入确认密码')}" class="inputStyle" value="">
<span class="fr-icon visiblePwd"><i class="layui-icon fa-eye-slash"></i></span>
</div>
<eq name="style" value="mobile">
<div class="layui-form-item item-input">
<input type="text" id="mobile" name="mobile" lay-verify="required" data-title="手机号"
placeholder="{:__('请输入手机号码')}" class="inputStyle mobile" value="">
</div>
<div class="layui-form-item item-input">
<input type="text" id="captcha" name="captcha" lay-verify="required" data-title="验证码"
maxlength="6"
placeholder="{:__('短信验证码')}" class="inputStyle" value="">
<input type="text" hidden name="event" class="event" value="login">
<span class="fr-icon getCaptcha" lay-ajax data-url="/api/ajax/smsSend"
data-object="mobile:mobile,event:event">获取验证码</span>
</div>
<else/>
<div class="layui-form-item item-input">
<input type="text" name="email" lay-verify="require|email" placeholder="请输入邮箱" class="inputStyle">
</div>
</eq>
<input type="hidden" id="token" name="__token__" value="{:token()}"/>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> 手机号</label> <div class="fl">
<div class="layui-input-block"> <input type="checkbox" name="remember" lay-skin="primary" title="{:__('记住密码')}" checked>
<input type="text" id="mobile" name="mobile" placeholder="请输入手机号" lay-verify="require|phone" </div>
class="layui-input mobile"> <div class="fr">
<a href="/index/user/login" class="forgot-link" style="margin-top: 7px;">{:__('返回登录')}</a>
</div> </div>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> 验证码</label> <button class="layui-btn layui-btn-login layui-btn-fluid layui-btn-normal"
<div class="layui-input-block"> lay-filter="submitIframe" data-reload="top" lay-submit>{:__('立即注册')}</button>
<input type="text" name="captcha" placeholder="{:__('验证码')}" class="layui-input captcha">
<div class="captcha fr">
<button id="captcha" type="button" class="layui-btn layui-btn-normal"
lay-ajax data-url="/ajax/smsSend" data-object="mobile:mobile,event:event"
>获取验证码
</button>
</div>
</div>
</div> </div>
<else/> <div class="agreement">
<div class="layui-form-item"> <span>未注册手机验证后自动登录,注册即代表同意<a href="#">《用户协议》</a>以及网站<a href="#">《隐私保护指引》</a></span>
<label class="layui-form-label"><span class="red">*</span> 邮箱地址</label>
<div class="layui-input-block">
<input type="text" name="email" lay-verify="require|email" placeholder="请输入邮箱" class="layui-input">
</div>
</div> </div>
</eq> </form>
</div>
<input type="text" hidden name="event" class="event" value="register"> <div class="loginLine"></div>
<div class="layui-footer layui-form-item layui-center"> <div class="appUserDown">
<button class="layui-btn layui-btn-primary" type="button" sa-event="closeDialog">{:__('取消')}</button> <div class="fr">
<button class="layui-btn layui-btn-normal" lay-filter="submitIframe" data-reload="top" lay-submit> <a class="link" href="#" target="_top">
{:__('立即注册')} <span>
</button> <i class="layui-icon fa-apple"></i>
<i class="layui-icon fa-android"></i>
<i class="layui-icon fa-windows"></i>
<span class="tit">下载 APP</span>
</span>
</a>
</div> </div>
</div>
</form>
</div> </div>
</body> </body>
<script>
layui.use(['jquery'], function (e) {
let $ = layui.jquery;
let layer = layui.layer;
$('#pwd, #pwd2').blur(function(e) {
let v1 = $('#pwd').val();
let v2 = $('#pwd2').val();
let v3 = v1 && v2 && (v1 !== v2);
v3 && layer.msg('密码不相同');
$('.layui-btn-login').attr('disabled', v3);
})
/* 显示隐藏密码 */
$('.visiblePwd').click(function() {
// 获取我同级上面得input元素
let elem = $(this).prev('input');
let type = $(elem).attr('type');
if (type === 'password') {
$(elem).attr('type','text');
$(this).find('i.layui-icon').addClass('fa-eye').removeClass('fa-eye-slash');
} else {
$(elem).attr('type','password');
$(this).find('i.layui-icon').addClass('fa-eye-slash').removeClass('fa-eye');
}
});
});
</script>
</html> </html>

View File

@@ -60,7 +60,7 @@
<span class="setting-intro">安全性高的密码可以使账户更安全;互联网账号存在被盗风险,建议您定期更换密码</span> <span class="setting-intro">安全性高的密码可以使账户更安全;互联网账号存在被盗风险,建议您定期更换密码</span>
</div> </div>
<div class="setting-operate fr"> <div class="setting-operate fr">
<a lay-open="" data-title="修改密码" data-url="/index/user/changepwd" data-area="470px,330px" href="javascript:;">修改</a> <a lay-open="" data-title="修改密码" data-url="/index/user/changePwd" data-area="470px,330px" href="javascript:;">修改</a>
</div> </div>
</div> </div>
@@ -84,7 +84,7 @@
</div> </div>
<div class="setting-operate fr"> <div class="setting-operate fr">
<a lay-open data-title="修改手机" data-url="/index/user/mobile" data-area="500px,300px">修改</a> <a lay-open data-title="修改手机" data-url="/index/user/changeMobile" data-area="500px,300px">修改</a>
</div> </div>
</div> </div>
@@ -108,7 +108,7 @@
</div> </div>
<div class="setting-operate fr"> <div class="setting-operate fr">
<a lay-open data-title="修改邮箱" data-url="/index/user/email" data-area="500px,300px">修改</a> <a lay-open data-title="修改邮箱" data-url="/index/user/changeEmail" data-area="500px,300px">修改</a>
</div> </div>
</div> </div>

View File

@@ -15,7 +15,7 @@
<dl class="layui-nav-child"> <dl class="layui-nav-child">
<dd><a lay-href="/index/user/profile">我的资料</a></dd> <dd><a lay-href="/index/user/profile">我的资料</a></dd>
<dd><a lay-href="/index/user/message">站内消息</a></dd> <dd><a lay-href="/index/user/message">站内消息</a></dd>
<dd><a lay-href="/index/user/login_log">登录日志</a></dd> <dd><a lay-href="/index/user/loginLog">登录日志</a></dd>
<dd><a lay-href="/index/user/certification">实名认证</a></dd> <dd><a lay-href="/index/user/certification">实名认证</a></dd>
<dd><a lay-href="/index/user/security">安全中心</a></dd> <dd><a lay-href="/index/user/security">安全中心</a></dd>
</dl> </dl>

View File

@@ -3,8 +3,7 @@ declare (strict_types=1);
namespace app\install\controller; namespace app\install\controller;
use app\common\library\DataBase; use support\Cache;
use think\facade\Cache;
use app\BaseController; use app\BaseController;
const SUCCESS = 'layui-icon-ok-circle'; const SUCCESS = 'layui-icon-ok-circle';
@@ -36,7 +35,7 @@ class Index extends BaseController
// 检测生产环境 // 检测生产环境
foreach ($this->checkEnv() as $key => $value) { foreach ($this->checkEnv() as $key => $value) {
if ($key == 'php' && (float)$value < 8.0.0) { if ($key == 'php' && (float)$value < 8.0) {
return $this->error('PHP版本过低'); return $this->error('PHP版本过低');
} }
} }

View File

@@ -11,7 +11,7 @@
Target Server Version : 50738 Target Server Version : 50738
File Encoding : 65001 File Encoding : 65001
Date: 25/04/2023 20:00:37 Date: 19/06/2023 14:24:08
*/ */
SET NAMES utf8mb4; SET NAMES utf8mb4;
@@ -49,15 +49,15 @@ CREATE TABLE `__PREFIX__admin` (
`delete_time` int(11) NULL DEFAULT NULL COMMENT '软删除标识', `delete_time` int(11) NULL DEFAULT NULL COMMENT '软删除标识',
PRIMARY KEY (`id`) USING BTREE, PRIMARY KEY (`id`) USING BTREE,
INDEX `id`(`id`) USING BTREE, INDEX `id`(`id`) USING BTREE,
UNIQUE INDEX `name`(`name`) USING BTREE, INDEX `name`(`name`) USING BTREE,
INDEX `pwd`(`pwd`) USING BTREE INDEX `pwd`(`pwd`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '后台管理员表' ROW_FORMAT = DYNAMIC; ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '后台管理员表' ROW_FORMAT = DYNAMIC;
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__admin -- Records of __PREFIX__admin
-- ---------------------------- -- ----------------------------
INSERT INTO `__PREFIX__admin` VALUES (1, '1', '2', '3', 'admin', '超级管理员', '13682bec405cf4b9002e6e8306312ce6', 1, 'a:3:{i:0;s:12:\"测试效果\";i:1;s:15:\"隔壁帅小伙\";i:2;s:9:\"技术宅\";}', '/upload/avatars/f8e34ec67a2a0233_100x100.jpg', '海阔天空,有容乃大', 'admin@swiftadmin.net', '0310', '15188888888', '高级管理人员', 391, '河北省邯郸市', '127.0.0.1', 1682411837, '3232254977', 1, NULL, 1596682835, 1682411837, NULL); INSERT INTO `__PREFIX__admin` VALUES (1, '1,2', '2', '3', 'admin', '超级管理员', '13682bec405cf4b9002e6e8306312ce6', 1, 'a:3:{i:0;s:12:\"测试效果\";i:1;s:15:\"隔壁帅小伙\";i:2;s:9:\"技术宅\";}', '/upload/avatars/f8e34ec67a2a0233_100x100.jpg', '海阔天空,有容乃大', 'admin@swiftadmin.net', '0310', '15188888888', '高级管理人员', 402, '河北省邯郸市', '127.0.0.1', 1687154816, '3232254977', 1, NULL, 1596682835, 1687154816, NULL);
INSERT INTO `__PREFIX__admin` VALUES (2, '2', '4', '5,6', 'ceshi', '测试用户', '13682bec405cf4b9002e6e8306312ce6', 1, 'a:3:{i:0;s:6:\"呵呵\";i:1;s:5:\"Think\";i:2;s:12:\"铁血柔肠\";}', '/upload/avatars/a0b923820dcc509a_100x100.png', 'PHP是全世界最好的语言', 'baimei@your.com', '0310', '15188888888', '我原本以为吕布已经天下无敌了,没想到还有比吕布勇猛的,这谁的部将?', 57, '河北省邯郸市廉颇大道110号指挥中心', '127.0.0.1', 1682221728, '3232254977', 1, '违规', 1609836672, 1682221728, NULL); INSERT INTO `__PREFIX__admin` VALUES (2, '2', '4', '5,4', 'ceshi', '测试用户', '13682bec405cf4b9002e6e8306312ce6', 1, 'a:3:{i:0;s:6:\"呵呵\";i:1;s:5:\"Think\";i:2;s:12:\"铁血柔肠\";}', '/upload/avatars/a0b923820dcc509a_100x100.png', 'PHP是全世界最好的语言', 'baimei@your.com', '0310', '15188888888', '我原本以为吕布已经天下无敌了,没想到还有比吕布勇猛的,这谁的部将?', 58, '河北省邯郸市廉颇大道110号指挥中心', '127.0.0.1', 1687154742, '3232254977', 1, '违规', 1609836672, 1687154742, NULL);
-- ---------------------------- -- ----------------------------
-- Table structure for __PREFIX__admin_access -- Table structure for __PREFIX__admin_access
@@ -75,8 +75,8 @@ CREATE TABLE `__PREFIX__admin_access` (
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__admin_access -- Records of __PREFIX__admin_access
-- ---------------------------- -- ----------------------------
INSERT INTO `__PREFIX__admin_access` VALUES (1, '1', '5,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,115,116', NULL); INSERT INTO `__PREFIX__admin_access` VALUES (1, '1,2', '5,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,115,116', NULL);
INSERT INTO `__PREFIX__admin_access` VALUES (2, '2', '5,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,115,116', NULL); INSERT INTO `__PREFIX__admin_access` VALUES (2, '2', '85,86,90,91,92,93,100,101,103,107,108,109,110,111,112', '');
-- ---------------------------- -- ----------------------------
-- Table structure for __PREFIX__admin_group -- Table structure for __PREFIX__admin_group
@@ -103,7 +103,7 @@ CREATE TABLE `__PREFIX__admin_group` (
-- Records of __PREFIX__admin_group -- Records of __PREFIX__admin_group
-- ---------------------------- -- ----------------------------
INSERT INTO `__PREFIX__admin_group` VALUES (1, 0, 1, '超级管理员', 'admin', 1, 1, '网站超级管理员组的', '100,107,108,109,110,111,112', NULL, 'layui-bg-blue', 1607832158, NULL); INSERT INTO `__PREFIX__admin_group` VALUES (1, 0, 1, '超级管理员', 'admin', 1, 1, '网站超级管理员组的', '100,107,108,109,110,111,112', NULL, 'layui-bg-blue', 1607832158, NULL);
INSERT INTO `__PREFIX__admin_group` VALUES (2, 1, 2, '网站编辑', 'editor', 1, 1, '负责公司软文的编写', '', NULL, 'layui-bg-cyan', 1607832158, NULL); INSERT INTO `__PREFIX__admin_group` VALUES (2, 1, 2, '网站编辑', 'editor', 1, 1, '负责公司软文的编写', '', '5', 'layui-bg-cyan', 1607832158, NULL);
-- ---------------------------- -- ----------------------------
-- Table structure for __PREFIX__admin_log -- Table structure for __PREFIX__admin_log
@@ -123,7 +123,7 @@ CREATE TABLE `__PREFIX__admin_log` (
`create_time` int(11) NULL DEFAULT NULL COMMENT '登录时间', `create_time` int(11) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE, PRIMARY KEY (`id`) USING BTREE,
INDEX `user_ip`(`user_ip`) USING BTREE INDEX `user_ip`(`user_ip`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户登录记录表' ROW_FORMAT = DYNAMIC; ) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户登录记录表' ROW_FORMAT = DYNAMIC;
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__admin_log -- Records of __PREFIX__admin_log
@@ -154,8 +154,8 @@ CREATE TABLE `__PREFIX__admin_notice` (
-- Records of __PREFIX__admin_notice -- Records of __PREFIX__admin_notice
-- ---------------------------- -- ----------------------------
INSERT INTO `__PREFIX__admin_notice` VALUES (1, 'notice', 1, '系统通知', '您有新的通知内容', 0, '10.10.11.22', 0, 0, 0, 1668249585, NULL); INSERT INTO `__PREFIX__admin_notice` VALUES (1, 'notice', 1, '系统通知', '您有新的通知内容', 0, '10.10.11.22', 0, 0, 0, 1668249585, NULL);
INSERT INTO `__PREFIX__admin_notice` VALUES (2, 'message', 1, '请注意查收短消息', '听说你又接了一个大项目', 2, '10.10.11.22', 0, 0, 1, 1668323353, NULL); INSERT INTO `__PREFIX__admin_notice` VALUES (2, 'message', 1, '请注意查收短消息', '听说你又接了一个大项目', 2, '10.10.11.22', 0, 0, 0, 1668323353, NULL);
INSERT INTO `__PREFIX__admin_notice` VALUES (3, 'todo', 1, '您有一项待办', '请完成项目的迭代工作与BUG修复', 0, '10.10.11.22', 0, 0, 0, 1668393025, NULL); INSERT INTO `__PREFIX__admin_notice` VALUES (3, 'todo', 1, '您有一项待办', '请完成项目的迭代工作与BUG修复', 0, '10.10.11.22', 0, 0, 3, 1668393025, NULL);
-- ---------------------------- -- ----------------------------
-- Table structure for __PREFIX__admin_rules -- Table structure for __PREFIX__admin_rules
@@ -181,7 +181,7 @@ CREATE TABLE `__PREFIX__admin_rules` (
PRIMARY KEY (`id`) USING BTREE, PRIMARY KEY (`id`) USING BTREE,
INDEX `id`(`id`) USING BTREE, INDEX `id`(`id`) USING BTREE,
INDEX `sort`(`sort`) USING BTREE INDEX `sort`(`sort`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 123 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单权限表' ROW_FORMAT = DYNAMIC; ) ENGINE = InnoDB AUTO_INCREMENT = 146 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单权限表' ROW_FORMAT = DYNAMIC;
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__admin_rules -- Records of __PREFIX__admin_rules
@@ -190,7 +190,7 @@ INSERT INTO `__PREFIX__admin_rules` VALUES (1, 0, 'Dashboard', 'Dashboard', 'das
INSERT INTO `__PREFIX__admin_rules` VALUES (2, 1, '控制台', '/index/console', 'index:console', 0, '', '', 2, '', 0, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (2, 1, '控制台', '/index/console', 'index:console', 0, '', '', 2, '', 0, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (3, 1, '分析页', '/index/analysis', 'index:analysis', 0, '', '', 3, '', 0, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (3, 1, '分析页', '/index/analysis', 'index:analysis', 0, '', '', 3, '', 0, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (4, 1, '监控页', '/index/monitor', 'index:monitor', 0, '', '', 4, '', 0, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (4, 1, '监控页', '/index/monitor', 'index:monitor', 0, '', '', 4, '', 0, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (5, 0, '系统管理', 'System', 'system', 0, '', '', 5, 'layui-icon-set-fill', 1, 1, 0, 1657367099, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (5, 0, '系统管理', 'System', 'system', 0, '', '', 5, 'layui-icon-set-fill', 1, 1, 0, 1687144413, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (6, 5, '基本设置', '/index/basecfg', 'index:basecfg', 0, '', '', 6, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (6, 5, '基本设置', '/index/basecfg', 'index:basecfg', 0, '', '', 6, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (7, 6, '修改配置', '/index/baseset', 'index:baseset', 2, '', '', 7, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (7, 6, '修改配置', '/index/baseset', 'index:baseset', 2, '', '', 7, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (8, 6, 'FTP接口', '/index/testftp', 'index:testftp', 2, '', '', 8, '', 0, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (8, 6, 'FTP接口', '/index/testftp', 'index:testftp', 2, '', '', 8, '', 0, 1, 0, 1657002180, 1657002180, NULL);
@@ -242,15 +242,15 @@ INSERT INTO `__PREFIX__admin_rules` VALUES (53, 50, '删除', '/system/LoginLog/
INSERT INTO `__PREFIX__admin_rules` VALUES (54, 50, '状态', '/system/LoginLog/status', 'system:LoginLog:status', 1, '', '', 54, NULL, 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (54, 50, '状态', '/system/LoginLog/status', 'system:LoginLog:status', 1, '', '', 54, NULL, 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (55, 0, '高级管理', 'Management', 'management', 0, '', '', 55, 'layui-icon-engine', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (55, 0, '高级管理', 'Management', 'management', 0, '', '', 55, 'layui-icon-engine', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (56, 55, '公司管理', '/system/Company/index', 'system:Company:index', 0, '', '', 56, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (56, 55, '公司管理', '/system/Company/index', 'system:Company:index', 0, '', '', 56, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (57, 56, '查看', '/system/Company/index', 'system:Company:index', 1, '', '', 57, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (57, 56, '查看', '/system/Company/index', 'system:Company:index', 1, '', '', 57, '', 1, 1, 0, 1686755836, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (58, 56, '添加', '/system/Company/add', 'system:Company:add', 1, '', '', 58, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (58, 56, '添加', '/system/Company/add', 'system:Company:add', 1, '', '', 58, '', 1, 1, 0, 1687147120, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (59, 56, '编辑', '/system/Company/edit', 'system:Company:edit', 1, '', '', 59, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (59, 56, '编辑', '/system/Company/edit', 'system:Company:edit', 1, '', '', 59, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (60, 56, '删除', '/system/Company/del', 'system:Company:del', 1, '', '', 60, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (60, 56, '删除', '/system/Company/del', 'system:Company:del', 1, '', '', 60, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (61, 56, '状态', '/system/Company/status', 'system:Company:status', 2, '', '', 61, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (61, 56, '状态', '/system/Company/status', 'system:Company:status', 2, '', '', 61, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (62, 55, '部门管理', '/system/Department/index', 'system:Department:index', 0, '', '', 62, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (62, 55, '部门管理', '/system/Department/index', 'system:Department:index', 0, '', '', 62, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (63, 62, '查看', '/system/Department/index', 'system:Department:index', 1, '', '', 63, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (63, 62, '查看', '/system/Department/index', 'system:Department:index', 1, '', '', 63, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (64, 62, '添加', '/system/Department/add', 'system:Department:add', 1, '', '', 64, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (64, 62, '添加', '/system/Department/add', 'system:Department:add', 1, '', '', 64, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (65, 62, '编辑', '/system/Department/edit', 'system:Department:edit', 1, '', '', 65, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (65, 62, '编辑', '/system/Department/edit', 'system:Department:edit', 1, '', '', 65, '', 1, 1, 0, 1686881933, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (66, 62, '删除', '/system/Department/del', 'system:Department:del', 1, '', '', 66, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (66, 62, '删除', '/system/Department/del', 'system:Department:del', 1, '', '', 66, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (67, 62, '状态', '/system/Department/status', 'system:Department:status', 2, '', '', 67, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (67, 62, '状态', '/system/Department/status', 'system:Department:status', 2, '', '', 67, '', 1, 1, 0, 1657002180, 1657002180, NULL);
INSERT INTO `__PREFIX__admin_rules` VALUES (68, 55, '岗位管理', '/system/Jobs/index', 'system:Jobs:index', 0, '', '', 68, '', 1, 1, 0, 1657002180, 1657002180, NULL); INSERT INTO `__PREFIX__admin_rules` VALUES (68, 55, '岗位管理', '/system/Jobs/index', 'system:Jobs:index', 0, '', '', 68, '', 1, 1, 0, 1657002180, 1657002180, NULL);
@@ -393,13 +393,13 @@ INSERT INTO `__PREFIX__config` VALUES (16, 'site_notice', 1, 'site', 'string', '
INSERT INTO `__PREFIX__config` VALUES (17, 'auth_key', 0, NULL, 'string', '38nfCIlkqancd', '授权码'); INSERT INTO `__PREFIX__config` VALUES (17, 'auth_key', 0, NULL, 'string', '38nfCIlkqancd', '授权码');
INSERT INTO `__PREFIX__config` VALUES (18, 'auth_code', 0, NULL, 'string', 'wMRkfKO4Lr37HTJQ', '加密KEY'); INSERT INTO `__PREFIX__config` VALUES (18, 'auth_code', 0, NULL, 'string', 'wMRkfKO4Lr37HTJQ', '加密KEY');
INSERT INTO `__PREFIX__config` VALUES (19, 'system_logs', 0, NULL, 'string', '0', '后台日志'); INSERT INTO `__PREFIX__config` VALUES (19, 'system_logs', 0, NULL, 'string', '0', '后台日志');
INSERT INTO `__PREFIX__config` VALUES (20, 'system_exception', 0, NULL, 'string', '0', '异常日志'); INSERT INTO `__PREFIX__config` VALUES (20, 'system_exception', 0, NULL, 'string', '1', '异常日志');
INSERT INTO `__PREFIX__config` VALUES (21, 'cache_status', 0, 'cache', 'string', '1', '缓存状态'); INSERT INTO `__PREFIX__config` VALUES (21, 'cache_status', 0, 'cache', 'string', '1', '缓存状态');
INSERT INTO `__PREFIX__config` VALUES (22, 'cache_type', 0, 'cache', 'string', 'redis', '缓存类型'); INSERT INTO `__PREFIX__config` VALUES (22, 'cache_type', 0, 'cache', 'string', 'redis', '缓存类型');
INSERT INTO `__PREFIX__config` VALUES (23, 'cache_time', 0, 'cache', 'string', '6000', '缓存时间'); INSERT INTO `__PREFIX__config` VALUES (23, 'cache_time', 0, 'cache', 'string', '6000', '缓存时间');
INSERT INTO `__PREFIX__config` VALUES (24, 'cache_host', 0, 'cache', 'string', '127.0.0.1', '服务器IP'); INSERT INTO `__PREFIX__config` VALUES (24, 'cache_host', 0, 'cache', 'string', '127.0.0.1', '服务器IP');
INSERT INTO `__PREFIX__config` VALUES (25, 'cache_port', 0, 'cache', 'string', '6379', '端口'); INSERT INTO `__PREFIX__config` VALUES (25, 'cache_port', 0, 'cache', 'string', '6379', '端口');
INSERT INTO `__PREFIX__config` VALUES (26, 'cache_select', 0, 'cache', 'string', '2', '缓存数据库'); INSERT INTO `__PREFIX__config` VALUES (26, 'cache_select', 0, 'cache', 'string', '4', '缓存数据库');
INSERT INTO `__PREFIX__config` VALUES (27, 'cache_user', 0, 'cache', 'string', '', '用户名'); INSERT INTO `__PREFIX__config` VALUES (27, 'cache_user', 0, 'cache', 'string', '', '用户名');
INSERT INTO `__PREFIX__config` VALUES (28, 'cache_pass', 0, 'cache', 'string', '', '密码'); INSERT INTO `__PREFIX__config` VALUES (28, 'cache_pass', 0, 'cache', 'string', '', '密码');
INSERT INTO `__PREFIX__config` VALUES (29, 'upload_path', 0, 'upload', 'string', 'upload', '上传路径'); INSERT INTO `__PREFIX__config` VALUES (29, 'upload_path', 0, 'upload', 'string', 'upload', '上传路径');
@@ -520,14 +520,14 @@ CREATE TABLE `__PREFIX__dictionary` (
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__dictionary -- Records of __PREFIX__dictionary
-- ---------------------------- -- ----------------------------
INSERT INTO `__PREFIX__dictionary` VALUES (1, 0, '内容属性', 'content', 1, '', 1, 1682217587, 1637738903, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (1, 0, '内容属性', 'content', 1, '', 1, 1687140686, 1637738903, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (2, 1, '头条', '1', 2, '', 1, 1669690446, 1638093403, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (2, 1, '头条', '1', 2, '', 1, 1669690446, 1638093403, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (3, 1, '推荐', '2', 3, '', 1, 1669690444, 1638093425, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (3, 1, '推荐', '2', 3, '', 1, 1669690444, 1638093425, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (4, 1, '幻灯', '3', 4, '', 1, 1669690440, 1638093430, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (4, 1, '幻灯', '3', 4, '', 1, 1669690440, 1638093430, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (5, 1, '滚动', '4', 5, '', 1, 1669690442, 1638093435, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (5, 1, '滚动', '4', 5, '', 1, 1669690442, 1638093435, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (6, 1, '图文', '5', 6, '', 1, 1638093456, 1638093456, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (6, 1, '图文', '5', 6, '', 1, 1638093456, 1638093456, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (7, 1, '跳转', '6', 7, '', 1, 1638093435, 1638093435, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (7, 1, '跳转', '6', 7, '', 1, 1638093435, 1638093435, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (8, 0, '友链类型', 'friendlink', 8, '', 1, 1682217595, 1638093456, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (8, 0, '友链类型', 'friendlink', 8, '', 1, 1687140689, 1638093456, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (9, 8, '资源', '1', 9, '', 1, 1638093430, 1638093430, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (9, 8, '资源', '1', 9, '', 1, 1638093430, 1638093430, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (10, 8, '社区', '2', 10, '', 1, 1638093435, 1638093435, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (10, 8, '社区', '2', 10, '', 1, 1638093435, 1638093435, NULL);
INSERT INTO `__PREFIX__dictionary` VALUES (11, 8, '合作伙伴', '3', 11, '', 1, 1659450310, 1638093456, NULL); INSERT INTO `__PREFIX__dictionary` VALUES (11, 8, '合作伙伴', '3', 11, '', 1, 1659450310, 1638093456, NULL);
@@ -588,7 +588,7 @@ CREATE TABLE `__PREFIX__system_log` (
INDEX `method`(`method`) USING BTREE, INDEX `method`(`method`) USING BTREE,
INDEX `create_time`(`create_time`) USING BTREE, INDEX `create_time`(`create_time`) USING BTREE,
INDEX `line`(`line`) USING BTREE INDEX `line`(`line`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统日志表' ROW_FORMAT = DYNAMIC; ) ENGINE = InnoDB AUTO_INCREMENT = 32 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统日志表' ROW_FORMAT = DYNAMIC;
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__system_log -- Records of __PREFIX__system_log
@@ -645,12 +645,12 @@ CREATE TABLE `__PREFIX__user` (
INDEX `create_time`(`create_time`) USING BTREE, INDEX `create_time`(`create_time`) USING BTREE,
INDEX `login_time`(`login_time`) USING BTREE, INDEX `login_time`(`login_time`) USING BTREE,
INDEX `invite_id`(`invite_id`) USING BTREE INDEX `invite_id`(`invite_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员管理' ROW_FORMAT = DYNAMIC; ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员管理' ROW_FORMAT = DYNAMIC;
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__user -- Records of __PREFIX__user
-- ---------------------------- -- ----------------------------
INSERT INTO `__PREFIX__user` VALUES (1, 1, '创始人', '513bd12b00b512d0b879962b777b5560', 'wdONQC', NULL, NULL, '/upload/avatars/a0b923820dcc509a_100x100.png', '这个人很懒,什么都没有留下~ ', 'test@swiftadmin.net', NULL, '林自图', 0, '2022-11-04 20:04:55', '15253325632533', '河北省邯郸市中华区人民东路023号', '', 0, 100, 1983.56, '你的幸运数字是?', 'aa', 1, 1, 10001, 'myKDalrGjpEVxWPQcXzwFu', NULL, NULL, NULL, NULL, NULL, NULL, 1, '127.0.0.1', 1682390408, 162, NULL, '1861775580', 1657332918, NULL); INSERT INTO `__PREFIX__user` VALUES (1, 1, '创始人', '513bd12b00b512d0b879962b777b5560', 'wdONQC', NULL, NULL, '/upload/avatars/a0b923820dcc509a_100x100.png', '这个人很懒,什么都没有留下~ ', 'test@swiftadmin.net', NULL, '林自图', 0, '2022-11-04 20:04:55', '15253325632533', '河北省邯郸市中华区人民东路023号', '', 0, 100, 1983.56, '你的幸运数字是?', '1', 1, 1, 10001, 'myKDalrGjpEVxWPQcXzwFu', NULL, NULL, NULL, NULL, NULL, NULL, 1, '127.0.0.1', 1686621464, 163, NULL, '1861775580', 1657332918, NULL);
-- ---------------------------- -- ----------------------------
-- Table structure for __PREFIX__user_group -- Table structure for __PREFIX__user_group
@@ -697,7 +697,7 @@ CREATE TABLE `__PREFIX__user_log` (
`create_time` int(11) NULL DEFAULT NULL COMMENT '登录时间', `create_time` int(11) NULL DEFAULT NULL COMMENT '登录时间',
PRIMARY KEY (`id`) USING BTREE, PRIMARY KEY (`id`) USING BTREE,
INDEX `user_ip`(`login_ip`) USING BTREE INDEX `user_ip`(`login_ip`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户记录表' ROW_FORMAT = DYNAMIC; ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户记录表' ROW_FORMAT = DYNAMIC;
-- ---------------------------- -- ----------------------------
-- Records of __PREFIX__user_log -- Records of __PREFIX__user_log
@@ -775,4 +775,4 @@ CREATE TABLE `__PREFIX__user_validate` (
-- Records of __PREFIX__user_validate -- Records of __PREFIX__user_validate
-- ---------------------------- -- ----------------------------
SET FOREIGN_KEY_CHECKS = 1; SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -61,8 +61,8 @@
<tbody> <tbody>
<tr> <tr>
<td>php</td> <td>php</td>
<td> >= 8.0.0 </td> <td> >= 8.0 </td>
<td <elt name="$checkEnv.php" value="8.0.0"> style="color:red;" </elt> >{$checkEnv.php}</td> <td <elt name="$checkEnv.php" value="8.0"> style="color:red;" </elt> >{$checkEnv.php}</td>
</tr> </tr>
<tr> <tr>
<td>mysqli</td> <td>mysqli</td>

View File

@@ -9,7 +9,7 @@ use Webman\RedisQueue\Consumer;
* @author meystack * @author meystack
* @date 2022-11-20 * @date 2022-11-20
*/ */
class Works implements Consumer class Worker implements Consumer
{ {
/** /**
* 消费队列名称 * 消费队列名称

View File

@@ -31,7 +31,6 @@
"workerman/webman-framework": "1.5.5", "workerman/webman-framework": "1.5.5",
"webman/think-orm": "^1.0", "webman/think-orm": "^1.0",
"webman/redis-queue": "^1.2", "webman/redis-queue": "^1.2",
"webman/think-cache": "^1.0",
"webman/console": "1.2.33", "webman/console": "1.2.33",
"webman/event": "^1.0", "webman/event": "^1.0",
"webman/captcha": "^1.0", "webman/captcha": "^1.0",
@@ -47,7 +46,9 @@
"php-di/php-di": "^6.4", "php-di/php-di": "^6.4",
"yansongda/pay": "~3.1.0", "yansongda/pay": "~3.1.0",
"overtrue/pinyin": "5.0", "overtrue/pinyin": "5.0",
"phpoffice/phpspreadsheet": "^1.28" "phpoffice/phpspreadsheet": "^1.28",
"illuminate/redis": "^9.52",
"symfony/cache": "^5.4"
}, },
"suggest": { "suggest": {
"ext-event": "For better performance. " "ext-event": "For better performance. "

932
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -38,7 +38,7 @@ return [
'dispatch_success' => app_path() . '/admin/view/public/jumptpl.html', 'dispatch_success' => app_path() . '/admin/view/public/jumptpl.html',
'exception_tpl' => app_path() . '/admin/view/error/500.html', 'exception_tpl' => app_path() . '/admin/view/error/500.html',
'error_message' => '页面错误!请稍后再试~', 'error_message' => '页面错误!请稍后再试~',
'version' => 'v1.1.6', 'version' => 'v1.1.7',
'cors_domain' => ['*', '127.0.0.1'], 'cors_domain' => ['*', '127.0.0.1'],
'api_url' => 'https://api.swiftadmin.net/', 'api_url' => 'https://api.swiftadmin.net/',
'show_error_msg' => false, 'show_error_msg' => false,

View File

@@ -12,9 +12,11 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License * @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ */
use app\common\bootstrap\RedisCache;
return [ return [
support\bootstrap\Session::class, support\bootstrap\Session::class,
support\bootstrap\LaravelDb::class, support\bootstrap\LaravelDb::class,
RedisCache::class, // 缓存服务器
Webman\ThinkOrm\ThinkOrm::class, Webman\ThinkOrm\ThinkOrm::class,
Webman\ThinkCache\ThinkCache::class,
]; ];

View File

@@ -1,3 +0,0 @@
<?php
return [
];

View File

@@ -1,4 +1,4 @@
<?php <?php
return [ return [
'enable' => true, 'enable' => false,
]; ];

View File

@@ -1,4 +1,4 @@
<?php <?php
return [ return [
'enable' => true, 'enable' => false,
]; ];

View File

@@ -14,9 +14,11 @@
return [ return [
'default' => [ 'default' => [
'host' => '127.0.0.1', 'host' => get_env('CACHE_HOSTNAME') ?? '127.0.0.1',
'password' => get_env('REDIS_PASSWORD'), 'password' => get_env('REDIS_PASSWORD'),
'port' => 6379, 'port' => get_env('CACHE_HOSTPORT') ?? 6379,
'database' => 1, 'database' => get_env('CACHE_SELECT') ?? 0,
'prefix' => 'redis_',
'expire' => 0,
], ],
]; ];

View File

@@ -14,16 +14,6 @@ use Webman\Route;
// 验证码路由 // 验证码路由
Route::any('/captcha', [app\BaseController::class, 'captcha']); Route::any('/captcha', [app\BaseController::class, 'captcha']);
/**
* 加载自定义路由 [插件路由]
*/
$defineRoute = require __DIR__ . '/defineRoute.php';
if ($defineRoute && is_array($defineRoute)) {
foreach ($defineRoute as $key => $value) {
Route::any($key, $value);
}
}
/** /**
* 默认管理员路由 * 默认管理员路由
* @var string $manage * @var string $manage
@@ -76,4 +66,30 @@ Route::fallback(function ($request) {
} }
return response(request_error(current($parseApp)), 404); return response(request_error(current($parseApp)), 404);
}); });
// 执行插件初始化
$pluginList = get_plugin_list();
foreach ($pluginList as $item) {
if (!$item['status']) {
continue;
}
foreach ($item['rewrite'] as $route => $value) {
$separator = explode('/', $value);
$method = end($separator);
array_pop($separator);
$filePath = implode('\\', $separator);
$controller = 'app\\index\\controller\\' . $filePath;
if (class_exists($controller) && method_exists($controller, $method)) {
try {
$classFullName = (new ReflectionClass($controller))->getName();
Route::any($route, [$classFullName, $method]);
} catch (\Throwable $e) {
var_dump('error: ' . $e->getMessage());
}
} else {
var_dump("\033[31m$controller or $method does not exist!\033[0m");
}
}
}

View File

@@ -1,3 +0,0 @@
<?php
return [
];

View File

@@ -1,24 +0,0 @@
<?php
return [
'default' => get_env('CACHE_DRIVER') ?: 'file',
'stores' => [
'file' => [
'type' => 'File',
// 缓存保存目录
'path' => runtime_path() . '/cache/',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
'redis' => [
'type' => 'redis',
'host' => get_env('CACHE_HOSTNAME') ?: '127.0.0.1',
'port' => get_env('CACHE_HOSTPORT') ?: 6379,
'select' => get_env('CACHE_SELECT') ?: 0,
'password' => get_env('CACHE_PASSWORD') ?: '',
'prefix' => 'redis_',
'expire' => 0,
],
],
];

View File

@@ -25,7 +25,9 @@ return [
// 断线重连 // 断线重连
'break_reconnect' => true, 'break_reconnect' => true,
// 关闭SQL监听日志 // 关闭SQL监听日志
'trigger_sql' => false, 'trigger_sql' => true,
// 开启字段缓存
'fields_cache' => false,
], ],
], ],
]; ];

View File

@@ -23,7 +23,7 @@ return [
'tpl_cache' => true, 'tpl_cache' => true,
'taglib_begin' => '<', 'taglib_begin' => '<',
'taglib_end' => '>', 'taglib_end' => '>',
'taglib_pre_load' => implode(',', array_merge(['app\common\taglib\SaLibs'],include __DIR__ . '/taglib.php')), 'taglib_pre_load' => 'app\common\taglib\SaLibs',
'tpl_replace_string' => [ 'tpl_replace_string' => [
'__STATIC__' => '/static/', '__STATIC__' => '/static/',
'__STATICJS__' => '/static/js/', '__STATICJS__' => '/static/js/',

View File

@@ -65,6 +65,11 @@ b.msg {
color: #000; color: #000;
} }
.layui-btn {
height: 33px!important;
line-height: 33px!important;
}
.layui-form-label { .layui-form-label {
padding: 6px 15px; padding: 6px 15px;
} }

View File

@@ -107,7 +107,7 @@ a {
#header #login { #header #login {
right: 20px; right: 20px;
left: unset; left: unset;
width: 150px; /*width: 150px;*/
} }
#header .nav-item a { #header .nav-item a {

View File

@@ -409,7 +409,7 @@ a {
} }
.layui-tree-iconClick .layui-icon { .layui-tree-iconClick .layui-icon {
font-size: 16px!important; font-size: 14px!important;
} }
.layui-tree-txt { .layui-tree-txt {
@@ -1312,10 +1312,6 @@ a {
right: 0 right: 0
} }
.layui-tree-subtraction .layui-form-checkbox[lay-skin=primary] i.layui-icon-ok:before {
content: "\e67e";
}
.swiftadmin-tabs-select.layui-nav { .swiftadmin-tabs-select.layui-nav {
position: absolute; position: absolute;
left: 0; left: 0;
@@ -2233,22 +2229,18 @@ a {
} }
.layui-form-onswitch { .layui-form-onswitch {
height: 16px;
line-height: 16px;
min-width: 28px;
margin-top: 6px;
background-color: #1890ff; background-color: #1890ff;
border: 1px solid #1890ff; border: 1px solid #1890ff;
} }
.layui-form-switch i { .layui-form-switch i {
top: 2px; top: 1px;
width: 12px; width: 12px;
height: 12px; height: 12px;
} }
.layui-form-onswitch i { .layui-form-onswitch i {
margin-left: -18px; margin-left: -16px;
} }
/* 拖拽上传 */ /* 拖拽上传 */
@@ -2437,6 +2429,24 @@ a {
.layui-table-view .layui-form-checkbox[lay-skin=primary] i { .layui-table-view .layui-form-checkbox[lay-skin=primary] i {
width: 16px; width: 16px;
height: 16px; height: 16px;
line-height: 15px;
}
.layui-form-checkbox[lay-skin="primary"] > .layui-icon-indeterminate {
border-color: #1890ff;
color: #fff;
background-color: #1890ff;
}
.layui-form-checkbox[lay-skin="primary"] > .layui-icon-indeterminate:before {
content: '';
display: inline-block;
vertical-align: middle;
position: relative;
width: 50%;
height: 1px;
margin: -1px auto 0;
background-color: #fff;
} }
.layui-laypage .layui-laypage-curr .layui-laypage-em { .layui-laypage .layui-laypage-curr .layui-laypage-em {

View File

@@ -12,7 +12,6 @@ layui.config({
iconPicker: 'iconPicker/iconPicker', iconPicker: 'iconPicker/iconPicker',
echarts: "echarts/echarts", echarts: "echarts/echarts",
xmselect: 'xmselect/xmselect', xmselect: 'xmselect/xmselect',
treetable: 'treetable/treetable',
tableSelect: 'tableSelect/tableSelect', tableSelect: 'tableSelect/tableSelect',
formDesign: 'formDesign/formDesign', formDesign: 'formDesign/formDesign',
soulTable: 'soulTable/soulTable', soulTable: 'soulTable/soulTable',

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-view{display:block;position:relative;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#fafafa;color:#333;font-family:Courier New;font-size:13px}.layui-code-title{position:relative;padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee;font-size:12px}.layui-code-title>.layui-code-about{position:absolute;right:10px;top:0;color:#b7b7b7}.layui-code-about>a{padding-left:10px}.layui-code-view>.layui-code-ol,.layui-code-view>.layui-code-ul{position:relative;overflow:auto}.layui-code-view>.layui-code-ol>li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view>.layui-code-ol>li:first-child,.layui-code-view>.layui-code-ul>li:first-child{padding-top:10px}.layui-code-view>.layui-code-ol>li:last-child,.layui-code-view>.layui-code-ul>li:last-child{padding-bottom:10px}.layui-code-view>.layui-code-ul>li{position:relative;line-height:20px;padding:0 10px;list-style-type:none;*list-style-type:none;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-dark{border:1px solid #0c0c0c;border-left-color:#3f3f3f;background-color:#0c0c0c;color:#c2be9e}.layui-code-dark>.layui-code-title{border-bottom:none}.layui-code-dark>.layui-code-ol>li,.layui-code-dark>.layui-code-ul>li{background-color:#3f3f3f;border-left:none}.layui-code-dark>.layui-code-ul>li{margin-left:6px}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none}

View File

@@ -1,16 +0,0 @@
/** 图标字体 **/
@font-face {font-family: 'laydate-icon';
src: url('./font/iconfont.eot');
src: url('./font/iconfont.eot#iefix') format('embedded-opentype'),
url('./font/iconfont.svg#iconfont') format('svg'),
url('./font/iconfont.woff') format('woff'),
url('./font/iconfont.ttf') format('truetype');
}
.laydate-icon{
font-family:"laydate-icon" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.layui-tags{border:1px solid #e3e7f1;height:29px;line-height:1.3;background-color:#fff;border-radius:2px;padding-left:10px}.layui-tags input{width:90px;font-family:helvetica;font-size:13px;border:1px solid transparent;background:0 0;color:#000;outline:0;height:28px;float:left}.layui-tags .tag-elem{float:left;height:25px;font-size:12px;box-sizing:border-box;margin-right:5px;padding:5px;margin-top:2px;-moz-border-radius:2px;-webkit-border-radius:2px;font-family:helvetica;color:#1890ff;background:#e6f7ff;border:1px solid #91d5ff}.layui-tags span.tag-elem i{font-family:Verdana;color:#0084ff;margin-left:5px;font-size:12px;cursor:pointer}#layui-tags-ajax li b,.layui-tags span.tag-elem i:hover{color:red}#layui-tags-ajax{text-align:left;cursor:default;background:#fff;border:1px solid rgba(0,0,0,.15);border-radius:2px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);-moz-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box;position:absolute;display:none;z-index:1029;max-height:254px;overflow:hidden;overflow-y:auto;width:138px;box-sizing:border-box}#layui-tags-ajax li{position:relative;line-height:20px;overflow:hidden;text-overflow:ellipsis;font-size:1em;color:#333;padding:5px 10px;cursor:pointer;white-space:nowrap}#layui-tags-ajax .layui-tag-this,#layui-tags-ajax li:hover{background:#f0f0f0}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 299 KiB

After

Width:  |  Height:  |  Size: 322 KiB

File diff suppressed because one or more lines are too long

View File

@@ -3,12 +3,13 @@
* by meystack to www.swiftadmin.net * by meystack to www.swiftadmin.net
* Apache2.0 Licensed * Apache2.0 Licensed
*/ */
layui.define(['laypage'], function (exports) { layui.define(['laypage','dropdown'], function (exports) {
"use strict"; "use strict";
var $ = layui.$ var $ = layui.$
, laypage = layui.laypage , laypage = layui.laypage
, dropdown = layui.dropdown
//模块名 //模块名
, MOD_NAME = 'fileManager' , MOD_NAME = 'fileManager'
, MOD_INDEX = 'layui_' + MOD_NAME + '_index' //模块索引名 , MOD_INDEX = 'layui_' + MOD_NAME + '_index' //模块索引名
@@ -238,7 +239,7 @@ layui.define(['laypage'], function (exports) {
}); });
} }
layui.dropdown.render({ dropdown.render({
elem: item elem: item
, trigger: 'contextmenu' , trigger: 'contextmenu'
, id: 'file' + index , id: 'file' + index

View File

@@ -5,6 +5,7 @@ layui.define(['i18n'], function (exports) {
var table = layui.table; var table = layui.table;
var i18n = layui.i18n; var i18n = layui.i18n;
var form = layui.form; var form = layui.form;
var notice = layui.notice;
i18n.render(layui.admin.getStorage('language') || 'zh-CN'); i18n.render(layui.admin.getStorage('language') || 'zh-CN');
var area = [$(window).width() > 800 ? '660px' : '85%', $(window).height() > 800 ? '680px' : '85%']; var area = [$(window).width() > 800 ? '660px' : '85%', $(window).height() > 800 ? '680px' : '85%'];
@@ -61,8 +62,9 @@ layui.define(['i18n'], function (exports) {
top.layui.admin.reloadLayout(); top.layui.admin.reloadLayout();
} else { } else {
notice.error({
layer.msg(res.msg, 'error'); message: res.msg,
})
// 登录超时 // 登录超时
if (res.code === -101) { if (res.code === -101) {
plugin.login(); plugin.login();
@@ -111,7 +113,9 @@ layui.define(['i18n'], function (exports) {
layer.closeAll(); layer.closeAll();
plugin.againClick(); plugin.againClick();
} else { } else {
layer.msg(res.msg, 'error'); notice.error({
message: res.msg,
})
} }
}, 'json') }, 'json')
@@ -185,7 +189,9 @@ layui.define(['i18n'], function (exports) {
delete window.plugins[name]; delete window.plugins[name];
$(elems).find('td:last').children('div').html(html); $(elems).find('td:last').children('div').html(html);
} else { } else {
layer.msg(i18n.prop(res.msg), 'error'); notice.error({
message: res.msg,
})
} }
layer.close(window.unIndex); layer.close(window.unIndex);
@@ -211,7 +217,7 @@ layui.define(['i18n'], function (exports) {
html += '<div class="layui-form-item">'; html += '<div class="layui-form-item">';
html += '<label class="layui-form-label">用户邮箱</label>'; html += '<label class="layui-form-label">用户邮箱</label>';
html += '<div class="layui-input-block">'; html += '<div class="layui-input-block">';
html += '<input type="text" name="nickname" style="width:330px;" lay-verify="required" placeholder="请输入邮箱或手机号" autocomplete="off" class="layui-input" >'; html += '<input type="text" name="nickname" style="width:330px;" lay-verify="required" placeholder="请输入邮箱或用户名" autocomplete="off" class="layui-input" >';
html += '</div></div>'; html += '</div></div>';
html += '<div class="layui-form-item"><label class="layui-form-label">密码</label>'; html += '<div class="layui-form-item"><label class="layui-form-label">密码</label>';
html += '<div class="layui-input-block">'; html += '<div class="layui-input-block">';
@@ -270,7 +276,7 @@ layui.define(['i18n'], function (exports) {
let name = plugin.getTableData(this)['name']; let name = plugin.getTableData(this)['name'];
layui.sessionData('api_install_index', { layui.sessionData('api_install_index', {
key: 'index', key: 'index',
value: plugin.getTableData(this)['LAY_TABLE_INDEX'], value: plugin.getTableData(this)['LAY_INDEX'],
}); });
plugin.request(name, null, plugin.getUrl('Plugin', 'install')); plugin.request(name, null, plugin.getUrl('Plugin', 'install'));
}) })
@@ -291,7 +297,9 @@ layui.define(['i18n'], function (exports) {
error: function (res) { error: function (res) {
$(obj.elem).prop('checked', !obj.elem.checked); $(obj.elem).prop('checked', !obj.elem.checked);
form.render('checkbox'); form.render('checkbox');
layer.msg(res.msg, 'error'); notice.error({
message: res.msg,
})
}, },
success: function (res) { success: function (res) {
layer.msg(res.msg); layer.msg(res.msg);
@@ -335,7 +343,7 @@ layui.define(['i18n'], function (exports) {
html += '</div></form> '; html += '</div></form> ';
layui.sessionData('api_install_index', { layui.sessionData('api_install_index', {
key: 'index', key: 'index',
value: plugin.getTableData(this)['LAY_TABLE_INDEX'], value: plugin.getTableData(this)['LAY_INDEX'],
}); });
layer.open({ layer.open({
type: 1, type: 1,
@@ -388,7 +396,9 @@ layui.define(['i18n'], function (exports) {
layer.msg(res.msg); layer.msg(res.msg);
layer.close(confirm); layer.close(confirm);
} else { } else {
layer.msg(res.msg, 'error'); notice.error({
message: res.msg,
})
} }
}) })
}); });

View File

@@ -1,22 +0,0 @@
.treeTable-empty {
width: 20px;
display: inline-block;
}
.treeTable-icon {
cursor: pointer;
}
table .treeTable-icon i.layui-icon {
font-size: 14px;
}
.treeTable-icon .layui-icon-right:before {
content: "\e602";
}
.treeTable-icon.open .layui-icon-right:before {
content: "\e61a";
background-color: transparent;
}

Some files were not shown because too many files have changed in this diff Show More