diff --git a/lib/common/static/options_review.js b/lib/common/static/options_review.js index 43518fd..2c6ec72 100644 --- a/lib/common/static/options_review.js +++ b/lib/common/static/options_review.js @@ -98,12 +98,12 @@ p.set("source_type", activeSource); var uly = ($("or-filter-uly") || {}).value || ""; var opt = ($("or-filter-opt") || {}).value || ""; - var strategy = (($("or-filter-strategy") || {}).value || "").trim(); + var q = (($("or-filter-q") || $("or-filter-strategy") || {}).value || "").trim(); var from = ($("or-filter-from") || {}).value || ""; var to = ($("or-filter-to") || {}).value || ""; if (uly) p.set("underlying", uly); if (opt) p.set("opt_type", opt); - if (strategy) p.set("strategy_tag", strategy); + if (q) p.set("q", q); if (from) p.set("closed_from", from.replace("T", " ") + ":00"); if (to) p.set("closed_to", to.replace("T", " ") + ":00"); if (($("or-include-hedge-legs") || {}).checked) p.set("include_hedge_legs", "1"); @@ -1152,7 +1152,7 @@ }); } }); - ["or-filter-strategy", "or-filter-from", "or-filter-to"].forEach(function (id) { + ["or-filter-q", "or-filter-strategy", "or-filter-from", "or-filter-to"].forEach(function (id) { var el = $(id); if (el) { el.addEventListener("change", function () { diff --git a/lib/options/options_review_lib.py b/lib/options/options_review_lib.py index 43f4b60..5aec20a 100644 --- a/lib/options/options_review_lib.py +++ b/lib/options/options_review_lib.py @@ -591,12 +591,29 @@ def enrich_trade_row(row: dict[str, Any], entry: dict[str, Any] | None = None) - return out +def _review_search_tokens(q: str) -> list[str]: + """自由搜索词:BTCUSDT 同时匹配 BTC / BTCUSDT.""" + raw = str(q or "").strip() + if not raw: + return [] + tokens = [raw] + u = raw.upper() + for suf in ("-USDT", "-USD", "-USDC", "USDT", "USD", "USDC"): + if u.endswith(suf) and len(u) > len(suf): + base = u[: -len(suf)].rstrip("-_") + if base and base not in {t.upper() for t in tokens}: + tokens.append(base) + break + return tokens + + def _review_trades_filters( *, source_type: str | None = None, underlying: str | None = None, opt_type: str | None = None, strategy_tag: str | None = None, + q: str | None = None, reviewed: str | None = None, include_hedge_legs: bool = False, closed_from: str | None = None, @@ -635,9 +652,26 @@ def _review_trades_filters( if closed_to: wheres.append("COALESCE(t.closed_at,'')<=?") args.append(closed_to) - if strategy_tag: - wheres.append("e.strategy_tag=?") + # 兼容旧参数:精确策略标签;前端已改用 q 模糊搜索 + if strategy_tag and not q: + wheres.append("UPPER(COALESCE(e.strategy_tag,''))=UPPER(?)") args.append(strategy_tag) + search_tokens = _review_search_tokens(q or "") + if search_tokens: + token_ors: list[str] = [] + for tok in search_tokens: + like = f"%{tok}%" + token_ors.append( + """( + UPPER(COALESCE(t.underlying,'')) LIKE UPPER(?) + OR UPPER(COALESCE(t.inst_id,'')) LIKE UPPER(?) + OR UPPER(COALESCE(t.legs_json,'')) LIKE UPPER(?) + OR UPPER(COALESCE(e.strategy_tag,'')) LIKE UPPER(?) + OR UPPER(COALESCE(e.result_tag,'')) LIKE UPPER(?) + )""" + ) + args.extend([like, like, like, like, like]) + wheres.append("(" + " OR ".join(token_ors) + ")") if reviewed == "1" or reviewed == "yes": wheres.append("e.id IS NOT NULL") elif reviewed == "0" or reviewed == "no": @@ -653,6 +687,7 @@ def count_review_trades( underlying: str | None = None, opt_type: str | None = None, strategy_tag: str | None = None, + q: str | None = None, reviewed: str | None = None, include_hedge_legs: bool = False, closed_from: str | None = None, @@ -664,6 +699,7 @@ def count_review_trades( underlying=underlying, opt_type=opt_type, strategy_tag=strategy_tag, + q=q, reviewed=reviewed, include_hedge_legs=include_hedge_legs, closed_from=closed_from, @@ -688,6 +724,7 @@ def list_review_trades( underlying: str | None = None, opt_type: str | None = None, strategy_tag: str | None = None, + q: str | None = None, reviewed: str | None = None, include_hedge_legs: bool = False, closed_from: str | None = None, @@ -701,6 +738,7 @@ def list_review_trades( underlying=underlying, opt_type=opt_type, strategy_tag=strategy_tag, + q=q, reviewed=reviewed, include_hedge_legs=include_hedge_legs, closed_from=closed_from, diff --git a/lib/options/options_review_register.py b/lib/options/options_review_register.py index 64683cb..c73dbef 100644 --- a/lib/options/options_review_register.py +++ b/lib/options/options_review_register.py @@ -135,6 +135,7 @@ def register_options_review_routes(app: Flask, cfg: dict[str, Any], repo_root: s underlying=(request.args.get("underlying") or "").strip() or None, opt_type=(request.args.get("opt_type") or "").strip() or None, strategy_tag=(request.args.get("strategy_tag") or "").strip() or None, + q=(request.args.get("q") or "").strip() or None, reviewed=(request.args.get("reviewed") or "").strip() or None, include_hedge_legs=(request.args.get("include_hedge_legs") or "") .strip() diff --git a/lib/options/templates/options_review_panel.html b/lib/options/templates/options_review_panel.html index 1d5e36e..73135c5 100644 --- a/lib/options/templates/options_review_panel.html +++ b/lib/options/templates/options_review_panel.html @@ -94,7 +94,7 @@ - +