update: docs

This commit is contained in:
2026-03-13 14:48:32 +08:00
parent e0a40ceff0
commit b7e973e2b6
31 changed files with 2183 additions and 196 deletions

View File

@@ -8,6 +8,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings from app.core.config import settings
from app.core.database import get_db from app.core.database import get_db
from app.models.report import ExportReport from app.models.report import ExportReport
from app.models.report import ReportType
from app.repositories.case_repo import CaseRepository from app.repositories.case_repo import CaseRepository
from app.schemas.report import ReportCreate, ReportOut, ReportListOut from app.schemas.report import ReportCreate, ReportOut, ReportListOut
@@ -20,6 +21,8 @@ async def generate_report(case_id: UUID, body: ReportCreate, db: AsyncSession =
case = await repo.get(case_id) case = await repo.get(case_id)
if not case: if not case:
raise HTTPException(404, "案件不存在") raise HTTPException(404, "案件不存在")
if body.report_type == ReportType.word:
raise HTTPException(400, "当前仅支持 PDF 和 Excel 报告导出")
from app.services.report_service import generate_report as gen from app.services.report_service import generate_report as gen
report = await gen(case_id, body, db) report = await gen(case_id, body, db)
@@ -30,7 +33,7 @@ async def generate_report(case_id: UUID, body: ReportCreate, db: AsyncSession =
async def list_reports(case_id: UUID, db: AsyncSession = Depends(get_db)): async def list_reports(case_id: UUID, db: AsyncSession = Depends(get_db)):
result = await db.execute( result = await db.execute(
select(ExportReport) select(ExportReport)
.where(ExportReport.case_id == case_id) .where(ExportReport.case_id == case_id, ExportReport.report_type != ReportType.word)
.order_by(ExportReport.created_at.desc()) .order_by(ExportReport.created_at.desc())
) )
items = list(result.scalars().all()) items = list(result.scalars().all())

View File

@@ -13,7 +13,6 @@ class ReportCreate(CamelModel):
include_timeline: bool = True include_timeline: bool = True
include_reasons: bool = True include_reasons: bool = True
include_inquiry: bool = False include_inquiry: bool = False
include_screenshots: bool = False
class ReportOut(CamelModel): class ReportOut(CamelModel):

View File

@@ -1,16 +1,19 @@
"""Report generation: Excel / Word / PDF.""" """Report generation: Excel / PDF."""
import uuid import uuid
from pathlib import Path from pathlib import Path
from uuid import UUID from uuid import UUID
from datetime import datetime
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings from app.core.config import settings
from app.models.assessment import FraudAssessment, ReviewStatus from app.models.assessment import FraudAssessment, ReviewStatus
from app.models.case import Case
from app.models.transaction import TransactionRecord from app.models.transaction import TransactionRecord
from app.models.report import ExportReport, ReportType from app.models.report import ExportReport, ReportType
from app.schemas.report import ReportCreate from app.schemas.report import ReportCreate
from app.services.flow_service import build_flow_graph
async def generate_report(case_id: UUID, body: ReportCreate, db: AsyncSession) -> ExportReport: async def generate_report(case_id: UUID, body: ReportCreate, db: AsyncSession) -> ExportReport:
@@ -26,10 +29,10 @@ async def generate_report(case_id: UUID, body: ReportCreate, db: AsyncSession) -
if body.report_type == ReportType.excel: if body.report_type == ReportType.excel:
file_path = await _gen_excel(case_id, report_dir, body, db) file_path = await _gen_excel(case_id, report_dir, body, db)
elif body.report_type == ReportType.word: elif body.report_type == ReportType.pdf:
file_path = await _gen_word(case_id, report_dir, body, db)
else:
file_path = await _gen_pdf(case_id, report_dir, body, db) file_path = await _gen_pdf(case_id, report_dir, body, db)
else:
raise ValueError(f"Unsupported report_type: {body.report_type}")
relative = str(file_path.relative_to(settings.upload_path)) relative = str(file_path.relative_to(settings.upload_path))
@@ -86,6 +89,63 @@ async def _get_inquiry_suggestions(case_id: UUID, db: AsyncSession) -> list[str]
return await generate_inquiry_suggestions(case_id, db) return await generate_inquiry_suggestions(case_id, db)
def _fmt_dt(value: datetime | None, with_seconds: bool = False) -> str:
if not value:
return "-"
return value.strftime("%Y-%m-%d %H:%M:%S" if with_seconds else "%Y-%m-%d %H:%M")
def _mask_text(value: str, keep: int = 12) -> str:
text = (value or "").strip()
if len(text) <= keep:
return text
return f"{text[:keep]}..."
async def _build_report_dataset(case_id: UUID, db: AsyncSession) -> dict:
case_obj = await db.get(Case, case_id)
transactions = await _get_all_transactions(case_id, db)
transactions_sorted = sorted(transactions, key=lambda x: x.trade_time or datetime.min)
assessment_by_tx = await _get_all_assessments(case_id, db)
all_assessments = list(assessment_by_tx.values())
confirmed = [a for a in all_assessments if a.review_status == ReviewStatus.confirmed and float(a.assessed_amount) > 0]
pending = [a for a in all_assessments if a.review_status in {ReviewStatus.pending, ReviewStatus.needs_info}]
rejected = [a for a in all_assessments if a.review_status == ReviewStatus.rejected]
confirmed_total = sum(float(a.assessed_amount) for a in confirmed)
pending_total = sum(float(a.assessed_amount) for a in pending if float(a.assessed_amount) > 0)
rejected_total = sum(float(a.assessed_amount) for a in rejected if float(a.assessed_amount) > 0)
valid_for_timeline = [tx for tx in transactions_sorted if not tx.is_duplicate]
start_time = valid_for_timeline[0].trade_time if valid_for_timeline else None
end_time = valid_for_timeline[-1].trade_time if valid_for_timeline else None
level_count = {"high": 0, "medium": 0, "low": 0}
for a in all_assessments:
key = a.confidence_level.value
if key in level_count:
level_count[key] += 1
flow_graph = await build_flow_graph(case_id, db)
return {
"case": case_obj,
"transactions": transactions_sorted,
"assessment_by_tx": assessment_by_tx,
"confirmed": confirmed,
"pending": pending,
"rejected": rejected,
"confirmed_total": confirmed_total,
"pending_total": pending_total,
"rejected_total": rejected_total,
"level_count": level_count,
"start_time": start_time,
"end_time": end_time,
"flow_graph": flow_graph,
}
# ── Excel ── # ── Excel ──
async def _gen_excel(case_id: UUID, report_dir: Path, body: ReportCreate, db: AsyncSession) -> Path: async def _gen_excel(case_id: UUID, report_dir: Path, body: ReportCreate, db: AsyncSession) -> Path:
@@ -195,71 +255,6 @@ async def _gen_excel(case_id: UUID, report_dir: Path, body: ReportCreate, db: As
return file_path return file_path
# ── Word ──
async def _gen_word(case_id: UUID, report_dir: Path, body: ReportCreate, db: AsyncSession) -> Path:
from docx import Document
doc = Document()
doc.add_heading("受害人被骗金额汇总报告", level=1)
if body.include_summary:
confirmed = await _get_confirmed(case_id, db)
total = sum(float(a.assessed_amount) for a in confirmed)
doc.add_paragraph(f"已确认被骗金额: ¥{total:,.2f}")
doc.add_paragraph(f"已确认交易笔数: {len(confirmed)}")
table = doc.add_table(rows=1, cols=4)
table.style = "Table Grid"
hdr = table.rows[0].cells
hdr[0].text, hdr[1].text, hdr[2].text, hdr[3].text = "交易时间", "金额(元)", "对方", "认定理由"
for a in confirmed:
tx = await db.get(TransactionRecord, a.transaction_id)
row = table.add_row().cells
row[0].text = tx.trade_time.strftime("%Y-%m-%d %H:%M") if tx else ""
row[1].text = f"{float(a.assessed_amount):,.2f}"
row[2].text = tx.counterparty_name if tx else ""
row[3].text = a.reason[:80]
if body.include_transactions:
doc.add_heading("交易明细", level=2)
table2 = doc.add_table(rows=1, cols=6)
table2.style = "Table Grid"
for i, h in enumerate(["交易时间", "金额", "方向", "对方", "订单号", "备注"]):
table2.rows[0].cells[i].text = h
for tx in await _get_all_transactions(case_id, db):
row = table2.add_row().cells
row[0].text = tx.trade_time.strftime("%Y-%m-%d %H:%M")
row[1].text = f"{float(tx.amount):,.2f}"
row[2].text = tx.direction.value
row[3].text = tx.counterparty_name[:20]
row[4].text = tx.order_no[:20]
row[5].text = tx.remark[:30]
if body.include_reasons:
doc.add_heading("认定理由与排除说明", level=2)
assessment_by_tx = await _get_all_assessments(case_id, db)
for tx in await _get_all_transactions(case_id, db):
fa = assessment_by_tx.get(tx.id)
if not fa:
continue
doc.add_paragraph(
f"[{tx.trade_time.strftime('%Y-%m-%d %H:%M')}] ¥{float(tx.amount):,.2f} "
f"{fa.confidence_level.value}{fa.reason[:100]}"
)
if fa.exclude_reason:
doc.add_paragraph(f" 排除条件: {fa.exclude_reason[:100]}")
if body.include_inquiry:
doc.add_heading("笔录辅助问询建议", level=2)
suggestions = await _get_inquiry_suggestions(case_id, db)
for i, s in enumerate(suggestions, 1):
doc.add_paragraph(f"{i}. {s}")
file_path = report_dir / f"report_{uuid.uuid4().hex[:8]}.docx"
doc.save(file_path)
return file_path
# ── PDF ── # ── PDF ──
async def _gen_pdf(case_id: UUID, report_dir: Path, body: ReportCreate, db: AsyncSession) -> Path: async def _gen_pdf(case_id: UUID, report_dir: Path, body: ReportCreate, db: AsyncSession) -> Path:
@@ -301,8 +296,16 @@ async def _gen_pdf(case_id: UUID, report_dir: Path, body: ReportCreate, db: Asyn
leftMargin=15 * mm, rightMargin=15 * mm, leftMargin=15 * mm, rightMargin=15 * mm,
topMargin=20 * mm, bottomMargin=20 * mm) topMargin=20 * mm, bottomMargin=20 * mm)
elements = [] elements = []
elements.append(Paragraph("受害人被骗金额汇总报告", title_style)) dataset = await _build_report_dataset(case_id, db)
elements.append(Spacer(1, 10 * mm)) case_obj = dataset["case"]
transactions = dataset["transactions"]
tx_by_id = {tx.id: tx for tx in transactions}
assessment_by_tx = dataset["assessment_by_tx"]
confirmed = dataset["confirmed"]
pending = dataset["pending"]
rejected = dataset["rejected"]
flow_graph = dataset["flow_graph"]
level_count = dataset["level_count"]
def _make_table(header, rows, col_widths): def _make_table(header, rows, col_widths):
data = [header] + rows data = [header] + rows
@@ -319,65 +322,150 @@ async def _gen_pdf(case_id: UUID, report_dir: Path, body: ReportCreate, db: Asyn
])) ]))
return tbl return tbl
if body.include_summary: # Section 1: cover and case meta
confirmed = await _get_confirmed(case_id, db) elements.append(Paragraph("受害人被骗金额归集与认定报告", title_style))
total = sum(float(a.assessed_amount) for a in confirmed) elements.append(Spacer(1, 4 * mm))
elements.append(Paragraph(f"已确认被骗金额: ¥{total:,.2f}", normal_style)) elements.append(Paragraph(f"案件编号:{case_obj.case_no if case_obj else '-'}", normal_style))
elements.append(Paragraph(f"已确认交易笔数: {len(confirmed)}", normal_style)) elements.append(Paragraph(f"案件名称:{case_obj.title if case_obj else '-'}", normal_style))
elements.append(Spacer(1, 6 * mm)) elements.append(Paragraph(f"受害人:{case_obj.victim_name if case_obj else '-'} 承办人:{case_obj.handler if case_obj else '-'}", normal_style))
header = ["交易时间", "金额(元)", "对方", "认定理由"] elements.append(Paragraph(f"报告版本v{len((await db.execute(select(ExportReport).where(ExportReport.case_id == case_id, ExportReport.report_type == ReportType.pdf))).scalars().all()) + 1}", normal_style))
rows = [] elements.append(Paragraph(f"生成时间:{_fmt_dt(datetime.now(), with_seconds=True)}", normal_style))
for a in confirmed: elements.append(Spacer(1, 5 * mm))
tx = await db.get(TransactionRecord, a.transaction_id)
rows.append([
tx.trade_time.strftime("%Y-%m-%d %H:%M") if tx else "",
f"{float(a.assessed_amount):,.2f}",
(tx.counterparty_name if tx else "")[:20],
Paragraph(a.reason[:120], normal_style),
])
if rows:
elements.append(_make_table(header, rows, [38*mm, 25*mm, 35*mm, 72*mm]))
else:
elements.append(Paragraph("暂无已确认交易记录。", normal_style))
elements.append(Spacer(1, 8 * mm))
# Section 2: scope and statistical boundaries
elements.append(Paragraph("统计口径与数据范围", h2_style))
elements.append(Paragraph(
f"证据截图数:{case_obj.image_count if case_obj else 0} 张;交易记录数:{len(transactions)} 笔;统计时间范围:{_fmt_dt(dataset['start_time'])}{_fmt_dt(dataset['end_time'])}",
normal_style,
))
elements.append(Paragraph("纳入口径:复核状态为“已确认”且认定金额大于 0 的交易。", normal_style))
elements.append(Paragraph("排除口径:复核状态为“已排除”或规则判定为中转/收入等不应计损交易。", normal_style))
elements.append(Paragraph("待复核口径:状态为“待复核/需补充”的交易,暂不纳入最终被骗金额。", normal_style))
elements.append(Paragraph("说明PDF 报告不包含原始截图附件,仅在明细中保留证据索引字段。", normal_style))
elements.append(Spacer(1, 5 * mm))
# Section 3: executive summary
if body.include_summary:
elements.append(Paragraph("核心结论摘要", h2_style))
elements.append(Paragraph(f"已确认被骗金额:¥{dataset['confirmed_total']:,.2f}", normal_style))
elements.append(Paragraph(f"待复核金额:¥{dataset['pending_total']:,.2f}", normal_style))
elements.append(Paragraph(f"已排除金额:¥{dataset['rejected_total']:,.2f}", normal_style))
elements.append(
Paragraph(
f"已确认 {len(confirmed)} 笔,待复核 {len(pending)} 笔,已排除 {len(rejected)} 笔;置信分布:高 {level_count['high']} / 中 {level_count['medium']} / 低 {level_count['low']}",
normal_style,
)
)
summary_header = ["交易时间", "认定金额(元)", "对方", "认定理由"]
summary_rows = []
for a in confirmed[:30]:
tx = tx_by_id.get(a.transaction_id)
summary_rows.append([
_fmt_dt(tx.trade_time if tx else None),
f"{float(a.assessed_amount):,.2f}",
_mask_text(tx.counterparty_name if tx else "", 14),
Paragraph(_mask_text(a.reason, 80), normal_style),
])
if summary_rows:
elements.append(_make_table(summary_header, summary_rows, [36 * mm, 28 * mm, 34 * mm, 72 * mm]))
else:
elements.append(Paragraph("暂无已确认被骗交易。", normal_style))
elements.append(Spacer(1, 6 * mm))
# Section 4: flow summary (textual)
if body.include_flow_chart:
elements.append(Paragraph("资金路径分析", h2_style))
elements.append(
Paragraph(
f"节点数:{len(flow_graph.nodes)},路径边数:{len(flow_graph.edges)}。以下列出关键资金流向按金额降序最多10条",
normal_style,
)
)
node_label_map = {n.id: n.label for n in flow_graph.nodes}
sorted_edges = sorted(flow_graph.edges, key=lambda e: float(e.amount), reverse=True)[:10]
edge_rows = [
[
_mask_text(node_label_map.get(e.source, e.source), 12),
_mask_text(node_label_map.get(e.target, e.target), 12),
f"{float(e.amount):,.2f}",
str(e.count),
e.trade_time or "-",
]
for e in sorted_edges
]
if edge_rows:
elements.append(_make_table(["来源节点", "目标节点", "累计金额", "交易次数", "首笔时间"], edge_rows, [34 * mm, 34 * mm, 28 * mm, 20 * mm, 54 * mm]))
else:
elements.append(Paragraph("暂无可用的资金路径数据。", normal_style))
elements.append(Spacer(1, 6 * mm))
# Section 5: timeline
if body.include_timeline:
elements.append(Paragraph("交易时间轴", h2_style))
timeline_rows = []
for tx in [x for x in transactions if not x.is_duplicate][:80]:
fa = assessment_by_tx.get(tx.id)
status = fa.review_status.value if fa else "pending"
timeline_rows.append([
_fmt_dt(tx.trade_time),
f"{float(tx.amount):,.2f}",
"支出" if tx.direction.value == "out" else "收入",
_mask_text(tx.counterparty_name, 14),
tx.source_app.value,
status,
])
if timeline_rows:
elements.append(_make_table(["时间", "金额(元)", "方向", "对方", "来源APP", "状态"], timeline_rows, [34 * mm, 24 * mm, 15 * mm, 34 * mm, 22 * mm, 28 * mm]))
else:
elements.append(Paragraph("暂无可生成时间轴的交易记录。", normal_style))
elements.append(Spacer(1, 6 * mm))
# Section 6: detailed transaction table
if body.include_transactions: if body.include_transactions:
elements.append(Paragraph("交易明细", h2_style)) elements.append(Paragraph("重点交易明细(含证据索引)", h2_style))
elements.append(Spacer(1, 4 * mm)) elements.append(Spacer(1, 4 * mm))
header = ["交易时间", "金额", "方向", "对方", "订单号"] header = ["交易时间", "金额", "方向", "来源APP", "对方", "证据索引", "状态"]
rows = [] rows = []
for tx in await _get_all_transactions(case_id, db): for tx in transactions[:120]:
fa = assessment_by_tx.get(tx.id)
rows.append([ rows.append([
tx.trade_time.strftime("%Y-%m-%d %H:%M"), _fmt_dt(tx.trade_time),
f"{float(tx.amount):,.2f}", f"{float(tx.amount):,.2f}",
"" if tx.direction.value == "out" else "", "" if tx.direction.value == "out" else "",
tx.counterparty_name[:16], tx.source_app.value,
tx.order_no[:16], _mask_text(tx.counterparty_name, 12),
str(tx.evidence_image_id)[:12] if tx.evidence_image_id else "-",
fa.review_status.value if fa else "pending",
]) ])
if rows: if rows:
elements.append(_make_table(header, rows, [38*mm, 22*mm, 12*mm, 48*mm, 48*mm])) elements.append(_make_table(header, rows, [31 * mm, 19 * mm, 12 * mm, 20 * mm, 30 * mm, 35 * mm, 24 * mm]))
elements.append(Spacer(1, 8 * mm)) elements.append(Spacer(1, 8 * mm))
# Section 7: reasons and exclusion
if body.include_reasons: if body.include_reasons:
elements.append(Paragraph("认定理由与排除说明", h2_style)) elements.append(Paragraph("认定理由与排除说明", h2_style))
elements.append(Spacer(1, 4 * mm)) elements.append(Spacer(1, 4 * mm))
assessment_by_tx = await _get_all_assessments(case_id, db) for tx in transactions:
for tx in await _get_all_transactions(case_id, db):
fa = assessment_by_tx.get(tx.id) fa = assessment_by_tx.get(tx.id)
if not fa: if not fa:
continue continue
line = ( line = (
f"[{tx.trade_time.strftime('%m-%d %H:%M')}] ¥{float(tx.amount):,.2f} " f"[{_fmt_dt(tx.trade_time)}] ¥{float(tx.amount):,.2f} "
f"| {fa.confidence_level.value} | {fa.reason[:80]}" f"| 置信:{fa.confidence_level.value} | 状态:{fa.review_status.value} | 理由:{_mask_text(fa.reason, 80)}"
) )
elements.append(Paragraph(line, normal_style)) elements.append(Paragraph(line, normal_style))
if fa.exclude_reason: if fa.exclude_reason:
elements.append(Paragraph(f" 排除: {fa.exclude_reason[:80]}", normal_style)) elements.append(Paragraph(f" 排除说明: {_mask_text(fa.exclude_reason, 100)}", normal_style))
if fa.review_status in {ReviewStatus.pending, ReviewStatus.needs_info}:
elements.append(Paragraph(" 待补证提示: 建议补充问询与对账凭证后再作最终认定。", normal_style))
elements.append(Spacer(1, 8 * mm)) elements.append(Spacer(1, 8 * mm))
# Section 8: inquiry suggestions
if body.include_inquiry: if body.include_inquiry:
elements.append(Paragraph("笔录辅助问询建议", h2_style)) elements.append(Paragraph("待复核事项与笔录辅助问询建议", h2_style))
elements.append(Spacer(1, 4 * mm)) elements.append(Spacer(1, 4 * mm))
if pending:
elements.append(Paragraph(f"当前待复核交易共 {len(pending)} 笔,涉及待复核金额约 ¥{dataset['pending_total']:,.2f}", normal_style))
suggestions = await _get_inquiry_suggestions(case_id, db) suggestions = await _get_inquiry_suggestions(case_id, db)
for i, s in enumerate(suggestions, 1): for i, s in enumerate(suggestions, 1):
elements.append(Paragraph(f"{i}. {s}", normal_style)) elements.append(Paragraph(f"{i}. {s}", normal_style))

