feat(dev): 添加可编辑表格组件

- 新增 CuteEditTable 组件实现表格行内编辑功能
- 支持 input 和 select 类型的单元格编辑
- 提供行删除、上移、下移操作按钮
- 集成到 CuteSimpleTableDemo 演示页面
- 配置可编辑表格的数据源和字段定义
- 实现表格数据变更的双向绑定机制
This commit is contained in:
2026-02-02 15:09:05 +08:00
parent d370e51c02
commit 2e0d60e834
2 changed files with 197 additions and 5 deletions
@@ -0,0 +1,174 @@
<!--
* 可编辑表格组件
* @author odboy
* @email tianjun@odboy.cn
* @created 2026-02-01
-->
<template>
<el-table
ref="table"
stripe
empty-text="暂无数据"
:row-key="primaryKey"
fit
:data="dataSource"
style="width: 100%;"
:height="height"
:max-height="height"
highlight-current-row
>
<el-table-column type="index" width="70" />
<el-table-column v-for="item in schema" :key="item[primaryKey]" :prop="item.name" :label="item.title">
<template slot-scope="scope">
<el-input v-if="item.type === 'input'" v-model="scope.row[item.name]" @input="(val) => onRowChange(val, scope.$index, item.name)" />
<el-select v-if="item.type === 'select'" v-model="scope.row[item.name]" @change="(val) => onRowChange(val, scope.$index, item.name)">
<el-option
v-for="option in (item.dataSource || [])"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column>
<template slot-scope="scope">
<el-button type="text" size="small" @click="onRowRemove(scope.$index)">删除</el-button>
<el-button type="text" size="small" :disabled="scope.$index < 1" @click="onRowUpMove(scope.$index)">上移</el-button>
<el-button type="text" size="small" :disabled="scope.$index + 1 >= dataSource.length" @click="onRowDownMove(scope.$index)">下移</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
name: 'CuteEditTable',
props: {
/**
* 绑定的值
*/
value: {
type: Array,
required: false,
default: function() {
return []
}
},
/**
* 主键:列表排序用
*/
primaryKey: {
type: String,
required: true
},
/**
* 对表格字段的定义
*/
schema: {
type: Array,
require: true
},
/**
* 自定义高度
*/
customHeight: {
type: Number,
required: false,
default: null
}
},
data() {
return {
dataSource: []
}
},
computed: {
height() {
if (this.customHeight) {
return this.customHeight
}
return document.documentElement.clientHeight - 300
}
},
mounted() {
if (this.value && this.value.length > 0) {
this.dataSource = this.value
}
},
methods: {
/**
* 当行内数据变更
* @param val 当前值
* @param index
* @param name
*/
onRowChange(val, index, name) {
const dataSource = this.dataSource
dataSource[index][name] = val
this.dataSource = [...dataSource]
this.$emit('input', this.dataSource)
},
/**
* 当删除按钮被点击
* @param index
*/
onRowRemove(index) {
const dataSource = this.dataSource
dataSource.splice(index, 1)
this.dataSource = [...dataSource]
this.$emit('input', this.dataSource)
},
/**
* 当上移按钮被点击
* @param index
*/
onRowUpMove(index) {
if (index <= 0) {
return
}
const dataSource = this.dataSource
const temp = dataSource[index]
dataSource[index] = dataSource[index - 1]
dataSource[index - 1] = temp
this.dataSource = [...dataSource]
this.$emit('input', this.dataSource)
},
/**
* 当下移按钮被点击
* @param index
*/
onRowDownMove(index) {
console.log('=====onRowDownMove1', index)
if (index >= this.dataSource.length - 1) {
return
}
const dataSource = this.dataSource
const temp = dataSource[index]
dataSource[index] = dataSource[index + 1]
dataSource[index + 1] = temp
this.dataSource = [...dataSource]
this.$emit('input', this.dataSource)
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/assets/styles/variables.scss";
.selection-box {
text-align: left;
font-size: 12px;
padding-left: 10px;
min-height: 26.7px;
max-height: 26.7px;
padding-top: 7px;
}
.selection-count {
color: $menuActiveText;
}
</style>
@@ -99,6 +99,9 @@
<el-table-column prop="description" label="备注" /> <el-table-column prop="description" label="备注" />
</cute-transfer> </cute-transfer>
</el-form-item> </el-form-item>
<el-form-item label="可编辑表格" prop="editValues" label-width="100px">
<cute-edit-table v-model="editTableDataSource" primary-key="id" :schema="editTableSchema" />
</el-form-item>
</cute-form-drawer> </cute-form-drawer>
</div> </div>
</template> </template>
@@ -111,18 +114,33 @@ import CuteFormDrawer from '@/views/components/dev/CuteFormDrawer'
import { FormatRowDateTimeStr } from '@/utils/KitUtil' import { FormatRowDateTimeStr } from '@/utils/KitUtil'
import CuteButton from '@/views/components/dev/CuteButton.vue' import CuteButton from '@/views/components/dev/CuteButton.vue'
import CuteTransfer from '@/views/components/dev/CuteTransfer.vue' import CuteTransfer from '@/views/components/dev/CuteTransfer.vue'
import CuteEditTable from '@/views/components/dev/CuteEditTable.vue'
export default { export default {
name: 'CuteSimpleTableDemo', name: 'CuteSimpleTableDemo',
components: { CuteTransfer, CuteButton, CuteFormDrawer, CuteFormDialog, CuteSimpleTable }, components: { CuteEditTable, CuteTransfer, CuteButton, CuteFormDrawer, CuteFormDialog, CuteSimpleTable },
data() { data() {
return { return {
modeDataSource: [ modeDataSource: [
{ id: 1, name: '小明', description: '小明牛P' }, { id: 1, name: '小明', description: '小明牛P' },
{ id: 2, name: '小明', description: '小明牛P' }, { id: 4, name: '小绿', description: '小绿牛P' },
{ id: 3, name: '小明', description: '小明牛P' }, { id: 5, name: '小黄', description: '小黄牛P' },
{ id: 4, name: '小明', description: '小明牛P' }, { id: 6, name: '小紫', description: '小紫牛P' },
{ id: 5, name: '小明', description: '小明牛P' } { id: 17, name: '小郑', description: '小郑牛P' },
{ id: 18, name: '小王', description: '小王牛P' }
],
editTableSchema: [
{ name: 'name', title: '姓名', type: 'input' },
{ name: 'sex', title: '性别', type: 'select', dataSource: [{ label: '男', value: 'nn' }, { label: '女', value: 'mm' }] },
{ name: 'description', title: '描述', type: 'input' }
],
editTableDataSource: [
{ id: 1, name: '小明', sex: 'mm', description: '小明牛P' },
{ id: 4, name: '小绿', sex: 'nn', description: '小绿牛P' },
{ id: 5, name: '小黄', sex: 'nn', description: '小黄牛P' },
{ id: 6, name: '小紫', sex: 'nn', description: '小紫牛P' },
{ id: 17, name: '小郑', sex: 'mm', description: '小郑牛P' },
{ id: 18, name: '小王', sex: 'nn', description: '小王牛P' }
], ],
form: { form: {
model: { model: {