package com.zksy.property.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zksy.property.domain.*; import com.zksy.property.domain.bo.*; import com.zksy.property.domain.dto.ContractFormDTO; import com.zksy.property.domain.dto.ReceiptDto; import com.zksy.property.domain.dto.ReturnReceiptDto; import com.zksy.property.domain.vo.CanBeGetReceiptVo; import com.zksy.property.domain.vo.CanBeGetReturnReceiptVo; import com.zksy.property.factory.ContractFactory; import com.zksy.property.mapper.AContractInfoMapper; import com.zksy.property.service.*; import com.zksy.service.MinioFileStorageService; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import static com.zksy.utils.util.generateAssetNumber; /** * @author Administrator * @description 针对表【a_contract_info(合同信息表)】的数据库操作Service实现 * @createDate 2025-07-14 11:59:44 */ @Service public class AContractInfoServiceImpl extends ServiceImpl implements AContractInfoService { @Autowired private MinioFileStorageService minioFileStorageService; @Autowired private AReceiptInfoService aReceiptInfoService; @Autowired private ARefundService aRefundService; @Autowired private AContractInfoMapper baseMapper; @Override public String returnRent(String houseId) { ASimplifiedHouseInfo houseInfo = aSimplifiedHouseInfoService.getById(houseId); if(houseInfo.getStatus().equals("空闲")){ throw new RuntimeException("此房屋未出租"); } AContractInfo contractInfo = this.getBySimplifiedHouseId(houseId); if(contractInfo == null){ throw new RuntimeException("数据不存在"); } houseInfo.setStatus("空闲"); //删除租户信息 ATenantInfo tenantInfo = aTenantInfoService.getBySimplifiedHouseId(houseId); if(tenantInfo != null){ aTenantInfoService.removeById(tenantInfo); } aSimplifiedHouseInfoService.updateById(houseInfo); contractInfo.setContractStatus("已退租"); this.updateById(contractInfo); return "退租成功"; } @Override @SneakyThrows public String uploadSignContract(String contractId, MultipartFile file) { AContractInfo contractInfo = this.getById(contractId); if (contractInfo == null){ throw new RuntimeException("数据不存在"); } if(StringUtils.isNotBlank(contractInfo.getSignContractUrl())){ minioFileStorageService.deleteFile(contractInfo.getSignContractUrl()); } String path = minioFileStorageService.uploadFile(file, "合同"); contractInfo.setSignContractUrl(path); contractInfo.setUpdateTime(LocalDateTime.now()); return this.updateById(contractInfo) ? "上传成功" : "上传失败"; } @Override public String getReceipt(String contractId, ReceiptDto dto) { /*LambdaQueryWrapper aReceiptInfoLambdaQueryWrapper = new LambdaQueryWrapper<>(); aReceiptInfoLambdaQueryWrapper.eq(AReceiptInfo::getContractId,contractId); var res = aReceiptInfoService.getOne(aReceiptInfoLambdaQueryWrapper); if(res != null){ throw new BusinessException(999,"此合同已生成收据",res.getAttachmentUrl()); }*/ AContractInfo contractInfo = this.getById(contractId); if (contractInfo == null){ throw new RuntimeException("数据不存在"); } ASimplifiedHouseInfo houseInfo = aSimplifiedHouseInfoService.getById(contractInfo.getSimplifiedHouseId()); if(houseInfo == null){ throw new RuntimeException("数据不存在"); } String receiptNumber = generateAssetNumber(); RentalTempBo bo = new RentalTempBo(); bo.setD1(dto.getPaymentUnit()); bo.setD2(dto.getPaymentMethod()); bo.setD3(convertToUppercase(dto.getRmb())); bo.setD4(String.valueOf(dto.getRmb())); bo.setD5(String.valueOf(dto.getZj())); bo.setD6(String.valueOf(dto.getWyf())); bo.setD7(String.valueOf(dto.getYj())); bo.setD8(String.valueOf(dto.getSf())); bo.setD9(dto.getPaymentReason()); bo.setD10(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy年M月d日"))); bo.setD11(dto.getOperator()); bo.setD12(receiptNumber); DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy年M月d日"); LocalDate rzrqDate = LocalDate.parse(dto.getRzrq(), inputFormatter); bo.setD13(rzrqDate.format(outputFormatter)); if(StringUtils.isNotBlank(dto.getStartDate())){ LocalDate startDate = LocalDate.parse(dto.getStartDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd")); bo.setD14(startDate.format(DateTimeFormatter.ofPattern("yyyy年M月d日"))); } if(StringUtils.isNotBlank(dto.getEndDate())){ LocalDate endDate = LocalDate.parse(dto.getEndDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd")); bo.setD15(endDate.format(DateTimeFormatter.ofPattern("yyyy年M月d日"))); } bo.setD16(String.valueOf(dto.getDf())); String attachmentUrl = aRentalContractService.generatorRental("4", bo, true); AReceiptInfo receiptInfo = new AReceiptInfo(); receiptInfo.setContractId(contractId); receiptInfo.setReceiptNumber(receiptNumber); receiptInfo.setPayer(dto.getPaymentUnit()); receiptInfo.setPaymentMethod(dto.getPaymentMethod()); receiptInfo.setTotalAmount(dto.getRmb()); receiptInfo.setRent(dto.getZj()); receiptInfo.setPropertyFee(dto.getWyf()); receiptInfo.setDeposit(dto.getYj()); receiptInfo.setWaterFee(dto.getSf()); receiptInfo.setElectricityBill(dto.getDf()); if (StringUtils.isNotBlank(dto.getRzrq())){ receiptInfo.setAccountingDate(LocalDate.parse(dto.getRzrq())); } receiptInfo.setReceiptReason(dto.getPaymentReason()); receiptInfo.setAttachmentUrl(attachmentUrl); receiptInfo.setGenerationDate(LocalDate.now()); if(StringUtils.isNotBlank(dto.getStartDate())){ receiptInfo.setStartDate(LocalDate.parse(dto.getStartDate())); } if(StringUtils.isNotBlank(dto.getEndDate())){ receiptInfo.setEndDate(LocalDate.parse(dto.getEndDate())); } receiptInfo.setOperator(dto.getOperator()); receiptInfo.setCreateTime(LocalDateTime.now()); receiptInfo.setUpdateTime(LocalDateTime.now()); aReceiptInfoService.save(receiptInfo); return attachmentUrl; } @Override public CanBeGetReceiptVo canBeDetReceiptData(String contractId) { AContractInfo contractInfo = this.getById(contractId); if (contractInfo == null){ throw new RuntimeException("数据不存在"); } ASimplifiedHouseInfo houseInfo = aSimplifiedHouseInfoService.getById(contractInfo.getSimplifiedHouseId()); if (houseInfo == null) { throw new RuntimeException("数据不存在"); } CanBeGetReceiptVo vo = new CanBeGetReceiptVo(); vo.setLd(houseInfo.getBuilding()); vo.setLc(houseInfo.getFloor()); vo.setJkdw(houseInfo.getHouseName()); vo.setZj(houseInfo.getRentRange()); vo.setYj(contractInfo.getContractDeposit()); return vo; } @Override public CanBeGetReturnReceiptVo canBeDetReturnReceiptData(String contractId) { AContractInfo contractInfo = this.getById(contractId); if (contractInfo == null){ throw new RuntimeException("数据不存在"); } ASimplifiedHouseInfo houseInfo = aSimplifiedHouseInfoService.getById(contractInfo.getSimplifiedHouseId()); if (houseInfo == null) { throw new RuntimeException("数据不存在"); } return new CanBeGetReturnReceiptVo( houseInfo.getBuilding(), houseInfo.getFloor(), houseInfo.getHouseName(), contractInfo.getContractDeposit() ); } @Override public String getReturnReceipt(String contractId, ReturnReceiptDto dto) { /*LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ARefund::getContractId,contractId); var res = aRefundService.getOne(queryWrapper); if(res != null){ throw new BusinessException(999,"此合同已生成退据",res.getAttachmentUrl()); }*/ AContractInfo contractInfo = this.getById(contractId); if (contractInfo == null){ throw new RuntimeException("数据不存在"); } ASimplifiedHouseInfo houseInfo = aSimplifiedHouseInfoService.getById(contractInfo.getSimplifiedHouseId()); if(houseInfo == null){ throw new RuntimeException("数据不存在"); } RentalTempBo bo = new RentalTempBo(); bo.setE1(dto.getDw()); bo.setE2(dto.getZh()); bo.setE3(String.valueOf(dto.getYj())); bo.setE4(String.valueOf(dto.getZj())); bo.setE5(String.valueOf(dto.getWyf())); bo.setE6(convertToUppercase(dto.getRmb())); bo.setE7(String.valueOf(dto.getRmb())); bo.setE8(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy年M月d日"))); String attachmentUrl = aRentalContractService.generatorRental("5", bo, true); ARefund refund = new ARefund(); refund.setContractId(contractId); refund.setUnit(dto.getDw()); refund.setTenant(dto.getZh()); refund.setDeposit(dto.getYj()); refund.setRent(dto.getZj()); refund.setPropertyFee(dto.getWyf()); refund.setTotalAmount(dto.getRmb()); refund.setAttachmentUrl(attachmentUrl); refund.setGenerationDate(LocalDate.now()); refund.setCreateTime(LocalDateTime.now()); refund.setUpdateTime(LocalDateTime.now()); aRefundService.save(refund); return attachmentUrl; } @Override public boolean removeBatchId(String[] ids) { try { for (String id : ids){ // 查询是否绑定了退据 ARefund refund = aRefundService.getOne(new LambdaQueryWrapper().eq(ARefund::getContractId,id),false); if(refund != null){ throw new RuntimeException("该房屋已存在退据,请先删除退据"); } // 查询是否绑定收据 AReceiptInfo receiptInfo = aReceiptInfoService.getOne(new LambdaQueryWrapper().eq(AReceiptInfo::getContractId,id),false); if(receiptInfo != null){ throw new RuntimeException("该房屋已存在收据,请先删除收据"); } AContractInfo contractInfo = this.getById(id); // 删除原合同 minioFileStorageService.deleteFile(contractInfo.getOriginalContractUrl()); // 删除签订后的合同 minioFileStorageService.deleteFile(contractInfo.getSignContractUrl()); boolean remove = this.removeById(id); if(!remove){ throw new RuntimeException("删除失败"); } return true; } }catch (Exception e){ throw new RuntimeException(e); } return false; } @Autowired @Lazy private ASimplifiedHouseInfoService aSimplifiedHouseInfoService; @Autowired private ATenantInfoService aTenantInfoService; @Override public Page findByPage(long pageNum, long pageSize, String contractNumber, String contractDate, String contractStatus,String assetType,String building,String floor, String houseName) { Page page = new Page<>(pageNum, pageSize); IPage iPage = baseMapper.selectContractWithHouse(page, contractNumber, contractDate, contractStatus,assetType, building, floor, houseName); return (Page) iPage; } @Override public List getAContractInfoList(String contractNumber, String contractDate, String contractStatus) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); queryWrapper.like(contractNumber != null, AContractInfo::getContractNumber, contractNumber); queryWrapper.eq(contractDate != null, AContractInfo::getContractDate, contractDate); queryWrapper.like(contractStatus != null, AContractInfo::getContractStatus, contractStatus); List list = this.list(queryWrapper); return list; } @Override public AContractInfo getBySimplifiedHouseId(String simplifiedHouseId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(AContractInfo::getSimplifiedHouseId, simplifiedHouseId); queryWrapper.eq(AContractInfo::getContractStatus, "有效"); return this.getOne(queryWrapper); } @Autowired private AHouseInfoDetailService aHouseInfoDetailService; @Override @Transactional public String signContract(ContractFormDTO dto) { AHouseInfoDetail houseInfoDetail = aHouseInfoDetailService.getBySimplifiedHouseId(dto.getHouseId()); ASimplifiedHouseInfo aSimplifiedHouseInfo = aSimplifiedHouseInfoService.getById(dto.getHouseId()); if (!"空闲".equals(aSimplifiedHouseInfo.getStatus())) { throw new RuntimeException("此房屋已租"); } Contract baseContract = ContractFactory.createContract(aSimplifiedHouseInfo.getAssetType()); BeanUtil.copyProperties(dto.getContractData(), baseContract); RentalTempBo bo = new RentalTempBo(); var resPath = ""; AContractInfo contractInfo = new AContractInfo(); var contractNumber = generateAssetNumber(); if (baseContract instanceof ContractA) { var contractA = (ContractA) baseContract; processContractA(contractA , aSimplifiedHouseInfo, houseInfoDetail, bo); resPath = fillContractData(bo, aSimplifiedHouseInfo.getAssetType()); contractInfo.setContractNumber(contractNumber); contractInfo.setContractDate(LocalDate.parse(contractA.getTenantTimeStart())); contractInfo.setContractTime(contractA.getTenantTime()); contractInfo.setContractExpirationDate(LocalDate.parse(contractA.getTenantTimeEnd())); contractInfo.setContractDeposit(new BigDecimal(contractA.getTenantDepositAmount())); contractInfo.setContractStatus("有效"); contractInfo.setSimplifiedHouseId(dto.getHouseId()); contractInfo.setOriginalContractUrl(resPath); contractInfo.setSignContractUrl(null); contractInfo.setCreateTime(LocalDateTime.now()); contractInfo.setUpdateTime(LocalDateTime.now()); this.save(contractInfo); } else if (baseContract instanceof ContractB) { var contractB = (ContractB) baseContract; processContractB(contractB, aSimplifiedHouseInfo, houseInfoDetail, bo); resPath = fillContractData(bo, aSimplifiedHouseInfo.getAssetType()); contractInfo.setContractNumber(contractNumber); contractInfo.setContractDate(LocalDate.parse(contractB.getLeaseStartDate())); contractInfo.setContractTime(contractB.getLeaseTermYears()); contractInfo.setContractExpirationDate(LocalDate.parse(contractB.getLeaseEndDate())); contractInfo.setContractDeposit(new BigDecimal(contractB.getDepositAmount())); contractInfo.setContractStatus("有效"); contractInfo.setSimplifiedHouseId(dto.getHouseId()); contractInfo.setOriginalContractUrl(resPath); contractInfo.setSignContractUrl(null); contractInfo.setCreateTime(LocalDateTime.now()); contractInfo.setUpdateTime(LocalDateTime.now()); this.save(contractInfo); } else if (baseContract instanceof ContractC) { var contractC = (ContractC) baseContract; processContractC(contractC, bo,contractNumber); resPath = fillContractData(bo, aSimplifiedHouseInfo.getAssetType()); contractInfo.setContractNumber(contractNumber); contractInfo.setContractDate(LocalDate.parse(contractC.getLeaseStartDate())); contractInfo.setContractTime(contractC.getLeaseTermMonths()); contractInfo.setContractExpirationDate(LocalDate.parse(contractC.getLeaseEndDate())); contractInfo.setContractDeposit(new BigDecimal(contractC.getDepositAmount())); contractInfo.setContractStatus("有效"); contractInfo.setSimplifiedHouseId(dto.getHouseId()); contractInfo.setOriginalContractUrl(resPath); contractInfo.setSignContractUrl(null); contractInfo.setCreateTime(LocalDateTime.now()); contractInfo.setUpdateTime(LocalDateTime.now()); this.save(contractInfo); } aSimplifiedHouseInfo.setStatus("已租"); aSimplifiedHouseInfoService.updateById(aSimplifiedHouseInfo); ATenantInfo aTenantInfo = new ATenantInfo(); aTenantInfo.setTenantName(dto.getRentalInfo().getRentalName()); aTenantInfo.setTenantNumber(dto.getRentalInfo().getRentalPhone()); aTenantInfo.setTenantIdCard(dto.getRentalInfo().getRentalIdCard()); aTenantInfo.setTenantInDate(LocalDate.parse(dto.getRentalInfo().getRentalTimeStart())); aTenantInfo.setTenantTime(dto.getRentalInfo().getRentalTime()); aTenantInfo.setTenantRent(new BigDecimal(dto.getRentalInfo().getRentalRect())); aTenantInfo.setSimplifiedHouseId(dto.getHouseId()); aTenantInfo.setCreateTime(LocalDateTime.now()); aTenantInfo.setUpdateTime(LocalDateTime.now()); aTenantInfoService.save(aTenantInfo); return "签约成功"; } private static void processContractC(ContractC baseContract, RentalTempBo bo,String contractNumber) { ContractC contractC = baseContract; //todo 处理bo bo.setC1(contractNumber); bo.setC2(contractC.getLessorName()); bo.setC3(contractC.getLessorLegalRep()); bo.setC4(contractC.getLessorUniCode()); bo.setC5(contractC.getLesseeName()); bo.setC6(contractC.getLesseeLegalRep()); bo.setC7(contractC.getLesseeIdCode()); bo.setC8(contractC.getPropertyLocation()); bo.setC9(contractC.getRentableArea()); bo.setC10(contractC.getUsableArea()); bo.setC11(contractC.getSharedArea()); bo.setC12(contractC.getPropertyUseNature()); bo.setC13(contractC.getStoreName()); bo.setC14(contractC.getBrand()); bo.setC15(contractC.getBusinessScope()); bo.setC16(contractC.getLeaseTermMonths()); bo.setC17(contractC.getLeaseStartDate()); bo.setC18(contractC.getLeaseEndDate()); bo.setC19(contractC.getRenovationStartDate()); bo.setC20(contractC.getRenovationEndDate()); bo.setC21(contractC.getOfficialLeaseStartDate()); bo.setC22(convertToUppercase(contractC.getAnnualRentLower())); bo.setC23(contractC.getAnnualRentLower()); bo.setC24(convertToUppercase(contractC.getAnnualPropertyFeeLower())); bo.setC25(contractC.getAnnualPropertyFeeLower()); bo.setC26(contractC.getDepositAmount()); bo.setC27(convertToUppercase(contractC.getDepositAmount())); } private static void processContractB(ContractB baseContract, ASimplifiedHouseInfo aSimplifiedHouseInfo, AHouseInfoDetail houseDetailInfo, RentalTempBo bo) { ContractB contractB = baseContract; //todo 处理bo bo.setB1(contractB.getPurpose()); bo.setB2(contractB.getLandlordName()); bo.setB3(contractB.getLandlordUniCode()); bo.setB4(contractB.getLandlordLegalRepresentative()); bo.setB5(contractB.getLandlordDuty()); bo.setB6(contractB.getTenantName()); bo.setB7(contractB.getTenantUniCode()); bo.setB8(contractB.getTenantLegalRepresentative()); bo.setB9(contractB.getTenantDuty()); bo.setB10(contractB.getWho()); bo.setB11(contractB.getWhatTime()); bo.setB12(contractB.getTitle()); bo.setB13(aSimplifiedHouseInfo.getHouseName()); bo.setB14(aSimplifiedHouseInfo.getFloor()); bo.setB15(houseDetailInfo.getArea()); bo.setB16(contractB.getSupportingRoomArea()); bo.setB17(contractB.getOfficeArea()); bo.setB18(contractB.getCanteenArea()); bo.setB19(contractB.getTotalLeasedArea()); bo.setB20(contractB.getDormTotalRooms()); bo.setB21(contractB.getDormSmallRooms()); bo.setB22(contractB.getDormLargeRooms()); bo.setB23(contractB.getDeliveryDate()); bo.setB24(contractB.getProductionProject()); bo.setB25(contractB.getLeaseTermYears()); bo.setB26(contractB.getLeaseStartDate()); bo.setB27(contractB.getLeaseEndDate()); bo.setB28(contractB.getRenewNoticeMonths()); bo.setB29(contractB.getFactorySpecificFloor1()); bo.setB30(contractB.getRentPerSqmFloor1()); bo.setB31(contractB.getFactorySpecificFloor2()); bo.setB32(contractB.getRentPerSqmFloor2()); bo.setB33(contractB.getFactoryAnnualRent()); bo.setB34(convertToUppercase(contractB.getFactoryAnnualRent())); bo.setB35(contractB.getSupportingRoomRentPerSqm()); bo.setB36(contractB.getSupportingRoomAnnualRent()); bo.setB37(convertToUppercase(contractB.getSupportingRoomAnnualRent())); bo.setB38(contractB.getDormSmallRoomRent()); bo.setB39(contractB.getDormLargeRoomRent()); bo.setB40(contractB.getDormAnnualRent()); bo.setB41(convertToUppercase(contractB.getDormAnnualRent())); bo.setB42(contractB.getTotalAnnualRent()); bo.setB43(convertToUppercase(contractB.getTotalAnnualRent())); bo.setB44(contractB.getPropertyFeePerSqm()); bo.setB45(contractB.getFactorySupportingPropertyFee()); bo.setB46(convertToUppercase(contractB.getFactorySupportingPropertyFee())); bo.setB47(contractB.getDormSmallRoomPropertyFee()); bo.setB48(contractB.getDormLargeRoomPropertyFee()); bo.setB49(contractB.getDormAnnualPropertyFee()); bo.setB50(convertToUppercase(contractB.getDormAnnualPropertyFee())); bo.setB51(contractB.getTotalAnnualPropertyFee()); bo.setB52(convertToUppercase(contractB.getTotalAnnualPropertyFee())); bo.setB53(contractB.getAnnualTotalRentAndPropertyFee()); bo.setB54(convertToUppercase(contractB.getAnnualTotalRentAndPropertyFee())); bo.setB55(contractB.getDepositAmount()); bo.setB56(convertToUppercase(contractB.getDepositAmount())); } private static void processContractA(ContractA baseContract, ASimplifiedHouseInfo aSimplifiedHouseInfo, AHouseInfoDetail houseDetailInfo, RentalTempBo bo) { ContractA contractA = baseContract; bo.setA1(contractA.getLandlordName()); bo.setA2(contractA.getTenantName()); bo.setA3(aSimplifiedHouseInfo.getAddress()); bo.setA4(contractA.getTenantTime()); bo.setA5(contractA.getTenantTimeStart()); bo.setA6(contractA.getTenantTimeEnd()); bo.setA7(contractA.getTenantRent()); bo.setA8(contractA.getTenantDeposit()); bo.setA9(contractA.getTenantDepositAmount()); } @Autowired private ARentalContractService aRentalContractService; private String fillContractData(RentalTempBo bo, String houseType) { var f = 0; switch (houseType) { case "公租房": { f = 1; break; } case "厂房": { f = 2; break; } case "创新创业基地": { f = 3; break; } } return aRentalContractService.generatorRental(String.valueOf(f), bo); } public static String convertToUppercase(String numberStr) { // 输入验证 if (numberStr == null || numberStr.trim().isEmpty()) { throw new IllegalArgumentException("输入不能为空"); } numberStr = numberStr.trim(); // 处理负号 boolean isNegative = false; if (numberStr.startsWith("-")) { isNegative = true; numberStr = numberStr.substring(1); } // 验证数字格式 if (!numberStr.matches("\\d+(\\.\\d{1,2})?")) { throw new IllegalArgumentException("输入格式错误,需为合法数字"); } // 转换为double类型(注意:使用BigDecimal可避免精度问题,但此处保持与原方法一致) double number = Double.parseDouble(numberStr); // 调用原有的转换方法 String result = convertToUppercase(number); // 添加负号前缀 return isNegative ? "负" + result : result; } public static String convertToUppercase(BigDecimal number) { if (number == null) { return "零元整"; } if (number.compareTo(BigDecimal.ZERO) < 0) { return "负" + convertToUppercase(number.abs()); } String[] units = {"", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆"}; String[] digits = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; // 分离整数部分和小数部分 BigDecimal roundedNumber = number.setScale(2, RoundingMode.HALF_UP); BigInteger integerPart = roundedNumber.toBigInteger(); int decimalPart = roundedNumber.remainder(BigDecimal.ONE).multiply(BigDecimal.valueOf(100)).intValue(); StringBuilder result = new StringBuilder(); String integerStr = integerPart.toString(); // 处理整数部分 boolean zeroFlag = false; for (int i = 0; i < integerStr.length(); i++) { int digit = integerStr.charAt(i) - '0'; int unitIndex = integerStr.length() - i - 1; if (digit == 0) { zeroFlag = true; // 处理单位:万、亿、兆 if (unitIndex % 4 == 0 && unitIndex > 0) { // 检查是否需要添加单位 boolean needUnit = false; for (int j = i + 1; j < Math.min(i + 5, integerStr.length()); j++) { if (integerStr.charAt(j) != '0') { needUnit = true; break; } } if (!needUnit) { result.append(units[unitIndex]); } } } else { if (zeroFlag) { result.append("零"); zeroFlag = false; } result.append(digits[digit]).append(units[unitIndex]); } } if (result.length() == 0) { result.append("零"); } result.append("元"); // 处理小数部分 int jiao = decimalPart / 10; int fen = decimalPart % 10; if (jiao == 0 && fen == 0) { result.append("整"); } else { if (jiao != 0) { result.append(digits[jiao]).append("角"); } if (fen != 0) { result.append(digits[fen]).append("分"); } } return result.toString(); } public static String convertToUppercase(double number) { return convertToUppercase(BigDecimal.valueOf(number)); } }