dsh-xueqiu 1.22.2 → 1.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -135,6 +135,8 @@ The data layer is defended in depth — safe to leave open for hours:
135
135
 
136
136
  ## Changelog
137
137
 
138
+ - **1.22.4** (2026-08-26) — **Fix: switching to the minute tab crashed the whole panel** (1.22.3 regression). The double-click-to-latest cleanup used `boxRef.current.removeEventListener`, but React clears refs before running effect cleanup on unmount, so `boxRef.current` was null → TypeError → the `conversation.input.dock` slot crashed entirely, leaving only the mini badge with no way back in. Now the node is captured in a closure inside the effect. Regression-tested: K-line↔minute 4 toggle rounds + collapse/badge-reopen/re-enter detail, 0 errors.
139
+ - **1.22.3** (2026-08-26) — **Fix: K-line OHLC legend permanently drawn over the candles**. KLineChart v10 defaults `candle.tooltip.showRule` to `'always'`, painting time/OHLC/volume in the candle pane's top-left corner at all times (pixel-scan measured 1394 text pixels covering candles from y=23). Changed to `'follow_cross'` (shown on crosshair hover, like Xueqiu) — the indicator tooltip had been disabled but the candle's own legend was missed. Also: the chart footer promised "double-click to return to latest" but no dblclick handler existed (verified: after left-drag loaded 999 bars, double-click did nothing) — now wired to `chart.scrollToRealTime()` (verified: visible range 132→430-500). Minor: K-line date label now includes the year (a 500-bar daily range showed "08-26 ~ 08-24", reading like time travel across two years); the detail-page hero price/change now follows the quote's actual decimal digits (HK 00700 previously 440.40 → 440.4).
138
140
  - **1.22.2** (2026-08-24) — **Fix: MA / avg-price lines landed in sub-panes instead of overlaying the main chart**. KLineChart v10's `createIndicator('MA')` opens a new pane by default — MAs were not on the candle pane (squeezed to 72px) and the minute chart's avg/prev-close lived in their own sub-pane. The fix passes `{ name, paneId: 'candle_pane' }` to explicitly overlay the main pane (pane id confirmed from engine source). Result: candlestick pane at 173px with MA5/10/30/60 overlaid (volume remains the only sub-pane); minute chart is a single pane with price + avg + prev-close overlaid, matching Xueqiu's layout. Also a Xueqiu-inspired detail-page restyle: hero quote header (large red/green price + change + pct), lighter 16-stat grid (tinted cards, tabular numerals), accent bar on card titles, theme-tinted active states for mode/period buttons, chart height 264→300px, harmonized 4-color MA palette, and high/low duplicate price marks disabled.
139
141
  - **1.22.1** (2026-08-24) — chore: drop peerDependencies to silence install warnings; static smoke script falls back to local `npx dsh` (dsh not on PATH under prepublishOnly).
140
142
  - **1.22.0** (2026-08-24) — **K-line / minute charts migrated to the KLineChart v10 engine** (canvas rendering, built-in light/dark theming): candles + volume + MA overlays + crosshair legend across 7 periods (5m/15m/30m/60m/day/week/month); wheel zoom, drag pan, and auto-fetch of earlier history on left-drag (500 bars per fetch); minute chart as a price-colored area with avg line and prev-close baseline.
package/README.md CHANGED
@@ -190,6 +190,12 @@ dsh-xueqiu/
190
190
 
191
191
  ## 📋 更新日志
192
192
 
