Blogger Information
Blog 57
fans 3
comment 0
visits 59786
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
laravel实战-通用后台管理系统-登录/注销和主界面
岂几岂几
Original
1128 people have browsed it

laravel实战-通用后台管理系统-登录/注销和主界面

1. 登录/注销

1.1 界面布局: 登录框水平垂直居中

  • 使用定位的方式
    • 创建登录框, 指定宽度和高度, 登录框容器为 <body> 的第一个元素, 这样登录框的原始位置就抵住浏览器左边和顶部.
    • 使用 position: absolute 定位, 相对自己原位置定位. 设置偏移登录框原位置的左边50%, 顶部50%; 因为登录框有宽度和高度, 所以使用 margin-left: -登录框宽度的一半margin-top: -登录框高度的一半 , 把登录框再往回退.

代码:

1-登录页 <body> 元素代码片段:

  1. <body style="background: #1E9FFF">
  2. <!-- 1. login-box是<body>的第一个子元素, 它的原始位置是抵住浏览器窗口的左边和顶部 -->
  3. <div class="login-box">
  4. <div class="layui-form">
  5. @CSRF
  6. <div class="layui-form-item">
  7. <span class="title">通用后台管理系统</span>
  8. </div>
  9. <div class="layui-form-item">
  10. <label class="layui-form-label">用户名</label>
  11. <div class="layui-input-inline">
  12. <input type="text" class="layui-input" name="username">
  13. </div>
  14. </div>
  15. <!-- 其他登录表单空间省略... -->
  16. </div>
  17. </div>
  18. </body>

2-水平垂直居中的样式代码片段

  1. /* 2. 设置登录框水平垂直居中 */
  2. .login-box {
  3. /* 相对登录框在文档流中的位置定位, 因为登录框是<body>元素的第一个子元素,
  4. 相当于相对浏览器的左边框和上边框定位 */
  5. position: absolute;
  6. width: 480px;
  7. height: 400px;
  8. /* 偏移浏览器窗口宽度的50% */
  9. left: 50%;
  10. /* 偏移浏览器窗口宽度的50% */
  11. top: 50%;
  12. /* 左外边距设置为"负值的登录框宽度的一半", 这样登录框会向左移动240px */
  13. margin-left: -240px;
  14. /* 上外边距设置为"负值的登录框高度的一半", 这样登录框会向上移动200px */
  15. margin-top: -200px;
  16. background: white;
  17. padding: 10px;
  18. border-radius: 5px;
  19. box-shadow: 5px 5px 20px #444;
  20. }
  • 复习: 设置元素水平垂直居中的其他方式
      1. 使用 margin: 0 auto , 把容器设为水平居中; 再为设置父容器的样式: display: table-cell; vertical-align: middle; , 即把父容器的显示方式设置为表格的单元格, 就能使用 vertical-align 属性设置垂直居中了.
      1. 把父容器设置为 flex 布局, 再设置样式属性: justify-content: center; 实现水平居中; 设置样式属性: align-items: center 实现垂直居中(主轴为水平方向).
      1. 把父容器设置为 grid 布局, 设置样式属性: grid-template-columns: auto 登录框宽度 autogrid-template-rows: auto 登录框高度 auto 把父容器设置为九宫格布局, 其中第5个单元格的宽高跟登录框相同. 为登录框容器设置样式: grid-column-start: 2; grid-column-end: 3; grid-row-start: 2; grid-column-end: 3 把登录框填充到第5个单元格.

1.2 验证码实现

  • 使用 composer 下载 gregwar/captcha 验证码插件.

  • 在图片点击时发送请求获取验证码, 并把服务器返回的验证码图片数据赋给 img.src 属性.

  • 服务器生成验证码后, 把验证码在 session 中也保存一份, 用来跟用户输入的验证码比对.

代码:

1-显示验证码的 <img> 元素:

  1. <img src="" alt="" style="height: 38px; width: 140px; cursor: pointer" onclick="getCaptcha()">

