first commit

This commit is contained in:
Mr.Qin
2022-08-19 19:48:37 +08:00
commit afdd648b65
3275 changed files with 631084 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
<?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\index\controller;
use app\common\library\Email;
use app\common\library\Sms;
use app\common\model\system\User;
use app\HomeController;
use support\Response;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
/**
* Ajax控制器
* @ 异步调用
*/
class Ajax extends HomeController
{
/**
* 首页
*/
public function index(): Response
{
return \response('Hello SWIFT!', 200);
}
/**
* 发送短信
* @return mixed|void
* @throws DataNotFoundException
* @throws DbException
* @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(__('发送频繁'));
}
$userinfo = User::getByMobile($mobile);
if (in_array($event, ['register', 'changer']) && $userinfo) {
return $this->error('当前手机号已被占用');
} else if ($event == 'forgot' && !$userinfo) {
return $this->error('当前手机号未注册');
}
if ($sms->send($mobile, $event)) {
return $this->success("验证码发送成功!");
} else {
return $this->error($sms->getError());
}
}
}
/**
* 发送邮件
* @return mixed|void
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
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(__('发送频繁'));
}
$userinfo = User::getByEmail($email);
if (in_array($event, ['register', 'changer']) && $userinfo) {
return $this->error('当前邮箱已被注册');
} else if ($event == 'forgot' && !$userinfo) {
return $this->error('当前邮箱不存在');
}
if ($Ems->captcha($email, $event)->send()) {
return $this->success("验证码发送成功!");
} else {
return $this->error($Ems->getError());
}
}
}
}

View File

@@ -0,0 +1,30 @@
<?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\index\controller;
use app\HomeController;
use Psr\SimpleCache\InvalidArgumentException;
use support\Response;
class Index extends HomeController
{
/**
* 前端首页
* @return Response
* @throws InvalidArgumentException
*/
public function index(): \support\Response
{
return $this->view('index/index', ['name' => 'meystack']);
}
}

View File

