feat(import): 支持同曲不同词样本的新歌入库逻辑
Showing
2 changed files
with
21 additions
and
11 deletions
| ... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment