first commit

This commit is contained in:
2026-08-26 14:25:17 +08:00
commit 06debfd1fc
10595 changed files with 1836924 additions and 0 deletions
@@ -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>