Skip to content

v0.11.0-alpha.8

Choose a tag to compare

@github-actions github-actions released this 01 Oct 15:26
· 234 commits to main since this release

相比 v0.11.0-alpha.7 的变更 / Changes since v0.11.0-alpha.7

✨ 新功能 / Features

  • 第三方渲染层注册(破坏性): 新增 Controller 级 Layer 操作(注册、查询、移除、启用开关、请求重绘)与插件渲染能力,注册名开放为第三方字符串,同一 Controller 与插件共用 ChartRendererAccess,Scene 成为已挂载 Layer 的释放所有者。
  • Third-party renderer registration (breaking): Adds Controller-level Layer operations (register, query, remove, enable toggle, request render) plus plugin render capabilities, opens registration names to third-party strings, shares one ChartRendererAccess between controllers and plugins, and makes Scene the release owner of mounted Layers.
  • 价格轴滚轮缩放与光标价格锚点: 价格轴画布位于绘图区之外,宿主滚轮监听收不到轴上事件;改为 core 按事件目标分流,以 PriceScale 在原生刻度空间补偿中心位移实现锚点缩放,线性、对数、百分比刻度共用同一套锚点规则,Chart.scalePrice 新增可选锚点参数。
  • Price axis wheel zoom with cursor anchor: Routes wheel events by target inside core and compensates the center shift in PriceScale's native scale space, so linear, logarithmic, and percent scales share one anchor rule; Chart.scalePrice gains an optional anchor parameter.
  • 统一可移动的价格轴设置菜单: 将价格轴控制项收敛为向上展开的菜单,含当前模式勾选与左右侧放置,重置时按可见高低点重算纵向范围并保留所选刻度与范围模式;移除图表设置弹窗中的轴控制项。
  • Unified movable price axis settings menu: Consolidates axis controls into an upward-opening menu with current-mode checkmarks and left/right placement, refits the vertical range to visible highs and lows on reset while preserving the selected scale and range mode, and drops axis controls from the chart settings dialog.
  • 价格轴悬浮快捷切换刻度: 鼠标悬停价格轴时在轴按钮上方显示 A/L/% 快捷切换,复用菜单命令,指针移出即隐藏。
  • Hover axis-type shortcuts: Shows A/L/% shortcuts above the price axis button on hover, reusing the existing menu commands and hiding again when the pointer leaves the axis.
  • 可选主题预设: 新增可选主题预设(配色板 + 视觉主题),点击即应用并持久化,图表在弹窗保持打开时重渲染;预设只调整配色,不改其他设置。
  • Selectable theme presets: Adds selectable theme presets (visual palettes plus visual themes) that apply and persist on click and re-render the chart while the dialog stays open, adjusting colours only.
  • 绘图模板画布浮条: 在画布浮条直接保存与应用图元样式模板,共用既有的按类型 IndexedDB 模板契约,应用模板只写入共有颜色字段并经 updateBatch;单选时才提供保存。
  • Drawing template toolbar menu: Saves and applies drawing style templates from the canvas toolbar, reusing the per-kind IndexedDB template contract, writing only shared colour fields through updateBatch, and offering save for a single selection.
  • 图元复制: 新增画布工具栏按钮与 drawings_copy Agent 工具,通过同一 core 入口复制单选或多选图元;副本保留类型、样式、标签与参数,获得全新 ID 并可见未锁定,替换选中以便直接拖动,按时间轴 16px、价格轴 48px 偏移且近边缘翻转,整组记录为一步撤销。
  • Drawing copy: Adds a canvas toolbar button and a drawings_copy agent tool that copy the current single or multi selection through one shared core entry, keeping kind, style, labels, and params, offsetting 16px right and 48px down with edge flipping, and recording the batch as one undo step.
  • 图元显隐与批量删除: 新增图元显隐开关(含 Agent 历史联动)以及批量删除与虚线框选图标的工具栏入口,替换原先的删除入口。
  • Drawing visibility and bulk deletion: Adds drawing visibility toggles wired into agent history plus toolbar entries for bulk deletion and a dashed box-selection icon.
  • 连续绘制开关与磁吸工具栏(破坏性): 左侧工具栏磁吸旁新增连续绘制开关,完成图元时保留当前工具;磁吸模式三档接入左工具栏,强磁吸改为无条件取最近 OHLC 价格,移除 MAGNET_RADIUS_STRONG。
  • Continuous drawing toggle and magnet toolbar (breaking): Adds a continuous-drawing toggle beside the magnet switch so finishing a drawing keeps the current tool, wires the three magnet modes into the left toolbar, and makes strong snapping unconditionally pick the nearest OHLC price, removing MAGNET_RADIUS_STRONG.
  • K 线收盘倒计时按交易时段推算: 倒计时改为解析当前品种注册的交易时段,日内周期按交易区间步进并跳过午休、收盘截断最后一根,日线结束于当日收盘;新增 showLastPriceCountdown 设置项(默认开启),关闭后不再派生文本并停止秒级刷新。
  • Session-aware bar countdown: Resolves the registered market session so intraday bars step across trading intervals, skip breaks, and clip at the close while daily bars end at the last session close, and adds a showLastPriceCountdown setting (on by default) that stops deriving text and second-level refreshes when disabled.
  • 未来区交易日历与时间外推: 新增 projectTradingTimestamp 纯函数按 MarketSessionConfig.tradingDays 外推未来时间,未来区时间轴刻度与纵向网格由日历驱动,无日历时以 T、T+1、T+2 相对索引占位,十字线与横竖绘图锚点共用同一外推入口;MT5 会话补注册,跨视图缩放锚点跟随指针槽位。
  • Trading-calendar future space: Adds the projectTradingTimestamp pure function driven by MarketSessionConfig.tradingDays, renders future-region ticks and vertical grid from the calendar, falls back to T/T+1/T+2 relative slots without one, shares the extrapolation entry across crosshair and drawing anchors, registers the MT5 session, and anchors zoom to the pointer slot across views.
  • 未来区可滚动与十字线外延: 指针越过最后一根 K 线时十字线按尾部槽位步长吸附未来槽位,滚动上限按未来区屏数放行,缩放后不再被拉回数据右缘。
  • Future-space panning and crosshair extrapolation: Lets the crosshair snap to future slots by trailing step, opens scroll bounds by the future screens, and stops zoom from snapping back to the data edge.

