ek-ui
ek 生态的常驻主界面 crate(DV-1:egui/eframe 0.33)。UI 即插件:观测窗不是宿主外壳,
与 dm/oms/ctp 同列的一个插件——总线面收事件维护共享快照,eframe 窗口面只读渲染。
(0.2.10 BD-UI-38 用户裁定:sim 纸面网关退场,ctp/SimNow 两套前置满足需求。)
零配置口径(2026-10-17 定盘):ek-ui 不读任何配置文件,界面本身无设置;
宿主侧同样不预读配置。插件结构只由 --from 清单或 demo 缺省决定。需要配置的
插件(唯一 = ek-ctp 虚拟账号),配置面长在插件自身——菜单「账户」面板提供
手工输入位(9 格,密码掩码;无订阅字段)与账户清单,经 ask {gw}.configure 进插件
(网关注册名由 broker + 账号派生 ctp_<broker>_<账号>,不写配置文件;ek-ctp 自带配置口:
0.3.0 引入,0.5.0 补 configure 强制重连);宿主与界面都不代读、不转发。
实连 CTP 需 --features ctp-native(默认关,日常构建不碰 C++)。
界面框架(v4,BD-UI-27/28;0.2.0 BD-UI-31 体验轮;0.2.2 BD-UI-32 字号与独立窗):
全局字号 16px 面(apply_ui_style);菜单栏(运维|账户|查询合约
一键直达弹窗,帮助保留菜单)→ 行情带(全宽、无题字,tick 唯一源,按交易所二级
tab,单击行带入下单面板,双击行弹 K线窗)→ 交易带(左下单面板无题字 9 字段 +
「自动开平」勾选 + 委托/全撤 + 盘口无题字;右 2×2 监控格「委托|未成交」「成交」「持仓」
「资金|日志」,列面逐值抄录 Python 蓝图:委托 17 列含名称/交易所/类型/来源,
成交 12 列(方向上色),持仓 16 列;撤单 = 行钮或双击委托行);全表行选中跳色
(行内任意格单击 = 选中,悬停淡底,每表一行;行情带选中 = 当前合约;行情带
盘口四列带入带方向:买1 价/量 → 卖,卖1 价/量 → 买,价格列顺带填价,其余列
方向保持默认)——
查询合约窗与 K 线窗是独立 OS 窗(原生最小化/最大化/关闭,可拖出主窗放
屏幕任意处;不支持多窗的后端自动回退主窗内弹窗);运维/账户窗同为独立 OS 窗
(BD-UI-33 四窗一型),都不占主界面 tab。默认窗 1280×860。
表头固定与表头带(0.2.5/0.2.6,BD-UI-34;0.2.27,BD-UI-41 补 chrome):六张表
(行情带/委托/成交/持仓/日志/查询合约)表头固定——纵向滚动表头钉顶,横向滚动表头同移
(单 grid 列对齐 + 滚动区顶部覆盖带纯 painter 重画);空表表头照常在场。表头带照
qdarkstyle QHeaderView::section:带底 + 1px 下边线,表头字号比正文小一档
(Small 14 vs Body 16,Python 侧正是表头 13px < 正文 ≈14.7px);浮动窗里三张短表
(账户清单/运维插件表/服务目录)走 header_band 同一配色,服务目录本轮补上表头。
网格线只给查询合约表(Python 侧只有合约表开网格,交易表 setShowGrid(False));
斑马纹改跟主题(visuals.striped,四套主题都是 false)。日志格从「monospace 行 +
定高 180px」换成带「时间/信息」表头的表 → 窗口最大化它跟着长。页签照
QTabBar::tab:top:未选中也有头底,选中多一条 3px 下划线;「成交」「持仓」两格补
单 tab(Python 四个区全是 QTabWidget)。K 线窗打开即最大化,
ESC 快捷关闭。菜单栏「主题」钮一键循环五套配色(金融深色默认/egui深色/
egui浅色/Qt灰白/Qt深色),语义色(多红空绿等)跨主题恒定。「Qt深色」(0.2.26,BD-UI-40)
复刻 Python/PySide6 版的黑色主题 QDarkStyle 3.2.3:底 #19232D、按钮 #455364→#54687A→#60798B、
选中 #346792、圆角 4px、描边 1px。
薄下单者(0.1.1,BD-UI-30):下单/撤单不直发网关——全部走 oms.submit_order
五段管线(拆单/风控/逐腿发送/记账)与 oms.cancel_order(守卫不可绕过);
「自动开平」勾选 = 拆单四态的 Auto/None 逐请求开关(风控与守卫不可旁)。
订阅两入口(订阅不在账户面板定死;一律路由到行情元账号):下单面板代码框回车即订阅(带 EX. 前缀
自动剥成裸码);菜单「查询合约」
弹窗(查询框留空 = 全部 + 勾选 + 订阅选中)。合约流由 ek-ctp 登录后自动查询,
UI 只收不催。多账号面只有一个行情元账号(账户面板指定,已装配后锁定),
订阅只发它 —— 纯 TD 账号收到订阅会静默成功却永远不来 tick,所以路由在界面侧定死。
账户状态列与『断开』(0.2.19,随 ek-ctp 0.9.0):账户面板状态列是两段——
实例装配位(svctl.list 在场)+ 登录态(每 2 秒向每个已装配且在场的账户 ask 一次
{gw}.status 折出来):已装配·在线 / ·掉线 / ·登录失败 / ·查询断供 / ·已断开 /
·登录态未知。界面只认网关的 td_logged_in(纯行情账户认 md_logged_in),
「句柄已建」不当「在线」用、"从未回报过"不当"0 秒前回报过"用;
「查询断供」= 查询连续被拒达 3 次 或 资金回报超 30 秒未更新(阈值在界面,可覆盖)。
有话可说的行在面板底部给一句 状态细节 <派生名>:<原因>(带次数/秒数)。
『断开』走 {gw}.disconnect = 停会话(实例、配置、订阅、状态计数全留,『连接』可恢复);
『移除』走 svctl.remove = 停实例 —— 两个动作两条口,不共用。
三条口径写进界面(0.2.20,随 ek-ctp 0.9.1):① 收录勾选只管该网关自己收录并上抛的合约,
公用合约表 = 在场各网关的并集,改勾选须『连接/重试』才下发(面板底部与配置弹窗各写明一次);
② 运维窗不再对账户清册里的实例提供『移除』/『重注入』 —— 那一格改写成「起停归『账户』面板
(带撤单守卫)」,实例仍列在表里;清册外的 ctp_* 实例仍留这条出口;③ 日志溢出时同一行接上
「日志窗是窗口不是历史 —— 登录/掉线/查询被拒看状态列与状态细节,别回扫这里」。
状态细节另接 ek-ctp 0.9.1 的分项:合约查询被拒 N 次(与断供句并存,不重复点名)。
「从未到手」也会超时(0.2.21):「查询断供」三条判据 —— 连续被拒达 3 次 / 距最后一次资金回报
超 30 秒 / 登录后超 30 秒资金回报一次都没到手(实连读数照出来的:登录着、零被拒、None 一直不变
的账户,原来永远显示「在线」)。刚登录几秒不算;真到手即回在线。
中文渲染(BD-UI-26):启动时自动从系统字体目录装载 CJK 回退字体
(simhei 等,只收纯 .ttf/.otf);装载证据行 stderr 可 grep
([ek-ui] CJK 回退字体已装载: <path>)。候选全空时中文显形为豆腐块并
在 stderr 警告——属环境侧字体缺失,非界面缺陷。
快速开始
cargo run # 无参:dm + oms + ui demo 窗(网关经运维窗 svctl 激活)
cargo run -- --pick # 启动器:勾选插件 → 写清单 → spawn 子进程 → boot-wait
use StationConfig;
let mut cfg = demo; // = dm + oms
cfg.plugins.push;
run_station_ui?;
launcher 协议(bin级):ek-ui --from <清单> --ready-file <标记>,start 成功即写
ready\n;ek-station --from ... 同 mate(清单由 --pick 窗生成)。
ek-ui --pick 走选窗 → 工作线程 spawn(30s 就绪上限;失败退 2,成功子进程分离脱管)。
自动化测试(S1b 起,人工核查 0 项)
- L1:
tests/ui_state.rs—— 环形日志/快照/revision/停止位(线程面状态机)。 - L2:
render_body(ctx, &UiShared)单渲染入口(真实 App 与测试共用;面板组合 在入口内,BD-UI-29:菜单/行情带 TopBottomPanel + 下单侧栏 SidePanel + CentralPanel 2×2 格 + 弹窗最后)。 - L3:
tests/ui_kittest.rs(25 钉)——egui_kittest官方建构(ctx 级build, render_body 自开顶层面板):AccessKit 节点断言、清空日志就地交互、下单面板入列(委托钮/坏价红字/全撤扇出)、代码框回车 订阅(s20:focus+type_text+key_press 全链)、委托行双击撤单(s11:建构用with_step_dt(0.1),kittest 每事件一帧口径,BD-UI-28⑥)、行情带单击带入 下单面板、查询合约窗勾选订阅、菜单开窗(运维/账户/查询合约)、行情带 tab 切换、静态布局首帧快照(s3 含 BD-UI-29 结构钉:右列贴边不裁切/底行沉底 无死区/侧栏在左/两列等宽随窗分配)与满表视觉钉 s21(委托 17/成交 12/ 持仓 16 列,布局泄漏与列面回归即快照 diff 爆红;tests/snapshots/, 1280×860 基线,更新基线用$env:UPDATE_SNAPSHOTS='true'后跑cargo test;点击一律click_accesskit(坐标点击只打可见钮,横向滚动面外控件用 AccessKit 动作),建构面统一harness_for()实窗尺寸,见 BD-UI-23/27/28/29)。 - 装配链:
tests/ui_runtime.rs—— ui 工厂可装配、eTimer 1s 快照回路、 关窗协议(stop 位 → 观察线程 close_all → 全体 on_stop)。 - 行情面:
tests/ui_market.rs—— DM 金样本回放逐位、回灌闭环(帧统计三钉)。 - 交易面:
tests/ui_converter_chain.rs(3 钉;0.2.10 BD-UI-38 改写)—— oms 五段 管线全链(Auto 拆 2 腿今先/冻结/账本清零/parent 聚合)、mode None 单腿旁路、 手数闸拒 = 网关零接触;网关位 = 测试本地 "ctp" 受理夹具(受理形制忠实 ek-ctp, 成交按 CTP 回报行直发注入)。纸面网关tests/ui_sim.rs(9 钉)与 ek-paper 引用 已随 sim 退场撤除(网关档案见 ek-paper, 历史 BD-UI-36;退场裁定 BD-UI-38)。 - 运维面:
tests/ui_ops.rs—— 命令队列往返/两步确认/检疫检测(u0–u2)+ 移除重启环与未知工厂拒装(t0/t1)。 - 启动器:
tests/launch.rs+tests/pick_ui.rs—— spawn/ready 协议、退出码、 选窗勾选写清单与派生。 - 字体面:
src/fonts.rs单测 f0(22 常用汉字 has_glyph)+ kittest s16 汉字密集页 快照(BD-UI-26 乱码根因钉;无 CJK 候选环境显形失败,属设计)。 - CTP 配置面:
tests/ui_ctp.rs—— ui→askctp.configure/ctp.subscribe总线 闭环(空地址守卫日志、服务目录 5 口、校验拒面、ctp 不在场失败不炸链)+ kittest s13(手工表单入列逐位、窗面无订阅字段口径)。 - CTP 实连(手工):
tests/ui_ctp_live.rs——--features ctp-native+--ignored才跑;12 步全流程(判据三态 PASS/OBSERVE/FAIL,账号 env 手工注入)。
门禁
powershell -ExecutionPolicy Bypass -File scripts/gate.ps1
五闸:fmt --check / test / clippy -D warnings / doc / check-package(strict)。
依赖纪律
ek 生态件一律 crates.io 装版引用(运行时七件直接依赖:core/event/data/dm/ctp/oms/station;
0.1.1 起运行时还经 station 传递吃到第八件 ek-risk 0.1.x(风控闸装配,含多账号面的合约预检闸,见 CHANGELOG);
dev-dep converter 0.1.1 已随 0.1.1 退役——拆单器入驻 oms 管线,见 CHANGELOG);
三方库只在本 crate(eframe = egui = egui_kittest = 0.33.3 四件套锁定,见 DESIGN BD-UI-7)。
remote 授权(2026-10-17 建仓):https://cnb.cool/enkeep/ek-ui(本仓)与
https://cnb.cool/enkeep/ek-station;此前为纯本地提交(方案 §3 双启动矩阵:
ek-dm 同域纪律)。