sinake
5 天以前 83942be780d0560baa75c15e1124cc2bc997510b
ruoyi-common/src/main/java/com/ruoyi/common/utils/ChineseUtils.java
@@ -1,6 +1,47 @@
package com.ruoyi.common.utils;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class ChineseUtils {
    private static final String[] CN_NUM = {
            "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"
    };
    private static final String[] CN_UNIT = {
            "", "拾", "佰", "仟"
    };
    private static final String[] CN_BIG_UNIT = {
            "", "万", "亿", "兆"
    };
    private static final Map<Character, Integer> CN_NUM_MAP = new HashMap<>();
    private static final Map<Character, Integer> CN_UNIT_MAP = new HashMap<>();
    static {
        for (int i = 0; i < CN_NUM.length; i++) {
            CN_NUM_MAP.put(CN_NUM[i].charAt(0), i);
        }
        CN_NUM_MAP.put('零', 0);
        CN_NUM_MAP.put('一', 1);
        CN_NUM_MAP.put('二', 2);
        CN_NUM_MAP.put('三', 3);
        CN_NUM_MAP.put('四', 4);
        CN_NUM_MAP.put('五', 5);
        CN_NUM_MAP.put('六', 6);
        CN_NUM_MAP.put('七', 7);
        CN_NUM_MAP.put('八', 8);
        CN_NUM_MAP.put('九', 9);
        CN_NUM_MAP.put('两', 2);
        CN_UNIT_MAP.put('拾', 10);
        CN_UNIT_MAP.put('佰', 100);
        CN_UNIT_MAP.put('仟', 1000);
        CN_UNIT_MAP.put('十', 10);
        CN_UNIT_MAP.put('百', 100);
        CN_UNIT_MAP.put('千', 1000);
    }
    /**
     * 校验是否是中文
@@ -23,4 +64,251 @@
        return c >= 0x4E00 && c <= 0x9FA5;
    }
    /**
     * 数字金额转中文大写
     * 例如:1234.56 -> 壹仟贰佰叁拾肆元伍角陆分
     */
    public static String numberToChinese(BigDecimal amount) {
        if (amount == null) {
            throw new IllegalArgumentException("金额不能为空");
        }
        boolean negative = amount.signum() < 0;
        amount = amount.abs().setScale(2, BigDecimal.ROUND_HALF_UP);
        long integerPart = amount.longValue();
        int decimalPart = amount.subtract(new BigDecimal(integerPart))
                .multiply(new BigDecimal(100))
                .intValue();
        int jiao = decimalPart / 10;
        int fen = decimalPart % 10;
        StringBuilder sb = new StringBuilder();
        if (negative) {
            sb.append("负");
        }
        if (integerPart == 0) {
            sb.append("零元");
        } else {
            sb.append(integerToChinese(integerPart)).append("元");
        }
        if (jiao == 0 && fen == 0) {
            sb.append("整");
        } else {
            if (jiao > 0) {
                sb.append(CN_NUM[jiao]).append("角");
            } else if (fen > 0 && integerPart > 0) {
                sb.append("零");
            }
            if (fen > 0) {
                sb.append(CN_NUM[fen]).append("分");
            }
        }
        return sb.toString();
    }
    public static String numberToChinese(double amount) {
        return numberToChinese(BigDecimal.valueOf(amount));
    }
    public static String numberToChinese(String amount) {
        return numberToChinese(new BigDecimal(amount));
    }
    /**
     * 整数部分转中文大写
     */
    private static String integerToChinese(long num) {
        if (num == 0) {
            return "零";
        }
        StringBuilder sb = new StringBuilder();
        int unitIndex = 0;
        boolean needZero = false;
        while (num > 0) {
            int section = (int) (num % 10000);
            if (section != 0) {
                String sectionStr = sectionToChinese(section);
                if (needZero || (section < 1000 && sb.length() > 0)) {
                    sb.insert(0, "零");
                }
                sb.insert(0, sectionStr + CN_BIG_UNIT[unitIndex]);
                needZero = section < 1000;
            } else {
                if (sb.length() > 0 && !sb.toString().startsWith("零")) {
                    needZero = true;
                }
            }
            num /= 10000;
            unitIndex++;
        }
        String result = sb.toString();
        result = result.replaceAll("零+", "零");
        result = result.replaceAll("零$", "");
        result = result.replaceAll("零万", "万");
        result = result.replaceAll("零亿", "亿");
        return result;
    }
    /**
     * 四位以内数字转中文
     */
    private static String sectionToChinese(int section) {
        StringBuilder sb = new StringBuilder();
        int unit = 1000;
        boolean zeroFlag = false;
        while (section > 0) {
            int digit = section / unit;
            if (digit == 0) {
                if (sb.length() > 0 && !zeroFlag) {
                    zeroFlag = true;
                    sb.append("零");
                }
            } else {
                zeroFlag = false;
                sb.append(CN_NUM[digit]).append(CN_UNIT[getUnitIndex(unit)]);
            }
            section %= unit;
            unit /= 10;
        }
        String result = sb.toString();
        if (result.endsWith("零")) {
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }
    private static int getUnitIndex(int unit) {
        switch (unit) {
            case 1000: return 3;
            case 100: return 2;
            case 10: return 1;
            default: return 0;
        }
    }
    /**
     * 中文大写金额转数字
     * 例如:壹仟贰佰叁拾肆元伍角陆分 -> 1234.56
     */
    public static BigDecimal chineseToNumber(String chinese) {
        if (chinese == null || chinese.trim().isEmpty()) {
            throw new IllegalArgumentException("中文金额不能为空");
        }
        String str = chinese.trim()
                .replace("整", "")
                .replace("正", "")
                .replace("人民币", "");
        boolean negative = str.startsWith("负");
        if (negative) {
            str = str.substring(1);
        }
        // 分离元、角、分
        String integerPartStr;
        String decimalPartStr = "";
        int yuanIndex = str.indexOf("元");
        if (yuanIndex >= 0) {
            integerPartStr = str.substring(0, yuanIndex);
            String rest = str.substring(yuanIndex + 1);
            int jiaoIndex = rest.indexOf("角");
            int fenIndex = rest.indexOf("分");
            if (jiaoIndex >= 0) {
                decimalPartStr += chineseDigitToNumber(rest.substring(0, jiaoIndex)) + "";
            } else if (fenIndex > 0) {
                decimalPartStr += "0";
            }
            if (fenIndex >= 0) {
                String fenStr = rest.substring(jiaoIndex >= 0 ? jiaoIndex + 1 : 0, fenIndex);
                decimalPartStr += chineseDigitToNumber(fenStr) + "";
            } else {
                if (decimalPartStr.length() == 1) {
                    decimalPartStr += "0";
                }
            }
        } else {
            // 没有“元”,按纯数字中文处理
            integerPartStr = str;
        }
        long integerPart = chineseIntegerToNumber(integerPartStr);
        if (decimalPartStr.isEmpty()) {
            decimalPartStr = "00";
        } else if (decimalPartStr.length() == 1) {
            decimalPartStr += "0";
        }
        BigDecimal result = new BigDecimal(integerPart + "." + decimalPartStr);
        return negative ? result.negate() : result;
    }
    /**
     * 中文整数转 long
     */
    private static long chineseIntegerToNumber(String chinese) {
        if (chinese == null || chinese.isEmpty() || chinese.equals("零")) {
            return 0;
        }
        long result = 0;
        long section = 0;
        long number = 0;
        for (int i = 0; i < chinese.length(); i++) {
            char c = chinese.charAt(i);
            if (CN_NUM_MAP.containsKey(c)) {
                number = CN_NUM_MAP.get(c);
            } else if (CN_UNIT_MAP.containsKey(c)) {
                int unit = CN_UNIT_MAP.get(c);
                if (number == 0) {
                    number = 1;
                }
                section += number * unit;
                number = 0;
            } else if (c == '万') {
                section += number;
                result += section * 10000;
                section = 0;
                number = 0;
            } else if (c == '亿') {
                section += number;
                result += section * 100000000;
                section = 0;
                number = 0;
            } else if (c == '兆') {
                section += number;
                result += section * 1000000000000L;
                section = 0;
                number = 0;
            }
        }
        return result + section + number;
    }
    private static int chineseDigitToNumber(String chinese) {
        if (chinese == null || chinese.isEmpty()) {
            return 0;
        }
        char c = chinese.charAt(0);
        return CN_NUM_MAP.getOrDefault(c, 0);
    }
}