Vue2 + ElementUI 批量更新排序/产品分类完整实现
分两种场景:批量拖拽排序 、批量勾选修改分类,适配你产品列表分页场景,编辑返回保留页码逻辑不变。
一、批量拖拽排序(el-table 行拖拽)
1. 安装拖拽依赖 sortablejs
bash
npm i sortablejs --save
2. 表格组件代码
vue
<template>
<div>
<el-table
ref="table"
:data="tableData"
border
row-key="id"
>
<el-table-column label="排序" width="80">
<template slot-scope="{ row }">
<i class="el-icon-sort" style="cursor:move;color:#999"></i>
</template>
</el-table-column>
<el-table-column prop="name" label="产品名称"></el-table-column>
<el-table-column prop="sort" label="当前排序值"></el-table-column>
</el-table>
<el-button type="primary" @click="batchSaveSort">批量保存排序</el-button>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
data() {
return {
tableData: [],
// 拖拽后新排序数组
sortList: []
}
},
mounted() {
this.initDrag()
},
methods: {
// 初始化拖拽
initDrag() {
const el = this.$refs.table.$el.querySelector('.el-table__body-wrapper tbody')
Sortable.create(el, {
animation: 150,
ghostClass: 'sort-ghost',
onEnd: ({ newIndex, oldIndex }) => {
// 拖拽完成记录新顺序
this.sortList = this.tableData.map((item, idx) => ({
id: item.id,
sort: idx + 1 // 排序值从1自增
}))
}
})
},
// 批量提交排序接口
async batchSaveSort() {
if (!this.sortList.length) {
this.$message.warning('未调整排序')
return
}
const res = await this.$api.product.batchSort(this.sortList)
if (res.code === 0) {
this.$message.success('排序更新成功')
// 刷新当前页列表(保留分页)
this.getList()
this.sortList = []
}
},
// 请求列表(原有分页逻辑不变)
getList() {
// ...你的分页请求代码
}
}
}
</script>
<style scoped>
::v-deep .sort-ghost {
background: #ecf5ff !important;
}
</style>
后端接口传参格式
js
// sortList 传给后端
[
{ id: 101, sort: 1 },
{ id: 105, sort: 2 },
{ id: 103, sort: 3 }
]
二、批量勾选修改产品分类(最常用批量操作)
1. 表格+批量操作按钮
vue
<template>
<div>
<!-- 批量操作区 -->
<el-button type="warning" @click="openBatchCateDialog">批量修改分类</el-button>
<el-table
ref="table"
:data="tableData"
border
row-key="id"
@selection-change="handleSelectionChange"
>
<!-- 多选框 -->
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="name" label="产品名称"></el-table-column>
<el-table-column prop="cateName" label="所属分类"></el-table-column>
</el-table>
<!-- 批量修改分类弹窗 -->
<el-dialog title="批量修改分类" :visible.sync="batchDialogVisible" width="400px">
<el-select v-model="batchCateId" placeholder="请选择分类">
<el-option
v-for="item in cateList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
<div slot="footer" class="dialog-footer">
<el-button @click="batchDialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmBatchCate">确定修改</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [],
multipleSelection: [], // 选中行数组
batchDialogVisible: false,
batchCateId: '', // 批量选中分类ID
cateList: [] // 全部分类下拉数据
}
},
methods: {
// 勾选事件
handleSelectionChange(val) {
this.multipleSelection = val
},
// 打开批量弹窗
openBatchCateDialog() {
if (!this.multipleSelection.length) {
this.$message.warning('请先勾选要修改的产品')
return
}
this.batchCateId = ''
this.batchDialogVisible = true
},
// 确认批量修改分类
async confirmBatchCate() {
if (!this.batchCateId) {
this.$message.warning('请选择分类')
return
}
// 提取勾选产品id数组
const ids = this.multipleSelection.map(item => item.id)
const params = {
ids,
cateId: this.batchCateId
}
const res = await this.$api.product.batchUpdateCate(params)
if (res.code === 0) {
this.$message.success('批量修改成功')
this.batchDialogVisible = false
this.multipleSelection = [] // 清空勾选
this.$refs.table.clearSelection() // 清空表格勾选框
// 刷新当前分页列表(保留第二页不跳回第一页)
this.getList()
}
},
getList() {
// 原有分页请求逻辑
}
}
}
</script>
后端批量接口参数
js
{
ids: [101,102,103], // 批量产品ID数组
cateId: 5 // 目标分类ID
}
三、结合你之前「编辑返回丢失页码」问题配套处理
1. keep-alive 缓存列表 + 批量操作刷新不丢页
js
// 列表页 activated 钩子,从编辑/批量弹窗回来自动刷新
activated() {
// 批量修改、编辑完成后都会重新请求当前页数据
this.getList()
}
2. 如果不用 keep-alive,分页参数统一存 query
批量操作成功后不用 router.back(),直接刷新当前路由:
js
// 批量成功后刷新列表,保留页码
this.$router.push({
path: '/product/list',
query: {
page: this.pageNum,
size: this.pageSize
}
})
四、常用拓展功能
- 批量删除
和批量改分类逻辑一致,拿到ids数组调用删除接口,成功刷新列表。 - 批量上下架
增加下拉选择状态,传ids + status批量更新。 - 拖拽排序分页兼容问题
- 拖拽仅作用当前页数据,跨页排序不推荐前端处理;
- 如需全局统一排序,后端提供全局拖拽接口,分页只展示当前区间。
五、踩坑点
- sortablejs 绑定tbody,不要绑定table,否则拖拽失效;
- 批量操作后必须
clearSelection(),否则勾选状态残留; - 分页第二页批量更新后,调用
getList()即可保持当前页码,不会重置pageNum=1; - query 参数是字符串,请求接口时记得转数字
Number(this.$route.query.page)。