分享通过 vxe-table 实现电商系统商品列表页面,包含多行文本、展开子列表功能等
具体可以去看官网文档:vxetable.cn
Gitee:gitee.com/x-extends/v…
Github:github.com/x-extends/v…
安装
npm install vxe-pc-ui@4.3.90 vxe-table@4.11.3
// ...
import VxeUI from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'
import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'
// ...
createApp(App).use(VxeUI).use(VxeUITable).mount('#app')
// ...
效果
代码
<template>
<div class="demo-page-wrapper">
<vxe-grid v-bind="gridOptions" v-on="gridEvents">
<template #productNameDefault="{ row }">
<vxe-text-ellipsis status="primary" line-clamp="3" :content="row.productName" href="https://vxeui.com" target="_blank"></vxe-text-ellipsis>
<div>颜色:{{ row.productColor }} 尺寸:{{ row.productSize }}</div>
</template>
<template #productSKUDefault="{ row }">
<div>SKU:<vxe-text :content="row.productSKU" click-to-copy></vxe-text></div>
<div>编码:<vxe-text :content="row.productCode" click-to-copy></vxe-text></div>
</template>
<template #productAmountDefault="{ row }">
<div>现价:¥{{ row.productAmount }}</div>
<div>折扣价:¥{{ row.productDiscountAmount }}</div>
<div>秒杀价:¥{{ row.productLkAmount }}</div>
</template>
<template #productNumDefault="{ row }">
<div>库存:{{ row.productStoreNum }}</div>
<div>已上架:{{ row.productAddNum }}</div>
<div>已下架:{{ row.productRemoveNum }}</div>
</template>
<template #productStatusDefault="{ row }">
<vxe-tag :status="row.productStatus" :content="row.productStatus === 'success' ? '已上架' : '已下架'"></vxe-tag>
</template>
<template #productOwnerDefault="{ row }">
<div>负责人:{{ row.productOwner }}</div>
<div>创建人:{{ row.createBy }}</div>
<div>更新人:{{ row.updateBy }}</div>
</template>
<template #updateDateDefault="{ row }">
<div>上架时间:{{ row.addDate }}</div>
<div>下架时间:{{ row.removeDate }}</div>
<div>更新时间:{{ row.updateDate }}</div>
<div>更新时间:{{ row.updateDate }}</div>
</template>
<template #expandContent="{ row }">
<vxe-grid v-bind="subGridOptions" :data="row.subList">
<template #statusDefault="{ row }">
<vxe-tag :status="row.status" :content="row.status === 'success' ? '成功' : '失败'"></vxe-tag>
</template>
</vxe-grid>
</template>
</vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const productUrlCellRender = reactive({
name: 'VxeImage',
props: {
width: 100,
height: 100
}
})
const countRow = reactive({
checkbox: '合计',
productName: 0,
productAmount: 0
})
const gridOptions = reactive({
border: true,
loading: false,
stripe: true,
showOverflow: true,
showFooter: true,
height: '100%',
cellConfig: {
height: 140
},
columnConfig: {
resizable: true,
drag: true
},
columnDragConfig: {
trigger: 'cell',
showIcon: false
},
rowConfig: {
drag: true
},
resizableConfig: {
isDblclickAutoWidth: true
},
expandConfig: {
padding: true
},
formConfig: {
titleWidth: 80,
titleAlign: 'right',
items: [
{ field: 'productName', title: '产品名字', span: 6, itemRender: { name: 'VxeInput' } },
{ field: 'productSKU', title: 'SKU', span: 6, itemRender: { name: 'VxeInput' } },
{ field: 'productCode', title: '产品编码', span: 6, itemRender: { name: 'VxeInput' } },
{ field: 'email', title: '邮箱', span: 6, folding: true, itemRender: { name: 'VxeInput' } },
{ field: 'nickname', title: '昵称', span: 6, folding: true, itemRender: { name: 'VxeInput' } },
{ field: 'startTime', title: '开始时间', span: 6, folding: true, itemRender: { name: 'VxeDatePicker' } },
{ field: 'endTime', title: '结束时间', span: 6, folding: true, itemRender: { name: 'VxeDatePicker' } },
{
span: 6,
collapseNode: true,
itemRender: {
name: 'VxeButtonGroup',
options: [
{ type: 'submit', content: '查询', status: 'primary', icon: 'vxe-icon-search' },
{ type: 'reset', content: '重置', icon: 'vxe-icon-repeat' }
]
}
}
]
},
toolbarConfig: {
custom: true,
refresh: true,
zoom: true
},
checkboxConfig: {
range: true
},
mouseConfig: {
selected: true
},
keyboardConfig: {
isEdit: true,
isArrow: true,
isEnter: true,
isBack: true,
isDel: true,
isEsc: true
},
pagerConfig: {
pageSize: 100,
pageSizes: [3, 20, 100, 500, 1000, 5000, 10000, 50000, 100000]
},
scrollX: {
gt: 0,
enabled: true
},
scrollY: {
gt: 0,
mode: 'wheel',
enabled: true
},
columns: [
{ field: 'checkbox', type: 'checkbox', width: 60, align: 'center' },
{ field: 'seq', type: 'seq', width: 100, align: 'center', dragSort: true },
{ field: 'expand', type: 'expand', width: 60, align: 'center', slots: { content: 'expandContent' } },
{ field: 'productUrl', title: '产品图片', width: 160, align: 'center', cellRender: productUrlCellRender },
{ field: 'productName', title: '产品名称', minWidth: 200, slots: { default: 'productNameDefault' } },
{ field: 'productSKU', title: 'SKU', minWidth: 200, slots: { default: 'productSKUDefault' } },
{ field: 'productAmount', title: '价格', width: 160, slots: { default: 'productAmountDefault' } },
{ field: 'productNum', title: '数量', width: 120, slots: { default: 'productNumDefault' } },
{ field: 'productStatus', title: '状态', width: 100, align: 'center', slots: { default: 'productStatusDefault' } },
{ field: 'productOwner', title: '负责人', width: 160, slots: { default: 'productOwnerDefault' } },
{ field: 'updateDate', title: '更新时间', width: 240, slots: { default: 'updateDateDefault' } }
],
proxyConfig: {
response: {
result: 'data',
total: 'total'
},
ajax: {
query ({ page }) {
// 调用后端接口,返回 { total: 1000, data: [] }
return axios.get(`https://vxeui.com/test/list/${page.pageSize}/${page.currentPage}`).then(res => res.data)
}
}
},
footerData: [
countRow
]
})
const gridEvents = {
pageChange ({ pageSize }) {
gridOptions.pagerConfig.pageSize = pageSize
},
proxyQuery () {
updateFooterCount()
}
}
const imgUrlCellRender = reactive({
name: 'VxeImage',
props: {
width: 40,
height: 40
}
})
const subGridOptions = reactive({
border: true,
showOverflow: true,
columns: [
{ field: 'imgUrl', title: '关联产品', width: 80, align: 'center', cellRender: imgUrlCellRender },
{ field: 'name', title: '名称' },
{ field: 'storeNum', title: '库存', width: 120, align: 'center' },
{ field: 'status', title: '状态', width: 120, align: 'center', slots: { default: 'statusDefault' } },
{ field: 'color', title: '颜色', width: 120, align: 'center' },
{ field: 'size', title: '尺寸', width: 120, align: 'center' }
]
})
const updateFooterCount = () => {
countRow.productName = 999
countRow.productAmount = 888
}
</script>