dsh-xueqiu 1.7.1 → 1.7.2
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 +1 -0
- package/README.md +2 -0
- package/dynamic/client.js +37 -1
- package/dynamic/host.js +4 -1
- package/package.json +7 -2
- package/src/client/index.js +39 -3
- package/src/index.js +4 -1
package/README.en.md
CHANGED
|
@@ -121,6 +121,7 @@ The data layer is defended in depth — safe to leave open for hours:
|
|
|
121
121
|
|
|
122
122
|
## Changelog
|
|
123
123
|
|
|
124
|
+
- **1.7.2** (2025-08-19) — News tab pagination: scroll-to-bottom or "load earlier" fetches older items (max_id cursor, deduped); refresh resets to the latest page.
|
|
124
125
|
- **1.7.1** (2025-08-19) — Fix static install (`dsh plugin add`) crashing `dsh web` startup: dual-mode RPC (harness.handle for dynamic runs, a loopback+same-origin fenced `/xq-rpc` webServer route for static installs) and a proper `__ModuleLoader__` CJS client bundle.
|
|
125
126
|
- **1.7.0** (2025-08-19) — Hidden-tab polling pause + CN/HK/US market session hints.
|
|
126
127
|
- **1.6.1** — Pipeline deadlock watchdog fix, tab-switch fix, badgePos restore fix, debug RPC.
|
package/README.md
CHANGED
|
@@ -151,6 +151,8 @@ dsh-xueqiu/
|
|
|
151
151
|
|
|
152
152
|
## 📋 更新日志
|
|
153
153
|
|
|
154
|
+
- **1.7.2**(2025-08-19)
|
|
155
|
+
- 新增:快讯 tab 翻页——滚动到底或点「加载更早」自动加载历史快讯(max_id 游标,自动去重),「刷新」重置回最新一页。
|
|
154
156
|
- **1.7.1**(2025-08-19)
|
|
155
157
|
- 修复:`dsh plugin add` 静态安装后 `dsh web` 启动即崩(`harness is not defined`)——静态安装改走 `webServer` 前缀路由 `/xq-rpc`(带回环 + 同源双重栅栏),动态运行时仍走 `harness.handle`,双模式自动切换。
|
|
156
158
|
- 修复:静态安装的浏览器端 bundle 格式(`__ModuleLoader__` CJS 工厂)与网络通道(同源 fetch 替代 `host.call`),面板/徽章/指数条在静态模式下完整可用。
|
package/dynamic/client.js
CHANGED
|
@@ -62,6 +62,8 @@ return {
|
|
|
62
62
|
'.xq-news-item{font-size:12.5px;padding:6px 8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:7px;}\n' +
|
|
63
63
|
'.xq-news-item.xq-important{border-left:3px solid var(--dsw-alias-state-warn-primary);}\n' +
|
|
64
64
|
'.xq-news-time{font-size:10.5px;color:var(--dsw-alias-label-secondary);margin-top:3px;}\n' +
|
|
65
|
+
'.xq-news-more{font-size:11.5px;color:var(--dsw-alias-label-secondary);text-align:center;padding:6px 0 2px;cursor:pointer;user-select:none;}\n' +
|
|
66
|
+
'.xq-news-more:hover{color:var(--dsw-alias-label-primary);}\n' +
|
|
65
67
|
'.xq-detail-head{display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap;}\n' +
|
|
66
68
|
'.xq-detail-name{font-size:15px;font-weight:700;}\n' +
|
|
67
69
|
'.xq-detail-code{font-size:11px;color:var(--dsw-alias-label-secondary);}\n' +
|
|
@@ -461,6 +463,8 @@ return {
|
|
|
461
463
|
const [hot, setHot] = React.useState([])
|
|
462
464
|
const [hotMarket, setHotMarket] = React.useState('cn')
|
|
463
465
|
const [news, setNews] = React.useState([])
|
|
466
|
+
const [newsMore, setNewsMore] = React.useState(false) // 翻页加载中
|
|
467
|
+
const [newsNoMore, setNewsNoMore] = React.useState(false) // 已到最旧
|
|
464
468
|
const [searchQ, setSearchQ] = React.useState('')
|
|
465
469
|
const [searchMode, setSearchMode] = React.useState('stock')
|
|
466
470
|
const [searchRes, setSearchRes] = React.useState([])
|
|
@@ -505,12 +509,32 @@ return {
|
|
|
505
509
|
]).then(function (res) {
|
|
506
510
|
setHot((res[0] && res[0].list) || [])
|
|
507
511
|
setNews((res[1] && res[1].items) || [])
|
|
512
|
+
setNewsMore(false)
|
|
513
|
+
setNewsNoMore(false)
|
|
508
514
|
setErr('')
|
|
509
515
|
}).catch(function (e) {
|
|
510
516
|
setErr(String((e && e.message) || e))
|
|
511
517
|
})
|
|
512
518
|
}
|
|
513
519
|
|
|
520
|
+
// 快讯翻页:max_id = 当前最旧一条 id,返回严格更早的记录
|
|
521
|
+
function loadMoreNews() {
|
|
522
|
+
if (newsMore || newsNoMore || !news.length) return
|
|
523
|
+
const maxId = news[news.length - 1].id
|
|
524
|
+
setNewsMore(true)
|
|
525
|
+
call('news', { count: 20, max_id: maxId }).then(function (res) {
|
|
526
|
+
const items = (res && res.items) || []
|
|
527
|
+
const seen = {}
|
|
528
|
+
news.forEach(function (it) { seen[it.id] = true })
|
|
529
|
+
const fresh = items.filter(function (it) { return !seen[it.id] })
|
|
530
|
+
if (!fresh.length) setNewsNoMore(true)
|
|
531
|
+
else setNews(news.concat(fresh))
|
|
532
|
+
setNewsMore(false)
|
|
533
|
+
}).catch(function () {
|
|
534
|
+
setNewsMore(false)
|
|
535
|
+
})
|
|
536
|
+
}
|
|
537
|
+
|
|
514
538
|
React.useEffect(function () {
|
|
515
539
|
setLoading(true)
|
|
516
540
|
refreshMarket().then(function () { return refreshContent() })
|
|
@@ -868,8 +892,20 @@ return {
|
|
|
868
892
|
el('div', { key: 'm', className: 'xq-news-time' }, fmtTime(it.created_at) + (it.mark === 1 ? ' · 重要' : ''))
|
|
869
893
|
])
|
|
870
894
|
})
|
|
895
|
+
// 滚动到底自动加载;手动入口兜底(滚轮惯性/触控板场景)
|
|
896
|
+
kids.push(el('div', {
|
|
897
|
+
key: 'more',
|
|
898
|
+
className: 'xq-news-more',
|
|
899
|
+
onClick: function () { loadMoreNews() }
|
|
900
|
+
}, newsMore ? '加载中…' : (newsNoMore ? '没有更早的快讯了' : '加载更早 ↑')))
|
|
871
901
|
return news.length
|
|
872
|
-
? el('div', {
|
|
902
|
+
? el('div', {
|
|
903
|
+
className: 'xq-news',
|
|
904
|
+
onScroll: function (e) {
|
|
905
|
+
const n = e.target
|
|
906
|
+
if (n.scrollTop + n.clientHeight >= n.scrollHeight - 40) loadMoreNews()
|
|
907
|
+
}
|
|
908
|
+
}, kids)
|
|
873
909
|
: el('div', { className: 'xq-muted' }, '暂无快讯')
|
|
874
910
|
}
|
|
875
911
|
|
package/dynamic/host.js
CHANGED
|
@@ -375,7 +375,10 @@ return {
|
|
|
375
375
|
|
|
376
376
|
async function actNews(args) {
|
|
377
377
|
const count = Math.min(Math.max(parseInt(args.count, 10) || 20, 1), 50)
|
|
378
|
-
|
|
378
|
+
// max_id 翻页游标:-1 取最新一页;传上一页最旧一条 id 继续往回翻
|
|
379
|
+
const maxId = parseInt(args.max_id, 10)
|
|
380
|
+
const cursor = isFinite(maxId) && maxId > 0 ? maxId : -1
|
|
381
|
+
const data = await getJSON('/statuses/livenews/list.json', { since_id: -1, max_id: cursor, count: count }, { base: SITE, ttl: 120000 })
|
|
379
382
|
const items = (data && data.items) || []
|
|
380
383
|
return {
|
|
381
384
|
items: items.map(function (it) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-xueqiu",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "雪球 mini 行情面板 — DeepSeek Harness 免登录 A股/港美股实时行情、K线(蜡烛/成交量/均线)、分时图、热榜、搜索、7x24 快讯、热议用户。嵌入式面板 + 可拖拽行情徽标,内置请求节流、TTL 缓存与 Cookie 自动续期。",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -46,5 +46,10 @@
|
|
|
46
46
|
"cordis.patch.yml",
|
|
47
47
|
"README.md",
|
|
48
48
|
"LICENSE"
|
|
49
|
-
]
|
|
49
|
+
],
|
|
50
|
+
"scripts": {
|
|
51
|
+
"generate": "python3 scripts/gen-static.py",
|
|
52
|
+
"check": "python3 scripts/gen-static.py --check && node --check src/index.js && node --check src/client/index.js && node -e \"new Function(require('fs').readFileSync('dynamic/host.js','utf8'))\" && node -e \"new Function(require('fs').readFileSync('dynamic/client.js','utf8'))\" && bash scripts/static-smoke.sh",
|
|
53
|
+
"prepublishOnly": "npm run check"
|
|
54
|
+
}
|
|
50
55
|
}
|
package/src/client/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
// 由 scripts/gen-static.py 从 dynamic/client.js 生成 —— 勿手改;改 dynamic/ 后重新生成。
|
|
1
2
|
// 静态 bundle 格式:classic script 注册到 __ModuleLoader__,factory 为 CJS 形式。
|
|
2
|
-
// 由 dynamic/client.js 机械转换生成 —— 修改请先改 dynamic/ 再重新转换。
|
|
3
3
|
window.__ModuleLoader__.load({
|
|
4
4
|
id: 'dsh-xueqiu',
|
|
5
5
|
factory: function (require) {
|
|
@@ -7,7 +7,7 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
var exports = module.exports
|
|
8
8
|
const React = require('react')
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// 动态运行时 styles.insert 的替代:自管 <style> 标签(随插件停用移除交给卸载流程)
|
|
11
11
|
let _styleTag = null
|
|
12
12
|
function insertStyle (css) {
|
|
13
13
|
if (typeof document === 'undefined' || !document.head) return
|
|
@@ -81,6 +81,8 @@ exports.default = {
|
|
|
81
81
|
'.xq-news-item{font-size:12.5px;padding:6px 8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:7px;}\n' +
|
|
82
82
|
'.xq-news-item.xq-important{border-left:3px solid var(--dsw-alias-state-warn-primary);}\n' +
|
|
83
83
|
'.xq-news-time{font-size:10.5px;color:var(--dsw-alias-label-secondary);margin-top:3px;}\n' +
|
|
84
|
+
'.xq-news-more{font-size:11.5px;color:var(--dsw-alias-label-secondary);text-align:center;padding:6px 0 2px;cursor:pointer;user-select:none;}\n' +
|
|
85
|
+
'.xq-news-more:hover{color:var(--dsw-alias-label-primary);}\n' +
|
|
84
86
|
'.xq-detail-head{display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap;}\n' +
|
|
85
87
|
'.xq-detail-name{font-size:15px;font-weight:700;}\n' +
|
|
86
88
|
'.xq-detail-code{font-size:11px;color:var(--dsw-alias-label-secondary);}\n' +
|
|
@@ -480,6 +482,8 @@ exports.default = {
|
|
|
480
482
|
const [hot, setHot] = React.useState([])
|
|
481
483
|
const [hotMarket, setHotMarket] = React.useState('cn')
|
|
482
484
|
const [news, setNews] = React.useState([])
|
|
485
|
+
const [newsMore, setNewsMore] = React.useState(false) // 翻页加载中
|
|
486
|
+
const [newsNoMore, setNewsNoMore] = React.useState(false) // 已到最旧
|
|
483
487
|
const [searchQ, setSearchQ] = React.useState('')
|
|
484
488
|
const [searchMode, setSearchMode] = React.useState('stock')
|
|
485
489
|
const [searchRes, setSearchRes] = React.useState([])
|
|
@@ -524,12 +528,32 @@ exports.default = {
|
|
|
524
528
|
]).then(function (res) {
|
|
525
529
|
setHot((res[0] && res[0].list) || [])
|
|
526
530
|
setNews((res[1] && res[1].items) || [])
|
|
531
|
+
setNewsMore(false)
|
|
532
|
+
setNewsNoMore(false)
|
|
527
533
|
setErr('')
|
|
528
534
|
}).catch(function (e) {
|
|
529
535
|
setErr(String((e && e.message) || e))
|
|
530
536
|
})
|
|
531
537
|
}
|
|
532
538
|
|
|
539
|
+
// 快讯翻页:max_id = 当前最旧一条 id,返回严格更早的记录
|
|
540
|
+
function loadMoreNews() {
|
|
541
|
+
if (newsMore || newsNoMore || !news.length) return
|
|
542
|
+
const maxId = news[news.length - 1].id
|
|
543
|
+
setNewsMore(true)
|
|
544
|
+
call('news', { count: 20, max_id: maxId }).then(function (res) {
|
|
545
|
+
const items = (res && res.items) || []
|
|
546
|
+
const seen = {}
|
|
547
|
+
news.forEach(function (it) { seen[it.id] = true })
|
|
548
|
+
const fresh = items.filter(function (it) { return !seen[it.id] })
|
|
549
|
+
if (!fresh.length) setNewsNoMore(true)
|
|
550
|
+
else setNews(news.concat(fresh))
|
|
551
|
+
setNewsMore(false)
|
|
552
|
+
}).catch(function () {
|
|
553
|
+
setNewsMore(false)
|
|
554
|
+
})
|
|
555
|
+
}
|
|
556
|
+
|
|
533
557
|
React.useEffect(function () {
|
|
534
558
|
setLoading(true)
|
|
535
559
|
refreshMarket().then(function () { return refreshContent() })
|
|
@@ -887,8 +911,20 @@ exports.default = {
|
|
|
887
911
|
el('div', { key: 'm', className: 'xq-news-time' }, fmtTime(it.created_at) + (it.mark === 1 ? ' · 重要' : ''))
|
|
888
912
|
])
|
|
889
913
|
})
|
|
914
|
+
// 滚动到底自动加载;手动入口兜底(滚轮惯性/触控板场景)
|
|
915
|
+
kids.push(el('div', {
|
|
916
|
+
key: 'more',
|
|
917
|
+
className: 'xq-news-more',
|
|
918
|
+
onClick: function () { loadMoreNews() }
|
|
919
|
+
}, newsMore ? '加载中…' : (newsNoMore ? '没有更早的快讯了' : '加载更早 ↑')))
|
|
890
920
|
return news.length
|
|
891
|
-
? el('div', {
|
|
921
|
+
? el('div', {
|
|
922
|
+
className: 'xq-news',
|
|
923
|
+
onScroll: function (e) {
|
|
924
|
+
const n = e.target
|
|
925
|
+
if (n.scrollTop + n.clientHeight >= n.scrollHeight - 40) loadMoreNews()
|
|
926
|
+
}
|
|
927
|
+
}, kids)
|
|
892
928
|
: el('div', { className: 'xq-muted' }, '暂无快讯')
|
|
893
929
|
}
|
|
894
930
|
|
package/src/index.js
CHANGED
|
@@ -375,7 +375,10 @@ export default {
|
|
|
375
375
|
|
|
376
376
|
async function actNews(args) {
|
|
377
377
|
const count = Math.min(Math.max(parseInt(args.count, 10) || 20, 1), 50)
|
|
378
|
-
|
|
378
|
+
// max_id 翻页游标:-1 取最新一页;传上一页最旧一条 id 继续往回翻
|
|
379
|
+
const maxId = parseInt(args.max_id, 10)
|
|
380
|
+
const cursor = isFinite(maxId) && maxId > 0 ? maxId : -1
|
|
381
|
+
const data = await getJSON('/statuses/livenews/list.json', { since_id: -1, max_id: cursor, count: count }, { base: SITE, ttl: 120000 })
|
|
379
382
|
const items = (data && data.items) || []
|
|
380
383
|
return {
|
|
381
384
|
items: items.map(function (it) {
|