feat(qc): 新增批量检验功能并优化数据处理流程

- 添加 BatchInspectionMainBo 和 BatchInspectionTensileBo 数据传输对象
- 集成检验明细列表到 WmsInspectionMainBo 和 WmsInspectionTensileDetailBo
- 在 inspectionMain 控制器中实现批量插入检验主数据接口
- 在 inspectionTensileDetail 控制器中实现批量插入拉伸试验明细接口
- 重构前端检验样品页面,合并主表和明细表的保存操作
- 优化前端拉伸试验页面的批量新增逻辑,统一使用批量插入接口
- 更新服务层实现以支持批量插入并更新申请单关联ID列表
- 移除前端页面中单独的明细表增删改操作接口调用
This commit is contained in:
2026-07-08 13:43:31 +08:00
parent 51b27cf536
commit 7cf9f4eca4
14 changed files with 228 additions and 45 deletions

View File

@@ -42,3 +42,12 @@ export function delInspectionMain(mainId) {
method: 'delete' method: 'delete'
}) })
} }
// 批量新增检验主及明细并更新申请单detailIds
export function batchInsertMainWithDetails(data) {
return request({
url: '/wms/inspectionMain/batchInsertWithDetails',
method: 'post',
data: data
})
}

View File

@@ -42,3 +42,12 @@ export function delInspectionTensileDetail(detailId) {
method: 'delete' method: 'delete'
}) })
} }
// 批量插入明细并更新申请单detailIds
export function batchInsertTensileDetails(data) {
return request({
url: '/wms/inspectionTensileDetail/batchInsertDetails',
method: 'post',
data: data
})
}

View File

