电子请购单优化 库存明细页面
This commit is contained in:
235
klp-ui/src/views/wms/stock/detail.vue
Normal file
235
klp-ui/src/views/wms/stock/detail.vue
Normal file
@@ -0,0 +1,235 @@
|
||||
<template>
|
||||
<div class="app-container" v-loading="loading">
|
||||
<!-- 标题 -->
|
||||
<h2 style="text-align: center; margin-bottom: 16px;">{{ title }}</h2>
|
||||
|
||||
<!-- 空数据 -->
|
||||
<el-empty v-if="!loading && tableData.length === 0" description="暂无数据" />
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table
|
||||
v-if="tableData.length > 0"
|
||||
:data="tableData"
|
||||
border
|
||||
style="width: 100%"
|
||||
:header-cell-style="{ background: '#f2f2f2', fontWeight: 600, textAlign: 'center' }"
|
||||
:cell-style="cellStyle"
|
||||
size="small"
|
||||
>
|
||||
<el-table-column label="业务员" prop="dimension" min-width="100" align="center" />
|
||||
|
||||
<el-table-column v-for="cat in CATEGORIES" :key="cat.key" :label="cat.label" align="center">
|
||||
<el-table-column :label="'A/B'" :prop="cat.key + '_AB'" width="85" align="center">
|
||||
<template slot-scope="{ row }">{{ formatNum(row[cat.key + '_AB']) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="'C/D/O'" :prop="cat.key + '_CDO'" width="85" align="center">
|
||||
<template slot-scope="{ row }">{{ formatNum(row[cat.key + '_CDO']) }}</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="合计" prop="total" width="100" align="center">
|
||||
<template slot-scope="{ row }">{{ formatNum(row.total) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listCoilWithIds } from "@/api/wms/coil";
|
||||
|
||||
const CATEGORIES = [
|
||||
{ key: '冷硬钢卷', label: '冷硬钢卷' },
|
||||
{ key: '冷轧钢卷', label: '冷轧钢卷' },
|
||||
{ key: '镀锌钢卷', label: '镀锌钢卷' },
|
||||
{ key: '镀锌管材', label: '镀锌管材' },
|
||||
{ key: '花纹板', label: '花纹板' },
|
||||
{ key: '镀铬', label: '镀铬' },
|
||||
]
|
||||
|
||||
/**
|
||||
* 品质等级 → 分组映射
|
||||
* A/B → 'AB', C/D/O → 'CDO', 其他 → null
|
||||
*/
|
||||
function getQualityGroup(status) {
|
||||
if (!status) return null
|
||||
const s = String(status).toUpperCase().trim()
|
||||
if (['A', 'B'].includes(s)) return 'AB'
|
||||
if (['C', 'D', 'O'].includes(s)) return 'CDO'
|
||||
return null
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "StockDetail",
|
||||
dicts: ['wip_pack_saleman'],
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
rawList: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
CATEGORIES: () => CATEGORIES,
|
||||
|
||||
title() {
|
||||
const now = new Date()
|
||||
return `${now.getMonth()+1}.${now.getDate()}.${String(now.getFullYear()).slice(-2)} 库存明细`
|
||||
},
|
||||
|
||||
tableData() {
|
||||
if (!this.rawList.length) return []
|
||||
|
||||
// ========== 第一层:分类聚合 ==========
|
||||
// orderData: { [saleName]: { [catKey]: { AB: 0, CDO: 0 } } }
|
||||
// spotData: { [catKey]: { AB: 0, CDO: 0 } }
|
||||
const orderData = {}
|
||||
const spotData = {}
|
||||
let unmatchedCount = 0
|
||||
|
||||
this.rawList.forEach(item => {
|
||||
// 匹配钢材品类
|
||||
const cat = CATEGORIES.find(c => item.itemName && item.itemName.includes(c.key))
|
||||
if (!cat) { unmatchedCount++; return }
|
||||
|
||||
// 品质分组
|
||||
const group = getQualityGroup(item.qualityStatus)
|
||||
if (!group) { unmatchedCount++; return }
|
||||
|
||||
const weight = Number(item.netWeight) || 0
|
||||
|
||||
if (Number(item.isRelatedToOrder) === 1 && item.saleName) {
|
||||
// 订单相关 → 归属业务员
|
||||
if (!orderData[item.saleName]) orderData[item.saleName] = {}
|
||||
if (!orderData[item.saleName][cat.key]) orderData[item.saleName][cat.key] = { AB: 0, CDO: 0 }
|
||||
orderData[item.saleName][cat.key][group] += weight
|
||||
} else {
|
||||
// 非订单相关 → 现货
|
||||
if (!spotData[cat.key]) spotData[cat.key] = { AB: 0, CDO: 0 }
|
||||
spotData[cat.key][group] += weight
|
||||
}
|
||||
})
|
||||
|
||||
if (unmatchedCount > 0) {
|
||||
console.log(`[库存明细] 未匹配品类的钢卷数: ${unmatchedCount}`)
|
||||
}
|
||||
|
||||
// ========== 第二层:组装行数据 ==========
|
||||
// 工具函数:创建空行
|
||||
const createRow = (dimension, rowType, remark = '') => {
|
||||
const row = { dimension, rowType, remark, total: 0 }
|
||||
CATEGORIES.forEach(c => { row[c.key + '_AB'] = 0; row[c.key + '_CDO'] = 0 })
|
||||
return row
|
||||
}
|
||||
|
||||
// 2.1 业务员行(按字典 wip_pack_saleman 顺序)
|
||||
const dictItems = this.dict.type.wip_pack_saleman || []
|
||||
const personRows = dictItems.map(dictItem => {
|
||||
const row = createRow(dictItem.label, 'person')
|
||||
const personData = orderData[dictItem.value] || {}
|
||||
CATEGORIES.forEach(cat => {
|
||||
const vals = personData[cat.key] || { AB: 0, CDO: 0 }
|
||||
row[cat.key + '_AB'] = vals.AB
|
||||
row[cat.key + '_CDO'] = vals.CDO
|
||||
row.total += vals.AB + vals.CDO
|
||||
})
|
||||
return row
|
||||
})
|
||||
|
||||
// 2.2 订单小计
|
||||
const makeSubtotal = () => {
|
||||
const row = createRow('订单小计', 'summary')
|
||||
CATEGORIES.forEach(cat => {
|
||||
let ab = 0, cdo = 0
|
||||
personRows.forEach(r => {
|
||||
ab += r[cat.key + '_AB'] || 0
|
||||
cdo += r[cat.key + '_CDO'] || 0
|
||||
})
|
||||
row[cat.key + '_AB'] = ab
|
||||
row[cat.key + '_CDO'] = cdo
|
||||
row.total += ab + cdo
|
||||
})
|
||||
return row
|
||||
}
|
||||
|
||||
// 2.3 现货
|
||||
const makeSpot = () => {
|
||||
const row = createRow('现货', 'summary')
|
||||
CATEGORIES.forEach(cat => {
|
||||
const vals = spotData[cat.key] || { AB: 0, CDO: 0 }
|
||||
row[cat.key + '_AB'] = vals.AB
|
||||
row[cat.key + '_CDO'] = vals.CDO
|
||||
row.total += vals.AB + vals.CDO
|
||||
})
|
||||
return row
|
||||
}
|
||||
|
||||
// 2.4 合计 = 订单小计 + 现货
|
||||
const makeTotal = () => {
|
||||
const row = createRow('合计', 'summary')
|
||||
CATEGORIES.forEach(cat => {
|
||||
const ab = (orderSubtotal[cat.key + '_AB'] || 0) + (spotRow[cat.key + '_AB'] || 0)
|
||||
const cdo = (orderSubtotal[cat.key + '_CDO'] || 0) + (spotRow[cat.key + '_CDO'] || 0)
|
||||
row[cat.key + '_AB'] = ab
|
||||
row[cat.key + '_CDO'] = cdo
|
||||
row.total += ab + cdo
|
||||
})
|
||||
return row
|
||||
}
|
||||
|
||||
// 2.5 各产品小计
|
||||
const makeProductSummary = () => {
|
||||
const row = createRow('各产品小计', 'summary')
|
||||
CATEGORIES.forEach(cat => {
|
||||
const merged = (totalRow[cat.key + '_AB'] || 0) + (totalRow[cat.key + '_CDO'] || 0)
|
||||
row[cat.key + '_AB'] = merged
|
||||
row[cat.key + '_CDO'] = 0
|
||||
row.total += merged
|
||||
})
|
||||
return row
|
||||
}
|
||||
|
||||
const orderSubtotal = makeSubtotal()
|
||||
const spotRow = makeSpot()
|
||||
const totalRow = makeTotal()
|
||||
|
||||
return [
|
||||
...personRows,
|
||||
orderSubtotal,
|
||||
spotRow,
|
||||
totalRow,
|
||||
makeProductSummary(),
|
||||
]
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatNum(val) {
|
||||
if (val === null || val === undefined || isNaN(val)) return '0.00'
|
||||
return Number(val).toFixed(2)
|
||||
},
|
||||
cellStyle({ row }) {
|
||||
return row.rowType === 'summary' ? { backgroundColor: '#FFFACD' } : {}
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.rawList = []
|
||||
|
||||
listCoilWithIds({
|
||||
status: 0,
|
||||
dataType: 1,
|
||||
pageSize: 99999,
|
||||
pageNum: 1,
|
||||
}).then(res => {
|
||||
this.rawList = res.rows || []
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user