<template>
<div class="table">
<sv-table :data="tableOptions.list" :height="800" :span-method="mergeRow">
<template v-for="(item, index) in tableOptions.columns" :key="index">
<sv-column
:title="item.title"
:field="item.field"
:minWidth="item.minWidth || 120"
:formatter="item.dict ? ['formatDict', item.dict] : null"
>
<template #default="{ row }">
<template v-if="item.type === 'action'">
<a-button>编辑</a-button>
</template>
<span v-else>
{{ row[item.field] }}
</span>
</template>
</sv-column>
</template>
</sv-table>
</div>
</template>
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
import { productList } from './mock'
const tableOptions = ref({})
const FIXED_COLUMNS = [
{ title: '操作', field: 'action', type: 'action' },
{ title: 'pid', field: 'pid' },
{ title: '供应商编码', field: 'vendorCode' },
{ title: '供应商名称', field: 'vendorName' },
{ title: '货品编码', field: 'goodsCode' },
{ title: '货品名称', field: 'goodsName' },
{ title: '货品规格', field: 'goodsModel' },
{ title: '生产订单完成进度', field: 'compRate', minWidth: 150 },
{ title: '排产订单总数', field: 'totalPlanQty' },
{ title: '实际生产订单数', field: 'totalActualQty' },
{ title: '项目名称', field: 'project', dict: [] }
]
const MERGE_GROUP_FIELDS = ['compRate', 'totalPlanQty', 'totalActualQty']
const MERGE_FIELDS = [
'pid',
'vendorCode',
'vendorName',
'goodsName',
'goodsCode',
'action'
]
function generateDateColumns(start, end) {
const list = []
let current = dayjs(start)
while (!current.isAfter(end)) {
list.push({
title: current.format('YYYY-MM-DD'),
field: current.format('YYYY-MM-DD')
})
current = current.add(1, 'day')
}
return list
}
function generateTableOptions(start, end) {
const dateColumns = generateDateColumns(start, end)
const columns = [...FIXED_COLUMNS, ...dateColumns]
return {
columns
}
}
function setParentId(item, fields) {
return fields.map((key) => item[key]).join('-')
}
function handleList(list) {
const result = []
for (const item of list) {
const parentId = setParentId(item, ['vendorCode', 'goodsCode'])
const { group } = item
for (const groupItem of group) {
const { projectList, totalActualQty, totalPlanQty, compRate } = groupItem
for (const { dataList, projectCode } of projectList) {
const newItem = {
...item,
pid: parentId,
groupId: `${parentId}-${group.indexOf(groupItem)}`,
project: projectCode,
totalActualQty,
totalPlanQty,
compRate
}
for (const key in dataList) {
dataList.forEach((d) => {
newItem[d.invDate] = d.qty
})
}
result.push(newItem)
}
}
}
return result
}
function getMergeSpan(list, type) {
const map = new Map()
list.forEach((row) => {
const val = row[type]
if (!map.has(val)) {
map.set(val, {
span: 1
})
} else {
map.get(val).span++
}
})
return map
}
const mergeRow = ({ row, rowIndex, column, visibleData }) => {
const columnFieldName = column.field
const isFieldMergeable = MERGE_FIELDS.includes(columnFieldName)
const isGroupMergeable = MERGE_GROUP_FIELDS.includes(columnFieldName)
function handleMerge(groupKey) {
const groupValue = row[groupKey]
const groupSpan = getMergeSpan(tableOptions.value.list, groupKey)
const index = tableOptions.value.list.findIndex(
(r) => r[groupKey] === groupValue
)
if (rowIndex === index) {
return {
rowspan: groupSpan.get(groupValue).span,
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
if (isFieldMergeable) {
return handleMerge('pid')
}
if (isGroupMergeable) {
return handleMerge('groupId')
}
return {
rowspan: 1,
colspan: 1
}
}
function getList() {
return new Promise((resolve, reject) => {
resolve(productList)
})
}
async function init() {
const start = dayjs('2024-04-10')
const end = dayjs(start).add(3, 'day')
const { columns } = generateTableOptions(start, end)
const list = await getList()
tableOptions.value = {
columns,
list: handleList(list)
}
}
init()
</script>
<style scoped>
.table {
padding: 10px;
}
</style>
const dataList = new Array(5).fill(0).map((_, index) => {
return {
dataList: [
{
invDate: '2024-04-10',
qty: 10
},
{
invDate: '2024-04-11',
qty: 1
},
{
invDate: '2024-04-12',
qty: 1
}
],
projectCode: index
}
})
const productList = new Array(2).fill(0).map((_, index) => {
return {
vendorCode: 'SM246' + index,
vendorName: '义乌市钻杰饰品有限公司' + index,
goodsCode: '711073' + index,
goodsModel: '个',
goodsName: '金色米饭碗碗身' + index,
group: [
{
compRate: '10%',
totalActualQty: 7 + index,
totalPlanQty: 4 + index,
projectList: dataList.slice(0, 2)
},
{
compRate: '20%',
totalActualQty: 7 + index,
totalPlanQty: 4 + index,
projectList: dataList.slice(2)
}
]
}
})
export { productList }
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d54b304c657a43f097ec91af7673e172.jpeg#pic_center)