Compare commits

..

44 Commits

Author SHA1 Message Date
f7a8b3df22 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-04-20 11:04:18 +08:00
4fefc68bbc fix(wms): 修复合同ID为空时添加合同关系的错误
在合并、分条和批量分条操作中,当合同ID为空时不再尝试添加合同关系
同时优化批量分条时的合同关系添加逻辑,先过滤掉空合同ID
2026-04-20 11:04:14 +08:00
cdcf5e2428 加入规程管理sql 2026-04-19 14:29:57 +08:00
deb684ce27 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-04-19 14:28:02 +08:00
3f300e05e9 加入规程管理sql 2026-04-19 14:27:05 +08:00
af002b84d3 feat(合同管理): 新增钢卷与合同关联功能
- 添加钢卷与合同关联的API接口
- 在合卷、分条、打字等操作中增加合同选择组件
- 创建合同选择组件ContractSelect
- 在合同详情页新增生产成果展示页签
- 实现合同列表的本地存储功能
2026-04-18 16:18:22 +08:00
143764f7f8 feat(钢卷调拨): 新增调拨类型列和改判功能
添加调拨类型列显示和钢卷改判功能,包括改判弹窗和重贴标签操作
2026-04-18 15:56:28 +08:00
0822ca7cc8 refactor(wms): 修改钢卷合卷功能返回结果卷
- 将IWmsMaterialCoilService.mergeCoils方法返回值从Boolean改为Long
- 更新WmsMaterialCoilController.mergeCoils方法以返回合卷后的新钢卷ID
- 修改WmsMaterialCoilServiceImpl.mergeCoils实现以返回合并后的钢卷ID
- 移除原有的布尔返回值,改为返回实际的业务数据ID
- 保持事务处理和业务逻辑完整性
2026-04-18 14:53:42 +08:00
5b452bad31 fix(order): 修复订单详情中钢卷信息关联错误
- 将合同ID替换为订单ID进行钢卷信息映射
- 确保钢卷列表正确关联到对应的订单记录
- 修复了因键值不匹配导致的钢卷信息丢失问题
2026-04-18 14:48:58 +08:00
4f259c5aba Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-04-18 14:28:55 +08:00
34dd8004c4 fix(order): 解决计划日期时间设置问题
- 将日期设置为当天的开始时间 00:00:00
- 使用Calendar类精确设置小时、分钟、秒和毫秒为零值
- 确保计划日期查询使用正确的日期范围
- 避免因时间戳差异导致的数据查询不准确问题
2026-04-18 14:28:44 +08:00
254dada485 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-04-18 14:24:22 +08:00
ee2bb280b6 refactor(mapper): 更新 MyBatis 映射文件中的对应 SQL 查询 ID
- 将 ApsPlanSheetMapper 中的 selectList 方法重命名为 selectListByReq
- 更新 MyBatis 映射文件中的对应 SQL 查询 ID
- 修改服务实现类中的方法调用以匹配新方法名
2026-04-18 14:21:42 +08:00
96082b9124 feat(wms): 添加左侧逻辑库位查询功能并优化钢卷管理界面
在钢卷管理相关页面添加左侧逻辑库位树形查询功能,方便用户快速筛选库位
移除部分冗余代码和注释,优化页面布局和交互体验
添加钢卷统计数据显示功能,提升数据可视化
2026-04-18 13:36:24 +08:00
ddb1beb629 feat(wms): 添加钢卷物料订单关联信息查询功能
- 新增 queryPageListWithOrderRel 方法支持查询钢卷关联订单列表
- 实现批量查询避免 N+1 问题,提升查询性能
- 添加 listWithOrderRel 控制器接口供前端调用
- 集成 wms_coil_contract_rel 中间表与 crm_order 联查
- 优化查询逻辑,支持按需加载订单关联信息
- 完善异常处理和日志记录机制
2026-04-18 13:01:28 +08:00
67cf5aa7cb feat(wms): 添加钢卷关联订单信息查询功能
- 在WmsCoilContractRelMapper中新增selectOrdersByCoilId和selectOrdersByCoilIds方法
- 在WmsCoilContractRelMapper.xml中实现钢卷与订单关联查询的SQL映射
- 扩展WmsCoilContractRelVo类添加订单相关字段和@JsonFormat注解
- 在WmsMaterialCoilServiceImpl中注入coilContractRelMapper并实现填充订单信息逻辑
- 在WmsMaterialCoilVo中添加orderList字段存储关联订单列表
- 实现根据钢卷ID查询完整订单信息的JOIN查询功能
2026-04-18 11:49:10 +08:00
e1cc0fda34 feat(crm): 添加每日订单查询功能
- 在 ApsPlanDetailBo 中新增 planSheetIds 字段用于批量查询
- 实现 IApsPlanDetailService 的 queryListByPlanSheetIds 方法
- 添加 CrmOrderService 的 queryByIds 批量查询接口
- 在 CrmOrderController 中新增 /daily 接口查询当日订单
- 集成 APS 排产计划数据获取当日关联的 CRM 订单
- 添加 klp-aps 模块依赖支持跨模块数据查询
2026-04-18 11:11:14 +08:00
4e5e1bbca1 feat(crm): 订单查询功能新增关联钢卷信息展示
- 集成WMS钢卷合同关联查询服务
- 实现订单与钢卷批量关联查询逻辑
- 添加钢卷详细信息映射和组装功能
- 在CrmOrderVo中新增coilList字段存储钢卷列表
- 优化查询性能,避免N+1问题
- 支持按合同ID分组获取关联钢卷数据
2026-04-18 11:03:35 +08:00
2e363f9ad8 Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-04-18 10:23:57 +08:00
f158830abf feat(wms): 添加钢卷与合同关联关系管理功能
- 创建 WmsCoilContractRel 实体类定义钢卷与合同关联关系数据结构
- 实现 IWmsCoilContractRelService 接口提供基础CRUD操作方法
- 开发 WmsCoilContractRelServiceImpl 业务逻辑实现类
- 添加 WmsCoilContractRelController 控制器支持RESTful API接口
- 设计 WmsCoilContractRelMapper 数据访问接口及XML映射文件
- 创建 WmsCoilContractRelBo 业务对象和 WmsCoilContractRelVo 视图对象
- 集成分页查询、新增、修改、删除和导出功能
- 添加数据验证和重复提交防护机制
2026-04-18 10:23:48 +08:00
843512ab7e Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-04-18 10:23:27 +08:00
dd27069b4c feat(KLPTable): 增强浮层组件功能并优化表格显示
- 为浮层组件添加列数配置和排除列功能
- 优化浮层位置计算逻辑,防止超出视窗边界
- 调整表格列显示,移除不必要列并添加净重列
- 更新浮层样式,支持网格布局和响应式显示
- 扩展浮层配置项,支持更多自定义选项
2026-04-18 10:23:24 +08:00
b95bd5b93d Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-04-18 10:18:02 +08:00
4d588985e8 feat(WmsMaterialCoil): 添加调拨类型非空筛选功能
- 在WmsMaterialCoilBo中新增hasTransferType字段用于标识是否查询调拨类型不为空的钢卷
- 在WmsMaterialCoilServiceImpl中实现调拨类型非空筛选逻辑
- 当hasTransferType为true时查询调拨类型不为空且不为字符串的钢卷记录
2026-04-18 10:17:22 +08:00
3ad3fd2fee feat(PlanDetailForm): 添加订单明细选择功能以快速录入成品信息
在成品信息组中添加选择订单明细按钮,点击可打开对话框选择订单明细并自动填充表单字段。移除未使用的订单类型列并优化附件查看按钮的样式。
2026-04-17 17:02:12 +08:00
79ee9d572d feat(contract): 替换产品内容组件为订单详情组件并优化表单字段
重构合同预览和订单详情展示,使用新的OrderDetail组件替代原有的ProductContent组件
调整订单详情表单字段,增加宽度、厚度等必要字段,移除不必要字段
优化表单验证规则和显示逻辑
2026-04-17 15:11:09 +08:00
c9742b08cf fix(wms): 修复规格分割可能导致的错误并增加分页大小
处理规格分割时可能出现的空值问题,使用可选链操作符和默认值
同时增加多个报表页面的分页大小限制
2026-04-17 15:10:21 +08:00
6bd5d2ded3 feat(CrmOrderItem): 添加订单项产品规格字段
- 在CrmOrderItem实体类中新增表面处理、切边要求、包装要求、宽度、厚度、用途字段
- 在CrmOrderItemBo业务对象中同步添加对应字段定义
- 在CrmOrderItemVo视图对象中添加Excel导出注解配置
- 更新MyBatis映射文件中的结果映射和插入字段列表
- 在查询条件构建器中添加新字段的查询支持
2026-04-17 14:16:46 +08:00
da1813e65a Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-04-17 09:54:43 +08:00
8dbb7d1113 feat(钢卷管理): 添加钢卷统计功能并优化仓库选择排序
新增钢卷统计接口和展示总净重功能
优化仓库选择组件,按使用频率排序选项
调整钢卷选择器布局和样式
2026-04-17 09:55:27 +08:00
ae77c529ae feat(wms): 添加物料卷统计总数功能
- 在WmsMaterialCoilServiceImpl中新增total_count字段统计
- 将统计结果添加到返回结果集中
- 处理空值情况并设置默认值为BigDecimal.ZERO
2026-04-17 09:54:34 +08:00
edcbf7a5f1 feat(退火操作): 新增退火操作事件记录功能
添加退火操作事件API及页面,实现退火炉操作记录功能
在计划管理页面增加操作事件记录,包括入炉、完成、添加和解绑操作
2026-04-16 17:12:08 +08:00
28622a2b16 refactor(wms): 优化钢卷计划和材料钢卷服务逻辑
- 在更新钢卷计划时设置创建时间和更新时间
- 添加登录用户信息到钢卷计划的创建者和更新者字段
- 初始化钢卷计划的状态和导出相关字段
- 移除占用仓库的冗余方法实现
- 在材料钢卷服务中同时更新数据类型和排他状态字段
2026-04-16 16:46:09 +08:00
44303cb1c7 fix(wms): 修复钢卷单个更新时的二维码步骤类型检查逻辑
- 修改了qrcodeStepType为空判断条件,从非空且不等于annealing改为直接判断是否为空
- 确保在qrcodeStepType为空时能够正确执行钢卷操作权限验证
- 修正了原有的逻辑错误,避免在特定条件下跳过必要的权限检查
2026-04-16 16:31:47 +08:00
c0f7c699a8 fix(wms): 修复钢卷更新时二维码步骤类型检查逻辑
- 在非退火步骤类型时才进行独占状态检查
- 添加对qrcodeStepType为空的边界情况处理
- 修复二维码内容更新中的空指针检查逻辑
2026-04-16 16:30:05 +08:00
e69dc5e76e fix(task): 关闭仓库使用次数定时任务
- 注释掉 cron 表达式以禁用定时执行
- 保留事务回滚配置以确保数据一致性
- 记录任务开始执行的日志信息功能仍然可用
2026-04-16 16:18:40 +08:00
ec0660acba refactor(vo): 让WmsAnnealOperateEventVo继承BaseEntity
- 添加com.klp.common.core.domain.BaseEntity导入
- 修改WmsAnnealOperateEventVo类继承BaseEntity
- 保持原有的Excel注解配置不变
2026-04-16 16:01:39 +08:00
110597657e Merge remote-tracking branch 'origin/0.8.X' into 0.8.X 2026-04-16 15:56:39 +08:00
50670b64d8 feat(material-coil): 添加退火操作的二维码步骤类型支持
- 修改IWmsMaterialCoilService接口中的updateByBo方法,增加qrcodeStepType参数
- 在WmsFurnacePlanServiceImpl中实现退火操作的库位分配功能
- 添加updateQrcodeContentForCustomStep方法支持自定义二维码步骤类型
- 更新controller调用传入null作为默认值
- 完善退火操作的二维码内容更新逻辑
2026-04-16 15:56:26 +08:00
砂糖
823afd7a00 Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X 2026-04-16 15:50:58 +08:00
砂糖
344488f08e 临时修改 2026-04-16 15:50:54 +08:00
c2da7640c3 feat(wms): 添加退火操作事件管理功能
- 创建退火操作事件实体类 WmsAnnealOperateEvent
- 定义退火操作事件服务接口 IWmsAnnealOperateEventService
- 实现退火操作事件服务业务逻辑 WmsAnnealOperateEventServiceImpl
- 添加退火操作事件控制器 WmsAnnealOperateEventController
- 创建退火操作事件数据访问层 WmsAnnealOperateEventMapper
- 实现退火操作事件业务对象 WmsAnnealOperateEventBo 和视图对象 WmsAnnealOperateEventVo
- 集成 MyBatis Plus 分页查询和基础 CRUD 功能
- 添加 Excel 导出功能和操作日志记录
- 实现表单验证和重复提交防护机制
2026-04-16 14:55:43 +08:00
e99d7709d2 feat(warehouse): 添加仓库使用次数统计功能
- 在WmsMaterialCoilMapper中新增selectWarehouseIdCount方法用于统计仓库钢卷数量
- 在WmsWarehouseBo中新增orderByUseCount字段支持按使用次数排序
- 修改WmsWarehouseServiceImpl实现按使用次数或序号排序逻辑
- 创建WarehouseUseCountTask定时任务每晚1点更新仓库使用次数
- 实现定时计算各仓库中钢卷数量并更新到useCount字段功能
2026-04-16 14:25:54 +08:00
623e78629d feat(warehouse): 添加仓库使用次数字段支持
- 在WmsWarehouse实体类中新增useCount字段及注释
- 在WmsWarehouseBo业务对象中添加useCount属性
- 更新WmsWarehouseMapper.xml映射文件,增加useCount字段映射
- 在WmsWarehouseServiceImpl查询条件中加入useCount过滤逻辑
- 在WmsWarehouseVo视图对象中添加useCount字段并配置Excel导出
2026-04-16 14:03:26 +08:00
86 changed files with 3849 additions and 555 deletions

View File