2-异步获取验证码图片数据的js方法

  1. function getCaptcha() {
  2. $.get('/admin/account/captcha?rand=' + Math.random(), null, function(data) {
  3. // 把服务器返回的验证码图片数据设置给img的src属性.
  4. $('img').attr('src', data);
  5. });
  6. }

3-生成验证码的控制器方法

  1. // 生成二维码
  2. public function getCaptcha() {
  3. //生成验证码图片的Builder对象,配置相应属性(4位验证码)
  4. $builder = new CaptchaBuilder(4);
  5. //可以设置图片宽高及字体
  6. $builder->build($width = 100, $height = 40, $font = null);
  7. //获取验证码的内容
  8. $phrase = $builder->getPhrase();
  9. session_start();
  10. //把内容存入session
  11. $_SESSION['captcha'] = $phrase;
  12. // 返回验证码到客户端
  13. echo $builder->inline();
  14. }

4-登录时验证验证码的代码片段

  1. public function doLogin(Request $request) {
  2. // 通过laravel封装的Request对象获取前端封装的数据,当获取不到某个参数值时,会返回null
  3. // 使用$_POST, $_GET, $_REQUEST获取参数值有个缺点, 就是如果获取未定义的key值时,会报错;
  4. $username = $request->username;
  5. $password = $request->password;
  6. // 用户输入的验证码
  7. $vericode = $request->vericode;
  8. // 判断验证码
  9. session_start();
  10. $captcha = $_SESSION['captcha'];
  11. if(strtoupper($vericode) != strtoupper($captcha)) {
  12. exit(json_encode(['status' => 1, 'message' => '验证码输入错误']));
  13. }
  14. // 后续业务处理代码省略...
  15. }

5-路由(略)

1.3 登录认证和注销登录

  • 使用laravel提供的门面类 \Illuminate\Support\Facades\Auth 提供 attempt([用户字段名 => 用户字段值, 密码字段名 => 密码字段值]) 的方法验证登录名和密码.

  • 执行登录验证前要开启session: session_start() ; 登录成功返回json消息时, 要用return返回, 不能用 exit() , 因为后者会无法触发session写入用户信息.

  • 给转到登录页面的路由起名字, 当session过期时, 自动跳转到登录界面. 路由名字要跟登录情况验证中间件\App\Http\Middleware\AuthenticateredirectTo()方法指定的路由名称一致(默认为login).
  • 同样使用 Auth 门面类提供的 logout() 方式实现用户注销.

登录功能代码:
1-登录按钮

  1. <div class="layui-form-item">
  2. <div class="layui-input-block">
  3. <button class="layui-btn" lay-submit lay-filter="formDemo" onclick="doLogin()">立即提交</button>
  4. </div>
  5. </div>

2-提交登录请求的js方法

  1. function doLogin() {
  2. var username = $.trim($('input[name="username"]').val());
  3. var password = $.trim($('input[name="password"]').val());
  4. var vericode = $.trim($('input[name="vericode"]').val());
  5. // laravel token,不带上,laravel会报419错误
  6. var _token = $('input[name="_token"]').val();
  7. if (username == undefined || username == '') {
  8. return layer.alert('请输入用户名', {
  9. icon: 2
  10. });
  11. }
  12. if (password == undefined || password == '') {
  13. return layer.alert('请输入密码', {
  14. icon: 2
  15. });
  16. }
  17. if (vericode == undefined || vericode == '') {
  18. return layer.alert('请输入验证码', {
  19. icon: 2
  20. });
  21. }
  22. var data = {
  23. username: username,
  24. password: password,
  25. vericode: vericode,
  26. _token: _token
  27. };
  28. // 提交登录请求
  29. $.post('/admin/account/doLogin', data, function(data) { //alert(data);return;
  30. var res = JSON.parse(data);
  31. // 登陆失败
  32. if (res.status != undefined && res.status == '1') {
  33. // 提示错误
  34. layer.alert(res.message, {
  35. icon: 2
  36. });
  37. } else if (res.status == '0') { // 登陆成功
  38. layer.msg(res.message, {
  39. icon: 1
  40. });
  41. // 1秒后跳转到主页面
  42. setTimeout(() => {
  43. window.location.href = "/admin/home/index";
  44. }, 1000);
  45. }
  46. });
  47. }

