新增新增贷款查询和导出

This commit is contained in:
wjj
2026-07-03 10:01:17 +08:00
parent 8b9226643c
commit bb41fd7e89
14 changed files with 794 additions and 0 deletions

View File

@@ -8,6 +8,8 @@ import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferDetailQueryD
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectFamilyAssetLiabilityDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectFamilyAssetLiabilityListQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectIncreaseLendingQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectIncreaseLendingExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedRecruitmentDetailVO;
@@ -16,16 +18,21 @@ import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedTransferDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedTransferListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectIncreaseLendingListVO;
import com.ruoyi.ccdi.project.service.CcdiProjectAccessService;
import com.ruoyi.ccdi.project.service.ICcdiProjectSpecialCheckService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -138,4 +145,29 @@ public class CcdiProjectSpecialCheckController extends BaseController {
CcdiProjectExtendedTransferDetailVO result = specialCheckService.getExtendedTransferDetail(queryDTO);
return AjaxResult.success(result);
}
/**
* 查询新增贷款列表
*/
@GetMapping("/increase-lending/list")
@Operation(summary = "查询新增贷款列表")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getIncreaseLendingList(@Validated CcdiProjectIncreaseLendingQueryDTO queryDTO) {
projectAccessService.assertCanRead(queryDTO.getProjectId());
CcdiProjectIncreaseLendingListVO result = specialCheckService.getIncreaseLendingList(queryDTO);
return AjaxResult.success(result);
}
/**
* 导出新增贷款列表
*/
@PostMapping("/increase-lending/export")
@Operation(summary = "导出新增贷款列表")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public void exportIncreaseLending(HttpServletResponse response, @Validated CcdiProjectIncreaseLendingQueryDTO queryDTO) {
projectAccessService.assertCanRead(queryDTO.getProjectId());
List<CcdiProjectIncreaseLendingExcel> rows = specialCheckService.exportIncreaseLendingList(queryDTO);
ExcelUtil<CcdiProjectIncreaseLendingExcel> util = new ExcelUtil<>(CcdiProjectIncreaseLendingExcel.class);
util.exportExcel(response, rows, "新增贷款查询");
}
}

View File

@@ -0,0 +1,36 @@
package com.ruoyi.ccdi.project.domain.dto;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 项目新增贷款查询入参
*/
@Data
public class CcdiProjectIncreaseLendingQueryDTO {
/** 项目ID */
@NotNull(message = "项目ID不能为空")
private Long projectId;
/** 柜员号 */
private String staffId;
/** 员工身份证号 */
private String staffIdCard;
/** 审核人柜员号 */
private String approver;
/** 发放日期起 */
private String loanStartDate;
/** 发放日期止 */
private String loanEndDate;
/** 页码 */
private Integer pageNum = 1;
/** 每页条数 */
private Integer pageSize = 10;
}

View File

