Files
klp-oa/klp-ui/src/views/wms/report/template/action.vue
砂糖 3e640b4a4d feat: 新增业务员、合同号查询与展示,优化钢卷管理功能
1.  在钢卷相关API中新增对saleName和contractNo字段的过滤逻辑,避免数据覆盖
2.  多个报表页面新增业务员和合同号查询条件
3.  钢卷物料页面重构表单布局,新增生产耗时计算、合同绑定功能
4.  告警页面优化UI展示,新增详情弹窗和备注处理流程
5.  多处代码格式化与注释优化
2026-06-22 14:42:46 +08:00

1190 lines
55 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container" v-loading="loading">
<!-- all 类型视图选择器 -->
<div v-if="reportType === 'all'" style="margin-bottom: 10px;">
<el-radio-group v-model="viewType" @change="handleViewTypeChange">
<el-radio-button label="day">日视图</el-radio-button>
<el-radio-button label="month">月视图</el-radio-button>
<el-radio-button label="year">年视图</el-radio-button>
<el-radio-button label="custom">自定义</el-radio-button>
</el-radio-group>
<el-date-picker v-if="viewType === 'day'" style="width: 200px; margin-left: 10px;" v-model="dayDate" type="date"
value-format="yyyy-MM-dd" placeholder="选择日期" @change="handleDayDateChange" />
<el-date-picker v-if="viewType === 'month'" style="width: 200px; margin-left: 10px;" v-model="monthDate"
type="month" value-format="yyyy-MM" placeholder="选择月份" @change="handleMonthDateChange" />
<el-date-picker v-if="viewType === 'year'" style="width: 200px; margin-left: 10px;" v-model="yearDate" type="year"
value-format="yyyy" placeholder="选择年份" @change="handleYearDateChange" />
<span v-if="viewType === 'custom'" style="margin-left: 10px;">
<el-date-picker style="width: 200px;" v-model="queryParams.startTime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择开始日期"></el-date-picker>
<el-date-picker style="width: 200px;" v-model="queryParams.endTime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择结束日期"></el-date-picker>
</span>
</div>
<el-row v-else>
<el-form label-width="80px" inline>
<template v-if="['out', 'loss'].includes(reportType)">
<el-form-item label="时间范围" prop="timeRange">
<time-range-picker v-model="queryParams" start-key="startTime" end-key="endTime"
:default-start-time="defaultStartTime" :default-end-time="defaultEndTime" @quick-select="handleQuery" />
</el-form-item>
</template>
<el-form-item v-else-if="reportType === 'day'" label="日期" prop="date">
<el-date-picker style="width: 200px;" v-model="dayDate" type="date" value-format="yyyy-MM-dd"
placeholder="选择日期" @change="handleDateChange"></el-date-picker>
</el-form-item>
<el-form-item v-else-if="reportType === 'month'" label="日期" prop="date">
<el-date-picker style="width: 200px;" v-model="monthDate" type="month" value-format="yyyy-MM"
placeholder="选择月份" @change="handleDateChange"></el-date-picker>
</el-form-item>
<el-form-item v-else-if="reportType === 'year'" label="日期" prop="date">
<el-date-picker style="width: 200px;" v-model="yearDate" type="year" value-format="yyyy" placeholder="选择年份"
@change="handleDateChange"></el-date-picker>
</el-form-item>
<template v-else-if="reportType === 'team'">
<el-form-item label="开始日期">
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeStart" type="date"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="结束日期">
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeEnd" type="date"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期"></el-date-picker>
</el-form-item>
<el-form-item label="班组">
<el-select v-model="queryParams.team" placeholder="请选择班组" style="width: 200px;">
<el-option label="甲" value="甲" />
<el-option label="乙" value="乙" />
</el-select>
</el-form-item>
</template>
</el-form>
</el-row>
<el-row>
<el-form label-width="80px" inline>
<template v-if="reportType !== 'all'">
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input style="width: 200px; display: inline-block;" v-model="queryParams.enterCoilNo"
placeholder="请输入入场钢卷号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input style="width: 200px;" v-model="queryParams.currentCoilNo" placeholder="请输入当前钢卷号" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="产品名称" prop="itemName">
<el-input style="width: 200px;" v-model="queryParams.itemName" placeholder="请输入产品名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="规格" prop="itemSpecification">
<memo-input style="width: 200px;" v-model="queryParams.itemSpecification" storageKey="coilSpec"
placeholder="请选择规格" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="材质" prop="itemMaterial">
<dict-select style="width: 200px;" v-model="queryParams.itemMaterial" dict-type="coil_material"
placeholder="请选择材质" clearable @keyup.enter.native="handleQuery" multiple />
</el-form-item>
<el-form-item label="厂家" prop="itemManufacturer">
<dict-select style="width: 200px;" v-model="queryParams.itemManufacturer" dict-type="coil_manufacturer"
placeholder="请选择厂家" clearable @keyup.enter.native="handleQuery" multiple />
</el-form-item>
<el-form-item label="品质" prop="qualityStatusCsv">
<muti-select v-model="queryParams.qualityStatusCsv" :options="dict.type.coil_quality_status"
placeholder="请选择品质" clearable />
</el-form-item>
<el-form-item label="逻辑库位" prop="warehouseId">
<warehouse-select v-model="queryParams.warehouseId" placeholder="请选择仓库/库区/库位"
style="width: 100%; display: inline-block; width: 200px;" clearable />
</el-form-item>
<el-form-item label="业务员" prop="saleName">
<el-input v-model="queryParams.saleName" placeholder="请输入业务员" clearable size="small" />
</el-form-item>
<el-form-item label="合同号" prop="contractNo">
<el-input v-model="queryParams.contractNo" placeholder="请输入合同号" clearable size="small" />
</el-form-item>
</template>
<template v-else>
<el-form-item label="入场钢卷号" prop="enterCoilNo">
<el-input style="width: 200px; display: inline-block;" v-model="queryParams.enterCoilNo"
placeholder="请输入入场钢卷号" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="当前钢卷号" prop="currentCoilNo">
<el-input style="width: 200px;" v-model="queryParams.currentCoilNo" placeholder="请输入当前钢卷号" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="逻辑库位" prop="warehouseIds">
<el-select v-model="warehouseIds" collapse-tags multiple placeholder="请选择逻辑库位" style="width: 200px;">
<el-option v-for="item in warehouseOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="产品名称" prop="itemName">
<el-input style="width: 200px;" v-model="queryParams.itemName" placeholder="请输入产品名称" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="规格" prop="itemSpecification">
<memo-input style="width: 200px;" v-model="queryParams.itemSpecification" storageKey="coilSpec"
placeholder="请选择规格" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="材质" prop="itemMaterial">
<dict-select style="width: 200px;" v-model="queryParams.itemMaterial" dictType="coil_material"
placeholder="请选择材质" clearable multiple />
</el-form-item>
<el-form-item label="厂家" prop="itemManufacturer">
<dict-select style="width: 200px;" v-model="queryParams.itemManufacturer" dictType="coil_manufacturer"
placeholder="请选择厂家" clearable multiple />
</el-form-item>
<el-form-item label="品质" prop="qualityStatusCsv">
<muti-select v-model="queryParams.qualityStatusCsv" :options="dict.type.coil_quality_status"
placeholder="请选择品质" clearable />
</el-form-item>
<el-form-item label="业务员" prop="saleName">
<el-input v-model="queryParams.saleName" placeholder="请输入业务员" clearable size="small" />
</el-form-item>
<el-form-item label="合同号" prop="contractNo">
<el-input v-model="queryParams.contractNo" placeholder="请输入合同号" clearable size="small" />
</el-form-item>
</template>
<el-form-item>
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-button type="primary" @click="settingVisible = true">列配置</el-button>
<el-button v-if="['out', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary"
@click="exportData">导出产出</el-button>
<el-button v-if="['loss', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary"
@click="exportLossData">导出消耗</el-button>
<el-button v-if="['out', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary"
@click="openCustomExport('output')">自定义导出产出</el-button>
<el-button v-if="['loss', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary"
@click="openCustomExport('loss')">自定义导出消耗</el-button>
<el-button v-if="['out', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary"
@click="saveOutputReport">保存产出</el-button>
<el-button v-if="['loss', 'team', 'day', 'month', 'year', 'all'].includes(reportType)" type="primary"
@click="saveLossReport">保存消耗</el-button>
</el-form-item>
</el-form>
</el-row>
<!-- out 类型的统计信息 -->
<el-descriptions v-if="reportType === 'out'" title="统计信息" :column="3" border>
<el-descriptions-item label="总钢卷数量">{{ outSummary.totalCount }}</el-descriptions-item>
<el-descriptions-item label="总重">{{ outSummary.totalWeight }}t</el-descriptions-item>
<el-descriptions-item label="均重">{{ outSummary.avgWeight }}t</el-descriptions-item>
</el-descriptions>
<!-- loss 类型的统计信息 -->
<el-descriptions v-else-if="reportType === 'loss'" title="统计信息" :column="3" border>
<el-descriptions-item label="总钢卷数量">{{ lossSummary.totalCount }}</el-descriptions-item>
<el-descriptions-item label="总重">{{ lossSummary.totalWeight }}t</el-descriptions-item>
<el-descriptions-item label="均重">{{ lossSummary.avgWeight }}t</el-descriptions-item>
</el-descriptions>
<!-- all 类型的统计信息comprehensive 风格 -->
<template v-else-if="reportType === 'all'">
<el-descriptions title="统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ summary.outCount }}<span
v-if="viewType === 'day' && yesterdaySummary.outCount"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.outCount
}})</span></el-descriptions-item>
<el-descriptions-item label="产出总重">{{ summary.outTotalWeight }}t<span
v-if="viewType === 'day' && yesterdaySummary.outTotalWeight"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.outTotalWeight
}}t)</span></el-descriptions-item>
<el-descriptions-item label="产出均重">{{ summary.outAvgWeight }}t<span
v-if="viewType === 'day' && yesterdaySummary.outAvgWeight"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.outAvgWeight
}}t)</span></el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ summary.lossCount }}<span
v-if="viewType === 'day' && yesterdaySummary.lossCount"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.lossCount
}})</span></el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ summary.lossTotalWeight }}t<span
v-if="viewType === 'day' && yesterdaySummary.lossTotalWeight"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.lossTotalWeight
}}t)</span></el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ summary.lossAvgWeight }}t<span
v-if="viewType === 'day' && yesterdaySummary.lossAvgWeight"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.lossAvgWeight
}}t)</span></el-descriptions-item>
<el-descriptions-item label="数量差值">{{ summary.countDiff }}<span
v-if="viewType === 'day' && yesterdaySummary.countDiff"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.countDiff
}})</span></el-descriptions-item>
<el-descriptions-item label="总重差值">{{ summary.weightDiff }}<span
v-if="viewType === 'day' && yesterdaySummary.weightDiff"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.weightDiff
}})</span></el-descriptions-item>
<el-descriptions-item label="均重差值">{{ summary.avgWeightDiff }}t<span
v-if="viewType === 'day' && yesterdaySummary.avgWeightDiff"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.avgWeightDiff
}}t)</span></el-descriptions-item>
<el-descriptions-item label="成品率">{{ summary.passRate }}<span
v-if="viewType === 'day' && yesterdaySummary.passRate"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.passRate
}})</span></el-descriptions-item>
<el-descriptions-item label="损耗率">{{ summary.lossRate }}<span
v-if="viewType === 'day' && yesterdaySummary.lossRate"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.lossRate
}})</span></el-descriptions-item>
<el-descriptions-item label="异常率">{{ summary.abRate }}<span v-if="viewType === 'day' && yesterdaySummary.abRate"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.abRate
}})</span></el-descriptions-item>
<el-descriptions-item label="正品率">{{ summary.passRate2 }}<span
v-if="viewType === 'day' && yesterdaySummary.passRate2"
style="margin-left: 10px; font-size: 12px; color: #999;">(昨日: {{ yesterdaySummary.passRate2
}})</span></el-descriptions-item>
</el-descriptions>
<el-descriptions title="已处理M统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ mSummary.outCount }}</el-descriptions-item>
<el-descriptions-item label="产出总重">{{ mSummary.outTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="产出均重">{{ mSummary.outAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ mSummary.lossCount }}</el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ mSummary.lossTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ mSummary.lossAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="数量差值">{{ mSummary.countDiff }}</el-descriptions-item>
<el-descriptions-item label="总重差值">{{ mSummary.weightDiff }}</el-descriptions-item>
<el-descriptions-item label="均重差值">{{ mSummary.avgWeightDiff }}t</el-descriptions-item>
<el-descriptions-item label="成品率">{{ mSummary.passRate }}</el-descriptions-item>
<el-descriptions-item label="损耗率">{{ mSummary.lossRate }}</el-descriptions-item>
<el-descriptions-item label="异常率">{{ mSummary.abRate }}</el-descriptions-item>
<el-descriptions-item label="正品率">{{ mSummary.passRate2 }}</el-descriptions-item>
</el-descriptions>
<el-descriptions title="异常统计" :column="4" border>
<el-descriptions-item v-for="item in abSummary" :key="item.label" :label="item.label">{{ item.value
}}</el-descriptions-item>
</el-descriptions>
<!-- 月视图日数据折线图 -->
<div v-if="viewType === 'month'" style="margin-top: 20px; height: 400px;">
<el-card>
<template slot="header">
<div class="clearfix">
<span>日数据趋势</span>
</div>
</template>
<div ref="monthChart" style="width: 100%; height: 350px;"></div>
</el-card>
</div>
<!-- 分条信息统计 -->
<split-summary v-if="productionLine == '分条线'" :origin-outputlist="outList" :origin-loss-list="lossList"
:common-coil-ids="commonCoilIds"></split-summary>
<el-descriptions title="尺寸异常统计" :column="4" border>
<el-descriptions-item label="长度异常卷数">{{ sizeAbnormalSummary.length.count }}</el-descriptions-item>
<el-descriptions-item label="长度异常总重">{{ sizeAbnormalSummary.length.weight }}t</el-descriptions-item>
<el-descriptions-item label="长度异常数量占比">{{ sizeAbnormalSummary.length.countRate }}</el-descriptions-item>
<el-descriptions-item label="长度异常重量占比">{{ sizeAbnormalSummary.length.weightRate }}</el-descriptions-item>
<el-descriptions-item label="厚度异常卷数">{{ sizeAbnormalSummary.thickness.count }}</el-descriptions-item>
<el-descriptions-item label="厚度异常总重">{{ sizeAbnormalSummary.thickness.weight }}t</el-descriptions-item>
<el-descriptions-item label="厚度异常数量占比">{{ sizeAbnormalSummary.thickness.countRate }}</el-descriptions-item>
<el-descriptions-item label="厚度异常重量占比">{{ sizeAbnormalSummary.thickness.weightRate }}</el-descriptions-item>
</el-descriptions>
</template>
<!-- team, day, month, year 类型的统计信息 -->
<template v-else>
<el-descriptions title="统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ summary.outCount }}</el-descriptions-item>
<el-descriptions-item label="产出总重">{{ summary.outTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="产出均重">{{ summary.outAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ summary.lossCount }}</el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ summary.lossTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ summary.lossAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="数量差值">{{ summary.countDiff }}</el-descriptions-item>
<el-descriptions-item label="总重差值">{{ summary.weightDiff }}</el-descriptions-item>
<el-descriptions-item label="均重差值">{{ summary.avgWeightDiff }}t</el-descriptions-item>
<el-descriptions-item label="成品率">{{ summary.passRate }}</el-descriptions-item>
<el-descriptions-item label="损耗率">{{ summary.lossRate }}</el-descriptions-item>
<el-descriptions-item label="异常率">{{ summary.abRate }}</el-descriptions-item>
<el-descriptions-item label="正品率">{{ summary.passRate2 }}</el-descriptions-item>
</el-descriptions>
<el-descriptions title="已处理M统计信息" :column="3" border>
<el-descriptions-item label="产出数量">{{ mSummary.outCount }}</el-descriptions-item>
<el-descriptions-item label="产出总重">{{ mSummary.outTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="产出均重">{{ mSummary.outAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗数量">{{ mSummary.lossCount }}</el-descriptions-item>
<el-descriptions-item label="消耗总重">{{ mSummary.lossTotalWeight }}t</el-descriptions-item>
<el-descriptions-item label="消耗均重">{{ mSummary.lossAvgWeight }}t</el-descriptions-item>
<el-descriptions-item label="数量差值">{{ mSummary.countDiff }}</el-descriptions-item>
<el-descriptions-item label="总重差值">{{ mSummary.weightDiff }}</el-descriptions-item>
<el-descriptions-item label="均重差值">{{ mSummary.avgWeightDiff }}t</el-descriptions-item>
<el-descriptions-item label="成品率">{{ mSummary.passRate }}</el-descriptions-item>
<el-descriptions-item label="损耗率">{{ mSummary.lossRate }}</el-descriptions-item>
<el-descriptions-item label="异常率">{{ mSummary.abRate }}</el-descriptions-item>
<el-descriptions-item label="正品率">{{ mSummary.passRate2 }}</el-descriptions-item>
</el-descriptions>
<el-descriptions v-if="reportType === 'team'" title="异常统计" :column="4" border>
<el-descriptions-item v-for="item in abSummary" :key="item.label" :label="item.label">{{ item.value
}}</el-descriptions-item>
</el-descriptions>
<template v-if="reportType === 'team'">
<el-descriptions title="班组统计信息" :column="3" border>
</el-descriptions>
<el-table :data="teamSummary" border>
<el-table-column label="班组" align="center" prop="team" />
<el-table-column label="产出数量" align="center" prop="outCount" />
<el-table-column label="产出总重" align="center" prop="outWeight" />
</el-table>
</template>
<!-- day 类型小时数据趋势图 -->
<div v-if="reportType === 'day'" style="margin-top: 20px; height: 400px;">
<el-card>
<template slot="header">
<div class="clearfix">
<span>小时数据趋势</span>
</div>
</template>
<div ref="dayChart" style="width: 100%; height: 350px;"></div>
</el-card>
</div>
<!-- month 类型日数据趋势图 -->
<div v-if="reportType === 'month'" style="margin-top: 20px; height: 400px;">
<el-card>
<template slot="header">
<div class="clearfix">
<span>日数据趋势</span>
</div>
</template>
<div ref="monthChart" style="width: 100%; height: 350px;"></div>
</el-card>
</div>
<el-descriptions title="尺寸异常统计" :column="4" border>
<el-descriptions-item label="长度异常卷数">{{ sizeAbnormalSummary.length.count }}</el-descriptions-item>
<el-descriptions-item label="长度异常总重">{{ sizeAbnormalSummary.length.weight }}t</el-descriptions-item>
<el-descriptions-item label="长度异常数量占比">{{ sizeAbnormalSummary.length.countRate }}</el-descriptions-item>
<el-descriptions-item label="长度异常重量占比">{{ sizeAbnormalSummary.length.weightRate }}</el-descriptions-item>
<el-descriptions-item label="厚度异常卷数">{{ sizeAbnormalSummary.thickness.count }}</el-descriptions-item>
<el-descriptions-item label="厚度异常总重">{{ sizeAbnormalSummary.thickness.weight }}t</el-descriptions-item>
<el-descriptions-item label="厚度异常数量占比">{{ sizeAbnormalSummary.thickness.countRate }}</el-descriptions-item>
<el-descriptions-item label="厚度异常重量占比">{{ sizeAbnormalSummary.thickness.weightRate }}</el-descriptions-item>
</el-descriptions>
</template>
<!-- 明细信息和标签页 -->
<!-- all 类型产出在前投入在后 -->
<template v-if="reportType === 'all'">
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<el-tabs v-model="activeTab">
<el-tab-pane label="产出钢卷" name="output">
<coil-table :columns="outputColumns" :data="outList" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
<el-tab-pane label="投入钢卷" name="loss">
<coil-table :columns="lossColumns" :data="lossList" :highlight-config="{ rows: commonCoilIds }"></coil-table>
</el-tab-pane>
</el-tabs>
</template>
<template v-else-if="reportType !== 'out' && reportType !== 'loss'">
<el-descriptions title="明细信息" :column="3" border>
</el-descriptions>
<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">
<coil-table :data="outList" :columns="outputColumns" :loading="loading" height="calc(100vh - 360px)" />
</el-tab-pane>
</el-tabs>
</template>
<!-- out 类型只显示产出钢卷 -->
<coil-table v-else-if="reportType === 'out'" :columns="outputColumns" :data="outList"></coil-table>
<!-- loss 类型只显示投入钢卷 -->
<coil-table v-else-if="reportType === 'loss'" :columns="lossColumns" :data="lossList"></coil-table>
<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>
</el-dialog>
<custom-export ref="customExport" :visible.sync="customExportVisible" :storage-key="customExportStorageKey"
:column-groups="columnGroups" @export="handleCustomExport" />
</div>
</template>
<script>
import { listCoilWithIds } from "@/api/wms/coil";
import {
listLightPendingAction,
} from '@/api/wms/pendingAction';
import MemoInput from "@/components/MemoInput";
import MutiSelect from "@/components/MutiSelect";
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { calcSummary, calcAbSummary, calcTeamSummary, calcMSummary } from "@/views/wms/report/js/calc";
import CoilTable from "@/views/wms/report/components/coilTable";
import ColumnsSetting from "@/views/wms/report/components/setting/columns";
import TimeRangePicker from "@/views/wms/report/components/timeRangePicker.vue";
import SplitSummary from "@/views/wms/report/components/summary/splitSummary.vue";
import CustomExport from "@/views/wms/report/components/CustomExport.vue";
import { saveReportFile } from "@/views/wms/report/js/reportFile";
import * as echarts from 'echarts';
export default {
name: 'MergeTemplate',
props: {
actionType: {
type: [Number, String],
required: true
},
productionLine: {
type: String,
default: '',
},
reportType: {
type: String,
default: 'day', // day | month | year | all | team | out | loss
},
warehouseOptions: {
type: Array,
default: () => []
}
},
components: {
MemoInput,
MutiSelect,
ProductInfo,
RawMaterialInfo,
CoilNo,
WarehouseSelect,
CoilTable,
ColumnsSetting,
TimeRangePicker,
SplitSummary,
CustomExport,
},
dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status'],
data() {
const addZero = (num) => num.toString().padStart(2, '0')
const now = new Date()
const currentYear = `${now.getFullYear()}`
const currentMonth = `${now.getFullYear()}-${addZero(now.getMonth() + 1)}`
const currentDay = `${now.getFullYear()}-${addZero(now.getMonth() + 1)}-${addZero(now.getDate())}`
const yesterday = new Date(now)
yesterday.setDate(yesterday.getDate() - 1)
const yesYear = yesterday.getFullYear()
const yesMonth = addZero(yesterday.getMonth() + 1)
const yesDay = addZero(yesterday.getDate())
const defaultStartTime = `${yesYear}-${yesMonth}-${yesDay} 07:00:00`
const defaultEndTime = `${now.getFullYear()}-${addZero(now.getMonth() + 1)}-${addZero(now.getDate())} 07:00:00`
const getDayTimeRange = (dateStr) => {
const yearPattern = /^\d{4}$/;
const monthPattern = /^\d{4}-\d{2}$/;
const dayPattern = /^\d{4}-\d{2}-\d{2}$/;
let startDate, endDate;
if (yearPattern.test(dateStr)) {
startDate = `${dateStr}-01-01`;
endDate = `${dateStr}-12-31`;
} else if (monthPattern.test(dateStr)) {
const [year, month] = dateStr.split('-').map(Number);
startDate = `${dateStr}-01`;
const lastDayOfMonth = new Date(year, month, 0).getDate();
endDate = `${dateStr}-${lastDayOfMonth.toString().padStart(2, '0')}`;
} else if (dayPattern.test(dateStr)) {
startDate = dateStr;
endDate = dateStr;
} else {
throw new Error('输入格式错误,请传入 yyyy、yyyy-MM 或 yyyy-MM-dd 格式的字符串');
}
return {
start: `${startDate} 00:00:00`,
end: `${endDate} 23:59:59`
};
};
const { start, end } = getDayTimeRange(currentMonth);
return {
lossList: [],
outList: [],
activeTab: 'loss',
activeColumnConfig: 'coil-report-loss',
settingVisible: false,
loading: false,
dayDate: currentDay,
monthDate: currentMonth,
yearDate: currentYear,
defaultStartTime,
defaultEndTime,
getDayTimeRange,
// all 类型专用
viewType: 'custom',
yesterdaySummary: {},
monthChart: null,
dayChart: null,
customExportVisible: false,
customExportType: 'output',
columnGroups: {
'基本信息': ['itemTypeDesc', 'warehouseName', 'actualWarehouseName', 'dataTypeText'],
'钢卷号': ['enterCoilNo', 'supplierCoilNo', 'currentCoilNo'],
'时间': ['createTime', 'exportTime', 'exportBy'],
'物理属性': ['netWeight', 'length', 'specification', 'actualThickness', 'theoreticalThickness', 'theoreticalLength', 'scheduleThickness'],
'材质属性': ['material', 'manufacturer', 'surfaceTreatmentDesc', 'zincLayer', 'packingStatus', 'temperGrade', 'coatingType', 'chromePlateCoilNo'],
'用途': ['purpose', 'businessPurpose'],
'状态': ['qualityStatus', 'statusDesc', 'isRelatedToOrderText'],
'其他': ['itemName', 'itemId', 'packagingRequirement', 'trimmingRequirement', 'transferType', 'contractNo', 'saleName', 'remark', 'team'],
},
queryParams: {
startTime: start,
endTime: end,
enterCoilNo: '',
currentCoilNo: '',
warehouseId: '',
itemName: '',
itemSpecification: '',
itemMaterial: '',
itemManufacturer: '',
team: '',
pageSize: 9999,
pageNum: 1,
},
warehouseIds: [
'1988150099140866050',
'1988150263284953089',
'1988150545175736322',
'1988150150521090049',
'2019583656787259393',
'2019583325311414274',
'2019583429955104769',
'2019583137616310273',
],
lossColumns: [],
outputColumns: [],
actionIds: '',
lengthThreshold: 0,
thicknessThreshold: 0
}
},
computed: {
summary() {
return calcSummary(this.outList, this.lossList)
},
mSummary() {
return calcMSummary(this.outList, this.lossList)
},
abSummary() {
return calcAbSummary(this.outList)
},
teamSummary() {
const teamOutSummary = calcTeamSummary(this.outList);
const allTeams = [...new Set(Object.keys(teamOutSummary))];
return allTeams.map(team => {
const outData = teamOutSummary[team] || { count: 0, weight: 0 };
const formatWeight = (weight) => Number(weight || 0).toFixed(2);
return {
team: team,
outCount: outData.count,
outWeight: formatWeight(outData.weight)
};
});
},
outSummary() {
const totalCount = this.outList.length;
const totalWeight = this.outList.reduce((acc, cur) => acc + parseFloat(cur.netWeight), 0);
const avgWeight = totalCount > 0 ? (totalWeight / totalCount).toFixed(2) : 0;
return {
totalCount,
totalWeight: totalWeight.toFixed(2),
avgWeight,
};
},
lossSummary() {
const totalCount = this.lossList.length;
const totalWeight = this.lossList.reduce((acc, cur) => acc + parseFloat(cur.netWeight), 0);
const avgWeight = totalCount > 0 ? (totalWeight / totalCount).toFixed(2) : 0;
return {
totalCount,
totalWeight: totalWeight.toFixed(2),
avgWeight,
};
},
commonCoilIds() {
if (this.productionLine !== '分条线') {
return []
}
const outputCoilIds = new Set(this.outList.map(item => item.coilId))
const lossCoilIds = new Set(this.lossList.map(item => item.coilId))
const commonIds = []
outputCoilIds.forEach(id => {
if (lossCoilIds.has(id)) {
commonIds.push(id)
}
})
return commonIds
},
customExportStorageKey() {
return `coil-report-action-${this.actionType}`
},
sizeAbnormalSummary() {
const totalCount = this.outList.length
const totalWeight = this.outList.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0)
const lengthAbnormal = this.outList.filter(row => {
const lengthDiff = (row.actualLength || 0) - (row.theoreticalLength || 0)
const theoreticalLength = row.theoreticalLength || 1
return Math.abs(lengthDiff) / theoreticalLength > this.lengthThreshold
})
const thicknessAbnormal = this.outList.filter(row => {
const thicknessDiff = (row.theoreticalThickness || 0) - (row.computedThickness || 0)
return thicknessDiff > this.thicknessThreshold
})
const laCount = lengthAbnormal.length
const laWeight = lengthAbnormal.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0)
const taCount = thicknessAbnormal.length
const taWeight = thicknessAbnormal.reduce((acc, cur) => acc + (parseFloat(cur.netWeight) || 0), 0)
return {
length: {
count: laCount,
weight: laWeight.toFixed(2),
countRate: totalCount > 0 ? (laCount / totalCount * 100).toFixed(2) + '%' : '0.00%',
weightRate: totalWeight > 0 ? (laWeight / totalWeight * 100).toFixed(2) + '%' : '0.00%',
},
thickness: {
count: taCount,
weight: taWeight.toFixed(2),
countRate: totalCount > 0 ? (taCount / totalCount * 100).toFixed(2) + '%' : '0.00%',
weightRate: totalWeight > 0 ? (taWeight / totalWeight * 100).toFixed(2) + '%' : '0.00%',
}
}
},
},
watch: {
warehouseOptions: {
handler(newVal) {
if (newVal) {
this.warehouseIds = newVal.map(item => item.value);
}
},
immediate: true
}
},
created() {
this.initDateByReportType()
this.handleQuery()
this.loadColumns()
this.getAlarmThreshold()
},
methods: {
initDateByReportType() {
if (this.reportType === 'out' || this.reportType === 'loss') {
this.queryParams.startTime = this.defaultStartTime;
this.queryParams.endTime = this.defaultEndTime;
} else if (this.reportType === 'team') {
const { start, end } = this.getDayTimeRange(this.dayDate);
this.queryParams.byCreateTimeStart = start;
this.queryParams.byCreateTimeEnd = end;
} else if (this.reportType === 'all') {
// all 类型默认使用当前月份作为自定义时间范围
this.viewType = 'custom';
const { start, end } = this.getDayTimeRange(this.monthDate);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
} else {
let dateStr;
if (this.reportType === 'year') {
dateStr = this.yearDate;
} else if (this.reportType === 'month') {
dateStr = this.monthDate;
} else if (this.reportType === 'day') {
dateStr = this.dayDate;
}
const { start, end } = this.getDayTimeRange(dateStr);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
}
},
handleDateChange() {
let dateStr;
if (this.reportType === 'year') {
dateStr = this.yearDate;
} else if (this.reportType === 'month') {
dateStr = this.monthDate;
} else if (this.reportType === 'day') {
dateStr = this.dayDate;
}
if (dateStr) {
const { start, end } = this.getDayTimeRange(dateStr);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
this.handleQuery();
}
},
// all 类型:视图类型切换
handleViewTypeChange() {
switch (this.viewType) {
case 'day': {
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
this.dayDate = `${year}-${month}-${day}`;
this.handleDayDateChange();
break;
}
case 'month':
this.handleMonthDateChange();
break;
case 'year':
this.handleYearDateChange();
break;
case 'custom':
break;
}
},
// all 类型:日视图日期变更
handleDayDateChange() {
if (this.dayDate) {
const { start, end } = this.getDayTimeRange(this.dayDate);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
this.handleQuery();
}
},
// all 类型:月视图日期变更
handleMonthDateChange() {
if (this.monthDate) {
const { start, end } = this.getDayTimeRange(this.monthDate);
this.queryParams.startTime = start;
this.queryParams.endTime = end;
this.handleQuery();
}
},
// all 类型:年视图日期变更
handleYearDateChange() {
if (this.yearDate) {
this.queryParams.startTime = `${this.yearDate}-01-01 00:00:00`;
this.queryParams.endTime = `${this.yearDate}-12-31 23:59:59`;
this.handleQuery();
}
},
handleQuery() {
this.getList()
},
async getList() {
this.loading = true;
if (this.reportType === 'all') {
// all 类型使用 comprehensive 方式查询
const res = await listLightPendingAction({
enterCoilNo: this.queryParams.enterCoilNo,
startTime: this.queryParams.startTime,
endTime: this.queryParams.endTime,
actionTypes: this.actionType,
actionStatus: 2
});
const lossIds = res.data.filter(item => item.coilId).map(item => item.coilId);
const lossActionIds = res.data.filter(item => item.actionId).map(item => item.actionId);
this.actionIds = lossActionIds.join(',')
const outIds = [...new Set(res.data.filter(item => item.processedCoilIds).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, actionIds: lossActionIds.join(',') || '', startTime: '', endTime: '', selectType: 'raw_material' }),
listCoilWithIds({ ...this.queryParams, coilIds: outIds.join(',') || '', startTime: '', endTime: '', byCreateTimeStart: this.queryParams.startTime, byCreateTimeEnd: this.queryParams.endTime, selectType: 'product' }),
]);
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) }
});
if (this.viewType === 'day') {
this.getYesterdayData()
}
if (this.viewType === 'month') {
this.$nextTick(() => {
this.initMonthChart()
})
}
this.loading = false;
return
}
const res = await listLightPendingAction({
enterCoilNo: this.queryParams.enterCoilNo,
startTime: this.queryParams.startTime,
endTime: this.queryParams.endTime,
actionTypes: this.actionType,
actionStatus: 2
});
const lossIds = res.data.filter(item => item.coilId).map(item => item.coilId);
const lossActionIds = res.data.filter(item => item.actionId).map(item => item.actionId);
this.actionIds = lossActionIds.join(',')
const outIds = [...new Set(res.data.filter(item => item.processedCoilIds).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, actionIds: lossActionIds.join(',') || '', startTime: '', endTime: '', selectType: 'raw_material' }),
listCoilWithIds({ ...this.queryParams, coilIds: outIds.join(',') || '', startTime: '', endTime: '', byCreateTimeStart: this.queryParams.startTime, byCreateTimeEnd: this.queryParams.endTime, selectType: 'product' }),
]);
if (this.reportType === 'out') {
this.outList = outRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return { ...item, computedThickness: parseFloat(thickness), computedWidth: parseFloat(width) }
});
this.lossList = [];
} else if (this.reportType === 'loss') {
this.lossList = lossRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return { ...item, computedThickness: parseFloat(thickness), computedWidth: parseFloat(width) }
});
this.outList = [];
} else {
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) }
});
}
if (this.reportType === 'day') {
this.$nextTick(() => {
this.initDayChart()
})
}
if (this.reportType === 'month') {
this.$nextTick(() => {
this.initMonthChart()
})
}
this.loading = false;
},
// all 类型:获取昨日数据(逻辑同 getList时间向前推一天
async getYesterdayData() {
const yesterday = new Date(this.dayDate)
yesterday.setDate(yesterday.getDate() - 1)
const year = yesterday.getFullYear()
const month = String(yesterday.getMonth() + 1).padStart(2, '0')
const day = String(yesterday.getDate()).padStart(2, '0')
const yesterdayDate = `${year}-${month}-${day}`
const { start, end } = this.getDayTimeRange(yesterdayDate)
const yesterdayParams = {
enterCoilNo: this.queryParams.enterCoilNo,
actionTypes: this.actionType,
actionStatus: 2,
startTime: start,
endTime: end,
}
const res = await listLightPendingAction({ ...yesterdayParams })
const lossIds = res.data.filter(item => item.coilId).map(item => item.coilId)
const lossActionIds = res.data.filter(item => item.actionId).map(item => item.actionId)
const outIds = [...new Set(res.data.filter(item => item.processedCoilIds).map(item => item.processedCoilIds))]
if (lossIds.length === 0 || outIds.length === 0) {
this.yesterdaySummary = {}
return
}
const [lossRes, outRes] = await Promise.all([
listCoilWithIds({ ...yesterdayParams, actionIds: lossActionIds.join(',') || '', startTime: '', endTime: '', selectType: 'raw_material' }),
listCoilWithIds({ ...yesterdayParams, coilIds: outIds.join(',') || '', startTime: '', endTime: '', byCreateTimeStart: start, byCreateTimeEnd: end, selectType: 'product' }),
])
const yesterdayLossList = lossRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return { ...item, computedThickness: parseFloat(thickness), computedWidth: parseFloat(width) }
})
const yesterdayOutList = outRes.rows.map(item => {
const [thickness, width] = item.specification?.split('*') || []
return { ...item, computedThickness: parseFloat(thickness), computedWidth: parseFloat(width) }
})
this.yesterdaySummary = calcSummary(yesterdayOutList, yesterdayLossList)
},
// all 类型:初始化月视图折线图
initMonthChart() {
if (!this.$refs.monthChart) return
if (this.monthChart) {
this.monthChart.dispose()
}
this.monthChart = echarts.init(this.$refs.monthChart)
const dailyData = {}
this.outList.forEach(item => {
const date = item.createTime.split(' ')[0]
if (!dailyData[date]) {
dailyData[date] = { outCount: 0, outTotalWeight: 0, lossCount: 0, lossTotalWeight: 0 }
}
dailyData[date].outCount++
dailyData[date].outTotalWeight += parseFloat(item.netWeight) || 0
})
this.lossList.forEach(item => {
const date = item.actionCompleteTime?.split(' ')[0]
if (!dailyData[date]) {
dailyData[date] = { outCount: 0, outTotalWeight: 0, lossCount: 0, lossTotalWeight: 0 }
}
dailyData[date].lossCount++
dailyData[date].lossTotalWeight += parseFloat(item.netWeight) || 0
})
const dates = Object.keys(dailyData).sort()
const outCountData = dates.map(date => dailyData[date].outCount)
const outTotalWeightData = dates.map(date => dailyData[date].outTotalWeight.toFixed(2))
const lossCountData = dates.map(date => dailyData[date].lossCount)
const lossTotalWeightData = dates.map(date => dailyData[date].lossTotalWeight.toFixed(2))
const option = {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } }
},
legend: { data: ['产出数量', '产出总重', '消耗数量', '消耗总重'] },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: [{ type: 'category', boundaryGap: false, data: dates }],
yAxis: [
{ type: 'value', name: '数量', position: 'left' },
{ type: 'value', name: '重量(t)', position: 'right' }
],
series: [
{ name: '产出数量', type: 'line', data: outCountData, yAxisIndex: 0 },
{ name: '产出总重', type: 'line', data: outTotalWeightData, yAxisIndex: 1 },
{ name: '消耗数量', type: 'line', data: lossCountData, yAxisIndex: 0 },
{ name: '消耗总重', type: 'line', data: lossTotalWeightData, yAxisIndex: 1 }
]
}
this.monthChart.setOption(option)
window.addEventListener('resize', () => {
this.monthChart.resize()
})
},
// day 类型:初始化小时数据折线图
initDayChart() {
if (!this.$refs.dayChart) return
if (this.dayChart) {
this.dayChart.dispose()
}
this.dayChart = echarts.init(this.$refs.dayChart)
const hourlyData = {}
for (let h = 0; h < 24; h++) {
hourlyData[h] = { outCount: 0, outTotalWeight: 0, lossCount: 0, lossTotalWeight: 0 }
}
this.outList.forEach(item => {
const timeStr = item.createTime?.split(' ')[1] || '00:00:00'
const hour = parseInt(timeStr.split(':')[0])
if (hourlyData[hour] !== undefined) {
hourlyData[hour].outCount++
hourlyData[hour].outTotalWeight += parseFloat(item.netWeight) || 0
}
})
this.lossList.forEach(item => {
const timeStr = item.actionCompleteTime?.split(' ')[1] || '00:00:00'
const hour = parseInt(timeStr.split(':')[0])
if (hourlyData[hour] !== undefined) {
hourlyData[hour].lossCount++
hourlyData[hour].lossTotalWeight += parseFloat(item.netWeight) || 0
}
})
const hours = Object.keys(hourlyData).map(Number).sort((a, b) => a - b)
const hourLabels = hours.map(h => `${String(h).padStart(2, '0')}:00`)
const outCountData = hours.map(h => hourlyData[h].outCount)
const outTotalWeightData = hours.map(h => hourlyData[h].outTotalWeight.toFixed(2))
const lossCountData = hours.map(h => hourlyData[h].lossCount)
const lossTotalWeightData = hours.map(h => hourlyData[h].lossTotalWeight.toFixed(2))
const option = {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985' } }
},
legend: { data: ['产出数量', '产出总重', '消耗数量', '消耗总重'] },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: [{ type: 'category', boundaryGap: false, data: hourLabels }],
yAxis: [
{ type: 'value', name: '数量', position: 'left' },
{ type: 'value', name: '重量(t)', position: 'right' }
],
series: [
{ name: '产出数量', type: 'line', data: outCountData, yAxisIndex: 0 },
{ name: '产出总重', type: 'line', data: outTotalWeightData, yAxisIndex: 1 },
{ name: '消耗数量', type: 'line', data: lossCountData, yAxisIndex: 0 },
{ name: '消耗总重', type: 'line', data: lossTotalWeightData, yAxisIndex: 1 }
]
}
this.dayChart.setOption(option)
window.addEventListener('resize', () => {
this.dayChart.resize()
})
},
// 自定义导出
openCustomExport(type) {
if (type === 'output' && this.outList.length === 0) {
this.$message({ message: '暂无产出数据可导出', type: 'warning' })
return
}
if (type === 'loss' && this.lossList.length === 0) {
this.$message({ message: '暂无消耗数据可导出', type: 'warning' })
return
}
this.customExportType = type
this.$refs.customExport.open()
},
handleCustomExport(orderedColumns) {
const { pageNum, pageSize, startTime, endTime, ...filters } = this.queryParams
const type = this.customExportType
const list = type === 'loss' ? this.lossList : this.outList
this.download('wms/materialCoil/exportCustomOrdered', {
...filters,
coilIds: list.map(item => item.coilId).join(','),
columnsOrdered: orderedColumns.join(','),
}, `materialCoil_${new Date().getTime()}.xlsx`)
},
exportData() {
if (this.outList.length === 0) {
this.$message.warning('暂无数据可导出')
return
}
let fileName = `materialCoil_${new Date().getTime()}.xlsx`;
if (['day', 'month', 'year', 'all'].includes(this.reportType)) {
fileName = `materialCoil_${this.queryParams.date || ''}_${new Date().getTime()}.xlsx`;
}
this.download('wms/materialCoil/export', {
coilIds: this.outList.map(item => item.coilId).join(',')
}, fileName)
},
exportLossData() {
if (this.lossList.length === 0) {
this.$message.warning('暂无数据可导出')
return
}
let fileName = `materialCoil_${new Date().getTime()}.xlsx`;
if (['day', 'month', 'year', 'all'].includes(this.reportType)) {
fileName = `materialCoil_${this.queryParams.date || ''}_${new Date().getTime()}.xlsx`;
}
this.download('wms/materialCoil/export', {
actionIds: this.actionIds
}, fileName)
},
saveOutputReport() {
this.loading = true
let reportTypeStr = '产出报表';
if (this.reportType === 'day') {
reportTypeStr = '产出报表,日报表';
} else if (this.reportType === 'month') {
reportTypeStr = '产出报表,月报表';
} else if (this.reportType === 'year') {
reportTypeStr = '产出报表,年报表';
} else if (this.reportType === 'team') {
reportTypeStr = '产出报表,班报表';
} else if (this.reportType === 'all') {
reportTypeStr = '产出报表,综合报表';
}
saveReportFile(this.outList.map(item => item.coilId).join(','), {
reportParams: this.queryParams,
reportType: reportTypeStr,
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
let reportTypeStr = '消耗报表';
if (this.reportType === 'day') {
reportTypeStr = '消耗报表,日报表';
} else if (this.reportType === 'month') {
reportTypeStr = '消耗报表,月报表';
} else if (this.reportType === 'year') {
reportTypeStr = '消耗报表,年报表';
} else if (this.reportType === 'team') {
reportTypeStr = '消耗报表,班报表';
} else if (this.reportType === 'all') {
reportTypeStr = '消耗报表,综合报表';
}
saveReportFile(this.lossList.map(item => item.coilId).join(','), {
reportParams: this.queryParams,
reportType: reportTypeStr,
productionLine: this.productionLine,
}).then(res => {
this.$message({ message: '保存成功', type: 'success' })
}).catch(err => {
this.$message({ message: '保存失败', type: 'error' })
}).finally(() => {
this.loading = false
})
},
getAlarmThreshold() {
this.getConfigKey('material.warning.length').then(response => { this.lengthThreshold = parseFloat(response.msg) || 0 })
this.getConfigKey('material.warning.thickness').then(response => { this.thicknessThreshold = parseFloat(response.msg) || 0 })
},
loadColumns() {
this.lossColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-loss') || '[]') || []
this.outputColumns = JSON.parse(localStorage.getItem('preference-tableColumns-coil-report-output') || '[]') || []
}
}
}
</script>
<style></style>