@@ -142,7 +142,7 @@
<script> <script>
import { listInspectionMain, addInspectionMain, updateInspectionMain, delInspectionMain } from '@/api/mes/qc/inspectionMain' import { listInspectionMain, addInspectionMain, updateInspectionMain, delInspectionMain } from '@/api/mes/qc/inspectionMain'
import { listInspectionDetail, addInspectionDetail, updateInspectionDetail } from '@/api/mes/qc/inspectionDetail' import { listInspectionDetail } from '@/api/mes/qc/inspectionDetail'
import { listInspectionItemTemplate, getInfoByInspectionItem } from '@/api/mes/qc/inspectionItemTemplate' import { listInspectionItemTemplate, getInfoByInspectionItem } from '@/api/mes/qc/inspectionItemTemplate'
export default { export default {
@@ -391,36 +391,28 @@ export default {
handleSaveMain(row) { handleSaveMain(row) {
row._saving = true row._saving = true
const detailList = this.checkItems.map(checkItem => {
const itemData = row._items[checkItem.itemName]
if (!itemData || (!itemData.itemValue && !itemData.detailId)) return null
return {
detailId: itemData.detailId,
mainId: row.mainId,
itemName: itemData.itemName,
itemValue: itemData.itemValue || '',
itemUnit: itemData.itemUnit || '',
upperLimit: itemData.upperLimit,
lowerLimit: itemData.lowerLimit,
rangeDesc: itemData.rangeDesc || ''
}
}).filter(Boolean)
updateInspectionMain({ updateInspectionMain({
mainId: row.mainId, mainId: row.mainId,
sampleName: row.sampleName, sampleName: row.sampleName,
sampleNo: row.sampleNo, sampleNo: row.sampleNo,
batchNo: row.batchNo, batchNo: row.batchNo,
inspectionDate: row.inspectionDate, inspectionDate: row.inspectionDate,
remark: row.remark remark: row.remark,
}).then(() => { detailList: detailList
const items = this.checkItems.map(checkItem => {
const itemData = row._items[checkItem.itemName]
return itemData || { itemName: checkItem.itemName }
})
const promises = items.map(item => {
const data = {
mainId: row.mainId,
itemName: item.itemName,
itemValue: item.itemValue,
itemUnit: item.itemUnit,
upperLimit: item.upperLimit,
lowerLimit: item.lowerLimit
}
if (item.detailId) {
data.detailId = item.detailId
return updateInspectionDetail(data)
} else if (item.itemValue) {
return addInspectionDetail(data)
}
return Promise.resolve()
})
return Promise.all(promises)
}).then(() => { }).then(() => {
this.$message.success('保存成功') this.$message.success('保存成功')
return listInspectionDetail({ mainId: row.mainId, pageNum: 1, pageSize: 9999 }) return listInspectionDetail({ mainId: row.mainId, pageNum: 1, pageSize: 9999 })

View File

@@ -519,7 +519,7 @@
<script> <script>
import { listInspectionTensile, getInspectionTensile, addInspectionTensile, updateInspectionTensile } from '@/api/mes/qc/inspectionTensile' import { listInspectionTensile, getInspectionTensile, addInspectionTensile, updateInspectionTensile } from '@/api/mes/qc/inspectionTensile'
import { listInspectionTensileDetail, addInspectionTensileDetail, updateInspectionTensileDetail, delInspectionTensileDetail } from '@/api/mes/qc/inspectionTensileDetail' import { listInspectionTensileDetail, addInspectionTensileDetail, updateInspectionTensileDetail, delInspectionTensileDetail, batchInsertTensileDetails } from '@/api/mes/qc/inspectionTensileDetail'
import { listMaterialCoil } from '@/api/wms/coil' import { listMaterialCoil } from '@/api/wms/coil'
import { listChemicalItem } from '@/api/mes/qc/chemicalItem' import { listChemicalItem } from '@/api/mes/qc/chemicalItem'
import { listPhysicalItem } from '@/api/mes/qc/physicalItem' import { listPhysicalItem } from '@/api/mes/qc/physicalItem'
@@ -765,16 +765,12 @@ export default {
this.$message.warning('请选择钢卷') this.$message.warning('请选择钢卷')
return return
} }
let successCount = 0
let failCount = 0
this.detailLoading = true this.detailLoading = true
const detailList = []
for (let index = 0; index < coils.length; index++) { for (const coil of coils) {
const coil = coils[index]
try { try {
const data = await this.fetchLatestChemAndPhys(coil.enterCoilNo) const data = await this.fetchLatestChemAndPhys(coil.enterCoilNo)
addInspectionTensileDetail({ detailList.push({
testMainId: this.currentTestId, testMainId: this.currentTestId,
steelCoilNo: coil.currentCoilNo, steelCoilNo: coil.currentCoilNo,
material: coil.material, material: coil.material,
@@ -782,21 +778,27 @@ export default {
rawMaterialNo: coil.enterCoilNo, rawMaterialNo: coil.enterCoilNo,
...data ...data
}) })
successCount++
} catch { } catch {
failCount++ // skip failed coil
} }
} }
if (detailList.length === 0) {
this.batchAddDialogVisible = false this.detailLoading = false
if (failCount === 0) { this.$message.error('批量新增失败,请稍后重试')
this.$message.success(`批量新增成功,共新增 ${successCount} 条明细`) return
} else if (successCount === 0) {
this.$message.error('批量新增失败')
} else {
this.$message.warning(`批量新增完成,成功 ${successCount} 条,失败 ${failCount}`)
} }
this.getDetailList() updateInspectionTensile({
testId: this.currentTestId,
detailList: detailList
}).then(() => {
this.$message.success(`批量新增成功,共新增 ${detailList.length} 条明细`)
}).catch(() => {
this.$message.error('批量新增失败')
}).finally(() => {
this.batchAddDialogVisible = false
this.detailLoading = false
this.getDetailList()
})
}, },
// 保存明细 // 保存明细

View File

@@ -3,6 +3,7 @@ package com.klp.controller;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
import com.klp.domain.bo.BatchInspectionMainBo;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*; import javax.validation.constraints.*;
@@ -96,4 +97,14 @@ public class WmsInspectionMainController extends BaseController {
@PathVariable Long[] mainIds) { @PathVariable Long[] mainIds) {
return toAjax(iWmsInspectionMainService.deleteWithValidByIds(Arrays.asList(mainIds), true)); return toAjax(iWmsInspectionMainService.deleteWithValidByIds(Arrays.asList(mainIds), true));
} }
/**
* 批量新增检验主及明细更新申请单detailIds为主键列表
*/
@Log(title = "批量新增检验主", businessType = BusinessType.INSERT)
@PostMapping("/batchInsertWithDetails")
public R<Void> batchInsertWithDetails(@RequestBody BatchInspectionMainBo batchBo) {
return toAjax(iWmsInspectionMainService.batchInsertWithDetails(
batchBo.getMasterId(), batchBo.getApplicationId(), batchBo.getBoList()));
}
} }

View File

@@ -3,6 +3,7 @@ package com.klp.controller;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
import com.klp.domain.bo.BatchInspectionTensileBo;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*; import javax.validation.constraints.*;
@@ -19,7 +20,9 @@ import com.klp.common.enums.BusinessType;
import com.klp.common.utils.poi.ExcelUtil; import com.klp.common.utils.poi.ExcelUtil;
import com.klp.domain.vo.WmsInspectionTensileDetailVo; import com.klp.domain.vo.WmsInspectionTensileDetailVo;
import com.klp.domain.bo.WmsInspectionTensileDetailBo; import com.klp.domain.bo.WmsInspectionTensileDetailBo;
import com.klp.domain.bo.WmsInspectionTensileBo;
import com.klp.service.IWmsInspectionTensileDetailService; import com.klp.service.IWmsInspectionTensileDetailService;
import com.klp.service.IWmsInspectionTensileService;
import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.page.TableDataInfo;
/** /**
@@ -96,4 +99,14 @@ public class WmsInspectionTensileDetailController extends BaseController {
@PathVariable String[] detailIds) { @PathVariable String[] detailIds) {
return toAjax(iWmsInspectionTensileDetailService.deleteWithValidByIds(Arrays.asList(detailIds), true)); return toAjax(iWmsInspectionTensileDetailService.deleteWithValidByIds(Arrays.asList(detailIds), true));
} }
/**
* 批量插入明细并更新申请单detailIds
*/
@Log(title = "批量插入拉伸试验明细", businessType = BusinessType.INSERT)
@PostMapping("/batchInsertDetails")
public R<Void> batchInsertDetails(@RequestBody BatchInspectionTensileBo bo) {
return toAjax(iWmsInspectionTensileDetailService.batchInsertDetails(
bo.getMasterId(), bo.getApplicationId(), bo.getDetailList()));
}
} }

View File

@@ -0,0 +1,11 @@
package com.klp.domain.bo;
import java.util.List;
import lombok.Data;
@Data
public class BatchInspectionMainBo {
private Long masterId;
private Long applicationId;
private List<WmsInspectionMainBo> boList;
}

View File

@@ -0,0 +1,12 @@
package com.klp.domain.bo;
import lombok.Data;
import java.util.List;
@Data
public class BatchInspectionTensileBo {
private Long masterId;
private Long applicationId;
private List<WmsInspectionTensileDetailBo> detailList;
}

View File

@@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode;
import javax.validation.constraints.*; import javax.validation.constraints.*;
import java.util.Date; import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
@@ -74,5 +75,10 @@ public class WmsInspectionMainBo extends BaseEntity {
*/ */
private String remark; private String remark;
/**
* 检验项目明细列表
*/
private List<WmsInspectionDetailBo> detailList;
} }

View File

@@ -7,6 +7,8 @@ import javax.validation.constraints.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
/** /**
@@ -265,4 +267,9 @@ public class WmsInspectionTensileDetailBo extends BaseEntity {
private String remark; private String remark;
/**
* 试验样品明细列表
*/
private List<WmsInspectionTensileDetailBo> detailList;
} }