@@ -0,0 +1,84 @@
package com.ruoyi.ccdi.project.domain.excel;
import com.ruoyi.common.annotation.Excel;
import java.math.BigDecimal;
import lombok.Data;
/**
* 新增贷款查询导出对象
*/
@Data
public class CcdiProjectIncreaseLendingExcel {
/** 柜员号 */
@Excel(name = "柜员号")
private String staffId;
/** 员工姓名 */
@Excel(name = "员工姓名")
private String staffName;
/** 员工身份证 */
@Excel(name = "员工身份证")
private String staffIdCard;
/** 部门 */
@Excel(name = "部门")
private String deptName;
/** 合同编号 */
@Excel(name = "合同编号")
private String contractNo;
/** 放款机构号 */
@Excel(name = "放款机构号")
private String lendingOrgNo;
/** 借款人 */
@Excel(name = "借款人")
private String borrowerName;
/** 借款人证件号 */
@Excel(name = "借款人证件号")
private String borrowerCertNo;
/** 贷款产品 */
@Excel(name = "贷款产品")
private String loanProduct;
/** 合同金额 */
@Excel(name = "合同金额")
private BigDecimal contractAmount;
/** 当前余额 */
@Excel(name = "当前余额")
private BigDecimal loanBalance;
/** 发放日期 */
@Excel(name = "发放日期")
private String loanStartDate;
/** 到期日期 */
@Excel(name = "到期日期")
private String loanEndDate;
/** 合同状态 */
@Excel(name = "合同状态")
private String status;
/** 五级分类 */
@Excel(name = "五级分类")
private String fiveClassification;
/** 客户经理ID */
@Excel(name = "客户经理ID")
private String customerManagerId;
/** 客户经理 */
@Excel(name = "客户经理")
private String customerManagerName;
/** 审批人 */
@Excel(name = "审批人")
private String approver;
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.ccdi.project.domain.vo;
import java.math.BigDecimal;
import lombok.Data;
/**
* 项目新增贷款查询列表项
*/
@Data
public class CcdiProjectIncreaseLendingListItemVO {
/** 员工ID/柜员号 */
private String staffId;
/** 员工姓名 */
private String staffName;
/** 员工身份证号 */
private String staffIdCard;
/** 所属部门 */
private String deptName;
/** 合同编号 */
private String contractNo;
/** 放款机构号 */
private String lendingOrgNo;
/** 借款人名称 */
private String borrowerName;
/** 借款人证件号码 */
private String borrowerCertNo;
/** 贷款产品 */
private String loanProduct;
/** 合同金额 */
private BigDecimal contractAmount;
/** 当前贷款余额 */
private BigDecimal loanBalance;
/** 贷款发放日期 */
private String loanStartDate;
/** 贷款到期日期 */
private String loanEndDate;
/** 合同状态 */
private String status;
/** 五级分类 */
private String fiveClassification;
/** 客户经理ID */
private String customerManagerId;
/** 客户经理姓名 */
private String customerManagerName;
/** 审批人 */
private String approver;
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.ccdi.project.domain.vo;
import java.util.List;
import lombok.Data;
/**
* 项目新增贷款查询列表结果
*/
@Data
public class CcdiProjectIncreaseLendingListVO {
/** 列表数据 */
private List<CcdiProjectIncreaseLendingListItemVO> rows;
/** 总数 */
private Long total;
}

View File

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedPurchaseQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedRecruitmentQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectIncreaseLendingQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectIncreaseLendingExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseListItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseSupplierVO;
@@ -15,6 +17,7 @@ import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityListItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyDebtItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectIncreaseLendingListItemVO;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -145,6 +148,28 @@ public interface CcdiProjectSpecialCheckMapper {
@Param("query") CcdiProjectExtendedTransferQueryDTO queryDTO
);
/**
* 查询项目新增贷款列表
*
* @param page 分页对象
* @param queryDTO 查询条件
* @return 分页结果
*/
Page<CcdiProjectIncreaseLendingListItemVO> selectIncreaseLendingPage(
@Param("page") Page<CcdiProjectIncreaseLendingListItemVO> page,
@Param("query") CcdiProjectIncreaseLendingQueryDTO queryDTO
);
/**
* 查询项目新增贷款导出列表
*
* @param queryDTO 查询条件
* @return 导出列表
*/
List<CcdiProjectIncreaseLendingExcel> selectIncreaseLendingExportList(
@Param("query") CcdiProjectIncreaseLendingQueryDTO queryDTO
);
/**
* 查询专项核查调动拓展详情
*

View File

@@ -8,6 +8,8 @@ import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferDetailQueryD
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectFamilyAssetLiabilityDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectFamilyAssetLiabilityListQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectIncreaseLendingQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectIncreaseLendingExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedRecruitmentDetailVO;
@@ -16,6 +18,8 @@ import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedTransferDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedTransferListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectIncreaseLendingListVO;
import java.util.List;
/**
* 项目专项核查服务接口
@@ -91,4 +95,20 @@ public interface ICcdiProjectSpecialCheckService {
* @return 详情结果
*/
CcdiProjectExtendedTransferDetailVO getExtendedTransferDetail(CcdiProjectExtendedTransferDetailQueryDTO queryDTO);
/**
* 查询项目新增贷款列表
*
* @param queryDTO 查询条件
* @return 列表结果
*/
CcdiProjectIncreaseLendingListVO getIncreaseLendingList(CcdiProjectIncreaseLendingQueryDTO queryDTO);
/**
* 导出项目新增贷款列表
*
* @param queryDTO 查询条件
* @return 导出列表
*/
List<CcdiProjectIncreaseLendingExcel> exportIncreaseLendingList(CcdiProjectIncreaseLendingQueryDTO queryDTO);
}

View File

@@ -10,6 +10,8 @@ import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferDetailQueryD
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectExtendedTransferQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectFamilyAssetLiabilityDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectFamilyAssetLiabilityListQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectIncreaseLendingQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectIncreaseLendingExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseListItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectExtendedPurchaseListVO;
@@ -25,10 +27,13 @@ import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityListItemV
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyDebtDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyIncomeDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectIncreaseLendingListItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectIncreaseLendingListVO;
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
import com.ruoyi.ccdi.project.mapper.CcdiProjectSpecialCheckMapper;
import com.ruoyi.ccdi.project.service.ICcdiProjectSpecialCheckService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
@@ -178,6 +183,37 @@ public class CcdiProjectSpecialCheckServiceImpl implements ICcdiProjectSpecialCh
return detail;
}
@Override
public CcdiProjectIncreaseLendingListVO getIncreaseLendingList(CcdiProjectIncreaseLendingQueryDTO queryDTO) {
validateIncreaseLendingQuery(queryDTO);
Page<CcdiProjectIncreaseLendingListItemVO> page = new Page<>(
defaultPageNum(queryDTO.getPageNum()),
defaultPageSize(queryDTO.getPageSize())
);
Page<CcdiProjectIncreaseLendingListItemVO> resultPage = specialCheckMapper.selectIncreaseLendingPage(page, queryDTO);
CcdiProjectIncreaseLendingListVO result = new CcdiProjectIncreaseLendingListVO();
result.setRows(resultPage == null ? List.of() : defaultList(resultPage.getRecords()));
result.setTotal(resultPage == null ? 0L : resultPage.getTotal());
return result;
}
@Override
public List<CcdiProjectIncreaseLendingExcel> exportIncreaseLendingList(CcdiProjectIncreaseLendingQueryDTO queryDTO) {
validateIncreaseLendingQuery(queryDTO);
return defaultList(specialCheckMapper.selectIncreaseLendingExportList(queryDTO));
}
private void validateIncreaseLendingQuery(CcdiProjectIncreaseLendingQueryDTO queryDTO) {
ensureProjectExists(queryDTO.getProjectId());
if (StringUtils.isBlank(queryDTO.getStaffId())
&& StringUtils.isBlank(queryDTO.getStaffIdCard())
&& StringUtils.isBlank(queryDTO.getApprover())) {
throw new ServiceException("柜员号、员工身份证和审核人柜员号至少填写一项");
}
}
private void ensureProjectExists(Long projectId) {
CcdiProject project = projectMapper.selectById(projectId);
if (project == null) {

View File

@@ -67,6 +67,28 @@
<result property="transferDate" column="transfer_date"/>
</resultMap>
<resultMap id="IncreaseLendingListItemResultMap"
type="com.ruoyi.ccdi.project.domain.vo.CcdiProjectIncreaseLendingListItemVO">
<result property="staffId" column="staff_id"/>
<result property="staffName" column="staff_name"/>
<result property="staffIdCard" column="staff_id_card"/>
<result property="deptName" column="dept_name"/>
<result property="contractNo" column="contract_no"/>
<result property="lendingOrgNo" column="lending_org_no"/>
<result property="borrowerName" column="borrower_name"/>
<result property="borrowerCertNo" column="borrower_cert_no"/>
<result property="loanProduct" column="loan_product"/>
<result property="contractAmount" column="contract_amount"/>
<result property="loanBalance" column="loan_balance"/>
<result property="loanStartDate" column="loan_start_date"/>
<result property="loanEndDate" column="loan_end_date"/>
<result property="status" column="status"/>
<result property="fiveClassification" column="five_classification"/>
<result property="customerManagerId" column="customer_manager_id"/>
<result property="customerManagerName" column="customer_manager_name"/>
<result property="approver" column="approver"/>
</resultMap>
<resultMap id="FamilyAssetLiabilityDetailResultMap"
type="com.ruoyi.ccdi.project.domain.vo.CcdiProjectFamilyAssetLiabilityDetailVO">
<association property="incomeDetail"
@@ -806,4 +828,95 @@
)
</select>
<select id="selectIncreaseLendingPage" resultMap="IncreaseLendingListItemResultMap">
select
trim(loan.customer_manager_id) as staff_id,
coalesce(staff.name, loan.customer_manager_name) as staff_name,
staff.id_card as staff_id_card,
dept.dept_name,
loan.nfaacono as contract_no,
loan.nfaabrno as lending_org_no,
loan.borrower_name,
loan.borrower_cert_no,
loan.loan_product,
loan.contract_amount,
loan.loan_balance,
date_format(loan.loan_start_date, '%Y-%m-%d') as loan_start_date,
date_format(loan.loan_end_date, '%Y-%m-%d') as loan_end_date,
loan.status,
loan.five_classification,
loan.customer_manager_id,
loan.customer_manager_name,
loan.approver
from ccdi_increase_lending loan
left join ccdi_base_staff staff
on trim(loan.customer_manager_id) = cast(staff.staff_id as char)
left join sys_dept dept
on dept.dept_id = staff.dept_id
<where>
<if test="query.staffId != null and query.staffId != ''">
and trim(loan.customer_manager_id) = #{query.staffId}
</if>
<if test="query.staffIdCard != null and query.staffIdCard != ''">
and staff.id_card = #{query.staffIdCard}
</if>
<if test="query.approver != null and query.approver != ''">
and trim(loan.approver) = #{query.approver}
</if>
<if test="query.loanStartDate != null and query.loanStartDate != ''">
and loan.loan_start_date &gt;= #{query.loanStartDate}
</if>
<if test="query.loanEndDate != null and query.loanEndDate != ''">
and loan.loan_start_date &lt;= #{query.loanEndDate}
</if>
</where>
order by loan.loan_start_date desc, loan.nfaacono desc
</select>
<select id="selectIncreaseLendingExportList"
resultType="com.ruoyi.ccdi.project.domain.excel.CcdiProjectIncreaseLendingExcel">
select
trim(loan.customer_manager_id) as staff_id,
coalesce(staff.name, loan.customer_manager_name) as staff_name,
staff.id_card as staff_id_card,
dept.dept_name,
loan.nfaacono as contract_no,
loan.nfaabrno as lending_org_no,
loan.borrower_name,
loan.borrower_cert_no,
loan.loan_product,
loan.contract_amount,
loan.loan_balance,
date_format(loan.loan_start_date, '%Y-%m-%d') as loan_start_date,
date_format(loan.loan_end_date, '%Y-%m-%d') as loan_end_date,
loan.status,
loan.five_classification,
loan.customer_manager_id,
loan.customer_manager_name,
loan.approver
from ccdi_increase_lending loan
left join ccdi_base_staff staff
on trim(loan.customer_manager_id) = cast(staff.staff_id as char)
left join sys_dept dept
on dept.dept_id = staff.dept_id
<where>
<if test="query.staffId != null and query.staffId != ''">
and trim(loan.customer_manager_id) = #{query.staffId}
</if>
<if test="query.staffIdCard != null and query.staffIdCard != ''">
and staff.id_card = #{query.staffIdCard}
</if>
<if test="query.approver != null and query.approver != ''">
and trim(loan.approver) = #{query.approver}
</if>
<if test="query.loanStartDate != null and query.loanStartDate != ''">
and loan.loan_start_date &gt;= #{query.loanStartDate}
</if>
<if test="query.loanEndDate != null and query.loanEndDate != ''">
and loan.loan_start_date &lt;= #{query.loanEndDate}
</if>
</where>
order by loan.loan_start_date desc, loan.nfaacono desc
</select>
</mapper>

View File

@@ -0,0 +1,38 @@
# 新增贷款查询模块实施计划
## 需求范围
在项目详情的“专项排查”页面中,于资金流向图谱下方新增“新增贷款查询”模块。模块用于查询某个员工经办/管户或审核的新增贷款合同,支持通过柜员号、员工身份证、审核人柜员号和发放日期筛选,并支持导出单人查询结果。
## 设计口径
- 页面位置:`项目详情 > 专项排查 > 资金流向图谱下方`
- 数据范围:按输入的柜员号或员工身份证查询对应贷款,不默认展开全量列表,不再限定当前项目排查人员范围;柜员号精确匹配
- 关联方式:柜员号对应 `ccdi_increase_lending.customer_manager_id`
- 查询条件:柜员号、员工身份证、审核人柜员号、发放日期范围;柜员号、员工身份证、审核人柜员号均使用等值查询,不做模糊匹配
- 查询交互:默认展示筛选框和空表头;输入柜员号或员工身份证并点击查询后加载分页结果
- 导出口径:导出当前单人查询条件下的全部匹配贷款明细,不受当前分页页码限制
## 后端实施
1.`CcdiProjectSpecialCheckController` 新增 `/increase-lending/list` 查询接口。
2. 新增 `CcdiProjectIncreaseLendingQueryDTO`,包含 `projectId``staffId``staffIdCard``approver``loanStartDate``loanEndDate`、分页参数。
3. 新增 `CcdiProjectIncreaseLendingListVO``CcdiProjectIncreaseLendingListItemVO`
4.`CcdiProjectSpecialCheckServiceImpl` 增加分页查询方法。
5.`CcdiProjectSpecialCheckMapper.xml` 使用 `ccdi_increase_lending.customer_manager_id` 直接精确匹配柜员号查询,员工身份证通过 `ccdi_base_staff.id_card` 精确过滤,审核人柜员号通过 `ccdi_increase_lending.approver` 精确过滤,并按 `loan_start_date` 支持发放日期范围筛选。
6. 新增导出 Excel 对象和 `/increase-lending/export` 接口,复用同一查询口径导出全部匹配明细。
## 前端实施
1.`projectSpecialCheck.js` 新增 `getIncreaseLendingList` API。
2. 新增 `IncreaseLendingSection.vue`,默认展示筛选区和空表头,查询后展示贷款列表与分页;筛选区包含柜员号、员工身份证、审核人柜员号、发放日期范围。
3.`SpecialCheck.vue` 的资金流向图谱下方挂载新增贷款查询模块。
4. 在筛选按钮区新增“导出”按钮,仅在填写柜员号、员工身份证或审核人柜员号后允许导出。
## 验证计划
- 后端执行 `mvn -pl ccdi-project -DskipTests compile`
- 前端执行 `npm run build:prod`
- 打开真实项目详情页,进入专项排查,确认新增贷款查询模块显示在资金流向图谱下方
- 验证柜员号、员工身份证、审核人柜员号、发放日期筛选条件能触发列表查询
- 验证导出接口导出当前查询条件下的全部结果

View File

@@ -0,0 +1,34 @@
# 新增贷款查询模块实施记录
## 本次修改
- 在项目专项排查后端新增“新增贷款查询”分页接口。
- 新增查询 DTO 与列表 VO返回员工信息、合同编号、借款人、贷款产品、合同金额、当前余额、发放日期、到期日期、合同状态、五级分类等字段。
- 柜员号查询直接精确匹配 `ccdi_increase_lending.customer_manager_id`,员工身份证查询通过 `ccdi_base_staff.id_card` 精确过滤,审核人柜员号查询直接精确匹配 `ccdi_increase_lending.approver`,并支持按贷款发放日期范围过滤。
- 前后端均限制柜员号、员工身份证和审核人柜员号至少填写一项,避免默认展开大列表。
- 新增“新增贷款查询”导出接口与 Excel 导出对象,按当前单人查询条件导出全部匹配贷款明细,不受表格分页页码限制。
- 在前端专项排查页面新增 `IncreaseLendingSection`,放置于资金流向图谱下方、拓展查询上方。
- 新增柜员号、员工身份证、审核人柜员号与发放日期筛选框;默认展示空表头,点击查询后加载分页贷款列表,并支持导出当前查询结果。
## 影响范围
- 后端:`ccdi-project` 模块项目专项排查接口。
- 前端:`ruoyi-ui` 项目详情专项排查页面。
- 数据库:不新增或修改表结构,依赖既有 `ccdi_increase_lending` 表。
## 验证情况
- 后端执行 `mvn -pl ccdi-project -DskipTests compile`,编译被既有 `CcdiFileUploadServiceImpl` 调用 `LsfxAnalysisClient.uploadFile(Integer, File, String)` 与当前客户端方法签名 `uploadFile(Integer, File)` 不一致阻塞;阻塞点不在本次新增贷款查询改动范围内。
- 前端执行 `npm run build:prod` 成功,存在既有资源体积告警;已覆盖“默认不展示结果表、输入柜员号或员工身份证查询后展开列表”的交互调整。
- 当前数据库 `ccdi_increase_lending` 已存在 6 条演示数据,柜员号为 `9021001``9021006`
- 早期联调用本地 mock 验证过页面交互;最终验收以真实 Java 后端 `62318` 为准。
- 按项目要求执行 `nvm use` 时,由于未指定版本返回“缺少版本参数”;随后使用当前 Node `v22.22.3`、npm `10.9.8` 执行 `npm run build:prod` 通过。
- 真实页面浏览器自动化检查受本地 Node/npm 环境限制未复跑;本地 8080 前端服务已存在,可刷新页面手工验证。
- 后续调整柜员号口径:`customer_manager_id` 已由模糊匹配改为精确匹配,前端不做 7 位格式提示,输入半截柜员号自然无结果。
- 审核人字段口径:当前按 `approver` 精确匹配“审核人柜员号”,字段为空时查询自然无结果;后续数据入库后无需改代码即可按审核人柜员号联动查询和导出。
- 后端验证:`mvn -pl ruoyi-admin -am -DskipTests compile``mvn -pl ruoyi-admin -am clean package -DskipTests` 均通过;真实后端已在 `62318` 启动,未登录直接访问业务接口返回 `401`,说明当前端口已由 Java 后端接管。
- 提交前检查:当前 `dev-ui` 可继续提交本次功能;但 `dev``dev-ui` 之间已有大量历史冲突,后续直接合入 `dev` 需要单独解决冲突,不能视为无冲突直合。
- 本次收紧单人查询:员工身份证条件同步改为精确匹配;真实接口验证 `projectId=90337&staffId=9021001` 返回 `total=1``staffId/customerManagerId` 均为 `9021001``staffId=902100` 返回 `total=0`
- 新增导出验证:真实接口 `projectId=90337&staffId=9021001` 导出 Excel 成功,文件 sheet 为“新增贷款查询”,表头包含“审批人”,导出 1 行贷款明细。
- 审核人柜员号验证:当前 `approver` 字段缺少有效数据,真实接口 `projectId=90337&approver=9021001` 返回 `total=0`;后续 `approver` 有柜员号数据后可直接联动查询和导出。
-`.nvmrc` 执行 `nvm use 14.21.3` 后,本地 nvm 目录缺少 `npm.cmd`,无法用 Node 14 启动前端构建;改用本机可用的 Node `v22.22.3` / npm `10.9.8` 执行 `npm run build:prod` 通过,存在既有资源体积告警。

View File

@@ -100,3 +100,21 @@ export function getExtendedTransferDetail(params) {
},
});
}
export function getIncreaseLendingList(params) {
const { projectId, staffId, staffIdCard, approver, loanStartDate, loanEndDate, pageNum, pageSize } = params;
return request({
url: "/ccdi/project/special-check/increase-lending/list",
method: "get",
params: {
projectId,
staffId,
staffIdCard,
approver,
loanStartDate,
loanEndDate,
pageNum,
pageSize,
},
});
}

