feat(wms): 新增报表透视表组件并优化操作状态显示

refactor: 替换select为tag显示操作状态
feat: 添加今天按钮到时间范围选择器
fix: 移除调试用的console.log
style: 调整按钮间距样式
feat: 新增厂家材质透视表和宽度厚度统计表
refactor: 优化导出功能去除orderBy参数
feat: 添加表面处理等查询条件
feat: 在coilTable中添加settings插槽
feat: 使用下拉菜单整合报表操作按钮
This commit is contained in:
2026-05-05 14:52:24 +08:00
parent 723ccc9e58
commit fa198181ee
11 changed files with 491 additions and 91 deletions

View File

@@ -191,13 +191,17 @@
<el-table-column label="操作状态" align="center" prop="actionStatus" width="120"> <el-table-column label="操作状态" align="center" prop="actionStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.actionStatus" placeholder="请选择操作状态" <!-- <el-select v-model="scope.row.actionStatus" placeholder="请选择操作状态"
@change="handleStatusChange(scope.row)"> @change="handleStatusChange(scope.row)">
<el-option label="待处理" :value="0" /> <el-option label="待处理" :value="0" />
<el-option label="处理中" :value="1" /> <el-option label="处理中" :value="1" />
<el-option label="已完成" :value="2" /> <el-option label="已完成" :value="2" />
<el-option label="已取消" :value="3" /> <el-option label="已取消" :value="3" />
</el-select> </el-select> -->
<el-tag v-if="scope.row.actionStatus === 0" type="info" size="mini">待处理</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 1" type="warning" size="mini">处理中</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 2" type="success" size="mini">已完成</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 3" type="danger" size="mini">已取消</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -72,12 +72,16 @@
<el-table-column label="操作状态" align="center" prop="actionStatus" width="120"> <el-table-column label="操作状态" align="center" prop="actionStatus" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.actionStatus" placeholder="请选择操作状态" @change="handleStatusChange(scope.row)"> <!-- <el-select v-model="scope.row.actionStatus" placeholder="请选择操作状态" @change="handleStatusChange(scope.row)">
<el-option label="待处理" :value="0" /> <el-option label="待处理" :value="0" />
<el-option label="处理中" :value="1" /> <el-option label="处理中" :value="1" />
<el-option label="已完成" :value="2" /> <el-option label="已完成" :value="2" />
<el-option label="已取消" :value="3" /> <el-option label="已取消" :value="3" />
</el-select> </el-select> -->
<el-tag v-if="scope.row.actionStatus === 0" type="info" size="mini">待处理</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 1" type="warning" size="mini">处理中</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 2" type="success" size="mini">已完成</el-tag>
<el-tag v-else-if="scope.row.actionStatus === 3" type="danger" size="mini">已取消</el-tag>
</template> </template>
</el-table-column> </el-table-column>

View File

