From caa0c01952a46d97b7ba7fc0d9d65e0a4b246d64 Mon Sep 17 00:00:00 2001 From: rosercode Date: Wed, 30 Sep 2026 16:14:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BA=AC=E4=B8=9C?= =?UTF-8?q?=E8=B4=A6=E5=8D=95=E5=B8=A6=E8=AF=B4=E6=98=8E=E7=9A=84=E9=87=91?= =?UTF-8?q?=E9=A2=9D=E8=A7=A3=E6=9E=90=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 京东交易流水中,全额退款的订单金额会被写成「230.88(已全额退款)」这类带中文说明的文本,原实现直接按数值解析会抛异常,导致这些行被判为不可导入而丢失。现改为从金额文本中提取数值部分,兼容括号说明、货币符号与千分位。 变更内容: - JdBillParser 金额解析改用正则从文本中提取数值(兼容「数字(说明)」、¥/¥ 符号与千分位逗号),替换原先按字符剔除符号的实现。 说明: - 仅影响京东账单解析,支付宝、微信等其它解析器未改动。 - 实测京东流水 103 行(含 5 行「已全额退款」)全部可正常解析并导入。 --- .../rosercode/ledgerly/importer/JdBillParser.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/cn/rosercode/ledgerly/importer/JdBillParser.java b/src/main/java/cn/rosercode/ledgerly/importer/JdBillParser.java index afd08b9..f65d306 100644 --- a/src/main/java/cn/rosercode/ledgerly/importer/JdBillParser.java +++ b/src/main/java/cn/rosercode/ledgerly/importer/JdBillParser.java @@ -14,6 +14,8 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -56,8 +58,8 @@ public class JdBillParser implements BillParser { /** CSV 解析格式:逗号分隔并去除字段首尾空白(含制表符) */ private static final CSVFormat CSV_FORMAT = CSVFormat.DEFAULT.builder().setTrim(true).build(); - /** 金额中需要剔除的货币符号与分隔符 */ - private static final String AMOUNT_STRIP_PATTERN = "[¥¥,\\s]"; + /** 金额中提取数值的正则:兼容「230.88(已全额退款)」等带说明、含货币符号与千分位的金额 */ + private static final Pattern AMOUNT_PATTERN = Pattern.compile("[-+]?\\d[\\d,]*(?:\\.\\d+)?"); /** JSON 序列化器,用于生成原始完整数据 */ private final ObjectMapper objectMapper; @@ -163,9 +165,11 @@ public class JdBillParser implements BillParser { String amountStr = get(header, values, COL_AMOUNT); if (StringUtils.hasText(amountStr)) { - try { - row.setAmount(new BigDecimal(amountStr.replaceAll(AMOUNT_STRIP_PATTERN, ""))); - } catch (NumberFormatException e) { + // 金额可能带「(已全额退款)」等说明,仅提取其中的数值部分 + Matcher matcher = AMOUNT_PATTERN.matcher(amountStr); + if (matcher.find()) { + row.setAmount(new BigDecimal(matcher.group().replace(",", ""))); + } else { row.setError("金额格式无法解析:" + amountStr); } }