@@ -15,6 +15,166 @@ import {Col} from '@app/lib/components'
1515import { WstackProps } from '@app/types/widget'
1616import { FC } from 'react'
1717
18+ /**榜单信息*/
19+ interface TopInfo {
20+ /**榜单名字*/
21+ title : string
22+ 23+ /**榜单链接*/
24+ href : string
25+ }
26+ 27+ /**文章信息*/
28+ interface ArticleInfo {
29+ /**文章标题*/
30+ title : string
31+ 32+ /**原文地址*/
33+ href : string
34+ 35+ /**文章热度*/
36+ hot : string
37+ }
38+ 39+ /**页面信息*/
40+ interface PageInfo {
41+ /**页面标题*/
42+ title : string
43+ 44+ /**该榜单的 logo */
45+ logo : string
46+ 47+ /**文章列表*/
48+ articleList : ArticleInfo [ ]
49+ 50+ /**js执行的错误信息*/
51+ err : Error
52+ }
53+ 54+ /**内置榜单别名,可在桌面小部件编辑传入别名*/
55+ const topList : TopInfo [ ] = [
56+ {
57+ title : '知乎' ,
58+ href : 'https://tophub.today/n/mproPpoq6O' ,
59+ } ,
60+ {
61+ title : '微博' ,
62+ href : 'https://tophub.today/n/KqndgxeLl9' ,
63+ } ,
64+ {
65+ title : '微信' ,
66+ href : 'https://tophub.today/n/WnBe01o371' ,
67+ } ,
68+ {
69+ title : '澎湃' ,
70+ href : 'https://tophub.today/n/wWmoO5Rd4E' ,
71+ } ,
72+ {
73+ title : '百度' ,
74+ href : 'https://tophub.today/n/Jb0vmloB1G' ,
75+ } ,
76+ {
77+ title : '知乎日报' ,
78+ href : 'https://tophub.today/n/KMZd7VOvrO' ,
79+ } ,
80+ {
81+ title : '历史上的今天' ,
82+ href : 'https://tophub.today/n/KMZd7X3erO' ,
83+ } ,
84+ {
85+ title : '神马搜索' ,
86+ href : 'https://tophub.today/n/n6YoVqDeZa' ,
87+ } ,
88+ {
89+ title : '搜狗' ,
90+ href : 'https://tophub.today/n/NaEdZndrOM' ,
91+ } ,
92+ {
93+ title : '今日头条' ,
94+ href : 'https://tophub.today/n/x9ozB4KoXb' ,
95+ } ,
96+ {
97+ title : '360搜索' ,
98+ href : 'https://tophub.today/n/KMZd7x6erO' ,
99+ } ,
100+ {
101+ title : '36氪' ,
102+ href : 'https://tophub.today/n/Q1Vd5Ko85R' ,
103+ } ,
104+ {
105+ title : '好奇心日报' ,
106+ href : 'https://tophub.today/n/Y3QeLGAd7k' ,
107+ } ,
108+ {
109+ title : '少数派' ,
110+ href : 'https://tophub.today/n/Y2KeDGQdNP' ,
111+ } ,
112+ {
113+ title : '果壳' ,
114+ href : 'https://tophub.today/n/20MdK2vw1q' ,
115+ } ,
116+ {
117+ title : '虎嗅网' ,
118+ href : 'https://tophub.today/n/5VaobgvAj1' ,
119+ } ,
120+ {
121+ title : 'IT之家' ,
122+ href : 'https://tophub.today/n/74Kvx59dkx' ,
123+ } ,
124+ {
125+ title : '爱范儿' ,
126+ href : 'https://tophub.today/n/74KvxK7okx' ,
127+ } ,
128+ {
129+ title : 'GitHub' ,
130+ href : 'https://tophub.today/n/rYqoXQ8vOD' ,
131+ } ,
132+ {
133+ title : '威锋网' ,
134+ href : 'https://tophub.today/n/n4qv90roaK' ,
135+ } ,
136+ {
137+ title : 'CSDN' ,
138+ href : 'https://tophub.today/n/n3moBVoN5O' ,
139+ } ,
140+ {
141+ title : '掘金' ,
142+ href : 'https://tophub.today/n/QaqeEaVe9R' ,
143+ } ,
144+ {
145+ title : '哔哩哔哩' ,
146+ href : 'https://tophub.today/n/74KvxwokxM' ,
147+ } ,
148+ {
149+ title : '抖音' ,
150+ href : 'https://tophub.today/n/DpQvNABoNE' ,
151+ } ,
152+ {
153+ title : '吾爱破解' ,
154+ href : 'https://tophub.today/n/NKGoRAzel6' ,
155+ } ,
156+ {
157+ title : '百度贴吧' ,
158+ href : 'https://tophub.today/n/Om4ejxvxEN' ,
159+ } ,
160+ {
161+ title : '天涯' ,
162+ href : 'https://tophub.today/n/Jb0vmmlvB1' ,
163+ } ,
164+ {
165+ title : 'V2EX' ,
166+ href : 'https://tophub.today/n/wWmoORe4EO' ,
167+ } ,
168+ {
169+ title : '虎扑社区' ,
170+ href : 'https://tophub.today/n/G47o8weMmN' ,
171+ } ,
172+ {
173+ title : '汽车之家' ,
174+ href : 'https://tophub.today/n/YqoXQGXvOD' ,
175+ } ,
176+ ]
177+ 18178const { setStorage, getStorage} = useStorage ( 'newsTop-xiaoming' )
19179
20180/**文字颜色*/
@@ -43,6 +203,28 @@ const colors = {
43203 black : '#000000' ,
44204}
45205
206+ /**
207+ * 文章组件
208+ * @param param.article 文章
209+ * @param param.sort 文章序号
210+ */
211+ const Article : FC < { article : ArticleInfo ; sort : number } > = ( { article, sort} ) => {
212+ return (
213+ < >
214+ < wspacer length = { 5 } > </ wspacer >
215+ < wstack verticalAlign = "center" href = { article . href } >
216+ < wtext maxLine = { 1 } font = { Font . lightSystemFont ( 14 ) } >
217+ { sort } 、{ article . title }
218+ </ wtext >
219+ < wspacer > </ wspacer >
220+ < wtext maxLine = { 1 } font = { Font . lightSystemFont ( 12 ) } opacity = { 0.6 } >
221+ { article . hot }
222+ </ wtext >
223+ </ wstack >
224+ </ >
225+ )
226+ }
227+ 46228class NewsTop {
47229 async init ( ) {
48230 if ( isLaunchInsideApp ( ) ) {
@@ -58,6 +240,11 @@ class NewsTop {
58240 if ( isLaunchInsideApp ( ) ) {
59241 await showNotification ( { title : '稍等片刻' , body : '小部件渲染中...' , sound : 'alert' } )
60242 }
243+ // 获取榜单url
244+ const topUrl = this . getTopUrl ( )
245+ // 获取榜单数据
246+ const { title, logo, articleList} = await this . getNewsTop ( topUrl )
247+ 61248 // 多久(毫秒)更新一次小部件(默认1小时)
62249 const updateInterval = 1 * 60 * 60 * 1000
63250 // 渲染尺寸
@@ -68,26 +255,53 @@ class NewsTop {
68255 updateDate = { new Date ( Date . now ( ) + updateInterval ) }
69256 background = { boxBg . match ( '透明背景' ) ? transparentBg : boxBg }
70257 >
71- { size === 'small' && this . renderSmall ( ) }
72- { size === 'medium' && this . renderMedium ( ) }
73- { size === 'large' && this . renderLarge ( ) }
258+ < wstack flexDirection = "column" padding = { [ 16 , 16 , 16 , 16 ] } >
259+ { /* 标题和logo */ }
260+ < wstack verticalAlign = "center" >
261+ < wimage src = { logo } width = { 14 } height = { 14 } borderRadius = { 4 } > </ wimage >
262+ < wspacer length = { 10 } > </ wspacer >
263+ < wtext opacity = { 0.7 } font = { Font . boldSystemFont ( 12 ) } >
264+ { title }
265+ </ wtext >
266+ </ wstack >
267+ { /* 内容 */ }
268+ { size === 'small' && this . renderSmall ( articleList ) }
269+ { size === 'medium' && this . renderMedium ( articleList ) }
270+ { size === 'large' && this . renderLarge ( articleList ) }
271+ </ wstack >
74272 </ wbox >
75273 )
76274 }
77275
78276 // 渲染小尺寸
79- renderSmall ( ) {
277+ renderSmall ( articleList : ArticleInfo [ ] ) {
80278 return < wstack flexDirection = "column" > </ wstack >
81279 }
82280
83281 // 渲染中尺寸
84- renderMedium ( ) {
85- return < wstack > </ wstack >
282+ renderMedium ( articleList : ArticleInfo [ ] ) {
283+ const _articleList = articleList . slice ( 0 , 5 )
284+ return (
285+ < wstack flexDirection = "column" >
286+ { _articleList . map ( ( article , index ) => (
287+ < Article article = { article } sort = { index + 1 } > </ Article >
288+ ) ) }
289+ < wspacer > </ wspacer >
290+ </ wstack >
291+ )
86292 }
87293
88294 // 渲染大尺寸
89- renderLarge ( ) {
90- return < wstack flexDirection = "column" > </ wstack >
295+ renderLarge ( articleList : ArticleInfo [ ] ) {
296+ const _articleList = articleList . slice ( 0 , 10 )
297+ return (
298+ < wstack flexDirection = "column" >
299+ { _articleList . map ( ( article , index ) => (
300+ < Article article = { article } sort = { index + 1 } > </ Article >
301+ ) ) }
302+ < wspacer > </ wspacer >
303+ </ wstack >
304+ )
91305 }
92306
93307 // 显示菜单
@@ -130,6 +344,58 @@ class NewsTop {
130344 break
131345 }
132346 }
347+ 348+ // 获取热榜数据
349+ async getNewsTop ( url : string ) : Promise < PageInfo > {
350+ const webview = new WebView ( )
351+ await webview . loadURL ( url )
352+ await webview . waitForLoad ( )
353+ const { title = '今日热榜' , logo = 'flame.fill' , articleList = [ ] , err} = ( await webview . evaluateJavaScript (
354+ `
355+ let title = ''
356+ let logo = ''
357+ let articleList = []
358+ let err = ''
359+ try {
360+ title = document.title.split(' ')[0]
361+ logo = document.querySelector('.custom-info-content > img').src
362+ articleList = Array.from(document.querySelector('.divider > .weui-panel > .weui-panel__bd').querySelectorAll('a')).map(a => {
363+ return {
364+ title: a.querySelector('h4').innerText.replace(/\\d+?[、]\\s*/, ''),
365+ href: a.href,
366+ hot: a.querySelector('h4+p').innerText
367+ }
368+ })
369+ } catch(err) {
370+ err = err
371+ }
372+ Object.assign({}, {title, logo, articleList, err})
373+ ` ,
374+ ) ) as PageInfo
375+ err && console . warn ( `热榜获取出错: ${ err } ` )
376+ return { title, logo, articleList, err}
377+ }
378+ 379+ // 获取要显示的榜单 url
380+ getTopUrl ( ) : string {
381+ // 默认为知乎榜单
382+ const defaultUrl = 'https://tophub.today/n/mproPpoq6O'
383+ // 从小部件编辑处获取关键词或链接
384+ const keyword = ( args . widgetParameter as string ) || defaultUrl
385+ if ( this . isUrl ( keyword ) ) return keyword
386+ const topInfo = topList . find ( item => item . title . toLowerCase ( ) === keyword . toLowerCase ( ) )
387+ if ( topInfo ) return topInfo . href
388+ return defaultUrl
389+ }
390+ 391+ /**
392+ * 判断一个值是否为网络连接
393+ * @param value 值
394+ */
395+ isUrl ( value : string ) : boolean {
396+ const reg = / ^ ( h t t p | h t t p s ) \: \/ \/ [ \w \W ] + /
397+ return reg . test ( value )
398+ }
133399}
134400
135401EndAwait ( ( ) => new NewsTop ( ) . init ( ) )
0 commit comments