@@ -51,6 +51,27 @@
clearable @keyup.enter.native="handleQuery" /> clearable @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item label="表面处理">
<el-input v-model="queryParams.itemSurfaceTreatmentDesc" placeholder="请输入表面处理" clearable size="small" />
</el-form-item>
<el-form-item label="切边" prop="trimmingRequirement">
<el-select v-model="queryParams.trimmingRequirement" placeholder="请选择切边" clearable style="width: 100%">
<el-option label="净边" value="净边" />
<el-option label="毛边" value="毛边" />
</el-select>
</el-form-item>
<el-form-item label="包装" prop="packagingRequirement">
<el-select v-model="queryParams.packagingRequirement" placeholder="请选择包装" clearable style="width: 100%">
<el-option label="裸包" value="裸包" />
<el-option label="普包" value="普包" />
<el-option label="简包" value="简包" />
</el-select>
</el-form-item>
<el-form-item label="品质">
<muti-select v-model="queryParams.qualityStatusCsv" :options="dict.type.coil_quality_status"
placeholder="请选择品质" clearable />
</el-form-item>
<el-form-item v-if="showWaybill" label="发货状态"> <el-form-item v-if="showWaybill" label="发货状态">
<el-radio-group v-model="queryParams.status" @change="handleQuery"> <el-radio-group v-model="queryParams.status" @change="handleQuery">
<el-radio-button label="">全部</el-radio-button> <el-radio-button label="">全部</el-radio-button>
@@ -1691,9 +1712,8 @@ export default {
}); });
}, },
handleExportAll() { handleExportAll() {
this.download('wms/materialCoil/export', { const { orderBy, ...query } = this.queryParams;
...this.queryParams this.download('wms/materialCoil/export', query, `materialCoil_${new Date().getTime()}.xlsx`)
}, `materialCoil_${new Date().getTime()}.xlsx`)
}, },
/** 批量打印标签按钮 */ /** 批量打印标签按钮 */
handleBatchPrintLabel() { handleBatchPrintLabel() {

View File

@@ -26,7 +26,7 @@ export default {
materialType: '成品', materialType: '成品',
itemType: 'product', itemType: 'product',
status: 0, status: 0,
orderBy: false orderBy: true
}, },
labelType: '3', labelType: '3',
showStatus: true, showStatus: true,

View File

@@ -38,10 +38,20 @@
:options="dict.type.coil_manufacturer" placeholder="请选择厂家" clearable @keyup.enter.native="handleQuery" /> :options="dict.type.coil_manufacturer" placeholder="请选择厂家" clearable @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="getList">查询</el-button> <!-- <el-button type="primary" @click="getList">查询</el-button> -->
<el-button type="primary" @click="exportData">导出产出钢卷</el-button> <el-dropdown split-button type="primary" @click="getList" @command="handleCommand">
<!-- <el-button type="primary" @click="exportLossData">导出消耗钢卷</el-button> --> 查询
<el-button type="primary" @click="settingVisible = true">列设置</el-button> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="exportData">导出产出钢卷</el-dropdown-item>
<el-dropdown-item command="exportLossData">导出消耗钢卷</el-dropdown-item>
<el-dropdown-item command="saveOutputReport">保存产出报表</el-dropdown-item>
<el-dropdown-item command="saveLossReport">保存消耗报表</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<!-- <el-button type="primary" @click="exportData">导出产出钢卷</el-button>
<el-button type="primary" @click="exportLossData">导出消耗钢卷</el-button>
<el-button type="primary" @click="saveOutputReport">保存产出报表</el-button>
<el-button type="primary" @click="saveLossReport">保存消耗报表</el-button> -->
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-row> </el-row>
@@ -86,19 +96,24 @@
<el-descriptions title="明细信息" :column="3" border> <el-descriptions title="明细信息" :column="3" border>
</el-descriptions> </el-descriptions>
<el-tabs v-model="activeTab"> <el-tabs v-model="activeTab">
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :data="lossList" :columns="lossColumns" :loading="loading" height="calc(100vh - 360px)" />
</el-tab-pane>
<el-tab-pane label="产出钢卷" name="output"> <el-tab-pane label="产出钢卷" name="output">
<coil-table :data="outList" :columns="outputColumns" :loading="loading" height="calc(100vh - 360px)" /> <coil-table :data="outList" :columns="outputColumns" :loading="loading" height="calc(100vh - 360px)">
<template slot="settings">
<el-button icon="el-icon-setting" @click="() => {settingVisible = true; activeColumnConfig = 'coil-report-output';}">列设置</el-button>
</template>
</coil-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :data="lossList" :columns="lossColumns" :loading="loading" height="calc(100vh - 360px)">
<template slot="settings">
<el-button icon="el-icon-setting" @click="() => {settingVisible = true; activeColumnConfig = 'coil-report-loss';}">列设置</el-button>
</template>
</coil-table>
</el-tab-pane>
</el-tabs> </el-tabs>
<el-dialog title="列设置" :visible.sync="settingVisible" width="50%"> <el-dialog title="列设置" :visible.sync="settingVisible" width="50%">
<el-radio-group v-model="activeColumnConfig">
<!-- <el-radio-button label="coil-report-loss">投入明细配置</el-radio-button> -->
<el-radio-button label="coil-report-output">产出明细配置</el-radio-button>
</el-radio-group>
<columns-setting :reportType="activeColumnConfig"></columns-setting> <columns-setting :reportType="activeColumnConfig"></columns-setting>
</el-dialog> </el-dialog>
</div> </div>
@@ -118,6 +133,7 @@ import { calcSummary, calcMSummary } from "@/views/wms/report/js/calc";
import CoilTable from "@/views/wms/report/components/coilTable"; import CoilTable from "@/views/wms/report/components/coilTable";
import ColumnsSetting from "@/views/wms/report/components/setting/columns"; import ColumnsSetting from "@/views/wms/report/components/setting/columns";
import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue"; import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
export default { export default {
name: 'MergeTemplate', name: 'MergeTemplate',
@@ -182,8 +198,8 @@ export default {
return { return {
lossList: [], lossList: [],
outList: [], outList: [],
activeTab: 'loss', activeTab: 'output',
activeColumnConfig: 'coil-report-loss', activeColumnConfig: 'coil-report-output',
settingVisible: false, settingVisible: false,
loading: false, loading: false,
timeRangeParams: { timeRangeParams: {
@@ -201,7 +217,7 @@ export default {
itemSpecification: '', itemSpecification: '',
itemMaterial: '', itemMaterial: '',
itemManufacturer: '', itemManufacturer: '',
pageSize: 9999, pageSize: 99999,
pageNum: 1, pageNum: 1,
}, },
lossColumns: [], lossColumns: [],
@@ -243,6 +259,48 @@ export default {
handleQuery() { handleQuery() {
this.getList() this.getList()
}, },
// 保存产出报表
saveOutputReport() {
this.loading = true
saveReportFile(this.outList.map(item => item.coilId).join(','), {
reportParams: this.queryParams,
reportType: '产出报表,异常报表',
productionLine: this.productionLine,
}).then(res => {
this.$message({
message: '保存成功',
type: 'success',
})
}).catch(err => {
this.$message({
message: '保存失败',
type: 'error',
})
}).finally(() => {
this.loading = false
})
},
// 保存消耗报表
saveLossReport() {
this.loading = true
saveReportFile(this.lossList.map(item => item.coilId).join(','), {
reportParams: this.queryParams,
reportType: '消耗报表,异常报表',
productionLine: this.productionLine,
}).then(res => {
this.$message({
message: '保存成功',
type: 'success',
})
}).catch(err => {
this.$message({
message: '保存失败',
type: 'error',
})
}).finally(() => {
this.loading = false
})
},
async getList() { async getList() {
this.loading = true; this.loading = true;
const actions = await listPendingAction({ ...this.queryParams, actionTypes: this.actionTypes, actionStatus: 2 }); const actions = await listPendingAction({ ...this.queryParams, actionTypes: this.actionTypes, actionStatus: 2 });
@@ -282,68 +340,9 @@ export default {
} }
}); });
// if (!lossIds) {
// this.lossList = []
// } else {
// const lossRes = await listCoilWithIds({ ...this.queryParams, coilIds: lossIds || '', startTime: '', endTime: '' });
// this.lossList = lossRes.rows.map(item => {
// // 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
// const [thickness, width] = item.specification?.split('*') || []
// return {
// ...item,
// computedThickness: parseFloat(thickness),
// computedWidth: parseFloat(width),
// }
// });
// }
this.loading = false; this.loading = false;
// this.loading = true;
// const res1 = await listPendingAction({ ...this.queryParams, actionTypes: '201,202,203,204,205,206', actionStatus: 2 });
// const res = res1.rows;
// // 获取两层数据
// const lossIds = res.map(item => item.coilId);
// // 使用new Set去重
// const outIds = [...new Set(res.map(item => item.processedCoilIds))];
// if (lossIds.length === 0 || outIds.length === 0) {
// this.$message({
// message: '查询结果为空',
// type: 'warning'
// })
// this.loading = false;
// return
// }
// const [lossRes, outRes] = await Promise.all([
// listCoilWithIds({ ...this.queryParams, coilIds: lossIds.join(',') || '', startTime: '', endTime: '' }),
// listCoilWithIds({ ...this.queryParams, coilIds: outIds.join(',') || '', startTime: '', endTime: '' }),
// ]);
// this.lossList = lossRes.rows.map(item => {
// // 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
// const [thickness, width] = item.specification?.split('*') || []
// return {
// ...item,
// computedThickness: parseFloat(thickness),
// computedWidth: parseFloat(width),
// }
// });
// this.outList = outRes.rows.map(item => {
// // 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
// const [thickness, width] = item.specification?.split('*') || []
// return {
// ...item,
// computedThickness: parseFloat(thickness),
// computedWidth: parseFloat(width),
// }
// });
// this.loading = false;
}, },
// 导出 // 导出产出钢卷
exportData() { exportData() {
if (this.outList.length === 0) { if (this.outList.length === 0) {
this.$message.warning('暂无数据可导出') this.$message.warning('暂无数据可导出')
@@ -353,6 +352,8 @@ export default {
coilIds: this.outList.map(item => item.coilId).join(',') coilIds: this.outList.map(item => item.coilId).join(',')
}, `materialCoil_${new Date().getTime()}.xlsx`) }, `materialCoil_${new Date().getTime()}.xlsx`)
}, },
// 导出消耗钢卷
exportLossData() { exportLossData() {
if (this.lossList.length === 0) { if (this.lossList.length === 0) {
this.$message.warning('暂无数据可导出') this.$message.warning('暂无数据可导出')
@@ -362,9 +363,21 @@ export default {
coilIds: this.lossList.map(item => item.coilId).join(',') coilIds: this.lossList.map(item => item.coilId).join(',')
}, `materialCoil_${new Date().getTime()}.xlsx`) }, `materialCoil_${new Date().getTime()}.xlsx`)
}, },
// 处理命令
handleCommand(command) {
if (command === 'exportData') {
this.exportData()
} else if (command === 'exportLossData') {
this.exportLossData()
} else if (command === 'saveOutputReport') {
this.saveOutputReport()
} else if (command === 'saveLossReport') {
this.saveLossReport()
}
},
// 加载列设置 // 加载列设置
loadColumns() { loadColumns() {
// this.lossColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-loss') || '[]') || [] this.lossColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-loss') || '[]') || []
this.outputColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-output') || '[]') || [] this.outputColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-output') || '[]') || []
} }
} }