🐛 Bug 修复 / Fixes

  • 共享 GPU 后端绘制区域错绑: ChartRenderer 在构建帧时依次调用所有 Pane 的 beginFrame 后才 scene.paint,共享 GPU 后端绘制时仍绑定最后一个 Pane,导致主图 K 线被画到副图区域;FramePaint 改为携带 SurfaceRegion 与后端,由 Scene 在分发每批次图层前绑定区域并传递 clear 标志,Overlay 批次保持 clear: false。
  • Pane region binding for shared GPU backends: FramePaint now carries a SurfaceRegion and the backend, letting Scene bind the region before dispatching each batch and pass the clear flag, keeping overlay batches at clear: false.
  • 拖拽图元时跳帧: 帧去重只比较正式文档,导致拖拽过程被判定为未变化而跳帧,只有抬起后才跳到落点;每个 Pane 增加正式图元画布,正式层按 committed 投影复用几何与像素,会话层消费拖拽覆盖、预览与框选。
  • Continuous repaint while dragging drawings: Adds a committed drawing canvas per pane so the formal layer reuses projection and pixels while the session layer consumes drag overrides, previews, and marquee selection.
  • 切换品种后价格轴停在旧区间: 锁定价格对 K 线比例时切换品种会沿用上一个品种的手动范围快照与纵向变换;现在主品种身份变化时由 kernel 原子提交品种并清空手动范围,新行情首个有效帧据此重算自动范围再继续锁定。
  • Locked price range on symbol switch: Atomically commits the new symbol and clears the manual range when the primary symbol identity changes, refitting the automatic range on the first valid frame.
  • 主图图例配置失效: Vue 图例配置调用了已移除的 updateRendererConfig,图表挂载即抛 TypeError 中断;改为经 updateOptionsFacade 写入 chart options,由 optionsState 统一持有,两个图例 Layer 每帧读取配置快照。
  • Main legend configuration: Drives main-legend configuration through chart options instead of the removed updateRendererConfig, so both legend layers read one options snapshot per frame.
  • 最新价标签未按刻度格式化: 标签硬编码价格文本,切到百分比刻度后仍显示价格;改为与刻度、十字线价签共用同一显示语义解析器。
  • Last price label follows the active scale: Formats the last price label with the shared display-semantics resolver used by ticks and the crosshair tag.
  • 未归一化品种被判数据源不支持: unknown 的 assetClass(如 GoTDX 恒指 HSI)不在源声明范围内,整源被判不支持,Router 在请求前抛 SourceRoutingError;新增唯一判定入口 isFilterableAssetClass,registry、router 与 protocol 三处筛选点统一复用。
  • Unknown asset class filtered out: Treats unknown asset classes as unfiltered through a single isFilterableAssetClass predicate shared by registry, router, and protocol, so not-yet-normalized symbols no longer fail routing.
  • 十字线标签对比度不足: 三处十字线标签使用通用 label token,深色下底色近黑导致标签糊在轴背景;回归专用的 crosshairLabelBg / crosshairLabelText(对比度 8.79:1),浅色模式不变。
  • Crosshair label contrast: Renders all three crosshair labels from their dedicated tokens, lifting dark-mode contrast to 8.79:1.
  • MT5 未来区时间外推整体失效: 内建会话注册表缺少 MT5,品种会话解析抛错使 futureSession 恒为 null;补注册 MT5 -> FOREX_MARKET_SESSION(24/5 主场景)。
  • MT5 trading-calendar extrapolation: Registers the MT5 session against the forex (24/5) profile so future-region extrapolation, crosshair tags, and grid no longer break on the MT5 link.
  • 水平图元锚点携带 futureOffset: completeDrawing 无差别传 { timestamp, futureOffset, price },与水平锚 futureOffset?: never 的契约冲突;改为水平命令仅传 price,未来区落点可按价格创建水平线。
  • Horizontal anchors carried futureOffset: Strips futureOffset from horizontal commands so future-slot drops create horizontal lines by price.
  • 绘图时十字线消失: 绘图预览先消费指针移动导致十字线被隐藏;改为绘图期间保留悬停更新并以虚线渲染两条标线。
  • Crosshair hidden while drawing: Keeps hover updates during drawing and renders both guides dashed so placement stays visible.
  • 默认 K 线提示框空白: 提示框挂载即渲染,而可见性只在订阅内解析(订阅时不触发);改为初始隐藏、setup 时求值一次,数据变化时重新求值。
  • Blank default K-line tooltip: Starts hidden, evaluates visibility once at setup, and re-evaluates on data changes.
  • Android WebView 不跟随系统主题: 补充系统主题跟随判定,使 WebView 内嵌场景也能随系统深浅色切换。
  • Android WebView system theme: Follows the system colour scheme inside Android WebView hosts.
  • 下拉触发器文字下沿被裁切: dropdown__value 同时使用 line-height: 1 与 overflow: 隐藏,省略号裁切区截断了字体下沿笔画;改为 1.4。
  • Dropdown trigger text clipping: Raises the trigger line-height to 1.4 so the ellipsis box no longer cuts the glyph descenders.
  • 领域错误码常量缺失: SCALE_/FOOTPRINT_/AVWAP_/INDICATOR_/HEATMAP_/MTF_/CHART_TYPE_/REPLAY_/DEPTH_ 错误码引用了 errors.ts 未导出的常量对象,导致 core 无法通过类型检查;补齐常量并统一文件格式。
  • Missing domain error code constants: Adds the missing error-code constant objects referenced by scale, footprint, AVWAP, indicator, heatmap, MTF, chart type, replay, and depth call sites.

