feat:载具信息表
This commit is contained in:
@@ -19,4 +19,7 @@ public interface ErrorCodeConstants {
|
||||
|
||||
// ================ 组盘记录相关错误码 =================
|
||||
ErrorCode GROUP_PLATE_NOT_EXISTS = new ErrorCode(9, "组盘记录不存在");
|
||||
|
||||
// ========== 载具信息相关错误码 ==========
|
||||
ErrorCode STORAGE_VEHICLE_INFO_NOT_EXISTS = new ErrorCode(11, "载具信息不存在");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package cn.code.nl.module.wms.controller.admin.storagevehicleinfo;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.*;
|
||||
import jakarta.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.code.nl.framework.common.pojo.PageParam;
|
||||
import cn.code.nl.framework.common.pojo.PageResult;
|
||||
import cn.code.nl.framework.common.pojo.CommonResult;
|
||||
import cn.code.nl.framework.common.util.object.BeanUtils;
|
||||
import static cn.code.nl.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.code.nl.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.code.nl.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import static cn.code.nl.framework.apilog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo.*;
|
||||
import cn.code.nl.module.wms.dal.dataobject.storagevehicleinfo.StorageVehicleInfoDO;
|
||||
import cn.code.nl.module.wms.service.storagevehicleinfo.StorageVehicleInfoService;
|
||||
|
||||
@Tag(name = "管理后台 - 载具信息")
|
||||
@RestController
|
||||
@RequestMapping("/wms/storage-vehicle-info")
|
||||
@Validated
|
||||
public class StorageVehicleInfoController {
|
||||
|
||||
@Resource
|
||||
private StorageVehicleInfoService storageVehicleInfoService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建载具信息")
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:create')")
|
||||
public CommonResult<Long> createStorageVehicleInfo(@Valid @RequestBody StorageVehicleInfoSaveReqVO createReqVO) {
|
||||
return success(storageVehicleInfoService.createStorageVehicleInfo(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新载具信息")
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:update')")
|
||||
public CommonResult<Boolean> updateStorageVehicleInfo(@Valid @RequestBody StorageVehicleInfoSaveReqVO updateReqVO) {
|
||||
storageVehicleInfoService.updateStorageVehicleInfo(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除载具信息")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:delete')")
|
||||
public CommonResult<Boolean> deleteStorageVehicleInfo(@RequestParam("id") Long id) {
|
||||
storageVehicleInfoService.deleteStorageVehicleInfo(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete-list")
|
||||
@Parameter(name = "ids", description = "编号", required = true)
|
||||
@Operation(summary = "批量删除载具信息")
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:delete')")
|
||||
public CommonResult<Boolean> deleteStorageVehicleInfoList(@RequestParam("ids") List<Long> ids) {
|
||||
storageVehicleInfoService.deleteStorageVehicleInfoListByIds(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得载具信息")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:query')")
|
||||
public CommonResult<StorageVehicleInfoRespVO> getStorageVehicleInfo(@RequestParam("id") Long id) {
|
||||
StorageVehicleInfoDO storageVehicleInfo = storageVehicleInfoService.getStorageVehicleInfo(id);
|
||||
return success(BeanUtils.toBean(storageVehicleInfo, StorageVehicleInfoRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得载具信息分页")
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:query')")
|
||||
public CommonResult<PageResult<StorageVehicleInfoRespVO>> getStorageVehicleInfoPage(@Valid StorageVehicleInfoPageReqVO pageReqVO) {
|
||||
PageResult<StorageVehicleInfoDO> pageResult = storageVehicleInfoService.getStorageVehicleInfoPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, StorageVehicleInfoRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出载具信息 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('wms:storage-vehicle-info:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportStorageVehicleInfoExcel(@Valid StorageVehicleInfoPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<StorageVehicleInfoDO> list = storageVehicleInfoService.getStorageVehicleInfoPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "载具信息.xls", "数据", StorageVehicleInfoRespVO.class,
|
||||
BeanUtils.toBean(list, StorageVehicleInfoRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.code.nl.framework.common.pojo.PageParam;
|
||||
import java.math.BigDecimal;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.code.nl.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 载具信息分页 Request VO")
|
||||
@Data
|
||||
public class StorageVehicleInfoPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "载具编码")
|
||||
private String storageVehicleCode;
|
||||
|
||||
@Schema(description = "载具名称")
|
||||
private String storageVehicleName;
|
||||
|
||||
@Schema(description = "一维码")
|
||||
private String oneCode;
|
||||
|
||||
@Schema(description = "二维码")
|
||||
private String twoCode;
|
||||
|
||||
@Schema(description = "是否启用")
|
||||
private Boolean isUsed;
|
||||
|
||||
@Schema(description = "载具类型")
|
||||
private String storageVehicleType;
|
||||
|
||||
@Schema(description = "载具宽度")
|
||||
private Integer vehicleWidth;
|
||||
|
||||
@Schema(description = "载具长度")
|
||||
private Integer vehicleLong;
|
||||
|
||||
@Schema(description = "载具高度")
|
||||
private Integer vehicleHeight;
|
||||
|
||||
@Schema(description = "托盘重量")
|
||||
private BigDecimal weigth;
|
||||
|
||||
@Schema(description = "载具是否超仓位")
|
||||
private String overStructType;
|
||||
|
||||
@Schema(description = "占仓位数")
|
||||
private Integer occupyStructQty;
|
||||
|
||||
@Schema(description = "木箱号")
|
||||
private String boxNo;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.math.BigDecimal;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import cn.idev.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 载具信息 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class StorageVehicleInfoRespVO {
|
||||
|
||||
private Long storageVehicleId;
|
||||
|
||||
@Schema(description = "载具编码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("载具编码")
|
||||
private String storageVehicleCode;
|
||||
|
||||
@Schema(description = "载具名称")
|
||||
@ExcelProperty("载具名称")
|
||||
private String storageVehicleName;
|
||||
|
||||
@Schema(description = "一维码")
|
||||
@ExcelProperty("一维码")
|
||||
private String oneCode;
|
||||
|
||||
@Schema(description = "二维码")
|
||||
@ExcelProperty("二维码")
|
||||
private String twoCode;
|
||||
|
||||
@Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("是否启用")
|
||||
private Boolean isUsed;
|
||||
|
||||
@Schema(description = "载具类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("载具类型")
|
||||
private String storageVehicleType;
|
||||
|
||||
@Schema(description = "载具宽度")
|
||||
@ExcelProperty("载具宽度")
|
||||
private Integer vehicleWidth;
|
||||
|
||||
@Schema(description = "载具长度")
|
||||
@ExcelProperty("载具长度")
|
||||
private Integer vehicleLong;
|
||||
|
||||
@Schema(description = "载具高度")
|
||||
@ExcelProperty("载具高度")
|
||||
private Integer vehicleHeight;
|
||||
|
||||
@Schema(description = "托盘重量")
|
||||
@ExcelProperty("托盘重量")
|
||||
private BigDecimal weigth;
|
||||
|
||||
@Schema(description = "载具是否超仓位", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("载具是否超仓位")
|
||||
private String overStructType;
|
||||
|
||||
@Schema(description = "占仓位数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("占仓位数")
|
||||
private Integer occupyStructQty;
|
||||
|
||||
@Schema(description = "木箱号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("木箱号")
|
||||
private String boxNo;
|
||||
|
||||
@Schema(description = "外部标识")
|
||||
@ExcelProperty("外部标识")
|
||||
private String extId;
|
||||
|
||||
@Schema(description = "创建者")
|
||||
@ExcelProperty("创建者")
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新者")
|
||||
@ExcelProperty("更新者")
|
||||
private String updater;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 载具信息新增/修改 Request VO")
|
||||
@Data
|
||||
public class StorageVehicleInfoSaveReqVO {
|
||||
|
||||
private Long storageVehicleId;
|
||||
|
||||
@Schema(description = "载具编码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "载具编码不能为空")
|
||||
private String storageVehicleCode;
|
||||
|
||||
@Schema(description = "载具名称")
|
||||
private String storageVehicleName;
|
||||
|
||||
@Schema(description = "一维码")
|
||||
private String oneCode;
|
||||
|
||||
@Schema(description = "二维码")
|
||||
private String twoCode;
|
||||
|
||||
@Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "是否启用不能为空")
|
||||
private Boolean isUsed;
|
||||
|
||||
@Schema(description = "载具类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "载具类型不能为空")
|
||||
private String storageVehicleType;
|
||||
|
||||
@Schema(description = "载具宽度")
|
||||
private Integer vehicleWidth;
|
||||
|
||||
@Schema(description = "载具长度")
|
||||
private Integer vehicleLong;
|
||||
|
||||
@Schema(description = "载具高度")
|
||||
private Integer vehicleHeight;
|
||||
|
||||
@Schema(description = "托盘重量")
|
||||
private BigDecimal weigth;
|
||||
|
||||
@Schema(description = "载具是否超仓位", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "载具是否超仓位不能为空")
|
||||
private String overStructType;
|
||||
|
||||
@Schema(description = "占仓位数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "占仓位数不能为空")
|
||||
private Integer occupyStructQty;
|
||||
|
||||
@Schema(description = "木箱号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "木箱号不能为空")
|
||||
private String boxNo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package cn.code.nl.module.wms.dal.dataobject.storagevehicleinfo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.code.nl.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 载具信息 DO
|
||||
*
|
||||
* @author 诺力管理员
|
||||
*/
|
||||
@TableName("wms_storage_vehicle_info")
|
||||
@KeySequence("wms_storage_vehicle_info_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class StorageVehicleInfoDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 载具标识
|
||||
*/
|
||||
@TableId
|
||||
private Long storageVehicleId;
|
||||
/**
|
||||
* 载具编码
|
||||
*/
|
||||
private String storageVehicleCode;
|
||||
/**
|
||||
* 载具名称
|
||||
*/
|
||||
private String storageVehicleName;
|
||||
/**
|
||||
* 一维码
|
||||
*/
|
||||
private String oneCode;
|
||||
/**
|
||||
* 二维码
|
||||
*/
|
||||
private String twoCode;
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private Boolean isUsed;
|
||||
/**
|
||||
* 载具类型
|
||||
*/
|
||||
private String storageVehicleType;
|
||||
/**
|
||||
* 载具宽度
|
||||
*/
|
||||
private Integer vehicleWidth;
|
||||
/**
|
||||
* 载具长度
|
||||
*/
|
||||
private Integer vehicleLong;
|
||||
/**
|
||||
* 载具高度
|
||||
*/
|
||||
private Integer vehicleHeight;
|
||||
/**
|
||||
* 托盘重量
|
||||
*/
|
||||
private BigDecimal weigth;
|
||||
/**
|
||||
* 载具是否超仓位
|
||||
*/
|
||||
private String overStructType;
|
||||
/**
|
||||
* 占仓位数
|
||||
*/
|
||||
private Integer occupyStructQty;
|
||||
/**
|
||||
* 木箱号
|
||||
*/
|
||||
private String boxNo;
|
||||
/**
|
||||
* 外部标识
|
||||
*/
|
||||
private String extId;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.code.nl.module.wms.dal.mysql.storagevehicleinfo;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.code.nl.framework.common.pojo.PageResult;
|
||||
import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.code.nl.module.wms.dal.dataobject.storagevehicleinfo.StorageVehicleInfoDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo.*;
|
||||
|
||||
/**
|
||||
* 载具信息 Mapper
|
||||
*
|
||||
* @author 诺力管理员
|
||||
*/
|
||||
@Mapper
|
||||
public interface StorageVehicleInfoMapper extends BaseMapperX<StorageVehicleInfoDO> {
|
||||
|
||||
default PageResult<StorageVehicleInfoDO> selectPage(StorageVehicleInfoPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<StorageVehicleInfoDO>()
|
||||
.eqIfPresent(StorageVehicleInfoDO::getStorageVehicleCode, reqVO.getStorageVehicleCode())
|
||||
.likeIfPresent(StorageVehicleInfoDO::getStorageVehicleName, reqVO.getStorageVehicleName())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getOneCode, reqVO.getOneCode())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getTwoCode, reqVO.getTwoCode())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getIsUsed, reqVO.getIsUsed())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getStorageVehicleType, reqVO.getStorageVehicleType())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getVehicleWidth, reqVO.getVehicleWidth())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getVehicleLong, reqVO.getVehicleLong())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getVehicleHeight, reqVO.getVehicleHeight())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getWeigth, reqVO.getWeigth())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getOverStructType, reqVO.getOverStructType())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getOccupyStructQty, reqVO.getOccupyStructQty())
|
||||
.eqIfPresent(StorageVehicleInfoDO::getBoxNo, reqVO.getBoxNo())
|
||||
.betweenIfPresent(StorageVehicleInfoDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(StorageVehicleInfoDO::getStorageVehicleId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.code.nl.module.wms.service.storagevehicleinfo;
|
||||
|
||||
import java.util.*;
|
||||
import jakarta.validation.*;
|
||||
import cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo.*;
|
||||
import cn.code.nl.module.wms.dal.dataobject.storagevehicleinfo.StorageVehicleInfoDO;
|
||||
import cn.code.nl.framework.common.pojo.PageResult;
|
||||
import cn.code.nl.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 载具信息 Service 接口
|
||||
*
|
||||
* @author 诺力管理员
|
||||
*/
|
||||
public interface StorageVehicleInfoService {
|
||||
|
||||
/**
|
||||
* 创建载具信息
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createStorageVehicleInfo(@Valid StorageVehicleInfoSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新载具信息
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateStorageVehicleInfo(@Valid StorageVehicleInfoSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除载具信息
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteStorageVehicleInfo(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除载具信息
|
||||
*
|
||||
* @param ids 编号
|
||||
*/
|
||||
void deleteStorageVehicleInfoListByIds(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得载具信息
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 载具信息
|
||||
*/
|
||||
StorageVehicleInfoDO getStorageVehicleInfo(Long id);
|
||||
|
||||
/**
|
||||
* 获得载具信息分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 载具信息分页
|
||||
*/
|
||||
PageResult<StorageVehicleInfoDO> getStorageVehicleInfoPage(StorageVehicleInfoPageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.code.nl.module.wms.service.storagevehicleinfo;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.code.nl.module.wms.controller.admin.storagevehicleinfo.vo.*;
|
||||
import cn.code.nl.module.wms.dal.dataobject.storagevehicleinfo.StorageVehicleInfoDO;
|
||||
import cn.code.nl.framework.common.pojo.PageResult;
|
||||
import cn.code.nl.framework.common.pojo.PageParam;
|
||||
import cn.code.nl.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.code.nl.module.wms.dal.mysql.storagevehicleinfo.StorageVehicleInfoMapper;
|
||||
|
||||
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.code.nl.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.code.nl.framework.common.util.collection.CollectionUtils.diffList;
|
||||
import static cn.code.nl.module.wms.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 载具信息 Service 实现类
|
||||
*
|
||||
* @author 诺力管理员
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class StorageVehicleInfoServiceImpl implements StorageVehicleInfoService {
|
||||
|
||||
@Resource
|
||||
private StorageVehicleInfoMapper storageVehicleInfoMapper;
|
||||
|
||||
@Override
|
||||
public Long createStorageVehicleInfo(StorageVehicleInfoSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
StorageVehicleInfoDO storageVehicleInfo = BeanUtils.toBean(createReqVO, StorageVehicleInfoDO.class);
|
||||
storageVehicleInfoMapper.insert(storageVehicleInfo);
|
||||
|
||||
// 返回
|
||||
return storageVehicleInfo.getStorageVehicleId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStorageVehicleInfo(StorageVehicleInfoSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateStorageVehicleInfoExists(updateReqVO.getStorageVehicleId());
|
||||
// 更新
|
||||
StorageVehicleInfoDO updateObj = BeanUtils.toBean(updateReqVO, StorageVehicleInfoDO.class);
|
||||
storageVehicleInfoMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStorageVehicleInfo(Long id) {
|
||||
// 校验存在
|
||||
validateStorageVehicleInfoExists(id);
|
||||
// 删除
|
||||
storageVehicleInfoMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteStorageVehicleInfoListByIds(List<Long> ids) {
|
||||
// 删除
|
||||
storageVehicleInfoMapper.deleteByIds(ids);
|
||||
}
|
||||
|
||||
|
||||
private void validateStorageVehicleInfoExists(Long id) {
|
||||
if (storageVehicleInfoMapper.selectById(id) == null) {
|
||||
throw exception(STORAGE_VEHICLE_INFO_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageVehicleInfoDO getStorageVehicleInfo(Long id) {
|
||||
return storageVehicleInfoMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<StorageVehicleInfoDO> getStorageVehicleInfoPage(StorageVehicleInfoPageReqVO pageReqVO) {
|
||||
return storageVehicleInfoMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.code.nl.module.wms.dal.mysql.groupplate.GroupPlateMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.code.nl.module.wms.dal.mysql.storagevehicleinfo.StorageVehicleInfoMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
</mapper>
|
||||
@@ -3,7 +3,7 @@ VITE_BASE=/
|
||||
# 请求路径
|
||||
VITE_BASE_URL=http://127.0.0.1:48080
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=http://127.0.0.1:48080/admin-api
|
||||
VITE_GLOB_API_URL=/admin-api
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
|
||||
@@ -23,4 +23,4 @@ VITE_INJECT_APP_LOADING=true
|
||||
VITE_ARCHIVER=true
|
||||
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace WmsStorageVehicleInfoApi {
|
||||
/** 载具信息信息 */
|
||||
export interface StorageVehicleInfo {
|
||||
storageVehicleId?: string;
|
||||
storageVehicleCode?: string; // 载具编码
|
||||
storageVehicleName: string; // 载具名称
|
||||
oneCode: string; // 一维码
|
||||
twoCode: string; // 二维码
|
||||
isUsed?: boolean; // 是否启用
|
||||
storageVehicleType?: string; // 载具类型
|
||||
vehicleWidth: number; // 载具宽度
|
||||
vehicleLong: number; // 载具长度
|
||||
vehicleHeight: number; // 载具高度
|
||||
weigth: number; // 托盘重量
|
||||
overStructType?: string; // 载具是否超仓位
|
||||
occupyStructQty?: number; // 占仓位数
|
||||
boxNo?: string; // 木箱号
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询载具信息分页 */
|
||||
export function getStorageVehicleInfoPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<WmsStorageVehicleInfoApi.StorageVehicleInfo>>(
|
||||
'/wms/storage-vehicle-info/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询载具信息详情 */
|
||||
export function getStorageVehicleInfo(id: number) {
|
||||
return requestClient.get<WmsStorageVehicleInfoApi.StorageVehicleInfo>(
|
||||
`/wms/storage-vehicle-info/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增载具信息 */
|
||||
export function createStorageVehicleInfo(data: WmsStorageVehicleInfoApi.StorageVehicleInfo) {
|
||||
return requestClient.post('/wms/storage-vehicle-info/create', data);
|
||||
}
|
||||
|
||||
/** 修改载具信息 */
|
||||
export function updateStorageVehicleInfo(data: WmsStorageVehicleInfoApi.StorageVehicleInfo) {
|
||||
return requestClient.put('/wms/storage-vehicle-info/update', data);
|
||||
}
|
||||
|
||||
/** 删除载具信息 */
|
||||
export function deleteStorageVehicleInfo(id: number) {
|
||||
return requestClient.delete(`/wms/storage-vehicle-info/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除载具信息 */
|
||||
export function deleteStorageVehicleInfoList(ids: number[]) {
|
||||
return requestClient.delete(
|
||||
`/wms/storage-vehicle-info/delete-list?ids=${ids.join(',')}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 导出载具信息 */
|
||||
export function exportStorageVehicleInfo(params: any) {
|
||||
return requestClient.download('/wms/storage-vehicle-info/export-excel', { params });
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { WmsStorageVehicleInfoApi } from '#/api/wms/storagevehicleinfo';
|
||||
|
||||
import { getRangePickerDefaultProps } from '#/utils';
|
||||
|
||||
/** 新增/修改的表单 */
|
||||
export function useFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
fieldName: 'storageVehicleId',
|
||||
component: 'Input',
|
||||
dependencies: {
|
||||
triggerFields: [''],
|
||||
show: () => false,
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'storageVehicleCode',
|
||||
label: '载具编码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
placeholder: '后台自动生成',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'storageVehicleName',
|
||||
label: '载具名称',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入载具名称',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'oneCode',
|
||||
label: '一维码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入一维码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'twoCode',
|
||||
label: '二维码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入二维码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'isUsed',
|
||||
label: '是否启用',
|
||||
rules: 'required',
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
options: [],
|
||||
buttonStyle: 'solid',
|
||||
optionType: 'button',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'storageVehicleType',
|
||||
label: '载具类型',
|
||||
rules: 'required',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [],
|
||||
placeholder: '请选择载具类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'vehicleWidth',
|
||||
label: '载具宽度',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入载具宽度',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'vehicleLong',
|
||||
label: '载具长度',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入载具长度',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'vehicleHeight',
|
||||
label: '载具高度',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入载具高度',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'weigth',
|
||||
label: '托盘重量',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入托盘重量',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'overStructType',
|
||||
label: '载具是否超仓位',
|
||||
rules: 'required',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [],
|
||||
placeholder: '请选择载具是否超仓位',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'occupyStructQty',
|
||||
label: '占仓位数',
|
||||
rules: 'required',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入占仓位数',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'boxNo',
|
||||
label: '木箱号',
|
||||
rules: 'required',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入木箱号',
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/** 列表的搜索表单 */
|
||||
export function useGridFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
fieldName: 'storageVehicleCode',
|
||||
label: '载具编码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入载具编码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'storageVehicleName',
|
||||
label: '载具名称',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入载具名称',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'oneCode',
|
||||
label: '一维码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入一维码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'twoCode',
|
||||
label: '二维码',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入二维码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'isUsed',
|
||||
label: '是否启用',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
options: [],
|
||||
placeholder: '请选择是否启用',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'storageVehicleType',
|
||||
label: '载具类型',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
options: [],
|
||||
placeholder: '请选择载具类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'vehicleWidth',
|
||||
label: '载具宽度',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入载具宽度',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'vehicleLong',
|
||||
label: '载具长度',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入载具长度',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'vehicleHeight',
|
||||
label: '载具高度',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入载具高度',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'weigth',
|
||||
label: '托盘重量',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入托盘重量',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'overStructType',
|
||||
label: '载具是否超仓位',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
options: [],
|
||||
placeholder: '请选择载具是否超仓位',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'occupyStructQty',
|
||||
label: '占仓位数',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入占仓位数',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'boxNo',
|
||||
label: '木箱号',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
placeholder: '请输入木箱号',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'createTime',
|
||||
label: '创建时间',
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
...getRangePickerDefaultProps(),
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/** 列表的字段 */
|
||||
export function useGridColumns(): VxeTableGridOptions<WmsStorageVehicleInfoApi.StorageVehicleInfo>['columns'] {
|
||||
return [
|
||||
{ type: 'checkbox', width: 40 },
|
||||
{
|
||||
field: 'storageVehicleCode',
|
||||
title: '载具编码',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'storageVehicleName',
|
||||
title: '载具名称',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'oneCode',
|
||||
title: '一维码',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'twoCode',
|
||||
title: '二维码',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'isUsed',
|
||||
title: '是否启用',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'storageVehicleType',
|
||||
title: '载具类型',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'vehicleWidth',
|
||||
title: '载具宽度',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'vehicleLong',
|
||||
title: '载具长度',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'vehicleHeight',
|
||||
title: '载具高度',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'weigth',
|
||||
title: '托盘重量',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'overStructType',
|
||||
title: '载具是否超仓位',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'occupyStructQty',
|
||||
title: '占仓位数',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'boxNo',
|
||||
title: '木箱号',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'extId',
|
||||
title: '外部标识',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'creator',
|
||||
title: '创建者',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
title: '创建时间',
|
||||
minWidth: 120,
|
||||
formatter: 'formatDateTime',
|
||||
},
|
||||
{
|
||||
field: 'updater',
|
||||
title: '更新者',
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
field: 'updateTime',
|
||||
title: '更新时间',
|
||||
minWidth: 120,
|
||||
formatter: 'formatDateTime',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 200,
|
||||
fixed: 'right',
|
||||
slots: { default: 'actions' },
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { WmsStorageVehicleInfoApi } from '#/api/wms/storagevehicleinfo';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { confirm, Page, useVbenModal } from '@vben/common-ui';
|
||||
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
|
||||
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import {
|
||||
deleteStorageVehicleInfo,
|
||||
deleteStorageVehicleInfoList,
|
||||
exportStorageVehicleInfo,
|
||||
getStorageVehicleInfoPage,
|
||||
} from '#/api/wms/storagevehicleinfo';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useGridColumns, useGridFormSchema } from './data';
|
||||
import Form from './modules/form.vue';
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
connectedComponent: Form,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
/** 刷新表格 */
|
||||
function handleRefresh() {
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
/** 创建载具信息 */
|
||||
function handleCreate() {
|
||||
formModalApi.setData(null).open();
|
||||
}
|
||||
|
||||
/** 编辑载具信息 */
|
||||
function handleEdit(row: WmsStorageVehicleInfoApi.StorageVehicleInfo) {
|
||||
formModalApi.setData(row).open();
|
||||
}
|
||||
|
||||
/** 删除载具信息 */
|
||||
async function handleDelete(row: WmsStorageVehicleInfoApi.StorageVehicleInfo) {
|
||||
const hideLoading = message.loading({
|
||||
content: $t('ui.actionMessage.deleting', [row.id]),
|
||||
duration: 0,
|
||||
});
|
||||
try {
|
||||
await deleteStorageVehicleInfo(row.id!);
|
||||
message.success($t('ui.actionMessage.deleteSuccess', [row.id]));
|
||||
handleRefresh();
|
||||
} finally {
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
/** 批量删除载具信息 */
|
||||
async function handleDeleteBatch() {
|
||||
await confirm($t('ui.actionMessage.deleteBatchConfirm'));
|
||||
const hideLoading = message.loading({
|
||||
content: $t('ui.actionMessage.deletingBatch'),
|
||||
duration: 0,
|
||||
});
|
||||
try {
|
||||
await deleteStorageVehicleInfoList(checkedIds.value);
|
||||
checkedIds.value = [];
|
||||
message.success($t('ui.actionMessage.deleteSuccess'));
|
||||
handleRefresh();
|
||||
} finally {
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
const checkedIds = ref<number[]>([]);
|
||||
function handleRowCheckboxChange({
|
||||
records,
|
||||
}: {
|
||||
records: WmsStorageVehicleInfoApi.StorageVehicleInfo[];
|
||||
}) {
|
||||
checkedIds.value = records.map((item) => item.id!);
|
||||
}
|
||||
|
||||
/** 导出表格 */
|
||||
async function handleExport() {
|
||||
const data = await exportStorageVehicleInfo(await gridApi.formApi.getValues());
|
||||
downloadFileFromBlobPart({ fileName: '载具信息.xls', source: data });
|
||||
}
|
||||
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions: {
|
||||
schema: useGridFormSchema(),
|
||||
},
|
||||
gridOptions: {
|
||||
columns: useGridColumns(),
|
||||
height: 'auto',
|
||||
keepSource: true,
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
return await getStorageVehicleInfoPage({
|
||||
pageNo: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
rowConfig: {
|
||||
keyField: 'id',
|
||||
isHover: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
refresh: true,
|
||||
search: true,
|
||||
},
|
||||
} as VxeTableGridOptions<WmsStorageVehicleInfoApi.StorageVehicleInfo>,
|
||||
gridEvents: {
|
||||
checkboxAll: handleRowCheckboxChange,
|
||||
checkboxChange: handleRowCheckboxChange,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<FormModal @success="handleRefresh" />
|
||||
<Grid table-title="载具信息列表">
|
||||
<template #toolbar-tools>
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: $t('ui.actionTitle.create', ['载具信息']),
|
||||
type: 'primary',
|
||||
icon: ACTION_ICON.ADD,
|
||||
auth: ['wms:storage-vehicle-info:create'],
|
||||
onClick: handleCreate,
|
||||
},
|
||||
{
|
||||
label: $t('ui.actionTitle.export'),
|
||||
type: 'primary',
|
||||
icon: ACTION_ICON.DOWNLOAD,
|
||||
auth: ['wms:storage-vehicle-info:export'],
|
||||
onClick: handleExport,
|
||||
},
|
||||
{
|
||||
label: $t('ui.actionTitle.deleteBatch'),
|
||||
type: 'primary',
|
||||
danger: true,
|
||||
icon: ACTION_ICON.DELETE,
|
||||
auth: ['wms:storage-vehicle-info:delete'],
|
||||
disabled: isEmpty(checkedIds),
|
||||
onClick: handleDeleteBatch,
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
<template #actions="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: $t('common.edit'),
|
||||
type: 'link',
|
||||
icon: ACTION_ICON.EDIT,
|
||||
auth: ['wms:storage-vehicle-info:update'],
|
||||
onClick: handleEdit.bind(null, row),
|
||||
},
|
||||
{
|
||||
label: $t('common.delete'),
|
||||
type: 'link',
|
||||
danger: true,
|
||||
icon: ACTION_ICON.DELETE,
|
||||
auth: ['wms:storage-vehicle-info:delete'],
|
||||
popConfirm: {
|
||||
title: $t('ui.actionMessage.deleteConfirm', [row.id]),
|
||||
confirm: handleDelete.bind(null, row),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
</template>
|
||||
@@ -0,0 +1,82 @@
|
||||
<script lang="ts" setup>
|
||||
import type { WmsStorageVehicleInfoApi } from '#/api/wms/storagevehicleinfo';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'antdv-next';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { createStorageVehicleInfo, getStorageVehicleInfo, updateStorageVehicleInfo } from '#/api/wms/storagevehicleinfo';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useFormSchema } from '../data';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const formData = ref<WmsStorageVehicleInfoApi.StorageVehicleInfo>();
|
||||
const getTitle = computed(() => {
|
||||
return formData.value?.storageVehicleId
|
||||
? $t('ui.actionTitle.edit', ['载具信息'])
|
||||
: $t('ui.actionTitle.create', ['载具信息']);
|
||||
});
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
formItemClass: 'col-span-2',
|
||||
labelWidth: 80,
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: useFormSchema(),
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
modalApi.lock();
|
||||
// 提交表单
|
||||
const data = (await formApi.getValues()) as WmsStorageVehicleInfoApi.StorageVehicleInfo;
|
||||
try {
|
||||
await (formData.value?.id ? updateStorageVehicleInfo(data) : createStorageVehicleInfo(data));
|
||||
// 关闭并提示
|
||||
await modalApi.close();
|
||||
emit('success');
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
} finally {
|
||||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
formData.value = undefined;
|
||||
return;
|
||||
}
|
||||
// 加载数据
|
||||
const data = modalApi.getData<WmsStorageVehicleInfoApi.StorageVehicleInfo>();
|
||||
if (!data || !data.id) {
|
||||
return;
|
||||
}
|
||||
modalApi.lock();
|
||||
try {
|
||||
formData.value = await getStorageVehicleInfo(data.id);
|
||||
// 设置到 values
|
||||
await formApi.setValues(formData.value);
|
||||
} finally {
|
||||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
347
前端Jenkins部署指南.md
Normal file
347
前端Jenkins部署指南.md
Normal file
@@ -0,0 +1,347 @@
|
||||
# 前端 Jenkins 部署指南
|
||||
|
||||
## 一、项目概况
|
||||
|
||||
| 项目 | 说明 |
|
||||
|------|------|
|
||||
| 源码路径 | `nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/` |
|
||||
| 框架 | Vue 3 + Vite + Ant Design Vue 4(基于 vue-vben-admin 5.7.0) |
|
||||
| 包管理器 | pnpm 11.7.0(强制,不可用 npm/yarn) |
|
||||
| Node 版本 | >= 22.18.0(`.node-version` 指定 24.16.0) |
|
||||
| 构建工具 | Turbo(monorepo 编排)+ Vite(打包) |
|
||||
| 构建产物 | `apps/web-antdv-next/dist/` |
|
||||
| 路由模式 | hash 模式(`VITE_ROUTER_HISTORY=hash`) |
|
||||
|
||||
---
|
||||
|
||||
## 二、环境变量说明
|
||||
|
||||
构建时通过 `.env.production` 控制关键配置,可按环境覆盖。
|
||||
|
||||
**文件位置:** `apps/web-antdv-next/.env.production`
|
||||
|
||||
| 变量 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `VITE_BASE` | `/` | 部署路径前缀,部署在子路径时改为 `/admin/` |
|
||||
| `VITE_GLOB_API_URL` | `http://127.0.0.1:48080/admin-api` | 后端 API 地址(完整 URL) |
|
||||
| `VITE_ROUTER_HISTORY` | `hash` | 路由模式,hash 模式无需 nginx 特殊配置 |
|
||||
| `VITE_COMPRESS` | `none` | 压缩方式(none / gzip / brotli) |
|
||||
| `VITE_ARCHIVER` | `true` | 是否生成 `dist.zip` |
|
||||
| `VITE_PWA` | `false` | 是否启用 PWA |
|
||||
|
||||
**多环境覆盖方式**:在 Jenkins 构建步骤中创建 `.env.production.local` 文件覆盖 `VITE_GLOB_API_URL` 等变量,Vite 会优先读取 local 文件。
|
||||
|
||||
---
|
||||
|
||||
## 三、Jenkins 流水线(Pipeline)
|
||||
|
||||
### 3.1 声明式流水线(推荐,使用 Docker 镜像自带 Node 环境)
|
||||
|
||||
```groovy
|
||||
pipeline {
|
||||
// 使用 Docker 镜像,自带 Node 24 + pnpm,不需要 Jenkins 宿主机装 Node
|
||||
agent {
|
||||
docker {
|
||||
image 'node:24-slim'
|
||||
args '-u root --memory=4g'
|
||||
}
|
||||
}
|
||||
|
||||
// 构建参数,支持按环境选择
|
||||
parameters {
|
||||
choice(name: 'DEPLOY_ENV', choices: ['dev', 'staging', 'prod'], description: '部署环境')
|
||||
string(name: 'API_BASE_URL', defaultValue: 'http://127.0.0.1:48080/admin-api', description: '后端 API 地址')
|
||||
}
|
||||
|
||||
environment {
|
||||
// 源码子目录(仓库根目录下的相对路径)
|
||||
SOURCE_DIR = 'nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben'
|
||||
// pnpm 缓存目录,挂到宿主机避免重复下载
|
||||
PNPM_HOME = '/root/.local/share/pnpm'
|
||||
}
|
||||
|
||||
stages {
|
||||
|
||||
// ==================== 第一步:拉取代码 ====================
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 第二步:安装依赖 ====================
|
||||
stage('Setup') {
|
||||
steps {
|
||||
dir(env.SOURCE_DIR) {
|
||||
sh 'corepack enable'
|
||||
sh 'corepack prepare pnpm@11.7.0 --activate'
|
||||
// 安装依赖(锁定版本)
|
||||
sh 'pnpm install --frozen-lockfile'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 第三步:代码检查(可选) ====================
|
||||
stage('Lint') {
|
||||
steps {
|
||||
dir(env.SOURCE_DIR) {
|
||||
sh 'pnpm run lint || true'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 第四步:构建 ====================
|
||||
stage('Build') {
|
||||
steps {
|
||||
dir(env.SOURCE_DIR) {
|
||||
script {
|
||||
// 根据部署环境覆盖 API 地址
|
||||
def apiUrl = params.API_BASE_URL
|
||||
if (params.DEPLOY_ENV == 'prod') {
|
||||
apiUrl = 'https://api.your-domain.com/admin-api'
|
||||
} else if (params.DEPLOY_ENV == 'staging') {
|
||||
apiUrl = 'https://staging-api.your-domain.com/admin-api'
|
||||
}
|
||||
|
||||
// 写入环境变量(Vite 构建时读取)
|
||||
writeFile file: 'apps/web-antdv-next/.env.production.local', text: """
|
||||
VITE_GLOB_API_URL=${apiUrl}
|
||||
""".stripIndent().trim()
|
||||
|
||||
// 执行构建
|
||||
sh '''#!/bin/bash
|
||||
export NODE_OPTIONS="--max-old-space-size=8192"
|
||||
pnpm run build --filter=@vben/web-antdv-next
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 第五步:打包产物 ====================
|
||||
stage('Archive') {
|
||||
steps {
|
||||
dir(env.SOURCE_DIR) {
|
||||
script {
|
||||
def distPath = 'apps/web-antdv-next/dist'
|
||||
sh "tar -czf dist-${params.DEPLOY_ENV}.tar.gz -C ${distPath} ."
|
||||
archiveArtifacts artifacts: "dist-${params.DEPLOY_ENV}.tar.gz", fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 第六步:部署 ====================
|
||||
stage('Deploy') {
|
||||
when {
|
||||
expression { params.DEPLOY_ENV == 'dev' || params.DEPLOY_ENV == 'staging' || params.DEPLOY_ENV == 'prod' }
|
||||
}
|
||||
steps {
|
||||
dir(env.SOURCE_DIR) {
|
||||
script {
|
||||
def serverIp = ''
|
||||
def deployPath = '/usr/share/nginx/html/admin'
|
||||
|
||||
if (params.DEPLOY_ENV == 'dev') { serverIp = '192.168.1.10' }
|
||||
else if (params.DEPLOY_ENV == 'staging') { serverIp = '192.168.1.20' }
|
||||
else if (params.DEPLOY_ENV == 'prod') { serverIp = '192.168.1.30' }
|
||||
|
||||
sshagent(['deploy-ssh-key']) {
|
||||
sh """
|
||||
ssh root@${serverIp} 'mkdir -p ${deployPath}'
|
||||
scp dist-${params.DEPLOY_ENV}.tar.gz root@${serverIp}:/tmp/
|
||||
ssh root@${serverIp} '
|
||||
rm -rf ${deployPath}/*
|
||||
tar -xzf /tmp/dist-${params.DEPLOY_ENV}.tar.gz -C ${deployPath}
|
||||
rm -f /tmp/dist-${params.DEPLOY_ENV}.tar.gz
|
||||
nginx -t && nginx -s reload
|
||||
'
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success { echo "构建成功!环境:${params.DEPLOY_ENV}" }
|
||||
failure { echo "构建失败!请检查日志。" }
|
||||
always { cleanWs() }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 简化版流水线(仅构建 + 归档,手动部署)
|
||||
|
||||
```groovy
|
||||
pipeline {
|
||||
agent {
|
||||
docker {
|
||||
image 'node:24-slim'
|
||||
args '-u root --memory=4g'
|
||||
}
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(name: 'API_BASE_URL', defaultValue: 'http://127.0.0.1:48080/admin-api', description: '后端 API 地址')
|
||||
string(name: 'VITE_BASE', defaultValue: '/', description: '部署子路径')
|
||||
}
|
||||
|
||||
environment {
|
||||
SOURCE_DIR = 'nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') { steps { checkout scm } }
|
||||
|
||||
stage('Install & Build') {
|
||||
steps {
|
||||
dir(env.SOURCE_DIR) {
|
||||
sh 'corepack enable && corepack prepare pnpm@11.7.0 --activate'
|
||||
sh 'pnpm install --frozen-lockfile'
|
||||
|
||||
writeFile file: 'apps/web-antdv-next/.env.production.local', text: """
|
||||
VITE_GLOB_API_URL=${params.API_BASE_URL}
|
||||
VITE_BASE=${params.VITE_BASE}
|
||||
""".stripIndent().trim()
|
||||
|
||||
sh '''
|
||||
export NODE_OPTIONS="--max-old-space-size=8192"
|
||||
pnpm run build --filter=@vben/web-antdv-next
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Package') {
|
||||
steps {
|
||||
dir("${env.SOURCE_DIR}/apps/web-antdv-next") {
|
||||
sh 'tar -czf dist.tar.gz -C dist .'
|
||||
archiveArtifacts artifacts: 'dist.tar.gz', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always { cleanWs() }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、Nginx 部署配置
|
||||
|
||||
项目使用 hash 路由,nginx 配置很简单:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name admin.your-domain.com;
|
||||
|
||||
# 前端静态文件
|
||||
root /usr/share/nginx/html/admin;
|
||||
index index.html;
|
||||
|
||||
# hash 路由模式,单页应用标准配置
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# API 反向代理到后端网关
|
||||
location /admin-api/ {
|
||||
proxy_pass http://backend-gateway:48080/admin-api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
# 静态资源缓存
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、Docker 部署(可选)
|
||||
|
||||
项目自带 Dockerfile 但默认构建的是 playground 应用,需要调整。推荐新建一个:
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile 放在 yudao-ui-admin-vben/ 目录下
|
||||
# ============ 构建阶段 ============
|
||||
FROM node:24-slim AS builder
|
||||
|
||||
RUN npm install -g pnpm@11.7.0
|
||||
|
||||
WORKDIR /app
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json .npmrc ./
|
||||
COPY internal/ internal/
|
||||
COPY packages/ packages/
|
||||
COPY apps/web-antdv-next/ apps/web-antdv-next/
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
ARG VITE_GLOB_API_URL=http://127.0.0.1:48080/admin-api
|
||||
ENV VITE_GLOB_API_URL=${VITE_GLOB_API_URL}
|
||||
|
||||
RUN NODE_OPTIONS="--max-old-space-size=8192" pnpm run build --filter=@vben/web-antdv-next
|
||||
|
||||
# ============ 运行阶段 ============
|
||||
FROM nginx:stable-alpine
|
||||
|
||||
COPY --from=builder /app/apps/web-antdv-next/dist /usr/share/nginx/html
|
||||
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
构建镜像:
|
||||
|
||||
```bash
|
||||
docker build \
|
||||
--build-arg VITE_GLOB_API_URL=https://api.your-domain.com/admin-api \
|
||||
-t nl-admin-ui:latest \
|
||||
.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、Jenkins 配置清单
|
||||
|
||||
在 Jenkins 上配置前需要准备:
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|--------|------|
|
||||
| **Node.js 插件** | 安装 Jenkins NodeJS Plugin,添加 Node.js 24.x 安装 |
|
||||
| **SSH 凭据** | 添加目标服务器的 SSH 私钥(ID 为 `deploy-ssh-key`) |
|
||||
| **Git 仓库** | 确保 Jenkins 能访问代码仓库 |
|
||||
| **构建机资源** | 内存 >= 4GB(`NODE_OPTIONS=--max-old-space-size=8192`) |
|
||||
| **网络** | 构建机能访问 `registry.npmmirror.com`(或换内网 npm 镜像) |
|
||||
|
||||
---
|
||||
|
||||
## 七、常见问题
|
||||
|
||||
### Q1:构建报 `pnpm: command not found`
|
||||
|
||||
Jenkins 环境中 `corepack enable` 可能不生效,改用 `npm install -g pnpm@11.7.0`。
|
||||
|
||||
### Q2:构建 OOM(内存溢出)
|
||||
|
||||
调大 Node 内存限制:`NODE_OPTIONS="--max-old-space-size=8192"`,流水线中已默认设置。
|
||||
|
||||
### Q3:API 地址不对
|
||||
|
||||
检查 `.env.production.local` 是否在构建前正确写入,且 `VITE_GLOB_API_URL` 为完整 URL(如 `https://api.your-domain.com/admin-api`)。
|
||||
|
||||
### Q4:页面 404 白屏
|
||||
|
||||
确认 nginx 配置了 `try_files $uri $uri/ /index.html`,以及 `VITE_BASE` 与部署路径匹配。
|
||||
Reference in New Issue
Block a user