feat(frontend): 新增拖拽表格组件并优化数据表格相关功能

- 新增 CuteDragTable组件,支持行拖拽排序功能
- 重构 CuteTable 组件,改为 CuteSimpleTable,简化功能
- 更新 README.md,添加新组件说明
- 优化 OneKeyCopy 组件,改名为 CuteOneKeyCopy
- 删除示例页面 cuteTableDemo.vue
This commit is contained in:
2025-07-16 21:13:57 +08:00
parent 48e8c14463
commit 61e0a12c6a
7 changed files with 208 additions and 243 deletions
@@ -1,61 +0,0 @@
<template>
<div>
<el-divider>clipboard版</el-divider>
<span>{{ msg }}</span>
<div id="btn" @click="copy">复制</div>
<el-divider>OneKeyCopy组件版</el-divider>
<one-key-copy style="margin-left: 10pt" :content.sync="msg" />
</div>
</template>
<script>
import Clipboard from 'clipboard'
import { Message } from 'element-ui'
import OneKeyCopy from '@/views/components/base/OneKeyCopy.vue'
export default {
components: { OneKeyCopy },
data() {
return {
msg: '来复制我吧'
}
},
methods: {
// 复制方法
copy() {
const that = this
const clipboard = new Clipboard('#btn', {
text(trigger) {
console.log(trigger)
// 返回字符串
return that.msg
}
})
// 复制成功
clipboard.on('success', (e) => {
Message.success('复制成功')
console.log(e, '复制成功')
clipboard.destroy()
})
// //复制失败
clipboard.on('error', (e) => {
Message.error('复制失败')
console.log(e, '复制失败')
clipboard.destroy()
})
}
}
}
</script>
<style scoped>
#btn {
display: inline-block;
padding: 3px 12px;
border-radius: 6px;
background-color: #eee;
color: #333;
cursor: pointer;
}
#btn:active {
background-color: #ddd;
color: #666;
}
</style>
@@ -0,0 +1,176 @@
<template>
<div>
<el-table
ref="table"
v-loading="crud.loading"
stripe
empty-text="暂无数据"
:row-key="crud.primaryKey"
fit
:data="crud.dataSource"
style="width: 100%;"
height="450"
max-height="450"
@selection-change="onTableSelectionChange"
>
<el-table-column v-if="mode === 'multi'" type="selection" width="55" />
<el-table-column v-for="(column, index) in crud.columns" :key="index" :label="column.label" :prop="column.prop" :formatter="column.formatter ? column.formatter : null" />
<el-table-column v-if="crud.operateColumn" :width="crud.operateColumn.width" label="操作" :formatter="crud.operateColumn.formatter" :fixed="crud.operateColumn.fixed" />
</el-table>
<el-pagination
:current-page="pageProps.current"
:page-sizes="[10, 20, 50]"
:page-size="pageProps.pageSize"
layout="total, sizes, prev, pager, next"
:total="pageProps.total"
@size-change="(size) => crud.onPageChange(pageProps.current, size, pageProps.total)"
@current-change="(current) => crud.onPageChange(current, pageProps.pageSize, pageProps.total)"
/>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
name: 'CuteDragTable',
props: {
primaryKey: {
type: String,
required: true,
default: null
},
columns: {
type: Array,
required: true,
default: null
},
operateColumn: {
type: Object,
required: true,
default: null
},
dataSource: {
type: Array,
required: false,
default: null
},
fetch: {
type: Function,
required: false,
default: null
},
paramsTransform: {
type: Function,
required: false,
default: null
},
responseTransform: {
type: Function,
required: false,
default: null
},
mode: {
type: String,
required: false,
default: 'none'
},
pageProps: {
type: Object,
required: true,
default: function() {
return {
current: 1,
pageSize: 10,
total: 0
}
}
}
},
data() {
return {
crud: {
loading: false,
primaryKey: this.primaryKey ? this.primaryKey : 'id',
columns: this.columns && this.columns.length > 0 ? this.columns : [],
operateColumn: this.operateColumn,
fetchUrl: null,
dataSource: this.dataSource && this.dataSource.length > 0 ? this.dataSource : [],
onPageChange: (currentPage, pageSize) => {
this.pageProps.current = currentPage
this.pageProps.pageSize = pageSize
console.log('on-page-change', currentPage, pageSize)
// this.$emit('onPageChange', currentPage, pageSize, total)
this.refresh()
}
}
}
},
mounted() {
this.initData()
},
methods: {
refresh() {
this.initData()
this.initDragTable()
},
async initData() {
// 以dataSource属性为准
if (this.dataSource) {
this.crud.dataSource = this.dataSource
return
}
let params = {}
// 自定义请求参数
if (this.paramsTransform) {
params = this.paramsTransform(this.pageProps)
}
if (this.fetch) {
try {
this.crud.loading = true
// 请求远程数据
const response = await this.fetch(params)
// console.error('response', response)
// { content: [], totalElements: 0 }
// 转换为表格所需要的数据
if (this.responseTransform) {
return this.responseTransform(response)
}
if (response && response.totalElements && response.content) {
this.pageProps.total = response.totalElements
this.crud.dataSource = response.content
}
return response
} finally {
this.crud.loading = false
}
}
},
onTableSelectionChange(selection) {
this.$emit('selection-change', selection)
},
initDragTable() {
const that = this
const table = that.$refs.table.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
Sortable.create(table, {
animation: 1000,
onEnd({ newIndex, oldIndex }) {
// 拖拽排序数据
that.crud.dataSource.splice(newIndex, 0, that.crud.dataSource.splice(oldIndex, 1)[0])
const newArray = that.crud.dataSource.slice(0)
that.crud.dataSource = [] // 必须有此步骤,不然拖拽后回弹
that.$nextTick(function() {
that.crud.dataSource = newArray // 重新赋值,用新数据来刷新视图
this.updateOrderNum(that.crud.dataSource)// 更改列表中的序号,使序号1.2.3.4.....显示,不然就是行拖拽后乱序显示如:3.2.4.1...
})
}
})
},
updateOrderNum(data) {
data.forEach((item, index) => {
item.orderNum = index + 1
})
}
}
}
</script>
@@ -1,7 +1,6 @@
<!-- 一键复制组件 -->
<!-- 使用方式: <one-key-copy style="margin-left: 10pt" :content.sync="data" /> -->
<template>
<!-- <el-tooltip class="item" effect="dark" content="复制" placement="right-end">-->
<el-button
v-clipboard:copy="content"
v-clipboard:success="onCopy"
@@ -9,11 +8,11 @@
size="mini"
icon="el-icon-document-copy"
/>
<!-- </el-tooltip>-->
</template>
<script>
export default {
name: 'CuteOneKeyCopy',
props: {
content: {
type: String,
@@ -18,13 +18,13 @@
<el-table-column v-if="crud.operateColumn" :width="crud.operateColumn.width" label="操作" :formatter="crud.operateColumn.formatter" :fixed="crud.operateColumn.fixed" />
</el-table>
<el-pagination
:current-page="crud.pageProps.current"
:current-page="pageProps.current"
:page-sizes="[10, 20, 50]"
:page-size="crud.pageProps.pageSize"
:page-size="pageProps.pageSize"
layout="total, sizes, prev, pager, next"
:total="crud.pageProps.total"
@size-change="(size) => crud.onPageChange(crud.pageProps.current, size, crud.pageProps.total)"
@current-change="(current) => crud.onPageChange(current, crud.pageProps.pageSize, crud.pageProps.total)"
:total="pageProps.total"
@size-change="(size) => crud.onPageChange(pageProps.current, size, pageProps.total)"
@current-change="(current) => crud.onPageChange(current, pageProps.pageSize, pageProps.total)"
/>
</div>
</template>
@@ -32,7 +32,7 @@
<script>
export default {
name: 'CuteTable',
name: 'CuteSimpleTable',
props: {
primaryKey: {
type: String,
@@ -73,6 +73,17 @@ export default {
type: String,
required: false,
default: 'none'
},
pageProps: {
type: Object,
required: true,
default: function() {
return {
current: 1,
pageSize: 10,
total: 0
}
}
}
},
data() {
@@ -84,16 +95,12 @@ export default {
operateColumn: this.operateColumn,
fetchUrl: null,
dataSource: this.dataSource && this.dataSource.length > 0 ? this.dataSource : [],
pageProps: {
current: 1,
pageSize: 10,
total: 0
},
onPageChange: (currentPage, pageSize) => {
this.crud.pageProps.current = currentPage
this.crud.pageProps.pageSize = pageSize
this.pageProps.current = currentPage
this.pageProps.pageSize = pageSize
console.log('on-page-change', currentPage, pageSize)
// this.$emit('onPageChange', currentPage, pageSize, total)
this.refresh()
}
}
}
@@ -114,7 +121,7 @@ export default {
let params = {}
// 自定义请求参数
if (this.paramsTransform) {
params = this.paramsTransform(this.crud.pageProps)
params = this.paramsTransform(this.pageProps)
}
if (this.fetch) {
try {
@@ -128,7 +135,7 @@ export default {
return this.responseTransform(response)
}
if (response && response.totalElements && response.content) {
this.crud.pageProps.total = response.totalElements
this.pageProps.total = response.totalElements
this.crud.dataSource = response.content
}
return response