4 changed files with 207 additions and 107 deletions
@ -1,96 +1,145 @@ |
|||
<template> |
|||
<el-table |
|||
class="guip-table" |
|||
ref="guiptable" |
|||
v-bind="$attrs" |
|||
:data="tableData" |
|||
v-on="$listeners" |
|||
:border="border" |
|||
@selection-change="handleSelectionChange" |
|||
:style="{ width: width || '100%', height: height || '100%' }" |
|||
v-loading="loading"> |
|||
|
|||
<!-- 多选列 --> |
|||
<el-table-column |
|||
v-if="multiple" |
|||
type="selection" |
|||
width="55"> |
|||
</el-table-column> |
|||
|
|||
<!-- 优先使用插槽内容 --> |
|||
<slot> |
|||
<!-- 如果没有插槽内容,则使用 columns 渲染 --> |
|||
<template v-if="columns"> |
|||
<el-table-column |
|||
v-for="column in columns" |
|||
:key="column.prop" |
|||
:prop="column.prop" |
|||
:label="column.label" |
|||
:width="column.width"> |
|||
|
|||
<template #default="{ row }" v-if="column.popover"> |
|||
<el-popover :visible="row[`popoverVisible_${column.prop}`]" placement="top" trigger="click"> |
|||
<slot :name="`popover-content-${column.prop}`" :row="row" :column="column"> |
|||
<div> |
|||
<p>默认内容:{{ `popoverVisible_${column.prop}` }}</p> |
|||
<el-input v-model="row[`edit_${column.prop}`]" :placeholder="`请输入${column.label}`" /> |
|||
</div> |
|||
</slot> |
|||
<div class="flex" style="text-align: right; margin-top: 32px;justify-content: flex-end;"> |
|||
<GuipButton size="medium" @click="handleCancel(row, column.prop)">取消</GuipButton> |
|||
<GuipButton type="primary" @click="handleConfirm(row, column.prop)" size="medium">确定</GuipButton> |
|||
</div> |
|||
<template #reference> |
|||
<span style="cursor: pointer">{{ row[column.prop] }}</span> |
|||
</template> |
|||
</el-popover> |
|||
</template> |
|||
</el-table-column> |
|||
</template> |
|||
</slot> |
|||
|
|||
<template #empty> |
|||
<el-empty :image="emptyImg"></el-empty> |
|||
</template> |
|||
</el-table> |
|||
<div class="table-container"> |
|||
|
|||
<el-table ref="guiptable" v-bind="$attrs" :data="tableData" v-on="$listeners" :border="border" @selection-change="handleSelectionChange" |
|||
:style="{ width: width ? width : '100%', height: height ? height : '100%' }" v-loading="loading" empty-text=" "> |
|||
<!-- 多选 --> |
|||
<template v-if="multiple"> |
|||
<el-table-column type="selection" width="55"> |
|||
</el-table-column> |
|||
</template> |
|||
<!-- 自定义header --> |
|||
<slot></slot> |
|||
<!-- 通过json数据遍历渲染 --> |
|||
<template v-if="columns"> |
|||
<el-table-column v-for="column in columns" :key="column.prop" :prop="column.prop" :label="column.label" |
|||
:width="column.width"> |
|||
<template #default="{ row }" v-if="column.popover"> |
|||
<el-popover :visible="row[`popoverVisible_${column.prop}`]" class="tablePopover" placement="top" |
|||
trigger="click"> |
|||
<!-- 自定义内容插槽 --> |
|||
<slot :name="`popover-content-${column.prop}`" :row="row" :column="column"> |
|||
<div> |
|||
<p>默认内容:{{ `popoverVisible_${column.prop}` }}</p> |
|||
<el-input v-model="row[`edit_${column.prop}`]" :placeholder="`请输入${column.label}`" /> |
|||
</div> |
|||
</slot> |
|||
<!-- 确定和取消按钮 --> |
|||
<div class="flex" style="text-align: right; margin-top: 32px;justify-content: flex-end;"> |
|||
<GuipButton size="medium" @click="handleCancel(row, column.prop)">取消</GuipButton> |
|||
<GuipButton type="primary" @click="handleConfirm(row, column.prop)" size="medium">确定</GuipButton> |
|||
</div> |
|||
<!-- 单元格内容 --> |
|||
<template #reference> |
|||
<span style="cursor: pointer">{{ row[column.prop] }}</span> |
|||
</template> |
|||
</el-popover> |
|||
</template> |
|||
|
|||
</el-table-column> |
|||
</template> |
|||
</el-table> |
|||
<div v-if="tableData && tableData.length === 0" class="custom-empty"> |
|||
<img :src="emptyImg" alt="无数据" /> |
|||
<p>暂无数据</p> |
|||
</div> |
|||
</div> |
|||
|
|||
</template> |
|||
|
|||
<script> |
|||
import GuipButton from '../../GuipButton/src/index.vue'; |
|||
|
|||
export default { |
|||
name: 'GuipTable', |
|||
props: { |
|||
tableData: Array, |
|||
loading: Boolean, |
|||
width: String, |
|||
height: String, |
|||
columns: Array, |
|||
border: Boolean, |
|||
multiple: Boolean |
|||
}, |
|||
components: { |
|||
GuipButton |
|||
}, |
|||
data() { |
|||
return { |
|||
emptyImg: require('../../assets/table_empty.png') |
|||
} |
|||
}, |
|||
methods: { |
|||
handleSelectionChange(row) { |
|||
this.$emit('selectChange', row) |
|||
}, |
|||
handleConfirm(row, prop) { |
|||
row[prop] = row[`edit_${prop}`]; |
|||
row[`popoverVisible_${prop}`] = false; |
|||
this.$emit('confirm', row, prop); |
|||
}, |
|||
handleCancel(row, prop) { |
|||
row[`edit_${prop}`] = row[prop]; |
|||
row[`popoverVisible_${prop}`] = false; |
|||
this.$emit('cancel', row, prop); |
|||
} |
|||
} |
|||
name: 'GuipTextarea', |
|||
props: ['tableData', 'loading', 'width', 'height', 'autoColumn', 'columns', 'border', 'multiple'], |
|||
data() { |
|||
return { |
|||
emptyImg:require('../../assets/table_empty.png') |
|||
// loading:false |
|||
} |
|||
}, |
|||
components: { |
|||
GuipButton, |
|||
}, |
|||
mounted() { |
|||
}, |
|||
methods: { |
|||
handleSelectionChange(row) { |
|||
// 获取的当前行信息 |
|||
console.log(row, '======'); |
|||
this.$emit('selectChange', row) |
|||
}, |
|||
// 点击确定按钮 |
|||
handleConfirm(row, prop) { |
|||
// 将编辑后的值同步到原始数据 |
|||
row[prop] = row[`edit_${prop}`]; |
|||
row[`popoverVisible_${prop}`] = false; // 关闭气泡框 |
|||
this.$emit('confirm', row, prop); // 触发确认事件 |
|||
}, |
|||
// 点击取消按钮 |
|||
handleCancel(row, prop) { |
|||
// 恢复原始数据 |
|||
row[`edit_${prop}`] = row[prop]; |
|||
row[`popoverVisible_${prop}`] = false; // 关闭气泡框 |
|||
this.$emit('cancel', row, prop); // 触发取消事件 |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
<style scoped lang="scss"> |
|||
|
|||
/* 外层容器需设为 relative,以便空状态定位 */ |
|||
.table-container { |
|||
position: relative; |
|||
width: 100%; |
|||
} |
|||
|
|||
/* 空状态固定定位(不随滚动移动) */ |
|||
.custom-empty { |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -35%); |
|||
width: 200px; |
|||
text-align: center; |
|||
background-color: #fff; /* 避免透明背景被表格线干扰 */ |
|||
// padding: 20px; |
|||
z-index: 10; /* 确保显示在表格上方 */ |
|||
img{ |
|||
width: 80px; |
|||
height: 80px; |
|||
} |
|||
p{ |
|||
font-size: 12px; |
|||
font-weight: normal; |
|||
line-height: 13px; |
|||
letter-spacing: 0.08em; |
|||
color: #626573; |
|||
} |
|||
} |
|||
|
|||
/* 确保表格有最小高度(避免高度塌陷) */ |
|||
.el-table ::v-deep .el-table__body-wrapper { |
|||
min-height: 162px !important; |
|||
} |
|||
|
|||
.empty-image { |
|||
width: 160px; |
|||
height: 160px; |
|||
} |
|||
|
|||
.empty-text { |
|||
color: #626573; |
|||
letter-spacing: 0.08em; |
|||
height: 18px; |
|||
line-height: 18px; |
|||
} |
|||
.el-empty{ |
|||
padding: 0; |
|||
} |
|||
.guip-table ::v-deep .el-empty__description{ |
|||
line-height: 20px; |
|||
margin-top: 0; |
|||
} |
|||
</script> |
|||
</style> |
|||
|
|||
Loading…
Reference in new issue