11
docs/project-book/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
# LaTeX 编译产物
build/
*.aux
*.log
*.toc
*.out
*.bbl
*.blg
*.synctex.gz
*.fls
*.fdb_latexmk

View File

@@ -0,0 +1,19 @@
# 智析反诈 项目书 - LaTeX 编译
# 使用: make 或 make pdf
MAIN = main
LATEX = xelatex
BUILD_DIR = build
.PHONY: pdf clean
pdf: $(MAIN).tex
@mkdir -p $(BUILD_DIR)
$(LATEX) -output-directory=$(BUILD_DIR) -interaction=nonstopmode $(MAIN).tex
$(LATEX) -output-directory=$(BUILD_DIR) -interaction=nonstopmode $(MAIN).tex
@cp $(BUILD_DIR)/$(MAIN).pdf . 2>/dev/null || true
@echo "PDF 已生成: $(BUILD_DIR)/$(MAIN).pdf"
clean:
rm -rf $(BUILD_DIR)
rm -f *.aux *.log *.toc *.out *.bbl *.blg *.synctex.gz

View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# 智析反诈 项目书 - 一键编译脚本
# 使用: bash build.sh
set -e
cd "$(dirname "$0")"
MAIN=main
BUILD_DIR=build
mkdir -p "$BUILD_DIR"
xelatex -output-directory="$BUILD_DIR" -interaction=nonstopmode "$MAIN.tex" || true
xelatex -output-directory="$BUILD_DIR" -interaction=nonstopmode "$MAIN.tex"
if [ -f "$BUILD_DIR/$MAIN.pdf" ]; then
cp "$BUILD_DIR/$MAIN.pdf" .
echo "PDF 已生成: $BUILD_DIR/$MAIN.pdf"
else
echo "编译可能有问题,请检查 $BUILD_DIR 目录下的 .log 文件"
exit 1
fi

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,30 @@
% ============================================================
% 第一章 引言
% 对应评审维度:需求与场景适配、应用价值
% ============================================================
\chapter{引言}
\section{目标用户与典型场景概述}
本项目面向基层派出所、反诈中心及刑侦部门的办案民警。在电信网络诈骗案件办理中,民警需要受理受害人报案、制作笔录、核查资金流向并认定被骗金额。受害人通常会提供大量来自微信、支付宝、银行卡、短信通知等不同来源的账单截图,民警需逐张查看、登记、汇总、排重、计算。这一环节是典型的高频、耗时、易错场景,也是本系统的核心目标用户与典型使用场景。第三章将详细展开目标用户画像与典型使用场景。
\section{项目背景}
电信网络诈骗案件持续高发基层民警在受害人报案受理、资金核查、笔录制作过程中面临大量来自不同APP的账单截图。现有工作模式主要依赖人工逐张查看、登记、汇总、排重、计算存在效率低、重复统计、认定不统一、证据整理负担重等问题。
为破解该痛点,本项目面向受害人资金核查实战,研发多智能体协同的截图证据解析与被骗金额认定系统,实现多源截图自动识别、跨平台关联、资金路径分析、认定复核和文书化输出,服务电诈案件快速、规范、可追溯办理。
\section{研究/建设目标}
本项目的建设目标凝练为三项:
\begin{enumerate}[label=(\arabic*)]
\item \textbf{自动化}:让截图证据从人工整理转向自动识别和结构化处理
\item \textbf{规范化}:让被骗金额认定从经验判断转向规则化、可解释化输出
\item \textbf{实战化}:让分析结果直接服务笔录制作、资金核查和案件材料生成
\end{enumerate}
\section{文档结构说明}
本项目的结构安排如下第二章介绍背景与现状第三章进行需求分析第四章描述系统架构设计第五章阐述关键实现第六章总结创新点与特色第七章讨论应用成效与评估第八章为总结与展望。附录提供API端点、数据库模型、图清单、初选录屏说明及答辩常见问题与建议回答。

View File

@@ -0,0 +1,52 @@
% ============================================================
% 第二章 背景与现状
% 对应评审维度:需求与场景适配、应用价值
% ============================================================
\chapter{背景与现状}
\section{电信诈骗受害人资金核查业务流程}
典型的电信诈骗案件资金核查流程可概括为:受案 $\to$ 笔录制作 $\to$ 核账 $\to$ 认定 $\to$ 报卷。受害人在报案时通常提供微信、支付宝、银行卡、短信通知等截图作为转账凭证。民警需要将这些零散证据整理为可追溯、可认定的资金流水,并回答执法层面的关键问题:哪些钱可以认定为被骗金额,理由是什么,证据在哪里。
\section{传统人工模式的瓶颈}
传统人工核账模式下,民警逐张查看截图、手动登记交易信息、人工判断重复与中转、计算被骗金额并撰写认定理由。该模式存在以下瓶颈:
\begin{itemize}[leftmargin=*]
\item 截图来源杂:微信、支付宝、银行卡、短信、数字钱包混杂
\item 截图数量大:一案几十张到上百张截图
\item 重复统计风险高:同一笔交易跨平台多次出现
\item 中转情形复杂:本人账户过渡、充值提现、退款混杂
\item 认定理由依赖经验:标准不统一
\item 结果需反复整理:表格、笔录、报告重复劳动重
\end{itemize}
% 图 2-1 占位
\placeholderfigure{Fig-traditional-flow.pdf}{传统人工核账流程图}
\section{痛点与影响对照}
\ref{tab:pain-points} 归纳了传统模式下的主要痛点及其影响。
\begin{table}[H]
\centering
\caption{痛点与影响对照表}
\label{tab:pain-points}
\begin{tabular}{lll}
\toprule
\textbf{痛点} & \textbf{具体表现} & \textbf{影响} \\
\midrule
截图来源杂 & 微信、支付宝、银行、短信等混杂 & 分类与整理耗时 \\
截图数量大 & 一案数十至上百张 & 人工逐张登记极耗时间 \\
重复统计 & 同笔交易跨平台多次出现 & 易重复累计被骗金额 \\
中转复杂 & 本人账户过渡、自充、退款 & 易错认、易漏排 \\
认定不统一 & 依赖个人经验 & 口径不一致、难以复核 \\
文书整理重 & 表格、笔录、报告反复整理 & 重复劳动多 \\
\bottomrule
\end{tabular}
\end{table}
\section{智慧警务与 AI 智能体发展趋势}
智慧警务建设强调技术赋能基层、减负增效。AI 智能体具备目标导向、环境感知、规划执行、工具调用和反馈闭环等特征,适合承担高重复、高耗时的信息抽取与初判任务,而将最终确认权、补证权、修正权保留给民警。本项目正是在此背景下,将多智能体协同技术应用于电诈受害人资金核查这一垂直警务场景。