View File

@@ -22,6 +22,8 @@
<el-pagination layout="total, sizes, prev, pager, next, jumper" :total="total" :page-size.sync="pageSize" <el-pagination layout="total, sizes, prev, pager, next, jumper" :total="total" :page-size.sync="pageSize"
:page-sizes="[10, 20, 50, 100, 200, 500, 1000]" @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100, 200, 500, 1000]" @size-change="handleSizeChange"
@current-change="handleCurrentChange" /> @current-change="handleCurrentChange" />
<slot name="settings"></slot>
</div> </div>
<el-table :data="tableData" style="width: 100%" height="calc(100vh - 320px)" border row-key="coilId" :row-class-name="getRowClassName"> <el-table :data="tableData" style="width: 100%" height="calc(100vh - 320px)" border row-key="coilId" :row-class-name="getRowClassName">

View File

@@ -0,0 +1,195 @@
<template>
<el-table :data="tableData" border :style="{ width: '100%', marginBottom: '20px' }">
<el-table-column :prop="config.rowField" :label="config.rowLabel" :width="config.rowWidth" align="center"
fixed></el-table-column>
<template v-for="colVal in columnValues">
<el-table-column :key="'group_' + colVal" :label="colVal + ''" align="center">
<template v-for="summary in config.summaryColumns">
<el-table-column :key="`${colVal}_${summary.prop}`" :label="summary.label" align="center">
<template #default="scope">
<!-- 强制显示值 -->
<span>{{ scope.row[`${summary.prop}_${colVal}`] || '--' }}</span>
</template>
</el-table-column>
</template>
</el-table-column>
</template>
<el-table-column label="合计" align="center">
<template v-for="summary in config.summaryColumns">
<el-table-column :key="'total_' + summary.prop" :prop="'total_' + summary.prop" :label="summary.label"
:width="summary.width" align="center"></el-table-column>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
name: 'CrossTable',
props: {
data: {
type: Array,
required: true
},
config: {
type: Object,
required: true
}
},
computed: {
// 第一步:统计数据,生成行、列和单元格统计值
statisticsData() {
const {
rowField,
columnField,
summaryColumns,
formatKey
} = this.config
const formatNum = (num) => {
if (num === null || num === undefined) return null
return parseFloat(num).toFixed(2)
}
const formatKeyFn = formatKey || formatNum
// 数据结构rowValues 行列表colValues 列列表cellStats[row][col][prop] = 统计值
const rowValues = new Set()
const colValues = new Set()
const cellStats = new Map() // Map<rowKey, Map<colKey, { prop: value }>>
// 遍历原始数据,统计每个单元格
this.data.forEach(item => {
const colVal = item[columnField]
const rowVal = item[rowField]
if (colVal != null && colVal !== '' && rowVal != null && rowVal !== '') {
const colKey = formatKeyFn(colVal)
const rowKey = formatKeyFn(rowVal)
rowValues.add(rowKey)
colValues.add(colKey)
// 初始化单元格
if (!cellStats.has(rowKey)) {
cellStats.set(rowKey, new Map())
}
const rowStats = cellStats.get(rowKey)
if (!rowStats.has(colKey)) {
const initial = {}
summaryColumns.forEach(sc => {
initial[sc.prop] = 0
})
rowStats.set(colKey, initial)
}
const cell = rowStats.get(colKey)
// 累计统计值
summaryColumns.forEach(sc => {
if (sc.field === '') {
cell[sc.prop] += 1
} else {
cell[sc.prop] += parseFloat(item[sc.field]) || 0
}
})
}
})
// 排序并返回
return {
rowValues: Array.from(rowValues).map(v => parseFloat(v)).sort((a, b) => a - b).map(v => formatKeyFn(v)),
colValues: Array.from(colValues).map(v => parseFloat(v)).sort((a, b) => a - b).map(v => formatKeyFn(v)),
cellStats
}
},
// 第二步:根据统计数据生成 Element-UI Table 可用的数据
tableData() {
const {
rowField,
summaryColumns,
formatValue
} = this.config
const { rowValues, colValues, cellStats } = this.statisticsData
// 生成每一行数据
const rows = rowValues.map(rowKey => {
const row = { [rowField]: parseFloat(rowKey) }
const rowStats = cellStats.get(rowKey)
const rowTotals = {}
summaryColumns.forEach(sc => {
rowTotals[sc.prop] = 0
})
// 填充每一列的数据
colValues.forEach(colKey => {
const cell = rowStats?.get(colKey) || {}
summaryColumns.forEach(sc => {
const val = cell[sc.prop] || 0
row[`${sc.prop}_${colKey}`] = formatValue ? formatValue(val, sc) : val.toFixed(3)
rowTotals[sc.prop] += val
})
})
// 填充行合计
summaryColumns.forEach(sc => {
row[`total_${sc.prop}`] = formatValue ? formatValue(rowTotals[sc.prop], sc) : rowTotals[sc.prop].toFixed(3)
})
return row
})
// 在 tableData 计算属性中,生成 rows 后添加
console.log('Generated row sample:', rows[0])
console.log('Field names:', Object.keys(rows[0] || {}))
console.log('rows length:', rows.length)
console.log('colValues:', colValues)
console.log('summaryColumns:', summaryColumns)
// 生成合计行
const totalRow = { [rowField]: '合计' }
const grandTotals = {}
summaryColumns.forEach(sc => {
grandTotals[sc.prop] = 0
})
colValues.forEach(colKey => {
const colTotals = {}
summaryColumns.forEach(sc => {
colTotals[sc.prop] = 0
})
rows.forEach(row => {
summaryColumns.forEach(sc => {
const val = parseFloat(row[`${sc.prop}_${colKey}`]) || 0
colTotals[sc.prop] += val
grandTotals[sc.prop] += val
})
})
summaryColumns.forEach(sc => {
totalRow[`${sc.prop}_${colKey}`] = formatValue ? formatValue(colTotals[sc.prop], sc) : colTotals[sc.prop].toFixed(3)
})
})
// 填充总合计
summaryColumns.forEach(sc => {
totalRow[`total_${sc.prop}`] = formatValue ? formatValue(grandTotals[sc.prop], sc) : grandTotals[sc.prop].toFixed(3)
})
console.log(rows, 'rows')
return [...rows, totalRow]
},
columnValues() {
console.log(this.statisticsData.colValues, 'colValues')
return this.statisticsData.colValues
}
}
}
</script>
<style scoped></style>

