This commit is contained in:
dekun
2026-05-27 16:32:30 +08:00
parent b9af1f69fe
commit bb8aca0cb3
10 changed files with 366 additions and 36 deletions
+11 -1
View File
@@ -1,4 +1,4 @@
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, Response
from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify, Response, send_file
import sqlite3
import csv
from io import StringIO
@@ -6912,6 +6912,16 @@ def api_reviews():
return jsonify([row_to_dict(r) for r in rows])
_AI_REVIEW_RENDER_JS = os.path.join(os.path.dirname(BASE_DIR), "static", "ai_review_render.js")
@app.route("/static/ai_review_render.js")
def static_ai_review_render_js():
if not os.path.isfile(_AI_REVIEW_RENDER_JS):
return Response("not found", status=404, mimetype="text/plain; charset=utf-8")
return send_file(_AI_REVIEW_RENDER_JS, mimetype="application/javascript; charset=utf-8")
@app.route("/export/review_md/<rid>")
@login_required
def export_review_md(rid):
+43 -6
View File
@@ -62,6 +62,15 @@
.pnl-loss{color:#ff6666;font-weight:600}
.flash{padding:10px;background:#1e2533;color:#4cc2ff;border-radius:10px;margin-bottom:12px;text-align:center;border:1px solid #304164}
.ai-result{background:#1a1a29;border:1px solid #2e2e45;border-radius:8px;padding:10px;white-space:pre-wrap;max-height:220px;overflow:auto;font-size:.84rem;line-height:1.45;margin-top:8px}
.ai-result.ai-result-md,.detail-modal .panel-body.md-review{white-space:normal}
.ai-result-md p,.detail-modal .panel-body.md-review p{margin:6px 0;color:#dde2ff}
.ai-result-md ul,.ai-result-md ol,.detail-modal .panel-body.md-review ul,.detail-modal .panel-body.md-review ol{margin:6px 0 8px 1.25em;padding:0}
.ai-result-md li,.detail-modal .panel-body.md-review li{margin:5px 0;line-height:1.5}
.ai-result-md strong,.detail-modal .panel-body.md-review strong{color:#f0f3ff;font-weight:600}
.ai-result-md h2,.detail-modal .panel-body.md-review h2{font-size:1.02rem;color:#b8c8ff;margin:14px 0 8px;padding-bottom:4px;border-bottom:1px solid #2e2e45}
.ai-result-md h3,.detail-modal .panel-body.md-review h3{font-size:.92rem;color:#c9d4ff;margin:10px 0 6px}
.ai-result-md code,.detail-modal .panel-body.md-review code{background:#252538;padding:1px 4px;border-radius:4px;font-size:.82em}
.ai-result-md .md-raw-block-title,.detail-modal .panel-body.md-review .md-raw-block-title{margin-top:14px;padding-top:10px;border-top:1px dashed #3a3a55;color:#a8b0d8;font-weight:600}
.price-up{color:#4cd97f}
.price-down{color:#ff6666}
.price-flat{color:#cfd3ef}
@@ -861,6 +870,7 @@
</div>
</div>
<script src="/static/ai_review_render.js?v=1"></script>
<script>
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
@@ -925,12 +935,39 @@ document.addEventListener("keydown", function(e){
const card = document.getElementById("review-card");
if(card && card.classList.contains("is-fullscreen")){ toggleReviewCardFullscreen(); }
});
function setAiReviewMarkdown(el, rawText){
if(!el) return;
if(window.AiReviewRender && AiReviewRender.setElementMarkdown){
AiReviewRender.setElementMarkdown(el, rawText || "");
} else {
el.classList.remove("ai-result-md");
el.innerText = rawText || "";
}
}
function setDetailBodyPlain(text){
const body = document.getElementById("detailBody");
if(!body) return;
body.classList.remove("md-review");
body.innerText = text || "";
}
function setDetailBodyMarkdown(text){
const body = document.getElementById("detailBody");
if(!body) return;
if(window.AiReviewRender && AiReviewRender.setElementMarkdown){
body.classList.add("md-review");
AiReviewRender.setElementMarkdown(body, text || "");
} else {
setDetailBodyPlain(text);
}
}
function openAiInlineResultFullscreen(title, elementId){
const el = document.getElementById(elementId || "daily_result");
const text = String((el && el.innerText) || "").trim();
const text = (window.AiReviewRender && AiReviewRender.getElementMarkdown)
? String(AiReviewRender.getElementMarkdown(el) || "").trim()
: String((el && el.innerText) || "").trim();
if(!text){ alert("暂无内容"); return; }
document.getElementById("detailTitle").innerText = title || "AI复盘";
document.getElementById("detailBody").innerText = text;
setDetailBodyMarkdown(text);
const imgEl = document.getElementById("detailImage");
imgEl.src = "";
imgEl.style.display = "none";
@@ -969,7 +1006,7 @@ function openJournalDetail(id){
`备注:${o.note || "无"}`,
].join("\n");
document.getElementById("detailTitle").innerText = `交易复盘详情|${o.coin || "-"} ${o.tf || "-"}`;
document.getElementById("detailBody").innerText = detail;
setDetailBodyPlain(detail);
const imgEl = document.getElementById("detailImage");
if(o.image){
imgEl.src = `/static/images/${o.image}`;
@@ -986,7 +1023,7 @@ function openReviewDetail(id, fullscreen){
const r = reviewCache[id];
if(!r){ return; }
document.getElementById("detailTitle").innerText = `${r.review_type === "daily" ? "日复盘" : "周复盘"}${r.target_date || "-"}`;
document.getElementById("detailBody").innerText = r.content || "";
setDetailBodyMarkdown(r.content || "");
const imgEl = document.getElementById("detailImage");
imgEl.src = "";
imgEl.style.display = "none";
@@ -1198,7 +1235,7 @@ function genDaily(){
.then(r=>r.json()).then(data=>{
const el=document.getElementById("daily_result");
const wrap=document.getElementById("daily_result_wrap");
el.innerText=data.result;
setAiReviewMarkdown(el, data.result);
if(wrap){ wrap.style.display="block"; }
else { el.style.display="block"; }
loadReviews();
@@ -1213,7 +1250,7 @@ function genWeekly(){
.then(r=>r.json()).then(data=>{
const el=document.getElementById("weekly_result");
const wrap=document.getElementById("weekly_result_wrap");
el.innerText=data.result;
setAiReviewMarkdown(el, data.result);
if(wrap){ wrap.style.display="block"; }
else { el.style.display="block"; }
loadReviews();