View File

@@ -0,0 +1,100 @@
% ============================================================
% 第三章 需求分析
% 对应评审维度:需求与场景适配、技术可行性
% ============================================================
\chapter{需求分析}
\section{目标用户画像}
本系统的主要目标用户包括:
\begin{enumerate}[label=(\arabic*)]
\item \textbf{派出所一线民警}:受理电诈报案,制作笔录,完成资金核查初核
\item \textbf{反诈中心办案人员}:统筹多案资金分析,复核认定结论
\item \textbf{刑侦/经侦办案人员}:涉诈资金链梳理、多账户资金归集
\end{enumerate}
\section{典型使用场景}
\ref{tab:use-scenarios} 以「角色 + 任务 + 痛点 + 本系统介入方式」的形式描述典型使用场景。
\begin{table}[H]
\centering
\caption{典型使用场景}
\label{tab:use-scenarios}
\begin{tabular}{p{2cm}p{2.5cm}p{2.5cm}p{3cm}}
\toprule
\textbf{角色} & \textbf{任务} & \textbf{痛点} & \textbf{本系统介入} \\
\midrule
派出所民警 & 受理电诈报案后核账 & 截图多、重复统计、认定难 & 批量上传、自动去重、认定初判 \\
派出所民警 & 制作笔录前梳理资金 & 需人工整理表格、问询无依据 & 导出汇总表、生成问询建议 \\
反诈中心 & 复核多案认定结论 & 口径不统一、证据链难追溯 & 结构化字段、认定理由、证据索引 \\
刑侦/经侦 & 涉诈资金链分析 & 多账户、多平台流水混杂 & 跨平台关联、资金流图、路径分析 \\
\bottomrule
\end{tabular}
\end{table}
% 图 3-1 占位
\placeholderfigure{Fig-user-usecase.pdf}{用户角色与用例示意}
\section{业务需求}
系统需支持以下核心业务能力:
\begin{itemize}[leftmargin=*]
\item 案件管理:创建、查看、更新案件信息
\item 截图上传批量上传多APP账单截图
\item 截图解析自动识别APP类型、页面类型提取交易字段
\item 交易归并:去重、聚类、识别本人账户中转
\item 资金分析:资金流转关系图、交易时间轴、收款方聚合
\item 认定复核:高/中/低置信分层,人工复核确认,自动生成认定理由
\item 笔录辅助:基于分析结果生成笔录问询建议
\item 报告导出Excel 汇总表、PDF 报告、Word 文书,含证据索引和审计快照
\end{itemize}
\section{功能需求}
\ref{tab:func-req} 列出主要功能需求。
\begin{table}[H]
\centering
\caption{功能需求列表}
\label{tab:func-req}
\begin{tabular}{cll}
\toprule
\textbf{编号} & \textbf{功能} & \textbf{说明} \\
\midrule
F1 & 案件管理 & 创建、查看、更新案件 \\
F2 & 截图上传 & 批量上传,支持多格式 \\
F3 & 截图分类 & 识别来源APP、页面类型 \\
F4 & 交易抽取 & OCR 提取标准化交易字段 \\
F5 & 交易去重 & 订单号、金额+时间窗口去重 \\
F6 & 中转识别 & 识别本人账户中转 \\
F7 & 认定分层 & 高/中/低置信,纳入/排除/待复核 \\
F8 & 人工复核 & 确认、修正、留痕 \\
F9 & 问询建议 & 基于认定结果生成笔录建议 \\
F10 & 报告导出 & Excel、Word、PDF \\
\bottomrule
\end{tabular}
\end{table}
\section{非功能需求}
\begin{table}[H]
\centering
\caption{非功能需求}
\label{tab:nfr}
\begin{tabular}{lll}
\toprule
\textbf{类别} & \textbf{需求} & \textbf{说明} \\
\midrule
性能 & 批量处理 & 支持数十张截图并发解析 \\
性能 & 响应时间 & 单张解析在可接受延迟内完成 \\
安全 & 数据隔离 & 按案件隔离存储 \\
安全 & 审计留痕 & 分析、复核、修改记录可追溯 \\
合规 & 本地部署 & 支持专网/本地化部署 \\
合规 & 可解释性 & 认定理由、排除依据可追溯 \\
\bottomrule
\end{tabular}
\end{table}

View File

@@ -0,0 +1,93 @@
% ============================================================
% 第四章 系统架构设计
% 对应评审维度:技术可行性、技术深度、作品完整性
% ============================================================
\chapter{系统架构设计}
\section{总体架构}
系统采用四层架构:证据接入层、智能体协同层、案件推理层、结果输出层。
\begin{enumerate}[label=(\arabic*)]
\item \textbf{证据接入层}:微信、支付宝、银行、短信、数字钱包等截图批量上传
\item \textbf{智能体协同层}:编排智能体统一调度各专业智能体
\item \textbf{案件推理层}:去重、关联、中转识别、认定评分、人工复核
\item \textbf{结果输出层}:资金流图、交易明细、认定结论、问询建议、证据化报告
\end{enumerate}
% 图 4-1 占位
\placeholderfigure{Fig-architecture.pdf}{系统四层架构图}
\section{多智能体分工}
系统由以下八个专业智能体协同完成案件处理:
\begin{itemize}[leftmargin=*]
\item \textbf{案件编排智能体}:接收案件目标,规划处理步骤,调度各子智能体
\item \textbf{截图理解智能体}识别截图所属APP、页面类型、截图有效性
\item \textbf{交易抽取智能体}:将账单截图解析为标准化交易记录
\item \textbf{跨平台关联智能体}:识别同一交易在不同平台的重复呈现
\item \textbf{资金路径分析智能体}:识别本人账户中转、分流、汇聚
\item \textbf{被骗金额认定智能体}:纳入/排除/待复核判定,生成认定理由
\item \textbf{文书与笔录辅助智能体}:输出认定说明、问询建议、证据化报告
\item \textbf{人工复核协同智能体}:将低置信与争议记录提交民警确认
\end{itemize}
% 图 4-2 占位
\placeholderfigure{Fig-agent-collab.pdf}{多智能体协作示意图}
\section{核心业务流程}
核心业务流程为:上传 $\to$ 解析 $\to$ 分析 $\to$ 复核 $\to$ 报告。具体包括:新建案件、批量上传截图、自动识别来源与页面类型、自动抽取交易字段、自动去重与中转识别、生成资金路径与被骗金额初判、民警对低置信记录复核、一键导出汇总表与问询建议。
% 图 4-3 占位
\placeholderfigure{Fig-business-flow.pdf}{核心业务流程}
\section{技术选型}
\ref{tab:tech-stack} 列出技术栈。
\begin{table}[H]
\centering
\caption{技术栈一览}
\label{tab:tech-stack}
\begin{tabular}{ll}
\toprule
\textbf{层级} & \textbf{技术} \\
\midrule
前端 & React 18, TypeScript, Ant Design, ECharts, TanStack Query, Zustand \\
后端 & Python, FastAPI, SQLAlchemy 2.x (async), Pydantic v2 \\
数据库 & PostgreSQL 16 \\
队列 & Celery, Redis 7 \\
AI 能力 & 云 OCR / 多模态大模型 API可配置 \\
报告 & openpyxl, python-docx \\
\bottomrule
\end{tabular}
\end{table}
\section{设计目标与实现情况对照}
\ref{tab:design-vs-impl} 对照设计目标与当前实现情况,体现作品完整性。
\begin{table}[H]
\centering
\caption{设计目标 vs 实现情况}
\label{tab:design-vs-impl}
\begin{tabular}{lp{4cm}p{4cm}}
\toprule
\textbf{功能模块} & \textbf{设计目标} & \textbf{实现情况} \\
\midrule
案件管理 & 创建、查看、更新案件 & 已实现 \\
截图上传 & 批量上传多 APP 截图 & 已实现 \\
截图分类 & 识别 APP、页面类型 & 已实现OCR/多模态) \\
交易抽取 & 标准化字段提取 & 已实现 \\
交易去重 & 订单号、金额+时间窗口 & 已实现 \\
中转识别 & 本人账户中转排除 & 已实现 \\
认定分层 & 高/中/低置信 & 已实现 \\
人工复核 & 确认、修正、留痕 & 已实现 \\
问询建议 & 笔录辅助生成 & 已实现 \\
报告导出 & Excel、Word、PDF & 已实现 \\
\bottomrule
\end{tabular}
\end{table}

View File

@@ -0,0 +1,74 @@
% ============================================================
% 第五章 关键实现
% 对应评审维度:技术深度、技术可行性
% ============================================================
\chapter{关键实现}
\section{截图理解与交易抽取}
系统采用多模态大模型 API 完成截图分类与交易字段抽取。首先识别截图所属 APP微信、支付宝、银行、数字钱包等及页面类型账单列表、详情、转账回执等再根据页面类型调用相应抽取策略输出标准化交易记录。
抽取字段包括:交易时间、金额、收支方向、对手方名称/账号、本方账户尾号、订单号、备注、识别置信度。输出为结构化数据,支持可计算、可追溯、可比对、可复核。
% 图 5-1 占位
\placeholderfigure{Fig-extract-fields.pdf}{交易抽取字段与置信度示意}
\section{跨平台关联与去重}
去重逻辑基于规则引擎实现,主要包括:订单号一致则判定为重复;金额与时间窗口相近且对手方一致时可聚类。聚类后保留置信度最高的一条为主记录,其余标记为重复。本人账户中转识别通过比对对手方与本方已知账户实现,标记为「中转」的交易不纳入被骗金额累计。
% 图 5-2 占位
\placeholderfigure{Fig-dedup-transit.pdf}{去重与中转识别逻辑示意}
\section{被骗金额认定}
认定逻辑结合规则与 LLM 辅助:规则负责纳入/排除边界控制如本人账户中转排除、收入方向排除等LLM 负责生成更规范的认定理由与问询建议。每笔交易输出高/中/低置信分层,低置信记录进入人工复核流程。
\section{报告生成}
报告服务支持导出 Excel、Word、PDF 三种格式,内容可包含:被骗金额汇总、交易明细、认定理由与排除说明、笔录辅助问询建议。报告保留版本快照,支持证据索引与审计追踪。
\section{交易结构化字段定义}
\ref{tab:tx-fields} 定义交易结构化字段。
\begin{table}[H]
\centering
\caption{交易结构化字段定义}
\label{tab:tx-fields}
\begin{tabular}{llp{5cm}}
\toprule
\textbf{字段} & \textbf{类型} & \textbf{说明} \\
\midrule
trade\_time & datetime & 交易时间,格式 YYYY-MM-DD HH:MM:SS \\
amount & decimal & 金额(元) \\
direction & enum & in / out \\
counterparty\_name & string & 对手方名称 \\
counterparty\_account & string & 对手方账号 \\
self\_account\_tail\_no & string & 本方账户尾号 \\
order\_no & string & 订单号 \\
remark & string & 备注 \\
confidence & float & 识别置信度 0--1 \\
\bottomrule
\end{tabular}
\end{table}
\section{认定置信度分层}
\ref{tab:confidence} 说明认定置信度分层及对应处理策略。
\begin{table}[H]
\centering
\caption{认定置信度分层说明}
\label{tab:confidence}
\begin{tabular}{llp{4cm}}
\toprule
\textbf{等级} & \textbf{含义} & \textbf{处理策略} \\
\midrule
& 明确可纳入被骗金额 & 可直接确认 \\
& 需结合案情判断 & 建议人工复核 \\
& 建议排除或待核实 & 必须人工复核 \\
\bottomrule
\end{tabular}
\end{table}

View File

