张善主

Merge remote-tracking branch 'origin/main'

Showing 54 changed files with 1528 additions and 84 deletions
@@ -38,4 +38,8 @@ export { NumberFormatterUtils } from './src/main/ets/utils/NumberFormatterUtils' @@ -38,4 +38,8 @@ export { NumberFormatterUtils } from './src/main/ets/utils/NumberFormatterUtils'
38 38
39 // export { PermissionUtils } from './src/main/ets/utils/PermissionUtils' 39 // export { PermissionUtils } from './src/main/ets/utils/PermissionUtils'
40 40
41 -export { ErrorToastUtils } from './src/main/ets/utils/ErrorToastUtils'  
  41 +export { ErrorToastUtils } from './src/main/ets/utils/ErrorToastUtils'
  42 +
  43 +export { EmitterUtils } from './src/main/ets/utils/EmitterUtils'
  44 +
  45 +export { EmitterEventId } from './src/main/ets/utils/EmitterEventId'
  1 +/**
  2 + * 线程间通信事件id枚举
  3 + */
  4 +export enum EmitterEventId {
  5 + // 通知登出,事件id
  6 + FORCE_USER_LOGIN_OUT = 1
  7 +}
  8 +
  1 +import emitter from '@ohos.events.emitter';
  2 +import HashMap from '@ohos.util.HashMap';
  3 +
  4 +const TAG: string = 'EmitterUtils';
  5 +
  6 +/**
  7 + * 线程间通信简单工具
  8 + * TODO 待优化
  9 + */
  10 +export class EmitterUtils {
  11 + /**
  12 + * 发送空消息
  13 + * @param eventId 事件id
  14 + */
  15 + static sendEmptyEvent(eventId: number) {
  16 + let event: emitter.InnerEvent = {
  17 + eventId: eventId,
  18 + priority: emitter.EventPriority.LOW
  19 + };
  20 + emitter.emit(event);
  21 + }
  22 +
  23 + /**
  24 + * 发送消息
  25 + * @param eventId 事件id
  26 + * @param data 数据
  27 + */
  28 + static sendEvent(eventId: number, data: { [key: string]: any; }) {
  29 + let event: emitter.InnerEvent = {
  30 + eventId: eventId,
  31 + priority: emitter.EventPriority.LOW
  32 + };
  33 + let eventData: emitter.EventData = {
  34 + data: data
  35 + };
  36 + emitter.emit(event, eventData);
  37 + }
  38 +
  39 + /**
  40 + * 接收消息
  41 + * @param eventId 事件id
  42 + * @param callback 回调函数
  43 + */
  44 + static receiveEvent(eventId: number, callback: (data?: { [key: string]: any; }) => void) {
  45 + let event: emitter.InnerEvent = {
  46 + eventId: eventId
  47 + };
  48 +
  49 + // 收到eventId为1的事件后执行该回调
  50 + let callback1 = (eventData: emitter.EventData): void => {
  51 + callback(eventData.data)
  52 + };
  53 +
  54 + // 订阅eventId为1的事件
  55 + emitter.on(event, callback1);
  56 + }
  57 +}
  58 +
@@ -4,3 +4,5 @@ export { HttpRequest as WDHttp } from "./src/main/ets/http/HttpRequest" @@ -4,3 +4,5 @@ export { HttpRequest as WDHttp } from "./src/main/ets/http/HttpRequest"
4 4
5 export { HttpUrlUtils } from "./src/main/ets/http/HttpUrlUtils" 5 export { HttpUrlUtils } from "./src/main/ets/http/HttpUrlUtils"
6 6
  7 +export { HttpBizUtil } from "./src/main/ets/http/HttpBizUtil"
  8 +
  1 +/*
  2 + * refresh token接口返回
  3 + */
  4 +export interface RefreshTokenRes {
  5 + jwtToken: string;
  6 + refreshToken: string;
  7 +}
  1 +import { SpConstants } from 'wdConstant/Index';
  2 +import { EmitterEventId, EmitterUtils, Logger, SPHelper, ToastUtils } from 'wdKit/Index';
  3 +import HashMap from '@ohos.util.HashMap';
  4 +import { ResponseDTO } from '../bean/ResponseDTO';
  5 +import { HttpUrlUtils, WDHttp } from '../../../../Index';
  6 +import { RefreshTokenRes } from '../bean/RefreshTokenRes';
  7 +
  8 +const TAG: string = 'HttpBizUtil'
  9 +
  10 +/**
  11 + * 网络请求工具,业务封装http,暂添加TokenInterceptor功能
  12 + * TODO 待优化,将HttpBizUtil接入 AxiosInstance.interceptors.response.use
  13 + */
  14 +export class HttpBizUtil {
  15 + /**
  16 + * get请求,封装了刷新token逻辑,接口选用,不涉及业务接口可以用原来的接口(如page接口)。
  17 + *
  18 + * @param url 请求地址
  19 + * @param headers 请求header参数
  20 + * @returns 返回值
  21 + */
  22 + static get<T = string>(url: string, headers?: HashMap<string, string>): Promise<ResponseDTO<T>> {
  23 + return new Promise<ResponseDTO<T>>((success, debug) => {
  24 + WDHttp.get<ResponseDTO<T>>(url, headers).then((resDTO: ResponseDTO<T>) => {
  25 + Logger.debug(TAG, 'get: ' + resDTO.code)
  26 + Logger.debug(TAG, 'get: ' + resDTO.message)
  27 + // 403:临时token;406:强制下线、封禁、清空登录信息还要跳转登录页面
  28 + if (resDTO.code == 403 || resDTO.code == 406) {
  29 + HttpBizUtil.refreshToken().then((token: string) => {
  30 + if (headers) {
  31 + headers.replace('RMRB-X-TOKEN', token)
  32 + headers.replace('cookie', 'RMRB-X-TOKEN=' + token)
  33 + }
  34 + Logger.debug(TAG, 'get again send: ' + token)
  35 + // refreshToken为空场景不处理,直接请求接口。
  36 + WDHttp.get<ResponseDTO<T>>(url, headers).then((resDTO: ResponseDTO<T>) => {
  37 + Logger.debug(TAG, 'get again: ' + resDTO.message)
  38 + success(resDTO)
  39 + }).catch((res: object) => {
  40 + debug(res)
  41 + })
  42 + });
  43 + } else {
  44 + success(resDTO)
  45 + }
  46 + }).catch((res: object) => {
  47 + debug(res)
  48 + })
  49 + })
  50 + }
  51 +
  52 + /**
  53 + * post请求,封装了刷新token逻辑,接口选用,不涉及业务接口可以用原来的接口(如page接口)。
  54 + *
  55 + * @param url 请求地址
  56 + * @param headers 请求header参数
  57 + * @returns 返回值
  58 + */
  59 + static post<T = string>(url: string, data?: object, headers?: HashMap<string, string>): Promise<ResponseDTO<T>> {
  60 + return new Promise<ResponseDTO<T>>((success, debug) => {
  61 + WDHttp.post<ResponseDTO<T>>(url, data, headers).then((resDTO: ResponseDTO<T>) => {
  62 + Logger.debug(TAG, 'post: ' + resDTO.code)
  63 + Logger.debug(TAG, 'post: ' + resDTO.message)
  64 + // 403:临时token;406:强制下线、封禁、清空登录信息还要跳转登录页面
  65 + if (resDTO.code == 0 || resDTO.code == 406) {
  66 + HttpBizUtil.refreshToken().then((token: string) => {
  67 + if (headers) {
  68 + headers.replace('RMRB-X-TOKEN', token)
  69 + headers.replace('cookie', 'RMRB-X-TOKEN=' + token)
  70 + }
  71 + // refreshToken为空场景不处理,直接请求接口。
  72 + WDHttp.post<ResponseDTO<T>>(url, headers).then((resDTO: ResponseDTO<T>) => {
  73 + success(resDTO)
  74 + }).catch((res: object) => {
  75 + debug(res)
  76 + })
  77 + });
  78 + } else {
  79 + success(resDTO)
  80 + }
  81 + }).catch((res: object) => {
  82 + debug(res)
  83 + })
  84 + })
  85 + }
  86 +
  87 + /*
  88 + * 获取刷新后的token,可能为空
  89 + */
  90 + static refreshToken(): Promise<string> {
  91 + let url = HttpUrlUtils.getRefreshTokenUrl();
  92 + let params: HashMap<string, string> = new HashMap<string, string>()
  93 + params.set('refreshToken', HttpUrlUtils.getRefreshToken())
  94 + params.set('deviceId', HttpUrlUtils.getDeviceId())
  95 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  96 + Logger.debug(TAG, 'refreshToken getRefreshToken: ' + HttpUrlUtils.getRefreshToken())
  97 + // // 请求刷新token接口
  98 + return new Promise<string>((success, debug) => {
  99 + WDHttp.post<ResponseDTO<RefreshTokenRes>>(url, params, headers).then((resDTO: ResponseDTO<RefreshTokenRes>) => {
  100 + let newToken = ''
  101 + if (resDTO) {
  102 + Logger.debug(TAG, 'refreshToken getRefreshToken: ' + resDTO.message)
  103 + Logger.debug(TAG, 'refreshToken getRefreshToken: ' + resDTO.code)
  104 + if (resDTO.code == 377) {
  105 + // 377强制用户下线、重新登录、封禁等场景;refreshToken 失效
  106 + ToastUtils.showToast("已登出,请重新登入", 1000);
  107 + EmitterUtils.sendEmptyEvent(EmitterEventId.FORCE_USER_LOGIN_OUT)
  108 + // WDRouterRule.jumpWithPage(WDRouterPage.loginPage)
  109 + } else if (resDTO.code == 0 && resDTO.data) {
  110 + newToken = resDTO.data.jwtToken
  111 + let refreshToken = resDTO.data.refreshToken
  112 + SPHelper.default.save(SpConstants.USER_JWT_TOKEN, newToken)
  113 + SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, refreshToken)
  114 + Logger.debug(TAG, 'refreshToken jwtToken: ' + resDTO.data.jwtToken)
  115 + Logger.debug(TAG, 'refreshToken refreshToken: ' + resDTO.data.refreshToken)
  116 + }
  117 + }
  118 + success(newToken)
  119 + });
  120 + })
  121 + }
  122 +}
