npm-vue3-element-table
v1.1.5
Published
注: 由于 sass 版本变更较大,如果遇到安装后报错的 可以查看本地之前安装的 sass 版本是否是 1.80.4 , sass-loader 是否是 16.0.2 如果不是这个版本,请升级一下 sass 版本,并且在 vite.config.ts 里面加上
Downloads
894
Maintainers
Readme
注: 由于 sass 版本变更较大,如果遇到安装后报错的 可以查看本地之前安装的 sass 版本是否是 1.80.4 , sass-loader 是否是 16.0.2 如果不是这个版本,请升级一下 sass 版本,并且在 vite.config.ts 里面加上
css: {
preprocessorOptions: {
scss: {
silenceDeprecations: ['legacy-js-api'], //去掉警告提示
}
}
}
如果引入 npm-vue3-element-table 报 ts 类型错误,在 src 文件夹下面创建 shims-vue.d.ts 文件,写入 declare module 'npm-vue3-element-table'
示例图片
github 项目使用链接地址
封装表格使用说明
调用方法
1.在 main.ts 中全局引入 import { MyBasicTable } from 'npm-vue3-element-table'
app.use(MyBasicTable)
2.在页面中单独引入 import { MyBasicTable } from 'npm-vue3-element-table'
接收参数
1.表格:tableObj(在父组件 computed 计算方法里面声明)
const tableObj = computed(() => {
let table = {
data: tableData.value,
option: tableOptions.value,
config: {
height:'300',//高度
showHeader:true,//是否显示表头
columnType:'selection', // selection(复选框) expand(展开) radio(单选框)
hasRadio:true/false, //是否显示单选框
hasSelection:true/false, //是否显示复选框
defaultSort: { prop: 'startTime', order: 'descending' }.//默认排序
rowKey:id, //为表格数据的唯一值,例如id、uuid
defaultExpandAll: false ,//有展开列时,用该参数设置是否默认展开所有列
reserveSelection:true// 仅对 type=selection 的列有效
},
operation: {
label: '操作',//操作列
width: operation.width || '120',
fixed: operation.fixed || false,
show: operation.show || false,
minWidth: operation.minWidth || '',
showIcon: operation.showIcon || false
}
}
return table
})
2.tableOptions:
tableOptions 中的每一项的 width,min-width 都支持设置
const tableOptions = computed(() => {
let tableOptions = [
{
prop: 'applyPersonName',
label: '申请人',
showOverflowToolTip: true,
show:true/false //当前列是否显示
},
{
prop: 'name', //如果无需修改,可以直接写后端返回的对应的 key
showOverflowToolTip: true, //展示超出时鼠标悬浮提示
fun: (row: any) => {
goDetail(row) //点击进入详情页
},
label: '申请名称' //列名
},
{
prop: 'applyPersonName',
label: '申请人',
showOverflowToolTip: true,
headerRender: (row: any) => { //自定义表头
return h(
ElButton,
{
onClick: btnClick
},
['row.action + row.target']
)
},
},
{
prop: 'status',
label: '状态',
showOverflowToolTip: true,
filter: true,
filterKey: 'status',
selectOptions: statusOptions.value,
render: (row: any) => {
return h(statusItem, {
row: row
})
}
},
//平台管理-账单管理-消费概览
{
prop: 'nameTxt',
label: '项目名称',
multipleTip: true, //鼠标悬浮,tooltip 有多个提示的情况
multipleTipContent: 'multipleTipContent' //tooltip 中展示的内容
},
// 表格展开示例
{
prop: 'expand',
label: '',
render: (row: any) => {
return h(
'span',
row.action ? row.status + '(' + row.userAccount + ')' : '-'
)
}
},
]
return tableOptions
})
3.分页:Pagination(没有特殊需求,在 data 中声明即可)
const Pagination = reactive({
pagingData: [10, 50, 100, 200],
pageSize: 10,
total: 0,
currentPage: 1,
show: true
})
4.方法
分页:@pagingEvent="pagingChange"
排序:@sortChange="sortChange"
列表中的筛选事件:@filterChange="filterChange"
当选择项发生变化时会触发该事件:@handleSelectionChange="handleSelectionChange"(handlerSelectAll,handlerSelect的触发 均会触发handleSelectionChange事件,一般情况下写这个事件就可以获取选中的行)
当用户手动勾选全选 Checkbox 时触发的事件:@handlerSelectAll="handlerSelectAll"
当用户手动勾选数据行的 Checkbox 时触发的事件:@handlerSelect="handlerSelect"
5.示例
父页面:
<template>
<my-basic-table
ref="logTable"
:Pagination="Pagination"
@pagingEvent="pagingChange"
:tableObj
@sortChange="sortChange"
@filterChange="filterChange"
></my-basic-table>
</template>
<script lang="ts" setup>
import { ref, computed, reactive, h } from 'vue'
import { ElButton } from 'element-plus'
import statusItem from './status-item.vue'
import editName from './edit-name.vue'
const moduleOptions = ref([
{ value: 'module_login', text: '登录' },
{ value: 'module_job', text: '作业管理' },
])
const statusOptions = ref([
{ value: 'success', text: '成功' },
{ value: 'fail', text: '失败' },
])
const tableData = ref([
{
type: 'file',
createtime: '2024-10-29 13:14:33',
createpin: '',
updatetime: null,
updatepin: '',
yn: 1,
uuid: '6d995990-f629-4072-b237-93dc01115d97',
userAccount: 'gjx',
userName: 'gjx1',
managerNum:3,
multipleTipContent:['account1','account2','account3'],
module: '登录',
action: '登录',
chinese: 2,
else: 3,
target: '',
targetUuid: '6c219b34-db38-48d4-8dd0-a6e84454eacd',
targetName: 'gjx',
status: '成功',
message: null,
messageExtra: null,
ip: '172.27.133.22',
startTime: '2024-10-29 13:14:33',
endTime: '2024-10-29 13:14:33',
},
])
const addOperation = (server: any) => {
const operation = []
operation.push({
value: '删除',
className:'del',
fun: (item, row) => {
return openDrawer('删除', row)
}
})
operation.push({
value: '编辑',
fun: (item, row) => {
return openDrawer('编辑', row)
}
})
return (server.operation = operation)
}
const openDrawer = (str: string, obj: object) => {}
tableData.value.map((item: any) => {
// @ts-ignore
item.operation = addOperation(item)
})
const Pagination = reactive({
pagingData: [10, 50, 100, 200],
pageSize: 10,
total: 100,
currentPage: 1,
show: true,
})
const tableOptions = computed(() => {
const tableOptions = [
// 表格展开示例
{
prop: 'expand',
label: '',
render: (row: any) => {
return h(
'span',
{
class: 'mgl60',
},
row.action ? row.status + '(' + row.userAccount + ')' : '-',
)
},
},
{
prop: 'name',
label: '操作人',
showOverflowToolTip: true,
render: (row: any) => {
return h(
'span',
row.userAccount ? row.userAccount + '(' + row.userName + ')' : '-',
)
},
},
{
prop: 'managerNum',
label: '管理员',
multipleTip: true,
multipleTipContent: 'multipleTipContent',
showOverflowToolTip: true
},
{
label: '作业量',
align: 'center',
showOverflowToolTip: true,
children: [
{
prop: 'chinese',
label: '语文',
showOverflowToolTip: true,
sortProp: 'chinese',
minWidth: 120,
},
{
prop: 'else',
label: '其它',
minWidth: 110,
filter: true,
filterKey: 'elseNum',
selectOptions: [
{ value: 'math', text: '数学' },
{ value: 'english', text: '英语' },
],
showOverflowToolTip: true,
},
],
},
{
prop: 'module',
label: '操作模块',
showOverflowToolTip: true,
width: 140,
filter: true,
filterKey: 'module',
selectOptions: moduleOptions.value,
},
{
prop: 'actionTxt',
showOverflowToolTip: true,
width: 140,
label: '执行动作', // 自定义渲染表头示例
headerRender: (row: any) => {
return h(
ElButton,
{
onClick: btnClick,
},
['自定义表头'],
)
},
render: (row: any) => {
return h('span', row.action + row.target)
},
},
{
prop: 'operationName',
showOverflowToolTip: true,
width: 200,
label: '操作对象',
render: (row: any) => {
return h(editName)
},
},
{
prop: 'status',
label: '状态',
filter: true,
filterKey: 'status',
selectOptions: statusOptions.value,
render: (row: any) => {
return h(statusItem, {
row: row,
})
},
},
{
prop: 'startTime',
label: '操作时间',
width: 160,
sortProp: 'startTime',
},
]
return tableOptions
})
const tableObj = computed(() => {
const table = {
data: tableData.value,
option: tableOptions.value,
operation:{show:true},
config: {
defaultSort: { prop: 'startTime', order: 'descending' },
},
}
return table
})
const pagingChange = (type: string, val: number) => {
console.log(type, val, '分页')
}
const filterChange = (obj: any) => {
console.log(obj, '筛选条件')
}
const btnClick = () => {
console.log('自定义表头按钮点击事件')
}
const sortChange = (obj: any) => {
console.log(obj, '排序条件')
}
</script>
<style lang="scss">
#app {
height: 100vh;
}
.mgl60 {
margin-left: 60px;
}
</style>
status-item子页面
<template>
<div class="">
<span class="status">
<span
class="status-circle"
:class="
row.status == '成功'
? 'success'
: row.status == '失败'
? 'fail'
: 'color-create-update-delete'
">
<!-- ● -->
</span>
<span
class="fs14"
:class="
row.status == '成功'
? 'success'
: row.status == '失败'
? 'fail'
: 'color-create-update-delete'
">
{{
row.status == '成功'
? '成功'
: row.status == '失败'
? '失败'
: '操作中'
}}
</span>
<el-popover
v-if="row.status == '失败'"
placement="top"
popper-class="ope-status-pop"
title="【失败原因】"
width="200"
trigger="hover">
<template #reference>
<img class="icon-img" src="../../assets/images/warning.png" alt="" />
</template>
<template #default>
<div class="ope-status-pop-content">
{{ row.message }}
</div>
</template>
</el-popover>
</span>
</div>
</template>
<script lang="ts" setup>
defineProps({ row: Object as any })
</script>
<style lang="scss" scoped>
.status {
// 成功
.success {
color: #333;
font-size: 1rem;
&::before {
background: #50b89c;
}
}
// 其他
.color-create-update-delete {
font-size: 1rem;
color: #333;
&::before {
background: #206bfa;
}
}
// 失败
.fail {
color: #333;
font-size: 1rem;
&::before {
background: #ec7c7c;
}
}
.status-circle {
&::before {
content: '';
display: inline-block;
width: 0.375rem;
height: 0.375rem;
border-radius: 50%;
position: relative;
top: -0.125rem;
margin-right: 0.25rem;
white-space: nowrap;
}
}
.fs14 {
font-size: 0.875rem !important;
}
.icon-img {
width: 0.875rem;
height: 0.875rem;
position: relative;
top: 0.125rem;
margin-left: 0.125rem;
}
}
</style>
<style lang="scss">
.ope-status-pop {
font-weight: 400;
font-size: 0.875rem;
color: #333;
letter-spacing: 0;
text-align: justify;
line-height: 1.375rem;
.ope-status-pop-content {
max-height: 300px;
overflow-y: auto;
}
.el-popover__title {
font-weight: 600;
font-size: 1rem;
color: #333;
}
}
.ope-status-pop .el-popper__arrow {
}
</style>
edit-name子页面
<template>
<div class="table-name-wrapper">
<el-icon>
<FolderOpened v-if="row.type == 'folder'" />
<Shop v-else />
</el-icon>
<div class="edit-show-box">
<template v-if="isEdit">
<el-input
v-model="inputShowName"
placeholder="请输入"
maxlength="255" />
<!-- 扩展名 -->
<span v-if="row.type == 'file'">{{ extendName }}</span>
<!-- 按钮 -->
<el-icon @click="confirm"><Check /></el-icon>
<el-icon><Close @click="cancel" /></el-icon>
</template>
<span v-else class="show-name-box">
<span :title="showName">{{ showName }}{{ extendName }}</span>
<el-icon @click="edit"><EditPen /></el-icon>
</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const props = defineProps<{
row: {
userName: string
type: 'file' | 'folder'
}
}>()
const $emit = defineEmits(['openDialog'])
const isEdit = ref(false)
const inputShowName = ref('') // input内绑定名称
const showName = ref('') // 表格内显示名称
const extendName = ref('') // 扩展名
function edit() {
isEdit.value = true
inputShowName.value = showName.value
}
function confirm() {
isEdit.value = false
showName.value = inputShowName.value
ElMessage({
message: '编辑成功',
type: 'success'
})
}
function cancel() {
isEdit.value = false
}
function init() {
console.log(props.row, 'row')
showName.value = props.row.userName
}
init()
</script>
<style scoped lang="scss">
.table-name-wrapper {
display: flex;
align-items: center;
.icon-wenjianjia1 {
color: #ffca28;
}
.icon-yingyong {
color: #1496db;
}
.edit-show-box {
margin-left: 8px;
display: flex;
align-items: center;
flex: 1;
width: calc(100% - 8px - 1rem);
.el-icon {
font-size: 16px;
cursor: pointer;
margin-left: 8px;
}
.show-name-box {
display: flex;
align-items: center;
width: 100%;
> span {
color: #206bfa;
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.el-icon {
color: #206bfa;
}
}
}
}
</style>