博客列表 >laravel--通用后台管理系统--分页--图片上传

laravel--通用后台管理系统--分页--图片上传

王娇
王娇原创
2020年06月21日 16:09:561284浏览

学习总结

1.文章列表的分页,前端使用layui中的laypage进行渲染,后端使用laravel中的paginate(每页显示的记录个数)方法实现文章列表的分页

2.在DBServiceProvider.php中把paginate()进行扩展,扩展后的方法名称为pages()以数组的形式返回所查询到的数据,并且返回数据记录的总数

3.文件上传使用layui的Upload进行文件上传操作,上传的文件通过Upload控制器中的upload_img方法进行存储,并且返回可访问的地址。

5.上传的文件应当存储在storage目录下的public目录下

6.渲染保存在数据库的富文本编辑器中的内容 应该使用{!! $detail['contents'] !!}

1.文章控制器Article.php

  1. <?php
  2. namespace App\Http\Controllers\admins;
  3. use App\Http\Controllers\Controller;
  4. //登录验证
  5. use Illuminate\Support\Facades\Auth;
  6. use Illuminate\Http\Request;
  7. //引入数据库查询构造器,链式调用
  8. use Illuminate\Support\Facades\DB;
  9. //后台文章管理控制器
  10. class Article extends Controller
  11. {
  12. //显示文章列表
  13. public function index(Request $req)
  14. {
  15. $res['page'] =(int)$req->page;//当前显示的是第几页
  16. $limit = 8;//每页显示的记录数
  17. $pageInfo = DB::table('article')->orderby('id','desc')->pages($limit);//pages()方法为自定义的分页方法
  18. $res['articles'] = $pageInfo['data'];//得到分页数据
  19. $res['total'] = $pageInfo['total'];//得到记录总数
  20. $res['limit'] = $limit;//得到每页显示多少条记录
  21. //$res['articles'] = DB::table('article')->paginate(1);
  22. // $res['articles'] = DB::table('article')->lists();
  23. $res['cates'] = DB::table('article_cate')->cate('id');
  24. $res['auths'] = DB::table('admin')->select('id','real_name')->cate('id');
  25. // echo '<pre>';
  26. // print_r($res);
  27. // exit;
  28. return view('/admins/article/index',$res);
  29. }
  30. //添加修改文章
  31. public function add(Request $req)
  32. {
  33. //获取当前登录用户的id
  34. $res['admin_id'] = Auth::user()->id;
  35. //使用aid判断用户是添加文章=0,修改文章aid不为0
  36. $res['aid'] = (int)$req->aid;
  37. $res['article'] = DB::table('article')->where('id',$res['aid'])->item();
  38. //把文章分类数据带入视图中
  39. $res['cates'] = DB::table('article_cate')->lists();
  40. //把文章作者数据带入视图中
  41. $res['auths'] = DB::table('admin')->select('id','real_name')->lists();
  42. //获取文章详情
  43. $res['detail']= DB::table('article_detail')->where('aid',$res['aid'])->item();
  44. // echo '<pre>';
  45. // print_r($res);
  46. // exit;
  47. return view('/admins/article/add',$res);
  48. }
  49. //保存文章
  50. public function save(Request $req)
  51. {
  52. $aid = (int)$req->aid;
  53. $data['title'] = trim($req->title);
  54. if($data['title']==''):
  55. return (json_encode(['status'=>'1','msg'=>'文章标题不能为空']));
  56. endif;
  57. $data['cid'] =(int)$req->cid;
  58. $data['auth_id'] =(int)$req->auth_id;
  59. $data['subtitle'] = trim($req->subtitle);
  60. $data['thumb'] = $req->thumb;
  61. $data['keywords'] = trim($req->keywords);
  62. $data['descs'] = trim($req->descs);
  63. $data['status'] =(int)$req->status;
  64. $content = $req->detail;
  65. // echo '<pre>';
  66. // print_r($data);
  67. // exit;
  68. if($aid==0):
  69. $data['add_time'] =time();
  70. $artIndex = DB::table('article')->insertGetId($data);//插入文章后获取文章id索引
  71. if($artIndex>0):
  72. $res = DB::table('article_detail')->insert(['aid'=>$artIndex,'contents'=>$content]);//把文章详情插入文章内容表中
  73. endif;
  74. else:
  75. $artIndex = DB::table('article')->where('id',$aid)->update($data);//修改文章
  76. $res = DB::table('article_detail')->where('aid',$aid)->update(['contents'=>$content]);//更新文章内容表中的内容
  77. endif;
  78. return json_encode(['status'=>0,'msg'=>'保存成功']);
  79. }
  80. //删除文章
  81. public function del(Request $req)
  82. {
  83. $aid = $req->aid;
  84. $res = DB::table('article')->where('id',$aid)->delete();
  85. $res = DB::table('article_detail')->where('aid',$aid)->delete();
  86. return json_encode(['status'=>0,'msg'=>'删除成功']);
  87. }
  88. public function cates()
  89. {
  90. return view('/admins/article/cates');
  91. }
  92. }

