同步进度增加详细天数反馈,优化日期范围避免重复请求无数据的历史日期

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 14:03:33 +08:00
parent ca98967af0
commit 58327a9a66
2 changed files with 28 additions and 11 deletions
+14 -4
View File
@@ -52,6 +52,7 @@ def sync_contract_bars_bg(contract_code: str) -> bool:
with _lock: with _lock:
_progress["total"] = len(bars) _progress["total"] = len(bars)
total_bars = len(bars)
inserted = 0 inserted = 0
min_date = None min_date = None
for i, bar in enumerate(bars): for i, bar in enumerate(bars):
@@ -71,6 +72,7 @@ def sync_contract_bars_bg(contract_code: str) -> bool:
min_date = bar["date"] min_date = bar["date"]
with _lock: with _lock:
_progress["done"] = i + 1 _progress["done"] = i + 1
_progress["label"] = f"同步行情 {code} · {i + 1}/{total_bars}"
if inserted > 0: if inserted > 0:
db.flush() db.flush()
@@ -102,10 +104,19 @@ def sync_positions_bg(contract_code: str) -> bool:
.filter(DailyBar.contract == code) .filter(DailyBar.contract == code)
.order_by(DailyBar.date).all() .order_by(DailyBar.date).all()
] ]
missing = [d for d in bar_dates if d not in existing_dates] # Only sync dates within or after existing position date range;
# akshare may not have data for very old dates
if existing_dates:
min_pos = min(existing_dates)
missing = [d for d in bar_dates if d not in existing_dates and d >= min_pos]
else:
missing = [d for d in bar_dates if d not in existing_dates]
total_missing = len(missing)
with _lock: with _lock:
_progress["total"] = len(missing) _progress["total"] = total_missing
if total_missing == 0:
_progress["label"] = f"同步持仓 {code} · 已是最新"
inserted = 0 inserted = 0
for i, d in enumerate(missing): for i, d in enumerate(missing):
@@ -120,8 +131,7 @@ def sync_positions_bg(contract_code: str) -> bool:
db.flush() db.flush()
with _lock: with _lock:
_progress["done"] = i + 1 _progress["done"] = i + 1
_progress["label"] = f"同步持仓 {code} · {i + 1}/{total_missing}"
db.commit()
finally: finally:
db.close() db.close()
+14 -7
View File
@@ -193,8 +193,10 @@
<script> <script>
var syncTimer = null; var syncTimer = null;
var progressShownAt = 0;
function showProgress() { function showProgress() {
progressShownAt = Date.now();
document.getElementById('sync-progress').style.display = 'block'; document.getElementById('sync-progress').style.display = 'block';
document.getElementById('sync-progress-bar').style.width = '0%'; document.getElementById('sync-progress-bar').style.width = '0%';
document.getElementById('sync-progress-pct').textContent = ''; document.getElementById('sync-progress-pct').textContent = '';
@@ -203,6 +205,7 @@ function showProgress() {
function hideProgress() { function hideProgress() {
clearInterval(syncTimer); clearInterval(syncTimer);
syncTimer = null;
document.getElementById('sync-progress').style.display = 'none'; document.getElementById('sync-progress').style.display = 'none';
} }
@@ -216,23 +219,27 @@ function pollProgress() {
document.getElementById('sync-progress-label').textContent = data.label; document.getElementById('sync-progress-label').textContent = data.label;
if (data.finished) { if (data.finished) {
clearInterval(syncTimer); var elapsed = Date.now() - progressShownAt;
document.getElementById('sync-progress-bar').style.width = '100%'; var delay = elapsed < 1000 ? 1000 - elapsed : 0;
document.getElementById('sync-progress-pct').textContent = '100%'; setTimeout(function() {
document.getElementById('sync-progress-label').textContent = data.label + ' 完成'; clearInterval(syncTimer);
document.getElementById('sync-progress-pct').textContent = '✓'; syncTimer = null;
document.getElementById('sync-progress-bar').style.width = '100%';
document.getElementById('sync-progress-label').textContent = data.label + ' ✓';
document.getElementById('sync-progress-pct').textContent = '';
}, delay);
} }
}); });
} }
function startSync(url) { function startSync(url) {
if (syncTimer) { clearInterval(syncTimer); } if (syncTimer) { clearInterval(syncTimer); syncTimer = null; }
showProgress(); showProgress();
fetch(url, { method: 'POST' }) fetch(url, { method: 'POST' })
.then(function(r) { return r.json(); }) .then(function(r) { return r.json(); })
.then(function(data) { .then(function(data) {
if (!data.ok) { hideProgress(); return; } if (!data.ok) { hideProgress(); return; }
syncTimer = setInterval(pollProgress, 600); syncTimer = setInterval(pollProgress, 500);
}); });
} }