feat(wms): 新增APS排产对比功能页面
- 添加 compare.vue 页面实现排产明细与现存钢卷对比展示 - 实现左侧排产明细表格按工序筛选功能 - 实现右侧现存钢卷信息展示包括重量统计 - 添加日期查询和汇总统计功能 - 创建 materialCoil API 接口用于获取钢卷数据 - 集成排产明细和钢卷数据的并列对比显示
This commit is contained in:
10
klp-ui/src/api/aps/materialCoil.js
Normal file
10
klp-ui/src/api/aps/materialCoil.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询钢卷物料列表
|
||||||
|
export function listMaterialCoil(query) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/materialCoil/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
312
klp-ui/src/views/wms/post/aps/compare.vue
Normal file
312
klp-ui/src/views/wms/post/aps/compare.vue
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<template>
|
||||||
|
<div class="aps-compare-page">
|
||||||
|
<!-- 顶部工具栏 -->
|
||||||
|
<div class="aps-compare-toolbar">
|
||||||
|
<span class="aps-compare-label">生产日期:</span>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择生产日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
size="small"
|
||||||
|
style="width:160px"
|
||||||
|
@change="handleQuery"
|
||||||
|
/>
|
||||||
|
<el-button size="small" class="aps-btn-red" icon="el-icon-search" @click="handleQuery">查询</el-button>
|
||||||
|
<div v-if="summaryText" class="aps-compare-summary">
|
||||||
|
<span>{{ summaryText }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-row :gutter="12" style="flex:1;min-height:0;">
|
||||||
|
<!-- 左侧:排产明细(按工序筛选) -->
|
||||||
|
<el-col :span="12" style="height:100%;display:flex;flex-direction:column;">
|
||||||
|
<div class="detail-card aps-compare-card">
|
||||||
|
<div class="detail-card-header">
|
||||||
|
<span>排产明细 — 按工序筛选</span>
|
||||||
|
<span v-if="scheduleList.length > 0" style="font-weight:normal;font-size:12px;opacity:0.8;">
|
||||||
|
共 {{ scheduleList.length }} 条
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- 工序筛选按钮 -->
|
||||||
|
<div v-if="actionTypes.length > 0" class="action-filter-bar">
|
||||||
|
<el-button
|
||||||
|
v-for="at in actionTypes"
|
||||||
|
:key="at"
|
||||||
|
size="mini"
|
||||||
|
:type="selectedActionType === at ? 'danger' : 'default'"
|
||||||
|
@click="filterByActionType(at)"
|
||||||
|
>{{ at || '(空)' }}</el-button>
|
||||||
|
<el-button size="mini" :type="selectedActionType === '' ? 'danger' : ''" @click="filterByActionType('')">全部</el-button>
|
||||||
|
</div>
|
||||||
|
<div v-loading="schLoading" class="detail-card-body" style="padding:0;flex:1;overflow:auto;">
|
||||||
|
<el-table
|
||||||
|
v-if="filteredScheduleList.length > 0"
|
||||||
|
:data="filteredScheduleList"
|
||||||
|
border
|
||||||
|
size="small"
|
||||||
|
class="aps-table"
|
||||||
|
>
|
||||||
|
<el-table-column label="排产单号" prop="scheduleNo" min-width="130" show-overflow-tooltip />
|
||||||
|
<el-table-column label="工序类型" prop="actionType" width="90" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="规格" prop="spec" min-width="100" show-overflow-tooltip />
|
||||||
|
<el-table-column label="材质" prop="material" width="80" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="排产吨数" prop="scheduleWeight" width="90" align="right" />
|
||||||
|
<el-table-column label="品名" prop="productType" min-width="80" show-overflow-tooltip />
|
||||||
|
<el-table-column label="订货单位" prop="customerName" min-width="120" show-overflow-tooltip />
|
||||||
|
</el-table>
|
||||||
|
<div v-else-if="!schLoading" style="padding:40px;text-align:center;color:#909399;">
|
||||||
|
{{ hasQueried ? '暂无排产明细' : '请选择日期查询' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 右侧:现存钢卷 -->
|
||||||
|
<el-col :span="12" style="height:100%;display:flex;flex-direction:column;">
|
||||||
|
<div class="detail-card aps-compare-card">
|
||||||
|
<div class="detail-card-header">
|
||||||
|
<span>现存钢卷(今日加工)</span>
|
||||||
|
<span v-if="coilList.length > 0" style="font-weight:normal;font-size:12px;opacity:0.8;">
|
||||||
|
共 {{ coilTotal }} 条,净重合计 {{ coilTotalWeight }} 吨
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-loading="coilLoading" class="detail-card-body" style="padding:0;flex:1;overflow:auto;">
|
||||||
|
<el-table
|
||||||
|
v-if="coilList.length > 0"
|
||||||
|
:data="coilList"
|
||||||
|
border
|
||||||
|
size="small"
|
||||||
|
class="aps-table"
|
||||||
|
>
|
||||||
|
<el-table-column label="入场钢卷号" prop="enterCoilNo" min-width="130" show-overflow-tooltip />
|
||||||
|
<el-table-column label="当前钢卷号" prop="currentCoilNo" min-width="130" show-overflow-tooltip />
|
||||||
|
<el-table-column label="净重(kg)" prop="netWeight" width="100" align="right" />
|
||||||
|
<el-table-column label="材料类型" prop="materialType" width="90" align="center" show-overflow-tooltip />
|
||||||
|
<el-table-column label="物品类型" prop="itemType" width="90" align="center" />
|
||||||
|
<el-table-column label="状态" prop="status" width="80" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span :style="{ color: scope.row.status === 0 ? '#52c41a' : scope.row.status === 1 ? '#1890ff' : '#ff4d4f' }">{{ coilStatusMap[scope.row.status] || scope.row.status }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="班组" prop="team" width="70" align="center" />
|
||||||
|
<el-table-column label="备注" prop="remark" min-width="100" show-overflow-tooltip />
|
||||||
|
</el-table>
|
||||||
|
<div v-else-if="!coilLoading" style="padding:40px;text-align:center;color:#909399;">
|
||||||
|
{{ hasQueried ? '暂无钢卷数据' : '请选择日期查询' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listScheduleItem } from '@/api/aps/schedule'
|
||||||
|
import { listMaterialCoil } from '@/api/aps/materialCoil'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ApsCompare',
|
||||||
|
data() {
|
||||||
|
const today = new Date()
|
||||||
|
const y = today.getFullYear()
|
||||||
|
const m = String(today.getMonth() + 1).padStart(2, '0')
|
||||||
|
const d = String(today.getDate()).padStart(2, '0')
|
||||||
|
return {
|
||||||
|
queryDate: `${y}-${m}-${d}`,
|
||||||
|
hasQueried: false,
|
||||||
|
summaryText: '',
|
||||||
|
|
||||||
|
// 左侧排产明细
|
||||||
|
schLoading: false,
|
||||||
|
scheduleList: [],
|
||||||
|
actionTypes: [],
|
||||||
|
selectedActionType: '',
|
||||||
|
coilStatusMap: { 0: '在库', 1: '在途', 2: '已出库' },
|
||||||
|
|
||||||
|
// 右侧钢卷
|
||||||
|
coilLoading: false,
|
||||||
|
coilList: [],
|
||||||
|
coilTotal: 0,
|
||||||
|
coilTotalWeight: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
filteredScheduleList() {
|
||||||
|
if (!this.selectedActionType) return this.scheduleList
|
||||||
|
return this.scheduleList.filter(item => (item.actionType || '') === this.selectedActionType)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleQuery() {
|
||||||
|
if (!this.queryDate) {
|
||||||
|
this.$message.warning('请选择生产日期')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.hasQueried = true
|
||||||
|
this.queryScheduleItems()
|
||||||
|
this.queryCoils()
|
||||||
|
},
|
||||||
|
|
||||||
|
// ====== 左侧:排产明细 ======
|
||||||
|
queryScheduleItems() {
|
||||||
|
this.schLoading = true
|
||||||
|
this.scheduleList = []
|
||||||
|
this.actionTypes = []
|
||||||
|
this.selectedActionType = ''
|
||||||
|
|
||||||
|
listScheduleItem({ prodDate: this.queryDate, pageNum: 1, pageSize: 9999 }).then(res => {
|
||||||
|
this.scheduleList = (res.rows || []).sort((a, b) => (a.scheduleNo || '').localeCompare(b.scheduleNo || ''))
|
||||||
|
// 提取所有不同的 actionType
|
||||||
|
const types = new Set()
|
||||||
|
this.scheduleList.forEach(item => {
|
||||||
|
if (item.actionType) types.add(item.actionType)
|
||||||
|
})
|
||||||
|
this.actionTypes = [...types].sort()
|
||||||
|
this.updateSummary()
|
||||||
|
}).catch(() => {
|
||||||
|
this.scheduleList = []
|
||||||
|
this.actionTypes = []
|
||||||
|
}).finally(() => {
|
||||||
|
this.schLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
filterByActionType(type) {
|
||||||
|
this.selectedActionType = type
|
||||||
|
},
|
||||||
|
|
||||||
|
// ====== 右侧:钢卷 ======
|
||||||
|
queryCoils() {
|
||||||
|
this.coilLoading = true
|
||||||
|
this.coilList = []
|
||||||
|
|
||||||
|
listMaterialCoil({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 9999
|
||||||
|
// 可根据需要加上日期和 dataType 过滤
|
||||||
|
}).then(res => {
|
||||||
|
this.coilList = res.rows || []
|
||||||
|
this.coilTotal = res.total || this.coilList.length
|
||||||
|
this.coilTotalWeight = this.coilList.reduce((sum, c) => sum + (parseFloat(c.netWeight) || 0) / 1000, 0).toFixed(3)
|
||||||
|
this.updateSummary()
|
||||||
|
}).catch(() => {
|
||||||
|
this.coilList = []
|
||||||
|
this.coilTotal = 0
|
||||||
|
this.coilTotalWeight = 0
|
||||||
|
}).finally(() => {
|
||||||
|
this.coilLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateSummary() {
|
||||||
|
this.summaryText = `排产 ${this.scheduleList.length} 条 | 钢卷 ${this.coilTotal} 条 ${this.coilTotalWeight} 吨`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import './scss/aps-theme.scss';
|
||||||
|
|
||||||
|
.aps-compare-page {
|
||||||
|
height: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: $aps-bg;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aps-compare-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 16px;
|
||||||
|
background: $aps-white;
|
||||||
|
border: 1px solid $aps-border;
|
||||||
|
border-radius: $aps-radius;
|
||||||
|
box-shadow: $aps-shadow-sm;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aps-compare-label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $aps-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aps-compare-summary {
|
||||||
|
margin-left: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
color: $aps-text-muted;
|
||||||
|
background: $aps-silver-1;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: $aps-radius;
|
||||||
|
border: 1px solid $aps-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aps-compare-card {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-filter-bar {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-bottom: 1px solid $aps-border;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aps-btn-red {
|
||||||
|
@include aps-btn-red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card {
|
||||||
|
background: $aps-white;
|
||||||
|
border: 1px solid $aps-border;
|
||||||
|
border-radius: $aps-radius;
|
||||||
|
box-shadow: $aps-shadow-sm;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card-header {
|
||||||
|
background: linear-gradient(to right, $aps-red-2, $aps-red-3);
|
||||||
|
color: white;
|
||||||
|
padding: 8px 14px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card-body {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.aps-table {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
::v-deep th {
|
||||||
|
background: $aps-silver-1 !important;
|
||||||
|
color: $aps-text !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep td {
|
||||||
|
padding: 6px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user