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 }  
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