feat(example): 添加生产订单生成功能并优化界面布局

This commit is contained in:
zxy 2026-04-21 10:19:47 +08:00
parent 3077a47d15
commit f4f8491247
7 changed files with 162 additions and 80 deletions

View File

@ -9,7 +9,6 @@
od.ord_item_status AS ordItemStatus, od.ord_item_status AS ordItemStatus,
od.ord_qty AS ordQty, od.ord_qty AS ordQty,
od.produce_qty AS produceQty, od.produce_qty AS produceQty,
(od.ord_qty - IFNULL(od.produce_qty, 0)) AS remainingQty,
od.material_name AS materialName, od.material_name AS materialName,
od.unit AS unit, od.unit AS unit,
od.spec AS spec, od.spec AS spec,
@ -24,7 +23,6 @@
eo.sale_ord_no AS saleOrdNo, eo.sale_ord_no AS saleOrdNo,
eo.cust_name AS custName, eo.cust_name AS custName,
eo.ord_type AS ordType, eo.ord_type AS ordType,
eo.ord_status AS ordStatus,
eo.pro_status AS proStatus, eo.pro_status AS proStatus,
eo.ord_date AS ordDate, eo.ord_date AS ordDate,
eo.req_delivery_date AS reqDeliveryDate, eo.req_delivery_date AS reqDeliveryDate,

View File

