From 61cfdecaf6b76acb27478e5901eb0908244e3875 Mon Sep 17 00:00:00 2001
From: sinake <sinake1@qq.com>
Date: 星期四, 15 十月 2026 16:36:54 +0800
Subject: [PATCH] 发票识别
---
ruoyi-common/src/main/java/com/ruoyi/common/utils/ChineseUtils.java | 288 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 288 insertions(+), 0 deletions(-)
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ChineseUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ChineseUtils.java
index cd1b79e..f43a4da 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ChineseUtils.java
+++ b/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;
+ }
+ }
+
+ /**
+ * 涓枃澶у啓閲戦杞暟瀛�
+ * 渚嬪锛氬9浠熻窗浣板弫鎷捐倖鍏冧紞瑙掗檰鍒� -> 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);
+ }
}
--
Gitblit v1.9.3