@@ -0,0 +1,286 @@
<?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\index\controller;
use app\common\library\Auth;
use app\common\library\ResultCode;
use app\HomeController;
use app\common\model\system\User;
use app\common\model\system\UserThird;
use support\Response;
use system\Random;
/**
* 社会化登录
* @ QQ 微信 微博
*/
class Third extends HomeController
{
/**
* 类型
* @var string
*/
public $type = null;
/**
* 类型实例
* @var Object
*/
public $oauth = null;
/**
* @var array
*/
public $repeatLogin = [];
/**
* 初始化构造函数
*/
public function __construct()
{
parent::__construct();
}
/**
* 获取第三方登录配置
* @return mixed|string
* @throws \Exception
*/
private function oType()
{
$this->type = input('type');
$class = "\\system\\third\\" . $this->type;
if (!class_exists($class)) {
throw new \Exception('暂时还不支持该方式扩展');
}
return new $class;
}
/**
* 用户登录操作
*/
public function login(): \support\Response
{
try {
$this->oauth = $this->oType();
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
$referer = input('ref', request()->server('HTTP_REFERER', '/'));
request()->cookie('redirectUrl', $referer);
return $this->oauth->login();
}
/**
* 用户回调函数
* @return mixed|void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function callback()
{
try {
$this->oauth = $this->oType();
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
$userInfos = $this->oauth->getUserInfo();
if (!empty($userInfos) && !$this->auth->isLogin()) {
return $this->register($userInfos, $this->type);
} else if ($this->auth->isLogin()) { // 绑定用户
return $this->doBind($userInfos, $this->type);
}
}
/**
* 用户注册操作
* @param array $userInfos
* @param string|null $type
* @return mixed
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function register(array $userInfos = [], string $type = null)
{
$openid = $userInfos['openid'] ?? $userInfos['id'];
$nickname = $userInfos['userinfo']['name'] ?? $userInfos['userinfo']['nickname'];
$userInfo = UserThird::alias('th')
->view('user', '*', 'user.id=th.user_id')
->where(['openid' => $openid, 'type' => $type])
->find();
if (!empty($userInfo)) {
$array['id'] = $userInfo['id'];
$array['login_time'] = time();
$array['login_ip'] = request()->getRemoteIp();
$array['login_count'] = $userInfo['login_count'] + 1;
if (User::update($array)) {
$response = $this->auth->responseToken($userInfo);
$response->withBody(json_encode(ResultCode::LOGINSUCCESS))->redirect(request()->cookie('redirectUrl', '/'));
}
} else {
// 注册本地用户
$data['nickname'] = $nickname;
$data['avatar'] = $userInfos['userinfo']['avatar'];
if (User::getByNickname($nickname)) {
$data['nickname'] .= Random::alpha(3);
}
$data['group_id'] = 1;
$data['create_ip'] = request()->getRemoteIp();
$result = $this->auth->register($data);
// 封装第三方数据
if (!empty($result)) {
$userThird = [
'type' => $this->type,
'user_id' => $result['id'],
'openid' => $openid,
'nickname' => $nickname,
'access_token' => $userInfos['access_token'],
'refresh_token' => $userInfos['refresh_token'],
'expires_in' => $userInfos['expires_in'],
'login_time' => time(),
'expiretime' => time() + $userInfos['expires_in'],
];
}
// 注册第三方数据
if (isset($userThird) && is_array($userThird)) {
if (UserThird::create($userThird)) {
$response = $this->auth->responseToken($result);
$response->withBody(json_encode(ResultCode::LOGINSUCCESS))->redirect(request()->cookie('redirectUrl', '/'));
}
}
}
return $this->error('登录失败');
}
/**
* 用户绑定操作
* @return Response
*/
public function bind(): \support\Response
{
if (Auth::instance()->isLogin()) {
$buildQuery = [
'bind' => true,
'type' => input('type'),
'ref' => input('ref', request()->server('HTTP_REFERER', '/')),
];
return $this->redirect("/third/login?" . http_build_query($buildQuery));
}
return $this->error('请先登录');
}
/**
* 用户解除绑定
* @return mixed|void
* @throws \think\db\exception\DbException
*/
public function unbind(): \support\Response
{
try {
$this->oauth = $this->oType();
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
if ($this->auth->isLogin()) {
$result = $this->auth->userInfo;
if (!empty($result)) {
if (empty($result['email']) || empty($result['pwd'])) {
return $this->error('解除绑定需要设置邮箱和密码!');
}
$where['type'] = $this->type;
$where['user_id'] = request()->cookie('uid');
if (UserThird::where($where)->delete()) {
return $this->success('解除绑定成功!');
}
}
}
return $this->error();
}
/**
* 用户绑定操作实例
* @param array $userInfos
* @param string|null $type
* @return \support\Response|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function doBind(array $userInfos = [], string $type = null)
{
$openid = $userInfos['openid'] ?? $userInfos['id'];
$nickname = $userInfos['userinfo']['name'] ?? $userInfos['userinfo']['nickname'];
// 查询是否被注册
$where['openid'] = $openid;
$where['type'] = $this->type;
if (!UserThird::where($where)->find()) {
// 拼装数据
$third = [
'type' => $type,
'user_id' => request()->cookie('uid'),
'openid' => $openid,
'nickname' => $nickname,
'access_token' => $userInfos['access_token'],
'refresh_token' => $userInfos['refresh_token'],
'expires_in' => $userInfos['expires_in'],
'login_time' => time(),
'expiretime' => time() + $userInfos['expires_in'],
];
if (UserThird::create($third)) {
return $this->redirectUrl();
} else {
return $this->error('绑定异常');
}
}
return $this->error('当前用户已被其他账户绑定!');
}
/**
* 跳转URL
* @return void
*/
protected function redirectUrl(): \support\Response
{
$referer = request()->cookie('redirectUrl', '/');
if (preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) {
$referer = '/';
}
request()->cookie('redirectUrl', null,1);
return $this->redirect($referer);
}
}

View File

@@ -0,0 +1,477 @@
<?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> MIT License Code
// +----------------------------------------------------------------------
namespace app\index\controller;
use app\common\library\ResultCode;
use app\HomeController;
use app\common\library\Sms;
use app\common\library\Email;
use app\common\library\Upload;
use app\common\model\system\User as UserModel;
use support\Request;
use support\Response;
use system\Random;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
class User extends HomeController
{
/**
* 鉴权控制器
*/
public $needLogin = true;
/**
* 非登录鉴权方法
*/
public $noNeedAuth = ['login', 'register', 'forgot', 'check'];
public function __construct()
{
parent::__construct();
$this->model = new UserModel();
}
/**
* 退出登录
* @return Response
* @throws \Exception
*/
public function logout(): \support\Response
{
$this->auth->logout();
return $this->success('退出成功', url('index/index'));
}
/**
* 用户中心
* @return mixed
*/
public function index(): \support\Response
{
return view('/user/index');
}
/**
* 用户注册
* @return \support\Response
* @throws \Psr\SimpleCache\InvalidArgumentException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function register(): \support\Response
{
if (request()->isPost()) {
// 获取参数
$post = \request()->post();
$post = request_validate_rules($post, get_class($this->model));
if (!is_array($post)) {
return $this->error($post);
}
// 手机号注册
if (saenv('user_register') == '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 view('/user/register', [
'style' => saenv('user_register'),
]);
}
/**
* 用户登录
* @return \support\Response
*/
public function login(): \support\Response
{
if (request()->isPost()) {
$nickname = \request()->post('nickname');
$password = \request()->post('pwd');
$response = $this->auth->login($nickname, $password);
if (!$response) {
return $this->error($this->auth->getError());
}
$response->withBody(json_encode(ResultCode::LOGINSUCCESS));
return $response;
}
return view('/user/login', [
'referer' => request()->server('HTTP_REFERER', '/'),
]);
}
/**
* 找回密码
* @return \support\Response
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function forgot(): \support\Response
{
if (request()->isPost()) {
$email = input('email');
$mobile = input('mobile');
$event = input('event');
$captcha = input('captcha');
$pwd = input('pwd');
if (!empty($email)) {
if (!Email::instance()->check($email, $captcha, $event)) {
return $this->error(Email::instance()->getError());
}
} else {
if (!Sms::instance()->check($mobile, $captcha, $event)) {
return $this->error(Sms::instance()->getError());
}
}
$where = $email ? ['email' => $email] : ['mobile' => $mobile];
$userInfo = $this->model->where($where)->find();
if (!$userInfo) {
return $this->error('用户不存在');
}
try {
$salt = Random::alpha();
$pwd = encryptPwd($pwd, $salt);
$this->model->update(['id' => $userInfo['id'], 'pwd' => $pwd, 'salt' => $salt]);
} catch (\Exception $e) {
return $this->error('修改密码失败,请联系管理员');
}
return $this->success('修改密码成功!');
}
return view('/user/forgot');
}
/**
* 用户资料
* @param Request $request
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function profile(Request $request): \support\Response
{
if (request()->isPost()) {
$nickname = input('nickname');
$post = request_validate_rules(request()->Post(), get_class($this->model), 'nickname');
if (!is_array($post)) {
return $this->error($post);
}
if ($this->model->where('nickname', $nickname)->find()) {
return $this->error('当前昵称已被占用,请更换!');
}
if ($this->model->update(['id' => $request->userId, 'nickname' => $nickname])) {
return $this->success('修改昵称成功!', (string)url('/user/index'));
}
return $this->error();
}
return view('/user/profile');
}
/**
* 修改密码
* @param Request $request
* @return Response
*/
public function changePwd(Request $request): \support\Response
{
if (request()->isPost()) {
// 获取参数
$pwd = input('pwd');
$oldPwd = input('oldpwd');
$yPwd = encryptPwd($oldPwd, $request->userInfo->salt);
if ($yPwd != $request->userInfo->pwd) {
return $this->error('原密码输入错误!');
}
$salt = Random::alpha();
$pwd = encryptPwd($pwd, $salt);
$result = $this->model->update(['id' => $request->userId, 'pwd' => $pwd, 'salt' => $salt]);
if (!empty($result)) {
return $this->success('修改密码成功!');
}
return $this->error();
}
return view('/user/changepwd');
}
/**
* 申请appKey
* @return Response|void
*/
public function appid(Request $request)
{
if (request()->isPost()) {
$data = array();
$data['id'] = $request->userId;
$data['app_id'] = 10000 + $request->userId;
$data['app_secret'] = Random::alpha(22);
if ($this->model->update($data)) {
return $this->success();
}
return $this->error();
}
}
/**
* 修改邮箱
* @return \support\Response
* @throws \PHPMailer\PHPMailer\Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function email(Request $request): \support\Response
{
if (request()->isPost()) {
$email = input('email');
$event = input('event');
$captcha = input('captcha');
if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
return $this->error("您输入的邮箱格式不正确!");
}
if (UserModel::getByEmail($email)) {
return $this->error("您输入的邮箱已被占用!");
}
$Ems = Email::instance();
if (!empty($email) && !empty($captcha)) {
if ($Ems->check($email, $captcha, $event)) {
$this->model->update(['id' => $request->userId, 'email' => $email]);
return $this->success('修改邮箱成功!');
}
return $this->error($Ems->getError());
}
$last = $Ems->getLast($email);
if ($last && (time() - strtotime($last['create_time'])) < 60) {
return $this->error(__('发送频繁'));
}
if ($Ems->captcha($email, $event)->send()) {
return $this->success("邮件发送成功,请查收!");
} else {
return $this->error($Ems->getError());
}
}
return view('/user/email');
}
/**
* 修改手机号
* @param Request $request
* @return Response
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function mobile(Request $request): Response
{
if (request()->isPost()) {
$mobile = input('mobile');
$event = input('event');
$captcha = input('captcha');
if (!is_mobile($mobile)) {
return $this->error('手机号码不正确');
}
if ($mobile && UserModel::getByMobile($mobile)) {
return $this->error("您输入的手机号已被占用!");
}
$Sms = Sms::instance();
if (!empty($mobile) && !empty($captcha)) {
if ($Sms->check($mobile, $captcha, $event)) {
$this->model->update(['id' => $request->userId, 'mobile' => (int)$mobile]);
return $this->success('修改手机号成功!');
}
return $this->error($Sms->getError());
} else {
$data = $Sms->getLast($mobile);
if ($data && (time() - strtotime($data['create_time'])) < 60) {
return $this->error(__('发送频繁'));
}
if ($Sms->send($mobile, $event)) {
return $this->success("验证码发送成功");
} else {
return $this->error($Sms->getError());
}
}
}
return view('/user/mobile');
}
/**
* 设置密保
* @param Request $request
* @return Response
*/
public function protection(Request $request): \support\Response
{
$validate = [
'你家的宠物叫啥?',
'你的幸运数字是?',
'你不想上班的理由是?',
];
if (request()->isPost()) {
$question = input('question');
$answer = input('answer');
if (!$question || !$answer) {
return $this->error('设置失败');
}
if (!in_array($question, $validate)) {
$question = current($validate);
}
try {
$request->userInfo->question = $question;
$request->userInfo->answer = $answer;
$request->userInfo->save();
} catch (\Throwable $th) {
return $this->error();
}
return $this->success();
}
return view('/user/protection', [
'validate' => $validate
]);
}
/**
* 安全配置中心
* @param Request $request
* @return Response
*/
public function security(Request $request): Response
{
$maxProgress = 5;
$thisProgress = 1;
if ($request->userInfo->email) {
$thisProgress++;
}
if ($request->userInfo->mobile) {
$thisProgress++;
}
if ($request->userInfo->answer) {
$thisProgress++;
}
if ($request->userInfo->wechat) {
$thisProgress++;
}
// 计算比例
$progress = (($thisProgress / $maxProgress) * 100);
return view('/user/security', [
'progress' => $progress,
]);
}
/**
* 用户头像上传
* @param Request $request
* @return Response|void
* @throws \Exception
*/
public function avatar(Request $request)
{
if (request()->isPost()) {
$response = Upload::instance()->upload();
if (!$response) {
return $this->error(Upload::instance()->getError());
}
$request->userInfo->avatar = $response['url'] . '?' . Random::alpha(12);
if ($request->userInfo->save()) {
return json($response);
}
}
return json(ResultCode::SUCCESS);
}
/**
* 文件上传函数
* @return mixed
* @throws \Exception
*/
public function upload()
{
if (request()->isPost()) {
$file = Upload::instance()->upload();
if (!$file) {
return $this->error(Upload::instance()->getError());
}
return json($file);
}
return json(ResultCode::SUCCESS);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace app\index\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* Class StaticFile
* @package app\middleware
*/
class StaticFile implements MiddlewareInterface
{
public function process(Request $request, callable $next): Response
{
// Access to files beginning with. Is prohibited
if (strpos($request->path(), '/.') !== false) {
return response('<h1>403 forbidden</h1>', 403);
}
/** @var Response $response */
$response = $next($request);
// Add cross domain HTTP header
/*$response->withHeaders([
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Credentials' => 'true',
]);*/
return $response;
}
}

View File

@@ -0,0 +1,47 @@
<?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\index\middleware\system;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
use function redirect;
use function root_path;
/**
* 前台应用中间件
* Class AppInitialize
* @package app\index\middleware\system
* @author meystack <
*/
class IndexInitialize implements MiddlewareInterface
{
public function process(Request $request, callable $handler): Response
{
try {
if (saenv('site_status')) {
$content = file_get_contents(root_path('extend/conf/tpl') . 'close.tpl');
$content = str_replace('{text}',saenv('site_notice'),$content);
return \response($content, 503);
}
} catch (\Throwable $th) {
return \response('Web site has been closed', 503);
}
if (!is_file(root_path('extend/conf').'install.lock')) {
return redirect('/install/index');
}
return $handler($request);
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace app\index\middleware\system;
use app\common\library\Auth;
use support\View;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* 管理员权限
* @package app\admin\middleware\system
* @author meystack <
*/
class IndexPermissions implements MiddlewareInterface
{
/**
* 控制器登录鉴权
* @var bool
*/
public $needLogin = false;
/**
* 禁止登录重复
* @var array
*/
public $repeatLogin = ['login', 'register'];
/**
* 非鉴权方法
* @var array
*/
public $noNeedAuth = [];
/**
* 跳转URL地址
* @var string
*/
public $JumpUrl = '/user/index';
/**
* 校验权限
* @param Request $request
* @param callable $handler
* @return Response
*/
public function process(Request $request, callable $handler): Response
{
$app = request()->getApp();
$controller = request()->getController();
$action = request()->getAction();
// 控制器是否存在
$className = '\app' . $app . '\\controller\\' . $controller;
$className = str_replace('/', '\\', $className);
if (class_exists($className)) {
$refClass = new \ReflectionClass($className);
$property = $refClass->getDefaultProperties();
$this->needLogin = $property['needLogin'] ?? false;
$this->noNeedAuth = $property['noNeedAuth'] ?? [];
$this->repeatLogin = $property['repeatLogin'] ?? ['login', 'register'];
$this->JumpUrl = $property['JumpUrl'] ?: '/user/index';
}
// 是否验证登录器
$auth = Auth::instance();
if ($auth->isLogin()) {
$request->userId = $auth->userInfo['id'];
$request->userInfo = $auth->userInfo;
if (in_array($action, $this->repeatLogin)) {
return redirect($this->JumpUrl);
}
View::assign('user', $auth->userInfo);
} else {
if ($this->needLogin && !in_array($action, $this->noNeedAuth)) {
return redirect('/');
}
}
return $handler($request);
}
}

View File

@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SwiftAdmin 官方演示站</title>
<meta http-equiv="Cache-Control" content="no-transform " />
<include file="public:header" />
</head>
<body>
<div id="header">
<include file="public:nav"/>
</div>
<div id="content" >
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-md6">
<div class="layui-swift-box">
<h1>SWIFTADMIN 极速开发框架</h1>
<h1 style="font-size: 26px; font-weight: 300">基于高性能WM框架性能在TP5 10倍以上</h1>
<p>SwiftAdmin框架主张简单就是高效的原则在设计和运维上采用最精简最高效的做法去完成业务系统的需求并且基于ant Design的设计原则是一款优秀的前后台极速开发解决方案。相信你第一眼就有立刻想体验SwiftAdmin框架的冲动和热情</p>
<div class="layui-swift-desc">
<a href="#" onclick="javascript:layui.layer.msg('基于高性能WebMan');return false;" target="_blank">
<img src="https://badgen.net/badge/WebMan/1.4LTS/red" alt="WebMan">
</a>
<a href="#" onclick="javascript:layui.layer.msg('前端采用Layui经典规范');return false;" target="_blank">
<img src="https://badgen.net/badge/layui/2DEV/" alt="layui">
</a>
<a href="https://gitee.com/meystack/swiftadmin/stargazers" target="_blank">
<img src="https://gitee.com/meystack/swiftadmin/badge/star.svg?theme=gvp" alt="star">
</a>
<a class="fork" href="https://gitee.com/meystack/swiftadmin/members" target="_blank">
<img src="https://gitee.com/meystack/swiftadmin/badge/fork.svg?theme=gvp" alt="fork">
</a>
<a href="#" onclick="javascript:layui.layer.msg('请遵循Apache2.0开源协议精神');return false;" target="_blank">
<img src="https://badgen.net/badge/license/Apache/" alt="swiftadmin">
</a>
</div>
<div class="layui-swift-images">
<img src="/static/images/demo/1.png" >
<img src="/static/images/demo/2.png" >
<img src="/static/images/demo/3.png" >
<img class="hidden" src="/static/images/demo/4.png" >
</div>
</div>
</div>
<div class="layui-col-md6">
<img src="/static/images/hero-img.png" width="90%" height="500" alt="">
</div>
</div>
</div>
</div>
<include file="public:footer"/>
</body>
<script>
layui.use(['jquery','layer'],function(){
var $ = layui.jquery;
var layer = layui.layer;
$('.layui-swift-images img').click(function(){
layer.photos({
photos: '.layui-swift-images',
shadeClose: true,
closeBtn: 2,
anim: 10
})
})
})
</script>
</html>

View File

@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>控制台 | 用户中心</title>
<include file="user:include"/>
</head>
<body>
{__CONTENT__}
</body>
</html>

View File

@@ -0,0 +1,5 @@
<div id="footer" >
<div class="layui-footer" >
<div style="text-align: center;"> copyright © 2020 www.swiftadmin.net all rights reserved.</div>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" href="/static/js/layui/css/layui.css">
<link rel="stylesheet" href="/static/css/style.css?v={:release()}">
<script src="/static/js/layui/layui.js"></script>
<script src="/static/js/common.js?v={:release()}"></script>
<!--[if lt IE 9]>
<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>
<![endif]-->

View File

@@ -0,0 +1,21 @@
<div class="layui-container" >
<div class="layui-logo">
<a href="/"><img src="/static/system/images/logo.png" alt="logo" height="26">SWIFTADMIN</a>
</div>
<ul class="layui-nav">
<li class="layui-nav-item active"><a href="/" class="nav-link">主页</a></li>
<li class="layui-nav-item "><a href="#" onclick="layer.msg('感谢您使用SAPHP<br><br>您可以尽情在此框架上二次开发');" class="nav-link">关于</a></li>
<li class="layui-nav-item "><a href="https://www.swiftadmin.net/plugin/" class="nav-link">插件市场</a></li>
<li class="layui-nav-item layui-hide-xs"><a href="https://www.swiftadmin.net/agreement.html" class="nav-link">使用协议</a></li>
<li class="layui-nav-item layui-hide-xs"><a href="https://doc.swiftadmin.net/help/" class="nav-link">帮助文档</a></li>
<li class="layui-nav-item layui-hide-xs"><a href="https://ask.swiftadmin.net/" class="nav-link">社区中心</a></li>
<li class="layui-nav-item layui-hide-xs"><a href="https://qm.qq.com/cgi-bin/qm/qr?k=rUxEL3_DV8PnflvZiJamjED0dfHwpiMw&jump_from=webapi" target="_blank" class="nav-link">联系我们</a></li>
</ul>
<div class="layui-nav layui-hide-xs fr" id="login">
<notempty name="$user.id"> <li class="layui-nav-item"><a class="" href="/user/index" >会员中心</a></li> <else/>
<li class="layui-nav-item"><a href="javascript:;" lay-open data-title="用户注册" data-area="490px" data-url="/user/register" >注册</a></li>
<li class="layui-nav-item"><a href="javascript:;" lay-open data-title="用户登录" data-area="450px,420px" data-url="/user/login" >登录</a></li>
</notempty>
</div>
</div>

View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>修改密码</title>
<include file="user:include"/>
</head>
<body>
<div class="layui-card-body">
<form action="/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

@@ -0,0 +1,32 @@
<layout name="layout:layout"/>
<!-- 内容主体区域 -->
<div id="content">
<div class="layui-fluid ">
<form class="layui-form layui-form-fixed" action="/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" type="button" lay-ajax data-url="/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

@@ -0,0 +1,5 @@
<div class="layui-footer">
<!-- 底部固定区域 -->
copyright © <php>echo date('Y');</php> <a href="http://www.swiftadmin.net" target="_blank">SwiftAdmin</a> all rights reserved.
<span class="layui-layout-right" style="margin-right: 10px;">Build {:release()}</span>
</div>

View File

@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<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;
}
.layui-form-item {
margin-bottom: 25px;
}
.red {
color: red;
}
.layui-input:hover {
border: 1px solid #1890ff!important;
}
</style>
<div class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/user/forgot" method="post" >
<input type="hidden" name="__token__" value="{:token()}"/>
<div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> {:__('手机/邮箱')}</label>
<div class="layui-input-inline" style="width: 306px">
<input id="string" name="mobile" placeholder="{:__('请输入邮箱或手机号')}" type="text" class="layui-input string"
autocomplete="off" lay-verify="required"/>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> {:__('验证码')}</label>
<div class="layui-input-inline">
<input name="captcha" placeholder="{:__('请输入验证码')}" type="text" class="layui-input" autocomplete="off" lay-verify="required" maxlength="10"/>
</div>
<button id="send" class="layui-btn layui-btn-normal" type="button"
lay-ajax data-url="/ajax/smssend" data-object="mobile:string,event:event">{:__('获取')}
</button>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> {:__('新密码')}</label>
<div class="layui-input-inline" style="width: 306px">
<input type="password" id="pwd" name="pwd" lay-verify="required" placeholder="{:__('密码')}" class="layui-input" >
</div>
</div>
<input type="text" hidden name="event" class="event" value="forgot">
<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" lay-filter="submitIframe" lay-submit>{:__('提交')}</button>
</div>
</form>
</div>
</body>
<script>
layui.use('jquery', function() {
let $ = layui.jquery;
$('#string').on('keyup',function (e) {
let val = $(this).val();
let string = $('#string');
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');
}
})
})
</script>
</html>

View File

@@ -0,0 +1,40 @@
<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="/user/changepwd" lay-area="470px,330px" href="javascript:;">修改密码</a>
</dd>
<dd><a href="/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

@@ -0,0 +1,26 @@
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" href="/static/js/layui/css/layui.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()}">
<script src="/static/js/layui/layui.js"></script>
<script src="/static/js/common.js?v={:release()}"></script>
<!-- // 加载font-awesome图标 -->
<!--[if lt IE 9]>
<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>
<![endif]-->
<style>
/* 移动端 */
@media screen and (max-width: 768px) {
.layui-layout-admin .layui-layout-left,
.layui-layout-admin .layui-body,
.layui-layout-admin .layui-footer{left: 0;}
.layui-layout-admin .layui-side{width: 0px;}
}
</style>

View File

@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>控制台 | 用户中心</title>
<include file="user:include"/>
</head>
<body>
<div class="layui-layout layui-layout-admin">
<div class="layui-header">
<div class="layui-logo layui-side-body layui-hide-xs layui-bg-black">
<!-- // 可以增加LOGO-->
<img src="/static/system/images/logo.png" style="margin-bottom: 8px;margin-right: 10px" alt="logo" width="22" height="22" >
<span class="logo-text">用户中心</span>
</div>
<ul class="layui-nav layui-layout-left">
<li id="shrink" class="layui-nav-item layui-show-xs-inline-block" >
<i class="layui-icon layui-icon-shrink-right"></i>
</li>
</ul>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item" lay-unselect="">
<a href="/" title="主页">
<i class="layui-icon fa-home"></i>
</a>
</li>
<li class="layui-nav-item" >
<a href="javascript:;" id="notice">
<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 data-title="修改密码" data-url="/user/changepwd" data-area="470px,330px" href="javascript:;">修改密码</a>
</dd>
<dd><a href="/user/logout">退出</a></dd>
</dl>
</li>
<li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
<a href="javascript:;">
<i id="skin" class="layui-icon fa-moon-o"></i>
</a>
</li>
</ul>
</div>
<div class="layui-side layui-side-body layui-bg-black">
<div class="layui-side-scroll">
<!-- 左侧导航区域可配合layui已有的垂直导航 -->
<include file="user:userNav"/>
</div>
</div>
<div class="layui-body">
<!-- 内容主体区域 -->
<iframe id="iframe" src="/user/profile" frameborder="0" class="layui-layer-load" onload="this.className='';" ></iframe>
</div>
<include file="user:footer"/>
</div>
<script !src="">
layui.use(['jquery','upload'],function(){
let $ = layui.jquery;
let upload = layui.upload;
// 默认展现首个菜单栏
$('.layui-nav-tree .layui-nav-item').each(function (k,e) {
if ($(e).find('dl.layui-nav-child').length) {
$(e).addClass('layui-nav-itemed');
return false;
}
})
// 点击切换页面地址
$('body').on('click', '.layui-nav-tree a', function () {
let href = $(this).attr('lay-href');
if (href && href !== 'javascript:;') {
$('#iframe').attr('class','layui-layer-load');
$('#iframe').attr('src',href);
}
})
// 上传头像
upload.render({
elem: '.layui-user-avatar'
,url: '/user/avatars'
,method: 'post'
,accept: 'file'
,before: function(res) {
layer.msg('上传中');
},done: function(res, index, upload) {
// 上传成功
if (res.code == 200) {
layer.msg(res.msg);
$('#imgHead img').attr('src',res.url);
} else {
layer.msg(res.msg,'error');
}
}
})
let leftAnimate = function (action = true) {
if (action) {
$('.layui-side').animate({width: '0px'});
$('.layui-body,.layui-footer').animate({left: '5px'});
} else {
$('.layui-side').animate({width: '200px'});
$('.layui-body,.layui-footer').animate({left: '200px'});
}
}
$('#shrink i.layui-icon').click(function () {
let right = 'layui-icon-shrink-right',
left = 'layui-icon-spread-left';
if ($(this).hasClass(right)) {
leftAnimate();
$(this).removeClass(right).addClass(left);
}else {
leftAnimate(false);
$(this).removeClass(left).addClass(right);
}
})
// 初始化宽度
if ($(window).width() <= 992) {
$('#shrink i.layui-icon-shrink-right').removeClass('layui-icon-shrink-right').addClass('layui-icon-spread-left');
}
let skin = layui.data('skin').theme || undefined;
if (skin === 'layui-bg-white') {
$('.layui-side-body').removeClass('layui-bg-black').addClass(skin);
$('#skin').removeClass('fa-moon-o').addClass('fa-sun-o');
}
// 切换皮肤
$('#skin').on('click',function () {
let value = $(this).hasClass('fa-moon-o');
console.log(value)
if (value) {
$(this).removeClass('fa-moon-o').addClass('fa-sun-o');
$('.layui-side-body').removeClass('layui-bg-black').addClass('layui-bg-white');
layui.data('skin',{
key: 'theme',
value: 'layui-bg-white'
});
} else {
$(this).removeClass('fa-sun-o').addClass('fa-moon-o');
$('.layui-side-body').removeClass('layui-bg-white').addClass('layui-bg-black');
layui.data('skin',{
key: 'theme',
value: 'layui-bg-black'
});
}
})
})
</script>
</body>
</html>

View File

@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<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="/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="/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

@@ -0,0 +1,30 @@
<layout name="layout:layout"/>
<!-- 内容主体区域 -->
<div id="content">
<div class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/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" type="button" lay-ajax data-url="/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

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<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

@@ -0,0 +1,246 @@
<layout name="layout:layout"/>
<!-- 内容主体区域 -->
<div id="content">
<div class="layui-row layui-col-space20">
<div class="layui-col-md9">
<div class="layui-card">
<div class="layui-card-body goindex">
<div class="layui-col-md8">
<div class="tips"> Hi{$user.nickname} <span class="regular"> 下午好,今天是你加入的第 {$user.create_time|distance_day} 天~</span>
</div>
</div>
<div class="layui-col-md4">
</div>
</div>
</div>
<div id="profile" class="layui-card">
<div class="layui-card-body">
<h2>个人信息</h2>
<div class="clear">
<div class="layui-col-md3">
<div class="contract-title">手机</div>
<div class="contract-detail">+86 {$user.mobile}
<i class="layui-icon fa-edit" title="编辑" lay-open data-title="修改手机"
data-url="/user/mobile" data-area="500px,300px"></i>
</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">微信号</div>
<div class="contract-detail">{$user.wechat|default='--'}</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">办公室邮箱</div>
<div class="contract-detail">{$user.email}
<i class="layui-icon fa-edit" title="编辑" lay-open data-title="修改邮箱"
data-url="/user/email" data-area="500px,300px"></i>
</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">登录IP</div>
<div class="contract-detail">{$user.login_ip}</div>
</div>
</div>
<div class="clear">
<div class="layui-col-md3">
<div class="contract-title">登陆次数</div>
<div class="contract-detail">{$user.login_count}</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">用户组</div>
<div class="contract-detail">{$user.group.title}</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">积分</div>
<div class="contract-detail">{$user.score}</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">加入时间</div>
<div class="contract-detail">{$user.create_time}</div>
</div>
</div>
<div class="layui-col-md3">
<div class="contract-title">所在住址</div>
<div class="contract-detail">{$user.address}</div>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-header">我的帖子</div>
<div class="layui-card-body">
<table class="layui-table" lay-skin="nob">
<thead>
<tr>
<th>标题</th>
<th>回答数</th>
<th>发表时间</th>
<th>访问量</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<div class="layui-col-md3">
<div id="account" class="layui-card">
<div class="layui-card-body">
<div id="imgHead" class="layui-user-avatar">
<img src="{$user.avatar}" alt="{$user.nickname}" class="avatar">
</div>
<div class="nickname">
{$user.nickname}
<span class="edits">
<i class="layui-icon fa-edit" lay-open data-title="修改昵称" data-url="#nickname" data-area="398px,230px"></i>
</span>
</div>
<div class="intro">{$user.heart}</div>
<div id="thrid" class="layui-input-inline">
<if check_user_third(
'qq',$user['id']) >
<a lay-ajax data-url="{:url('/third/unbind',['type'=> 'qq'])}" title="点击解绑" type="button"
class="layui-btn layui-btn-sm"><i
class="layui-icon layui-icon-login-qq"></i></a>
<else/>
<a href="{:url('/third/bind?type=qq&ref=/user/index')}" title="点击绑定" type="button" target="_top"
class="layui-btn layui-btn-sm layui-bind-third"><i
class="layui-icon layui-icon-login-qq"></i></a>
</if>
<if check_user_third(
'weixin',$user['id']) >
<a lay-ajax data-url="{:url('/third/unbind?type=weixin')}" title="点击解绑" type="button"
class="layui-btn layui-btn-sm"><i
class="layui-icon layui-icon-login-wechat"></i></a>
<else/>
<a href="{:url('/third/bind')}?type=weixin&ref=/user/index" title="点击绑定" type="button"
target="_top"
class="layui-btn layui-btn-sm layui-bind-third"><i
class="layui-icon layui-icon-login-wechat"></i></a>
</if>
<if check_user_third(
'weibo',$user['id']) >
<a lay-ajax data-url="{:url('/third/unbind?type=weibo')}" title="点击解绑" type="button"
class="layui-btn layui-btn-sm"><i
class="layui-icon layui-icon-login-weibo"></i></a>
<else/>
<a href="{:url('/third/bind')}?type=wiebo&ref=/user/index" title="点击绑定" type="button"
target="_top"
class="layui-btn layui-btn-sm layui-bind-third"><i
class="layui-icon layui-icon-login-weibo"></i></a>
</if>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-header">APP KEY</div>
<div id="appkey" class="layui-card-body">
<notempty name="user.app_id">
<div class="layui-form">
<div class="layui-form-item">
<label class="layui-form-label">app_id</label>
<div class="layui-input-block">
<div class="layui-form-mid layui-word-aux">{$user.app_id}</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">app_secret</label>
<div class="layui-input-block">
<div class="layui-form-mid layui-word-aux">{$user.app_secret}</div>
</div>
</div>
<div class="layui-form-item">
<button type="submit" class="layui-btn layui-btn-normal" lay-ajax=""
data-url="/user/appid" data-reload="self">更换APPKEY
</button>
</div>
</div>
<else/>
<div class="layui-form">
<div class="layui-form-item">
<div class="layui-input-block">
<div class="layui-form-mid layui-word-aux">还没有生成appKey,请点击按钮生成!</div>
</div>
</div>
<div class="layui-form-item">
<button type="submit" class="layui-btn layui-btn-normal" lay-ajax=""
data-url="/user/appid" data-reload="self">生成APPKEY
</button>
</div>
</div>
</notempty>
</div>
</div>
</div>
</div>
</div>
<!-- // 修改用户昵称 -->
<script type="text/html" id="nickname">
<div class="layui-fluid layui-bg-white">
<form class="layui-form layui-form-fixed" action="/user/profile">
<div class="layui-form-item">
<label class="layui-form-label">{:__('用户昵称')}</label>
<div class="layui-input-inline">
<input name="nickname" autocomplete="off" placeholder="{:__('请输入昵称')}" type="text"
class="layui-input" lay-verify="required"/>
</div>
</div>
<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" lay-filter="submitPage" data-reload="parent" lay-submit>
{:__('提交')}
</button>
</div>
</form>
</div>
</script>
<script>
layui.use(['jquery', 'upload'], function () {
var $ = layui.jquery;
var upload = layui.upload;
// 上传头像
upload.render({
elem: '.layui-user-avatar'
, url: '/user/avatar?action=avatar' // 默认的上传地址
, method: 'post'
, accept: 'image'
, before: function (res) {
layer.msg('上传中');
}, done: function (res, index, upload) {
// 上传成功
if (res.code === 200) {
$('.avatar').attr('src', res.url + '?' + parseInt(100 * Math.random()));
return layer.msg(res.msg);
}
layer.msg(res.msg, 'error');
}
})
})
</script>

View File

@@ -0,0 +1,30 @@
<layout name="layout:layout"/>
<!-- 内容主体区域 -->
<div id="content">
<div class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/user/protection">
<div class="layui-form-item">
<label class="layui-form-label">{:__('密保问题')}</label>
<div class="layui-input-inline" style="width: 260px">
<select name="question" lay-verify="required">
<volist name="validate" id="vo">
<option value="{$vo}">{$vo}</option>
</volist>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">{:__('密保答案')}</label>
<div class="layui-input-inline" style="width: 260px">
<input name="answer" placeholder="{:__('请输入密保答案')}" type="text" class="layui-input"
autocomplete="off" lay-verify="required"/>
</div>
</div>
<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" lay-filter="submitIframe" data-reload="parent" lay-submit>{:__('提交')}</button>
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SwiftAdmin 用户注册</title>
<include file="public:header"/>
</head>
<body>
<style>
.layui-form-item {
margin-bottom: 15px;
}
.red {
color: red;
}
.layui-input:hover {
border: 1px solid #1890ff !important;
}
</style>
<div id="register" class="layui-fluid">
<form class="layui-form layui-form-fixed" action="/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 class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> 密码</label>
<div class="layui-input-block">
<input type="password" id="pwd" name="pwd" placeholder="请输入密码" class="layui-input">
</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">
<label class="layui-form-label"><span class="red">*</span> 手机号</label>
<div class="layui-input-block">
<input type="text" id="mobile" name="mobile" placeholder="请输入手机号" lay-verify="require|phone"
class="layui-input mobile">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><span class="red">*</span> 验证码</label>
<div class="layui-input-block">
<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>
<else/>
<div class="layui-form-item">
<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>
</eq>
<input type="text" hidden name="event" class="event" value="register">
<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" lay-filter="submitIframe" data-reload="top" lay-submit>
{:__('立即注册')}
</button>
</div>
</form>
</div>
</body>
</html>

View File

@@ -0,0 +1,115 @@
<layout name="layout:layout"/>
<div id="content">
<div class="layui-card">
<div class="layui-card-header"><h5>安全设置</h5></div>
<div class="layui-card-body">
<div id="user-detail">
<div class="layui-user-avatar fl" >
<img src="{$user.avatar}" alt="" width="80">
</div>
<div class="fl" style="margin-left: 35px">
<div class="u-info"><span class="label">会员ID:</span>{$user.id}</div>
<div class="u-info"><span class="label">注册日期:</span>{$user.create_time}</div>
<div class="u-info">
<span class="label">安全级别:</span>
<div class="layui-progress layui-progress-big">
<div class="layui-progress-bar layui-bg-blue" lay-percent="{$progress}%"></div>
</div>
<span class="text-stress">建议您启动全部安全设置,以保障账户及资金安全。</span>
</div>
</div>
</div>
<div class="settings-tier">
<div class="settings-detail fl">
<span class="setting-status">
<i class="layui-icon fa-check"></i>
</span>
<span class="setting-name">修改密码</span>
<span class="setting-intro">安全性高的密码可以使账户更安全;互联网账号存在被盗风险,建议您定期更换密码</span>
</div>
<div class="setting-operate fr">
<a lay-open="" data-title="修改密码" data-url="/user/changepwd" data-area="470px,330px" href="javascript:;">修改</a>
</div>
</div>
<div class="settings-tier">
<div class="settings-detail fl">
<span class="setting-status">
<empty name="$user['mobile']">
<i class="layui-icon fa-warning"></i>
<else/>
<i class="layui-icon fa-check"></i>
</empty>
</span>
<span class="setting-name">手机绑定</span>
<span class="setting-intro">您的手机:
<empty name="$user['mobile']">
未绑定
<else/>
{:hide_str($user['mobile'])}
</empty>。绑定认证后可用于手机找回密码、接收手机动态验证码等,保障您的账户安全。
</span>
</div>
<div class="setting-operate fr">
<a lay-open data-title="修改手机" data-url="/user/mobile" data-area="500px,300px">修改</a>
</div>
</div>
<div class="settings-tier">
<div class="settings-detail fl">
<span class="setting-status">
<empty name="$user['email']">
<i class="layui-icon fa-warning"></i>
<else/>
<i class="layui-icon fa-check"></i>
</empty>
</span>
<span class="setting-name">邮箱绑定 </span>
<span class="setting-intro">您的邮箱:
<empty name="$user['email']">
未绑定
<else/>
{:hide_str($user['email'])}
</empty>。绑定认证后可用于邮箱找回密码、接收订单提醒等,保障您的账户安全。
</span>
</div>
<div class="setting-operate fr">
<a lay-open data-title="修改邮箱" data-url="/user/email" data-area="500px,300px">修改</a>
</div>
</div>
<div class="settings-tier">
<div class="settings-detail fl">
<span class="setting-status">
<empty name="$user['answer']">
<i class="layui-icon fa-warning"></i>
<else/>
<i class="layui-icon fa-check"></i>
</empty>
</span>
<span class="setting-name">密保问题 </span>
<span class="setting-intro">设置密保问题可以进一步提升您的账户安全性。是您找回登录密码的方式之一。</span>
</div>
<div class="setting-operate fr">
<a lay-open data-title="设置密保" data-url="/user/protection" data-area="500px,300px">设置</a>
</div>
</div>
<div class="settings-tier">
<div class="settings-detail fl">
<span class="setting-status">
<i class="layui-icon fa-wechat"></i>
</span>
<span class="setting-name">微信绑定</span>
<span class="setting-intro">暂未绑定。 绑定认证后可用于快捷登录、接收微信通知</span>
</div>
<div class="setting-operate fr"><a href="">绑定</a></div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,15 @@
<!--// 初始化菜单-->
<ul class="layui-nav layui-nav-tree" lay-filter="master">
<li class="layui-nav-item layui-this">
<a lay-href="/user/profile">控制台</a>
</li>
<!--// 前台菜单-->
{:get_plugin_menu()}
<li class="layui-nav-item">
<a class="#" href="javascript:;">账号设置</a>
<dl class="layui-nav-child">
<dd><a lay-href="/user/security">安全设置</a></dd>
</dl>
</li>
</ul>