fix: 主页预嵌入统计数据,日历首次加载即可显示状态圆点
This commit is contained in:
101
app.py
101
app.py
@@ -68,11 +68,58 @@ def logout():
|
|||||||
|
|
||||||
# ── 主页 ──────────────────────────────────────────────
|
# ── 主页 ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
def compute_stats():
|
||||||
|
"""计算统计数据,供 API 和模板共用"""
|
||||||
|
rows = get_all_checkins()
|
||||||
|
total_days = len(rows)
|
||||||
|
total_morning = 0
|
||||||
|
total_evening = 0
|
||||||
|
total_study = 0
|
||||||
|
calendar = {}
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
d = row['date']
|
||||||
|
data = row['data']
|
||||||
|
morning = data.get('morning', [])
|
||||||
|
evening = data.get('evening', [])
|
||||||
|
study = data.get('study', [])
|
||||||
|
|
||||||
|
total_morning += sum(1 for x in morning if isinstance(x, str) and x.strip())
|
||||||
|
total_evening += sum(1 for x in evening if (
|
||||||
|
isinstance(x, str) and x.strip() or
|
||||||
|
isinstance(x, dict) and (x.get('mistake', '') or '').strip()
|
||||||
|
))
|
||||||
|
total_study += sum(1 for x in study if x.get('done'))
|
||||||
|
|
||||||
|
day_score = 0
|
||||||
|
has_morning = any(isinstance(x, str) and x.strip() for x in morning)
|
||||||
|
has_evening = any(
|
||||||
|
(isinstance(x, str) and x.strip()) or
|
||||||
|
(isinstance(x, dict) and (x.get('mistake', '') or '').strip())
|
||||||
|
for x in evening
|
||||||
|
)
|
||||||
|
has_study = any(x.get('done') for x in study)
|
||||||
|
if has_morning: day_score += 1
|
||||||
|
if has_evening: day_score += 1
|
||||||
|
if has_study: day_score += 1
|
||||||
|
|
||||||
|
calendar[d] = 'pass' if day_score >= 2 else 'fail'
|
||||||
|
|
||||||
|
return dict(
|
||||||
|
total_days=total_days, total_morning=total_morning,
|
||||||
|
total_evening=total_evening, total_study=total_study,
|
||||||
|
calendar=calendar
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@login_required
|
@login_required
|
||||||
def index():
|
def index():
|
||||||
|
import json
|
||||||
|
stats = compute_stats()
|
||||||
return render_template('index.html',
|
return render_template('index.html',
|
||||||
username=session.get('display_name', session.get('username', '')))
|
username=session.get('display_name', session.get('username', '')),
|
||||||
|
initial_stats=json.dumps(stats, ensure_ascii=False))
|
||||||
|
|
||||||
|
|
||||||
# ── API ──────────────────────────────────────────────
|
# ── API ──────────────────────────────────────────────
|
||||||
@@ -116,56 +163,8 @@ def api_history():
|
|||||||
@app.route('/api/stats', methods=['GET'])
|
@app.route('/api/stats', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def api_stats():
|
def api_stats():
|
||||||
"""返回统计数据和日历状态映射"""
|
stats = compute_stats()
|
||||||
rows = get_all_checkins()
|
return jsonify({'ok': True, **stats})
|
||||||
|
|
||||||
total_days = len(rows)
|
|
||||||
total_morning = 0
|
|
||||||
total_evening = 0
|
|
||||||
total_study = 0
|
|
||||||
calendar = {}
|
|
||||||
|
|
||||||
for row in rows:
|
|
||||||
d = row['date']
|
|
||||||
data = row['data']
|
|
||||||
morning = data.get('morning', [])
|
|
||||||
evening = data.get('evening', [])
|
|
||||||
study = data.get('study', [])
|
|
||||||
|
|
||||||
# 统计条目
|
|
||||||
total_morning += sum(1 for x in morning if isinstance(x, str) and x.strip())
|
|
||||||
total_evening += sum(1 for x in evening if (
|
|
||||||
isinstance(x, str) and x.strip() or
|
|
||||||
isinstance(x, dict) and (x.get('mistake', '') or '').strip()
|
|
||||||
))
|
|
||||||
total_study += sum(1 for x in study if x.get('done'))
|
|
||||||
|
|
||||||
# 评分
|
|
||||||
day_score = 0
|
|
||||||
has_morning = any(isinstance(x, str) and x.strip() for x in morning)
|
|
||||||
has_evening = any(
|
|
||||||
(isinstance(x, str) and x.strip()) or
|
|
||||||
(isinstance(x, dict) and (x.get('mistake', '') or '').strip())
|
|
||||||
for x in evening
|
|
||||||
)
|
|
||||||
has_study = any(x.get('done') for x in study)
|
|
||||||
if has_morning:
|
|
||||||
day_score += 1
|
|
||||||
if has_evening:
|
|
||||||
day_score += 1
|
|
||||||
if has_study:
|
|
||||||
day_score += 1
|
|
||||||
|
|
||||||
calendar[d] = 'pass' if day_score >= 2 else 'fail'
|
|
||||||
|
|
||||||
return jsonify({
|
|
||||||
'ok': True,
|
|
||||||
'total_days': total_days,
|
|
||||||
'total_morning': total_morning,
|
|
||||||
'total_evening': total_evening,
|
|
||||||
'total_study': total_study,
|
|
||||||
'calendar': calendar
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/user', methods=['GET'])
|
@app.route('/api/user', methods=['GET'])
|
||||||
|
|||||||
@@ -218,7 +218,7 @@
|
|||||||
document.getElementById('stat-study').textContent = data.total_study;
|
document.getElementById('stat-study').textContent = data.total_study;
|
||||||
calendarStatus = data.calendar || {};
|
calendarStatus = data.calendar || {};
|
||||||
}
|
}
|
||||||
renderCalendar(); // 无论成败都重新渲染
|
renderCalendar();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,9 +649,19 @@
|
|||||||
initStudyPresets();
|
initStudyPresets();
|
||||||
bindAutoSave();
|
bindAutoSave();
|
||||||
lastSavedDate = todayStr;
|
lastSavedDate = todayStr;
|
||||||
|
|
||||||
|
// 从页面嵌入数据获取初始统计(0 延迟)
|
||||||
|
if (window.__INITIAL_STATS__) {
|
||||||
|
var s = window.__INITIAL_STATS__;
|
||||||
|
document.getElementById('stat-days').textContent = s.total_days;
|
||||||
|
document.getElementById('stat-morning').textContent = s.total_morning;
|
||||||
|
document.getElementById('stat-study').textContent = s.total_study;
|
||||||
|
calendarStatus = s.calendar || {};
|
||||||
|
}
|
||||||
|
|
||||||
loadCheckin();
|
loadCheckin();
|
||||||
loadStats();
|
loadStats(); // 异步刷新最新数据
|
||||||
renderCalendar(); // 立即渲染日历,不等异步统计
|
renderCalendar(); // 同步渲染 — calendarStatus 已有值
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
if (document.readyState === 'loading') {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>紫微 · 磁场管理</title>
|
<title>紫微 · 磁场管理</title>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||||
|
<script>window.__INITIAL_STATS__ = {{ initial_stats | safe }};</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% include "icons.html" %}
|
{% include "icons.html" %}
|
||||||
|
|||||||
Reference in New Issue
Block a user