@ -112,13 +112,11 @@ public class ExampleOrderServiceImpl extends ServiceImpl<ExampleOrderMapper, Exa
/** 验证表单唯一字段,正则,非空 i-0新增-1修改*/ /** 验证表单唯一字段,正则,非空 i-0新增-1修改*/
@Override @Override
public String checkForm(ExampleOrderForm form, int i) { public String checkForm(ExampleOrderForm form, int i) {
boolean isUp =StringUtil.isNotEmpty(form.getId()) && !form.getId().equals("0"); boolean isUp = StringUtil.isNotEmpty(form.getId()) && !form.getId().equals("0");
String id=""; String id = "";
String countRecover = ""; String countRecover = "";
if (isUp){ if (isUp) {
id = form.getId(); id = form.getId();
}
//主表字段验证
ExampleOrderEntity order = this.getInfo(id); ExampleOrderEntity order = this.getInfo(id);
if (order == null) { if (order == null) {
return "该销售订单不存在,请确认!"; return "该销售订单不存在,请确认!";
@ -129,6 +127,8 @@ public class ExampleOrderServiceImpl extends ServiceImpl<ExampleOrderMapper, Exa
return "该销售订单状态不是已送审,请刷新界面!"; return "该销售订单状态不是已送审,请刷新界面!";
} }
}
//主表字段验证
return countRecover; return countRecover;
} }
/** /**

View File

@ -11,6 +11,7 @@ import jnpf.model.orderdetail.OrderDetailForm;
import jnpf.service.*; import jnpf.service.*;
import jnpf.util.GeneraterSwapUtil; import jnpf.util.GeneraterSwapUtil;
import jnpf.util.JsonUtil; import jnpf.util.JsonUtil;
import jnpf.util.UserProvider;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -42,6 +43,8 @@ public class ProOrderServiceImpl extends ServiceImpl<ProOrderMapper, ProOrderEnt
private final GeneraterSwapUtil generaterSwapUtil; private final GeneraterSwapUtil generaterSwapUtil;
private final UserProvider userProvider;
@Override @Override
public List<ProOrderVO> getList(ProOrderPagination proOrderPagination) { public List<ProOrderVO> getList(ProOrderPagination proOrderPagination) {
@ -115,8 +118,13 @@ public class ProOrderServiceImpl extends ServiceImpl<ProOrderMapper, ProOrderEnt
proOrder.setPlanQty(orderForm.getPlanQty()); proOrder.setPlanQty(orderForm.getPlanQty());
proOrder.setProcessFlow(orderForm.getProcessFlow()); proOrder.setProcessFlow(orderForm.getProcessFlow());
proOrder.setPlanStatus("0");
proOrder.setIsAllLine(orderForm.getIsAllLine()); proOrder.setIsAllLine(orderForm.getIsAllLine());
proOrder.setPlanStatus(orderForm.getPlanStatus());
// 获取当前用户信息
proOrder.setPlanEmpId(userProvider.get().getUserId());
proOrder.setPlanEmpName(userProvider.get().getUserName());
proOrder.setCompleteQty(new BigDecimal(0));
// 物料信息从订单明细中获取 // 物料信息从订单明细中获取
List<OrderDetailForm> orderItems = orderForm.getOrderItems(); List<OrderDetailForm> orderItems = orderForm.getOrderItems();
OrderDetailForm orderDetailForm = orderItems.stream().findFirst().get(); OrderDetailForm orderDetailForm = orderItems.stream().findFirst().get();
@ -149,15 +157,31 @@ public class ProOrderServiceImpl extends ServiceImpl<ProOrderMapper, ProOrderEnt
proSoRelationEntity.setSpec(detailEntity.getSpec()); proSoRelationEntity.setSpec(detailEntity.getSpec());
proSoRelationEntity.setUnit(detailEntity.getUnit()); proSoRelationEntity.setUnit(detailEntity.getUnit());
proSoRelationEntity.setMaterialId(detailEntity.getMaterialId()); proSoRelationEntity.setMaterialId(detailEntity.getMaterialId());
proSoRelationEntity.setProItemId(detailEntity.getId());
proSoRelationService.save(proSoRelationEntity); proSoRelationService.save(proSoRelationEntity);
// 更新订单明细状态为已转产 // 更新订单明细状态为已转产
detailEntity.setOrdItemStatus("2"); detailEntity.setOrdItemStatus("2");
// 默认金额可能为 null // 剩余数量 = ord_qty - produce_qty 默认数量为null 需要设置默认值为0
detailEntity.setProduceQty(detailEntity.getProduceQty() == null ? BigDecimal.ZERO : detailEntity.getProduceQty().add(orderItem.getPlanQty())); BigDecimal ordQty = detailEntity.getOrdQty() == null ? BigDecimal.ZERO : detailEntity.getOrdQty();
BigDecimal produceQty = detailEntity.getProduceQty() == null ? BigDecimal.ZERO : detailEntity.getProduceQty();
produceQty = produceQty.add(orderItem.getPlanQty());
if (ordQty.compareTo(produceQty) == 0) {
detailEntity.setOrdItemStatus("2");
} else {
detailEntity.setOrdItemStatus("1");
}
detailEntity.setProduceQty(produceQty);
orderDetailService.updateById(detailEntity); orderDetailService.updateById(detailEntity);
} }
// 查询所有订单明细如果全部转生产则更新订单状态为已转生产
List<OrderDetailEntity> detailEntities = orderDetailService.getListByOrderId(detailEntity.getSaleOrdId());
boolean allProduce = detailEntities.stream().allMatch(item -> "2".equals(item.getOrdItemStatus()));
if (allProduce) {
orderEntity.setProStatus("2");
} else {
orderEntity.setProStatus("1"); orderEntity.setProStatus("1");
}
orderService.updateById(orderEntity); orderService.updateById(orderEntity);
} }

View File

@ -144,6 +144,8 @@ public class ExampleOrderForm {
private String isAllLine; private String isAllLine;
private String planStatus;
private List<OrderDetailForm> orderItems; private List<OrderDetailForm> orderItems;
private List<OrderLineForm> proLines; private List<OrderLineForm> proLines;

View File

@ -86,4 +86,7 @@ public class ProSoRelationEntity {
@TableField("material_code") @TableField("material_code")
private String materialCode; private String materialCode;
@TableField("pro_item_id")
private Long proItemId;
} }

View File

@ -1,23 +1,17 @@
<template> <template>
<div class="generate-order-container"> <div class="generate-order-container">
<!-- <div class="page-header">
<el-button @click="goBack" class="back-btn">
<i class="el-icon-arrow-left"></i> 返回
</el-button>
<h2 class="page-title">生成订单</h2>
</div> -->
<div class="main-content"> <div class="main-content">
<div class="section"> <div class="main-section">
<div class="section-header"> <!-- 基础信息 -->
<div class="section-title-row">
<span class="section-title">基础信息</span> <span class="section-title">基础信息</span>
</div> </div>
<div class="section-body"> <div class="section-content">
<el-form ref="formRef" :model="baseForm" :rules="dataRule" label-width="120px" class="base-form"> <el-form ref="formRef" :model="baseForm" :rules="dataRule" label-width="120px" class="base-form">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<el-form-item label="订单编号" prop="orderNo"> <el-form-item label="订单编号" prop="orderNo">
<el-input disabled placeholder=""/> <el-input disabled placeholder="" value="自动生成"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
@ -107,41 +101,49 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input v-model="baseForm.remark" type="textarea" :rows="2" placeholder="请输入备注"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<el-form-item> <el-form-item>
<el-checkbox v-model="baseForm.isAllLine" true-label="0" false-label="1"/> <el-checkbox v-model="baseForm.isAllLine" true-label="0" false-label="1"/>
<span style="margin-left: 5px;">所有产线</span> <span style="margin-left: 5px;">所有产线</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-form-item label="备注" prop="remark">
<el-input v-model="baseForm.remark" type="textarea" :rows="2" placeholder="请输入备注"/>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
</div> </div>
</div>
<div class="section"> <!-- 分割线 -->
<div class="section-header"> <div class="divider"></div>
<!-- 销售订单信息 -->
<div class="section-title-row">
<span class="section-title">销售订单信息</span> <span class="section-title">销售订单信息</span>
</div> </div>
<div class="section-body"> <div class="section-content">
<el-table :data="orderList" border :height="200"> <el-table :data="orderList" border :height="180">
<el-table-column prop="itemId" label="序号" align="center" type="index" width="50"/> <el-table-column prop="itemId" label="序号" align="center" type="index" width="50"/>
<el-table-column prop="saleOrdNo" label="订单编码" align="center"/> <el-table-column prop="saleOrdNo" label="订单编码" align="center"/>
<el-table-column prop="proStatus" label="生产状态" align="center"> <el-table-column prop="ordItemStatus" label="生产状态" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
{{ getProStatusText(scope.row.proStatus) }} {{ getLabel('orderItemStatus', scope.row.ordItemStatus) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ordDate" label="下单日期" align="center" :formatter="jnpf.tableDateFormat1"/> <el-table-column prop="ordDate" label="下单日期" align="center" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="ordQty" label="订单数量" align="center"/> <el-table-column prop="ordQty" label="订单数量" align="center"/>
<el-table-column prop="produceQty" label="已转生产数量" align="center"/> <el-table-column prop="produceQty" label="已转生产数量" align="center">
<el-table-column prop="remainingQty" label="剩余数量" align="center"/> <template slot-scope="scope">
{{ scope.row.produceQty || 0 }}
</template>
</el-table-column>
<el-table-column prop="remainingQty" label="剩余数量" align="center">
<template slot-scope="scope">
{{ scope.row.remainingQty || 0 }}
</template>
</el-table-column>
<el-table-column label="转生产数量" align="center"> <el-table-column label="转生产数量" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input <el-input
@ -172,20 +174,22 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</div>
<div class="section"> <!-- 分割线 -->
<div class="section-header" style="display: flex; align-items: center; justify-content: flex-start;"> <div class="divider"></div>
<!-- 下发产线信息 -->
<div class="section-title-row" style="display: flex; align-items: center; justify-content: flex-start;">
<span class="section-title">下发产线信息</span> <span class="section-title">下发产线信息</span>
<el-button type="primary" size="small" @click="addLine" style="margin-left: 30px;"> <el-button type="primary" size="small" @click="addLine" style="margin-left: 30px;">
<i class="el-icon-plus"></i> <i class="el-icon-plus"></i>
</el-button> </el-button>
</div> </div>
<div class="section-body"> <div class="section-content">
<div v-if="!allocateQtyMatch && lineList.length > 0" style="color: #e6a23c; margin-bottom: 10px; font-size: 14px;"> <div v-if="!allocateQtyMatch && lineList.length > 0" style="color: #e6a23c; margin-bottom: 10px; font-size: 14px;">
<i class="el-icon-warning"></i> 产线分配数量不等于计划数量请确认 <i class="el-icon-warning"></i> 产线分配数量不等于计划数量请确认
</div> </div>
<el-table :data="lineList" border :height="200"> <el-table :data="lineList" border :height="180">
<el-table-column prop="index" label="序号" align="center" type="index"/> <el-table-column prop="index" label="序号" align="center" type="index"/>
<el-table-column prop="lineCode" label="产线编码" align="center"/> <el-table-column prop="lineCode" label="产线编码" align="center"/>
<el-table-column prop="lineName" label="产线名称" align="center"/> <el-table-column prop="lineName" label="产线名称" align="center"/>
@ -205,12 +209,32 @@
</el-table-column> </el-table-column>
<el-table-column prop="planStartDate" label="计划开工日期" align="center"> <el-table-column prop="planStartDate" label="计划开工日期" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-date-picker v-model="scope.row.planStartDate" type="date" placeholder="选择日期"/> <el-date-picker
v-model="scope.row.planStartDate"
type="date"
placeholder="选择日期"
:picker-options="{ disabledDate: (time) => {
if (scope.row.planEndDate) {
return time.getTime() > new Date(scope.row.planEndDate).getTime();
}
return false;
}}"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="planEndDate" label="计划完成日期" align="center"> <el-table-column prop="planEndDate" label="计划完成日期" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-date-picker v-model="scope.row.planEndDate" type="date" placeholder="选择日期"/> <el-date-picker
v-model="scope.row.planEndDate"
type="date"
placeholder="选择日期"
:picker-options="{ disabledDate: (time) => {
if (scope.row.planStartDate) {
return time.getTime() < new Date(scope.row.planStartDate).getTime();
}
return false;
}}"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注" align="center"> <el-table-column prop="remark" label="备注" align="center">
@ -258,7 +282,7 @@ export default {
return { return {
lineModalVisible: false, lineModalVisible: false,
baseForm: { baseForm: {
orderNo: "", orderNo: "自动生成",
proDate: "", proDate: "",
orderStatus: "0", orderStatus: "0",
materialName: "", materialName: "",
@ -279,6 +303,9 @@ export default {
processFlowLoading: false, processFlowLoading: false,
allocateQtyMatch: true, allocateQtyMatch: true,
dataRule: { dataRule: {
orderNo: [
{required: true, message: "自动生成", trigger: "blur"}
],
proDate: [ proDate: [
{required: true, message: "请选择订单日期", trigger: "change"} {required: true, message: "请选择订单日期", trigger: "change"}
], ],
@ -294,7 +321,9 @@ export default {
planQty: [ planQty: [
{required: true, message: "", trigger: "blur"} {required: true, message: "", trigger: "blur"}
], ],
unit: [
{required: true, message: "请选择单位", trigger: "change"}
],
planBgDate: [ planBgDate: [
{required: true, message: "请选择开始日期", trigger: "change"} {required: true, message: "请选择开始日期", trigger: "change"}
], ],
@ -504,8 +533,7 @@ export default {
return; return;
} }
if (this.baseForm.isAllLine !== "0" && this.lineList.length > 0 && !this.validateAllocateQty()) return; if (this.baseForm.isAllLine !== "0" && this.lineList.length > 0 && !this.validateAllocateQty()) return;
const submitData = this.prepareSubmitData(); const submitData = this.prepareSubmitData("0");
submitData.orderStatus = "0";
this.generateCheck(submitData).then(() => { this.generateCheck(submitData).then(() => {
this.doGenerate(submitData); this.doGenerate(submitData);
}).catch(() => { }).catch(() => {
@ -516,10 +544,22 @@ export default {
}, },
submit() { submit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
if (!this.validateOrderPlanQty()) return;
if (this.baseForm.isAllLine !== "0" && (!this.lineList || this.lineList.length === 0)) { if (this.baseForm.isAllLine !== "0" && (!this.lineList || this.lineList.length === 0)) {
this.$message.warning("生产订单下发必须指定产线,请确认!"); this.$message.warning("生产订单下发必须指定产线,请确认!");
return; return;
} }
if (this.baseForm.isAllLine !== "0" && this.lineList.length > 0 && !this.validateAllocateQty()) return;
const submitData = this.prepareSubmitData("1");
this.generateCheck(submitData).then(() => {
this.doGenerate(submitData);
}).catch(() => {
return;
});
}
});
}, },
generateCheck(submitData) { generateCheck(submitData) {
@ -627,7 +667,7 @@ export default {
return true; return true;
}, },
prepareSubmitData() { prepareSubmitData(planStatus) {
const orderItems = this.orderList.map(item => ({ const orderItems = this.orderList.map(item => ({
itemId: item.itemId, itemId: item.itemId,
planQty: item.planQty planQty: item.planQty
@ -651,6 +691,7 @@ export default {
planEndDate: this.baseForm.planEndDate, planEndDate: this.baseForm.planEndDate,
processFlow: this.baseForm.processFlow, processFlow: this.baseForm.processFlow,
proDate: this.baseForm.proDate ? new Date(this.baseForm.proDate).toISOString() : '', proDate: this.baseForm.proDate ? new Date(this.baseForm.proDate).toISOString() : '',
planStatus: planStatus,
orderItems: orderItems, orderItems: orderItems,
proLines: proLines proLines: proLines
}; };
@ -688,24 +729,21 @@ export default {
.main-content { .main-content {
flex: 1; flex: 1;
padding: 24px; padding: 16px;
padding-bottom: 80px; padding-bottom: 70px;
overflow-y: auto; overflow-y: auto;
} }
.section { .main-section {
background: #fff; background: #fff;
border-radius: 8px; border-radius: 6px;
margin-bottom: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
padding: 12px 16px;
} }
.section-header { .section-title-row {
padding: 16px 20px; padding: 6px 0;
border-bottom: 1px solid #e4e7ed; margin-bottom: 8px;
display: flex;
justify-content: space-between;
align-items: center;
} }
.section-title { .section-title {
@ -714,8 +752,14 @@ export default {
color: #303133; color: #303133;
} }
.section-body { .section-content {
padding: 20px; margin-bottom: 8px;
}
.divider {
height: 1px;
background-color: #e4e7ed;
margin: 8px 0;
} }
.base-form { .base-form {
@ -740,16 +784,16 @@ export default {
left: 0; left: 0;
right: 0; right: 0;
background: #fff; background: #fff;
padding: 16px 24px; padding: 10px 16px;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
gap: 16px; gap: 12px;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06); box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
z-index: 100; z-index: 100;
} }
.page-footer el-button { .page-footer el-button {
padding: 8px 24px; padding: 6px 20px;
} }
/* 产线选择弹窗样式 */ /* 产线选择弹窗样式 */

