sinake
9 天以前 61cfdecaf6b76acb27478e5901eb0908244e3875
发票识别
已修改4个文件
已添加1个文件
746 ■■■■■ 文件已修改
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HttpUtils.java 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-druid.yml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application.yml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/ChineseUtils.java 288 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -1,26 +1,31 @@
package com.ruoyi.web.controller.common;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ChineseUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.web.controller.tool.HttpUtils;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.AbstractProtocol;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.management.*;
@@ -28,7 +33,11 @@
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.Set;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
/**
 * é€šç”¨è¯·æ±‚处理
@@ -42,6 +51,8 @@
    @Autowired
    private ServerConfig serverConfig;
    @Value("${appcode}")
    private String  appcode;
    /**
     * é€šç”¨ä¸‹è½½è¯·æ±‚
@@ -120,6 +131,120 @@
        }
    }
    public String aliOCR(String base64) {
        String host = "https://mixedmulti.market.alicloudapi.com";
        String path = "/ocrservice/mixedMultiInvoice";
        String method = "POST";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求,定义相对应的Content-Type
        headers.put("Content-Type", "application/json; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        String bodys = "{\"img\":\""+base64+"\"}";
        try {
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            System.out.println(response.toString());
            //获取response的body
            String content=EntityUtils.toString(response.getEntity());
            JSONObject jsonContent=JSONObject.parseObject(content);
            JSONArray subMsgs=jsonContent.getJSONArray("subMsgs");
            List<Map<String,Object>> lists=new ArrayList<>();
            for(Object row: subMsgs){
                Map<String,Object> tempList=new HashMap<>();
                JSONObject rowObject=(JSONObject)row;
                tempList.put("发票分类",rowObject.getString("type"));
                JSONObject result=((JSONObject)rowObject.get("result")).getJSONObject("data");
                for(Map.Entry<String, Object> entry : result.entrySet()){
                    tempList.put(entry.getKey(),entry.getValue());
                }
                if(rowObject.getString("type").equals("银行承兑汇票")){
                    BigDecimal totalAmount= ChineseUtils.chineseToNumber(result.getString("票据金额大写"));
                    tempList.put("发票金额",totalAmount);
                }
                if(rowObject.getString("type").equals("火车票")){
                    tempList.put("发票金额",result.getString("票价"));
                }
                lists.add(tempList);
            }
            System.out.println(content);
            return JSON.toJSONString(lists);
        } catch (Exception e) {
            e.printStackTrace();
            return "{}";
        }
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚
     */
    @ApiOperation("testOCR")
    @PostMapping("/common/testOCR")
    public AjaxResult testOCR(@RequestBody String fileName) throws Exception {
        Path filePath= Paths.get(fileName);
        String base64= Base64.getEncoder().encodeToString( Files.readAllBytes(filePath));
        AjaxResult ajax = AjaxResult.success();
        ajax.put("OCRList", aliOCR(base64));
        return ajax;
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚
     */
    @PostMapping("/common/uploadOCR")
    public AjaxResult uploadOCR(MultipartFile file) throws Exception {
        try {
            // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
            String filePath = RuoYiConfig.getUploadPath();
            //判断文件是否存在
            String filename = file.getOriginalFilename().trim();
            String felinamePath = FileUploadUtils.extractFilename(file);
//            String pathFileName = FileUploadUtils.getPathFileName(filePath, s);
            for (int i=1;i<500;i++) {
                File file1 = new File(filePath + "/" + felinamePath);
                boolean exists = file1.exists();
                if (exists) {
                    int index = filename.lastIndexOf(".");
                    String startStr = filename.substring(0, index);
                    String endStr = filename.substring(index, filename.length());
                    String newFilename = startStr + "-" + i + endStr; // your new filename
                    felinamePath = DateUtils.datePath() + "/" + newFilename;
                    String contentType = file.getContentType();
                    byte[] bytes = file.getBytes();
                    file = new MockMultipartFile(newFilename, newFilename, contentType, bytes);
                }else{
                    break;
                }
            }
            // ä¸Šä¼ å¹¶è¿”回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url1 = serverConfig.getUrl();
            log.info("url1的值old :{}", url1);
            if (url1.contains("8032")) {
                //这里的8032不是tomcat的,所以要转成tomcat的
                url1 = url1.replace("8032", "8032/prod-api");
            }
            String base64= Base64.getEncoder().encodeToString(file.getBytes());
            log.info("url1的值new :{}", url1);
            String url = url1 + fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", fileName);
            ajax.put("url", url);
            ajax.put("OCRList", aliOCR(base64));
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }
//    private static void parseUTF(int[] bits) {
//        int index = 0;//这个指针指向每一行循环时列下标的位置,下一行开始时重新置位0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HttpUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,312 @@
package com.ruoyi.web.controller.tool;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
public class HttpUtils {
    /**
     * get
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doGet(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        return httpClient.execute(request);
    }
    /**
     * post form
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param bodys
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      Map<String, String> bodys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }
        return httpClient.execute(request);
    }
    /**
     * Post String
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }
        return httpClient.execute(request);
    }
    /**
     * Post stream
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPost(String host, String path, String method,
                                      Map<String, String> headers,
                                      Map<String, String> querys,
                                      byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }
        return httpClient.execute(request);
    }
    /**
     * Put String
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     String body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }
        return httpClient.execute(request);
    }
    /**
     * Put stream
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPut(String host, String path, String method,
                                     Map<String, String> headers,
                                     Map<String, String> querys,
                                     byte[] body)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (body != null) {
            request.setEntity(new ByteArrayEntity(body));
        }
        return httpClient.execute(request);
    }
    /**
     * Delete
     *
     * @param host
     * @param path
     * @param method
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doDelete(String host, String path, String method,
                                        Map<String, String> headers,
                                        Map<String, String> querys)
            throws Exception {
        HttpClient httpClient = wrapClient(host);
        HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        return httpClient.execute(request);
    }
    private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }
        return sbUrl.toString();
    }
    private static HttpClient wrapClient(String host) {
        HttpClient httpClient = new DefaultHttpClient();
        if (host.startsWith("https://")) {
            sslClient(httpClient);
        }
        return httpClient;
    }
    private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                }
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }
}
ruoyi-admin/src/main/resources/application-druid.yml
@@ -7,12 +7,12 @@
      # ä¸»åº“数据源
      master:
        # å¼€å‘环境
        url: jdbc:mysql://127.0.0.1:3306/opo?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: sendohill
#        url: jdbc:mysql://haiershi.a1.luyouxia.net:23844/opo?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
#        username: smartor
#        password: Smartor.2023
#        url: jdbc:mysql://127.0.0.1:3306/opo?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
#        username: root
#        password: sendohill
        url: jdbc:mysql://haiershi.a1.luyouxia.net:23844/opo?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
        username: smartor
        password: Smartor.2023
      # ä»Žåº“数据源
      slave:
ruoyi-admin/src/main/resources/application.yml
@@ -132,6 +132,7 @@
#与协友交互的新功能开关 1开   2关
newSwitch: 1
appcode: 07b7e4f573a54d97865abdeb3fc3408e
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);
    }
}