2.显示文章列表,进行分页渲染index.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <title>文章管理</title>
  9. </head>
  10. <style>
  11. .addBtn {
  12. margin-top: 10px;
  13. width: 120px;
  14. margin-left: auto;
  15. margin-right: 50px;
  16. }
  17. .layui-table {
  18. width: 95%;
  19. margin: 20px;
  20. }
  21. </style>
  22. <body>
  23. <div class="addBtn">
  24. <button class="layui-btn" onclick="add()">添加文章</button>
  25. </div>
  26. <table class="layui-table">
  27. <thead>
  28. <tr>
  29. <th>编号</th>
  30. <th>文章分类</th>
  31. <th>标题</th>
  32. <th>封面图</th>
  33. <th>作者</th>
  34. <th>状态</th>
  35. <th>注册时间</th>
  36. <th>操作</th>
  37. </tr>
  38. </thead>
  39. <tbody>
  40. @foreach($articles as $article)
  41. <tr>
  42. <td>{{$article['id']}}</td>
  43. <td>{{$cates[$article['cid']]['title']}}</td>
  44. <td>{{$article['title']}}</td>
  45. <td><img src="{{$article['thumb']}}" alt="" style="height:30px"></td>
  46. <td>{{$auths[$article['auth_id']]['real_name']}}</td>
  47. <td>{{$article['status']?'已发布':'草稿'}}</td>
  48. <td>{{$article['add_time']?date('Y-m-d',$article['add_time']):''}}</td>
  49. <td>
  50. <button class="layui-btn layui-btn-xs" onclick="add({{$article['id']}})">修改</button>
  51. <button class="layui-btn layui-btn-xs layui-btn-danger"
  52. onclick="del({{$article['id']}})">删除</button>
  53. </td>
  54. </tr>
  55. @endforeach
  56. </tbody>
  57. </table>
  58. <div id="pageList" style="width:500px;margin-left: auto; margin-right:auto;"></div>
  59. </body>
  60. <script>
  61. layui.use(['layer', 'laypage'], function() {
  62. layer = layui.layer;
  63. $ = layui.jquery;
  64. //创建分页
  65. laypage = layui.laypage;
  66. //渲染分页条
  67. laypage.render({
  68. elem: 'pageList',
  69. count:{{$total}}, //数据记录总数
  70. limit: {{$limit}}, //每页显示几条数据
  71. curr:{{ $page }},//当前显示的是第几页的数据
  72. groups: 5, //中间连续显示几个页码
  73. layout:['prev','page','next','skip','count'],
  74. // first: '首页',可以自定义首页,下一页,尾页,上一页的文件显示
  75. // last: '尾页',
  76. // prev: '上一页',
  77. // next: '下一页',
  78. jump: function(obj, first) {
  79. //console.log(obj.curr);当前点击分页条的页码数
  80. if (!first) {
  81. window.location.href="?page="+obj.curr;
  82. }
  83. }
  84. });
  85. });
  86. //添加修改文章
  87. function add(aid) {
  88. //iframe层
  89. layer.open({
  90. type: 2,
  91. title: aid?'修改文章':'添加文章',
  92. shadeClose: true,
  93. shade: 0.8,
  94. area: ['680px', '100%'],
  95. content: '/admins/article/add?aid='+aid, //iframe的url
  96. btn: ['保存'],
  97. yes: function(index, layero) {
  98. //得到iframe页的窗口对象,执行iframe页的方法:iframeWin.子页面的方法名称();
  99. var iframeWin = window[layero.find('iframe')[0]['name']];;
  100. iframeWin.save();
  101. }
  102. });
  103. }
  104. //删除文章
  105. function del(aid) {
  106. layer.confirm('确认要删除文章吗?', function() {
  107. $.get('/admins/article/del?aid=' + aid, function(res) {
  108. if (res.status > 0) {
  109. layer.alert(res.msg, {
  110. icon: 2
  111. });
  112. } else {
  113. layer.msg(res.msg, {
  114. time: 3000
  115. });
  116. window.location.reload();
  117. }
  118. }, 'json');
  119. });
  120. }
  121. </script>
  122. </html>