@@ -0,0 +1,66 @@
% ============================================================
% 第六章 创新点与特色
% 对应评审维度:创新点、创新程度
% ============================================================
\chapter{创新点与特色}
\section{传统模式 vs 本方案对照}
\ref{tab:traditional-vs-ours} 逐条对比传统模式与本方案,突出创新与突破。
\begin{table}[H]
\centering
\caption{传统模式 vs 本方案对照}
\label{tab:traditional-vs-ours}
\begin{tabular}{lp{4cm}p{4cm}}
\toprule
\textbf{维度} & \textbf{传统模式} & \textbf{本方案} \\
\midrule
截图处理 & 人工逐张查看、手写登记 & 多智能体自动分类、OCR 抽取 \\
重复识别 & 人工凭记忆比对 & 跨平台关联、订单号/金额+时间去重 \\
中转识别 & 依赖经验、易漏 & 规则引擎+已知账户比对 \\
认定逻辑 & 个人经验、口径不一 & 规则化+LLM 辅助,可解释 \\
输出形态 & 手工整理表格、笔录 & 一键导出 Excel/Word/PDF含证据索引 \\
复核机制 & 无系统化留痕 & 高/中/低置信分层,人工复核闭环 \\
工作流 & 民警全量核账 & AI 初判 + 民警重点复核 \\
\bottomrule
\end{tabular}
\end{table}
\section{多智能体协同创新}
将截图理解、交易抽取、关联分析、金额认定、文书生成拆分为专业智能体,由编排智能体协同调度,形成案件目标驱动的闭环处理流程。每个智能体只解决一类专业问题,输出可结构化传递,符合警务场景可管可控要求。
\section{跨平台资金证据关联创新}
面向微信、支付宝、银行卡、短信等多源截图,识别同笔交易的跨平台重复表达,实现资金证据自动关联和去重,直接解决「重复统计」这一实战高频痛点。
\section{被骗金额认定创新}
不止识别流水,而是围绕执法需要,结合规则和上下文对每笔交易进行纳入、排除、待复核判断,并生成认定理由与排除依据。
\section{证据化输出与人机协同}
将智能分析结果转化为可复核、可导出、可纳入案卷的报告和问询材料。同时强调人机协同AI 负责高强度初判,民警保留最终确认权,低置信结果主动提交人工复核。
\section{AI 智能体五特征与本项目对应}
\ref{tab:agent-features} 说明本项目如何符合 AI 智能体的五个核心特征。
\begin{table}[H]
\centering
\caption{AI 智能体五特征与本项目对应关系}
\label{tab:agent-features}
\begin{tabular}{ll}
\toprule
\textbf{智能体特征} & \textbf{本项目体现} \\
\midrule
目标导向 & 以「受害人被骗金额认定」为目标,非单纯识图 \\
环境感知 & 感知微信、支付宝、银行、短信等多源截图证据 \\
规划执行 & 依次完成分类、抽取、去重、关联、分析、认定、输出 \\
工具调用 & 调用 OCR、多模态模型、规则引擎、数据库、报表导出 \\
反馈闭环 & 低置信结果进入人工复核,保留修正记录 \\
\bottomrule
\end{tabular}
\end{table}

View File

@@ -0,0 +1,64 @@
% ============================================================
% 第七章 应用成效与评估
% 对应评审维度:应用价值、警务/教育适配性
% ============================================================
\chapter{应用成效与评估}
\section{应用场景与试点情况}
系统面向基层派出所、反诈中心及刑侦部门,适用于电信诈骗受害人资金核查、涉诈资金链梳理、涉赌资金流水分析、经侦案件多账户资金归集等场景。【占位:如有试点,请在此处补充试点单位、时间、案件数量等。】
\section{成效指标}
\ref{tab:metrics} 列出建议跟踪的成效指标,实测数据列供用户填写。
\begin{table}[H]
\centering
\caption{成效指标}
\label{tab:metrics}
\begin{tabular}{llll}
\toprule
\textbf{指标} & \textbf{说明} & \textbf{预期方向} & \textbf{实测数据} \\
\midrule
单案核查时间 & 从上传到出报告 & 压缩 & \placeholdercell \\
人工录入工作量 & 民警手工录入比例 & 下降 & \placeholdercell \\
重复交易识别 & 准确率/召回率 & 提升 & \placeholdercell \\
本人账户中转识别 & 准确率 & 提升 & \placeholdercell \\
认定一致性 & 多案/多人认定一致性 & 提升 & \placeholdercell \\
报告生成时间 & 从确认到导出 & 缩短 & \placeholdercell \\
\bottomrule
\end{tabular}
\end{table}
\textbf{指标参考口径}:传统人工核查需 2--4 小时的案件,系统可在数分钟内完成初步结构化和归并分析;多平台重复交易自动识别后,重复统计风险明显下降;民警由「全量逐条核对」转为「聚焦争议记录复核」,工作重心明显优化。
% 图 7-1, 7-2, 7-3 占位
\placeholderfigure{Fig-main-ui.png}{系统主界面截图}
\placeholderfigure{Fig-review-ui.png}{分析/复核界面截图}
\placeholderfigure{Fig-report-sample.png}{报告导出样例截图}
\section{应用价值与推广路径}
\textbf{应用价值}:对基层民警减负增效;对案件办理提升认定规范性、完整性和可解释性;对智慧警务构建可推广、可复制的反诈资金核查智能体范式。
\textbf{推广路径}:派出所试点 $\to$ 反诈中心推广 $\to$ 刑侦/经侦扩展。系统流程标准、通用性强,可根据不同单位部署条件选择本地化或专网化落地。
\section{警务/教育适配性}
\begin{itemize}[leftmargin=*]
\item \textbf{警校特色}:来源于基层民警真实办案需求,可结合反诈课程、实训教学使用
\item \textbf{落地价值}:支持本地化/专网部署,符合公安信息安全要求
\item \textbf{数据安全}:案件数据按案隔离,证据与报告全流程留痕
\item \textbf{可解释可信}:每笔认定可追溯至原始截图,人工拥有最终确认权
\end{itemize}
\section{安全合规与可信设计}
\begin{enumerate}[label=(\arabic*)]
\item \textbf{数据安全}:按案管理、隔离存储;支持本地/专网部署;模型接口可切换
\item \textbf{权限与审计}:区分上传、复核、导出权限;保留分析时间、复核人、修改记录;报告版本快照
\item \textbf{可信 AI}:低置信不直接下结论;人工最终确认;认定理由可解释;结果可追溯
\end{enumerate}

View File

@@ -0,0 +1,24 @@
% ============================================================
% 第八章 总结与展望
% ============================================================
\chapter{总结与展望}
\section{项目总结}
本项目聚焦电信网络诈骗案件受害人资金核查这一基层高频、耗时、易错场景,构建多智能体协同的截图证据解析与被骗金额认定系统。系统围绕案件目标,自动完成多 APP 账单截图识别、交易字段抽取、跨平台重复关联、本人账户中转识别、资金路径分析、被骗金额认定和证据化报告输出,并通过人工复核机制保障结果可信可控。
项目不是单点 OCR 工具,而是面向警务实战的垂直智能体系统,能够显著提升资金核查效率、规范认定标准、减轻基层负担,具备较强的实战价值、推广价值和示范意义。
\section{推广前景}
本项目面向基层高频警务场景,具有显著的通用性和可复制性。系统能力不仅适用于电信诈骗受害人资金核查,还可扩展应用于涉诈资金链梳理、涉赌资金流水分析、经侦案件多账户资金归集等场景,具备在派出所、反诈中心、刑侦部门等多层级单位推广应用的潜力。
\section{后续计划}
\begin{itemize}[leftmargin=*]
\item 持续优化 OCR 与抽取准确率
\item 扩展更多 APP 与页面类型的识别支持
\item 深化资金路径分析与可视化
\item 推进试点落地与效果数据采集
\end{itemize}

View File

@@ -0,0 +1,31 @@
% ============================================================
% 附录 AAPI 端点一览
% ============================================================
\chapter{API 端点一览}
\label{app:api}
\begin{table}[H]
\centering
\caption{系统主要 API 端点}
\begin{tabular}{lll}
\toprule
\textbf{端点} & \textbf{方法} & \textbf{功能} \\
\midrule
/api/v1/cases & GET, POST & 案件列表 / 创建 \\
/api/v1/cases/\{id\} & GET, PATCH & 案件详情 / 更新 \\
/api/v1/cases/\{id\}/images & GET, POST & 截图列表 / 上传 \\
/api/v1/images/\{id\} & GET & 截图详情 + OCR 结果 \\
/api/v1/cases/\{id\}/analyze & POST & 触发分析 \\
/api/v1/cases/\{id\}/transactions & GET & 交易列表 \\
/api/v1/cases/\{id\}/flows & GET & 资金流图 \\
/api/v1/cases/\{id\}/assessments & GET & 认定列表 \\
/api/v1/assessments/\{id\}/review & POST & 提交复核 \\
/api/v1/cases/\{id\}/inquiry-suggestions & GET & 问询建议 \\
/api/v1/cases/\{id\}/reports & GET, POST & 报告列表 / 生成 \\
/api/v1/reports/\{id\}/download & GET & 下载报告 \\
\bottomrule
\end{tabular}
\end{table}
API 文档可通过访问 \texttt{/docs} 获取交互式 Swagger 文档。

View File

@@ -0,0 +1,23 @@
% ============================================================
% 附录 B数据库/模型简要说明
% ============================================================
\chapter{数据库/模型简要说明}
\label{app:models}
\section{核心数据模型}
主要数据模型包括:
\begin{itemize}[leftmargin=*]
\item \textbf{Case}:案件,含案件编号、状态、创建时间等
\item \textbf{EvidenceImage}:证据截图,含来源 APP、页面类型、存储路径、OCR 状态
\item \textbf{TransactionRecord}:交易记录,含时间、金额、方向、对手方、订单号、是否重复、是否中转等
\item \textbf{TransactionCluster}:交易聚类,用于去重后的主记录关联
\item \textbf{FraudAssessment}:被骗金额认定,含置信等级、认定金额、理由、复核状态
\item \textbf{ExportReport}导出报告含类型Excel/Word/PDF、路径、版本、内容快照
\end{itemize}
\section{案件状态流转}
案件状态包括:\texttt{draft}(草稿)、\texttt{analyzing}(分析中)、\texttt{reviewing}(复核中)、\texttt{closed}(已关闭)。

View File

@@ -0,0 +1,36 @@
% ============================================================
% 附录 C图清单与占位说明
% 供用户按图补充,对应评审维度:技术可行性
% ============================================================
\chapter{图清单与占位说明}
\label{app:figures}
以下为正文中需要用户提供的图片清单。请根据 \texttt{figures/README.md} 中的说明准备相应图片,并替换占位框。
\begin{table}[H]
\centering
\caption{图清单与占位说明}
\begin{tabular}{clp{5cm}}
\toprule
\textbf{图号} & \textbf{建议文件名} & \textbf{建议内容} \\
\midrule
图 2-1 & Fig-traditional-flow.pdf & 传统人工核账流程图 \\
图 3-1 & Fig-user-usecase.pdf & 用户角色与用例示意 \\
图 4-1 & Fig-architecture.pdf & 系统四层架构图 \\
图 4-2 & Fig-agent-collab.pdf & 多智能体协作示意图 \\
图 4-3 & Fig-business-flow.pdf & 核心业务流程 \\
图 5-1 & Fig-extract-fields.pdf & 交易抽取字段与置信度示意 \\
图 5-2 & Fig-dedup-transit.pdf & 去重与中转识别逻辑示意 \\
图 7-1 & Fig-main-ui.png & 系统主界面截图 \\
图 7-2 & Fig-review-ui.png & 分析/复核界面截图 \\
图 7-3 & Fig-report-sample.png & 报告导出样例截图 \\
\bottomrule
\end{tabular}
\end{table}
将图片放入 \texttt{figures/} 目录后,可在对应章节中将 \texttt{\textbackslash placeholderfigure} 替换为:
\begin{lstlisting}
\includegraphics[width=0.9\textwidth]{文件名}
\end{lstlisting}

View File

