11/**
2- * 今日热榜小部件
2+ * 联通话费流量查询小部件
33 */
44
55import {
@@ -14,6 +14,7 @@ import {
1414 sleep ,
1515} from '@app/lib/help'
1616import { FC } from 'react'
17+ import { WtextProps , WstackProps } from '@app/types/widget'
1718
1819/**手机卡数据列表*/
1920interface PhoneDatas {
@@ -27,7 +28,7 @@ interface PhoneData {
2728 pointUpdateTimeStamp : string
2829 paperwork4 : string
2930 buttonBacImageUrlBig : string
30- type : string
31+ type : PhoneDataType
3132 remainTitle : string
3233 buttonText7 : string
3334 buttonLinkMode : string
@@ -57,25 +58,13 @@ interface PhoneData {
5758 warningPointColor ?: string
5859}
5960
60- /**页面信息*/
61- interface PageInfo {
62- /**页面数据*/
63- phoneDatas : PhoneDatas
64-
65- /**cookie*/
66- cookie : string | null
67-
68- /**js执行的错误信息*/
69- err : string
70- }
71-
7261/**有用的手机卡数据*/
7362interface UsefulPhoneData {
7463 /**类型*/
75- type : string
64+ type : PhoneDataType
7665
7766 /**剩余百分比数字*/
78- present : number
67+ percent : number
7968
8069 /**单位*/
8170 unit : string
@@ -87,6 +76,39 @@ interface UsefulPhoneData {
8776 label : string
8877}
8978
79+ /**手机卡数据类型*/
80+ enum PhoneDataType {
81+ /**流量*/
82+ FLOW = 'flow' ,
83+
84+ /**话费*/
85+ FEE = 'fee' ,
86+
87+ /**语音*/
88+ VOICE = 'voice' ,
89+
90+ /**积分*/
91+ POINT = 'point' ,
92+
93+ /**信用分*/
94+ CREDIT = 'credit' ,
95+
96+ /**电子券*/
97+ WOPAY = 'woPay' ,
98+ }
99+
100+ const typeDesc : Record < PhoneDataType , string > = {
101+ [ PhoneDataType . FLOW ] : '流量' ,
102+ [ PhoneDataType . FEE ] : '话费' ,
103+ [ PhoneDataType . VOICE ] : '语音' ,
104+ [ PhoneDataType . POINT ] : '积分' ,
105+ [ PhoneDataType . CREDIT ] : '信用分' ,
106+ [ PhoneDataType . WOPAY ] : '电子券' ,
107+ }
108+
109+ // 格式化数字
110+ const formatNum = ( num : number ) => parseFloat ( Number ( num ) . toFixed ( 1 ) )
111+
90112const { setStorage, getStorage} = useStorage ( 'china10010-xiaoming' )
91113
92114/**默认背景颜色*/
@@ -117,7 +139,7 @@ class China10010 {
117139 await showNotification ( { title : '稍等片刻' , body : '小部件渲染中...' , sound : 'alert' } )
118140 }
119141 // 多久(毫秒)更新一次小部件(默认3分钟)
120- const updateInterval = 3 * 60 * 1000
142+ const updateInterval = 1 * 60 * 1000
121143
122144 // 渲染尺寸
123145 const size = config . widgetFamily
@@ -142,7 +164,6 @@ class China10010 {
142164 background = { typeof boxBg === 'string' && boxBg . match ( '透明背景' ) ? transparentBg : boxBg }
143165 >
144166 < wstack flexDirection = "column" padding = { [ 0 , 16 , 0 , 16 ] } >
145- < wspacer > </ wspacer >
146167 < wspacer > </ wspacer >
147168 { /* 标题和logo */ }
148169 < wstack verticalAlign = "center" >
@@ -153,12 +174,11 @@ class China10010 {
153174 borderRadius = { 4 }
154175 > </ wimage >
155176 < wspacer length = { 8 } > </ wspacer >
156- < wtext opacity = { 0.7 } font = { Font . boldSystemFont ( 16 ) } textColor = { textColor } >
177+ < wtext opacity = { 0.7 } font = { Font . boldSystemFont ( 14 ) } textColor = { textColor } >
157178 中国联通
158179 </ wtext >
159180 </ wstack >
160181 < wspacer > </ wspacer >
161- < wspacer > </ wspacer >
162182 { /* 内容 */ }
163183 { size === 'small' && this . renderSmall ( usefulPhoneDatas ) }
164184 { size === 'medium' && this . renderMedium ( usefulPhoneDatas ) }
@@ -170,27 +190,103 @@ class China10010 {
170190
171191 // 渲染小尺寸
172192 renderSmall ( usefulPhoneDatas : UsefulPhoneData [ ] ) {
193+ // 流量
194+ const flow = usefulPhoneDatas . find ( item => item . type === PhoneDataType . FLOW ) as UsefulPhoneData
195+ // 话费
196+ const fee = usefulPhoneDatas . find ( item => item . type === PhoneDataType . FEE ) as UsefulPhoneData
173197 return (
174198 < >
175- < wtext > hello</ wtext >
199+ < wtext textColor = { textColor } font = { Font . lightSystemFont ( 14 ) } >
200+ 剩余流量{ formatNum ( flow . count || 0 ) + flow . unit }
201+ </ wtext >
202+ < wspacer > </ wspacer >
203+ < wtext textColor = { textColor } font = { Font . lightSystemFont ( 14 ) } >
204+ 剩余话费{ formatNum ( fee . count || 0 ) + fee . unit }
205+ </ wtext >
206+ < wspacer > </ wspacer >
176207 </ >
177208 )
178209 }
179210
180211 // 渲染中尺寸
181212 renderMedium ( usefulPhoneDatas : UsefulPhoneData [ ] ) {
182- return (
183- < >
184- < wtext > hello</ wtext >
185- </ >
186- )
213+ const showDataType : PhoneDataType [ ] = [ PhoneDataType . FLOW , PhoneDataType . FEE , PhoneDataType . VOICE ]
214+ return this . renderLarge ( usefulPhoneDatas . filter ( data => showDataType . indexOf ( data . type ) >= 0 ) )
187215 }
188216
189217 // 渲染大尺寸
190218 renderLarge ( usefulPhoneDatas : UsefulPhoneData [ ] ) {
219+ /**进度条*/
220+ const Progress : FC < {
221+ color : WstackProps [ 'background' ]
222+ bgcolor : WstackProps [ 'background' ]
223+ progress : number
224+ width : number
225+ height : number
226+ borderRadius ?: number
227+ } > = ( { ...props } ) => {
228+ const { color, bgcolor, progress, width, height, borderRadius = 0 } = props
229+ return (
230+ < wstack background = { bgcolor } width = { width } height = { height } borderRadius = { borderRadius } >
231+ < wstack background = { color } height = { height } width = { width * progress } >
232+ < wtext > </ wtext >
233+ </ wstack >
234+ { progress < 1 && < wspacer > </ wspacer > }
235+ </ wstack >
236+ )
237+ }
238+
239+ /**表格格子*/
240+ const TableGrid : FC <
241+ WtextProps & { text : string | React . ReactNode ; width : number ; align : 'left' | 'center' | 'right' }
242+ > = ( { text, width, align, ...props } ) => (
243+ < wstack width = { width } >
244+ { ( align === 'center' || align === 'right' ) && < wspacer > </ wspacer > }
245+ { typeof text === 'string' ? (
246+ < wtext font = { 14 } textColor = { textColor } { ...props } >
247+ { text }
248+ </ wtext >
249+ ) : (
250+ text
251+ ) }
252+ { ( align === 'center' || align === 'left' ) && < wspacer > </ wspacer > }
253+ </ wstack >
254+ )
255+
256+ /**表格行*/
257+ const TableRow : FC < WtextProps & { texts : ( string | React . ReactNode ) [ ] } > = ( { texts, ...props } ) => (
258+ < wstack verticalAlign = "center" >
259+ < TableGrid text = { texts [ 0 ] } { ...props } width = { 60 } align = "left" > </ TableGrid >
260+ < wspacer > </ wspacer >
261+ < TableGrid text = { texts [ 1 ] } { ...props } width = { 90 } align = "center" > </ TableGrid >
262+ < wspacer > </ wspacer >
263+ < TableGrid text = { texts [ 2 ] } { ...props } width = { 70 } align = "right" > </ TableGrid >
264+ </ wstack >
265+ )
191266 return (
192267 < >
193- < wtext > hello</ wtext >
268+ < TableRow texts = { [ '类型' , '剩余百分比' , '剩余量' ] } > </ TableRow >
269+ { usefulPhoneDatas . map ( item => (
270+ < >
271+ < wspacer > </ wspacer >
272+ < TableRow
273+ font = { Font . lightSystemFont ( 14 ) }
274+ texts = { [
275+ typeDesc [ item . type ] ,
276+ Progress ( {
277+ color : '#39b54a' ,
278+ bgcolor : '#dddddd' ,
279+ width : 80 ,
280+ height : 10 ,
281+ borderRadius : 5 ,
282+ progress : formatNum ( item . percent ) / 100 ,
283+ } ) ,
284+ formatNum ( item . count ) + item . unit ,
285+ ] }
286+ > </ TableRow >
287+ </ >
288+ ) ) }
289+ < wspacer > </ wspacer >
194290 </ >
195291 )
196292 }
@@ -199,14 +295,14 @@ class China10010 {
199295 async showMenu ( ) {
200296 const selectIndex = await showActionSheet ( {
201297 title : '菜单' ,
202- itemList : [ '登录 ' , '设置手机号和cookie' , '设置颜色' , '设置透明背景' , '预览组件' ] ,
298+ itemList : [ '登录获取cookie ' , '设置手机号和cookie' , '设置颜色' , '设置透明背景' , '预览组件' ] ,
203299 } )
204300 switch ( selectIndex ) {
205301 case 0 :
206302 const { cancel : cancelLogin } = await showModal ( {
207303 title : '为什么要登录' ,
208304 content :
209- '获取手机号码信息需要 cookie,而 cookie 不登录获取不到\n\n若 cookie 失效,再次登录即可\n\ n登录完成后,关闭网页,网页会再自动打开\n\n此时点击底部按钮复制 cookie ,然后关网页去设置cookie' ,
305+ '获取手机号码信息需要 cookie,而 cookie 不登录获取不到\n\n登录完成后,关闭网页,网页会再自动打开\n\n此时点击底部按钮复制 cookie ,然后关网页去设置cookie\n\n若 cookie 失效,再次登录复制即可 ' ,
210306 confirmText : '去登录' ,
211307 } )
212308 if ( cancelLogin ) return
@@ -319,9 +415,9 @@ class China10010 {
319415 if ( ! isLaunchInsideApp ( ) && ! getStorage ( 'cookie' ) ) return 'cookie 不存在,请先登录'
320416 const api = `https://wap.10010.com/mobileService/home/queryUserInfoSeven.htm?version=iphone_c@7.0403&desmobiel=${ phoneNumber } &showType=3`
321417 // 获取手机卡信息列表
322- const res = await request < PhoneDatas > ( {
418+ const res = await request < string > ( {
323419 url : api ,
324- dataType : 'json ' ,
420+ dataType : 'text ' ,
325421 header : {
326422 'user-agent' :
327423 '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' ,
@@ -331,15 +427,15 @@ class China10010 {
331427 // isLaunchInsideApp() && cookie && setStorage('cookie', cookie)
332428 let usefulPhoneDatas : UsefulPhoneData [ ] = [ ]
333429 try {
334- const phoneDatas : PhoneData [ ] = res . data ? .data . dataList || [ ]
430+ const phoneDatas : PhoneData [ ] = ( JSON . parse ( res . data || '' ) as PhoneDatas ) . data . dataList || [ ]
335431 // 提取有用的信息
336432 usefulPhoneDatas = phoneDatas . map ( info => {
337- const present = info . usedTitle . replace ( / ( 已 用 | 剩 余 ) ( [ \d \. ] + ) ? \% / , ( ...args ) => {
433+ const percent = info . usedTitle . replace ( / ( 已 用 | 剩 余 ) ( [ \d \. ] + ) ? \% / , ( ...args ) => {
338434 return args [ 1 ] === '剩余' ? args [ 2 ] : 100 - args [ 2 ]
339435 } )
340436 return {
341437 type : info . type ,
342- present : Number ( present ) > 100 ? 100 : Number ( present ) ,
438+ percent : Number ( percent ) > 100 ? 100 : Number ( percent ) ,
343439 unit : info . unit ,
344440 count : Number ( info . number ) ,
345441 label : info . remainTitle ,
@@ -352,58 +448,6 @@ class China10010 {
352448 }
353449 return usefulPhoneDatas
354450 }
355- // // 获取手机卡数据
356- // async getPhoneData(phoneNumber: number): Promise<UsefulPhoneData[] | string> {
357- // const api = `https://wap.10010.com/mobileService/home/queryUserInfoSeven.htm?version=iphone_c@7.0403&desmobiel=${phoneNumber}&showType=3`
358- // if (isLaunchInsideApp()) {
359- // const webview = new WebView()
360- // await webview.loadURL(api)
361- // await webview.waitForLoad()
362- // const {cookie} = (await webview.evaluateJavaScript(`
363- // let cookie = document.cookie
364- // Object.assign({}, {cookie})
365- // `)) as PageInfo
366- // cookie && setStorage('cookie', cookie)
367- // }
368- // let usefulPhoneData: UsefulPhoneData[] = []
369- // try {
370- // const cookie = getStorage<string>('cookie')
371- // if (!cookie) {
372- // await showNotification({title: 'cookie 不存在,请先登录', sound: 'failure'})
373- // return 'cookie 不存在,请先登录'
374- // }
375- // // 获取手机卡信息列表
376- // const dataList: PhoneData[] =
377- // (
378- // await request<PhoneDatas>({
379- // url: api,
380- // dataType: 'text',
381- // header: {
382- // 'user-agent':
383- // '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',
384- // cookie,
385- // },
386- // })
387- // ).data?.data.dataList || []
388- // // 提取有用的信息
389- // usefulPhoneData = dataList.map(info => {
390- // const present = info.usedTitle.replace(/(已用|剩余)([\d\.]+)?\%/, (...args) => {
391- // return args[1] === '剩余' ? args[2] : 100 - args[2]
392- // })
393- // return {
394- // type: info.type,
395- // present: Number(present) > 100 ? 100 : Number(present),
396- // unit: info.unit,
397- // count: Number(info.number),
398- // label: info.remainTitle,
399- // }
400- // })
401- // } catch (err) {
402- // await showNotification({title: '获取联通卡信息失败', body: '检查一下网络,或重新登录', sound: 'failure'})
403- // return '获取联通卡信息失败\n检查一下网络,或重新登录'
404- // }
405- // return usefulPhoneData
406- // }
407451}
408452
409453EndAwait ( ( ) => new China10010 ( ) . init ( ) )
0 commit comments