View File

@@ -46,4 +46,9 @@ public interface IWmsInspectionMainService {
* 校验并批量删除检验主信息 * 校验并批量删除检验主信息
*/ */
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 批量新增检验主及明细并更新申请单detailIds为主键列表
*/
Boolean batchInsertWithDetails(Long masterId, Long applicationId, List<WmsInspectionMainBo> boList);
} }

View File

@@ -46,4 +46,6 @@ public interface IWmsInspectionTensileDetailService {
* 校验并批量删除金属材料室温拉伸试验样品明细信息 * 校验并批量删除金属材料室温拉伸试验样品明细信息
*/ */
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid); Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
Boolean batchInsertDetails(Long masterId, Long applicationId, List<WmsInspectionTensileDetailBo> detailList);
} }

View File

@@ -2,15 +2,19 @@ package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery; import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils; import com.klp.common.utils.StringUtils;
import com.klp.domain.WmsInspectionApplication;
import com.klp.mapper.WmsInspectionApplicationMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.klp.domain.bo.WmsInspectionMainBo; import com.klp.domain.bo.WmsInspectionMainBo;
import com.klp.domain.bo.WmsInspectionDetailBo;
import com.klp.domain.vo.WmsInspectionMainVo; import com.klp.domain.vo.WmsInspectionMainVo;
import com.klp.domain.vo.WmsInspectionDetailVo; import com.klp.domain.vo.WmsInspectionDetailVo;
import com.klp.domain.WmsInspectionMain; import com.klp.domain.WmsInspectionMain;
@@ -19,6 +23,7 @@ import com.klp.mapper.WmsInspectionMainMapper;
import com.klp.mapper.WmsInspectionDetailMapper; import com.klp.mapper.WmsInspectionDetailMapper;
import com.klp.service.IWmsInspectionMainService; import com.klp.service.IWmsInspectionMainService;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -37,6 +42,7 @@ public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService {
private final WmsInspectionMainMapper baseMapper; private final WmsInspectionMainMapper baseMapper;
private final WmsInspectionDetailMapper detailMapper; private final WmsInspectionDetailMapper detailMapper;
private final WmsInspectionApplicationMapper applicationMapper;
/** /**
* 查询检验主 * 查询检验主
@@ -107,6 +113,15 @@ public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService {
boolean flag = baseMapper.insert(add) > 0; boolean flag = baseMapper.insert(add) > 0;
if (flag) { if (flag) {
bo.setMainId(add.getMainId()); bo.setMainId(add.getMainId());
if (CollUtil.isNotEmpty(bo.getDetailList())) {
List<WmsInspectionDetail> detailEntities = new ArrayList<>();
for (WmsInspectionDetailBo detailBo : bo.getDetailList()) {
detailBo.setMainId(add.getMainId());
detailBo.setDetailId(null);
detailEntities.add(BeanUtil.toBean(detailBo, WmsInspectionDetail.class));
}
detailMapper.insertBatch(detailEntities);
}
} }
return flag; return flag;
} }
@@ -118,7 +133,59 @@ public class WmsInspectionMainServiceImpl implements IWmsInspectionMainService {
public Boolean updateByBo(WmsInspectionMainBo bo) { public Boolean updateByBo(WmsInspectionMainBo bo) {
WmsInspectionMain update = BeanUtil.toBean(bo, WmsInspectionMain.class); WmsInspectionMain update = BeanUtil.toBean(bo, WmsInspectionMain.class);
validEntityBeforeSave(update); validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0; boolean flag = baseMapper.updateById(update) > 0;
if (flag && CollUtil.isNotEmpty(bo.getDetailList())) {
for (WmsInspectionDetailBo detailBo : bo.getDetailList()) {
detailBo.setMainId(bo.getMainId());
WmsInspectionDetail detail = BeanUtil.toBean(detailBo, WmsInspectionDetail.class);
if (detailBo.getDetailId() != null) {
detailMapper.updateById(detail);
} else {
detail.setDetailId(null);
detailMapper.insert(detail);
}
}
}
return flag;
}
/**
* 批量新增检验主及明细并更新申请单detailIds为主键列表
*/
@Override
public Boolean batchInsertWithDetails(Long masterId, Long applicationId, List<WmsInspectionMainBo> boList) {
if (CollUtil.isEmpty(boList)) {
return false;
}
List<Long> mainIds = new ArrayList<>();
for (WmsInspectionMainBo bo : boList) {
WmsInspectionMain add = BeanUtil.toBean(bo, WmsInspectionMain.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (!flag) {
return false;
}
bo.setMainId(add.getMainId());
mainIds.add(add.getMainId());
if (CollUtil.isNotEmpty(bo.getDetailList())) {
List<WmsInspectionDetail> detailEntities = new ArrayList<>();
for (WmsInspectionDetailBo detailBo : bo.getDetailList()) {
detailBo.setMainId(add.getMainId());
detailBo.setDetailId(null);
detailEntities.add(BeanUtil.toBean(detailBo, WmsInspectionDetail.class));
}
detailMapper.insertBatch(detailEntities);
}
}
if (masterId != null && applicationId != null) {
String detailIds = mainIds.stream().map(String::valueOf).collect(Collectors.joining(","));
applicationMapper.update(null,
new LambdaUpdateWrapper<WmsInspectionApplication>()
.eq(WmsInspectionApplication::getMainId, masterId)
.eq(WmsInspectionApplication::getApplicationId, applicationId)
.set(WmsInspectionApplication::getDetailIds, detailIds));
}
return true;
} }
/** /**

View File

@@ -1,12 +1,16 @@
package com.klp.service.impl; package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.klp.common.core.page.TableDataInfo; import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery; import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils; import com.klp.common.utils.StringUtils;
import com.klp.domain.WmsInspectionApplication;
import com.klp.mapper.WmsInspectionApplicationMapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.klp.domain.bo.WmsInspectionTensileDetailBo; import com.klp.domain.bo.WmsInspectionTensileDetailBo;
@@ -15,9 +19,11 @@ import com.klp.domain.WmsInspectionTensileDetail;
import com.klp.mapper.WmsInspectionTensileDetailMapper; import com.klp.mapper.WmsInspectionTensileDetailMapper;
import com.klp.service.IWmsInspectionTensileDetailService; import com.klp.service.IWmsInspectionTensileDetailService;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Collection; import java.util.Collection;
import java.util.stream.Collectors;
/** /**
* 金属材料室温拉伸试验样品明细Service业务层处理 * 金属材料室温拉伸试验样品明细Service业务层处理
@@ -31,6 +37,8 @@ public class WmsInspectionTensileDetailServiceImpl implements IWmsInspectionTens
private final WmsInspectionTensileDetailMapper baseMapper; private final WmsInspectionTensileDetailMapper baseMapper;
private final WmsInspectionApplicationMapper applicationMapper;
/** /**
* 查询金属材料室温拉伸试验样品明细 * 查询金属材料室温拉伸试验样品明细
*/ */
@@ -151,4 +159,33 @@ public class WmsInspectionTensileDetailServiceImpl implements IWmsInspectionTens
} }
return baseMapper.deleteBatchIds(ids) > 0; return baseMapper.deleteBatchIds(ids) > 0;
} }
/**
* 批量插入明细并更新申请单detailIds
*/
@Override
public Boolean batchInsertDetails(Long masterId, Long applicationId, List<WmsInspectionTensileDetailBo> detailList) {
if (CollUtil.isEmpty(detailList)) {
return false;
}
List<WmsInspectionTensileDetail> details = new ArrayList<>();
for (WmsInspectionTensileDetailBo bo : detailList) {
bo.setDetailId(null);
details.add(BeanUtil.toBean(bo, WmsInspectionTensileDetail.class));
}
boolean flag = baseMapper.insertBatch(details);
if (flag && masterId != null && applicationId != null) {
String detailIds = details.stream()
.map(WmsInspectionTensileDetail::getDetailId)
.collect(Collectors.joining(","));
applicationMapper.update(null,
new LambdaUpdateWrapper<WmsInspectionApplication>()
.eq(WmsInspectionApplication::getMainId, masterId)
.eq(WmsInspectionApplication::getApplicationId, applicationId)
.set(WmsInspectionApplication::getDetailIds, detailIds));
}
return flag;
}
} }