Compare commits

..

14 Commits

Author SHA1 Message Date
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
ae77c529ae feat(wms): 添加物料卷统计总数功能
- 在WmsMaterialCoilServiceImpl中新增total_count字段统计
- 将统计结果添加到返回结果集中
- 处理空值情况并设置默认值为BigDecimal.ZERO
2026-04-17 09:54:34 +08:00
36 changed files with 1252 additions and 103 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

@@ -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

@@ -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,45 @@ 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();
}
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.getContractId() != null && coilIdMap.containsKey(vo.getContractId())) {
List<Long> coilIdList = coilIdMap.get(vo.getContractId());
// 设置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

@@ -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

@@ -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,8 +14,10 @@
<el-table v-loading="loading" :data="orderItemList">
<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="rawMaterialSpec" />
<!-- <el-table-column label="原料规格" align="center" prop="rawMaterialSpec" /> -->
<el-table-column label="宽度公差" align="center" prop="widthTolerance" />
<el-table-column label="厚度公差" align="center" prop="thicknessTolerance" />
@@ -29,6 +31,12 @@
</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" />
@@ -50,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>
@@ -71,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">
@@ -170,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

@@ -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

@@ -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

@@ -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

@@ -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

@@ -45,8 +45,8 @@
clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<MaterialSelect :hideType="hideType" :itemId.sync="queryParams.itemIds" :itemType.sync="queryParams.itemType"
:multiple="true" />
<!-- <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>
@@ -83,10 +83,6 @@
<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>
@@ -115,11 +111,10 @@
<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="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" prop="materialType" /> -->
<el-table-column label="产品类型" align="center" width="180">
<template slot-scope="scope">
<ProductInfo v-if="scope.row.itemType == 'product'" :product="scope.row" />
@@ -128,7 +123,6 @@
</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%"
@@ -144,8 +138,7 @@
</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">
<!-- <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,7 +151,7 @@
</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">
@@ -280,7 +273,7 @@
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<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)">
预览标签
@@ -812,11 +805,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' },

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

@@ -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.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

@@ -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

@@ -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

@@ -0,0 +1,47 @@
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 lombok.Data;
/**
* 钢卷与合同关联关系视图对象 wms_coil_contract_rel
*
* @author klp
* @date 2026-04-18
*/
@Data
@ExcelIgnoreUnannotated
public class WmsCoilContractRelVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long relId;
/**
* 钢卷ID
*/
@ExcelProperty(value = "钢卷ID")
private Long coilId;
/**
* 合同ID
*/
@ExcelProperty(value = "合同ID")
private Long contractId;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
}

View File

@@ -0,0 +1,15 @@
package com.klp.mapper;
import com.klp.domain.WmsCoilContractRel;
import com.klp.domain.vo.WmsCoilContractRelVo;
import com.klp.common.core.mapper.BaseMapperPlus;
/**
* 钢卷与合同关联关系Mapper接口
*
* @author klp
* @date 2026-04-18
*/
public interface WmsCoilContractRelMapper extends BaseMapperPlus<WmsCoilContractRelMapper, WmsCoilContractRel, WmsCoilContractRelVo> {
}

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

@@ -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

@@ -404,6 +404,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 +576,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) {

View File

@@ -0,0 +1,20 @@
<?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>
</mapper>