Skip to content

Commit d27790c

Browse files
committed
编写联通卡信息小部件
1 parent 7698f5d commit d27790c

File tree

1 file changed

+367
-0
lines changed

1 file changed

+367
-0
lines changed

src/scripts/china10010.tsx

Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
/**
2+
* 今日热榜小部件
3+
*/
4+
5+
import {
6+
isLaunchInsideApp,
7+
setTransparentBackground,
8+
showActionSheet,
9+
showModal,
10+
showNotification,
11+
showPreviewOptions,
12+
useStorage,
13+
request,
14+
} from '@app/lib/help'
15+
import {FC} from 'react'
16+
17+
/**手机卡数据列表*/
18+
interface PhoneDatas {
19+
data: {
20+
dataList: PhoneData[]
21+
}
22+
}
23+
24+
/**手机卡数据*/
25+
interface PhoneData {
26+
pointUpdateTimeStamp: string
27+
paperwork4: string
28+
buttonBacImageUrlBig: string
29+
type: string
30+
remainTitle: string
31+
buttonText7: string
32+
buttonLinkMode: string
33+
displayTime: string
34+
buttonText7TextColor: string
35+
buttonBacImageUrlSmall: string
36+
button: string
37+
remainTitleColoer: string
38+
buttonBacImageUrl: string
39+
buttonTextColor: string
40+
isShake: string
41+
number: string
42+
isWarn?: string
43+
paperwork4Coloer: string
44+
url: string
45+
buttonUrl7: string
46+
unit: string
47+
button7LinkMode: string
48+
persent: string
49+
persentColor: string
50+
buttonAddress: string
51+
usedTitle: string
52+
ballRippleColor1: string
53+
ballRippleColor2: string
54+
markerImg?: string
55+
warningTextColor?: string
56+
warningPointColor?: string
57+
}
58+
59+
/**页面信息*/
60+
interface PageInfo {
61+
/**页面数据*/
62+
phoneDatas: PhoneDatas
63+
64+
/**cookie*/
65+
cookie: string | null
66+
67+
/**js执行的错误信息*/
68+
err: Error
69+
}
70+
71+
/**有用的手机卡数据*/
72+
interface UsefulPhoneData {
73+
/**类型*/
74+
type: string
75+
76+
/**剩余百分比数字*/
77+
present: number
78+
79+
/**单位*/
80+
unit: string
81+
82+
/**剩余量数字*/
83+
count: number
84+
85+
/**描述*/
86+
label: string
87+
}
88+
89+
const {setStorage, getStorage} = useStorage('china10010-xiaoming')
90+
91+
/**默认背景颜色*/
92+
const defaultBgColor = Color.dynamic(new Color('#ffffff', 1), new Color('#000000', 1))
93+
94+
/**文字颜色*/
95+
const textColor = getStorage<string>('textColor') || Color.dynamic(new Color('#000000', 1), new Color('#dddddd', 1))
96+
97+
/**透明背景*/
98+
const transparentBg: Image | Color = getStorage<Image>('transparentBg') || defaultBgColor
99+
100+
/**背景颜色或背景图链接*/
101+
const boxBg = getStorage<string>('boxBg') || defaultBgColor
102+
103+
class China10010 {
104+
async init() {
105+
if (isLaunchInsideApp()) {
106+
return await this.showMenu()
107+
}
108+
const widget = (await this.render()) as ListWidget
109+
Script.setWidget(widget)
110+
Script.complete()
111+
}
112+
113+
//渲染组件
114+
async render(): Promise<unknown> {
115+
if (isLaunchInsideApp()) {
116+
await showNotification({title: '稍等片刻', body: '小部件渲染中...', sound: 'alert'})
117+
}
118+
// 多久(毫秒)更新一次小部件(默认3分钟)
119+
const updateInterval = 3 * 60 * 1000
120+
121+
// 渲染尺寸
122+
const size = config.widgetFamily
123+
124+
return (
125+
<wbox
126+
padding={[0, 0, 0, 0]}
127+
updateDate={new Date(Date.now() + updateInterval)}
128+
background={typeof boxBg === 'string' && boxBg.match('透明背景') ? transparentBg : boxBg}
129+
>
130+
<wstack flexDirection="column" padding={[0, 16, 0, 16]}>
131+
<wspacer></wspacer>
132+
<wspacer></wspacer>
133+
{/* 标题和logo */}
134+
<wstack verticalAlign="center">
135+
<wimage
136+
src="https://p.pstatp.com/origin/1381a0002e9cbaedbc301"
137+
width={20}
138+
height={20}
139+
borderRadius={4}
140+
></wimage>
141+
<wspacer length={8}></wspacer>
142+
<wtext opacity={0.7} font={Font.boldSystemFont(16)} textColor={textColor}>
143+
中国联通
144+
</wtext>
145+
</wstack>
146+
<wspacer></wspacer>
147+
<wspacer></wspacer>
148+
{/* 内容 */}
149+
{size === 'small' && this.renderSmall(articleList)}
150+
{size === 'medium' && this.renderMedium(articleList)}
151+
{size === 'large' && this.renderLarge(articleList)}
152+
</wstack>
153+
</wbox>
154+
)
155+
}
156+
157+
// 渲染小尺寸
158+
renderSmall(articleList: ArticleInfo[]) {
159+
const article = articleList[0]
160+
return (
161+
<wstack flexDirection="column">
162+
<wtext font={Font.lightSystemFont(14)} textColor={textColor}>
163+
{article.title}
164+
</wtext>
165+
<wspacer></wspacer>
166+
<wstack>
167+
<wspacer></wspacer>
168+
<wtext maxLine={1} font={Font.lightSystemFont(12)} opacity={0.6} textColor={textColor}>
169+
{article.hot}
170+
</wtext>
171+
</wstack>
172+
<wspacer></wspacer>
173+
</wstack>
174+
)
175+
}
176+
177+
// 渲染中尺寸
178+
renderMedium(articleList: ArticleInfo[]) {
179+
const _articleList = articleList.slice(0, 4)
180+
return (
181+
<>
182+
<wstack flexDirection="column">
183+
{_articleList.map((article, index) => (
184+
<Article article={article} sort={index + 1}></Article>
185+
))}
186+
</wstack>
187+
<wspacer></wspacer>
188+
<wspacer></wspacer>
189+
</>
190+
)
191+
}
192+
193+
// 渲染大尺寸
194+
renderLarge(articleList: ArticleInfo[]) {
195+
const _articleList = articleList.slice(0, 10)
196+
return (
197+
<>
198+
<wstack flexDirection="column">
199+
{_articleList.map((article, index) => (
200+
<Article article={article} sort={index + 1}></Article>
201+
))}
202+
</wstack>
203+
<wspacer></wspacer>
204+
<wspacer></wspacer>
205+
</>
206+
)
207+
}
208+
209+
// 显示菜单
210+
async showMenu() {
211+
const selectIndex = await showActionSheet({
212+
title: '菜单',
213+
itemList: ['登录', '设置手机号', '设置颜色', '设置透明背景', '预览组件'],
214+
})
215+
switch (selectIndex) {
216+
case 0:
217+
const {cancel: cancelLogin} = await showModal({
218+
title: '为什么要登录',
219+
content:
220+
'获取手机号码信息需要 cookie,而 cookie 不登录获取不到\n\n若 cookie 失效,再次登录即可\n\n登录完成后,自行关闭网页',
221+
confirmText: '去登录',
222+
})
223+
if (cancelLogin) return
224+
const loginUrl = 'https://uac.10010.com/oauth2/new_auth?display=wap&page_type=05'
225+
await WebView.loadURL(loginUrl, undefined, true)
226+
break
227+
case 1:
228+
break
229+
case 2:
230+
const {texts, cancel} = await showModal({
231+
title: '设置全局背景和颜色',
232+
content: '如果为空,则还原默认',
233+
inputItems: [
234+
{
235+
text: getStorage<string>('boxBg') || '',
236+
placeholder: '全局背景:可以是颜色、图链接',
237+
},
238+
{
239+
text: getStorage<string>('textColor') || '',
240+
placeholder: '这里填文字颜色',
241+
},
242+
],
243+
})
244+
if (cancel) return
245+
setStorage('boxBg', texts[0])
246+
setStorage('textColor', texts[1])
247+
await showNotification({title: '设置完成', sound: 'default'})
248+
break
249+
case 3:
250+
const img: Image | null = (await setTransparentBackground()) || null
251+
if (img) {
252+
setStorage('transparentBg', img)
253+
setStorage('boxBg', '透明背景')
254+
await showNotification({title: '设置透明背景成功', sound: 'default'})
255+
}
256+
break
257+
case 4:
258+
await showPreviewOptions(this.render.bind(this))
259+
break
260+
}
261+
}
262+
263+
// 获取手机卡数据
264+
async getPhoneData(phoneNumber: number): Promise<UsefulPhoneData[] | string> {
265+
if (!isLaunchInsideApp() && !getStorage('cookie')) {
266+
await showNotification({title: 'cookie 不存在,请先登录', sound: 'failure'})
267+
return 'cookie 不存在,请先登录'
268+
}
269+
const api = `https://wap.10010.com/mobileService/home/queryUserInfoSeven.htm?version=iphone_c@7.0403&desmobiel=${phoneNumber}&showType=3`
270+
const getPageInfo = async (): Promise<PageInfo> => {
271+
const webview = new WebView()
272+
await webview.loadURL(api)
273+
await webview.waitForLoad()
274+
const setCookie = `document.cookie = "${getStorage('cookie') || ''}"`
275+
const {phoneDatas, cookie, err} = (await webview.evaluateJavaScript(`
276+
let cookie = document.cookie
277+
let phoneDatas = {}
278+
let err = ''
279+
${isLaunchInsideApp() ? '' : setCookie}
280+
try {
281+
phoneDatas = JSON.parse(document.body.innerText)
282+
} catch (error) {
283+
err = error
284+
}
285+
Object.assign({}, {phoneDatas, cookie, err})
286+
`)) as PageInfo
287+
err && console.warn('获取数据出错', err)
288+
return {phoneDatas, cookie, err}
289+
}
290+
const {phoneDatas, cookie} = await getPageInfo()
291+
isLaunchInsideApp() && cookie && setStorage('cookie', cookie)
292+
let usefulPhoneData: UsefulPhoneData[] = []
293+
try {
294+
// 提取有用的信息
295+
usefulPhoneData = phoneDatas.data.dataList.map(info => {
296+
const present = info.usedTitle.replace(/(|)([\d\.]+)?\%/, (...args) => {
297+
return args[1] === '剩余' ? args[2] : 100 - args[2]
298+
})
299+
return {
300+
type: info.type,
301+
present: Number(present) > 100 ? 100 : Number(present),
302+
unit: info.unit,
303+
count: Number(info.number),
304+
label: info.remainTitle,
305+
}
306+
})
307+
} catch (err) {
308+
await showNotification({title: '获取联通卡信息失败', body: '检查一下网络,或重新登录', sound: 'failure'})
309+
return '获取联通卡信息失败\n检查一下网络,或重新登录'
310+
}
311+
return usefulPhoneData
312+
}
313+
// // 获取手机卡数据
314+
// async getPhoneData(phoneNumber: number): Promise<UsefulPhoneData[] | string> {
315+
// const api = `https://wap.10010.com/mobileService/home/queryUserInfoSeven.htm?version=iphone_c@7.0403&desmobiel=${phoneNumber}&showType=3`
316+
// if (isLaunchInsideApp()) {
317+
// const webview = new WebView()
318+
// await webview.loadURL(api)
319+
// await webview.waitForLoad()
320+
// const {cookie} = (await webview.evaluateJavaScript(`
321+
// let cookie = document.cookie
322+
// Object.assign({}, {cookie})
323+
// `)) as PageInfo
324+
// cookie && setStorage('cookie', cookie)
325+
// }
326+
// let usefulPhoneData: UsefulPhoneData[] = []
327+
// try {
328+
// const cookie = getStorage<string>('cookie')
329+
// if (!cookie) {
330+
// await showNotification({title: 'cookie 不存在,请先登录', sound: 'failure'})
331+
// return 'cookie 不存在,请先登录'
332+
// }
333+
// // 获取手机卡信息列表
334+
// const dataList: PhoneData[] =
335+
// (
336+
// await request<PhoneDatas>({
337+
// url: api,
338+
// dataType: 'text',
339+
// header: {
340+
// 'user-agent':
341+
// 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1',
342+
// cookie,
343+
// },
344+
// })
345+
// ).data?.data.dataList || []
346+
// // 提取有用的信息
347+
// usefulPhoneData = dataList.map(info => {
348+
// const present = info.usedTitle.replace(/(已用|剩余)([\d\.]+)?\%/, (...args) => {
349+
// return args[1] === '剩余' ? args[2] : 100 - args[2]
350+
// })
351+
// return {
352+
// type: info.type,
353+
// present: Number(present) > 100 ? 100 : Number(present),
354+
// unit: info.unit,
355+
// count: Number(info.number),
356+
// label: info.remainTitle,
357+
// }
358+
// })
359+
// } catch (err) {
360+
// await showNotification({title: '获取联通卡信息失败', body: '检查一下网络,或重新登录', sound: 'failure'})
361+
// return '获取联通卡信息失败\n检查一下网络,或重新登录'
362+
// }
363+
// return usefulPhoneData
364+
// }
365+
}
366+
367+
EndAwait(() => new China10010().init())

0 commit comments

Comments
 (0)