Skip to content

Commit e68dc6c

Browse files
committed
基本实现热榜展示
1 parent f1999fb commit e68dc6c

File tree

2 files changed

+275
-9
lines changed

2 files changed

+275
-9
lines changed

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import './scripts/helloWorld.tsx'
1+
import './scripts/newsTop.tsx'

src/scripts/newsTop.tsx

Lines changed: 274 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,166 @@ import {Col} from '@app/lib/components'
1515
import {WstackProps} from '@app/types/widget'
1616
import {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+
18178
const {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+
46228
class 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 = /^(http|https)\:\/\/[\w\W]+/
397+
return reg.test(value)
398+
}
133399
}
134400

135401
EndAwait(() => new NewsTop().init())

0 commit comments

Comments
 (0)