Commit c8ead117 c8ead11724e1dcb9ff13128f1f23342792405a17 by 沈秋雨

feat(import): 支持同曲不同词样本的新歌入库逻辑

1 parent 527d6149
...@@ -1565,7 +1565,7 @@ ...@@ -1565,7 +1565,7 @@
1565 els.importReviewedBtn.textContent = '入库中...'; 1565 els.importReviewedBtn.textContent = '入库中...';
1566 try { 1566 try {
1567 const payload = await reviewPostJSON('/api/import-reviewed'); 1567 const payload = await reviewPostJSON('/api/import-reviewed');
1568 alert(`提交完成:不重复入库 ${payload.inserted_count} 条,重复样本 ${payload.duplicate_count || 0} 条,其中作者有增量 ${payload.author_merged_count || 0} 条。结果文件:${payload.review_csv}`); 1568 alert(`提交完成:不重复入库 ${payload.inserted_count} (含同曲不同词 ${payload.diff_lyric_count || 0} 条),重复样本 ${payload.duplicate_count || 0} 条,其中作者有增量 ${payload.author_merged_count || 0} 条。结果文件:${payload.review_csv}`);
1569 // 刷新统计和加载列表并行 1569 // 刷新统计和加载列表并行
1570 await Promise.all([reloadSummary(), loadGroups()]); 1570 await Promise.all([reloadSummary(), loadGroups()]);
1571 renderAll(); 1571 renderAll();
......
...@@ -806,7 +806,7 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o ...@@ -806,7 +806,7 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o
806 cursor.execute( 806 cursor.execute(
807 f""" 807 f"""
808 SELECT s.staging_id, s.id AS incoming_id, s.source_song_id, s.source_table_name, s.name, 808 SELECT s.staging_id, s.id AS incoming_id, s.source_song_id, s.source_table_name, s.name,
809 s.lyricist, s.composer, s.biz_review_status, s.matched_song_id 809 s.lyricist, s.composer, s.biz_review_status, s.matched_song_id, s.merge_diff_type
810 FROM {TARGET_TABLE_NAME_TMP} s 810 FROM {TARGET_TABLE_NAME_TMP} s
811 INNER JOIN ( 811 INNER JOIN (
812 SELECT source_song_id, MAX(staging_id) AS max_staging_id 812 SELECT source_song_id, MAX(staging_id) AS max_staging_id
...@@ -828,9 +828,17 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o ...@@ -828,9 +828,17 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o
828 conn.rollback() 828 conn.rollback()
829 raise ValueError("没有可提交的已审核样本") 829 raise ValueError("没有可提交的已审核样本")
830 approved_rows = [row for row in reviewed_rows if row["biz_review_status"] == "approved_import"] 830 approved_rows = [row for row in reviewed_rows if row["biz_review_status"] == "approved_import"]
831 duplicate_rows = [row for row in reviewed_rows if row["biz_review_status"] == "rejected_duplicate"] 831 # 同曲不同词:歌词不同,需作为新歌入库
832 staging_ids = [row["staging_id"] for row in approved_rows] 832 diff_lyric_rows = [row for row in reviewed_rows
833 approved_source_ids = [str(row["source_song_id"]) for row in approved_rows] 833 if row["biz_review_status"] == "rejected_duplicate"
834 and row.get("merge_diff_type") == "diff_lyric_same_melody"]
835 # 纯重复 / 同词不同曲:不入库,仅合并作者
836 duplicate_rows = [row for row in reviewed_rows
837 if row["biz_review_status"] == "rejected_duplicate"
838 and row.get("merge_diff_type") != "diff_lyric_same_melody"]
839 import_rows = approved_rows + diff_lyric_rows
840 staging_ids = [row["staging_id"] for row in import_rows]
841 all_import_source_ids = [str(row["source_song_id"]) for row in import_rows]
834 duplicate_targets: dict[object, int] = {} 842 duplicate_targets: dict[object, int] = {}
835 unresolved_duplicates = [] 843 unresolved_duplicates = []
836 for row in duplicate_rows: 844 for row in duplicate_rows:
...@@ -858,7 +866,7 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o ...@@ -858,7 +866,7 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o
858 866
859 inserted_count = 0 867 inserted_count = 0
860 id_map: dict[str, object] = {} 868 id_map: dict[str, object] = {}
861 if approved_rows: 869 if import_rows:
862 staging_placeholders = ",".join(["%s"] * len(staging_ids)) 870 staging_placeholders = ",".join(["%s"] * len(staging_ids))
863 conflicts = _find_import_conflicts(cursor, staging_ids) 871 conflicts = _find_import_conflicts(cursor, staging_ids)
864 if conflicts: 872 if conflicts:
...@@ -893,13 +901,13 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o ...@@ -893,13 +901,13 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o
893 FROM {TARGET_TABLE_NAME} 901 FROM {TARGET_TABLE_NAME}
894 WHERE source_song_id IN ({source_placeholders}) 902 WHERE source_song_id IN ({source_placeholders})
895 """, 903 """,
896 approved_source_ids, 904 all_import_source_ids,
897 ) 905 )
898 id_map = {str(row["source_song_id"]): row["target_id"] for row in cursor.fetchall()} 906 id_map = {str(row["source_song_id"]): row["target_id"] for row in cursor.fetchall()}
899 907
900 imported_updated = 0 908 imported_updated = 0
901 for approved_row in approved_rows: 909 for import_row in import_rows:
902 sid = str(approved_row["source_song_id"]) 910 sid = str(import_row["source_song_id"])
903 target_id = id_map.get(sid) 911 target_id = id_map.get(sid)
904 if target_id is None: 912 if target_id is None:
905 raise RuntimeError(f"入库后未找到目标记录: source_song_id={sid}") 913 raise RuntimeError(f"入库后未找到目标记录: source_song_id={sid}")
...@@ -910,7 +918,7 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o ...@@ -910,7 +918,7 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o
910 review_version = review_version + 1 918 review_version = review_version + 1
911 WHERE staging_id = %s AND staging_status = 'staged' 919 WHERE staging_id = %s AND staging_status = 'staged'
912 """, 920 """,
913 (target_id, approved_row["staging_id"]), 921 (target_id, import_row["staging_id"]),
914 ) 922 )
915 imported_updated += cursor.rowcount 923 imported_updated += cursor.rowcount
916 924
...@@ -958,12 +966,14 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o ...@@ -958,12 +966,14 @@ def _import_approved_staging(source_ids: list[str] | None = None) -> dict[str, o
958 conn.commit() 966 conn.commit()
959 return { 967 return {
960 "approved_count": len(approved_rows), 968 "approved_count": len(approved_rows),
969 "diff_lyric_count": len(diff_lyric_rows),
961 "inserted_count": inserted_count, 970 "inserted_count": inserted_count,
962 "imported_song_ids_updated": imported_updated, 971 "imported_song_ids_updated": imported_updated,
963 "duplicate_count": len(duplicate_rows), 972 "duplicate_count": len(duplicate_rows),
964 "duplicate_staging_updated": duplicate_updated, 973 "duplicate_staging_updated": duplicate_updated,
965 "author_merged_count": author_merged, 974 "author_merged_count": author_merged,
966 "source_ids": approved_source_ids, 975 "source_ids": [str(row["source_song_id"]) for row in approved_rows],
976 "diff_lyric_source_ids": [str(row["source_song_id"]) for row in diff_lyric_rows],
967 "duplicate_source_ids": [str(row["source_song_id"]) for row in duplicate_rows], 977 "duplicate_source_ids": [str(row["source_song_id"]) for row in duplicate_rows],
968 } 978 }
969 979
......