3.添加或者修改文章add.blade.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <!-- html文件编辑器配置文件 -->
  9. <script src="/static/plugins/ueditor/ueditor.config.js"></script>
  10. <!-- 编辑器源码文件 -->
  11. <script src="/static/plugins/ueditor/ueditor.all.js"></script>
  12. <title>添加文章</title>
  13. <style>
  14. .layui-form {
  15. margin-top: 20px;
  16. margin-right: 20px;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <form action="" class="layui-form">
  22. @csrf
  23. <input type="hidden" name="aid" id="" value="{{ $article['id']?$article['id']:0 }}">
  24. <div class="layui-form-item">
  25. <label for="" class="layui-form-label">标题</label>
  26. <div class="layui-input-block">
  27. <input type="text" class="layui-input" name="title" value="{{ $article['title'] }}">
  28. </div>
  29. </div>
  30. <div class="layui-form-item">
  31. <label for="" class="layui-form-label">作者</label>
  32. <div class="layui-input-block">
  33. <select name="auth_id" id="">
  34. <option value=""></option>
  35. @foreach ($auths as $auth )
  36. @if($aid>0)
  37. {{-- 修改文章时作者id为数据库中保存的作者id --}}
  38. <option value="{{ $auth['id'] }}" {{ $auth['id'] === $article['auth_id']?'selected':'' }}>{{ $auth['real_name'] }}</option>
  39. @else
  40. {{-- 添加文章时作者id为登录用户的id --}}
  41. <option value="{{ $auth['id'] }}" {{ $auth['id'] === $admin_id?'selected':'' }}>{{ $auth['real_name'] }}</option>
  42. @endif
  43. @endforeach
  44. </select>
  45. </div>
  46. </div>
  47. <div class="layui-form-item">
  48. <label for="" class="layui-form-label">文章分类</label>
  49. <div class="layui-input-block">
  50. <select name="cid" id="">
  51. <option value=""></option>
  52. @foreach ($cates as $cate )
  53. <option value="{{ $cate['id'] }}" {{ $cate['id'] === $article['cid']?'selected':'' }}>{{ $cate['title'] }}</option>
  54. @endforeach
  55. </select>
  56. </div>
  57. </div>
  58. <div class="layui-form-item">
  59. <label for="" class="layui-form-label">封面图片</label>
  60. <div class="layui-input-block">
  61. <img src="{{ $article['thumb'] }}" alt="" id="show_thumb" style="height: 30px;">
  62. <button type="button" class="layui-btn" id="thumb">
  63. <i class="layui-icon">&#xe67c;</i>上传图片
  64. </button>
  65. </div>
  66. </div>
  67. <div class="layui-form-item">
  68. <label for="" class="layui-form-label">副标题</label>
  69. <div class="layui-input-block">
  70. <input type="text" class="layui-input" name="subtitle" value="{{ $article['subtitle'] }}">
  71. </div>
  72. </div>
  73. <div class="layui-form-item">
  74. <label for="" class="layui-form-label">关键词</label>
  75. <div class="layui-input-block">
  76. <input type="text" class="layui-input" name="keywords" value="{{ $article['keywords'] }}">
  77. </div>
  78. </div>
  79. <div class="layui-form-item">
  80. <label for="" class="layui-form-label">描述</label>
  81. <div class="layui-input-block">
  82. <textarea class="layui-textarea" name="descs">{{ $article['descs'] }}</textarea>
  83. </div>
  84. </div>
  85. <div class="layui-form-item">
  86. <label for="" class="layui-form-label">是否发布</label>
  87. <div class="layui-input-block">
  88. <input type="checkbox" lay-skin="switch" name="status" lay-text="发布|草稿" {{ $article['status']?'checked':'' }}>
  89. </div>
  90. </div>
  91. <!-- html文本编辑器 -->
  92. <div class="layui-form-item" style="padding-left:10px">
  93. <!-- 加载编辑器的容器 -->
  94. {{-- {!! $detail['contents'] !!} 进行html解析 --}}
  95. <script id="detail" name="detail" type="text/plain">{!! $detail['contents'] !!}</script>
  96. </div>
  97. </form>
  98. </body>
  99. <script>
  100. layui.use(['form', 'layer', 'upload'], function() {
  101. var form = layui.form;
  102. var layer = layui.layer;
  103. $ = layui.jquery;
  104. //<!-- 实例化编辑器 -->
  105. //var ue = UE.getEditor('detail', {
  106. ue = UE.getEditor('detail', {//副文本编辑器去掉var关键字,变成全局变量
  107. initialFrameWidth: '100%', //设定ueditor的宽度
  108. initialFrameHeight: '500' //设定ueditor的高度
  109. });
  110. var upload = layui.upload;
  111. _token = $('input[name="_token"]').val();//_token也去掉var关键字,成为全局变量
  112. //上传封面图片执行实例
  113. var uploadInst = upload.render({
  114. elem: '#thumb' //绑定元素
  115. ,
  116. url: '/admins/upload/upload_img' //上传接口
  117. ,
  118. data: {
  119. _token: _token
  120. },
  121. done: function(res) {
  122. //上传完毕回调
  123. // console.log(res.data.src);
  124. $('#show_thumb').attr('src', res.data.src);
  125. },
  126. error: function() {
  127. //请求异常回调
  128. layer.alert('封面图片上传失败', {
  129. icon: 2
  130. });
  131. }
  132. });
  133. });
  134. //在父窗口中调用了save方法
  135. function save() {
  136. if ($('input[name="title"]').val().trim() === '') {
  137. error('请输入文章标题');
  138. return false;
  139. }
  140. //把form表单中的数据序列化后通过post提交
  141. var data ={
  142. _token:_token,
  143. aid: $('input[name="aid"]').val(),
  144. title: $('input[name="title"]').val(),
  145. auth_id: $('select[name="auth_id"]').val(),
  146. cid: $('select[name="cid"]').val(),
  147. thumb:$('#show_thumb').attr('src'),
  148. subtitle:$('input[name="subtitle"]').val(),
  149. keywords:$('input[name="keywords"]').val(),
  150. descs:$('textarea[name="descs"]').val(),
  151. //获取状态的checed属性值,如果选中保存为1=已发布,否则保存为0=草稿
  152. status:$('input[name="status"]').attr('checked')?1:0,
  153. detail:ue.getContent(),//获取副文本编辑器中的数据
  154. };
  155. //把js对象转换为一个json字符串,然后在网络中传输
  156. JSON.stringify(data);
  157. $.post('/admins/article/save',
  158. data,
  159. function(res) {
  160. if (res.status > 0) {
  161. error(res.msg);
  162. } else {
  163. layer.msg(res.msg);
  164. setTimeout(function() {
  165. //假设这是iframe页
  166. var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
  167. //关闭当前窗口
  168. parent.layer.close(index); //再执行关闭
  169. //刷新父窗口,重新显示账号管理员列表
  170. parent.window.location.reload();
  171. }, 1000);
  172. }
  173. }, 'json');
  174. function error(msg) {
  175. layer.alert(msg, {
  176. icon: 2
  177. });
  178. }
  179. }
  180. </script>
  181. </html>


4.路由文件web.php

  1. <?php
  2. use Illuminate\Support\Facades\Route;
  3. /*
  4. |--------------------------------------------------------------------------
  5. | Web Routes
  6. |--------------------------------------------------------------------------
  7. |
  8. | Here is where you can register web routes for your application. These
  9. | routes are loaded by the RouteServiceProvider within a group which
  10. | contains the "web" middleware group. Now create something great!
  11. |
  12. */
  13. Route::get('/', function(){
  14. return view('welcome');
  15. });
  16. //登录页面
  17. Route::get('/admins/account/login','admins\Account@login')->name('login');//使用name()方法对路由进行命名
  18. //验证码图片
  19. Route::get('/admins/account/captcha','admins\Account@captcha');
  20. //登录操作
  21. Route::post('/admins/account/dologin','admins\Account@dologin');
  22. //后台首页
  23. //调用框架自带的auth中间件判断是否登录,namespace()方法指定控制器的命令空间,group()方法中是一个回调函数,把一组路由写在这个回调函数中
  24. Route::namespace('admins')->middleware(['auth','rights'])->group(function(){
  25. Route::get('/admins/home/index','Home@index');
  26. Route::get('/admins/home/welcome','Home@welcome');
  27. Route::get('/admins/home/logout','Home@logout');
  28. //账号管理
  29. Route::get('/admins/admin/index','Admin@index');
  30. //添加账号
  31. Route::get('/admins/admin/add','Admin@add');
  32. //修改账号
  33. Route::get('/admins/admin/edit','Admin@edit');
  34. //保存账号
  35. Route::post('/admins/admin/save','Admin@save');
  36. //删除账号
  37. Route::get('/admins/admin/del','Admin@del');
  38. //菜单管理
  39. Route::get('/admins/menus/index','Menus@index');
  40. //添加菜单
  41. Route::get('/admins/menus/add','Menus@add');
  42. //修改菜单
  43. Route::get('/admins/menus/edit','Menus@edit');
  44. //保存菜单
  45. Route::post('/admins/menus/save','Menus@save');
  46. //删除菜单
  47. Route::get('/admins/menus/del','Menus@del');
  48. //角色管理
  49. Route::get('/admins/groups/index','Groups@index');
  50. //添加角色
  51. Route::get('/admins/groups/add','Groups@add');
  52. //修改角色
  53. Route::get('/admins/groups/edit','Groups@edit');
  54. //保存角色
  55. Route::post('/admins/groups/save','Groups@save');
  56. //删除角色
  57. Route::get('/admins/groups/del','Groups@del');
  58. //文章管理
  59. Route::get('/admins/article/index','Article@index');
  60. //添加文章
  61. Route::get('/admins/article/add','Article@add');
  62. //修改文章
  63. Route::get('/admins/article/edit','Article@edit');
  64. //保存文章
  65. Route::post('/admins/article/save','Article@save');
  66. //删除文章
  67. Route::get('/admins/article/del','Article@del');
  68. //文件上传管理
  69. //文章封面上传
  70. Route::post('/admins/upload/upload_img','Upload@upload_img');
  71. });

5.数据库扩展DBserviceProvider.php

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Database\Query\Builder as QueryBuilder;
  4. use Illuminate\Support\ServiceProvider;
  5. class DBServiceProvider extends ServiceProvider
  6. {
  7. public function boot()
  8. {
  9. //扩展DB类中的查询结果集的方法,把结果集转换为数组
  10. QueryBuilder::macro('lists',function(){
  11. $res=[];
  12. $data = $this->get()->toArray();
  13. foreach($data as $item):
  14. $res[]=(array)$item;
  15. endforeach;
  16. return $res?$res:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  17. });
  18. //扩展DB类中的查询结果为一条记录,把结果转换为数组
  19. QueryBuilder::macro('item',function(){
  20. $data=[];
  21. $data = $this->get()->first();
  22. $data = (array)$data;
  23. return $data?$data:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  24. });
  25. //扩展DB类中的查询结果为数组的索引转换为记录的索引
  26. QueryBuilder::macro('cate',function($index){
  27. $res=[];
  28. $data = $this->lists();
  29. foreach($data as $item):
  30. //把查询结果集中的索引转换为记录中索引号
  31. $res[$item[$index]]=(array)$item;
  32. endforeach;
  33. return $res?$res:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  34. });
  35. QueryBuilder::macro('pages',function( $perPage = 15,$columns = ['*'],$pageName = 'page',$page = null){
  36. $res= [];
  37. $res['data']=[];
  38. $res['total']=[];
  39. $pageObj = $this->paginate($perPage,$columns,$pageName,$page);
  40. $lists = $pageObj->items();
  41. foreach($lists as $list):
  42. $res['data'][] = (array)$list;
  43. endforeach;
  44. $res['total'] = $pageObj->total();
  45. return $res?$res:false;//判断返回结果是否为空,为空返回false,这样前端渲染数据不容易出错
  46. });
  47. }
  48. }

6.文件上传控制器Upload.php

  1. <?php
  2. namespace App\Http\Controllers\admins;
  3. use App\Http\Controllers\Controller;
  4. //引入storage类,用于文件存储
  5. use Illuminate\Support\Facades\Storage;
  6. use Illuminate\Http\Request;
  7. //引入数据库查询构造器,链式调用
  8. use Illuminate\Support\Facades\DB;
  9. use PhpParser\Node\Expr\FuncCall;
  10. //文件上传控制器
  11. class Upload extends Controller
  12. {
  13. public function upload_img(Request $req)
  14. {
  15. //把上传的文件进行存储,存储在stroage目录中的app目录下的public/thumb
  16. $path = $req->file('file')->store('public/thumb/'.date('Y/m/d'));
  17. //使用
  18. //把存储文件地址转换为能访问的文件地址
  19. $path = Storage::url($path);
  20. // echo '<pre>';
  21. // print_r($path);
  22. // exit;
  23. return json_encode(['status'=>'0','msg'=>'文件上传成功','data'=>['src'=>$path]]);
  24. }
  25. }
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议