feat(biz): 添加产品批次重量配置和退库功能模块
This commit is contained in:
parent
8ae537466d
commit
4a04aa40e4
1
.gitignore
vendored
1
.gitignore
vendored
@ -54,3 +54,4 @@ application-my.yaml
|
||||
|
||||
### Trae ###
|
||||
/.trae/
|
||||
/mes-ui/mes-ui-admin-vue3/.agent-browser/
|
||||
|
||||
@ -103,7 +103,7 @@ public class ProPackPageReqVO extends PageParam {
|
||||
private Integer lineId;
|
||||
|
||||
@Schema(description = "入库状态( 1 待入库 2 部分入库 3 已入库)", example = "1")
|
||||
private String packStatus;
|
||||
private String [] packStatus;
|
||||
|
||||
@Schema(description = "损耗数量")
|
||||
private BigDecimal lossQty;
|
||||
|
||||
@ -3,6 +3,8 @@ package com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostorage.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 成品入/出库新增/修改 Request VO")
|
||||
@Data
|
||||
public class ProStorageInsertReqVO {
|
||||
@ -18,4 +20,8 @@ public class ProStorageInsertReqVO {
|
||||
private String storeAreCd;
|
||||
private String storeAreaName;
|
||||
|
||||
//退库信息
|
||||
private BigDecimal returnQty;
|
||||
private Integer returnBagQty;
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static com.ningxia.yunxi.chemmes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
import static com.ningxia.yunxi.chemmes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 成品入/出库分页 Request VO")
|
||||
@ -22,7 +23,7 @@ public class ProStoragePageReqVO extends PageParam {
|
||||
private String billNo;
|
||||
|
||||
@Schema(description = "操作类型 1为入库,2为出库", example = "1")
|
||||
private Boolean operatorType;
|
||||
private String operatorType;
|
||||
|
||||
@Schema(description = "业务类型 (10 生产入库,11 盘盈入库,12 其它入库 21 成品出库 22 盘亏出库 23生产退库)", example = "1")
|
||||
private Integer businessType;
|
||||
@ -38,7 +39,7 @@ public class ProStoragePageReqVO extends PageParam {
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "业务日期")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate[] billDate;
|
||||
|
||||
@Schema(description = "操作人id", example = "21958")
|
||||
|
||||
@ -3,9 +3,8 @@ package com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostorage.vo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 成品入/出库新增/修改 Request VO")
|
||||
@Data
|
||||
@ -14,45 +13,46 @@ public class ProStorageSaveReqVO {
|
||||
@Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "26146")
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "单据编号不能为空")
|
||||
private String billNo;
|
||||
|
||||
@Schema(description = "操作类型 1为入库,2为出库", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "操作类型 1为入库,2为出库不能为空")
|
||||
private Boolean operatorType;
|
||||
|
||||
@Schema(description = "业务类型 (10 生产入库,11 盘盈入库,12 其它入库 21 成品出库 22 盘亏出库 23生产退库)", example = "1")
|
||||
private Integer businessType;
|
||||
// @Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
// @NotEmpty(message = "单据编号不能为空")
|
||||
// private String billNo;
|
||||
//
|
||||
// @Schema(description = "操作类型 1为入库,2为出库", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
// @NotNull(message = "操作类型 1为入库,2为出库不能为空")
|
||||
// private Boolean operatorType;
|
||||
//
|
||||
// @Schema(description = "业务类型 (10 生产入库,11 盘盈入库,12 其它入库 21 成品出库 22 盘亏出库 23生产退库)", example = "1")
|
||||
// private Integer businessType;
|
||||
|
||||
@Schema(description = "备注", example = "你说的对")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "状态:1 已创建;2 提交", example = "1")
|
||||
private Boolean status;
|
||||
private String status;
|
||||
|
||||
@Schema(description = "业务日期")
|
||||
private LocalDate billDate;
|
||||
|
||||
@Schema(description = "操作人id", example = "21958")
|
||||
private Integer operatorId;
|
||||
// @Schema(description = "操作人id", example = "21958")
|
||||
// private Integer operatorId;
|
||||
//
|
||||
// @Schema(description = "操作人", example = "张三")
|
||||
// private String operatorName;
|
||||
//
|
||||
// @Schema(description = "关联单号")
|
||||
// private String relarionNo;
|
||||
|
||||
@Schema(description = "操作人", example = "张三")
|
||||
private String operatorName;
|
||||
// @Schema(description = "关联单号id", example = "10903")
|
||||
// private Integer relarionId;
|
||||
|
||||
@Schema(description = "关联单号")
|
||||
private String relarionNo;
|
||||
|
||||
@Schema(description = "关联单号id", example = "10903")
|
||||
private Integer relarionId;
|
||||
|
||||
@Schema(description = "单据类型(1 标准采购申请 2设备采购申请 3 标准采购退料 4设备采购退料)", example = "1")
|
||||
private String billType;
|
||||
|
||||
@Schema(description = "来源单号")
|
||||
private String sourceNo;
|
||||
|
||||
@Schema(description = "来源单号id", example = "27114")
|
||||
private Integer sourceId;
|
||||
// @Schema(description = "单据类型(1 标准采购申请 2设备采购申请 3 标准采购退料 4设备采购退料)", example = "1")
|
||||
// private String billType;
|
||||
//
|
||||
// @Schema(description = "来源单号")
|
||||
// private String sourceNo;
|
||||
//
|
||||
// @Schema(description = "来源单号id", example = "27114")
|
||||
// private Integer sourceId;
|
||||
|
||||
List<ProStorageInsertReqVO> details;
|
||||
}
|
||||
|
||||
@ -70,6 +70,15 @@ public class ProStorageMatController {
|
||||
return success(BeanUtils.toBean(proStorageMat, ProStorageMatRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/getByStockId")
|
||||
@Operation(summary = "获得成品入/出库子")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('twm:pro-storage-mat:query')")
|
||||
public CommonResult<List<ProStorageMatRespVO>> getProStorageMatByStockId(@RequestParam("stockId") Integer stockId) {
|
||||
List<ProStorageMatDO> proStorageMatByStockId = proStorageMatService.getProStorageMatByStockId(stockId);
|
||||
return success(BeanUtils.toBean(proStorageMatByStockId, ProStorageMatRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得成品入/出库子分页")
|
||||
@PreAuthorize("@ss.hasPermission('twm:pro-storage-mat:query')")
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
package com.ningxia.yunxi.chemmes.module.biz.dal.mysql.propack;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
||||
import com.ningxia.yunxi.chemmes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.ningxia.yunxi.chemmes.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.ningxia.yunxi.chemmes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.propack.vo.ProPackPageReqVO;
|
||||
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.propack.ProPackDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@ -51,7 +49,7 @@ public interface ProPackMapper extends BaseMapperX<ProPackDO> {
|
||||
.eqIfPresent(ProPackDO::getLineCd, reqVO.getLineCd())
|
||||
.likeIfPresent(ProPackDO::getLineName, reqVO.getLineName())
|
||||
.eqIfPresent(ProPackDO::getLineId, reqVO.getLineId())
|
||||
.eqIfPresent(ProPackDO::getPackStatus, reqVO.getPackStatus())
|
||||
.inIfPresent(ProPackDO::getPackStatus, reqVO.getPackStatus())
|
||||
.eqIfPresent(ProPackDO::getLossQty, reqVO.getLossQty())
|
||||
.eqIfPresent(ProPackDO::getJudgResult, reqVO.getJudgResult())
|
||||
.eqIfPresent(ProPackDO::getInspStatus, reqVO.getInspStatus())
|
||||
@ -62,4 +60,4 @@ public interface ProPackMapper extends BaseMapperX<ProPackDO> {
|
||||
.orderByDesc(ProPackDO::getProDate));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ public interface ProStorageMapper extends BaseMapperX<ProStorageDO> {
|
||||
|
||||
default PageResult<ProStorageDO> selectPage(ProStoragePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<ProStorageDO>()
|
||||
.eqIfPresent(ProStorageDO::getBillNo, reqVO.getBillNo())
|
||||
.likeIfPresent(ProStorageDO::getBillNo, reqVO.getBillNo())
|
||||
.eqIfPresent(ProStorageDO::getOperatorType, reqVO.getOperatorType())
|
||||
.eqIfPresent(ProStorageDO::getBusinessType, reqVO.getBusinessType())
|
||||
.eqIfPresent(ProStorageDO::getRemark, reqVO.getRemark())
|
||||
|
||||
@ -7,6 +7,8 @@ import com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostoragemat.vo.Pr
|
||||
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.prostoragemat.ProStorageMatDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 成品入/出库子 Mapper
|
||||
*
|
||||
@ -42,4 +44,11 @@ public interface ProStorageMatMapper extends BaseMapperX<ProStorageMatDO> {
|
||||
.orderByDesc(ProStorageMatDO::getId));
|
||||
}
|
||||
|
||||
default List<ProStorageMatDO> selectByStockId(Integer id) {
|
||||
return selectList(new LambdaQueryWrapperX<ProStorageMatDO>().eq(ProStorageMatDO::getStockId, id));
|
||||
}
|
||||
|
||||
default int deleteByStockId(Integer id) {
|
||||
return delete(new LambdaQueryWrapperX<ProStorageMatDO>().eq(ProStorageMatDO::getStockId, id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.ningxia.yunxi.chemmes.module.biz.service.prostorage;
|
||||
|
||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
||||
import com.ningxia.yunxi.chemmes.framework.common.util.CodeGenerateUtils;
|
||||
import com.ningxia.yunxi.chemmes.framework.common.util.object.BeanUtils;
|
||||
import com.ningxia.yunxi.chemmes.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostorage.vo.ProStorageInsertReqVO;
|
||||
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostorage.vo.ProStoragePageReqVO;
|
||||
@ -51,25 +50,100 @@ public class ProStorageServiceImpl implements ProStorageService {
|
||||
|
||||
@Override
|
||||
public Integer createProStorage(ProStorageSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
ProStorageDO proStorage = BeanUtils.toBean(createReqVO, ProStorageDO.class);
|
||||
proStorageMapper.insert(proStorage);
|
||||
// 返回
|
||||
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
||||
AdminUserDO user = adminUserService.getUser(loginUserId);
|
||||
String nickname = user.getNickname();
|
||||
ProStorageDO proStorage = saveProStorage(23, loginUserId, nickname, "", null, createReqVO.getRemark());
|
||||
|
||||
saveMat(createReqVO, proStorage);
|
||||
|
||||
if ("2".equals(createReqVO.getStatus())) {
|
||||
process(proStorage, loginUserId, nickname);
|
||||
}
|
||||
|
||||
return proStorage.getId();
|
||||
}
|
||||
|
||||
private void process(ProStorageDO proStorage, Long loginUserId, String nickname) {
|
||||
List<ProStorageMatDO> proStorageMatDOS = proStorageMatMapper.selectByStockId(proStorage.getId());
|
||||
for (ProStorageMatDO proStorageMatDO : proStorageMatDOS) {
|
||||
ProStorageInventoryDO storageInventoryDO = proStorageInventoryService.getProStorageInventory(Long.valueOf(proStorageMatDO.getId()));
|
||||
storageInventoryDO.setYardQty(storageInventoryDO.getYardQty().subtract(proStorageMatDO.getOperatorQty()));
|
||||
storageInventoryDO.setPackQty(storageInventoryDO.getPackQty() - proStorageMatDO.getBagQty());
|
||||
proStorageInventoryMapper.updateById(storageInventoryDO);
|
||||
|
||||
ProStorageMatDO proStorageMat = new ProStorageMatDO();
|
||||
proStorageMat.setStockId(proStorage.getId());
|
||||
proStorageMat.setDescription("");
|
||||
proStorageMat.setStoreHouseId(storageInventoryDO.getStoreHouseId());
|
||||
proStorageMat.setStoreAreaId(storageInventoryDO.getStoreAreaId());
|
||||
proStorageMat.setStoreHouseCd(storageInventoryDO.getStoreHouseCd());
|
||||
proStorageMat.setStoreHouseName(storageInventoryDO.getStoreHouseName());
|
||||
proStorageMat.setStoreAreCd(storageInventoryDO.getStoreAreCd());
|
||||
proStorageMat.setStoreAreaName(storageInventoryDO.getStoreAreaName());
|
||||
proStorageMat.setMaterialId(storageInventoryDO.getMaterialId());
|
||||
proStorageMat.setMatName(storageInventoryDO.getMatName());
|
||||
proStorageMat.setMatCode(storageInventoryDO.getMatCode());
|
||||
proStorageMat.setSpec(storageInventoryDO.getSpec());
|
||||
proStorageMat.setUnit(storageInventoryDO.getUnit());
|
||||
proStorageMat.setLotNo(storageInventoryDO.getLotNo());
|
||||
proStorageMat.setOperatorQty(proStorageMatDO.getOperatorQty());
|
||||
// proStorageMat.setSourceId(0L);
|
||||
// proStorageMat.setRelarionId(0);
|
||||
// proStorageMat.setBagSpec(0);
|
||||
// proStorageMat.setBagQty(0);
|
||||
// proStorageMat.setPlanId(0);
|
||||
// proStorageMat.setProNo("");
|
||||
proStorageMat.setInventBillNo(storageInventoryDO.getInventBillNo());
|
||||
proStorageMatMapper.insert(proStorageMat);
|
||||
|
||||
ProStorageLogDO proStorageLog = new ProStorageLogDO();
|
||||
// proStorageLog.setStockId(0);
|
||||
// proStorageLog.setDescription("");
|
||||
// proStorageLog.setStatus("");
|
||||
proStorageLog.setStoreHouseId(storageInventoryDO.getStoreHouseId());
|
||||
proStorageLog.setStoreAreaId(storageInventoryDO.getStoreAreaId());
|
||||
proStorageLog.setStoreHouseCd(storageInventoryDO.getStoreHouseCd());
|
||||
proStorageLog.setStoreHouseName(storageInventoryDO.getStoreHouseName());
|
||||
proStorageLog.setStoreAreCd(storageInventoryDO.getStoreAreCd());
|
||||
proStorageLog.setStoreAreaName(storageInventoryDO.getStoreAreaName());
|
||||
proStorageLog.setMaterialId(storageInventoryDO.getMaterialId());
|
||||
proStorageLog.setMatName(storageInventoryDO.getMatName());
|
||||
proStorageLog.setMatCode(storageInventoryDO.getMatCode());
|
||||
proStorageLog.setSpec(storageInventoryDO.getSpec());
|
||||
proStorageLog.setUnit(storageInventoryDO.getUnit());
|
||||
proStorageLog.setLotNo(storageInventoryDO.getLotNo());
|
||||
proStorageLog.setOperatorQty(proStorageMatDO.getOperatorQty());
|
||||
proStorageLog.setOperatorType("2");
|
||||
proStorageLog.setBusinessType("23");
|
||||
// proStorageLog.setStorageAft(new BigDecimal("0"));
|
||||
// proStorageLog.setStorageBef(new BigDecimal("0"));
|
||||
// proStorageLog.setStockItemId(0);
|
||||
proStorageLog.setBillDate(LocalDate.now());
|
||||
proStorageLog.setOperatorId(String.valueOf(loginUserId));
|
||||
proStorageLog.setOperatorName(nickname);
|
||||
proStorageLog.setRelarionNo(proStorage.getBillNo());
|
||||
proStorageLog.setRelarionId(proStorage.getId());
|
||||
proStorageLog.setRelarionDetailId(proStorageMat.getId());
|
||||
// proStorageLog.setDpstNo("");
|
||||
proStorageLog.setInventBillNo(storageInventoryDO.getInventBillNo());
|
||||
proStorageLogService.saveProStorageLog(proStorageLog);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveProStorage(List<ProStorageInsertReqVO> reqVOS) {
|
||||
|
||||
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
||||
AdminUserDO user = adminUserService.getUser(loginUserId);
|
||||
String nickname = user.getNickname();
|
||||
for (ProStorageInsertReqVO createReqVO : reqVOS) {
|
||||
ProPackDO proPackDO = proPackMapper.selectById(createReqVO.getId());
|
||||
ProStorageDO proStorage = saveProStorage(loginUserId, nickname, proPackDO);
|
||||
ProStorageDO proStorage = saveProStorage(10, loginUserId, nickname, proPackDO.getPackNo(), proPackDO.getId(), "");
|
||||
ProStorageInventoryDO storageInventoryDO = svaeStorageInventory(createReqVO, proPackDO);
|
||||
saveLog(createReqVO, proStorage, proPackDO, storageInventoryDO, loginUserId, nickname);
|
||||
proPackDO.setPackStatus("3");
|
||||
proPackMapper.updateById(proPackDO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,18 +187,19 @@ public class ProStorageServiceImpl implements ProStorageService {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ProStorageDO saveProStorage(Long loginUserId, String nickname, ProPackDO proPackDO) {
|
||||
private ProStorageDO saveProStorage(Integer businessType, Long loginUserId, String nickname,
|
||||
String relationNo, Integer relationId, String remark) {
|
||||
ProStorageDO proStorage = new ProStorageDO();
|
||||
proStorage.setBillNo(generateBillNo("2"));
|
||||
proStorage.setOperatorType(1);
|
||||
proStorage.setBusinessType(10);
|
||||
proStorage.setRemark("");
|
||||
proStorage.setOperatorType(2);
|
||||
proStorage.setBusinessType(businessType);
|
||||
proStorage.setRemark(remark);
|
||||
proStorage.setStatus(2);
|
||||
proStorage.setBillDate(LocalDate.now());
|
||||
proStorage.setOperatorId(loginUserId);
|
||||
proStorage.setOperatorName(nickname);
|
||||
proStorage.setRelarionNo(proPackDO.getPackNo());
|
||||
proStorage.setRelarionId(proPackDO.getId());
|
||||
proStorage.setRelarionNo(relationNo);
|
||||
proStorage.setRelarionId(relationId);
|
||||
// proStorage.setBillType("0");
|
||||
// proStorage.setSourceNo();
|
||||
// proStorage.setSourceId();
|
||||
@ -194,11 +269,45 @@ public class ProStorageServiceImpl implements ProStorageService {
|
||||
|
||||
@Override
|
||||
public void updateProStorage(ProStorageSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateProStorageExists(updateReqVO.getId());
|
||||
// 更新
|
||||
ProStorageDO updateObj = BeanUtils.toBean(updateReqVO, ProStorageDO.class);
|
||||
proStorageMapper.updateById(updateObj);
|
||||
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
|
||||
AdminUserDO user = adminUserService.getUser(loginUserId);
|
||||
String nickname = user.getNickname();
|
||||
ProStorageDO proStorage = saveProStorage(23, loginUserId, nickname, "", null, updateReqVO.getRemark());
|
||||
proStorageMatMapper.deleteByStockId(proStorage.getId());
|
||||
saveMat(updateReqVO, proStorage);
|
||||
|
||||
if ("2".equals(updateReqVO.getStatus())) {
|
||||
process(proStorage, loginUserId, nickname);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveMat(ProStorageSaveReqVO updateReqVO, ProStorageDO proStorage) {
|
||||
for (ProStorageInsertReqVO detail : updateReqVO.getDetails()) {
|
||||
ProStorageInventoryDO storageInventoryDO = proStorageInventoryService.getProStorageInventory(Long.valueOf(detail.getId()));
|
||||
ProStorageMatDO proStorageMat = new ProStorageMatDO();
|
||||
proStorageMat.setStockId(proStorage.getId());
|
||||
proStorageMat.setDescription("");
|
||||
proStorageMat.setStoreHouseId(storageInventoryDO.getStoreHouseId());
|
||||
proStorageMat.setStoreAreaId(storageInventoryDO.getStoreAreaId());
|
||||
proStorageMat.setStoreHouseCd(storageInventoryDO.getStoreHouseCd());
|
||||
proStorageMat.setStoreHouseName(storageInventoryDO.getStoreHouseName());
|
||||
proStorageMat.setStoreAreCd(storageInventoryDO.getStoreAreCd());
|
||||
proStorageMat.setStoreAreaName(storageInventoryDO.getStoreAreaName());
|
||||
proStorageMat.setMaterialId(storageInventoryDO.getMaterialId());
|
||||
proStorageMat.setMatName(storageInventoryDO.getMatName());
|
||||
proStorageMat.setMatCode(storageInventoryDO.getMatCode());
|
||||
proStorageMat.setSpec(storageInventoryDO.getSpec());
|
||||
proStorageMat.setUnit(storageInventoryDO.getUnit());
|
||||
proStorageMat.setLotNo(storageInventoryDO.getLotNo());
|
||||
proStorageMat.setOperatorQty(detail.getReturnQty());
|
||||
// proStorageMat.setSourceId(0L);
|
||||
// proStorageMat.setRelarionId(0);
|
||||
// proStorageMat.setBagSpec(0);
|
||||
// proStorageMat.setBagQty(0);
|
||||
// proStorageMat.setProNo("");
|
||||
proStorageMat.setInventBillNo(storageInventoryDO.getInventBillNo());
|
||||
proStorageMatMapper.insert(proStorageMat);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -227,9 +336,9 @@ public class ProStorageServiceImpl implements ProStorageService {
|
||||
|
||||
@Override
|
||||
public String generateBillNo(String operatorType) {
|
||||
String prefix = "CK";
|
||||
String prefix = "RKD";
|
||||
if ("2".equals(operatorType)) {
|
||||
prefix = "RKD";
|
||||
prefix = "CKD";
|
||||
}
|
||||
String maxBillNo = proStorageMapper.selectMaxBillNo();
|
||||
return CodeGenerateUtils.generateBillNo(prefix, maxBillNo);
|
||||
|
||||
@ -6,6 +6,7 @@ import com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostoragemat.vo.Pr
|
||||
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.prostoragemat.ProStorageMatDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 成品入/出库子 Service 接口
|
||||
@ -44,6 +45,8 @@ public interface ProStorageMatService {
|
||||
*/
|
||||
ProStorageMatDO getProStorageMat(Integer id);
|
||||
|
||||
List<ProStorageMatDO> getProStorageMatByStockId(Integer id);
|
||||
|
||||
/**
|
||||
* 获得成品入/出库子分页
|
||||
*
|
||||
|
||||
@ -11,6 +11,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.ningxia.yunxi.chemmes.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
@ -62,6 +64,11 @@ public class ProStorageMatServiceImpl implements ProStorageMatService {
|
||||
return proStorageMatMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProStorageMatDO> getProStorageMatByStockId(Integer id) {
|
||||
return proStorageMatMapper.selectByStockId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ProStorageMatDO> getProStorageMatPage(ProStorageMatPageReqVO pageReqVO) {
|
||||
return proStorageMatMapper.selectPage(pageReqVO);
|
||||
|
||||
12
mes-ui/mes-ui-admin-vue3/mcp.config.json
Normal file
12
mes-ui/mes-ui-admin-vue3/mcp.config.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"lanhu-browser": {
|
||||
"command": "node",
|
||||
"args": ["./mcp-lanhu-server/index.js"],
|
||||
"env": {
|
||||
"EDGE_PROFILE_PATH": "./.agent-browser/profile",
|
||||
"LANHU_BASE_URL": "https://lanhuapp.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
mes-ui/mes-ui-admin-vue3/src/api/biz/lotconfig/index.ts
Normal file
41
mes-ui/mes-ui-admin-vue3/src/api/biz/lotconfig/index.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface LotConfigVO {
|
||||
id: number
|
||||
remark: string
|
||||
matCode: string
|
||||
matName: string
|
||||
matId: number
|
||||
lotWgt: number
|
||||
enabledStatus: boolean
|
||||
}
|
||||
|
||||
// 查询产品批次重量配置分页
|
||||
export const getLotConfigPage = async (params) => {
|
||||
return await request.get({ url: `/biz/lot-config/page`, params })
|
||||
}
|
||||
|
||||
// 查询产品批次重量配置详情
|
||||
export const getLotConfig = async (id: number) => {
|
||||
return await request.get({ url: `/biz/lot-config/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增产品批次重量配置
|
||||
export const createLotConfig = async (data: LotConfigVO) => {
|
||||
return await request.post({ url: `/biz/lot-config/create`, data })
|
||||
}
|
||||
|
||||
// 修改产品批次重量配置
|
||||
export const updateLotConfig = async (data: LotConfigVO) => {
|
||||
return await request.put({ url: `/biz/lot-config/update`, data })
|
||||
}
|
||||
|
||||
// 删除产品批次重量配置
|
||||
export const deleteLotConfig = async (id: number) => {
|
||||
return await request.delete({ url: `/biz/lot-config/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出产品批次重量配置 Excel
|
||||
export const exportLotConfig = async (params) => {
|
||||
return await request.download({ url: `/biz/lot-config/export-excel`, params })
|
||||
}
|
||||
@ -15,6 +15,7 @@ export interface ProStorageVO {
|
||||
billType: string
|
||||
sourceNo: string
|
||||
sourceId: number
|
||||
details: ProPackVO[]
|
||||
}
|
||||
|
||||
export interface ProPackVO {
|
||||
@ -23,7 +24,7 @@ export interface ProPackVO {
|
||||
storeAreaId: number
|
||||
storeHouseCd: string
|
||||
storeHouseName: string
|
||||
storeAreaCd: string
|
||||
storeAreCd: string
|
||||
storeAreaName: string
|
||||
}
|
||||
|
||||
|
||||
@ -1,56 +1,61 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface ProStorageMatVO {
|
||||
id: number
|
||||
stockId: number
|
||||
description: string
|
||||
storeHouseId: number
|
||||
storeAreaId: number
|
||||
storeHouseCd: string
|
||||
storeHouseName: string
|
||||
storeAreCd: string
|
||||
storeAreaName: string
|
||||
materialId: number
|
||||
matName: string
|
||||
matCode: string
|
||||
spec: string
|
||||
unit: string
|
||||
lotNo: string
|
||||
operatorQty: number
|
||||
sourceId: number
|
||||
relarionId: number
|
||||
bagSpec: number
|
||||
bagQty: number
|
||||
planId: number
|
||||
proNo: string
|
||||
}
|
||||
|
||||
// 查询成品入/出库子分页
|
||||
export const getProStorageMatPage = async (params) => {
|
||||
return await request.get({ url: `/twm/pro-storage-mat/page`, params })
|
||||
}
|
||||
|
||||
// 查询成品入/出库子详情
|
||||
export const getProStorageMat = async (id: number) => {
|
||||
return await request.get({ url: `/twm/pro-storage-mat/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增成品入/出库子
|
||||
export const createProStorageMat = async (data: ProStorageMatVO) => {
|
||||
return await request.post({ url: `/twm/pro-storage-mat/create`, data })
|
||||
}
|
||||
|
||||
// 修改成品入/出库子
|
||||
export const updateProStorageMat = async (data: ProStorageMatVO) => {
|
||||
return await request.put({ url: `/twm/pro-storage-mat/update`, data })
|
||||
}
|
||||
|
||||
// 删除成品入/出库子
|
||||
export const deleteProStorageMat = async (id: number) => {
|
||||
return await request.delete({ url: `/twm/pro-storage-mat/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出成品入/出库子 Excel
|
||||
export const exportProStorageMat = async (params) => {
|
||||
return await request.download({ url: `/twm/pro-storage-mat/export-excel`, params })
|
||||
}
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface ProStorageMatVO {
|
||||
id: number
|
||||
stockId: number
|
||||
description: string
|
||||
storeHouseId: number
|
||||
storeAreaId: number
|
||||
storeHouseCd: string
|
||||
storeHouseName: string
|
||||
storeAreCd: string
|
||||
storeAreaName: string
|
||||
materialId: number
|
||||
matName: string
|
||||
matCode: string
|
||||
spec: string
|
||||
unit: string
|
||||
lotNo: string
|
||||
operatorQty: number
|
||||
sourceId: number
|
||||
relarionId: number
|
||||
bagSpec: number
|
||||
bagQty: number
|
||||
planId: number
|
||||
proNo: string
|
||||
}
|
||||
|
||||
// 查询成品入/出库子分页
|
||||
export const getProStorageMatPage = async (params) => {
|
||||
return await request.get({ url: `/twm/pro-storage-mat/page`, params })
|
||||
}
|
||||
|
||||
// 查询成品入/出库子详情
|
||||
export const getProStorageMat = async (id: number) => {
|
||||
return await request.get({ url: `/twm/pro-storage-mat/get?id=` + id })
|
||||
}
|
||||
|
||||
// 查询成品入/出库子分页
|
||||
export const getProStorageMatPageByStockId = async (stockId: number) => {
|
||||
return await request.get({ url: `/twm/pro-storage-mat/getByStockId?stockId=` + stockId })
|
||||
}
|
||||
|
||||
// 新增成品入/出库子
|
||||
export const createProStorageMat = async (data: ProStorageMatVO) => {
|
||||
return await request.post({ url: `/twm/pro-storage-mat/create`, data })
|
||||
}
|
||||
|
||||
// 修改成品入/出库子
|
||||
export const updateProStorageMat = async (data: ProStorageMatVO) => {
|
||||
return await request.put({ url: `/twm/pro-storage-mat/update`, data })
|
||||
}
|
||||
|
||||
// 删除成品入/出库子
|
||||
export const deleteProStorageMat = async (id: number) => {
|
||||
return await request.delete({ url: `/twm/pro-storage-mat/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出成品入/出库子 Excel
|
||||
export const exportProStorageMat = async (params) => {
|
||||
return await request.download({ url: `/twm/pro-storage-mat/export-excel`, params })
|
||||
}
|
||||
|
||||
@ -74,6 +74,7 @@ declare module 'vue' {
|
||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||
ElTag: typeof import('element-plus/es')['ElTag']
|
||||
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
ElTree: typeof import('element-plus/es')['ElTree']
|
||||
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
|
||||
@ -90,6 +91,7 @@ declare module 'vue' {
|
||||
InputPassword: typeof import('./../components/InputPassword/src/InputPassword.vue')['default']
|
||||
InputWithColor: typeof import('./../components/InputWithColor/index.vue')['default']
|
||||
MagicCubeEditor: typeof import('./../components/MagicCubeEditor/index.vue')['default']
|
||||
MaterialSelectDialog: typeof import('./../views/biz/proreturn/MaterialSelectDialog.vue')['default']
|
||||
Pagination: typeof import('./../components/Pagination/index.vue')['default']
|
||||
ProcessDesigner: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue')['default']
|
||||
ProcessPalette: typeof import('./../components/bpmnProcessDesigner/package/palette/ProcessPalette.vue')['default']
|
||||
@ -97,6 +99,8 @@ declare module 'vue' {
|
||||
Propack: typeof import('./../api/biz/propack/index.ts')['default']
|
||||
ProPackForm: typeof import('./../views/biz/prostorage/ProPackForm.vue')['default']
|
||||
PropertiesPanel: typeof import('./../components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue')['default']
|
||||
Proreturn: typeof import('./../views/biz/proreturn/index.vue')['default']
|
||||
ProReturnForm: typeof import('./../views/biz/proreturn/ProReturnForm.vue')['default']
|
||||
Prostorage: typeof import('./../views/biz/prostorage/index.vue')['default']
|
||||
ProStorageForm: typeof import('./../views/biz/prostorage/ProStorageForm.vue')['default']
|
||||
Qrcode: typeof import('./../components/Qrcode/src/Qrcode.vue')['default']
|
||||
@ -109,6 +113,9 @@ declare module 'vue' {
|
||||
ShortcutDateRangePicker: typeof import('./../components/ShortcutDateRangePicker/index.vue')['default']
|
||||
SignalAndMessage: typeof import('./../components/bpmnProcessDesigner/package/penal/signal-message/SignalAndMessage.vue')['default']
|
||||
Sticky: typeof import('./../components/Sticky/src/Sticky.vue')['default']
|
||||
StorageForm: typeof import('./../views/biz/proreturn/StorageForm.vue')['default']
|
||||
Storagemat: typeof import('./../views/biz/storagemat/index.vue')['default']
|
||||
StorageMatForm: typeof import('./../views/biz/storagemat/StorageMatForm.vue')['default']
|
||||
SummaryCard: typeof import('./../components/SummaryCard/index.vue')['default']
|
||||
Table: typeof import('./../components/Table/src/Table.vue')['default']
|
||||
Tooltip: typeof import('./../components/Tooltip/src/Tooltip.vue')['default']
|
||||
|
||||
@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="800px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="产品名称" prop="matName" required>
|
||||
<div class="flex items-center gap-2">
|
||||
<el-input v-model="formData.matName" placeholder="请选择产品名称" :disabled="formType === 'update'" class="flex-1" @click="openMaterialSelect"/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="规格型号" prop="spec">
|
||||
<el-input v-model="formData.spec" placeholder="请输入规格型号" :disabled="formType === 'update'"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="批次重量" prop="lotWgt" required>
|
||||
<MoneyInput
|
||||
v-model="formData.lotWgt"
|
||||
:decimal-places="0"
|
||||
:allow-negative="false"
|
||||
:show-prefix="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态" prop="enabledStatus">
|
||||
<el-select v-model="formData.enabledStatus" placeholder="请选择状态">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入描述" :rows="3" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">保 存</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<!-- 物料选择弹窗 -->
|
||||
<MaterialSelect ref="materialSelectRef" @confirm="handleMaterialSelect" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import * as LotConfigApi from '@/api/biz/lotconfig'
|
||||
import { watch } from 'vue'
|
||||
import MaterialSelect from '@/views/biz/material/MaterialSelect.vue'
|
||||
import MoneyInput from '@/views/biz/components/MoneyInput.vue'
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
matCode: undefined,
|
||||
matId: undefined,
|
||||
matName: undefined,
|
||||
spec: undefined,
|
||||
lotWgt: undefined,
|
||||
enabledStatus: 0,
|
||||
description: undefined,
|
||||
})
|
||||
|
||||
// 物料选择弹窗引用
|
||||
const materialSelectRef = ref()
|
||||
|
||||
/** 打开物料选择弹窗 */
|
||||
const openMaterialSelect = () => {
|
||||
materialSelectRef.value?.open()
|
||||
}
|
||||
|
||||
/** 处理物料选择结果 */
|
||||
const handleMaterialSelect = (items: any[]) => {
|
||||
if (items && items.length > 0) {
|
||||
const item = items[0]
|
||||
formData.value.matName = item.matName
|
||||
formData.value.spec = item.spec
|
||||
formData.value.matCode = item.matCode
|
||||
formData.value.matId = item.id
|
||||
}
|
||||
}
|
||||
/** 弹窗关闭时通知父组件 */
|
||||
watch(dialogVisible, (val) => {
|
||||
if (!val) {
|
||||
emit('close')
|
||||
}
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
matName: [{ required: true, message: '产品名称不能为空', trigger: 'change' }],
|
||||
spec: [{ required: true, message: '规格型号不能为空', trigger: 'change' }],
|
||||
lotWgt: [{ required: true, message: '批次重量不能为空', trigger: 'blur' }],
|
||||
enabledStatus: [{ required: true, message: '启用状态不能为空', trigger: 'change' }],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await LotConfigApi.getLotConfig(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success', 'close']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as LotConfigApi.LotConfigVO
|
||||
if (formType.value === 'create') {
|
||||
await LotConfigApi.createLotConfig(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await LotConfigApi.updateLotConfig(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
matName: undefined,
|
||||
matCode: undefined,
|
||||
matId: undefined,
|
||||
spec: undefined,
|
||||
lotWgt: undefined,
|
||||
enabledStatus: 0,
|
||||
description: undefined,
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
185
mes-ui/mes-ui-admin-vue3/src/views/biz/lotconfig/index.vue
Normal file
185
mes-ui/mes-ui-admin-vue3/src/views/biz/lotconfig/index.vue
Normal file
@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="产品名称" prop="matName">
|
||||
<el-input
|
||||
v-model="queryParams.matName"
|
||||
placeholder="请输入产品名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态" prop="enabledStatus">
|
||||
<el-select
|
||||
v-model="queryParams.enabledStatus"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['biz:lot-config:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="序号" align="center" type="index" width="60px"/>
|
||||
|
||||
<el-table-column label="产品编码" align="center" prop="matCode" />
|
||||
<el-table-column label="产品名称" align="center" prop="matName" />
|
||||
<el-table-column label="规格型号" align="center" prop="matId" />
|
||||
<el-table-column label="批次重量" align="center" prop="lotWgt" />
|
||||
<el-table-column label="状态" align="center" prop="enabledStatus">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_STATUS" :value="scope.row.enabledStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="创建人" align="center" prop="creatorName" />
|
||||
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['biz:lot-config:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<LotConfigForm ref="formRef" @success="getList" @close="handleQuery"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as LotConfigApi from '@/api/biz/lotconfig'
|
||||
import LotConfigForm from './LotConfigForm.vue'
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
defineOptions({ name: 'LotConfig' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(false) // 列表的加载中(默认不加载)
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
matName: undefined,
|
||||
enabledStatus: undefined,
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await LotConfigApi.getLotConfigPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await LotConfigApi.deleteLotConfig(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await LotConfigApi.exportLotConfig(queryParams)
|
||||
download.excel(data, '产品批次重量配置.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
// 默认不自动查询,需手动点击搜索按钮
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,441 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="90%">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<!-- 基本信息 -->
|
||||
<div class="mb-6">
|
||||
<div style="font-weight: bold; margin-bottom: 15px;">基本信息</div>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="业务类型" prop="businessType">
|
||||
<el-select
|
||||
v-model="formData.businessType"
|
||||
placeholder="请选择"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
>
|
||||
<el-option label="成品出库" value="21" />
|
||||
<el-option label="盘亏出库" value="22" />
|
||||
<el-option label="生产退库" value="23" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="退库单号" prop="billNo">
|
||||
<el-input
|
||||
v-model="formData.billNo"
|
||||
placeholder="保存时自动生成"
|
||||
disabled
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="退库日期" prop="billDate">
|
||||
<el-date-picker
|
||||
v-model="formData.billDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择日期"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="单据状态" prop="status">
|
||||
<el-select v-model="formData.status" disabled class="!w-full">
|
||||
<el-option label="已创建" value="1" />
|
||||
<el-option label="已提交" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
placeholder="请输入"
|
||||
:disabled="formType === 'detail'"
|
||||
class="!w-full"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 明细信息 -->
|
||||
<div>
|
||||
<div style="font-weight: bold; margin-bottom: 15px; display: flex; align-items: center;">
|
||||
<span>明细信息</span>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="openMaterialSelect"
|
||||
v-if="formType !== 'detail'"
|
||||
class="ml-4"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" />新增
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="detailList"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
border
|
||||
style="width: 100%;"
|
||||
>
|
||||
<el-table-column label="序号" type="index" min-width="60px" align="center" />
|
||||
<el-table-column label="产品名称" min-width="150px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.productName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格型号" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.spec || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="批次号" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.lotNo || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存数量" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.stockQty || 0 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存袋数" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.stockBagQty || 0 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退库数量(*)" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<el-input
|
||||
v-model="scope.row.returnQty"
|
||||
placeholder="手动录入"
|
||||
:disabled="formType === 'detail'"
|
||||
class="bg-yellow-100"
|
||||
@input="calculateBagQty(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退库袋数(*)" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<el-input
|
||||
v-model="scope.row.returnBagQty"
|
||||
placeholder="手动录入"
|
||||
:disabled="formType === 'detail'"
|
||||
class="bg-yellow-100"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="仓储名称" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.storeHouseName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库区名称" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.storeAreaName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" min-width="80px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.unit || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品编码" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.productCode || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单袋规格" min-width="100px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.bagSpec || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="生产计划号" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.planNo || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="存货账单号" min-width="120px" align="center">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.stockBillNo || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="80px" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="formType !== 'detail'"
|
||||
link
|
||||
type="danger"
|
||||
@click="deleteDetailRow(scope.$index)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<!-- 库存选择弹窗 -->
|
||||
<ProStorageInventorySelectDialog
|
||||
ref="inventorySelectRef"
|
||||
@select="handleInventorySelect"
|
||||
@close="handleInventoryClose"
|
||||
/>
|
||||
|
||||
<template #footer>
|
||||
<div >
|
||||
<el-button @click="submitForm('save')" type="primary" :disabled="formLoading">
|
||||
保存
|
||||
</el-button>
|
||||
<el-button @click="submitForm('confirm')" type="primary" :disabled="formLoading">
|
||||
确认
|
||||
</el-button>
|
||||
<el-button @click="dialogVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch } from 'vue'
|
||||
import * as ProStorageApi from '@/api/biz/prostorage'
|
||||
import * as ProStorageMatApi from '@/api/biz/prostoragemat'
|
||||
import ProStorageInventorySelectDialog from '@/views/biz/prostorageinventory/ProStorageInventorySelectDialog.vue'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
billNo: undefined,
|
||||
businessType: '23', // 默认生产退库
|
||||
billDate: new Date().toISOString().split('T')[0], // 默认当日日期
|
||||
status: '1', // 默认已创建
|
||||
remark: undefined,
|
||||
})
|
||||
|
||||
// 明细列表
|
||||
const detailList = ref([])
|
||||
|
||||
// 库存选择弹窗引用
|
||||
const inventorySelectRef = ref()
|
||||
|
||||
/** 打开库存选择弹窗 */
|
||||
const openMaterialSelect = () => {
|
||||
inventorySelectRef.value?.open()
|
||||
}
|
||||
|
||||
/** 处理库存选择确认 */
|
||||
const handleInventorySelect = (selectedInventory: any[]) => {
|
||||
if (selectedInventory && selectedInventory.length > 0) {
|
||||
selectedInventory.forEach(inventory => {
|
||||
detailList.value.push({
|
||||
id: inventory.id,
|
||||
productName: inventory.matName,
|
||||
spec: inventory.spec,
|
||||
lotNo: inventory.lotNo,
|
||||
stockQty: inventory.yardQty,
|
||||
stockBagQty: inventory.packQty,
|
||||
returnQty: undefined,
|
||||
returnBagQty: undefined,
|
||||
storeHouseName: inventory.storeHouseName,
|
||||
storeAreaName: inventory.storeAreaName,
|
||||
unit: inventory.unit,
|
||||
productCode: inventory.matCode,
|
||||
bagSpec: inventory.bagSpec,
|
||||
planNo: inventory.planNo,
|
||||
stockBillNo: inventory.inventBillNo,
|
||||
materialId: inventory.materialId,
|
||||
storeHouseId: inventory.storeHouseId,
|
||||
storeAreaId: inventory.storeAreaId,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理库存选择关闭 */
|
||||
const handleInventoryClose = () => {
|
||||
// 弹窗关闭时的处理
|
||||
}
|
||||
|
||||
/** 弹窗关闭时通知父组件 */
|
||||
watch(dialogVisible, (val) => {
|
||||
if (!val) {
|
||||
emit('close')
|
||||
}
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
businessType: [{ required: true, message: '业务类型不能为空', trigger: 'change' }],
|
||||
billDate: [{ required: true, message: '退库日期不能为空', trigger: 'change' }],
|
||||
})
|
||||
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
|
||||
// 修改或详情时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = await ProStorageApi.getProStorage(id)
|
||||
formData.value = {
|
||||
...formData.value,
|
||||
...data,
|
||||
}
|
||||
// 加载明细数据
|
||||
await loadDetailList(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 加载明细列表 */
|
||||
const loadDetailList = async (stockId: number) => {
|
||||
try {
|
||||
const data = await ProStorageMatApi.getProStorageMatPageByStockId(stockId)
|
||||
detailList.value = (data.list || []).map(item => ({
|
||||
...item,
|
||||
returnQty: item.operatorQty, // 退库数量
|
||||
returnBagQty: item.bagQty, // 退库袋数
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载明细列表失败:', error)
|
||||
detailList.value = []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** 删除明细行 */
|
||||
const deleteDetailRow = (index: number) => {
|
||||
detailList.value.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 计算袋数(根据退库数量和单袋规格) */
|
||||
const calculateBagQty = (row: any) => {
|
||||
// 校验退库数量不能大于库存数量
|
||||
const returnQty = parseFloat(row.returnQty) || 0
|
||||
const stockQty = parseFloat(row.stockQty) || 0
|
||||
|
||||
if (returnQty > stockQty) {
|
||||
message.warning('退库数量不能大于库存数量')
|
||||
row.returnQty = stockQty.toString()
|
||||
}
|
||||
|
||||
// 计算袋数
|
||||
if (row.returnQty && row.bagSpec) {
|
||||
row.returnBagQty = Math.ceil(parseFloat(row.returnQty) / parseFloat(row.bagSpec))
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success', 'close']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async (action: string) => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
|
||||
// 校验明细列表
|
||||
if (detailList.value.length === 0) {
|
||||
message.error('请至少添加一条明细')
|
||||
return
|
||||
}
|
||||
|
||||
// 校验必填字段
|
||||
for (let i = 0; i < detailList.value.length; i++) {
|
||||
const row = detailList.value[i]
|
||||
if (!row.returnQty) {
|
||||
message.error(`第${i + 1}行退库数量不能为空`)
|
||||
return
|
||||
}
|
||||
if (!row.returnBagQty) {
|
||||
message.error(`第${i + 1}行退库袋数不能为空`)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const submitData = {
|
||||
...formData.value,
|
||||
details: detailList.value.map(item => ({
|
||||
id: item.id,
|
||||
returnQty: item.returnQty, // 退库数量
|
||||
returnBagQty: item.returnBagQty, // 退库袋数
|
||||
})),
|
||||
}
|
||||
|
||||
if (formType.value === 'create') {
|
||||
if (action === 'confirm') {
|
||||
submitData.status = '2' // 提交
|
||||
}
|
||||
await ProStorageApi.createProStorage(submitData)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
if (action === 'confirm') {
|
||||
submitData.status = '2' // 提交
|
||||
}
|
||||
await ProStorageApi.updateProStorage(submitData)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
billNo: undefined,
|
||||
businessType: '23',
|
||||
billDate: new Date().toISOString().split('T')[0], // 默认当日日期
|
||||
status: '1',
|
||||
remark: undefined,
|
||||
}
|
||||
detailList.value = []
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bg-yellow-100 {
|
||||
background-color: #fef3c7;
|
||||
}
|
||||
</style>
|
||||
309
mes-ui/mes-ui-admin-vue3/src/views/biz/proreturn/index.vue
Normal file
309
mes-ui/mes-ui-admin-vue3/src/views/biz/proreturn/index.vue
Normal file
@ -0,0 +1,309 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="退库日期" prop="billDate">
|
||||
<el-date-picker
|
||||
v-model="queryParams.billDate"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="退库单号" prop="billNo">
|
||||
<el-input
|
||||
v-model="queryParams.billNo"
|
||||
placeholder="请输入退库单号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="单据状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择单据状态"
|
||||
clearable
|
||||
class="!w-200px"
|
||||
>
|
||||
<el-option label="已创建" value="1" />
|
||||
<el-option label="已提交" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['twm:storage:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 退库单信息(主表) -->
|
||||
<ContentWrap>
|
||||
<el-card class="mb-10px">
|
||||
<template #header>
|
||||
<span class="font-bold">退库单信息</span>
|
||||
</template>
|
||||
<el-table
|
||||
ref="masterTableRef"
|
||||
v-loading="loading"
|
||||
:data="masterList"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
@row-click="handleMasterRowClick"
|
||||
highlight-current-row
|
||||
>
|
||||
<el-table-column type="selection" width="55px" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" width="60px" />
|
||||
<el-table-column label="业务类型" align="center" prop="businessType" min-width="100px">
|
||||
<template #default="scope">
|
||||
<span>{{ getBusinessTypeName(scope.row.businessType) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退库单号" align="center" prop="billNo" min-width="150px" />
|
||||
<el-table-column label="单据状态" align="center" prop="status" min-width="100px">
|
||||
<template #default="scope">
|
||||
<span :class="scope.row.status === '1' ? 'text-blue' : 'text-green'">
|
||||
{{ scope.row.status === '1' ? '已创建' : '已提交' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="退库日期" align="center" prop="billDate" :formatter="dateFormatter2" min-width="120px" />
|
||||
<el-table-column label="退库人员" align="center" prop="operatorName" min-width="100px" />
|
||||
<el-table-column label="操作" align="center" width="200px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['twm:storage:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="info"
|
||||
@click="handleViewDetail(scope.row)"
|
||||
>
|
||||
详情
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['twm:storage:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 主表分页 -->
|
||||
<Pagination
|
||||
:total="masterTotal"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getMasterList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 退库明细信息(子表) -->
|
||||
<el-card>
|
||||
<template #header>
|
||||
<span class="font-bold">退库明细信息</span>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="subLoading"
|
||||
:data="subList"
|
||||
:stripe="true"
|
||||
:show-overflow-tooltip="true"
|
||||
show-summary
|
||||
:summary-method="getSummary"
|
||||
>
|
||||
<el-table-column label="序号" align="center" type="index" width="60px" />
|
||||
<el-table-column label="产品编码" align="center" prop="matCode" min-width="120px" />
|
||||
<el-table-column label="产品名称" align="center" prop="matName" min-width="150px" />
|
||||
<el-table-column label="规格型号" align="center" prop="spec" min-width="120px" />
|
||||
<el-table-column label="退库数量" align="center" prop="operatorQty" min-width="100px" />
|
||||
<el-table-column label="退库袋数" align="center" prop="bagQty" min-width="100px" />
|
||||
<el-table-column label="批次号" align="center" prop="lotNo" min-width="120px" />
|
||||
<el-table-column label="仓储名称" align="center" prop="storeHouseName" min-width="120px" />
|
||||
<el-table-column label="库区名称" align="center" prop="storeAreaName" min-width="120px" />
|
||||
<el-table-column label="单位" align="center" prop="unit" min-width="80px" :formatter="getUnitName" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<ProReturnForm ref="formRef" @success="handleMasterRowClick(currentMasterRow)" @close="handleQuery"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { dateFormatter2, getCurrentSimMonthRange } from '@/utils/formatTime'
|
||||
import * as ProStorageApi from '@/api/biz/prostorage'
|
||||
import * as ProStorageMatApi from '@/api/biz/prostoragemat'
|
||||
import ProReturnForm from './ProReturnForm.vue'
|
||||
import { getUnitName, getDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
|
||||
defineOptions({ name: 'ProReturn' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
// ========== 主表相关 ==========
|
||||
const loading = ref(false) // 主表加载中
|
||||
const masterList = ref([]) // 主表数据
|
||||
const masterTotal = ref(0) // 主表总页数
|
||||
const masterTableRef = ref() // 主表引用
|
||||
const currentMasterRow = ref(null) // 当前选中的主表行
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
billNo: undefined,
|
||||
billDate: getCurrentSimMonthRange(),
|
||||
status: undefined,
|
||||
operatorType: "2",
|
||||
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
||||
/** 获取业务类型名称 */
|
||||
const getBusinessTypeName = (type) => {
|
||||
const typeMap = {
|
||||
'21': '成品出库',
|
||||
'22': '盘亏出库',
|
||||
'23': '生产退库',
|
||||
}
|
||||
return typeMap[type] || type
|
||||
}
|
||||
|
||||
/** 查询主表列表 */
|
||||
const getMasterList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ProStorageApi.getProStoragePage(queryParams)
|
||||
masterList.value = data.list
|
||||
masterTotal.value = data.total
|
||||
|
||||
// 如果有数据,默认选中第一行
|
||||
if (data.list && data.list.length > 0) {
|
||||
handleMasterRowClick(data.list[0])
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 主表行点击事件 */
|
||||
const handleMasterRowClick = async (row) => {
|
||||
if (!row) return
|
||||
currentMasterRow.value = row
|
||||
await getSubList(row.id)
|
||||
}
|
||||
|
||||
// ========== 子表相关 ==========
|
||||
const subLoading = ref(false) // 子表加载中
|
||||
const subList = ref([]) // 子表数据
|
||||
|
||||
/** 查询子表列表 */
|
||||
const getSubList = async (stockId: number) => {
|
||||
if (!stockId) {
|
||||
subList.value = []
|
||||
return
|
||||
}
|
||||
|
||||
subLoading.value = true
|
||||
try {
|
||||
const data = await ProStorageMatApi.getProStorageMatPageByStockId(stockId)
|
||||
subList.value = data || []
|
||||
} finally {
|
||||
subLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 子表汇总方法 */
|
||||
const getSummary = (param) => {
|
||||
const { columns, data } = param
|
||||
const sums = []
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
sums[index] = '合计'
|
||||
} else if (column.prop === 'operatorQty') {
|
||||
const values = data.map(item => Number(item[column.prop]) || 0)
|
||||
sums[index] = values.reduce((prev, curr) => prev + curr, 0)
|
||||
} else if (column.prop === 'bagQty') {
|
||||
const values = data.map(item => Number(item[column.prop]) || 0)
|
||||
sums[index] = values.reduce((prev, curr) => prev + curr, 0)
|
||||
} else {
|
||||
sums[index] = ''
|
||||
}
|
||||
})
|
||||
return sums
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getMasterList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
const handleViewDetail = (row) => {
|
||||
handleMasterRowClick(row)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await ProStorageApi.deleteProStorage(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getMasterList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
// 默认不自动查询,需手动点击搜索按钮
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.text-blue {
|
||||
color: #409EFF;
|
||||
}
|
||||
.text-green {
|
||||
color: #67C23A;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,282 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="800px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="包装单号(PK+年份+月份+4位流水号)" prop="packNo">
|
||||
<el-input v-model="formData.packNo" placeholder="请输入包装单号(PK+年份+月份+4位流水号)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品id" prop="materialId">
|
||||
<el-input v-model="formData.materialId" placeholder="请输入产品id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品编码" prop="materialCode">
|
||||
<el-input v-model="formData.materialCode" placeholder="请输入产品编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产品名称" prop="materialName">
|
||||
<el-input v-model="formData.materialName" placeholder="请输入产品名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格型号" prop="spec">
|
||||
<el-input v-model="formData.spec" placeholder="请输入规格型号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位" prop="unit">
|
||||
<el-input v-model="formData.unit" placeholder="请输入单位" />
|
||||
</el-form-item>
|
||||
<el-form-item label="包装实绩数量" prop="packQtyAct">
|
||||
<el-input v-model="formData.packQtyAct" placeholder="请输入包装实绩数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="包装袋数" prop="packBagQty">
|
||||
<el-input v-model="formData.packBagQty" placeholder="请输入包装袋数" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单袋规格" prop="bagSpec">
|
||||
<el-input v-model="formData.bagSpec" placeholder="请输入单袋规格" />
|
||||
</el-form-item>
|
||||
<el-form-item label="批次号" prop="lotNo">
|
||||
<el-input v-model="formData.lotNo" placeholder="请输入批次号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料类型(1 原材料 2 半成品 3 成品 4 联产品 )" prop="matType">
|
||||
<el-select v-model="formData.matType" placeholder="请选择物料类型(1 原材料 2 半成品 3 成品 4 联产品 )">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装开始时间" prop="packBgDtime">
|
||||
<el-date-picker
|
||||
v-model="formData.packBgDtime"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择包装开始时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装结束时间" prop="outEndDtime">
|
||||
<el-date-picker
|
||||
v-model="formData.outEndDtime"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择包装结束时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装日期" prop="proDate">
|
||||
<el-date-picker
|
||||
v-model="formData.proDate"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择包装日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装班组" prop="groupCd">
|
||||
<el-input v-model="formData.groupCd" placeholder="请输入包装班组" />
|
||||
</el-form-item>
|
||||
<el-form-item label="包装班次" prop="shiftCd">
|
||||
<el-input v-model="formData.shiftCd" placeholder="请输入包装班次" />
|
||||
</el-form-item>
|
||||
<el-form-item label="生产计划id" prop="planId">
|
||||
<el-input v-model="formData.planId" placeholder="请输入生产计划id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="生产计划号" prop="planNo">
|
||||
<el-input v-model="formData.planNo" placeholder="请输入生产计划号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="机台编码" prop="machineCd">
|
||||
<el-input v-model="formData.machineCd" placeholder="请输入机台编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="机台名称" prop="machineName">
|
||||
<el-input v-model="formData.machineName" placeholder="请输入机台名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="机台id" prop="machineId">
|
||||
<el-input v-model="formData.machineId" placeholder="请输入机台id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产线编码" prop="lineCd">
|
||||
<el-input v-model="formData.lineCd" placeholder="请输入产线编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产线名称" prop="lineName">
|
||||
<el-input v-model="formData.lineName" placeholder="请输入产线名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="产线id" prop="lineId">
|
||||
<el-input v-model="formData.lineId" placeholder="请输入产线id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="入库状态( 1 待入库 2 部分入库 3 已入库)" prop="packStatus">
|
||||
<el-radio-group v-model="formData.packStatus">
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="损耗数量" prop="lossQty">
|
||||
<el-input v-model="formData.lossQty" placeholder="请输入损耗数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="判定结果(0 合格 1 不合格 2让步接收)" prop="judgResult">
|
||||
<el-input v-model="formData.judgResult" placeholder="请输入判定结果(0 合格 1 不合格 2让步接收)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验状态(0-未检验 1已检验)" prop="inspStatus">
|
||||
<el-radio-group v-model="formData.inspStatus">
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装理论数量" prop="packQtyTheory">
|
||||
<el-input v-model="formData.packQtyTheory" placeholder="请输入包装理论数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验日期" prop="inspDate">
|
||||
<el-date-picker
|
||||
v-model="formData.inspDate"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择检验日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="检验人员id" prop="checkUserId">
|
||||
<el-input v-model="formData.checkUserId" placeholder="请输入检验人员id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验人员名称" prop="checkUserName">
|
||||
<el-input v-model="formData.checkUserName" placeholder="请输入检验人员名称" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import * as ProPackApi from '@/api/biz/propack'
|
||||
import { watch } from 'vue'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
packNo: undefined,
|
||||
remark: undefined,
|
||||
materialId: undefined,
|
||||
materialCode: undefined,
|
||||
materialName: undefined,
|
||||
spec: undefined,
|
||||
unit: undefined,
|
||||
packQtyAct: undefined,
|
||||
packBagQty: undefined,
|
||||
bagSpec: undefined,
|
||||
lotNo: undefined,
|
||||
matType: undefined,
|
||||
packBgDtime: undefined,
|
||||
outEndDtime: undefined,
|
||||
proDate: undefined,
|
||||
groupCd: undefined,
|
||||
shiftCd: undefined,
|
||||
planId: undefined,
|
||||
planNo: undefined,
|
||||
machineCd: undefined,
|
||||
machineName: undefined,
|
||||
machineId: undefined,
|
||||
lineCd: undefined,
|
||||
lineName: undefined,
|
||||
lineId: undefined,
|
||||
packStatus: undefined,
|
||||
lossQty: undefined,
|
||||
judgResult: undefined,
|
||||
inspStatus: undefined,
|
||||
packQtyTheory: undefined,
|
||||
inspDate: undefined,
|
||||
checkUserId: undefined,
|
||||
checkUserName: undefined,
|
||||
})
|
||||
/** 弹窗关闭时通知父组件 */
|
||||
watch(dialogVisible, (val) => {
|
||||
if (!val) {
|
||||
emit('close')
|
||||
}
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await ProPackApi.getProPack(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success', 'close']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as ProPackApi.ProPackVO
|
||||
if (formType.value === 'create') {
|
||||
await ProPackApi.createProPack(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ProPackApi.updateProPack(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
packNo: undefined,
|
||||
remark: undefined,
|
||||
materialId: undefined,
|
||||
materialCode: undefined,
|
||||
materialName: undefined,
|
||||
spec: undefined,
|
||||
unit: undefined,
|
||||
packQtyAct: undefined,
|
||||
packBagQty: undefined,
|
||||
bagSpec: undefined,
|
||||
lotNo: undefined,
|
||||
matType: undefined,
|
||||
packBgDtime: undefined,
|
||||
outEndDtime: undefined,
|
||||
proDate: undefined,
|
||||
groupCd: undefined,
|
||||
shiftCd: undefined,
|
||||
planId: undefined,
|
||||
planNo: undefined,
|
||||
machineCd: undefined,
|
||||
machineName: undefined,
|
||||
machineId: undefined,
|
||||
lineCd: undefined,
|
||||
lineName: undefined,
|
||||
lineId: undefined,
|
||||
packStatus: undefined,
|
||||
lossQty: undefined,
|
||||
judgResult: undefined,
|
||||
inspStatus: undefined,
|
||||
packQtyTheory: undefined,
|
||||
inspDate: undefined,
|
||||
checkUserId: undefined,
|
||||
checkUserName: undefined,
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
338
mes-ui/mes-ui-admin-vue3/src/views/biz/prostorage/index.vue
Normal file
338
mes-ui/mes-ui-admin-vue3/src/views/biz/prostorage/index.vue
Normal file
@ -0,0 +1,338 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="包装日期" prop="proDate">
|
||||
<el-date-picker
|
||||
v-model="queryParams.proDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="包装机台" prop="machineCd">
|
||||
<el-select
|
||||
v-model="queryParams.machineCd"
|
||||
placeholder="请选择包装机台"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in machineOptions"
|
||||
:key="item.id"
|
||||
:label="item.machineName"
|
||||
:value="item.machineCd"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 查询
|
||||
</el-button>
|
||||
<el-button type="primary" plain>
|
||||
<Icon icon="ep:grid" class="mr-5px" /> 垛位推荐
|
||||
</el-button>
|
||||
<el-button type="success" plain @click="handleStorage">
|
||||
<Icon icon="ep:download" class="mr-5px" /> 入库
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" ref="tableRef">
|
||||
<el-table-column type="selection" width="55px" align="center" fixed="left" />
|
||||
<el-table-column label="序号" align="center" type="index" width="60px" fixed="left" />
|
||||
<el-table-column label="产品名称" align="center" prop="materialName" width="150px" fixed="left" />
|
||||
<el-table-column label="规格型号" align="center" prop="spec" width="120px" fixed="left" />
|
||||
<el-table-column label="批次号" align="center" prop="lotNo" width="150px" fixed="left" />
|
||||
<el-table-column label="仓储 (*)" min-width="150px" align="center">
|
||||
<template #default="scope">
|
||||
<!-- pack_status = 3 时显示文本,其他状态显示下拉框 -->
|
||||
<template v-if="scope.row.packStatus === '3'">
|
||||
<span>{{ scope.row.warehouseName}}</span>
|
||||
</template>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="scope.row.storeHouseId"
|
||||
placeholder="请选择仓储"
|
||||
class="!w-full"
|
||||
@change="handleWarehouseChange(scope.row)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in warehouseOptions"
|
||||
:key="item.id"
|
||||
:label="item.storeHouseName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库区 (*)" min-width="150px" align="center">
|
||||
<template #default="scope">
|
||||
<!-- pack_status = 3 时显示文本,其他状态显示下拉框 -->
|
||||
<template v-if="scope.row.packStatus === '3'">
|
||||
<span>{{ scope.row.areaName }}</span>
|
||||
</template>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="scope.row.storeAreaId"
|
||||
placeholder="请选择库区"
|
||||
class="!w-full"
|
||||
@change="handleAreaChange(scope.row)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in (scope.row.areaOptions || [])"
|
||||
:key="item.id"
|
||||
:label="item.storeAreaName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否检验" align="center" prop="inspStatus" width="100px">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.inspStatus === '1' ? 'success' : 'info'">
|
||||
{{ scope.row.inspStatus === '1' ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检验结果" align="center" prop="judgResult" width="100px">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.judgResult === '0' ? 'success' : (scope.row.judgResult === '1' ? 'danger' : 'warning')">
|
||||
{{ scope.row.judgResult === '0' ? '合格' : (scope.row.judgResult === '1' ? '不合格' : '让步接收') }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="包装袋数" align="center" prop="packBagQty" width="100px" />
|
||||
<el-table-column label="单袋规格" align="center" prop="bagSpec" width="100px" />
|
||||
<el-table-column label="包装数量" align="center" prop="packQtyAct" width="100px" />
|
||||
<el-table-column label="包装机台" align="center" prop="machineName" width="120px" />
|
||||
<el-table-column label="活化炉机台" align="center" prop="activationMachineName" width="120px" />
|
||||
<el-table-column label="生产计划号" align="center" prop="planNo" width="150px" />
|
||||
<el-table-column label="单位" align="center" prop="unit" width="80px" />
|
||||
<el-table-column label="包装日期" align="center" prop="proDate" width="110px" :formatter="dateFormatter2" />
|
||||
<el-table-column label="包装单号" align="center" prop="packNo" width="180px" />
|
||||
<el-table-column label="班次" align="center" prop="shiftCd" width="100px" />
|
||||
<el-table-column label="产品编码" align="center" prop="materialCode" width="180px" />
|
||||
<el-table-column label="备注" align="center" prop="remark" width="180px" />
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { dateFormatter2, getCurrentSimMonthRange } from '@/utils/formatTime'
|
||||
import * as ProPackApi from '@/api/biz/propack'
|
||||
import * as ProStorageApi from '@/api/biz/prostorage'
|
||||
import * as WarehouseApi from '@/api/biz/storehouse'
|
||||
import * as AreaApi from '@/api/biz/storearea'
|
||||
import * as MachineApi from '@/api/biz/machine'
|
||||
|
||||
defineOptions({ name: 'ProStorage' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(false) // 列表的加载中(默认不加载)
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const warehouseOptions = ref([]) // 仓库选项
|
||||
const machineOptions = ref([]) // 包装机台选项
|
||||
const tableRef = ref() // 表格引用
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
proDate: getCurrentSimMonthRange(),
|
||||
machineCd: undefined,
|
||||
packStatus: ["1", "2"]
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
|
||||
/** 加载包装机台列表 */
|
||||
const loadMachineList = async () => {
|
||||
try {
|
||||
const data = await MachineApi.getMachineDropdown({})
|
||||
machineOptions.value = data || []
|
||||
} catch (error) {
|
||||
console.error('加载包装机台列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载仓库列表 */
|
||||
const loadWarehouseList = async () => {
|
||||
try {
|
||||
const list = await WarehouseApi.getStoreHouseSelect("1")
|
||||
warehouseOptions.value = (list || []).map((item: any) => ({
|
||||
...item,
|
||||
id: Number(item.id)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载仓库列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理仓库变化,重新加载库区 */
|
||||
const handleWarehouseChange = async (row: any) => {
|
||||
row.storeAreaId = undefined // 清空库区选择
|
||||
row.storeAreaName = undefined
|
||||
|
||||
if (row.storeHouseId) {
|
||||
// 获取选中的仓储信息
|
||||
const warehouse = warehouseOptions.value.find((w: any) => w.id === row.storeHouseId)
|
||||
if (warehouse) {
|
||||
row.storeHouseCd = warehouse.storeHouseCd
|
||||
row.storeHouseName = warehouse.storeHouseName
|
||||
}
|
||||
|
||||
try {
|
||||
const list = await AreaApi.getStoreAreaSelect(row.storeHouseId)
|
||||
row.areaOptions = (list || []).map((area: any) => ({
|
||||
...area,
|
||||
id: Number(area.id)
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error('加载库区列表失败:', error)
|
||||
row.areaOptions = []
|
||||
}
|
||||
} else {
|
||||
row.areaOptions = []
|
||||
row.storeHouseCd = undefined
|
||||
row.storeHouseName = undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理库区变化,获取库区信息 */
|
||||
const handleAreaChange = (row: any) => {
|
||||
if (row.storeAreaId && row.areaOptions) {
|
||||
const area = row.areaOptions.find((a: any) => a.id === row.storeAreaId)
|
||||
if (area) {
|
||||
row.storeAreCd = area.storeAreCd
|
||||
row.storeAreaName = area.storeAreaName
|
||||
}
|
||||
} else {
|
||||
row.storeAreCd = undefined
|
||||
row.storeAreaName = undefined
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ProPackApi.getProPackPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 入库操作 */
|
||||
const handleStorage = async () => {
|
||||
// 获取选中的行
|
||||
const selectedRows = tableRef.value?.getSelectionRows() || []
|
||||
|
||||
if (selectedRows.length === 0) {
|
||||
message.warning('请至少选择一条记录')
|
||||
return
|
||||
}
|
||||
|
||||
// 验证每条选中记录的仓储和库区是否已选择
|
||||
const invalidRows = []
|
||||
const validData = []
|
||||
|
||||
selectedRows.forEach((row, index) => {
|
||||
// packStatus = 3 的记录不能入库(已入库状态)
|
||||
if (row.packStatus === '3') {
|
||||
invalidRows.push(`第${index + 1}条记录(批次号: ${row.lotNo})已入库,无法重复入库`)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证仓储是否选择
|
||||
if (!row.storeHouseId) {
|
||||
invalidRows.push(`第${index + 1}条记录(批次号: ${row.lotNo})请选择仓储`)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证库区是否选择
|
||||
if (!row.storeAreaId) {
|
||||
invalidRows.push(`第${index + 1}条记录(批次号: ${row.lotNo})请选择库区`)
|
||||
return
|
||||
}
|
||||
|
||||
// 收集有效数据
|
||||
validData.push({
|
||||
id: row.id,
|
||||
storeHouseId: row.storeHouseId,
|
||||
storeAreaId: row.storeAreaId,
|
||||
storeHouseCd: row.storeHouseCd,
|
||||
storeHouseName: row.storeHouseName,
|
||||
storeAreCd: row.storeAreCd,
|
||||
storeAreaName: row.storeAreaName,
|
||||
lotNo: row.lotNo,
|
||||
})
|
||||
})
|
||||
|
||||
// 如果有验证失败的记录,显示错误信息
|
||||
if (invalidRows.length > 0) {
|
||||
message.error(invalidRows.join('\n'))
|
||||
return
|
||||
}
|
||||
|
||||
// 确认入库
|
||||
try {
|
||||
// 调用入库接口(这里需要根据实际API调整)
|
||||
await ProStorageApi.saveProStorage(validData)
|
||||
|
||||
console.log('准备入库的数据:', validData)
|
||||
message.success('入库成功')
|
||||
|
||||
// 刷新列表
|
||||
handleQuery()
|
||||
|
||||
// 清空选择
|
||||
tableRef.value?.clearSelection()
|
||||
} catch (error) {
|
||||
console.error('入库失败:', error)
|
||||
message.error('入库失败')
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
// 加载包装机台列表
|
||||
loadMachineList()
|
||||
// 加载仓库列表
|
||||
loadWarehouseList()
|
||||
// 默认不自动查询,需手动点击搜索按钮
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,187 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible" width="800px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="入/出库Id" prop="stockId">
|
||||
<el-input v-model="formData.stockId" placeholder="请输入入/出库Id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="description">
|
||||
<Editor v-model="formData.description" height="150px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="仓储id" prop="storeHouseId">
|
||||
<el-input v-model="formData.storeHouseId" placeholder="请输入仓储id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="库区id" prop="storeAreaId">
|
||||
<el-input v-model="formData.storeAreaId" placeholder="请输入库区id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="仓储编码" prop="storeHouseCd">
|
||||
<el-input v-model="formData.storeHouseCd" placeholder="请输入仓储编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="仓储名称" prop="storeHouseName">
|
||||
<el-input v-model="formData.storeHouseName" placeholder="请输入仓储名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="库区编码" prop="storeAreCd">
|
||||
<el-input v-model="formData.storeAreCd" placeholder="请输入库区编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="库区名称" prop="storeAreaName">
|
||||
<el-input v-model="formData.storeAreaName" placeholder="请输入库区名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料id" prop="materialId">
|
||||
<el-input v-model="formData.materialId" placeholder="请输入物料id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料名称" prop="matName">
|
||||
<el-input v-model="formData.matName" placeholder="请输入物料名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料编码" prop="matCode">
|
||||
<el-input v-model="formData.matCode" placeholder="请输入物料编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格型号" prop="spec">
|
||||
<el-input v-model="formData.spec" placeholder="请输入规格型号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位" prop="unit">
|
||||
<el-input v-model="formData.unit" placeholder="请输入单位" />
|
||||
</el-form-item>
|
||||
<el-form-item label="批次号" prop="lotNo">
|
||||
<el-input v-model="formData.lotNo" placeholder="请输入批次号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作数量" prop="operatorQty">
|
||||
<el-input v-model="formData.operatorQty" placeholder="请输入操作数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="采购数量" prop="purQty">
|
||||
<el-input v-model="formData.purQty" placeholder="请输入采购数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="来源数量" prop="sourceQty">
|
||||
<el-input v-model="formData.sourceQty" placeholder="请输入来源数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="来源单号id" prop="sourceId">
|
||||
<el-input v-model="formData.sourceId" placeholder="请输入来源单号id" />
|
||||
</el-form-item>
|
||||
<el-form-item label="关联单号id" prop="relarionId">
|
||||
<el-input v-model="formData.relarionId" placeholder="请输入关联单号id" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import * as StorageMatApi from '@/api/twm/storagemat'
|
||||
import { watch } from 'vue'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
stockId: undefined,
|
||||
description: undefined,
|
||||
storeHouseId: undefined,
|
||||
storeAreaId: undefined,
|
||||
storeHouseCd: undefined,
|
||||
storeHouseName: undefined,
|
||||
storeAreCd: undefined,
|
||||
storeAreaName: undefined,
|
||||
materialId: undefined,
|
||||
matName: undefined,
|
||||
matCode: undefined,
|
||||
spec: undefined,
|
||||
unit: undefined,
|
||||
lotNo: undefined,
|
||||
operatorQty: undefined,
|
||||
purQty: undefined,
|
||||
sourceQty: undefined,
|
||||
sourceId: undefined,
|
||||
relarionId: undefined,
|
||||
})
|
||||
/** 弹窗关闭时通知父组件 */
|
||||
watch(dialogVisible, (val) => {
|
||||
if (!val) {
|
||||
emit('close')
|
||||
}
|
||||
})
|
||||
|
||||
const formRules = reactive({
|
||||
stockId: [{ required: true, message: '入/出库Id不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await StorageMatApi.getStorageMat(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success', 'close']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as StorageMatApi.StorageMatVO
|
||||
if (formType.value === 'create') {
|
||||
await StorageMatApi.createStorageMat(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await StorageMatApi.updateStorageMat(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
stockId: undefined,
|
||||
description: undefined,
|
||||
storeHouseId: undefined,
|
||||
storeAreaId: undefined,
|
||||
storeHouseCd: undefined,
|
||||
storeHouseName: undefined,
|
||||
storeAreCd: undefined,
|
||||
storeAreaName: undefined,
|
||||
materialId: undefined,
|
||||
matName: undefined,
|
||||
matCode: undefined,
|
||||
spec: undefined,
|
||||
unit: undefined,
|
||||
lotNo: undefined,
|
||||
operatorQty: undefined,
|
||||
purQty: undefined,
|
||||
sourceQty: undefined,
|
||||
sourceId: undefined,
|
||||
relarionId: undefined,
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
375
mes-ui/mes-ui-admin-vue3/src/views/biz/storagemat/index.vue
Normal file
375
mes-ui/mes-ui-admin-vue3/src/views/biz/storagemat/index.vue
Normal file
@ -0,0 +1,375 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="入/出库Id" prop="stockId">
|
||||
<el-input
|
||||
v-model="queryParams.stockId"
|
||||
placeholder="请输入入/出库Id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓储id" prop="storeHouseId">
|
||||
<el-input
|
||||
v-model="queryParams.storeHouseId"
|
||||
placeholder="请输入仓储id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="库区id" prop="storeAreaId">
|
||||
<el-input
|
||||
v-model="queryParams.storeAreaId"
|
||||
placeholder="请输入库区id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓储编码" prop="storeHouseCd">
|
||||
<el-input
|
||||
v-model="queryParams.storeHouseCd"
|
||||
placeholder="请输入仓储编码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓储名称" prop="storeHouseName">
|
||||
<el-input
|
||||
v-model="queryParams.storeHouseName"
|
||||
placeholder="请输入仓储名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="库区编码" prop="storeAreCd">
|
||||
<el-input
|
||||
v-model="queryParams.storeAreCd"
|
||||
placeholder="请输入库区编码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="库区名称" prop="storeAreaName">
|
||||
<el-input
|
||||
v-model="queryParams.storeAreaName"
|
||||
placeholder="请输入库区名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料id" prop="materialId">
|
||||
<el-input
|
||||
v-model="queryParams.materialId"
|
||||
placeholder="请输入物料id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料名称" prop="matName">
|
||||
<el-input
|
||||
v-model="queryParams.matName"
|
||||
placeholder="请输入物料名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料编码" prop="matCode">
|
||||
<el-input
|
||||
v-model="queryParams.matCode"
|
||||
placeholder="请输入物料编码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="规格型号" prop="spec">
|
||||
<el-input
|
||||
v-model="queryParams.spec"
|
||||
placeholder="请输入规格型号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="单位" prop="unit">
|
||||
<el-input
|
||||
v-model="queryParams.unit"
|
||||
placeholder="请输入单位"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="批次号" prop="lotNo">
|
||||
<el-input
|
||||
v-model="queryParams.lotNo"
|
||||
placeholder="请输入批次号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作数量" prop="operatorQty">
|
||||
<el-input
|
||||
v-model="queryParams.operatorQty"
|
||||
placeholder="请输入操作数量"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="采购数量" prop="purQty">
|
||||
<el-input
|
||||
v-model="queryParams.purQty"
|
||||
placeholder="请输入采购数量"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="来源数量" prop="sourceQty">
|
||||
<el-input
|
||||
v-model="queryParams.sourceQty"
|
||||
placeholder="请输入来源数量"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="来源单号id" prop="sourceId">
|
||||
<el-input
|
||||
v-model="queryParams.sourceId"
|
||||
placeholder="请输入来源单号id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="关联单号id" prop="relarionId">
|
||||
<el-input
|
||||
v-model="queryParams.relarionId"
|
||||
placeholder="请输入关联单号id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['twm:storage-mat:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['twm:storage-mat:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="序号" align="center" type="index" width="60px"/>
|
||||
<el-table-column label="入/出库Id" align="center" prop="stockId" />
|
||||
<el-table-column label="备注" align="center" prop="description" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="仓储id" align="center" prop="storeHouseId" />
|
||||
<el-table-column label="库区id" align="center" prop="storeAreaId" />
|
||||
<el-table-column label="仓储编码" align="center" prop="storeHouseCd" />
|
||||
<el-table-column label="仓储名称" align="center" prop="storeHouseName" />
|
||||
<el-table-column label="库区编码" align="center" prop="storeAreCd" />
|
||||
<el-table-column label="库区名称" align="center" prop="storeAreaName" />
|
||||
<el-table-column label="物料id" align="center" prop="materialId" />
|
||||
<el-table-column label="物料名称" align="center" prop="matName" />
|
||||
<el-table-column label="物料编码" align="center" prop="matCode" />
|
||||
<el-table-column label="规格型号" align="center" prop="spec" />
|
||||
<el-table-column label="单位" align="center" prop="unit" />
|
||||
<el-table-column label="批次号" align="center" prop="lotNo" />
|
||||
<el-table-column label="操作数量" align="center" prop="operatorQty" />
|
||||
<el-table-column label="采购数量" align="center" prop="purQty" />
|
||||
<el-table-column label="来源数量" align="center" prop="sourceQty" />
|
||||
<el-table-column label="来源单号id" align="center" prop="sourceId" />
|
||||
<el-table-column label="关联单号id" align="center" prop="relarionId" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['twm:storage-mat:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['twm:storage-mat:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<StorageMatForm ref="formRef" @success="getList" @close="handleQuery"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as StorageMatApi from '@/api/twm/storagemat'
|
||||
import StorageMatForm from './StorageMatForm.vue'
|
||||
|
||||
defineOptions({ name: 'StorageMat' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(false) // 列表的加载中(默认不加载)
|
||||
const list = ref([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
stockId: undefined,
|
||||
description: undefined,
|
||||
createTime: [],
|
||||
storeHouseId: undefined,
|
||||
storeAreaId: undefined,
|
||||
storeHouseCd: undefined,
|
||||
storeHouseName: undefined,
|
||||
storeAreCd: undefined,
|
||||
storeAreaName: undefined,
|
||||
materialId: undefined,
|
||||
matName: undefined,
|
||||
matCode: undefined,
|
||||
spec: undefined,
|
||||
unit: undefined,
|
||||
lotNo: undefined,
|
||||
operatorQty: undefined,
|
||||
purQty: undefined,
|
||||
sourceQty: undefined,
|
||||
sourceId: undefined,
|
||||
relarionId: undefined,
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await StorageMatApi.getStorageMatPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await StorageMatApi.deleteStorageMat(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await StorageMatApi.exportStorageMat(queryParams)
|
||||
download.excel(data, '入/出库物料.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
// 默认不自动查询,需手动点击搜索按钮
|
||||
})
|
||||
</script>
|
||||
Loading…
Reference in New Issue
Block a user