View File

@ -103,7 +103,7 @@
{{ getLabel('ordType', scope.row.ordType) }} {{ getLabel('ordType', scope.row.ordType) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="reqDeliveryDate" label="要求交货日期" align="center" min-width="110" :formatter="jnpf.tableDateFormat1"/> <el-table-column prop="reqDeliveryDate" label="要求交货日期" align="center" min-width="90" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="isUrgent" label="是否急单" align="center" min-width="70"> <el-table-column prop="isUrgent" label="是否急单" align="center" min-width="70">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.isUrgent == '0' ? '是' : scope.row.isUrgent == '1' ? '否' : '' }} {{ scope.row.isUrgent == '0' ? '是' : scope.row.isUrgent == '1' ? '否' : '' }}
@ -187,6 +187,17 @@ export default {
'$route.query.refresh': function(newVal) { '$route.query.refresh': function(newVal) {
if (newVal) { if (newVal) {
this.initData(); this.initData();
//
this.selectedRows = [];
this.hasSelected = false;
//
const table = this.$refs.table;
if (table) {
const elTable = table.$refs.JNPFTable || table.$refs.table;
if (elTable && elTable.clearSelection) {
elTable.clearSelection();
}
}
// refresh // refresh
this.$router.replace({ query: {} }); this.$router.replace({ query: {} });
} }