first commit
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
<template>
|
||||
<div class="ele-table-tool">
|
||||
<div class="ele-table-tool-title">
|
||||
<div class="ele-table-tool-title-label">
|
||||
<slot v-if="$slots.label" name="label"></slot>
|
||||
<span v-else>{{ label }}</span>
|
||||
</div>
|
||||
<div class="ele-table-tool-title-content">
|
||||
<slot v-if="$slots.content" name="content"></slot>
|
||||
<span v-else>{{ content }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ele-tool">
|
||||
<div class="ele-space">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="ele-tool-item ele-action" v-if="columns && columns.length > 0">
|
||||
<!--控制列-->
|
||||
<i class="el-icon-menu" @click="openColumns" ></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog title="列设置" :visible.sync="columnDialog" width="40%">
|
||||
<div class="column-setting-container">
|
||||
<div class="column-setting-header">
|
||||
<el-checkbox
|
||||
:indeterminate="isIndeterminate"
|
||||
v-model="checkAll"
|
||||
@change="handleCheckAllChange">
|
||||
全选
|
||||
</el-checkbox>
|
||||
<span class="column-count">已选择 {{ checkedColumns.length }} / {{ tempColumns.length }} 列</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="tempColumns"
|
||||
ref="columnTableRef"
|
||||
@selection-change="handleSelectionChange"
|
||||
row-key="prop"
|
||||
class="column-setting-table"
|
||||
max-height="500px">
|
||||
<el-table-column type="selection" width="55" :selectable="isColumnSelectable"></el-table-column>
|
||||
<el-table-column label="标题" prop="label" min-width="120"></el-table-column>
|
||||
<!-- <el-table-column label="字段" prop="prop" min-width="100"></el-table-column>-->
|
||||
<el-table-column label="宽度PX" prop="width" min-width="120">
|
||||
<template slot-scope="{row}">
|
||||
<el-input
|
||||
v-model="row.width"
|
||||
type="number"
|
||||
size="mini"
|
||||
placeholder="自动">
|
||||
</el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="固定" prop="fixed" min-width="120">
|
||||
<template slot-scope="{row}">
|
||||
<el-radio-group v-model="row.fixed" size="mini" boder>
|
||||
<el-radio-button label="left">左侧</el-radio-button>
|
||||
<el-radio-button label="">自动</el-radio-button>
|
||||
<el-radio-button label="right">右侧</el-radio-button>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="columnDialog = false">取 消</el-button>
|
||||
<el-button type="primary" @click="doColumns">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
name: "index",
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: "表格数据"
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
columnDialog: false,
|
||||
checkedColumns: [],
|
||||
checkAll: false,
|
||||
isIndeterminate: false,
|
||||
sortable: null, // Sortable实例
|
||||
tempColumns: [] // 临时存储列配置,避免直接修改props
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 打开列设置
|
||||
openColumns() {
|
||||
// 创建临时列配置的深拷贝,避免直接修改props
|
||||
this.tempColumns = JSON.parse(JSON.stringify(this.columns))
|
||||
this.columnDialog = true
|
||||
this.initColumnSelection()
|
||||
this.initSortable()
|
||||
},
|
||||
|
||||
// 初始化拖拽排序
|
||||
initSortable() {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.columnTableRef && this.$refs.columnTableRef.$el) {
|
||||
const tbody = this.$refs.columnTableRef.$el.querySelector('.el-table__body-wrapper tbody')
|
||||
if (tbody && !this.sortable) {
|
||||
this.sortable = new Sortable(tbody, {
|
||||
animation: 150,
|
||||
ghostClass: 'sortable-ghost',
|
||||
chosenClass: 'sortable-chosen',
|
||||
dragClass: 'sortable-drag',
|
||||
onEnd: (evt) => {
|
||||
const {oldIndex, newIndex} = evt
|
||||
if (oldIndex !== newIndex) {
|
||||
// 在tempColumns中重新排序
|
||||
const movedItem = this.tempColumns.splice(oldIndex, 1)[0]
|
||||
this.tempColumns.splice(newIndex, 0, movedItem)
|
||||
|
||||
// 重新初始化选择状态
|
||||
this.$nextTick(() => {
|
||||
this.initColumnSelection()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 初始化列选择状态
|
||||
initColumnSelection() {
|
||||
// 设置默认选中状态(默认全部显示,除非明确指定visible为false)
|
||||
this.checkedColumns = this.tempColumns.filter(col => col.visible !== false)
|
||||
|
||||
// 更新全选状态
|
||||
this.updateCheckAllStatus()
|
||||
|
||||
// 设置表格选中状态
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.columnTableRef) {
|
||||
this.tempColumns.forEach(row => {
|
||||
if (row.visible !== false) {
|
||||
this.$refs.columnTableRef.toggleRowSelection(row, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 处理列选择变化
|
||||
handleSelectionChange(selection) {
|
||||
this.checkedColumns = selection
|
||||
this.updateCheckAllStatus()
|
||||
},
|
||||
|
||||
// 更新全选状态
|
||||
updateCheckAllStatus() {
|
||||
const selectableColumns = this.tempColumns.filter(col => this.isColumnSelectable(col))
|
||||
this.checkAll = this.checkedColumns.length === selectableColumns.length
|
||||
this.isIndeterminate = this.checkedColumns.length > 0 && this.checkedColumns.length < selectableColumns.length
|
||||
},
|
||||
|
||||
// 处理全选变化
|
||||
handleCheckAllChange(val) {
|
||||
const selectableColumns = this.tempColumns.filter(col => this.isColumnSelectable(col))
|
||||
|
||||
if (val) {
|
||||
this.checkedColumns = [...selectableColumns]
|
||||
selectableColumns.forEach(row => {
|
||||
this.$refs.columnTableRef.toggleRowSelection(row, true)
|
||||
})
|
||||
} else {
|
||||
this.checkedColumns = []
|
||||
this.$refs.columnTableRef.clearSelection()
|
||||
}
|
||||
this.isIndeterminate = false
|
||||
},
|
||||
|
||||
// 判断列是否可选择
|
||||
isColumnSelectable(row) {
|
||||
return row.required !== true && row.type !== 'selection' && row.type !== 'index'
|
||||
},
|
||||
|
||||
// 确定保存列设置
|
||||
doColumns() {
|
||||
// 基于tempColumns创建新的列配置数组,保留用户修改的宽度和固定值
|
||||
const updatedColumns = this.tempColumns.map(col => {
|
||||
return {
|
||||
...col,
|
||||
visible: this.checkedColumns.map(cc => cc.prop).includes(col.prop)
|
||||
}
|
||||
})
|
||||
|
||||
this.$emit('update:columns', updatedColumns)
|
||||
this.columnDialog = false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
columns: {
|
||||
handler() {
|
||||
// 只有在对话框未打开时才初始化,避免覆盖用户正在编辑的tempColumns
|
||||
if (!this.columnDialog) {
|
||||
this.initColumnSelection()
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
||||
columnDialog(val) {
|
||||
if (!val && this.sortable) {
|
||||
this.sortable.destroy()
|
||||
this.sortable = null
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.sortable) {
|
||||
this.sortable.destroy()
|
||||
this.sortable = null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ele-table-tool:not(.ele-table-tool-default):not(.ele-table-tools-none) .ele-tool .ele-tool-item {
|
||||
padding: 6px;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
border: unset;
|
||||
border-radius: unset;
|
||||
font-size: 14px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-table-tool-title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ele-table-tool-title-label {
|
||||
position: relative;
|
||||
padding-left: 1em;
|
||||
color: var(--color-primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ele-table-tool-title-label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 5px;
|
||||
height: 1.3em;
|
||||
background-color: var(--color-primary);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.ele-table-tool {
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-ms-flex-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ele-table-tool,
|
||||
.ele-table-tool .ele-table-tool-title {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-table-tool-title {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: auto;
|
||||
flex: auto;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
-ms-flex-align: center;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-table-tool-title > .ele-table-tool-title-label {
|
||||
margin-right: 8px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-table-tool-title > .ele-table-tool-title-content {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-tool {
|
||||
margin: 5px 0 5px auto;
|
||||
display: -webkit-inline-box;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-tool .ele-tool-item {
|
||||
font-size: 18px;
|
||||
padding: 0 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-tool .ele-tool-item .el-dropdown > i {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.ele-table-tool .ele-tool .ele-tool-item + .ele-tool-item {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.ele-table-tool.ele-toolbar-form .ele-table-tool-title {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ele-table-tool.ele-toolbar-form .ele-table-tool-title .el-form-item,
|
||||
.ele-table-tool.ele-toolbar-form .ele-table-tool-title .ele-form-actions {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.ele-table-tool.ele-toolbar-actions .ele-table-tool-title {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ele-table-tool.ele-toolbar-actions .ele-table-tool-title > .el-button,
|
||||
.ele-table-tool.ele-toolbar-actions .ele-table-tool-title > .el-dropdown,
|
||||
.ele-table-tool.ele-toolbar-actions .ele-table-tool-title > .el-link,
|
||||
.ele-table-tool.ele-toolbar-actions .ele-table-tool-title > .el-tag,
|
||||
.ele-table-tool.ele-toolbar-actions .ele-table-tool-title > .ele-action {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.ele-table-tool:not(.ele-table-tool-default):not(.ele-table-tools-none) .ele-tool .ele-tool-item {
|
||||
padding: 6px;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
border: 1px solid var(--border-color-base);
|
||||
border-radius: 50%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ele-table-tool:not(.ele-table-tool-default):not(.ele-table-tools-none) .ele-tool .ele-tool-item .el-dropdown > i {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ele-table-tool:not(.ele-table-tool-default):not(.ele-table-tools-none) .ele-tool .ele-tool-item:hover {
|
||||
color: var(--color-primary);
|
||||
border-color: var(--color-primary-3);
|
||||
background-color: var(--color-primary-1);
|
||||
}
|
||||
|
||||
.ele-table-tool:not(.ele-table-tool-default):not(.ele-table-tools-none) .ele-tool .ele-tool-item:hover .el-dropdown > i {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.ele-table-tool-default {
|
||||
margin-bottom: 0;
|
||||
padding: 5px 15px;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
background: var(--table-header-background-color);
|
||||
border-top: 1px solid var(--border-color-lighter);
|
||||
border-left: 1px solid var(--border-color-lighter);
|
||||
border-right: 1px solid var(--border-color-lighter);
|
||||
}
|
||||
|
||||
.ele-table-tool-default .ele-tool .ele-tool-item {
|
||||
font-size: 16px;
|
||||
padding: 5px 6px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--border-color-light);
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.ele-table-tool-default .ele-tool .ele-tool-item .el-dropdown > i {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.ele-tab-tool {
|
||||
padding: 0 15px;
|
||||
-ms-flex-negative: 0;
|
||||
flex-shrink: 0;
|
||||
width: auto;
|
||||
min-width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
-webkit-transition: background-color 0.3s,
|
||||
color 0.3s;
|
||||
transition: background-color 0.3s,
|
||||
color 0.3s;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ele-tab-tool .el-icon-house {
|
||||
font-size: 16px;
|
||||
vertical-align: -1px;
|
||||
}
|
||||
|
||||
.ele-tab-tool.is-tab:hover {
|
||||
color: var(--color-primary);
|
||||
background: var(--header-tool-hover-bg);
|
||||
}
|
||||
|
||||
.ele-tab-tool.is-tab:after {
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 2px;
|
||||
background: var(--color-primary);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ele-tab-tool.is-tab.is-active {
|
||||
color: var(--color-primary);
|
||||
background: var(--color-primary-1);
|
||||
}
|
||||
|
||||
.ele-tab-tool.is-tab.is-active:after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.column-setting-container {
|
||||
/*max-height: calc(100vh - 182px);
|
||||
overflow-y: auto;*/
|
||||
}
|
||||
|
||||
.column-setting-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.column-count {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.column-setting-table {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* 拖拽排序样式 */
|
||||
.sortable-ghost {
|
||||
opacity: 0.5;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.sortable-chosen {
|
||||
background-color: #e6f7ff;
|
||||
border: 1px dashed #1890ff;
|
||||
}
|
||||
|
||||
.sortable-drag {
|
||||
opacity: 0.8;
|
||||
transform: rotate(5deg);
|
||||
}
|
||||
|
||||
/* 表格行拖拽提示 */
|
||||
.column-setting-table .el-table__row {
|
||||
cursor: move;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.column-setting-table .el-table__row:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
/* 拖拽提示文本 */
|
||||
.column-setting-container::before {
|
||||
content: "💡 提示:可以拖拽表格行来调整列的显示顺序";
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
padding: 8px;
|
||||
background-color: #fafafa;
|
||||
border-left: 3px solid var(--color-primary);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user