diff --git a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/vo/DeptVO.java b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/vo/DeptVO.java index 1d36c2da..5f54f9e3 100644 --- a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/vo/DeptVO.java +++ b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/pojo/vo/DeptVO.java @@ -87,6 +87,12 @@ public class DeptVO extends Dept implements INode { */ private String parentName; + /** + * 所属公司名称(按 belongCompanyCode 解析) + */ + @Schema(description = "所属公司名称") + private String belongCompanyName; + /** * 机构类型名称 */ diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/QualificationCertificateOcrVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/QualificationCertificateOcrVO.java new file mode 100644 index 00000000..27962d8f --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/QualificationCertificateOcrVO.java @@ -0,0 +1,54 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is + * not liable for any claims arising from secondary or illegal development. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.transport.pojo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 从业资格证 OCR 识别结果。 + * + * @author Chill + */ +@Data +@Schema(description = "从业资格证OCR识别结果") +public class QualificationCertificateOcrVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 按第三方返回 key 聚合的字段,例如 qualification_category、certificate_no、valid_from、valid_until。 + */ + @Schema(description = "识别字段,键为第三方 OCR 的 key") + private Map fields = new LinkedHashMap<>(); + +} diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/WaybillImportDuplicateVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/WaybillImportDuplicateVO.java new file mode 100644 index 00000000..66dc148a --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/WaybillImportDuplicateVO.java @@ -0,0 +1,28 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + */ +package org.springblade.transport.pojo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** 运单批量导入行与已有运单的重复情况。 */ +@Data +@Schema(description = "运单批量导入行与已有运单的重复情况") +public class WaybillImportDuplicateVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Schema(description = "行号(从0开始,相对当前批次)") + private Integer rowIndex; + + @Schema(description = "命中的已有运单号") + private List waybillNos = new ArrayList<>(); +} diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/controller/DeptController.java b/blade-service/blade-system/src/main/java/org/springblade/system/controller/DeptController.java index 0c4a3256..11ea8d1c 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/controller/DeptController.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/controller/DeptController.java @@ -274,8 +274,8 @@ public class DeptController extends BladeController { @PreAuth(AuthConstant.PERMIT_ALL) @GetMapping("/business-dept-select") @ApiOperationSupport(order = 12) - @Operation(summary = "业务部门下拉", description = "返回是否业务部门=是的部门列表") - public R> businessDeptSelect() { + @Operation(summary = "业务部门下拉", description = "返回是否业务部门=是的部门列表(含上级组织名称)") + public R> businessDeptSelect() { return R.data(deptService.listBusinessDept()); } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/controller/RoleController.java b/blade-service/blade-system/src/main/java/org/springblade/system/controller/RoleController.java index 46eb4d01..f1f10b7a 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/controller/RoleController.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/controller/RoleController.java @@ -25,6 +25,7 @@ */ package org.springblade.system.controller; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import io.swagger.v3.oas.annotations.Operation; @@ -37,6 +38,7 @@ import jakarta.validation.Valid; import lombok.AllArgsConstructor; import org.springblade.core.boot.ctrl.BladeController; import org.springblade.core.cache.utils.CacheUtil; +import org.springblade.core.mp.support.Query; import org.springblade.core.secure.BladeUser; import org.springblade.core.secure.annotation.IsAdmin; import org.springblade.core.secure.annotation.PreAuth; @@ -85,7 +87,7 @@ public class RoleController extends BladeController { } /** - * 列表 + * 分页列表(按树形根节点分页) */ @GetMapping("/list") @Parameters({ @@ -93,9 +95,9 @@ public class RoleController extends BladeController { @Parameter(name = "roleAlias", description = "角色别名", in = ParameterIn.QUERY, schema = @Schema(type = "string")) }) @ApiOperationSupport(order = 2) - @Operation(summary = "列表", description = "传入role") - public R> list(@Parameter(hidden = true) @RequestParam Map role) { - return R.data(roleService.selectList(role)); + @Operation(summary = "分页", description = "传入role") + public R> list(@Parameter(hidden = true) @RequestParam Map role, Query query) { + return R.data(roleService.selectPage(role, query)); } /** diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/IDeptService.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/IDeptService.java index 39ccb769..c849721f 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/IDeptService.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/IDeptService.java @@ -109,9 +109,9 @@ public interface IDeptService extends IService { /** * 业务部门下拉(是否业务部门=是) * - * @return 业务部门列表 + * @return 业务部门列表(含上级组织名称,便于同名部门区分) */ - List listBusinessDept(); + List listBusinessDept(); /** * 根据部门名称精确匹配获取部门ID集合 diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleService.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleService.java index 6cc21d1e..97fc4261 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleService.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/IRoleService.java @@ -27,6 +27,7 @@ package org.springblade.system.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; +import org.springblade.core.mp.support.Query; import org.springblade.system.pojo.entity.Role; import org.springblade.system.pojo.vo.RoleVO; @@ -58,6 +59,15 @@ public interface IRoleService extends IService { */ List selectList(Map role); + /** + * 角色分页(按树形根节点分页,子节点随根节点返回) + * + * @param role 查询条件 Map + * @param query 分页参数 + * @return 角色分页结果,非超管时仅命中当前会话租户 + */ + IPage selectPage(Map role, Query query); + /** * 自定义角色分页查询 * diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/BusinessDeptConfigServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/BusinessDeptConfigServiceImpl.java index 38f91fe6..6aa2c025 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/BusinessDeptConfigServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/BusinessDeptConfigServiceImpl.java @@ -42,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional; import lombok.RequiredArgsConstructor; +import java.util.List; import java.util.Objects; import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE; @@ -88,6 +89,39 @@ public class BusinessDeptConfigServiceImpl extends BaseServiceImpl activePlatformList = deptService.list(Wrappers.lambdaQuery() + .eq(Dept::getIsPlatformCompany, 1) + .eq(Dept::getDeptName, platformCompanyName) + .orderByAsc(Dept::getId)); + for (Dept activePlatform : activePlatformList) { + if (activePlatform == null || Func.isEmpty(activePlatform.getId()) + || Objects.equals(activePlatform.getId(), platformCompanyId)) { + continue; + } + config = findByPlatformAndDept(activePlatform.getId(), businessDeptId); + if (config != null) { + return config; + } + } + return getOne(Wrappers.lambdaQuery() + .eq(BusinessDeptConfig::getPlatformCompanyName, platformCompanyName) + .eq(BusinessDeptConfig::getBusinessDeptId, businessDeptId) + .eq(BusinessDeptConfig::getIsDeleted, 0) + .orderByDesc(BusinessDeptConfig::getUpdateTime) + .last("LIMIT 1"), false); + } + + private BusinessDeptConfig findByPlatformAndDept(Long platformCompanyId, Long businessDeptId) { return getOne(Wrappers.lambdaQuery() .eq(BusinessDeptConfig::getPlatformCompanyId, platformCompanyId) .eq(BusinessDeptConfig::getBusinessDeptId, businessDeptId) diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java index 2b2f485e..ad2bd919 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DeptServiceImpl.java @@ -321,7 +321,7 @@ public class DeptServiceImpl extends ServiceImpl implements ID } @Override - public List listBusinessDept() { + public List listBusinessDept() { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() .eq(Dept::getIsBusinessDept, 1) .orderByAsc(Dept::getSort) @@ -329,7 +329,47 @@ public class DeptServiceImpl extends ServiceImpl implements ID if (!AuthUtil.isAdministrator()) { queryWrapper.eq(Dept::getTenantId, AuthUtil.getTenantId()); } - return list(queryWrapper); + List deptList = list(queryWrapper); + if (CollectionUtil.isEmpty(deptList)) { + return Collections.emptyList(); + } + // 批量补齐上级名称、所属公司名称:扁平下拉靠公司/上级区分同名业务部门 + Set parentIdSet = deptList.stream() + .map(Dept::getParentId) + .filter(Func::isNotEmpty) + .collect(Collectors.toSet()); + Map parentNameMap = Collections.emptyMap(); + if (CollectionUtil.isNotEmpty(parentIdSet)) { + parentNameMap = listByIds(parentIdSet).stream() + .filter(parent -> Func.isNotEmpty(parent.getId())) + .collect(Collectors.toMap(Dept::getId, Dept::getDeptName, (left, right) -> left)); + } + Set companyCodeSet = deptList.stream() + .map(Dept::getBelongCompanyCode) + .filter(Func::isNotEmpty) + .collect(Collectors.toSet()); + Map companyNameMap = Collections.emptyMap(); + if (CollectionUtil.isNotEmpty(companyCodeSet)) { + companyNameMap = list(Wrappers.lambdaQuery().in(Dept::getDeptCode, companyCodeSet)).stream() + .filter(company -> Func.isNotEmpty(company.getDeptCode())) + .collect(Collectors.toMap(Dept::getDeptCode, Dept::getDeptName, (left, right) -> left)); + } + Map finalParentNameMap = parentNameMap; + Map finalCompanyNameMap = companyNameMap; + return deptList.stream().map(dept -> { + DeptVO deptVO = BeanUtil.copyProperties(dept, DeptVO.class); + if (deptVO == null) { + return null; + } + if (Func.isNotEmpty(dept.getParentId())) { + deptVO.setParentName(finalParentNameMap.getOrDefault(dept.getParentId(), StringPool.EMPTY)); + } + if (Func.isNotEmpty(dept.getBelongCompanyCode())) { + deptVO.setBelongCompanyName( + finalCompanyNameMap.getOrDefault(dept.getBelongCompanyCode(), StringPool.EMPTY)); + } + return deptVO; + }).filter(Objects::nonNull).toList(); } @Override diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleServiceImpl.java index 61d64a76..6bf2dcc4 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/RoleServiceImpl.java @@ -33,6 +33,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.AllArgsConstructor; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.support.Condition; +import org.springblade.core.mp.support.Query; import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tenant.TenantGuard; import org.springblade.core.tool.constant.BladeConstant; @@ -92,9 +93,30 @@ public class RoleServiceImpl extends ServiceImpl implements IR public List selectList(Map role) { QueryWrapper queryWrapper = Condition.getQueryWrapper(role, Role.class); applyTenantScope(queryWrapper); + queryWrapper.lambda().orderByAsc(Role::getSort).orderByAsc(Role::getId); return RoleWrapper.build().listNodeVO(list(queryWrapper)); } + @Override + public IPage selectPage(Map role, Query query) { + List tree = selectList(role); + IPage page = Condition.getPage(query); + long total = tree.size(); + page.setTotal(total); + if (total == 0L || page.getSize() < 1L) { + page.setRecords(Collections.emptyList()); + return page; + } + int fromIndex = (int) ((page.getCurrent() - 1L) * page.getSize()); + if (fromIndex >= tree.size()) { + page.setRecords(Collections.emptyList()); + return page; + } + int toIndex = (int) Math.min(fromIndex + page.getSize(), tree.size()); + page.setRecords(new ArrayList<>(tree.subList(fromIndex, toIndex))); + return page; + } + @Override public IPage selectRolePage(IPage page, RoleVO role) { return page.setRecords(baseMapper.selectRolePage(page, role)); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BaiduOcrController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BaiduOcrController.java index 56c682b0..0dea728b 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BaiduOcrController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BaiduOcrController.java @@ -37,8 +37,10 @@ import org.springblade.core.tool.api.R; import org.springblade.transport.ocr.constant.BaiduOcrType; import org.springblade.transport.ocr.service.IBaiduOcrService; import org.springblade.transport.ocr.service.IBusinessLicenseOcrService; +import org.springblade.transport.ocr.service.IQualificationCertificateOcrService; import org.springblade.transport.pojo.vo.BaiduOcrResultVO; import org.springblade.transport.pojo.vo.BusinessLicenseOcrVO; +import org.springblade.transport.pojo.vo.QualificationCertificateOcrVO; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -63,6 +65,7 @@ public class BaiduOcrController extends BladeController { private final IBaiduOcrService baiduOcrService; private final IBusinessLicenseOcrService businessLicenseOcrService; + private final IQualificationCertificateOcrService qualificationCertificateOcrService; /** * 识别上传的图片。 @@ -126,6 +129,20 @@ public class BaiduOcrController extends BladeController { return R.data(businessLicenseOcrService.recognizeUrl(imageUrl)); } + /** + * 从业资格证图片地址识别(第三方 /Biaozhunbaodan)。 + * + * @param imageUrl 图片地址 + * @return 识别结果 + */ + @PostMapping("/qualification-certificate") + @ApiOperationSupport(order = 4) + @Operation(summary = "从业资格证OCR识别", description = "按图片地址调用第三方道路运输从业人员从业资格证识别接口") + public R recognizeQualificationCertificate( + @Parameter(description = "图片地址", required = true) @RequestParam String imageUrl) { + return R.data(qualificationCertificateOcrService.recognizeUrl(imageUrl)); + } + private BaiduOcrType resolveType(String type) { try { return BaiduOcrType.from(type); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/VoucherManageController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/VoucherManageController.java index 69f53eb0..abcee864 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/VoucherManageController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/VoucherManageController.java @@ -135,9 +135,10 @@ public class VoucherManageController extends BladeController { @ApiOperationSupport(order = 7) @Operation(summary = "可关联运输批次") public R>> waybillBatches(Query query, @RequestParam(required = false) String batchNo, - @RequestParam(required = false) String createUser, @RequestParam(required = false) Integer waybillCount, - @RequestParam(required = false) String createTimeStart, @RequestParam(required = false) String createTimeEnd) { - return R.data(voucherManageService.selectableWaybillBatches(Condition.getPage(query), batchNo, createUser, waybillCount, createTimeStart, createTimeEnd)); + @RequestParam(required = false) Long projectId, @RequestParam(required = false) String createUser, + @RequestParam(required = false) Integer waybillCount, @RequestParam(required = false) String createTimeStart, + @RequestParam(required = false) String createTimeEnd) { + return R.data(voucherManageService.selectableWaybillBatches(Condition.getPage(query), batchNo, projectId, createUser, waybillCount, createTimeStart, createTimeEnd)); } @PostMapping("/audit-pass") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java index 30af8573..c2c66d05 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java @@ -57,6 +57,7 @@ import org.springblade.transport.pojo.dto.WaybillImportBatchRequest; import org.springblade.transport.pojo.vo.BusinessRemoveResultVO; import org.springblade.transport.pojo.vo.LoadingManageVO; import org.springblade.transport.pojo.vo.WaybillImportBatchVO; +import org.springblade.transport.pojo.vo.WaybillImportDuplicateVO; import org.springblade.transport.pojo.vo.WaybillImportValidateResultVO; import org.springblade.transport.pojo.vo.WaybillLocateVO; import org.springblade.transport.pojo.vo.WaybillTrackVO; @@ -230,6 +231,13 @@ public class WaybillController extends BladeController { waybillImportBatchService.exportFailures(request, response); } + @PostMapping("/import-batch/duplicates") + @ApiOperationSupport(order = 6) + @Operation(summary = "查询与已有运单重复的导入行") + public R> checkImportDuplicates(@RequestBody WaybillImportBatchRequest request) { + return R.data(waybillImportBatchService.checkDuplicates(request)); + } + @PostMapping("/import-batch/confirm") @ApiOperationSupport(order = 7) @Operation(summary = "确认运单批量导入") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.java index 86e7a57e..7c30968e 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.java @@ -13,8 +13,9 @@ import org.apache.ibatis.annotations.Delete; public interface VoucherWaybillBatchMapper extends BaseMapper { @Delete("DELETE FROM blade_voucher_waybill_batch WHERE voucher_id = #{voucherId}") int deletePhysicalByVoucherId(@Param("voucherId") Long voucherId); - IPage> selectVoucherWaybillBatchPage(IPage page, @Param("tenantId") String tenantId, @Param("batchNo") String batchNo, @Param("createUser") String createUser, - @Param("waybillCount") Integer waybillCount, @Param("createTimeStart") String createTimeStart, @Param("createTimeEnd") String createTimeEnd, + IPage> selectVoucherWaybillBatchPage(IPage page, @Param("tenantId") String tenantId, @Param("batchNo") String batchNo, + @Param("projectId") Long projectId, @Param("createUser") String createUser, @Param("waybillCount") Integer waybillCount, + @Param("createTimeStart") String createTimeStart, @Param("createTimeEnd") String createTimeEnd, @Param("restrictCarrier") boolean restrictCarrier, @Param("carrierName") String carrierName); List> selectWaybillBatchesByIds(@Param("tenantId") String tenantId, @Param("ids") List ids, @Param("restrictCarrier") boolean restrictCarrier, @Param("carrierName") String carrierName); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.xml b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.xml index 2eadd452..4b599bb5 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.xml +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/VoucherWaybillBatchMapper.xml @@ -4,12 +4,14 @@