3-后台处理登录验证的控制器方法

  1. public function doLogin(Request $request) {
  2. // 通过laravel封装的Request对象获取前端封装的数据,当获取不到某个参数值时,会返回null
  3. // 使用$_POST, $_GET, $_REQUEST获取参数值有个缺点, 就是如果获取未定义的key值时,会报错;
  4. $username = $request->username;
  5. $password = $request->password;
  6. $vericode = $request->vericode;
  7. // 判断验证码
  8. session_start();
  9. $captcha = $_SESSION['captcha'];
  10. if(strtoupper($vericode) != strtoupper($captcha)) {
  11. exit(json_encode(['status' => 1, 'message' => '验证码输入错误']));
  12. }
  13. // 判空
  14. if($username == null || $username == '') {
  15. exit(json_encode(['status' => 1, 'message' => '用户名不能为空']));
  16. }
  17. if($password == null || $password == '') {
  18. exit(json_encode(['status' => 1, 'message' => '用户名不能为空']));
  19. }
  20. // 查询数据库,校验用户名和密码
  21. // laravel提供的一个用户名和密码的认证工具Auth::attempt--AES加密
  22. if(Auth::attempt(['username' => $username, 'password' => $password])) {
  23. // 注意,这里要用return返回,不要用exit,否则无法触发session写入用户信息的功能
  24. return (json_encode(['status' => 0, 'message' => '登陆成功']));
  25. } else {
  26. exit(json_encode(['status' => 1, 'message' => '账号或密码错误']));
  27. }
  28. }

4-路由

  1. // 后台登录(name()方法: 给路由起名字)
  2. Route::get('/admin/account/login', 'admins\Account@login')->name('login');

注销登录功能代码:

1-执行注销登录的控制器方法

  1. public function logout() {
  2. Auth::logout();
  3. return (json_encode(['status' => 0, 'message' => '登出成功!']));
  4. }

2-注销链接, 路由(略)

2. 主界面

2.1 页面布局

  • 左边栏导航, 整体浮动起来, 一级菜单用layui的手风琴折叠面板, 二级菜单采用layui的垂直/侧边导航的一级导航样式.

  • 内容区容器也浮动起来, 内容区采用内嵌iframe加载功能页面的方式. 页面加载完成, 要重新设置iframe的高度 = 浏览器窗口高度 - 顶部导航高度(50px).

布局代码:
1-左边栏菜单布局

  1. <!-- left menu -->
  2. <div class="left-menu">
  3. <!-- 在父容器加上lay-accordion属性, 就会开启手风琴模式, 打开一个子菜单, 其他菜单的子菜单自动合并 -->
  4. <div class="layui-collapse" lay-accordion style="width: 200px; float:left" lay-accordion>
  5. @foreach($menus as $menu1st)
  6. <!-- 一级菜单 -->
  7. <div class="layui-colla-item">
  8. <h2 class="layui-colla-title">{{$menu1st->title}}</h2>
  9. <!-- 加入.layui-show样式, 就会默认打开子菜单 -->
  10. <div class="layui-colla-content">
  11. <!-- 二级菜单列表 -->
  12. <ul class="layui-nav layui-nav-tree" id="L_demoNav" lay-filter="test">
  13. @foreach($menu1st->childs as $menu2st)
  14. <li class="layui-nav-item">
  15. <!-- controller和method属性分别记录该菜单项对应的控制器名和方法名 -->
  16. <a href="javascript:;" onclick="firemenu(this)" controller="{{$menu2st->controller}}" method="{{$menu2st->action}}">{{$menu2st->title}}</a>
  17. </li>
  18. @endforeach
  19. </ul>
  20. </div>
  21. </div>
  22. @endforeach
  23. </div>
  24. </div>