View File

@@ -0,0 +1,272 @@
<template>
<section class="increase-lending-section">
<div class="section-card">
<div class="block-header">
<div>
<div class="block-title">新增贷款查询</div>
<div class="block-subtitle">按客户经理柜员号查询经办/管户新增贷款</div>
</div>
</div>
<el-form :model="queryParams" size="small" :inline="true" label-width="104px" class="query-form">
<el-form-item label="柜员号">
<el-input
v-model="queryParams.staffId"
placeholder="请输入柜员号"
clearable
style="width: 180px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="员工身份证">
<el-input
v-model="queryParams.staffIdCard"
placeholder="请输入员工身份证"
clearable
style="width: 220px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="审核人柜员号">
<el-input
v-model="queryParams.approver"
placeholder="请输入审核人柜员号"
clearable
style="width: 180px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="发放日期">
<el-date-picker
v-model="loanDateRange"
type="daterange"
value-format="yyyy-MM-dd"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
clearable
style="width: 260px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" size="mini" @click="handleQuery">查询</el-button>
<el-button size="mini" :disabled="!hasPersonCondition" @click="handleExport">导出</el-button>
<el-button size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<div class="result-wrapper">
<el-table
v-loading="loading"
:data="rows"
:empty-text="searched ? '暂无数据' : '请输入条件后点击查询'"
border
class="increase-lending-table"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="staffId" label="柜员号" width="100" />
<el-table-column prop="staffName" label="员工姓名" min-width="110" />
<el-table-column prop="staffIdCard" label="员工身份证" min-width="170" />
<el-table-column prop="deptName" label="部门" min-width="140" />
<el-table-column prop="contractNo" label="合同编号" min-width="150" />
<el-table-column prop="borrowerName" label="借款人" min-width="120" />
<el-table-column prop="loanProduct" label="贷款产品" min-width="140" />
<el-table-column label="合同金额" min-width="120" align="right">
<template slot-scope="scope">{{ formatAmount(scope.row.contractAmount) }}</template>
</el-table-column>
<el-table-column label="当前余额" min-width="120" align="right">
<template slot-scope="scope">{{ formatAmount(scope.row.loanBalance) }}</template>
</el-table-column>
<el-table-column prop="loanStartDate" label="发放日期" width="120" />
<el-table-column prop="loanEndDate" label="到期日期" width="120" />
<el-table-column prop="status" label="合同状态" width="110" />
<el-table-column prop="fiveClassification" label="五级分类" width="110" />
<el-table-column prop="approver" label="审批人" min-width="110" />
</el-table>
<pagination
v-show="searched && total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="loadList"
/>
</div>
</div>
</section>
</template>
<script>
import { getIncreaseLendingList } from "@/api/ccdi/projectSpecialCheck";
export default {
name: "IncreaseLendingSection",
props: {
projectId: {
type: [String, Number],
required: true,
},
},
data() {
return {
loading: false,
searched: false,
rows: [],
total: 0,
queryParams: {
staffId: "",
staffIdCard: "",
approver: "",
loanStartDate: "",
loanEndDate: "",
pageNum: 1,
pageSize: 10,
},
loanDateRange: [],
};
},
watch: {
projectId() {
this.resetQuery();
},
},
computed: {
hasPersonCondition() {
return Boolean(this.queryParams.staffId || this.queryParams.staffIdCard || this.queryParams.approver);
},
},
methods: {
handleQuery() {
if (!this.hasPersonCondition) {
this.$message.warning("请输入柜员号、员工身份证或审核人柜员号后查询");
return;
}
this.syncLoanDateRange();
this.searched = true;
this.queryParams.pageNum = 1;
this.loadList();
},
resetQuery() {
this.queryParams = {
staffId: "",
staffIdCard: "",
approver: "",
loanStartDate: "",
loanEndDate: "",
pageNum: 1,
pageSize: 10,
};
this.loanDateRange = [];
this.searched = false;
this.rows = [];
this.total = 0;
},
handleExport() {
if (!this.hasPersonCondition) {
this.$message.warning("请输入柜员号、员工身份证或审核人柜员号后导出");
return;
}
this.syncLoanDateRange();
this.download(
"ccdi/project/special-check/increase-lending/export",
{
projectId: this.projectId,
staffId: this.queryParams.staffId,
staffIdCard: this.queryParams.staffIdCard,
approver: this.queryParams.approver,
loanStartDate: this.queryParams.loanStartDate,
loanEndDate: this.queryParams.loanEndDate,
},
`新增贷款查询_${this.queryParams.staffId || this.queryParams.staffIdCard || this.queryParams.approver}_${Date.now()}.xlsx`
);
},
async loadList() {
this.syncLoanDateRange();
if (!this.projectId) {
this.rows = [];
this.total = 0;
return;
}
this.loading = true;
try {
const response = await getIncreaseLendingList({
projectId: this.projectId,
...this.queryParams,
});
const data = (response && response.data) || {};
this.rows = Array.isArray(data.rows) ? data.rows : [];
this.total = Number(data.total || 0);
} catch (error) {
this.rows = [];
this.total = 0;
this.$message.error("新增贷款查询失败");
} finally {
this.loading = false;
}
},
formatAmount(value) {
if (value === null || value === undefined || value === "") {
return "-";
}
return Number(value).toLocaleString("zh-CN", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
},
syncLoanDateRange() {
const range = Array.isArray(this.loanDateRange) ? this.loanDateRange : [];
this.queryParams.loanStartDate = range[0] || "";
this.queryParams.loanEndDate = range[1] || "";
},
},
};
</script>
<style lang="scss" scoped>
.increase-lending-section {
margin-top: 16px;
margin-bottom: 16px;
}
.section-card {
padding: 20px;
border-radius: 0;
background: #fff;
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);
}
.block-header {
margin-bottom: 14px;
}
.block-title {
font-size: 16px;
font-weight: 600;
color: #1f2937;
}
.block-subtitle {
margin-top: 4px;
font-size: 12px;
color: #94a3b8;
}
.query-form {
margin-bottom: 8px;
}
.result-wrapper {
margin-top: 8px;
}
.increase-lending-table {
border-radius: 12px;
overflow: hidden;
}
:deep(.increase-lending-table th) {
background: #f8fafc;
color: #64748b;
}
</style>

View File

@@ -27,6 +27,8 @@
ref="fundGraphSection"
:project-id="projectId"
/>
<increase-lending-section :project-id="projectId" />
</div>
<div v-if="projectId" class="special-check-extended-wrapper">
@@ -41,6 +43,7 @@ import { getFamilyAssetLiabilityList } from "@/api/ccdi/projectSpecialCheck";
import ExtendedQuerySection from "./ExtendedQuerySection";
import FamilyAssetLiabilitySection from "./FamilyAssetLiabilitySection";
import FundGraphSection from "./graph/FundGraphSection";
import IncreaseLendingSection from "./IncreaseLendingSection";
export default {
name: "SpecialCheck",
@@ -48,6 +51,7 @@ export default {
ExtendedQuerySection,
FamilyAssetLiabilitySection,
FundGraphSection,
IncreaseLendingSection,
},
props: {
projectId: {