``
This commit is contained in:
parent
9c0d5a65a8
commit
90f8bfe677
128
src/api/system/mrp.js
Normal file
128
src/api/system/mrp.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询MRP运算结果复查列表
|
||||||
|
export function listMrp(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询MRP运算结果复查详细
|
||||||
|
export function getMrp(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增MRP运算结果复查
|
||||||
|
export function addMrp(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改MRP运算结果复查
|
||||||
|
export function updateMrp(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除MRP运算结果复查
|
||||||
|
export function delMrp(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出MRP运算结果复查列表
|
||||||
|
export function exportMrp(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 5 * 60 * 1000 // 导出可能需要较长时间,设置5分钟超时
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== MRP2 相关方法 ==========
|
||||||
|
|
||||||
|
// 查询MRP2运算结果列表
|
||||||
|
export function getMRP2Results(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询MRP2运算结果详细
|
||||||
|
export function getMRP2Result(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增MRP2运算结果
|
||||||
|
export function addMRP2Result(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改MRP2运算结果
|
||||||
|
export function updateMRP2Result(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除MRP2运算结果
|
||||||
|
export function delMRP2Result(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出MRP2运算结果
|
||||||
|
export function exportMRP2Data(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2/export',
|
||||||
|
method: 'post',
|
||||||
|
data: query,
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行MRP2运算
|
||||||
|
export function executeMRP2Calculation(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2/calculate',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取MRP2统计信息
|
||||||
|
export function getMRP2Stats(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/mrp2/stats',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
67
src/api/system/proPlan.js
Normal file
67
src/api/system/proPlan.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询方案管理列表
|
||||||
|
export function listProPlan(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}// 查询方案管理列表
|
||||||
|
export function listProPlan2(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan/list2',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询超期/临期项目列表
|
||||||
|
export function listProPlanOverdue() {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan/overdue',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询临期项目列表
|
||||||
|
export function listProPlanExpirys() {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan/expiryProjects',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询方案管理详细
|
||||||
|
export function getProPlan(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增方案管理
|
||||||
|
export function addProPlan(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改方案管理
|
||||||
|
export function updateProPlan(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除方案管理
|
||||||
|
export function delProPlan(id) {
|
||||||
|
return request({
|
||||||
|
url: '/system/proPlan/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
1050
src/views/indexDaping.vue
Normal file
1050
src/views/indexDaping.vue
Normal file
File diff suppressed because it is too large
Load Diff
945
src/views/system/mrp2/index.vue
Normal file
945
src/views/system/mrp2/index.vue
Normal file
@ -0,0 +1,945 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mrp2-standalone-container">
|
||||||
|
<!-- 独立页面头部 -->
|
||||||
|
<div class="standalone-header">
|
||||||
|
<div class="header-content">
|
||||||
|
<div class="header-left">
|
||||||
|
<h1 style="margin: 0; color: #303133; font-size: 24px;">
|
||||||
|
<i class="el-icon-data-analysis" style="margin-right: 12px; color: #409EFF;"></i>
|
||||||
|
项目供需查询(仅供参考)
|
||||||
|
</h1>
|
||||||
|
<p style="margin: 8px 0 0 0; color: #909399; font-size: 14px;">
|
||||||
|
物料需求计划运算结果查询
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<el-button type="primary" icon="el-icon-refresh" @click="handleRefreshAll">
|
||||||
|
刷新页面
|
||||||
|
</el-button>
|
||||||
|
<el-button type="info" icon="el-icon-back" @click="goBack">
|
||||||
|
返回
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 页面内容 -->
|
||||||
|
<div class="page-content">
|
||||||
|
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<el-card class="box-card" style="margin-bottom: 20px;">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span style="font-weight: 600; color: #303133;">
|
||||||
|
<i class="el-icon-search" style="margin-right: 8px; color: #409EFF;"></i>
|
||||||
|
查询条件
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||||
|
<el-form-item label="生产令号" prop="productionOrderNo">
|
||||||
|
<el-select
|
||||||
|
v-model="productionObj"
|
||||||
|
placeholder="请选择生产令号"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 400px"
|
||||||
|
@change="handleProductionOrderChange"
|
||||||
|
value-key="id"
|
||||||
|
:loading="productionOrderLoading"
|
||||||
|
:filter-method="filterProductionOrders"
|
||||||
|
remote
|
||||||
|
reserve-keyword
|
||||||
|
popper-class="production-order-select-dropdown"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in filteredProductionOrderList"
|
||||||
|
:key="item.id"
|
||||||
|
:value="item"
|
||||||
|
>
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; min-height: 40px; padding: 4px 0;">
|
||||||
|
<div style="flex: 1; min-width: 0;">
|
||||||
|
<div style="font-weight: 600; color: #303133; font-size: 14px; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" :title="item.productionOrderNo">
|
||||||
|
{{ item.productionOrderNo }}
|
||||||
|
</div>
|
||||||
|
<div style="color: #909399; font-size: 12px; margin-top: 2px; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" :title="item.productionName">
|
||||||
|
{{ item.productionName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right; margin-left: 12px; flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end;">
|
||||||
|
<el-tag
|
||||||
|
v-if="item.drawingNo"
|
||||||
|
size="mini"
|
||||||
|
type="info"
|
||||||
|
style="margin-bottom: 2px; max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"
|
||||||
|
:title="item.drawingNo"
|
||||||
|
>
|
||||||
|
{{ item.drawingNo }}
|
||||||
|
</el-tag>
|
||||||
|
<div style="color: #67c23a; font-size: 11px; line-height: 1.2; max-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" :title="item.createdBy || '系统'">
|
||||||
|
{{ item.createdBy || '系统' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 当前选择的生产令号信息 -->
|
||||||
|
<el-card v-if="productionObj" class="box-card production-order-info" style="margin-bottom: 20px;">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span style="font-weight: 600; color: #303133;">
|
||||||
|
<i class="el-icon-document" style="margin-right: 8px; color: #409EFF;"></i>
|
||||||
|
当前选择的生产令号
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px; padding: 10px 0;">
|
||||||
|
<div style="flex: 1;">
|
||||||
|
<div style="display: flex; align-items: center; gap: 12px;">
|
||||||
|
<el-tag type="primary" size="medium" style="font-weight: 600;">
|
||||||
|
{{ productionObj.productionOrderNo }}
|
||||||
|
</el-tag>
|
||||||
|
<span style="font-size: 16px; font-weight: 600; color: #303133;">
|
||||||
|
{{ productionObj.productionName }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 8px; display: flex; gap: 16px; font-size: 13px; color: #606266;">
|
||||||
|
<span v-if="productionObj.drawingNo">
|
||||||
|
<i class="el-icon-document-copy" style="margin-right: 4px;"></i>
|
||||||
|
图号: {{ productionObj.drawingNo }}
|
||||||
|
</span>
|
||||||
|
<span v-if="productionObj.createdBy">
|
||||||
|
<i class="el-icon-user" style="margin-right: 4px;"></i>
|
||||||
|
创建人: {{ productionObj.createdBy }}
|
||||||
|
</span>
|
||||||
|
<span v-if="productionObj.createTime">
|
||||||
|
<i class="el-icon-time" style="margin-right: 4px;"></i>
|
||||||
|
创建时间: {{ formatDateTime(productionObj.createTime) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
@click="handleRefreshMrpData"
|
||||||
|
:loading="mrpLoading"
|
||||||
|
>
|
||||||
|
刷新数据
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- MRP运算结果 -->
|
||||||
|
<el-card class="box-card mrp-result-card" style="margin-bottom: 20px;">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span style="font-weight: 600; color: #303133;">
|
||||||
|
<i class="el-icon-data-analysis" style="margin-right: 8px; color: #409EFF;"></i>
|
||||||
|
运算结果
|
||||||
|
</span>
|
||||||
|
<div style="float: right; display: flex; align-items: center; gap: 12px;">
|
||||||
|
<!-- 运算状态显示 -->
|
||||||
|
<div v-if="loadingMRP" class="mrp-status-indicator">
|
||||||
|
<i class="el-icon-loading" style="margin-right: 6px;"></i>
|
||||||
|
<span>{{ mrpOperationStatus || '运算进行中...' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 运算结果按钮 -->
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="medium"
|
||||||
|
:loading="loadingMRP"
|
||||||
|
:disabled="loadingMRP"
|
||||||
|
@click="getMRPResults()"
|
||||||
|
class="mrp-calculate-btn"
|
||||||
|
>
|
||||||
|
{{ loadingMRP ? '核算中...' : '开始核算' }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<!-- 搜索输入框 -->
|
||||||
|
<el-input
|
||||||
|
v-model="mrpSearchKeyword"
|
||||||
|
placeholder="搜索物料名称或编码"
|
||||||
|
style="width: 220px;"
|
||||||
|
size="small"
|
||||||
|
clearable
|
||||||
|
@input="handleMrpSearch"
|
||||||
|
@clear="clearMrpSearch"
|
||||||
|
class="mrp-search-input"
|
||||||
|
>
|
||||||
|
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||||
|
</el-input>
|
||||||
|
|
||||||
|
<!-- 导出按钮 -->
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
size="small"
|
||||||
|
icon="el-icon-download"
|
||||||
|
@click="handleExportMrp"
|
||||||
|
:loading="exportLoading"
|
||||||
|
:disabled="!productionObj || !productionObj.id"
|
||||||
|
class="mrp-export-btn"
|
||||||
|
:title="productionObj && productionObj.id ? `导出${productionObj.productionOrderNo}的MRP数据` : '请先选择生产令号'"
|
||||||
|
>
|
||||||
|
导出Excel
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-button type="text" @click="handleRefreshMrpData">
|
||||||
|
<i class="el-icon-refresh"></i> 刷新
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 统计信息 -->
|
||||||
|
<div
|
||||||
|
v-if="productionObj"
|
||||||
|
style="margin-bottom: 15px; padding: 15px; background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%); border-radius: 8px; border-left: 4px solid #409EFF;">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="6">
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #409EFF;">{{ mrpStats.totalMaterials }}</div>
|
||||||
|
<div style="font-size: 12px; color: #606266;">总物料数</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #67c23a;">{{ mrpStats.positiveStock }}</div>
|
||||||
|
<div style="font-size: 12px; color: #606266;">正库存</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #f56c6c;">{{ mrpStats.negativeStock }}</div>
|
||||||
|
<div style="font-size: 12px; color: #606266;">负库存</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #e6a23c;">{{ mrpStats.zeroStock }}</div>
|
||||||
|
<div style="font-size: 12px; color: #606266;">零库存</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 提示信息 -->
|
||||||
|
<div v-if="!productionObj" style="text-align: center; padding: 40px; color: #909399;">
|
||||||
|
<i class="el-icon-info" style="font-size: 48px; margin-bottom: 16px;"></i>
|
||||||
|
<p style="font-size: 16px; margin: 0;">请先选择生产令号以查看运算结果</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
v-else
|
||||||
|
:data="mrpResultData"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="{ background: '#f5f7fa', color: '#606266' }"
|
||||||
|
:row-class-name="getMrpRowClass"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
size="small"
|
||||||
|
v-loading="mrpLoading"
|
||||||
|
>
|
||||||
|
<el-table-column prop="materialCode" label="物料编码" min-width="120" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="materialName" label="物料名称" min-width="100" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="purchaseNotInStock" label="项目本批数" width="130" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #e6a23c">{{ scope.row.purchaseNotInStock.toFixed(2) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="availableStock" label="本项目可用库存" width="120" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span :style="{ color: scope.row.availableStock < 0 ? '#f56c6c' : '#67c23a' }">
|
||||||
|
{{ scope.row.availableStock.toFixed(3) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="realTimeStock" label="当前可用库存" width="100" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span :style="{ color: scope.row.realTimeStock < 0 ? '#f56c6c' : '#67c23a' }">
|
||||||
|
{{ scope.row.realTimeStock.toFixed(3) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="prodNotInStock" label="本次生产未入库" width="130" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #e6a23c">{{ scope.row.prodNotInStock.toFixed(3) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="purchaseRequestQty" label="本项目采购申请" width="130" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #409eff">{{ scope.row.purchaseRequestQty.toFixed(3) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column prop="childNotPickedQty" label="子项未领料数量" width="130" align="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span style="color: #f56c6c">{{ scope.row.childNotPickedQty.toFixed(3) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="createTime" label="创建时间" width="160" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ formatDateTime(scope.row.createTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="updateTime" label="更新时间" width="160" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ formatDateTime(scope.row.updateTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<el-pagination
|
||||||
|
v-if="productionObj"
|
||||||
|
@size-change="handleMrpSizeChange"
|
||||||
|
@current-change="handleMrpCurrentChange"
|
||||||
|
:current-page="mrpQueryParams.pageNum"
|
||||||
|
:page-sizes="[10, 50, 100, 500]"
|
||||||
|
:page-size="mrpQueryParams.pageSize"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="mrpTotal"
|
||||||
|
style="margin-top: 20px; text-align: right;"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { listMrp, exportMrp } from '@/api/system/mrp'
|
||||||
|
import { listOrderPro, getMRPResults } from '@/api/system/orderPro'
|
||||||
|
import dayjs from "dayjs"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MRPIndex",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
productionOrderNo: null,
|
||||||
|
materialCode: null,
|
||||||
|
materialName: null
|
||||||
|
},
|
||||||
|
showSearch: true,
|
||||||
|
|
||||||
|
// 生产令号对象(模拟orderPro中的productionObj)
|
||||||
|
productionObj: null,
|
||||||
|
productionOrderList: [], // 生产令号列表
|
||||||
|
filteredProductionOrderList: [], // 过滤后的生产令号列表
|
||||||
|
productionOrderLoading: false, // 生产令号加载状态
|
||||||
|
|
||||||
|
// MRP相关数据(与orderPro中的MRP数据完全一致)
|
||||||
|
mrpResultData: [],
|
||||||
|
mrpLoading: false,
|
||||||
|
mrpTotal: 0,
|
||||||
|
mrpSearchKeyword: '',
|
||||||
|
mrpQueryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
materialName: '',
|
||||||
|
materialCode: '',
|
||||||
|
orderProId: null
|
||||||
|
},
|
||||||
|
loadingMRP: false,
|
||||||
|
mrpOperationStatus: '', // MRP运算状态
|
||||||
|
exportLoading: false, // 导出加载状态
|
||||||
|
mrpStats: {
|
||||||
|
totalMaterials: 0,
|
||||||
|
positiveStock: 0,
|
||||||
|
negativeStock: 0,
|
||||||
|
zeroStock: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getProductionOrderList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 获取生产令号列表 */
|
||||||
|
async getProductionOrderList() {
|
||||||
|
this.productionOrderLoading = true
|
||||||
|
try {
|
||||||
|
const response = await listOrderPro({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 1000 // 获取所有生产令号
|
||||||
|
})
|
||||||
|
if (response && response.rows) {
|
||||||
|
this.productionOrderList = response.rows
|
||||||
|
this.filteredProductionOrderList = response.rows
|
||||||
|
} else {
|
||||||
|
this.productionOrderList = []
|
||||||
|
this.filteredProductionOrderList = []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取生产令号列表失败:', error)
|
||||||
|
this.$message.error('获取生产令号列表失败')
|
||||||
|
this.productionOrderList = []
|
||||||
|
this.filteredProductionOrderList = []
|
||||||
|
} finally {
|
||||||
|
this.productionOrderLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 过滤生产令号 */
|
||||||
|
filterProductionOrders(query) {
|
||||||
|
if (!query) {
|
||||||
|
this.filteredProductionOrderList = this.productionOrderList
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyword = query.toLowerCase()
|
||||||
|
this.filteredProductionOrderList = this.productionOrderList.filter(item =>
|
||||||
|
item.productionOrderNo.toLowerCase().includes(keyword) ||
|
||||||
|
item.productionName.toLowerCase().includes(keyword) ||
|
||||||
|
(item.drawingNo && item.drawingNo.toLowerCase().includes(keyword)) ||
|
||||||
|
(item.createdBy && item.createdBy.toLowerCase().includes(keyword))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 处理生产令号变化 */
|
||||||
|
handleProductionOrderChange(selectedOrder) {
|
||||||
|
if (selectedOrder) {
|
||||||
|
this.productionObj = selectedOrder
|
||||||
|
this.mrpQueryParams.orderProId = selectedOrder.id
|
||||||
|
// 选择生产令号后自动获取MRP数据
|
||||||
|
this.getMrpData()
|
||||||
|
} else {
|
||||||
|
this.productionObj = null
|
||||||
|
this.mrpQueryParams.orderProId = null
|
||||||
|
this.mrpResultData = []
|
||||||
|
this.mrpTotal = 0
|
||||||
|
this.mrpStats = {
|
||||||
|
totalMaterials: 0,
|
||||||
|
positiveStock: 0,
|
||||||
|
negativeStock: 0,
|
||||||
|
zeroStock: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 查询MRP结果列表 */
|
||||||
|
getList() {
|
||||||
|
if (!this.productionObj) {
|
||||||
|
this.$message.warning('请先选择生产令号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.getMrpData()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery() {
|
||||||
|
this.mrpQueryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
resetQuery() {
|
||||||
|
this.resetForm("queryForm")
|
||||||
|
this.handleQuery()
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
resetForm(refName) {
|
||||||
|
if (this.$refs[refName]) {
|
||||||
|
this.$refs[refName].resetFields()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** MRP运算结果复查相关方法 */
|
||||||
|
// 获取MRP运算结果
|
||||||
|
async getMRPResults() {
|
||||||
|
if (!this.productionObj || !this.productionObj.id) {
|
||||||
|
this.$message.error('请先选择生产令号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只显示一次开始提示,不重复弹窗
|
||||||
|
this.$message({
|
||||||
|
message: '运算已开始,由于数据量较大,可能需要较长时间,请耐心等待...',
|
||||||
|
type: 'info',
|
||||||
|
duration: 6000, // 减少到6秒
|
||||||
|
showClose: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.loadingMRP = true;
|
||||||
|
this.mrpOperationStatus = '运算已开始,正在处理数据...';
|
||||||
|
|
||||||
|
// 只更新状态,不弹窗提醒
|
||||||
|
const progressTimer = setInterval(() => {
|
||||||
|
this.mrpOperationStatus = '运算仍在进行中,请继续等待...';
|
||||||
|
// 移除弹窗提示,只更新状态显示
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const response = await getMRPResults(this.productionObj.id);
|
||||||
|
|
||||||
|
|
||||||
|
// 清除定时器
|
||||||
|
clearInterval(progressTimer);
|
||||||
|
|
||||||
|
if (response && response.code === 200) {
|
||||||
|
this.$message.success('MRP运算完成!');
|
||||||
|
// 运算完成后刷新MRP数据
|
||||||
|
await this.getMrpData();
|
||||||
|
} else {
|
||||||
|
console.error('运算失败,响应:', response);
|
||||||
|
this.$message.error(response?.msg || '运算失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 清除定时器
|
||||||
|
clearInterval(progressTimer);
|
||||||
|
|
||||||
|
console.error('运算异常:', error);
|
||||||
|
console.error('错误详情:', {
|
||||||
|
message: error.message,
|
||||||
|
code: error.code,
|
||||||
|
response: error.response,
|
||||||
|
status: error.response?.status,
|
||||||
|
data: error.response?.data
|
||||||
|
});
|
||||||
|
|
||||||
|
// 简化错误提示,避免重复弹窗
|
||||||
|
if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
|
||||||
|
this.$message.error('运算超时,请稍后重试');
|
||||||
|
} else if (error.response?.status === 404) {
|
||||||
|
this.$message.error('运算接口不存在,请检查后端服务');
|
||||||
|
} else if (error.response?.status === 500) {
|
||||||
|
this.$message.error('运算服务器内部错误,请稍后重试');
|
||||||
|
} else {
|
||||||
|
this.$message.error(`运算失败: ${error.message || '未知错误'}`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.loadingMRP = false;
|
||||||
|
this.mrpOperationStatus = ''; // 清空状态
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取MRP数据
|
||||||
|
async getMrpData() {
|
||||||
|
this.mrpLoading = true;
|
||||||
|
try {
|
||||||
|
this.mrpQueryParams.orderProId = this.productionObj.id;
|
||||||
|
const response = await listMrp(this.mrpQueryParams);
|
||||||
|
|
||||||
|
if (response && response.rows) {
|
||||||
|
// 统一转Number,避免 toFixed 报错
|
||||||
|
const processedRows = response.rows.map(item => ({
|
||||||
|
...item,
|
||||||
|
availableStock: Number(item.availableStock) || 0,
|
||||||
|
realTimeStock: Number(item.realTimeStock) || 0,
|
||||||
|
prodNotInStock: Number(item.prodNotInStock) || 0,
|
||||||
|
purchaseRequestQty: Number(item.purchaseRequestQty) || 0,
|
||||||
|
purchaseNotInStock: Number(item.purchaseNotInStock) || 0,
|
||||||
|
childNotPickedQty: Number(item.childNotPickedQty) || 0,
|
||||||
|
createTime: item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss') : '',
|
||||||
|
updateTime: item.updateTime ? dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||||
|
}));
|
||||||
|
this.mrpResultData = processedRows;
|
||||||
|
this.mrpTotal = response.total || processedRows.length;
|
||||||
|
// 统计计算也用处理过的数字数据
|
||||||
|
this.calculateMrpStats(processedRows);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error);
|
||||||
|
this.$message.error('获取数据失败');
|
||||||
|
} finally {
|
||||||
|
this.mrpLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// MRP分页大小改变
|
||||||
|
handleMrpSizeChange(size) {
|
||||||
|
this.mrpQueryParams.pageSize = size;
|
||||||
|
this.mrpQueryParams.pageNum = 1;
|
||||||
|
this.getMrpData();
|
||||||
|
},
|
||||||
|
|
||||||
|
// MRP当前页改变
|
||||||
|
handleMrpCurrentChange(page) {
|
||||||
|
this.mrpQueryParams.pageNum = page;
|
||||||
|
this.getMrpData();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
formatDateTime(date) {
|
||||||
|
if (!date) return '-';
|
||||||
|
if (typeof date === 'string') {
|
||||||
|
date = new Date(date);
|
||||||
|
}
|
||||||
|
if (isNaN(date.getTime())) return '-';
|
||||||
|
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// MRP搜索处理
|
||||||
|
handleMrpSearch() {
|
||||||
|
this.mrpQueryParams.pageNum = 1;
|
||||||
|
this.mrpQueryParams.materialCode = this.mrpSearchKeyword;
|
||||||
|
console.log('搜索参数:', this.mrpQueryParams);
|
||||||
|
this.getMrpData();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清空MRP搜索
|
||||||
|
clearMrpSearch() {
|
||||||
|
this.mrpSearchKeyword = '';
|
||||||
|
this.mrpQueryParams.materialCode = '';
|
||||||
|
this.mrpQueryParams.pageNum = 1;
|
||||||
|
this.getMrpData();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 过滤MRP数据(前端过滤,作为备用方案)
|
||||||
|
filterMrpData(data) {
|
||||||
|
if (!this.mrpSearchKeyword) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyword = this.mrpSearchKeyword.toLowerCase();
|
||||||
|
return data.filter(item =>
|
||||||
|
item.materialName.toLowerCase().includes(keyword) ||
|
||||||
|
item.materialCode.toLowerCase().includes(keyword)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 计算MRP统计信息
|
||||||
|
calculateMrpStats(data) {
|
||||||
|
const total = data.length;
|
||||||
|
const positive = data.filter(item => item.availableStock > 0).length;
|
||||||
|
const negative = data.filter(item => item.availableStock < 0).length;
|
||||||
|
const zero = data.filter(item => item.availableStock === 0).length;
|
||||||
|
|
||||||
|
this.mrpStats = {
|
||||||
|
totalMaterials: total,
|
||||||
|
positiveStock: positive,
|
||||||
|
negativeStock: negative,
|
||||||
|
zeroStock: zero
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// 刷新MRP数据
|
||||||
|
handleRefreshMrpData() {
|
||||||
|
this.mrpQueryParams.pageNum = 1;
|
||||||
|
this.getMrpData();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导出MRP数据
|
||||||
|
async handleExportMrp() {
|
||||||
|
// 增强参数验证
|
||||||
|
if (!this.productionObj) {
|
||||||
|
this.$message.error('请先选择生产令号');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.productionObj.id) {
|
||||||
|
this.$message.error('生产令号ID无效,请重新选择');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.productionObj.productionOrderNo) {
|
||||||
|
this.$message.error('生产令号信息不完整,请重新选择');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调试信息
|
||||||
|
console.log('productionObj:', this.productionObj);
|
||||||
|
console.log('productionObj.id:', this.productionObj.id);
|
||||||
|
console.log('mrpResultData.length:', this.mrpResultData?.length || 0);
|
||||||
|
|
||||||
|
// 显示导出确认信息
|
||||||
|
const exportInfo = `导出生产令号"${this.productionObj.productionOrderNo}"的数据`;
|
||||||
|
const searchInfo = this.mrpSearchKeyword ? `,包含搜索关键词"${this.mrpSearchKeyword}"` : '';
|
||||||
|
const dataInfo = this.mrpResultData && this.mrpResultData.length > 0
|
||||||
|
? `,当前显示${this.mrpResultData.length}条记录`
|
||||||
|
: '(后台将查询所有相关数据)';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.$confirm(
|
||||||
|
`${exportInfo}${searchInfo}${dataInfo}。\n\n确定要导出吗?`,
|
||||||
|
'确认导出',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定导出',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'info'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
// 用户取消导出
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exportLoading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 准备导出参数,主要传递orderProId给后台
|
||||||
|
const exportParams = {
|
||||||
|
orderProId: this.productionObj.id, // 核心参数:生产令号ID
|
||||||
|
materialCode: this.mrpSearchKeyword || '', // 可选的物料编码搜索
|
||||||
|
materialName: '', // 清空名称搜索,避免冲突
|
||||||
|
pageSize: 9999, // 后台查询时获取所有数据
|
||||||
|
pageNum: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const response = await exportMrp(exportParams);
|
||||||
|
|
||||||
|
// 创建下载链接
|
||||||
|
const blob = new Blob([response], {
|
||||||
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
|
});
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `MRP运算结果_${this.productionObj.productionOrderNo}_${new Date().getTime()}.xlsx`;
|
||||||
|
link.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
this.$message.success(`导出成功!文件已下载:运算结果_${this.productionObj.productionOrderNo}_${new Date().getTime()}.xlsx`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('导出失败:', error);
|
||||||
|
this.$message.error('导出失败: ' + (error.message || error));
|
||||||
|
} finally {
|
||||||
|
this.exportLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取MRP行样式类
|
||||||
|
getMrpRowClass({ row, rowIndex }) {
|
||||||
|
if (row.availableStock < 0) {
|
||||||
|
return 'negative-stock-row'
|
||||||
|
} else if (row.availableStock === 0) {
|
||||||
|
return 'zero-stock-row'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 刷新整个页面
|
||||||
|
handleRefreshAll() {
|
||||||
|
this.getProductionOrderList()
|
||||||
|
if (this.productionObj) {
|
||||||
|
this.getMrpData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
goBack() {
|
||||||
|
if (window.history.length > 1) {
|
||||||
|
this.$router.go(-1)
|
||||||
|
} else {
|
||||||
|
// 如果没有历史记录,可以跳转到首页或其他页面
|
||||||
|
this.$router.push('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.mrp2-standalone-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.standalone-header {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 20px 0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-left h1 {
|
||||||
|
color: white !important;
|
||||||
|
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-left p {
|
||||||
|
color: rgba(255, 255, 255, 0.8) !important;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-content {
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
border-bottom: 1px solid #e4e7ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-result-card {
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-status-indicator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #f0f9ff;
|
||||||
|
border: 1px solid #b3d8ff;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #409eff;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-calculate-btn {
|
||||||
|
background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-calculate-btn:hover {
|
||||||
|
background: linear-gradient(135deg, #66b1ff 0%, #409eff 100%);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 8px rgba(64, 158, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-search-input {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-export-btn {
|
||||||
|
background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0 2px 4px rgba(103, 194, 58, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-export-btn:hover {
|
||||||
|
background: linear-gradient(135deg, #85ce61 0%, #67c23a 100%);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 8px rgba(103, 194, 58, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表格行样式 */
|
||||||
|
:deep(.negative-stock-row) {
|
||||||
|
background-color: #fef0f0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.negative-stock-row:hover > td) {
|
||||||
|
background-color: #fde2e2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.zero-stock-row) {
|
||||||
|
background-color: #fdf6ec !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.zero-stock-row:hover > td) {
|
||||||
|
background-color: #faecd8 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 生产令号选择器优化样式 */
|
||||||
|
.production-order-select-dropdown {
|
||||||
|
min-width: 400px !important;
|
||||||
|
max-width: 600px !important;
|
||||||
|
max-height: 400px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-select-dropdown .el-select-dropdown__item {
|
||||||
|
height: auto !important;
|
||||||
|
min-height: 40px !important;
|
||||||
|
padding: 8px 16px !important;
|
||||||
|
line-height: 1.4 !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
border-bottom: 1px solid #f0f0f0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-select-dropdown .el-select-dropdown__item:last-child {
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-select-dropdown .el-select-dropdown__item:hover {
|
||||||
|
background-color: #f5f7fa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-select-dropdown .el-select-dropdown__item.selected {
|
||||||
|
background-color: #ecf5ff !important;
|
||||||
|
color: #409eff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-select-dropdown .el-select-dropdown__item.is-disabled {
|
||||||
|
color: #c0c4cc !important;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全局下拉选择器样式优化 */
|
||||||
|
:deep(.el-select-dropdown__item) {
|
||||||
|
height: auto !important;
|
||||||
|
padding: 12px 20px !important;
|
||||||
|
line-height: 1.4 !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-select-dropdown__item:hover) {
|
||||||
|
background-color: #f5f7fa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-select-dropdown__item.selected) {
|
||||||
|
background-color: #ecf5ff !important;
|
||||||
|
color: #409eff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 生产令号信息卡片样式 */
|
||||||
|
.production-order-info {
|
||||||
|
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||||
|
border-left: 4px solid #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-info .el-card__header {
|
||||||
|
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
|
||||||
|
border-bottom: 1px solid #b3d8ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.app-container {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mrp-status-indicator {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.production-order-info .el-card__body {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user