2-内容区布局

  1. <!-- main -->
  2. <div class="main">
  3. <!-- frameborder="0": 设置后iframe就没有边框了. 提升美观度 -->
  4. <!-- onload: 加载页面完成后要重新设置iframe的高度 -->
  5. <iframe src="/admin/home/welcome" frameborder="0" onload="resetIframeHeight(this)"></iframe>
  6. </div>

3-内容区布局样式: 不给 .main 设置宽高, 使用定位的上下左右属性值, 来设置 .main 容器的大小和位置.

  1. .main {
  2. position: absolute;
  3. /* 距离左边200px */
  4. left: 200px;
  5. /* 距离右边0px, 这样就可以撑满从左边200px到最右边的宽度 */
  6. right: 0px;
  7. top: 50px;
  8. bottom: 0px;
  9. }
  10. .main iframe {
  11. /* .main设置了left和right, 但是iframe并没有充满整个.main的宽度, 所以要设置width:100% */
  12. width: 100%;
  13. height: 100%;
  14. }

4-页面加载完成后重新设置iframe的高度

  1. function resetIframeHeight(iframe) {
  2. // 设置iframe的高度 = 浏览器窗口高度 - 顶部导航高度(50px)
  3. var main_height = document.documentElement.clientHeight - 50;
  4. iframe.style.height = main_height;
  5. }

2.2 用户菜单权限获取和菜单点击后渲染相应页面

  • 查询 admin_menu , admin_group, admin表获取用户菜单权限.

  • 在遍历渲染菜单项时, 给菜单项元素添加自定义属性 controlleraction , 分别赋值为该菜单项对应的控制器名和方法名.

    • 可以扩展 admin_menu 表, 再增加 module 属性和 menu_param 属性, 前者记录控制器所属模块; 后者记录点击该菜单项, 默认发送给后台的参数.
  • 在获取菜单项对应的页面的js方法中, 获取被点击菜单的 controlleraction , 拼成获取对应页面的url.

代码:

1-左侧菜单渲染(见上一节)

2-获取用户菜单权限列表代码片段

  1. public function index(Request $req) {
  2. // 从request对象中取出登录用户的信息(在权限中间件中有设置)
  3. $loginInfo = $req->loginInfo;
  4. $loginRights = $loginInfo->rights;
  5. // 查询出一级菜单列表(加上whereIn, 过滤出登录用户才有的菜单权限)
  6. $data['menus'] = DB::table('admin_menu')->where('pid', 0)->where('ishidden', 0)->where('status', 0)
  7. ->whereIn('mid', $loginRights)
  8. ->orderBy('ord')
  9. ->get()->all();
  10. // 查询二级菜单(加上whereIn, 过滤出登录用户才有的菜单权限)
  11. foreach($data['menus'] as $key => $menu) {
  12. $childs = DB::table('admin_menu')->where('pid', $menu->mid)->where('ishidden', 0)->where('status', 0)
  13. ->whereIn('mid', $loginRights)
  14. ->get()->all();
  15. $menu->childs = $childs;
  16. }
  17. // 其他处理略...
  18. return view('admins/home/index', $data);
  19. }

3-点击后在iframe中渲染相应的页面

  1. // 点击左边栏的菜单处理脚本
  2. function firemenu(obj) {
  3. var controller = $(obj).attr('controller');
  4. var method = $(obj).attr('method');
  5. // iframe中渲染链接到的页面
  6. $('.main iframe').attr('src', '/admin/' + controller + '/' + method);
  7. }

学习心得

  • 设置项目水平垂直居中的方式有多种, 西门老师教的是相对元素在文档流中定位+ margin-left 的方式实现.

  • 使用laravel提供的 Auth 门面类, 可以很方便的实现用户登录验证和注销登录.

  • 让iframe完美的嵌入到父页面中的实现, 很有用, 写下来备查.

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:布局使用的什么方式, 你可以根据自己想法来, 总之都教过不是吗?
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!