@@ -0,0 +1,34 @@
% ============================================================
% 附录 D初选录屏说明
% 对应评审维度:技术可行性(录屏效果清晰)
% ============================================================
\chapter{初选录屏说明}
\label{app:video}
初选阶段需提交系统演示录屏。建议按以下规范准备,以体现架构合理、核心功能可实现、录屏效果清晰。
\section{建议时长}
总时长建议 3--5 分钟,覆盖「一案跑到底」的完整闭环。
\section{建议流程与关键时间点}
\begin{enumerate}[label=(\arabic*)]
\item 新建案件(约 0:00--0:30
\item 批量上传多 APP 截图(约 0:30--1:00
\item 系统自动识别截图来源和页面类型(约 1:00--1:30
\item 自动抽取交易字段(约 1:30--2:00
\item 自动去重与中转识别(约 2:00--2:30
\item 生成资金路径与被骗金额初判(约 2:30--3:00
\item 对低置信记录进行人工复核(约 3:00--3:30
\item 一键导出被骗金额汇总和问询建议(约 3:30--4:00
\end{enumerate}
\section{录屏质量要求}
\begin{itemize}[leftmargin=*]
\item 分辨率清晰,界面文字可辨认
\item 操作连贯,无长时间黑屏或卡顿
\item 关键步骤有适当停顿或标注,便于评审理解
\end{itemize}

View File

@@ -0,0 +1,31 @@
% ============================================================
% 附录 E答辩常见问题与建议回答
% 对应评审维度:现场表现
% ============================================================
\chapter{答辩常见问题与建议回答}
\label{app:qa}
\section{与普通 OCR 的区别}
\textbf{}:你这个项目和普通 OCR 报销系统有什么区别?
\textbf{}:普通 OCR 系统解决的是「识别内容」,本项目解决的是「围绕案件目标认定被骗金额」。系统不仅做截图识别,还做跨平台关联、本人账户中转识别、认定理由生成、人工复核和证据化输出,核心是执法业务闭环而不是识别本身。
\section{为何采用多智能体}
\textbf{}:为什么要做多智能体,不直接用一个大模型?
\textbf{}:因为本场景同时包含视觉识别、结构化抽取、交易关联、规则推理、文书生成等异构任务。采用多智能体分工后,每一步更稳定、可解释、可替换,也更符合警务场景可管可控要求。
\section{识别错误的处理}
\textbf{}:如果模型识别错了怎么办?
\textbf{}:系统会输出置信度,并把低置信和争议记录交由民警复核;同时保留原始截图、抽取字段、认定理由和修正记录,确保结论不是黑箱生成,而是可追溯、可校正的。
\section{推广条件}
\textbf{}:这个项目是否具备推广条件?
\textbf{}:该项目面向基层反诈案件高频场景,流程标准、通用性强,并已具备前后端原型、案件流程、异步分析、报告导出等基础能力,可根据不同单位部署条件选择本地化或专网化落地,具备较强推广价值。

View File

@@ -0,0 +1,43 @@
# 项目书图片占位说明
请将以下图片放入本目录,并在对应章节中替换占位框。图片需用户自行提供或制作。
## 图片清单与评审维度对应
| 文件名 | 对应图号 | 建议内容 | 对应评审维度 |
|--------|----------|----------|--------------|
| Fig-traditional-flow.pdf | 图 2-1 | 传统人工核账流程图 | 需求与场景适配 |
| Fig-user-usecase.pdf | 图 3-1 | 用户角色与用例示意 | 需求与场景适配 |
| Fig-architecture.pdf | 图 4-1 | 系统四层架构图 | 技术可行性、技术深度 |
| Fig-agent-collab.pdf | 图 4-2 | 多智能体协作示意图 | 技术可行性、创新点 |
| Fig-business-flow.pdf | 图 4-3 | 核心业务流程(上传→解析→分析→复核→报告) | 技术可行性 |
| Fig-extract-fields.pdf | 图 5-1 | 交易抽取字段与置信度示意 | 技术深度 |
| Fig-dedup-transit.pdf | 图 5-2 | 去重与中转识别逻辑示意 | 技术深度 |
| Fig-main-ui.png | 图 7-1 | 系统主界面截图 | 应用价值、作品完整性 |
| Fig-review-ui.png | 图 7-2 | 分析/复核界面截图 | 应用价值、作品完整性 |
| Fig-report-sample.png | 图 7-3 | 报告导出样例截图 | 应用价值、作品完整性 |
## 替换说明
将图片放入本目录后,在对应章节的 `.tex` 文件中,将:
```latex
\placeholderfigure{文件名}{图题}
```
替换为:
```latex
\begin{figure}[H]
\centering
\includegraphics[width=0.9\textwidth]{文件名}
\caption{图题}
\label{fig:xxx}
\end{figure}
```
注意:`\graphicspath` 已配置为 `figures/`,直接使用文件名即可(如 `Fig-main-ui`)。
## 可选占位图
可放置 `placeholder.pdf` 作为统一占位图,在尚未准备好正式图片时使用 `\includegraphics{figures/placeholder}` 引用。

View File

@@ -0,0 +1,78 @@
% ============================================================
% 智析反诈 - 电信网络诈骗案件受害人资金核查多智能体系统
% 全国「智慧+警务」AI智能体大赛 项目书
% ============================================================
\input{preamble}
\begin{document}
% ------------------------------------------------------------
% 封面
% ------------------------------------------------------------
\begin{titlepage}
\centering
\vspace*{2cm}
% 单位 logo 占位
% 【占位:请在此处插入单位 logo如 \includegraphics[height=2cm]{logo.png}】
\vspace{2cm}
{\LARGE\bfseries 智析反诈}\\[0.5cm]
{\Large 电信网络诈骗案件受害人资金核查多智能体系统}\\[1cm]
{\large 多APP账单截图自动解析、资金路径分析与被骗金额认定智能体}\\[2cm]
{\large 项目书}\\[2cm]
\begin{tabular}{ll}
申报单位: & 【占位:请填写】 \\
团队成员: & 【占位:请填写】 \\
完成日期: & \today \\
\end{tabular}
\vfill
{\small 全国「智慧+警务」AI智能体大赛}
\end{titlepage}
% ------------------------------------------------------------
% 摘要
% ------------------------------------------------------------
\chapter*{摘要}
\addcontentsline{toc}{chapter}{摘要}
随着电信网络诈骗案件持续高发,基层民警在受害人报案受理、资金核查、笔录制作过程中,需要面对大量来自微信、支付宝、银行卡、短信通知等不同来源的账单截图。现有工作模式主要依赖人工逐张查看、登记、汇总、排重、计算,存在效率低、重复统计、认定不统一、证据整理负担重等问题。
本项目面向受害人资金核查实战研发多智能体协同的截图证据解析与被骗金额认定系统。系统围绕案件目标自动完成多APP账单截图识别、交易字段抽取、跨平台重复关联、本人账户中转识别、资金路径分析、被骗金额认定和证据化报告输出并通过人工复核机制保障结果可信可控。项目不是单点OCR工具而是面向警务实战的垂直智能体系统能够显著提升资金核查效率、规范认定标准、减轻基层负担具备较强的实战价值、推广价值和示范意义。
\vspace{0.5cm}
\noindent\textbf{关键词:}多智能体协同;电信诈骗;资金核查;被骗金额认定;证据化输出;人机协同
% ------------------------------------------------------------
% 目录
% ------------------------------------------------------------
\tableofcontents
\clearpage
% ------------------------------------------------------------
% 正文章节
% ------------------------------------------------------------
\input{chapters/01-introduction}
\input{chapters/02-background}
\input{chapters/03-demand-analysis}
\input{chapters/04-architecture}
\input{chapters/05-implementation}
\input{chapters/06-innovation}
\input{chapters/07-evaluation}
\input{chapters/08-conclusion}
% ------------------------------------------------------------
% 附录
% ------------------------------------------------------------
\appendix
\input{chapters/appendix-a-api}
\input{chapters/appendix-b-models}
\input{chapters/appendix-c-figures}
\input{chapters/appendix-d-video}
\input{chapters/appendix-e-qa}
\end{document}

View File

@@ -0,0 +1,80 @@
% ============================================================
% 智析反诈 项目书 - LaTeX 导言区
% ============================================================
% 文档类
\documentclass[12pt,a4paper]{report}
% 中文支持ctex 自动检测系统字体)
\usepackage{ctex}
% 版式
\usepackage[top=2.5cm,bottom=2.5cm,left=2.5cm,right=2.5cm,headheight=14pt]{geometry}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[C]{\small 智析反诈:电信网络诈骗案件受害人资金核查多智能体系统}
\fancyfoot[C]{\thepage}
\renewcommand{\headrulewidth}{0.4pt}
% 图表
\usepackage{graphicx}
\usepackage{float}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{longtable}
\graphicspath{{./figures/}{../figures/}}
% 表格与列表
\usepackage{array}
\usepackage{multicol}
\usepackage{enumitem}
% 链接与交叉引用
\usepackage{hyperref}
\usepackage{color}
\hypersetup{
colorlinks=true,
linkcolor=blue,
citecolor=blue,
urlcolor=blue,
pdfstartview=FitH,
}
% 代码(可选)
\usepackage{listings}
\lstset{
basicstyle=\ttfamily\small,
breaklines=true,
frame=single,
numbers=left,
numberstyle=\tiny,
}
% 数学
\usepackage{amsmath}
\usepackage{amssymb}
% 流程图(可选)
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,arrows.meta,positioning,fit}
% 自定义命令:占位图
\newcommand{\placeholderfigure}[2]{
\begin{figure}[H]
\centering
\fbox{\parbox{0.85\textwidth}{
\centering\vspace{3cm}
【占位:请在此处插入 #2】
\par\vspace{0.5cm}
\small 建议文件名:#1
\vspace{3cm}
}}
\caption{#2}
\end{figure}
}
% 自定义命令:表格占位
\newcommand{\placeholdercell}{\multicolumn{1}{c}{(待补充)}}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,324 @@
# 全国“智慧+警务”AI智能体大赛10页PPT大纲与讲稿
## 使用说明
本文档面向比赛路演场景设计,默认控制在 **8-10 分钟** 左右。
每页内容分为三部分:
- **本页标题**:建议直接作为 PPT 页标题使用
- **页面展示要点**:建议放在 PPT 上的文字内容
- **讲稿**:建议现场讲解时口述的内容
整体讲述逻辑遵循:
**实战痛点 -> 方案提出 -> 智能体架构 -> 业务闭环 -> 创新亮点 -> 实战成效 -> 安全可信 -> 推广价值**
---
## 第1页 项目封面与核心定位
### 本页标题
**智析反诈:电信网络诈骗案件受害人资金核查多智能体系统**
副标题建议:
**多APP账单截图自动解析、资金路径分析与被骗金额认定智能体**
### 页面展示要点
- 面向电信网络诈骗案件受害人资金核查场景
- 聚焦多APP截图自动识别、跨平台关联、金额认定、证据化输出
- 项目定位:垂直警务智能体系统
- 核心价值:更快、更准、更规范、更可追溯
### 讲稿
各位评委好,我们带来的项目是“智析反诈:电信网络诈骗案件受害人资金核查多智能体系统”。
这个项目来源于基层派出所电诈案件办理中的真实痛点。受害人往往会提供大量微信、支付宝、银行卡、短信通知等截图,民警需要逐张查看、逐笔登记、反复核对、人工计算被骗金额,不仅耗时,而且容易出现重复统计、遗漏统计和认定口径不一致的问题。
我们要解决的,不是单纯的截图识别问题,而是围绕案件办理目标,构建一个能够自动完成截图证据解析、跨平台交易关联、资金路径分析、被骗金额认定和证据化输出的多智能体协同系统,把传统人工核账模式升级为可复核、可解释、可出证的智能办案模式。
---
## 第2页 基层实战痛点与传统模式瓶颈
### 本页标题
**基层反诈资金核查面临的真实难题**
### 页面展示要点
- 截图来源杂:微信、支付宝、银行、短信、数字钱包混杂
- 截图数量大:一案几十张到上百张截图
- 重复统计风险高:同一笔交易跨平台多次出现
- 中转情形复杂:本人账户过渡、充值提现、退款混杂
- 人工整理负担重:核账、笔录、表格、报告反复重复劳动
- 认定标准依赖经验:不同人、不同案件口径不一致
### 讲稿
基层民警在办理电诈案件时,一个非常高频但又非常繁琐的环节,就是受害人资金核查。
第一,截图来源非常杂。受害人提供的不只是一个平台,而是微信、支付宝、银行卡明细、短信通知,甚至还有数字钱包或者其他支付平台。
第二,截图数量很大。一些案件里,几十张截图是常态,复杂一点的案件上百张也很常见。
第三,重复统计风险非常高。同一笔交易,可能在转账详情页出现一次,在账单列表里出现一次,在银行短信里再出现一次。如果全靠人工核对,极易重复累计。
第四,本人账户中转、自充、退款、正常消费等情形夹杂其中,哪些该算被骗金额,哪些应该排除,既考验经验,也容易出错。
第五,核账完成以后,民警还要把结果继续整理到笔录、表格和报告中,重复劳动非常重。
所以,这个场景本质上是一个高频、刚需、耗时、易错的典型基层警务难题。
---
## 第3页 项目目标与总体解决思路
### 本页标题
**从“人工翻截图”到“智能体闭环核查”**
### 页面展示要点
- 目标不是识别截图,而是认定被骗金额
- 建立“截图证据解析 -> 交易结构化 -> 关联分析 -> 认定复核 -> 报告输出”闭环
- 以案件目标驱动,不以单点功能驱动
- 保留人工最终确认权,构建人机协同模式
### 讲稿
针对上述痛点,我们提出的总体思路是,把零散的截图处理动作,重构成一条围绕案件目标运行的智能工作流。
这条工作流的核心不是“看懂一张图”,而是回答一个执法层面的关键问题,也就是:哪些交易可以认定为被骗金额,证据在哪里,理由是什么。
因此,我们将整个流程设计为五个连续阶段。首先是截图证据解析,其次是交易结构化抽取,然后是跨平台关联和资金路径分析,再往后是被骗金额认定和人工复核,最后输出能够直接服务办案的汇总表、问询建议和证据化报告。
这意味着项目从一开始就不是一个单点工具而是一个面向案件办理闭环的警务智能体系统。同时我们强调人机协同而不是全自动替代AI负责高强度、高重复工作民警保留最终确认权。
---
## 第4页 多智能体协同架构
### 本页标题
**多智能体分工协作,围绕案件目标持续行动**
### 页面展示要点
- 案件编排智能体:统一规划与调度
- 截图理解智能体识别APP、页面类型、有效性
- 交易抽取智能体:提取标准化交易字段
- 跨平台关联智能体:识别重复交易与映射关系
- 资金路径分析智能体:识别本人账户中转和流转链路
- 被骗金额认定智能体:进行纳入、排除、待复核判断
- 文书生成智能体:输出问询建议和证据化报告
- 人工复核协同智能体:承接低置信和争议记录
### 讲稿
本项目的核心创新之一,就是采用多智能体协同,而不是让一个模型完成所有任务。
最上层是案件编排智能体,它围绕案件目标进行任务规划和流程调度。它知道当前案件进行到哪一步,也知道什么时候应该调用识别能力,什么时候应该进入关联分析,什么时候应该把结果交由人工复核。
在它下面是多个职责清晰的专业智能体。截图理解智能体负责判断这张图来自哪个APP、属于账单列表还是详情页交易抽取智能体负责把截图转换成标准化交易记录跨平台关联智能体负责识别同一笔交易在不同平台和不同截图中的重复呈现资金路径分析智能体负责识别本人账户中转和链路节点被骗金额认定智能体负责做纳入、排除和待复核判断最后由文书生成智能体输出可直接用于办案的结果。
当系统遇到低置信或争议情况时,人工复核协同智能体会把最值得关注的问题提交给民警确认,形成完整闭环。
---
## 第5页 核心业务流程演示
### 本页标题
**一个案件如何在系统中跑完整个闭环**
### 页面展示要点
建议这一页配流程图:
- 新建案件
- 批量上传多APP截图
- 自动识别截图来源和页面类型
- 自动抽取交易时间、金额、方向、对手方、订单号等字段
- 自动去重、聚类、识别本人账户中转
- 自动生成资金路径和被骗金额初判
- 民警对低置信记录进行复核
- 一键导出汇总表、问询建议、证据化报告
### 讲稿
这一页建议用一个案件跑通全流程,向评委展示系统的闭环能力。
首先民警新建案件并上传受害人提供的多APP截图。系统接收到截图后会自动判断截图来源和页面类型识别哪些是有效账单截图哪些可能是无效或重复截图。
接下来,系统会对有效截图进行结构化抽取,把交易时间、金额、收支方向、对手方名称、订单号、备注等字段统一标准化。标准化以后,系统开始做跨平台匹配和去重,避免同一笔交易重复累计,同时识别本人账户中转等不应直接计入被骗金额的情形。
然后,系统会输出被骗金额初判结果,并把结果按高、中、低置信度分层展示。民警只需要重点复核低置信和争议记录,而不必从头逐条核算。最后,系统可以一键导出被骗金额汇总表、笔录辅助问询建议以及 Word、Excel、PDF 报告,实现从截图到文书的完整办案闭环。
---
## 第6页 核心创新点
### 本页标题
**项目的四个核心创新**
### 页面展示要点
- 创新一:多智能体协同,不是单模型问答
- 创新二:跨平台重复交易自动关联与去重
- 创新三:围绕执法需求的被骗金额认定与理由生成
- 创新四:从截图识别直达证据化报告输出
### 讲稿
如果从比赛评审视角总结,这个项目至少有四个核心创新点。
第一,是多智能体协同创新。我们不是做一个提示词很长的大模型问答,而是把截图理解、交易抽取、关联分析、认定判断、文书生成拆成多个专业智能体,由编排智能体统一调度。这种方式更稳定、更可解释,也更符合警务场景可管可控的要求。
第二是跨平台资金证据关联创新。系统能够识别同一笔交易在不同APP、不同截图中的重复表达关系避免重复统计这是基层实战中极具价值的能力。
第三,是被骗金额认定创新。很多系统只能做到流水识别,但我们进一步把输出提升为执法层面的认定结论,包括纳入、排除、待复核三类结果,并给出每笔交易的认定理由和排除依据。
第四,是证据化输出创新。系统最终输出的不是一句结论,而是带有来源截图、结构化字段、认定说明和复核状态的可导出报告,能够直接服务笔录制作和案件材料整理。
---
## 第7页 为什么这是真正的AI智能体
### 本页标题
**本项目符合AI智能体的五个核心特征**
### 页面展示要点
- 目标导向:目标是被骗金额认定,不是单纯识图
- 环境感知理解多APP、多页面、多证据载体输入
- 规划执行:完成分类、抽取、去重、分析、认定、输出
- 工具调用调用OCR、规则引擎、数据库、报告引擎
- 反馈闭环:低置信结果进入人工复核与修正
### 讲稿
这一页是答辩时非常关键的一页,因为很多评委都会问一个问题:你这个项目为什么叫智能体,而不只是一个用了大模型的软件。
我们的回答很明确。第一它是目标导向的系统不是为识别而识别而是围绕“被骗金额认定”这一案件目标持续行动。第二它具备环境感知能力能够理解来自不同APP、不同页面类型、不同证据载体的输入信息。第三它会做规划和执行把复杂任务拆分成分类、抽取、关联、推理、输出等多个步骤。第四它会调用工具不只是生成文字而是要调用OCR、多模态模型、规则引擎、数据库和报表组件。第五它具备反馈闭环低置信结果不会直接当成结论而是进入人工复核。
因此,本项目本质上不是“让模型回答问题”,而是让智能体围绕案件目标持续调度能力、完成证据核查闭环。
---
## 第8页 实战应用成效与价值
### 本页标题
**对基层民警、案件办理、智慧警务的三重价值**
### 页面展示要点
- 对基层民警:减负增效,减少机械性核账劳动
- 对案件办理:提升认定规范性、完整性、可解释性
- 对智慧警务:形成可复制、可推广的警务智能体范式
- 典型成效表达:
- 核查时间显著压缩
- 重复统计风险明显下降
- 民警从全量核对转向重点复核
- 文书整理效率明显提升
### 讲稿
从应用价值看,这个项目至少有三层意义。
第一,对基层民警来说,它直接解决了高频、重复、机械的截图核账工作。过去大量时间耗在翻截图、记流水、对表格,现在可以把这些工作交给系统自动完成,民警只需要把精力放在重点复核和案件判断上。
第二,对案件办理来说,它提升的是认定规范性。系统会对每笔交易给出来源、字段、理由和状态,减少口径不统一、重复累计和遗漏统计的情况,使被骗金额认定更加完整、可解释、可追溯。
第三对智慧警务来说这不仅是一个场景应用更是一种警务智能体建设范式。它证明AI不只是辅助问答而是可以进入案件处理闭环承接真实业务目标形成可复制、可推广的实战能力。
如果现场允许,这一页也可以补充阶段性效果数据,例如核查耗时压缩比例、重复识别准确率、民警满意度等,让说服力更强。
---
## 第9页 安全可信与人机协同机制
### 本页标题
**坚持可解释、可复核、可追溯的警务AI原则**
### 页面展示要点
- 不追求黑箱全自动,强调人机协同
- 高/中/低置信分层,低置信结果主动提交人工复核
- 每笔认定可追溯至原始截图和结构化字段
- 保留认定理由、排除依据、复核记录、版本快照
- 支持按案管理、权限控制、本地化或专网部署
### 讲稿
在警务场景里,系统好不好,不只看智能不智能,更要看是否可信、是否可控、是否经得起复核。
所以我们从设计之初就没有追求黑箱式全自动,而是强调人机协同。系统会对结果进行置信度分层,把低置信和争议记录主动交给民警确认,确保不把不确定结论伪装成确定结论。
同时,系统对每一笔交易都保留原始截图来源、结构化抽取字段、认定理由、排除依据和人工修正记录,形成可回溯的证据链。对导出的报告,还可以保留版本快照,保证前后口径一致。
在部署层面,系统支持按案管理、权限控制,也支持本地化或专网化部署方向,符合警务数据安全和应用合规要求。
---
## 第10页 总结与推广前景
### 本页标题
**让AI真正进入警务业务闭环**
### 页面展示要点
- 项目来源于基层真实痛点,具有强实战价值
- 项目不是OCR工具而是多智能体警务系统
- 项目实现了从截图到认定再到文书的全流程闭环
- 可向反诈中心、刑侦、经侦等涉案资金场景推广
- 结束口号建议:
- 让截图证据自己开口,让被骗金额认定更快更准
### 讲稿
最后总结一下,这个项目最核心的价值,不是把截图识别出来,而是把基层民警在电诈案件中最繁琐、最易错、最依赖经验的资金核查工作,重构为一个由多智能体协同完成、由民警最终复核把关、并能够直接形成证据材料的智能办案系统。
它来源于基层真实需求解决的是一线高频刚需问题它不是单点OCR而是围绕案件目标运行的警务智能体它不是给出一个模糊答案而是形成可解释、可复核、可追溯、可导出的办案结果。
未来,这套能力不仅可以服务电信诈骗受害人资金核查,还可以向反诈中心、刑侦、经侦以及其他涉案资金分析场景推广应用,形成更大范围的智慧警务实战价值。
我们的目标是让AI不只停留在展示层而是真正进入警务业务闭环。谢谢各位评委。
---
## 附:路演表达技巧建议
### 1. 时间分配建议
- 第1页40秒
- 第2页60秒
- 第3页50秒
- 第4页70秒
- 第5页70秒
- 第6页70秒
- 第7页60秒
- 第8页60秒
- 第9页50秒
- 第10页40秒
总计约 9 分钟。
### 2. 讲解时要反复强调的三句话
- 我们解决的不是OCR识图问题而是被骗金额认定问题。
- 我们不是单模型问答,而是多智能体围绕案件目标协同工作。
- 我们输出的不是一个答案,而是一套可复核、可追溯、可形成文书的证据结果。
### 3. 如果评委只记住一句话,建议让他记住
**把“人工翻截图、人工算金额、人工写理由”的传统核账模式,升级为“多智能体自动核查、民警重点复核、系统一键出证”的新型警务工作流。**

View File

@@ -0,0 +1,675 @@
# 全国“智慧+警务”AI智能体大赛参赛方案
## 一、项目定位
### 1. 项目名称建议
**智析反诈:电信网络诈骗案件受害人资金核查多智能体系统**
可选副标题:
- 多APP账单截图自动解析与被骗金额认定智能体
- 面向反诈实战的截图证据解析、资金路径分析与证据化输出平台
- 受害人资金核查场景下的警务协同智能体系统
### 2. 一句话介绍
本项目面向电信网络诈骗案件受害人资金核查场景,构建“截图证据解析 + 多平台账单关联 + 资金路径分析 + 被骗金额认定 + 证据化输出”的多智能体协同系统,将基层民警高频、繁琐、易错的人工核账流程,升级为可追溯、可复核、可出具文书的智能办案流程。
### 3. 参赛核心定位
从比赛评审视角本项目不能只包装成“OCR识别工具”或“报表生成系统”而应明确定位为
**以案件目标为牵引、以证据链闭环为核心、以人机协同复核为保障的垂直警务智能体系统。**
这一定义非常关键因为评审专家对“AI智能体”的关注点不在于是否用了大模型而在于是否具备
- 明确目标驱动,而非单点识别
- 多步骤自主协同,而非单轮问答
- 可调用工具与规则,而非纯文本生成
- 面向真实业务闭环,而非概念演示
- 可审计、可解释、可复核,而非“黑箱结论”
## 二、从专家级评审视角看,本项目的真正亮点
### 1. 不是“识图”,而是“围绕案件目标的任务闭环”
传统OCR产品解决的是“看懂一张图”而基层反诈场景真正要解决的是
- 受害人提供了几十张甚至上百张不同APP截图
- 同一笔资金可能跨微信、支付宝、银行卡、短信通知等多个载体重复出现
- 其中夹杂本人账户中转、退款、充值、生活消费、无关流水
- 民警最终必须回答一个执法问题:**哪些钱可以认定为被骗金额,理由是什么,证据在哪里**
因此,项目的核心不是图像识别能力,而是**以“被骗金额认定”这一执法目标为中心的智能体任务闭环**。这天然符合高水平AI智能体项目的评审标准。
### 2. 不是“一个大模型”,而是“多智能体分工协作”
项目最有竞争力的点,是可以清晰拆解为多个具备独立职责的专业智能体,由编排智能体统一调度,形成符合办案逻辑的协同链路。
建议在参赛材料中明确采用如下表述:
- **案件编排智能体**:接收案件目标,规划处理步骤,调度各子智能体
- **截图理解智能体**识别截图所属APP、页面类型、截图有效性
- **交易抽取智能体**:将账单截图解析为标准化交易记录
- **跨平台关联智能体**:识别同一交易在不同平台的重复呈现与映射关系
- **资金路径分析智能体**:识别本人账户中转、分流、汇聚、链路节点
- **被骗金额认定智能体**:结合规则与证据,对交易进行纳入/排除/待复核判定
- **文书与笔录辅助智能体**:自动输出认定说明、问询建议、证据化报告
- **人工复核协同智能体**:在低置信和争议场景下把案件退回人工确认,形成闭环
这样一来,评审看到的就不是一个“功能堆叠的软件”,而是一个**具备角色分工、任务衔接、状态流转和结果复核机制的智能体系统**。
### 3. 不是“生成答案”,而是“形成证据”
警务场景和一般政务、企业办公场景最大的不同,在于结果要进入证据体系、笔录体系、案件卷宗体系。
所以本项目最大的专业亮点是:
- 输出不是一句“被骗金额大概多少”
- 而是每一笔金额的来源截图、结构化字段、关联关系、认定理由、排除依据、复核状态
- 最终还能导出 Excel、Word、PDF 等文书化结果
这代表项目具备**证据化输出能力**,而这正是智慧警务类评审会高度重视的差异化优势。
### 4. 不是“替代民警”,而是“人机协同增强”
在公安实战中,完全自动认定往往不可信,也不合规。
所以本项目要强调的不是“AI自动判案”而是
- AI负责高强度、高重复、高耗时的信息抽取与初判
- 民警保留最终确认权、补证权、修正权、解释权
- 系统通过高/中/低置信分层,把最该人工关注的部分突出出来
这会让项目在评审中更可信、更成熟,也更符合警务智能化建设导向。
## 三、AI智能体本质与本项目的高度契合点
参赛答辩时,建议直接回应“什么是智能体,为什么你的项目是真正的智能体”。
### 1. 智能体的本质
从专家视角AI智能体至少应具备以下五个特征
1. **目标导向**:围绕清晰任务目标持续行动
2. **环境感知**:能够理解输入环境中的多源信息
3. **规划执行**:将复杂任务拆解为多步骤流程
4. **工具调用**调用OCR、规则库、数据库、图谱、报告引擎等外部能力
5. **反馈闭环**:根据中间结果调整路径,并接受人工干预
### 2. 本项目如何符合智能体定义
本项目与上述五个特征一一对应:
| 智能体特征 | 本项目体现 |
|---|---|
| 目标导向 | 以“受害人被骗金额认定”而非单纯识别为目标 |
| 环境感知 | 感知微信、支付宝、银行、短信等多源截图证据 |
| 规划执行 | 依次完成分类、抽取、去重、关联、分析、认定、输出 |
| 工具调用 | 调用OCR、多模态模型、规则引擎、数据库、报表导出组件 |
| 反馈闭环 | 对低置信结果进入人工复核,并保留修正记录 |
建议在答辩中明确一句话:
**本项目不是“让大模型回答问题”,而是让智能体围绕案件目标,持续调用多种能力完成证据核查闭环。**
### 3. 为什么必须采用“多智能体”而不是“单模型”
因为该场景天然具备多任务异构特征:
- 截图识别是视觉理解问题
- 交易标准化是结构化抽取问题
- 跨平台合并是实体匹配问题
- 中转识别是规则推理问题
- 金额认定是业务决策问题
- 问询建议与文书生成是语言生成问题
这些能力混在一个模型里,容易出现:
- 提示词过长,效果不稳定
- 任务耦合,难以调试
- 错误来源不清晰
- 难以解释和复核
多智能体方案的价值就在于:
- 每个智能体只解决一类专业问题
- 输出可结构化传递
- 每一步可替换、可迭代、可追责
- 更符合警务系统建设中的可管可控要求
## 四、项目痛点与业务价值
### 1. 一线实战痛点
基层民警在制作电诈受害人笔录和资金核查时,普遍面临以下问题:
- 截图来源杂,微信、支付宝、银行卡、短信、数字钱包混杂
- 截图数量大,人工逐张登记极耗时间
- 同一笔交易跨平台重复展示,易重复统计
- 本人账户过渡、中转、充值提现等情形复杂,易错认
- 认定理由依赖经验,标准不统一
- 结果需反复整理为表格、笔录和报告,重复劳动重
### 2. 业务价值
建议用“提质、提效、减负、规范、留痕”五个词来概括:
- **提质**:减少重复统计、漏统、错统,提升被骗金额认定准确率
- **提效**:将人工逐张核账变为批量自动处理,显著压缩办案时间
- **减负**:减少基层民警在截图整理、表格汇总、笔录梳理上的机械劳动
- **规范**:统一认定逻辑、输出格式和复核路径
- **留痕**:保留截图来源、识别结果、认定依据、人工修正记录,满足审计追踪
### 3. 适用场景扩展
除典型电信诈骗案件外,还可扩展到:
- 帮信、洗钱案件中的资金流初筛
- 网络赌博、刷单返利等案件的流水梳理
- 经侦类案件中的多账户资金归集
- 检法环节中的证据辅助核查
## 五、参赛方案的推荐总体叙事
### 1. 推荐主叙事
建议全程围绕一句核心表达:
**把“人工翻截图、人工算金额、人工写理由”的传统核账模式,升级为“多智能体自动核查、民警重点复核、系统一键出证”的新型警务工作流。**
### 2. 推荐价值主张
建议在材料中固定使用以下三层价值表达:
- **对基层民警**:减负增效,把时间从机械整理中释放出来
- **对案件办理**:提升被骗金额认定的规范性、完整性和可解释性
- **对智慧警务**:构建可推广、可复制、可沉淀的反诈资金核查智能体范式
### 3. 推荐比赛标签
可用于申报书、路演PPT、海报、短视频字幕
- 多智能体协同
- 警务垂直智能体
- 证据智能解析
- 资金路径分析
- 被骗金额认定
- 人机协同复核
- 文书自动生成
- 可解释可信AI
## 六、系统架构包装建议
### 1. 总体架构
建议在图示中体现“四层结构”:
1. **证据接入层**
微信、支付宝、银行、短信、数字钱包等截图批量上传
2. **智能体协同层**
编排智能体统一调度各专业智能体
3. **案件推理层**
去重、关联、中转识别、认定评分、人工复核
4. **结果输出层**
资金流图、交易明细、认定结论、问询建议、证据化报告
### 2. 多智能体职责设计
#### 1案件编排智能体
职责:
- 接收案件处理请求
- 判断当前案件状态和处理阶段
- 规划执行顺序
- 监控任务完成情况
- 将异常或低置信结果提交人工复核
输入:
- 案件信息
- 受害人截图集合
- 基础案情说明
输出:
- 子任务清单
- 执行状态
- 汇总结果
#### 2截图理解智能体
职责:
- 判断截图来源APP
- 判断页面类型
- 识别无效截图、重复截图、非账单截图
价值:
- 解决“先分类再抽取”的前置问题
- 为后续使用不同抽取策略提供依据
#### 3交易抽取智能体
职责:
- 对账单截图进行OCR和结构化字段提取
- 标准化交易时间、金额、方向、对手方、订单号、备注等要素
- 给出抽取置信度
价值:
- 将非结构化截图证据变成可计算、可关联的数据对象
#### 4跨平台关联智能体
职责:
- 识别同一笔交易在不同截图、不同APP中的重复表达
- 建立交易聚类关系
- 避免同一笔被骗资金重复累计
价值:
- 直接解决“重复统计”这一实战高频痛点
#### 5资金路径分析智能体
职责:
- 识别本人账户中转、自转、自充等非最终被骗路径
- 判断是否存在汇聚账户、过桥账户、二跳转移
- 输出资金流路径和关系图
价值:
- 将“金额汇总”升级为“路径分析”
- 增强案件扩线和后续侦查价值
#### 6被骗金额认定智能体
职责:
- 结合规则、上下文和案件目标进行纳入/排除/待复核判断
- 生成每笔交易的认定理由和排除依据
- 输出高/中/低置信分层结果
价值:
- 这是最能体现警务专业性的核心智能体
- 直接对应执法环节中的关键结论输出
#### 7笔录与报告生成智能体
职责:
- 生成受害人问询建议
- 生成被骗金额汇总表
- 输出 Word / Excel / PDF 等证据化文书
价值:
- 让智能体结果直接进入基层实战使用链路
#### 8人工复核协同智能体
职责:
- 汇总低置信、矛盾、缺失字段记录
- 以“最少干预”方式请求民警确认
- 保存复核意见和修正轨迹
价值:
- 体现可信AI和警务合规理念
- 将“全自动”风险转化为“可控智能增强”
## 七、结合当前项目实现,可重点包装的技术亮点
结合当前系统已有能力,建议重点突出以下内容:
### 1. 已具备较完整的案件处理链路
当前项目已经形成较完整流程:
- 案件创建与管理
- 批量截图上传
- OCR识别与字段抽取
- 交易去重与聚类
- 本人账户中转识别
- 交易认定与理由生成
- 人工复核
- 报告导出
这说明项目不是停留在想法层面,而是已经具备原型系统基础。
### 2. 结构化输出而不是自由文本输出
系统将截图解析为标准交易字段,例如:
- 交易时间
- 金额
- 收支方向
- 对手方名称/账号
- 本方账户尾号
- 订单号
- 备注
- 识别置信度
这一点对评审非常重要,因为结构化输出意味着:
- 可计算
- 可追溯
- 可比对
- 可复核
- 可进入业务系统
### 3. 规则引擎与模型推理结合
项目不是完全依赖大模型,而是采用“模型理解 + 规则约束”的路线:
- 模型负责复杂截图理解和字段抽取
- 规则负责重复识别、中转识别、认定边界控制
- 大模型辅助生成更规范的认定理由和问询建议
这是一条非常适合警务场景的技术路线,因为它兼顾:
- 智能性
- 稳定性
- 解释性
- 可管控性
### 4. 支持证据化报告输出
系统可输出 Excel、Word、PDF 报告,这意味着:
- 结果可以直接服务笔录制作和案件材料整理
- 不再停留在“屏幕上看一看”的演示阶段
- 体现出“从识别到文书”的警务闭环
### 5. 支持人工复核闭环
高/中/低置信分层与人工确认机制,是项目成熟度的重要体现。
评审往往很关注“错了怎么办”,你可以明确回答:
- 系统不会把不确定结果伪装成确定结论
- 系统会把低置信结果主动交给民警确认
- 人工复核结果可以反向修正最终认定
这会明显提升项目可信度。
## 八、参赛材料中必须突出的“重点分析维度”
### 1. 业务刚需性
要让评审相信:这不是“为了比赛设计的需求”,而是基层民警天天遇到的刚需问题。
建议突出:
- 高发场景
- 高频动作
- 高耗时环节
- 高易错环节
### 2. 智能体真实性
很多参赛项目容易被质疑为“套壳大模型”。
你的项目要重点证明:
- 有任务目标,不是聊天问答
- 有任务分工,不是一个提示词包打天下
- 有状态流转,不是单次调用
- 有工具调用,不是只会生成文本
- 有人工闭环,不是输出即结束
### 3. 警务专业深度
评审会重点看项目是否真正理解公安业务。
建议重点突出以下专业点:
- 同笔交易跨平台重复识别
- 本人账户中转识别
- 认定理由生成
- 排除逻辑与复核逻辑
- 证据索引与卷宗化输出
### 4. 可解释与可信
在警务场景里,“为什么认定这笔是被骗金额”比“模型分数高不高”更重要。
因此必须强调:
- 每一笔认定均有来源截图
- 每一笔认定均有结构化字段
- 每一笔认定均有理由说明
- 每一笔排除均有依据
- 每一步都有人工复核入口
### 5. 工程落地能力
要让评审看到这是可以推广的系统而不是实验室Demo。
建议强调:
- 前后端完整系统
- 支持案件、截图、分析、复核、报告全流程
- 支持异步任务处理
- 支持模型接口替换
- 支持 mock 演示与真实模型配置切换
## 九、申报书建议写法
### 1. 项目背景
建议按以下逻辑写:
随着电信网络诈骗案件持续高发,基层民警在受害人报案受理、资金核查、笔录制作过程中,需要面对大量来自微信、支付宝、银行卡、短信通知等不同来源的账单截图。现有工作模式主要依赖人工逐张查看、登记、汇总、排重、计算,存在效率低、重复统计、认定不统一、证据整理负担重等问题。为破解该痛点,本项目面向受害人资金核查实战,研发多智能体协同的截图证据解析与被骗金额认定系统,实现多源截图自动识别、跨平台关联、资金路径分析、认定复核和文书化输出,服务电诈案件快速、规范、可追溯办理。
### 2. 建设目标
建议凝练成三项目标:
1. **自动化**:让截图证据从人工整理转向自动识别和结构化处理
2. **规范化**:让被骗金额认定从经验判断转向规则化、可解释化输出
3. **实战化**:让分析结果直接服务笔录制作、资金核查和案件材料生成
### 3. 创新点写法
建议至少写四个创新点:
1. **多智能体协同创新**
将截图理解、交易抽取、关联分析、金额认定、文书生成拆分为专业智能体,由编排智能体协同调度,形成案件目标驱动的闭环处理流程。
2. **跨平台资金证据关联创新**
面向微信、支付宝、银行卡、短信等多源截图,识别同笔交易的跨平台重复表达,实现资金证据自动关联和去重。
3. **被骗金额认定创新**
不止识别流水,而是围绕执法需要,结合规则和上下文对每笔交易进行纳入、排除、待复核判断,并生成认定理由。
4. **证据化输出创新**
将智能分析结果转化为可复核、可导出、可纳入案卷的报告和问询材料,构建从截图到文书的完整闭环。
### 4. 推广价值写法
建议写成:
本项目面向基层高频警务场景,具有显著的通用性和可复制性。系统能力不仅适用于电信诈骗受害人资金核查,还可扩展应用于涉诈资金链梳理、涉赌资金流水分析、经侦案件多账户资金归集等场景,具备在派出所、反诈中心、刑侦部门等多层级单位推广应用的潜力。
## 十、答辩和路演的最佳呈现方式
### 1. PPT建议结构
建议控制在 10 页左右:
1. 项目名称 + 一句话价值
2. 基层实战痛点
3. 现有模式的问题
4. 项目总体方案
5. 多智能体协同架构
6. 核心业务流程演示
7. 关键创新点
8. 应用成效与指标
9. 安全合规与可信机制
10. 推广前景与总结
### 2. 演示脚本建议
建议按照“一个案件跑到底”的方式演示:
1. 新建案件
2. 批量上传多APP截图
3. 系统自动识别截图来源和页面类型
4. 自动抽取交易字段
5. 自动完成去重与中转识别
6. 生成资金路径与被骗金额初判
7. 对低置信记录进行人工复核
8. 一键导出被骗金额汇总和问询建议
这样最能体现“智能体闭环”,而不是单点功能切换。
### 3. 现场讲解要点
建议重点讲三句话:
- **第一句**我们解决的不是OCR问题而是基层民警最耗时、最易错的被骗资金核查问题。
- **第二句**:我们不是单模型问答,而是多智能体围绕案件目标协同工作。
- **第三句**:我们输出的不是一个答案,而是一套可复核、可追溯、可形成文书的证据结果。
## 十一、建议准备的量化指标
如果要冲击高奖项,必须尽可能提供量化结果。即使是阶段性数据,也比纯定性描述更有说服力。
建议准备以下指标:
- 单案平均核查时间压缩比例
- 单案人工录入工作量下降比例
- 重复交易识别准确率
- 本人账户中转识别准确率
- 被骗金额认定一致性提升幅度
- 报告生成时间缩短比例
- 民警满意度或使用反馈
### 指标写法示例
可参考如下口径:
- 传统人工核查需 2 至 4 小时的案件,系统可在数分钟内完成初步结构化和归并分析
- 多平台重复交易自动识别后,重复统计风险明显下降
- 民警由“全量逐条核对”转为“聚焦争议记录复核”,工作重心明显优化
如果后续你有真实数据,建议替换为具体数字,如“平均耗时下降 70%”等。
## 十二、安全、合规与可信设计建议
警务类比赛中,这一部分非常重要,不能缺失。
### 1. 数据安全
建议强调:
- 案件数据按案管理,隔离存储
- 证据图片、识别结果、报告文件全流程留痕
- 支持本地化部署或专网部署
- 支持模型接口按需切换
### 2. 权限与审计
建议强调:
- 不同角色区分上传、复核、导出权限
- 保留分析时间、复核时间、复核人、修改记录
- 导出报告保留版本快照,防止后续口径不一致
### 3. 可信AI
建议强调:
- 对低置信结果不直接下结论
- 人工拥有最终确认权
- 所有关键认定均有可解释理由
- 结果可追溯至原始截图证据
## 十三、评审可能追问的问题与建议回答
### 1. 你这个项目和普通OCR报销系统有什么区别
建议回答:
普通OCR系统解决的是“识别内容”本项目解决的是“围绕案件目标认定被骗金额”。系统不仅做截图识别还做跨平台关联、本人账户中转识别、认定理由生成、人工复核和证据化输出核心是执法业务闭环而不是识别本身。
### 2. 为什么要做多智能体,不直接用一个大模型?
建议回答:
因为本场景同时包含视觉识别、结构化抽取、交易关联、规则推理、文书生成等异构任务。采用多智能体分工后,每一步更稳定、可解释、可替换,也更符合警务场景可管可控要求。
### 3. 如果模型识别错了怎么办?
建议回答:
系统会输出置信度,并把低置信和争议记录交由民警复核;同时保留原始截图、抽取字段、认定理由和修正记录,确保结论不是黑箱生成,而是可追溯、可校正的。
### 4. 这个项目是否具备推广条件?
建议回答:
该项目面向基层反诈案件高频场景,流程标准、通用性强,并已具备前后端原型、案件流程、异步分析、报告导出等基础能力,可根据不同单位部署条件选择本地化或专网化落地,具备较强推广价值。
## 十四、冲击高奖项的包装建议
如果目标不是“参赛即可”,而是争取更高奖项,建议在现有基础上强化以下表达:
### 1. 突出“实战首创性”
建议强调:
- 来源于基层民警真实办案需求
- 在真实案件工作流中设计和应用
- 不是从技术找场景,而是从痛点反推系统
### 2. 突出“执法专业性”
建议强调:
- 认定的是“被骗金额”,不是简单流水金额
- 输出包含纳入、排除、待复核三类结果
- 支持认定理由和排除理由说明
### 3. 突出“闭环可用性”
建议强调:
- 能上传
- 能识别
- 能分析
- 能复核
- 能出报告
比“模型准确率多高”更能打动警务评审。
### 4. 突出“可复制推广”
建议强调:
- 技术路线可复制
- 场景边界清晰
- 业务模板可复用
- 可扩展到其他涉案资金场景
## 十五、建议的最终参赛口号
可任选其一:
- **让截图证据自己开口,让被骗金额认定更快更准。**
- **从海量账单截图到一键证据报告,打造反诈资金核查智能体。**
- **把基层民警从“翻截图、算金额、写材料”中解放出来。**
- **以多智能体协同,重塑电诈案件资金核查新模式。**
## 十六、可直接用于申报书摘要的精炼版本
本项目聚焦电信网络诈骗案件受害人资金核查这一基层高频、耗时、易错场景构建多智能体协同的截图证据解析与被骗金额认定系统。系统围绕案件目标自动完成多APP账单截图识别、交易字段抽取、跨平台重复关联、本人账户中转识别、资金路径分析、被骗金额认定和证据化报告输出并通过人工复核机制保障结果可信可控。项目不是单点OCR工具而是面向警务实战的垂直智能体系统能够显著提升资金核查效率、规范认定标准、减轻基层负担具备较强的实战价值、推广价值和示范意义。
## 十七、结论:评审最容易被打动的核心表达
最终在所有材料和答辩中,建议把项目价值浓缩为下面这段话:
**这个项目最重要的不是把截图识别出来而是把基层民警在电诈案件中最繁琐、最易错、最依赖经验的被骗资金核查流程重构为一个由多智能体协同完成、由民警最终复核把关、并能直接形成证据材料的智能办案系统。它体现的不是“AI会看图”而是“AI真正进入警务业务闭环”。**

View File

@@ -14,6 +14,7 @@ import {
Divider, Divider,
Descriptions, Descriptions,
Checkbox, Checkbox,
Alert,
message, message,
Result, Result,
} from 'antd'; } from 'antd';
@@ -21,7 +22,6 @@ import {
FileTextOutlined, FileTextOutlined,
FileExcelOutlined, FileExcelOutlined,
FilePdfOutlined, FilePdfOutlined,
FileWordOutlined,
DownloadOutlined, DownloadOutlined,
PrinterOutlined, PrinterOutlined,
HistoryOutlined, HistoryOutlined,
@@ -36,8 +36,7 @@ type ContentKeys =
| 'include_flow_chart' | 'include_flow_chart'
| 'include_timeline' | 'include_timeline'
| 'include_reasons' | 'include_reasons'
| 'include_inquiry' | 'include_inquiry';
| 'include_screenshots';
const contentOptions: Array<{ key: ContentKeys; label: string; defaultOn: boolean }> = [ const contentOptions: Array<{ key: ContentKeys; label: string; defaultOn: boolean }> = [
{ key: 'include_summary', label: '被骗金额汇总表', defaultOn: true }, { key: 'include_summary', label: '被骗金额汇总表', defaultOn: true },
@@ -46,7 +45,6 @@ const contentOptions: Array<{ key: ContentKeys; label: string; defaultOn: boolea
{ key: 'include_timeline', label: '交易时间轴', defaultOn: true }, { key: 'include_timeline', label: '交易时间轴', defaultOn: true },
{ key: 'include_reasons', label: '认定理由与排除说明', defaultOn: true }, { key: 'include_reasons', label: '认定理由与排除说明', defaultOn: true },
{ key: 'include_inquiry', label: '笔录辅助问询建议', defaultOn: false }, { key: 'include_inquiry', label: '笔录辅助问询建议', defaultOn: false },
{ key: 'include_screenshots', label: '原始截图附件', defaultOn: false },
]; ];
const STORAGE_PREFIX = 'report-content-'; const STORAGE_PREFIX = 'report-content-';
@@ -80,7 +78,7 @@ const Reports: React.FC = () => {
const { id = '1' } = useParams(); const { id = '1' } = useParams();
const qc = useQueryClient(); const qc = useQueryClient();
const [generated, setGenerated] = useState(false); const [generated, setGenerated] = useState(false);
const [selectedFormats, setSelectedFormats] = useState<Array<'excel' | 'pdf' | 'word'>>([ const [selectedFormats, setSelectedFormats] = useState<Array<'excel' | 'pdf'>>([
'excel', 'excel',
'pdf', 'pdf',
]); ]);
@@ -114,7 +112,7 @@ const Reports: React.FC = () => {
); );
const genMutation = useMutation({ const genMutation = useMutation({
mutationFn: async (reportTypes: Array<'excel' | 'pdf' | 'word'>) => { mutationFn: async (reportTypes: Array<'excel' | 'pdf'>) => {
const result = await Promise.all( const result = await Promise.all(
reportTypes.map((reportType) => reportTypes.map((reportType) =>
generateReport(id, { report_type: reportType, ...contentSel }), generateReport(id, { report_type: reportType, ...contentSel }),
@@ -150,7 +148,6 @@ const Reports: React.FC = () => {
const map: Record<string, { icon: React.ReactNode; label: string; color: string }> = { const map: Record<string, { icon: React.ReactNode; label: string; color: string }> = {
pdf: { icon: <FilePdfOutlined />, label: 'PDF', color: 'red' }, pdf: { icon: <FilePdfOutlined />, label: 'PDF', color: 'red' },
excel: { icon: <FileExcelOutlined />, label: 'Excel', color: 'green' }, excel: { icon: <FileExcelOutlined />, label: 'Excel', color: 'green' },
word: { icon: <FileWordOutlined />, label: 'Word', color: 'blue' },
}; };
const cfg = map[t] || map.pdf; const cfg = map[t] || map.pdf;
return <Tag icon={cfg.icon} color={cfg.color}>{cfg.label}</Tag>; return <Tag icon={cfg.icon} color={cfg.color}>{cfg.label}</Tag>;
@@ -322,35 +319,17 @@ const Reports: React.FC = () => {
</Checkbox> </Checkbox>
</div> </div>
</Card> </Card>
<Card
hoverable
style={{ width: 140, textAlign: 'center' }}
styles={{ body: { padding: 16 } }}
>
<FileWordOutlined style={{ fontSize: 32, color: '#1677ff' }} />
<div style={{ marginTop: 8 }}>
<Typography.Text>Word </Typography.Text>
</div>
<div>
<Checkbox
checked={selectedFormats.includes('word')}
onChange={(e) => {
setSelectedFormats((prev) =>
e.target.checked
? Array.from(new Set([...prev, 'word']))
: prev.filter((x) => x !== 'word'),
);
}}
>
</Checkbox>
</div>
</Card>
</Space> </Space>
</div> </div>
<Typography.Text strong></Typography.Text> <Typography.Text strong></Typography.Text>
<div style={{ margin: '12px 0 24px' }}> <div style={{ margin: '12px 0 24px' }}>
<Alert
type="info"
showIcon
style={{ marginBottom: 12 }}
message="PDF 报告不包含原始截图附件,仅保留证据索引。"
/>
<Space direction="vertical"> <Space direction="vertical">
{contentOptions.map((opt) => ( {contentOptions.map((opt) => (
<Checkbox <Checkbox
@@ -406,15 +385,6 @@ const Reports: React.FC = () => {
> >
PDF PDF
</Button>, </Button>,
<Button
key="word"
icon={<DownloadOutlined />}
href={latestReportByType.word ? getReportDownloadUrl(latestReportByType.word.id) : undefined}
target="_blank"
disabled={!latestReportByType.word}
>
Word
</Button>,
<Button <Button
key="print" key="print"
icon={<PrinterOutlined />} icon={<PrinterOutlined />}

View File

@@ -440,7 +440,11 @@ const Review: React.FC = () => {
onClick={() => { onClick={() => {
setReviewModal(r); setReviewModal(r);
setEditableTx({ ...r.transaction }); setEditableTx({ ...r.transaction });
setReviewAction(getAiSuggestedAction(r, allAssessments)); setReviewAction(
r.reviewStatus === 'pending'
? getAiSuggestedAction(r, allAssessments)
: (r.reviewStatus as ReviewAction),
);
setReviewNote(''); setReviewNote('');
}} }}
> >
@@ -788,34 +792,32 @@ const Review: React.FC = () => {
</Card> </Card>
)} )}
{reviewModal.reviewStatus === 'pending' && ( <Divider />
<> <Space direction="vertical" style={{ width: '100%' }}>
<Divider /> <Typography.Text strong></Typography.Text>
<Space direction="vertical" style={{ width: '100%' }}> <Typography.Text type="secondary">
<Typography.Text strong></Typography.Text> {reviewModal.reviewStatus === 'pending'
<Typography.Text type="secondary"> ? `已默认选中 AI 建议:${aiSuggestionLabel[getAiSuggestedAction(reviewModal, allAssessments)]}`
AI {aiSuggestionLabel[getAiSuggestedAction(reviewModal, allAssessments)]} : '当前可修改复核状态并重新提交。'}
</Typography.Text> </Typography.Text>
<Select <Select
value={reviewAction} value={reviewAction}
onChange={setReviewAction} onChange={setReviewAction}
style={{ width: '100%' }} style={{ width: '100%' }}
options={[ options={[
{ label: '确认 - 该笔计入被骗金额', value: 'confirmed' }, { label: '确认 - 该笔计入被骗金额', value: 'confirmed' },
{ label: '排除 - 该笔不计入被骗金额', value: 'rejected' }, { label: '排除 - 该笔不计入被骗金额', value: 'rejected' },
{ label: '需补充 - 需进一步调查确认', value: 'needs_info' }, { label: '需补充 - 需进一步调查确认', value: 'needs_info' },
]} ]}
/> />
<Typography.Text strong></Typography.Text> <Typography.Text strong></Typography.Text>
<Input.TextArea <Input.TextArea
rows={3} rows={3}
value={reviewNote} value={reviewNote}
onChange={(e) => setReviewNote(e.target.value)} onChange={(e) => setReviewNote(e.target.value)}
placeholder="请输入复核意见或备注..." placeholder="请输入复核意见或备注..."
/> />
</Space> </Space>
</>
)}
{reviewModal.reviewStatus !== 'pending' && reviewModal.reviewedBy && ( {reviewModal.reviewStatus !== 'pending' && reviewModal.reviewedBy && (
<Descriptions column={2} size="small" style={{ marginTop: 16 }}> <Descriptions column={2} size="small" style={{ marginTop: 16 }}>
@@ -839,24 +841,22 @@ const Review: React.FC = () => {
> >
</Button> </Button>
{reviewModal.reviewStatus === 'pending' && ( <Button
<Button type="primary"
type="primary" loading={reviewMutation.isPending}
loading={reviewMutation.isPending} onClick={() => {
onClick={() => { reviewMutation.mutate({
reviewMutation.mutate({ assessmentId: reviewModal.id,
assessmentId: reviewModal.id, body: {
body: { review_status: reviewAction,
review_status: reviewAction, review_note: reviewNote,
review_note: reviewNote, reviewed_by: 'demo_user',
reviewed_by: 'demo_user', },
}, });
}); }}
}} >
>
</Button>
</Button>
)}
</div> </div>
</> </>
)} )}

View File

@@ -509,6 +509,23 @@ const Transactions: React.FC = () => {
)} )}
</Space> </Space>
</Descriptions.Item> </Descriptions.Item>
<Descriptions.Item label="标记修改">
<Select
style={{ width: '100%' }}
value={getEffectiveMark(detail)}
options={[
{ label: '重复', value: 'duplicate' },
{ label: '中转', value: 'transit' },
{ label: '有效', value: 'valid' },
]}
onChange={(val) =>
setMarkOverrides((prev) => ({
...prev,
[detail.id]: val as 'duplicate' | 'transit' | 'valid',
}))
}
/>
</Descriptions.Item>
</Descriptions> </Descriptions>
</Col> </Col>
</Row> </Row>

View File

@@ -250,7 +250,6 @@ export async function generateReport(
include_timeline?: boolean; include_timeline?: boolean;
include_reasons?: boolean; include_reasons?: boolean;
include_inquiry?: boolean; include_inquiry?: boolean;
include_screenshots?: boolean;
}, },
): Promise<ExportReport> { ): Promise<ExportReport> {
if (!(await isBackendUp())) return mockReports[0]; if (!(await isBackendUp())) return mockReports[0];

View File

@@ -93,7 +93,7 @@ export interface FundFlowEdge {
export interface ExportReport { export interface ExportReport {
id: string; id: string;
caseId: string; caseId: string;
reportType: 'pdf' | 'excel' | 'word'; reportType: 'pdf' | 'excel';
filePath: string; filePath: string;
createdAt: string; createdAt: string;
version: number; version: number;