@@ -112,6 +112,10 @@ export class HttpUrlUtils { @@ -112,6 +112,10 @@ export class HttpUrlUtils {
112 */ 112 */
113 static readonly APPOINTMENT_userArea_PATH: string = "/api/rmrb-content-center/c/service/sys-area/treeselect"; 113 static readonly APPOINTMENT_userArea_PATH: string = "/api/rmrb-content-center/c/service/sys-area/treeselect";
114 /** 114 /**
  115 + * 用户token刷新接口(token过期,需要刷新)
  116 + */
  117 + static readonly REFRESH_TOKEN_PATH: string = "/api/rmrb-user-center/auth/zh/c/refreshToken";
  118 + /**
115 /** 119 /**
116 * 个人中心 关注列表详情 120 * 个人中心 关注列表详情
117 */ 121 */
@@ -188,7 +192,6 @@ export class HttpUrlUtils { @@ -188,7 +192,6 @@ export class HttpUrlUtils {
188 * 搜索主页 热词 192 * 搜索主页 热词
189 */ 193 */
190 static readonly SEARCH_HOTS_DATA_PATH: string = "/api/rmrb-search-api/zh/c/hots"; 194 static readonly SEARCH_HOTS_DATA_PATH: string = "/api/rmrb-search-api/zh/c/hots";
191 -  
192 /** 195 /**
193 * 搜索联想词 196 * 搜索联想词
194 */ 197 */
@@ -198,7 +201,6 @@ export class HttpUrlUtils { @@ -198,7 +201,6 @@ export class HttpUrlUtils {
198 * 直播详情 201 * 直播详情
199 */ 202 */
200 static readonly LIVE_DETAILS_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail"; 203 static readonly LIVE_DETAILS_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail";
201 -  
202 /** 204 /**
203 * 直播详情-直播间列表 205 * 直播详情-直播间列表
204 */ 206 */
@@ -358,7 +360,7 @@ export class HttpUrlUtils { @@ -358,7 +360,7 @@ export class HttpUrlUtils {
358 return ''; 360 return '';
359 } 361 }
360 362
361 - private static getDeviceId() { 363 + public static getDeviceId() {
362 // TODO 364 // TODO
363 return '8a81226a-cabd-3e1b-b630-b51db4a720ed'; 365 return '8a81226a-cabd-3e1b-b630-b51db4a720ed';
364 } 366 }
@@ -452,6 +454,10 @@ export class HttpUrlUtils { @@ -452,6 +454,10 @@ export class HttpUrlUtils {
452 return url; 454 return url;
453 } 455 }
454 456
  457 + static getRefreshTokenUrl() {
  458 + let url = HttpUrlUtils._hostUrl + HttpUrlUtils.REFRESH_TOKEN_PATH;
  459 + return url;
  460 + }
455 461
456 static getResetPassworddUrl() { 462 static getResetPassworddUrl() {
457 let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/resetPassword"; 463 let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/resetPassword";
@@ -488,6 +494,20 @@ export class HttpUrlUtils { @@ -488,6 +494,20 @@ export class HttpUrlUtils {
488 return url; 494 return url;
489 } 495 }
490 496
  497 +
  498 + /*优质评论页*/
  499 + static getQualityCommentUrl() {
  500 + let url = HttpUrlUtils._hostUrl + "api/rmrb-comment/comment/zh/c/highQuality"
  501 + return url
  502 + }
  503 +
  504 + /*获取详情页评论列表*/
  505 + static getContentCommentListDataUrl() {
  506 + let url = HttpUrlUtils._hostUrl + "api/rmrb-comment/comment/zh/c/contentCommentList"
  507 + return url
  508 + }
  509 +
  510 +
491 //账户注销 511 //账户注销
492 static accountLogoutUrl() { 512 static accountLogoutUrl() {
493 let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/logoff"; 513 let url = HttpUrlUtils._hostUrl + "/api/rmrb-user-center/user/zh/c/logoff";
@@ -80,6 +80,8 @@ export function registerRouter() { @@ -80,6 +80,8 @@ export function registerRouter() {
80 return WDRouterPage.imageTextDetailPage 80 return WDRouterPage.imageTextDetailPage
81 } else if (action.params?.pageID == "BroadcastPage") { 81 } else if (action.params?.pageID == "BroadcastPage") {
82 return WDRouterPage.broadcastPage 82 return WDRouterPage.broadcastPage
  83 + } else if (action.params?.pageID == "SPACIAL_TOPIC_PAGE") {
  84 + return WDRouterPage.spacialTopicPage
83 } 85 }
84 return undefined 86 return undefined
85 }) 87 })
@@ -32,6 +32,8 @@ export class WDRouterPage { @@ -32,6 +32,8 @@ export class WDRouterPage {
32 static morningEveningPaperPage = new WDRouterPage("phone", "ets/pages/MorningEveningPaperPage") 32 static morningEveningPaperPage = new WDRouterPage("phone", "ets/pages/MorningEveningPaperPage")
33 // 图文详情页 33 // 图文详情页
34 static imageTextDetailPage = new WDRouterPage("phone", "ets/pages/ImageAndTextDetailPage"); 34 static imageTextDetailPage = new WDRouterPage("phone", "ets/pages/ImageAndTextDetailPage");
  35 + // 专题页
  36 + static spacialTopicPage = new WDRouterPage("phone", "ets/pages/SpacialTopicPage");
35 // 短视频详情页 37 // 短视频详情页
36 static detailVideoListPage = new WDRouterPage("wdDetailPlayShortVideo", "ets/pages/DetailVideoListPage"); 38 static detailVideoListPage = new WDRouterPage("wdDetailPlayShortVideo", "ets/pages/DetailVideoListPage");
37 static detailPlayShortVideoPage = new WDRouterPage("wdDetailPlayShortVideo", "ets/pages/DetailPlayShortVideoPage"); 39 static detailPlayShortVideoPage = new WDRouterPage("wdDetailPlayShortVideo", "ets/pages/DetailPlayShortVideoPage");
@@ -10,7 +10,7 @@ export class H5CallNativeType { @@ -10,7 +10,7 @@ export class H5CallNativeType {
10 static jsCall_callAppService = 'jsCall_callAppService' 10 static jsCall_callAppService = 'jsCall_callAppService'
11 // TODO 业务自行新增类型、自行在JsBridgeBiz#performJSCallNative里添加接收分支处理。 11 // TODO 业务自行新增类型、自行在JsBridgeBiz#performJSCallNative里添加接收分支处理。
12 12
13 - static init() { 13 + static {
14 H5CallNativeType.JsCallTypeList.push(H5CallNativeType.jsCall_currentPageOperate) 14 H5CallNativeType.JsCallTypeList.push(H5CallNativeType.jsCall_currentPageOperate)
15 H5CallNativeType.JsCallTypeList.push(H5CallNativeType.jsCall_getAppPublicInfo) 15 H5CallNativeType.JsCallTypeList.push(H5CallNativeType.jsCall_getAppPublicInfo)
16 H5CallNativeType.JsCallTypeList.push(H5CallNativeType.jsCall_getArticleDetailBussinessData) 16 H5CallNativeType.JsCallTypeList.push(H5CallNativeType.jsCall_getArticleDetailBussinessData)
@@ -6,6 +6,7 @@ import { BridgeHandler, BridgeUtil, BridgeWebViewControl, Callback } from 'wdJsB @@ -6,6 +6,7 @@ import { BridgeHandler, BridgeUtil, BridgeWebViewControl, Callback } from 'wdJsB
6 import { performJSCallNative } from './JsBridgeBiz'; 6 import { performJSCallNative } from './JsBridgeBiz';
7 import { setDefaultNativeWebSettings } from './WebComponentUtil'; 7 import { setDefaultNativeWebSettings } from './WebComponentUtil';
8 import { Message } from 'wdJsBridge/src/main/ets/bean/Message'; 8 import { Message } from 'wdJsBridge/src/main/ets/bean/Message';
  9 +import { H5CallNativeType } from './H5CallNativeType';
9 10
10 const TAG = 'WdWebComponent'; 11 const TAG = 'WdWebComponent';
11 12
@@ -80,16 +81,11 @@ export struct WdWebComponent { @@ -80,16 +81,11 @@ export struct WdWebComponent {
80 this.onPageEnd(event?.url) 81 this.onPageEnd(event?.url)
81 }) 82 })
82 .onPageBegin((event) => { 83 .onPageBegin((event) => {
83 - // setDefaultNativeWebSettings(this.webviewControl, this.webUrl).then(()=>{  
84 - // this.handleInfo && this.handleInfo.length > 1 ? this.handleInfo.forEach(value => {  
85 - // this.webviewControl.registerHandler(value[0], value[1])  
86 - // }) : this.defaultRegisterHandler()  
87 - // setTimeout(()=>{  
88 - // BridgeUtil.webViewLoadLocalJs(getContext(this), this.webviewControl)  
89 - // },500)  
90 - // })  
91 - // this.onPageBegin(event?.url)  
92 - // this.webviewControl?.setCustomUserAgent('Mozilla/5.0 (Linux; Android 12; HarmonyOS; OXF-AN00; HMSCore 6.13.0.302) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 HuaweiBrowser/14.0.6.300 Mobile Safari/537.36') 84 + this.onPageBegin(event?.url);
  85 + this.registerHandlers();
  86 + setTimeout(() => {
  87 + BridgeUtil.webViewLoadLocalJs(getContext(this), this.webviewControl)
  88 + }, 200)
93 }) 89 })
94 .onLoadIntercept((event) => { 90 .onLoadIntercept((event) => {
95 let url: string = event.data.getRequestUrl().toString() 91 let url: string = event.data.getRequestUrl().toString()
@@ -115,5 +111,16 @@ export struct WdWebComponent { @@ -115,5 +111,16 @@ export struct WdWebComponent {
115 this.webviewControl.refresh() 111 this.webviewControl.refresh()
116 } 112 }
117 } 113 }
  114 +
  115 + private registerHandlers(): void {
  116 + // 注册h5调用js相关
  117 + for (let i = 0; i < H5CallNativeType.JsCallTypeList.length; i++) {
  118 + let handleName = H5CallNativeType.JsCallTypeList[i];
  119 + let handle = (data: Message, f: Callback) => {
  120 + this.defaultPerformJSCallNative(data, f)
  121 + } ;
  122 + this.webviewControl.registerHandler(handleName, { handle: handle });
  123 + }
  124 + }
118 } 125 }
119 126
@@ -39,17 +39,6 @@ export struct WdWebLocalComponent { @@ -39,17 +39,6 @@ export struct WdWebLocalComponent {
39 // .onlineImageAccess(true) 39 // .onlineImageAccess(true)
40 // .fileAccess(true) 40 // .fileAccess(true)
41 .onPageBegin((event) => { 41 .onPageBegin((event) => {
42 -  
43 - // setDefaultNativeWebSettings(this.webviewControl, this.webResource).then(()=>{  
44 - // this.handleInfo && this.handleInfo.length > 1 ? this.handleInfo.forEach(value => {  
45 - // this.webviewControl.registerHandler(value[0], value[1])  
46 - // }) : this.defaultRegisterHandler()  
47 - // setTimeout(()=>{  
48 - // BridgeUtil.webViewLoadLocalJs(getContext(this), this.webviewControl)  
49 - // },500)  
50 - // })  
51 - // this.onPageBegin(event?.url)  
52 - // BridgeUtil.webViewLoadLocalJs(getContext(this), this.webviewControl);  
53 this.onPageBegin(event?.url); 42 this.onPageBegin(event?.url);
54 this.registerHandlers(); 43 this.registerHandlers();
55 setTimeout(() => { 44 setTimeout(() => {
@@ -79,8 +68,6 @@ export struct WdWebLocalComponent { @@ -79,8 +68,6 @@ export struct WdWebLocalComponent {
79 } 68 }
80 69
81 private registerHandlers(): void { 70 private registerHandlers(): void {
82 - // TODO 待优化  
83 - H5CallNativeType.init();  
84 // 注册h5调用js相关 71 // 注册h5调用js相关
85 for (let i = 0; i < H5CallNativeType.JsCallTypeList.length; i++) { 72 for (let i = 0; i < H5CallNativeType.JsCallTypeList.length; i++) {
86 let handleName = H5CallNativeType.JsCallTypeList[i]; 73 let handleName = H5CallNativeType.JsCallTypeList[i];
@@ -89,13 +76,6 @@ export struct WdWebLocalComponent { @@ -89,13 +76,6 @@ export struct WdWebLocalComponent {
89 } ; 76 } ;
90 this.webviewControl.registerHandler(handleName, { handle: handle }); 77 this.webviewControl.registerHandler(handleName, { handle: handle });
91 } 78 }
92 - // // TODO test  
93 - // this.webviewControl.registerHandler('changeNativeMessage', {  
94 - // handle: (data: Message, f: Callback) => {  
95 - // this.defaultPerformJSCallNative(data, f)  
96 - // }  
97 - // });  
98 -  
99 } 79 }
100 80
101 /** 81 /**
@@ -111,7 +91,7 @@ export struct WdWebLocalComponent { @@ -111,7 +91,7 @@ export struct WdWebLocalComponent {
111 Logger.debug(TAG, 'onPageEnd'); 91 Logger.debug(TAG, 'onPageEnd');
112 } 92 }
113 onLoadIntercept: (url?: string) => boolean = () => { 93 onLoadIntercept: (url?: string) => boolean = () => {
114 - Logger.debug(TAG, 'onPageBegin return false'); 94 + Logger.debug(TAG, 'onLoadIntercept return false');
115 return false 95 return false
116 } 96 }
117 } 97 }
@@ -64,3 +64,8 @@ export { FirstTabTopSearchComponent } from "./src/main/ets/components/search/Fir @@ -64,3 +64,8 @@ export { FirstTabTopSearchComponent } from "./src/main/ets/components/search/Fir
64 export { ListHasNoMoreDataUI } from "./src/main/ets/components/reusable/ListHasNoMoreDataUI" 64 export { ListHasNoMoreDataUI } from "./src/main/ets/components/reusable/ListHasNoMoreDataUI"
65 65
66 export { LottieView } from './src/main/ets/lottie/LottieView' 66 export { LottieView } from './src/main/ets/lottie/LottieView'
  67 +
  68 +export { SpacialTopicPageComponent } from './src/main/ets/components/SpacialTopicPageComponent'
  69 +
  70 +export { LogoutViewModel } from "./src/main/ets/viewmodel/LogoutViewModel"
  71 +
@@ -7,7 +7,7 @@ import { @@ -7,7 +7,7 @@ import {
7 ResponseBean 7 ResponseBean
8 } from 'wdBean'; 8 } from 'wdBean';
9 import { Logger } from 'wdKit'; 9 import { Logger } from 'wdKit';
10 -import { WdWebComponent, WdWebLocalComponent } from 'wdWebComponent'; 10 +import { WdWebLocalComponent } from 'wdWebComponent';
11 import { NativeCallH5Type } from 'wdWebComponent/src/main/ets/pages/NativeCallH5Type'; 11 import { NativeCallH5Type } from 'wdWebComponent/src/main/ets/pages/NativeCallH5Type';
12 import { BridgeWebViewControl } from 'wdJsBridge/Index'; 12 import { BridgeWebViewControl } from 'wdJsBridge/Index';
13 13
@@ -85,11 +85,6 @@ export struct ImageAndTextWebComponent { @@ -85,11 +85,6 @@ export struct ImageAndTextWebComponent {
85 webResource: $rawfile('apph5/index.html'), 85 webResource: $rawfile('apph5/index.html'),
86 backVisibility: false, 86 backVisibility: false,
87 }) 87 })
88 - // WdWebLocalComponent({  
89 - // webviewControl: this.webviewControl,  
90 - // webResource: "http://pd-people-uat.pdnews.cn/articletopic/35398-10000015965",  
91 - // backVisibility: false,  
92 - // })  
93 } 88 }
94 } 89 }
95 90
@@ -97,7 +92,7 @@ export struct ImageAndTextWebComponent { @@ -97,7 +92,7 @@ export struct ImageAndTextWebComponent {
97 Logger.debug('ImageAndTextWebComponent', 'jsCall_receiveAppData'); 92 Logger.debug('ImageAndTextWebComponent', 'jsCall_receiveAppData');
98 this.webviewControl.callHandle(NativeCallH5Type.jsCall_receiveAppData, 93 this.webviewControl.callHandle(NativeCallH5Type.jsCall_receiveAppData,
99 JSON.stringify(h5ReceiveAppData), (data: string) => { 94 JSON.stringify(h5ReceiveAppData), (data: string) => {
100 - // Logger.debug('ImageAndTextWebComponent', "from js data = " + data); 95 + Logger.debug('ImageAndTextWebComponent', "from js data = " + data);
101 }) 96 })
102 } 97 }
103 } 98 }
  1 +import { Action, ContentDetailDTO, ContentDTO, batchLikeAndCollectResult, InteractDataDTO, } from 'wdBean';
  2 +import DetailViewModel from '../viewmodel/DetailViewModel';
  3 +import { OperRowListView } from './view/OperRowListView';
  4 +import { WdWebComponent } from 'wdWebComponent';
  5 +import router from '@ohos.router';
  6 +import { CommonConstants } from 'wdConstant'
  7 +
  8 +const TAG = 'SpacialTopicPageComponent'
  9 +
  10 +@Component
  11 +export struct SpacialTopicPageComponent {
  12 + scroller: Scroller = new Scroller();
  13 + action: Action = {} as Action
  14 + private webUrl?: string;
  15 + @State contentDetailData: ContentDetailDTO [] = [] as ContentDetailDTO []
  16 + @State recommendList: ContentDTO[] = []
  17 + @State newsStatusOfUser: batchLikeAndCollectResult | undefined = undefined // 点赞、收藏状态
  18 + @State interactData: InteractDataDTO = {} as InteractDataDTO
  19 +
  20 + build() {
  21 + Column() {
  22 + Stack({ alignContent: Alignment.Bottom }) {
  23 + Column() {
  24 + WdWebComponent({
  25 + webUrl: this.webUrl,
  26 + backVisibility: false
  27 + })
  28 + }
  29 + .padding({bottom:56})
  30 + .width(CommonConstants.FULL_WIDTH)
  31 + .height(CommonConstants.FULL_HEIGHT)
  32 +
  33 + //底部交互区
  34 + Row() {
  35 + Image($r('app.media.icon_arrow_left'))
  36 + .width(24)
  37 + .height(24)
  38 + .onClick((event: ClickEvent) => {
  39 + router.back()
  40 + })
  41 +
  42 + Row() {
  43 + Image($r('app.media.icon_comment'))
  44 + .width(24)
  45 + .height(24)
  46 + .margin({ right: 24 })
  47 + .id('comment')
  48 +
  49 + Image($r('app.media.icon_star'))
  50 + .width(24)
  51 + .height(24)
  52 + .margin({ right: 24 })
  53 +
  54 + Image($r('app.media.icon_listen'))
  55 + .width(24)
  56 + .height(24)
  57 + .margin({ right: 24 })
  58 +
  59 + Image($r('app.media.icon_forward'))
  60 + .width(24)
  61 + .height(24)
  62 +
  63 + }
  64 + }
  65 + .width(CommonConstants.FULL_WIDTH)
  66 + .height(56)
  67 + .padding({ left: 15, right: 15, bottom: 20, top: 20 })
  68 + .justifyContent(FlexAlign.SpaceBetween)
  69 + .backgroundColor(Color.White)
  70 + }
  71 + }.width(CommonConstants.FULL_WIDTH).height(CommonConstants.FULL_HEIGHT)
  72 + .backgroundColor(Color.White)
  73 + }
  74 +
  75 + // private async getDetail() {
  76 + // let contentId: string = ''
  77 + // let relId: string = ''
  78 + // let relType: string = ''
  79 + // if (this.action && this.action.params) {
  80 + // if (this.action.params.contentID) {
  81 + // contentId = this.action.params.contentID;
  82 + // }
  83 + // if (this.action && this.action.params && this.action.params.extra) {
  84 + // if (this.action.params.extra.relId) {
  85 + // relId = this.action.params.extra.relId;
  86 + // }
  87 + // if (this.action.params.extra.relType) {
  88 + // relType = this.action.params.extra.relType
  89 + // }
  90 + //
  91 + // }
  92 + // let detailBeans = await DetailViewModel.getDetailPageData(relId, contentId, relType)
  93 + // if (detailBeans && detailBeans.length > 0) {
  94 + // this.contentDetailData = detailBeans;
  95 + // }
  96 + // }
  97 + // }
  98 +
  99 + aboutToAppear() {
  100 + let action: Action = router.getParams() as Action
  101 + if (action) {
  102 + this.webUrl = action.params?.url
  103 + }
  104 + // this.getDetail()
  105 + }
  106 +
  107 + aboutToDisappear() {
  108 + }
  109 +}
@@ -45,9 +45,9 @@ export struct Card3Component { @@ -45,9 +45,9 @@ export struct Card3Component {
45 .fontColor($r("app.color.color_B0B0B0")) 45 .fontColor($r("app.color.color_B0B0B0"))
46 .margin({ right: 6 }) 46 .margin({ right: 6 })
47 // TODO '评论取哪个字段' 47 // TODO '评论取哪个字段'
48 - // Text(`1806评`)  
49 - // .fontSize($r("app.float.font_size_12"))  
50 - // .fontColor($r("app.color.color_B0B0B0")) 48 + Text(`${this.contentDTO?.interactData?.commentNum}评`)
  49 + .fontSize($r("app.float.font_size_12"))
  50 + .fontColor($r("app.color.color_B0B0B0"))
51 }.width(CommonConstants.FULL_WIDTH) 51 }.width(CommonConstants.FULL_WIDTH)
52 .justifyContent(FlexAlign.Start) 52 .justifyContent(FlexAlign.Start)
53 .margin({ top: 8 }) 53 .margin({ top: 8 })
  1 +import PageModel from '../../../viewmodel/PageModel'
  2 +
  3 +
  4 +/// 所有用户类型定义
  5 +/// 1--普通账户正常;--不能直播、点播
  6 +/// 2--视频号,可以直播、点播;显示查看修改都是自己的信息;
  7 +/// 3--矩阵号,是有视频号升级来的;可以登陆app,我的里面是自己的信息;发评论、发视频、直播都是自己;矩阵号下面可以挂视频号、运营子账号;
  8 +/// 4--运营子账号,登陆使用的是自己的userId手机,密码;显示是对应视频号的信息,我的里面是视频号的信息,无法更改基本信息,自己没有头像,昵称信息;发点播、发直播、发评论,都是对应视频号的身份发送的;还是需要记录子账号的userId;(评论表 userId,userType,creatorId)
  9 +export enum WDPublicUserType {
  10 + /// 未知类型
  11 + WDPublicUserType_Unkown = 0,
  12 +
  13 + /// 普通用户
  14 + WDPublicUserType_NormalUser = 1,
  15 +
  16 + /// 号主
  17 + WDPublicUserType_AccountOwner = 2,
  18 +
  19 + /// 矩阵号
  20 + WDPublicUserType_Matrix = 3,
  21 +
  22 + /// 运营子账号
  23 + WDPublicUserType_OperatingSubAccount = 4,
  24 +
  25 + /// 内容源账号
  26 + WDPublicUserType_ContentSourceAccount = 5,
  27 +}
  28 +
  29 +@Observed
  30 +export class commentListModel extends PageModel{
  31 + pageNum: number = 0
  32 + pageSize: number = 0
  33 + totalCount: number = 0
  34 + hasNext: number = 0
  35 + list: commentItemModel[] = []
  36 +
  37 +}
  38 +
  39 +export class commentItemModel {
  40 + authorLike: string = ''
  41 + avatarFrame: string = ''
  42 + checkStatus: string = ''
  43 + childCommentNum: string = ''
  44 + childComments: commentItemModel[] = []
  45 + commentContent: string = ''
  46 + commentContentSensitive: string = ''
  47 + commentLevel: number = 0
  48 + commentPics: string = ''
  49 + commentSensitive: string = ''
  50 + commentType: number = 0
  51 + contentAuthor: number = 0
  52 + createTime: string = ''
  53 + creatorFlag: string = ''
  54 + fromCreatorId: string = ''
  55 + fromDeviceId: string = ''
  56 + fromUserHeader: string = ''
  57 + fromUserId: string = ''
  58 + fromUserName: string = ''
  59 + fromUserType: WDPublicUserType = 0
  60 + id: string = ''
  61 + likeNum: string = ''
  62 + /*是否点赞*/
  63 + isLike: boolean = false
  64 + mySelf: string = ''
  65 + parentId: string = ''
  66 + region: string = ''
  67 + replyNum: string = ''
  68 + rootCommentId: string = ''
  69 + sensitiveExist: string = ''
  70 + sensitiveShow: string = ''
  71 + toUserContentAuthor: string = ''
  72 + toUserId: string = ''
  73 + toUserName: string = ''
  74 + toUserType: string = ''
  75 + topFlag: string = ''
  76 + uuid: string = ''
  77 + /*本地使用,收起时默认3行 -1为不限制行数*/
  78 + maxLine: number = 3
  79 +
  80 + /*是否有展示更多*/
  81 + hasMore:boolean = false
  82 + /*当有展示更多的时候,当前的状态是展开还是收起*/
  83 + expanded:boolean = false
  84 +
  85 + highQualityExpireTime:string = '';
  86 + highQualityTime:string = '';
  87 + targetTitle:string = '';
  88 + targetStatus:string = '';
  89 + targetId:string = '';
  90 + targetRelId:string = '';
  91 + targetRelObjectId:string = '';
  92 + targetRelType:string = '';
  93 + targetType:string = '';
  94 + visitorComment:string = '';
  95 + shareInfo:commentItemShareInfoModel[] = []
  96 + // targetId:string = '';
  97 + // targetId:string = '';
  98 + // targetId:string = '';
  99 +
  100 +}
  101 +
  102 +export class commentItemShareInfoModel {
  103 + shareCoverUrl: string = ''
  104 + shareSummary: string = ''
  105 + shareTitle: string = ''
  106 + shareUrl: string = ''
  107 +}
  1 +import ArrayList from '@ohos.util.ArrayList'
  2 +import { ViewType } from 'wdConstant/Index';
  3 +import { LazyDataSource } from 'wdKit/Index';
  4 +import PageModel from '../../../viewmodel/PageModel';
  5 +import { commentItemModel, commentListModel, WDPublicUserType } from '../model/CommentModel';
  6 +import commentViewModel from '../viewmodel/CommentViewModel'
  7 +import { CommentText } from './CommentText';
  8 +import measure from '@ohos.measure'
  9 +
  10 +@Entry
  11 +@Preview
  12 +@Component
  13 +export struct CommentComponent {
  14 + @State private browSingModel: commentListModel = new commentListModel()
  15 + isloading: boolean = false
  16 + // @State allDatas :commentItemModel[] = [];
  17 +
  18 + @State allDatas: LazyDataSource<commentItemModel> = new LazyDataSource();
  19 +
  20 + aboutToAppear() {
  21 + this.getData();
  22 + this.getData();
  23 + this.getData();
  24 + this.getData();
  25 + }
  26 +
  27 + /*标题:全部评论*/
  28 + @Builder
  29 + titleHeader() {
  30 + Row() {
  31 + Row() {
  32 + Image($r('app.media.redLine'))
  33 + .height(16)
  34 + .width(3)
  35 + Text('全部评论')
  36 + .fontSize(18)// .fontColor('#222222')
  37 + .fontColor($r('app.color.color_222222'))
  38 + .fontWeight(FontWeight.Medium)
  39 + .margin({ left: 5 })
  40 +
  41 + }
  42 + .margin({ left: 16 })
  43 +
  44 + }.height(44)
  45 + .width('100%')
  46 + .justifyContent(FlexAlign.SpaceBetween);
  47 + }
  48 +
  49 + /*1级评论作为titleHeader*/
  50 + @Builder
  51 + CommentHeaderItem(item: commentItemModel) {
  52 + Column() {
  53 + Row() {
  54 + //头像
  55 + Stack() {
  56 + Image(item.fromUserHeader)
  57 + .alt($r('app.media.default_head'))
  58 + .width('32')
  59 + .height('32')
  60 + .objectFit(ImageFit.Cover)
  61 + .borderRadius(16)
  62 + Image($r('app.media.icon_border_test'))
  63 + .width('48')
  64 + .height('48')
  65 + .objectFit(ImageFit.Cover)
  66 + .borderRadius(24)
  67 + }
  68 + .width(48)
  69 + .height(48)
  70 + .margin({ left: 8 })
  71 + .alignContent(Alignment.Center)
  72 + .onClick(() => {
  73 + // TODO 跳转个人详情
  74 + })
  75 +
  76 + //昵称
  77 + Text(item.fromUserName)
  78 + .fontSize(14)
  79 + .fontColor($r('app.color.color_222222'))
  80 + .fontWeight(FontWeight.Medium)
  81 + .margin({ left: 5 })
  82 +
  83 +
  84 + /// 暂时不显示 “我” 的标签了
  85 + /// 人民号>置顶>作者
  86 +
  87 + //人民号
  88 + // if (item.fromUserType === WDPublicUserType.WDPublicUserType_Matrix) {
  89 + Image($r('app.media.comment_rmh_tag')).width(20).height(20).margin({ left: 5 });
  90 + // }
  91 + //置顶
  92 + // if (item.topFlag) {
  93 + Image($r('app.media.comment_icon_zhiding')).width(30).height(18).margin({ left: 5 });
  94 + // }
  95 + //作者
  96 + // if (item.contentAuthor === 1) {
  97 + Text('作者')
  98 + .fontSize(11)
  99 + .fontColor('#968562')
  100 + .backgroundColor('#F1EFEB')
  101 + .textAlign(TextAlign.Center)
  102 + .borderRadius(2)
  103 + .width(30)
  104 + .height(18)
  105 + .margin({ left: 5 });
  106 + // }
  107 + }
  108 +
  109 + CommentText({
  110 + longMessage: item.commentContent,
  111 + maxline: 3,
  112 + fontSize: 16,
  113 + fontWeight: FontWeight.Regular,
  114 + marginWidth: (59 + 16)
  115 + })
  116 + .margin({ left: 59, right: 16 })
  117 +
  118 +
  119 + this.CommentFooterView(item);
  120 + }.alignItems(HorizontalAlign.Start)
  121 +
  122 + }
  123 +
  124 + /*查看更多和收起*/
  125 + @Builder
  126 + GroupFooterView(item: commentItemModel) {
  127 + Row() {
  128 + if (item.expanded){
  129 + Row() {
  130 + Text('收起').fontColor($r('app.color.color_222222')).fontSize(14)
  131 + Image($r('app.media.comment_pickUp')).width(12).height(12)
  132 + }.margin({ left: 213 })
  133 + }else {
  134 + Row() {
  135 + Text().backgroundColor($r('app.color.color_EDEDED')).width(24).height(1)
  136 + Text('查看更多回复').fontColor($r('app.color.color_222222')).fontSize(14).margin({ left: 6 })
  137 + Image($r('app.media.comment_unfold')).width(12).height(12)
  138 + }.margin({ left: 53 })
  139 + }
  140 +
  141 +
  142 +
  143 +
  144 + }.height(30)
  145 + }
  146 +
  147 + /*评论内容下面的IP地址时间点赞*/
  148 + @Builder
  149 + CommentFooterView(item: commentItemModel) {
  150 + Row() {
  151 +
  152 + Row({ space: 6 }) {
  153 + Text(item.region ? (item.region + '网友') : '人民日报客户端网友')
  154 + .fontColor($r('app.color.color_B0B0B0'))
  155 + .fontSize(12);
  156 + Image($r('app.media.comment_hyphen'))
  157 + .size({
  158 + width: 4,
  159 + height: 4
  160 + })
  161 +
  162 + //TODO: 时间格式需要本地调整
  163 + // / 展现专用,用于获取多久之前
  164 + // ///小于1分钟:刚刚
  165 + // ///1~60分钟:x分钟前
  166 + // ///1小时~1天:x小时前
  167 + // ///1天~2天:1天前
  168 + // ///2天~:日期隐藏
  169 + Text(item.createTime)
  170 + .fontColor($r('app.color.color_B0B0B0'))
  171 + .fontSize(12)
  172 +
  173 + Image($r('app.media.comment_hyphen_block'))
  174 + .size({
  175 + width: 4,
  176 + height: 4
  177 + })
  178 +
  179 + Text('回复')
  180 + .fontColor($r('app.color.color_222222'))
  181 + .fontSize(12)
  182 + .onClick(() => {
  183 + //TODO: 回复
  184 + })
  185 + }
  186 +
  187 + Row({ space: 6 }) {
  188 + Text(item.likeNum)
  189 + .fontColor($r('app.color.color_666666'))
  190 + .fontSize(14)
  191 +
  192 + Image($r('app.media.comment_like_normal'))
  193 + .size({
  194 + width: 16,
  195 + height: 16
  196 + })
  197 + .onClick(() => {
  198 + //TODO: 点赞
  199 + })
  200 + }
  201 +
  202 + }
  203 + .justifyContent(FlexAlign.SpaceBetween)
  204 + .height(30)
  205 + .margin({ left: 59, right: 16 })
  206 + }
  207 +
  208 + build() {
  209 + Column() {
  210 +
  211 + List() {
  212 + ListItemGroup({ header: this.titleHeader() })
  213 + LazyForEach(this.allDatas, (item: commentItemModel, index: number) => {
  214 + if (item.hasMore) {
  215 + ListItemGroup({ header: this.CommentHeaderItem(item), footer: this.GroupFooterView(item) }) {
  216 + ForEach(item.childComments, (childItem: commentItemModel, subIndex: number) => {
  217 + ListItem() {
  218 + ChildCommentItem();
  219 + }
  220 + })
  221 + }
  222 + }else {
  223 + ListItemGroup({ header: this.CommentHeaderItem(item)}) {
  224 + ForEach(item.childComments, (childItem: commentItemModel, subIndex: number) => {
  225 + ListItem() {
  226 + ChildCommentItem();
  227 + }
  228 + })
  229 + }
  230 + }
  231 + })
  232 + }.layoutWeight(1)
  233 + }
  234 + }
  235 +
  236 + //获取数据
  237 + async getData() {
  238 + this.browSingModel.currentPage = 1
  239 + commentViewModel.getCommentLocal(getContext()).then(commentListModel => {
  240 + if (commentListModel && commentListModel.list && commentListModel.list.length > 0) {
  241 + commentListModel.hasMore = true;
  242 + this.browSingModel.viewType = ViewType.LOADED;
  243 + this.allDatas.push(...commentListModel.list)
  244 + if (commentListModel.list.length === this.browSingModel.pageSize) {
  245 + this.browSingModel.currentPage++;
  246 + this.browSingModel.hasMore = true;
  247 + } else {
  248 + this.browSingModel.hasMore = false;
  249 + }
  250 + } else {
  251 + this.browSingModel.viewType = ViewType.EMPTY;
  252 + }
  253 +
  254 +
  255 +
  256 + })
  257 + }
  258 +
  259 + /*回复评论*/
  260 + ReplyComment() {
  261 +
  262 + }
  263 +}
  264 +
  265 +
  266 +@Component
  267 +struct ChildCommentItem {
  268 + build() {
  269 + Text('child')
  270 + }
  271 +}
  272 +
  1 +import measure from '@ohos.measure'
  2 +import curves from '@ohos.curves';
  3 +import { BusinessError } from '@ohos.base';
  4 +import display from '@ohos.display';
  5 +
  6 +const collapseString = '...展开全文'
  7 +const uncollapseString = '...收起'
  8 +
  9 +@Component
  10 +@Preview
  11 +export struct CommentText {
  12 + // 长文本
  13 + @State longMessage: string = ''
  14 + // 最大显示行数
  15 + @State maxLineMesssage: string = '';
  16 +
  17 + @State lines: number = 3;
  18 + @State maxline: number = 3;
  19 + @State marginWidth:number = 0;
  20 + // 长文本状态(展开 or 收起)
  21 + @State collapseText: string = collapseString
  22 + // 屏幕宽度(单位px)
  23 + screenWidth: number = 0;
  24 + // 是否需要显示"展开"字样(注:当文本长度较短时就不需要“展开”)
  25 + @State isExpanded: boolean = false
  26 + /*当前展开状态*/
  27 + @State expandedStates: boolean = false;
  28 + @State fontSize: number = 18;
  29 + @State fontWeight: FontWeight = FontWeight.Regular
  30 + fontColor: ResourceColor = $r('app.color.color_222222')
  31 + // 测量文本宽度(单位px)
  32 + @State textWidth: number = 0;
  33 +
  34 + // constructor(longMessage?:string,) {
  35 + // super();
  36 + // this.longMessage = longMessage;
  37 + // }
  38 + // 获取当前所有的display对象
  39 + promise: Promise<Array<display.Display>> = display.getAllDisplays()
  40 +
  41 +
  42 +
  43 + aboutToAppear() {
  44 + console.log(`文本宽度为:${this.textWidth}`)
  45 + let padding = vp2px(5 + this.marginWidth)
  46 +
  47 + this.textWidth = measure.measureText({
  48 + textContent: this.longMessage,
  49 + fontSize: this.fontSize,
  50 + fontWeight: this.fontWeight,
  51 + constraintWidth:(this.screenWidth - padding)
  52 + })
  53 +
  54 + console.log(`文本宽度为:${this.textWidth}`)
  55 +
  56 + this.promise.then((data: Array<display.Display>) => {
  57 + console.log(`所有的屏幕信息:${JSON.stringify(data)}`)
  58 + //单位为像素
  59 + this.screenWidth = data[0]["width"]
  60 + // 屏幕宽度 * 最大行数 * 组件宽度比例 和 文字测量宽度
  61 + this.isExpanded = (this.screenWidth - padding) * this.lines <= this.textWidth
  62 + // this.expandedStates = this.isExpanded;
  63 +
  64 + //需要展开的话计算3行需要显示的文字
  65 + if (this.isExpanded) {
  66 +
  67 +
  68 + let padding = vp2px(5 + this.marginWidth)
  69 + let maxLineTextWidth = (this.screenWidth - padding) * this.maxline;
  70 +
  71 + for (let index = 0; index < this.longMessage.length; index++) {
  72 + const element = this.longMessage.substring(0, index)
  73 + const string = element + this.collapseText; //截取
  74 + const thisTextWidth = measure.measureText({
  75 + textContent: string,
  76 + fontSize: this.fontSize,
  77 + fontWeight: this.fontWeight,
  78 + constraintWidth:(this.screenWidth - padding)
  79 + })
  80 +
  81 + //计算有误差20
  82 +
  83 + if (thisTextWidth >= maxLineTextWidth) {
  84 + break
  85 + }
  86 + this.maxLineMesssage = element;
  87 +
  88 + }
  89 + }
  90 +
  91 +
  92 + }).catch((err: BusinessError) => {
  93 + console.error(`Failed to obtain all the display objects. Code: ${JSON.stringify(err)}`)
  94 + })
  95 +
  96 +
  97 + }
  98 +
  99 + build() {
  100 + Row() {
  101 + Column() {
  102 + if (this.isExpanded) {
  103 + // Stack({ alignContent: Alignment.BottomEnd }) {
  104 + Text(this.longMessage) {
  105 + Span(this.expandedStates ? this.longMessage : this.maxLineMesssage)
  106 + Span(this.collapseText).onClick(() => {
  107 + if (this.collapseText == collapseString) {
  108 + this.collapseText = uncollapseString;
  109 + this.expandedStates = true;
  110 + this.lines = -1; // 使得设置的最大行属性无效
  111 + // 展开动画
  112 + // animateTo({
  113 + // duration: 150,
  114 + // curve: curves.springMotion(),
  115 + // }, () => {
  116 + // this.lines = -1; // 使得设置的最大行属性无效
  117 + // })
  118 + } else {
  119 + this.collapseText = collapseString;
  120 + this.expandedStates = false;
  121 + this.lines = this.maxline; // 只显示3行
  122 + // 收起动画
  123 + // animateTo({
  124 + // duration: 100,
  125 + // curve: Curve.Friction,
  126 + // }, () => {
  127 + // this.lines = this.maxline; // 只显示3行
  128 + // })
  129 + }
  130 + })
  131 + }
  132 + .width('100%')
  133 + .fontSize(this.fontSize)
  134 + .fontWeight(this.fontWeight)
  135 + .fontColor(this.fontColor)
  136 + .maxLines(this.lines)
  137 + // .backgroundColor(Color.Red)
  138 +
  139 + // }
  140 + }
  141 + else {
  142 + Text('我没有展开收起')
  143 + .width('100%')
  144 + .fontSize(this.fontSize)
  145 + .fontWeight(this.fontWeight)
  146 + .fontColor(this.fontColor)
  147 + }
  148 + }
  149 + // .backgroundColor(Color.Brown)
  150 + .width('100%')
  151 + }
  152 +
  153 + // .height('100%')
  154 + }
  155 +}
  156 +
  157 +
  158 +// Index.ets
  159 +@Entry
  160 +@Component
  161 +struct Index {
  162 + build() {
  163 + Column() {
  164 + CommentText()
  165 + }
  166 + }
  167 +}
  1 +import { ViewType } from 'wdConstant/Index'
  2 +import { LazyDataSource } from 'wdKit/Index'
  3 +import { commentItemModel, commentListModel } from '../model/CommentModel'
  4 +import commentViewModel from '../viewmodel/CommentViewModel'
  5 +
  6 +@Entry
  7 +@Preview
  8 +@Component
  9 +export struct QualityCommentsComponent {
  10 + @State private browSingModel: commentListModel = new commentListModel()
  11 + isloading: boolean = false
  12 + @State allDatas: LazyDataSource<commentItemModel> = new LazyDataSource();
  13 +
  14 + aboutToAppear(): void {
  15 +
  16 + commentViewModel.fetchQualityCommentList('1').then((commentListModel)=>{
  17 + if (commentListModel && commentListModel.list && commentListModel.list.length > 0) {
  18 + commentListModel.hasMore = true;
  19 + this.browSingModel.viewType = ViewType.LOADED;
  20 + this.allDatas.push(...commentListModel.list)
  21 + if (commentListModel.list.length === this.browSingModel.pageSize) {
  22 + this.browSingModel.currentPage++;
  23 + this.browSingModel.hasMore = true;
  24 + } else {
  25 + this.browSingModel.hasMore = false;
  26 + }
  27 + } else {
  28 + this.browSingModel.viewType = ViewType.EMPTY;
  29 + }
  30 + })
  31 + }
  32 +
  33 + build() {
  34 +
  35 + }
  36 +}
  1 +import { Logger, ResourcesUtils } from 'wdKit/Index';
  2 +import { HttpUrlUtils, ResponseDTO } from 'wdNetwork/Index';
  3 +import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest';
  4 +import { commentItemModel, commentListModel } from '../model/CommentModel';
  5 +import HashMap from '@ohos.util.HashMap';
  6 +
  7 +const TAG = "CommentViewModel"
  8 +
  9 +class CommentViewModel {
  10 + private static instance: CommentViewModel
  11 + /**
  12 + * 单例模式
  13 + * @returns
  14 + */
  15 + public static getInstance(): CommentViewModel {
  16 + if (!CommentViewModel.instance) {
  17 + CommentViewModel.instance = new CommentViewModel();
  18 + }
  19 + return CommentViewModel.instance;
  20 + }
  21 +
  22 +
  23 + /*获取本地mock数据*/
  24 + async getCommentLocal(context: Context): Promise<commentListModel> {
  25 + Logger.info(TAG, `getBottomNavDataMock start`);
  26 + let compRes: ResponseDTO<commentListModel> | null = await ResourcesUtils.getResourcesJson<ResponseDTO<commentListModel>>(context,'comment_local.json' );
  27 + if (!compRes || !compRes.data) {
  28 + Logger.info(TAG, `getAppointmentListDataLocal compRes is empty`);
  29 + return new commentListModel()
  30 + }
  31 + Logger.info(TAG, `getAppointmentListDataLocal getResourcesJsonSync compRes : ${JSON.stringify(compRes)}`);
  32 + return compRes.data
  33 + }
  34 +
  35 +
  36 + fetchQualityCommentList(pageNum: string) {
  37 + let url = HttpUrlUtils.getQualityCommentUrl() + `?&pageSize=${10}&pageNum=${pageNum}`
  38 + let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
  39 + return new Promise<commentListModel>((success, fail) => {
  40 + HttpRequest.get<ResponseDTO<commentListModel>>(url, headers).then((data: ResponseDTO<commentListModel>) => {
  41 + if (!data || !data.data) {
  42 + fail("数据为空")
  43 + return
  44 + }
  45 + if (data.code != 0) {
  46 + fail(data.message)
  47 + return
  48 + }
  49 + let listData = data.data as commentListModel
  50 +
  51 + success(listData)
  52 + }, (error: Error) => {
  53 + fail(error.message)
  54 + Logger.debug(TAG, error.toString())
  55 + })
  56 + })
  57 + }
  58 +
  59 +
  60 + // BaseGetRequest(contentID:number,contentType:string,pageNum:string){
  61 + // let url = HttpUrlUtils.getMyCollectionListDataUrl()+ `?type=${type}&operateTag=${1}&pageSize=${10}&pageNum=${pageNum}`
  62 + // if (tagId.length > 0) {
  63 + // url = url + `&tagId=${tagId}`
  64 + // }
  65 + // let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders()
  66 + // return WDHttp.get<ResponseDTO<commentListModel>>(url, headers)
  67 + // }
  68 + //
  69 + //
  70 + // fetchCommentList(contentID:number,contentType:string,pageNum:string):Promise<commentListModel>{
  71 + // return new Promise<commentListModel>((success,error) => {
  72 + // this.BaseGetRequest(contentID,contentType,pageNum).then((navResDTO: ResponseDTO<commentListModel>) => {
  73 + // if (!navResDTO || navResDTO.code != 0) {
  74 + // // success(this.getAppointmentListDataLocal(context))
  75 + // return
  76 + // }
  77 + // Logger.info(TAG, "getAppointmentList then,AppointmentResDTO.timeStamp:" + navResDTO.timestamp);
  78 + // let listData = navResDTO.data as commentListModel
  79 + // success(listData)
  80 + // }).catch((err: Error) => {
  81 + // Logger.error(TAG, `fetchAppointmentListDataApi catch, error.name : ${err.name}, error.message:${err.message}`);
  82 + // error("page data invalid");
  83 + // })
  84 + // })
  85 + // }
  86 +
  87 +
  88 +}
  89 +
  90 +
  91 +const commentViewModel = CommentViewModel.getInstance();
  92 +
  93 +export default commentViewModel as CommentViewModel
@@ -288,7 +288,6 @@ struct ChannelDialog { @@ -288,7 +288,6 @@ struct ChannelDialog {
288 .justifyContent(FlexAlign.Center) 288 .justifyContent(FlexAlign.Center)
289 .backgroundColor(item.homeChannel === '1' || item.movePermitted === 0 ? '#F5F5F5' : '#ffffff') 289 .backgroundColor(item.homeChannel === '1' || item.movePermitted === 0 ? '#F5F5F5' : '#ffffff')
290 .onClick(() => { 290 .onClick(() => {
291 - console.log('onTouch')  
292 if (this.isEditIng) { 291 if (this.isEditIng) {
293 if (item.delPermitted === 1) { 292 if (item.delPermitted === 1) {
294 this.delChannelItem(index) 293 this.delChannelItem(index)
@@ -182,14 +182,13 @@ export struct PageComponent { @@ -182,14 +182,13 @@ export struct PageComponent {
182 } else { 182 } else {
183 this.pageModel.hasMore = false; 183 this.pageModel.hasMore = false;
184 } 184 }
185 - // // 二次请求,批查互动数据  
186 - // PageViewModel.getInteractData(pageDto.compList).then((data: CompDTO[]) => {  
187 - // // 刷新,替换所有数据  
188 - // this.pageModel.compList.replaceAll(...data)  
189 - // this.pageModel.timestamp = DateTimeUtils.getTimeStamp().toString()  
190 - // }) 185 + // 二次请求,批查互动数据
  186 + PageViewModel.getInteractData(this.pageDto.compList).then((data: CompDTO[]) => {
  187 + // 刷新,替换所有数据
  188 + this.pageModel.compList.replaceAll(...data)
  189 + this.pageModel.timestamp = DateTimeUtils.getTimeStamp().toString()
  190 + })
191 this.isFirstIn = false 191 this.isFirstIn = false
192 - Logger.debug(TAG, 'cj111');  
193 // } else { 192 // } else {
194 // Logger.debug(TAG, 'aboutToAppear, data response page ' + this.pageId + ', comp list is empty.'); 193 // Logger.debug(TAG, 'aboutToAppear, data response page ' + this.pageId + ', comp list is empty.');
195 // this.pageModel.viewType = ViewType.EMPTY; 194 // this.pageModel.viewType = ViewType.EMPTY;
@@ -3,7 +3,7 @@ import MinePagePersonalFunctionsItem from '../viewmodel/MinePagePersonalFunction @@ -3,7 +3,7 @@ import MinePagePersonalFunctionsItem from '../viewmodel/MinePagePersonalFunction
3 import MinePageCreatorFunctionsItem from '../viewmodel/MinePageCreatorFunctionsItem' 3 import MinePageCreatorFunctionsItem from '../viewmodel/MinePageCreatorFunctionsItem'
4 import MinePageMoreFunctionModel from '../viewmodel/MinePageMoreFunctionModel'; 4 import MinePageMoreFunctionModel from '../viewmodel/MinePageMoreFunctionModel';
5 import HashMap from '@ohos.util.HashMap'; 5 import HashMap from '@ohos.util.HashMap';
6 -import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork'; 6 +import { HttpBizUtil, HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork';
7 import { MineAppointmentListItem } from '../viewmodel/MineAppointmentListItem'; 7 import { MineAppointmentListItem } from '../viewmodel/MineAppointmentListItem';
8 import { Logger, ResourcesUtils, StringUtils } from 'wdKit'; 8 import { Logger, ResourcesUtils, StringUtils } from 'wdKit';
9 import { MineFollowListDetailItem } from '../viewmodel/MineFollowListDetailItem'; 9 import { MineFollowListDetailItem } from '../viewmodel/MineFollowListDetailItem';
@@ -371,7 +371,8 @@ class MinePageDatasModel{ @@ -371,7 +371,8 @@ class MinePageDatasModel{
371 fetchMineUserLevelData() { 371 fetchMineUserLevelData() {
372 let url = HttpUrlUtils.getMineUserLevelDataUrl() 372 let url = HttpUrlUtils.getMineUserLevelDataUrl()
373 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); 373 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
374 - return WDHttp.get<ResponseDTO<MineUserLevelItem>>(url, headers) 374 + // return WDHttp.get<ResponseDTO<MineUserLevelItem>>(url, headers)
  375 + return HttpBizUtil.get<MineUserLevelItem>(url, headers)
375 }; 376 };
376 377
377 async getMineUserLevelDataLocal(context: Context): Promise<MineUserLevelItem> { 378 async getMineUserLevelDataLocal(context: Context): Promise<MineUserLevelItem> {
@@ -409,7 +410,8 @@ class MinePageDatasModel{ @@ -409,7 +410,8 @@ class MinePageDatasModel{
409 fetchMineUserDetailData() { 410 fetchMineUserDetailData() {
410 let url = HttpUrlUtils.getMineUserDetailDataUrl() 411 let url = HttpUrlUtils.getMineUserDetailDataUrl()
411 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); 412 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
412 - return WDHttp.get<ResponseDTO<MineUserDetailItem>>(url, headers) 413 + // return WDHttp.get<ResponseDTO<MineUserDetailItem>>(url, headers)
  414 + return HttpBizUtil.get<MineUserDetailItem>(url, headers)
413 }; 415 };
414 416
415 async getMineUserDetailDataLocal(context: Context): Promise<MineUserDetailItem> { 417 async getMineUserDetailDataLocal(context: Context): Promise<MineUserDetailItem> {
@@ -103,9 +103,10 @@ export class ProcessUtils { @@ -103,9 +103,10 @@ export class ProcessUtils {
103 103
104 private static gotoSpecialTopic(content: ContentDTO) { 104 private static gotoSpecialTopic(content: ContentDTO) {
105 let taskAction: Action = { 105 let taskAction: Action = {
106 - type: 'JUMP_H5_BY_WEB_VIEW', 106 + type: 'JUMP_INNER_NEW_PAGE',
107 params: { 107 params: {
108 - url: content.linkUrl 108 + url: content.linkUrl,
  109 + pageID: 'SPACIAL_TOPIC_PAGE',
109 } as Params, 110 } as Params,
110 }; 111 };
111 WDRouterRule.jumpWithAction(taskAction) 112 WDRouterRule.jumpWithAction(taskAction)
@@ -11,22 +11,26 @@ export class LogoutViewModel{ @@ -11,22 +11,26 @@ export class LogoutViewModel{
11 requestLogout(){ 11 requestLogout(){
12 return new Promise<string>((success, fail) => { 12 return new Promise<string>((success, fail) => {
13 this.logout.requestLogout().then((data) => { 13 this.logout.requestLogout().then((data) => {
14 - SPHelper.default.save(SpConstants.USER_FIRST_MARK, '')  
15 - SPHelper.default.save(SpConstants.USER_ID, '')  
16 - SPHelper.default.save(SpConstants.USER_JWT_TOKEN, '')  
17 - SPHelper.default.save(SpConstants.USER_LONG_TIME_NO_LOGIN_MARK, '')  
18 - SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, '')  
19 - SPHelper.default.save(SpConstants.USER_STATUS, '')  
20 - SPHelper.default.save(SpConstants.USER_Type, '')  
21 - SPHelper.default.save(SpConstants.USER_NAME, '')  
22 - SPHelper.default.save(SpConstants.USER_PHONE, '')  
23 - HttpUrlUtils.setUserId("")  
24 - HttpUrlUtils.setUserType("")  
25 - HttpUrlUtils.setUserToken('') 14 + LogoutViewModel.clearLoginInfo()
26 success(data) 15 success(data)
27 }).catch((message: string) => { 16 }).catch((message: string) => {
28 fail(message) 17 fail(message)
29 }) 18 })
30 }) 19 })
31 } 20 }
  21 +
  22 + static clearLoginInfo() {
  23 + SPHelper.default.save(SpConstants.USER_FIRST_MARK, '')
  24 + SPHelper.default.save(SpConstants.USER_ID, '')
  25 + SPHelper.default.save(SpConstants.USER_JWT_TOKEN, '')
  26 + SPHelper.default.save(SpConstants.USER_LONG_TIME_NO_LOGIN_MARK, '')
  27 + SPHelper.default.save(SpConstants.USER_REFRESH_TOKEN, '')
  28 + SPHelper.default.save(SpConstants.USER_STATUS, '')
  29 + SPHelper.default.save(SpConstants.USER_Type, '')
  30 + SPHelper.default.save(SpConstants.USER_NAME, '')
  31 + SPHelper.default.save(SpConstants.USER_PHONE, '')
  32 + HttpUrlUtils.setUserId("")
  33 + HttpUrlUtils.setUserType("")
  34 + HttpUrlUtils.setUserToken('')
  35 + }
32 } 36 }
1 import HashMap from '@ohos.util.HashMap'; 1 import HashMap from '@ohos.util.HashMap';
2 import { HttpUrlUtils, ResponseDTO } from 'wdNetwork'; 2 import { HttpUrlUtils, ResponseDTO } from 'wdNetwork';
3 -import { Logger, SPHelper } from 'wdKit'; 3 +import { Logger, SPHelper, StringUtils } from 'wdKit';
4 import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; 4 import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest';
5 import { LoginBean } from './LoginBean'; 5 import { LoginBean } from './LoginBean';
6 import { CheckVerifyBean } from './CheckVerifyBean'; 6 import { CheckVerifyBean } from './CheckVerifyBean';
@@ -200,20 +200,35 @@ export class LoginModel { @@ -200,20 +200,35 @@ export class LoginModel {
200 bean['tempToken'] = tempToken; 200 bean['tempToken'] = tempToken;
201 201
202 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); 202 let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders();
203 - let JwtToken = SPHelper.default.getSync(SpConstants.USER_JWT_TOKEN, '') as string; 203 + // let JwtToken = SPHelper.default.getSync(SpConstants.USER_JWT_TOKEN, '') as string;
  204 + // headers.set('JwtToken',(JwtToken));
  205 + // headers.set('rmrb-x-token',(JwtToken));
  206 + // headers.set('cookie', 'RMRB-X-TOKEN=' + JwtToken)
  207 +
  208 +
  209 +// let obj: Record<string, string> = {};
  210 +// headers.forEach((value, key) =>{
  211 +// if(key != undefined && key != null && value != undefined && value != null) {
  212 +// obj[key as string] = value;
  213 +// }
  214 +// })
  215 +// let headerString = JSON.stringify(obj);
  216 +// let beanString = JSON.stringify(bean);
  217 +// AlertDialog.show({
  218 +// message:headerString + beanString
  219 +// })
204 220
205 - headers.set('JwtToken',(JwtToken));  
206 - headers.set('rmrb-x-token',(JwtToken));  
207 return new Promise<string>((success, fail) => { 221 return new Promise<string>((success, fail) => {
208 HttpRequest.post<ResponseDTO<string>>(HttpUrlUtils.getForgetPasswordUrl(), bean, headers).then((data: ResponseDTO<string>) => { 222 HttpRequest.post<ResponseDTO<string>>(HttpUrlUtils.getForgetPasswordUrl(), bean, headers).then((data: ResponseDTO<string>) => {
209 - if (!data || !data.data) {  
210 - fail("数据为空")  
211 - return  
212 - } 223 +
213 if (data.code != 0) { 224 if (data.code != 0) {
214 fail(data.message) 225 fail(data.message)
215 return 226 return
216 } 227 }
  228 + if (!data || !data.data) {
  229 + fail("数据为空")
  230 + return
  231 + }
217 success(data.data) 232 success(data.data)
218 }, (error: Error) => { 233 }, (error: Error) => {
219 fail(error.message) 234 fail(error.message)
@@ -7,10 +7,8 @@ import cryptoFramework from '@ohos.security.cryptoFramework' @@ -7,10 +7,8 @@ import cryptoFramework from '@ohos.security.cryptoFramework'
7 import buffer from '@ohos.buffer' 7 import buffer from '@ohos.buffer'
8 import { encryptMessage } from '../../utils/cryptoUtil' 8 import { encryptMessage } from '../../utils/cryptoUtil'
9 9
10 -import {  
11 - SpConstants  
12 -} from '../../../../../../../commons/wdNetwork/oh_modules/wdConstant/src/main/ets/constants/SpConstants'  
13 import { HttpUrlUtils } from 'wdNetwork/src/main/ets/http/HttpUrlUtils' 10 import { HttpUrlUtils } from 'wdNetwork/src/main/ets/http/HttpUrlUtils'
  11 +import { SpConstants } from 'wdConstant/Index'
14 12
15 const TAG = "LoginViewModel" 13 const TAG = "LoginViewModel"
16 14
1 -import { BottomNavigationComponent} from 'wdComponent'; 1 +import { BottomNavigationComponent, LogoutViewModel} from 'wdComponent';
2 import { BreakpointConstants } from 'wdConstant'; 2 import { BreakpointConstants } from 'wdConstant';
3 3
4 -import { BreakpointSystem, Logger } from 'wdKit'; 4 +import { BreakpointSystem, EmitterEventId, EmitterUtils, Logger } from 'wdKit';
5 import router from '@ohos.router'; 5 import router from '@ohos.router';
  6 +import { promptAction } from '@kit.ArkUI';
6 7
7 8
8 const TAG = 'MainPage'; 9 const TAG = 'MainPage';
@@ -22,6 +23,9 @@ struct MainPage { @@ -22,6 +23,9 @@ struct MainPage {
22 aboutToAppear() { 23 aboutToAppear() {
23 this.breakpointSystem.register() 24 this.breakpointSystem.register()
24 Logger.info(TAG, `aboutToAppear `); 25 Logger.info(TAG, `aboutToAppear `);
  26 + EmitterUtils.receiveEvent(EmitterEventId.FORCE_USER_LOGIN_OUT, () => {
  27 + LogoutViewModel.clearLoginInfo()
  28 + })
25 } 29 }
26 30
27 aboutToDisappear() { 31 aboutToDisappear() {
  1 +import { Action } from 'wdBean';
  2 +import { SpacialTopicPageComponent } from 'wdComponent'
  3 +import { Logger } from 'wdKit'
  4 +import router from '@ohos.router';
  5 +
  6 +const TAG = 'SpacialPage';
  7 +
  8 +@Entry
  9 +@Component
  10 +struct SpacialTopicPage {
  11 + action: Action = {} as Action
  12 +
  13 + build() {
  14 + Column() {
  15 + SpacialTopicPageComponent()
  16 + }
  17 + }
  18 +
  19 + pageTransition(){
  20 + // 定义页面进入时的效果,从右边侧滑入
  21 + PageTransitionEnter({ type: RouteType.None, duration: 300 })
  22 + .slide(SlideEffect.Right)
  23 + // 定义页面退出时的效果,向右边侧滑出
  24 + PageTransitionExit({ type: RouteType.None, duration: 300 })
  25 + .slide(SlideEffect.Right)
  26 + }
  27 +
  28 +
  29 + aboutToAppear() {
  30 + Logger.info(TAG, 'aboutToAppear');
  31 + let action: Action = router.getParams() as Action
  32 + this.action = action
  33 + }
  34 +
  35 + aboutToDisappear() {
  36 + Logger.info(TAG, 'aboutToDisappear');
  37 + }
  38 +
  39 + onPageShow() {
  40 + Logger.info(TAG, 'onPageShow');
  41 + }
  42 +
  43 + onPageHide() {
  44 + Logger.info(TAG, 'onPageHide');
  45 + }
  46 +
  47 + onBackPress() {
  48 + Logger.info(TAG, 'onBackPress');
  49 + }
  50 +}
  1 +{
  2 + "code": "0",
  3 + "data": {
  4 + "hasNext": 1,
  5 + "list": [{
  6 + "authorLike": 0,
  7 + "avatarFrame": "",
  8 + "checkStatus": 2,
  9 + "childCommentNum": 0,
  10 + "childComments": [],
  11 + "commentContent": "走在繁华的城市街头,明空感到无比紧张。他的心跳如雷鼓般擂动着胸膛,使得身上的伪装仿佛随时都要被揭开。然而,他仍然保持着冷静,凭借着过人的胆识与智慧,成功地躲过了敌人的层层封锁。走在繁华的城市街头,明空感到无比紧张。他的心跳如雷鼓般擂动着胸膛,使得身上的伪装仿佛随时都要被揭开。然而,他仍然保持着冷静,凭借着过人的胆识与智慧,成功地躲过了敌人的层层封锁。走在繁华的城市街头,明空感到无比紧张。他的心跳如雷鼓般擂动着胸膛,使得身上的伪装仿佛随时都要被揭开。然而,他仍然保持着冷静,凭借着过人的胆识与智慧,成功地躲过了敌人的层层封锁。",
  12 + "commentContentSensitive": "",
  13 + "commentLevel": 1,
  14 + "commentPics": "",
  15 + "commentSensitive": "",
  16 + "commentType": "1",
  17 + "contentAuthor": 0,
  18 + "createTime": "2024-04-09 18:07:24",
  19 + "creatorFlag": 0,
  20 + "fromCreatorId": "",
  21 + "fromDeviceId": "",
  22 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/202010/rmrb_mMCZxkBw1602498775.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  23 + "fromUserId": "531160058210565",
  24 + "fromUserName": "**勇",
  25 + "fromUserType": 1,
  26 + "id": 57187947,
  27 + "likeNum": 4,
  28 + "mySelf": 0,
  29 + "parentId": -1,
  30 + "region": "新疆维吾尔自治区乌鲁木齐市",
  31 + "replyNum": 0,
  32 + "rootCommentId": 57187947,
  33 + "sensitiveExist": 0,
  34 + "sensitiveShow": 1,
  35 + "toUserContentAuthor": 0,
  36 + "toUserId": "",
  37 + "toUserName": "",
  38 + "toUserType": null,
  39 + "topFlag": 0,
  40 + "uuid": "c31fe10c-38b4-48f9-a847-eeb33ffae35e"
  41 + }, {
  42 + "authorLike": 0,
  43 + "avatarFrame": "",
  44 + "checkStatus": 2,
  45 + "childCommentNum": 0,
  46 + "childComments": [],
  47 + "commentContent": "咎由自取",
  48 + "commentContentSensitive": "",
  49 + "commentLevel": 1,
  50 + "commentPics": "",
  51 + "commentSensitive": "",
  52 + "commentType": "1",
  53 + "contentAuthor": 0,
  54 + "createTime": "2024-04-09 17:59:17",
  55 + "creatorFlag": 0,
  56 + "fromCreatorId": "",
  57 + "fromDeviceId": "",
  58 + "fromUserHeader": "http://thirdqq.qlogo.cn/qqapp/100857255/F4069650B754E8DEDB65DFCCB6261211/100",
  59 + "fromUserId": "530949198104837",
  60 + "fromUserName": "[@王者之师@]",
  61 + "fromUserType": 1,
  62 + "id": 57255431,
  63 + "likeNum": 3,
  64 + "mySelf": 0,
  65 + "parentId": -1,
  66 + "region": "河南省商丘市",
  67 + "replyNum": 0,
  68 + "rootCommentId": 57255431,
  69 + "sensitiveExist": 0,
  70 + "sensitiveShow": 1,
  71 + "toUserContentAuthor": 0,
  72 + "toUserId": "",
  73 + "toUserName": "",
  74 + "toUserType": null,
  75 + "topFlag": 0,
  76 + "uuid": "a44b8513-4e7e-4644-b0ed-37fa3fd98788"
  77 + }, {
  78 + "authorLike": 0,
  79 + "avatarFrame": "",
  80 + "checkStatus": 2,
  81 + "childCommentNum": 0,
  82 + "childComments": [],
  83 + "commentContent": "违纪违法,严惩不贷!",
  84 + "commentContentSensitive": "",
  85 + "commentLevel": 1,
  86 + "commentPics": "",
  87 + "commentSensitive": "",
  88 + "commentType": "1",
  89 + "contentAuthor": 0,
  90 + "createTime": "2024-04-09 17:44:10",
  91 + "creatorFlag": 0,
  92 + "fromCreatorId": "",
  93 + "fromDeviceId": "",
  94 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/202010/rmrb_ZTKHKDIA1603932748.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  95 + "fromUserId": "531165579823365",
  96 + "fromUserName": "哆啦A梦伴我同行",
  97 + "fromUserType": 1,
  98 + "id": 57186915,
  99 + "likeNum": 3,
  100 + "mySelf": 0,
  101 + "parentId": -1,
  102 + "region": "安徽省铜陵市",
  103 + "replyNum": 0,
  104 + "rootCommentId": 57186915,
  105 + "sensitiveExist": 0,
  106 + "sensitiveShow": 1,
  107 + "toUserContentAuthor": 0,
  108 + "toUserId": "",
  109 + "toUserName": "",
  110 + "toUserType": null,
  111 + "topFlag": 0,
  112 + "uuid": "d9c7bd8f-59e8-46cb-9525-d4414049a8ea"
  113 + }, {
  114 + "authorLike": 0,
  115 + "avatarFrame": "",
  116 + "checkStatus": 2,
  117 + "childCommentNum": 0,
  118 + "childComments": [],
  119 + "commentContent": "反腐倡廉,没有禁区",
  120 + "commentContentSensitive": "",
  121 + "commentLevel": 1,
  122 + "commentPics": "",
  123 + "commentSensitive": "",
  124 + "commentType": "1",
  125 + "contentAuthor": 0,
  126 + "createTime": "2024-04-09 17:36:44",
  127 + "creatorFlag": 0,
  128 + "fromCreatorId": "",
  129 + "fromDeviceId": "",
  130 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/201709/rmrb_RIg022m31504938430.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  131 + "fromUserId": "530884188965125",
  132 + "fromUserName": "太宗裔仁寿李登榜",
  133 + "fromUserType": 1,
  134 + "id": 57186467,
  135 + "likeNum": 4,
  136 + "mySelf": 0,
  137 + "parentId": -1,
  138 + "region": "",
  139 + "replyNum": 0,
  140 + "rootCommentId": 57186467,
  141 + "sensitiveExist": 0,
  142 + "sensitiveShow": 1,
  143 + "toUserContentAuthor": 0,
  144 + "toUserId": "",
  145 + "toUserName": "",
  146 + "toUserType": null,
  147 + "topFlag": 0,
  148 + "uuid": "e54c1396-441e-450e-9714-632d9e097b08"
  149 + }, {
  150 + "authorLike": 0,
  151 + "avatarFrame": "",
  152 + "checkStatus": 2,
  153 + "childCommentNum": 0,
  154 + "childComments": [],
  155 + "commentContent": "严惩!",
  156 + "commentContentSensitive": "",
  157 + "commentLevel": 1,
  158 + "commentPics": "",
  159 + "commentSensitive": "",
  160 + "commentType": "1",
  161 + "contentAuthor": 0,
  162 + "createTime": "2024-04-09 17:29:56",
  163 + "creatorFlag": 0,
  164 + "fromCreatorId": "",
  165 + "fromDeviceId": "",
  166 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/201906/rmrb_sfiKkJEo1561260739.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  167 + "fromUserId": "530983644408069",
  168 + "fromUserName": "时间的折叠",
  169 + "fromUserType": 1,
  170 + "id": 57186157,
  171 + "likeNum": 1,
  172 + "mySelf": 0,
  173 + "parentId": -1,
  174 + "region": "河南省郑州市",
  175 + "replyNum": 0,
  176 + "rootCommentId": 57186157,
  177 + "sensitiveExist": 0,
  178 + "sensitiveShow": 1,
  179 + "toUserContentAuthor": 0,
  180 + "toUserId": "",
  181 + "toUserName": "",
  182 + "toUserType": null,
  183 + "topFlag": 0,
  184 + "uuid": "daebe242-5e10-430f-8de8-7ff1d8fae27b"
  185 + }, {
  186 + "authorLike": 0,
  187 + "avatarFrame": "",
  188 + "checkStatus": 2,
  189 + "childCommentNum": 0,
  190 + "childComments": [],
  191 + "commentContent": "孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。孔祥喜,寡廉鲜耻、贪得无厌,终落法网,大快人心。",
  192 + "commentContentSensitive": "",
  193 + "commentLevel": 1,
  194 + "commentPics": "",
  195 + "commentSensitive": "",
  196 + "commentType": "1",
  197 + "contentAuthor": 0,
  198 + "createTime": "2024-04-09 17:28:14",
  199 + "creatorFlag": 0,
  200 + "fromCreatorId": "",
  201 + "fromDeviceId": "",
  202 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/201912/rmrb_a_393944911428186112.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  203 + "fromUserId": "530796590283333",
  204 + "fromUserName": "爱我中华",
  205 + "fromUserType": 1,
  206 + "id": 57185773,
  207 + "likeNum": 20,
  208 + "mySelf": 0,
  209 + "parentId": -1,
  210 + "region": "陕西省榆林市",
  211 + "replyNum": 0,
  212 + "rootCommentId": 57185773,
  213 + "sensitiveExist": 0,
  214 + "sensitiveShow": 1,
  215 + "toUserContentAuthor": 0,
  216 + "toUserId": "",
  217 + "toUserName": "",
  218 + "toUserType": null,
  219 + "topFlag": 0,
  220 + "uuid": "a1371f97-ccfa-4477-893d-4f46144f320d"
  221 + }, {
  222 + "authorLike": 0,
  223 + "avatarFrame": "",
  224 + "checkStatus": 2,
  225 + "childCommentNum": 0,
  226 + "childComments": [],
  227 + "commentContent": "违法乱纪必究!",
  228 + "commentContentSensitive": "",
  229 + "commentLevel": 1,
  230 + "commentPics": "",
  231 + "commentSensitive": "",
  232 + "commentType": "1",
  233 + "contentAuthor": 0,
  234 + "createTime": "2024-04-09 17:27:10",
  235 + "creatorFlag": 0,
  236 + "fromCreatorId": "",
  237 + "fromDeviceId": "",
  238 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/202403/rmrb_pMPU7m4t1711116925.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  239 + "fromUserId": "530911710439685",
  240 + "fromUserName": "上善若水",
  241 + "fromUserType": 1,
  242 + "id": 57185770,
  243 + "likeNum": 5,
  244 + "mySelf": 0,
  245 + "parentId": -1,
  246 + "region": "",
  247 + "replyNum": 0,
  248 + "rootCommentId": 57185770,
  249 + "sensitiveExist": 0,
  250 + "sensitiveShow": 1,
  251 + "toUserContentAuthor": 0,
  252 + "toUserId": "",
  253 + "toUserName": "",
  254 + "toUserType": null,
  255 + "topFlag": 0,
  256 + "uuid": "60779cde-36cc-4fec-a984-58035dea35ea"
  257 + }, {
  258 + "authorLike": 0,
  259 + "avatarFrame": "",
  260 + "checkStatus": 2,
  261 + "childCommentNum": 0,
  262 + "childComments": [],
  263 + "commentContent": "反腐永遠吹衝鋒號",
  264 + "commentContentSensitive": "",
  265 + "commentLevel": 1,
  266 + "commentPics": "",
  267 + "commentSensitive": "",
  268 + "commentType": "1",
  269 + "contentAuthor": 0,
  270 + "createTime": "2024-04-09 17:26:34",
  271 + "creatorFlag": 0,
  272 + "fromCreatorId": "",
  273 + "fromDeviceId": "",
  274 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/default.png?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  275 + "fromUserId": "531302591987589",
  276 + "fromUserName": "荒菴",
  277 + "fromUserType": 1,
  278 + "id": 57185761,
  279 + "likeNum": 4,
  280 + "mySelf": 0,
  281 + "parentId": -1,
  282 + "region": "",
  283 + "replyNum": 0,
  284 + "rootCommentId": 57185761,
  285 + "sensitiveExist": 0,
  286 + "sensitiveShow": 1,
  287 + "toUserContentAuthor": 0,
  288 + "toUserId": "",
  289 + "toUserName": "",
  290 + "toUserType": null,
  291 + "topFlag": 0,
  292 + "uuid": "6d4bc2e1-78b8-4c71-af77-db3b460f35c8"
  293 + }, {
  294 + "authorLike": 0,
  295 + "avatarFrame": "",
  296 + "checkStatus": 2,
  297 + "childCommentNum": 0,
  298 + "childComments": [],
  299 + "commentContent": "丧失理想信念;\n背弃初心使命。\n无视八项规定;\n依法审查起诉。👈👈",
  300 + "commentContentSensitive": "",
  301 + "commentLevel": 1,
  302 + "commentPics": "",
  303 + "commentSensitive": "",
  304 + "commentType": "1",
  305 + "contentAuthor": 0,
  306 + "createTime": "2024-04-09 17:12:59",
  307 + "creatorFlag": 0,
  308 + "fromCreatorId": "",
  309 + "fromDeviceId": "",
  310 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/202312/rmrb_KVwjcPrp1701846404.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  311 + "fromUserId": "531592816140165",
  312 + "fromUserName": "佛系生存",
  313 + "fromUserType": 1,
  314 + "id": 57254110,
  315 + "likeNum": 20,
  316 + "mySelf": 0,
  317 + "parentId": -1,
  318 + "region": "新疆维吾尔自治区乌鲁木齐市",
  319 + "replyNum": 0,
  320 + "rootCommentId": 57254110,
  321 + "sensitiveExist": 0,
  322 + "sensitiveShow": 1,
  323 + "toUserContentAuthor": 0,
  324 + "toUserId": "",
  325 + "toUserName": "",
  326 + "toUserType": null,
  327 + "topFlag": 0,
  328 + "uuid": "a5a61f24-6c97-479f-8ff4-0b23330fe6c2"
  329 + }, {
  330 + "authorLike": 0,
  331 + "avatarFrame": "",
  332 + "checkStatus": 2,
  333 + "childCommentNum": 0,
  334 + "childComments": [],
  335 + "commentContent": "作恶必受报应👊🏻👊🏻",
  336 + "commentContentSensitive": "",
  337 + "commentLevel": 1,
  338 + "commentPics": "",
  339 + "commentSensitive": "",
  340 + "commentType": "1",
  341 + "contentAuthor": 0,
  342 + "createTime": "2024-04-09 17:11:32",
  343 + "creatorFlag": 0,
  344 + "fromCreatorId": "",
  345 + "fromDeviceId": "",
  346 + "fromUserHeader": "https://rmrbcmsonline.peopleapp.com/upload/user_app/202402/rmrb_QEU4YSVc1708676160.jpg?x-oss-process=image/resize,l_100/auto-orient,1/quality,q_90/format,jpg",
  347 + "fromUserId": "522520907165062",
  348 + "fromUserName": "天耀中华888合十",
  349 + "fromUserType": 1,
  350 + "id": 57184951,
  351 + "likeNum": 5,
  352 + "mySelf": 0,
  353 + "parentId": -1,
  354 + "region": "山东省烟台市",
  355 + "replyNum": 0,
  356 + "rootCommentId": 57184951,
  357 + "sensitiveExist": 0,
  358 + "sensitiveShow": 1,
  359 + "toUserContentAuthor": 0,
  360 + "toUserId": "",
  361 + "toUserName": "",
  362 + "toUserType": null,
  363 + "topFlag": 0,
  364 + "uuid": "81f86371-83b8-4144-8699-23e4ee876378"
  365 + }],
  366 + "pageNum": 0,
  367 + "pageSize": 10,
  368 + "totalCommentNum": 11,
  369 + "totalCount": 11
  370 + },
  371 + "message": "Success",
  372 + "meta": null,
  373 + "requestId": "",
  374 + "success": true,
  375 + "timestamp": 1712667900724
  376 +}