feat: 支持京东白条账单上传和清洗

This commit is contained in:
CHE LIANG ZHAO
2026-01-26 13:44:22 +08:00
parent 7b2d6a9fbb
commit 3cf39b4664
17 changed files with 383 additions and 27 deletions

View File

@@ -22,7 +22,7 @@ if sys.stdout.encoding != 'utf-8':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
from cleaners.base import compute_date_range_from_values
from cleaners import AlipayCleaner, WechatCleaner
from cleaners import AlipayCleaner, WechatCleaner, JDCleaner
from category import infer_category, get_all_categories, get_all_income_categories
from converter import convert_bill_file
@@ -43,7 +43,7 @@ class CleanRequest(BaseModel):
start: Optional[str] = None
end: Optional[str] = None
format: Optional[str] = "csv"
bill_type: Optional[str] = "auto" # auto, alipay, wechat
bill_type: Optional[str] = "auto" # auto, alipay, wechat, jd
class CleanResponse(BaseModel):
@@ -90,7 +90,7 @@ def detect_bill_type(filepath: str) -> str | None:
检测账单类型
Returns:
'alipay' | 'wechat' | None
'alipay' | 'wechat' | 'jd' | None
"""
try:
with open(filepath, "r", encoding="utf-8") as f:
@@ -107,6 +107,14 @@ def detect_bill_type(filepath: str) -> str | None:
if "交易类型" in line and "金额(元)" in line:
return "wechat"
# 京东特征:表头包含 "商户名称" 和 "交易说明"
if "商户名称" in line and "交易说明" in line:
return "jd"
# 京东特征:头部信息包含 "京东账号名"
if "京东账号名" in line:
return "jd"
# 数据行特征
if line.startswith("202"):
if "" in line:
@@ -155,14 +163,16 @@ def do_clean(
try:
if bill_type == "alipay":
cleaner = AlipayCleaner(input_path, output_path, output_format)
elif bill_type == "jd":
cleaner = JDCleaner(input_path, output_path, output_format)
else:
cleaner = WechatCleaner(input_path, output_path, output_format)
cleaner.set_date_range(start_date, end_date)
cleaner.clean()
type_names = {"alipay": "支付宝", "wechat": "微信"}
return True, bill_type, f"{type_names[bill_type]}账单清洗完成"
type_names = {"alipay": "支付宝", "wechat": "微信", "jd": "京东白条"}
return True, bill_type, f"{type_names.get(bill_type, bill_type)}账单清洗完成"
except Exception as e:
return False, bill_type, f"清洗失败: {str(e)}"
@@ -324,7 +334,7 @@ async def detect_bill_type_api(file: UploadFile = File(...)):
"""
检测账单类型
上传文件后自动检测是支付宝还是微信账单
上传文件后自动检测是支付宝、微信还是京东账单
"""
suffix = Path(file.filename).suffix or ".csv"
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
@@ -336,10 +346,10 @@ async def detect_bill_type_api(file: UploadFile = File(...)):
if bill_type is None:
raise HTTPException(status_code=400, detail="无法识别账单类型")
type_names = {"alipay": "支付宝", "wechat": "微信"}
type_names = {"alipay": "支付宝", "wechat": "微信", "jd": "京东白条"}
return {
"bill_type": bill_type,
"display_name": type_names[bill_type]
"display_name": type_names.get(bill_type, bill_type)
}
finally:
if os.path.exists(tmp_path):