feat: personal user edition v1.0.0-user on release branch

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-30 20:22:42 +08:00
parent e5f264b774
commit ec1c9873b7
20 changed files with 324 additions and 294 deletions
+30 -15
View File
@@ -44,7 +44,8 @@ from fee_specs import (
count_fee_rates_by_source,
purge_non_ctp_fee_rates,
)
from nav_settings import NAV_TOGGLES, get_nav_items, nav_enabled, save_nav_items
from edition import EDITION_ID, EDITION_LABEL, USER_EDITION
from nav_settings import NAV_TOGGLES, get_nav_items, nav_enabled, nav_toggles_for_settings, save_nav_items
from stats_engine import (
STATS_VIEWS,
build_all_stats,
@@ -266,7 +267,13 @@ def _ua_is_phone(ua: str) -> bool:
@app.context_processor
def inject_globals():
return {"nav_items": get_nav_items(get_setting), "asset_v": _static_asset_v()}
return {
"nav_items": get_nav_items(get_setting),
"asset_v": _static_asset_v(),
"user_edition": USER_EDITION,
"edition_id": EDITION_ID,
"edition_label": EDITION_LABEL,
}
def _trading_mode() -> str:
@@ -765,16 +772,17 @@ def start_background_threads():
from trading_context import get_trading_mode
threading.Thread(target=background_task, daemon=True).start()
threading.Thread(
target=lambda: kline_hub.worker_loop(
DB_PATH,
lambda sym, mc, sc: build_market_quote_payload(
sym, mc, sc, prefer_sina=True,
if not USER_EDITION:
threading.Thread(
target=lambda: kline_hub.worker_loop(
DB_PATH,
lambda sym, mc, sc: build_market_quote_payload(
sym, mc, sc, prefer_sina=True,
),
get_mode_fn=lambda: get_trading_mode(get_setting),
),
get_mode_fn=lambda: get_trading_mode(get_setting),
),
daemon=True,
).start()
daemon=True,
).start()
threading.Thread(target=refresh_main_index, daemon=True).start()
start_backup_worker(get_setting_fn=get_setting, set_setting_fn=set_setting)
@@ -867,7 +875,7 @@ def api_symbols_mains():
@app.route("/api/symbols/recommended")
@login_required
def api_symbols_recommended():
"""品种下拉:仅展示当前资金下可开仓品种(与下方可开仓品种表一致)。"""
"""品种下拉:当前资金下可报单品种(小账户四品种限制;完整版与下方可开仓表一致)。"""
from recommend_store import recommend_payload
from trading_context import (
get_fixed_lots,
@@ -1506,7 +1514,7 @@ def add_review():
)
pnl_net = round((gross_pnl or 0) - fee, 2) if gross_pnl is not None else None
auto_kline = bool(d.get("auto_kline"))
auto_kline = bool(d.get("auto_kline")) and not USER_EDITION
if auto_kline and not screenshot:
try:
generated = generate_review_kline_chart(
@@ -1732,6 +1740,9 @@ def api_dashboard_live():
@login_required
@require_nav("market")
def market_page():
if USER_EDITION:
flash("个人用户版不含行情 K 线")
return redirect(url_for("positions"))
symbol = request.args.get("symbol", "").strip()
period = request.args.get("period", "15m").strip()
valid = {p["key"] for p in MARKET_PERIODS}
@@ -1758,6 +1769,8 @@ def market_page():
@app.route("/api/kline")
@login_required
def api_kline():
if USER_EDITION:
return jsonify({"error": "个人用户版不含行情 K 线"}), 403
symbol = request.args.get("symbol", "").strip()
period = request.args.get("period", "15m").strip()
if not symbol:
@@ -1781,6 +1794,8 @@ def api_kline():
@app.route("/api/kline/stream")
@login_required
def api_kline_stream():
if USER_EDITION:
return jsonify({"error": "个人用户版不含行情 K 线"}), 403
from queue import Empty
symbol = request.args.get("symbol", "").strip()
@@ -2094,7 +2109,7 @@ def settings():
flash_msg = f"CTP 配置已保存;{pwd_note or '请稍后在持仓监控页重连'}"
flash(flash_msg)
elif action == "nav":
items = {k: request.form.get(f"nav_{k}") == "on" for k in NAV_TOGGLES}
items = {k: request.form.get(f"nav_{k}") == "on" for k in nav_toggles_for_settings()}
save_nav_items(set_setting, items)
flash("导航显示已保存")
elif action == "password":
@@ -2143,7 +2158,7 @@ def settings():
trailing_be_tick_buffer=get_setting("trailing_be_tick_buffer", "2"),
pending_order_timeout_min=get_setting("pending_order_timeout_min", "5"),
nav_items=get_nav_items(get_setting),
nav_toggles=NAV_TOGGLES,
nav_toggles=nav_toggles_for_settings(),
backup_dir=str(backup_dir()),
backup_last_at=get_backup_last_at(get_setting),
backup_running=backup_in_progress(),