View File

@@ -0,0 +1,108 @@
<template>
<el-table :data="tableData" border :style="{ width: '100%', marginBottom: '20px' }">
<template v-for="(column, idx) in config.groupFields">
<el-table-column
:key="column"
:prop="column"
:label="config.groupLabels ? config.groupLabels[idx] : column"
:align="config.groupAligns ? config.groupAligns[idx] : 'left'"
>
<template slot-scope="scope">
<span :style="{
paddingLeft: (scope.row.level * 20) + 'px',
fontWeight: scope.row.level === idx ? 'bold' : 'normal'
}">
{{ scope.row[column] }}
</span>
</template>
</el-table-column>
</template>
<template v-for="summary in config.summaryFields">
<el-table-column
:key="summary.prop"
:prop="summary.prop"
:label="summary.label"
:width="summary.width"
:align="summary.align"
></el-table-column>
</template>
</el-table>
</template>
<script>
export default {
name: 'HierarchicalPivot',
props: {
data: {
type: Array,
required: true
},
config: {
type: Object,
required: true
}
},
computed: {
tableData() {
const {
groupFields,
summaryFields,
formatValue
} = this.config
const buildHierarchy = (items, level = 0, parentKey = null) => {
const result = []
const field = groupFields[level]
if (!field) return result
const groupMap = new Map()
items.forEach(item => {
const key = item[field] || '未知'
if (!groupMap.has(key)) {
groupMap.set(key, [])
}
groupMap.get(key).push(item)
})
const sortedKeys = Array.from(groupMap.keys()).sort()
sortedKeys.forEach(key => {
const groupItems = groupMap.get(key)
const groupRow = {
level,
...groupFields.reduce((acc, f, idx) => {
acc[f] = idx === level ? key : ''
return acc
}, {})
}
summaryFields.forEach(sf => {
let val
if (sf.field === '') {
val = groupItems.length
} else {
val = groupItems.reduce((acc, item) => {
return acc + (parseFloat(item[sf.field]) || 0)
}, 0)
}
groupRow[sf.prop] = formatValue ? formatValue(val, sf) : val.toFixed(3)
})
result.push(groupRow)
if (level < groupFields.length - 1) {
const children = buildHierarchy(groupItems, level + 1, key)
result.push(...children)
}
})
return result
}
return buildHierarchy(this.data)
}
}
}
</script>
<style scoped></style>