193
+ - **1.22.4**(2026-08-26)
194
+ - 修复:**切分时整个面板崩溃消失**(1.22.3 回归)。双击回最新的清理函数里用了 `boxRef.current.removeEventListener`,但 React 卸载组件时先清 ref 再跑 effect 清理,此时 `boxRef.current` 已是 null → 抛 TypeError → `conversation.input.dock` 槽位整体崩溃,只剩自选股小徽章且无法重开。改为 effect 内闭包捕获节点。回归:K线↔分时来回 4 轮 + 收起/徽章重开/再进详情,0 报错。
195
+ - **1.22.3**(2026-08-26)
196
+ - 修复:**K线 OHLC 图例常驻压蜡烛**。KLineChart v10 默认 `candle.tooltip.showRule: 'always'` 把 time/open/high/low/close/volume 永久画在蜡烛区左上角(像素级实测 1394 个文字像素自 y=23 起覆盖蜡烛)。改为 `follow_cross`(十字光标悬停才显示,与雪球一致),此前只关了指标 tooltip 漏了蜡烛自身的。
197
+ - 修复:**"双击回最新"标签承诺无实现**。图表下方文案写了"双击回最新"但代码没有 dblclick 处理(实测左拖加载 999 根后双击无反应)。现监听容器 dblclick → `chart.scrollToRealTime()`(实测可视区 132→430-500 回到最新)。
198
+ - 细节:K线日期标签补年份(500 根日K时"08-26 ~ 08-24"像时间倒流,实际跨两年;现显示"2024-08-02 ~ 2026-08-25");详情页 hero 现价/涨跌额按现价实际小数位显示(港股 00700 此前 440.40 → 440.4)。
193
199
  - **1.22.2**(2026-08-24)
194
200
  - 修复:**K线均线 / 分时均价误落附图**。KLineChart v10 的 `createIndicator('MA')` 默认给指标新开 pane——均线不在蜡烛主图上(主图被挤到 72px),分时均价/昨收也在独立附图。须传 `{ name, paneId: 'candle_pane' }` 显式叠加到主图(pane id 从引擎源码确认)。修复后:K线主图 173px 蜡烛+MA5/10/30/60 叠加、附图仅成交量;分时只剩一张主图(分时曲线+均价+昨收全部叠加),与雪球布局一致。
195
201
  - 样式:**详情页参考雪球重排版**——顶部行情主标题(大号红/绿现价 + 涨跌额 + 涨跌幅,如 `1304.66 +31.83 +2.50%`);16 格 stat 卡片更轻盈(浅底/圆角/等宽数字/标签次要色);卡片标题左侧主题色强调条;K线/分时与周期按钮选中态改主题色 tint 填充;K线画布 264→300px;MA 均线和谐四色(蓝/橙/紫/青);关闭最高/最低点重复标注(消除窄图顶部杂乱数字)。
package/dynamic/client.js CHANGED
@@ -232,7 +232,7 @@ return {
232
232
  if (!ts) return ''
233
233
  const d = new Date(Number(ts))
234
234
  function p(n) { return n < 10 ? '0' + n : String(n) }
235
- return p(d.getMonth() + 1) + '-' + p(d.getDate())
235
+ return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate())
236
236
  }
237
237
  function fmtFullDay(ts) {
238
238
  if (!ts) return ''
@@ -355,6 +355,8 @@ return {
355
355
  upBorderColor: pal.up, downBorderColor: pal.down, noChangeBorderColor: pal.text,
356
356
  upWickColor: pal.up, downWickColor: pal.down, noChangeWickColor: pal.text
357
357
  },
358
+ // OHLC 图例:十字光标悬停才显示(v10 默认 always 常驻左上角,压蜡烛且与坐标轴数值重复)
359
+ tooltip: { showRule: 'follow_cross' },
358
360
  priceMark: {
359
361
  // 关闭最高/最低点重复标注(窄图时易与坐标轴重叠成杂乱数字),保留最新价标
360
362
  high: { show: false }, low: { show: false },
@@ -476,7 +478,15 @@ return {
476
478
  chart.createIndicator({ name: 'MA', paneId: 'candle_pane' })
477
479
  chart.createIndicator('VOL')
478
480
  chart.setOffsetRightDistance(16)
479
- return h.dispose
481
+ // 双击回最新(标签文案承诺过;kline v10 自带 dblclick 仅做空十字,需手动 scrollToRealTime)
482
+ const box = boxRef.current
483
+ const onDbl = function () { try { chart.scrollToRealTime() } catch (e) { /* 忽略 */ } }
484
+ box.addEventListener('dblclick', onDbl)
485
+ return function () {
486
+ // 卸载清理时 boxRef.current 已被 React 置 null(切 tab 触发,曾致槽位整体崩溃),须闭包捕获节点
487
+ try { box.removeEventListener('dblclick', onDbl) } catch (e) { /* 忽略 */ }
488
+ h.dispose()
489
+ }
480
490
  }, [])
481
491
 
482
492
  if (noLib) return klcNoLib()
@@ -1022,8 +1032,14 @@ return {
1022
1032
  ])
