创建文章模型层
php artisan make:model Models/Article
继承Base
class Article extends Base {
// 追加一个字段 集合访问器
protected $appends = ['action'];
// 访问器
public function getActionAttribute() {
return $this->editBtn('admin.article.edit').' '.$this->deleteBtn('admin.article.destroy');
}
}
创建资源控制器
php artisan make:controller ArticleController
列表展示
public function index(Request $request) {
if ($request->header('X-Requested-With') == 'XMLHttpRequest') {
// ajax请求
// 排序
//['column' => $column, 'dir' => $dir] = $request->get('order')[0];
$orderArr = $request->get('order')[0];
// 排序索引
$column = $orderArr['column'];
// 排序类型 升还是降
$dir = $orderArr['dir'];
// 排序字段
$orderField = $request->get('columns')[$column]['data'];
// 开启位置
$start = $request->get('start', 0);
// 开启时间
$datemin = $request->get('datemin');
// 结束时间
$datemax = $request->get('datemax');
// 搜索关键字
$title = $request->get('title');
// 查询对象
$query = Article::where('id', '>', 0);
// 日期
if (!empty($datemin) && !empty($datemax)) {
// 开始时间
$datemin = date('Y-m-d H:i:s', strtotime($datemin . ' 00:00:00'));
// 结束时间
$datemax = date('Y-m-d H:i:s', strtotime($datemax . ' 23:59:59'));
$query->whereBetween('created_at', [$datemin, $datemax]);
}
// 搜索关键词
if (!empty($title)) {
$query->where('title', 'like', "%{
$title}%");
}
// 获取记录数
$length = min(100, $request->get('length', 10));
// 记录总数
$total = $query->count();
// 获取数据
$data = $query->orderBy($orderField, $dir)->offset($start)->limit($length)->get();
/*
draw: 客户端调用服务器端次数标识
recordsTotal: 获取数据记录总条数
recordsFiltered: 数据过滤后的总数量
data: 获得的具体数据
注意:recordsTotal和recordsFiltered都设置为记录的总条数
*/
$result = [
'draw' => $request->get('draw'),
'recordsTotal' => $total,
'recordsFiltered' => $total,
'data' => $data
];
return $result;
}
// 取出所有的文章数据
//$data = Article::all();
return view('admin.article.index');
}
添加文章显示
public function create() {
return view('admin.article.create');
}
图片上传
public function upfile(Request $request) {
// 封面图片
$pic = config('up.pic');
if ($request->hasFile('file')) {
// 上传
// 参数2 配置的节点名称
$ret = $request->file('file')->store('', 'article');
$pic = '/uploads/article/' . $ret;
}
return ['status' => 0, 'url' => $pic];
}
添加处理
public function store(AddArtRequest $request) {
// 文件上传
$post = $request->except(['_token', 'file']);
// 添加到数据库
Article::create($post);
return redirect(route('admin.article.index'));
}
文章修改展示
/**
* 文章修改显示
*/
public function edit(Article $article) {
return view('admin.article.edit', compact('article'));
}
修改处理
/**
* 修改处理
*/
public function update(Request $request, Article $article) {
return $request->all();
exit;
$putData = $request->except(['action', 'created_at', 'updated_at', 'deleted_at', 'id']);
$article->update($putData);
return ['status'=>0,'url'=>route('admin.article.index')];
}
文章删除
// 删除
public function destroy(Article $article) {
// 软删除
$article->delete();
return ['id' => 1];
}
编写视图层
@extends('admin.common.main')
@section('cnt')
<nav class="breadcrumb">
<i class="Hui-iconfont"></i> 首页
<span class="c-gray en">></span> 文章管理
<span class="c-gray en">></span> 文章列表
<a class="btn btn-success radius r" style="line-height:1.6em;margin-top:3px" href="javascript:location.replace(location.href);" title="刷新"><i class="Hui-iconfont"></i></a>
</nav>
{
{
-- 消息提示 --}}
@include('admin.common.msg')
<div class="page-container">
<form method="get" class="text-c" onsubmit="return dopost()">
<input type="text" onfocus="WdatePicker({ maxDate:'#F{
$dp.$D(\'datemax\')||\'%y-%M-%d\'}' })" id="datemin" class="input-text Wdate" style="width:120px;">
-
<input type="text" onfocus="WdatePicker({ minDate:'#F{
$dp.$D(\'datemin\')}',maxDate:'%y-%M-%d' })" id="datemax" class="input-text Wdate" style="width:120px;">
文章标题:
<input type="text" class="input-text" style="width:250px" placeholder="文章标题" value="{
{ request()->get('title') }}" id="title" autocomplete="off">
<button type="submit" class="btn btn-success radius"><i class="Hui-iconfont"></i> 搜索文章</button>
</form>
<div class="cl pd-5 bg-1 bk-gray mt-20">
<span class="l">
<a href="{
{ route('admin.article.create') }}" class="btn btn-primary radius">
<i class="Hui-iconfont"></i> 添加文章
</a>
</span>
</div>
<div class="mt-20">
<table class="table table-border table-bordered table-hover table-bg table-sort">
<thead>
<tr class="text-c">
<th width="80">ID</th>
<th width="100">文章标题</th>
<th width="130">加入时间</th>
<th width="100">操作</th>
</tr>
</thead>
</table>
</div>
</div>
@endsection
@section('js')
<script>
// 列表显示
var dataTable = $('.table-sort').DataTable({
// 下接的分页数量
lengthMenu: [5, 10, 15, 20, 100],
// 隐藏搜索
searching: false,
columnDefs: [
// 索引第3列,不进行排序
{
targets: [3], orderable: false}
],
// 开启服务器端分页 开启ajax
serverSide: true,
// 进行ajax请求
ajax: {
// 请求地址
url: '{
{ route('admin.article.index') }}',
// 请求方式
type: 'get',
// 参数 动态获取表单数据用 function
data: function (ret) {
ret.datemin = $('#datemin').val();
ret.datemax = $('#datemax').val();
ret.title = $.trim($('#title').val());
}
},
// 指定每一列显示的数据
columns: [
//{'data': '字段名称1', "defaultContent": "默认值", 'className': '类名'},
{
data: 'id', className: 'text-c'},
{
data: 'title'},
{
data: 'created_at'},
{
data: 'aaa', defaultContent: '默认值'}
],
// 回调方法
// row 当前行的dom对象
// 当前行的数据
// 当前行的数据索引
createdRow: function (row, data, dataIndex) {
// 当前id
var id = data.id;
// 行的最后一列
var td = $(row).find('td:last-child');
// 显示的html内容
var html = `
<a href="/admin/article/${id}/edit" class="label label-secondary radius">修改</a>
<a href="/admin/article/${id}" onclick="return delArticle(event,this)" class="label label-warning radius">删除</a>
`;
// html添加到td中
td.html(html);
}
});
// 表单提交
function dopost() {
// 手动调用一次dataTable插件请求
dataTable.ajax.reload();
// 取消表单默认行为
return false;
}
// 删除
function delArticle2(obj) {
// 请求的URL地址
let url = $(obj).attr('href');
// 发起ajax
/*let ret = fetch(url, {
method: 'delete',
headers: {
'X-CSRF-TOKEN': '{
{csrf_token()}}'
},
body:'aa=bb&id=1'
});
ret.then(res=>{
// 文本 promise
//console.log(res.text());
// json对象
res.json().then(data=>console.log(data))
})*/
// 原生的,浏览自带
fetch(url, {
method: 'delete',
headers: {
'X-CSRF-TOKEN': '{
{csrf_token()}}'
},
body: 'aa=bb&id=1'
}).then(res => {
return res.json();
}).then(data => {
console.log(data)
});
// 取消默认行为
return false;
}
// async await promise 异步变同步
async function delArticle(evt, obj) {
evt.preventDefault();
// 请求的URL地址
let url = $(obj).attr('href');
// 发起ajax
// 原生的,浏览自带
let ret = await fetch(url, {
method: 'delete',
headers: {
'X-CSRF-TOKEN': '{
{csrf_token()}}'
}
});
let json = await ret.json();
console.log(json);
// 取消默认行为
return false;
}
</script>
@endsection
修改视图层
@extends('admin.common.main')
@section('css')
{
{
-- webuploader上传样式 --}}
<link rel="stylesheet" type="text/css" href="/webuploader/webuploader.css"/>
@endsection
@section('cnt')
<nav class="breadcrumb">
<i class="Hui-iconfont"></i> 首页
<span class="c-gray en">></span> 文章管理
<span class="c-gray en">></span> 修改文章
<a class="btn btn-success radius r" style="line-height:1.6em;margin-top:3px" href="javascript:location.replace(location.href);" title="刷新"><i class="Hui-iconfont"></i></a>
</nav>
<article class="page-container">
{
{
-- 表单验证提示 --}}
@include('admin.common.validate')
<form action="{
{ route('admin.article.update',$article) }}" ref="frm" class="form form-horizontal">
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章标题:</label>
<div class="formControls col-xs-8 col-sm-9">
<input type="text" class="input-text" name="title" v-model="info.title">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章描述:</label>
<div class="formControls col-xs-8 col-sm-9">
<input type="text" class="input-text" name="desn" v-model="info.desn">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章封面:</label>
<div class="formControls col-xs-4 col-sm-5">
<!-- 表单提交时的封面地址 -->
<input type="hidden" name="pic" id="pic" v-model="info.pic">
<div id="picker">上传文章封面</div>
</div>
<div class="formControls col-xs-4 col-sm-4">
<img :src="info.pic" id="img" style="width: 100px;">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章内容:</label>
<div class="formControls col-xs-8 col-sm-9">
<textarea name="body" id="body" cols="30" rows="10"></textarea>
</div>
</div>
<div class="row cl">
<div class="col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3">
<input class="btn btn-primary radius" type="button" @click="dopost" value="修改文章">
</div>
</div>
</form>
</article>
@endsection
@section('js')
<!-- 引入vue -->
<script src="/js/vue.js"></script>
<!-- webuploader上传js -->
<script type="text/javascript" src="/webuploader/webuploader.js"></script>
<!-- 配置文件 -->
<script type="text/javascript" src="/ueditor/ueditor.config.js"></script>
<!-- 编辑器源码文件 -->
<script type="text/javascript" src="/ueditor/ueditor.all.js"></script>
<!-- 实例化编辑器 -->
<script>
//vue管理
new Vue({
el: '.page-container',
data: {
info:{
!! $article !!}
},
// 组件挂载完毕
mounted() {
// 富文本编辑器
this.editor = UE.getEditor('body', {
initialFrameHeight: 200
});
// 渲染完毕
this.editor.addListener("ready", () => {
// 设置富文本内容
//this.editor.setContent(this.info.body)
});
// 上传
// 初始化Web Uploader
this.uploader = WebUploader.create({
// 选完文件后,是否自动上传
auto: true,
// swf文件路径
swf: '/webuploader/Uploader.swf',
// 文件接收服务端 上传PHP的代码
server: '{
{ route('admin.article.upfile') }}',
// 文件上传是携带参数
formData: {
_token: '{
{csrf_token()}}'
},
// 文件上传是的表单名称
fileVal: 'file',
// 选择文件的按钮
pick: {
id: '#picker',
// 是否开启选择多个文件的能力
multiple: false
},
// 压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
resize: true
});
// 上传成功时的回调方法
this.uploader.on('uploadSuccess', (file, ret) => {
// 图片路径
let src = ret.url;
this.info.pic = src;
});
},
methods: {
dopost() {
var frmData = new FormData(this.$refs.frm);
frmData.append('_token','{
{ csrf_token() }}')
fetch(this.$refs.frm.action, {
method: 'PUT',
body: frmData
})
/*// 获取内容
this.info.body = this.editor.getContent();
var frmData = new FormData(this.$refs.frm);
// JSON字符串的转换
//var frmData = JSON.stringify(this.info);
let ret = await fetch(this.$refs.frm.action, {
method: 'PUT',
credentials: 'include',
headers: {
'X-CSRF-TOKEN': '{
{ csrf_token() }}',
'Content-Type': 'application/x-www-form-urlencoded'
//'Content-Type': 'application/json'
},
body: frmData
});
let json = await ret.json();
//location.href = json.url;*/
}
}
});
</script>
@endsection
创建视图层
@extends('admin.common.main')
@section('css')
{
{
-- webuploader上传样式 --}}
<link rel="stylesheet" type="text/css" href="/webuploader/webuploader.css"/>
@endsection
@section('cnt')
<nav class="breadcrumb">
<i class="Hui-iconfont"></i> 首页
<span class="c-gray en">></span> 文章管理
<span class="c-gray en">></span> 添加文章
<a class="btn btn-success radius r" style="line-height:1.6em;margin-top:3px" href="javascript:location.replace(location.href);" title="刷新"><i class="Hui-iconfont"></i></a>
</nav>
<article class="page-container">
{
{
-- 表单验证提示 --}}
@include('admin.common.validate')
<form action="{
{ route('admin.article.store') }}" method="post" class="form form-horizontal">
@csrf
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章标题:</label>
<div class="formControls col-xs-8 col-sm-9">
<input type="text" class="input-text" name="title">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章描述:</label>
<div class="formControls col-xs-8 col-sm-9">
<input type="text" class="input-text" name="desn">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章封面:</label>
<div class="formControls col-xs-4 col-sm-5">
<!-- 表单提交时的封面地址 -->
<input type="hidden" name="pic" id="pic" value="{
{ config('up.pic') }}">
<div id="picker">上传文章封面</div>
</div>
<div class="formControls col-xs-4 col-sm-4">
<img src="" id="img" style="width: 100px;">
</div>
</div>
<div class="row cl">
<label class="form-label col-xs-4 col-sm-3"><span class="c-red">* </span>文章内容:</label>
<div class="formControls col-xs-8 col-sm-9">
<textarea name="body" id="body" cols="30" rows="10"></textarea>
</div>
</div>
<div class="row cl">
<div class="col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3">
<input class="btn btn-primary radius" type="submit" value="添加文章">
</div>
</div>
</form>
</article>
@endsection
@section('js')
<!-- webuploader上传js -->
<script type="text/javascript" src="/webuploader/webuploader.js"></script>
<!-- 配置文件 -->
<script type="text/javascript" src="/ueditor/ueditor.config.js"></script>
<!-- 编辑器源码文件 -->
<script type="text/javascript" src="/ueditor/ueditor.all.js"></script>
<!-- 实例化编辑器 -->
<script>
// 富文本编辑器
var ue = UE.getEditor('body', {
initialFrameHeight: 200
});
// 初始化Web Uploader
var uploader = WebUploader.create({
// 选完文件后,是否自动上传
auto: true,
// swf文件路径
swf: '/webuploader/Uploader.swf',
// 文件接收服务端 上传PHP的代码
server: '{
{ route('admin.article.upfile') }}',
// 文件上传是携带参数
formData: {
_token: '{
{csrf_token()}}'
},
// 文件上传是的表单名称
fileVal: 'file',
// 选择文件的按钮
pick: {
id: '#picker',
// 是否开启选择多个文件的能力
multiple: false
},
// 压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
resize: true
});
// 上传成功时的回调方法
uploader.on('uploadSuccess', function (file, ret) {
// 图片路径
let src = ret.url;
// 给表单添加value值
$('#pic').val(src);
// 给图片添加src
$('#img').attr('src',src);
});
</script>
@endsection
编写路由文件
// 文章管理 admin/article/upfile
Route::post('article/upfile','ArticleController@upfile')->name('article.upfile');
// 资源路由
Route::resource('article', 'ArticleController');