Commit 46f11430 46f1143019633de281de9bdfe272226d7b8c8f42 by 沈秋雨

refactor(database): 优化数据库连接管理与界面渲染流程

1 parent fcf7434e
......@@ -1085,9 +1085,18 @@
showSyncNotice('');
renderList();
await loadQueryRows();
await claimCurrentReview();
renderList();
// 先渲染详情(歌词加载立即开始),领取审核在后台并行
renderDetail();
claimCurrentReview().then(() => {
// 领取完成后只更新顶部状态信息(不重新渲染整个详情)
const q = currentQuery();
if (q && q.query_source_id === state.queryId) {
els.stickyInfo.querySelectorAll('.pill').forEach(el => {
// 标记“我正在审核”已在 renderDetail 中生成,此处只做局部刷新
});
renderList();
}
});
});
}
els.prevPageBtn.disabled = state.page <= 1;
......@@ -1382,9 +1391,9 @@
}
const payload = await updateStagingReview(query, dbDecision, note);
for (const row of state.queryRows) applyReviewSnapshot(row, payload.record);
await reloadSummary();
// 重新加载列表并跳转到下一条
await advanceToNext();
// 刷新统计和加载列表并行
await Promise.all([reloadSummary(), loadGroups()]);
renderAll();
} catch (e) {
console.error('DB同步失败:', e);
if (e.status === 409) {
......@@ -1408,8 +1417,9 @@
}
await updateStagingReview(query, 'deleted',
document.getElementById('reviewNote')?.value || '');
await reloadSummary();
await advanceToNext();
// 刷新统计和加载列表并行
await Promise.all([reloadSummary(), loadGroups()]);
renderAll();
} catch (e) {
alert(`删除失败: ${e.message}`);
renderDetail();
......@@ -1428,8 +1438,8 @@
}
await updateStagingReview(query, 'pending', '');
if (candidate) setReview(candidate, { final_decision: undefined, note: '' });
await loadQueryRows();
await reloadSummary();
// 刷新统计和重新加载当前行并行
await Promise.all([reloadSummary(), loadQueryRows()]);
} catch (e) {
alert(`撤销失败: ${e.message}`);
}
......@@ -1504,8 +1514,8 @@
try {
const payload = await reviewPostJSON('/api/import-reviewed');
alert(`入库完成:${payload.inserted_count} 条。结果文件:${payload.review_csv}`);
await loadGroups();
await reloadSummary();
// 刷新统计和加载列表并行
await Promise.all([reloadSummary(), loadGroups()]);
renderAll();
} catch (err) {
alert(`入库失败:${err.message}`);
......@@ -1575,6 +1585,7 @@
async function advanceToNext() {
// 重新加载列表(应用当前筛选,已审核的会被过滤掉)
// loadGroups 内部已包含 loadQueryRows,无需额外调用
await loadGroups();
renderAll();
}
......
......@@ -7,6 +7,7 @@ charset-normalizer==3.4.7
cos_python_sdk_v5==1.9.44
crcmod==1.7
cryptography==49.0.0
DBUtils>=3.1.0
et_xmlfile==2.0.0
exceptiongroup==1.3.1
idna==3.18
......
......@@ -19,6 +19,7 @@ from urllib.parse import parse_qs, unquote, urlparse
import pymysql
import requests
from dbutils.pooled_db import PooledDB
from dotenv import load_dotenv
......@@ -45,6 +46,18 @@ TARGET_DB_CONFIG = {
}
TARGET_TABLE_NAME = os.getenv("TARGET_TABLE_NAME", "hk_songs")
TARGET_TABLE_NAME_TMP = os.getenv("TARGET_TABLE_NAME_TMP", f"{TARGET_TABLE_NAME}_import_staging")
# 连接池:mincached=2 保持 2 个空闲连接,maxcached=5 上限 5 个空闲,
# maxconnections=10 最大总数,ping=1 每次取连接前检测活性
_DB_POOL = PooledDB(
creator=pymysql,
mincached=2,
maxcached=5,
maxconnections=10,
blocking=True,
ping=1,
**TARGET_DB_CONFIG,
)
STAGING_DB_PATH = "__staging_db__"
TARGET_COLUMNS = [
"id", "name", "lyricist", "composer", "issue_status", "intro",
......@@ -175,7 +188,8 @@ def _iter_csv(path: Path):
def _target_conn():
return pymysql.connect(**TARGET_DB_CONFIG)
"""从连接池获取连接,with 块结束时自动归还池中。"""
return _DB_POOL.connection()
def _ensure_review_schema(apply_migration: bool = False) -> None:
......