dsh-xueqiu 1.4.0 → 1.5.0

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/dynamic/client.js CHANGED
@@ -5,7 +5,9 @@ return {
5
5
  '.xq-dock{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;overflow:hidden;font-size:13px;line-height:1.45;color:var(--dsw-alias-label-primary);margin-bottom:6px;}\n' +
6
6
  '.xq-dock *{box-sizing:border-box;}\n' +
7
7
  '.xq-dock-head{display:flex;align-items:center;gap:8px;padding:7px 12px;border-bottom:1px solid var(--dsw-alias-border-l1);}\n' +
8
- '.xq-dock-body{max-height:56vh;overflow-y:auto;padding:8px 12px 10px;}\n' +
8
+ '.xq-dock-body{height:52vh;max-height:80vh;overflow-y:auto;padding:8px 12px 10px;}\n' +
9
+ '.xq-dock-resize{display:flex;align-items:center;justify-content:center;height:12px;cursor:ns-resize;user-select:none;border-top:1px solid var(--dsw-alias-border-l1);}\n' +
10
+ '.xq-dock-resize span{display:block;width:36px;height:3px;border-radius:2px;background:var(--dsw-alias-border-l2);}\n' +
9
11
  '.xq-badge{position:fixed;right:16px;bottom:64px;display:flex;align-items:center;gap:8px;padding:5px 12px;border-radius:999px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);box-shadow:0 6px 24px rgba(0,0,0,.25);font-size:11.5px;line-height:1.4;color:var(--dsw-alias-label-primary);cursor:grab;user-select:none;pointer-events:auto;z-index:1200;}\n' +
10
12
  '.xq-badge:active{cursor:grabbing;}\n' +
11
13
  '.xq-badge b{color:var(--dsw-alias-brand-primary);}\n' +
@@ -171,7 +173,7 @@ return {
171
173
 
172
174
  // ---------- 共享 UI 状态:面板开合 / 当前标签 / 徽章位置 ----------
173
175
  const ui = {
174
- open: false, tab: 'market', badgePos: null, hydrated: false,
176
+ open: false, tab: 'market', badgePos: null, dockH: null, hydrated: false,
175
177
  _fns: [],
176
178
  subscribe: function (fn) {
177
179
  this._fns.push(fn)
@@ -195,13 +197,16 @@ return {
195
197
  }
196
198
 
197
199
  const saveUi = ctx.debounce(function () {
198
- call('ui.set', { tab: ui.tab, open: ui.open, badgePos: ui.badgePos }).catch(function () { /* 忽略 */ })
200
+ call('ui.set', { tab: ui.tab, open: ui.open, badgePos: ui.badgePos, dockH: ui.dockH }).catch(function () { /* 忽略 */ })
199
201
  }, 800)
200
202
 
201
203
  // 徽章拖拽引用(实例唯一)
202
204
  let badgeDrag = null
203
205
  let badgeMoved = false
204
206
 
207
+ // 面板高度拖拽引用(实例唯一,避免组件重渲染丢失状态)
208
+ const dockResize = { active: false, startY: 0, startH: 0 }
209
+
205
210
  // ---------- K线蜡烛图(成交量 + 均线 + 十字光标/悬浮详情) ----------
206
211
  function KlineChart(props) {
207
212
  const rows = props.rows || []
@@ -856,6 +861,9 @@ return {
856
861
  if (d && d.badgePos && isFinite(Number(d.badgePos.x)) && isFinite(Number(d.badgePos.y))) {
857
862
  ui.set({ badgePos: { x: Number(d.badgePos.x), y: Number(d.badgePos.y) } })
858
863
  }
864
+ if (d && typeof d.dockH === 'number' && isFinite(d.dockH)) {
865
+ ui.set({ dockH: d.dockH })
866
+ }
859
867
  ui.set({ hydrated: true })
860
868
  }).catch(function () { ui.set({ hydrated: true }) })
861
869
  const off = ui.subscribe(function () { force(function (x) { return x + 1 }) })
@@ -866,10 +874,35 @@ return {
866
874
  }
867
875
 
868
876
  function DockPanel() {
877
+ const [, force] = React.useState(0)
869
878
  React.useEffect(function () {
870
- const off = ui.subscribe(function () { if (ui.hydrated) saveUi() })
879
+ const off = ui.subscribe(function () { if (ui.hydrated) saveUi(); force(function (x) { return x + 1 }) })
871
880
  return off
872
881
  }, [])
882
+ function onDown(e) {
883
+ if (e.pointerType === 'mouse' && e.button !== 0) return
884
+ dockResize.active = true
885
+ dockResize.startY = e.clientY
886
+ dockResize.startH = ui.dockH || defaultDockH()
887
+ try { e.currentTarget.setPointerCapture(e.pointerId) } catch (err) { /* ignore */ }
888
+ }
889
+ function onMove(e) {
890
+ if (!dockResize.active) return
891
+ const vp = viewport()
892
+ const maxH = Math.round((vp ? vp.h : 800) * 0.85)
893
+ let h = dockResize.startH + (e.clientY - dockResize.startY)
894
+ h = Math.min(Math.max(160, h), Math.min(maxH, 1200))
895
+ ui.set({ dockH: h })
896
+ }
897
+ function onUp(e) {
898
+ dockResize.active = false
899
+ try { if (e.currentTarget.hasPointerCapture(e.pointerId)) e.currentTarget.releasePointerCapture(e.pointerId) } catch (err) { /* ignore */ }
900
+ }
901
+ function defaultDockH() {
902
+ try { if (typeof window !== 'undefined' && window.innerHeight) return Math.round(window.innerHeight * 0.52) } catch (e) { /* ignore */ }
903
+ return 420
904
+ }
905
+ const bodyStyle = ui.dockH ? { height: ui.dockH + 'px' } : null
873
906
  return el('div', { className: 'xq-dock' }, [
874
907
  el('div', { key: 'head', className: 'xq-dock-head' }, [
875
908
  el('span', { key: 'logo', className: 'xq-logo' }, [el('b', { key: 'b' }, '雪球'), ' mini']),
@@ -878,9 +911,14 @@ return {
878
911
  el('span', { key: 'sp', className: 'xq-spacer' }),
879
912
  el('button', { key: 'min', className: 'xq-btn-mini', title: '收起(点右下角徽章重新打开)', onClick: function () { ui.set({ open: false }) } }, '收起 —')
880
913
  ]),
881
- el('div', { key: 'body', className: 'xq-dock-body' }, [
914
+ el('div', { key: 'body', className: 'xq-dock-body', style: bodyStyle }, [
882
915
  el(XueqiuPanel, { key: 'panel' })
883
- ])
916
+ ]),
917
+ el('div', {
918
+ key: 'rs', className: 'xq-dock-resize', title: '拖动调整面板高度(双击复位)',
919
+ onPointerDown: onDown, onPointerMove: onMove, onPointerUp: onUp, onPointerCancel: onUp,
920
+ onDoubleClick: function () { ui.set({ dockH: null }) }
921
+ }, [el('span', { key: 'g' }, null)])
884
922
  ])
885
923
  }
886
924
 
package/dynamic/host.js CHANGED
@@ -464,9 +464,11 @@ return {
464
464
 
465
465
  async function actUiGet() {
466
466
  const s = await loadUiState()
467
+ const hNum = Number(s.dockH)
467
468
  return {
468
469
  tab: s.tab || 'market', open: s.open !== false,
469
- badgePos: (s.badgePos && isFinite(Number(s.badgePos.x)) && isFinite(Number(s.badgePos.y)))
470
+ dockH: (s.dockH !== undefined && isFinite(hNum) && hNum >= 160 && hNum <= 1200) ? hNum : null,
471
+ badgePos: (s.badgePos && isFinite(Number(s.badgePos.x)) && isFinite(Number(s.badgePos.y())))
470
472
  ? { x: Number(s.badgePos.x), y: Number(s.badgePos.y) } : null
471
473
  }
472
474
  }
@@ -478,6 +480,10 @@ return {
478
480
  if (args.badgePos && typeof args.badgePos === 'object' && isFinite(Number(args.badgePos.x)) && isFinite(Number(args.badgePos.y))) {
479
481
  s.badgePos = { x: Number(args.badgePos.x), y: Number(args.badgePos.y) }
480
482
  }
483
+ if (args.dockH !== undefined) {
484
+ const dh = Number(args.dockH)
485
+ if (isFinite(dh)) s.dockH = Math.min(Math.max(dh, 160), 1200)
486
+ }
481
487
  await saveUiState()
482
488
  return { ok: true }
483
489
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-xueqiu",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "雪球 mini 行情面板 — DeepSeek Harness 免登录 A股/港美股实时行情、K线(蜡烛/成交量/均线)、分时图、热榜、搜索、7x24 快讯、热议用户。嵌入式面板 + 可拖拽行情徽标,内置请求节流、TTL 缓存与 Cookie 自动续期。",
5
5
  "keywords": [
6
6
  "dsh",
@@ -5,7 +5,9 @@ return {
5
5
  '.xq-dock{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;overflow:hidden;font-size:13px;line-height:1.45;color:var(--dsw-alias-label-primary);margin-bottom:6px;}\n' +
6
6
  '.xq-dock *{box-sizing:border-box;}\n' +
7
7
  '.xq-dock-head{display:flex;align-items:center;gap:8px;padding:7px 12px;border-bottom:1px solid var(--dsw-alias-border-l1);}\n' +
8
- '.xq-dock-body{max-height:56vh;overflow-y:auto;padding:8px 12px 10px;}\n' +
8
+ '.xq-dock-body{height:52vh;max-height:80vh;overflow-y:auto;padding:8px 12px 10px;}\n' +
9
+ '.xq-dock-resize{display:flex;align-items:center;justify-content:center;height:12px;cursor:ns-resize;user-select:none;border-top:1px solid var(--dsw-alias-border-l1);}\n' +
10
+ '.xq-dock-resize span{display:block;width:36px;height:3px;border-radius:2px;background:var(--dsw-alias-border-l2);}\n' +
9
11
  '.xq-badge{position:fixed;right:16px;bottom:64px;display:flex;align-items:center;gap:8px;padding:5px 12px;border-radius:999px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);box-shadow:0 6px 24px rgba(0,0,0,.25);font-size:11.5px;line-height:1.4;color:var(--dsw-alias-label-primary);cursor:grab;user-select:none;pointer-events:auto;z-index:1200;}\n' +
10
12
  '.xq-badge:active{cursor:grabbing;}\n' +
11
13
  '.xq-badge b{color:var(--dsw-alias-brand-primary);}\n' +
@@ -171,7 +173,7 @@ return {
171
173
 
172
174
  // ---------- 共享 UI 状态:面板开合 / 当前标签 / 徽章位置 ----------
173
175
  const ui = {
174
- open: false, tab: 'market', badgePos: null, hydrated: false,
176
+ open: false, tab: 'market', badgePos: null, dockH: null, hydrated: false,
175
177
  _fns: [],
176
178
  subscribe: function (fn) {
177
179
  this._fns.push(fn)
@@ -195,13 +197,16 @@ return {
195
197
  }
196
198
 
197
199
  const saveUi = ctx.debounce(function () {
198
- call('ui.set', { tab: ui.tab, open: ui.open, badgePos: ui.badgePos }).catch(function () { /* 忽略 */ })
200
+ call('ui.set', { tab: ui.tab, open: ui.open, badgePos: ui.badgePos, dockH: ui.dockH }).catch(function () { /* 忽略 */ })
199
201
  }, 800)
200
202
 
201
203
  // 徽章拖拽引用(实例唯一)
202
204
  let badgeDrag = null
203
205
  let badgeMoved = false
204
206
 
207
+ // 面板高度拖拽引用(实例唯一,避免组件重渲染丢失状态)
208
+ const dockResize = { active: false, startY: 0, startH: 0 }
209
+
205
210
  // ---------- K线蜡烛图(成交量 + 均线 + 十字光标/悬浮详情) ----------
206
211
  function KlineChart(props) {
207
212
  const rows = props.rows || []
@@ -856,6 +861,9 @@ return {
856
861
  if (d && d.badgePos && isFinite(Number(d.badgePos.x)) && isFinite(Number(d.badgePos.y))) {
857
862
  ui.set({ badgePos: { x: Number(d.badgePos.x), y: Number(d.badgePos.y) } })
858
863
  }
864
+ if (d && typeof d.dockH === 'number' && isFinite(d.dockH)) {
865
+ ui.set({ dockH: d.dockH })
866
+ }
859
867
  ui.set({ hydrated: true })
860
868
  }).catch(function () { ui.set({ hydrated: true }) })
861
869
  const off = ui.subscribe(function () { force(function (x) { return x + 1 }) })
@@ -866,10 +874,35 @@ return {
866
874
  }
867
875
 
868
876
  function DockPanel() {
877
+ const [, force] = React.useState(0)
869
878
  React.useEffect(function () {
870
- const off = ui.subscribe(function () { if (ui.hydrated) saveUi() })
879
+ const off = ui.subscribe(function () { if (ui.hydrated) saveUi(); force(function (x) { return x + 1 }) })
871
880
  return off
872
881
  }, [])
882
+ function onDown(e) {
883
+ if (e.pointerType === 'mouse' && e.button !== 0) return
884
+ dockResize.active = true
885
+ dockResize.startY = e.clientY
886
+ dockResize.startH = ui.dockH || defaultDockH()
887
+ try { e.currentTarget.setPointerCapture(e.pointerId) } catch (err) { /* ignore */ }
888
+ }
889
+ function onMove(e) {
890
+ if (!dockResize.active) return
891
+ const vp = viewport()
892
+ const maxH = Math.round((vp ? vp.h : 800) * 0.85)
893
+ let h = dockResize.startH + (e.clientY - dockResize.startY)
894
+ h = Math.min(Math.max(160, h), Math.min(maxH, 1200))
895
+ ui.set({ dockH: h })
896
+ }
897
+ function onUp(e) {
898
+ dockResize.active = false
899
+ try { if (e.currentTarget.hasPointerCapture(e.pointerId)) e.currentTarget.releasePointerCapture(e.pointerId) } catch (err) { /* ignore */ }
900
+ }
901
+ function defaultDockH() {
902
+ try { if (typeof window !== 'undefined' && window.innerHeight) return Math.round(window.innerHeight * 0.52) } catch (e) { /* ignore */ }
903
+ return 420
904
+ }
905
+ const bodyStyle = ui.dockH ? { height: ui.dockH + 'px' } : null
873
906
  return el('div', { className: 'xq-dock' }, [
874
907
  el('div', { key: 'head', className: 'xq-dock-head' }, [
875
908
  el('span', { key: 'logo', className: 'xq-logo' }, [el('b', { key: 'b' }, '雪球'), ' mini']),
@@ -878,9 +911,14 @@ return {
878
911
  el('span', { key: 'sp', className: 'xq-spacer' }),
879
912
  el('button', { key: 'min', className: 'xq-btn-mini', title: '收起(点右下角徽章重新打开)', onClick: function () { ui.set({ open: false }) } }, '收起 —')
880
913
  ]),
881
- el('div', { key: 'body', className: 'xq-dock-body' }, [
914
+ el('div', { key: 'body', className: 'xq-dock-body', style: bodyStyle }, [
882
915
  el(XueqiuPanel, { key: 'panel' })
883
- ])
916
+ ]),
917
+ el('div', {
918
+ key: 'rs', className: 'xq-dock-resize', title: '拖动调整面板高度(双击复位)',
919
+ onPointerDown: onDown, onPointerMove: onMove, onPointerUp: onUp, onPointerCancel: onUp,
920
+ onDoubleClick: function () { ui.set({ dockH: null }) }
921
+ }, [el('span', { key: 'g' }, null)])
884
922
  ])
885
923
  }
886
924
 
package/src/index.js CHANGED
@@ -464,9 +464,11 @@ export default {
464
464
 
465
465
  async function actUiGet() {
466
466
  const s = await loadUiState()
467
+ const hNum = Number(s.dockH)
467
468
  return {
468
469
  tab: s.tab || 'market', open: s.open !== false,
469
- badgePos: (s.badgePos && isFinite(Number(s.badgePos.x)) && isFinite(Number(s.badgePos.y)))
470
+ dockH: (s.dockH !== undefined && isFinite(hNum) && hNum >= 160 && hNum <= 1200) ? hNum : null,
471
+ badgePos: (s.badgePos && isFinite(Number(s.badgePos.x)) && isFinite(Number(s.badgePos.y())))
470
472
  ? { x: Number(s.badgePos.x), y: Number(s.badgePos.y) } : null
471
473
  }
472
474
  }
@@ -478,6 +480,10 @@ export default {
478
480
  if (args.badgePos && typeof args.badgePos === 'object' && isFinite(Number(args.badgePos.x)) && isFinite(Number(args.badgePos.y))) {
479
481
  s.badgePos = { x: Number(args.badgePos.x), y: Number(args.badgePos.y) }
480
482
  }
483
+ if (args.dockH !== undefined) {
484
+ const dh = Number(args.dockH)
485
+ if (isFinite(dh)) s.dockH = Math.min(Math.max(dh, 160), 1200)
486
+ }
481
487
  await saveUiState()
482
488
  return { ok: true }
483
489
  }