fastadmin表格右侧操作栏增加审核成功和审核失败按钮,点击提交ajax到后端
'# fastadmin表格右侧操作栏增加审核成功和审核失败按钮,点击提交ajax到后端
一、背景与问题
在内容管理系统中,审核操作是常见需求。传统FastAdmin框架中,表格右侧操作栏默认提供"编辑/删除"按钮,但缺少灵活的审核状态切换功能。当需要实现"审核通过"和"审核失败"两种操作时,传统方案存在以下痛点:
- 需要动态生成按钮并绑定不同操作
- 需要处理不同状态的AJAX请求
- 需要更新前端展示状态
- 需要保证操作的原子性
- 需要防范安全漏洞
本文将深入探讨如何通过AJAX实现审核状态切换的完整解决方案,并分析其适用场景和注意事项。
二、基本原理
FastAdmin基于ThinkPHP框架和Vue.js实现,其表格操作栏的实现原理如下:
- 前端通过Vue模板渲染表格行
- 使用v-for遍历数据源生成表格行
- 使用v-if或v-show控制操作栏显示
- 使用@click绑定点击事件
- 通过AJAX请求与后端交互
- 后端处理审核状态变更逻辑
- 前端根据返回结果更新界面状态
核心技术点包括:Vue事件绑定、AJAX通信、状态管理、权限控制和安全防护。
三、环境准备
开发环境要求:
- PHP 7.4+
- MySQL 5.7+
- Node.js 16+
- FastAdmin 1.8.0+(确保支持Vue3)
代码结构:
├── application │ └── admin │ └── controller │ └── ArticleController.php │ └── view │ └── article │ └── index.html数据库准备:
CREATE TABLE `think_article` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `status` tinyint NOT NULL DEFAULT 0, `create_time` datetime NOT NULL, PRIMARY KEY (`id`) );
四、核心实现
1. 前端模板改造(index.html)
<!-- 原始代码 -->
<th width="180">操作</th>
<td>
<a href="javascript:;" class="layui-btn layui-btn-xs" lay-options="{type: 'edit', url: '{:url('admin/article/edit')}'}" lay-filter="edit">编辑</a>
<a href="javascript:;" class="layui-btn layui-btn-danger layui-btn-xs" lay-options="{type: 'delete', url: '{:url('admin/article/delete')}'}" lay-filter="del">删除</a>
</td>
<!-- 修改后代码 -->
<th width="180">操作</th>
<td>
<!-- 审核按钮 -->
<div class="layui-btn-group">
<a href="javascript:;" class="layui-btn layui-btn-sm" @click="audit(1, '{{ $vo['id'] }}')">审核通过</a>
<a href="javascript:;" class="layui-btn layui-btn-sm layui-btn-danger" @click="audit(2, '{{ $vo['id'] }}')">审核失败</a>
</div>
<!-- 原有编辑删除按钮 -->
<a href="javascript:;" class="layui-btn layui-btn-xs" lay-options="{type: 'edit', url: '{:url('admin/article/edit')}'}" lay-filter="edit">编辑</a>
<a href="javascript:;" class="layui-btn layui-btn-danger layui-btn-xs" lay-options="{type: 'delete', url: '{:url('admin/article/delete')}'}" lay-filter="del">删除</a>
</td>关键点说明:
- 使用
@click绑定自定义方法 - 传递审核状态(1为通过,2为失败)和记录ID
- 使用
layui-btn-sm控制按钮尺寸
2. 前端JS逻辑(index.js)
// 原始代码(未修改)
var edit = {
init: function() {
// 初始化代码
}
};
// 修改后代码
var edit = {
init: function() {
// 绑定审核按钮点击事件
this.auditBtn();
},
auditBtn: function() {
const that = this;
// 绑定审核按钮点击事件
$(document).on('click', '.layui-btn-sm', function() {
const status = $(this).hasClass('layui-btn-success') ? 1 : 2;
const id = $(this).data('id');
that.audit(id, status);
});
},
audit: function(id, status) {
this.$axios.post('/admin/article/audit', {
id: id,
status: status
}).then(response => {
if (response.data.code === 0) {
// 成功提示
layer.msg('审核成功');
// 刷新当前行
this.$nextTick(() => {
this.$refs.table.refresh();
});
} else {
layer.msg('审核失败: ' + response.data.msg);
}
}).catch(error => {
console.error('审核失败:', error);
layer.msg('系统错误');
});
}
};关键点说明:
- 使用axios发送POST请求
- 使用data-id属性传递记录ID(需在模板中添加)
- 使用layer.msg显示提示信息
- 使用$nextTick刷新表格
3. 后端接口实现(ArticleController.php)
namespace app\admin\controller;
use think\Request;
use app\common\controller\Backend;
class Article extends Backend
{
public function audit()
{
$id = $this->request->post('id');
$status = $this->request->post('status');
// 验证请求合法性
if (!$this->request->isPost() || !isset($id) || !isset($status)) {
return json(['code' => 1, 'msg' => '请求非法']);
}
// 验证权限
if (!$this->auth->check('audit', 'article')) {
return json(['code' => 1, 'msg' => '无权限操作']);
}
// 更新审核状态
$result = $this->model->where(['id' => $id])->update(['status' => $status]);
if ($result) {
return json(['code' => 0, 'msg' => '操作成功']);
} else {
return json(['code' => 1, 'msg' => '操作失败']);
}
}
}关键点说明:
- 验证请求类型和参数
- 验证用户权限
- 使用模型进行数据更新
- 返回JSON格式响应
五、完整案例:文章审核系统
1. 项目结构
├── application
│ └── admin
│ └── controller
│ └── ArticleController.php
│ └── view
│ └── article
│ ├── index.html
│ └── index.js2. 前端完整代码(index.html)
<!-- 基础模板 -->
<template>
<div>
<table class="layui-table">
<thead>
<tr>
<th>标题</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in articles" :key="item.id">
<td>{{ item.title }}</td>
<td>{{ statusMap[item.status] }}</td>
<td>
<!-- 审核按钮 -->
<div class="layui-btn-group">
<a href="javascript:;" class="layui-btn layui-btn-sm" @click="audit(1, item.id)">审核通过</a>
<a href="javascript:;" class="layui-btn layui-btn-sm layui-btn-danger" @click="audit(2, item.id)">审核失败</a>
</div>
<!-- 原有操作 -->
<a href="javascript:;" class="layui-btn layui-btn-xs" lay-options="{type: 'edit', url: '{:url('admin/article/edit')}'}" lay-filter="edit">编辑</a>
<a href="javascript:;" class="layui-btn layui-btn-danger layui-btn-xs" lay-options="{type: 'delete', url: '{:url('admin/article/delete')}'}" lay-filter="del">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
articles: [],
statusMap: {
0: '未审核',
1: '已通过',
2: '已拒绝'
}
};
},
mounted() {
this.fetchData();
},
methods: {
fetchData() {
// 模拟数据获取
this.articles = [
{ id: 1, title: '测试文章1', status: 0 },
{ id: 2, title: '测试文章2', status: 1 },
{ id: 3, title: '测试文章3', status: 2 }
];
},
audit(status, id) {
// 模拟AJAX请求
setTimeout(() => {
this.articles = this.articles.map(item =>
item.id === id ? { ...item, status } : item
);
layer.msg('审核成功');
}, 500);
}
}
};
</script>3. 后端完整代码(ArticleController.php)
namespace app\admin\controller;
use think\Request;
use app\common\controller\Backend;
class Article extends Backend
{
public function index()
{
// 简化示例,实际应从数据库获取数据
$this->assign('articles', [
['id' => 1, 'title' => '测试文章1', 'status' => 0],
['id' => 2, 'title' => '测试文章2', 'status' => 1],
['id' => 3, 'title' => '测试文章3', 'status' => 2]
]);
return $this->fetch();
}
public function audit()
{
$id = $this->request->post('id');
$status = $this->request->post('status');
// 验证请求合法性
if (!$this->request->isPost() || !isset($id) || !isset($status)) {
return json(['code' => 1, 'msg' => '请求非法']);
}
// 验证权限
if (!$this->auth->check('audit', 'article')) {
return json(['code' => 1, 'msg' => '无权限操作']);
}
// 模拟数据库更新
$result = $this->model->where(['id' => $id])->update(['status' => $status]);
if ($result) {
return json(['code' => 0, 'msg' => '操作成功']);
} else {
return json(['code' => 1, 'msg' => '操作失败']);
}
}
}六、源码解析
1. 前端源码解析
模板语法:
- 使用Vue的
v-for遍历数据 - 使用
@click绑定点击事件 - 使用
{{ }}进行数据绑定
- 使用Vue的
状态管理:
- 使用
statusMap进行状态转换 - 使用
this.articles保存数据 - 使用
this.fetchData()初始化数据
- 使用
AJAX请求:
- 使用
setTimeout模拟AJAX请求 - 使用
layer.msg显示提示信息 - 使用
this.articles更新状态
- 使用
2. 后端源码解析
接口验证:
- 验证请求类型
- 验证参数存在性
- 验证用户权限
数据更新:
- 使用
$this->model进行数据库操作 - 使用
update()方法更新数据 - 返回JSON格式响应
- 使用
七、进阶使用
1. 权限控制增强
// 在audit方法中增加权限验证
if (!$this->auth->check('audit', 'article') || !$this->auth->check('edit', 'article', $id)) {
return json(['code' => 1, 'msg' => '无权限操作']);
}2. 防止重复提交
// 前端添加防重锁
audit: function(id, status) {
if (this.isProcessing) return;
this.isProcessing = true;
setTimeout(() => {
this.isProcessing = false;
this.articles = this.articles.map(item =>
item.id === id ? { ...item, status } : item
);
layer.msg('审核成功');
}, 500);
}3. 异步审核处理
// 在audit方法中进行异步处理
public function audit()
{
$id = $this->request->post('id');
$status = $this->request->post('status');
// 模拟异步处理
$this->model->where(['id' => $id])->update(['status' => $status]);
// 记录日志
$this->log->save([
'user_id' => $this->user->id,
'action' => 'audit',
'record_id' => $id,
'status' => $status
]);
return json(['code' => 0, 'msg' => '操作成功']);
}八、性能与工程实践
1. 性能优化
- 批量处理:对于大量审核操作,使用批量处理减少数据库查询
- 缓存状态:使用Redis缓存审核状态,减少数据库访问
- 异步处理:对于耗时操作,使用队列系统进行异步处理
- 事务控制:对于涉及多个表的审核操作,使用事务保证数据一致性
2. 安全防护
- CSRF防护:在前端添加CSRF token验证
- 输入过滤:对输入参数进行严格校验
- 日志审计:记录所有审核操作日志
- 权限控制:实施RBAC模型进行精细权限控制
3. 异常处理
// 增加异常处理
try {
$result = $this->model->where(['id' => $id])->update(['status' => $status]);
if (!$result) {
throw new \Exception('更新失败');
}
} catch (\Exception $e) {
return json(['code' => 1, 'msg' => '系统错误: ' . $e->getMessage()]);
}九、常见问题与踩坑
1. 常见错误
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 按钮无响应 | 未正确绑定事件 | 检查@click绑定 |
| 状态未更新 | 前端未正确更新数据 | 使用this.articles更新数据 |
| 权限验证失败 | 权限配置错误 | 检查RBAC配置 |
| 网络请求失败 | 未处理网络错误 | 添加错误处理逻辑 |
| 跨域问题 | 未配置CORS | 配置中间件处理 |
2. 常见坑点
- 权限验证顺序:先验证用户权限再处理业务逻辑
- 数据一致性:确保前端状态与后端数据同步
- CSRF防护:在AJAX请求中携带CSRF token
- 状态更新延迟:使用
$nextTick确保DOM更新 - 批量操作:避免逐条更新导致性能问题
十、最佳实践
- 使用Vue3的响应式系统:确保数据变化时界面自动更新
- 使用防重锁机制:防止用户重复点击提交
- 添加操作日志:记录所有审核操作以便审计
- 使用缓存机制:减少对数据库的频繁访问
- 实施RBAC模型:实现细粒度的权限控制
- 进行单元测试:确保审核逻辑正确性
- 使用日志系统:记录所有审核操作日志
十一、总结
通过在FastAdmin表格右侧操作栏添加审核按钮,实现审核状态的灵活切换,我们深入探讨了其技术原理、实现方法、性能优化、安全防护和常见问题。这种方案适用于需要精细审核控制的内容管理系统,但需要注意以下几点:
适用场景:
- 内容审核系统
- 商品审核平台
- 会员资质审核
- 信息报备系统
不适用场景:
- 高并发审核场景(需异步处理)
- 需要实时状态同步的系统
- 无需用户交互的审核流程
- 需要复杂审核规则的系统
通过本文的深入探讨,我们不仅掌握了实现该功能的技术要点,还了解了在实际项目中如何合理应用和规避潜在风险。在实际开发中,应根据具体业务需求选择合适的实现方案,并结合性能优化、安全防护等最佳实践,确保系统的稳定性和可维护性。
评论已关闭