View File

@@ -21,6 +21,7 @@
</div> </div>
<div class="quick-options"> <div class="quick-options">
<el-button size="small" @click="setQuickTime('prevDay')">前一天</el-button> <el-button size="small" @click="setQuickTime('prevDay')">前一天</el-button>
<el-button size="small" @click="setQuickTime('today')">今天</el-button>
<el-button size="small" @click="setQuickTime('nextDay')">后一天</el-button> <el-button size="small" @click="setQuickTime('nextDay')">后一天</el-button>
<el-button size="small" @click="setQuickTime('last7Days')">近7天</el-button> <el-button size="small" @click="setQuickTime('last7Days')">近7天</el-button>
<el-button size="small" @click="setQuickTime('last15Days')">近15天</el-button> <el-button size="small" @click="setQuickTime('last15Days')">近15天</el-button>
@@ -127,12 +128,15 @@ export default {
switch (type) { switch (type) {
case 'prevDay': case 'prevDay':
// 在当前时间基础上向前推一天
newStartDate.setDate(newStartDate.getDate() - 1) newStartDate.setDate(newStartDate.getDate() - 1)
newEndDate.setDate(newEndDate.getDate() - 1) newEndDate.setDate(newEndDate.getDate() - 1)
break break
case 'today':
const todayNow = new Date()
newStartDate = todayNow
newEndDate = todayNow
break
case 'nextDay': case 'nextDay':
// 在当前时间基础上向后推一天
newStartDate.setDate(newStartDate.getDate() + 1) newStartDate.setDate(newStartDate.getDate() + 1)
newEndDate.setDate(newEndDate.getDate() + 1) newEndDate.setDate(newEndDate.getDate() + 1)
break break
@@ -205,7 +209,11 @@ export default {
} }
.quick-options { .quick-options {
display: flex; display: flex;
gap: 8px; gap: 2px;
flex-wrap: wrap; flex-wrap: wrap;
} }
.el-button + .el-button {
margin-left: 4px
}
</style> </style>

View File

@@ -62,6 +62,12 @@
<el-descriptions-item label="均重">{{ summary.avgWeight }}t</el-descriptions-item> <el-descriptions-item label="均重">{{ summary.avgWeight }}t</el-descriptions-item>
</el-descriptions> </el-descriptions>
<!-- 厂家材质透视表 -->
<HierarchicalPivot :data="list" :config="hierarchicalPivotConfig" />
<!-- 宽度厚度统计表 -->
<CrossTable :data="list" :config="crossTableConfig" />
<el-descriptions title="明细信息" :column="3" border> <el-descriptions title="明细信息" :column="3" border>
</el-descriptions> </el-descriptions>
<coil-table :columns="receiveColumns" :data="list"></coil-table> <coil-table :columns="receiveColumns" :data="list"></coil-table>
@@ -90,6 +96,8 @@ import { listDeliveryPlan } from '@/api/wms/deliveryPlan'
import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue"; import ColumnsSetting from "@/views/wms/report/components/setting/columns.vue";
import CoilTable from "@/views/wms/report/components/coilTable/index.vue"; import CoilTable from "@/views/wms/report/components/coilTable/index.vue";
import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue"; import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue";
import HierarchicalPivot from "@/views/wms/report/components/hierarchicalPivot/index.vue";
import CrossTable from "@/views/wms/report/components/crossTable/index.vue";
import { saveReportFile } from "@/views/wms/report/js/reportFile"; import { saveReportFile } from "@/views/wms/report/js/reportFile";
@@ -104,12 +112,13 @@ export default {
ColumnsSetting, ColumnsSetting,
CoilTable, CoilTable,
TimeRangePicker, TimeRangePicker,
HierarchicalPivot,
CrossTable,
}, },
dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'], dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'],
data() { data() {
// 工具函数:个位数补零,保证格式统一(比如 9 → 095 → 05 // 工具函数:个位数补零,保证格式统一(比如 9 → 095 → 05
const addZero = (num) => num.toString().padStart(2, '0') const addZero = (num) => num.toString().padStart(2, '0')
const now = new Date() // 当前本地北京时间 const now = new Date() // 当前本地北京时间
// 核心:获取【昨天】的日期对象(自动处理跨月/跨年,无边界问题) // 核心:获取【昨天】的日期对象(自动处理跨月/跨年,无边界问题)
const yesterday = new Date(now) const yesterday = new Date(now)
@@ -151,6 +160,44 @@ export default {
loading: false, loading: false,
receiveColumns: [], receiveColumns: [],
// 厂家材质透视表配置
hierarchicalPivotConfig: {
groupFields: ['manufacturer', 'material'],
groupLabels: ['厂家', '材质'],
summaryFields: [
{ prop: 'count', label: '求和项:件数', field: '', align: 'center' },
{ prop: 'weight', label: '求和项:重量', field: 'netWeight', align: 'center' }
],
formatValue: (value, summaryField) => {
if (summaryField.field === '') {
return value
}
return value.toFixed(3)
}
},
// 宽度厚度统计表配置
crossTableConfig: {
rowField: 'computedWidth',
rowLabel: '宽度',
rowWidth: 100,
columnField: 'computedThickness',
summaryColumns: [
{ prop: 'count', label: '件数', width: 80, field: '' },
{ prop: 'weight', label: '重量', width: 100, field: 'netWeight' }
],
formatValue: (value, summaryField) => {
if (summaryField.field === '') {
return value
}
return value.toFixed(2)
},
formatKey: (num) => {
if (num === null || num === undefined || isNaN(num)) return null
return parseFloat(num).toFixed(2)
}
}
} }
}, },
computed: { computed: {
@@ -167,7 +214,8 @@ export default {
}, },
coilIds() { coilIds() {
return this.list.map(item => item.coilId).join(',') return this.list.map(item => item.coilId).join(',')
} },
}, },
methods: { methods: {
// 加载列设置 // 加载列设置
@@ -196,7 +244,6 @@ export default {
}).then(res => { }).then(res => {
const actions = res.rows const actions = res.rows
const coilIds = actions.map(item => item.coilId).join(',') const coilIds = actions.map(item => item.coilId).join(',')
console.log(coilIds)
if (!coilIds) { if (!coilIds) {
this.$message({ this.$message({
message: '暂无数据', message: '暂无数据',

View File

@@ -452,7 +452,6 @@ export default {
this.lossList = lossList.filter(item => !this.mergeCoils.includes(item.coilId)) this.lossList = lossList.filter(item => !this.mergeCoils.includes(item.coilId))
// 找出所有被剔除的卷的id, // 找出所有被剔除的卷的id,
const removedCoilIds = lossList.filter(item => this.mergeCoils.includes(item.coilId)).map(item => item.coilId) const removedCoilIds = lossList.filter(item => this.mergeCoils.includes(item.coilId)).map(item => item.coilId)
console.log(removedCoilIds)
this.list = outputList.filter(item => !removedCoilIds.includes(item.parentCoilId)) this.list = outputList.filter(item => !removedCoilIds.includes(item.parentCoilId))
// if (this.viewType == 'day') { // if (this.viewType == 'day') {
// this.getYesterdayData() // this.getYesterdayData()