🏗️ 架构与重构 / Architecture & Refactoring

  • Layer 成为 Scene 唯一绘制契约(破坏性): Layer<TFrame> / Scene<TFrame> 泛型化,Layer.pane 用具体 paneId 取代丢弃 id 的 paneRole,Layer.paint 直接接收帧上下文;pane 匹配、可见性、role 过滤、z 排序与逐 Layer 异常隔离上移到 createScene,Scene.paint(frame) 一次画完所有 pane。
  • Layer as the single Scene paint contract (breaking): Generic Layer<TFrame> / Scene<TFrame>, concrete paneId instead of paneRole, frame context passed directly to Layer.paint, and pane matching, visibility, role filtering, z-ordering, and per-Layer error isolation moved up into createScene.
  • 退役 RendererPlugin(破坏性): 删除 RendererPlugin / RendererPluginWithHost、RendererPluginManager、updateRendererConfig 与 createLayerFromPlugin / wrapRendererAsLayer;约 70 个渲染器工厂与指标 scale 统一返回原生 Layer<RenderContext>,指标接缝集中到 indicatorRendererLayer.ts,状态统一经 context.indicatorStateReader 读取。
  • Retire RendererPlugin (breaking): Removes the RendererPlugin contract and its manager/adapter layer, converting roughly 70 renderer factories plus indicator scales to native Layer<RenderContext> with a single indicatorRendererLayer.ts seam and injected state reads.
  • 未来区空间由视口派生(破坏性): 移除 futureScreens 图表选项,改为响应式几何统一派生内容宽度、滚动上限与未来槽位数,并保留末尾两个数据槽位,使平移无法把视口整体移入未来区;默认未来区由 3 屏收窄为 1 屏。
  • Viewport-derived future space (breaking): Removes the futureScreens chart option in favour of reactive geometry that derives content width, scroll bounds, and future slot counts while retaining the final two data slots, and narrows the default future area from three screens to one.
  • 图表视图切换集中化(破坏性): 周期与对比视图经同一决策解析,使对比命令保留分时模式;重写几何、价格轴与指针编排并移除影子状态,Chart.applyRenderState 改接受 zoomLevel 或 kWidth/slotWidth,Chart.setSymbols 拒绝多个主品种(对比改用 setComparisonSpecs)。
  • Centralized chart view transitions (breaking): Resolves period and comparison views through one decision so comparison commands preserve timeshare mode, rewrites geometry, price-axis, and pointer orchestration, and changes Chart.applyRenderState to accept zoomLevel or kWidth/slotWidth while setSymbols rejects multiple primary symbols.
  • 命中测试几何归入 foundation/geometry(破坏性): 新增业务无关的 foundation/geometry 作为 2D 值类型与纯谓词的唯一归属,替换绘图、marker、自定义 marker 形状、K 线/窗格判定与框选各自重写的 point-in-circle、AABB、两点成矩形与线段/矩形求交;ScreenPoint 更名为 Point 并下沉,engine/drawing 不再导出 ScreenPoint。
  • Hit-test geometry in foundation/geometry (breaking): Adds a business-agnostic foundation/geometry as the single home for 2D value types and pure predicates, rewiring the duplicated hit-test kernels and renaming ScreenPoint to Point.
  • 绘图模板领域归入 core: 模板读写(types/impl/codec + IndexedDB store)从 Vue 层的两套并存实现收敛到 core,模板列表按「仓库实例 + 图元类型」共享为唯一状态源,样式与文本位置解析拆为 resolveTemplateStyle 与 resolveTemplateLabel,菜单行操作抽到 DrawingTemplateMenu 供画布浮条与设置弹窗共用。
  • Drawing template domain in core: Moves template persistence into core behind one shared state source, splits style and label resolution, and extracts DrawingTemplateMenu for both the canvas toolbar and the settings dialog.
  • Provider 模块语义分层: 数据层按 types.ts + impl/ 布局重组,并将 packages/core/src/data 的硬编码字符串替换为具名常量(AUTO_SOURCE_ID、LATEST_TRADING_DATE、OLDER_DATA_STATUS.EXHAUSTED、V1_ENDPOINTS、JSON_HEADERS、CN_SESSION_ID)。
  • Provider module semantic layout: Restructures the data layer into the types.ts + impl/ layout and replaces magic strings in packages/core/src/data with named constants.
  • 内建数据源注册单一真源: 内建源清单集中到 core(provider/sources/index.ts),以 market-data/sources/ 语义子路径与逐源深导入暴露,取代 dist 路径通配导出;web-component 入口改为强引用内建源,避免被 sideEffects: false tree-shake 掉,并补静态 capabilities 让无头引导不再死锁。
  • Single-source builtin provider registration: Centralizes the builtin source list in core behind semantic subpaths, makes the web-component entry force-import builtin sources so tree-shaking cannot empty the registry, and declares static capabilities to unblock headless bootstrap.
  • 绘图工具与磁吸常量集中化: 从绘图契约发布 DrawingTool 与 MagnetMode 表并派生类型,交互层、工具表与 Vue 工具栏的运行时比较点统一消费。
  • Centralized drawing tool and magnet constants: Publishes DrawingTool and MagnetMode tables from the drawing contract and derives the types from them.
  • 倒计时时间并入帧输入: 倒计时此前在 timer 延迟、帧去重版本键与 paint 内三处各自现取 Date.now();改为在 derive 开始时从可注入 Clock 读一次并随快照下发 remainingMs 与 countdownText,版本键改用派生文本,timer 由帧事务副作用阶段统一续订。
  • Countdown time unified into frame input: Reads the clock once per derive from an injectable Clock and ships remainingMs and countdownText in the snapshot, keying frame dedupe on the derived text and renewing the timer in the frame transaction's side-effect phase.
  • 帧内容版本化: ChartRenderer 在帧事务 derive 阶段按值比较(Object.is)主层与交互层内容版本,命中即跳过 prepare、清屏与绘制;仅交互层变化时复用缓存几何只重画 overlay,主层像素保留。WebGL 上下文启用 preserveDrawingBuffer 保证跳帧期间可见内容持续显示。
  • Frame content versioning: Compares primary and interaction layer content versions by value in the derive phase and skips prepare, clear, and paint on a hit, reusing cached geometry to repaint only the overlay, with preserveDrawingBuffer enabled for WebGL.
  • Vue 组件逻辑抽取: 将 KLineChart.vue 内联的默认提示框逻辑抽为 useKLineTooltip、交互订阅抽为 useInteractionBridge,并在卸载时取消订阅与断开 ResizeObserver。
  • Vue composable extraction: Extracts the inlined default tooltip into useKLineTooltip and interaction subscriptions into useInteractionBridge, both unsubscribing and disconnecting observers on teardown.
  • 工具栏按钮共享样式: 抽出 control-button.css 统一品种选择、比较按钮与下拉触发器的尺寸、主题色、悬停、展开态、焦点环与窄屏降级,Dropdown 继续通过 --dropdown-trigger-* 支持主题定制,工具栏阴影改由 UI token 派生。
  • Shared toolbar button styles: Extracts control-button.css as the single definition of toolbar control appearance while keeping the --dropdown-trigger-* theming hook, and derives the toolbar shadow from a UI token.
  • BaseTooltip 统一悬浮提示: 原生 title 无法主题化且与 DropMenu 封装行为不一致,价格轴快捷按钮、Agent 头部按钮与 Dropdown 触发器改由 BaseTooltip 渲染,Dropdown 新增 ariaLabel prop。
  • Unified hover hints on BaseTooltip: Renders toolbar and agent header hints through BaseTooltip for themeable, consistent tooltips, and adds an ariaLabel prop to Dropdown.

