guochunsong
@@ -35,7 +35,11 @@ export class HttpUrlUtils { @@ -35,7 +35,11 @@ export class HttpUrlUtils {
35 * 详情页面详情接口 35 * 详情页面详情接口
36 */ 36 */
37 static readonly DETAIL_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail"; 37 static readonly DETAIL_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail";
38 - private static hostUrl: string = HttpUrlUtils.HOST_PRODUCT; 38 + /**
  39 + * 批查接口,查询互动相关数据,如收藏数、评论数等
  40 + */
  41 + static readonly INTERACT_DATA_PATH: string = "/api/rmrb-contact/contact/zh/c/content/interactData";
  42 + private static hostUrl: string = HttpUrlUtils.HOST_UAT;
39 43
40 static getCommonHeaders(): HashMap<string, string> { 44 static getCommonHeaders(): HashMap<string, string> {
41 let headers: HashMap<string, string> = new HashMap<string, string>() 45 let headers: HashMap<string, string> = new HashMap<string, string>()
@@ -52,12 +56,15 @@ export class HttpUrlUtils { @@ -52,12 +56,15 @@ export class HttpUrlUtils {
52 headers.set('os_version', this.getOsVersion()) 56 headers.set('os_version', this.getOsVersion())
53 headers.set('versionCode', this.getVersionCode()) 57 headers.set('versionCode', this.getVersionCode())
54 headers.set('system', this.getTerminalId()) 58 headers.set('system', this.getTerminalId())
55 - headers.set('version_name', 'debug')  
56 - headers.set('EagleEye-TraceID', '0B6DE03D2997435BA875FFBE05425ED2') 59 + headers.set('version_name', this.getVersionName())
  60 + headers.set('EagleEye-TraceID', 'D539562E48554A60977AF4BECB6D6C7A')
57 headers.set('imei', this.getImei()) 61 headers.set('imei', this.getImei())
58 headers.set('Accept-Language', 'zh') 62 headers.set('Accept-Language', 'zh')
59 headers.set('city', this.getCity()) 63 headers.set('city', this.getCity())
60 headers.set('city_dode', this.getCityCode()) 64 headers.set('city_dode', this.getCityCode())
  65 +
  66 + headers.set('mpassid', 'ZbHTMeTsfaYDAHqt8ZHIzcPs')
  67 +
61 // TODO 判断是否登录 68 // TODO 判断是否登录
62 headers.set('userId', this.getUserId()) 69 headers.set('userId', this.getUserId())
63 headers.set('userType', this.getUserType()) 70 headers.set('userType', this.getUserType())
@@ -107,6 +114,11 @@ export class HttpUrlUtils { @@ -107,6 +114,11 @@ export class HttpUrlUtils {
107 return url; 114 return url;
108 } 115 }
109 116
  117 + static getInteractDataUrl() {
  118 + let url = this.hostUrl + this.INTERACT_DATA_PATH;
  119 + return url;
  120 + }
  121 +
110 static addSpecialHeaders(headers: HashMap<string, string>) { 122 static addSpecialHeaders(headers: HashMap<string, string>) {
111 switch (this.hostUrl) { 123 switch (this.hostUrl) {
112 case this.HOST_UAT: 124 case this.HOST_UAT:
@@ -161,12 +173,12 @@ export class HttpUrlUtils { @@ -161,12 +173,12 @@ export class HttpUrlUtils {
161 173
162 private static getDeviceId() { 174 private static getDeviceId() {
163 // TODO 175 // TODO
164 - return 'b5cf725d-193d-3215-8c77-e76fe15ce64d'; 176 + return '8a81226a-cabd-3e1b-b630-b51db4a720ed';
165 } 177 }
166 178
167 private static getVersion() { 179 private static getVersion() {
168 // TODO 180 // TODO
169 - return '202312251034'; 181 + return '202401242103';
170 } 182 }
171 183
172 private static getVersionCode() { 184 private static getVersionCode() {
@@ -174,13 +186,18 @@ export class HttpUrlUtils { @@ -174,13 +186,18 @@ export class HttpUrlUtils {
174 return '7301'; 186 return '7301';
175 } 187 }
176 188
  189 + private static getVersionName() {
  190 + // TODO
  191 + return '7.3.0.1';
  192 + }
  193 +
177 private static getAdCode() { 194 private static getAdCode() {
178 return '340000'; 195 return '340000';
179 } 196 }
180 197
181 private static getOsVersion() { 198 private static getOsVersion() {
182 // TODO 199 // TODO
183 - return '13'; 200 + return '12';
184 } 201 }
185 202
186 private static getCityCode() { 203 private static getCityCode() {
@@ -207,7 +224,7 @@ export class HttpUrlUtils { @@ -207,7 +224,7 @@ export class HttpUrlUtils {
207 224
208 private static getImei() { 225 private static getImei() {
209 // TODO 226 // TODO
210 - return 'b5cf725d-193d-3215-8c77-e76fe15ce64d'; 227 + return '8a81226a-cabd-3e1b-b630-b51db4a720ed';
211 } 228 }
212 229
213 private static getUserId() { 230 private static getUserId() {
@@ -3,6 +3,7 @@ import { NavigationBodyDTO } from './bean/NavigationBodyDTO'; @@ -3,6 +3,7 @@ import { NavigationBodyDTO } from './bean/NavigationBodyDTO';
3 import { PageDTO } from './bean/PageDTO'; 3 import { PageDTO } from './bean/PageDTO';
4 import HashMap from '@ohos.util.HashMap'; 4 import HashMap from '@ohos.util.HashMap';
5 import { HttpUrlUtils } from '../network/HttpUrlUtils'; 5 import { HttpUrlUtils } from '../network/HttpUrlUtils';
  6 +import { InteractDataDTO } from './bean/InteractDataDTO';
6 7
7 export class PageRepository { 8 export class PageRepository {
8 static fetchNavigationDataApi() { 9 static fetchNavigationDataApi() {
@@ -23,4 +24,10 @@ export class PageRepository { @@ -23,4 +24,10 @@ export class PageRepository {
23 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); 24 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
24 return WDHttp.get<ResponseDTO<string>>(url, headers) 25 return WDHttp.get<ResponseDTO<string>>(url, headers)
25 }; 26 };
  27 +
  28 + static fetchInteractData(param: object) {
  29 + let url = HttpUrlUtils.getInteractDataUrl()
  30 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  31 + return WDHttp.post<ResponseDTO<InteractDataDTO[]>>(url, param, headers)
  32 + };
26 } 33 }
1 import { FullColumnImgUrlsDTO } from './FullColumnImgUrlsDTO'; 1 import { FullColumnImgUrlsDTO } from './FullColumnImgUrlsDTO';
  2 +import { InteractDataDTO } from './InteractDataDTO';
2 import { LiveInfo } from './LiveInfo' 3 import { LiveInfo } from './LiveInfo'
3 import { VideoInfo } from './VideoInfo' 4 import { VideoInfo } from './VideoInfo'
4 5
@@ -49,4 +50,6 @@ export interface ContentDTO { @@ -49,4 +50,6 @@ export interface ContentDTO {
49 liveInfo?: LiveInfo; // 直播新闻信息【BFF聚合】 50 liveInfo?: LiveInfo; // 直播新闻信息【BFF聚合】
50 videoInfo?: VideoInfo; // 视频新闻信息【BFF聚合】,视频非原片+清晰度最高的 51 videoInfo?: VideoInfo; // 视频新闻信息【BFF聚合】,视频非原片+清晰度最高的
51 corner:string; 52 corner:string;
  53 + // 二次请求接口,返回的数据,这里组装到content里;TODO 后续优化
  54 + interactData:InteractDataDTO;
52 } 55 }
  1 +/**
  2 + * 批查接口查询互动相关数据,返回数据bean
  3 + */
  4 +export interface InteractDataDTO {
  5 + collectNum: number;
  6 + commentNum: number;
  7 + contentId: string;
  8 + contentType: number;
  9 + likeNum: number;
  10 + readNum: number;
  11 + shareNum: number;
  12 +}
  1 +/**
  2 + * 批查接口查询互动相关数据,返回数据bean
  3 + */
  4 +export interface InteractParam {
  5 + contentList: Array<ContentBean>;
  6 + // 默认0;是否详情页访问;默认0:非详情;1:详情页(只有访问详情页时(detail=1),才触发浏览量加1)
  7 + detail: string;
  8 +}
  9 +
  10 +export interface ContentBean {
  11 + contentId: string;
  12 + contentType: string;
  13 +}
@@ -13,12 +13,12 @@ export class RefreshConstants { @@ -13,12 +13,12 @@ export class RefreshConstants {
13 /** 13 /**
14 * The delay time. 14 * The delay time.
15 */ 15 */
16 - static readonly DELAY_TIME: number = 1000; 16 + static readonly DELAY_TIME: number = 200;
17 17
18 /** 18 /**
19 * The animation duration. 19 * The animation duration.
20 */ 20 */
21 - static readonly ANIMATION_DURATION: number = 2000; 21 + static readonly ANIMATION_DURATION: number = 200;
22 /** 22 /**
23 * The RefreshConstant constants. 23 * The RefreshConstant constants.
24 */ 24 */
1 -import { Logger, ResourcesUtils } from 'wdKit'; 1 +import { CollectionUtils, Logger, ResourcesUtils, StringUtils } from 'wdKit';
2 import { ResponseDTO, } from 'wdNetwork'; 2 import { ResponseDTO, } from 'wdNetwork';
3 import { PageRepository } from '../repository/PageRepository'; 3 import { PageRepository } from '../repository/PageRepository';
4 import { NavigationBodyDTO } from '../repository/bean/NavigationBodyDTO'; 4 import { NavigationBodyDTO } from '../repository/bean/NavigationBodyDTO';
5 import { PageDTO } from '../repository/bean/PageDTO'; 5 import { PageDTO } from '../repository/bean/PageDTO';
6 import { BaseViewModel } from './BaseViewModel'; 6 import { BaseViewModel } from './BaseViewModel';
  7 +import { InteractDataDTO } from '../repository/bean/InteractDataDTO';
  8 +import { ContentBean, InteractParam } from '../repository/bean/InteractParam';
  9 +import { CompDTO } from '../repository/bean/CompDTO';
7 10
8 const TAG = 'PageViewModel'; 11 const TAG = 'PageViewModel';
9 /** 12 /**
@@ -11,6 +14,11 @@ const TAG = 'PageViewModel'; @@ -11,6 +14,11 @@ const TAG = 'PageViewModel';
11 * mock数据是本地json数据,可自行修改内容(‘entry\src\main\resources\rawfile\’目录) 14 * mock数据是本地json数据,可自行修改内容(‘entry\src\main\resources\rawfile\’目录)
12 */ 15 */
13 const mock_switch = false; 16 const mock_switch = false;
  17 +/**
  18 + * 互动数据获取开关开关,默认开。
  19 + * TODO 后续需要优化掉,变为二次请求异步刷新
  20 + */
  21 +const interact_sync_switch = true;
14 22
15 /** 23 /**
16 * 处理返回后的数据 24 * 处理返回后的数据
@@ -112,14 +120,141 @@ export class PageViewModel extends BaseViewModel { @@ -112,14 +120,141 @@ export class PageViewModel extends BaseViewModel {
112 return 120 return
113 } 121 }
114 Logger.info(TAG, "getPageData then,resDTO.timeStamp:" + resDTO.timestamp); 122 Logger.info(TAG, "getPageData then,resDTO.timeStamp:" + resDTO.timestamp);
  123 + if (!interact_sync_switch) {
  124 + success(resDTO.data);
  125 + return;
  126 + }
  127 + // TODO 打开同步请求互动数据,待优化为异步加载
  128 + if (CollectionUtils.isEmpty(resDTO.data.compList)) {
  129 + success(resDTO.data);
  130 + } else {
  131 + this.getInteractData(resDTO.data.compList).then(() => {
115 success(resDTO.data); 132 success(resDTO.data);
116 }) 133 })
  134 + }
  135 + })
117 .catch((err: Error) => { 136 .catch((err: Error) => {
118 Logger.error(TAG, `getPageData catch, error.name : ${err.name}, error.message:${err.message}`); 137 Logger.error(TAG, `getPageData catch, error.name : ${err.name}, error.message:${err.message}`);
119 error(err); 138 error(err);
120 }) 139 })
121 }) 140 })
122 } 141 }
  142 +
  143 + async getInteractData(compList: CompDTO[]) {
  144 + let param: InteractParam = this.getInteractParams(compList);
  145 + const SIZE = 20;
  146 + // 批查接口,参数size限制20,这里截断分批查询,0,20;20,40...
  147 + let count = Math.ceil(param.contentList.length / SIZE);
  148 + let promises = new Array;
  149 + if (count == 1) {
  150 + let promise: Promise<InteractDataDTO[]> = this.createInteractDataPromise(param);
  151 + promises.push(promise);
  152 + } else {
  153 + for (let i = 1;i <= count; i++) {
  154 + // 将查询参数截断(参数限制20个),分批请求接口
  155 + let subList = new Array<ContentBean>();
  156 + let start = 0;
  157 + let end = 0;
  158 + if (i == count) {
  159 + start = (i - 1) * SIZE;
  160 + end = param.contentList.length;
  161 + subList = CollectionUtils.getSubElements(param.contentList, start, end)
  162 + } else {
  163 + start = (i - 1) * SIZE;
  164 + end = start + SIZE;
  165 + subList = CollectionUtils.getSubElements(param.contentList, start, end)
  166 + }
  167 + let subParam: InteractParam = {} as InteractParam;
  168 + subParam.contentList = subList;
  169 + let promise: Promise<InteractDataDTO[]> = this.createInteractDataPromise(subParam);
  170 + promises.push(promise);
  171 + }
  172 + }
  173 +
  174 + return new Promise<CompDTO[]>((success, error) => {
  175 + Promise.all(promises).then((result) => {
  176 + if (!CollectionUtils.isArray(result)) {
  177 + success(compList);
  178 + return;
  179 + }
  180 +
  181 + let allInteractDataList = new Array();
  182 + result.forEach((value: InteractDataDTO[]) => {
  183 + if (value != null && value.length > 0) {
  184 + allInteractDataList.push(...value);
  185 + }
  186 + })
  187 + // 批查全部完成,统一设置到comp里
  188 + this.resetInteract(allInteractDataList, compList);
  189 + success(compList);
  190 + })
  191 + })
  192 + }
  193 +
  194 + private createInteractDataPromise(param: InteractParam) {
  195 + return new Promise<InteractDataDTO[]>((success, error) => {
  196 + PageRepository.fetchInteractData(param).then((resDTO: ResponseDTO<InteractDataDTO[]>) => {
  197 + if (this.isRespondsInvalid(resDTO, 'getInteractData')) {
  198 + Logger.info(TAG, "getInteractData then,resDTO.timeStamp:" + resDTO.timestamp);
  199 + success(null);
  200 + return;
  201 + }
  202 + success(resDTO.data);
  203 + }).catch((err: Error) => {
  204 + Logger.error(TAG, `getInteractData catch, error.name : ${err.name}, error.message:${err.message}`);
  205 + // 无论是否成功(暂不做重试),都回调结果,通知刷新数据
  206 + success(null);
  207 + })
  208 + });
  209 + }
  210 +
  211 + private resetInteract(interact: InteractDataDTO[], compList: CompDTO[]) {
  212 + if (interact == null || interact.length == 0) {
  213 + return
  214 + }
  215 + interact.forEach((interactData) => {
  216 + let id = interactData.contentId;
  217 + outer: for (let i = 0;i < compList.length; i++) {
  218 + let comp = compList[i];
  219 + if (comp == null || comp.operDataList == null || comp.operDataList.length == 0) {
  220 + continue;
  221 + }
  222 + for (let j = 0;j < comp.operDataList.length; j++) {
  223 + let content = comp.operDataList[j];
  224 + if (content == null) {
  225 + continue;
  226 + }
  227 + if (id == content.objectId) {
  228 + content.interactData = interactData;
  229 + break outer;
  230 + }
  231 + }
  232 + }
  233 + })
  234 + }
  235 +
  236 + private getInteractParams(compList: CompDTO[]): InteractParam {
  237 + if (compList == null || compList.length == 0) {
  238 + return null;
  239 + }
  240 +
  241 + let param: InteractParam = {} as InteractParam;
  242 + param.contentList = new Array<ContentBean>();
  243 + compList.forEach((value) => {
  244 + let contentList = value.operDataList;
  245 + if (contentList != null && contentList.length > 0) {
  246 + contentList.forEach((v) => {
  247 + if (StringUtils.isNotEmpty(v.objectId)) {
  248 + let bean = {} as ContentBean;
  249 + bean.contentId = v.objectId;
  250 + bean.contentType = v.objectType;
  251 + param.contentList.push(bean);
  252 + }
  253 + })
  254 + }
  255 + })
  256 + return param;
  257 + }
123 } 258 }
124 259
125 260
@@ -17,7 +17,7 @@ export class CollectionUtils { @@ -17,7 +17,7 @@ export class CollectionUtils {
17 * @returns {boolean} true(empty) 17 * @returns {boolean} true(empty)
18 */ 18 */
19 static isEmpty(collection?: any[]): boolean { 19 static isEmpty(collection?: any[]): boolean {
20 - return !collection || collection.length === 0; 20 + return!collection || collection.length === 0;
21 } 21 }
22 22
23 // static isEmptyList<T>(list1?: LinkList<T>): boolean { 23 // static isEmptyList<T>(list1?: LinkList<T>): boolean {
@@ -68,6 +68,25 @@ export class CollectionUtils { @@ -68,6 +68,25 @@ export class CollectionUtils {
68 return index >= 0 && index < collection.length ? collection[index] : null; 68 return index >= 0 && index < collection.length ? collection[index] : null;
69 } 69 }
70 70
  71 + /**
  72 + * 截取集合部分数据。
  73 + * start:0 - end:20 截取0-19,共20个数据
  74 + */
  75 + static getSubElements(collection?: any[], start?: number, end?: number): any[] {
  76 + if (CollectionUtils.isEmpty(collection) || start === undefined || end === undefined) {
  77 + return null;
  78 + }
  79 + if (start < 0 || end < start) {
  80 + return null;
  81 + }
  82 + if (end > collection.length) {
  83 + return null;
  84 + }
  85 + let ss = collection.slice(start, end);
  86 + ss;
  87 + return collection.slice(start, end);
  88 + }
  89 +
71 static isArray(value: any): boolean { 90 static isArray(value: any): boolean {
72 if (typeof Array.isArray === 'function') { 91 if (typeof Array.isArray === 'function') {
73 return Array.isArray(value); 92 return Array.isArray(value);
@@ -36,10 +36,21 @@ export class HttpRequest { @@ -36,10 +36,21 @@ export class HttpRequest {
36 return service.delete(url, config) 36 return service.delete(url, config)
37 } 37 }
38 38
39 - static post<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> { 39 + static post0<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> {
40 return service.post(url, data, config) 40 return service.post(url, data, config)
41 } 41 }
42 42
  43 + static post<T = any>(url: string, data1?: any, headers?: HashMap<string, string>): Promise<T> {
  44 + let requestHeaders: AxiosHeaders = new AxiosHeaders()
  45 + headers?.forEach((v, k) => {
  46 + requestHeaders.set(k, v);
  47 + });
  48 + let config: AxiosRequestConfig = {
  49 + headers: requestHeaders as RawAxiosRequestHeaders,
  50 + }
  51 + return service.post(url, data1, config)
  52 + }
  53 +
43 static put<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> { 54 static put<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> {
44 return service.put(url, data, config) 55 return service.put(url, data, config)
45 } 56 }
@@ -17,7 +17,9 @@ export { Action } from './src/main/ets/bean/content/Action' @@ -17,7 +17,9 @@ export { Action } from './src/main/ets/bean/content/Action'
17 export { Params } from './src/main/ets/bean/content/Params' 17 export { Params } from './src/main/ets/bean/content/Params'
18 18
19 export { Pic } from './src/main/ets/bean/content/Pic' 19 export { Pic } from './src/main/ets/bean/content/Pic'
20 - 20 +export { InteractDataDTO } from './src/main/ets/bean/content/InteractDataDTO';
  21 +export { InteractParam } from './src/main/ets/bean/content/InteractParam';
  22 +export { ContentBean } from './src/main/ets/bean/content/ContentBean';
21 export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean'; 23 export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean';
22 24
23 export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO'; 25 export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO';
1 import { FullColumnImgUrlDTO } from '../detail/FullColumnImgUrlDTO'; 1 import { FullColumnImgUrlDTO } from '../detail/FullColumnImgUrlDTO';
2 import { LiveInfoDTO } from '../detail/LiveInfoDTO'; 2 import { LiveInfoDTO } from '../detail/LiveInfoDTO';
3 import { VideoInfoDTO } from '../detail/VideoInfoDTO'; 3 import { VideoInfoDTO } from '../detail/VideoInfoDTO';
4 - 4 +import { InteractDataDTO } from './src/main/ets/bean/content/InteractDataDTO';
5 export interface ContentDTO { 5 export interface ContentDTO {
6 cityCode: string; 6 cityCode: string;
7 coverSize: string; 7 coverSize: string;
@@ -54,4 +54,7 @@ export interface ContentDTO { @@ -54,4 +54,7 @@ export interface ContentDTO {
54 videoInfo?: VideoInfoDTO; // 视频新闻信息【BFF聚合】,视频非原片+清晰度最高的 54 videoInfo?: VideoInfoDTO; // 视频新闻信息【BFF聚合】,视频非原片+清晰度最高的
55 55
56 newsSummary: string; //appstyle:2 ,新闻详情 56 newsSummary: string; //appstyle:2 ,新闻详情
  57 +
  58 + // 二次请求接口,返回的数据,这里组装到content里;TODO 后续优化
  59 + interactData:InteractDataDTO;
57 } 60 }
  1 +/**
  2 + * 批查接口查询互动相关数据,返回数据bean
  3 + */
  4 +export interface InteractDataDTO {
  5 + collectNum: number;
  6 + commentNum: number;
  7 + contentId: string;
  8 + contentType: number;
  9 + likeNum: number;
  10 + readNum: number;
  11 + shareNum: number;
  12 +}
  1 +/**
  2 + * 批查接口查询互动相关数据,返回数据bean
  3 + */
  4 +export interface InteractParam {
  5 + contentList: Array<ContentBean>;
  6 + // 默认0;是否详情页访问;默认0:非详情;1:详情页(只有访问详情页时(detail=1),才触发浏览量加1)
  7 + detail: string;
  8 +}
  9 +
  10 +export interface ContentBean {
  11 + contentId: string;
  12 + contentType: string;
  13 +}
1 import HashMap from '@ohos.util.HashMap'; 1 import HashMap from '@ohos.util.HashMap';
2 import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork'; 2 import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork';
3 import { DateTimeUtils } from 'wdKit'; 3 import { DateTimeUtils } from 'wdKit';
4 -import { ContentDetailDTO, NavigationBodyDTO, PageDTO } from 'wdBean'; 4 +import { ContentDetailDTO, NavigationBodyDTO, PageDTO,InteractDataDTO } from 'wdBean';
5 5
6 export class PageRepository { 6 export class PageRepository {
7 static getBottomNavGroupUrl() { 7 static getBottomNavGroupUrl() {
@@ -35,6 +35,11 @@ export class PageRepository { @@ -35,6 +35,11 @@ export class PageRepository {
35 return url; 35 return url;
36 } 36 }
37 37
  38 + static getInteractDataUrl() {
  39 + let url = HttpUrlUtils.getHost() + this.INTERACT_DATA_PATH;
  40 + return url;
  41 + }
  42 +
38 static fetchNavigationDataApi() { 43 static fetchNavigationDataApi() {
39 let url = PageRepository.getBottomNavGroupUrl(); 44 let url = PageRepository.getBottomNavGroupUrl();
40 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); 45 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
@@ -52,4 +57,10 @@ export class PageRepository { @@ -52,4 +57,10 @@ export class PageRepository {
52 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); 57 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
53 return WDHttp.get<ResponseDTO<ContentDetailDTO>>(url, headers) 58 return WDHttp.get<ResponseDTO<ContentDetailDTO>>(url, headers)
54 }; 59 };
  60 +
  61 + static fetchInteractData(param: object) {
  62 + let url = HttpUrlUtils.getInteractDataUrl()
  63 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  64 + return WDHttp.post<ResponseDTO<InteractDataDTO[]>>(url, param, headers)
  65 + };
55 } 66 }
@@ -13,12 +13,12 @@ export class RefreshConstants { @@ -13,12 +13,12 @@ export class RefreshConstants {
13 /** 13 /**
14 * The delay time. 14 * The delay time.
15 */ 15 */
16 - static readonly DELAY_TIME: number = 1000; 16 + static readonly DELAY_TIME: number = 200;
17 17
18 /** 18 /**
19 * The animation duration. 19 * The animation duration.
20 */ 20 */
21 - static readonly ANIMATION_DURATION: number = 2000; 21 + static readonly ANIMATION_DURATION: number = 200;
22 /** 22 /**
23 * The RefreshConstant constants. 23 * The RefreshConstant constants.
24 */ 24 */
1 -import { NavigationBodyDTO, PageDTO } from 'wdBean';  
2 -import { Logger, ResourcesUtils } from 'wdKit'; 1 +import { NavigationBodyDTO, PageDTO,InteractDataDTO,ContentBean, InteractParam,CompDTO } from 'wdBean';
  2 +import { CollectionUtils, Logger, ResourcesUtils, StringUtils } from 'wdKit';
3 import { ResponseDTO, } from 'wdNetwork'; 3 import { ResponseDTO, } from 'wdNetwork';
4 import { PageRepository } from '../repository/PageRepository'; 4 import { PageRepository } from '../repository/PageRepository';
5 import { BaseViewModel } from './BaseViewModel'; 5 import { BaseViewModel } from './BaseViewModel';
@@ -10,7 +10,11 @@ const TAG = 'PageViewModel'; @@ -10,7 +10,11 @@ const TAG = 'PageViewModel';
10 * mock数据是本地json数据,可自行修改内容(‘entry\src\main\resources\rawfile\’目录) 10 * mock数据是本地json数据,可自行修改内容(‘entry\src\main\resources\rawfile\’目录)
11 */ 11 */
12 const mock_switch = false; 12 const mock_switch = false;
13 - 13 +/**
  14 + * 互动数据获取开关开关,默认开。
  15 + * TODO 后续需要优化掉,变为二次请求异步刷新
  16 + */
  17 +const interact_sync_switch = true;
14 /** 18 /**
15 * 处理返回后的数据 19 * 处理返回后的数据
16 */ 20 */
@@ -123,14 +127,141 @@ export class PageViewModel extends BaseViewModel { @@ -123,14 +127,141 @@ export class PageViewModel extends BaseViewModel {
123 return 127 return
124 } 128 }
125 Logger.info(TAG, "getNavData then,resDTO.timestamp:" + resDTO.timestamp); 129 Logger.info(TAG, "getNavData then,resDTO.timestamp:" + resDTO.timestamp);
  130 + if (!interact_sync_switch) {
  131 + success(resDTO.data);
  132 + return;
  133 + }
  134 + // TODO 打开同步请求互动数据,待优化为异步加载
  135 + if (CollectionUtils.isEmpty(resDTO.data.compList)) {
  136 + success(resDTO.data);
  137 + } else {
  138 + this.getInteractData(resDTO.data.compList).then(() => {
126 success(resDTO.data); 139 success(resDTO.data);
127 }) 140 })
  141 + }
  142 + })
128 .catch((err: Error) => { 143 .catch((err: Error) => {
129 Logger.error(TAG, `getPageData catch, error.name : ${err.name}, error.message:${err.message}`); 144 Logger.error(TAG, `getPageData catch, error.name : ${err.name}, error.message:${err.message}`);
130 error(err); 145 error(err);
131 }) 146 })
132 }) 147 })
133 } 148 }
  149 +
  150 + async getInteractData(compList: CompDTO[]) {
  151 + let param: InteractParam = this.getInteractParams(compList);
  152 + const SIZE = 20;
  153 + // 批查接口,参数size限制20,这里截断分批查询,0,20;20,40...
  154 + let count = Math.ceil(param.contentList.length / SIZE);
  155 + let promises = new Array;
  156 + if (count == 1) {
  157 + let promise: Promise<InteractDataDTO[]> = this.createInteractDataPromise(param);
  158 + promises.push(promise);
  159 + } else {
  160 + for (let i = 1;i <= count; i++) {
  161 + // 将查询参数截断(参数限制20个),分批请求接口
  162 + let subList = new Array<ContentBean>();
  163 + let start = 0;
  164 + let end = 0;
  165 + if (i == count) {
  166 + start = (i - 1) * SIZE;
  167 + end = param.contentList.length;
  168 + subList = CollectionUtils.getSubElements(param.contentList, start, end)
  169 + } else {
  170 + start = (i - 1) * SIZE;
  171 + end = start + SIZE;
  172 + subList = CollectionUtils.getSubElements(param.contentList, start, end)
  173 + }
  174 + let subParam: InteractParam = {} as InteractParam;
  175 + subParam.contentList = subList;
  176 + let promise: Promise<InteractDataDTO[]> = this.createInteractDataPromise(subParam);
  177 + promises.push(promise);
  178 + }
  179 + }
  180 +
  181 + return new Promise<CompDTO[]>((success, error) => {
  182 + Promise.all(promises).then((result) => {
  183 + if (!CollectionUtils.isArray(result)) {
  184 + success(compList);
  185 + return;
  186 + }
  187 +
  188 + let allInteractDataList = new Array();
  189 + result.forEach((value: InteractDataDTO[]) => {
  190 + if (value != null && value.length > 0) {
  191 + allInteractDataList.push(...value);
  192 + }
  193 + })
  194 + // 批查全部完成,统一设置到comp里
  195 + this.resetInteract(allInteractDataList, compList);
  196 + success(compList);
  197 + })
  198 + })
  199 + }
  200 +
  201 + private createInteractDataPromise(param: InteractParam) {
  202 + return new Promise<InteractDataDTO[]>((success, error) => {
  203 + PageRepository.fetchInteractData(param).then((resDTO: ResponseDTO<InteractDataDTO[]>) => {
  204 + if (this.isRespondsInvalid(resDTO, 'getInteractData')) {
  205 + Logger.info(TAG, "getInteractData then,resDTO.timeStamp:" + resDTO.timestamp);
  206 + success(null);
  207 + return;
  208 + }
  209 + success(resDTO.data);
  210 + }).catch((err: Error) => {
  211 + Logger.error(TAG, `getInteractData catch, error.name : ${err.name}, error.message:${err.message}`);
  212 + // 无论是否成功(暂不做重试),都回调结果,通知刷新数据
  213 + success(null);
  214 + })
  215 + });
  216 + }
  217 +
  218 + private resetInteract(interact: InteractDataDTO[], compList: CompDTO[]) {
  219 + if (interact == null || interact.length == 0) {
  220 + return
  221 + }
  222 + interact.forEach((interactData) => {
  223 + let id = interactData.contentId;
  224 + outer: for (let i = 0;i < compList.length; i++) {
  225 + let comp = compList[i];
  226 + if (comp == null || comp.operDataList == null || comp.operDataList.length == 0) {
  227 + continue;
  228 + }
  229 + for (let j = 0;j < comp.operDataList.length; j++) {
  230 + let content = comp.operDataList[j];
  231 + if (content == null) {
  232 + continue;
  233 + }
  234 + if (id == content.objectId) {
  235 + content.interactData = interactData;
  236 + break outer;
  237 + }
  238 + }
  239 + }
  240 + })
  241 + }
  242 +
  243 + private getInteractParams(compList: CompDTO[]): InteractParam {
  244 + if (compList == null || compList.length == 0) {
  245 + return null;
  246 + }
  247 +
  248 + let param: InteractParam = {} as InteractParam;
  249 + param.contentList = new Array<ContentBean>();
  250 + compList.forEach((value) => {
  251 + let contentList = value.operDataList;
  252 + if (contentList != null && contentList.length > 0) {
  253 + contentList.forEach((v) => {
  254 + if (StringUtils.isNotEmpty(v.objectId)) {
  255 + let bean = {} as ContentBean;
  256 + bean.contentId = v.objectId;
  257 + bean.contentType = v.objectType;
  258 + param.contentList.push(bean);
  259 + }
  260 + })
  261 + }
  262 + })
  263 + return param;
  264 + }
134 } 265 }
135 266
136 267
@@ -160,5 +160,24 @@ export class CollectionUtils { @@ -160,5 +160,24 @@ export class CollectionUtils {
160 const arr = unescape(encodeURIComponent(str)).split('').map(val => val.charCodeAt(0)); 160 const arr = unescape(encodeURIComponent(str)).split('').map(val => val.charCodeAt(0));
161 return new Uint8Array(arr); 161 return new Uint8Array(arr);
162 } 162 }
  163 +
  164 + /**
  165 + * 截取集合部分数据。
  166 + * start:0 - end:20 截取0-19,共20个数据
  167 + */
  168 + static getSubElements(collection?: any[], start?: number, end?: number): any[] {
  169 + if (CollectionUtils.isEmpty(collection) || start === undefined || end === undefined) {
  170 + return null;
  171 + }
  172 + if (start < 0 || end < start) {
  173 + return null;
  174 + }
  175 + if (end > collection.length) {
  176 + return null;
  177 + }
  178 + let ss = collection.slice(start, end);
  179 + ss;
  180 + return collection.slice(start, end);
  181 + }
163 } 182 }
164 183
@@ -56,13 +56,24 @@ export class HttpRequest { @@ -56,13 +56,24 @@ export class HttpRequest {
56 return service.get(url, config) 56 return service.get(url, config)
57 } 57 }
58 58
59 - static post<T = ResponseDTO<string>>(url: string, data?: object, headers?: HashMap<string, string>): Promise<T> { 59 + static post0<T = ResponseDTO<string>>(url: string, data?: object, headers?: HashMap<string, string>): Promise<T> {
60 let config: AxiosRequestConfig = { 60 let config: AxiosRequestConfig = {
61 headers: HttpRequest.buildHeaderWithGlobalHeader(headers) 61 headers: HttpRequest.buildHeaderWithGlobalHeader(headers)
62 } 62 }
63 return service.post(url, data, config) 63 return service.post(url, data, config)
64 } 64 }
65 65
  66 + static post<T = any>(url: string, data1?: any, headers?: HashMap<string, string>): Promise<T> {
  67 + let requestHeaders: AxiosHeaders = new AxiosHeaders()
  68 + headers?.forEach((v, k) => {
  69 + requestHeaders.set(k, v);
  70 + });
  71 + let config: AxiosRequestConfig = {
  72 + headers: requestHeaders as RawAxiosRequestHeaders,
  73 + }
  74 + return service.post(url, data1, config)
  75 + }
  76 +
66 static put<T = ResponseDTO<string>>(url: string, data?: object, headers?: HashMap<string, string>): Promise<T> { 77 static put<T = ResponseDTO<string>>(url: string, data?: object, headers?: HashMap<string, string>): Promise<T> {
67 let config: AxiosRequestConfig = { 78 let config: AxiosRequestConfig = {
68 headers: HttpRequest.buildHeaderWithGlobalHeader(headers) 79 headers: HttpRequest.buildHeaderWithGlobalHeader(headers)
@@ -34,7 +34,10 @@ export class HttpUrlUtils { @@ -34,7 +34,10 @@ export class HttpUrlUtils {
34 * 详情页面详情接口 34 * 详情页面详情接口
35 */ 35 */
36 static readonly DETAIL_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail"; 36 static readonly DETAIL_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail";
37 - 37 + /**
  38 + * 批查接口,查询互动相关数据,如收藏数、评论数等
  39 + */
  40 + static readonly INTERACT_DATA_PATH: string = "/api/rmrb-contact/contact/zh/c/content/interactData";
38 private static hostUrl: string = HttpUrlUtils.HOST_PRODUCT; 41 private static hostUrl: string = HttpUrlUtils.HOST_PRODUCT;
39 42
40 static getCommonHeaders(): HashMap<string, string> { 43 static getCommonHeaders(): HashMap<string, string> {
@@ -55,8 +58,8 @@ export class HttpUrlUtils { @@ -55,8 +58,8 @@ export class HttpUrlUtils {
55 //headers.set('X-Ca-Stage', 'PRE') 58 //headers.set('X-Ca-Stage', 'PRE')
56 headers.set('versionCode', HttpUrlUtils.getVersionCode()) 59 headers.set('versionCode', HttpUrlUtils.getVersionCode())
57 headers.set('system', HttpUrlUtils.getTerminalId()) 60 headers.set('system', HttpUrlUtils.getTerminalId())
58 - headers.set('version_name', 'debug')  
59 - headers.set('EagleEye-TraceID', '0B6DE03D2997435BA875FFBE05425ED2') 61 + headers.set('version_name', this.getVersionName())
  62 + headers.set('EagleEye-TraceID', 'D539562E48554A60977AF4BECB6D6C7A')
60 headers.set('imei', HttpUrlUtils.getImei()) 63 headers.set('imei', HttpUrlUtils.getImei())
61 headers.set('Accept-Language', 'zh') 64 headers.set('Accept-Language', 'zh')
62 headers.set('city', HttpUrlUtils.getCity()) 65 headers.set('city', HttpUrlUtils.getCity())
@@ -64,6 +67,8 @@ export class HttpUrlUtils { @@ -64,6 +67,8 @@ export class HttpUrlUtils {
64 // TODO 判断是否登录 67 // TODO 判断是否登录
65 headers.set('userId', HttpUrlUtils.getUserId()) 68 headers.set('userId', HttpUrlUtils.getUserId())
66 headers.set('userType', HttpUrlUtils.getUserType()) 69 headers.set('userType', HttpUrlUtils.getUserType())
  70 +
  71 + headers.set('mpassid', 'ZbHTMeTsfaYDAHqt8ZHIzcPs')
67 HttpUrlUtils.addSpecialHeaders(headers); 72 HttpUrlUtils.addSpecialHeaders(headers);
68 // Logger.debug("TAG", '******************* commonHeaders headers start ******************************** '); 73 // Logger.debug("TAG", '******************* commonHeaders headers start ******************************** ');
69 // headers.forEach((v,k)=>{ 74 // headers.forEach((v,k)=>{
@@ -131,12 +136,12 @@ export class HttpUrlUtils { @@ -131,12 +136,12 @@ export class HttpUrlUtils {
131 136
132 private static getDeviceId() { 137 private static getDeviceId() {
133 // TODO 138 // TODO
134 - return 'b5cf725d-193d-3215-8c77-e76fe15ce64d'; 139 + return '8a81226a-cabd-3e1b-b630-b51db4a720ed';
135 } 140 }
136 141
137 private static getVersion() { 142 private static getVersion() {
138 // TODO 143 // TODO
139 - return '202312251034'; 144 + return '202401242103';
140 } 145 }
141 146
142 private static getVersionCode() { 147 private static getVersionCode() {
@@ -144,13 +149,18 @@ export class HttpUrlUtils { @@ -144,13 +149,18 @@ export class HttpUrlUtils {
144 return '7301'; 149 return '7301';
145 } 150 }
146 151
  152 + private static getVersionName() {
  153 + // TODO
  154 + return '7.3.0.1';
  155 + }
  156 +
147 private static getAdCode() { 157 private static getAdCode() {
148 return '340000'; 158 return '340000';
149 } 159 }
150 160
151 private static getOsVersion() { 161 private static getOsVersion() {
152 // TODO 162 // TODO
153 - return '13'; 163 + return '12';
154 } 164 }
155 165
156 public static getCityCode() { 166 public static getCityCode() {
@@ -177,7 +187,7 @@ export class HttpUrlUtils { @@ -177,7 +187,7 @@ export class HttpUrlUtils {
177 187
178 private static getImei() { 188 private static getImei() {
179 // TODO 189 // TODO
180 - return 'b5cf725d-193d-3215-8c77-e76fe15ce64d'; 190 + return '8a81226a-cabd-3e1b-b630-b51db4a720ed';
181 } 191 }
182 192
183 private static getUserId() { 193 private static getUserId() {