fix: AI review list UTC filter, vision timeout, and stuck loading state

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-05 13:59:17 +08:00
parent 4ac4c062e0
commit 3f1bf9905d
11 changed files with 199 additions and 122 deletions
+3 -2
View File
@@ -137,6 +137,7 @@ from history_window_lib import (
resolve_window,
sql_list_time_field,
utc_window_to_bj_sql_strings,
utc_window_to_utc_sql_strings,
)
@@ -7841,11 +7842,11 @@ def delete_journal(jid):
@login_required
def api_reviews():
win = _list_window_from_request()
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
start_sql, end_sql = utc_window_to_utc_sql_strings(win["start_utc"], win["end_utc"])
conn = get_db()
rows = conn.execute(
"SELECT * FROM ai_reviews WHERE created_at >= ? AND created_at <= ? ORDER BY created_at DESC LIMIT 200",
(start_bj, end_bj),
(start_sql, end_sql),
).fetchall()
conn.close()
return jsonify([row_to_dict(r) for r in rows])
+26 -14
View File
@@ -1245,7 +1245,9 @@ function genDaily(){
btnLabel:"日复盘生成中…"
});
}
fetch("/ai_daily_review",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`date=${encodeURIComponent(d)}`})
const ac = new AbortController();
const timer = setTimeout(()=>ac.abort(), 360000);
fetch("/ai_daily_review",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`date=${encodeURIComponent(d)}`,signal:ac.signal})
.then(r=>{ if(!r.ok) throw new Error("HTTP "+r.status); return r.json(); })
.then(data=>{
if(!data || data.result == null) throw new Error("返回数据为空");
@@ -1254,17 +1256,21 @@ function genDaily(){
setAiReviewMarkdown(el, data.result);
if(wrap){ wrap.style.display="block"; }
else if(el){ el.style.display="block"; }
if(window.AiReviewRender && AiReviewRender.clearGenerating) AiReviewRender.clearGenerating("gen-daily-btn");
loadReviews();
})
.catch(e=>{
if(window.AiReviewRender && AiReviewRender.clearGenerating) AiReviewRender.clearGenerating("gen-daily-btn");
.catch(err=>{
const el=document.getElementById("daily_result");
if(el){
if(el && el.classList.contains("is-loading")){
el.classList.remove("is-loading","ai-result-md");
el.innerText="生成失败,请重试。";
el.innerText = err.name === "AbortError"
? "生成超时(>6分钟),请检查 OPENAI_MODEL 是否与网关已启用模型一致,或增大 AI_REVIEW_TIMEOUT_SECONDS。"
: "生成失败,请重试。";
}
alert("生成日复盘失败:"+(e.message||e));
alert("生成日复盘失败:"+(err.message||err));
})
.finally(()=>{
clearTimeout(timer);
if(window.AiReviewRender && AiReviewRender.clearGenerating) AiReviewRender.clearGenerating("gen-daily-btn");
});
}
@@ -1282,7 +1288,9 @@ function genWeekly(){
btnLabel:"周复盘生成中…"
});
}
fetch("/ai_weekly_review",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`start_date=${encodeURIComponent(s)}&end_date=${encodeURIComponent(e)}`})
const ac = new AbortController();
const timer = setTimeout(()=>ac.abort(), 360000);
fetch("/ai_weekly_review",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`start_date=${encodeURIComponent(s)}&end_date=${encodeURIComponent(e)}`,signal:ac.signal})
.then(r=>{ if(!r.ok) throw new Error("HTTP "+r.status); return r.json(); })
.then(data=>{
if(!data || data.result == null) throw new Error("返回数据为空");
@@ -1291,17 +1299,21 @@ function genWeekly(){
setAiReviewMarkdown(el, data.result);
if(wrap){ wrap.style.display="block"; }
else if(el){ el.style.display="block"; }
if(window.AiReviewRender && AiReviewRender.clearGenerating) AiReviewRender.clearGenerating("gen-weekly-btn");
loadReviews();
})
.catch(e=>{
if(window.AiReviewRender && AiReviewRender.clearGenerating) AiReviewRender.clearGenerating("gen-weekly-btn");
.catch(err=>{
const el=document.getElementById("weekly_result");
if(el){
if(el && el.classList.contains("is-loading")){
el.classList.remove("is-loading","ai-result-md");
el.innerText="生成失败,请重试。";
el.innerText = err.name === "AbortError"
? "生成超时(>6分钟),请检查 OPENAI_MODEL 是否与网关已启用模型一致,或增大 AI_REVIEW_TIMEOUT_SECONDS。"
: "生成失败,请重试。";
}
alert("生成周复盘失败:"+(e.message||e));
alert("生成周复盘失败:"+(err.message||err));
})
.finally(()=>{
clearTimeout(timer);
if(window.AiReviewRender && AiReviewRender.clearGenerating) AiReviewRender.clearGenerating("gen-weekly-btn");
});
}