⚡ 性能 / Performance

  • 图层几何保留与整帧跳过: 数据与视口不变时仍逐帧重建 K 线/Ichimoku 几何并全量重画;新增 retainedGeometry(按 key 保留几何并计数重建)与 retainedProjection(合成 dataRevision、展示输入、轴映射与 kLineCenters 判定复用),配合帧内容版本跳过整帧。实测几何准备 P50 由 0.3-6.9ms 降到 0.00ms,geometryBuildCount 600 → 1(18/18 场景),WebGPU ichimoku 10000 由 116.4 升至 185.2/199.7 FPS、jank 由 63.7% 降到 8.0%/0.2%。
  • Retained layer geometry and frame skipping: Retains candle and Ichimoku geometry by key and skips unchanged frames via content versions, cutting geometry preparation P50 from 0.3-6.9ms to 0.00ms, geometryBuildCount from 600 to 1, and WebGPU ichimoku jank from 63.7% to 8.0%/0.2%.
  • 未来区槽位换算收敛为单一事实来源: 未来区槽位换算抽为 futureBarCount 纯函数,三处调用点共享物理像素量纲实现。
  • Single-source future slot math: Extracts futureBarCount so the three future-slot call sites share one physical-pixel implementation.

🔧 工程 / Engineering

  • 设置页横向滚动: BaseTabs 溢出时把滚轮映射到 scrollLeft 并在边缘透传给页面,拖拽改在 document 上运行,解决窄窗口下设置弹窗无法滚动。
  • Horizontal scrolling in BaseTabs: Always maps the wheel to scrollLeft when the tab bar overflows, passes it through at the edges, and runs the drag on the document.
  • 测试夹具与断言收敛: 抽出 mountChart / makeBars / getModeHandlers / emitResize、scrollContainerStub、共享 HAND 模式挂载与两级 bar 夹具,并把图例、图表 DPR、价格轴、未来区与磁吸用例改为表驱动或复用共享工厂,移除重复断言与全部 as unknown as 强转。
  • Shared test fixtures and assertions: Extracts shared chart mounts, bar fixtures, and scroll-container doubles, converts legend, chart DPR, price-axis, future-space, and magnet cases to table-driven or shared-factory suites, and removes duplicated assertions and as unknown as casts.
  • 拆分过胖的渲染器测试: 拆分超长渲染器测试文件并共享 Layer store 替身。
  • Split over-fat renderer tests: Splits oversized renderer test files and shares a Layer store double.
  • 依赖升级: 将 vite 升级至 8.3.1、vitest 升级至 5.0.2。
  • Dependency bumps: Bumps vite to 8.3.1 and vitest to 5.0.2.
  • 格式化与导入排序: 应用 Biome 导入排序与格式化,并修正 agent-runtime 的 tsconfig path 映射写法与工具栏阴影硬编码色。
  • Formatting and import order: Applies Biome import sorting and formatting, fixes the agent-runtime tsconfig path mapping style, and replaces the hardcoded toolbar shadow colour.

