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 @@
-
+