fanmingyou3_wd

把DevEco3.1的PeopleDaily_Harmony中的代码合并到DevEco4.0的sight_harmony中

Showing 103 changed files with 3266 additions and 1057 deletions
@@ -4,12 +4,15 @@ import UIAbility from '@ohos.app.ability.UIAbility'; @@ -4,12 +4,15 @@ import UIAbility from '@ohos.app.ability.UIAbility';
4 import Want from '@ohos.app.ability.Want'; 4 import Want from '@ohos.app.ability.Want';
5 import window from '@ohos.window'; 5 import window from '@ohos.window';
6 import { registerRouter } from 'wdRouter'; 6 import { registerRouter } from 'wdRouter';
7 -import { WindowModel } from 'wdKit'; 7 +import { SPHelper, WindowModel } from 'wdKit';
  8 +import { WDHttp } from 'wdNetwork'
8 9
9 export default class EntryAbility extends UIAbility { 10 export default class EntryAbility extends UIAbility {
10 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { 11 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  12 + SPHelper.init(this.context);
11 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 13 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
12 registerRouter(); 14 registerRouter();
  15 + WDHttp.initHttpHeader()
13 } 16 }
14 17
15 onDestroy(): void { 18 onDestroy(): void {
@@ -29,7 +32,7 @@ export default class EntryAbility extends UIAbility { @@ -29,7 +32,7 @@ export default class EntryAbility extends UIAbility {
29 .catch((err: Error) => { 32 .catch((err: Error) => {
30 hilog.error(0x0000, 'testTag', `setPreferredOrientation catch, error error.name : ${err.name}, error.message:${err.message}`); 33 hilog.error(0x0000, 'testTag', `setPreferredOrientation catch, error error.name : ${err.name}, error.message:${err.message}`);
31 }) 34 })
32 - windowStage.loadContent('pages/Index', (err, data) => { 35 + windowStage.loadContent('pages/MainPage', (err, data) => {
33 if (err.code) { 36 if (err.code) {
34 hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); 37 hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
35 return; 38 return;
1 -import { BottomNavBean } from 'wdBean';  
2 -import { BottomNavigationComponent, PageViewModel } from 'wdComponent'; 1 +import { BottomNavigationComponent} from 'wdComponent';
3 import { BreakpointConstants } from 'wdConstant'; 2 import { BreakpointConstants } from 'wdConstant';
  3 +
4 import { BreakpointSystem, Logger } from 'wdKit'; 4 import { BreakpointSystem, Logger } from 'wdKit';
5 5
6 -const TAG = 'Index'; 6 +const TAG = 'MainPage';
7 7
8 @Entry 8 @Entry
9 @Component 9 @Component
10 -struct Index { 10 +struct MainPage {
11 private breakpointSystem: BreakpointSystem = new BreakpointSystem() 11 private breakpointSystem: BreakpointSystem = new BreakpointSystem()
12 @StorageLink('currentBreakpoint') @Watch('watchCurrentBreakpoint') currentBreakpoint: string = BreakpointConstants.BREAKPOINT_XS; 12 @StorageLink('currentBreakpoint') @Watch('watchCurrentBreakpoint') currentBreakpoint: string = BreakpointConstants.BREAKPOINT_XS;
13 - @State bottomNavList: BottomNavBean[] = []  
14 13
15 watchCurrentBreakpoint() { 14 watchCurrentBreakpoint() {
16 Logger.info(TAG, `watchCurrentBreakpoint, this.currentBreakpoint: ${this.currentBreakpoint}`); 15 Logger.info(TAG, `watchCurrentBreakpoint, this.currentBreakpoint: ${this.currentBreakpoint}`);
17 } 16 }
18 17
19 - build() {  
20 - Column() {  
21 - BottomNavigationComponent({ bottomNavList: this.bottomNavList })  
22 - }  
23 - }  
24 -  
25 aboutToAppear() { 18 aboutToAppear() {
26 this.breakpointSystem.register() 19 this.breakpointSystem.register()
27 - let bottomNav = PageViewModel.getBottomNavData(getContext(this))  
28 - if (bottomNav) {  
29 - Logger.info(TAG, `aboutToAppear, bottomNav.length: ${bottomNav.length}`);  
30 - this.bottomNavList = bottomNav  
31 - } 20 + Logger.info(TAG, `aboutToAppear `);
32 } 21 }
33 22
34 aboutToDisappear() { 23 aboutToDisappear() {
@@ -47,4 +36,10 @@ struct Index { @@ -47,4 +36,10 @@ struct Index {
47 onBackPress() { 36 onBackPress() {
48 Logger.info(TAG, 'onBackPress'); 37 Logger.info(TAG, 'onBackPress');
49 } 38 }
  39 +
  40 + build() {
  41 + Column() {
  42 + BottomNavigationComponent()
  43 + }
  44 + }
50 } 45 }
1 { 1 {
2 "src": [ 2 "src": [
3 - "pages/Index", 3 + "pages/MainPage",
4 "pages/web/DefaultWebPage", 4 "pages/web/DefaultWebPage",
5 "pages/ENewspaper" 5 "pages/ENewspaper"
6 ] 6 ]
@@ -4,39 +4,40 @@ @@ -4,39 +4,40 @@
4 "backgroundColor": "#FFFFFF", 4 "backgroundColor": "#FFFFFF",
5 "bottomNavList": [ 5 "bottomNavList": [
6 { 6 {
7 - "backgroundUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/2e1d5f235d1a44cfb9fc120e8596c56b.png",  
8 - "channelChooseActionUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231227/vod/display/7c92f5b2a08b4a65aa9da13e66d5ad4a.pag",  
9 - "channelChooseCColor": "#666666",  
10 - "channelChooseColor": "#222222",  
11 - "channelMoreColor": "#666666", 7 + "backgroundUrl": "",
  8 + "channelChooseActionUrl": "",
  9 + "channelChooseCColor": "",
  10 + "channelChooseColor": "",
  11 + "channelMoreColor": "",
12 "extraData": "{\"haveSearch\":\"1\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}", 12 "extraData": "{\"haveSearch\":\"1\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}",
13 - "homePageColor": "#FFFFF",  
14 - "icon": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/0dc20f38da09405ea0ab675d700bc2ce.png",  
15 - "iconC": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/e162a5d3401045f298c237f1c795c015.gif", 13 + "homePageColor": "",
  14 + "icon": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/a59ee3978357490bb58cbc378d70b557.png",
  15 + "iconC": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/213ab95c788d41f2838771e1eaaba62d.png",
16 "id": 201, 16 "id": 201,
17 "immersiveIconCUrl": "", 17 "immersiveIconCUrl": "",
18 "immersiveIconUrl": "", 18 "immersiveIconUrl": "",
19 - "immersiveNameCColor": "#FFFFFF",  
20 - "immersiveNameColor": "#FFFFFF",  
21 - "logoUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231229/image/display/51d568f9af05421f9754a2c08906dc42.png",  
22 - "morningAndEveningUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/0f37cc0c86194c969d2143f85c056c9c.png", 19 + "immersiveNameCColor": "",
  20 + "immersiveNameColor": "",
  21 + "logoUrl": "",
  22 + "morningAndEveningUrl": "",
23 "name": "新闻", 23 "name": "新闻",
24 - "nameCColor": "#ED2800", 24 + "nameCColor": "#CB0000",
25 "nameColor": "#999999", 25 "nameColor": "#999999",
26 "nightIconCUrl": "", 26 "nightIconCUrl": "",
27 "nightIconUrl": "", 27 "nightIconUrl": "",
28 "nightNameCColor": "", 28 "nightNameCColor": "",
29 "nightNameColor": "", 29 "nightNameColor": "",
30 - "noticeColor": "#FFFFFF", 30 + "noticeColor": "",
31 "pageId": null, 31 "pageId": null,
32 "pageType": null, 32 "pageType": null,
33 - "searchBothColor": "#666666",  
34 - "searchUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/2f2a9b3af5334eac8d7c3b6007240b83.png", 33 + "searchBothColor": "",
  34 + "searchUrl": "",
35 "sortValue": 1, 35 "sortValue": 1,
36 - "statusBarColor": 1, 36 + "statusBarColor": null,
37 "topNavChannelList": [ 37 "topNavChannelList": [
38 { 38 {
39 - "channelId": 2002, 39 + "channelId": 2001,
  40 + "channelStrategy": 1,
40 "channelStyle": 2, 41 "channelStyle": 2,
41 "channelType": 1, 42 "channelType": 1,
42 "defaultPermitted": 1, 43 "defaultPermitted": 1,
@@ -53,21 +54,22 @@ @@ -53,21 +54,22 @@
53 "moreChannel": "0", 54 "moreChannel": "0",
54 "movePermitted": 0, 55 "movePermitted": 0,
55 "myChannel": "0", 56 "myChannel": "0",
56 - "name": "热点", 57 + "name": "推荐",
57 "num": 1, 58 "num": 1,
58 - "pageId": 20012, 59 + "pageId": 20011,
59 "pageType": "", 60 "pageType": "",
60 "underlineCColor": "" 61 "underlineCColor": ""
61 }, 62 },
62 { 63 {
63 - "channelId": 2001, 64 + "channelId": 2002,
  65 + "channelStrategy": 2,
64 "channelStyle": 2, 66 "channelStyle": 2,
65 "channelType": 1, 67 "channelType": 1,
66 "defaultPermitted": 1, 68 "defaultPermitted": 1,
67 "delPermitted": 0, 69 "delPermitted": 0,
68 "fontCColor": "#FFFFFF", 70 "fontCColor": "#FFFFFF",
69 "fontColor": "#F9AB99", 71 "fontColor": "#F9AB99",
70 - "headlinesOn": 0, 72 + "headlinesOn": 1,
71 "homeChannel": "0", 73 "homeChannel": "0",
72 "iconCUrl": "", 74 "iconCUrl": "",
73 "iconCUrlSize": "", 75 "iconCUrlSize": "",
@@ -77,15 +79,16 @@ @@ -77,15 +79,16 @@
77 "moreChannel": "0", 79 "moreChannel": "0",
78 "movePermitted": 0, 80 "movePermitted": 0,
79 "myChannel": "0", 81 "myChannel": "0",
80 - "name": "推荐", 82 + "name": "热点",
81 "num": 2, 83 "num": 2,
82 - "pageId": 20011, 84 + "pageId": 20012,
83 "pageType": "", 85 "pageType": "",
84 "underlineCColor": "" 86 "underlineCColor": ""
85 }, 87 },
86 { 88 {
87 - "channelId": 2009,  
88 - "channelStyle": 2, 89 + "channelId": 2066,
  90 + "channelStrategy": 2,
  91 + "channelStyle": 3,
89 "channelType": 1, 92 "channelType": 1,
90 "defaultPermitted": 0, 93 "defaultPermitted": 0,
91 "delPermitted": 1, 94 "delPermitted": 1,
@@ -101,14 +104,15 @@ @@ -101,14 +104,15 @@
101 "moreChannel": "0", 104 "moreChannel": "0",
102 "movePermitted": 1, 105 "movePermitted": 1,
103 "myChannel": "0", 106 "myChannel": "0",
104 - "name": "社会", 107 + "name": "播报",
105 "num": 3, 108 "num": 3,
106 - "pageId": 20019, 109 + "pageId": 21003,
107 "pageType": "", 110 "pageType": "",
108 "underlineCColor": "" 111 "underlineCColor": ""
109 }, 112 },
110 { 113 {
111 - "channelId": 2066, 114 + "channelId": 2006,
  115 + "channelStrategy": 2,
112 "channelStyle": 3, 116 "channelStyle": 3,
113 "channelType": 1, 117 "channelType": 1,
114 "defaultPermitted": 0, 118 "defaultPermitted": 0,
@@ -125,14 +129,15 @@ @@ -125,14 +129,15 @@
125 "moreChannel": "0", 129 "moreChannel": "0",
126 "movePermitted": 1, 130 "movePermitted": 1,
127 "myChannel": "0", 131 "myChannel": "0",
128 - "name": "播报", 132 + "name": "版面",
129 "num": 4, 133 "num": 4,
130 - "pageId": 21003, 134 + "pageId": 20016,
131 "pageType": "", 135 "pageType": "",
132 "underlineCColor": "" 136 "underlineCColor": ""
133 }, 137 },
134 { 138 {
135 - "channelId": 2012, 139 + "channelId": 2065,
  140 + "channelStrategy": 2,
136 "channelStyle": 2, 141 "channelStyle": 2,
137 "channelType": 1, 142 "channelType": 1,
138 "defaultPermitted": 0, 143 "defaultPermitted": 0,
@@ -147,16 +152,17 @@ @@ -147,16 +152,17 @@
147 "iconUrlSize": "", 152 "iconUrlSize": "",
148 "localChannel": "0", 153 "localChannel": "0",
149 "moreChannel": "0", 154 "moreChannel": "0",
150 - "movePermitted": 0, 155 + "movePermitted": 1,
151 "myChannel": "0", 156 "myChannel": "0",
152 - "name": "文化", 157 + "name": "三农",
153 "num": 5, 158 "num": 5,
154 - "pageId": 20022, 159 + "pageId": 21002,
155 "pageType": "", 160 "pageType": "",
156 "underlineCColor": "" 161 "underlineCColor": ""
157 }, 162 },
158 { 163 {
159 - "channelId": 2007, 164 + "channelId": 2063,
  165 + "channelStrategy": 2,
160 "channelStyle": 2, 166 "channelStyle": 2,
161 "channelType": 1, 167 "channelType": 1,
162 "defaultPermitted": 0, 168 "defaultPermitted": 0,
@@ -173,38 +179,15 @@ @@ -173,38 +179,15 @@
173 "moreChannel": "0", 179 "moreChannel": "0",
174 "movePermitted": 1, 180 "movePermitted": 1,
175 "myChannel": "0", 181 "myChannel": "0",
176 - "name": "镜头", 182 + "name": "两会",
177 "num": 6, 183 "num": 6,
178 - "pageId": 20017,  
179 - "pageType": "",  
180 - "underlineCColor": ""  
181 - },  
182 - {  
183 - "channelId": 2006,  
184 - "channelStyle": 3,  
185 - "channelType": 1,  
186 - "defaultPermitted": 0,  
187 - "delPermitted": 1,  
188 - "fontCColor": "#FFFFFF",  
189 - "fontColor": "#F9AB99",  
190 - "headlinesOn": 0,  
191 - "homeChannel": "0",  
192 - "iconCUrl": "",  
193 - "iconCUrlSize": "",  
194 - "iconUrl": "",  
195 - "iconUrlSize": "",  
196 - "localChannel": "0",  
197 - "moreChannel": "0",  
198 - "movePermitted": 1,  
199 - "myChannel": "0",  
200 - "name": "版面",  
201 - "num": 7,  
202 - "pageId": 20016, 184 + "pageId": 21000,
203 "pageType": "", 185 "pageType": "",
204 "underlineCColor": "" 186 "underlineCColor": ""
205 }, 187 },
206 { 188 {
207 "channelId": 2015, 189 "channelId": 2015,
  190 + "channelStrategy": 1,
208 "channelStyle": 2, 191 "channelStyle": 2,
209 "channelType": 1, 192 "channelType": 1,
210 "defaultPermitted": 0, 193 "defaultPermitted": 0,
@@ -214,9 +197,9 @@ @@ -214,9 +197,9 @@
214 "headlinesOn": 0, 197 "headlinesOn": 0,
215 "homeChannel": "0", 198 "homeChannel": "0",
216 "iconCUrl": "", 199 "iconCUrl": "",
217 - "iconCUrlSize": "210*60", 200 + "iconCUrlSize": "",
218 "iconUrl": "", 201 "iconUrl": "",
219 - "iconUrlSize": "210*60", 202 + "iconUrlSize": "",
220 "localChannel": "0", 203 "localChannel": "0",
221 "moreChannel": "0", 204 "moreChannel": "0",
222 "movePermitted": 1, 205 "movePermitted": 1,
@@ -228,11 +211,12 @@ @@ -228,11 +211,12 @@
228 "underlineCColor": "" 211 "underlineCColor": ""
229 }, 212 },
230 { 213 {
231 - "channelId": 2063, 214 + "channelId": 2003,
  215 + "channelStrategy": 2,
232 "channelStyle": 2, 216 "channelStyle": 2,
233 "channelType": 1, 217 "channelType": 1,
234 "defaultPermitted": 0, 218 "defaultPermitted": 0,
235 - "delPermitted": 0, 219 + "delPermitted": 1,
236 "fontCColor": "#FFFFFF", 220 "fontCColor": "#FFFFFF",
237 "fontColor": "#F9AB99", 221 "fontColor": "#F9AB99",
238 "headlinesOn": 0, 222 "headlinesOn": 0,
@@ -245,14 +229,15 @@ @@ -245,14 +229,15 @@
245 "moreChannel": "0", 229 "moreChannel": "0",
246 "movePermitted": 1, 230 "movePermitted": 1,
247 "myChannel": "0", 231 "myChannel": "0",
248 - "name": "两会", 232 + "name": "锐评",
249 "num": 9, 233 "num": 9,
250 - "pageId": 21000, 234 + "pageId": 20013,
251 "pageType": "", 235 "pageType": "",
252 "underlineCColor": "" 236 "underlineCColor": ""
253 }, 237 },
254 { 238 {
255 - "channelId": 2064, 239 + "channelId": 2011,
  240 + "channelStrategy": 1,
256 "channelStyle": 2, 241 "channelStyle": 2,
257 "channelType": 1, 242 "channelType": 1,
258 "defaultPermitted": 0, 243 "defaultPermitted": 0,
@@ -269,14 +254,15 @@ @@ -269,14 +254,15 @@
269 "moreChannel": "0", 254 "moreChannel": "0",
270 "movePermitted": 1, 255 "movePermitted": 1,
271 "myChannel": "0", 256 "myChannel": "0",
272 - "name": "二十大", 257 + "name": "体育",
273 "num": 10, 258 "num": 10,
274 - "pageId": 21001, 259 + "pageId": 20021,
275 "pageType": "", 260 "pageType": "",
276 "underlineCColor": "" 261 "underlineCColor": ""
277 }, 262 },
278 { 263 {
279 - "channelId": 2003, 264 + "channelId": 2005,
  265 + "channelStrategy": 2,
280 "channelStyle": 2, 266 "channelStyle": 2,
281 "channelType": 1, 267 "channelType": 1,
282 "defaultPermitted": 0, 268 "defaultPermitted": 0,
@@ -293,14 +279,15 @@ @@ -293,14 +279,15 @@
293 "moreChannel": "0", 279 "moreChannel": "0",
294 "movePermitted": 1, 280 "movePermitted": 1,
295 "myChannel": "0", 281 "myChannel": "0",
296 - "name": "锐评",  
297 - "num": 11,  
298 - "pageId": 20013, 282 + "name": "文件",
  283 + "num": 12,
  284 + "pageId": 20015,
299 "pageType": "", 285 "pageType": "",
300 "underlineCColor": "" 286 "underlineCColor": ""
301 }, 287 },
302 { 288 {
303 - "channelId": 2011, 289 + "channelId": 2016,
  290 + "channelStrategy": 2,
304 "channelStyle": 2, 291 "channelStyle": 2,
305 "channelType": 1, 292 "channelType": 1,
306 "defaultPermitted": 0, 293 "defaultPermitted": 0,
@@ -317,14 +304,15 @@ @@ -317,14 +304,15 @@
317 "moreChannel": "0", 304 "moreChannel": "0",
318 "movePermitted": 1, 305 "movePermitted": 1,
319 "myChannel": "0", 306 "myChannel": "0",
320 - "name": "体育",  
321 - "num": 12,  
322 - "pageId": 20021, 307 + "name": "乡村振兴",
  308 + "num": 13,
  309 + "pageId": 20026,
323 "pageType": "", 310 "pageType": "",
324 "underlineCColor": "" 311 "underlineCColor": ""
325 }, 312 },
326 { 313 {
327 - "channelId": 2005, 314 + "channelId": 2007,
  315 + "channelStrategy": 2,
328 "channelStyle": 2, 316 "channelStyle": 2,
329 "channelType": 1, 317 "channelType": 1,
330 "defaultPermitted": 0, 318 "defaultPermitted": 0,
@@ -341,14 +329,15 @@ @@ -341,14 +329,15 @@
341 "moreChannel": "0", 329 "moreChannel": "0",
342 "movePermitted": 1, 330 "movePermitted": 1,
343 "myChannel": "0", 331 "myChannel": "0",
344 - "name": "文件", 332 + "name": "镜头",
345 "num": 14, 333 "num": 14,
346 - "pageId": 20015, 334 + "pageId": 20017,
347 "pageType": "", 335 "pageType": "",
348 "underlineCColor": "" 336 "underlineCColor": ""
349 }, 337 },
350 { 338 {
351 - "channelId": 2065, 339 + "channelId": 2009,
  340 + "channelStrategy": 2,
352 "channelStyle": 2, 341 "channelStyle": 2,
353 "channelType": 1, 342 "channelType": 1,
354 "defaultPermitted": 0, 343 "defaultPermitted": 0,
@@ -365,14 +354,15 @@ @@ -365,14 +354,15 @@
365 "moreChannel": "0", 354 "moreChannel": "0",
366 "movePermitted": 1, 355 "movePermitted": 1,
367 "myChannel": "0", 356 "myChannel": "0",
368 - "name": "三农",  
369 - "num": 15,  
370 - "pageId": 21002, 357 + "name": "社会",
  358 + "num": 16,
  359 + "pageId": 20019,
371 "pageType": "", 360 "pageType": "",
372 "underlineCColor": "" 361 "underlineCColor": ""
373 }, 362 },
374 { 363 {
375 - "channelId": 2016, 364 + "channelId": 2010,
  365 + "channelStrategy": 1,
376 "channelStyle": 2, 366 "channelStyle": 2,
377 "channelType": 1, 367 "channelType": 1,
378 "defaultPermitted": 0, 368 "defaultPermitted": 0,
@@ -389,14 +379,15 @@ @@ -389,14 +379,15 @@
389 "moreChannel": "0", 379 "moreChannel": "0",
390 "movePermitted": 1, 380 "movePermitted": 1,
391 "myChannel": "0", 381 "myChannel": "0",
392 - "name": "乡村振兴",  
393 - "num": 16,  
394 - "pageId": 20026, 382 + "name": "财经",
  383 + "num": 17,
  384 + "pageId": 20020,
395 "pageType": "", 385 "pageType": "",
396 "underlineCColor": "" 386 "underlineCColor": ""
397 }, 387 },
398 { 388 {
399 - "channelId": 2010, 389 + "channelId": 2012,
  390 + "channelStrategy": 2,
400 "channelStyle": 2, 391 "channelStyle": 2,
401 "channelType": 1, 392 "channelType": 1,
402 "defaultPermitted": 0, 393 "defaultPermitted": 0,
@@ -411,16 +402,17 @@ @@ -411,16 +402,17 @@
411 "iconUrlSize": "", 402 "iconUrlSize": "",
412 "localChannel": "0", 403 "localChannel": "0",
413 "moreChannel": "0", 404 "moreChannel": "0",
414 - "movePermitted": 1, 405 + "movePermitted": 0,
415 "myChannel": "0", 406 "myChannel": "0",
416 - "name": "财经", 407 + "name": "文化",
417 "num": 18, 408 "num": 18,
418 - "pageId": 20020, 409 + "pageId": 20022,
419 "pageType": "", 410 "pageType": "",
420 "underlineCColor": "" 411 "underlineCColor": ""
421 }, 412 },
422 { 413 {
423 "channelId": 2013, 414 "channelId": 2013,
  415 + "channelStrategy": 2,
424 "channelStyle": 2, 416 "channelStyle": 2,
425 "channelType": 1, 417 "channelType": 1,
426 "defaultPermitted": 0, 418 "defaultPermitted": 0,
@@ -445,6 +437,7 @@ @@ -445,6 +437,7 @@
445 }, 437 },
446 { 438 {
447 "channelId": 2017, 439 "channelId": 2017,
  440 + "channelStrategy": 2,
448 "channelStyle": 2, 441 "channelStyle": 2,
449 "channelType": 1, 442 "channelType": 1,
450 "defaultPermitted": 0, 443 "defaultPermitted": 0,
@@ -469,6 +462,7 @@ @@ -469,6 +462,7 @@
469 }, 462 },
470 { 463 {
471 "channelId": 2014, 464 "channelId": 2014,
  465 + "channelStrategy": 1,
472 "channelStyle": 2, 466 "channelStyle": 2,
473 "channelType": 1, 467 "channelType": 1,
474 "defaultPermitted": 0, 468 "defaultPermitted": 0,
@@ -493,6 +487,7 @@ @@ -493,6 +487,7 @@
493 }, 487 },
494 { 488 {
495 "channelId": 2018, 489 "channelId": 2018,
  490 + "channelStrategy": 1,
496 "channelStyle": 2, 491 "channelStyle": 2,
497 "channelType": 1, 492 "channelType": 1,
498 "defaultPermitted": 0, 493 "defaultPermitted": 0,
@@ -517,6 +512,7 @@ @@ -517,6 +512,7 @@
517 }, 512 },
518 { 513 {
519 "channelId": 2019, 514 "channelId": 2019,
  515 + "channelStrategy": 1,
520 "channelStyle": 2, 516 "channelStyle": 2,
521 "channelType": 1, 517 "channelType": 1,
522 "defaultPermitted": 0, 518 "defaultPermitted": 0,
@@ -541,6 +537,7 @@ @@ -541,6 +537,7 @@
541 }, 537 },
542 { 538 {
543 "channelId": 2027, 539 "channelId": 2027,
  540 + "channelStrategy": 2,
544 "channelStyle": 2, 541 "channelStyle": 2,
545 "channelType": 2, 542 "channelType": 2,
546 "defaultPermitted": 0, 543 "defaultPermitted": 0,
@@ -565,6 +562,7 @@ @@ -565,6 +562,7 @@
565 }, 562 },
566 { 563 {
567 "channelId": 2029, 564 "channelId": 2029,
  565 + "channelStrategy": 2,
568 "channelStyle": 2, 566 "channelStyle": 2,
569 "channelType": 2, 567 "channelType": 2,
570 "defaultPermitted": 0, 568 "defaultPermitted": 0,
@@ -589,6 +587,7 @@ @@ -589,6 +587,7 @@
589 }, 587 },
590 { 588 {
591 "channelId": 2030, 589 "channelId": 2030,
  590 + "channelStrategy": 2,
592 "channelStyle": 2, 591 "channelStyle": 2,
593 "channelType": 2, 592 "channelType": 2,
594 "defaultPermitted": 0, 593 "defaultPermitted": 0,
@@ -613,6 +612,7 @@ @@ -613,6 +612,7 @@
613 }, 612 },
614 { 613 {
615 "channelId": 2031, 614 "channelId": 2031,
  615 + "channelStrategy": 1,
616 "channelStyle": 2, 616 "channelStyle": 2,
617 "channelType": 2, 617 "channelType": 2,
618 "defaultPermitted": 0, 618 "defaultPermitted": 0,
@@ -637,6 +637,7 @@ @@ -637,6 +637,7 @@
637 }, 637 },
638 { 638 {
639 "channelId": 2032, 639 "channelId": 2032,
  640 + "channelStrategy": 2,
640 "channelStyle": 2, 641 "channelStyle": 2,
641 "channelType": 2, 642 "channelType": 2,
642 "defaultPermitted": 0, 643 "defaultPermitted": 0,
@@ -661,6 +662,7 @@ @@ -661,6 +662,7 @@
661 }, 662 },
662 { 663 {
663 "channelId": 2033, 664 "channelId": 2033,
  665 + "channelStrategy": 1,
664 "channelStyle": 2, 666 "channelStyle": 2,
665 "channelType": 2, 667 "channelType": 2,
666 "defaultPermitted": 0, 668 "defaultPermitted": 0,
@@ -685,6 +687,7 @@ @@ -685,6 +687,7 @@
685 }, 687 },
686 { 688 {
687 "channelId": 2034, 689 "channelId": 2034,
  690 + "channelStrategy": 1,
688 "channelStyle": 2, 691 "channelStyle": 2,
689 "channelType": 2, 692 "channelType": 2,
690 "defaultPermitted": 0, 693 "defaultPermitted": 0,
@@ -709,6 +712,7 @@ @@ -709,6 +712,7 @@
709 }, 712 },
710 { 713 {
711 "channelId": 2035, 714 "channelId": 2035,
  715 + "channelStrategy": 1,
712 "channelStyle": 2, 716 "channelStyle": 2,
713 "channelType": 2, 717 "channelType": 2,
714 "defaultPermitted": 0, 718 "defaultPermitted": 0,
@@ -733,6 +737,7 @@ @@ -733,6 +737,7 @@
733 }, 737 },
734 { 738 {
735 "channelId": 2028, 739 "channelId": 2028,
  740 + "channelStrategy": 1,
736 "channelStyle": 2, 741 "channelStyle": 2,
737 "channelType": 2, 742 "channelType": 2,
738 "defaultPermitted": 0, 743 "defaultPermitted": 0,
@@ -757,6 +762,7 @@ @@ -757,6 +762,7 @@
757 }, 762 },
758 { 763 {
759 "channelId": 2036, 764 "channelId": 2036,
  765 + "channelStrategy": 1,
760 "channelStyle": 2, 766 "channelStyle": 2,
761 "channelType": 2, 767 "channelType": 2,
762 "defaultPermitted": 0, 768 "defaultPermitted": 0,
@@ -781,6 +787,7 @@ @@ -781,6 +787,7 @@
781 }, 787 },
782 { 788 {
783 "channelId": 2037, 789 "channelId": 2037,
  790 + "channelStrategy": 1,
784 "channelStyle": 2, 791 "channelStyle": 2,
785 "channelType": 2, 792 "channelType": 2,
786 "defaultPermitted": 0, 793 "defaultPermitted": 0,
@@ -805,6 +812,7 @@ @@ -805,6 +812,7 @@
805 }, 812 },
806 { 813 {
807 "channelId": 2038, 814 "channelId": 2038,
  815 + "channelStrategy": 2,
808 "channelStyle": 2, 816 "channelStyle": 2,
809 "channelType": 2, 817 "channelType": 2,
810 "defaultPermitted": 0, 818 "defaultPermitted": 0,
@@ -829,6 +837,7 @@ @@ -829,6 +837,7 @@
829 }, 837 },
830 { 838 {
831 "channelId": 2039, 839 "channelId": 2039,
  840 + "channelStrategy": 1,
832 "channelStyle": 2, 841 "channelStyle": 2,
833 "channelType": 2, 842 "channelType": 2,
834 "defaultPermitted": 0, 843 "defaultPermitted": 0,
@@ -853,6 +862,7 @@ @@ -853,6 +862,7 @@
853 }, 862 },
854 { 863 {
855 "channelId": 2040, 864 "channelId": 2040,
  865 + "channelStrategy": 1,
856 "channelStyle": 2, 866 "channelStyle": 2,
857 "channelType": 2, 867 "channelType": 2,
858 "defaultPermitted": 0, 868 "defaultPermitted": 0,
@@ -877,6 +887,7 @@ @@ -877,6 +887,7 @@
877 }, 887 },
878 { 888 {
879 "channelId": 2041, 889 "channelId": 2041,
  890 + "channelStrategy": 1,
880 "channelStyle": 2, 891 "channelStyle": 2,
881 "channelType": 2, 892 "channelType": 2,
882 "defaultPermitted": 0, 893 "defaultPermitted": 0,
@@ -901,6 +912,7 @@ @@ -901,6 +912,7 @@
901 }, 912 },
902 { 913 {
903 "channelId": 2042, 914 "channelId": 2042,
  915 + "channelStrategy": 1,
904 "channelStyle": 2, 916 "channelStyle": 2,
905 "channelType": 2, 917 "channelType": 2,
906 "defaultPermitted": 0, 918 "defaultPermitted": 0,
@@ -925,6 +937,7 @@ @@ -925,6 +937,7 @@
925 }, 937 },
926 { 938 {
927 "channelId": 2043, 939 "channelId": 2043,
  940 + "channelStrategy": 1,
928 "channelStyle": 2, 941 "channelStyle": 2,
929 "channelType": 2, 942 "channelType": 2,
930 "defaultPermitted": 0, 943 "defaultPermitted": 0,
@@ -949,6 +962,7 @@ @@ -949,6 +962,7 @@
949 }, 962 },
950 { 963 {
951 "channelId": 2044, 964 "channelId": 2044,
  965 + "channelStrategy": 1,
952 "channelStyle": 2, 966 "channelStyle": 2,
953 "channelType": 2, 967 "channelType": 2,
954 "defaultPermitted": 0, 968 "defaultPermitted": 0,
@@ -973,6 +987,7 @@ @@ -973,6 +987,7 @@
973 }, 987 },
974 { 988 {
975 "channelId": 2045, 989 "channelId": 2045,
  990 + "channelStrategy": 1,
976 "channelStyle": 2, 991 "channelStyle": 2,
977 "channelType": 2, 992 "channelType": 2,
978 "defaultPermitted": 0, 993 "defaultPermitted": 0,
@@ -997,6 +1012,7 @@ @@ -997,6 +1012,7 @@
997 }, 1012 },
998 { 1013 {
999 "channelId": 2046, 1014 "channelId": 2046,
  1015 + "channelStrategy": 1,
1000 "channelStyle": 2, 1016 "channelStyle": 2,
1001 "channelType": 2, 1017 "channelType": 2,
1002 "defaultPermitted": 0, 1018 "defaultPermitted": 0,
@@ -1021,6 +1037,7 @@ @@ -1021,6 +1037,7 @@
1021 }, 1037 },
1022 { 1038 {
1023 "channelId": 2047, 1039 "channelId": 2047,
  1040 + "channelStrategy": 1,
1024 "channelStyle": 2, 1041 "channelStyle": 2,
1025 "channelType": 2, 1042 "channelType": 2,
1026 "defaultPermitted": 0, 1043 "defaultPermitted": 0,
@@ -1045,6 +1062,7 @@ @@ -1045,6 +1062,7 @@
1045 }, 1062 },
1046 { 1063 {
1047 "channelId": 2048, 1064 "channelId": 2048,
  1065 + "channelStrategy": 1,
1048 "channelStyle": 2, 1066 "channelStyle": 2,
1049 "channelType": 2, 1067 "channelType": 2,
1050 "defaultPermitted": 0, 1068 "defaultPermitted": 0,
@@ -1069,6 +1087,7 @@ @@ -1069,6 +1087,7 @@
1069 }, 1087 },
1070 { 1088 {
1071 "channelId": 2049, 1089 "channelId": 2049,
  1090 + "channelStrategy": 1,
1072 "channelStyle": 2, 1091 "channelStyle": 2,
1073 "channelType": 2, 1092 "channelType": 2,
1074 "defaultPermitted": 0, 1093 "defaultPermitted": 0,
@@ -1093,6 +1112,7 @@ @@ -1093,6 +1112,7 @@
1093 }, 1112 },
1094 { 1113 {
1095 "channelId": 2050, 1114 "channelId": 2050,
  1115 + "channelStrategy": 1,
1096 "channelStyle": 2, 1116 "channelStyle": 2,
1097 "channelType": 2, 1117 "channelType": 2,
1098 "defaultPermitted": 0, 1118 "defaultPermitted": 0,
@@ -1117,6 +1137,7 @@ @@ -1117,6 +1137,7 @@
1117 }, 1137 },
1118 { 1138 {
1119 "channelId": 2051, 1139 "channelId": 2051,
  1140 + "channelStrategy": 1,
1120 "channelStyle": 2, 1141 "channelStyle": 2,
1121 "channelType": 2, 1142 "channelType": 2,
1122 "defaultPermitted": 0, 1143 "defaultPermitted": 0,
@@ -1141,6 +1162,7 @@ @@ -1141,6 +1162,7 @@
1141 }, 1162 },
1142 { 1163 {
1143 "channelId": 2052, 1164 "channelId": 2052,
  1165 + "channelStrategy": 1,
1144 "channelStyle": 2, 1166 "channelStyle": 2,
1145 "channelType": 2, 1167 "channelType": 2,
1146 "defaultPermitted": 0, 1168 "defaultPermitted": 0,
@@ -1165,6 +1187,7 @@ @@ -1165,6 +1187,7 @@
1165 }, 1187 },
1166 { 1188 {
1167 "channelId": 2053, 1189 "channelId": 2053,
  1190 + "channelStrategy": 1,
1168 "channelStyle": 2, 1191 "channelStyle": 2,
1169 "channelType": 2, 1192 "channelType": 2,
1170 "defaultPermitted": 0, 1193 "defaultPermitted": 0,
@@ -1189,6 +1212,7 @@ @@ -1189,6 +1212,7 @@
1189 }, 1212 },
1190 { 1213 {
1191 "channelId": 2054, 1214 "channelId": 2054,
  1215 + "channelStrategy": 1,
1192 "channelStyle": 2, 1216 "channelStyle": 2,
1193 "channelType": 2, 1217 "channelType": 2,
1194 "defaultPermitted": 0, 1218 "defaultPermitted": 0,
@@ -1213,6 +1237,7 @@ @@ -1213,6 +1237,7 @@
1213 }, 1237 },
1214 { 1238 {
1215 "channelId": 2055, 1239 "channelId": 2055,
  1240 + "channelStrategy": 2,
1216 "channelStyle": 2, 1241 "channelStyle": 2,
1217 "channelType": 2, 1242 "channelType": 2,
1218 "defaultPermitted": 0, 1243 "defaultPermitted": 0,
@@ -1237,6 +1262,7 @@ @@ -1237,6 +1262,7 @@
1237 }, 1262 },
1238 { 1263 {
1239 "channelId": 2056, 1264 "channelId": 2056,
  1265 + "channelStrategy": 2,
1240 "channelStyle": 2, 1266 "channelStyle": 2,
1241 "channelType": 2, 1267 "channelType": 2,
1242 "defaultPermitted": 0, 1268 "defaultPermitted": 0,
@@ -1261,6 +1287,7 @@ @@ -1261,6 +1287,7 @@
1261 }, 1287 },
1262 { 1288 {
1263 "channelId": 2057, 1289 "channelId": 2057,
  1290 + "channelStrategy": 2,
1264 "channelStyle": 2, 1291 "channelStyle": 2,
1265 "channelType": 2, 1292 "channelType": 2,
1266 "defaultPermitted": 0, 1293 "defaultPermitted": 0,
@@ -1285,6 +1312,7 @@ @@ -1285,6 +1312,7 @@
1285 }, 1312 },
1286 { 1313 {
1287 "channelId": 2020, 1314 "channelId": 2020,
  1315 + "channelStrategy": 2,
1288 "channelStyle": 2, 1316 "channelStyle": 2,
1289 "channelType": 1, 1317 "channelType": 1,
1290 "defaultPermitted": 0, 1318 "defaultPermitted": 0,
@@ -1309,6 +1337,7 @@ @@ -1309,6 +1337,7 @@
1309 }, 1337 },
1310 { 1338 {
1311 "channelId": 2021, 1339 "channelId": 2021,
  1340 + "channelStrategy": 1,
1312 "channelStyle": 2, 1341 "channelStyle": 2,
1313 "channelType": 1, 1342 "channelType": 1,
1314 "defaultPermitted": 0, 1343 "defaultPermitted": 0,
@@ -1332,7 +1361,8 @@ @@ -1332,7 +1361,8 @@
1332 "underlineCColor": "" 1361 "underlineCColor": ""
1333 }, 1362 },
1334 { 1363 {
1335 - "channelId": 2022, 1364 + "channelId": 2069,
  1365 + "channelStrategy": 2,
1336 "channelStyle": 2, 1366 "channelStyle": 2,
1337 "channelType": 1, 1367 "channelType": 1,
1338 "defaultPermitted": 0, 1368 "defaultPermitted": 0,
@@ -1349,18 +1379,19 @@ @@ -1349,18 +1379,19 @@
1349 "moreChannel": "0", 1379 "moreChannel": "0",
1350 "movePermitted": 1, 1380 "movePermitted": 1,
1351 "myChannel": "0", 1381 "myChannel": "0",
1352 - "name": "生活",  
1353 - "num": 59,  
1354 - "pageId": 20032, 1382 + "name": "冬奥",
  1383 + "num": 66,
  1384 + "pageId": 21006,
1355 "pageType": "", 1385 "pageType": "",
1356 "underlineCColor": "" 1386 "underlineCColor": ""
1357 }, 1387 },
1358 { 1388 {
1359 - "channelId": 2092, 1389 + "channelId": 2070,
  1390 + "channelStrategy": 2,
1360 "channelStyle": 2, 1391 "channelStyle": 2,
1361 "channelType": 1, 1392 "channelType": 1,
1362 "defaultPermitted": 0, 1393 "defaultPermitted": 0,
1363 - "delPermitted": 0, 1394 + "delPermitted": 1,
1364 "fontCColor": "#FFFFFF", 1395 "fontCColor": "#FFFFFF",
1365 "fontColor": "#F9AB99", 1396 "fontColor": "#F9AB99",
1366 "headlinesOn": 0, 1397 "headlinesOn": 0,
@@ -1373,18 +1404,19 @@ @@ -1373,18 +1404,19 @@
1373 "moreChannel": "0", 1404 "moreChannel": "0",
1374 "movePermitted": 1, 1405 "movePermitted": 1,
1375 "myChannel": "0", 1406 "myChannel": "0",
1376 - "name": "设计",  
1377 - "num": 68,  
1378 - "pageId": 21063, 1407 + "name": "旅游",
  1408 + "num": 67,
  1409 + "pageId": 21007,
1379 "pageType": "", 1410 "pageType": "",
1380 "underlineCColor": "" 1411 "underlineCColor": ""
1381 }, 1412 },
1382 { 1413 {
1383 - "channelId": 2098, 1414 + "channelId": 2077,
  1415 + "channelStrategy": 2,
1384 "channelStyle": 2, 1416 "channelStyle": 2,
1385 "channelType": 1, 1417 "channelType": 1,
1386 "defaultPermitted": 0, 1418 "defaultPermitted": 0,
1387 - "delPermitted": 0, 1419 + "delPermitted": 1,
1388 "fontCColor": "#FFFFFF", 1420 "fontCColor": "#FFFFFF",
1389 "fontColor": "#F9AB99", 1421 "fontColor": "#F9AB99",
1390 "headlinesOn": 0, 1422 "headlinesOn": 0,
@@ -1395,35 +1427,11 @@ @@ -1395,35 +1427,11 @@
1395 "iconUrlSize": "", 1427 "iconUrlSize": "",
1396 "localChannel": "0", 1428 "localChannel": "0",
1397 "moreChannel": "0", 1429 "moreChannel": "0",
1398 - "movePermitted": 0,  
1399 - "myChannel": "0",  
1400 - "name": "设计组件",  
1401 - "num": 72,  
1402 - "pageId": 21299,  
1403 - "pageType": "",  
1404 - "underlineCColor": ""  
1405 - },  
1406 - {  
1407 - "channelId": 2099,  
1408 - "channelStyle": 2,  
1409 - "channelType": 1,  
1410 - "defaultPermitted": 0,  
1411 - "delPermitted": 0,  
1412 - "fontCColor": "",  
1413 - "fontColor": "",  
1414 - "headlinesOn": 0,  
1415 - "homeChannel": "0",  
1416 - "iconCUrl": "",  
1417 - "iconCUrlSize": "",  
1418 - "iconUrl": "",  
1419 - "iconUrlSize": "",  
1420 - "localChannel": "0",  
1421 - "moreChannel": "0",  
1422 "movePermitted": 1, 1430 "movePermitted": 1,
1423 "myChannel": "0", 1431 "myChannel": "0",
1424 - "name": "设计号",  
1425 - "num": 73,  
1426 - "pageId": 21736, 1432 + "name": "设计",
  1433 + "num": 69,
  1434 + "pageId": 21528,
1427 "pageType": "", 1435 "pageType": "",
1428 "underlineCColor": "" 1436 "underlineCColor": ""
1429 } 1437 }
@@ -1432,39 +1440,40 @@ @@ -1432,39 +1440,40 @@
1432 "type": "1" 1440 "type": "1"
1433 }, 1441 },
1434 { 1442 {
1435 - "backgroundUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/2e1d5f235d1a44cfb9fc120e8596c56b.png",  
1436 - "channelChooseActionUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231227/vod/display/3835f09a973443cb824af179e30e87ed.pag",  
1437 - "channelChooseCColor": "#666666",  
1438 - "channelChooseColor": "#222222", 1443 + "backgroundUrl": "",
  1444 + "channelChooseActionUrl": "",
  1445 + "channelChooseCColor": "",
  1446 + "channelChooseColor": "",
1439 "channelMoreColor": "", 1447 "channelMoreColor": "",
1440 "extraData": "{\"haveSearch\":\"0\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}", 1448 "extraData": "{\"haveSearch\":\"0\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}",
1441 - "homePageColor": "#FFFFFF",  
1442 - "icon": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/460f61a48c6a4993af442d54aedb682b.png",  
1443 - "iconC": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/9aa759f72ccb4848b3ded2dee9502c25.gif", 1449 + "homePageColor": "",
  1450 + "icon": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/e54cb55897604f099940d0a8526680c0.png",
  1451 + "iconC": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/29e827defea748e295fa4397022b6cc9.png",
1444 "id": 202, 1452 "id": 202,
1445 "immersiveIconCUrl": "", 1453 "immersiveIconCUrl": "",
1446 "immersiveIconUrl": "", 1454 "immersiveIconUrl": "",
1447 - "immersiveNameCColor": "#FFFFFF",  
1448 - "immersiveNameColor": "#FFFFFF", 1455 + "immersiveNameCColor": "",
  1456 + "immersiveNameColor": "",
1449 "logoUrl": "", 1457 "logoUrl": "",
1450 "morningAndEveningUrl": "", 1458 "morningAndEveningUrl": "",
1451 "name": "人民号", 1459 "name": "人民号",
1452 - "nameCColor": "#ED2800", 1460 + "nameCColor": "#CB0000",
1453 "nameColor": "#999999", 1461 "nameColor": "#999999",
1454 "nightIconCUrl": "", 1462 "nightIconCUrl": "",
1455 "nightIconUrl": "", 1463 "nightIconUrl": "",
1456 "nightNameCColor": "", 1464 "nightNameCColor": "",
1457 "nightNameColor": "", 1465 "nightNameColor": "",
1458 - "noticeColor": "#FFFFFF", 1466 + "noticeColor": "",
1459 "pageId": null, 1467 "pageId": null,
1460 "pageType": null, 1468 "pageType": null,
1461 - "searchBothColor": "#222222", 1469 + "searchBothColor": "",
1462 "searchUrl": "", 1470 "searchUrl": "",
1463 "sortValue": 2, 1471 "sortValue": 2,
1464 - "statusBarColor": 1, 1472 + "statusBarColor": null,
1465 "topNavChannelList": [ 1473 "topNavChannelList": [
1466 { 1474 {
1467 "channelId": 2058, 1475 "channelId": 2058,
  1476 + "channelStrategy": 1,
1468 "channelStyle": 3, 1477 "channelStyle": 3,
1469 "channelType": 1, 1478 "channelType": 1,
1470 "defaultPermitted": 0, 1479 "defaultPermitted": 0,
@@ -1489,6 +1498,7 @@ @@ -1489,6 +1498,7 @@
1489 }, 1498 },
1490 { 1499 {
1491 "channelId": 2059, 1500 "channelId": 2059,
  1501 + "channelStrategy": 2,
1492 "channelStyle": 3, 1502 "channelStyle": 3,
1493 "channelType": 3, 1503 "channelType": 3,
1494 "defaultPermitted": 0, 1504 "defaultPermitted": 0,
@@ -1513,6 +1523,7 @@ @@ -1513,6 +1523,7 @@
1513 }, 1523 },
1514 { 1524 {
1515 "channelId": 2073, 1525 "channelId": 2073,
  1526 + "channelStrategy": 2,
1516 "channelStyle": 3, 1527 "channelStyle": 3,
1517 "channelType": 1, 1528 "channelType": 1,
1518 "defaultPermitted": 0, 1529 "defaultPermitted": 0,
@@ -1540,39 +1551,40 @@ @@ -1540,39 +1551,40 @@
1540 "type": "1" 1551 "type": "1"
1541 }, 1552 },
1542 { 1553 {
1543 - "backgroundUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/2e1d5f235d1a44cfb9fc120e8596c56b.png",  
1544 - "channelChooseActionUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231221/vod/display/65c6eb2ca91849c582d057adc9e76d46.pag",  
1545 - "channelChooseCColor": "#666666",  
1546 - "channelChooseColor": "#222222", 1554 + "backgroundUrl": "",
  1555 + "channelChooseActionUrl": "",
  1556 + "channelChooseCColor": "",
  1557 + "channelChooseColor": "",
1547 "channelMoreColor": "", 1558 "channelMoreColor": "",
1548 "extraData": "{\"haveSearch\":\"1\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}", 1559 "extraData": "{\"haveSearch\":\"1\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}",
1549 - "homePageColor": "#FFFFFF",  
1550 - "icon": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231221/image/display/bf77561966654001a538857ebef8a15c.png",  
1551 - "iconC": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231224/image/display/1a42d5b8183a4eb1a044ddd64223c687.png", 1560 + "homePageColor": "",
  1561 + "icon": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/551a687fccdc44ce916a391cc10eabdd.png",
  1562 + "iconC": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/8ebb3bfe44534b059d5af53aafba8919.png",
1552 "id": 203, 1563 "id": 203,
1553 "immersiveIconCUrl": "", 1564 "immersiveIconCUrl": "",
1554 "immersiveIconUrl": "", 1565 "immersiveIconUrl": "",
1555 - "immersiveNameCColor": "#FFFFFF",  
1556 - "immersiveNameColor": "#FFFFFF", 1566 + "immersiveNameCColor": "",
  1567 + "immersiveNameColor": "",
1557 "logoUrl": "", 1568 "logoUrl": "",
1558 "morningAndEveningUrl": "", 1569 "morningAndEveningUrl": "",
1559 "name": "视频", 1570 "name": "视频",
1560 - "nameCColor": "#ED2800", 1571 + "nameCColor": "#CB0000",
1561 "nameColor": "#999999", 1572 "nameColor": "#999999",
1562 "nightIconCUrl": "", 1573 "nightIconCUrl": "",
1563 "nightIconUrl": "", 1574 "nightIconUrl": "",
1564 "nightNameCColor": "", 1575 "nightNameCColor": "",
1565 "nightNameColor": "", 1576 "nightNameColor": "",
1566 - "noticeColor": "#FFFFFF", 1577 + "noticeColor": "",
1567 "pageId": null, 1578 "pageId": null,
1568 "pageType": null, 1579 "pageType": null,
1569 - "searchBothColor": "#222222", 1580 + "searchBothColor": "",
1570 "searchUrl": "", 1581 "searchUrl": "",
1571 "sortValue": 3, 1582 "sortValue": 3,
1572 - "statusBarColor": 1, 1583 + "statusBarColor": null,
1573 "topNavChannelList": [ 1584 "topNavChannelList": [
1574 { 1585 {
1575 "channelId": 2060, 1586 "channelId": 2060,
  1587 + "channelStrategy": 1,
1576 "channelStyle": 1, 1588 "channelStyle": 1,
1577 "channelType": 1, 1589 "channelType": 1,
1578 "defaultPermitted": 0, 1590 "defaultPermitted": 0,
@@ -1597,6 +1609,7 @@ @@ -1597,6 +1609,7 @@
1597 }, 1609 },
1598 { 1610 {
1599 "channelId": 2061, 1611 "channelId": 2061,
  1612 + "channelStrategy": 2,
1600 "channelStyle": 3, 1613 "channelStyle": 3,
1601 "channelType": 1, 1614 "channelType": 1,
1602 "defaultPermitted": 0, 1615 "defaultPermitted": 0,
@@ -1624,39 +1637,40 @@ @@ -1624,39 +1637,40 @@
1624 "type": "1" 1637 "type": "1"
1625 }, 1638 },
1626 { 1639 {
1627 - "backgroundUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/2e1d5f235d1a44cfb9fc120e8596c56b.png",  
1628 - "channelChooseActionUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231221/vod/display/65c6eb2ca91849c582d057adc9e76d46.pag",  
1629 - "channelChooseCColor": "#666666",  
1630 - "channelChooseColor": "#222222", 1640 + "backgroundUrl": "",
  1641 + "channelChooseActionUrl": "",
  1642 + "channelChooseCColor": "",
  1643 + "channelChooseColor": "",
1631 "channelMoreColor": "", 1644 "channelMoreColor": "",
1632 "extraData": "{\"haveSearch\":\"1\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}", 1645 "extraData": "{\"haveSearch\":\"1\",\"haveTopNav\":\"1\",\"leftIconurl\":\"\",\"rightIconUrl\":\"\"}",
1633 - "homePageColor": "#FFFFFF",  
1634 - "icon": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/5a6cf95f7b9e489390ec73faf458b58a.png",  
1635 - "iconC": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/1b075ed30a6b43d2ae319e5d892c66e4.gif", 1646 + "homePageColor": "",
  1647 + "icon": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/a35a51ac415343bb8122b48f84b5ca70.png",
  1648 + "iconC": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/972642ec160b4fc2a5dad2de3488d903.png",
1636 "id": 204, 1649 "id": 204,
1637 "immersiveIconCUrl": "", 1650 "immersiveIconCUrl": "",
1638 "immersiveIconUrl": "", 1651 "immersiveIconUrl": "",
1639 - "immersiveNameCColor": "#FFFFFF",  
1640 - "immersiveNameColor": "#FFFFFF", 1652 + "immersiveNameCColor": "",
  1653 + "immersiveNameColor": "",
1641 "logoUrl": "", 1654 "logoUrl": "",
1642 "morningAndEveningUrl": "", 1655 "morningAndEveningUrl": "",
1643 "name": "服务", 1656 "name": "服务",
1644 - "nameCColor": "#ED2800", 1657 + "nameCColor": "#CB0000",
1645 "nameColor": "#999999", 1658 "nameColor": "#999999",
1646 "nightIconCUrl": "", 1659 "nightIconCUrl": "",
1647 "nightIconUrl": "", 1660 "nightIconUrl": "",
1648 "nightNameCColor": "", 1661 "nightNameCColor": "",
1649 "nightNameColor": "", 1662 "nightNameColor": "",
1650 - "noticeColor": "#FFFFFF", 1663 + "noticeColor": "",
1651 "pageId": null, 1664 "pageId": null,
1652 "pageType": null, 1665 "pageType": null,
1653 - "searchBothColor": "#222222", 1666 + "searchBothColor": "",
1654 "searchUrl": "", 1667 "searchUrl": "",
1655 "sortValue": 4, 1668 "sortValue": 4,
1656 - "statusBarColor": 1, 1669 + "statusBarColor": null,
1657 "topNavChannelList": [ 1670 "topNavChannelList": [
1658 { 1671 {
1659 "channelId": 2062, 1672 "channelId": 2062,
  1673 + "channelStrategy": 2,
1660 "channelStyle": 3, 1674 "channelStyle": 3,
1661 "channelType": 1, 1675 "channelType": 1,
1662 "defaultPermitted": 0, 1676 "defaultPermitted": 0,
@@ -1684,36 +1698,36 @@ @@ -1684,36 +1698,36 @@
1684 "type": "1" 1698 "type": "1"
1685 }, 1699 },
1686 { 1700 {
1687 - "backgroundUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231214/image/display/3e1f4fe85b0445b6a0be24f3759d0ff6.png", 1701 + "backgroundUrl": "",
1688 "channelChooseActionUrl": "", 1702 "channelChooseActionUrl": "",
1689 - "channelChooseCColor": "#FFFFFF",  
1690 - "channelChooseColor": "#FFFFFF", 1703 + "channelChooseCColor": "",
  1704 + "channelChooseColor": "",
1691 "channelMoreColor": "", 1705 "channelMoreColor": "",
1692 "extraData": "{\"haveSearch\":\"0\",\"haveTopNav\":\"0\"}", 1706 "extraData": "{\"haveSearch\":\"0\",\"haveTopNav\":\"0\"}",
1693 - "homePageColor": "#222222",  
1694 - "icon": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/f55f0ac25b764809bc8285c284adb147.png",  
1695 - "iconC": "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231220/image/display/3b5cff54d2a546f5b523a8aa8c33352e.gif", 1707 + "homePageColor": "",
  1708 + "icon": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/3fa1832f3fbf49e6ad6765e64d27e60e.png",
  1709 + "iconC": "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231015/image/display/39a357a0f0954b86b993a18988d29f96.png",
1696 "id": 205, 1710 "id": 205,
1697 - "immersiveIconCUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/inen-20230403/image/display/9f22b579db15497797e8204b1ec12d14.png",  
1698 - "immersiveIconUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/inen-20230403/image/display/5be23055a4dc4d869be2139e9deb7a55.png", 1711 + "immersiveIconCUrl": "https://cdnjdphoto.aikan.pdnews.cn/inen-20230403/image/display/9f22b579db15497797e8204b1ec12d14.png",
  1712 + "immersiveIconUrl": "https://cdnjdphoto.aikan.pdnews.cn/inen-20230403/image/display/5be23055a4dc4d869be2139e9deb7a55.png",
1699 "immersiveNameCColor": "#FFFFFF", 1713 "immersiveNameCColor": "#FFFFFF",
1700 - "immersiveNameColor": "#FFFFFF", 1714 + "immersiveNameColor": "#6A6B75",
1701 "logoUrl": "", 1715 "logoUrl": "",
1702 "morningAndEveningUrl": "", 1716 "morningAndEveningUrl": "",
1703 "name": "我的", 1717 "name": "我的",
1704 - "nameCColor": "#ED2800", 1718 + "nameCColor": "#CB0000",
1705 "nameColor": "#999999", 1719 "nameColor": "#999999",
1706 - "nightIconCUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/inen-20230403/image/display/9d584ddcfdf74e3ea8e445d102127b97.png",  
1707 - "nightIconUrl": "https://uatjdcdnphoto.aikan.pdnews.cn/inen-20230403/image/display/1f79063b6ecb493c95703e45529d3a5f.png", 1720 + "nightIconCUrl": "https://cdnjdphoto.aikan.pdnews.cn/inen-20230403/image/display/9d584ddcfdf74e3ea8e445d102127b97.png",
  1721 + "nightIconUrl": "https://cdnjdphoto.aikan.pdnews.cn/inen-20230403/image/display/1f79063b6ecb493c95703e45529d3a5f.png",
1708 "nightNameCColor": "#DA1C1C", 1722 "nightNameCColor": "#DA1C1C",
1709 "nightNameColor": "#6A6B75", 1723 "nightNameColor": "#6A6B75",
1710 - "noticeColor": "#ED2800", 1724 + "noticeColor": "",
1711 "pageId": null, 1725 "pageId": null,
1712 "pageType": null, 1726 "pageType": null,
1713 - "searchBothColor": "#FFFFFF", 1727 + "searchBothColor": "",
1714 "searchUrl": "", 1728 "searchUrl": "",
1715 "sortValue": 5, 1729 "sortValue": 5,
1716 - "statusBarColor": 1, 1730 + "statusBarColor": null,
1717 "topNavChannelList": [], 1731 "topNavChannelList": [],
1718 "topStyle": "", 1732 "topStyle": "",
1719 "type": "2" 1733 "type": "2"
@@ -1728,9 +1742,9 @@ @@ -1728,9 +1742,9 @@
1728 }, 1742 },
1729 "message": "Success", 1743 "message": "Success",
1730 "meta": { 1744 "meta": {
1731 - "md5": "e2942dbcd76710d1bac0d98f9a0a9d0a" 1745 + "md5": "bab17ef603000513258f3ff7c4add868"
1732 }, 1746 },
1733 "requestId": "", 1747 "requestId": "",
1734 "success": true, 1748 "success": true,
1735 - "timestamp": 1704765430031 1749 + "timestamp": 1706625315509
1736 } 1750 }
1 -// enum  
2 -export { BottomNavi } from './src/main/ets/enum/BottomNavi';  
3 -  
4 -export { CompStyle } from './src/main/ets/enum/CompStyle';  
5 -  
6 -export { CompType } from './src/main/ets/enum/CompType';  
7 -  
8 -export { NetDataStatusType } from './src/main/ets/enum/NetDataStatusType';  
9 -  
10 -export { ViewType } from './src/main/ets/enum/ViewType';  
11 -  
12 -export { DelayTimeEnum } from './src/main/ets/enum/DelayTimeEnum';  
13 -  
14 -export { ScreenType } from './src/main/ets/enum/ScreenType';  
15 -  
16 // navigation 1 // navigation
17 -export { NavigationBody } from './src/main/ets/bean/navigation/NavigationBody'; 2 +export { NavigationBodyDTO } from './src/main/ets/bean/navigation/NavigationBodyDTO';
18 3
19 -export { BottomNavBean } from './src/main/ets/bean/navigation/BottomNavBean'; 4 +export { BottomNavDTO } from './src/main/ets/bean/navigation/BottomNavDTO';
20 5
21 -export { TopNavBean } from './src/main/ets/bean/navigation/TopNavBean'; 6 +export { TopNavDTO } from './src/main/ets/bean/navigation/TopNavDTO';
22 7
23 // entity 8 // entity
24 export { ItemDTO } from './src/main/ets/bean/ItemDTO'; 9 export { ItemDTO } from './src/main/ets/bean/ItemDTO';
@@ -36,6 +21,8 @@ export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean'; @@ -36,6 +21,8 @@ export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean';
36 21
37 export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO'; 22 export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO';
38 23
  24 +export { PageDTO } from './src/main/ets/bean/component/PageDTO';
  25 +
39 export { GroupDTO } from './src/main/ets/bean/component/GroupDTO'; 26 export { GroupDTO } from './src/main/ets/bean/component/GroupDTO';
40 27
41 export { CompDTO } from './src/main/ets/bean/component/CompDTO'; 28 export { CompDTO } from './src/main/ets/bean/component/CompDTO';
@@ -6,14 +6,9 @@ import { Pic } from './programme/Pic'; @@ -6,14 +6,9 @@ import { Pic } from './programme/Pic';
6 * 绑定到组件comp/view的数据Bean 6 * 绑定到组件comp/view的数据Bean
7 */ 7 */
8 @Observed 8 @Observed
9 -// export abstract class ItemBean<DTO> implements Mapper<DTO> {  
10 -export abstract class ItemBean extends ItemDTO {  
11 - landscapeCover?: string; // 横向低分辨封面图片  
12 - portraitCover?: string; // 竖向低分辨封面图片  
13 - highLandscapeCover?: string; // 横向高分辨封面图片  
14 - highPortraitCover?: string; // 竖向高分辨封面图片  
15 - lowResolutionV34?: string; // 低清竖图(3:4比例), 取图逻辑 3:4低清竖图-->3:4高清竖图-->低分辨率竖图-->高分辨率竖图  
16 - highResolutionV34?: string; // 高清竖图(3:4比例), 取图逻辑 3:4高清竖图-->3:4低清竖图-->高分辨率竖图-->低分辨率竖图 9 +export abstract class ItemBean {
  10 + action?: Action; // 事件行为
  11 + pics?: Pic
17 /** 12 /**
18 * 是否被曝光 13 * 是否被曝光
19 */ 14 */
@@ -23,18 +18,20 @@ export abstract class ItemBean extends ItemDTO { @@ -23,18 +18,20 @@ export abstract class ItemBean extends ItemDTO {
23 */ 18 */
24 position: string; 19 position: string;
25 20
26 - constructor(dto: ItemDTO) {  
27 - super(dto.action, dto.actionId, dto.pics, dto.h5pics)  
28 -  
29 - this.landscapeCover = !dto.pics ? "" : !dto.pics.lowResolutionH ? dto.pics.highResolutionH : dto.pics.lowResolutionH;  
30 - this.portraitCover = !dto.pics ? "" : !dto.pics.lowResolutionV ? dto.pics.highResolutionV : dto.pics.lowResolutionV;  
31 - this.highLandscapeCover = !dto.pics ? "" : !dto.pics.highResolutionH ? dto.pics.lowResolutionH : dto.pics.highResolutionH;  
32 - this.highPortraitCover = !dto.pics ? "" : !dto.pics.highResolutionV ? dto.pics.lowResolutionV : dto.pics.highResolutionV;  
33 -  
34 - this.lowResolutionV34 = !dto.pics ? "" : (!dto.pics.lowResolutionV34 ? dto.pics.lowResolutionV34 : (!dto.pics.highResolutionV34 ? dto.pics.highResolutionV34 : this.portraitCover));  
35 - this.highResolutionV34 = !dto.pics ? "" : (!dto.pics.highResolutionV34 ? dto.pics.highResolutionV34 : (!dto.pics.lowResolutionV34 ? dto.pics.lowResolutionV34 : this.highPortraitCover));  
36 - 21 + constructor(dto?: ItemDTO) {
  22 + if (dto) {
  23 + this.action = dto.action
  24 + this.pics = dto.pics
  25 + }
37 this.exposed = false 26 this.exposed = false
38 this.position = "0" 27 this.position = "0"
39 } 28 }
  29 +
  30 + public setAction(action: Action): void {
  31 + this.action = action
  32 + }
  33 +
  34 + public getAction(): Action {
  35 + return this.action ?? {} as Action
  36 + }
40 } 37 }
@@ -5,16 +5,7 @@ import { Pic } from './programme/Pic'; @@ -5,16 +5,7 @@ import { Pic } from './programme/Pic';
5 * 组件comp/view对应的服务端数据 5 * 组件comp/view对应的服务端数据
6 * DTO 数据传输实体类接口,所有数据传输层数据结构体需实现该接口 6 * DTO 数据传输实体类接口,所有数据传输层数据结构体需实现该接口
7 */ 7 */
8 -export abstract class ItemDTO { 8 +export interface ItemDTO {
9 action?: Action; // 事件对象 9 action?: Action; // 事件对象
10 - actionId?: string; // 点击事件id  
11 pics?: Pic // 图片 10 pics?: Pic // 图片
12 - h5pics?: Pic; // h5图片  
13 -  
14 - constructor(action?: Action, actionId?: string, pics?: Pic, h5pics?: Pic) {  
15 - this.action = action;  
16 - this.actionId = actionId;  
17 - this.pics = pics;  
18 - this.h5pics = h5pics;  
19 - }  
20 } 11 }
@@ -10,7 +10,7 @@ export interface ContentDTO { @@ -10,7 +10,7 @@ export interface ContentDTO {
10 heatValue: string; 10 heatValue: string;
11 innerUrl: string; 11 innerUrl: string;
12 landscape: number; 12 landscape: number;
13 - // lengthTime?: any; 13 + lengthTime?: object;
14 linkUrl: string; 14 linkUrl: string;
15 openLikes: number; 15 openLikes: number;
16 openUrl: string; 16 openUrl: string;
@@ -33,4 +33,11 @@ export interface ContentDTO { @@ -33,4 +33,11 @@ export interface ContentDTO {
33 title: string; 33 title: string;
34 vImageUrl: string; 34 vImageUrl: string;
35 screenType: string; 35 screenType: string;
  36 +
  37 + source: string;
  38 + objectId: string;
  39 + objectType: string;
  40 + channelId: string;
  41 + relId: string;
  42 + relType: string;
36 } 43 }
1 -import { GroupDTO } from './GroupDTO'; 1 +import { CompDTO } from './CompDTO';
2 2
3 /** 3 /**
4 * Page数据DTO 4 * Page数据DTO
5 */ 5 */
6 export interface PageDTO { 6 export interface PageDTO {
7 - id: number; // 页面id  
8 - name: string; // 页面名称  
9 - description: string; // 描述  
10 - groups: GroupDTO[]; // page下的group列表 7 + pageId: string; // 页面id
  8 + id: number; // 楼层id
  9 + name: string; // 名称
  10 + branchMark: boolean;
  11 + compList: CompDTO[]; // Components集合的布局信息
11 } 12 }
1 -import { TopNavBean } from './TopNavBean'; 1 +import { TopNavDTO } from './TopNavDTO';
2 2
3 /** 3 /**
4 * 底导(包含顶导列表)数据 4 * 底导(包含顶导列表)数据
5 */ 5 */
6 -export interface BottomNavBean { 6 +export interface BottomNavDTO {
7 backgroundUrl: string; 7 backgroundUrl: string;
8 channelChooseActionUrl: string; 8 channelChooseActionUrl: string;
9 channelChooseCColor: string; 9 channelChooseCColor: string;
@@ -34,7 +34,7 @@ export interface BottomNavBean { @@ -34,7 +34,7 @@ export interface BottomNavBean {
34 searchUrl: string; 34 searchUrl: string;
35 sortValue: number; 35 sortValue: number;
36 statusBarColor: number; 36 statusBarColor: number;
37 - topNavChannelList: TopNavBean[]; 37 + topNavChannelList: TopNavDTO[];
38 topStyle: string; 38 topStyle: string;
39 type: string; 39 type: string;
40 } 40 }
1 -import { BottomNavBean } from './BottomNavBean'; 1 +import { BottomNavDTO } from './BottomNavDTO';
2 2
3 /** 3 /**
4 * 导航Body数据 4 * 导航Body数据
5 */ 5 */
6 -export interface NavigationBody { 6 +export interface NavigationBodyDTO {
7 backgroundColor: string; 7 backgroundColor: string;
8 - bottomNavList: BottomNavBean[]; 8 + bottomNavList: BottomNavDTO[];
9 // greyBottomNav: GreyBottomNav; 9 // greyBottomNav: GreyBottomNav;
10 immersiveBackgroundColor: string; 10 immersiveBackgroundColor: string;
11 nightBackgroundColor: string; 11 nightBackgroundColor: string;
1 /** 1 /**
2 * 顶导 2 * 顶导
3 */ 3 */
4 -export interface TopNavBean { 4 +export interface TopNavDTO {
5 channelId: number; 5 channelId: number;
6 channelStyle: number; 6 channelStyle: number;
7 channelType: number; 7 channelType: number;
@@ -3,6 +3,5 @@ import { Params } from './Params'; @@ -3,6 +3,5 @@ import { Params } from './Params';
3 // 事件对象 3 // 事件对象
4 export interface Action { 4 export interface Action {
5 type: string; 5 type: string;
6 - name?: string; // 行为的名称,目前值与type相同,暂不启用  
7 params?: Params; // 参数集合 6 params?: Params; // 参数集合
8 } 7 }
1 -/**  
2 - * 延时枚举常量值  
3 - */  
4 -export const enum DelayTimeEnum {  
5 - DURATION_50 = 50, // 50毫秒  
6 - DURATION_100 = 100, // 50毫秒  
7 - DURATION_1000 = 1000, // 1秒/1000ms  
8 - DURATION_2000 = 2000, // 2秒/2000ms  
9 - LAUNCHER_DELAY_TIME = 1500, // 1.5秒  
10 - INTERVAL_4000 = 4000, //4秒  
11 -}  
@@ -2,34 +2,34 @@ export { PageViewModel } from "./src/main/ets/viewmodel/PageViewModel" @@ -2,34 +2,34 @@ export { PageViewModel } from "./src/main/ets/viewmodel/PageViewModel"
2 2
3 export { CompUtils } from "./src/main/ets/utils/CompUtils" 3 export { CompUtils } from "./src/main/ets/utils/CompUtils"
4 4
5 -export { EmptyComponent } from "./src/main/ets/components/EmptyComponent" 5 +export { EmptyComponent } from "./src/main/ets/components/view/EmptyComponent"
6 6
7 -export { ErrorComponent } from "./src/main/ets/components/ErrorComponent" 7 +export { ErrorComponent } from "./src/main/ets/components/view/ErrorComponent"
8 8
9 -export { LoadingComponent } from "./src/main/ets/components/LoadingComponent" 9 +export { LoadingComponent } from "./src/main/ets/components/view/LoadingComponent"
10 10
11 -export { PageComponent } from "./src/main/ets/components/PageComponent" 11 +export { PageComponent } from "./src/main/ets/components/page/PageComponent"
12 12
13 -export { BottomNavigationComponent } from "./src/main/ets/components/BottomNavigationComponent" 13 +export { BottomNavigationComponent } from "./src/main/ets/components/page/BottomNavigationComponent"
14 14
15 -export { TopNavigationComponent } from "./src/main/ets/components/TopNavigationComponent" 15 +export { TopNavigationComponent } from "./src/main/ets/components/page/TopNavigationComponent"
16 16
17 -export { LabelComponent } from "./src/main/ets/components/LabelComponent" 17 +export { LabelComponent } from "./src/main/ets/components/view/LabelComponent"
18 18
19 -export { BannerComponent } from "./src/main/ets/components/BannerComponent" 19 +export { BannerComponent } from "./src/main/ets/components/view/BannerComponent"
20 20
21 -export { SingleRow03Component } from "./src/main/ets/components/SingleRow03Component" 21 +export { SingleRow03Component } from "./src/main/ets/components/page/SingleRow03Component"
22 22
23 -export { SingleColumnComponent } from "./src/main/ets/components/SingleColumnComponent" 23 +export { SingleColumnComponent } from "./src/main/ets/components/page/SingleColumnComponent"
24 24
25 -export { GridLayout01Component } from "./src/main/ets/components/GridLayout01Component" 25 +export { GridLayout01Component } from "./src/main/ets/components/page/GridLayout01Component"
26 26
27 -export { WaterFlowComponent } from "./src/main/ets/components/WaterFlowComponent" 27 +export { WaterFlowComponent } from "./src/main/ets/components/page/WaterFlowComponent"
28 28
29 -export { NewspaperViewModel} from "./src/main/ets/viewmodel/NewspaperViewModel" 29 +export { NewspaperViewModel } from "./src/main/ets/viewmodel/NewspaperViewModel"
30 30
31 -export {ENewspaperPageComponent} from "./src/main/ets/components/ENewspaperPageComponent" 31 +export { ENewspaperPageComponent } from "./src/main/ets/components/ENewspaperPageComponent"
32 32
33 -export {ENewspaperItemComponent} from "./src/main/ets/components/ENewspaperItemComponent" 33 +export { ENewspaperItemComponent } from "./src/main/ets/components/ENewspaperItemComponent"
34 34
35 -export {ENewspaperListDialog} from "./src/main/ets/dialog/ENewspaperListDialog" 35 +export { ENewspaperListDialog } from "./src/main/ets/dialog/ENewspaperListDialog"
1 -import { CompDTO, ContentDTO, DelayTimeEnum } from 'wdBean';  
2 -import { BreakpointConstants } from 'wdConstant';  
3 -import { BreakPointType, Logger } from 'wdKit';  
4 -import { CarouselLayout01CardView } from './CardView';  
5 -import { EmptyComponent } from './EmptyComponent';  
6 -  
7 -const TAG = 'BannerComponent';  
8 -  
9 -/**  
10 - * 轮播组件,即Banner/轮播大图/焦点图/自动滑动  
11 - * 样式:  
12 - * 'Carousel_Layout-01', // 通用轮播卡:视频、直播、活动、专题、榜单、外链  
13 - */  
14 -@Component  
15 -export struct BannerComponent {  
16 - @StorageLink('currentBreakpoint') @Watch('watchCurrentBreakpoint') currentBreakpoint: string = BreakpointConstants.BREAKPOINT_XS;  
17 - @State compDTO: CompDTO = {} as CompDTO  
18 -  
19 - watchCurrentBreakpoint() {  
20 - Logger.info(TAG, `watchCurrentBreakpoint, this.currentBreakpoint: ${this.currentBreakpoint}`);  
21 - }  
22 -  
23 - aboutToAppear() {  
24 - Logger.info(TAG, `aboutToAppear, beanList:${this.compDTO?.operDataList?.length}, currentBreakpoint:${this.currentBreakpoint}`);  
25 - }  
26 -  
27 - aboutToDisappear() {  
28 - Logger.info(TAG, 'aboutToDisappear');  
29 - }  
30 -  
31 - onPageShow() {  
32 - Logger.info(TAG, 'onPageShow');  
33 - }  
34 -  
35 - onPageHide() {  
36 - Logger.info(TAG, 'onPageHide');  
37 - }  
38 -  
39 - onBackPress() {  
40 - Logger.info(TAG, 'onBackPress');  
41 - }  
42 -  
43 - build() {  
44 - if (this.compDTO && this.compDTO?.operDataList?.length > 0) {  
45 - Swiper() {  
46 - ForEach(this.compDTO?.operDataList, (item: ContentDTO, index: number) => {  
47 - this.buildItemBanner01(item, index)  
48 - })  
49 - }  
50 - .margin({ left: $r('app.float.main_margin'), right: $r('app.float.main_margin') })  
51 - .padding({ bottom: 14 })  
52 - .displayCount(this.buildDisplayCount()) // 仅展示1个图片  
53 - .cachedCount(2)  
54 - .index(1) // The default index of Swiper.  
55 - .autoPlay(true)  
56 - .interval(DelayTimeEnum.INTERVAL_4000)  
57 - .indicator(Indicator.dot()  
58 - .right(5)  
59 - .itemWidth(4)  
60 - .itemHeight(4)  
61 - .selectedItemWidth(10)  
62 - .selectedItemHeight(6))  
63 - .loop(true)  
64 - .duration(DelayTimeEnum.DURATION_1000)  
65 - .vertical(false)  
66 - .curve(Curve.Linear)  
67 - .onChange((index: number) => {  
68 - Logger.info(TAG, `Swiper onChange index : ${index}`);  
69 - })  
70 - } else {  
71 - EmptyComponent({ emptyHeight: 200 })  
72 - }  
73 - }  
74 -  
75 - public buildDisplayCount(): number {  
76 - return new BreakPointType({ xs: 1, sm: 1, md: 2, lg: 3 }).getValue(this.currentBreakpoint)  
77 - }  
78 -  
79 - /**  
80 - * 组件项  
81 - *  
82 - * @param programmeBean item 组件项  
83 - */  
84 - @Builder  
85 - buildItemBanner01(item: ContentDTO, index: number) {  
86 - CarouselLayout01CardView({  
87 - item: item,  
88 - index: index  
89 - })  
90 - }  
91 -}  
  1 +import { CommonConstants, CompStyle } from 'wdConstant';
  2 +import { BannerComponent } from './view/BannerComponent';
  3 +import { LabelComponent } from './view/LabelComponent';
  4 +import { TitleAbbrComponent } from './view/TitleAbbrComponent';
  5 +import { TitleAllComponent } from './view/TitleAllComponent';
  6 +import { HorizontalStrokeCardThreeTwoRadioForOneComponent } from './view/HorizontalStrokeCardThreeTwoRadioForOneComponent';
  7 +import { HorizontalStrokeCardThreeTwoRadioForTwoComponent } from './view/HorizontalStrokeCardThreeTwoRadioForTwoComponent';
  8 +import { HorizontalStrokeCardThreeTwoRadioForMoreComponent } from './view/HorizontalStrokeCardThreeTwoRadioForMoreComponent';
  9 +import { CompDTO } from 'wdBean';
  10 +
  11 +/**
  12 + * comp适配器.
  13 + */
  14 +@Component
  15 +export struct CompParser {
  16 + compDTO: CompDTO = {} as CompDTO;
  17 + compIndex: number = 0;
  18 +
  19 + build() {
  20 + this.componentBuilder(this.compDTO, this.compIndex);
  21 + }
  22 +
  23 + @Builder
  24 + componentBuilder(compDTO: CompDTO, compIndex: number) {
  25 + if (compDTO.compStyle === CompStyle.Label_03) {
  26 + LabelComponent({ compDTO: compDTO })
  27 + } else if (compDTO.compStyle === CompStyle.Title_Abbr_01) {
  28 + TitleAbbrComponent({ compDTO: compDTO })
  29 + } else if (compDTO.compStyle === CompStyle.Title_All_01) {
  30 + TitleAllComponent({ compDTO: compDTO })
  31 + } else if (compDTO.compStyle === CompStyle.Carousel_Layout_01) {
  32 + BannerComponent({ compDTO: compDTO })
  33 + } else {
  34 + // todo:组件未实现 / Component Not Implemented
  35 + Text(compDTO.compStyle)
  36 + .width(CommonConstants.FULL_PARENT)
  37 + .padding(10)
  38 + // .backgroundColor(Color.Brown) // 展示本页未实现的compStyle
  39 + }
  40 + }
  41 +}
  1 +import { CompDTO } from '../repository/bean/CompDTO';
  2 +import { ContentDTO } from '../repository/bean/ContentDTO';
  3 +
  4 +const FULL_PARENT: string = '100%';
  5 +const COLUMNS_TEMPLATE_ONE: string = '1fr';
  6 +const COLUMNS_TEMPLATE_TWO: string = '1fr 1fr';
  7 +const COLUMNS_TEMPLATE_THREE: string = '1fr 1fr 1fr';
  8 +const COLUMNS_TEMPLATE_FOUR: string = '1fr 1fr 1fr 1fr';
  9 +const COLUMNS_TEMPLATE_SIX: string = '1fr 1fr 1fr 1fr 1fr 1fr';
  10 +
  11 +const TAG = 'DemoPreviewerComponent';
  12 +
  13 +/**
  14 + * xxxx 布局及功能说明
  15 + *
  16 + * 【查看ArkUI预览效果】在线参考文档:
  17 + * https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/previewer-0000001054328973-V3#section146052489820
  18 + */
  19 +@Entry
  20 +@Component
  21 +export struct DemoPreviewerComponent {
  22 + @State compDTO: CompDTO = {
  23 + compStyle: 'compStyle3',
  24 + operDataList: [
  25 + {
  26 + title: 'title0',
  27 + description: "description0",
  28 + coverUrl: 'https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231208/image/display/d4496925a1264a749975ae9b01a4ef46.png?x-oss-process=image/resize,w_550/quality,q_90/format,jpg'
  29 + } as ContentDTO,
  30 + {
  31 + title: 'title1 title1 title1 title1 title1 title1 title1 title1 title1',
  32 + description: "description1",
  33 + coverUrl: "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20240104/image/display/c4a9b526e0994d1bbd3ac8450f5cfc6c.jpg?x-oss-process=image/resize,w_550/quality,q_90/format,jpg",
  34 + } as ContentDTO,
  35 + {
  36 + title: 'title2',
  37 + description: "description2",
  38 + coverUrl: "https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231206/image/live/bbe6d821e92b48919d90c7dadfd1f05a.jpg?x-oss-process=image/resize,l_850/auto-orient,1/quality,q_95/format,jpg",
  39 + } as ContentDTO,
  40 + {
  41 + title: 'title3',
  42 + description: "description3",
  43 + coverUrl: 'https://cdnjdphoto.aikan.pdnews.cn/sjbj-20231109/image/live/102e6eb9356b4ef19405b04c1f6ff875.png?x-oss-process=image/resize,l_850/auto-orient,1/quality,q_95/format,jpg'
  44 + } as ContentDTO,
  45 + {
  46 + title: 'title4',
  47 + description: "description4",
  48 + coverUrl: "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231218/image/display/62bdbbb35dbd45689e00790c81f04c4b.png?x-oss-process=image/resize,w_550/quality,q_90/format,jpg",
  49 + } as ContentDTO,
  50 + {
  51 + title: 'title5',
  52 + description: "description5",
  53 + coverUrl: "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231218/image/display/f79bbaa5a33b4bd88176071c4f797ff6.png?x-oss-process=image/resize,w_550/quality,q_90/format,jpg",
  54 + } as ContentDTO,
  55 + {
  56 + title: 'title6',
  57 + description: "description6",
  58 + coverUrl: "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231218/image/display/2c1d917009584ce2bb4a35cbb3a860a0.png?x-oss-process=image/resize,w_550/quality,q_90/format,jpg",
  59 + } as ContentDTO,
  60 + {
  61 + title: 'title7',
  62 + description: "description7",
  63 + coverUrl: "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231222/image/display/117dc516ca5c42d5843c0d32050c9fc6.jpeg?x-oss-process=image/resize,w_240/quality,q_90/format,jpg",
  64 + } as ContentDTO,
  65 + {
  66 + title: 'title8',
  67 + description: "description8",
  68 + coverUrl: "https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231228/image/display/90a2db4077d44a1f887f068fc659d977.jpeg?x-oss-process=image/resize,w_550/quality,q_90/format,jpg",
  69 + } as ContentDTO
  70 + ]
  71 + } as CompDTO
  72 +
  73 + aboutToAppear() {
  74 + // this.compDTO = {
  75 + // compStyle: 'compStyle3',
  76 + // operDataList: [
  77 + // {
  78 + // title: 'title0',
  79 + // description: "description0",
  80 + // coverUrl: 'https://uatjdcdnphoto.aikan.pdnews.cn/sjbj-20231208/image/display/d4496925a1264a749975ae9b01a4ef46.png?x-oss-process=image/resize,w_550/quality,q_90/format,jpg'
  81 + // } as ContentDTO
  82 + // ]
  83 + // } as CompDTO
  84 +
  85 + this.compDTO.operDataList[0].title = 'title_first_0'
  86 + }
  87 +
  88 + build() {
  89 + Grid() {
  90 + ForEach(this.compDTO.operDataList, (item: ContentDTO, index: number) => {
  91 + GridItem() {
  92 + this.gridItemView(item, index)
  93 + }
  94 + }, (item: ContentDTO, index: number) => JSON.stringify(item))
  95 + }
  96 + .height(FULL_PARENT)
  97 + .margin({ top: 10, bottom: 10, left: $r('app.float.main_margin'), right: $r('app.float.main_margin') })
  98 + .columnsTemplate(COLUMNS_TEMPLATE_TWO)
  99 + .columnsGap(4)
  100 + .rowsGap(2)
  101 + }
  102 +
  103 + /**
  104 + * 布局描述
  105 + *
  106 + * @param ContentDTO item 组件项
  107 + * @param index
  108 + */
  109 + @Builder
  110 + gridItemView(item: ContentDTO, index: number) {
  111 + Column() {
  112 + Image(item.coverUrl)
  113 + .width(FULL_PARENT)// .aspectRatio(3 / 4) // 宽/高比:纵向
  114 + // .aspectRatio(1 / 1) // 宽/高比:正方形
  115 + .aspectRatio(16 / 9)// 宽/高比:横向
  116 + .margin({ top: 8 })
  117 + .borderRadius(10)
  118 +
  119 + Text(item.title)
  120 + .width(FULL_PARENT)
  121 + .margin({ top: 4, left: 2, right: 2, bottom: 4 })
  122 + .backgroundColor(Color.White)
  123 + .fontWeight(FontWeight.Bold)// .textAlign(TextAlign.Center)
  124 + .fontSize($r('app.float.font_size_12'))
  125 + .fontColor('#808080')
  126 + .maxLines(1)
  127 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  128 + }
  129 + .width(FULL_PARENT)
  130 + .backgroundColor(Color.Yellow)
  131 + .justifyContent(FlexAlign.Center)
  132 + .onClick(() => {
  133 + console.info(TAG, `gridItemView onClick, index: ${index}`);
  134 + // MGRouterRule.jumpWithAction(item.action)
  135 + })
  136 + }
  137 +}
  1 +import { CommonConstants } from 'wdConstant';
  2 +import { CompDTO } from '../repository/bean/CompDTO';
  3 +import { CompUtils } from '../utils/CompUtils';
  4 +
  5 +@Component
  6 +export struct HeadPictureCardComponent {
  7 + @State compDTO: CompDTO = {} as CompDTO
  8 +
  9 + build() {
  10 + Stack() {
  11 + Image(this.compDTO.backgroundImgUrl)
  12 + .width(CommonConstants.FULL_WIDTH)
  13 + .height(CommonConstants.FULL_HEIGHT)
  14 + Row()
  15 + .width(CommonConstants.FULL_WIDTH)
  16 + .height(59)
  17 + .linearGradient({
  18 + colors:[
  19 + ['rgba(0, 0, 0, 0.0)', 0.0], ['rgba(0, 0, 0, 0.3)', 1.0]
  20 + ]
  21 + })
  22 + Row() {
  23 + Text(CompUtils.getLabelTitle(this.compDTO.extraData))
  24 + .width(CommonConstants.FULL_WIDTH)
  25 + .height(CommonConstants.FULL_HEIGHT)
  26 + .fontColor(Color.White)
  27 + .fontSize($r('app.float.normal_text_size'))
  28 + .fontWeight(FontWeight.Bold)
  29 + }
  30 + .height(25)
  31 + .margin({left: 12, bottom: 10, right: 12})
  32 + }
  33 + .alignContent(Alignment.Bottom)
  34 + }
  35 +}
1 -import { CompDTO, CompStyle, GroupDTO, ViewType } from 'wdBean';  
2 -import { CommonConstants } from 'wdConstant';  
3 -import { LazyDataSource, Logger } from 'wdKit';  
4 -import { PageViewModel } from '../viewmodel/PageViewModel';  
5 -import { BannerComponent } from './BannerComponent';  
6 -import { EmptyComponent } from './EmptyComponent';  
7 -import { ErrorComponent } from './ErrorComponent';  
8 -import { GridLayout01Component } from './GridLayout01Component';  
9 -import { LabelComponent } from './LabelComponent';  
10 -import { LoadingComponent } from './LoadingComponent';  
11 -import { SingleColumnComponent } from './SingleColumnComponent';  
12 -import { SingleRow03Component } from './SingleRow03Component';  
13 -import { WaterFlowComponent } from './WaterFlowComponent';  
14 -  
15 -const TAG = 'PageComponent';  
16 -  
17 -@Component  
18 -export struct PageComponent {  
19 - @Prop viewType: number = ViewType.LOADED;  
20 - // Group数据及子组件数据  
21 - @State groupList: LazyDataSource<GroupDTO> = new LazyDataSource();  
22 - @State currentTopNavSelectedIndex: number = 0;  
23 -  
24 - build() {  
25 - if (this.viewType == ViewType.LOADING) {  
26 - LoadingComponent()  
27 - } else if (this.viewType == ViewType.ERROR) {  
28 - ErrorComponent()  
29 - } else if (this.viewType == ViewType.EMPTY) {  
30 - EmptyComponent()  
31 - } else {  
32 - List() {  
33 - LazyForEach(this.groupList, (groupDTO: GroupDTO, groupIndex: number) => {  
34 - ListItem() {  
35 - Column() {  
36 - ForEach(groupDTO.compList, (compDTO: CompDTO, compIndex: number) => {  
37 - this.componentBuilder(compDTO, groupIndex, compIndex)  
38 - })  
39 - }  
40 - }  
41 - })  
42 - }  
43 - .cachedCount(5)  
44 - .height(CommonConstants.FULL_PARENT)  
45 - }  
46 - }  
47 -  
48 - @Builder  
49 - componentBuilder(compDTO: CompDTO, groupIndex: number, compIndex: number) {  
50 - if (compDTO.compStyle === CompStyle.Label_03) {  
51 - LabelComponent({ compDTO: compDTO })  
52 - } else if (compDTO.compStyle === CompStyle.Carousel_Layout_01) {  
53 - BannerComponent({ compDTO: compDTO })  
54 - } else if (compDTO.compStyle === CompStyle.Single_Row_03) {  
55 - SingleRow03Component({ dataList: compDTO.operDataList })  
56 - } else if (compDTO.compStyle === CompStyle.Single_Column_01 || compDTO.compStyle === CompStyle.Single_Column_02) {  
57 - SingleColumnComponent({ compDTO: compDTO })  
58 - } else if (compDTO.compStyle === CompStyle.Grid_Layout_01) {  
59 - GridLayout01Component({ dataList: compDTO.operDataList })  
60 - } else if (compDTO.compStyle === CompStyle.Masonry_Layout_01) {  
61 - WaterFlowComponent({ compDTO: compDTO })  
62 - } else {  
63 - // todo:组件未实现 / Component Not Implemented  
64 - Text(compDTO.compStyle)  
65 - .width(CommonConstants.FULL_PARENT)  
66 - .padding(10)  
67 - // .backgroundColor(Color.Brown) // 展示本页未实现的compStyle  
68 - }  
69 - }  
70 -  
71 - aboutToAppear() {  
72 - Logger.info(TAG, `aboutToAppear, this.pageId: ${this.viewType} this.currentTopNavSelectedIndex: ${this.currentTopNavSelectedIndex}`);  
73 - if (this.currentTopNavSelectedIndex === 1) { // 顶导tab的第0个item是【热点】,第1个item是【推荐】  
74 - this.groupList.replaceAll()  
75 - let groupDto = PageViewModel.getGroup2DTO(getContext(this))  
76 - if (groupDto) {  
77 - this.groupList.push(groupDto)  
78 - }  
79 - } else {  
80 - let groupDto = PageViewModel.getGroupDTO(getContext(this))  
81 - if (groupDto) {  
82 - this.groupList.push(groupDto)  
83 - }  
84 - }  
85 - }  
86 -}  
87 -  
1 -import { BottomNavBean, BottomNavi } from 'wdBean';  
2 -import { CommonConstants } from 'wdConstant';  
3 -import { LazyDataSource, Logger } from 'wdKit'; 1 +import { BottomNavi, CommonConstants } from 'wdConstant';
  2 +import { BottomNavDTO } from 'wdBean';
  3 +import { Logger } from 'wdKit';
4 import { TopNavigationComponent } from './TopNavigationComponent'; 4 import { TopNavigationComponent } from './TopNavigationComponent';
5 -import { PageComponent } from './PageComponent'; 5 +import { MinePageComponent } from './MinePageComponent';
  6 +import { CompUtils } from '../../utils/CompUtils';
  7 +import PageViewModel from '../../viewmodel/PageViewModel';
6 8
7 const TAG = 'BottomNavigationComponent'; 9 const TAG = 'BottomNavigationComponent';
8 10
@@ -12,7 +14,7 @@ const TAG = 'BottomNavigationComponent'; @@ -12,7 +14,7 @@ const TAG = 'BottomNavigationComponent';
12 @Component 14 @Component
13 export struct BottomNavigationComponent { 15 export struct BottomNavigationComponent {
14 // 底导/顶导全部数据 16 // 底导/顶导全部数据
15 - @Prop @Watch('onBottomNavigationDataUpdated') bottomNavList: BottomNavBean[] = [] 17 + @State @Watch('onBottomNavigationDataUpdated') bottomNavList: BottomNavDTO[] = []
16 // 底导当前选中/焦点下标 18 // 底导当前选中/焦点下标
17 @Provide currentNavIndex: number = BottomNavi.NEWS; 19 @Provide currentNavIndex: number = BottomNavi.NEWS;
18 // 底导TabsController 20 // 底导TabsController
@@ -27,8 +29,13 @@ export struct BottomNavigationComponent { @@ -27,8 +29,13 @@ export struct BottomNavigationComponent {
27 */ 29 */
28 readonly SIXTY_OPACITY: number = 0.6; 30 readonly SIXTY_OPACITY: number = 0.6;
29 31
30 - aboutToAppear() { 32 + async aboutToAppear() {
31 Logger.info(TAG, `aboutToAppear currentNavIndex: ${this.currentNavIndex}`); 33 Logger.info(TAG, `aboutToAppear currentNavIndex: ${this.currentNavIndex}`);
  34 + let bottomNav = await PageViewModel.getBottomNavData(getContext(this))
  35 + if (bottomNav && bottomNav.bottomNavList != null) {
  36 + Logger.info(TAG, `aboutToAppear, bottomNav.length: ${bottomNav.bottomNavList.length}`);
  37 + this.bottomNavList = bottomNav.bottomNavList
  38 + }
32 } 39 }
33 40
34 aboutToDisappear() { 41 aboutToDisappear() {
@@ -37,11 +44,12 @@ export struct BottomNavigationComponent { @@ -37,11 +44,12 @@ export struct BottomNavigationComponent {
37 44
38 build() { 45 build() {
39 Tabs({ barPosition: BarPosition.End, index: this.currentNavIndex, controller: this.navController }) { 46 Tabs({ barPosition: BarPosition.End, index: this.currentNavIndex, controller: this.navController }) {
40 - ForEach(this.bottomNavList, (navItem: BottomNavBean, index: number) => { 47 + ForEach(this.bottomNavList, (navItem: BottomNavDTO, index: number) => {
41 TabContent() { 48 TabContent() {
42 Column() { 49 Column() {
43 - if (navItem.topNavChannelList && navItem.topNavChannelList.length == 0 && navItem.name == '我的') {  
44 - PageComponent({ groupList: new LazyDataSource() }) // todo:我的页面组件数据列表 50 + if (CompUtils.isMine(navItem)) {
  51 + // 我的页面组件数据列表
  52 + MinePageComponent()
45 } else { 53 } else {
46 TopNavigationComponent({ topNavList: navItem.topNavChannelList }) 54 TopNavigationComponent({ topNavList: navItem.topNavChannelList })
47 } 55 }
@@ -60,7 +68,7 @@ export struct BottomNavigationComponent { @@ -60,7 +68,7 @@ export struct BottomNavigationComponent {
60 } 68 }
61 69
62 @Builder 70 @Builder
63 - tabBarBuilder(navItem: BottomNavBean, index: number) { 71 + tabBarBuilder(navItem: BottomNavDTO, index: number) {
64 Stack({ alignContent: Alignment.Bottom }) { 72 Stack({ alignContent: Alignment.Bottom }) {
65 Image(this.currentNavIndex === index ? navItem.iconC : navItem.icon) 73 Image(this.currentNavIndex === index ? navItem.iconC : navItem.icon)
66 .height(CommonConstants.FULL_PARENT) 74 .height(CommonConstants.FULL_PARENT)
1 -import { Action, ContentDTO, Params, ScreenType } from 'wdBean';  
2 -import { CommonConstants, ConfigConstants } from 'wdConstant'; 1 +import { Action, ContentDTO, Params } from 'wdBean';
  2 +import { CommonConstants, ConfigConstants, ScreenType } from 'wdConstant';
3 import { Logger } from 'wdKit'; 3 import { Logger } from 'wdKit';
4 -import { CompUtils } from '../utils/CompUtils'; 4 +import { CompUtils } from '../../utils/CompUtils';
5 import { WDRouterRule } from 'wdRouter'; 5 import { WDRouterRule } from 'wdRouter';
6 6
7 const TAG: string = 'CardView'; 7 const TAG: string = 'CardView';
  1 +import { PageComponent } from './PageComponent';
  2 +
  3 +const TAG = 'ColumnPageComponent';
  4 +
  5 +/**
  6 + * 二级栏目页面,展排数据
  7 + */
  8 +@Component
  9 +export struct ColumnPageComponent {
  10 + @State currentTopNavSelectedIndex: number = 0;
  11 + pageId: string = "";
  12 + channelId: string = "";
  13 +
  14 + build() {
  15 + PageComponent({
  16 + currentTopNavSelectedIndex: $currentTopNavSelectedIndex,
  17 + navIndex: this.currentTopNavSelectedIndex,
  18 + pageId: this.pageId,
  19 + channelId: this.channelId,
  20 + });
  21 +
  22 + }
  23 +}
  24 +
  1 +import { RefreshConstants } from '../../utils/RefreshConstants';
  2 +import { RefreshLayoutBean } from './RefreshLayoutBean';
  3 +
  4 +/**
  5 + * Custom layout to show refresh or load.
  6 + */
  7 +@Component
  8 +export default struct CustomLayout {
  9 + @ObjectLink refreshBean: RefreshLayoutBean;
  10 +
  11 + build() {
  12 + Row() {
  13 + Image(this.refreshBean.imageSrc)
  14 + .width(RefreshConstants.RefreshLayout_IMAGE_WIDTH)
  15 + .height(RefreshConstants.RefreshLayout_IMAGE_HEIGHT)
  16 +
  17 + Text(this.refreshBean.textValue)
  18 + .margin({
  19 + left: RefreshConstants.RefreshLayout_TEXT_MARGIN_LEFT,
  20 + bottom: RefreshConstants.RefreshLayout_TEXT_MARGIN_BOTTOM
  21 + })
  22 + .fontSize(RefreshConstants.RefreshLayout_TEXT_FONT_SIZE)
  23 + .textAlign(TextAlign.Center)
  24 + }
  25 + .clip(true)
  26 + .width(RefreshConstants.FULL_WIDTH)
  27 + .justifyContent(FlexAlign.Center)
  28 + .height(this.refreshBean.heightValue)
  29 + }
  30 +}
  1 +import CustomRefreshLoadLayout from './CustomRefreshLoadLayout';
  2 +import { RefreshLayoutBean } from './RefreshLayoutBean';
  3 +
  4 +/**
  5 + * The load more layout component.
  6 + */
  7 +@Component
  8 +export default struct LoadMoreLayout {
  9 + @ObjectLink refreshBean: RefreshLayoutBean;
  10 +
  11 + build() {
  12 + Column() {
  13 + if (this.refreshBean.isVisible) {
  14 + CustomRefreshLoadLayout({
  15 + refreshBean: new RefreshLayoutBean(this.refreshBean.isVisible,
  16 + this.refreshBean.imageSrc, this.refreshBean.textValue, this.refreshBean.heightValue)
  17 + })
  18 + } else {
  19 + CustomRefreshLoadLayout({
  20 + refreshBean: new RefreshLayoutBean(this.refreshBean.isVisible,
  21 + this.refreshBean.imageSrc, this.refreshBean.textValue, 0)
  22 + })
  23 + }
  24 + }
  25 + }
  26 +}
  1 +const TAG = 'PageComponent';
  2 +
  3 +/**
  4 + * 我的页面
  5 + */
  6 +@Component
  7 +export struct MinePageComponent {
  8 + // TODO 待完善
  9 + build() {
  10 + Text('我的页面')
  11 + }
  12 +}
  13 +
  1 +import { RefreshConstants } from '../../utils/RefreshConstants'
  2 +
  3 +/**
  4 + * The No more data layout component.
  5 + */
  6 +@Component
  7 +export default struct NoMoreLayout {
  8 + build() {
  9 + Row() {
  10 + Text($r('app.string.footer_text'))
  11 + .margin({ left: RefreshConstants.NoMoreLayoutConstant_NORMAL_PADDING })
  12 + .fontSize(RefreshConstants.NoMoreLayoutConstant_TITLE_FONT)
  13 + .textAlign(TextAlign.Center)
  14 + }
  15 + .width(RefreshConstants.FULL_WIDTH)
  16 + .justifyContent(FlexAlign.Center)
  17 + .height(RefreshConstants.CUSTOM_LAYOUT_HEIGHT)
  18 + }
  19 +}
  1 +import { CommonConstants, ViewType } from 'wdConstant';
  2 +import { Logger } from 'wdKit';
  3 +import PageViewModel from '../../viewmodel/PageViewModel';
  4 +import { EmptyComponent } from '../view/EmptyComponent';
  5 +import { ErrorComponent } from '../view/ErrorComponent';
  6 +import PageModel from '../../viewmodel/PageModel';
  7 +import { listTouchEvent } from '../../utils/PullDownRefresh';
  8 +import RefreshLayout from './RefreshLayout';
  9 +import { RefreshLayoutBean } from './RefreshLayoutBean';
  10 +import NoMoreLayout from './NoMoreLayout';
  11 +import LoadMoreLayout from './LoadMoreLayout';
  12 +import CustomRefreshLoadLayout from './CustomRefreshLoadLayout';
  13 +import { CompParser } from '../CompParser';
  14 +import { CompDTO } from 'wdBean';
  15 +
  16 +const TAG = 'PageComponent';
  17 +
  18 +@Component
  19 +export struct PageComponent {
  20 + @State private pageModel: PageModel = new PageModel();
  21 + navIndex: number = 0;
  22 + pageId: string = "";
  23 + channelId: string = "";
  24 + @Link @Watch('onChange') currentTopNavSelectedIndex: number
  25 +
  26 + build() {
  27 + Column() {
  28 + if (this.pageModel.viewType == ViewType.LOADING) {
  29 + // LoadingComponent()
  30 + this.LoadingLayout()
  31 + } else if (this.pageModel.viewType == ViewType.ERROR) {
  32 + ErrorComponent()
  33 + } else if (this.pageModel.viewType == ViewType.EMPTY) {
  34 + EmptyComponent()
  35 + } else {
  36 + this.ListLayout()
  37 + }
  38 + }
  39 + .width(CommonConstants.FULL_PARENT)
  40 + .height(CommonConstants.FULL_PARENT)
  41 + .onTouch((event: TouchEvent | undefined) => {
  42 + if (event) {
  43 + if (this.pageModel.viewType === ViewType.LOADED) {
  44 + listTouchEvent(this.pageModel, event);
  45 + }
  46 + }
  47 + })
  48 +
  49 + }
  50 +
  51 + @Builder ListLayout() {
  52 + List() {
  53 + // 下拉刷新
  54 + ListItem() {
  55 + RefreshLayout({
  56 + refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullDown, this.pageModel.pullDownRefreshImage,
  57 + this.pageModel.pullDownRefreshText, this.pageModel.pullDownRefreshHeight)
  58 + })
  59 + }
  60 +
  61 + LazyForEach(this.pageModel.compList, (compDTO: CompDTO, compIndex: number) => {
  62 + ListItem() {
  63 + Column() {
  64 + CompParser({ compDTO: compDTO, compIndex: compIndex });
  65 + }
  66 + }
  67 + })
  68 +
  69 + // 加载更多
  70 + ListItem() {
  71 + if (this.pageModel.hasMore) {
  72 + LoadMoreLayout({
  73 + refreshBean: new RefreshLayoutBean(this.pageModel.isVisiblePullUpLoad, this.pageModel.pullUpLoadImage,
  74 + this.pageModel.pullUpLoadText, this.pageModel.pullUpLoadHeight)
  75 + })
  76 + } else {
  77 + NoMoreLayout()
  78 + }
  79 + }
  80 + }
  81 + .cachedCount(5)
  82 + .height(CommonConstants.FULL_PARENT)
  83 + .onScrollIndex((start: number, end: number) => {
  84 + // Listen to the first index of the current list.
  85 + this.pageModel.startIndex = start;
  86 + // 包含了 头尾item,判断时需要考虑+2
  87 + this.pageModel.endIndex = end;
  88 + })
  89 + }
  90 +
  91 + @Builder LoadingLayout() {
  92 + CustomRefreshLoadLayout({ refreshBean: new RefreshLayoutBean(true,
  93 + $r('app.media.ic_pull_up_load'), $r('app.string.pull_up_load_text'), this.pageModel.pullDownRefreshHeight) })
  94 + }
  95 +
  96 + async aboutToAppear() {
  97 + // 选中tab,才请求数据。拦截大量接口请求
  98 + if (this.navIndex === this.currentTopNavSelectedIndex) {
  99 + this.getData();
  100 + }
  101 + }
  102 +
  103 + onChange() {
  104 + if (this.navIndex === this.currentTopNavSelectedIndex) {
  105 + this.getData();
  106 + }
  107 + }
  108 +
  109 + async getData() {
  110 + Logger.info(TAG, `getData id: ${this.pageId} , ${this.channelId} , navIndex: ${this.currentTopNavSelectedIndex}`);
  111 + this.pageModel.pageId = this.pageId;
  112 + this.pageModel.groupId = this.pageId;
  113 + this.pageModel.channelId = this.channelId;
  114 + this.pageModel.currentPage = 1;
  115 + let pageDto = await PageViewModel.getPageData(this.pageModel.pageId, this.pageModel.pageId, this.pageModel.channelId
  116 + , this.pageModel.currentPage, this.pageModel.pageSize, getContext(this))
  117 + if (pageDto && pageDto.compList && pageDto.compList.length > 0) {
  118 + this.pageModel.viewType = ViewType.LOADED;
  119 + this.pageModel.compList.push(...pageDto.compList)
  120 + if (pageDto.compList.length === this.pageModel.pageSize) {
  121 + this.pageModel.currentPage++;
  122 + this.pageModel.hasMore = true;
  123 + } else {
  124 + this.pageModel.hasMore = false;
  125 + }
  126 + } else {
  127 + Logger.debug(TAG, 'aboutToAppear, data response page ' + this.pageId + ', comp list is empty.');
  128 + this.pageModel.viewType = ViewType.EMPTY;
  129 + }
  130 + }
  131 +}
  132 +
  1 +import CustomRefreshLoadLayout from './CustomRefreshLoadLayout';
  2 +import { RefreshLayoutBean } from './RefreshLayoutBean';
  3 +
  4 +/**
  5 + * The refresh layout component.
  6 + */
  7 +@Component
  8 +export default struct RefreshLayout {
  9 + @ObjectLink refreshBean: RefreshLayoutBean;
  10 +
  11 + build() {
  12 + Column() {
  13 + if (this.refreshBean.isVisible) {
  14 + CustomRefreshLoadLayout({ refreshBean: new RefreshLayoutBean
  15 + (this.refreshBean.isVisible, this.refreshBean.imageSrc, this.refreshBean.textValue,
  16 + this.refreshBean.heightValue) })
  17 + }
  18 + }
  19 + }
  20 +}
  1 +/**
  2 + * Custom refresh load layout data.
  3 + */
  4 +@Observed
  5 +export class RefreshLayoutBean {
  6 + /**
  7 + * Custom refresh load layout isVisible.
  8 + */
  9 + isVisible: boolean;
  10 +
  11 + /**
  12 + * Custom refresh load layout imageSrc.
  13 + */
  14 + imageSrc: Resource;
  15 +
  16 + /**
  17 + * Custom refresh load layout textValue.
  18 + */
  19 + textValue: Resource;
  20 +
  21 + /**
  22 + * Custom refresh load layout heightValue.
  23 + */
  24 + heightValue: number;
  25 +
  26 + constructor(isVisible: boolean, imageSrc: Resource, textValue: Resource, heightValue: number) {
  27 + this.isVisible = isVisible;
  28 + this.imageSrc = imageSrc;
  29 + this.textValue = textValue;
  30 + this.heightValue = heightValue;
  31 + }
  32 +}
1 -import { CompDTO, CompStyle, ContentDTO } from 'wdBean';  
2 -import { BreakpointConstants } from 'wdConstant'; 1 +import { CompDTO, ContentDTO } from 'wdBean';
  2 +import { BreakpointConstants, CompStyle } from 'wdConstant';
3 import { BreakPointType, Logger } from 'wdKit'; 3 import { BreakPointType, Logger } from 'wdKit';
  4 +import { EmptyComponent } from '../view/EmptyComponent';
4 import { SingleColumn01CardView, SingleColumn02CardView } from './CardView'; 5 import { SingleColumn01CardView, SingleColumn02CardView } from './CardView';
5 -import { EmptyComponent } from './EmptyComponent';  
6 6
7 const TAG = 'SingleColumn01Component'; 7 const TAG = 'SingleColumn01Component';
8 8
1 -import { Action, GroupDTO, Params, TopNavBean } from 'wdBean'; 1 +import { CompDTO, TopNavDTO } from 'wdBean';
2 import { LazyDataSource, Logger } from 'wdKit'; 2 import { LazyDataSource, Logger } from 'wdKit';
3 -import { WDRouterRule } from 'wdRouter';  
4 import { PageComponent } from './PageComponent'; 3 import { PageComponent } from './PageComponent';
5 4
6 const TAG = 'TopNavigationComponent'; 5 const TAG = 'TopNavigationComponent';
@@ -13,31 +12,23 @@ export struct TopNavigationComponent { @@ -13,31 +12,23 @@ export struct TopNavigationComponent {
13 // 顶导当前选中/焦点下标 12 // 顶导当前选中/焦点下标
14 @State currentTopNavSelectedIndex: number = 0; 13 @State currentTopNavSelectedIndex: number = 0;
15 // 顶导数据 14 // 顶导数据
16 - @State @Watch('onTopNavigationDataUpdated') topNavList: TopNavBean[] = []  
17 - @State groupList: LazyDataSource<GroupDTO> = new LazyDataSource(); 15 + @State @Watch('onTopNavigationDataUpdated') topNavList: TopNavDTO[] = []
  16 + @State compList: LazyDataSource<CompDTO> = new LazyDataSource();
18 readonly MAX_LINE: number = 1; 17 readonly MAX_LINE: number = 1;
19 18
20 build() { 19 build() {
21 - Column(){  
22 - Image($r('app.media.icon_ren_min_ri_bao'))  
23 - .width(72)  
24 - .height(29)  
25 - .onClick((event: ClickEvent) => {  
26 - let taskAction: Action = {  
27 - type: 'JUMP_INNER_NEW_PAGE',  
28 - params: {  
29 - pageID: 'E_NEWSPAPER'  
30 - } as Params,  
31 - };  
32 - WDRouterRule.jumpWithAction(taskAction)  
33 - })  
34 Tabs() { 20 Tabs() {
35 - ForEach(this.topNavList, (navItem: TopNavBean, index: number) => { 21 + ForEach(this.topNavList, (navItem: TopNavDTO, index: number) => {
36 TabContent() { 22 TabContent() {
37 - PageComponent({ groupList: this.groupList, currentTopNavSelectedIndex:index}) 23 + PageComponent({
  24 + currentTopNavSelectedIndex: $currentTopNavSelectedIndex,
  25 + navIndex: index,
  26 + pageId: navItem.pageId + '',
  27 + channelId: navItem.channelId + ''
  28 + })
38 } 29 }
39 .tabBar(this.tabBarBuilder(navItem, index)) 30 .tabBar(this.tabBarBuilder(navItem, index))
40 - }, (navItem: TopNavBean) => JSON.stringify(navItem)); 31 + }, (navItem: TopNavDTO) => JSON.stringify(navItem));
41 } 32 }
42 .barHeight($r('app.float.top_tab_bar_height')) 33 .barHeight($r('app.float.top_tab_bar_height'))
43 .barMode(BarMode.Scrollable) 34 .barMode(BarMode.Scrollable)
@@ -48,10 +39,8 @@ export struct TopNavigationComponent { @@ -48,10 +39,8 @@ export struct TopNavigationComponent {
48 }) 39 })
49 } 40 }
50 41
51 - }  
52 -  
53 @Builder 42 @Builder
54 - tabBarBuilder(item: TopNavBean, index: number) { 43 + tabBarBuilder(item: TopNavDTO, index: number) {
55 Column() { 44 Column() {
56 Text(item.name) 45 Text(item.name)
57 .fontSize(this.currentTopNavSelectedIndex === index ? $r('app.float.selected_text_size') : $r('app.float.normal_text_size')) 46 .fontSize(this.currentTopNavSelectedIndex === index ? $r('app.float.selected_text_size') : $r('app.float.normal_text_size'))
@@ -62,7 +51,7 @@ export struct TopNavigationComponent { @@ -62,7 +51,7 @@ export struct TopNavigationComponent {
62 Divider() 51 Divider()
63 .width(16) 52 .width(16)
64 .strokeWidth(2) // 分割线粗细度。 53 .strokeWidth(2) // 分割线粗细度。
65 - .padding({top:2}) 54 + .padding({ top: 2 })
66 .color(Color.Red) 55 .color(Color.Red)
67 .opacity(this.currentTopNavSelectedIndex === index ? 1 : 0) 56 .opacity(this.currentTopNavSelectedIndex === index ? 1 : 0)
68 } 57 }
1 import { CompDTO, ContentDTO } from 'wdBean'; 1 import { CompDTO, ContentDTO } from 'wdBean';
2 import { BreakPointType, Logger } from 'wdKit'; 2 import { BreakPointType, Logger } from 'wdKit';
  3 +import { EmptyComponent } from '../view/EmptyComponent';
3 import { MasonryLayout01CardView } from './CardView'; 4 import { MasonryLayout01CardView } from './CardView';
4 -import { EmptyComponent } from './EmptyComponent';  
5 5
6 const TAG = 'WaterFlowComponent'; 6 const TAG = 'WaterFlowComponent';
7 7
  1 +/**
  2 + * BannerComponent
  3 + * 轮播图卡/单图
  4 + * 邢照杰
  5 + */
  6 +
  7 +import { CommonConstants } from 'wdConstant';
  8 +import colorSpaceManager from '@ohos.graphics.colorSpaceManager';
  9 +import { CompUtils } from '../../utils/CompUtils';
  10 +import { Action, CompDTO, ContentDTO, Params } from 'wdBean';
  11 +import { Logger } from 'wdKit';
  12 +import { WDRouterRule } from 'wdRouter';
  13 +
  14 +
  15 +const TAG = 'BannerComponent';
  16 +let timerIds: number[] = [];
  17 +
  18 +
  19 +/**
  20 + * 轮播卡(暂时仅展示主标题,不展示子标题)
  21 + * comp类型
  22 + * 重磅推荐/精选/电视剧/电影/综艺/短剧/更多>/
  23 + */
  24 +@Entry
  25 +@Component
  26 +export struct BannerComponent {
  27 + @State compDTO: CompDTO = {} as CompDTO
  28 + @State index: number = 0;
  29 + private bannerContent: ContentDTO = {} as ContentDTO;
  30 + private swiperController: SwiperController = new SwiperController();
  31 +
  32 + aboutToAppear() {
  33 +
  34 + // Data Initialization.
  35 + this.bannerContent = this.compDTO.operDataList[0];
  36 + // Turn on scheduled task.
  37 + if (this.compDTO.operDataList.length > 1) {
  38 + startPlay(this.swiperController);
  39 + }
  40 + }
  41 +
  42 + aboutToDisappear() {
  43 + stopPlay();
  44 + }
  45 +
  46 + build() {
  47 + // 整体父视图
  48 + Column() {
  49 + // 判断数组元素个数
  50 + if (this.compDTO.operDataList.length > 1) {
  51 + // 滚动banner
  52 + Swiper(this.swiperController) {
  53 + ForEach(this.compDTO.operDataList, (item: ContentDTO, index: number) => {
  54 + Stack() {
  55 + // 背景图
  56 + Image(item.coverUrl)
  57 + .objectFit(ImageFit.Fill)
  58 + .borderRadius(5)
  59 +
  60 + // 底部标题和时间
  61 + Column() {
  62 + Text(item.description)
  63 + .fontSize(18)
  64 + .margin({ bottom: 4 })
  65 + .fontColor(Color.White)
  66 + .fontWeight(600)
  67 + .maxLines(1)
  68 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  69 + .padding({ left: 10, right: 5 })
  70 + .width('100%')
  71 + .textAlign(TextAlign.Start)
  72 + if (item.lengthTime) {
  73 + Row() {
  74 + Image($r('app.media.videoTypeIcon'))
  75 + .height(20)
  76 + .width(20)
  77 + // .margin({right:3})
  78 + Text(item.lengthTime + '')
  79 + .padding({ left: 5, right: 5 })
  80 + .fontColor(Color.White)
  81 + }
  82 + .backgroundColor('#333333')
  83 + .height(20)
  84 + .margin({ right: 5, bottom: 3 })
  85 + .alignSelf(ItemAlign.End)
  86 + .borderRadius(2)
  87 + }
  88 + }
  89 + .height('50')
  90 + .width('100%')
  91 + }
  92 + .alignContent(Alignment.BottomStart)
  93 + .onClick((event: ClickEvent) => {
  94 + Logger.info(TAG, `BannerComponent onClick event index: ${this.index}`);
  95 + // let taskAction: Action = {
  96 + // type: 'JUMP_H5_BY_WEB_VIEW',
  97 + // params: {
  98 + // url: ConfigConstants.DETAIL_URL
  99 + // } as Params,
  100 + // };
  101 + // WDRouterRule.jumpWithAction(taskAction)
  102 +
  103 + let taskAction: Action = {
  104 + type: 'JUMP_DETAIL_PAGE',
  105 + params: {
  106 + detailPageType: 7, // 沉浸式竖屏详情页
  107 + contentID: '863556812'
  108 + } as Params,
  109 + };
  110 + WDRouterRule.jumpWithAction(taskAction)
  111 + })
  112 + }, (item: ContentDTO, index: number) => JSON.stringify(item))
  113 + }
  114 + .width('100%')
  115 + .height('100%')
  116 + .index(this.index)
  117 + .indicatorStyle({
  118 + selectedColor: Color.White,
  119 + color: Color.Gray,
  120 + size: 18,
  121 + left: 15
  122 + })
  123 + .indicator(true)
  124 + .duration(500)
  125 + } else {
  126 + // 不滚动banner
  127 + Stack() {
  128 + // 背景图
  129 + Image(this.bannerContent.coverUrl.toString())
  130 + .objectFit(ImageFit.Fill)
  131 + .borderRadius(5)
  132 +
  133 + // 底部标题和时间
  134 + Row() {
  135 + // 标题
  136 + Text(this.bannerContent.description.toString())
  137 + .fontSize(18)
  138 + .fontColor(Color.White)
  139 + .fontWeight(600)
  140 + .maxLines(2)
  141 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  142 + .padding({ left: 10, right: 0, bottom: 5 })
  143 + .width('80%')
  144 + // 时间
  145 + if (this.bannerContent.lengthTime) {
  146 + Row() {
  147 + Image($r('app.media.videoTypeIcon'))
  148 + .height(20)
  149 + .width(20)
  150 + // .margin({right:3})
  151 + Text(this.bannerContent.lengthTime.toString())
  152 + .padding({ left: 5, right: 5 })
  153 + .fontColor(Color.White)
  154 + }
  155 + .backgroundColor('#333333')
  156 + .height(20)
  157 + .borderRadius(2)
  158 + .margin({ bottom: 6 })
  159 + }
  160 + }
  161 + .width('100%')
  162 + .height('100%')
  163 + .alignItems(VerticalAlign.Bottom)
  164 + }
  165 + .alignContent(Alignment.BottomStart)
  166 + .width('100%')
  167 + .height('100%')
  168 + }
  169 + }
  170 + .width('100%')
  171 + .aspectRatio(1.7)
  172 + .padding({ left: 10, right: 15, top: 10, bottom: 10 })
  173 + }
  174 +}
  175 +
  176 +/**
  177 + * start scheduled task.
  178 + *
  179 + * @param swiperController Controller.
  180 + */
  181 +export function startPlay(swiperController: SwiperController) {
  182 + let timerId = setInterval(() => {
  183 + swiperController.showNext();
  184 + }, 3000);
  185 + timerIds.push(timerId);
  186 +}
  187 +
  188 +/**
  189 + * stop scheduled task.
  190 + */
  191 +export function stopPlay() {
  192 + timerIds.forEach((item) => {
  193 + clearTimeout(item);
  194 + })
  195 +}
@@ -46,7 +46,7 @@ export struct EmptyComponent { @@ -46,7 +46,7 @@ export struct EmptyComponent {
46 46
47 Text(this.buildNoDataTip()) 47 Text(this.buildNoDataTip())
48 .fontSize($r('app.float.normal_text_size')) 48 .fontSize($r('app.float.normal_text_size'))
49 - .fontColor('#B2B2B2') 49 + .fontColor('#000000')
50 .fontWeight(FontWeight.Normal) 50 .fontWeight(FontWeight.Normal)
51 .opacity(this.TEXT_OPACITY) 51 .opacity(this.TEXT_OPACITY)
52 .margin({ top: this.EMPTY_TIP_TEXT_MARGIN_TOP }) 52 .margin({ top: this.EMPTY_TIP_TEXT_MARGIN_TOP })
  1 +import { CompDTO } from 'wdBean'
  2 +import { CommonConstants } from 'wdConstant'
  3 +
  4 +@Component
  5 +export struct HorizontalStrokeCardThreeTwoRadioForMoreComponent {
  6 + @State compDTO: CompDTO = {} as CompDTO
  7 + private arr: number[] = [0, 1, 2]
  8 + build() {
  9 + Column() {
  10 + Row() {
  11 + Row() {
  12 + Image($r("app.media.redLine"))
  13 + .width(3)
  14 + .height(16)
  15 + .margin({ right: 4 })
  16 + Text("大标题")
  17 + .fontSize($r("app.float.font_size_17"))
  18 + .fontColor($r("app.color.color_222222"))
  19 + .fontWeight(600)
  20 + }
  21 +
  22 + Row() {
  23 + Text("更多")
  24 + .fontSize($r("app.float.font_size_14"))
  25 + .fontColor($r("app.color.color_999999"))
  26 + .margin({ right: 1 })
  27 + Image($r("app.media.more"))
  28 + .width(14)
  29 + .height(14)
  30 + }
  31 + }.justifyContent(FlexAlign.SpaceBetween)
  32 + .padding({left:16,right:16})
  33 + .margin({top:8 ,bottom:8})
  34 + .width('100%')
  35 + // .backgroundColor($r("app.color.white"))
  36 + List({ space: 12 }) {
  37 +
  38 + ForEach(this.arr, (item: number) => {
  39 + ListItem() {
  40 + Column() {
  41 + Image($r("app.media.setting"))
  42 + .aspectRatio(1.5)
  43 + .width(150)
  44 + .borderRadius(4)
  45 + .objectFit(ImageFit.Cover)
  46 +
  47 + Text("大发大法师法师打发大水发生发大水发大水发大发大法师法师打发大水发生发大水发大水发大发大法师法师打发大水发生发大水发大水发")
  48 + .fontSize($r("app.float.font_size_14"))
  49 + .fontColor($r("app.color.color_212228"))
  50 + .fontWeight(400)
  51 + .maxLines(2)
  52 + .textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出的部分显示省略号。
  53 + .textAlign(TextAlign.Start)
  54 + .margin({ top: 8 })
  55 + .width(150)
  56 + }
  57 + }
  58 + .padding({left:(item == 0)? 16:0, right:(item == this.arr.length - 1) ? 16:0})
  59 + // .offset({x:16})
  60 + }, (item: number) => JSON.stringify(item))
  61 +
  62 + }.listDirection(Axis.Horizontal)
  63 + .width('100%')
  64 + // .backgroundColor($r("app.color.color_FE4B05"))
  65 + // .padding({left:16,right:16})
  66 + // .margin({left:16,right:16})
  67 +
  68 + }
  69 + .width("100%")
  70 + .padding({
  71 + top: 14,
  72 + left: 0,
  73 + right: 0,
  74 + bottom: 14
  75 + })
  76 + .backgroundColor($r("app.color.white"))
  77 + // .backgroundColor($r("app.color.color_FE4B05"))
  78 + .margin({ bottom: 8 })
  79 + }
  80 +}
  81 +
  1 +import { CompDTO } from 'wdBean'
  2 +import { CommonConstants } from 'wdConstant'
  3 +
  4 +@Component
  5 +export struct HorizontalStrokeCardThreeTwoRadioForOneComponent {
  6 + @State compDTO: CompDTO = {} as CompDTO
  7 + build() {
  8 + Column() {
  9 + Row() {
  10 + Row() {
  11 + Image($r("app.media.redLine"))
  12 + .width(3)
  13 + .height(16)
  14 + .margin({ right: 4 })
  15 + Text("大标题")
  16 + .fontSize($r("app.float.font_size_17"))
  17 + .fontColor($r("app.color.color_222222"))
  18 + .fontWeight(600)
  19 + }
  20 +
  21 + Row() {
  22 + Text("更多")
  23 + .fontSize($r("app.float.font_size_14"))
  24 + .fontColor($r("app.color.color_999999"))
  25 + .margin({ right: 1 })
  26 + Image($r("app.media.more"))
  27 + .width(14)
  28 + .height(14)
  29 + }
  30 + }.justifyContent(FlexAlign.SpaceBetween)
  31 + .margin({ top: 8 ,bottom: 8})
  32 + .width('100%')
  33 +
  34 +
  35 + Image($r("app.media.setting"))
  36 + .aspectRatio(1.5)
  37 + .width('100%')
  38 + .borderRadius(4)
  39 + .objectFit(ImageFit.Cover)
  40 +
  41 + Text("大发大法师法师打发大水发生发大水发大水发大发大法师法师打发大水发生发大水发大水发大发大法师法师打发大水发生发大水发大水发")
  42 + .fontSize($r("app.float.font_size_14"))
  43 + .fontColor($r("app.color.color_212228"))
  44 + .fontWeight(400)
  45 + .maxLines(1)
  46 + .textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出的部分显示省略号。
  47 + .textAlign(TextAlign.Start)
  48 + .margin({ top: 8 })
  49 + .width('100%')
  50 +
  51 + }.width("100%")
  52 + .padding({
  53 + top: 14,
  54 + left: 16,
  55 + right: 16,
  56 + bottom: 14
  57 + })
  58 + .backgroundColor($r("app.color.white"))
  59 + .margin({ bottom: 8 })
  60 + }
  61 +}
  1 +import { CompDTO } from 'wdBean'
  2 +import { CommonConstants } from 'wdConstant'
  3 +
  4 +@Component
  5 +export struct HorizontalStrokeCardThreeTwoRadioForTwoComponent {
  6 + @State compDTO: CompDTO = {} as CompDTO
  7 + private arr: number[] = [0, 1, 2]
  8 + build() {
  9 + Column() {
  10 + Row() {
  11 + Row() {
  12 + Image($r("app.media.redLine"))
  13 + .width(3)
  14 + .height(16)
  15 + .margin({ right: 4 })
  16 + Text("大标题")
  17 + .fontSize($r("app.float.font_size_17"))
  18 + .fontColor($r("app.color.color_222222"))
  19 + .fontWeight(600)
  20 + }
  21 +
  22 + Row() {
  23 + Text("更多")
  24 + .fontSize($r("app.float.font_size_14"))
  25 + .fontColor($r("app.color.color_999999"))
  26 + .margin({ right: 1 })
  27 + Image($r("app.media.more"))
  28 + .width(14)
  29 + .height(14)
  30 + }
  31 + }.justifyContent(FlexAlign.SpaceBetween)
  32 + .padding({left:16,right:16})
  33 + .margin({top:8 ,bottom:8})
  34 + .width('100%')
  35 + // .backgroundColor($r("app.color.white"))
  36 + List({ space: 12 }) {
  37 +
  38 + ForEach(this.arr, (item: number) => {
  39 + ListItem() {
  40 + Column() {
  41 + Image($r("app.media.setting"))
  42 + .aspectRatio(1.5)
  43 + .width(210)
  44 + .borderRadius(4)
  45 + .objectFit(ImageFit.Cover)
  46 +
  47 + Text("大发大法师法师打发大水发生发大水发大水发大发大法师法师打发大水发生发大水发大水发大发大法师法师打发大水发生发大水发大水发")
  48 + .fontSize($r("app.float.font_size_14"))
  49 + .fontColor($r("app.color.color_212228"))
  50 + .fontWeight(400)
  51 + .maxLines(2)
  52 + .textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出的部分显示省略号。
  53 + .textAlign(TextAlign.Start)
  54 + .margin({ top: 8 })
  55 + .width(210)
  56 + }
  57 + }
  58 + .padding({left:(item == 0)? 16:0, right:(item == this.arr.length - 1) ? 16:0})
  59 + // .offset({x:16})
  60 + }, (item: number) => JSON.stringify(item))
  61 +
  62 + }.listDirection(Axis.Horizontal)
  63 + .width('100%')
  64 + // .backgroundColor($r("app.color.color_FE4B05"))
  65 + // .padding({left:16,right:16})
  66 + // .margin({left:16,right:16})
  67 +
  68 + }
  69 + .width("100%")
  70 + .padding({
  71 + top: 14,
  72 + left: 0,
  73 + right: 0,
  74 + bottom: 14
  75 + })
  76 + .backgroundColor($r("app.color.white"))
  77 + // .backgroundColor($r("app.color.color_FE4B05"))
  78 + .margin({ bottom: 8 })
  79 + }
  80 +}
  81 +
1 import { CompDTO } from 'wdBean'; 1 import { CompDTO } from 'wdBean';
2 import { CommonConstants } from 'wdConstant'; 2 import { CommonConstants } from 'wdConstant';
3 -import { CompUtils } from '../utils/CompUtils'; 3 +import { CompUtils } from '../../utils/CompUtils';
4 4
5 const TAG = 'LabelComponent'; 5 const TAG = 'LabelComponent';
6 6
  1 +// import { CommonConstants } from 'wdConstant/src/main/ets/constants/CommonConstants'
  2 +
  3 +@Entry
  4 +@Component
  5 +export struct SmallVideoCardComponent {
  6 + build() {
  7 + Row() {
  8 + Column() {
  9 + Text('“畅享亚运”新模式活动打卡,看杭州打开“金角银边活动启动 跟着体育明星云打卡,看杭州打开“金角银边')
  10 + .fontWeight(400)
  11 + .fontSize($r('app.float.font_size_17'))
  12 + .maxLines(4)
  13 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  14 + .fontColor($r('app.color.color_222222'))
  15 + .lineHeight(25)
  16 + Row() {
  17 + Text('人民日报')
  18 + .labelTextStyle()
  19 + Image($r('app.media.point'))
  20 + .width(16)
  21 + .height(16)
  22 + Text('20分钟前')
  23 + .labelTextStyle()
  24 + .margin({
  25 + right: 6
  26 + })
  27 + Text('2000评')
  28 + .labelTextStyle()
  29 + }
  30 + }
  31 + .height(156)
  32 + .layoutWeight(1)
  33 + .justifyContent(FlexAlign.SpaceBetween)
  34 + .alignItems(HorizontalAlign.Start)
  35 + .margin({ right: 12 })
  36 +
  37 + Stack({ alignContent: Alignment.BottomEnd }) {
  38 + Image('https://www.harmonyos.com/resource/image/partner/harmonyos-connect/pic_shengtai_connect_qudao_xianxia.jpg')
  39 + .width(117)
  40 + .aspectRatio(117 / 156)
  41 + .border({ radius: 4 })
  42 + Row() {
  43 + Image($r('app.media.iv_card_play_yellow_flag'))
  44 + .width(22)
  45 + .height(18)
  46 + Text('10:00')
  47 + .fontSize($r('app.float.font_size_13'))
  48 + .fontWeight(400)
  49 + .fontColor($r('app.color.color_fff'))
  50 + }
  51 + .height(18)
  52 + .padding({ right: 4 })
  53 + .margin({
  54 + right: 4,
  55 + bottom: 4
  56 + })
  57 + .backgroundColor($r('app.color.color_4d000000'))
  58 + }
  59 + }
  60 + // .width(CommonConstants.FULL_WIDTH)
  61 + .width('100%')
  62 + .height(184)
  63 + .padding({
  64 + top: 14,
  65 + bottom: 14,
  66 + left: 16,
  67 + right: 16
  68 + })
  69 + }
  70 +}
  71 +
  72 +@Extend(Text) function labelTextStyle() {
  73 + .fontSize($r('app.float.font_size_12'))
  74 + .fontWeight(400)
  75 + .fontColor($r('app.color.color_B0B0B0'))
  76 +}
  1 +//缩略标题
  2 +import { CompDTO } from 'wdBean'
  3 +import { CommonConstants } from 'wdConstant'
  4 +
  5 +@Component
  6 +export struct TitleAbbrComponent {
  7 + @State compDTO: CompDTO = {} as CompDTO
  8 +
  9 + build() {
  10 + Column() {
  11 + Text(this.compDTO.operDataList[0].title)
  12 + .fontSize($r("app.float.font_size_16"))
  13 + .fontColor($r("app.color.color_222222"))
  14 + .maxLines(3)
  15 + .textOverflow({ overflow: TextOverflow.Ellipsis })
  16 + .width(CommonConstants.FULL_WIDTH)
  17 + Row() {
  18 + Text("锐评")
  19 + .fontSize($r("app.float.font_size_12"))
  20 + .fontColor($r("app.color.color_ED2800"))
  21 + Text(this.compDTO.operDataList[0].source)
  22 + .fontSize($r("app.float.font_size_12"))
  23 + .fontColor($r("app.color.color_B0B0B0"))
  24 + .margin({ left: 6 })
  25 + Image($r("app.media.point"))
  26 + .width(16)
  27 + .height(16)
  28 +
  29 + Text("46分钟前")
  30 + .fontSize($r("app.float.font_size_12"))
  31 + .fontColor($r("app.color.color_B0B0B0"))
  32 +
  33 + }.width(CommonConstants.FULL_WIDTH)
  34 + .justifyContent(FlexAlign.Start)
  35 + .margin({ top: 8 })
  36 +
  37 + }.width(CommonConstants.FULL_WIDTH)
  38 + .padding({
  39 + top: 14,
  40 + left: 16,
  41 + right: 16,
  42 + bottom: 14
  43 + })
  44 + .backgroundColor($r("app.color.white"))
  45 + .margin({ bottom: 8 })
  46 + }
  47 +}
  1 +//全标题 "compStyle":"3",
  2 +import { CompDTO } from 'wdBean'
  3 +import { CommonConstants } from 'wdConstant'
  4 +
  5 +@Component
  6 +export struct TitleAllComponent {
  7 + @State compDTO: CompDTO = {} as CompDTO
  8 +
  9 + build() {
  10 + Column() {
  11 + Text(this.compDTO.operDataList[0].title)
  12 + .fontSize($r("app.float.font_size_16"))
  13 + .fontColor($r("app.color.color_222222"))
  14 + .width(CommonConstants.FULL_WIDTH)
  15 + Row() {
  16 + Text("锐评")
  17 + .fontSize($r("app.float.font_size_12"))
  18 + .fontColor($r("app.color.color_ED2800"))
  19 + Text(this.compDTO.operDataList[0].source)
  20 + .fontSize($r("app.float.font_size_12"))
  21 + .fontColor($r("app.color.color_B0B0B0"))
  22 + .margin({ left: 6 })
  23 + Image($r("app.media.point"))
  24 + .width(16)
  25 + .height(16)
  26 +
  27 + Text("46分钟前")
  28 + .fontSize($r("app.float.font_size_12"))
  29 + .fontColor($r("app.color.color_B0B0B0"))
  30 +
  31 + }.width(CommonConstants.FULL_WIDTH)
  32 + .justifyContent(FlexAlign.Start)
  33 + .margin({ top: 8 })
  34 +
  35 + }.width("100%")
  36 + .padding({
  37 + top: 14,
  38 + left: 16,
  39 + right: 16,
  40 + bottom: 14
  41 + })
  42 + .backgroundColor($r("app.color.white"))
  43 + .margin({ bottom: 8 })
  44 + }
  45 +}
  1 +export class ContentConstants {
  2 + /* content#objectType,跳转类型:0:不跳转 1:点播,2:直播,3:活动,4:广告,5:专题,6:链接,7:榜单,8:图文,9:组图,10:H5新闻,11:频道,12:组件,13:音频,14动态图文,15动态视频 */
  3 + /**
  4 + * 0:不跳转
  5 + */
  6 + static readonly TYPE_NONE: string = "0";
  7 + /**
  8 + * 1:点播
  9 + */
  10 + static readonly TYPE_VOD: string = "1";
  11 + /**
  12 + * 8:图文详情,这里是h5页面
  13 + */
  14 + static readonly TYPE_TELETEXT: string = "8";
  15 +}
1 -import { GroupDTO, NavigationBody } from 'wdBean';  
2 -import { WDHttp } from 'wdNetwork'; 1 +import HashMap from '@ohos.util.HashMap';
  2 +import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork';
  3 +import { DateTimeUtils } from 'wdKit';
  4 +import { NavigationBodyDTO, PageDTO } from 'wdBean';
3 5
4 export class PageRepository { 6 export class PageRepository {
  7 + static getBottomNavGroupUrl() {
  8 + // https: //pd-apis-uat.pdnews.cn/api/rmrb-bff-display-zh/display/zh/c/bottomNavGroup
  9 + return HttpUrlUtils.HOST + HttpUrlUtils.BOTTOM_NAV_PATH;
  10 + }
5 11
6 - static fetchNavigationDataApi(url: string) {  
7 - return WDHttp.Request.get<WDHttp.ResponseDTO<NavigationBody>>(url)  
8 - }; 12 + static getCompInfoUrl(pageId: string, groupId: string, channelId: string, currentPage: number, pageSize: number) {
  13 + let url = HttpUrlUtils.HOST + HttpUrlUtils.COMP_PATH;
  14 + // TODO 暂定只请求第一页,后续对接分页加载,参数再调整 first_load?
  15 + url = url + "?channelStrategy=2&loadStrategy=first_load"
  16 + + "&districtCode=" + HttpUrlUtils.getDistrictCode()
  17 + + "&provinceCode=" + HttpUrlUtils.getProvinceCode()
  18 + + "&cityCode=" + HttpUrlUtils.getCityCode()
  19 + + "&refreshTime=" + DateTimeUtils.getTimeStamp()
  20 + + "&pageId=" + pageId
  21 + + "&groupId=" + groupId
  22 + + "&channelId=" + channelId
  23 + + "&pageSize=" + pageSize
  24 + + "&pageNum=" + currentPage;
  25 + // Logger.debug("TAG", 'getCompInfoUrl url: '+url);
  26 + return url;
  27 + }
9 28
10 - static fetchPageData(url: string) {  
11 - return WDHttp.Request.get<WDHttp.ResponseDTO<GroupDTO>>(url) 29 + static fetchNavigationDataApi() {
  30 + let url = PageRepository.getBottomNavGroupUrl();
  31 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  32 + return WDHttp.get<ResponseDTO<NavigationBodyDTO>>(url, headers)
12 }; 33 };
13 34
  35 + static fetchPageData(pageId: string, groupId: string, channelId: string, currentPage: number, pageSize: number) {
  36 + let url = PageRepository.getCompInfoUrl(pageId, groupId, channelId, currentPage, pageSize)
  37 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  38 + return WDHttp.get<ResponseDTO<PageDTO>>(url, headers)
  39 + };
14 } 40 }
1 -import { LabelDTO } from 'wdBean'; 1 +import { BottomNavDTO, LabelDTO } from 'wdBean';
2 import { Logger } from 'wdKit'; 2 import { Logger } from 'wdKit';
3 3
4 const TAG: string = 'CompCornerUtil'; 4 const TAG: string = 'CompCornerUtil';
@@ -20,6 +20,17 @@ export class CompUtils { @@ -20,6 +20,17 @@ export class CompUtils {
20 public static readonly MAX_LINES_2: number = 2; 20 public static readonly MAX_LINES_2: number = 2;
21 public static readonly MAX_LINES_3: number = 3; 21 public static readonly MAX_LINES_3: number = 3;
22 22
  23 +
  24 + /**
  25 + * 判断是否为我的页面
  26 + */
  27 + static isMine(navItem: BottomNavDTO): boolean {
  28 + if (navItem == null) {
  29 + return false;
  30 + }
  31 + return navItem.type === '2';
  32 + }
  33 +
23 /** 34 /**
24 * 获取Label标题 35 * 获取Label标题
25 * 36 *
@@ -39,4 +50,5 @@ export class CompUtils { @@ -39,4 +50,5 @@ export class CompUtils {
39 50
40 return labelDTO.title ?? ""; 51 return labelDTO.title ?? "";
41 } 52 }
  53 +
42 } 54 }
  1 +import { Logger } from 'wdKit';
  2 +import { StringUtils } from 'wdKit/src/main/ets/utils/StringUtils';
  3 +import { ContentConstants } from '../constants/ContentConstants';
  4 +import { ContentDTO } from '../repository/bean/ContentDTO';
  5 +
  6 +const TAG = 'ProcessUtils';
  7 +
  8 +/**
  9 + * 页面跳转业务封装
  10 + */
  11 +export class ProcessUtils {
  12 + /**
  13 + * 页面跳转
  14 + */
  15 + static processPage(content: ContentDTO) {
  16 + if (content == null) {
  17 + Logger.error(TAG, "processPage, content is null");
  18 + return;
  19 + }
  20 + if (StringUtils.isEmpty(content.objectType)) {
  21 + Logger.error(TAG, "processPage, objectType is empty");
  22 + return;
  23 + }
  24 + let type = content.objectType;
  25 + switch (type) {
  26 + case ContentConstants.TYPE_NONE:
  27 + Logger.debug(TAG, "processPage, do nothing");
  28 + break;
  29 + case ContentConstants.TYPE_VOD:
  30 + Logger.debug(TAG, "processPage, nonsupport!!!");
  31 + // TODO 待对接更多页面
  32 + break;
  33 + case ContentConstants.TYPE_TELETEXT:
  34 + // 图文详情,跳转h5
  35 + ProcessUtils.gotoWeb(content);
  36 + break;
  37 + default:
  38 + break;
  39 + }
  40 + }
  41 +
  42 + private static gotoWeb(content: ContentDTO) {
  43 + // // topicId
  44 + // content.channelId;
  45 + // content.linkUrl;
  46 + // content.objectId;
  47 + // // CompId
  48 + // content.relId;
  49 + // content.relType;
  50 + // // ScrollToBottom
  51 + // // FromPage
  52 + // TODO 对接路由
  53 + Logger.debug(TAG, `gotoWeb, ${content.objectId}`);
  54 + }
  55 +}
  1 +import promptAction from '@ohos.promptAction';
  2 +import { RefreshConstants as Const, RefreshState } from './RefreshConstants';
  3 +import { touchMoveLoadMore, touchUpLoadMore } from './PullUpLoadMore';
  4 +import { PageDTO } from 'wdBean';
  5 +import PageModel from '../viewmodel/PageModel';
  6 +import PageViewModel from '../viewmodel/PageViewModel';
  7 +
  8 +export function listTouchEvent(pageModel: PageModel, event: TouchEvent) {
  9 + switch (event.type) {
  10 + case TouchType.Down:
  11 + pageModel.downY = event.touches[0].y;
  12 + pageModel.lastMoveY = event.touches[0].y;
  13 + break;
  14 + case TouchType.Move:
  15 + if ((pageModel.isRefreshing === true) || (pageModel.isLoading === true)) {
  16 + return;
  17 + }
  18 + let isDownPull = event.touches[0].y - pageModel.lastMoveY > 0;
  19 + if (((isDownPull === true) || (pageModel.isPullRefreshOperation === true)) && (pageModel.isCanLoadMore === false)) {
  20 + // Finger movement, processing pull-down refresh.
  21 + touchMovePullRefresh(pageModel, event);
  22 + } else {
  23 + // Finger movement, processing load more.
  24 + touchMoveLoadMore(pageModel, event);
  25 + }
  26 + pageModel.lastMoveY = event.touches[0].y;
  27 + break;
  28 + case TouchType.Cancel:
  29 + break;
  30 + case TouchType.Up:
  31 + if ((pageModel.isRefreshing === true) || (pageModel.isLoading === true)) {
  32 + return;
  33 + }
  34 + if ((pageModel.isPullRefreshOperation === true)) {
  35 + // Lift your finger and pull down to refresh.
  36 + touchUpPullRefresh(pageModel);
  37 + } else {
  38 + // Fingers up, handle loading more.
  39 + touchUpLoadMore(pageModel);
  40 + }
  41 + break;
  42 + default:
  43 + break;
  44 + }
  45 +}
  46 +
  47 +export function touchMovePullRefresh(pageModel: PageModel, event: TouchEvent) {
  48 + if (pageModel.startIndex === 0) {
  49 + pageModel.isPullRefreshOperation = true;
  50 + let height = vp2px(pageModel.pullDownRefreshHeight);
  51 + pageModel.offsetY = event.touches[0].y - pageModel.downY;
  52 + // The sliding offset is greater than the pull-down refresh layout height, and the refresh condition is met.
  53 + if (pageModel.offsetY >= height) {
  54 + pullRefreshState(pageModel, RefreshState.Release);
  55 + pageModel.offsetY = height + pageModel.offsetY * Const.Y_OFF_SET_COEFFICIENT;
  56 + } else {
  57 + pullRefreshState(pageModel, RefreshState.DropDown);
  58 + }
  59 + if (pageModel.offsetY < 0) {
  60 + pageModel.offsetY = 0;
  61 + pageModel.isPullRefreshOperation = false;
  62 + }
  63 + }
  64 +}
  65 +
  66 +export function touchUpPullRefresh(pageModel: PageModel) {
  67 + if (pageModel.isCanRefresh === true) {
  68 + pageModel.offsetY = vp2px(pageModel.pullDownRefreshHeight);
  69 + pullRefreshState(pageModel, RefreshState.Refreshing);
  70 + pageModel.currentPage = 1;
  71 + setTimeout(() => {
  72 + let self: PageModel = pageModel;
  73 +
  74 + PageViewModel.getPageData(self.pageId, self.groupId, self.channelId, self.currentPage, self.pageSize, getContext())
  75 + .then((data: PageDTO) => {
  76 + if (data == null || data.compList == null || data.compList.length == 0) {
  77 + self.hasMore = false;
  78 + } else {
  79 + if (data.compList.length == self.pageSize) {
  80 + self.currentPage++;
  81 + self.hasMore = true;
  82 + } else {
  83 + self.hasMore = false;
  84 + }
  85 + // 刷新,替换所有数据
  86 + self.compList.replaceAll(...data.compList)
  87 + }
  88 + closeRefresh(self, true);
  89 + }).catch((err: string | Resource) => {
  90 + promptAction.showToast({ message: err });
  91 + closeRefresh(self, false);
  92 + });
  93 + }, Const.DELAY_TIME);
  94 + } else {
  95 + closeRefresh(pageModel, false);
  96 + }
  97 +}
  98 +
  99 +export function pullRefreshState(pageModel: PageModel, state: number) {
  100 + switch (state) {
  101 + case RefreshState.DropDown:
  102 + pageModel.pullDownRefreshText = $r('app.string.pull_down_refresh_text');
  103 + pageModel.pullDownRefreshImage = $r('app.media.ic_pull_down_refresh');
  104 + pageModel.isCanRefresh = false;
  105 + pageModel.isRefreshing = false;
  106 + pageModel.isVisiblePullDown = true;
  107 + break;
  108 + case RefreshState.Release:
  109 + pageModel.pullDownRefreshText = $r('app.string.release_refresh_text');
  110 + pageModel.pullDownRefreshImage = $r('app.media.ic_pull_up_refresh');
  111 + pageModel.isCanRefresh = true;
  112 + pageModel.isRefreshing = false;
  113 + break;
  114 + case RefreshState.Refreshing:
  115 + pageModel.offsetY = vp2px(pageModel.pullDownRefreshHeight);
  116 + pageModel.pullDownRefreshText = $r('app.string.refreshing_text');
  117 + pageModel.pullDownRefreshImage = $r('app.media.ic_pull_up_load');
  118 + pageModel.isCanRefresh = true;
  119 + pageModel.isRefreshing = true;
  120 + break;
  121 + case RefreshState.Success:
  122 + pageModel.pullDownRefreshText = $r('app.string.refresh_success_text');
  123 + pageModel.pullDownRefreshImage = $r('app.media.ic_succeed_refresh');
  124 + pageModel.isCanRefresh = true;
  125 + pageModel.isRefreshing = true;
  126 + break;
  127 + case RefreshState.Fail:
  128 + pageModel.pullDownRefreshText = $r('app.string.refresh_fail_text');
  129 + pageModel.pullDownRefreshImage = $r('app.media.ic_fail_refresh');
  130 + pageModel.isCanRefresh = true;
  131 + pageModel.isRefreshing = true;
  132 + break;
  133 + default:
  134 + break;
  135 + }
  136 +}
  137 +
  138 +export function closeRefresh(pageModel: PageModel, isRefreshSuccess: boolean) {
  139 + let self = pageModel;
  140 + setTimeout(() => {
  141 + let delay = Const.RefreshConstant_DELAY_PULL_DOWN_REFRESH;
  142 + if (self.isCanRefresh === true) {
  143 + pullRefreshState(pageModel, isRefreshSuccess ? RefreshState.Success : RefreshState.Fail);
  144 + delay = Const.RefreshConstant_DELAY_SHRINK_ANIMATION_TIME;
  145 + }
  146 + animateTo({
  147 + duration: Const.RefreshConstant_CLOSE_PULL_DOWN_REFRESH_TIME,
  148 + delay: delay,
  149 + onFinish: () => {
  150 + pullRefreshState(pageModel, RefreshState.DropDown);
  151 + self.isVisiblePullDown = false;
  152 + self.isPullRefreshOperation = false;
  153 + }
  154 + }, () => {
  155 + self.offsetY = 0;
  156 + })
  157 + }, self.isCanRefresh ? Const.DELAY_ANIMATION_DURATION : 0);
  158 +}
  1 +import promptAction from '@ohos.promptAction';
  2 +import PageModel from '../viewmodel/PageModel';
  3 +import { RefreshConstants as Const } from './RefreshConstants';
  4 +import PageViewModel from '../viewmodel/PageViewModel';
  5 +import { PageDTO } from 'wdBean';
  6 +
  7 +export function touchMoveLoadMore(model: PageModel, event: TouchEvent) {
  8 + // list size +1
  9 + if (model.endIndex === model.compList.totalCount() || model.endIndex === model.compList.totalCount() + 1) {
  10 + model.offsetY = event.touches[0].y - model.downY;
  11 + if (Math.abs(model.offsetY) > vp2px(model.pullUpLoadHeight) / 2) {
  12 + model.isCanLoadMore = true;
  13 + model.isVisiblePullUpLoad = true;
  14 + model.offsetY = -vp2px(model.pullUpLoadHeight) + model.offsetY * Const.Y_OFF_SET_COEFFICIENT;
  15 + }
  16 + }
  17 +}
  18 +
  19 +export function touchUpLoadMore(model: PageModel) {
  20 + let self: PageModel = model;
  21 + animateTo({
  22 + duration: Const.ANIMATION_DURATION,
  23 + }, () => {
  24 + self.offsetY = 0;
  25 + })
  26 + if ((self.isCanLoadMore === true) && (self.hasMore === true)) {
  27 + self.isLoading = true;
  28 + setTimeout(() => {
  29 + closeLoadMore(model);
  30 + PageViewModel.getPageData(self.pageId, self.groupId, self.channelId, self.currentPage, self.pageSize, getContext())
  31 + .then((data: PageDTO) => {
  32 + if (data == null || data.compList == null || data.compList.length == 0) {
  33 + self.hasMore = false;
  34 + } else {
  35 + if (data.compList.length == self.pageSize) {
  36 + self.currentPage++;
  37 + self.hasMore = true;
  38 + } else {
  39 + self.hasMore = false;
  40 + }
  41 + self.compList.push(...data.compList)
  42 + }
  43 + }).catch((err: string | Resource) => {
  44 + promptAction.showToast({ message: err });
  45 + })
  46 + }, Const.DELAY_TIME);
  47 + } else {
  48 + closeLoadMore(self);
  49 + }
  50 +}
  51 +
  52 +export function closeLoadMore(model: PageModel) {
  53 + model.isCanLoadMore = false;
  54 + model.isLoading = false;
  55 + model.isVisiblePullUpLoad = false;
  56 +}
  1 +/**
  2 + * The constant of refresh.
  3 + */
  4 +export class RefreshConstants {
  5 + /**
  6 + * The off set coefficient.
  7 + */
  8 + static readonly Y_OFF_SET_COEFFICIENT: number = 0.1;
  9 + /**
  10 + * The animation delay time.
  11 + */
  12 + static readonly DELAY_ANIMATION_DURATION: number = 300;
  13 + /**
  14 + * The delay time.
  15 + */
  16 + static readonly DELAY_TIME: number = 1000;
  17 +
  18 + /**
  19 + * The animation duration.
  20 + */
  21 + static readonly ANIMATION_DURATION: number = 2000;
  22 + /**
  23 + * The RefreshConstant constants.
  24 + */
  25 + static readonly RefreshConstant_DELAY_PULL_DOWN_REFRESH: number = 50;
  26 + static readonly RefreshConstant_CLOSE_PULL_DOWN_REFRESH_TIME: number = 150;
  27 + static readonly RefreshConstant_DELAY_SHRINK_ANIMATION_TIME: number = 500;
  28 +
  29 + /**
  30 + * The page size.
  31 + */
  32 + static readonly PAGE_SIZE: number = 20;
  33 +
  34 + /**
  35 + * The refresh and load height.
  36 + */
  37 + static readonly CUSTOM_LAYOUT_HEIGHT: number = 70;
  38 + /**
  39 + * Full the width.
  40 + */
  41 + static readonly FULL_WIDTH: string = '100%';
  42 + /**
  43 + * The NoMoreLayout constants.
  44 + */
  45 + static readonly NoMoreLayoutConstant_NORMAL_PADDING: number = 8;
  46 + static readonly NoMoreLayoutConstant_TITLE_FONT: string = '16fp';
  47 +
  48 + /**
  49 + * The RefreshLayout constants.
  50 + */
  51 + static readonly RefreshLayout_MARGIN_LEFT: string = '40%';
  52 + static readonly RefreshLayout_TEXT_MARGIN_BOTTOM: number = 1;
  53 + static readonly RefreshLayout_TEXT_MARGIN_LEFT: number = 7;
  54 + static readonly RefreshLayout_TEXT_FONT_SIZE: number = 17;
  55 + static readonly RefreshLayout_IMAGE_WIDTH: number = 18;
  56 + static readonly RefreshLayout_IMAGE_HEIGHT: number = 18;
  57 +}
  58 +/**
  59 + * The refresh state enum.
  60 + */
  61 +export const enum RefreshState {
  62 + DropDown = 0,
  63 + Release = 1,
  64 + Refreshing = 2,
  65 + Success = 3,
  66 + Fail = 4
  67 +}
  1 +import { Logger } from 'wdKit';
  2 +import { ResponseDTO } from 'wdNetwork';
  3 +
  4 +/**
  5 + * 处理返回后的数据
  6 + */
  7 +export abstract class BaseViewModel {
  8 + abstract getLogTag(): string;
  9 +
  10 + public isRespondsInvalid(resDTO: ResponseDTO<object>, tag?: string): boolean {
  11 + if (resDTO == null) {
  12 + Logger.error(this.getLogTag(), `${tag == null ? '' : tag + ', '}resDTO is empty`);
  13 + return true;
  14 + }
  15 + // code = 0, success
  16 + if (resDTO.code != 0) {
  17 + Logger.error(this.getLogTag(), `${tag == null ? '' : tag + ', '}code error, code:${resDTO.code}, message:${resDTO.message}`);
  18 + return true;
  19 + }
  20 + if (!resDTO.data) {
  21 + Logger.error(this.getLogTag(), `${tag == null ? '' : tag + ', '}resDTO.data is null`);
  22 + return true;
  23 + }
  24 + return false;
  25 + }
  26 +}
1 -import { BottomNavBean, GroupDTO, NavigationBody, NewspaperListBean, NewspaperTimeInfoBean } from 'wdBean';  
2 import { Logger, ResourcesUtils } from 'wdKit'; 1 import { Logger, ResourcesUtils } from 'wdKit';
3 -import { ResponseDTO, WDHttp } from 'wdNetwork';  
4 -import { PageRepository } from '../repository/PageRepository';  
5 -import http from '@ohos.net.http';  
6 -import { BusinessError } from '@ohos.base'; 2 +import { ResponseDTO } from 'wdNetwork';
  3 +import { NewspaperListBean, NewspaperTimeInfoBean } from 'wdBean';
7 4
8 const TAG = 'NewspaperViewModel'; 5 const TAG = 'NewspaperViewModel';
9 6
10 export class NewspaperViewModel { 7 export class NewspaperViewModel {
11 -  
12 static getNewspaperTimeFromLocal(context: Context): NewspaperTimeInfoBean[] { 8 static getNewspaperTimeFromLocal(context: Context): NewspaperTimeInfoBean[] {
13 Logger.info(TAG, `getNewspaperTimeFromLocal start`); 9 Logger.info(TAG, `getNewspaperTimeFromLocal start`);
14 let newspaperTimeInfo: ResponseDTO<NewspaperTimeInfoBean[]> | null = ResourcesUtils.getResourcesJsonSync<ResponseDTO<NewspaperTimeInfoBean[]>>(context, 'newspaper_info.json'); 10 let newspaperTimeInfo: ResponseDTO<NewspaperTimeInfoBean[]> | null = ResourcesUtils.getResourcesJsonSync<ResponseDTO<NewspaperTimeInfoBean[]>>(context, 'newspaper_info.json');
  1 +import { CompDTO } from 'wdBean';
  2 +import { LazyDataSource } from 'wdKit';
  3 +import { ViewType } from 'wdConstant/src/main/ets/enum/ViewType';
  4 +import { RefreshConstants as Const } from '../utils/RefreshConstants';
  5 +
  6 +export default class PageModel {
  7 + // 页面数据
  8 + pageId: string = "";
  9 + groupId: string = "";
  10 + channelId: string = "";
  11 + compList: LazyDataSource<CompDTO> = new LazyDataSource();
  12 + // 页面状态,刷新、加载更多等
  13 + currentPage: number = 1;
  14 + pageSize: number = Const.PAGE_SIZE;
  15 + pullDownRefreshText: Resource = $r('app.string.pull_down_refresh_text');
  16 + pullDownRefreshImage: Resource = $r('app.media.ic_pull_down_refresh');
  17 + pullDownRefreshHeight: number = Const.CUSTOM_LAYOUT_HEIGHT;
  18 + isVisiblePullDown: boolean = false;
  19 + pullUpLoadText: Resource = $r('app.string.pull_up_load_text');
  20 + pullUpLoadImage: Resource = $r('app.media.ic_pull_up_load');
  21 + pullUpLoadHeight: number = Const.CUSTOM_LAYOUT_HEIGHT;
  22 + isVisiblePullUpLoad: boolean = false;
  23 + offsetY: number = 0;
  24 + viewType: number = ViewType.LOADING;
  25 + hasMore: boolean = true;
  26 + startIndex = 0;
  27 + endIndex = 0;
  28 + downY = 0;
  29 + lastMoveY = 0;
  30 + isRefreshing: boolean = false;
  31 + isCanRefresh = false;
  32 + isPullRefreshOperation = false;
  33 + isLoading: boolean = false;
  34 + isCanLoadMore: boolean = false;
  35 +}
1 -import { BottomNavBean, GroupDTO, NavigationBody } from 'wdBean'; 1 +import { NavigationBodyDTO, PageDTO } from 'wdBean';
2 import { Logger, ResourcesUtils } from 'wdKit'; 2 import { Logger, ResourcesUtils } from 'wdKit';
3 -import { ResponseDTO, WDHttp } from 'wdNetwork'; 3 +import { ResponseDTO, } from 'wdNetwork';
4 import { PageRepository } from '../repository/PageRepository'; 4 import { PageRepository } from '../repository/PageRepository';
5 -import http from '@ohos.net.http';  
6 -import { BusinessError } from '@ohos.base'; 5 +import { BaseViewModel } from './BaseViewModel';
7 6
8 const TAG = 'PageViewModel'; 7 const TAG = 'PageViewModel';
  8 +/**
  9 + * mock数据开关,默认关。
  10 + * mock数据是本地json数据,可自行修改内容(‘entry\src\main\resources\rawfile\’目录)
  11 + */
  12 +const mock_switch = true;
9 13
10 /** 14 /**
11 * 处理返回后的数据 15 * 处理返回后的数据
12 */ 16 */
13 -export class PageViewModel { 17 +export class PageViewModel extends BaseViewModel {
  18 + getLogTag() {
  19 + return TAG;
  20 + }
  21 +
14 /** 22 /**
15 * get Nav Data from Resource . 23 * get Nav Data from Resource .
16 * 24 *
17 * @return BottomNavBean[] Nav Data List 25 * @return BottomNavBean[] Nav Data List
18 */ 26 */
19 - static getBottomNavData(context: Context): BottomNavBean[] { 27 + async getBottomNavData(context: Context): Promise<NavigationBodyDTO> {
20 Logger.info(TAG, `getBottomNavData start`); 28 Logger.info(TAG, `getBottomNavData start`);
21 - let compRes: ResponseDTO<NavigationBody> | null = ResourcesUtils.getResourcesJsonSync<ResponseDTO<NavigationBody>>(context, 'bottom_nav.json');  
22 - if (!compRes || !compRes.data || !compRes.data.bottomNavList) {  
23 - Logger.info(TAG, `getBottomNavData compRes bottomNavList is empty`);  
24 - return [] 29 + if (mock_switch) {
  30 + return this.getBottomNavDataMock(context);
  31 + }
  32 + return this.getNavData();
25 } 33 }
26 - Logger.info(TAG, `getBottomNavData getResourcesJsonSync compRes : ${JSON.stringify(compRes)}`);  
27 - return compRes.data.bottomNavList 34 +
  35 + async getBottomNavDataMock(context: Context): Promise<NavigationBodyDTO> {
  36 + Logger.info(TAG, `getBottomNavDataMock start`);
  37 + let compRes: ResponseDTO<NavigationBodyDTO> | null = await ResourcesUtils.getResourcesJson<ResponseDTO<NavigationBodyDTO>>(context, 'bottom_nav.json');
  38 + if (!compRes || !compRes.data) {
  39 + Logger.info(TAG, `getBottomNavDataMock compRes bottomNavList is empty`);
  40 + return {} as NavigationBodyDTO
  41 + }
  42 + Logger.info(TAG, `getBottomNavDataMock getResourcesJsonSync compRes : ${JSON.stringify(compRes)}`);
  43 + return compRes.data
28 } 44 }
29 45
30 - static getNavData(url: string): Promise<NavigationBody> {  
31 - return new Promise<NavigationBody>((success, error) => { 46 + private getNavData(): Promise<NavigationBodyDTO> {
  47 + return new Promise<NavigationBodyDTO>((success, error) => {
32 Logger.info(TAG, `getNavData start`); 48 Logger.info(TAG, `getNavData start`);
33 - PageRepository.fetchNavigationDataApi(url).then((navResDTO: WDHttp.ResponseDTO<NavigationBody>) => {  
34 - if (!navResDTO) { 49 + PageRepository.fetchNavigationDataApi().then((navResDTO: ResponseDTO<NavigationBodyDTO>) => {
  50 + if (!navResDTO || !navResDTO.data) {
35 Logger.error(TAG, 'getNavData then navResDTO is empty'); 51 Logger.error(TAG, 'getNavData then navResDTO is empty');
36 error('navResDTO is empty'); 52 error('navResDTO is empty');
37 return 53 return
38 } 54 }
39 - if (navResDTO.code != http.ResponseCode.OK) { 55 + if (navResDTO.code != 0) {
40 Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`); 56 Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`);
41 error('navResDTO Response Code is failure'); 57 error('navResDTO Response Code is failure');
42 return 58 return
43 } 59 }
44 - if (!navResDTO.body?.bottomNavList) {  
45 - error('navResDTO list is empty');  
46 - return  
47 - }  
48 // let navResStr = JSON.stringify(navResDTO); 60 // let navResStr = JSON.stringify(navResDTO);
49 - Logger.info(TAG, "getNavData then,navResDTO.timeStamp:" + navResDTO.timeStamp);  
50 - let navigationBean = navResDTO.body  
51 - success(navigationBean);  
52 - }).catch((err: BusinessError) => {  
53 - Logger.error(TAG, `fetchNavigationDataApi catch, error.code : ${err.code}, error.message:${err.message}`); 61 + Logger.info(TAG, "getNavData then,navResDTO.timestamp:" + navResDTO.timestamp);
  62 + success(navResDTO.data);
  63 + }).catch((err: Error) => {
  64 + Logger.error(TAG, `fetchNavigationDataApi catch, error.name : ${err.name}, error.message:${err.message}`);
54 error(err); 65 error(err);
55 }) 66 })
56 }) 67 })
57 } 68 }
58 69
59 /** 70 /**
60 - * Get Group data. 71 + * Get PageDTO data.
61 * 72 *
62 * @return {GroupDTO} compRes.data 73 * @return {GroupDTO} compRes.data
63 */ 74 */
64 - static getGroupDTO(context: Context): GroupDTO {  
65 - let compRes: ResponseDTO<GroupDTO> | null = ResourcesUtils.getResourcesJsonSync<ResponseDTO<GroupDTO>>(context, 'comp_list0.json'); 75 + private async getPageData1(currentPage: number, context: Context): Promise<PageDTO> {
  76 + if (currentPage > 1) {
  77 + // 加载更多,返回无数据
  78 + return {} as PageDTO
  79 + }
  80 + let compRes: ResponseDTO<PageDTO> | null = await ResourcesUtils.getResourcesJson<ResponseDTO<PageDTO>>(context, 'comp_list0.json');
66 if (!compRes || !compRes.data) { 81 if (!compRes || !compRes.data) {
67 Logger.info(TAG, `getCompList compRes is empty`); 82 Logger.info(TAG, `getCompList compRes is empty`);
68 - return {} as GroupDTO 83 + return {} as PageDTO
69 } 84 }
70 Logger.info(TAG, `getCompList getResourcesJson compRes : ${JSON.stringify(compRes)}`); 85 Logger.info(TAG, `getCompList getResourcesJson compRes : ${JSON.stringify(compRes)}`);
71 return compRes.data 86 return compRes.data
@@ -75,35 +90,43 @@ export class PageViewModel { @@ -75,35 +90,43 @@ export class PageViewModel {
75 * Get Group data. 90 * Get Group data.
76 * 91 *
77 * @return {GroupDTO} compRes.data 92 * @return {GroupDTO} compRes.data
  93 + * @deprecated
78 */ 94 */
79 - static getGroup2DTO(context: Context): GroupDTO {  
80 - let compRes: ResponseDTO<GroupDTO> | null = ResourcesUtils.getResourcesJsonSync<ResponseDTO<GroupDTO>>(context, 'comp_list2.json'); 95 + private async getPageData2(context: Context): Promise<PageDTO> {
  96 + let compRes: ResponseDTO<PageDTO> | null = await ResourcesUtils.getResourcesJson<ResponseDTO<PageDTO>>(context, 'comp_list2.json');
81 if (!compRes || !compRes.data) { 97 if (!compRes || !compRes.data) {
82 Logger.info(TAG, `getCompList compRes is empty`); 98 Logger.info(TAG, `getCompList compRes is empty`);
83 - return {} as GroupDTO 99 + return {} as PageDTO
84 } 100 }
  101 + // router.push('')
85 Logger.info(TAG, `getCompList getResourcesJson compRes : ${JSON.stringify(compRes)}`); 102 Logger.info(TAG, `getCompList getResourcesJson compRes : ${JSON.stringify(compRes)}`);
86 return compRes.data 103 return compRes.data
87 } 104 }
88 105
89 -  
90 - static getPageData(url: string): Promise<GroupDTO> {  
91 - return new Promise<GroupDTO>((success, error) => {  
92 - PageRepository.fetchPageData(url).then((resDTO: WDHttp.ResponseDTO<GroupDTO>) => {  
93 - if (!resDTO) {  
94 - Logger.error(TAG, 'getPageData then resDTO is empty');  
95 - error("page data is empty"); 106 + async getPageData(pageId: string, groupId: string, channelId: string, currentPage: number
  107 + , pageSize: number, context: Context): Promise<PageDTO> {
  108 + Logger.debug(TAG, 'getPageData pageId: ' + pageId);
  109 + if (mock_switch) {
  110 + return this.getPageData1(currentPage, context);
  111 + }
  112 + return new Promise<PageDTO>((success, error) => {
  113 + PageRepository.fetchPageData(pageId, groupId, channelId, currentPage, pageSize)
  114 + .then((resDTO: ResponseDTO<PageDTO>) => {
  115 + if (!resDTO || !resDTO.data) {
  116 + Logger.error(TAG, 'getNavData then resDTO is empty');
  117 + error('resDTO is empty');
96 return 118 return
97 } 119 }
98 - if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {  
99 - Logger.error(TAG, `getPageData then code:${resDTO.code}, message:${resDTO.message}`);  
100 - error(`get page data error code:${resDTO.code}, message:${resDTO.message}`); 120 + if (resDTO.code != 0) {
  121 + Logger.error(TAG, `getNavData then code:${resDTO.code}, message:${resDTO.message}`);
  122 + error('resDTO Response Code is failure');
101 return 123 return
102 } 124 }
103 - Logger.info(TAG, "getPageData then,resDTO.timeStamp:" + resDTO.timeStamp);  
104 - success(resDTO.body);  
105 - }).catch((err: BusinessError) => {  
106 - Logger.error(TAG, `getPageData catch, error.code : ${err.code}, error.message:${err.message}`); 125 + Logger.info(TAG, "getNavData then,resDTO.timestamp:" + resDTO.timestamp);
  126 + success(resDTO.data);
  127 + })
  128 + .catch((err: Error) => {
  129 + Logger.error(TAG, `getPageData catch, error.name : ${err.name}, error.message:${err.message}`);
107 error(err); 130 error(err);
108 }) 131 })
109 }) 132 })
@@ -111,7 +134,6 @@ export class PageViewModel { @@ -111,7 +134,6 @@ export class PageViewModel {
111 } 134 }
112 135
113 136
114 -  
115 let pageViewModel = new PageViewModel(); 137 let pageViewModel = new PageViewModel();
116 138
117 export default pageViewModel as PageViewModel; 139 export default pageViewModel as PageViewModel;
@@ -35,6 +35,22 @@ @@ -35,6 +35,22 @@
35 { 35 {
36 "name": "color_ED2800", 36 "name": "color_ED2800",
37 "value": "#ED2800" 37 "value": "#ED2800"
  38 + },
  39 + {
  40 + "name": "color_B0B0B0",
  41 + "value": "#B0B0B0"
  42 + },
  43 + {
  44 + "name": "color_212228",
  45 + "value": "#212228"
  46 + },
  47 + {
  48 + "name": "color_fff",
  49 + "value": "#ffffff"
  50 + },
  51 + {
  52 + "name": "color_4d000000",
  53 + "value": "#4d000000"
38 } 54 }
39 ] 55 ]
40 } 56 }
@@ -7,6 +7,30 @@ @@ -7,6 +7,30 @@
7 { 7 {
8 "name": "footer_text", 8 "name": "footer_text",
9 "value": "已经到底了" 9 "value": "已经到底了"
  10 + },
  11 + {
  12 + "name": "pull_up_load_text",
  13 + "value": "加载中..."
  14 + },
  15 + {
  16 + "name": "pull_down_refresh_text",
  17 + "value": "下拉刷新"
  18 + },
  19 + {
  20 + "name": "release_refresh_text",
  21 + "value": "松开刷新"
  22 + },
  23 + {
  24 + "name": "refreshing_text",
  25 + "value": "正在刷新"
  26 + },
  27 + {
  28 + "name": "refresh_success_text",
  29 + "value": "刷新成功"
  30 + },
  31 + {
  32 + "name": "refresh_fail_text",
  33 + "value": "刷新失败"
10 } 34 }
11 ] 35 ]
12 } 36 }
@@ -3,3 +3,18 @@ export { CommonConstants } from './src/main/ets/constants/CommonConstants'; @@ -3,3 +3,18 @@ export { CommonConstants } from './src/main/ets/constants/CommonConstants';
3 export { BreakpointConstants } from './src/main/ets/constants/BreakpointConstants'; 3 export { BreakpointConstants } from './src/main/ets/constants/BreakpointConstants';
4 4
5 export { ConfigConstants } from './src/main/ets/constants/ConfigConstants'; 5 export { ConfigConstants } from './src/main/ets/constants/ConfigConstants';
  6 +
  7 +// enum
  8 +export { BottomNavi } from './src/main/ets/enum/BottomNavi';
  9 +
  10 +export { CompStyle } from './src/main/ets/enum/CompStyle';
  11 +
  12 +export { CompType } from './src/main/ets/enum/CompType';
  13 +
  14 +export { NetDataStatusType } from './src/main/ets/enum/NetDataStatusType';
  15 +
  16 +export { ViewType } from './src/main/ets/enum/ViewType';
  17 +
  18 +export { DurationEnum } from './src/main/ets/enum/DurationEnum';
  19 +
  20 +export { ScreenType } from '../wdConstant/src/main/ets/enum/ScreenType';
@@ -28,7 +28,7 @@ export class ConfigConstants { @@ -28,7 +28,7 @@ export class ConfigConstants {
28 /** 28 /**
29 * 产品渠道应用对照关系: 29 * 产品渠道应用对照关系:
30 */ 30 */
31 - static readonly appCode: string = ""; 31 + static readonly appCode: string = "83092caa603a421aa0222308b3f6b27a";
32 /** 32 /**
33 * 基线代码和客户端应用版本号规范 33 * 基线代码和客户端应用版本号规范
34 */ 34 */
  1 +/**
  2 + * 常见图片宽/高比
  3 + */
  4 +export const enum AspectRatioEnum {
  5 + // 常见纵向比例
  6 + ASPECT_RATIO_2_3 = 2 / 3,
  7 + ASPECT_RATIO_3_4 = 3 / 4,
  8 + ASPECT_RATIO_4_5 = 4 / 5,
  9 + ASPECT_RATIO_5_7 = 5 / 7,
  10 + ASPECT_RATIO_9_16 = 9 / 16,
  11 + ASPECT_RATIO_10_16 = 10 / 16,
  12 + ASPECT_RATIO_9_21 = 9 / 21,
  13 +
  14 + // 正方形
  15 + ASPECT_RATIO_1_1 = 1 / 1,
  16 +
  17 + // 常见横向比例
  18 + ASPECT_RATIO_7_5 = 7 / 5,
  19 + ASPECT_RATIO_5_4 = 5 / 4,
  20 + ASPECT_RATIO_4_3 = 4 / 3,
  21 + ASPECT_RATIO_3_2 = 3 / 2,
  22 + ASPECT_RATIO_16_10 = 16 / 10,
  23 + ASPECT_RATIO_16_9 = 16 / 9,
  24 + ASPECT_RATIO_21_9 = 21 / 9,
  25 +
  26 + // 其他常见比例
  27 + ASPECT_RATIO_2_1 = 2 / 1, // banner图宽高比
  28 + ASPECT_RATIO_1_2 = 1 / 2,
  29 + ASPECT_RATIO_75_45 = 75 / 45, // 角标宽高比
  30 +}
@@ -19,4 +19,6 @@ export const enum CompStyle { @@ -19,4 +19,6 @@ export const enum CompStyle {
19 Grid_Layout_01 = 'Grid_Layout-01', // 横屏宫格卡:视频、直播 19 Grid_Layout_01 = 'Grid_Layout-01', // 横屏宫格卡:视频、直播
20 Grid_Layout_02 = 'Grid_Layout-02', // 竖屏宫格卡:视频、直播、榜单 20 Grid_Layout_02 = 'Grid_Layout-02', // 竖屏宫格卡:视频、直播、榜单
21 Masonry_Layout_01 = 'Masonry_Layout-01', // 双列瀑布流/瀑布流卡:视频、直播、专题、活动 21 Masonry_Layout_01 = 'Masonry_Layout-01', // 双列瀑布流/瀑布流卡:视频、直播、专题、活动
  22 + Title_Abbr_01 = 'Title_Abbr_01', // 标题缩略
  23 + Title_All_01 = 'Title_All_01', // 全标题
22 } 24 }
  1 +/**
  2 + * 时间跨度/延时枚举常量值
  3 + * duration/delay/interval
  4 + */
  5 +export const enum DurationEnum {
  6 + DURATION_MS_50 = 50, // 50毫秒
  7 + DURATION_MS_100 = 100, // 50毫秒
  8 + DURATION_MS_1000 = 1000, // 1秒/1000ms
  9 + DURATION_MS_1500 = 1500, // 1.5秒
  10 + DURATION_1 = 1000, // 1秒
  11 + DURATION_2 = 2000, // 2秒
  12 + DURATION_3 = 3000, // 3秒
  13 + DURATION_4 = 4000, // 4秒
  14 +}
  1 +/**
  2 + * 屏幕类型。1: 竖屏; 2: 横屏;
  3 + */
  4 +export const enum ScreenType {
  5 + PORTRAIT = "1", // 竖屏
  6 + LANDSCAPE = "2", // 横屏;
  7 +}
@@ -7,4 +7,7 @@ export { PlayError } from './src/main/ets/view/PlayError' @@ -7,4 +7,7 @@ export { PlayError } from './src/main/ets/view/PlayError'
7 7
8 export { devicePLSensorManager } from './src/main/ets/utils/devicePortLandSensor' 8 export { devicePLSensorManager } from './src/main/ets/utils/devicePortLandSensor'
9 9
  10 +export { ContentDetailDTO } from './src/main/ets/bean/ContentDetailDTO'
  11 +
  12 +
10 13
1 import { Logger, ResourcesUtils } from 'wdKit'; 1 import { Logger, ResourcesUtils } from 'wdKit';
2 -import { WDHttp } from 'wdNetwork' 2 +import { ResponseDTO, WDHttp } from 'wdNetwork'
3 import { ContentDetailDTO } from '../bean/ContentDetailDTO' 3 import { ContentDetailDTO } from '../bean/ContentDetailDTO'
4 4
5 const TAG = 'ContentDetailRequest'; 5 const TAG = 'ContentDetailRequest';
@@ -13,9 +13,9 @@ export interface ContentDetailRequestParams { @@ -13,9 +13,9 @@ export interface ContentDetailRequestParams {
13 } 13 }
14 14
15 export class ContentDetailRequest { 15 export class ContentDetailRequest {
16 - static getContentDetailDataMock(context: Context): Promise<WDHttp.ResponseDTO<ContentDetailDTO[]>> { 16 + static getContentDetailDataMock(context: Context): Promise<ResponseDTO<ContentDetailDTO[]>> {
17 Logger.info(TAG, `getContentDetailDataMock start`); 17 Logger.info(TAG, `getContentDetailDataMock start`);
18 - return ResourcesUtils.getResourcesJson<WDHttp.ResponseDTO<ContentDetailDTO[]>>(context, 'content_detail.json') 18 + return ResourcesUtils.getResourcesJson<ResponseDTO<ContentDetailDTO[]>>(context, 'content_detail.json')
19 } 19 }
20 20
21 /** 21 /**
@@ -35,13 +35,11 @@ export class ContentDetailRequest { @@ -35,13 +35,11 @@ export class ContentDetailRequest {
35 return url; 35 return url;
36 } 36 }
37 37
38 - static getContentDetail(params: ContentDetailRequestParams): Promise<WDHttp.ResponseDTO<ContentDetailDTO[]>> { 38 + static getContentDetail(params: ContentDetailRequestParams): Promise<ResponseDTO<ContentDetailDTO[]>> {
39 if (mock_switch) { 39 if (mock_switch) {
40 return ContentDetailRequest.getContentDetailDataMock(getContext()); 40 return ContentDetailRequest.getContentDetailDataMock(getContext());
41 } 41 }
42 - let headers: Record<string, string> = {};  
43 let url = ContentDetailRequest.getContentDetailUrl(params.contentId, params.relId, params.relType) 42 let url = ContentDetailRequest.getContentDetailUrl(params.contentId, params.relId, params.relType)
44 - // let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();  
45 - return WDHttp.Request.get<WDHttp.ResponseDTO<ContentDetailDTO[]>>(url, headers) 43 + return WDHttp.get<ResponseDTO<ContentDetailDTO[]>>(url)
46 } 44 }
47 } 45 }
1 import { BusinessError } from '@ohos.base' 1 import { BusinessError } from '@ohos.base'
2 import { Logger } from 'wdKit' 2 import { Logger } from 'wdKit'
3 -import { WDHttp } from 'wdNetwork'  
4 -import { ContentDetailRequest } from 'wdDetailPlayApi'  
5 -import { ContentDetailDTO } from 'wdDetailPlayApi/src/main/ets/bean/ContentDetailDTO' 3 +import { ResponseDTO} from 'wdNetwork'
  4 +import { ContentDetailDTO, ContentDetailRequest } from 'wdDetailPlayApi'
6 5
7 const TAG = 'PlayViewModel'; 6 const TAG = 'PlayViewModel';
8 7
@@ -36,7 +35,7 @@ export class PlayViewModel { @@ -36,7 +35,7 @@ export class PlayViewModel {
36 contentId: this.contentId, 35 contentId: this.contentId,
37 relId: this.relId, 36 relId: this.relId,
38 relType: this.relType 37 relType: this.relType
39 - }).then((resDTO: WDHttp.ResponseDTO<ContentDetailDTO[]>) => { 38 + }).then((resDTO: ResponseDTO<ContentDetailDTO[]>) => {
40 if (!resDTO) { 39 if (!resDTO) {
41 Logger.error(TAG, 'getContentDetailData then resDTO is empty'); 40 Logger.error(TAG, 'getContentDetailData then resDTO is empty');
42 return 41 return
@@ -4,8 +4,6 @@ export { ResourcesUtils } from './src/main/ets/utils/ResourcesUtils' @@ -4,8 +4,6 @@ export { ResourcesUtils } from './src/main/ets/utils/ResourcesUtils'
4 4
5 export { StringUtils } from './src/main/ets/utils/StringUtils' 5 export { StringUtils } from './src/main/ets/utils/StringUtils'
6 6
7 -export { ArrayUtils } from './src/main/ets/utils/ArrayUtils';  
8 -  
9 export { AppUtils } from './src/main/ets/utils/AppUtils'; 7 export { AppUtils } from './src/main/ets/utils/AppUtils';
10 8
11 export { BasicDataSource } from './src/main/ets/utils/BasicDataSource'; 9 export { BasicDataSource } from './src/main/ets/utils/BasicDataSource';
@@ -19,3 +17,15 @@ export { ToastUtils } from './src/main/ets/utils/ToastUtils'; @@ -19,3 +17,15 @@ export { ToastUtils } from './src/main/ets/utils/ToastUtils';
19 export { WindowModel } from './src/main/ets/utils/WindowModel' 17 export { WindowModel } from './src/main/ets/utils/WindowModel'
20 18
21 export { SPHelper } from './src/main/ets/utils/SPHelper' 19 export { SPHelper } from './src/main/ets/utils/SPHelper'
  20 +
  21 +export { AccountManagerUtils } from './src/main/ets/utils/AccountManagerUtils'
  22 +
  23 +export { CollectionUtils } from './src/main/ets/utils/CollectionUtils'
  24 +
  25 +export { DateTimeUtils } from './src/main/ets/utils/DateTimeUtils'
  26 +
  27 +export { DeviceUtil } from './src/main/ets/utils/DeviceUtil'
  28 +
  29 +export { DisplayUtils } from './src/main/ets/utils/DisplayUtils'
  30 +
  31 +export { SystemUtils } from './src/main/ets/utils/SystemUtils'
  1 +import { StringUtils } from './StringUtils';
  2 +import { SPHelper } from './SPHelper';
  3 +import { Logger } from './Logger';
  4 +
  5 +const KEY_USER_TOKEN = 'userToken';
  6 +
  7 +const TAG: string = 'AccountManagerUtils';
  8 +
  9 +// 是否已登录hadLogin
  10 +let hasLogin: boolean = false;
  11 +
  12 +export class AccountManagerUtils {
  13 + // 是否已登录hadLogin
  14 + // private static hasLogin: boolean = undefined;
  15 +
  16 + constructor() {
  17 + }
  18 +
  19 + static async getUserToken(): Promise<string> {
  20 + let userToken = await SPHelper.default.get(KEY_USER_TOKEN, '') as string;
  21 + // Logger.info(TAG, 'getUserToken UserToken.' + userToken);
  22 + return userToken;
  23 + }
  24 +
  25 + static getUserTokenSync(): string {
  26 + let userToken = SPHelper.default.getSync(KEY_USER_TOKEN, '') as string;
  27 + // Logger.info(TAG, 'getUserToken UserToken.' + userToken);
  28 + return userToken;
  29 + }
  30 +
  31 + static async putUserToken(value: string) {
  32 + await SPHelper.default.save(KEY_USER_TOKEN, value);
  33 + }
  34 +
  35 + static putUserTokenSync(value: string) {
  36 + SPHelper.default.saveSync(KEY_USER_TOKEN, value);
  37 + }
  38 +
  39 + static async deleteUserToken() {
  40 + await SPHelper.default.delete(KEY_USER_TOKEN);
  41 + }
  42 +
  43 + static deleteUserTokenSync() {
  44 + SPHelper.default.deleteSync(KEY_USER_TOKEN);
  45 + }
  46 +
  47 + /**
  48 + * 是否已登录
  49 + * @param folder
  50 + * @param files
  51 + */
  52 + static async isLogin() {
  53 + Logger.info(TAG, 'isLogin hasLogin1:' + hasLogin);
  54 + let lastUserToken = await AccountManagerUtils.getUserToken()
  55 + Logger.info(TAG, 'isLogin lastUserToken:' + lastUserToken);
  56 + if (StringUtils.isEmpty(lastUserToken)) {
  57 + hasLogin = false;
  58 + Logger.info(TAG, "isLogin lastUserToken is empty");
  59 + } else {
  60 + hasLogin = true;
  61 + Logger.info(TAG, "isLogin lastUserToken is not empty,lastUserToken:" + lastUserToken);
  62 + }
  63 + // hasLogin = true;
  64 + Logger.info(TAG, 'isLogin hasLogin2:' + hasLogin);
  65 + return hasLogin;
  66 + }
  67 +
  68 + /**
  69 + * 是否已登录
  70 + * @param folder
  71 + * @param files
  72 + */
  73 + static isLoginSync() {
  74 + Logger.info(TAG, 'isLogin hasLogin1:' + hasLogin);
  75 + let lastUserToken = AccountManagerUtils.getUserTokenSync()
  76 + Logger.info(TAG, 'isLogin lastUserToken:' + lastUserToken);
  77 + if (StringUtils.isEmpty(lastUserToken)) {
  78 + hasLogin = false;
  79 + Logger.info(TAG, "isLogin lastUserToken is empty");
  80 + } else {
  81 + hasLogin = true;
  82 + Logger.info(TAG, "isLogin lastUserToken is not empty,lastUserToken:" + lastUserToken);
  83 + }
  84 + // hasLogin = true;
  85 + Logger.info(TAG, 'isLogin hasLogin2:' + hasLogin);
  86 + return hasLogin;
  87 + }
  88 +}
  89 +
  90 +// export const accountManagerUtils = new AccountManagerUtils();
1 import LinkList from '@ohos.util.List'; 1 import LinkList from '@ohos.util.List';
  2 +import HashMap from '@ohos.util.HashMap';
2 3
3 -export class ArrayUtils { 4 +/**
  5 + * ArrayUtils class.
  6 + */
  7 +
  8 +export class CollectionUtils {
4 /** 9 /**
5 * The Array utils tag. 10 * The Array utils tag.
6 */ 11 */
@@ -20,7 +25,32 @@ export class ArrayUtils { @@ -20,7 +25,32 @@ export class ArrayUtils {
20 * @returns {boolean} true(empty) 25 * @returns {boolean} true(empty)
21 */ 26 */
22 static isEmpty(collection?: any[]): boolean { 27 static isEmpty(collection?: any[]): boolean {
23 - return!collection || collection.length === 0; 28 + return !collection || collection.length === 0;
  29 + }
  30 +
  31 + static isEmptyList<T>(list1?: LinkList<T>): boolean {
  32 + return !list1 || list1.length === 0;
  33 + }
  34 +
  35 + static isEmptyHashMap(obj?: HashMap<any, any>): boolean {
  36 + if (!obj) {
  37 + return true;
  38 + }
  39 + return obj.isEmpty();
  40 + }
  41 +
  42 + static isEmptyMap(obj?: Map<any, any>): boolean {
  43 + if (!obj) {
  44 + return true;
  45 + }
  46 + return Object.keys(obj).length === 0 && obj.constructor === Object;
  47 + }
  48 +
  49 + static isEmptyRecord(obj?: Record<string, string>): boolean {
  50 + if (!obj) {
  51 + return true;
  52 + }
  53 + return Object.keys(obj).length === 0 && obj.constructor === Object;
24 } 54 }
25 55
26 /** 56 /**
@@ -36,18 +66,18 @@ export class ArrayUtils { @@ -36,18 +66,18 @@ export class ArrayUtils {
36 } 66 }
37 67
38 static getListSize(collection?: any[]): number { 68 static getListSize(collection?: any[]): number {
39 - return ArrayUtils.isEmpty(collection) ? 0 : collection.length; 69 + return CollectionUtils.isEmpty(collection) ? 0 : collection.length;
40 } 70 }
41 71
42 static getListElement(collection?: any[], index?: number): any { 72 static getListElement(collection?: any[], index?: number): any {
43 - if (ArrayUtils.isEmpty(collection) || index === undefined) { 73 + if (CollectionUtils.isEmpty(collection) || index === undefined) {
44 return null; 74 return null;
45 } 75 }
46 return index >= 0 && index < collection.length ? collection[index] : null; 76 return index >= 0 && index < collection.length ? collection[index] : null;
47 } 77 }
48 78
49 static convertArray<T>(objectList: T[] | T): T[] { 79 static convertArray<T>(objectList: T[] | T): T[] {
50 - if (ArrayUtils.isArray(objectList)) { 80 + if (CollectionUtils.isArray(objectList)) {
51 return objectList as T[]; 81 return objectList as T[];
52 } else { 82 } else {
53 return [objectList as T]; 83 return [objectList as T];
@@ -131,3 +161,4 @@ export class ArrayUtils { @@ -131,3 +161,4 @@ export class ArrayUtils {
131 return new Uint8Array(arr); 161 return new Uint8Array(arr);
132 } 162 }
133 } 163 }
  164 +
  1 +import { StringUtils } from './StringUtils';
  2 +
  3 +/**
  4 + * 日期/时间工具
  5 + */
  6 +// let myDate = new Date();
  7 +// myDate.getTime() // 获取以毫秒为单位的时间值。
  8 +// myDate.getFullYear(); // 获取完整的年份(4位,1970-????)
  9 +// myDate.getMonth(); // 获取myDate月份(0-11,0代表1月)
  10 +// myDate.getDate(); // 获取myDate日期(1-31)
  11 +// myDate.getDay(); // 获取myDate星期X(0-6,0代表星期天)
  12 +// myDate.getTime(); // 获取myDate时间(从1970.1.1开始的毫秒数)
  13 +// myDate.getHours(); // 获取myDate小时数(0-23)
  14 +// myDate.getMinutes(); // 获取myDate分钟数(0-59)
  15 +// myDate.getSeconds(); // 获取myDate秒数(0-59)
  16 +// myDate.getMilliseconds(); // 获取myDate毫秒数(0-999)
  17 +// myDate.toLocaleDateString(); // 获取当前日期:使用当前或指定的区域设置将日期转换为字符串。
  18 +// myDate.toLocaleTimeString(); // 获取当前时间:使用当前或指定的区域设置将时间转换为字符串。
  19 +// myDate.toLocaleString(); // 获取日期与时间:使用当前或指定的区域设置将日期和时间转换为字符串
  20 +
  21 +// 日期时间的年月日时分秒以及毫秒的各个字段
  22 +// export class DateOpt {
  23 +// year: string = ''; // 年 小写y
  24 +// month: string = ''; // 月 大写M
  25 +// day: string = ''; // 日 小写d
  26 +// hour: string = ''; // 时 大写H(24小时制)
  27 +// // hh: string = ''; // 时 小写H(12小时制)
  28 +// minute: string = ''; // 分 小写m
  29 +// second: string = ''; // 秒 小写s
  30 +// millisecond: string = ''; // 毫秒 大写S
  31 +// }
  32 +
  33 +export class DateTimeUtils {
  34 + static readonly MAX_TIME = Math.pow(10, 8) * 24 * 60 * 60 * 1000; // 8640000000000000 毫秒
  35 + static readonly MIN_TIME = -DateTimeUtils.MAX_TIME; // -8640000000000000 毫秒
  36 +
  37 + // 日期+时间格式
  38 + static readonly PATTERN_DATE_TIME_DEFAULT: string = 'yyyyMMddHHmmss'; // 年月日时分秒
  39 + static readonly PATTERN_DATE_TIME_HYPHEN: string = 'yyyy-MM-dd HH:mm:ss'; // 日期中包含连字符/中划线(HYPHEN),时间是以冒号(Colon)分割
  40 + static readonly PATTERN_DATE_TIME_HYPHEN_MS: string = 'yyyy-MM-dd HH:mm:ss.SSS'; // 日期中包含连字符/中划线(HYPHEN),时间是以冒号(Colon)分割
  41 + static readonly PATTERN_DATE_TIME_SLASH: string = 'yyyy/MM/dd HH:mm:ss'; // 日期中包含正斜杠(forward slash '/')
  42 + static readonly PATTERN_DATE_TIME_BACK_SLASH: string = 'yyyy\\MM\\dd HH:mm:ss'; // 日期中包含反斜杠(back slash '\')
  43 + static readonly PATTERN_DATE_TIME_DOT: string = 'yyyy.MM.dd HH:mm:ss'; // 日期中包含英文小圆点(DOT '.')
  44 + static readonly PATTERN_DATE_TIME_CN: string = 'yyyy年MM月dd日 HH:mm:ss'; // 日期中包含包含中文年月日
  45 + static readonly PATTERN_DATE_TIME_MS: string = 'yyyyMMddHHmmssSSS'; // 时间中包含毫秒
  46 + static readonly PATTERN_DATE_TIME_WITHOUT_SECOND: string = 'yyyyMMddHHmm'; // 时间中不包含秒
  47 + static readonly PATTERN_DATE_TIME_SIMPLIFY: string = 'MM/dd HH:mm'; // 精简的日期+时间(不包含年份和秒), 月/日 时:分
  48 +
  49 + // 仅日期格式(不包含时间)
  50 + static readonly PATTERN_DATE_DEFAULT: string = 'yyyyMMdd'; // 年月日
  51 + static readonly PATTERN_DATE_HYPHEN: string = 'yyyy-MM-dd'; // 日期中包含连字符/中划线(HYPHEN)
  52 + static readonly PATTERN_DATE_SLASH: string = 'yyyy/MM/dd'; // 日期中包含正斜杠(forward slash '/')
  53 + static readonly PATTERN_DATE_BACK_SLASH: string = 'yyyy\\MM\\dd'; // 日期中包含反斜杠(back slash '\')
  54 + static readonly PATTERN_DATE_DOT: string = 'yyyy.MM.dd'; // 日期中包含英文小圆点(DOT '.')
  55 + static readonly PATTERN_DATE_CN: string = 'yyyy年MM月dd日'; // 日期中包含包含中文年月日
  56 + static readonly PATTERN_DATE_SLASH_WITHOUT_YEAR: string = 'MM/dd'; // 日期中不包含年份
  57 + static readonly PATTERN_DATE_CN_WITHOUT_YEAR: string = 'MM月dd日'; // 日期中不包含年份,且month与day是中文
  58 +
  59 + // 仅时间格式(不包含日期)
  60 + static readonly PATTERN_TIME_DEFAULT: string = 'HHmmss'; // 时分秒
  61 + static readonly PATTERN_TIME_COLON: string = 'HH:mm:ss'; // 时间是以冒号(Colon)分割
  62 + static readonly PATTERN_TIME_MS: string = 'HHmmssSSS'; // 时间中包含毫秒
  63 + static readonly PATTERN_TIME_COLON_DOT_MS: string = 'HH:mm:ss.SSS'; // 时间是以冒号(Colon)与点号(DOT)分割,且包含毫秒
  64 + static readonly PATTERN_TIME_WITHOUT_SECOND: string = 'HHmm'; // 时间中不包含秒
  65 + static readonly PATTERN_TIME_COLON_WITHOUT_SECOND: string = 'HH:mm'; // 时间是以冒号(Colon)分割,且不包含秒
  66 + static readonly PATTERN_TIME_COLON_WITHOUT_HOUR: string = 'mm:ss'; // 时间是以冒号(Colon)分割,且不包含小时(分钟长度至少2位,可能是3位)
  67 +
  68 + static readonly PATTERN_WEEK: string = 'E'; // 周几/星期几
  69 +
  70 + static readonly MONTHS_IN_YEAR: number = 12; // 1年12个月
  71 + static readonly QUARTERS_IN_YEAR: number = 4; // 1年4个季度
  72 + static readonly MONTHS_IN_QUARTER: number = 3; // 1季度3个月
  73 + static readonly DAYS_MONTH: number[] = [31, 30, 29, 28]; // 每月多少天:大月(1/3/5/7/8/10/12月);小月(4/6/9/11月);2月(闰年29天/非闰月28天)
  74 + static readonly DAYS_IN_WEEK: number = 7; // 1周7天
  75 + static readonly HOURS_IN_DAY = 24; // 1天24小时
  76 + // 分钟
  77 + static readonly MINUTES_IN_HOUR = 60; // 1小时60分(时分秒之间的进制RADIX)
  78 + static readonly MINUTES_IN_DAY = 1440 // 60 * 24 // 1天1440分钟
  79 + // 秒
  80 + static readonly SECONDS_IN_MINUTE = 60; // 1分60秒(时分秒之间的进制RADIX)
  81 + static readonly SECONDS_IN_HOUR = 3600 // 60 * 60 // 1小时3600秒
  82 + static readonly SECONDS_IN_DAY = 86400 // 60 * 60 * 24 // 1天86400秒
  83 + // 毫秒
  84 + static readonly MILLISECONDS_IN_SECOND: number = 1000; // 1秒是1000毫秒,秒与毫秒之间的转换进制RADIX
  85 + static readonly MILLISECONDS_IN_MINUTE: number = 60000; // 1000 * 60 // 1分钟是60000毫秒
  86 + static readonly MILLISECONDS_IN_HOUR: number = 3600000; // 1000 * 60 * 60 // 1小时是3600000毫秒
  87 + static readonly MILLISECONDS_IN_DAY: number = 86400000; // 1000 * 60 * 60 * 24 // 1天是86400000毫秒
  88 +
  89 + static readonly CHINESE_YEAR: string = '年';
  90 + static readonly CHINESE_MONTH: string = '月';
  91 + static readonly CHINESE_DAY: string = '日';
  92 + static readonly CHINESE_LAST_WEEK: string = '上周';
  93 + static readonly CHINESE_YESTERDAY: string = '昨天';
  94 + static readonly CHINESE_TODAY: string = '今天';
  95 + static readonly CHINESE_TOMORROW: string = '明天';
  96 + static readonly CHINESE_NEXT_WEEK: string = '下周';
  97 + // 周x/星期X
  98 + static readonly CHINESE_WEEK1: string[] = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  99 + static readonly CHINESE_WEEK2: string[] = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
  100 + static readonly ENGLISH_WEEK1 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  101 + static readonly ENGLISH_WEEK2 = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  102 + static readonly ENGLISH_MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  103 +
  104 + /**
  105 + * 获取当前日期:年月日
  106 + * 返回格式,默认如:yyyyMMdd,20230926
  107 + */
  108 + static getCurDate(format = DateTimeUtils.PATTERN_DATE_DEFAULT): string {
  109 + const DATETIME = new Date()
  110 + return DateTimeUtils.formatDate(DATETIME.getTime(), format)
  111 + }
  112 +
  113 + /**
  114 + * 获取当前时间:时分秒
  115 + * 返回格式,默认如:HHmmss,230559
  116 + */
  117 + static getCurTime(format = DateTimeUtils.PATTERN_TIME_DEFAULT): string {
  118 + const DATETIME = new Date()
  119 + return DateTimeUtils.formatDate(DATETIME.getTime(), format)
  120 + }
  121 +
  122 + /**
  123 + * 获取当前时间戳,毫秒
  124 + * */
  125 + public static getTimeStamp(): number {
  126 + return new Date().getTime();
  127 + }
  128 +
  129 + /**
  130 + * 当数字转字符串不足maxLength位时,用前导0补足maxLength位
  131 + * @param value-数据值
  132 + * @returns
  133 + * 年份是4位
  134 + * 月/日/时/分/秒,都是2位
  135 + * 毫秒是3位
  136 + */
  137 + static fill(num: number, maxLength: number = 2): string {
  138 + let value: string = '' + num
  139 + return value.padStart(maxLength, '0')
  140 + }
  141 +
  142 + /**
  143 + * 获取两个时间点的时间差
  144 + * @param milliseconds1
  145 + * @param milliseconds2
  146 + * @returns Duration
  147 + */
  148 + static getDuration(milliseconds1: number, milliseconds2: number): number {
  149 + let date1 = new Date(milliseconds1)
  150 + let date2 = new Date(milliseconds2)
  151 + let timeDiff = Math.abs(date2.getTime() - date1.getTime());
  152 + return timeDiff;
  153 + }
  154 +
  155 + /**
  156 + * 格式化Duration时间
  157 + * @param duration 毫秒
  158 + * @returns 返回格式化后的Duration时间
  159 + */
  160 + static getFormattedDuration(duration: number): string {
  161 + // 也可以直接先除以1000转换为秒后再计算 // duration = duration/1000
  162 + // Math.floor 用于向下取整
  163 + let hour = Math.floor(duration / (DateTimeUtils.MILLISECONDS_IN_HOUR))
  164 + // 用总毫秒数duration减去hour所对应的毫秒数差,再除以每分钟所占用的毫秒数
  165 + let minute = Math.floor((duration - hour * (DateTimeUtils.MILLISECONDS_IN_HOUR)) / (DateTimeUtils.MILLISECONDS_IN_MINUTE));
  166 + let second = Math.floor(duration / DateTimeUtils.MILLISECONDS_IN_SECOND) % DateTimeUtils.SECONDS_IN_MINUTE; // 先除以1000,转换为秒;再对整分钟取余
  167 + if (hour > 0) {
  168 + return `${DateTimeUtils.fill(hour)}:${DateTimeUtils.fill(minute)}:${DateTimeUtils.fill(second)}`
  169 + }
  170 + return `${DateTimeUtils.fill(minute)}:${DateTimeUtils.fill(second)}`
  171 + }
  172 +
  173 + /**
  174 + * 格式化显示倒计时
  175 + * @param milliseconds 时间戳 毫秒
  176 + * @returns 返回格式化后的Duration时间
  177 + */
  178 + static getDurationToNow(milliseconds: number): string {
  179 + let nowDateTime = new Date();
  180 + let duration = milliseconds - nowDateTime.getTime();
  181 + if (duration < 0) {
  182 + duration = 0;
  183 + }
  184 + return DateTimeUtils.getFormattedDuration(duration)
  185 + }
  186 +
  187 + /**
  188 + * 根据日期/时间字符串反序列化对应的时间戳
  189 + * @param dateTimeString string 日期+时间字符串
  190 + * 列举字符串格式,如:
  191 + * 20231129,yyyyMMdd
  192 + * 20231126230559 yyyyMMddHHmmss
  193 + * 20231126230559729 yyyyMMddHHmmssSSS
  194 + * 2023-11-26 23:05:59.729, yyyy-MM-dd HH:mm:ss.SSS(先移除所有中划线和冒号及空格等非数字字符)
  195 + * 日期/时间字符串中包含连字符/中划线(Hyphen/Strike)/移除冒号(Colon)/移除空白字符(包括空格、制表符、换行符等)/移除正斜杠(forward slash '/')/移除反斜杠(back slash '\')
  196 + * @param format:string 日期+时间的格式,默认格式:yyyy-MM-dd
  197 + * @param referenceDate:Date 参考日期+时间
  198 + * @returns 转换后的时间戳:milliseconds 毫秒
  199 + * let dateTimeStr:string = "(预告) 2024年12月24日 02:50 开播"
  200 + * let formatPattern:string = "(预告) yyyy年MM月dd日 HH:mm 开播"
  201 + * let parsedDate = DateTimeUtils.parseDate(dateTimeStr, formatPattern)
  202 + */
  203 + static parseDate(dateTimeString: string, format: string = DateTimeUtils.PATTERN_DATE_HYPHEN, referenceDate?: Date): number {
  204 + if (!dateTimeString) {
  205 + return 0
  206 + }
  207 + if (!referenceDate) {
  208 + referenceDate = new Date(); // 参考当前时间
  209 + }
  210 +
  211 + const optPatternList: string[] = ['y+', 'M+', 'd+', 'H+', 'm+', 's+', 'S+'];
  212 + let targetYear: number = 0 // 年
  213 + let targetMonth: number = 0 // 月, monthIndex
  214 + let targetDay: number = 0 // 日
  215 + let targetHour: number = 0 // 时
  216 + let targetMinute: number = 0 // 分
  217 + let targetSecond: number = 0 // 秒
  218 + let targetMillisecond: number = 0 // 毫秒
  219 + for (let i = 0; i < optPatternList.length; i++) {
  220 + const optPattern = optPatternList[i];
  221 + const regExp = new RegExp(optPattern, 'g');
  222 + // console.log(optPattern);
  223 + let matches = regExp.exec(format);
  224 + if (!matches) {
  225 + continue
  226 + }
  227 + // console.dir(matches)
  228 + // console.dir(matches?.[0])
  229 + // console.dir(matches?.index)
  230 + let pick: number = StringUtils.parseNumber(dateTimeString.substring(matches.index, matches.index + matches?.[0].length))
  231 + // console.dir(pick)
  232 + switch (optPattern) {
  233 + case 'y+':
  234 + if (pick >= -271821 && pick <= 275760) { // 根据最大日期/时间与根据最小日期/时间计算出的年份范围
  235 + targetYear = pick
  236 + } else {
  237 + targetYear = referenceDate.getFullYear() // 当解析不到年份时,则设置为今年
  238 + }
  239 + break;
  240 + case 'M+': // monthIndex between 0 and 11
  241 + if (pick >= 1 && pick <= 12) {
  242 + targetMonth = pick - 1
  243 + } else {
  244 + targetMonth = referenceDate.getMonth() // 当解析不到月份时,则设置为本月
  245 + }
  246 + break;
  247 + case 'd+': // between 1 and 31.
  248 + if (pick >= 1 && pick <= 31) {
  249 + targetDay = pick
  250 + } else {
  251 + targetDay = referenceDate.getDate()
  252 + }
  253 + break;
  254 + case 'H+': // from 0 to 23
  255 + if (pick >= 0 && pick <= 23) {
  256 + targetHour = pick
  257 + } else {
  258 + targetDay = referenceDate.getDate()
  259 + }
  260 + break;
  261 + case 'm+': // from 0 to 59
  262 + if (pick >= 0 && pick <= 59) {
  263 + targetMinute = pick
  264 + } else {
  265 + targetDay = referenceDate.getMinutes()
  266 + }
  267 + break;
  268 + case 's+': // from 0 to 59
  269 + if (pick >= 0 && pick <= 59) {
  270 + targetSecond = pick
  271 + } else {
  272 + targetSecond = referenceDate.getSeconds()
  273 + }
  274 + break;
  275 + case 'S+': // from 0 to 999
  276 + if (pick >= 0 && pick <= 999) {
  277 + targetMillisecond = pick
  278 + } else {
  279 + targetMillisecond = referenceDate.getMilliseconds()
  280 + }
  281 + break;
  282 + default:
  283 + break;
  284 + }
  285 + }
  286 + let targetDate: Date = new Date(targetYear, targetMonth, targetDay, targetHour, targetMinute, targetSecond, targetMillisecond)
  287 + return targetDate.getTime()
  288 + }
  289 +
  290 + /**
  291 + * 把整数时间戳格式化为指定格式的日期+时间字符串
  292 + * @param timestamp:毫秒
  293 + * @param format 指定要格式化的pattern,默认格式:yyyy-MM-dd
  294 + * @returns 格式化后的字符串
  295 + * 举例:
  296 + * let date_fmt = DateTimeUtils.formatDate(dateTime, "预告 (E) MM月dd日 HH:mm 开播")
  297 + */
  298 + static formatDate(timestamp: number, format: string = DateTimeUtils.PATTERN_DATE_HYPHEN): string {
  299 + try {
  300 + const date = new Date(timestamp);
  301 + let targetYear: string = date.getFullYear().toString();
  302 + let targetMonth: string = DateTimeUtils.fill(date.getMonth() + 1);
  303 + let targetDay: string = DateTimeUtils.fill(date.getDate());
  304 + let targetHours: string = DateTimeUtils.fill(date.getHours());
  305 + let targetMinutes: string = DateTimeUtils.fill(date.getMinutes());
  306 + let targetSeconds: string = DateTimeUtils.fill(date.getSeconds());
  307 + let targetMilliseconds: string = DateTimeUtils.fill(date.getMilliseconds(), 3);
  308 + let targetDayOfWeek: number = date.getDay();
  309 +
  310 + const dateOptionPatternList: string[] = ['y+', 'M+', 'd+', 'H+', 'm+', 's+', 'S+', 'E'];
  311 + for (let i = 0; i < dateOptionPatternList.length; i++) {
  312 + const dateOptionPattern = dateOptionPatternList[i];
  313 + const dateOptionRegExp = new RegExp(dateOptionPattern);
  314 + let match = dateOptionRegExp.exec(format); // 使用 RegExp 的exec 方法在目标字符串中查找匹配项
  315 + if (!match) {
  316 + continue
  317 + }
  318 + switch (dateOptionPattern) {
  319 + case 'y+':
  320 + format = format.replace(dateOptionRegExp, targetYear);
  321 + break;
  322 + case 'M+':
  323 + format = format.replace(dateOptionRegExp, targetMonth);
  324 + break;
  325 + case 'd+':
  326 + format = format.replace(dateOptionRegExp, targetDay);
  327 + break;
  328 + case 'H+':
  329 + format = format.replace(dateOptionRegExp, targetHours);
  330 + break;
  331 + case 'm+':
  332 + format = format.replace(dateOptionRegExp, targetMinutes);
  333 + break;
  334 + case 's+':
  335 + format = format.replace(dateOptionRegExp, targetSeconds);
  336 + break;
  337 + case 'S+':
  338 + format = format.replace(dateOptionRegExp, targetMilliseconds);
  339 + break;
  340 + case 'E': // from 0 to 6; the day of the week
  341 + format = format.replace(dateOptionRegExp, DateTimeUtils.CHINESE_WEEK1[targetDayOfWeek]);
  342 + break;
  343 + default:
  344 + break;
  345 + }
  346 + }
  347 + return format;
  348 + } catch (error) {
  349 + console.error(`ERROR formatDate error: ${error}.`);
  350 + return "";
  351 + }
  352 + }
  353 +
  354 + /**
  355 + * 构造一周中的哪一天/构造星期X/周X
  356 + * @param timestamp
  357 + * @returns
  358 + */
  359 + static buildDayOfWeek(timestamp: number, weeks: string[] = DateTimeUtils.CHINESE_WEEK1): string {
  360 + try {
  361 + const date = new Date(timestamp);
  362 + let day = date.getDay()
  363 + let week = weeks[day];
  364 + return week ?? ''
  365 + } catch (error) {
  366 + console.error(`ERROR formatDate error: ${error}.`);
  367 + return ''
  368 + }
  369 + }
  370 +
  371 + static startOfDay(argument: number): Date {
  372 + const _date = new Date(argument);
  373 + _date.setHours(0, 0, 0, 0);
  374 + return _date;
  375 + }
  376 +
  377 + static isSameDay(dateLeft: number, dateRight: number): boolean {
  378 + const dateLeftStartOfDay = DateTimeUtils.startOfDay(dateLeft);
  379 + const dateRightStartOfDay = DateTimeUtils.startOfDay(dateRight);
  380 + return dateLeftStartOfDay.getTime() === dateRightStartOfDay.getTime();
  381 + }
  382 +
  383 + static addDays(argument: number, amount: number): Date {
  384 + const _date = new Date(argument);
  385 + if (amount == 0) {
  386 + return _date;
  387 + }
  388 + _date.setDate(_date.getDate() + amount);
  389 + return _date;
  390 + }
  391 +
  392 + static subDays(date: number, amount: number): Date {
  393 + return DateTimeUtils.addDays(date, -amount);
  394 + }
  395 +
  396 + static isToday(date: number,): boolean {
  397 + return DateTimeUtils.isSameDay(date, Date.now());
  398 + }
  399 +
  400 + static isYesterday(date: number): boolean {
  401 + return DateTimeUtils.isSameDay(date, DateTimeUtils.subDays(Date.now(), 1).getTime());
  402 + }
  403 +
  404 + static isTomorrow(date: number): boolean {
  405 + return DateTimeUtils.isSameDay(date, DateTimeUtils.addDays(Date.now(), 1).getTime());
  406 + }
  407 +
  408 + // 检查指定的日期是过去的吗?
  409 + static isPast(_date: Date): boolean {
  410 + return _date.getTime() < Date.now();
  411 + }
  412 +
  413 + // 检查指定的日期在未来/将来吗?
  414 + static isFuture(_date: Date): boolean {
  415 + return _date.getTime() > Date.now();
  416 + }
  417 +
  418 + // 检查_date是在dateToCompare之后吗?,如
  419 + // const result = isAfter(new Date(1989, 6, 10), new Date(1987, 1, 11))
  420 + // => true
  421 + static isAfter(_date: Date, dateToCompare: Date): boolean {
  422 + return _date.getTime() > dateToCompare.getTime();
  423 + }
  424 +
  425 + // 检查_date是在dateToCompare之前吗?,如
  426 + // const result = isBefore(new Date(1989, 6, 10), new Date(1987, 1, 11))
  427 + // => false
  428 + static isBefore(_date: Date, dateToCompare: Date): boolean {
  429 + return _date.getTime() < dateToCompare.getTime();
  430 + }
  431 +}
  432 +
  433 +// const dateTimeUtils = new DateTimeUtils()
  1 +import util from '@ohos.util';
  2 +import deviceInfo from '@ohos.deviceInfo';
  3 +import { SPHelper } from './SPHelper';
  4 +
  5 +const TAG = 'DeviceUtil';
  6 +
  7 +/**
  8 + * 与(硬件)设备相关(不可改变或不可升级)属性或操作
  9 + */
  10 +export class DeviceUtil {
  11 + static clientId() {
  12 + let uuid = SPHelper.default.getSync("clientId", '');
  13 + if (uuid == '') {
  14 + uuid = util.generateRandomUUID();
  15 + SPHelper.default.saveSync("clientId", uuid);
  16 + }
  17 + return uuid.toString();
  18 + }
  19 +
  20 + /**
  21 + * 返回设备厂家名称
  22 + * HUAWEI
  23 + * @returns
  24 + */
  25 + static getManufacture(): string {
  26 + return deviceInfo.manufacture;
  27 + }
  28 +
  29 + /**
  30 + * 返回设备品牌名称
  31 + * HUAWEI MATE 40 PRO
  32 + * @returns
  33 + */
  34 + static getBrand(): string {
  35 + return deviceInfo.brand;
  36 + }
  37 +
  38 + /**
  39 + * 返回认证型号
  40 + * LIO-AL00
  41 + * @returns
  42 + */
  43 + static getProductModel(): string {
  44 + return deviceInfo.productModel;
  45 + }
  46 +
  47 + /**
  48 + * 返回产品版本
  49 + * OpenHarmony-3.2.6.5(Beta2)
  50 + * @returns
  51 + */
  52 + static getDisplayVersion(): string {
  53 + return deviceInfo.productModel;
  54 + }
  55 +}
  1 +import display from '@ohos.display';
  2 +import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant';
  3 +import {Logger} from './Logger';
  4 +
  5 +const TAG = 'DisplayUtils';
  6 +
  7 +/**
  8 + * 设备显示器/Display属性:
  9 + *
  10 + 手机(HUAWEI Mate 40 Pro & NOH-AN00)-竖屏:
  11 + {
  12 + "id": 0,
  13 + "name": "UNKNOW",
  14 + "alive": true,
  15 + "state": 0,
  16 + "refreshRate": 90,
  17 + "rotation": 0,
  18 + "width": 1344, // 屏幕显示的实际宽度/(像素个数/以像素px为单位)
  19 + "height": 2772, // 屏幕显示的实际高度/(像素个数/以像素px为单位)
  20 + "densityDPI": 560, // 实际像素密度(每英寸像素:120/160/240/320/560)PPI,是一个具体的数值
  21 + "orientation": 0,
  22 + "densityPixels": 3.5, // 屏幕密度(当像素密度为160时屏幕密度为1.0, 像素比例0.75/1.0/1.5/2.0/3.5) | 缩放因子density = 屏幕像素密度/160, 可用于vp和px转化
  23 + "scaledDensity": 3.5, // 可用于fp和px转化
  24 + "xDPI": 461.3188781738281,
  25 + "yDPI": 457.1999816894531
  26 + }
  27 +
  28 + 手机(HUAWEI Mate 40 Pro & NOH-AN00)-横屏:
  29 + {
  30 + "id": 0,
  31 + "name": "UNKNOW",
  32 + "alive": true,
  33 + "state": 0,
  34 + "refreshRate": 90,
  35 + "rotation": 1,
  36 + "width": 2772,
  37 + "height": 1344,
  38 + "densityDPI": 560,
  39 + "orientation": 1,
  40 + "densityPixels": 3.5,
  41 + "scaledDensity": 3.5,
  42 + "xDPI": 951.47021484375,
  43 + "yDPI": 221.67271423339844
  44 + }
  45 +
  46 + Fold手机(HUAWEI Mate X5 & ALT-AL10)-折叠状态-竖屏:
  47 + {
  48 + "id": 0,
  49 + "name": "UNKNOW",
  50 + "alive": true,
  51 + "state": 0,
  52 + "refreshRate": 90,
  53 + "rotation": 0,
  54 + "width": 1080,
  55 + "height": 2504,
  56 + "densityDPI": 500,
  57 + "orientation": 1,
  58 + "densityPixels": 3.125,
  59 + "scaledDensity": 3.125,
  60 + "xDPI": 173.62025451660156,
  61 + "yDPI": 451.0751647949219
  62 + }
  63 +
  64 + Fold手机(HUAWEI Mate X5 & ALT-AL10)-折叠状态-横屏:
  65 + {
  66 + "id": 0,
  67 + "name": "UNKNOW",
  68 + "alive": true,
  69 + "state": 0,
  70 + "refreshRate": 90,
  71 + "rotation": 3,
  72 + "width": 2504,
  73 + "height": 1080,
  74 + "densityDPI": 500,
  75 + "orientation": 2,
  76 + "densityPixels": 3.125,
  77 + "scaledDensity": 3.125,
  78 + "xDPI": 402.541748046875,
  79 + "yDPI": 194.55319213867188
  80 + }
  81 +
  82 + Fold手机(HUAWEI Mate X5 & ALT-AL10)-完全展开状态-竖屏:
  83 + {
  84 + "id": 0,
  85 + "name": "UNKNOW",
  86 + "alive": true,
  87 + "state": 0,
  88 + "refreshRate": 90,
  89 + "rotation": 0,
  90 + "width": 2224,
  91 + "height": 2496,
  92 + "densityDPI": 500,
  93 + "orientation": 1,
  94 + "densityPixels": 3.125,
  95 + "scaledDensity": 3.125,
  96 + "xDPI": 357.52911376953125,
  97 + "yDPI": 449.634033203125
  98 + }
  99 +
  100 + 平板电脑(HUAWEI MatePad Pro & WGR-W09)(2in1设备)-横屏:
  101 + {
  102 + "id": 0,
  103 + "name": "UNKNOW",
  104 + "alive": true,
  105 + "state": 0,
  106 + "refreshRate": 60,
  107 + "rotation": 0,
  108 + "width": 2560,
  109 + "height": 1600,
  110 + "densityDPI": 240,
  111 + "orientation": 1,
  112 + "densityPixels": 1.5,
  113 + "scaledDensity": 1.5,
  114 + "xDPI": 239.05882263183594,
  115 + "yDPI": 239.05882263183594
  116 + }
  117 + */
  118 +/**
  119 + * 与显示器/display/screen(硬件)设备相关(不可改变或不可升级)属性或操作(应该读取窗口Window的宽高,而不是显示器display的宽高,因为电脑设备的窗口可以动态调整Window窗口大小)
  120 + * 屏幕密度是160时,1vp=1px
  121 + */
  122 +export class DisplayUtils {
  123 + /**
  124 + * Get 屏幕显示/display/screen Width(单位vp)
  125 + * 手机(HUAWEI Mate 40 Pro & NOH-AN00)-竖屏:width为1344*3.5=384vp
  126 + * 手机(HUAWEI Mate 40 Pro & NOH-AN00)-横屏:width为2772*3.5=792vp
  127 + * @returns screen width.
  128 + */
  129 + public static getDeviceWidth(): number {
  130 + let displayObject: display.Display = display.getDefaultDisplaySync();
  131 + // Logger.info(TAG, `getDeviceWidth, displayObject: ${JSON.stringify(displayObject)}`);
  132 + let screenWidth = displayObject.width;
  133 + let screenDensityDPI = displayObject.densityDPI;
  134 + // 像素密度(Pixel Density)
  135 + let densityPixels = screenDensityDPI / ConfigurationConstant.ScreenDensity.SCREEN_DENSITY_MDPI
  136 + // let densityPixels = displayObject.densityPixels
  137 + let deviceWidth = screenWidth / densityPixels;
  138 + // Logger.info(TAG, `getDeviceWidth, deviceWidth: ${deviceWidth}`);
  139 + return deviceWidth
  140 + }
  141 +
  142 + /**
  143 + * Get the 显示/display/screen height(单位vp).
  144 + *
  145 + * @returns screen height.
  146 + */
  147 + public static getDeviceHeight(): number {
  148 + let displayObject: display.Display = display.getDefaultDisplaySync();
  149 + let screenHeight = displayObject.height;
  150 + let screenDensityDPI = displayObject.densityDPI;
  151 + // 像素密度(Pixel Density)
  152 + let densityPixels = screenDensityDPI / ConfigurationConstant.ScreenDensity.SCREEN_DENSITY_MDPI
  153 + // let densityPixels = displayObject.densityPixels
  154 + let deviceHeight = screenHeight / densityPixels
  155 + // Logger.info(TAG, `getDeviceHeight, deviceHeight: ${deviceHeight}`); // 345.6 // 711.68
  156 + return deviceHeight
  157 + }
  158 +}
@@ -26,56 +26,97 @@ export class LazyDataSource<T> extends BasicDataSource<T> { @@ -26,56 +26,97 @@ export class LazyDataSource<T> extends BasicDataSource<T> {
26 return this.dataArray[index]; 26 return this.dataArray[index];
27 } 27 }
28 28
  29 + // 获取索引对应的Item数据
  30 + public get(index: number): T {
  31 + return this.getData(index);
  32 + }
  33 +
  34 + public getFirst(): T {
  35 + return this.getData(0);
  36 + }
  37 +
  38 + public getLast(): T {
  39 + return this.getData(this.totalCount() - 1);
  40 + }
  41 +
  42 + // 获取所有数据
  43 + public getDataArray(): T[] {
  44 + return this.dataArray;
  45 + }
  46 +
29 // 增加/插入1个Item/数据,若index为undefined,则在数据尾部增加1个元素;否则,在指定索引(可为负/或大于数组长度)位置插入1个元素 47 // 增加/插入1个Item/数据,若index为undefined,则在数据尾部增加1个元素;否则,在指定索引(可为负/或大于数组长度)位置插入1个元素
30 - public addItem(data: T, index?: number): void {  
31 - if (index == undefined) { 48 + public addItem(item: T, startPosition?: number): void {
  49 + if (startPosition == undefined) {
32 // 将新元素添加到数组的末尾 50 // 将新元素添加到数组的末尾
33 - this.dataArray.push(data);  
34 - // this.dataArray.splice(this.dataArray.length, 0, data) 51 + this.dataArray.push(item);
  52 + // this.dataArray.splice(this.dataArray.length, 0, item)
35 this.notifyDataAdd(this.dataArray.length - 1); 53 this.notifyDataAdd(this.dataArray.length - 1);
36 } else { 54 } else {
37 // 从数组中的index位置开始删除0个元素,并在同一位置插入((1个或多个))新元素,返回已删除的元素。 55 // 从数组中的index位置开始删除0个元素,并在同一位置插入((1个或多个))新元素,返回已删除的元素。
38 - // 当index大于等于数组长度时,不删除任何数据,且data加在数组末尾 56 + // 当index大于等于数组长度时,不删除任何数据,且item加在数组末尾
39 // 当index为负数时,其代表从数组后向前的索引位置 57 // 当index为负数时,其代表从数组后向前的索引位置
40 - this.dataArray.splice(index, 0, data); 58 + this.dataArray.splice(startPosition, 0, item);
  59 + this.notifyDataAdd(startPosition);
  60 + }
  61 + }
  62 +
  63 + public addItems(arr: T[], startPosition?: number): void {
  64 + if (startPosition == undefined) {
  65 + // 将新元素添加到数组的末尾
  66 + this.dataArray.push(...arr)
  67 + for (let index = this.dataArray.length - arr.length; index < this.dataArray.length; index++) {
41 this.notifyDataAdd(index); 68 this.notifyDataAdd(index);
42 } 69 }
  70 + } else {
  71 + // 从数组中的position位置开始删除0个元素,并在同一位置插入((1个或多个))新元素,返回已删除的元素。
  72 + // 当index大于等于数组长度时,不删除任何数据,且arr加在数组末尾
  73 + // 当index为负数时,其代表从数组后向前的索引位置
  74 + this.dataArray.splice(startPosition, 0, ...arr);
  75 + for (let index = startPosition; index < arr.length; index++) {
  76 + this.notifyDataAdd(index);
  77 + }
  78 + }
43 } 79 }
44 80
45 // 在数据尾部增加1到多个元素 81 // 在数据尾部增加1到多个元素
46 - public push(...data: T[]): void {  
47 - this.dataArray.push(...data)  
48 - for (let index = this.dataArray.length - data.length; index < this.dataArray.length; index++) { 82 + public push(...items: T[]): void {
  83 + this.dataArray.push(...items)
  84 + for (let index = this.dataArray.length - items.length; index < this.dataArray.length; index++) {
49 this.notifyDataAdd(index); 85 this.notifyDataAdd(index);
50 } 86 }
51 } 87 }
52 88
  89 + // 在数据尾部增加一个同类型的LazyDataSource
  90 + public pushDataSource(dataSource: LazyDataSource<T>): void {
  91 + this.push(...dataSource.dataArray)
  92 + }
  93 +
53 // 在数据尾部增加1个元素 94 // 在数据尾部增加1个元素
54 - public addLastItem(data: T): void {  
55 - this.addItem(data) 95 + public addLastItem(item: T): void {
  96 + this.addItem(item)
56 } 97 }
57 98
58 // 在数据开头插入1个元素 99 // 在数据开头插入1个元素
59 - public addFirstItem(data: T): void { 100 + public addFirstItem(item: T): void {
60 // 在数组的开头插入(1个或多个)新元素 101 // 在数组的开头插入(1个或多个)新元素
61 - // this.dataArray.unshift(data) 102 + // this.dataArray.unshift(item)
62 // this.notifyDataAdd(0); 103 // this.notifyDataAdd(0);
63 - this.addItem(data, 0) 104 + this.addItem(item, 0)
64 } 105 }
65 106
66 // 在第2个元素位置,插入1个元素 107 // 在第2个元素位置,插入1个元素
67 - public add2ndItem(data: T): void {  
68 - this.addItem(data, 1) 108 + public add2ndItem(item: T): void {
  109 + this.addItem(item, 1)
69 } 110 }
70 111
71 // 在第3个元素位置,插入1个元素 112 // 在第3个元素位置,插入1个元素
72 - public add3rdItem(data: T): void {  
73 - this.addItem(data, 2) 113 + public add3rdItem(item: T): void {
  114 + this.addItem(item, 2)
74 } 115 }
75 116
76 // 在第4个元素位置,插入1个元素 117 // 在第4个元素位置,插入1个元素
77 - public add4thItem(data: T): void {  
78 - this.addItem(data, 3) 118 + public add4thItem(item: T): void {
  119 + this.addItem(item, 3)
79 } 120 }
80 121
81 // 把from位置的item移动到to位置(暂不支持from/to为负数或大于等于数组长度) 122 // 把from位置的item移动到to位置(暂不支持from/to为负数或大于等于数组长度)
@@ -159,53 +200,80 @@ export class LazyDataSource<T> extends BasicDataSource<T> { @@ -159,53 +200,80 @@ export class LazyDataSource<T> extends BasicDataSource<T> {
159 } 200 }
160 201
161 // 修改/更新index指定索引位置的元素 202 // 修改/更新index指定索引位置的元素
162 - public updateItem(data: T, index?: number): void { 203 + public updateItem(item: T, index?: number): void {
163 if (index == undefined || index >= this.dataArray.length) { 204 if (index == undefined || index >= this.dataArray.length) {
164 // 当不传index或index大于等于数组长度时,修改/更新数组的最后1个元素 205 // 当不传index或index大于等于数组长度时,修改/更新数组的最后1个元素
165 - this.dataArray.splice(this.dataArray.length - 1, 1, data); 206 + this.dataArray.splice(this.dataArray.length - 1, 1, item);
166 this.notifyDataChange(this.dataArray.length); 207 this.notifyDataChange(this.dataArray.length);
167 } else { 208 } else {
168 // 从数组中的index位置开始,删除1个元素 209 // 从数组中的index位置开始,删除1个元素
169 // 当index为负数时,其代表从数组后向前的索引位置 210 // 当index为负数时,其代表从数组后向前的索引位置
170 - this.dataArray.splice(index, 1, data); 211 + this.dataArray.splice(index, 1, item);
171 this.notifyDataChange(index); 212 this.notifyDataChange(index);
172 } 213 }
173 } 214 }
174 215
175 // 修改/更新最后1个元素 216 // 修改/更新最后1个元素
176 - public updateLastItem(data: T): void {  
177 - this.updateItem(data) 217 + public updateLastItem(item: T): void {
  218 + this.updateItem(item)
178 } 219 }
179 220
180 // 修改/更新第1个元素 221 // 修改/更新第1个元素
181 - public updateFirstItem(data: T): void {  
182 - this.updateItem(data, 0) 222 + public updateFirstItem(item: T): void {
  223 + this.updateItem(item, 0)
183 } 224 }
184 225
185 // 修改/更新第1个元素 226 // 修改/更新第1个元素
186 - public update2ndItem(data: T): void {  
187 - this.updateItem(data, 0) 227 + public update2ndItem(item: T): void {
  228 + this.updateItem(item, 0)
188 } 229 }
189 230
190 // 修改/更新第2个元素 231 // 修改/更新第2个元素
191 - public update1stItem(data: T): void {  
192 - this.updateItem(data, 1) 232 + public update1stItem(item: T): void {
  233 + this.updateItem(item, 1)
193 } 234 }
194 235
195 // 修改/更新第3个元素 236 // 修改/更新第3个元素
196 - public update3rdItem(data: T): void {  
197 - this.updateItem(data, 2) 237 + public update3rdItem(item: T): void {
  238 + this.updateItem(item, 2)
198 } 239 }
199 240
200 // 修改/更新第4个元素 241 // 修改/更新第4个元素
201 - public update4thItem(data: T): void {  
202 - this.updateItem(data, 3) 242 + public update4thItem(item: T): void {
  243 + this.updateItem(item, 3)
  244 + }
  245 +
  246 + // 清空数组
  247 + public clear(): void {
  248 + this.replaceAll()
203 } 249 }
204 250
205 // 把数据全部删除,再添加全部新元素 251 // 把数据全部删除,再添加全部新元素
206 - public replaceAll(...data: T[]): void { 252 + public replaceAll(...items: T[]): void {
207 // 从数组中的0位置开始删除dataArray.length个元素,并在同一位置插入((1个或多个))新元素,返回已删除的元素。 253 // 从数组中的0位置开始删除dataArray.length个元素,并在同一位置插入((1个或多个))新元素,返回已删除的元素。
208 - this.dataArray.splice(0, this.dataArray.length, ...data); 254 + this.dataArray.splice(0, this.dataArray.length, ...items);
209 this.notifyDataReload() 255 this.notifyDataReload()
210 } 256 }
  257 +
  258 + // 获取指定元素的下标
  259 + public getIndexOf(element: T): number {
  260 + for (let index = 0; index < this.dataArray.length; index++) {
  261 + if (this.dataArray[index] == element) {
  262 + return index
  263 + }
  264 + }
  265 + return -1
  266 + }
  267 +
  268 + public isEmpty(): boolean {
  269 + return this.dataArray.length == 0
  270 + }
  271 +
  272 + public isNotEmpty(): boolean {
  273 + return this.dataArray.length > 0
  274 + }
  275 +
  276 + public sort(comparator: (firstValue: T, secondValue: T) => number): void {
  277 + this.dataArray.sort(comparator)
  278 + }
211 } 279 }
@@ -79,16 +79,17 @@ export class ResourcesUtils { @@ -79,16 +79,17 @@ export class ResourcesUtils {
79 * SubscribeListData.json 79 * SubscribeListData.json
80 * @returns JSON Object 80 * @returns JSON Object
81 * 81 *
82 - * 调用方式:todo: 82 + * 调用方式:
  83 + * let compRes: MGHttp.ResponseDTO<BodyComponent> = await ResourcesUtils.getResourcesJson<MGHttp.ResponseDTO<BodyComponent>>(context, 'model/componentList.json');
83 */ 84 */
84 - static getResourcesJson<R>(context:Context, filename: string): Promise<R> { 85 + static getResourcesJson<R>(context: Context, filename: string): Promise<R> {
85 Logger.info(TAG, `getResourcesJson filename: ${filename}`); 86 Logger.info(TAG, `getResourcesJson filename: ${filename}`);
86 return new Promise<R>((resolve, reject) => { 87 return new Promise<R>((resolve, reject) => {
87 ResourcesUtils.getResourcesText(context, filename) 88 ResourcesUtils.getResourcesText(context, filename)
88 .then((text: string) => { 89 .then((text: string) => {
89 try { 90 try {
90 // let config: R = JSON.parse(text) 91 // let config: R = JSON.parse(text)
91 - let config:R = JSON.parse(text) as R; 92 + let config: R = JSON.parse(text) as R;
92 if (config) { 93 if (config) {
93 Logger.info(TAG, "getResourcesJson parse JSON file success."); 94 Logger.info(TAG, "getResourcesJson parse JSON file success.");
94 // Logger.info(TAG, `getResourcesJson config : ${JSON.stringify(config)}`); 95 // Logger.info(TAG, `getResourcesJson config : ${JSON.stringify(config)}`);
@@ -117,7 +118,7 @@ export class ResourcesUtils { @@ -117,7 +118,7 @@ export class ResourcesUtils {
117 } 118 }
118 try { 119 try {
119 // let config: R = JSON.parse(text) 120 // let config: R = JSON.parse(text)
120 - let config:R = JSON.parse(text) as R; 121 + let config: R = JSON.parse(text) as R;
121 return config 122 return config
122 } catch (err) { 123 } catch (err) {
123 // json解析异常 124 // json解析异常
  1 +import deviceInfo from '@ohos.deviceInfo';
  2 +
  3 +/**
  4 + * 与鸿蒙系统(软件)设备相关(可改变或可升级)属性或操作
  5 + */
  6 +export class SystemUtils {
  7 + /**
  8 + * 返回AGC格式的系统名称
  9 + * OpenHarmony 3.2.6.5(Beta2)
  10 + */
  11 + static getOsFullName(): string {
  12 + // OpenHarmony-3.2.6.5(Beta2)
  13 + let fullName = deviceInfo.osFullName.split('-');
  14 + if (fullName && fullName.length >= 1) {
  15 + return fullName[0] + ' ' + fullName[1];
  16 + }
  17 + return '';
  18 + }
  19 +
  20 + /**
  21 + * 返回系统空闲存储空间,TODO:
  22 + * @returns number
  23 + */
  24 + static getFreeBytes(): number {
  25 + return 0;
  26 + }
  27 +}
1 -export { ResponseDTO } from './src/main/ets/bean/ResponseDTO' 1 +export { ResponseDTO } from "./src/main/ets/bean/ResponseDTO"
2 2
3 -export { ResponseVO } from './src/main/ets/bean/ResponseVO' 3 +export { HttpRequest as WDHttp } from "./src/main/ets/http/HttpRequest"
4 4
5 -export { ResultCode } from './src/main/ets/bean/ResultCode' 5 +export { HttpUrlUtils } from "./src/main/ets/http/HttpUrlUtils"
6 6
7 -export { WDHttp } from './src/main/ets/http/WDHttp'  
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 "version": "1.0.0", 8 "version": "1.0.0",
9 "dependencies": { 9 "dependencies": {
10 "wdKit": "file:../wdKit", 10 "wdKit": "file:../wdKit",
  11 + "wdConstant": "file:../wdConstant",
11 "@ohos/axios": "^2.1.1" 12 "@ohos/axios": "^2.1.1"
12 } 13 }
13 } 14 }
1 -/**  
2 - * ResponseVO  
3 - */  
4 -export interface ResponseVO<T = string> {  
5 - // 返回代码,参考附录ResultCode 即(ACCEPTED/SUCCESS/FAILED/REJECTED等)  
6 - resultCode: string;  
7 -  
8 - // 返回描述  
9 - resultDesc: string;  
10 -  
11 - // 错误码,参考附录和接口中ErrorCode(当resultCode=FAILED才有),如:"ERR_USER_NOTFOUND"  
12 - errorCode?: string;  
13 -  
14 - // 业务数据  
15 - data?: T;  
16 -}  
1 -/**  
2 - * The Response ResultCode enum.  
3 - */  
4 -export const enum ResultCode {  
5 - // 请求执行(查询)成功  
6 - SUCCESS = 'SUCCESS',  
7 - // 请求执行(查询)失败  
8 - FAILED = 'FAILED',  
9 - // 该请求被拒绝处理,例如参数错误或非法等  
10 - REJECTED = 'REJECTED',  
11 - // 该请求已经被接收,但是本次同步返回无法知道执行结果  
12 - ACCEPTED = 'ACCEPTED',  
13 - // 参数错误  
14 - // ERR_NOT_VALID_PARAMETERS = 'ERR_NOT_VALID_PARAMETERS'  
15 -}  
1 -import type { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from '@ohos/axios';  
2 -import axios, { HttpStatusCode } from '@ohos/axios'; 1 +import axios, {
  2 + AxiosError,
  3 + AxiosInstance,
  4 + AxiosResponse,
  5 + HttpStatusCode,
  6 + InternalAxiosRequestConfig
  7 +} from '@ohos/axios';
3 8
4 // import type ResponseDTO from '../models/ResponseDTO'; 9 // import type ResponseDTO from '../models/ResponseDTO';
5 10
@@ -57,8 +62,7 @@ instance.interceptors.request.use( @@ -57,8 +62,7 @@ instance.interceptors.request.use(
57 // } 62 // }
58 63
59 // 添加响应拦截器 64 // 添加响应拦截器
60 -instance.interceptors.response.use(  
61 - // 响应拦截器response类型就是Axios.request<T = any, R = AxiosResponse<T>, D = any>中的泛型R 65 +instance.interceptors.response.use(// 响应拦截器response类型就是Axios.request<T = any, R = AxiosResponse<T>, D = any>中的泛型R
62 // 泛型 T 就是服务器返回数据的类型 66 // 泛型 T 就是服务器返回数据的类型
63 // 泛型 R 就是这个泛型 T 数据经过 axios 包装一层得到的 response 对象的类型,而 request 方法的返回值是一个 Promise,其值就是成功态的 R,也就是 response对象。 67 // 泛型 R 就是这个泛型 T 数据经过 axios 包装一层得到的 response 对象的类型,而 request 方法的返回值是一个 Promise,其值就是成功态的 R,也就是 response对象。
64 (response: AxiosResponse) => { 68 (response: AxiosResponse) => {
@@ -83,7 +87,9 @@ instance.interceptors.response.use( @@ -83,7 +87,9 @@ instance.interceptors.response.use(
83 // 改造返回的数据,即将AxiosResponse的data返回,服务端返回的数据 87 // 改造返回的数据,即将AxiosResponse的data返回,服务端返回的数据
84 return response.data; 88 return response.data;
85 } else { 89 } else {
86 - return Promise.reject(response); 90 + console.log(`httpStatus:${response.status}-${response.status}!`)
  91 + // return Promise.reject(error);
  92 + return response.data;
87 } 93 }
88 }, 94 },
89 (error: AxiosError) => { 95 (error: AxiosError) => {
@@ -101,7 +107,7 @@ instance.interceptors.response.use( @@ -101,7 +107,7 @@ instance.interceptors.response.use(
101 107
102 export default instance; 108 export default instance;
103 109
104 -function buildErrorMsg(httpStatus: number):string { 110 +function buildErrorMsg(httpStatus: number): string {
105 let message = ""; 111 let message = "";
106 switch (httpStatus) { 112 switch (httpStatus) {
107 case HttpStatusCode.BadRequest: 113 case HttpStatusCode.BadRequest:
  1 +import ArrayList from '@ohos.util.ArrayList';
  2 +import service from './AxiosRequest';
  3 +import { HttpUtils } from '../utils/HttpUtils';
  4 +import { AxiosError, AxiosHeaders, AxiosRequestConfig, RawAxiosRequestHeaders } from '@ohos/axios';
  5 +import { ResponseDTO } from '../bean/ResponseDTO';
  6 +import HashMap from '@ohos.util.HashMap';
  7 +
  8 +export class HttpRequest {
  9 + private static globalHeaderProviders: ArrayList<() => Record<string, string>> = new ArrayList();
  10 +
  11 + static addGlobalHeaderProvider(provider: () => Record<string, string>) {
  12 + HttpRequest.globalHeaderProviders.add(provider)
  13 + }
  14 +
  15 + static initHttpHeader() {
  16 + HttpRequest.addGlobalHeaderProvider(() => {
  17 + return HttpUtils.buildHeaders();
  18 + })
  19 + }
  20 +
  21 + // 加入泛型限定,返回数据类型为T,
  22 + static request<T = ResponseDTO<string>>(config: AxiosRequestConfig): Promise<T> {
  23 + return new Promise<T>((resolve, reject) => {
  24 + service.request<ResponseDTO<string>, T>(config)
  25 + .then((res: T) => {
  26 + resolve(res)
  27 + })
  28 + .catch((err: AxiosError) => {
  29 + reject(err)
  30 + })
  31 + })
  32 + // return service.request<any, T>(config)
  33 + }
  34 +
  35 + static buildHeaderWithGlobalHeader(headers?: HashMap<string, string>): AxiosHeaders {
  36 + let commonHeader: AxiosHeaders = new AxiosHeaders()
  37 + headers?.forEach((v, k) => {
  38 + commonHeader.set(k, v);
  39 + });
  40 + HttpRequest.globalHeaderProviders.forEach((func) => {
  41 + let headers = func();
  42 + for (const obj of Object.entries(headers)) {
  43 + commonHeader.set(obj[0], obj[1]);
  44 + }
  45 + })
  46 + if (!commonHeader.get('Content-Type')) {
  47 + commonHeader.set('Content-Type', 'application/json;charset=utf-8');
  48 + }
  49 + return commonHeader
  50 + }
  51 +
  52 + static get<T = ResponseDTO<string>>(url: string, headers?: HashMap<string, string>): Promise<T> {
  53 + let config: AxiosRequestConfig = {
  54 + headers: HttpRequest.buildHeaderWithGlobalHeader(headers)
  55 + }
  56 + return service.get(url, config)
  57 + }
  58 +
  59 + static post<T = ResponseDTO<string>>(url: string, data?: object, headers?: HashMap<string, string>): Promise<T> {
  60 + let config: AxiosRequestConfig = {
  61 + headers: HttpRequest.buildHeaderWithGlobalHeader(headers)
  62 + }
  63 + return service.post(url, data, config)
  64 + }
  65 +
  66 + static put<T = ResponseDTO<string>>(url: string, data?: object, headers?: HashMap<string, string>): Promise<T> {
  67 + let config: AxiosRequestConfig = {
  68 + headers: HttpRequest.buildHeaderWithGlobalHeader(headers)
  69 + }
  70 + return service.put(url, data, config)
  71 + }
  72 +
  73 + static delete<T = ResponseDTO<string>>(url: string, headers?: HashMap<string, string>): Promise<T> {
  74 + let config: AxiosRequestConfig = {
  75 + headers: HttpRequest.buildHeaderWithGlobalHeader(headers)
  76 + }
  77 + return service.delete(url, config)
  78 + }
  79 +}
1 -import type { AxiosError, AxiosRequestConfig} from '@ohos/axios';  
2 -import service from './AxiosRequest';  
3 -  
4 -export default class HttpRequest {  
5 - // 加入泛型限定,返回数据类型为T,  
6 - static request<T = any>(config: AxiosRequestConfig): Promise<T> {  
7 - return new Promise<T>((resolve, reject) => {  
8 - service.request<any, T>(config)  
9 - .then((res:T) => {  
10 - resolve(res)  
11 - })  
12 - .catch((err:AxiosError) => {  
13 - reject(err)  
14 - })  
15 - })  
16 - // return service.request<any, T>(config)  
17 - }  
18 -  
19 - static get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {  
20 - return service.get(url, config)  
21 - }  
22 -  
23 - static delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {  
24 - return service.delete(url, config)  
25 - }  
26 -  
27 - static post<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> {  
28 - return service.post(url, data, config)  
29 - }  
30 -  
31 - static put<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> {  
32 - return service.put(url, data, config)  
33 - }  
34 -}  
  1 +import HashMap from '@ohos.util.HashMap'
  2 +import { ConfigConstants } from 'wdConstant'
  3 +import { DateTimeUtils, Logger } from 'wdKit'
  4 +
  5 +/**
  6 + * 网络请求业务侧工具类
  7 + */
  8 +export class HttpUrlUtils {
  9 + /**
  10 + * 现网地址
  11 + */
  12 + static readonly HOST: string = "https://pd-apis-uat.pdnews.cn";
  13 + /**
  14 + * 启动接口(底导接口)
  15 + */
  16 + static readonly BOTTOM_NAV_PATH: string = "/api/rmrb-bff-display-zh/display/zh/c/bottomNavGroup";
  17 + /**
  18 + * 展现comp接口
  19 + */
  20 + static readonly COMP_PATH: string = "/api/rmrb-bff-display-zh/display/zh/c/compInfo";
  21 +
  22 + static getCommonHeaders(): HashMap<string, string> {
  23 + let headers: HashMap<string, string> = new HashMap<string, string>()
  24 + headers.set('User-Agent', 'Dalvik/2.1.0 (Linux; U; Android 13; 22101317C Build/TKQ1.221013.002)')
  25 + headers.set('channel', HttpUrlUtils.getChannel())
  26 + headers.set('appCode', ConfigConstants.appCode)
  27 + headers.set('plat', HttpUrlUtils.getPlat())
  28 + headers.set('Authorization', 'APPCODE 83092caa603a421aa0222308b3f6b27a')
  29 + headers.set('Content-Type', 'application/json; charset=utf-8')
  30 + headers.set('timestamp', HttpUrlUtils.getTimestamp())
  31 + headers.set('RMRB-X-TOKEN', HttpUrlUtils.getXToken())
  32 + headers.set('device_id', HttpUrlUtils.getDeviceId())
  33 + headers.set('cookie', 'RMRB-X-TOKEN=eyJhbGciOiJIUzI1NiIsImtpZCI6ImQ4WkI2QkhxSEZrdjJ2U25BNlRwZEdKRjBHcjItVzBvS2FaYzdLOUUycmcifQ.eyJpc3MiOiJwZW9wbGVzLWRhaWx5LWZvdXJhIiwic3ViIjoicGVvcGxlcy1kYWlseS1mb3VyYSIsImV4cCI6MTcwMzY0OTYwNiwidXNlcklkIjo0NTk3NzYyOTc0NzQ5NDksInVzZXJWZXJzaW9uIjoiNDU5Nzc2Mjk3NDc0OTQ5XzIiLCJ1c2VyTmFtZSI6IkJ1bGlraWtpMTgxIiwidXNlclR5cGUiOjIsImNyZWF0b3JJZCI6NDI2NTM5MH0.jhQ9kylcm3FxWf0-lBMZuLkdtIQ6XpFnAi0AFZJNwfc')
  34 + headers.set('build_version', HttpUrlUtils.getVersion())
  35 + headers.set('adcode', HttpUrlUtils.getAdCode())
  36 + headers.set('os_version', HttpUrlUtils.getOsVersion())
  37 + headers.set('X-Ca-Stage', 'PRE')
  38 + headers.set('versionCode', HttpUrlUtils.getVersionCode())
  39 + headers.set('system', HttpUrlUtils.getTerminalId())
  40 + headers.set('version_name', 'debug')
  41 + headers.set('EagleEye-TraceID', '0B6DE03D2997435BA875FFBE05425ED2')
  42 + headers.set('imei', HttpUrlUtils.getImei())
  43 + headers.set('Accept-Language', 'zh')
  44 + headers.set('city', HttpUrlUtils.getCity())
  45 + headers.set('city_dode', HttpUrlUtils.getCityCode())
  46 + // TODO 判断是否登录
  47 + headers.set('userId', HttpUrlUtils.getUserId())
  48 + headers.set('userType', HttpUrlUtils.getUserType())
  49 +
  50 + // Logger.debug("TAG", '******************* commonHeaders headers start ******************************** ');
  51 + // headers.forEach((v,k)=>{
  52 + // Logger.debug("TAG", 'getCommonHeaders header: ' + k + ': ' + v);
  53 + // })
  54 + // Logger.debug("TAG", '******************* commonHeaders headers end ******************************** ');
  55 + return headers;
  56 + }
  57 +
  58 +
  59 + private static getCity() {
  60 + // TODO 对接定位
  61 + return '%E5%90%88%E8%82%A5%E5%B8%82';
  62 + }
  63 +
  64 + private static getChannel() {
  65 + // TODO 对接配置
  66 + return 'rmrb_china_0000';
  67 + }
  68 +
  69 + private static getPlat() {
  70 + return 'Phone';
  71 + }
  72 +
  73 + private static getTimestamp() {
  74 + // return DateTimeUtils.getCurrentTime() + '';
  75 + // TODO 暂时写死,有些page 真实时间戳 返回数据为空
  76 + return '155203523';
  77 + }
  78 +
  79 + private static getXToken() {
  80 + return 'eyJhbGciOiJIUzI1NiIsImtpZCI6ImQ4WkI2QkhxSEZrdjJ2U25BNlRwZEdKRjBHcjItVzBvS2FaYzdLOUUycmcifQ.eyJpc3MiOiJwZW9wbGVzLWRhaWx5LWZvdXJhIiwic3ViIjoicGVvcGxlcy1kYWlseS1mb3VyYSIsImV4cCI6MTcwMzY0OTYwNiwidXNlcklkIjo0NTk3NzYyOTc0NzQ5NDksInVzZXJWZXJzaW9uIjoiNDU5Nzc2Mjk3NDc0OTQ5XzIiLCJ1c2VyTmFtZSI6IkJ1bGlraWtpMTgxIiwidXNlclR5cGUiOjIsImNyZWF0b3JJZCI6NDI2NTM5MH0.jhQ9kylcm3FxWf0-lBMZuLkdtIQ6XpFnAi0AFZJNwfc';
  81 + }
  82 +
  83 + private static getDeviceId() {
  84 + // TODO
  85 + return 'b5cf725d-193d-3215-8c77-e76fe15ce64d';
  86 + }
  87 +
  88 + private static getVersion() {
  89 + // TODO
  90 + return '202312251034';
  91 + }
  92 +
  93 + private static getVersionCode() {
  94 + // TODO
  95 + return '7301';
  96 + }
  97 +
  98 + private static getAdCode() {
  99 + return '340000';
  100 + }
  101 +
  102 + private static getOsVersion() {
  103 + // TODO
  104 + return '13';
  105 + }
  106 +
  107 + public static getCityCode() {
  108 + // TODO
  109 + return '340100';
  110 + }
  111 +
  112 + public static getProvinceCode() {
  113 + // TODO
  114 + return '340000';
  115 + }
  116 +
  117 + /**
  118 + * 地区code
  119 + */
  120 + public static getDistrictCode() {
  121 + // TODO
  122 + return '340103';
  123 + }
  124 +
  125 + private static getTerminalId() {
  126 + return 'Android';
  127 + }
  128 +
  129 + private static getImei() {
  130 + // TODO
  131 + return 'b5cf725d-193d-3215-8c77-e76fe15ce64d';
  132 + }
  133 +
  134 + private static getUserId() {
  135 + // TODO 对接登录
  136 + return '459776297474949';
  137 + }
  138 +
  139 + private static getUserType() {
  140 + return '2';
  141 + }
  142 +}
1 -import http from '@ohos.net.http';  
2 -import { BusinessError } from '@ohos.base';  
3 -import ArrayList from '@ohos.util.ArrayList';  
4 -import { Logger } from 'wdKit';  
5 -import { HttpUtils } from '../utils/HttpUtils';  
6 -  
7 -const TAG = 'WDHttp';  
8 -  
9 -export namespace WDHttp {  
10 -  
11 - export enum RequestMethod {  
12 - OPTIONS = http.RequestMethod.OPTIONS,  
13 - GET = http.RequestMethod.GET,  
14 - HEAD = http.RequestMethod.HEAD,  
15 - POST = http.RequestMethod.POST,  
16 - PUT = http.RequestMethod.PUT,  
17 - DELETE = http.RequestMethod.DELETE,  
18 - TRACE = http.RequestMethod.TRACE,  
19 - CONNECT = http.RequestMethod.CONNECT,  
20 - }  
21 -  
22 - export enum HttpParamsType {  
23 - STRING,  
24 - OBJECT,  
25 - ARRAY_BUFFER  
26 - }  
27 -  
28 - export interface RequestOptions {  
29 - // 请求方法  
30 - method?: RequestMethod;  
31 -  
32 - // 请求头  
33 - header?: object;  
34 -  
35 - // 读超时时间 单位s 默认60  
36 - readTimeout?: number;  
37 -  
38 - // 连接超时时间 单位s 默认60  
39 - connectTimeout?: number;  
40 -  
41 - // 请求参数 当请求为get请求时 该参数会自动拼接在url后面  
42 - params?: object;  
43 -  
44 - // 请求参数类型 当请求为post时有效  
45 - paramsType?: HttpParamsType;  
46 - }  
47 -  
48 - export const enum ErrorCode {  
49 - // 请求执行(查询)失败  
50 - FAILED = -1,  
51 - // 请求执行(查询)成功  
52 - SUCCESS = http.ResponseCode.OK,  
53 - // 业务错误码。。。  
54 - }  
55 -  
56 - /**  
57 - * ResponseDTO  
58 - * 微服务通用返回结构  
59 - * http://confluence.cmvideo.cn/confluence/pages/viewpage.action?pageId=4232418  
60 - */  
61 - export interface ResponseDTO<T = string> {  
62 - // 服务请求响应值/微服务响应状态码”  
63 - code: number;  
64 -  
65 - // 服务请求响应说明  
66 - message: string;  
67 -  
68 - // 响应结果  
69 - body?: T;  
70 - data?: T;  
71 -  
72 - // 请求响应时间戳(unix格式)  
73 - timeStamp?: number;  
74 -  
75 - // timestamp?: number;  
76 -  
77 - // 返回当前时间戳,格式:yyyyMMddHHmmss,如20230918102124  
78 - dataVersion?: string;  
79 - }  
80 -  
81 - /**  
82 - * ResponseVO  
83 - * 基础服务通用返回结构  
84 - * 如PUGC错误码:http://confluence.cmvideo.cn/confluence/pages/viewpage.action?pageId=168081524  
85 - */  
86 - export interface ResponseVO<T = string> {  
87 - // 返回代码,参考附录ResultCode 即(ACCEPTED/SUCCESS/FAILED/REJECTED等)  
88 - resultCode: string;  
89 -  
90 - // 返回描述  
91 - resultDesc: string;  
92 -  
93 - // 错误码,参考附录和接口中ErrorCode(当resultCode=FAILED才有),如:"ERR_USER_NOTFOUND"  
94 - errorCode?: string;  
95 -  
96 - // 业务数据  
97 - data?: T;  
98 - }  
99 -  
100 - /**  
101 - * The Response ResultCode enum.  
102 - */  
103 - export const enum ResultCode {  
104 - // 请求执行(查询)成功  
105 - SUCCESS = 'SUCCESS',  
106 - // 请求执行(查询)失败  
107 - FAILED = 'FAILED',  
108 - // 该请求被拒绝处理,例如参数错误或非法等  
109 - REJECTED = 'REJECTED',  
110 - // 该请求已经被接收,但是本次同步返回无法知道执行结果  
111 - ACCEPTED = 'ACCEPTED',  
112 - // 参数错误  
113 - // ERR_NOT_VALID_PARAMETERS = 'ERR_NOT_VALID_PARAMETERS'  
114 - }  
115 -  
116 - export class Request {  
117 - private static globalHeaderProviders: ArrayList<() => Record<string, string>> = new ArrayList();  
118 -  
119 - static addGlobalHeaderProvider(provider: () => Record<string, string>) {  
120 - Request.globalHeaderProviders.add(provider)  
121 - }  
122 -  
123 - static initHttpHeader() {  
124 - Request.addGlobalHeaderProvider(() => {  
125 - return HttpUtils.buildHeaders();  
126 - })  
127 - }  
128 -  
129 - private static makeRequestOptions(options?: RequestOptions): http.HttpRequestOptions {  
130 - if (options) {  
131 - let op: http.HttpRequestOptions = {};  
132 - op.method = options.method!.toString() as http.RequestMethod;  
133 - op.header = options.header  
134 - op.readTimeout = (options.readTimeout ?? 60) * 1000  
135 - op.connectTimeout = (options.connectTimeout ?? 60) * 1000  
136 - if (options.method == RequestMethod.POST) {  
137 - op.extraData = options.params;  
138 - if (options.paramsType == HttpParamsType.STRING) {  
139 - op.expectDataType = http.HttpDataType.STRING;  
140 - } else if (options.paramsType == HttpParamsType.OBJECT) {  
141 - op.expectDataType = http.HttpDataType.OBJECT;  
142 - } else if (options.paramsType == HttpParamsType.ARRAY_BUFFER) {  
143 - op.expectDataType = http.HttpDataType.ARRAY_BUFFER;  
144 - }  
145 - } else if (options.method == RequestMethod.PUT) {  
146 - // todo  
147 - } else if (options.method == RequestMethod.DELETE) {  
148 - // todo  
149 - }  
150 - return op;  
151 - }  
152 - return {}  
153 - }  
154 -  
155 - private static makeUrl(url: string, options?: RequestOptions): string {  
156 - if (!options || (options.method && options.method != RequestMethod.GET)) {  
157 - return url;  
158 - }  
159 - if (!options.params) {  
160 - return url;  
161 - }  
162 - let paramStr = "";  
163 - if (typeof options.params == "string") {  
164 - paramStr = options.params;  
165 - } else if (typeof options.params == "object") {  
166 - let arr: string[] = [];  
167 - Object.entries(options.params).forEach((entry: object) => {  
168 - arr.push(`${entry[0]}=${entry[1]}`)  
169 - })  
170 - if (arr.length == 0) {  
171 - return url;  
172 - }  
173 - paramStr = arr.join("&")  
174 - }  
175 - if (url.indexOf("?") == -1) {  
176 - return url + "?" + paramStr;  
177 - } else {  
178 - if (url.endsWith("?")) {  
179 - return url + paramStr;  
180 - } else {  
181 - return url + "&" + paramStr;  
182 - }  
183 - }  
184 - }  
185 -  
186 - // 加入泛型限定,返回数据类型为T,  
187 - // static request<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {  
188 - // let httpRequest = http.createHttp();  
189 - // if (!options) {  
190 - // options = {};  
191 - // }  
192 - // if (!options.method) {  
193 - // options.method = RequestMethod.GET;  
194 - // }  
195 - // if (!options.header) {  
196 - // let header: Record<string, string> = {  
197 - // // 'Content-Type': 'text/plain'  
198 - // 'Content-Type': 'application/json;charset=utf-8'  
199 - // };  
200 - // options.header = header  
201 - // } else if (!options.header['Content-Type']) {  
202 - // options.header['Content-Type'] = 'application/json;charset=utf-8';  
203 - // }  
204 - //  
205 - // Request.globalHeaders.forEach((value, key) => {  
206 - // options!.header![key] = value;  
207 - // })  
208 - // let realUrl = Request.makeUrl(url, options);  
209 - // httpRequest.request(realUrl, Request.makeRequestOptions(options), (error, responseData: http.HttpResponse) => {  
210 - // if (callback) {  
211 - // if (error) {  
212 - // callback(error, undefined)  
213 - // } else {  
214 - // try {  
215 - // let response: ResponseDTO<T> = JSON.parse(`${responseData.result}`)  
216 - // callback(error, response)  
217 - // } catch (err) {  
218 - // callback(error, { code: responseData?.responseCode, message: responseData?.result?.toString() })  
219 - // }  
220 - // }  
221 - // }  
222 - // })  
223 - // }  
224 - //  
225 - // static get<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {  
226 - // let op = options ?? {}  
227 - // op.method = RequestMethod.GET;  
228 - // Request.request<T>(url, op, callback)  
229 - // }  
230 - //  
231 - // static post<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {  
232 - // let op = options ?? {}  
233 - // op.method = RequestMethod.POST;  
234 - // Request.request<T>(url, op, callback)  
235 - // }  
236 - //  
237 - // static put<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {  
238 - // let op = options ?? {}  
239 - // op.method = RequestMethod.PUT;  
240 - // Request.request<T>(url, op, callback)  
241 - // }  
242 - //  
243 - // static delete<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {  
244 - // let op = options ?? {}  
245 - // op.method = RequestMethod.DELETE;  
246 - // Request.request<T>(url, op, callback)  
247 - // }  
248 - ////  
249 - static request<T = string>(url: string, options?: RequestOptions): Promise<T> {  
250 - let httpRequest = http.createHttp();  
251 - if (!options) {  
252 - options = {};  
253 - }  
254 - if (!options.method) {  
255 - options.method = RequestMethod.GET;  
256 - }  
257 - if (!options.header) {  
258 - let header: Record<string, string> = {  
259 - // 'Content-Type': 'text/plain'  
260 - 'Content-Type': 'application/json;charset=utf-8'  
261 - };  
262 - options.header = header  
263 - } else if (!options.header['Content-Type']) {  
264 - options.header['Content-Type'] = 'application/json;charset=utf-8';  
265 - }  
266 - let commonHeader: Record<string, string | number> = {};  
267 - Request.globalHeaderProviders.forEach((func) => {  
268 - let headers = func();  
269 - for (const obj of Object.entries(headers)) {  
270 - commonHeader[obj[0]] = obj[1];  
271 - }  
272 - })  
273 - let userHeader = options.header as Record<string, string | number>  
274 - for (const obj1 of Object.entries(userHeader)) {  
275 - commonHeader[obj1[0]] = obj1[1];  
276 - }  
277 - options.header = commonHeader  
278 - let realUrl = Request.makeUrl(url, options);  
279 - Logger.info(TAG, `request realUrl: ${realUrl}`);  
280 - Logger.info(TAG, `header: ${realUrl}`);  
281 - return new Promise<T>((resolve, reject) => {  
282 - httpRequest.request(realUrl, Request.makeRequestOptions(options))  
283 - .then((responseData: http.HttpResponse) => {  
284 - try {  
285 - if (responseData.responseCode == http.ResponseCode.OK) {  
286 - // todo:待处理JSON.parse只解析目标class中指定的字段  
287 - // let response = JSON.parse(`${data}`) as ResponseDTO<T>  
288 - let response: T = JSON.parse(`${responseData.result}`)  
289 - resolve(response)  
290 - } else {  
291 - // 返回码不是ok  
292 - let responseError: BusinessError = {  
293 - code: responseData?.responseCode,  
294 - message: responseData?.result?.toString(),  
295 - name: '业务错误',  
296 - }  
297 - reject(responseError)  
298 - }  
299 - } catch (err) {  
300 - // json解析异常  
301 - let responseParseError: BusinessError = {  
302 - code: responseData?.responseCode,  
303 - message: responseData?.result?.toString(),  
304 - name: '解析异常',  
305 - }  
306 - reject(responseParseError)  
307 - }  
308 - })  
309 - .catch((error: BusinessError) => {  
310 - reject(error)  
311 - })  
312 - })  
313 - }  
314 -  
315 - static get<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {  
316 - let op = options ?? {}  
317 - op.method = RequestMethod.GET;  
318 - return Request.request<T>(url, op)  
319 - }  
320 -  
321 - static post<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {  
322 - let op = options ?? {}  
323 - op.method = RequestMethod.POST;  
324 - return Request.request<T>(url, op)  
325 - }  
326 -  
327 - static put<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {  
328 - let op = options ?? {}  
329 - op.method = RequestMethod.PUT;  
330 - return Request.request<T>(url, op)  
331 - }  
332 -  
333 - static delete<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {  
334 - let op = options ?? {}  
335 - op.method = RequestMethod.DELETE;  
336 - return Request.request<T>(url, op)  
337 - }  
338 - }  
339 -}  
  1 +// import { ResponseLogin } from '../bean/account/ResponseLogin';
  2 +import { Logger } from 'wdKit';
  3 +
  4 +// import { UserInfo } from '../bean/account/UserInfo';
  5 +// import { ConfigConstants } from '../constants/ConfigConstants';
  6 +// import { AccountManagerUtils } from './AccountManagerUtils';
  7 +// import { AppUtils } from './AppUtils';
  8 +// import { DeviceUtil } from './DeviceUtil';
  9 +// import { Logger } from './Logger';
  10 +// import { StringUtils } from './StringUtils';
  11 +
1 const TAG: string = '[HttpUtils]' 12 const TAG: string = '[HttpUtils]'
2 13
3 export class HttpUtils { 14 export class HttpUtils {
4 static buildHeaders(): Record<string, string> { 15 static buildHeaders(): Record<string, string> {
5 let timestamp: number = new Date().getTime(); // 单位毫秒 16 let timestamp: number = new Date().getTime(); // 单位毫秒
  17 + // let clientId = DeviceUtil.clientId()
6 18
7 let headers: Record<string, string> = {}; 19 let headers: Record<string, string> = {};
8 // 通用请求头 20 // 通用请求头
  21 + headers["version"] = 'V3';
  22 + // headers["appId"] = ConfigConstants.appId; // 应用id
  23 + // headers["terminalId"] = ConfigConstants.terminalId; // 终端ID
  24 + // headers["sourceId"] = ConfigConstants.sourceId; // 咪咕视频
  25 + // headers["appType"] = ConfigConstants.appType; // 手机客户端App(安卓)
  26 + // headers["clientType"] = ConfigConstants.clientType; // 客户端类型
  27 + // headers["appVersion"] = AppUtils.getAppVersionCode() + ''; // 客户端版本号:2600010500
  28 + // headers["APP-VERSION-CODE"] = AppUtils.getAppVersionCode() + ''; // APP版本号:250006577
  29 + // headers["appVersionName"] = AppUtils.getAppVersionName() // app对外显示版本: '6.1.5.00'
  30 + // headers["appCode"] = ConfigConstants.appCode; // 应用编码:产品_渠道_应用的拼接串,用下划线_ 拼接而成
  31 + // headers["ptvCode"] = ConfigConstants.ptvCode; // 基线版本号_应用版本号 todo:
  32 + // headers["clientProvinceCode"] = ''; // 客户端分省号 // 02
  33 + // headers["provinceCode"] = ''; // 客户端分省号 // 02
  34 + // headers["clientCityId"] = ''; // 客户端城市ID // 0210
  35 + // headers["carrierCode"] = ''; // 运营商信息
9 36
10 // 设备信息请求头 37 // 设备信息请求头
11 // headers["User-Agent"] = ''; // 终端UA,自动获取 38 // headers["User-Agent"] = ''; // 终端UA,自动获取
12 headers["Content-Type"] = 'application/json;charset=UTF-8'; // 返回/响应的HTTP内容类型 39 headers["Content-Type"] = 'application/json;charset=UTF-8'; // 返回/响应的HTTP内容类型
13 - headers["os"] = 'harmony'; // 操作系统类型:鸿蒙、安卓或iOS  
14 -  
15 - // 用户信息/登录信息请求头:登录完成之后二级接口返回,带入头信息;未登录情况下,头信息不传这些字段 40 + headers["os"] = 'android'; // 操作系统类型:鸿蒙、安卓或iOS
  41 + // headers["osInfo"] = 'AD'; // 操作系统信息
  42 + headers["Phone-Info"] = 'HUAWEI'; // 手机信息: todo
  43 + // headers["oaid"] = ''; // 开放匿名设备ID,是中国移动安全联盟(MSA)发起并制定标准用户识别ID
  44 + headers["networkInfo"] = 'WIFI'; // 网络类型: todo
  45 + headers["cache-control"] = 'no-cache'; // 请求和响应遵循的缓存机制
  46 + // headers["clientId"] = clientId; // 客户端编号:客户端初始化时生成的客户端ID,保证唯一性
  47 + headers["imei"] = 'd1de6d3ae0db44bea1b3f0e20a14d90a'; // 终端手机序列号: todo
  48 + headers["X-UP-CLIENT-CHANNEL-ID"] = '2600010500-99000-101700010130012'; // 客户端渠道ID: todo
  49 + headers["channelCode"] = 'VIDEO_APPMAIL'; // 渠道编码
  50 + // headers["l_c"] = clientId; // 客户端id,同clientId
  51 + // headers["l_t"] = timestamp + ''; // 本机时间戳
  52 + // headers["l_s"] = ''; // l_c和l_t拼接后的MD5校验
16 53
17 // 签名相关请求头 54 // 签名相关请求头
18 headers["timeStamp"] = timestamp + ''; // 服务端时间戳(毫秒):1701667763664 55 headers["timeStamp"] = timestamp + ''; // 服务端时间戳(毫秒):1701667763664
19 headers["signType"] = 'RSA'; // 签名类型,固定RSA 56 headers["signType"] = 'RSA'; // 签名类型,固定RSA
20 57
21 // 业务请求头 58 // 业务请求头
  59 + // headers["promotionID"] = '54b0f421-a6df-41d3-9be2-92820b2c5d8c'; // 促销Id todo
  60 + // headers["tenantId"] = ''; // 租户Id
22 61
23 // 添加其他header 62 // 添加其他header
24 -  
25 - // Logger.info(TAG, "buildHeader headers:" + JSON.stringify(headers)); 63 + // headers["sdkCeId"] = '27fb3129-5a54-45bc-8af1-7dc8f1155501'; // 用户中台老接口定义的ID,保持不变,现网:咪咕视频Android版,27fb3129-5a54-45bc-8af1-7dc8f1155501 todo
  64 + headers["support-pendant"] = '1'; // 挂件标识, "1":客户端支持挂件节目结构;非"1":不支持挂件节目结构-展示通用对象
  65 + Logger.info(TAG, "buildHeader headers:" + JSON.stringify(headers));
26 return headers; 66 return headers;
27 } 67 }
28 } 68 }