📚 文档 / Documentation

  • 设计决策文档新增: 新增主题预设、资产类别 unknown 过滤、数据层模块布局、绘图复制、绘图会话图层、帧内容版本、帧倒计时时间、未来区默认屏数、未来区两数据槽位、最后价格时段倒计时、未来槽位相对标签、价格轴菜单、价格轴滚轮缩放、退役 RendererPlugin 契约、Scene 窗格区域绑定与图表视图切换等设计决策文档。
  • New design decision docs: Documents theme presets, unknown asset-class filtering, data-layer module layout, drawing copy, the drawing session layer, frame content versioning, frame countdown time, future-space defaults and data slots, session-aware last-price countdown, relative future-slot labels, the price axis menu and wheel zoom, the retired RendererPlugin contract, Scene pane-region binding, and chart view transitions.
  • 渲染管线文档补充第三方 Layer 接入: docs/rendering-pipeline.md 增补第三方 Layer 与指标注册章节,覆盖运行时契约与接入示例。
  • Rendering pipeline doc: Adds a third-party Layer and indicator registration section with the runtime contract and integration example.
  • PR 流程要求人工测试: 将贡献流程中「中间不经过 E2E 测试、视觉回归测试」改为「中间不经过用户手动测试」。
  • Manual testing in the PR flow: Requires manual user testing between contributions instead of E2E and visual regression tests.
  • 数据源与架构文档同步: 更新架构文档与 BaoStock/MT5 数据源说明以匹配 Provider 语义分层。
  • Data source and architecture docs: Updates the architecture doc and the BaoStock/MT5 data-source guides to match the provider semantic layout.