修改
This commit is contained in:
@@ -36,6 +36,7 @@ if _REPO_ROOT not in sys.path:
|
||||
sys.path.insert(0, _REPO_ROOT)
|
||||
from ai_client import ai_generate, ai_review, ai_short_advice
|
||||
from ai_review_lib import build_journal_ai_chart_path, collect_images_for_ai_review
|
||||
from form_submit_lib import check_duplicate_submit, submit_scope_add_key, submit_scope_add_order
|
||||
from journal_chart_lib import (
|
||||
JOURNAL_CHART_DEFAULT_LIMIT,
|
||||
JOURNAL_CHART_DEFAULT_TF1,
|
||||
@@ -5825,6 +5826,14 @@ def add_key():
|
||||
if not symbol:
|
||||
flash("symbol 不能为空")
|
||||
return redirect("/")
|
||||
mt = (d.get("type") or "").strip()
|
||||
direction_pre = (d.get("direction") or "long").strip().lower()
|
||||
dup_msg = check_duplicate_submit(
|
||||
session, submit_scope_add_key(symbol, mt, direction_pre)
|
||||
)
|
||||
if dup_msg:
|
||||
flash(dup_msg)
|
||||
return redirect("/")
|
||||
rank, total = _daily_volume_rank(symbol)
|
||||
if rank is None:
|
||||
flash("日成交量排名读取失败,请稍后重试")
|
||||
@@ -5852,6 +5861,11 @@ def add_order():
|
||||
conn.close()
|
||||
flash("symbol 不能为空")
|
||||
return redirect("/")
|
||||
dup_msg = check_duplicate_submit(session, submit_scope_add_order(symbol, direction))
|
||||
if dup_msg:
|
||||
conn.close()
|
||||
flash(dup_msg)
|
||||
return redirect("/trade")
|
||||
ok, reason = precheck_risk(conn, symbol, direction)
|
||||
if not ok:
|
||||
if "已达最大持仓数" in reason:
|
||||
@@ -7004,7 +7018,9 @@ 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")
|
||||
_REPO_STATIC_DIR = os.path.join(os.path.dirname(BASE_DIR), "static")
|
||||
_AI_REVIEW_RENDER_JS = os.path.join(_REPO_STATIC_DIR, "ai_review_render.js")
|
||||
_FORM_SUBMIT_GUARD_JS = os.path.join(_REPO_STATIC_DIR, "form_submit_guard.js")
|
||||
|
||||
|
||||
@app.route("/static/ai_review_render.js")
|
||||
@@ -7014,6 +7030,13 @@ def static_ai_review_render_js():
|
||||
return send_file(_AI_REVIEW_RENDER_JS, mimetype="application/javascript; charset=utf-8")
|
||||
|
||||
|
||||
@app.route("/static/form_submit_guard.js")
|
||||
def static_form_submit_guard_js():
|
||||
if not os.path.isfile(_FORM_SUBMIT_GUARD_JS):
|
||||
return Response("not found", status=404, mimetype="text/plain; charset=utf-8")
|
||||
return send_file(_FORM_SUBMIT_GUARD_JS, mimetype="application/javascript; charset=utf-8")
|
||||
|
||||
|
||||
@app.route("/export/review_md/<rid>")
|
||||
@login_required
|
||||
def export_review_md(rid):
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
.pnl-loss{color:#ff6666;font-weight:600}
|
||||
.pnl-neutral{color:#cfd3ef;font-weight:600}
|
||||
.flash{padding:10px;background:#1e2533;color:#4cc2ff;border-radius:10px;margin-bottom:12px;text-align:center;border:1px solid #304164}
|
||||
form.is-form-submitting{opacity:.88;pointer-events:none}
|
||||
form.is-form-submitting button[type=submit],form.is-form-submitting input[type=submit]{cursor:wait}
|
||||
.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}
|
||||
@@ -318,7 +320,7 @@
|
||||
</select>
|
||||
<button type="submit">手动划转</button>
|
||||
</form>
|
||||
<form action="/add_order" method="post" class="form-row">
|
||||
<form id="add-order-form" action="/add_order" method="post" class="form-row">
|
||||
<input id="order-symbol" name="symbol" placeholder="BTC 或 BTC/USDT" required>
|
||||
<select id="order-direction" name="direction" required>
|
||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||
@@ -701,6 +703,7 @@
|
||||
</div>
|
||||
|
||||
<script src="/static/ai_review_render.js?v=1"></script>
|
||||
<script src="/static/form_submit_guard.js?v=1"></script>
|
||||
<script>
|
||||
const JOURNAL_ENTRY_REASON_OPTIONS = {{ entry_reason_options | tojson }};
|
||||
const JOURNAL_ENTRY_REASON_OTHER = {{ entry_reason_other_value | tojson }};
|
||||
@@ -1392,26 +1395,48 @@ const keyForm = document.getElementById("key-form");
|
||||
if(keyForm){
|
||||
keyForm.addEventListener("submit", (e)=>{
|
||||
e.preventDefault();
|
||||
if(window.FormSubmitGuard && FormSubmitGuard.isLocked(keyForm)) return;
|
||||
const symbolEl = keyForm.querySelector('[name="symbol"]');
|
||||
const symbol = (symbolEl ? symbolEl.value : "").trim();
|
||||
if(!symbol){
|
||||
alert("请先输入交易对");
|
||||
return;
|
||||
}
|
||||
if(window.FormSubmitGuard) FormSubmitGuard.lock(keyForm, "校验排名中…");
|
||||
fetch(`/api/symbol_liquidity_rank?symbol=${encodeURIComponent(symbol)}`)
|
||||
.then(r=>r.json().then(d=>({status:r.status, data:d})))
|
||||
.then(({status,data})=>{
|
||||
if(status >= 400 || !data.ok){
|
||||
alert((data && data.msg) || "日成交量排名读取失败");
|
||||
if(window.FormSubmitGuard) FormSubmitGuard.unlock(keyForm);
|
||||
return;
|
||||
}
|
||||
if(!data.in_top30){
|
||||
alert(`${data.symbol} 当前日成交量排名 ${data.rank}/${data.total},不在前30,已拦截。`);
|
||||
if(window.FormSubmitGuard) FormSubmitGuard.unlock(keyForm);
|
||||
return;
|
||||
}
|
||||
keyForm.submit();
|
||||
if(window.FormSubmitGuard) FormSubmitGuard.nativeSubmitOnce(keyForm, "提交中…");
|
||||
else keyForm.submit();
|
||||
})
|
||||
.catch(()=>alert("日成交量排名检查失败,请稍后重试"));
|
||||
.catch(()=>{
|
||||
alert("日成交量排名检查失败,请稍后重试");
|
||||
if(window.FormSubmitGuard) FormSubmitGuard.unlock(keyForm);
|
||||
});
|
||||
});
|
||||
}
|
||||
const addOrderForm = document.getElementById("add-order-form");
|
||||
if(addOrderForm){
|
||||
addOrderForm.addEventListener("submit", function(ev){
|
||||
if(addOrderForm.dataset.submitOnce === "1"){
|
||||
addOrderForm.dataset.submitOnce = "0";
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
if(window.FormSubmitGuard && FormSubmitGuard.isLocked(addOrderForm)) return;
|
||||
addOrderForm.dataset.submitOnce = "1";
|
||||
if(window.FormSubmitGuard) FormSubmitGuard.nativeSubmitOnce(addOrderForm, "开仓提交中…");
|
||||
else addOrderForm.submit();
|
||||
});
|
||||
}
|
||||
// 复盘/AI列表:初次进入页面后再异步刷新一次,避免浏览器 bfcache/重定向后仍显示旧缓存
|
||||
|
||||
Reference in New Issue
Block a user