1023
1033
  })
1024
1034
  // 行情主标题:现价 + 涨跌额 + 涨跌幅(参考雪球 ¥18.23 +0.14 +0.77% 层级)
1035
+ // 精度取现价自身小数位(港交所 1 位等),涨跌额同精度
1036
+ const qDigits = (function () {
1037
+ const m = String(q.current == null ? '' : q.current).split('.')
1038
+ const d = m[1] ? m[1].length : 0
1039
+ return Math.max(2, Math.min(4, d))
1040
+ })()
1025
1041
  const chgRaw = (q.current != null && q.last_close != null) ? (Number(q.current) - Number(q.last_close)) : null
1026
- const chgStr = (chgRaw != null && isFinite(chgRaw)) ? (chgRaw > 0 ? '+' + fmt(chgRaw) : (chgRaw < 0 ? '-' + fmt(Math.abs(chgRaw)) : '0.00')) : ''
1042
+ const chgStr = (chgRaw != null && isFinite(chgRaw)) ? (chgRaw > 0 ? '+' + fmt(chgRaw, qDigits) : (chgRaw < 0 ? '-' + fmt(Math.abs(chgRaw), qDigits) : fmt(0, qDigits))) : ''
1027
1043
  const priceCls = colorOf(q.percent)
1028
1044
  return el('div', null, [
1029
1045
  el('div', { key: 'h', className: 'xq-detail-head' }, [
@@ -1032,7 +1048,7 @@ return {
1032
1048
  el('span', { key: 'c', className: 'xq-detail-code' }, view),
1033
1049
  el('span', { key: 'sp', className: 'xq-spacer' }),
1034
1050
  el('div', { key: 'px', className: 'xq-detail-price' }, [
1035
- el('span', { key: 'cur', className: 'xq-detail-cur ' + priceCls }, fmt(q.current)),
1051
+ el('span', { key: 'cur', className: 'xq-detail-cur ' + priceCls }, fmt(q.current, qDigits)),
1036
1052
  el('span', { key: 'dl', className: 'xq-detail-delta' }, [
1037
1053
  chgStr ? el('span', { key: 'chg', className: 'xq-detail-chg ' + priceCls }, chgStr) : null,
1038
1054
  el('span', { key: 'pct', className: 'xq-detail-pct ' + priceCls }, fmtPct(q.percent))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-xueqiu",
3
- "version": "1.22.2",
3
+ "version": "1.22.4",
4
4
  "description": "雪球 mini 行情面板 — DeepSeek Harness 免登录 A股/港美股实时行情、K线(蜡烛/成交量/均线)、分时图、热榜、搜索、7x24 快讯、热议用户。嵌入式面板 + 可拖拽行情徽标,内置请求节流、TTL 缓存与 Cookie 自动续期。",
5
5
  "keywords": [
6
6
  "dsh",
@@ -263,7 +263,7 @@ exports.default = {
263
263
  if (!ts) return ''
264
264
  const d = new Date(Number(ts))
265
265
  function p(n) { return n < 10 ? '0' + n : String(n) }
266
- return p(d.getMonth() + 1) + '-' + p(d.getDate())
266
+ return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate())
267
267
  }
268
268
  function fmtFullDay(ts) {
269
269
  if (!ts) return ''
@@ -386,6 +386,8 @@ exports.default = {
386
386
  upBorderColor: pal.up, downBorderColor: pal.down, noChangeBorderColor: pal.text,
387
387
  upWickColor: pal.up, downWickColor: pal.down, noChangeWickColor: pal.text
388
388
  },
389
+ // OHLC 图例:十字光标悬停才显示(v10 默认 always 常驻左上角,压蜡烛且与坐标轴数值重复)
390
+ tooltip: { showRule: 'follow_cross' },
389
391
  priceMark: {
390
392
  // 关闭最高/最低点重复标注(窄图时易与坐标轴重叠成杂乱数字),保留最新价标
391
393
  high: { show: false }, low: { show: false },
@@ -507,7 +509,15 @@ exports.default = {
507
509
  chart.createIndicator({ name: 'MA', paneId: 'candle_pane' })
508
510
  chart.createIndicator('VOL')
509
511
  chart.setOffsetRightDistance(16)
510
- return h.dispose
512
+ // 双击回最新(标签文案承诺过;kline v10 自带 dblclick 仅做空十字,需手动 scrollToRealTime)
513
+ const box = boxRef.current
514
+ const onDbl = function () { try { chart.scrollToRealTime() } catch (e) { /* 忽略 */ } }
515
+ box.addEventListener('dblclick', onDbl)
516
+ return function () {
517
+ // 卸载清理时 boxRef.current 已被 React 置 null(切 tab 触发,曾致槽位整体崩溃),须闭包捕获节点
518
+ try { box.removeEventListener('dblclick', onDbl) } catch (e) { /* 忽略 */ }
519
+ h.dispose()
520
+ }
511
521
  }, [])
512
522
 
513
523
  if (noLib) return klcNoLib()
@@ -1053,8 +1063,14 @@ exports.default = {
1053
1063
  ])
1054
1064
  })
1055
1065
  // 行情主标题:现价 + 涨跌额 + 涨跌幅(参考雪球 ¥18.23 +0.14 +0.77% 层级)
1066
+ // 精度取现价自身小数位(港交所 1 位等),涨跌额同精度
1067
+ const qDigits = (function () {
1068
+ const m = String(q.current == null ? '' : q.current).split('.')
1069
+ const d = m[1] ? m[1].length : 0
1070
+ return Math.max(2, Math.min(4, d))
1071
+ })()
1056
1072
  const chgRaw = (q.current != null && q.last_close != null) ? (Number(q.current) - Number(q.last_close)) : null
1057
- const chgStr = (chgRaw != null && isFinite(chgRaw)) ? (chgRaw > 0 ? '+' + fmt(chgRaw) : (chgRaw < 0 ? '-' + fmt(Math.abs(chgRaw)) : '0.00')) : ''
1073
+ const chgStr = (chgRaw != null && isFinite(chgRaw)) ? (chgRaw > 0 ? '+' + fmt(chgRaw, qDigits) : (chgRaw < 0 ? '-' + fmt(Math.abs(chgRaw), qDigits) : fmt(0, qDigits))) : ''
1058
1074
  const priceCls = colorOf(q.percent)
1059
1075
  return el('div', null, [
1060
1076
  el('div', { key: 'h', className: 'xq-detail-head' }, [
@@ -1063,7 +1079,7 @@ exports.default = {
1063
1079
  el('span', { key: 'c', className: 'xq-detail-code' }, view),
1064
1080
  el('span', { key: 'sp', className: 'xq-spacer' }),
1065
1081
  el('div', { key: 'px', className: 'xq-detail-price' }, [
1066
- el('span', { key: 'cur', className: 'xq-detail-cur ' + priceCls }, fmt(q.current)),
1082
+ el('span', { key: 'cur', className: 'xq-detail-cur ' + priceCls }, fmt(q.current, qDigits)),
1067
1083
  el('span', { key: 'dl', className: 'xq-detail-delta' }, [
1068
1084
  chgStr ? el('span', { key: 'chg', className: 'xq-detail-chg ' + priceCls }, chgStr) : null,
1069
1085
  el('span', { key: 'pct', className: 'xq-detail-pct ' + priceCls }, fmtPct(q.percent))