@@ -7,6 +7,7 @@ import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
@@ -31,6 +32,11 @@ public class ApsPlanDetailBo extends BaseEntity {
*/
private Long planSheetId;
/**
* 关联排产单ID列表用于批量查询
*/
private List<Long> planSheetIds;
/**
* 内容序号
*/

View File

@@ -18,5 +18,5 @@ import java.util.List;
*/
public interface ApsPlanSheetMapper extends BaseMapperPlus<ApsPlanSheetMapper, ApsPlanSheet, ApsPlanSheetVo> {
List<ApsPlanSheetRowVo> selectList(ApsPlanSheetQueryReq req);
List<ApsPlanSheetRowVo> selectListByReq(ApsPlanSheetQueryReq req);
}

View File

@@ -31,6 +31,11 @@ public interface IApsPlanDetailService {
*/
List<ApsPlanDetailVo> queryList(ApsPlanDetailBo bo);
/**
* 根据排产单ID列表查询明细
*/
List<ApsPlanDetailVo> queryListByPlanSheetIds(List<Long> planSheetIds);
/**
* 新增排产单明细
*/

View File

@@ -105,6 +105,19 @@ public class ApsPlanDetailServiceImpl implements IApsPlanDetailService {
return baseMapper.selectVoList(lqw);
}
/**
* 根据排产单ID列表查询明细
*/
@Override
public List<ApsPlanDetailVo> queryListByPlanSheetIds(List<Long> planSheetIds) {
if (planSheetIds == null || planSheetIds.isEmpty()) {
return new java.util.ArrayList<>();
}
LambdaQueryWrapper<ApsPlanDetail> lqw = Wrappers.lambdaQuery();
lqw.in(ApsPlanDetail::getPlanSheetId, planSheetIds);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ApsPlanDetail> buildQueryWrapper(ApsPlanDetailBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ApsPlanDetail> lqw = Wrappers.lambdaQuery();

View File

@@ -318,7 +318,7 @@ public class ApsPlanSheetServiceImpl implements IApsPlanSheetService {
}
private List<ApsPlanSheetRowVo> queryListAll(ApsPlanSheetQueryReq req) {
return baseMapper.selectList(req);
return baseMapper.selectListByReq(req);
}
private String nvl(Object v, Object fallback) {

View File

@@ -19,7 +19,7 @@
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<select id="selectList" parameterType="com.klp.aps.domain.dto.ApsPlanSheetQueryReq" resultType="com.klp.aps.domain.vo.ApsPlanSheetRowVo">
<select id="selectListByReq" parameterType="com.klp.aps.domain.dto.ApsPlanSheetQueryReq" resultType="com.klp.aps.domain.vo.ApsPlanSheetRowVo">
SELECT
d.plan_detail_id AS detailSheetId,
s.plan_date AS planDate,

View File

@@ -12,7 +12,7 @@
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -43,5 +43,9 @@
<groupId>com.klp</groupId>
<artifactId>klp-wms</artifactId>
</dependency>
<dependency>
<groupId>com.klp</groupId>
<artifactId>klp-aps</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,12 +1,17 @@
package com.klp.crm.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Date;
import com.klp.aps.domain.bo.ApsPlanDetailBo;
import com.klp.aps.domain.bo.ApsPlanSheetBo;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
@@ -21,6 +26,10 @@ import com.klp.crm.domain.vo.CrmOrderVo;
import com.klp.crm.domain.bo.CrmOrderBo;
import com.klp.crm.service.ICrmOrderService;
import com.klp.common.core.page.TableDataInfo;
import com.klp.aps.domain.vo.ApsPlanSheetVo;
import com.klp.aps.domain.vo.ApsPlanDetailVo;
import com.klp.aps.service.IApsPlanSheetService;
import com.klp.aps.service.IApsPlanDetailService;
/**
* 正式订单主
@@ -35,6 +44,8 @@ import com.klp.common.core.page.TableDataInfo;
public class CrmOrderController extends BaseController {
private final ICrmOrderService iCrmOrderService;
private final IApsPlanSheetService iApsPlanSheetService;
private final IApsPlanDetailService iApsPlanDetailService;
/**
* 查询正式订单主列表
@@ -96,4 +107,54 @@ public class CrmOrderController extends BaseController {
@PathVariable String[] orderIds) {
return toAjax(iCrmOrderService.deleteWithValidByIds(Arrays.asList(orderIds), true));
}
/**
* 查询每日订单(根据排产计划获取今天的订单)
*
* @param planDate 排产日期,默认今天
*/
@GetMapping("/daily")
public R<List<CrmOrderVo>> getDailyOrders(
@RequestParam(value = "planDate", required = false)
@DateTimeFormat(pattern = "yyyy-MM-dd") Date planDate) {
if (planDate == null) {
planDate = new Date();
}
// 将日期设置为当天的开始时间 00:00:00
java.util.Calendar calendar = java.util.Calendar.getInstance();
calendar.setTime(planDate);
calendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
calendar.set(java.util.Calendar.MINUTE, 0);
calendar.set(java.util.Calendar.SECOND, 0);
calendar.set(java.util.Calendar.MILLISECOND, 0);
planDate = calendar.getTime();
ApsPlanSheetBo bo = new ApsPlanSheetBo();
bo.setPlanDate(planDate);
List<ApsPlanSheetVo> planSheetList = iApsPlanSheetService.queryList(bo);
if (planSheetList == null || planSheetList.isEmpty()) {
return R.ok(new ArrayList<>());
}
List<Long> planSheetIds = new ArrayList<>();
for (ApsPlanSheetVo sheet : planSheetList) {
planSheetIds.add(sheet.getPlanSheetId());
}
ApsPlanDetailBo detailBo = new ApsPlanDetailBo();
detailBo.setPlanSheetIds(planSheetIds);
List<ApsPlanDetailVo> detailList = iApsPlanDetailService.queryListByPlanSheetIds(planSheetIds);
if (detailList == null || detailList.isEmpty()) {
return R.ok(new ArrayList<>());
}
List<Long> orderIds = new ArrayList<>();
for (ApsPlanDetailVo detail : detailList) {
if (detail.getOrderId() != null) {
orderIds.add(detail.getOrderId());
}
}
if (orderIds.isEmpty()) {
return R.ok(new ArrayList<>());
}
List<CrmOrderVo> orders = iCrmOrderService.queryByIds(orderIds);
return R.ok(orders);
}
}

View File

@@ -93,6 +93,30 @@ public class CrmOrderItem extends BaseEntity {
* 排产批次
*/
private String productionBatch;
/**
* 表面处理
*/
private String surfaceTreatment;
/**
* 切边要求
*/
private String edgeCuttingReq;
/**
* 包装要求
*/
private String packagingReq;
/**
* 宽度
*/
private BigDecimal width;
/**
* 厚度
*/
private BigDecimal thickness;
/**
* 用途
*/
private String purpose;
/**
* 删除标识 0正常 2删除
*/

View File

@@ -108,5 +108,34 @@ public class CrmOrderItemBo extends BaseEntity {
*/
private String productionBatch;
/**
* 表面处理
*/
private String surfaceTreatment;
/**
* 切边要求
*/
private String edgeCuttingReq;
/**
* 包装要求
*/
private String packagingReq;
/**
* 宽度
*/
private BigDecimal width;
/**
* 厚度
*/
private BigDecimal thickness;
/**
* 用途
*/
private String purpose;
}

View File

@@ -131,5 +131,40 @@ public class CrmOrderItemVo {
@ExcelProperty(value = "排产批次")
private String productionBatch;
/**
* 表面处理
*/
@ExcelProperty(value = "表面处理")
private String surfaceTreatment;
/**
* 切边要求
*/
@ExcelProperty(value = "切边要求")
private String edgeCuttingReq;
/**
* 包装要求
*/
@ExcelProperty(value = "包装要求")
private String packagingReq;
/**
* 宽度
*/
@ExcelProperty(value = "宽度")
private BigDecimal width;
/**
* 厚度
*/
@ExcelProperty(value = "厚度")
private BigDecimal thickness;
/**
* 用途
*/
@ExcelProperty(value = "用途")
private String purpose;
}

View File

@@ -2,12 +2,15 @@ package com.klp.crm.domain.vo;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import com.klp.common.core.domain.BaseEntity;
import com.klp.domain.vo.WmsMaterialCoilVo;
import lombok.Data;
@@ -292,4 +295,8 @@ public class CrmOrderVo extends BaseEntity {
private String createByName;
//更新人
private String updateByName;
/**
* 关联的钢卷列表
*/
private List<WmsMaterialCoilVo> coilList;
}

View File

@@ -22,6 +22,11 @@ public interface ICrmOrderService {
*/
CrmOrderVo queryById(String orderId);
/**
* 根据ID列表查询正式订单
*/
List<CrmOrderVo> queryByIds(List<Long> orderIds);
/**
* 查询正式订单主列表
*/

View File

@@ -101,6 +101,12 @@ public class CrmOrderItemServiceImpl implements ICrmOrderItemService {
lqw.eq(StringUtils.isNotBlank(bo.getCustomizer()), CrmOrderItem::getCustomizer, bo.getCustomizer());
lqw.eq(StringUtils.isNotBlank(bo.getShipper()), CrmOrderItem::getShipper, bo.getShipper());
lqw.eq(StringUtils.isNotBlank(bo.getProductionBatch()), CrmOrderItem::getProductionBatch, bo.getProductionBatch());
lqw.eq(StringUtils.isNotBlank(bo.getSurfaceTreatment()), CrmOrderItem::getSurfaceTreatment, bo.getSurfaceTreatment());
lqw.eq(StringUtils.isNotBlank(bo.getEdgeCuttingReq()), CrmOrderItem::getEdgeCuttingReq, bo.getEdgeCuttingReq());
lqw.eq(StringUtils.isNotBlank(bo.getPackagingReq()), CrmOrderItem::getPackagingReq, bo.getPackagingReq());
lqw.eq(bo.getWidth() != null, CrmOrderItem::getWidth, bo.getWidth());
lqw.eq(bo.getThickness() != null, CrmOrderItem::getThickness, bo.getThickness());
lqw.eq(StringUtils.isNotBlank(bo.getPurpose()), CrmOrderItem::getPurpose, bo.getPurpose());
return lqw;
}

View File

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import com.klp.crm.domain.vo.CrmOrderOperationTraceVo;
import com.klp.mapper.WmsCoilContractRelMapper;
import com.klp.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -17,6 +18,11 @@ import com.klp.crm.domain.vo.CrmOrderVo;
import com.klp.crm.domain.CrmOrder;
import com.klp.crm.mapper.CrmOrderMapper;
import com.klp.crm.service.ICrmOrderService;
import com.klp.domain.WmsCoilContractRel;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.vo.WmsMaterialCoilVo;
import com.klp.service.IWmsCoilContractRelService;
import com.klp.service.IWmsMaterialCoilService;
import java.util.*;
import java.util.stream.Collectors;
@@ -35,6 +41,10 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
private final ISysUserService userService;
private final WmsCoilContractRelMapper coilContractRelMapper;
private final IWmsMaterialCoilService materialCoilService;
/**
* 查询正式订单主
*/
@@ -43,6 +53,19 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
return baseMapper.selectVoById(orderId);
}
/**
* 根据ID列表查询正式订单
*/
@Override
public List<CrmOrderVo> queryByIds(List<Long> orderIds) {
if (orderIds == null || orderIds.isEmpty()) {
return new ArrayList<>();
}
LambdaQueryWrapper<CrmOrder> lqw = Wrappers.lambdaQuery();
lqw.in(CrmOrder::getOrderId, orderIds);
return baseMapper.selectVoList(lqw);
}
/**
* 查询正式订单主列表
*/
@@ -76,6 +99,57 @@ public class CrmOrderServiceImpl implements ICrmOrderService {
}
}
}
// 查询订单关联的钢卷ID列表
List<Long> contractIds = records.stream()
.map(CrmOrderVo::getOrderId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (!contractIds.isEmpty()) {
// 批量查询钢卷与合同关联关系
LambdaQueryWrapper<WmsCoilContractRel> coilQw = Wrappers.lambdaQuery();
coilQw.in(WmsCoilContractRel::getContractId, contractIds);
coilQw.eq(WmsCoilContractRel::getDelFlag, 0);
List<WmsCoilContractRel> coilRels = coilContractRelMapper.selectList(coilQw);
// 按contractId分组,收集coilId列表
Map<Long, List<Long>> coilIdMap = coilRels.stream()
.filter(rel -> rel.getContractId() != null && rel.getCoilId() != null)
.collect(Collectors.groupingBy(
WmsCoilContractRel::getContractId,
Collectors.mapping(WmsCoilContractRel::getCoilId, Collectors.toList())
));
// 查询所有相关钢卷的详细信息
Set<Long> allCoilIds = coilIdMap.values().stream()
.flatMap(List::stream)
.collect(Collectors.toSet());
Map<Long, WmsMaterialCoilVo> coilVoMap = Collections.emptyMap();
if (!allCoilIds.isEmpty()) {
WmsMaterialCoilBo coilBo = new WmsMaterialCoilBo();
coilBo.setCoilIds(allCoilIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
List<WmsMaterialCoilVo> allCoils = materialCoilService.queryList(coilBo);
coilVoMap = allCoils.stream()
.collect(Collectors.toMap(WmsMaterialCoilVo::getCoilId, c -> c, (a, b) -> a));
}
// 设置到每个订单的coilIds和coilList字段
for (CrmOrderVo vo : records) {
if (vo.getOrderId() != null && coilIdMap.containsKey(vo.getOrderId())) {
List<Long> coilIdList = coilIdMap.get(vo.getOrderId());
// 设置coilList钢卷详细信息列表
List<WmsMaterialCoilVo> coilList = coilIdList.stream()
.map(coilVoMap::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
vo.setCoilList(coilList);
}
}
}
return TableDataInfo.build(result);
}

View File

@@ -23,6 +23,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="customizer" column="customizer"/>
<result property="shipper" column="shipper"/>
<result property="productionBatch" column="production_batch"/>
<result property="surfaceTreatment" column="surface_treatment"/>
<result property="edgeCuttingReq" column="edge_cutting_req"/>
<result property="packagingReq" column="packaging_req"/>
<result property="width" column="width"/>
<result property="thickness" column="thickness"/>
<result property="purpose" column="purpose"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
@@ -50,6 +56,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
customizer,
shipper,
production_batch,
surface_treatment,
edge_cutting_req,
packaging_req,
width,
thickness,
purpose,
create_by,
create_time,
update_by,

View File

@@ -52,3 +52,14 @@ export function listOrderPackaging(orderId) {
method: 'get',
})
}
/**
* 查询今日订单
*/
export function listTodayOrder(query) {
return request({
url: '/crm/order/daily',
method: 'get',
params: query
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询退火操作事件列表
export function listAnnealOperateEvent(query) {
return request({
url: '/wms/annealOperateEvent/list',
method: 'get',
params: query
})
}
// 查询退火操作事件详细
export function getAnnealOperateEvent(eventId) {
return request({
url: '/wms/annealOperateEvent/' + eventId,
method: 'get'
})
}
// 新增退火操作事件
export function addAnnealOperateEvent(data) {
return request({
url: '/wms/annealOperateEvent',
method: 'post',
data: data
})
}
// 修改退火操作事件
export function updateAnnealOperateEvent(data) {
return request({
url: '/wms/annealOperateEvent',
method: 'put',
data: data
})
}
// 删除退火操作事件
export function delAnnealOperateEvent(eventId) {
return request({
url: '/wms/annealOperateEvent/' + eventId,
method: 'delete'
})
}

View File

@@ -389,4 +389,12 @@ export function listTypeErrorCoil() {
method: 'get',
timeout: 600000
})
}
export function getCoilStatisticsList(params) {
return request({
url: '/wms/materialCoil/statisticsList',
method: 'get',
params,
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询钢卷与合同关联关系列表
export function listCoilContractRel(query) {
return request({
url: '/wms/coilContractRel/list',
method: 'get',
params: query
})
}
// 查询钢卷与合同关联关系详细
export function getCoilContractRel(relId) {
return request({
url: '/wms/coilContractRel/' + relId,
method: 'get'
})
}
// 新增钢卷与合同关联关系
export function addCoilContractRel(data) {
return request({
url: '/wms/coilContractRel',
method: 'post',
data: data
})
}
// 修改钢卷与合同关联关系
export function updateCoilContractRel(data) {
return request({
url: '/wms/coilContractRel',
method: 'put',
data: data
})
}
// 删除钢卷与合同关联关系
export function delCoilContractRel(relId) {
return request({
url: '/wms/coilContractRel/' + relId,
method: 'delete'
})
}

View File

@@ -21,13 +21,7 @@
@close="handleClose" append-to-body :fullscreen="orderBy">
<!-- 搜索区域 -->
<el-form v-if="!rangeMode" inline :model="queryParams" class="search-form">
<!-- <el-form-item label="类型">
<el-select v-model="queryParams.selectType" placeholder="请选择类型" size="small">
<el-option label="成品" value="product" />
<el-option label="原料" value="raw_material" />
</el-select>
</el-form-item> -->
<el-form-item label="入场卷号">
<el-form-item label="入场卷号">
<el-input v-model="queryParams.enterCoilNo" placeholder="请输入入场卷号" clearable size="small"
@keyup.enter.native="handleQuery" />
</el-form-item>
@@ -74,8 +68,8 @@
</el-select>
</el-form-item>
<el-form-item label="品质">
<muti-select v-model="queryParams.qualityStatusCsv" :options="dict.type.coil_quality_status" placeholder="请选择品质"
clearable />
<muti-select v-model="queryParams.qualityStatusCsv" :options="dict.type.coil_quality_status"
placeholder="请选择品质" clearable />
</el-form-item>
<el-form-item label="实际库区" v-if="orderBy">
<actual-warehouse-select v-model="queryParams.actualWarehouseId" placeholder="请选择实际库区" canSelectLevel2
@@ -86,7 +80,8 @@
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="small" @click="resetQuery">重置</el-button>
<el-checkbox v-if="orderBy" style="margin-left: 10px;" v-model="showCoilMap" size="small">显示钢卷地图</el-checkbox>
<el-checkbox v-if="orderBy && orderId" style="margin-left: 10px;" v-model="showOrderInfo" size="small">显示订单详情</el-checkbox>
<el-checkbox v-if="orderBy && orderId" style="margin-left: 10px;" v-model="showOrderInfo"
size="small">显示订单详情</el-checkbox>
</el-form-item>
</el-form>
@@ -122,8 +117,15 @@
</div>
<!-- 分页 -->
<pagination v-if="!rangeMode" v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getList" />
<div style="display: flex; justify-content: flex-end; align-items: flex-end; gap: 10px;">
<span>
总净重{{ coilTrimStatistics.total_net_weight || 0 }}t
</span>
<pagination v-if="!rangeMode" v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize" @pagination="getList" />
</div>
<div v-if="multiple && selectedCoils.length > 0" class="selected-stats">
<div class="stats-content">
@@ -181,7 +183,7 @@
</template>
<script>
import { listMaterialCoil } from '@/api/wms/coil';
import { listMaterialCoil, getCoilStatisticsList } from '@/api/wms/coil';
import { listActualWarehouse } from "@/api/wms/actualWarehouse";
import { treeActualWarehouseTwoLevel } from "@/api/wms/actualWarehouse";
import MemoInput from '@/components/MemoInput/index.vue';
@@ -312,6 +314,7 @@ export default {
treeProps: { label: "actualWarehouseName", children: "children" },
treeLoading: false,
showOrderInfo: false,
coilTrimStatistics: {},
};
},
computed: {
@@ -503,6 +506,11 @@ export default {
queryPayload.saleId = this.currentUserId;
}
const response = await listMaterialCoil(queryPayload);
const { pageNum, pageSize, excludeBound, orderBy, ...noPager } = queryPayload;
getCoilStatisticsList(noPager).then((res) => {
console.log('钢卷统计数据:', res);
this.coilTrimStatistics = res.data || {};
});
if (response.code === 200) {
this.coilList = response.rows || [];
this.total = response.total || 0;

View File

@@ -0,0 +1,269 @@
<template>
<div>
<div style="display: flex; align-items: center; margin-bottom: 12px;">
<el-select v-model="selectedValue" placeholder="请选择合同" style="width: 100%">
<el-option v-for="item in contractList" :key="item.orderId" :value="item.orderId"
:label="item.contractCode" />
</el-select>
<!-- 编辑按钮点击打开弹窗 -->
<el-button v-if="mode == 'today'" @click="openSelectDialog" type="primary" size="small" style="margin-left: 8px; padding: 0 12px;">
<i class="el-icon-setting"></i>
</el-button>
<!-- 刷新时不会移除手动添加的合同 -->
<el-button @click="handleRefresh" type="info" size="small" style="margin-left: 8px; padding: 0 12px;">
<i class="el-icon-refresh"></i>
</el-button>
</div>
<!-- 查询所有的合同和当前localstorage中的合同可以对localstorage中的合同进行新增和删除手动新增的合同带有手动添加的标记 -->
<el-dialog title="可选合同配置" :visible.sync="dialogVisible" width="80%">
<el-tabs v-model="activeTab">
<!-- 已配置合同tab -->
<el-tab-pane label="可选合同" name="configured">
<div v-if="contractList.length === 0" style="text-align: center; padding: 20px;">
暂无已配置合同
</div>
<el-table v-else :data="contractList" style="width: 100%" size="mini" height="600">
<el-table-column prop="contractCode" label="合同编号" width="160" />
<el-table-column prop="contractName" label="合同名称" width="180" />
<el-table-column prop="customer" label="客户" width="140" />
<el-table-column prop="salesman" label="销售人员" width="100" />
<el-table-column prop="deliveryDate" label="交付日期" width="110">
<template slot-scope="scope">
{{ scope.row.deliveryDate || '-' }}
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" show-overflow-tooltip />
<el-table-column label="添加方式" width="90">
<template slot-scope="scope">
<el-tag v-if="scope.row.isManual" type="success" size="small">手动</el-tag>
<el-tag v-else type="info" size="small">接口</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="70">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="removeContract(scope.row.orderId)" plain>
移除
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!-- 所有合同tab -->
<el-tab-pane label="所有合同" name="all">
<div style="margin-bottom: 16px;">
<el-input v-model="searchKeyword" placeholder="搜索合同" @input="handleSearch" clearable size="small">
<el-button slot="append" icon="el-icon-search" size="small"></el-button>
</el-input>
</div>
<el-table :data="allContracts" style="width: 100%" size="mini" height="600">
<el-table-column prop="contractCode" label="合同编号" width="160" />
<el-table-column prop="contractName" label="合同名称" width="180" />
<el-table-column prop="customer" label="客户" width="140" />
<el-table-column prop="salesman" label="销售人员" width="100" />
<el-table-column prop="deliveryDate" label="交付日期" width="110">
<template slot-scope="scope">
{{ scope.row.deliveryDate || '-' }}
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" show-overflow-tooltip />
<el-table-column label="状态" width="80">
<template slot-scope="scope">
<el-tag v-if="isContractInList(scope.row.orderId)" type="success" size="small">已添加</el-tag>
<el-tag v-else type="info" size="small">未添加</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<el-button
v-if="!isContractInList(scope.row.orderId)"
type="primary"
size="mini"
@click="addContract(scope.row)"
plain
>
添加
</el-button>
<el-button
v-else
type="danger"
size="mini"
@click="removeContract(scope.row.orderId)"
plain
>
移除
</el-button>
</template>
</el-table-column>
</el-table>
<div v-if="allContracts.length === 0" style="text-align: center; padding: 20px;">
暂无合同数据
</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</div>
</template>
<script>
import { listOrder, listTodayOrder } from '@/api/crm/order';
export default {
name: "ContractSelect",
props: {
value: {
type: String,
default: ""
},
mode: {
type: String,
default: "today" // today 或 all
}
},
data() {
return {
contractList: [],
dialogVisible: false,
searchKeyword: '',
allContracts: [],
activeTab: 'configured', // 默认显示已配置合同tab
}
},
computed: {
selectedValue: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
}
},
mounted() {
if (this.mode == "today") {
// 从localstorage中获取合同列表
this.loadFromLocalStorage();
} else {
this.loadContractList();
}
},
methods: {
// 从localStorage中加载合同列表
loadFromLocalStorage() {
try {
const storedContracts = localStorage.getItem('todayContracts');
if (storedContracts) {
this.contractList = JSON.parse(storedContracts);
} else {
// 如果localStorage中没有从接口获取
this.loadContractList();
}
} catch (error) {
console.error('Failed to load contracts from localStorage:', error);
this.loadContractList();
}
},
// 保存合同列表到localStorage
saveToLocalStorage() {
try {
localStorage.setItem('todayContracts', JSON.stringify(this.contractList));
} catch (error) {
console.error('Failed to save contracts to localStorage:', error);
}
},
// 加载合同列表
async loadContractList(keyword) {
if (this.mode == "all") {
const res = await listOrder({
pageNum: 1,
pageSize: 1000,
keyword: keyword || undefined,
});
this.contractList = res.rows || [];
}
else if (this.mode == "today") {
const res = await listTodayOrder();
// 获取现有手动添加的合同
const existingManualContracts = this.contractList.filter(item => item.isManual);
// 将接口返回的合同标记为非手动添加
const apiContracts = (res.data || []).map(item => ({
...item,
isManual: false
}));
// 合并合同列表,保留手动添加的合同
this.contractList = [...apiContracts, ...existingManualContracts];
// 去重,避免重复合同
this.contractList = this.contractList.filter((item, index, self) =>
index === self.findIndex(t => t.orderId === item.orderId)
);
// 保存到localStorage
this.saveToLocalStorage();
}
},
// 打开选择弹窗
async openSelectDialog() {
this.dialogVisible = true;
// 加载所有合同供选择
await this.loadAllContracts();
},
// 加载所有合同
async loadAllContracts() {
try {
const res = await listOrder({
pageNum: 1,
pageSize: 1000,
keyword: this.searchKeyword || undefined,
});
// 合并现有合同(包括手动添加的)
const existingContracts = this.contractList;
this.allContracts = [...res.rows || [], ...existingContracts].filter((item, index, self) =>
index === self.findIndex(t => t.orderId === item.orderId)
);
} catch (error) {
console.error('Failed to load all contracts:', error);
this.allContracts = [];
}
},
// 搜索合同
handleSearch() {
this.loadAllContracts();
},
// 检查合同是否在列表中
isContractInList(orderId) {
return this.contractList.some(item => item.orderId === orderId);
},
// 添加合同
addContract(contract) {
if (!this.isContractInList(contract.orderId)) {
this.contractList.push({
...contract,
isManual: true // 标记为手动添加
});
this.saveToLocalStorage();
}
},
// 移除合同
removeContract(orderId) {
this.contractList = this.contractList.filter(item => item.orderId !== orderId);
this.saveToLocalStorage();
},
// 刷新合同列表
handleRefresh() {
this.loadContractList();
},
}
}
</script>

View File

@@ -74,8 +74,10 @@ export default {
console.log('仓库API返回数据:', response);
const data = response.data || [];
console.log('处理后的数据:', data);
this.warehouseOptions = this.buildTreeOptions(data);
console.log('构建的树形选项:', this.warehouseOptions);
let options = this.buildTreeOptions(data);
options = this.sortOptionsByUsage(options);
this.warehouseOptions = options;
console.log('构建并排序后的树形选项:', this.warehouseOptions);
}).catch(error => {
console.error("加载仓库选项失败:", error);
this.warehouseOptions = [];
@@ -106,7 +108,36 @@ export default {
return options;
},
getWarehouseUsage() {
try {
const usage = localStorage.getItem('warehouseUsage');
return usage ? JSON.parse(usage) : {};
} catch (error) {
console.error('获取仓库使用记录失败:', error);
return {};
}
},
updateWarehouseUsage(warehouseId) {
try {
const usage = this.getWarehouseUsage();
usage[warehouseId] = (usage[warehouseId] || 0) + 1;
localStorage.setItem('warehouseUsage', JSON.stringify(usage));
} catch (error) {
console.error('更新仓库使用记录失败:', error);
}
},
sortOptionsByUsage(options) {
const usage = this.getWarehouseUsage();
return options.sort((a, b) => {
const usageA = usage[a.warehouseId] || 0;
const usageB = usage[b.warehouseId] || 0;
return usageB - usageA;
});
},
onChange(val) {
if (val) {
this.updateWarehouseUsage(val);
}
this.$emit('input', val);
this.$emit('change', val);
}

View File

@@ -7,7 +7,6 @@
<script>
import { listWarehouse } from '@/api/wms/warehouse';
// import { listActualWarehouse } from '@/api/wms/actualWarehouse';
import { treeActualWarehouseTwoLevel } from '@/api/wms/actualWarehouse';
export default {

View File

@@ -2,7 +2,7 @@
<transition name="el-fade-in-linear">
<div v-if="tooltipVisible && data" class="row-tooltip" :style="adjustedTooltipStyle" ref="rowTooltip">
<slot>
<div class="tooltip-list">
<div class="tooltip-list" :style="{ gridTemplateColumns: `repeat(${columnCount}, 1fr)` }">
<div class="tooltip-item" v-for="field in visibleColumns" :key="field.prop">
<span class="label">{{ field.label }}</span>
<span class="value">{{ formatTooltipValue(data, field) }}</span>
@@ -21,6 +21,10 @@ export default {
type: Array,
default: () => []
},
columnCount: {
type: Number,
default: 2
},
data: {
type: Object,
default: () => ({})
@@ -45,15 +49,34 @@ export default {
const tooltipRect = this.$refs.rowTooltip?.getBoundingClientRect();
if (!tooltipRect) return this.tooltipStyle;
// 检查是否超出底部边界
if (parseInt(top) + tooltipRect.height > window.innerHeight) {
return { ...this.tooltipStyle, top: `${window.innerHeight - tooltipRect.height - 12}px` };
let adjustedTop = parseInt(top);
let adjustedLeft = parseInt(left);
const offset = 16;
// 检查是否超出底部边界 - 如果超出,将浮层显示在鼠标上方
if (adjustedTop + tooltipRect.height > window.innerHeight) {
adjustedTop = adjustedTop - tooltipRect.height - offset;
}
// 检查是否超出右侧边界
if (parseInt(left) + tooltipRect.width > window.innerWidth) {
return { ...this.tooltipStyle, left: `${window.innerWidth - tooltipRect.width - 16}px` };
// 检查是否超出右侧边界 - 如果超出,将浮层显示在鼠标左侧
if (adjustedLeft + tooltipRect.width > window.innerWidth) {
adjustedLeft = adjustedLeft - tooltipRect.width - offset;
}
return this.tooltipStyle;
// 检查是否超出顶部边界
if (adjustedTop < 0) {
adjustedTop = offset;
}
// 检查是否超出左侧边界
if (adjustedLeft < 0) {
adjustedLeft = offset;
}
return {
top: `${adjustedTop}px`,
left: `${adjustedLeft}px`
};
}
},
methods: {
@@ -98,9 +121,28 @@ export default {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
padding: 12px 14px;
pointer-events: none;
z-index: 5;
/* max-height: 70%; */
z-index: 9999;
overflow: auto;
transition: all 0.3s ease-in-out;
}
.tooltip-list {
display: grid;
gap: 8px;
}
.tooltip-item {
display: flex;
align-items: flex-start;
}
.tooltip-item .label {
flex-shrink: 0;
color: #666;
}
.tooltip-item .value {
color: #333;
word-break: break-word;
}
</style>

View File

@@ -18,7 +18,7 @@
<slot name="append" v-bind="scope"></slot>
</template>
<!-- 3. 透传自定义列插槽直接接收<el-table-column> 嵌套的情况 -->
<!-- 3. 透传"自定义列"插槽直接接收<el-table-column> 嵌套的情况 -->
<slot v-bind:tableRef="tableRef"></slot>
<el-table-column v-if="selectionColumn" type="selection" width="55" align="center"></el-table-column>
@@ -27,7 +27,7 @@
</el-table>
<!-- 浮层组件 -->
<KLPTableFloatLayer v-if="floatLayer" :columns="floatLayerColumns" :data="hoveredRow" :tooltipVisible="tooltipVisible"
:tooltipStyle="tooltipStyle" />
:tooltipStyle="tooltipStyle" :columnCount="floatLayerColumnCount" />
</div>
<!-- 扩展层可后续统一添加分页如与 MyPagination 组件联动 -->
<slot name="pagination"></slot>
@@ -78,7 +78,9 @@ export default {
type: Object,
default: () => ({
columns: [],
title: '详细信息'
title: '详细信息',
columnCount: 2,
excludeColumns: ['action']
})
},
height: {
@@ -101,11 +103,16 @@ export default {
},
computed: {
floatLayerColumns() {
console.log(this.floatLayerConfig?.columns?.length > 1)
if (this.floatLayerConfig?.columns?.length > 1) {
return this.floatLayerConfig.columns
}
return this.columns;
},
floatLayerColumnCount() {
return this.floatLayerConfig?.columnCount || 2;
},
excludeColumns() {
return this.floatLayerConfig?.excludeColumns || ['action'];
}
},
methods: {
@@ -157,6 +164,15 @@ export default {
// 浮层相关
handleCellEnter(row, column, cell, event) {
if (!row || !event) return
// 检查是否是排除的列(操作列等)
const excludeColumns = this.excludeColumns
if (excludeColumns.includes(column.property)) {
this.tooltipVisible = false
this.hoveredRow = null
return
}
this.hoveredRow = row
this.tooltipVisible = true
this.updateTooltipPosition(event)

View File

@@ -14,13 +14,13 @@
@change="handleChange"
>
<!-- 全选选项 -->
<el-option
<!-- <el-option
v-if="showSelectAll && options.length > 0"
key="selectAll"
label="全选"
value="selectAll"
@click="toggleSelectAll"
/>
/> -->
<el-option
v-for="item in options"
:key="item.value"

View File

@@ -11,8 +11,8 @@
:type="formData.orderId ? 'success' : 'default'">
{{ formData.orderId ? formData.contractCode : '选择订单' }}
</el-button>
<div v-if="formData.orderId" @click.stop="openOrderAttachmentDialog" style="margin-left: 10px; cursor: pointer; color: #409eff;"
type="primary">
<div v-if="formData.orderId" @click.stop="openOrderAttachmentDialog"
style="margin-left: 10px; cursor: pointer; color: #409eff;" type="primary">
查看附件
</div>
</template>
@@ -68,6 +68,12 @@
<!-- 成品信息组 -->
<el-collapse-item title="成品信息" name="3">
<template slot="title">
<!-- 如果已经绑定了订单可以在这里选择订单明细来快速录入要生产的成品信息 -->
<span>成品信息</span>
<el-button type="primary" plain v-if="formData.orderId" style="margin-left: 10px;"
@click.stop="openOrderItemDialog">选择订单明细</el-button>
</template>
<el-row>
<el-col :span="12">
<el-form-item label="成品名称" prop="productName">
@@ -228,8 +234,6 @@
<!-- 订单列表 -->
<el-table v-loading="orderLoading" :data="orderList" style="width: 100%" @row-click="handleOrderSelect">
<el-table-column type="selection" width="55" />
<!-- <el-table-column prop="orderCode" label="订单号" width="150" /> -->
<el-table-column prop="orderType" label="订单类型" width="100" />
<el-table-column prop="contractCode" label="合同号" width="150" />
<el-table-column prop="signTime" label="签订时间" width="150" />
<el-table-column prop="signLocation" label="签订地点" />
@@ -254,6 +258,37 @@
</div>
</el-dialog>
<el-dialog title="选择订单明细" :visible.sync="orderItem.open" width="80%" append-to-body>
<el-table v-loading="orderItem.loading" :data="orderItem.list" @row-click="selectOrderItem">
<el-table-column label="产品类型" align="center" prop="productType" />
<el-table-column label="成品宽度" align="center" prop="width" />
<el-table-column label="成品厚度" align="center" prop="thickness" />
<el-table-column label="成品规格" align="center" prop="finishedProductSpec" />
<el-table-column label="宽度公差" align="center" prop="widthTolerance" />
<el-table-column label="厚度公差" align="center" prop="thicknessTolerance" />
<el-table-column label="材质" align="center" prop="material" />
<el-table-column label="重量" align="center" prop="weight" />
<!-- <el-table-column label="含税单价(元/吨)" align="center" prop="contractPrice" />
<el-table-column label="含税总额" align="center">
<template slot-scope="scope">
{{ scope.row.weight * scope.row.contractPrice }}
</template>
</el-table-column>
<el-table-column label="无税单价(元/吨)" align="center" prop="itemAmount" /> -->
<el-table-column label="卷数" align="center" prop="productNum" />
<el-table-column label="表面处理" align="center" prop="surfaceTreatment" />
<el-table-column label="包装要求" align="center" prop="packagingReq" />
<el-table-column label="切边要求" align="center" prop="edgeCuttingReq" />
<el-table-column label="用途" align="center" prop="purpose" />
<el-table-column label="特殊要求" align="center" prop="specialRequire" />
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
</el-dialog>
<el-dialog title="合同附件" :visible.sync="attachmentOpen" width="50%" append-to-body>
<div class="attachment-section" v-loading="loading">
<!-- <div class="attachment-item">
@@ -275,7 +310,7 @@
<script>
import { listOrder, getOrder } from '@/api/crm/order';
import { listContract, getContract } from '@/api/crm/contract';
import { listOrderItem } from '@/api/crm/orderItem'
import FileList from '@/components/FileList'
export default {
@@ -347,6 +382,11 @@ export default {
attachmentOpen: false,
contract: {},
loading: false,
orderItem: {
loading: false,
open: false,
list: []
}
};
},
methods: {
@@ -365,6 +405,34 @@ export default {
// 加载订单列表
this.getOrderList();
},
openOrderItemDialog() {
this.orderItem.open = true;
this.orderItem.loading = true;
listOrderItem({ orderId: this.formData.orderId }).then(res => {
this.orderItem.list = res.rows;
this.orderItem.loading = false;
})
},
selectOrderItem(row) {
this.formData = {
...this.formData,
productName: row.productType,
productMaterial: row.material,
productWidth: row.width,
rollingThick: row.thickness,
markCoatThick: row.thickness,
tonSteelLengthRange: 0,
planQty: row.productNum,
planWeight: row.weight,
surfaceTreatment: row.surfaceTreatment,
productPackaging: row.packagingReq,
widthReq: row.edgeCuttingReq,
productEdgeReq: row.widthTolerance,
usageReq: row.purpose,
}
this.orderItem.open = false;
// this.formData.orderItemId = row.orderItemId;
},
async openOrderAttachmentDialog() {
this.loading = true;
this.attachmentOpen = true;
@@ -375,12 +443,6 @@ export default {
return;
}
const order = await getOrder(this.formData.orderId);
// if (!order.data.contractId) {
// this.$message.error('未找到合同')
// return;
// }
// 根据合同id拿到合同详情
// const contract = await getContract(order.data.contractId);
this.contract = order.data;
} catch {
this.$message.error('获取合同附件失败')
@@ -388,12 +450,6 @@ export default {
this.loading = false;
}
},
/** 获取合同列表 */
// getContractList() {
// listContract().then(response => {
// this.contractList = response.rows;
// });
// },
/** 获取订单列表 */
getOrderList() {
this.orderLoading = true;

View File

@@ -14,25 +14,31 @@
<el-table v-loading="loading" :data="orderItemList">
<el-table-column label="产品类型" align="center" prop="productType" />
<el-table-column label="原料规格" align="center" prop="rawMaterialSpec" />
<el-table-column label="成品宽度" align="center" prop="width" />
<el-table-column label="成品厚度" align="center" prop="thickness" />
<el-table-column label="成品规格" align="center" prop="finishedProductSpec" />
<!-- <el-table-column label="原料规格" align="center" prop="rawMaterialSpec" /> -->
<el-table-column label="宽度公差" align="center" prop="widthTolerance" />
<el-table-column label="厚度公差" align="center" prop="thicknessTolerance" />
<el-table-column label="成品规格" align="center" prop="finishedProductSpec" />
<el-table-column label="材质" align="center" prop="material" />
<el-table-column label="等级" align="center" prop="grade" />
<el-table-column label="重量" align="center" prop="weight" />
<el-table-column label="合同定价" align="center" prop="contractPrice" />
<el-table-column label="金额(元)" align="center">
<template slot-scope="scope">
<el-table-column label="含税单价(元/吨)" align="center" prop="contractPrice" />
<el-table-column label="含税总额" align="center">
<template slot-scope="scope">
{{ scope.row.weight * scope.row.contractPrice }}
</template>
</el-table-column>
<el-table-column label="定制人" align="center" prop="customizer" />
<el-table-column label="发货人" align="center" prop="shipper" />
<el-table-column label="排产批次" align="center" prop="productionBatch" />
<!-- <el-table-column label="产品数量" align="center" prop="productNum" /> -->
<!-- <el-table-column label="特殊要求" align="center" prop="specialRequire" /> -->
<!-- <el-table-column label="明细金额" align="center" prop="itemAmount" /> -->
<el-table-column label="无税单价(元/吨)" align="center" prop="itemAmount" />
<el-table-column label="卷数" align="center" prop="productNum" />
<el-table-column label="表面处理" align="center" prop="surfaceTreatment" />
<el-table-column label="包装要求" align="center" prop="packagingReq" />
<el-table-column label="切边要求" align="center" prop="edgeCuttingReq" />
<el-table-column label="用途" align="center" prop="purpose" />
<el-table-column label="特殊要求" align="center" prop="specialRequire" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" v-if="editable">
<template slot-scope="scope">
@@ -52,18 +58,15 @@
<el-form-item label="产品类型" prop="productType">
<el-input v-model="form.productType" placeholder="请输入产品类型" />
</el-form-item>
<!-- <el-form-item label="产品数量" prop="productNum">
<el-input v-model="form.productNum" placeholder="请输入产品数量" />
</el-form-item> -->
<!-- <el-form-item label="明细金额" prop="itemAmount">
<el-input size="mini" v-model="form.itemAmount" placeholder="请输入明细金额" />
</el-form-item> -->
<el-form-item label="原料规格" prop="rawMaterialSpec">
<el-input v-model="form.rawMaterialSpec" placeholder="请输入原料规格" />
</el-form-item>
<el-form-item label="成品规格" prop="finishedProductSpec">
<el-input v-model="form.finishedProductSpec" placeholder="请输入成品规格" />
</el-form-item>
<el-form-item label="成品宽度" prop="width">
<el-input v-model="form.width" placeholder="请输入宽度" />
</el-form-item>
<el-form-item label="成品厚度" prop="thickness">
<el-input v-model="form.thickness" placeholder="请输入厚度" />
</el-form-item>
<el-form-item label="宽度公差" prop="widthTolerance">
<el-input v-model="form.widthTolerance" placeholder="请输入宽度公差" />
</el-form-item>
@@ -73,23 +76,34 @@
<el-form-item label="材质" prop="material">
<el-input v-model="form.material" placeholder="请输入材质" />
</el-form-item>
<el-form-item label="等级" prop="grade">
<el-input v-model="form.grade" placeholder="请输入等级" />
</el-form-item>
<el-form-item label="重量" prop="weight">
<el-input v-model="form.weight" placeholder="请输入重量" />
</el-form-item>
<el-form-item label="合同定价" prop="contractPrice">
<el-input v-model="form.contractPrice" placeholder="请输入合同定价" />
<el-form-item label="含税单价(元/吨)" prop="contractPrice">
<el-input v-model="form.contractPrice" placeholder="请输入含税单价" />
</el-form-item>
<el-form-item label="定制人" prop="customizer">
<el-input v-model="form.customizer" placeholder="请输入定制人" />
<el-form-item label="无税单价(元/吨)" prop="itemAmount">
<el-input v-model="form.itemAmount" placeholder="请输入无税单价" />
</el-form-item>
<el-form-item label="发货人" prop="shipper">
<el-input v-model="form.shipper" placeholder="请输入发货人" />
<el-form-item label="卷数" prop="productNum">
<el-input v-model="form.productNum" placeholder="请输入卷数" />
</el-form-item>
<el-form-item label="排产批次" prop="productionBatch">
<el-input v-model="form.productionBatch" placeholder="请输入排产批次" />
<el-form-item label="表面处理" prop="surfaceTreatment">
<el-input v-model="form.surfaceTreatment" placeholder="请输入表面处理" />
</el-form-item>
<el-form-item label="包装要求" prop="packagingReq">
<el-input v-model="form.packagingReq" placeholder="请输入包装要求" />
</el-form-item>
<el-form-item label="切边要求" prop="edgeCuttingReq">
<el-input v-model="form.edgeCuttingReq" placeholder="请输入切边要求" />
</el-form-item>
<el-form-item label="用途" prop="purpose">
<el-input v-model="form.purpose" placeholder="请输入用途" />
</el-form-item>
<el-form-item label="特殊要求" prop="specialRequire">
<el-input v-model="form.specialRequire" placeholder="请输入特殊要求" />
</el-form-item>
<el-form-item label="备注" prop="remark">
@@ -172,29 +186,29 @@ export default {
productType: [
{ required: true, message: "请输入产品类型", trigger: "blur" }
],
productNum: [
{ required: true, message: "请输入产品数量", trigger: "blur" }
],
rawMaterialSpec: [
{ required: true, message: "请输入原料规格", trigger: "blur" }
],
finishedProductSpec: [
{ required: true, message: "请输入成品规格", trigger: "blur" }
],
// productNum: [
// { required: true, message: "请输入产品数量", trigger: "blur" }
// ],
// rawMaterialSpec: [
// { required: true, message: "请输入原料规格", trigger: "blur" }
// ],
// finishedProductSpec: [
// { required: true, message: "请输入成品规格", trigger: "blur" }
// ],
// 重量和合同定价不能为空,且必须是数字,最多两位小数
weight: [
{ required: true, message: "请输入重量", trigger: "blur" },
// 必须是数字,最多两位小数,使用自定义的校验规则
{
validator: (rule, value, callback) => {
if (!/^\d+(\.\d{1,2,3})?$/.test(value)) {
callback(new Error("请输入最多三位小数的数字"));
} else {
callback();
}
}, trigger: "change"
}
],
// weight: [
// { required: true, message: "请输入重量", trigger: "blur" },
// // 必须是数字,最多两位小数,使用自定义的校验规则
// {
// validator: (rule, value, callback) => {
// if (!/^\d+(\.\d{1,2,3})?$/.test(value)) {
// callback(new Error("请输入最多三位小数的数字"));
// } else {
// callback();
// }
// }, trigger: "change"
// }
// ],
contractPrice: [
{ required: true, message: "请输入合同定价", trigger: "blur" },
// 必须是数字,最多两位小数,使用自定义的校验规则

View File

@@ -51,8 +51,8 @@
<el-input v-model="queryParams.signLocation" placeholder="请输入签订地点" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item label="合同状态" prop="contractStatus">
<el-select v-model="queryParams.contractStatus" placeholder="请选择合同状态">
<el-form-item label="合同状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择合同状态">
<el-option label="草稿" value="0" />
<el-option label="已生效" value="1" />
<el-option label="已作废" value="2" />

View File

@@ -27,12 +27,12 @@
<div style="margin-top: 20px;">
<h4 style="margin-bottom: 10px; color: #606266;">产品内容</h4>
<ProductContent v-model="contract.productContent" readonly />
<OrderDetail :orderId="contract.orderId" :remark="contract.remark" readonly />
<!-- <ProductContent v-model="contract.productContent" readonly /> -->
<!-- <div v-html="contract.productContent" style="border: 1px solid #e4e7ed; padding: 10px; border-radius: 4px;"></div> -->
</div>
<div>
<!-- <h4 style="margin-bottom: 10px; color: #606266;">合同内容</h4> -->
<div v-html="contract.contractContent" style="border: 1px solid #e4e7ed; padding: 10px; border-radius: 4px;"></div>
</div>
@@ -61,11 +61,13 @@
<script>
import ProductContent from './ProductContent.vue';
import OrderDetail from './OrderDetail.vue';
export default {
name: "ContractPreview",
components: {
ProductContent
ProductContent,
OrderDetail
},
props: {
contract: {

View File

@@ -20,6 +20,12 @@
<!-- 订单异议内容 -->
<OrderObjection :order="currentOrder" />
</div>
</el-tab-pane>
<el-tab-pane label="生产成果" name="product">
<div class="order-record" v-if="activeTab === 'product'">
<!-- 生产成果内容 -->
<CoilTable :data="productList || []" />
</div>
</el-tab-pane>
<el-tab-pane label="发货配卷" name="coil">
<div class="order-record" v-if="activeTab === 'coil'">
@@ -99,6 +105,10 @@ export default {
type: Array,
default: () => []
},
productList: {
type: Array,
default: () => []
},
loading: {
type: Boolean,
default: false

View File

@@ -0,0 +1,307 @@
<template>
<div v-loading="loading">
<!-- 网格布局实现的表格共8列 -->
<div class="product-content">
<!-- 第一行合并所有八个单元格内容为嘉祥科伦普重工有限公司 -->
<div class="table-row table-header">
<div class="table-cell" colspan="3">
<div class="company-name">产品名称{{ productName }}</div>
</div>
<div class="table-cell" colspan="5">
<div class="company-name">生产厂家嘉祥科伦普重工有限公司</div>
</div>
</div>
<!-- 第二行为表头 -->
<div class="table-row">
<div class="table-cell">序号</div>
<div class="table-cell">规格mm</div>
<div class="table-cell">材质</div>
<div class="table-cell">数量</div>
<div class="table-cell">含税单价/</div>
<div class="table-cell">不含税单价/</div>
<div class="table-cell">含税总额</div>
<div class="table-cell">备注</div>
</div>
<!-- 产品行 -->
<div
v-for="(item, index) in products"
:key="index"
class="table-row"
:class="{ 'table-row-hover': !readonly }"
>
<div class="table-cell">
<div class="serial-number">
<span>{{ index + 1 }}</span>
</div>
</div>
<div class="table-cell">
{{ item.finishedProductSpec }}
</div>
<div class="table-cell">
{{ item.material }}
</div>
<div class="table-cell">
{{ item.weight }}
</div>
<div class="table-cell">
{{ item.contractPrice }}
</div>
<div class="table-cell">
{{ item.itemAmount }}
</div>
<div class="table-cell">
{{ item.contractPrice * item.weight }}
</div>
<div class="table-cell">
{{ item.remark }}
</div>
</div>
<!-- 合计行 -->
<div class="table-row table-total-row">
<div class="table-cell" colspan="3">合计</div>
<div class="table-cell">{{ totalQuantity }}</div>
<div class="table-cell"></div>
<div class="table-cell"></div>
<div class="table-cell">{{ totalTaxTotal }}</div>
<div class="table-cell"></div>
</div>
<!-- 合计人民币(大写) -->
<div class="table-row">
<div class="table-cell" colspan="8">
<span>合计人民币(大写)</span>
<span>{{ totalAmountInWords }}</span>
</div>
</div>
<!-- 备注 -->
<div class="table-row">
<div class="table-cell" colspan="8">
<span>备注</span>
<pre>{{ remark }}</pre>
</div>
</div>
</div>
</div>
</template>
<script>
import { listOrderItem } from '@/api/crm/orderItem'
export default {
name: 'ProductContent',
props: {
orderId: {
type: Number,
default: 0
},
remark: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
loading: false,
products: [],
productName: ''
}
},
computed: {
// 计算总数量(吨)
totalQuantity() {
return this.products.reduce((sum, item) => sum + (Number(item.weight) || 0), 0)
},
// 计算含税总额(元)
totalTaxTotal() {
return this.products.reduce((sum, item) => sum + (Number(item.contractPrice) || 0) * (Number(item.weight) || 0), 0)
},
// 计算合计人民币(大写)
totalAmountInWords() {
const amount = this.totalTaxTotal
if (amount === 0) return '零元整'
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
const units = ['', '拾', '佰', '仟']
const bigUnits = ['', '万', '亿']
let integerPart = Math.floor(amount)
let decimalPart = Math.round((amount - integerPart) * 100)
let result = ''
let unitIndex = 0
let bigUnitIndex = 0
if (integerPart === 0) {
result = '零'
} else {
while (integerPart > 0) {
let section = integerPart % 10000
if (section > 0) {
let sectionResult = ''
let sectionUnitIndex = 0
while (section > 0) {
let digit = section % 10
if (digit > 0) {
sectionResult = digits[digit] + units[sectionUnitIndex] + sectionResult
} else if (sectionResult && !sectionResult.startsWith('零')) {
sectionResult = '零' + sectionResult
}
section = Math.floor(section / 10)
sectionUnitIndex++
}
result = sectionResult + bigUnits[bigUnitIndex] + result
}
integerPart = Math.floor(integerPart / 10000)
bigUnitIndex++
}
}
result += '元'
if (decimalPart === 0) {
result += '整'
} else {
const jiao = Math.floor(decimalPart / 10)
const fen = decimalPart % 10
if (jiao > 0) {
result += digits[jiao] + '角'
}
if (fen > 0) {
result += digits[fen] + '分'
}
}
return result
}
},
watch: {
// 监听 orderId 变化,重新获取订单商品列表
orderId: {
handler(newVal) {
if (newVal) {
this.getOrderItems()
} else {
this.products = []
this.productName = ''
}
},
immediate: true
}
},
methods: {
// 获取订单商品列表
async getOrderItems() {
this.loading = true
try {
const res = await listOrderItem({
orderId: this.orderId
})
if (res.code === 200) {
this.products = res.rows || []
this.productName = res.rows[0]?.productType || ''
} else {
this.products = []
this.productName = ''
}
} catch (error) {
console.error('获取订单商品列表失败:', error)
this.products = []
this.productName = ''
} finally {
this.loading = false
}
}
}
}
</script>
<style scoped>
.product-content {
border: 1px solid #e4e7ed;
border-radius: 4px;
overflow: hidden;
}
.table-header {
background-color: #f5f7fa;
text-align: center;
border-bottom: 1px solid #e4e7ed;
}
.company-name {
font-size: 16px;
font-weight: bold;
}
.table-row {
display: grid;
grid-template-columns: 80px 150px 120px 100px 140px 150px 120px 1fr;
border-bottom: 1px solid #e4e7ed;
}
.table-row-hover:hover {
background-color: #f5f7fa;
}
.table-header-row {
background-color: #f5f7fa;
font-weight: bold;
}
.table-total-row {
background-color: #f5f7fa;
font-weight: bold;
}
.table-cell {
padding: 8px;
border-right: 1px solid #e4e7ed;
display: flex;
align-items: center;
}
.table-cell:last-child {
border-right: none;
}
.table-cell[colspan="3"] {
grid-column: span 3;
}
.table-cell[colspan="5"] {
grid-column: span 5;
}
.table-cell[colspan="8"] {
grid-column: span 8;
}
.serial-number {
position: relative;
display: inline-flex;
align-items: center;
}
.delete-btn {
opacity: 0;
margin-left: 10px;
}
.serial-number:hover .delete-btn {
opacity: 1;
}
.el-input {
width: 100%;
}
</style>

View File

@@ -24,7 +24,7 @@
<!-- 右侧下方Tab标签页 -->
<div class="tab-panel" ref="tabPanel" style="flex: 1; overflow-y: auto;">
<ContractTabs :orderId="form.orderId" :deliveryWaybillList="wmsDeliveryWaybills" :coilList="coilList" :contract-attachment="form.businessAnnex" :technical-agreement="form.techAnnex"
:other-attachment="form.productionSchedule" :currentOrder="form" />
:other-attachment="form.productionSchedule" :currentOrder="form" :productList="form.coilList" />
</div>
</div>
<div v-else style="flex: 1; display: flex; flex-direction: column;">
@@ -81,9 +81,9 @@
</el-col>
</el-row>
<el-form-item label="产品内容">
<!-- <el-form-item label="产品内容">
<ProductContent v-model="form.productContent" :readonly="false" />
</el-form-item>
</el-form-item> -->
<el-form-item label="合同内容">
<editor v-model="form.contractContent" :min-height="192" />
</el-form-item>

View File

@@ -105,13 +105,14 @@ export default {
const data = response.data || {};
this.summary = data.summary || {};
this.detailList = data.details.map(item => {
return item.coils.map(coil => {
return item.coils?.map(coil => {
return {
...item,
...coil,
}
})
}) || []
}).flat();
console.log(this.detailList);
this.loading = false;
}).catch(() => {
this.loading = false;

View File

@@ -153,30 +153,36 @@
</div>
</div>
<el-table :data="coilList" v-loading="coilLoading" class="light-table">
<el-table-column label="钢卷层级" align="center" width="80">
<template slot-scope="scope">
<el-input v-model="scope.row.furnaceLevel" placeholder="请输入钢卷层级"
@change="handlePLanCoilChange(scope.row)" />
</template>
</el-table-column>
<el-table-column label="入场钢卷号" align="center" prop="enterCoilNo" />
<!-- <el-table-column label="当前钢卷号" align="center" prop="currentCoilNo" /> -->
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
<template slot-scope="scope">
<el-date-picker style="width: 185px" v-model="scope.row.createTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择创建时间" @change="handlePLanCoilChange(scope.row)"/>
<el-date-picker style="width: 185px" v-model="scope.row.createTime" type="datetime"
value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择创建时间" @change="handlePLanCoilChange(scope.row)" />
</template>
</el-table-column>
<el-table-column label="钢卷去向" align="center" width="220">
<template slot-scope="scope">
<WarehouseSelect v-model="scope.row.logicWarehouseId" @change="handlePLanCoilChange(scope.row)"/>
<el-select v-model="scope.row.logicWarehouseId" @change="handlePLanCoilChange(scope.row)">
<el-option v-for="item in warehouseList" :key="item.warehouseId" :label="item.warehouseName"
:value="item.warehouseId" />
</el-select>
</template>
</el-table-column>
<el-table-column label="钢卷层级" align="center" width="80">
<template slot-scope="scope">
<el-input v-model="scope.row.furnaceLevel" placeholder="请输入钢卷层级" @change="handlePLanCoilChange(scope.row)"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<!-- <el-table-column label="操作" align="center" width="100">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleUnbind(scope.row)">
{{ unbindLabel(currentPlan.status) }}
</el-button>
</template>
</el-table-column>
</el-table-column> -->
</el-table>
</div>
</el-card>
@@ -184,12 +190,15 @@
</el-row>
<el-dialog title="完成退火" :visible.sync="completeOpen" width="720px" append-to-body>
<div class="complete-tip">请为每条钢卷分配实际库位未分配将无法完成</div>
<div class="complete-tip">请为每条钢卷分配逻辑库区去向未分配将无法完成</div>
<el-table :data="completeCoils" v-loading="completeLoading" height="360px">
<el-table-column label="入场钢卷号" prop="enterCoilNo" align="center" />
<el-table-column label="钢卷去向" align="center" width="240">
<template slot-scope="scope">
<WarehouseSelect v-model="scope.row.warehouseId" />
<el-select v-model="scope.row.warehouseId" @change="handlePLanCoilChange(scope.row)">
<el-option v-for="item in warehouseList" :key="item.warehouseId" :label="item.warehouseName"
:value="item.warehouseId" />
</el-select>
</template>
</el-table-column>
</el-table>
@@ -253,7 +262,9 @@
import { listAnnealPlan, updateAnnealPlanCoil, getAnnealPlan, addAnnealPlan, updateAnnealPlan, delAnnealPlan, changeAnnealPlanStatus, inFurnace, completeAnnealPlan, listAnnealPlanCoils, bindAnnealPlanCoils, unbindAnnealPlanCoil } from "@/api/wms/annealPlan";
import { listAnnealFurnace } from "@/api/wms/annealFurnace";
import { listMaterialCoil } from "@/api/wms/coil";
import { listWarehouse } from '@/api/wms/warehouse'
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { addAnnealOperateEvent } from "@/api/wms/annealOperateEvent";
export default {
name: "AnnealPlan",
@@ -308,14 +319,15 @@ export default {
completeLoading: false,
completePlanId: null,
completeCoils: [],
warehouseList: [],
};
},
created() {
this.getList();
this.loadFurnaces();
this.getMaterialCoils();
this.loadActualWarehouses();
},
this.loadWarehouses();
},
methods: {
getList() {
this.loading = true;
@@ -325,6 +337,11 @@ export default {
this.loading = false;
});
},
loadWarehouses() {
listWarehouse().then(response => {
this.warehouseList = response.data || [];
});
},
loadFurnaces() {
listAnnealFurnace({ pageNum: 1, pageSize: 999, status: 1 }).then(response => {
this.furnaceOptions = response.rows || [];
@@ -372,6 +389,7 @@ export default {
this.completeLoading = true;
listAnnealPlanCoils(this.currentPlan.planId).then(response => {
this.completeCoils = (response.data || []).map(item => ({
...item,
coilId: item.coilId,
enterCoilNo: item.enterCoilNo,
warehouseId: item.logicWarehouseId || null
@@ -395,6 +413,7 @@ export default {
planId: this.currentPlan.planId,
coilId: item.coilId
}).then(() => {
// anneal-todo: 新增操作事件
this.$message.success('已加入计划');
this.loadPlanCoils();
}).finally(() => {
@@ -526,6 +545,15 @@ export default {
});
this.loading = true;
await inFurnace({ planId: row.planId });
// 炉火开始加工
const targetFurnaceName = this.furnaceOptions.find(item => item.furnaceId === row.targetFurnaceId)?.furnaceName || '';
addAnnealOperateEvent({
annealFurnaceId: row.targetFurnaceId,
operateType: 'IN',
operateContent: '退火炉' + targetFurnaceName + '开始加工',
})
// anneal-todo: 新增操作事件
this.loading = false;
row.status = 2;
row.actualStartTime = new Date();
@@ -552,6 +580,13 @@ export default {
planId: this.completePlanId,
locations: locations
}).then(() => {
// anneal-todo: 新增操作事件
const targetFurnaceName = this.furnaceOptions.find(item => item.furnaceId === this.currentPlan.targetFurnaceId)?.furnaceName || '';
addAnnealOperateEvent({
annealFurnaceId: this.currentPlan.targetFurnaceId,
operateType: 'COMPLETE',
operateContent: '退火炉' + targetFurnaceName + '完成加工。',
})
this.$message.success('已完成');
this.completeOpen = false;
this.getList();
@@ -571,6 +606,7 @@ export default {
coilId: row.coilId
});
}).then(() => {
// anneal-todo: 新增操作事件
this.$message.success('解绑成功');
this.loadPlanCoils();
});

View File

@@ -67,8 +67,8 @@
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click.stop="handleUpdate(scope.row)">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click.stop="handleDelete(scope.row)">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-s-operation"
@click.stop="openStatusDialog(scope.row)">状态</el-button>
<!-- <el-button size="mini" type="text" icon="el-icon-s-operation"
@click.stop="openStatusDialog(scope.row)">状态</el-button> -->
<!-- <el-button v-if="scope.row.status === 0" size="mini" type="text" icon="el-icon-s-flag"
:disabled="!scope.row.coilCount" @click.stop="handleInFurnace(scope.row)">入炉</el-button> -->
<el-button v-if="scope.row.status === 2" size="mini" type="text" icon="el-icon-check"
@@ -153,6 +153,12 @@
</div> -->
</div>
<el-table :data="coilList" v-loading="coilLoading" class="light-table">
<el-table-column label="钢卷层级" align="center" width="80">
<template slot-scope="scope">
<el-input v-model="scope.row.furnaceLevel" placeholder="请输入钢卷层级"
@change="handlePLanCoilChange(scope.row)" />
</template>
</el-table-column>
<el-table-column label="入场钢卷号" align="center" prop="enterCoilNo" />
<el-table-column label="创建时间" align="center" prop="createTime">
<template slot-scope="scope">
@@ -166,7 +172,7 @@
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleUnbind(scope.row)">
<el-button v-if="currentPlan.status === 0" size="mini" type="text" icon="el-icon-delete" @click="handleUnbind(scope.row)">
{{ unbindLabel(currentPlan.status) }}
</el-button>
</template>
@@ -208,13 +214,13 @@
:value="item.furnaceId" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<!-- <el-form-item label="状态" prop="status">
<el-select v-model="form.status" placeholder="请选择">
<el-option label="未开始" :value="0" />
<el-option label="进行中" :value="2" />
<el-option label="已完成" :value="3" />
</el-select>
</el-form-item>
</el-form-item> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
@@ -226,7 +232,7 @@
</el-dialog>
<el-dialog title="更新状态" :visible.sync="statusOpen" width="360px" append-to-body>
<el-form label-width="90px">
<!-- <el-form label-width="90px">
<el-form-item label="状态">
<el-select v-model="statusForm.status" placeholder="请选择">
<el-option label="未开始" :value="0" />
@@ -234,7 +240,7 @@
<el-option label="已完成" :value="3" />
</el-select>
</el-form-item>
</el-form>
</el-form> -->
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitStatus"> </el-button>
<el-button @click="statusOpen = false"> </el-button>
@@ -244,10 +250,11 @@
</template>
<script>
import { listAnnealPlan, getAnnealPlan, addAnnealPlan, updateAnnealPlan, delAnnealPlan, changeAnnealPlanStatus, inFurnace, completeAnnealPlan, listAnnealPlanCoils, bindAnnealPlanCoils, unbindAnnealPlanCoil } from "@/api/wms/annealPlan";
import { listAnnealPlan, getAnnealPlan, updateAnnealPlanCoil ,addAnnealPlan, updateAnnealPlan, delAnnealPlan, changeAnnealPlanStatus, inFurnace, completeAnnealPlan, listAnnealPlanCoils, bindAnnealPlanCoils, unbindAnnealPlanCoil } from "@/api/wms/annealPlan";
import { listAnnealFurnace } from "@/api/wms/annealFurnace";
import { listMaterialCoil } from "@/api/wms/coil";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import { addAnnealOperateEvent } from "@/api/wms/annealOperateEvent";
export default {
name: "AnnealPlan",
@@ -308,7 +315,6 @@ export default {
this.getList();
this.loadFurnaces();
this.getMaterialCoils();
this.loadActualWarehouses();
},
methods: {
getList() {
@@ -345,6 +351,13 @@ export default {
this.resetMaterialForm();
this.handleMaterialQuery();
},
handlePLanCoilChange(row) {
updateAnnealPlanCoil(row).then(() => {
this.$message.success('已更新');
}).finally(() => {
this.loadPlanCoils();
});
},
openCompleteDialog() {
if (!this.currentPlan.planId) {
this.$message.warning('请先选择计划');
@@ -383,6 +396,15 @@ export default {
coilId: item.coilId
}).then(() => {
this.$message.success('已加入计划');
// 查找对应id退火炉的名称
const targetFurnaceName = this.furnaceOptions.find(item => item.furnaceId === this.currentPlan.targetFurnaceId)?.furnaceName || '';
// anneal-todo: 新增操作事件
addAnnealOperateEvent({
annealFurnaceId: this.currentPlan.targetFurnaceId,
operateType: 'ADD',
operateContent: '钢卷号' + item.enterCoilNo + '加入退火炉' + targetFurnaceName,
coilId: item.coilId,
})
this.loadPlanCoils();
}).finally(() => {
this.coilLoading = false;
@@ -512,6 +534,7 @@ export default {
});
this.loading = true;
await inFurnace({ planId: row.planId });
// anneal-todo: 新增操作事件
this.loading = false;
row.status = 2;
row.actualStartTime = new Date();
@@ -540,6 +563,7 @@ export default {
}).then(() => {
this.$message.success('已完成');
this.completeOpen = false;
// anneal-todo: 新增操作事件
this.getList();
this.loadPlanCoils();
}).finally(() => {
@@ -558,6 +582,15 @@ export default {
});
}).then(() => {
this.$message.success('解绑成功');
// 查找对应id退火炉的名称
const targetFurnaceName = this.furnaceOptions.find(item => item.furnaceId === this.currentPlan.targetFurnaceId)?.furnaceName || '';
// anneal-todo: 新增操作事件
addAnnealOperateEvent({
annealFurnaceId: this.currentPlan.targetFurnaceId,
operateType: 'UNBIND',
operateContent: '钢卷号' + row.enterCoilNo + '解绑退火炉' + targetFurnaceName,
coilId: row.coilId,
})
this.loadPlanCoils();
});
},

View File

@@ -0,0 +1,408 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="退火炉" prop="annealFurnaceId">
<el-select
v-model="queryParams.annealFurnaceId"
placeholder="请选择退火炉"
clearable
@keyup.enter.native="handleQuery"
>
<el-option
v-for="item in annealFurnaceList"
:key="item.furnaceId"
:label="item.furnaceName"
:value="item.furnaceId"
/>
</el-select>
</el-form-item>
<el-form-item label="操作类型" prop="operateType">
<el-select
v-model="queryParams.operateType"
placeholder="请选择操作类型"
clearable
@keyup.enter.native="handleQuery"
>
<el-option
label="新增"
value="ADD"
/>
<el-option
label="解绑"
value="UNBIND"
/>
<el-option
label="入炉"
value="IN"
/>
<el-option
label="完成"
value="COMPLETE"
/>
</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-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
>补录</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="annealOperateEventList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="主键ID" align="center" prop="eventId" v-if="true"/> -->
<el-table-column label="退火炉" align="center" prop="annealFurnaceName">
<template slot-scope="scope">
{{ getAnnealFurnaceName(scope.row.annealFurnaceId) || '-' }}
</template>
</el-table-column>
<el-table-column label="操作类型" align="center" prop="operateType">
<template slot-scope="scope">
{{ getOperateTypeName(scope.row.operateType) || '-' }}
</template>
</el-table-column>
<el-table-column label="操作描述" align="center" prop="operateContent" />
<!-- <el-table-column label="钢卷ID(可选)" align="center" prop="coilId" /> -->
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作人" align="center" prop="createBy" />
<el-table-column label="操作时间" align="center" prop="createTime" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改退火操作事件对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="退火炉" prop="annealFurnaceId">
<el-select v-model="form.annealFurnaceId" placeholder="请选择退火炉">
<el-option v-for="item in annealFurnaceList" :key="item.furnaceId" :label="item.furnaceName" :value="item.furnaceId" />
</el-select>
</el-form-item>
<el-form-item label="操作描述">
<el-input type="textarea" v-model="form.operateContent" placeholder="请输入操作描述" />
</el-form-item>
<el-form-item label="操作类型" prop="operateType">
<el-select v-model="form.operateType" placeholder="请选择操作类型" clearable>
<el-option
label="新增"
value="ADD"
/>
<el-option
label="解绑"
value="UNBIND"
/>
<el-option
label="入炉"
value="IN"
/>
<el-option
label="完成"
value="COMPLETE"
/>
</el-select>
</el-form-item>
<el-form-item label="操作人" prop="createBy">
<el-input v-model="form.createBy" placeholder="请输入操作人" />
</el-form-item>
<el-form-item label="操作时间" prop="createTime">
<el-date-picker
v-model="form.createTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择操作时间"
/>
</el-form-item>
<!-- <el-form-item label="钢卷ID(可选)" prop="coilId">
<el-input v-model="form.coilId" placeholder="请输入钢卷ID(可选)" />
</el-form-item> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listAnnealOperateEvent, getAnnealOperateEvent, delAnnealOperateEvent, addAnnealOperateEvent, updateAnnealOperateEvent } from "@/api/wms/annealOperateEvent";
import { listAnnealFurnace } from "@/api/wms/annealFurnace";
export default {
name: "AnnealOperateEvent",
data() {
return {
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 退火操作事件表格数据
annealOperateEventList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
annealFurnaceId: undefined,
operateType: undefined,
operateContent: undefined,
coilId: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
eventId: [
{ required: true, message: "主键ID不能为空", trigger: "blur" }
],
annealFurnaceId: [
{ required: true, message: "退火炉ID不能为空", trigger: "blur" }
],
operateType: [
{ required: true, message: "操作类型 如:START/PAUSE/STOP/FEED/TAKE/RESET不能为空", trigger: "change" }
],
operateContent: [
{ required: true, message: "操作内容描述不能为空", trigger: "blur" }
],
coilId: [
{ required: true, message: "钢卷ID(可选)不能为空", trigger: "blur" }
],
delFlag: [
{ required: true, message: "删除标志不能为空", trigger: "blur" }
],
// remark: [
// { required: true, message: "备注不能为空", trigger: "blur" }
// ],
createBy: [
{ required: true, message: "操作人不能为空", trigger: "blur" }
],
createTime: [
{ required: true, message: "操作时间不能为空", trigger: "blur" }
],
updateTime: [
{ required: true, message: "更新时间不能为空", trigger: "blur" }
],
},
// 退火炉列表
annealFurnaceList: [],
};
},
created() {
this.getList();
this.getAnnealFurnaceList();
},
methods: {
/** 查询退火操作事件列表 */
getList() {
this.loading = true;
listAnnealOperateEvent(this.queryParams).then(response => {
this.annealOperateEventList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 查询退火炉列表 */
getAnnealFurnaceList() {
listAnnealFurnace({ pageNum: 1, pageSize: 10000 }).then(response => {
this.annealFurnaceList = response.rows;
});
},
/** 获取退火炉名称 */
getAnnealFurnaceName(furnaceId) {
const item = this.annealFurnaceList.find(item => item.furnaceId === furnaceId);
return item ? item.furnaceName : '-';
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
/** 获取操作类型名称 */
getOperateTypeName(operateType) {
const map = {
'ADD': '新增',
'UNBIND': '解绑',
'IN': '入炉',
'COMPLETE': '完成',
}
return map[operateType] || '-';
},
// 表单重置
reset() {
this.form = {
eventId: undefined,
annealFurnaceId: undefined,
operateType: undefined,
operateContent: undefined,
coilId: undefined,
delFlag: undefined,
remark: undefined,
createTime: undefined,
createBy: undefined,
updateTime: undefined,
updateBy: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.eventId)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加退火操作事件";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.loading = true;
this.reset();
const eventId = row.eventId || this.ids
getAnnealOperateEvent(eventId).then(response => {
this.loading = false;
this.form = response.data;
this.open = true;
this.title = "修改退火操作事件";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.eventId != null) {
updateAnnealOperateEvent(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
addAnnealOperateEvent(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const eventIds = row.eventId || this.ids;
this.$modal.confirm('是否确认删除退火操作事件编号为"' + eventIds + '"的数据项?').then(() => {
this.loading = true;
return delAnnealOperateEvent(eventIds);
}).then(() => {
this.loading = false;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport() {
this.download('wms/annealOperateEvent/export', {
...this.queryParams
}, `annealOperateEvent_${new Date().getTime()}.xlsx`)
}
}
};
</script>

View File

@@ -292,9 +292,9 @@ import { getCoilTagPrintType } from '@/views/wms/coil/js/coilPrint'
export default {
name: 'DoPage',
dicts: ['action_type', 'coil_abnormal_code', 'coil_abnormal_position', 'coil_abnormal_degree', 'coil_quality_status'],
dicts: ['action_type', 'coil_abnormal_code', 'coil_abnormal_position', 'coil_abnormal_degree', 'coil_quality_status', 'coil_business_purpose'],
props: {
label: {
label: {
type: String,
default: () => '酸连轧工序'
},
@@ -314,7 +314,6 @@ export default {
RawMaterialSelect,
CoilTraceResult,
},
dicts: ['coil_business_purpose'],
data() {
return {
traceOpen: false,

View File

@@ -1,5 +1,7 @@
<template>
<BasePage :qrcode="qrcode" :querys="querys" :labelType="labelType" :hideType="hideType" :showControl="showControl" />
<BasePage
:leftWarehouseQuery="true"
:qrcode="qrcode" :querys="querys" :labelType="labelType" :hideType="hideType" :showControl="showControl" />
</template>
<script>

View File

@@ -1,5 +1,8 @@
<template>
<BasePage :qrcode="qrcode" :querys="querys" :labelType="labelType" :hideType="hideType" />
<BasePage
:leftWarehouseQuery="true"
:qrcode="qrcode" :querys="querys" :labelType="labelType" :hideType="hideType"
/>
</template>
<script>

View File

@@ -252,6 +252,12 @@
</el-form-item>
</div>
<div class="form-row">
<el-form-item label="关联合同" prop="contractId">
<ContractSelect v-model="targetCoil.contractId" placeholder="请选择合同" />
</el-form-item>
</div>
<div class="form-row">
<el-form-item label="异常信息" class="form-item-full">
<div class="abnormal-container">
@@ -301,6 +307,8 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import TimeInput from "@/components/TimeInput";
import AbnormalForm from './components/AbnormalForm';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
export default {
name: 'MergeCoil',
@@ -311,7 +319,8 @@ export default {
ProductSelector,
WarehouseSelect,
TimeInput,
AbnormalForm
AbnormalForm,
ContractSelect
},
dicts: ['coil_quality_status', 'coil_abnormal_position', 'coil_abnormal_code', 'coil_abnormal_degree', 'coil_business_purpose'],
data() {
@@ -752,11 +761,19 @@ export default {
text: '正在合卷,请稍后...',
background: 'rgba(0, 0, 0, 0.7)'
});
await mergeMaterialCoil(mergeData);
const response = await mergeMaterialCoil(mergeData);
const coilId = response.data;
if (this.targetCoil.contractId) {
addCoilContractRel({
coilId: coilId,
contractId: this.targetCoil.contractId,
})
}
this.$message.success('合卷保存成功');
// 延迟返回,让用户看到成功提示
setTimeout(() => {
this.$router.back();

View File

@@ -9,13 +9,7 @@
<el-input v-model="queryParams.currentCoilNo" placeholder="请输入当前钢卷号" clearable
@keyup.enter.native="handleQuery" />
</el-form-item>
<!-- <el-form-item label="数据状态">
<el-select v-model="queryParams.dataType" placeholder="请选择数据状态" clearable>
<el-option :value="0" label="历史数据">历史数据</el-option>
<el-option :value="1" label="当前数据">当前数据</el-option>
</el-select>
</el-form-item> -->
<el-form-item label="逻辑库位" prop="warehouseId" v-if="!hideWarehouseQuery">
<el-form-item label="逻辑库位" prop="warehouseId" v-if="!hideWarehouseQuery && !leftWarehouseQuery">
<warehouse-select v-model="queryParams.warehouseId" placeholder="请选择仓库/库区/库位"
style="width: 100%; display: inline-block;" clearable />
</el-form-item>
@@ -45,9 +39,6 @@
clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<MaterialSelect :hideType="hideType" :itemId.sync="queryParams.itemIds" :itemType.sync="queryParams.itemType"
:multiple="true" />
<el-form-item v-if="showWaybill" label="发货状态">
<el-select v-model="queryParams.status" placeholder="请选择发货状态" clearable>
<el-option :value="0" label="未发货">未发货</el-option>
@@ -79,17 +70,14 @@
</el-form>
<el-row :gutter="10" class="mb8" v-if="showControl">
<el-col :span="1.5">
<!-- <el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single"
@click="handleCheck">修正</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
@click="handleDelete">删除</el-button>
</el-col> -->
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExportAll">导出</el-button>
</el-col>
<el-col :span="2" v-if="canExportAll">
<el-button type="info" plain icon="el-icon-printer" size="mini" :disabled="multiple"
@click="handleBatchPrintLabel">批量打印标签</el-button>
@@ -98,54 +86,65 @@
<el-checkbox v-model="queryParams.orderBy" v-loading="loading" @change="getList"
label="orderBy">按实际库区排序</el-checkbox>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<KLPTable v-loading="loading" :data="materialCoilList" @selection-change="handleSelectionChange" :floatLayer="true"
:floatLayerConfig="floatLayerConfig" @row-click="handleRowClick"
:height="showAbnormal ? 'calc(100vh - 400px)' : 'calc(100vh - 300px)'">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="入场钢卷号" align="center" prop="enterCoilNo">
<template slot-scope="scope">
<coil-no :coil-no="scope.row.enterCoilNo"></coil-no>
</template>
</el-table-column>
<el-table-column label="当前钢卷号" align="center" prop="currentCoilNo">
<template slot-scope="scope">
<current-coil-no :current-coil-no="scope.row.currentCoilNo"></current-coil-no>
</template>
</el-table-column>
<!-- <el-table-column label="厂家卷号" align="center" prop="supplierCoilNo" /> -->
<el-table-column label="逻辑库位" align="center" prop="warehouseName" v-if="!hideWarehouseQuery" />
<el-table-column label="实际库区" align="center" prop="actualWarehouseName"
v-if="!hideWarehouseQuery && !showExportTime" />
<!-- <el-table-column label="物料类型" align="center" prop="materialType" /> -->
<el-table-column label="产品类型" align="center" width="180">
<template slot-scope="scope">
<ProductInfo v-if="scope.row.itemType == 'product'" :product="scope.row" />
<RawMaterialInfo v-else-if="scope.row.itemType === 'raw_material'" :material="scope.row" />
</template>
</el-table-column>
<el-table-column v-if="showAbnormal" label="异常数量" align="center" prop="abnormalCount"></el-table-column>
<el-table-column label="长度 (米)" align="center" prop="length" v-if="showLength" />
<el-table-column label="更新时间" v-if="!showExportTime" align="center" prop="updateTime" />
<el-table-column label="发货时间" v-if="showExportTime" align="center" prop="exportTime" width="205">
<template slot-scope="scope">
<el-date-picker @change="handleExportTimeChange(scope.row)" v-if="canEditExportTime" style="width: 100%"
v-model="scope.row.exportTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择发货时间" />
<div v-else>{{ scope.row.exportTime }}</div>
</template>
</el-table-column>
<el-table-column label="发货人" v-if="showExportTime" align="center" prop="exportByName" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.exportBy" placeholder="请选择发货人" filterable
@change="handleExportByNameChange(scope.row)">
<el-option v-for="item in userList" :key="item.userName" :value="item.userName" :label="item.nickName" />
</el-select>
</template>
</el-table-column>
<el-table-column label="更新人" v-if="!showExportTime" align="center" prop="updateByName" />
<el-table-column label="关联信息" align="center" :show-overflow-tooltip="true">
<div style="display: flex; align-items: flex-start;">
<div v-if="leftWarehouseQuery"
:style="{
width: '220px',
height: showAbnormal ? 'calc(100vh - 400px)' : 'calc(100vh - 300px)',
backgroundColor: '#ffffff',
overflowY: 'auto',
overflowX: 'hidden' }">
<warehouse-tree warehouseType="logic" @node-click="handleWarehouseNodeClick" />
</div>
<div style="flex: 1;">
<KLPTable v-loading="loading" :data="materialCoilList" @selection-change="handleSelectionChange"
:floatLayer="true" :floatLayerConfig="floatLayerConfig" @row-click="handleRowClick"
:height="showAbnormal ? 'calc(100vh - 400px)' : 'calc(100vh - 300px)'">
<!-- <el-table-column type="selection" width="55" align="center" /> -->
<el-table-column label="入场钢卷号" align="center" prop="enterCoilNo">
<template slot-scope="scope">
<coil-no :coil-no="scope.row.enterCoilNo"></coil-no>
</template>
</el-table-column>
<el-table-column label="当前钢卷号" align="center" prop="currentCoilNo">
<template slot-scope="scope">
<current-coil-no :current-coil-no="scope.row.currentCoilNo"></current-coil-no>
</template>
</el-table-column>
<el-table-column label="净重" align="center" prop="netWeight" v-if="!hideWarehouseQuery" />
<el-table-column label="逻辑库位" align="center" prop="warehouseName" v-if="!hideWarehouseQuery" />
<el-table-column label="实际库区" align="center" prop="actualWarehouseName"
v-if="!hideWarehouseQuery && !showExportTime" />
<el-table-column label="产品类型" align="center" width="180">
<template slot-scope="scope">
<ProductInfo v-if="scope.row.itemType == 'product'" :product="scope.row" />
<RawMaterialInfo v-else-if="scope.row.itemType === 'raw_material'" :material="scope.row" />
</template>
</el-table-column>
<el-table-column v-if="showAbnormal" label="异常数量" align="center" prop="abnormalCount"></el-table-column>
<el-table-column label="长度 (米)" align="center" prop="length" v-if="showLength" />
<el-table-column label="发货时间" v-if="showExportTime" align="center" prop="exportTime" width="205">
<template slot-scope="scope">
<el-date-picker @change="handleExportTimeChange(scope.row)" v-if="canEditExportTime" style="width: 100%"
v-model="scope.row.exportTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择发货时间" />
<div v-else>{{ scope.row.exportTime }}</div>
</template>
</el-table-column>
<el-table-column label="发货人" v-if="showExportTime" align="center" prop="exportByName" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.exportBy" placeholder="请选择发货人" filterable
@change="handleExportByNameChange(scope.row)">
<el-option v-for="item in userList" :key="item.userName" :value="item.userName"
:label="item.nickName" />
</el-select>
</template>
</el-table-column>
<!-- <el-table-column label="关联信息" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span v-if="scope.row.parentCoilNos && scope.row.hasMergeSplit === 1 && scope.row.dataType === 1">
<el-tag type="warning" size="mini">来自母卷{{ scope.row.parentCoilNos }}</el-tag>
@@ -158,165 +157,188 @@
</span>
<span v-else></span>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column v-if="showGrade" label="质量状态" align="center" prop="qualityStatus">
<template slot-scope="scope">
<el-select v-model="scope.row.qualityStatus" placeholder="请选择质量状态" @change="handleGradeChange(scope.row)">
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</template>
</el-table-column>
<el-table-column label="逻辑库位" align="center" prop="warehouseId" v-if="editWarehouse">
<template slot-scope="scope">
<warehouse-select @change="handleWarehouseChange(scope.row)" v-model="scope.row.warehouseId"
placeholder="请选择仓库/库区/库位" style="width: 100%;" clearable />
</template>
</el-table-column>
<el-table-column v-if="showGrade" label="质量状态" align="center" prop="qualityStatus">
<!-- <template slot-scope="scope">
<el-select v-model="scope.row.qualityStatus" placeholder="请选择质量状态" @change="handleGradeChange(scope.row)">
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</template> -->
</el-table-column>
<el-table-column label="逻辑库位" align="center" prop="warehouseId" v-if="editWarehouse">
<template slot-scope="scope">
<warehouse-select @change="handleWarehouseChange(scope.row)" v-model="scope.row.warehouseId"
placeholder="请选择仓库/库区/库位" style="width: 100%;" clearable />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="钢卷去向" align="center" prop="nextWarehouseId" v-if="editNext" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.nextWarehouseId" placeholder="钢卷去向" filterable
@change="handleNextWarehouseChange(scope.row)">
<el-option v-for="item in dict.type.wms_next_warehouse" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="业务目的" align="center" prop="businessPurpose" v-if="showBusinessPurpose" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.businessPurpose" placeholder="业务目的" filterable
@change="handleRowChange(scope.row)">
<el-option v-for="item in dict.type.coil_business_purpose" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</template>
</el-table-column>
<el-table-column v-if="hasTransferType" label="调拨类型" align="center" prop="transferType" />
<el-table-column label="关联订单" align="center" prop="relatedToOrder" v-if="showRelatedToOrder" width="150">
<template slot-scope="scope">
<el-switch @change="handleRowChange(scope.row)" v-model="scope.row.isRelatedToOrder" :active-value="1"
:inactive-value="0" />
</template>
</el-table-column>
<el-table-column label="钢卷去向" align="center" prop="nextWarehouseId" v-if="editNext" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.nextWarehouseId" placeholder="钢卷去向" filterable
@change="handleNextWarehouseChange(scope.row)">
<el-option v-for="item in dict.type.wms_next_warehouse" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</template>
</el-table-column>
<el-table-column label="发货计划" align="center" prop="nextWarehouseId" v-if="showWaybill" width="150">
<template slot-scope="scope">
{{ scope.row.bindPlanName || '-' }}
</template>
</el-table-column>
<el-table-column label="业务目的" align="center" prop="businessPurpose" v-if="showBusinessPurpose" width="150">
<template slot-scope="scope">
<el-select v-model="scope.row.businessPurpose" placeholder="业务目的" filterable
@change="handleRowChange(scope.row)">
<el-option v-for="item in dict.type.coil_business_purpose" :key="item.value" :value="item.value"
:label="item.label" />
</el-select>
</template>
</el-table-column>
<el-table-column label="发货单据" align="center" prop="nextWarehouseId" v-if="showWaybill" width="150">
<template slot-scope="scope">
<el-popover placement="top" width="400" trigger="hover">
<div>
<el-descriptions :column="2" :border="false">
<el-descriptions-item label="单据名称">
{{ scope.row.bindWaybillName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="车牌号">
{{ scope.row.bindLicensePlate || '-' }}
</el-descriptions-item>
<el-descriptions-item label="收货单位">
{{ scope.row.bindConsigneeUnit || '-' }}
</el-descriptions-item>
<el-descriptions-item label="负责人">
{{ scope.row.bindPrincipal || '-' }}
</el-descriptions-item>
<el-descriptions-item label="单据状态">
<el-tag v-if="scope.row.bindWaybillStatus === 0" type="info" size="mini">未发货</el-tag>
<el-tag v-else-if="scope.row.bindWaybillStatus === 1" type="info" size="mini">已发货</el-tag>
<el-tag v-else-if="scope.row.bindWaybillStatus === 2" type="info" size="mini">未打印</el-tag>
<el-tag v-else-if="scope.row.bindWaybillStatus === 3" type="info" size="mini">已打印</el-tag>
<el-tag v-else type="danger" size="mini">未知状态</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
<div slot="reference" class="text-ellipsis" v-text>{{ scope.row.bindLicensePlate || '-' }}</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="关联订单" align="center" prop="relatedToOrder" v-if="showRelatedToOrder" width="150">
<template slot-scope="scope">
<el-switch @change="handleRowChange(scope.row)" v-model="scope.row.isRelatedToOrder" :active-value="1"
:inactive-value="0" />
</template>
</el-table-column>
<el-table-column label="发货状态" align="center" prop="status" v-if="showWaybill" width="150">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 1" type="success" size="mini">已发货</el-tag>
<el-tag v-else type="info" size="mini">未发货</el-tag>
</template>
</el-table-column>
<el-table-column label="发货计划" align="center" prop="nextWarehouseId" v-if="showWaybill" width="150">
<template slot-scope="scope">
{{ scope.row.bindPlanName || '-' }}
</template>
</el-table-column>
<el-table-column label="实测宽度" align="center" prop="width" v-if="showWidthEdit" width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.actualWidth" placeholder="请输入实测宽度"
@change="handleRowChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="发货单据" align="center" prop="nextWarehouseId" v-if="showWaybill" width="150">
<template slot-scope="scope">
<el-popover placement="top" width="400" trigger="hover">
<div>
<el-descriptions :column="2" :border="false">
<el-descriptions-item label="单据名称">
{{ scope.row.bindWaybillName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="车牌号">
{{ scope.row.bindLicensePlate || '-' }}
</el-descriptions-item>
<el-descriptions-item label="收货单位">
{{ scope.row.bindConsigneeUnit || '-' }}
</el-descriptions-item>
<el-descriptions-item label="负责人">
{{ scope.row.bindPrincipal || '-' }}
</el-descriptions-item>
<el-descriptions-item label="单据状态">
<el-tag v-if="scope.row.bindWaybillStatus === 0" type="info" size="mini">未发货</el-tag>
<el-tag v-else-if="scope.row.bindWaybillStatus === 1" type="info" size="mini">已发货</el-tag>
<el-tag v-else-if="scope.row.bindWaybillStatus === 2" type="info" size="mini">未打印</el-tag>
<el-tag v-else-if="scope.row.bindWaybillStatus === 3" type="info" size="mini">已打印</el-tag>
<el-tag v-else type="danger" size="mini">未知状态</el-tag>
</el-descriptions-item>
</el-descriptions>
</div>
<div slot="reference" class="text-ellipsis" v-text>{{ scope.row.bindLicensePlate || '-' }}</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="实测厚度(m)" align="center" prop="actualThickness" v-if="showWidthEdit" width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.actualThickness" placeholder="请输入实测厚度"
@change="handleRowChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="发货状态" align="center" prop="status" v-if="showWaybill" width="150">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === 1" type="success" size="mini">已发货</el-tag>
<el-tag v-else type="info" size="mini">未发货</el-tag>
</template>
</el-table-column>
<el-table-column label="预留宽度" align="center" prop="width" v-if="showWidthEdit" width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.reservedWidth" placeholder="请输入预留宽度"
@change="handleRowChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="实测宽度" align="center" prop="width" v-if="showWidthEdit" width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.actualWidth" placeholder="请输入实测宽度"
@change="handleRowChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="生产开始" align="center" prop="productionStartTime" v-if="showProductionTimeEdit" width="150">
</el-table-column>
<el-table-column label="实测厚度(m)" align="center" prop="actualThickness" v-if="showWidthEdit" width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.actualThickness" placeholder="请输入实测厚度"
@change="handleRowChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="生产结束" align="center" prop="productionEndTime" v-if="showProductionTimeEdit" width="150">
</el-table-column>
<el-table-column label="预留宽度" align="center" prop="width" v-if="showWidthEdit" width="150">
<template slot-scope="scope">
<el-input v-model="scope.row.reservedWidth" placeholder="请输入预留宽度"
@change="handleRowChange(scope.row)"></el-input>
</template>
</el-table-column>
<el-table-column label="生产耗时" align="center" prop="productionDuration" v-if="showProductionTimeEdit" width="150">
<template slot-scope="scope">
{{ formatDuration(scope.row.productionDuration * 60 * 1000) }}
</template>
</el-table-column>
<el-table-column label="生产开始" align="center" prop="productionStartTime" v-if="showProductionTimeEdit"
width="150">
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreviewLabel(scope.row)">
预览标签
</el-button>
<el-button size="mini" type="text" icon="el-icon-printer" @click="handlePrintLabel(scope.row)">
打印标签
</el-button>
<el-button size="mini" v-if="showStatus" type="text" icon="el-icon-upload"
@click="handleExportCoil(scope.row)">
发货
</el-button>
<el-button size="mini" v-if="showExportTime" type="text" icon="el-icon-close"
@click="handleCancelExport(scope.row)">
撤回发货
</el-button>
<el-button size="mini" v-if="showProductionTimeEdit" type="text" icon="el-icon-close"
@click="handleProductionTimeEdit(scope.row)">
加工修正
</el-button>
<el-button size="mini" v-if="showExportTime" type="text" icon="el-icon-sold-out"
@click="handleReturnCoil(scope.row)">
退货钢卷
</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleCheck(scope.row)"
v-if="showControl">修正</el-button>
<el-button size="mini" type="text" icon="el-icon-search" @click="handleTrace(scope.row)">追溯</el-button>
<el-button size="mini" v-if="showWaybill" type="text" icon="el-icon-close"
@click="handleRemoveFromWaybill(scope.row)">
移出发货单
</el-button>
</template>
</el-table-column>
</KLPTable>
<el-table-column label="生产结束" align="center" prop="productionEndTime" v-if="showProductionTimeEdit"
width="150">
</el-table-column>
<el-table-column label="生产耗时" align="center" prop="productionDuration" v-if="showProductionTimeEdit"
width="150">
<template slot-scope="scope">
{{ formatDuration(scope.row.productionDuration * 60 * 1000) }}
</template>
</el-table-column>
<el-table-column prop="action" label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreviewLabel(scope.row)">
预览标签
</el-button>
<el-button size="mini" type="text" icon="el-icon-printer" @click="handlePrintLabel(scope.row)">
打印标签
</el-button>
<el-button size="mini" v-if="showStatus" type="text" icon="el-icon-upload"
@click="handleExportCoil(scope.row)">
发货
</el-button>
<el-button size="mini" v-if="showExportTime" type="text" icon="el-icon-close"
@click="handleCancelExport(scope.row)">
撤回发货
</el-button>
<el-button size="mini" v-if="showProductionTimeEdit" type="text" icon="el-icon-close"
@click="handleProductionTimeEdit(scope.row)">
加工修正
</el-button>
<el-button size="mini" v-if="showExportTime" type="text" icon="el-icon-sold-out"
@click="handleReturnCoil(scope.row)">
退货钢卷
</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleCheck(scope.row)"
v-if="showControl">修正</el-button>
<el-button size="mini" type="text" icon="el-icon-search" @click="handleTrace(scope.row)">追溯</el-button>
<el-button size="mini" v-if="showWaybill" type="text" icon="el-icon-close"
@click="handleRemoveFromWaybill(scope.row)">
移出发货单
</el-button>
<el-button v-if="showGrade" size="mini" type="text" icon="el-icon-edit" @click="handleJudge(scope.row)">
改判
</el-button>
<el-button size="mini" v-if="hasTransferType" type="text" icon="el-icon-close"
@click="handleReplaceLabel(scope.row)">
重贴标签
</el-button>
</template>
</el-table-column>
</KLPTable>
</div>
</div>
<div v-show="total > 0" style="display: flex; justify-content: flex-end; align-items: flex-end; gap: 10px;">
<span>
总净重{{ statistics.total_net_weight || 0 }}t
</span>
<pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
</div>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 添加或修改钢卷物料对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
@@ -474,7 +496,6 @@
@change="(value) => { productionTimeForm.productionEndTime = value; calculateProductionDuration(); }" />
</el-form-item>
<el-form-item label="生产耗时" prop="productionDuration">
<!-- <div>{{ productionTimeForm.formattedDuration }}</div> -->
<el-input v-model="productionTimeForm.formattedDuration" placeholder="自动计算" disabled />
</el-form-item>
</el-form>
@@ -493,6 +514,70 @@
<process-flow v-if="showProcessFlow" ref="processFlow"></process-flow>
</div>
</DragResizeBox>
<!-- 钢卷改判弹窗 -->
<el-dialog title="钢卷改判" :visible.sync="judgeDialogVisible" width="800px" append-to-body>
<el-descriptions :column="3" border>
<el-descriptions-item label="入场钢卷号">{{ judgeForm.enterCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="当前钢卷号">{{ judgeForm.currentCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="厂家原料卷号">{{ judgeForm.supplierCoilNo || '-' }}</el-descriptions-item>
<el-descriptions-item label="逻辑库位">{{ judgeForm.warehouseName || '-' }}</el-descriptions-item>
<el-descriptions-item label="实际库区">{{ judgeForm.actualWarehouseName || '-' }}</el-descriptions-item>
<el-descriptions-item label="班组">{{ judgeForm.team || '-' }}</el-descriptions-item>
<el-descriptions-item label="材料类型">{{ judgeForm.materialType || '-' }}</el-descriptions-item>
<el-descriptions-item label="产品/原料">{{ judgeForm.itemName || '-' }}</el-descriptions-item>
<el-descriptions-item label="规格">{{ judgeForm.specification || '-' }}</el-descriptions-item>
<el-descriptions-item label="材质">{{ judgeForm.material || '-' }}</el-descriptions-item>
<el-descriptions-item label="厂家">{{ judgeForm.manufacturer || '-' }}</el-descriptions-item>
<el-descriptions-item label="镀层质量">{{ judgeForm.zincLayer || '-' }}</el-descriptions-item>
<el-descriptions-item label="表面处理">{{ judgeForm.surfaceTreatmentDesc || '-'
}}</el-descriptions-item>
<el-descriptions-item label="质量状态">{{ judgeForm.qualityStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="切边要求">{{ judgeForm.trimmingRequirement || '-'
}}</el-descriptions-item>
<el-descriptions-item label="原料材质">{{ judgeForm.packingStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="包装要求">{{ judgeForm.packagingRequirement || '-'
}}</el-descriptions-item>
<el-descriptions-item label="实测厚度(m)">{{ judgeForm.actualThickness || '-' }}
m</el-descriptions-item>
<el-descriptions-item label="实测宽度(m)">{{ judgeForm.actualWidth || '-' }}
m</el-descriptions-item>
<el-descriptions-item label="长度">{{ judgeForm.length || '-' }}
m</el-descriptions-item>
<el-descriptions-item label="毛重">{{ judgeForm.grossWeight || '-' }} t</el-descriptions-item>
<el-descriptions-item label="净重">{{ judgeForm.netWeight || '-' }} t</el-descriptions-item>
<el-descriptions-item label="生产开始时间">{{ judgeForm.productionStartTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="生产结束时间">{{ judgeForm.productionEndTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="调制度">{{ judgeForm.temperGrade || '-' }}</el-descriptions-item>
<el-descriptions-item label="镀层种类">{{ judgeForm.coatingType || '-' }}</el-descriptions-item>
<el-descriptions-item label="钢卷表面处理">{{ judgeForm.coilSurfaceTreatment || '-' }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ judgeForm.remark || '-' }}</el-descriptions-item>
</el-descriptions>
<div style="margin-top: 20px; padding: 15px; background-color: #f5f7fa; border-radius: 4px;">
<el-form :model="judgeForm" label-width="120px">
<el-form-item label="修改质量状态">
<el-select v-model="judgeForm.qualityStatus" placeholder="请选择质量状态" style="width: 200px">
<el-option v-for="item in dict.type.coil_quality_status" :key="item.value" :value="item.value" :label="item.label" />
</el-select>
</el-form-item>
<el-form-item label="通知重贴标签">
<el-checkbox v-model="judgeForm.notifyReLabel">是否通知重贴标签</el-checkbox>
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="judgeDialogVisible = false">取消</el-button>
<el-button :loading="buttonLoading" type="primary" @click="submitJudgeForm">确认</el-button>
</div>
</el-dialog>
</div>
</template>
@@ -508,6 +593,7 @@ import {
cancelExportCoil,
checkCoilNo,
returnCoil,
getCoilStatisticsList
} from "@/api/wms/coil";
import { listBoundCoil } from "@/api/wms/deliveryWaybillDetail";
import { addPendingAction } from "@/api/wms/pendingAction";
@@ -537,6 +623,7 @@ import LogTable from "@/views/wms/warehouse/components/LogTable.vue";
import { getCoilTagPrintType } from '@/views/wms/coil/js/coilPrint';
import DragResizeBox from '@/components/DragResizeBox/index.vue';
import ProcessFlow from '../components/ProcessFlow.vue';
import WarehouseTree from '@/components/KLPService/WarehouseTree/index.vue';
import { listDeliveryWaybillDetail, delDeliveryWaybillDetail } from "@/api/wms/deliveryWaybillDetail";
export default {
@@ -560,6 +647,7 @@ export default {
LogTable,
ProcessFlow,
DragResizeBox,
WarehouseTree,
},
dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer', 'coil_quality_status', 'wms_next_warehouse', 'coil_business_purpose'],
props: {
@@ -657,6 +745,14 @@ export default {
type: Boolean,
default: false,
},
leftWarehouseQuery: {
type: Boolean,
default: false,
},
hasTransferType: {
type: Boolean,
default: false,
},
},
data() {
return {
@@ -753,27 +849,6 @@ export default {
],
currentCoilNo: [
{ required: true, message: "当前钢卷号不能为空", trigger: "blur" },
// 仅在新增的时候校验
// {
// validator: (rule, value, callback) => {
// // if (this.form.coilId) {
// // // 修改时会有coilId不触发校验
// // console.log('修改时会有coilId不触发校验');
// // callback();
// // } else {
// // 没有coilId则为新增 触发校验
// checkCoilNo({ currentCoilNo: value, coilId: this.form.coilId }).then(res => {
// const { duplicateType } = res.data;
// if (duplicateType === 'current' || duplicateType === 'both') {
// // alert('当前钢卷号重复,请重新输入');
// callback(new Error('当前钢卷号重复,请重新输入'));
// } else {
// callback();
// }
// })
// // }
// }, trigger: 'blur'
// }
],
itemId: [
{ required: true, message: "物品ID不能为空", trigger: "blur" }
@@ -812,11 +887,19 @@ export default {
{ label: '净重', prop: 'netWeight' },
{ label: '毛重', prop: 'grossWeight' },
{ label: '备注', prop: 'remark' },
{ label: '创建人', prop: 'createBy' },
{ label: '创建时间', prop: 'createTime' },
{ label: '更新人', prop: 'updateBy' },
{ label: '更新时间', prop: 'updateTime' },
{ label: '质量状态', prop: 'qualityStatus' },
{ label: '原料材质', prop: 'packingStatus' },
{ label: '切边要求', prop: 'edgeRequirement' },
{ label: '包装要求', prop: 'packagingRequirement' },
{ label: '厂家', prop: 'itemManufacturer' },
{ label: '物料名称', prop: 'itemName' },
{ label: '材质', prop: 'material' },
{ label: '规格', prop: 'specification' },
{ label: '镀层质量', prop: 'zincLayer' },
{ label: '厂家', prop: 'manufacturer' },
{ label: '调制度', prop: 'temperGrade' },
{ label: '镀层种类', prop: 'coatingType' },
{ label: '实测长度(m)', prop: 'actualLength' },
@@ -845,6 +928,23 @@ export default {
// 统计数据:已发货的数量和未发货的数量
shippedCount: 0,
unshippedCount: 0,
statistics: {},
// 钢卷改判弹窗
judgeDialogVisible: false,
judgeForm: {
coilId: undefined,
enterCoilNo: undefined,
currentCoilNo: undefined,
netWeight: undefined,
warehouseName: undefined,
actualWarehouseName: undefined,
qualityStatus: undefined,
itemName: undefined,
itemMaterial: undefined,
itemSpecification: undefined,
itemManufacturer: undefined,
notifyReLabel: false
},
};
},
computed: {
@@ -893,11 +993,16 @@ export default {
// 初始化时计算一次
this.calculateProductionDuration();
},
// 处理逻辑库位点击事件
handleWarehouseNodeClick(node) {
this.queryParams.warehouseId = node.warehouseId;
this.getList();
},
async handleRemoveFromWaybill(row) {
const coilId = row.coilId;
// 根据id查询所在的单据明细
const res = await listDeliveryWaybillDetail({ coilId });
if (res.rows.length != 1) {
this.$message({
message: '发货单查找失败',
@@ -911,17 +1016,30 @@ export default {
this.$modal.confirm('确认要将该钢卷从发货单中移除吗?', {
title: '确认移除',
type: 'warning',
}).then(() => {
delDeliveryWaybillDetail(detailId).then(res => {
this.$message({
message: '移除成功',
type: 'success',
});
this.getList();
}).then(() => {
delDeliveryWaybillDetail(detailId).then(res => {
this.$message({
message: '移除成功',
type: 'success',
});
this.getList();
});
})
// 打开一个弹窗列出查询到的所有单据明细
},
// 处理重贴标签
handleReplaceLabel(row) {
updateMaterialCoilSimple({
...row,
transferType: '',
}).then(res => {
this.$message({
message: '标签已重贴,记录移除',
type: 'success',
});
this.getList();
})
},
// 格式化毫秒值为xx天xx小时xx分钟
formatDuration(milliseconds) {
if (!milliseconds || milliseconds < 0) return '';
@@ -1086,6 +1204,9 @@ export default {
this.total = response.total;
this.loading = false;
});
getCoilStatisticsList(query).then(res => {
this.statistics = res.data || [];
})
},
/** 追溯按钮操作 */
handleTrace(row) {
@@ -1399,6 +1520,39 @@ export default {
this.buttonLoading = false;
});
},
/** 改判按钮操作 */
handleJudge(row) {
// 填充改判表单数据
this.judgeForm = {
...row,
notifyReLabel: true
};
this.judgeDialogVisible = true;
},
/** 提交改判表单 */
submitJudgeForm() {
this.buttonLoading = true;
const submitData = {
...this.judgeForm,
// 如果通知重贴标签,则设置 transferType 为技术部改判
transferType: this.judgeForm.notifyReLabel ? '技术部改判' : null
};
updateMaterialCoilSimple(submitData).then(res => {
this.buttonLoading = false;
this.$message({
message: '改判成功',
type: 'success'
});
this.judgeDialogVisible = false;
this.getList();
}).catch(err => {
this.buttonLoading = false;
this.$message({
message: '改判失败',
type: 'error'
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const coilIds = row.coilId || this.ids;
@@ -1625,4 +1779,8 @@ export default {
box-sizing: border-box;
overflow: hidden;
}
::v-deep .el-table {
margin-top: 0;
}
</style>

View File

@@ -33,6 +33,7 @@
<el-descriptions-item label="物料名称">{{ coilInfo.itemName || '-' }}</el-descriptions-item>
<el-descriptions-item label="规格">{{ coilInfo.specification || '-' }}</el-descriptions-item>
<el-descriptions-item label="材质">{{ coilInfo.material || '-' }}</el-descriptions-item>
<el-descriptions-item label="厂家">{{ coilInfo.manufacturer || '-' }}</el-descriptions-item>
<el-descriptions-item label="原料材质">{{ coilInfo.packingStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="实测长度(m)">{{ coilInfo.actualLength || '-' }}</el-descriptions-item>
<el-descriptions-item label="实测宽度(m)">{{ coilInfo.actualWidth || '-' }}</el-descriptions-item>
@@ -186,7 +187,8 @@
<MemoInput storageKey="coatingType" v-model="splitForm.coatingType" placeholder="请输入镀层种类" />
</el-form-item>
<el-form-item label="钢卷表面处理" prop="coilSurfaceTreatment">
<MemoInput storageKey="surfaceTreatmentDesc" v-model="splitForm.coilSurfaceTreatment" placeholder="请输入钢卷表面处理" />
<MemoInput storageKey="surfaceTreatmentDesc" v-model="splitForm.coilSurfaceTreatment"
placeholder="请输入钢卷表面处理" />
</el-form-item>
<el-form-item label="生产开始时间" prop="productionStartTime">
<TimeInput v-model="splitForm.productionStartTime" @input="calculateProductionDuration" />
@@ -202,6 +204,10 @@
<el-input v-model="splitForm.remark" placeholder="请输入备注" type="textarea" />
</el-form-item>
<el-form-item label="关联合同" prop="contractId">
<ContractSelect v-model="splitForm.contractId" placeholder="请选择合同" />
</el-form-item>
<el-form-item label="异常信息">
<div class="abnormal-container">
<div v-for="(abnormal, index) in abnormals" :key="index" class="abnormal-item"
@@ -270,7 +276,8 @@
<el-descriptions-item label="调制度">{{ selectedSplitItem.temperGrade || '-' }}</el-descriptions-item>
<el-descriptions-item label="镀层种类">{{ selectedSplitItem.coatingType || '-' }}</el-descriptions-item>
<el-descriptions-item label="钢卷表面处理">{{ selectedSplitItem.coilSurfaceTreatment || '-' }}</el-descriptions-item>
<el-descriptions-item label="钢卷表面处理">{{ selectedSplitItem.coilSurfaceTreatment || '-'
}}</el-descriptions-item>
<el-descriptions-item label="生产开始时间">{{ selectedSplitItem.productionStartTime || '-'
}}</el-descriptions-item>
<el-descriptions-item label="生产结束时间">{{ selectedSplitItem.productionEndTime || '-'
@@ -315,6 +322,8 @@ import AbnormalForm from '../components/AbnormalForm';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
export default {
name: 'StepSplit',
@@ -345,6 +354,7 @@ export default {
AbnormalForm,
ProductInfo,
RawMaterialInfo,
ContractSelect,
},
dicts: ['coil_quality_status', 'coil_abnormal_position', 'coil_abnormal_code', 'coil_abnormal_degree', 'coil_business_purpose'],
data() {
@@ -405,21 +415,6 @@ export default {
}
}, trigger: 'blur'
},
// 仅在新增的时候校验
// {
// validator: (rule, value, callback) => {
// // 没有coilId则为新增 触发校验
// checkCoilNo({ currentCoilNo: value, coilId: this.splitForm.coilId }).then(res => {
// const { duplicateType } = res.data;
// if (duplicateType === 'current' || duplicateType === 'both') {
// // alert('当前钢卷号重复,请重新输入');
// callback(new Error('当前钢卷号重复,请重新输入'));
// } else {
// callback();
// }
// })
// }, trigger: 'blur'
// }
],
materialType: [{ required: true, message: '请选择材料类型', trigger: 'change' }],
itemId: [{ required: true, message: '请选择成品/原料', trigger: 'change' }],
@@ -546,7 +541,6 @@ export default {
}
const action = await getPendingAction(this.actionId)
this.currentAction = action.data || {}
// this.$set(this.splitForm, 'productionStartTime', action.data.createTime)
const coilIds = action.data.remark;
console.log('coilIds', coilIds)
if (!coilIds) {
@@ -616,7 +610,7 @@ export default {
// 材料类型变更处理
handleMaterialTypeChange(val) {
// 清空物品选择
// 清空物品选择
this.splitForm.itemId = null;
// 根据材料类型设置物品类型
@@ -680,6 +674,13 @@ export default {
} else {
// 新增分条:调用创建接口
res = await createSpecialChild(this.coilId, this.actionId, splitData)
// 新增分条后,需要添加分条的合同关系
if (this.splitForm.contractId) {
addCoilContractRel({
coilId: res.data.coilId,
contractId: this.splitForm.contractId,
})
}
}
this.$message.success(this.splitForm.coilId ? '编辑分条成功' : '新增分条成功')

View File

@@ -6,6 +6,7 @@
:hideType="hideType"
:showLength="showLength"
:canExportAll="canExportAll"
:leftWarehouseQuery="true"
/>
</template>

View File

@@ -249,6 +249,11 @@
<el-form-item label="备注">
<el-input v-model="item.remark" placeholder="请输入备注" :disabled="readonly" />
</el-form-item>
<el-form-item label="关联合同" prop="contractId">
<ContractSelect v-model="item.contractId" placeholder="请选择合同" />
</el-form-item>
<el-form-item label="异常信息">
<div class="abnormal-container">
<div
@@ -316,6 +321,8 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import TimeInput from "@/components/TimeInput";
import AbnormalForm from './components/AbnormalForm';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import ContractSelect from "@/components/KLPService/ContractSelect";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
export default {
name: 'SplitCoil',
@@ -325,7 +332,8 @@ export default {
ProductSelect,
WarehouseSelect,
TimeInput,
AbnormalForm
AbnormalForm,
ContractSelect
},
dicts: ['coil_quality_status', 'coil_abnormal_position', 'coil_abnormal_code', 'coil_abnormal_degree', 'coil_business_purpose'],
data() {
@@ -674,6 +682,19 @@ export default {
if (response.code === 200) {
this.$message.success('分条保存成功');
// 拿到多个子卷的coilId
const newCoilIds = response.msg.split(',');
// 先构建所有的请求体,并移除合同为空为空的项
const requests = newCoilIds.map((coilId, index) => ({
coilId,
contractId: this.splitList[index].contractId
}))
.filter(req => req.contractId);
// 为每个子卷添加合同关联
Promise.all(requests.map(async (req, index) => {
addCoilContractRel(req);
}));
// 如果是从待操作列表进来的,标记操作为完成
if (this.actionId) {
await completeAction(this.actionId, response.msg);

View File

@@ -94,7 +94,7 @@
</div>
<div class="info-row">
<span class="info-label">逻辑库区</span>
<span class="info-value">{{ currentInfo.nextWarehouseName || '—' }}</span>
<span class="info-value">{{ currentInfo.warehouseName || '—' }}</span>
</div>
<div class="info-row" v-if="currentInfo.remark">
<span class="info-label">备注</span>
@@ -195,7 +195,7 @@
<el-form-item label="实测厚度(m)" prop="actualThickness" class="form-item-half">
<el-input-number :controls="false" v-model="updateForm.actualThickness" placeholder="请输入实测厚度"
type="number" :step="0.01" :disabled="readonly">
type="number" :step="0.01">
<template slot="append"></template>
</el-input-number>
</el-form-item>
@@ -251,6 +251,10 @@
show-word-limit />
</el-form-item>
<el-form-item label="关联合同" prop="contractId">
<ContractSelect v-model="updateForm.contractId" placeholder="请选择合同" />
</el-form-item>
<el-form-item label="异常信息">
<div class="abnormal-container">
<div
@@ -335,6 +339,8 @@ import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import TimeInput from "@/components/TimeInput";
import AbnormalForm from './components/AbnormalForm';
import { generateCoilNoPrefix } from "@/utils/coil/coilNo";
import { addCoilContractRel } from "@/api/wms/coilContractRel";
import ContractSelect from "@/components/KLPService/ContractSelect";
export default {
name: 'TypingCoil',
@@ -344,7 +350,8 @@ export default {
ProductSelect,
WarehouseSelect,
TimeInput,
AbnormalForm
AbnormalForm,
ContractSelect
},
dicts: ['coil_quality_status', 'coil_abnormal_position', 'coil_abnormal_code', 'coil_abnormal_degree', 'coil_business_purpose'],
data() {
@@ -365,7 +372,6 @@ export default {
netWeight: undefined,
warehouseId: null,
warehouseId: null,
nextWarehouseName: '',
status: 0,
remark: '',
length: undefined,
@@ -449,8 +455,6 @@ export default {
{ required: true, message: '请选择逻辑库区', trigger: 'change' }
],
},
warehouseList: [],
historySteps: [],
actionId: null,
acidPrefill: {
visible: false,
@@ -458,10 +462,6 @@ export default {
title: ''
},
isAcidRolling: false,
// 原材料和产品列表(实时搜索,不再保存完整备份)
rawMaterialList: [],
productList: [],
itemSearchLoading: false,
// 酸连轧最近记录
acidRecentRecords: [],
// 异常信息
@@ -480,7 +480,8 @@ export default {
defectCode: null,
degree: null,
remark: null
}
},
contractList: [],
};
},
computed: {
@@ -502,26 +503,8 @@ export default {
}
return '请先选择材料类型';
},
// 当前物品列表(根据物品类型动态切换)
currentItemList() {
if (this.updateForm.itemType === 'raw_material') {
return this.rawMaterialList.map(item => ({
id: item.rawMaterialId,
name: this.formatItemName(item)
}));
} else if (this.updateForm.itemType === 'product') {
return this.productList.map(item => ({
id: item.productId,
name: this.formatItemName(item)
}));
}
return [];
}
},
async created() {
// 先加载库区列表
await this.loadWarehouses();
// 从路由参数获取coilId和actionId
const coilId = this.$route.query.coilId;
const actionId = this.$route.query.actionId;
@@ -645,12 +628,9 @@ export default {
// 根据材料类型设置物品类型
if (value === '成品') {
this.$set(this.updateForm, 'itemType', 'product');
// 清空列表,等待用户搜索
this.productList = [];
} else if (value === '原料') {
this.$set(this.updateForm, 'itemType', 'raw_material');
// 清空列表,等待用户搜索
this.rawMaterialList = [];
}
},
@@ -675,8 +655,6 @@ export default {
// 填充当前信息(左侧)
this.currentInfo = {
...data,
itemName: this.getItemName(data),
nextWarehouseName: this.getWarehouseName(data.warehouseId),
};
// 填充时间相关字段
@@ -698,14 +676,6 @@ export default {
}
},
// 获取物料名称
getItemName(data) {
if (data.itemName) {
return data.itemName;
}
return '';
},
// 获取物品类型文本
getItemTypeText(itemType) {
if (itemType === 'raw_material') return '原材料';
@@ -713,13 +683,6 @@ export default {
return '—';
},
// 获取库区名称
getWarehouseName(warehouseId) {
if (!warehouseId) return '';
const warehouse = this.warehouseList.find(w => w.warehouseId === warehouseId);
return warehouse ? warehouse.warehouseName : '';
},
// 格式化物品名称(添加规格和参数信息)
formatItemName(item) {
if (!item) return '';
@@ -754,41 +717,7 @@ export default {
return displayName;
},
// 加载库区列表
async loadWarehouses() {
try {
const response = await listWarehouse({ pageNum: 1, pageSize: 1000 });
if (response.code === 200) {
this.warehouseList = response.rows || response.data || [];
}
} catch (error) {
console.error('加载库区列表失败', error);
}
},
// 加载变更历史
async loadHistory() {
if (!this.currentInfo.enterCoilNo) {
return;
}
try {
this.historyLoading = true;
const response = await getMaterialCoilTrace({
enterCoilNo: this.currentInfo.enterCoilNo,
currentCoilNo: this.currentInfo.currentCoilNo || undefined
});
if (response.code === 200 && response.data) {
this.historySteps = response.data.steps || [];
}
} catch (error) {
console.error('加载变更历史失败', error);
} finally {
this.historyLoading = false;
}
},
// 复制当前信息到更新表单
copyFromCurrent() {
@@ -872,6 +801,15 @@ export default {
const response = await updateMaterialCoil(updateData);
// 更新完成后如果选定了合同,需要增加与合同的绑定关系
const coilId = response.msg;
if (this.updateForm.contractId) {
await addCoilContractRel({
coilId: coilId,
contractId: this.updateForm.contractId,
});
}
if (response.code === 200) {
this.$message.success('钢卷信息更新成功');
@@ -880,6 +818,8 @@ export default {
await completeAction(this.actionId, response.msg);
}
// 延迟返回
setTimeout(() => {
this.$router.back();

View File

@@ -0,0 +1,27 @@
<template>
<BasePage :qrcode="qrcode" :querys="querys" :hideWarehouseQuery="hideWarehouseQuery"
:hideType="hideType" :showControl="showControl" :hasTransferType="hasTransferType" />
</template>
<script>
import BasePage from '../../panels/base.vue';
export default {
components: {
BasePage
},
data() {
return {
qrcode: false,
querys: {
hasTransferType: true,
// dataType: 1,
},
hideWarehouseQuery: true,
hasTransferType: true,
showControl: false,
hideType: false,
}
}
}
</script>

View File

@@ -25,8 +25,8 @@
</el-form-item>
<el-form-item label="生效状态">
<el-select v-model="queryParams.isTransferred" @change="handleRegularSearch">
<el-option :label="1">已生效</el-option>
<el-option :label="0">未生效</el-option>
<el-option value="1" label="已生效"></el-option>
<el-option value="0" label="未生效"></el-option>
</el-select>
</el-form-item>
<el-form-item>

View File

@@ -118,7 +118,7 @@ export default {
list: [],
queryParams: {
pageNum: 1,
pageSize: 9999,
pageSize: 99999,
status: 1,
dataType: 1,
byExportTimeStart: startTime,
@@ -170,7 +170,7 @@ export default {
}).then(res => {
this.list = res.rows.map(item => {
// 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
const [thickness, width] = item.specification.split('*')
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),

View File

@@ -256,7 +256,7 @@ export default {
]);
this.lossList = lossRes.rows.map(item => {
// 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
const [thickness, width] = item.specification.split('*')
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),

View File

@@ -186,7 +186,7 @@ export default {
// actionStatus: 2,
warehouseId: this.queryParams.planId,
actionType: 401,
pageSize: 9999,
pageSize: 99999,
pageNum: 1,
startTime: this.queryParams.byCreateTimeStart,
endTime: this.queryParams.byCreateTimeEnd,
@@ -209,7 +209,7 @@ export default {
}).then(res => {
this.list = res.rows.map(item => {
// 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
const [thickness, width] = item.specification.split('*')
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),

View File

@@ -26,10 +26,10 @@
<!-- 自定义日期选择器 -->
<span v-if="viewType === 'custom'" style="margin-left: 10px;">
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeStart"
type="date" value-format="yyyy-MM-dd" placeholder="选择开始日期"></el-date-picker>
type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择开始日期"></el-date-picker>
<el-date-picker style="width: 200px;" v-model="queryParams.byCreateTimeEnd"
type="date" value-format="yyyy-MM-dd" placeholder="选择结束日期"></el-date-picker>
type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择结束日期"></el-date-picker>
</span>
</div>
<el-row>

View File

@@ -267,7 +267,7 @@ export default {
});
this.outList = outRes.rows.map(item => {
// 计算宽度和厚度,将规格按照*分割,*前的是厚度,*后的是宽度
const [thickness, width] = item.specification.split('*')
const [thickness, width] = item.specification?.split('*') || []
return {
...item,
computedThickness: parseFloat(thickness),

View File

@@ -0,0 +1,99 @@
package com.klp.controller;
import java.util.List;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.domain.vo.WmsAnnealOperateEventVo;
import com.klp.domain.bo.WmsAnnealOperateEventBo;
import com.klp.service.IWmsAnnealOperateEventService;
import com.klp.common.core.page.TableDataInfo;
/**
* 退火操作事件
*
* @author klp
* @date 2026-04-16
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/annealOperateEvent")
public class WmsAnnealOperateEventController extends BaseController {
private final IWmsAnnealOperateEventService iWmsAnnealOperateEventService;
/**
* 查询退火操作事件列表
*/
@GetMapping("/list")
public TableDataInfo<WmsAnnealOperateEventVo> list(WmsAnnealOperateEventBo bo, PageQuery pageQuery) {
return iWmsAnnealOperateEventService.queryPageList(bo, pageQuery);
}
/**
* 导出退火操作事件列表
*/
@Log(title = "退火操作事件", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WmsAnnealOperateEventBo bo, HttpServletResponse response) {
List<WmsAnnealOperateEventVo> list = iWmsAnnealOperateEventService.queryList(bo);
ExcelUtil.exportExcel(list, "退火操作事件", WmsAnnealOperateEventVo.class, response);
}
/**
* 获取退火操作事件详细信息
*
* @param eventId 主键
*/
@GetMapping("/{eventId}")
public R<WmsAnnealOperateEventVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long eventId) {
return R.ok(iWmsAnnealOperateEventService.queryById(eventId));
}
/**
* 新增退火操作事件
*/
@Log(title = "退火操作事件", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsAnnealOperateEventBo bo) {
return toAjax(iWmsAnnealOperateEventService.insertByBo(bo));
}
/**
* 修改退火操作事件
*/
@Log(title = "退火操作事件", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsAnnealOperateEventBo bo) {
return toAjax(iWmsAnnealOperateEventService.updateByBo(bo));
}
/**
* 删除退火操作事件
*
* @param eventIds 主键串
*/
@Log(title = "退火操作事件", businessType = BusinessType.DELETE)
@DeleteMapping("/{eventIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] eventIds) {
return toAjax(iWmsAnnealOperateEventService.deleteWithValidByIds(Arrays.asList(eventIds), true));
}
}

View File

@@ -0,0 +1,99 @@
package com.klp.controller;
import java.util.List;
import java.util.Arrays;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.klp.common.annotation.RepeatSubmit;
import com.klp.common.annotation.Log;
import com.klp.common.core.controller.BaseController;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.domain.R;
import com.klp.common.core.validate.AddGroup;
import com.klp.common.core.validate.EditGroup;
import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil;
import com.klp.domain.vo.WmsCoilContractRelVo;
import com.klp.domain.bo.WmsCoilContractRelBo;
import com.klp.service.IWmsCoilContractRelService;
import com.klp.common.core.page.TableDataInfo;
/**
* 钢卷与合同关联关系
*
* @author klp
* @date 2026-04-18
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wms/coilContractRel")
public class WmsCoilContractRelController extends BaseController {
private final IWmsCoilContractRelService iWmsCoilContractRelService;
/**
* 查询钢卷与合同关联关系列表
*/
@GetMapping("/list")
public TableDataInfo<WmsCoilContractRelVo> list(WmsCoilContractRelBo bo, PageQuery pageQuery) {
return iWmsCoilContractRelService.queryPageList(bo, pageQuery);
}
/**
* 导出钢卷与合同关联关系列表
*/
@Log(title = "钢卷与合同关联关系", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WmsCoilContractRelBo bo, HttpServletResponse response) {
List<WmsCoilContractRelVo> list = iWmsCoilContractRelService.queryList(bo);
ExcelUtil.exportExcel(list, "钢卷与合同关联关系", WmsCoilContractRelVo.class, response);
}
/**
* 获取钢卷与合同关联关系详细信息
*
* @param relId 主键
*/
@GetMapping("/{relId}")
public R<WmsCoilContractRelVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long relId) {
return R.ok(iWmsCoilContractRelService.queryById(relId));
}
/**
* 新增钢卷与合同关联关系
*/
@Log(title = "钢卷与合同关联关系", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WmsCoilContractRelBo bo) {
return toAjax(iWmsCoilContractRelService.insertByBo(bo));
}
/**
* 修改钢卷与合同关联关系
*/
@Log(title = "钢卷与合同关联关系", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WmsCoilContractRelBo bo) {
return toAjax(iWmsCoilContractRelService.updateByBo(bo));
}
/**
* 删除钢卷与合同关联关系
*
* @param relIds 主键串
*/
@Log(title = "钢卷与合同关联关系", businessType = BusinessType.DELETE)
@DeleteMapping("/{relIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] relIds) {
return toAjax(iWmsCoilContractRelService.deleteWithValidByIds(Arrays.asList(relIds), true));
}
}

View File

@@ -68,6 +68,16 @@ public class WmsMaterialCoilController extends BaseController {
return iWmsMaterialCoilService.queryPageListWithBindInfo(bo, pageQuery);
}
/**
* 查询钢卷物料表列表(包含订单关联信息)
* 前端调用此接口时每个钢卷会携带其关联的订单列表通过wms_coil_contract_rel中间表JOIN crm_order
* 注意此接口比普通list多一次联表查询仅在需要查看订单关联时使用
*/
@GetMapping("/listWithOrderRel")
public TableDataInfo<WmsMaterialCoilVo> listWithOrderRel(WmsMaterialCoilBo bo, PageQuery pageQuery) {
return iWmsMaterialCoilService.queryPageListWithOrderRel(bo, pageQuery);
}
/**
* 统计筛选条件下的全量汇总数据
* 独立的统计接口,使用与分页列表相同的查询条件
@@ -234,7 +244,7 @@ public class WmsMaterialCoilController extends BaseController {
@RepeatSubmit()
@PutMapping()
public R<String> edit(@Validated(EditGroup.class) @RequestBody WmsMaterialCoilBo bo) {
return R.ok(iWmsMaterialCoilService.updateByBo(bo));
return R.ok(iWmsMaterialCoilService.updateByBo(bo, null));
}
/**
@@ -246,8 +256,8 @@ public class WmsMaterialCoilController extends BaseController {
@Log(title = "钢卷物料表-合卷", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/merge")
public R<Void> mergeCoils(@Validated(EditGroup.class) @RequestBody WmsMaterialCoilBo bo) {
return toAjax(iWmsMaterialCoilService.mergeCoils(bo));
public R<Long> mergeCoils(@Validated(EditGroup.class) @RequestBody WmsMaterialCoilBo bo) {
return R.ok(iWmsMaterialCoilService.mergeCoils(bo));
}
/**

View File

@@ -0,0 +1,53 @@
package com.klp.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 退火操作事件对象 wms_anneal_operate_event
*
* @author klp
* @date 2026-04-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_anneal_operate_event")
public class WmsAnnealOperateEvent extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "event_id")
private Long eventId;
/**
* 退火炉ID
*/
private Long annealFurnaceId;
/**
* 操作类型 如:START/PAUSE/STOP/FEED/TAKE/RESET
*/
private String operateType;
/**
* 操作内容描述
*/
private String operateContent;
/**
* 钢卷ID(可选)
*/
private Long coilId;
/**
* 删除标志0=正常,1=已删除)
*/
@TableLogic
private Integer delFlag;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,45 @@
package com.klp.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 钢卷与合同关联关系对象 wms_coil_contract_rel
*
* @author klp
* @date 2026-04-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wms_coil_contract_rel")
public class WmsCoilContractRel extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* 主键ID
*/
@TableId(value = "rel_id")
private Long relId;
/**
* 钢卷ID
*/
private Long coilId;
/**
* 合同ID
*/
private Long contractId;
/**
* 备注
*/
private String remark;
/**
* 删除标识 0正常 2删除
*/
@TableLogic
private Long delFlag;
}

View File

@@ -40,6 +40,10 @@ public class WmsWarehouse extends TreeEntity<WmsWarehouse> {
* 同级排序号
*/
private Long sortNo;
/**
* 使用次数(用于排序:使用越多越靠前)
*/
private Integer useCount;
/**
* 是否启用0=否1=是)
*/

View File

@@ -0,0 +1,51 @@
package com.klp.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
/**
* 退火操作事件业务对象 wms_anneal_operate_event
*
* @author klp
* @date 2026-04-16
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsAnnealOperateEventBo extends BaseEntity {
/**
* 主键ID
*/
private Long eventId;
/**
* 退火炉ID
*/
private Long annealFurnaceId;
/**
* 操作类型 如:START/PAUSE/STOP/FEED/TAKE/RESET
*/
private String operateType;
/**
* 操作内容描述
*/
private String operateContent;
/**
* 钢卷ID(可选)
*/
private Long coilId;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,41 @@
package com.klp.domain.bo;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.*;
/**
* 钢卷与合同关联关系业务对象 wms_coil_contract_rel
*
* @author klp
* @date 2026-04-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class WmsCoilContractRelBo extends BaseEntity {
/**
* 主键ID
*/
private Long relId;
/**
* 钢卷ID
*/
private Long coilId;
/**
* 合同ID
*/
private Long contractId;
/**
* 备注
*/
private String remark;
}

View File

@@ -354,5 +354,11 @@ public class WmsMaterialCoilBo extends BaseEntity {
//根据逗号分割的创建人筛选
private String createBys;
/**
* 是否查询调拨类型不为空的钢卷
*/
@TableField(exist = false)
private Boolean hasTransferType;
}

View File

@@ -47,6 +47,11 @@ public class WmsWarehouseBo extends TreeEntity<WmsWarehouseBo> {
*/
private Long sortNo;
/**
* 使用次数(用于排序:使用越多越靠前)
*/
private Integer useCount;
/**
* 是否启用0=否1=是)
*/
@@ -57,5 +62,10 @@ public class WmsWarehouseBo extends TreeEntity<WmsWarehouseBo> {
*/
private String remark;
/**
* 是否按使用次数排序true=按useCount降序false或不传=按sortNo升序
*/
private Boolean orderByUseCount;
}

View File

@@ -0,0 +1,60 @@
package com.klp.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.klp.common.annotation.ExcelDictFormat;
import com.klp.common.convert.ExcelDictConvert;
import com.klp.common.core.domain.BaseEntity;
import lombok.Data;
/**
* 退火操作事件视图对象 wms_anneal_operate_event
*
* @author klp
* @date 2026-04-16
*/
@Data
@ExcelIgnoreUnannotated
public class WmsAnnealOperateEventVo extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long eventId;
/**
* 退火炉ID
*/
@ExcelProperty(value = "退火炉ID")
private Long annealFurnaceId;
/**
* 操作类型 如:START/PAUSE/STOP/FEED/TAKE/RESET
*/
@ExcelProperty(value = "操作类型 如:START/PAUSE/STOP/FEED/TAKE/RESET")
private String operateType;
/**
* 操作内容描述
*/
@ExcelProperty(value = "操作内容描述")
private String operateContent;
/**
* 钢卷ID(可选)
*/
@ExcelProperty(value = "钢卷ID(可选)")
private Long coilId;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,138 @@
package com.klp.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 钢卷与合同(订单)关联关系视图对象 wms_coil_contract_rel + crm_order JOIN
*
* @author klp
* @date 2026-04-18
*/
@Data
@ExcelIgnoreUnannotated
public class WmsCoilContractRelVo {
private static final long serialVersionUID = 1L;
// ========== 中间表自身字段 ==========
/** 主键ID */
private Long relId;
/** 钢卷ID */
@ExcelProperty(value = "钢卷ID")
private Long coilId;
/** 合同/订单ID */
@ExcelProperty(value = "合同/订单ID")
private Long contractId;
/** 备注 */
@ExcelProperty(value = "备注")
private String remark;
// ========== 关联订单信息JOIN crm_order==========
/** 订单ID主键 */
private Long orderId;
/** 订单编号 */
private String orderCode;
/** 订单类型pre-预订单formal-正式订单 */
private Long orderType;
/** 关联客户ID */
private String customerId;
/** 订单总金额 */
private BigDecimal orderAmount;
/** 销售员 */
private String salesman;
/** 交货日期 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date deliveryDate;
/** 预订单状态 */
private Long preOrderStatus;
/** 审核人 */
private String auditUser;
/** 审核时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;
/** 订单状态 */
private Long orderStatus;
/** 财务状态 */
private Long financeStatus;
/** 未结款数额 */
private BigDecimal unpaidAmount;
/** 备注 */
private String orderRemark;
/** 合同号 */
private String contractCode;
/** 合同名称 */
private String contractName;
/** 供方 */
private String supplier;
/** 需方 */
private String customer;
/** 签订时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date signTime;
/** 签订地点 */
private String signLocation;
/** 产品内容 */
private String productContent;
/** 合同内容 */
private String contractContent;
/** 供方地址 */
private String supplierAddress;
/** 供方电话 */
private String supplierPhone;
/** 供方开户行 */
private String supplierBank;
/** 供方账号 */
private String supplierAccount;
/** 供方税号 */
private String supplierTaxNo;
/** 需方地址 */
private String customerAddress;
/** 需方电话 */
private String customerPhone;
/** 需方开户行 */
private String customerBank;
/** 需方账号 */
private String customerAccount;
/** 需方税号 */
private String customerTaxNo;
/** 技术附件 */
private String techAnnex;
/** 商务附件 */
private String businessAnnex;
/** 排产函 */
private String productionSchedule;
/** 算单价备注 */
private String unitPriceRemark;
/** 应付定金(万元) */
private BigDecimal depositPayable;
/** 已付定金(万元) */
private BigDecimal depositPaid;
/** 定金比例(% */
private BigDecimal depositRatio;
/** 合同状态 0=草稿 1=生效 2=作废 3=已完成 */
private Long status;
/** 关联合同ID */
private Long orderIdInOrder; // crm_order.contract_id与contractId可能不同
/** 附件 */
private String annexFiles;
/** 创建人 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新人 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}

View File

@@ -329,5 +329,10 @@ public class WmsMaterialCoilVo extends BaseEntity {
* 调拨类型
*/
private String transferType;
/**
* 关联的订单列表通过wms_coil_contract_rel中间表JOIN crm_order
*/
private List<com.klp.domain.vo.WmsCoilContractRelVo> orderList;
}

View File

@@ -56,6 +56,12 @@ public class WmsWarehouseVo {
@ExcelProperty(value = "同级排序号")
private Long sortNo;
/**
* 使用次数(用于排序:使用越多越靠前)
*/
@ExcelProperty(value = "使用次数")
private Integer useCount;
/**
* 是否启用0=否1=是)
*/

View File

@@ -0,0 +1,15 @@
package com.klp.mapper;
import com.klp.domain.WmsAnnealOperateEvent;
import com.klp.domain.vo.WmsAnnealOperateEventVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 退火操作事件Mapper接口
*
* @author klp
* @date 2026-04-16
*/
public interface WmsAnnealOperateEventMapper extends BaseMapperPlus<WmsAnnealOperateEventMapper, WmsAnnealOperateEvent, WmsAnnealOperateEventVo> {
}

View File

@@ -0,0 +1,27 @@
package com.klp.mapper;
import com.klp.domain.WmsCoilContractRel;
import com.klp.domain.vo.WmsCoilContractRelVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 钢卷与合同关联关系Mapper接口
*
* @author klp
* @date 2026-04-18
*/
public interface WmsCoilContractRelMapper extends BaseMapperPlus<WmsCoilContractRelMapper, WmsCoilContractRel, WmsCoilContractRelVo> {
/**
* 根据钢卷ID查询关联的订单完整信息JOIN crm_order表
*/
List<WmsCoilContractRelVo> selectOrdersByCoilId(@Param("coilId") Long coilId);
/**
* 批量根据钢卷ID列表查询关联的订单完整信息
*/
List<WmsCoilContractRelVo> selectOrdersByCoilIds(@Param("coilIds") List<Long> coilIds);
}

View File

@@ -104,5 +104,13 @@ List<WmsMaterialCoilDeliveryExportVo> selectDeliveryExportListByCoilIds(@Param("
* @return 统计结果Map包含totalGrossWeight, totalNetWeight
*/
Map<String, Object> selectStatistics(@Param("ew") QueryWrapper<WmsMaterialCoil> qw);
/**
* 统计仓库使用次数按warehouse_id出现次数排序
*
* @param warehouseIds 仓库ID列表
* @return 每个仓库的钢卷数量
*/
List<Map<String, Object>> selectWarehouseIdCount(@Param("list") List<Long> warehouseIds);
}

View File

@@ -0,0 +1,49 @@
package com.klp.service;
import com.klp.domain.WmsAnnealOperateEvent;
import com.klp.domain.vo.WmsAnnealOperateEventVo;
import com.klp.domain.bo.WmsAnnealOperateEventBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 退火操作事件Service接口
*
* @author klp
* @date 2026-04-16
*/
public interface IWmsAnnealOperateEventService {
/**
* 查询退火操作事件
*/
WmsAnnealOperateEventVo queryById(Long eventId);
/**
* 查询退火操作事件列表
*/
TableDataInfo<WmsAnnealOperateEventVo> queryPageList(WmsAnnealOperateEventBo bo, PageQuery pageQuery);
/**
* 查询退火操作事件列表
*/
List<WmsAnnealOperateEventVo> queryList(WmsAnnealOperateEventBo bo);
/**
* 新增退火操作事件
*/
Boolean insertByBo(WmsAnnealOperateEventBo bo);
/**
* 修改退火操作事件
*/
Boolean updateByBo(WmsAnnealOperateEventBo bo);
/**
* 校验并批量删除退火操作事件信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -0,0 +1,49 @@
package com.klp.service;
import com.klp.domain.WmsCoilContractRel;
import com.klp.domain.vo.WmsCoilContractRelVo;
import com.klp.domain.bo.WmsCoilContractRelBo;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 钢卷与合同关联关系Service接口
*
* @author klp
* @date 2026-04-18
*/
public interface IWmsCoilContractRelService {
/**
* 查询钢卷与合同关联关系
*/
WmsCoilContractRelVo queryById(Long relId);
/**
* 查询钢卷与合同关联关系列表
*/
TableDataInfo<WmsCoilContractRelVo> queryPageList(WmsCoilContractRelBo bo, PageQuery pageQuery);
/**
* 查询钢卷与合同关联关系列表
*/
List<WmsCoilContractRelVo> queryList(WmsCoilContractRelBo bo);
/**
* 新增钢卷与合同关联关系
*/
Boolean insertByBo(WmsCoilContractRelBo bo);
/**
* 修改钢卷与合同关联关系
*/
Boolean updateByBo(WmsCoilContractRelBo bo);
/**
* 校验并批量删除钢卷与合同关联关系信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

View File

@@ -37,6 +37,12 @@ public interface IWmsMaterialCoilService {
*/
TableDataInfo<WmsMaterialCoilBindVo> queryPageListWithBindInfo(WmsMaterialCoilBo bo, PageQuery pageQuery);
/**
* 查询钢卷物料表列表(包含订单关联信息)
* 前端传 includeOrderRel=true 时返回每个钢卷关联的订单列表
*/
TableDataInfo<WmsMaterialCoilVo> queryPageListWithOrderRel(WmsMaterialCoilBo bo, PageQuery pageQuery);
/**
* 查询钢卷物料表列表
*/
@@ -59,7 +65,7 @@ public interface IWmsMaterialCoilService {
* 如果newCoils为空则进行单个更新
* @return 单个更新或合卷时返回新钢卷ID分卷时返回逗号分隔的新钢卷ID字符串
*/
String updateByBo(WmsMaterialCoilBo bo);
String updateByBo(WmsMaterialCoilBo bo, String qrcodeStepType);
/**
* 合卷操作
@@ -67,7 +73,7 @@ public interface IWmsMaterialCoilService {
* 如果传递了actionId则更新操作记录状态为已完成并设置完成时间和合卷后的钢卷ID到processedCoilIds
* 如果未传actionId则创建新的操作记录
*/
Boolean mergeCoils(WmsMaterialCoilBo bo);
Long mergeCoils(WmsMaterialCoilBo bo);
/**
* 简单更新钢卷物料表

View File

@@ -0,0 +1,112 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.domain.bo.WmsAnnealOperateEventBo;
import com.klp.domain.vo.WmsAnnealOperateEventVo;
import com.klp.domain.WmsAnnealOperateEvent;
import com.klp.mapper.WmsAnnealOperateEventMapper;
import com.klp.service.IWmsAnnealOperateEventService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 退火操作事件Service业务层处理
*
* @author klp
* @date 2026-04-16
*/
@RequiredArgsConstructor
@Service
public class WmsAnnealOperateEventServiceImpl implements IWmsAnnealOperateEventService {
private final WmsAnnealOperateEventMapper baseMapper;
/**
* 查询退火操作事件
*/
@Override
public WmsAnnealOperateEventVo queryById(Long eventId){
return baseMapper.selectVoById(eventId);
}
/**
* 查询退火操作事件列表
*/
@Override
public TableDataInfo<WmsAnnealOperateEventVo> queryPageList(WmsAnnealOperateEventBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsAnnealOperateEvent> lqw = buildQueryWrapper(bo);
Page<WmsAnnealOperateEventVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询退火操作事件列表
*/
@Override
public List<WmsAnnealOperateEventVo> queryList(WmsAnnealOperateEventBo bo) {
LambdaQueryWrapper<WmsAnnealOperateEvent> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsAnnealOperateEvent> buildQueryWrapper(WmsAnnealOperateEventBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsAnnealOperateEvent> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getAnnealFurnaceId() != null, WmsAnnealOperateEvent::getAnnealFurnaceId, bo.getAnnealFurnaceId());
lqw.eq(StringUtils.isNotBlank(bo.getOperateType()), WmsAnnealOperateEvent::getOperateType, bo.getOperateType());
lqw.eq(StringUtils.isNotBlank(bo.getOperateContent()), WmsAnnealOperateEvent::getOperateContent, bo.getOperateContent());
lqw.eq(bo.getCoilId() != null, WmsAnnealOperateEvent::getCoilId, bo.getCoilId());
return lqw;
}
/**
* 新增退火操作事件
*/
@Override
public Boolean insertByBo(WmsAnnealOperateEventBo bo) {
WmsAnnealOperateEvent add = BeanUtil.toBean(bo, WmsAnnealOperateEvent.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setEventId(add.getEventId());
}
return flag;
}
/**
* 修改退火操作事件
*/
@Override
public Boolean updateByBo(WmsAnnealOperateEventBo bo) {
WmsAnnealOperateEvent update = BeanUtil.toBean(bo, WmsAnnealOperateEvent.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsAnnealOperateEvent entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除退火操作事件
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -0,0 +1,109 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.klp.domain.bo.WmsCoilContractRelBo;
import com.klp.domain.vo.WmsCoilContractRelVo;
import com.klp.domain.WmsCoilContractRel;
import com.klp.mapper.WmsCoilContractRelMapper;
import com.klp.service.IWmsCoilContractRelService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 钢卷与合同关联关系Service业务层处理
*
* @author klp
* @date 2026-04-18
*/
@RequiredArgsConstructor
@Service
public class WmsCoilContractRelServiceImpl implements IWmsCoilContractRelService {
private final WmsCoilContractRelMapper baseMapper;
/**
* 查询钢卷与合同关联关系
*/
@Override
public WmsCoilContractRelVo queryById(Long relId){
return baseMapper.selectVoById(relId);
}
/**
* 查询钢卷与合同关联关系列表
*/
@Override
public TableDataInfo<WmsCoilContractRelVo> queryPageList(WmsCoilContractRelBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsCoilContractRel> lqw = buildQueryWrapper(bo);
Page<WmsCoilContractRelVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询钢卷与合同关联关系列表
*/
@Override
public List<WmsCoilContractRelVo> queryList(WmsCoilContractRelBo bo) {
LambdaQueryWrapper<WmsCoilContractRel> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<WmsCoilContractRel> buildQueryWrapper(WmsCoilContractRelBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsCoilContractRel> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getCoilId() != null, WmsCoilContractRel::getCoilId, bo.getCoilId());
lqw.eq(bo.getContractId() != null, WmsCoilContractRel::getContractId, bo.getContractId());
return lqw;
}
/**
* 新增钢卷与合同关联关系
*/
@Override
public Boolean insertByBo(WmsCoilContractRelBo bo) {
WmsCoilContractRel add = BeanUtil.toBean(bo, WmsCoilContractRel.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setRelId(add.getRelId());
}
return flag;
}
/**
* 修改钢卷与合同关联关系
*/
@Override
public Boolean updateByBo(WmsCoilContractRelBo bo) {
WmsCoilContractRel update = BeanUtil.toBean(bo, WmsCoilContractRel.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(WmsCoilContractRel entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 批量删除钢卷与合同关联关系
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

View File

@@ -7,15 +7,19 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.common.core.domain.PageQuery;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.exception.ServiceException;
import com.klp.common.helper.LoginHelper;
import com.klp.common.utils.StringUtils;
import com.klp.domain.*;
import com.klp.domain.bo.WmsFurnacePlanBo;
import com.klp.domain.bo.WmsFurnacePlanCoilBo;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.vo.WmsFurnacePlanCoilVo;
import com.klp.domain.vo.WmsFurnacePlanVo;
import com.klp.mapper.*;
import com.klp.service.IWmsFurnacePlanService;
import com.klp.service.IWmsMaterialCoilService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -41,6 +45,7 @@ public class WmsFurnacePlanServiceImpl implements IWmsFurnacePlanService {
private final WmsMaterialCoilMapper materialCoilMapper;
private final WmsActualWarehouseMapper actualWarehouseMapper;
private final WmsWarehouseMapper warehouseMapper;
private final IWmsMaterialCoilService materialCoilService;
@Override
public WmsFurnacePlanVo queryById(Long planId) {
@@ -321,15 +326,51 @@ public class WmsFurnacePlanServiceImpl implements IWmsFurnacePlanService {
throw new ServiceException("请先分配逻辑库位");
}
java.util.Map<Long, Long> locationMap = locations.stream()
.collect(Collectors.toMap(com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getCoilId,
.collect(java.util.stream.Collectors.toMap(com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getCoilId,
com.klp.domain.bo.WmsFurnacePlanLocationItemBo::getWarehouseId, (a, b) -> a));
for (WmsFurnacePlanCoilVo coil : coils) {
Long targetLocation = locationMap.get(coil.getCoilId());
if (targetLocation == null) {
throw new ServiceException("钢卷" + coil.getEnterCoilNo() + "未分配库位");
}
occupyWarehouse(planId, coil.getCoilId(), targetLocation);
WmsMaterialCoil oldCoil = materialCoilMapper.selectById(coil.getCoilId());
if (oldCoil == null) {
throw new ServiceException("钢卷不存在: " + coil.getCoilId());
}
WmsMaterialCoilBo updateBo = new WmsMaterialCoilBo();
// 复制老钢卷的所有信息
BeanUtils.copyProperties(oldCoil, updateBo);
// 只覆盖需要修改的字段
updateBo.setCoilId(coil.getCoilId());
updateBo.setWarehouseId(targetLocation);
updateBo.setActualWarehouseId(-1L);
updateBo.setCreateTime(new Date());
updateBo.setUpdateTime(new Date());
updateBo.setExclusiveStatus(0);
updateBo.setCreateBy(LoginHelper.getUsername());
updateBo.setUpdateBy(LoginHelper.getUsername());
updateBo.setNextWarehouseId(null);
updateBo.setStatus(0);
updateBo.setExportBy(null);
updateBo.setExportTime(null);
materialCoilService.updateByBo(updateBo, "annealing");
WmsFurnacePlanCoil wmsFurnacePlanCoil = planCoilMapper.selectOne(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId)
.eq(WmsFurnacePlanCoil::getCoilId, coil.getCoilId())
.eq(WmsFurnacePlanCoil::getDelFlag, 0));
if (wmsFurnacePlanCoil != null && wmsFurnacePlanCoil.getPlanCoilId() != null) {
planCoilMapper.update(null, Wrappers.<WmsFurnacePlanCoil>lambdaUpdate()
.eq(WmsFurnacePlanCoil::getPlanCoilId, wmsFurnacePlanCoil.getPlanCoilId())
.set(WmsFurnacePlanCoil::getLogicWarehouseId, targetLocation));
}
}
Date now = new Date();
WmsFurnacePlan update = new WmsFurnacePlan();
update.setPlanId(planId);
@@ -358,34 +399,6 @@ public class WmsFurnacePlanServiceImpl implements IWmsFurnacePlanService {
.set(WmsMaterialCoil::getExclusiveStatus, 2));
}
private void occupyWarehouse(Long planId, Long coilId, Long warehouseId) {
if (warehouseId == null) {
throw new ServiceException("逻辑库位不能为空");
}
WmsWarehouse warehouse = warehouseMapper.selectById(warehouseId);
if (warehouse == null || warehouse.getDelFlag() != null && warehouse.getDelFlag() == 1) {
throw new ServiceException("逻辑库位不存在");
}
// wmsfurnace_plan_coil也要插入这个去向的逻辑库区
WmsFurnacePlanCoil wmsFurnacePlanCoil = planCoilMapper.selectOne(Wrappers.<WmsFurnacePlanCoil>lambdaQuery()
.eq(WmsFurnacePlanCoil::getPlanId, planId)
.eq(WmsFurnacePlanCoil::getCoilId, coilId)
//逻辑删除
.eq(WmsFurnacePlanCoil::getDelFlag, 0));
if (wmsFurnacePlanCoil != null && wmsFurnacePlanCoil.getPlanCoilId() != null) {
planCoilMapper.update(null, Wrappers.<WmsFurnacePlanCoil>lambdaUpdate()
.eq(WmsFurnacePlanCoil::getPlanCoilId, wmsFurnacePlanCoil.getPlanCoilId())
.set(WmsFurnacePlanCoil::getLogicWarehouseId, warehouseId));
}
WmsMaterialCoil updateCoil = new WmsMaterialCoil();
updateCoil.setCoilId(coilId);
updateCoil.setWarehouseId(warehouseId);
updateCoil.setExclusiveStatus(0);
materialCoilMapper.updateById(updateCoil);
}
private List<Long> parseCoilIds(WmsFurnacePlanCoilBo bo) {
List<Long> coilIds = new ArrayList<>();

View File

@@ -26,6 +26,7 @@ import com.klp.domain.vo.dashboard.CategoryWidthRawVo;
import com.klp.domain.WmsCoilPendingAction;
import com.klp.domain.bo.WmsCoilPendingActionBo;
import com.klp.mapper.*;
import com.klp.service.*;
import com.klp.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -33,16 +34,6 @@ import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.klp.service.IWmsMaterialCoilService;
import com.klp.service.IWmsStockService;
import com.klp.service.IWmsGenerateRecordService;
import com.klp.service.IWmsWarehouseService;
import com.klp.service.IWmsActualWarehouseService;
import com.klp.service.IWmsRawMaterialService;
import com.klp.service.IWmsBomItemService;
import com.klp.service.IWmsCoilPendingActionService;
import com.klp.service.IWmsProductService;
import com.klp.service.IWmsCoilAbnormalService;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
@@ -80,6 +71,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
private final WmsDeliveryWaybillDetailMapper deliveryWaybillDetailMapper;
private final WmsCoilWarehouseOperationLogMapper wmsCoilWarehouseOperationLogMapper;
private final IWmsCoilAbnormalService coilAbnormalService;
private final WmsCoilContractRelMapper coilContractRelMapper;
/**
* 查询钢卷物料表
@@ -94,6 +86,9 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
// 查询关联对象
fillRelatedObjects(vo);
// 查询钢卷关联的订单信息
fillOrderListForSingle(coilId, vo);
return vo;
}
@@ -304,6 +299,21 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
}
}
}
// 查询合同信息通过中间表拿到合同id然后查询出合同信息
}
/**
* 填充单个钢卷的关联订单列表完整WmsCoilContractRelVo含JOIN订单信息
*/
private void fillOrderListForSingle(Long coilId, WmsMaterialCoilVo vo) {
try {
List<com.klp.domain.vo.WmsCoilContractRelVo> orders = coilContractRelMapper.selectOrdersByCoilId(coilId);
if (orders != null && !orders.isEmpty()) {
vo.setOrderList(orders);
}
} catch (Exception e) {
log.warn("查询钢卷关联订单信息失败, coilId: {}", coilId, e);
}
}
/**
@@ -342,6 +352,69 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
return TableDataInfo.build(bindResult);
}
/**
* 查询钢卷物料表列表(包含订单关联信息)
* 前端传 includeOrderRel=true 时调用此方法,返回每个钢卷关联的订单列表
* 使用批量查询避免N+1问题先收集所有coilId一次查询中间表+crm_order再回填
*/
@Override
public TableDataInfo<WmsMaterialCoilVo> queryPageListWithOrderRel(WmsMaterialCoilBo bo, PageQuery pageQuery) {
Page<WmsMaterialCoilVo> result = queryMaterialCoilPage(bo, pageQuery);
List<WmsMaterialCoilVo> records = result.getRecords();
if (records == null || records.isEmpty()) {
return TableDataInfo.build(result);
}
// 填充通用字段(昵称等)
fillPageCommonFields(records);
// 批量填充订单关联信息
fillOrderRelForPage(records);
return TableDataInfo.build(result);
}
/**
* 批量填充钢卷列表的订单关联信息(一次查询中间表+订单避免N+1
*/
private void fillOrderRelForPage(List<WmsMaterialCoilVo> records) {
try {
// 1. 收集所有钢卷ID
Set<Long> coilIds = records.stream()
.map(WmsMaterialCoilVo::getCoilId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (coilIds.isEmpty()) {
return;
}
// 2. 批量查询所有关联关系JOIN crm_order返回WmsCoilContractRelVo含全量订单字段
List<com.klp.domain.vo.WmsCoilContractRelVo> allRels = coilContractRelMapper.selectOrdersByCoilIds(new ArrayList<>(coilIds));
if (allRels == null || allRels.isEmpty()) {
return;
}
// 3. 按coilId分组
Map<Long, List<com.klp.domain.vo.WmsCoilContractRelVo>> relMap = allRels.stream()
.filter(rel -> rel.getCoilId() != null)
.collect(Collectors.groupingBy(
com.klp.domain.vo.WmsCoilContractRelVo::getCoilId,
Collectors.toList()
));
// 4. 回填到每个钢卷VO
for (WmsMaterialCoilVo vo : records) {
if (vo.getCoilId() != null && relMap.containsKey(vo.getCoilId())) {
vo.setOrderList(relMap.get(vo.getCoilId()));
}
}
} catch (Exception e) {
log.warn("批量查询钢卷关联订单信息失败", e);
}
}
/**
* 统计筛选条件下的全量汇总数据高性能只查sum/count
* 独立的统计接口,不影响分页查询
@@ -404,6 +477,8 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
if (stats != null) {
Object grossWeight = stats.get("total_gross_weight");
Object netWeight = stats.get("total_net_weight");
Object count = stats.get("total_count");
result.put("total_count", count != null ? new BigDecimal(count.toString()) : BigDecimal.ZERO);
result.put("total_gross_weight", grossWeight != null ? new BigDecimal(grossWeight.toString()) : BigDecimal.ZERO);
result.put("total_net_weight", netWeight != null ? new BigDecimal(netWeight.toString()) : BigDecimal.ZERO);
}
@@ -574,6 +649,11 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
qw.eq(bo.getCoilSurfaceTreatment() != null, "mc.coil_surface_treatment", bo.getCoilSurfaceTreatment());
// 调拨类型
qw.eq(StringUtils.isNotBlank(bo.getTransferType()), "mc.transfer_type", bo.getTransferType());
// 查询调拨类型不为空的钢卷
if (Boolean.TRUE.equals(bo.getHasTransferType())) {
qw.isNotNull("mc.transfer_type");
qw.ne("mc.transfer_type", "");
}
// 如果actualWarehouseId不为空则根据实际库区ID进行查询 如果为-1,则查询无库区的数据
if (bo.getActualWarehouseId() != null) {
if (bo.getActualWarehouseId() == -1) {
@@ -1193,7 +1273,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String updateByBo(WmsMaterialCoilBo bo) {
public String updateByBo(WmsMaterialCoilBo bo, String qrcodeStepType) {
// 判断是否批量更新
if (bo.getNewCoils() != null && !bo.getNewCoils().isEmpty()) {
// 批量更新逻辑(分卷/合卷)
@@ -1203,7 +1283,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
if (bo.getCoilId() == null) {
throw new RuntimeException("钢卷ID不能为空");
}
return updateBySingle(bo); // 返回新钢卷ID字符串
return updateBySingle(bo, qrcodeStepType); // 返回新钢卷ID字符串
}
}
@@ -1320,11 +1400,15 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
/**
* 单个更新
* @param bo 更新数据
* @param qrcodeStepType 二维码步骤类型null/空-默认"更新", "annealing"-退火
* @return 新钢卷ID字符串
*/
private String updateBySingle(WmsMaterialCoilBo bo) {
// 检查独占状态
validateCoilOperationPermission(bo.getCoilId(), "单个更新");
private String updateBySingle(WmsMaterialCoilBo bo, String qrcodeStepType) {
if (StringUtils.isBlank(qrcodeStepType)){
// 检查独占状态
validateCoilOperationPermission(bo.getCoilId(), "单个更新");
}
// 查询原钢卷
WmsMaterialCoil oldCoil = baseMapper.selectById(bo.getCoilId());
@@ -1350,7 +1434,8 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
// 1. 将原钢卷标记为历史数据dataType = 0
LambdaUpdateWrapper<WmsMaterialCoil> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(WmsMaterialCoil::getCoilId, oldCoil.getCoilId())
.set(WmsMaterialCoil::getDataType, 0); // 设置为历史数据
.set(WmsMaterialCoil::getDataType, 0) // 设置为历史数据
.set(WmsMaterialCoil::getExclusiveStatus, 0);
baseMapper.update(null, updateWrapper);
// 2. 创建新记录
@@ -1386,7 +1471,11 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
// 3. 更新二维码内容添加更新步骤并更新current_coil_id
if (oldCoil.getQrcodeRecordId() != null) {
updateQrcodeContentForNormalUpdate(oldCoil, bo, newCoil.getCoilId());
if (StringUtils.isNotBlank(qrcodeStepType) && "annealing".equals(qrcodeStepType)) {
updateQrcodeContentForCustomStep(oldCoil, bo, newCoil.getCoilId(), "退火", "退火操作");
} else {
updateQrcodeContentForNormalUpdate(oldCoil, bo, newCoil.getCoilId());
}
}
// 只有当新的库区ID不为空时更新库区状态
@@ -2155,6 +2244,73 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
}
}
/**
* 更新二维码内容(自定义步骤类型)
* 用于退火完成等场景action和operation可以自定义
* @param oldCoil 旧钢卷记录
* @param bo 更新数据
* @param newCoilId 新钢卷ID
* @param action 自定义action如"更新"、"退火"
* @param operation 自定义operation如"信息更新"、"退火操作"
*/
private void updateQrcodeContentForCustomStep(WmsMaterialCoil oldCoil, WmsMaterialCoilBo bo, Long newCoilId, String action, String operation) {
try {
WmsGenerateRecordVo oldRecord = generateRecordService.queryById(oldCoil.getQrcodeRecordId());
if (oldRecord == null) {
throw new RuntimeException("二维码记录不存在");
}
ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map<String, Object> contentMap = objectMapper.readValue(oldRecord.getContent(), Map.class);
@SuppressWarnings("unchecked")
List<Map<String, Object>> steps = (List<Map<String, Object>>) contentMap.get("steps");
if (steps == null) {
steps = new ArrayList<>();
}
Map<String, Object> newStep = new HashMap<>();
newStep.put("step", steps.size() + 1);
newStep.put("action", action);
newStep.put("operation", operation);
newStep.put("old_current_coil_no", oldCoil.getCurrentCoilNo());
newStep.put("new_current_coil_no", bo.getCurrentCoilNo() != null ? bo.getCurrentCoilNo() : oldCoil.getCurrentCoilNo());
newStep.put("old_coil_id", String.valueOf(oldCoil.getCoilId()));
newStep.put("new_coil_id", String.valueOf(newCoilId));
newStep.put("operator", LoginHelper.getUsername());
List<String> changedFields = new ArrayList<>();
if (bo.getWarehouseId() != null && !bo.getWarehouseId().equals(oldCoil.getWarehouseId())) {
changedFields.add("逻辑库区ID: " + oldCoil.getWarehouseId() + "" + bo.getWarehouseId());
}
if (bo.getActualWarehouseId() != null && !bo.getActualWarehouseId().equals(oldCoil.getActualWarehouseId())) {
changedFields.add("真实库区ID: " + oldCoil.getActualWarehouseId() + "" + bo.getActualWarehouseId());
}
newStep.put("changed_fields", String.join("; ", changedFields));
newStep.put("update_time", new java.util.Date());
steps.add(newStep);
contentMap.put("steps", steps);
if (bo.getCurrentCoilNo() != null) {
contentMap.put("current_coil_no", bo.getCurrentCoilNo());
}
if (newCoilId != null) {
contentMap.put("current_coil_id", String.valueOf(newCoilId));
}
String newContentJson = objectMapper.writeValueAsString(contentMap);
WmsGenerateRecordBo updateBo = new WmsGenerateRecordBo();
updateBo.setRecordId(oldCoil.getQrcodeRecordId());
updateBo.setContent(newContentJson);
generateRecordService.updateByBo(updateBo);
} catch (Exception e) {
throw new RuntimeException("更新二维码失败: " + e.getMessage());
}
}
/**
* 保存前的数据校验
@@ -2743,7 +2899,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean mergeCoils(WmsMaterialCoilBo bo) {
public Long mergeCoils(WmsMaterialCoilBo bo) {
if (bo.getNewCoils() == null || bo.getNewCoils().isEmpty()) {
throw new RuntimeException("合卷操作需要提供参与合卷的钢卷列表");
}
@@ -2824,7 +2980,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
coilPendingActionService.updateByBo(pendingActionBo);
}
return true;
return mergedCoilId;
}
/**
@@ -3472,7 +3628,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
result.put("operationType", "SPLIT");
return result;
}
// 这里不写新是因为还有退货操作,但是也和新一样可以回滚所以直接找new_coil_id即可
// 这里不写新是因为还有退货操作和退火操作,但是也和新一样可以回滚所以直接找new_coil_id即可
// 如果找到普通更新操作
Object newCoilIdObj = step.get("new_coil_id");
if (newCoilIdObj != null && newCoilIdObj.toString().equals(currentCoilId.toString())) {

View File

@@ -54,9 +54,14 @@ public class WmsWarehouseServiceImpl implements IWmsWarehouseService {
lqw.like(StringUtils.isNotBlank(bo.getWarehouseName()), WmsWarehouse::getWarehouseName, bo.getWarehouseName());
lqw.eq(bo.getWarehouseType() != null, WmsWarehouse::getWarehouseType, bo.getWarehouseType());
lqw.eq(bo.getSortNo() != null, WmsWarehouse::getSortNo, bo.getSortNo());
lqw.eq(bo.getUseCount() != null, WmsWarehouse::getUseCount, bo.getUseCount());
lqw.eq(bo.getIsEnabled() != null, WmsWarehouse::getIsEnabled, bo.getIsEnabled());
// 新增排序SortNo升序
lqw.orderByAsc(WmsWarehouse::getSortNo);
// 排序逻辑orderByUseCount为true时按useCount降序否则按sortNo升序
if (Boolean.TRUE.equals(bo.getOrderByUseCount())) {
lqw.orderByDesc(WmsWarehouse::getUseCount).orderByAsc(WmsWarehouse::getSortNo);
} else {
lqw.orderByAsc(WmsWarehouse::getSortNo);
}
return lqw;
}

View File

@@ -0,0 +1,61 @@
package com.klp.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.klp.domain.WmsWarehouse;
import com.klp.mapper.WmsMaterialCoilMapper;
import com.klp.mapper.WmsWarehouseMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@RequiredArgsConstructor
@Component
public class WarehouseUseCountTask {
private final WmsMaterialCoilMapper materialCoilMapper;
private final WmsWarehouseMapper warehouseMapper;
// @Scheduled(cron = "0 0 1 * * ?")
@Transactional(rollbackFor = Exception.class)
public void calculateWarehouseUseCount() {
log.info("[仓库使用次数定时任务] 开始计算仓库使用次数");
LambdaQueryWrapper<WmsWarehouse> wrapper = new LambdaQueryWrapper<>();
wrapper.select(WmsWarehouse::getWarehouseId);
List<WmsWarehouse> warehouses = warehouseMapper.selectList(wrapper);
if (warehouses.isEmpty()) {
log.info("[仓库使用次数定时任务] 未找到仓库记录");
return;
}
List<Long> warehouseIds = warehouses.stream()
.map(WmsWarehouse::getWarehouseId)
.collect(Collectors.toList());
List<Map<String, Object>> countList = materialCoilMapper.selectWarehouseIdCount(warehouseIds);
Map<Long, Long> countMap = new HashMap<>();
for (Map<String, Object> item : countList) {
Long wid = ((Number) item.get("warehouse_id")).longValue();
Long count = ((Number) item.get("coil_count")).longValue();
countMap.put(wid, count);
}
for (WmsWarehouse warehouse : warehouses) {
Long count = countMap.getOrDefault(warehouse.getWarehouseId(), 0L);
warehouse.setUseCount(count.intValue());
warehouseMapper.updateById(warehouse);
}
log.info("[仓库使用次数定时任务] 完成,共更新 {} 个仓库", warehouses.size());
}
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.mapper.WmsAnnealOperateEventMapper">
<resultMap type="com.klp.domain.WmsAnnealOperateEvent" id="WmsAnnealOperateEventResult">
<result property="eventId" column="event_id"/>
<result property="annealFurnaceId" column="anneal_furnace_id"/>
<result property="operateType" column="operate_type"/>
<result property="operateContent" column="operate_content"/>
<result property="coilId" column="coil_id"/>
<result property="delFlag" column="del_flag"/>
<result property="remark" column="remark"/>
<result property="createTime" column="create_time"/>
<result property="createBy" column="create_by"/>
<result property="updateTime" column="update_time"/>
<result property="updateBy" column="update_by"/>
</resultMap>
</mapper>

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.klp.mapper.WmsCoilContractRelMapper">
<resultMap type="com.klp.domain.WmsCoilContractRel" id="WmsCoilContractRelResult">
<result property="relId" column="rel_id"/>
<result property="coilId" column="coil_id"/>
<result property="contractId" column="contract_id"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
<!-- 根据钢卷ID查询关联的订单完整信息JOIN crm_order返回WmsCoilContractRelVo全量字段 -->
<select id="selectOrdersByCoilId" resultType="com.klp.domain.vo.WmsCoilContractRelVo">
SELECT
rel.rel_id AS relId,
rel.coil_id AS coilId,
rel.contract_id AS contractId,
rel.remark,
-- 订单信息
co.order_id AS orderId,
co.order_code AS orderCode,
co.order_type AS orderType,
co.customer_id AS customerId,
co.order_amount AS orderAmount,
co.salesman AS salesman,
co.delivery_date AS deliveryDate,
co.pre_order_status AS preOrderStatus,
co.audit_user AS auditUser,
co.audit_time AS auditTime,
co.order_status AS orderStatus,
co.finance_status AS financeStatus,
co.unpaid_amount AS unpaidAmount,
co.remark AS orderRemark,
co.contract_code AS contractCode,
co.contract_name AS contractName,
co.supplier AS supplier,
co.customer AS customer,
co.sign_time AS signTime,
co.sign_location AS signLocation,
co.product_content AS productContent,
co.contract_content AS contractContent,
co.supplier_address AS supplierAddress,
co.supplier_phone AS supplierPhone,
co.supplier_bank AS supplierBank,
co.supplier_account AS supplierAccount,
co.supplier_tax_no AS supplierTaxNo,
co.customer_address AS customerAddress,
co.customer_phone AS customerPhone,
co.customer_bank AS customerBank,
co.customer_account AS customerAccount,
co.customer_tax_no AS customerTaxNo,
co.tech_annex AS techAnnex,
co.business_annex AS businessAnnex,
co.production_schedule AS productionSchedule,
co.unit_price_remark AS unitPriceRemark,
co.deposit_payable AS depositPayable,
co.deposit_paid AS depositPaid,
co.deposit_ratio AS depositRatio,
co.status,
co.contract_id AS orderIdInOrder,
co.annex_files AS annexFiles,
co.create_by AS createBy,
co.create_time AS createTime,
co.update_by AS updateBy,
co.update_time AS updateTime
FROM wms_coil_contract_rel rel
INNER JOIN crm_order co ON rel.contract_id = co.order_id AND co.del_flag = 0
WHERE rel.coil_id = #{coilId} AND rel.del_flag = 0
</select>
<!-- 批量根据钢卷ID列表查询关联的订单完整信息 -->
<select id="selectOrdersByCoilIds" resultType="com.klp.domain.vo.WmsCoilContractRelVo">
SELECT
rel.rel_id AS relId,
rel.coil_id AS coilId,
rel.contract_id AS contractId,
rel.remark,
co.order_id AS orderId,
co.order_code AS orderCode,
co.order_type AS orderType,
co.customer_id AS customerId,
co.order_amount AS orderAmount,
co.salesman AS salesman,
co.delivery_date AS deliveryDate,
co.pre_order_status AS preOrderStatus,
co.audit_user AS auditUser,
co.audit_time AS auditTime,
co.order_status AS orderStatus,
co.finance_status AS financeStatus,
co.unpaid_amount AS unpaidAmount,
co.remark AS orderRemark,
co.contract_code AS contractCode,
co.contract_name AS contractName,
co.supplier AS supplier,
co.customer AS customer,
co.sign_time AS signTime,
co.sign_location AS signLocation,
co.product_content AS productContent,
co.contract_content AS contractContent,
co.supplier_address AS supplierAddress,
co.supplier_phone AS supplierPhone,
co.supplier_bank AS supplierBank,
co.supplier_account AS supplierAccount,
co.supplier_tax_no AS supplierTaxNo,
co.customer_address AS customerAddress,
co.customer_phone AS customerPhone,
co.customer_bank AS customerBank,
co.customer_account AS customerAccount,
co.customer_tax_no AS customerTaxNo,
co.tech_annex AS techAnnex,
co.business_annex AS businessAnnex,
co.production_schedule AS productionSchedule,
co.unit_price_remark AS unitPriceRemark,
co.deposit_payable AS depositPayable,
co.deposit_paid AS depositPaid,
co.deposit_ratio AS depositRatio,
co.status,
co.contract_id AS orderIdInOrder,
co.annex_files AS annexFiles,
co.create_by AS createBy,
co.create_time AS createTime,
co.update_by AS updateBy,
co.update_time AS updateTime
FROM wms_coil_contract_rel rel
INNER JOIN crm_order co ON rel.contract_id = co.order_id AND co.del_flag = 0
WHERE rel.coil_id IN
<foreach collection="coilIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND rel.del_flag = 0
</select>
</mapper>

View File

@@ -924,5 +924,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
${ew.customSqlSegment}
</select>
<!-- 统计仓库使用次数按warehouse_id出现次数排序 -->
<select id="selectWarehouseIdCount" resultType="java.util.Map">
SELECT warehouse_id, COUNT(*) AS coil_count
FROM wms_material_coil
WHERE del_flag = 0
AND warehouse_id IN
<foreach collection="list" item="wid" open="(" separator="," close=")">
#{wid}
</foreach>
GROUP BY warehouse_id
</select>
</mapper>

View File

@@ -11,6 +11,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="warehouseName" column="warehouse_name"/>
<result property="warehouseType" column="warehouse_type"/>
<result property="sortNo" column="sort_no"/>
<result property="useCount" column="use_count"/>
<result property="isEnabled" column="is_enabled"/>
<result property="delFlag" column="del_flag"/>
<result property="remark" column="remark"/>

93
script/sql/mysql/spec.sql Normal file
View File

@@ -0,0 +1,93 @@
create table wms_process_spec
(
spec_id bigint auto_increment comment '规程ID'
primary key,
spec_code varchar(50) not null comment '规程编号',
spec_name varchar(100) not null comment '规程名称',
spec_type varchar(20) not null comment '规程类型PROCESS=工艺规程STANDARD=工艺标准)',
line_id bigint not null comment '产线ID',
product_type varchar(50) null comment '产品类型如HB',
is_enabled tinyint(1) default 1 not null comment '是否启用0=否1=是)',
del_flag tinyint(1) default 0 not null comment '删除标志0=未删除1=已删除)',
remark varchar(255) null comment '备注',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
create_by varchar(50) null comment '创建人',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
update_by varchar(50) null comment '更新人',
constraint uk_spec_code
unique (spec_code)
)
comment '规程/工艺标准主表'
engine = InnoDB
row_format = DYNAMIC;
create table wms_process_spec_version
(
version_id bigint auto_increment comment '版本ID'
primary key,
spec_id bigint not null comment '规程ID',
version_code varchar(50) not null comment '版本号',
is_active tinyint(1) default 0 not null comment '是否当前生效版本1=是)',
status tinyint(1) default 1 not null comment '状态0=禁用1=启用)',
del_flag tinyint(1) default 0 not null comment '删除标志',
remark varchar(255) null comment '备注',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
create_by varchar(50) null comment '创建人',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
update_by varchar(50) null comment '更新人',
constraint uk_spec_version
unique (spec_id, version_code)
)
comment '规程版本表'
engine = InnoDB
row_format = DYNAMIC;
create table wms_process_plan
(
plan_id bigint auto_increment comment '方案ID'
primary key,
version_id bigint not null comment '版本ID',
segment_type varchar(50) not null comment '段类型INLET/PROCESS/OUTLET',
segment_name varchar(100) not null comment '段名称',
point_name varchar(100) not null comment '点位名称',
point_code varchar(100) null comment '点位编码',
actual_point_id bigint null comment '实际点位ID设备点位',
sort_order int default 0 not null comment '排序',
del_flag tinyint(1) default 0 not null comment '删除标志',
remark varchar(255) null comment '备注',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
create_by varchar(50) null comment '创建人',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
update_by varchar(50) null comment '更新人',
index idx_version_id (version_id)
)
comment '方案点位表'
engine = InnoDB
row_format = DYNAMIC;
create table wms_process_plan_param
(
param_id bigint auto_increment comment '参数ID'
primary key,
plan_id bigint not null comment '方案ID',
param_code varchar(50) not null comment '参数编码TEMP/PRESS等',
param_name varchar(100) not null comment '参数名称',
target_value decimal(18, 4) null comment '设定值',
lower_limit decimal(18, 4) null comment '下限',
upper_limit decimal(18, 4) null comment '上限',
unit varchar(20) null comment '单位',
sort_order int default 0 not null comment '排序',
del_flag tinyint(1) default 0 not null comment '删除标志',
remark varchar(255) null comment '备注',
create_time datetime default CURRENT_TIMESTAMP not null comment '创建时间',
create_by varchar(50) null comment '创建人',
update_time datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
update_by varchar(50) null comment '更新人',
index idx_plan_id (plan_id)
)
comment '方案参数表'
engine = InnoDB
row_format = DYNAMIC;