fanmingyou3_wd

Merge branch 'main' of http://192.168.1.42/developOne/harmonyPool into main

Showing 103 changed files with 5579 additions and 2 deletions
@@ -105,6 +105,18 @@ @@ -105,6 +105,18 @@
105 ] 105 ]
106 } 106 }
107 ] 107 ]
  108 + },
  109 + {
  110 + "name": "wdLayout",
  111 + "srcPath": "./wdLayout",
  112 + "targets": [
  113 + {
  114 + "name": "default",
  115 + "applyToProducts": [
  116 + "default"
  117 + ]
  118 + }
  119 + ]
108 } 120 }
109 ] 121 ]
110 } 122 }
1 export { CommonConstants } from './src/main/ets/constants/CommonConstants'; 1 export { CommonConstants } from './src/main/ets/constants/CommonConstants';
2 2
3 export { BreakpointConstants } from './src/main/ets/constants/BreakpointConstants'; 3 export { BreakpointConstants } from './src/main/ets/constants/BreakpointConstants';
  4 +
  5 +export { ConfigConstants } from './src/main/ets/constants/ConfigConstants';
  1 +/**
  2 + * Config Constants.
  3 + */
  4 +export class ConfigConstants {
  5 + /**
  6 + * 应用id/appId
  7 + *
  8 + */
  9 + static readonly appId: string = "";
  10 +
  11 + /**
  12 + * 终端id/terminalId
  13 + *
  14 + */
  15 + static readonly terminalId: string = "android";
  16 +
  17 + /**
  18 + * 36_渠道编码(sappType)
  19 + *
  20 + */
  21 + // static readonly appType: string = "2"; // wap
  22 + static readonly appType: string = "3"; // 手机客户端App(安卓)
  23 +
  24 + static readonly clientType: string = "";
  25 +
  26 + /**
  27 + * SourceID
  28 + *
  29 + */
  30 + static readonly sourceId: string = "";
  31 +
  32 + /**
  33 + * 产品渠道应用对照关系:
  34 + */
  35 + static readonly appCode: string = "";
  36 +
  37 + /**
  38 + * 基线代码和客户端应用版本号规范
  39 + */
  40 + static readonly ptvCode: string = "";
  41 +
  42 +
  43 + /**
  44 + * 省份code/province(02->上海)
  45 + */
  46 + static readonly province: string = "02";
  47 +
  48 + /**
  49 + * 正在播放的节目ID
  50 + */
  51 + static playingContentId?: string = null
  52 +
  53 + /**
  54 + * 设备Id/deviceId
  55 + * 设备Id或者能标识请求端的唯一标识
  56 + */
  57 + static readonly DEVICE_ID: string = "5bfed7be-0497-487f-990b-991e5b828a6e";
  58 + /**
  59 + * base url VOD
  60 + */
  61 + static readonly BASE_URL_VOD: string = "";
  62 +
  63 + /**
  64 + * base url Live
  65 + */
  66 + static readonly BASE_URL_LIVE: string = "";
  67 +
  68 + /**
  69 + * 获取用户信息的服务器
  70 + */
  71 + static readonly BASE_URL: string = "";
  72 + /**
  73 + * 内容列表路径
  74 + */
  75 + static readonly CONTENT_LIST_PATH: string = "/display/v4/static";
  76 + /**
  77 + * 电视台(直播)列表路径
  78 + */
  79 + static readonly LIVE_TV_PATH: string = "/live/v2/tv-data";
  80 +}
@@ -4,6 +4,10 @@ export { ResourcesUtils } from './src/main/ets/utils/ResourcesUtils' @@ -4,6 +4,10 @@ export { ResourcesUtils } from './src/main/ets/utils/ResourcesUtils'
4 4
5 export { StringUtils } from './src/main/ets/utils/StringUtils' 5 export { StringUtils } from './src/main/ets/utils/StringUtils'
6 6
  7 +export { ArrayUtils } from './src/main/ets/utils/ArrayUtils';
  8 +
  9 +export { AppUtils } from './src/main/ets/utils/AppUtils';
  10 +
7 export { BasicDataSource } from './src/main/ets/utils/BasicDataSource'; 11 export { BasicDataSource } from './src/main/ets/utils/BasicDataSource';
8 12
9 export { LazyDataSource } from './src/main/ets/utils/LazyDataSource' 13 export { LazyDataSource } from './src/main/ets/utils/LazyDataSource'
  1 +import common from '@ohos.app.ability.common';
  2 +import bundleManager from '@ohos.bundle.bundleManager';
  3 +
  4 +const TAG: string = 'AppUtils';
  5 +
  6 +/**
  7 + * 与应用相关属性或操作
  8 + */
  9 +export class AppUtils {
  10 + /**
  11 + * 获取应用名称
  12 + * 即:咪咕视频
  13 + */
  14 + static getAppName(context: common.Context): string {
  15 + // todo:获取到的是 $string:app_name
  16 + // return context.applicationInfo?.label;
  17 + return context.resourceManager.getStringByNameSync("app_name");
  18 + }
  19 +
  20 + /**
  21 + * 获取应用的包名
  22 + * 即:com.cmcc.myapplication
  23 + */
  24 + static getPackageName(context: common.Context): string {
  25 + return context.applicationInfo?.name;
  26 + }
  27 +
  28 + /**
  29 + * 获取应用版本号,如:1.0.0.0
  30 + * @returns 版本号字符串
  31 + */
  32 + static getAppVersionName(): string {
  33 + try {
  34 + let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)
  35 + return bundleInfo?.versionName
  36 + } catch (e) {
  37 + }
  38 + return "";
  39 + }
  40 +
  41 + /**
  42 + * 获取应用版本编码,如:1000000
  43 + * @returns 应用版本编码
  44 + */
  45 + static getAppVersionCode(): string {
  46 + return "2600010700"
  47 + // try {
  48 + // let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)
  49 + // return bundleInfo?.versionCode
  50 + // } catch (e) {
  51 + // Logger.warn(TAG, 'get app version error:' + e?.message);
  52 + // }
  53 + // return 0;
  54 + }
  55 +}
  1 +import LinkList from '@ohos.util.List';
  2 +
  3 +export class ArrayUtils {
  4 + /**
  5 + * The Array utils tag.
  6 + */
  7 + private static readonly TAG: string = 'ArrayUtils';
  8 +
  9 + static isArray(value: any): boolean {
  10 + if (typeof Array.isArray === 'function') {
  11 + return Array.isArray(value);
  12 + } else {
  13 + return Object.prototype.toString.call(value) === '[object Array]';
  14 + }
  15 + }
  16 +
  17 + /**
  18 + * Check collection is empty or not.
  19 + * @param collection any[]
  20 + * @returns {boolean} true(empty)
  21 + */
  22 + static isEmpty(collection?: any[]): boolean {
  23 + return!collection || collection.length === 0;
  24 + }
  25 +
  26 + /**
  27 + * Check collection is empty or not.
  28 + * @param collection any[]
  29 + * @returns {boolean} true(not empty)
  30 + */
  31 + static isNotEmpty(collection?: any[]): boolean {
  32 + if (!collection) {
  33 + return false
  34 + }
  35 + return collection.length > 0;
  36 + }
  37 +
  38 + static getListSize(collection?: any[]): number {
  39 + return ArrayUtils.isEmpty(collection) ? 0 : collection.length;
  40 + }
  41 +
  42 + static getListElement(collection?: any[], index?: number): any {
  43 + if (ArrayUtils.isEmpty(collection) || index === undefined) {
  44 + return null;
  45 + }
  46 + return index >= 0 && index < collection.length ? collection[index] : null;
  47 + }
  48 +
  49 + static convertArray<T>(objectList: T[] | T): T[] {
  50 + if (ArrayUtils.isArray(objectList)) {
  51 + return objectList as T[];
  52 + } else {
  53 + return [objectList as T];
  54 + }
  55 + }
  56 +
  57 + /**
  58 + * 把list2合入list1后
  59 + * @param list1
  60 + * @param list2
  61 + * @returns
  62 + */
  63 + static addAll<T>(list1: LinkList<T>, list2: LinkList<T>): LinkList<T> {
  64 + if (!list1) {
  65 + list1 = new LinkList<T>();
  66 + }
  67 + if (!list2) {
  68 + return list1;
  69 + }
  70 +
  71 + for (let index = 0; index < list2.length; index++) {
  72 + list1.add(list2[index])
  73 + }
  74 + return list1
  75 + }
  76 +
  77 + static deepCopy(objectList: any[]): any[] {
  78 + const list: any[] = [];
  79 + for (const objectItem of objectList) {
  80 + if (typeof objectItem !== 'object') {
  81 + list.push(objectItem);
  82 + continue;
  83 + }
  84 + if (objectItem.constructor === Date) {
  85 + list.push(new Date(objectItem));
  86 + continue;
  87 + }
  88 + if (objectItem.constructor === RegExp) {
  89 + list.push(new RegExp(objectItem));
  90 + continue;
  91 + }
  92 + if (objectItem.clone) {
  93 + list.push(objectItem.clone());
  94 + continue;
  95 + }
  96 + const newObj = new objectItem.constructor();
  97 + for (const key in objectItem) {
  98 + if (Object.hasOwnProperty.call(objectItem, key)) {
  99 + const val = objectItem[key];
  100 + newObj[key] = val;
  101 + }
  102 + }
  103 + list.push(newObj);
  104 + }
  105 + return list;
  106 + }
  107 +
  108 + static deepCopyNumber(values: Set<number>): Set<number> {
  109 + const newSet: Set<number> = new Set();
  110 + values.forEach((value => {
  111 + newSet.add(value);
  112 + }));
  113 + return newSet;
  114 + }
  115 +
  116 + /**
  117 + * Uint8Array to string
  118 + * @param fileData Uint8Array
  119 + */
  120 + static uint8ArrayToString(fileData: Uint8Array): string {
  121 + return decodeURIComponent(escape(String.fromCharCode(...fileData)));
  122 + }
  123 +
  124 + /**
  125 + * string to Uint8Array
  126 + * @param str string
  127 + */
  128 + static stringToUint8Array(str: string): Uint8Array {
  129 + // spilt('') Each character is divided between them
  130 + const arr = unescape(encodeURIComponent(str)).split('').map(val => val.charCodeAt(0));
  131 + return new Uint8Array(arr);
  132 + }
  133 +}
  1 +export { PageUtils } from './src/main/ets/utils/PageUtils'
  2 +
  3 +export { WDPage } from "./src/main/ets/layout/WDPage"
  4 +
  5 +export { WDGroup } from "./src/main/ets/layout/WDGroup"
  6 +
  7 +export { WDComp } from "./src/main/ets/layout/WDComp"
  8 +
  9 +export { Lego } from "./src/main/ets/lego/LegoService"
  10 +
  11 +export { PageViewModel } from "./src/main/ets/viewmodel/PageViewModel"
  1 +{
  2 + "apiType": "stageMode",
  3 + "buildOption": {
  4 + "arkOptions": {
  5 + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */
  6 + }
  7 + },
  8 + "buildOptionSet": [
  9 + {
  10 + "name": "release",
  11 + "arkOptions": {
  12 + "obfuscation": {
  13 + "ruleOptions": {
  14 + "enable": true,
  15 + "files": [
  16 + "./obfuscation-rules.txt"
  17 + ]
  18 + }
  19 + }
  20 + }
  21 + },
  22 + ],
  23 + "targets": [
  24 + {
  25 + "name": "default"
  26 + }
  27 + ]
  28 +}
  1 +import { hspTasks } from '@ohos/hvigor-ohos-plugin';
  2 +
  3 +export default {
  4 + system: hspTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
  5 + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
  6 +}
  1 +# Define project specific obfuscation rules here.
  2 +# You can include the obfuscation configuration files in the current module's build-profile.json5.
  3 +#
  4 +# For more details, see
  5 +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
  6 +
  7 +# Obfuscation options:
  8 +# -disable-obfuscation: disable all obfuscations
  9 +# -enable-property-obfuscation: obfuscate the property names
  10 +# -enable-toplevel-obfuscation: obfuscate the names in the global scope
  11 +# -compact: remove unnecessary blank spaces and all line feeds
  12 +# -remove-log: remove all console.* statements
  13 +# -print-namecache: print the name cache that contains the mapping from the old names to new names
  14 +# -apply-namecache: reuse the given cache file
  15 +
  16 +# Keep options:
  17 +# -keep-property-name: specifies property names that you want to keep
  18 +# -keep-global-name: specifies names that you want to keep in the global scope
  1 +{
  2 + "name": "wdlayout",
  3 + "version": "1.0.0",
  4 + "description": "Please describe the basic information.",
  5 + "main": "Index.ets",
  6 + "author": "",
  7 + "license": "Apache-2.0",
  8 + "dependencies": {
  9 + "wdKit": "file:../wdKit",
  10 + "wdNetwork": "file:../wdNetwork",
  11 + "wdConstant": "file:../wdConstant"
  12 + }
  13 +}
  1 +import { Params } from './Params';
  2 +
  3 +export interface Action {
  4 + type: string;
  5 + name?: string; // 行为的名称,目前值与type相同,暂不启用
  6 + params?: Params; // 参数集合
  7 + androidMinVersion?: string; // 最低版本号, -1(-1表示不限制)
  8 + iosMinVersion?: string; // -1(-1表示不限制)
  9 +}
  1 +export interface AdInfo {
  2 + adPosition: string[];
  3 + materialStyle: string[];
  4 + adID: string[];
  5 + startPosition: string;
  6 + displayStride: string;
  7 +}
  1 +export interface Baseline {
  2 + baselineShow: string;
  3 +}
  1 +/**
  2 + * 底导数据容器
  3 + */
  4 +import { NavButton } from './NavButton';
  5 +
  6 +export class BottomBar {
  7 + backgroundImg?: string;
  8 + buttons: NavButton[];
  9 +}
  1 +import { ButtonDTO } from './ButtonDTO';
  2 +import { ItemBean } from './ItemBean';
  3 +
  4 +@Observed
  5 +export class ButtonBean extends ItemBean {
  6 + label: string; // button类型,即:按钮1/按钮2
  7 + title: string; // 标题,如:换一换/更多/更多热播电视剧/更多好剧/更多综艺/更多热点/古装剧场/燃剧场
  8 + subTitle: string; // 副标题
  9 + icon?: string; // 小图标
  10 +
  11 + constructor(dto: ButtonDTO) {
  12 + super(dto);
  13 + this.label = dto.label;
  14 + this.title = dto.title;
  15 + this.subTitle = dto.subTitle;
  16 + this.icon = dto.icon;
  17 + }
  18 +}
  1 +import { ItemDTO } from './ItemDTO';
  2 +
  3 +export class ButtonDTO extends ItemDTO {
  4 + label: string; // button类型,即:按钮1/按钮2
  5 + title: string; // 标题,如:换一换/更多/更多热播电视剧/更多好剧/更多综艺/更多热点/古装剧场/燃剧场
  6 + subTitle: string; // 副标题
  7 + icon?: string; // 小图标
  8 +}
  1 +export interface CacheTrace {
  2 + refreshTime?: string;
  3 + updateTime?: string;
  4 + description?: string;
  5 + traceId?: string;
  6 + updateTimeStamp?: string;
  7 +}
  1 +/**
  2 + * 组件DTO
  3 + */
  4 +import { Action } from './Action';
  5 +import { AdInfo } from './AdInfo';
  6 +import { DataSourceRequest } from './DataSourceRequest';
  7 +import { ExtraDTO } from './ExtraDTO';
  8 +import { OsVersion } from './OsVersion';
  9 +
  10 +export class CompDTO {
  11 + id: string; // 组件id
  12 + name: string; // 组件名称
  13 + title?: string; // 标题:若无值,则不露出该字段
  14 + description?: string; // 描述:若无值,则不露出该字段
  15 + compType: string; // 组件类型
  16 + compStyle: string; // 组件样式
  17 + fetchDataType: string; // 获取数据方式
  18 + dataCount: string; // 需要填充的数据数量
  19 + dataSource?: string; // Comp的数据源:若无值,则不露出该字段
  20 + vomsNodeID?: string; // VOMS展现对象节点ID:若无值,则不露出该字段(暂不维护)
  21 + searchCondition?: string; // 搜索条件:若无值,则不露出该字段
  22 + // bodyComponent?: BodyComponent; // 可保存二次请求的数据【组件id】对应/映射BodyComponent的id
  23 + // contentInfoData?: ContentInfoData; // 可保存二次请求的数据【剧集/节目id】
  24 + // bodyPlayUrl?:BodyPlayUrl;// 保存二次请求的数据播放数据
  25 + extraData?: ExtraDTO; // 辅助数据
  26 + isWaterfallFlow: string; // 是否以瀑布流形式展示0:否 1:是
  27 + isContainAD: number; // 是否内嵌广告,数据字典:0:否1:是
  28 + adInfo?: AdInfo; // 广告信息
  29 + sortValue: string; // 展现顺序
  30 + icon?: string; // comp的icon图标: 若无值,则不露出该字段
  31 + status: string; // 状态,0为无效,1为有效
  32 + location: string; // comp所在页面路径
  33 + action?: Action; // 事件对象
  34 + fitArea: string[]; // 适用地区
  35 + displayCount: string; // 展示数量
  36 + platformId: string[]; // 适用平台
  37 + zIndex: string; // 浮层高度
  38 + iosVersion?: OsVersion; // ios版本号
  39 + androidVersion?: OsVersion; // 安卓版本号
  40 + // 符合的用户类型:
  41 + // 非会员 0,体验会员 1,世界杯会员 2,黄金会员 3,钻石会员 4,钻石会员(TV尊享)5,超级会员 6,大站包会员 7,未登录用户 -1,咪爱会员 8
  42 + userType: string[];
  43 + ipadVersion?: OsVersion; // ipad版本号
  44 + dataSourceRequest?: DataSourceRequest[]; // 数据源请求(目前只支持“猜你喜欢”): 若无值,则不露出该字段
  45 + vrVersion?: OsVersion; // vr版本
  46 + styleRefreshStrategy: string;
  47 + yingshizongShowTv: string;
  48 +}
  1 +/**
  2 + * 组件对应服务器返回的comp数据Body
  3 + */
  4 +import { ItemDTO } from './ItemDTO';
  5 +import { ProgrammeDTO } from './ProgrammeDTO';
  6 +
  7 +export class CompDataDTO extends ItemDTO {
  8 + id: string; // 组件主键ID
  9 + name: string; // 名称
  10 + branchMark: boolean; // 是否有分众数据标志位 true表示存在分众信息
  11 + data: ProgrammeDTO[]; // Object是被Wrapper后的节目数据
  12 + // totalPage: string = ''; // 总页数
  13 + // totalCount: string = ''; // 总数据条数
  14 + // refreshTime: string = ''; // 缓存刷新时间
  15 + // dataSourceType: string = ''; // 数据源类型
  16 + // fitArea: string[] = []; //适用地区
  17 + // cacheTraceVO?: CacheTraceVO = {}; // comp缓存链路跟踪信息
  18 +}
  1 +export class CopyRightVo {
  2 + terminal: string;
  3 + area: string;
  4 + beginDate: string;
  5 + endDate: string;
  6 + way: string;
  7 +}
  1 +export interface DataSourceRequest {
  2 + method: string; // 请求方式
  3 + responseDataType: number;
  4 + paramter: any; // JSON 请求参数
  5 + header: any; // JSON 请求头信息入参
  6 + poolId: string; //池ID(新数据源存在,原老comp数据源不存在)
  7 + // 数据源类型
  8 + dataSourceType: string;
  9 + timeout: number; // 数据源超时时间,单位毫秒
  10 + // 客户端数据刷新策略
  11 + // CACHE:本地缓存优先
  12 + // NET:网络数据优先,
  13 + // NET_ONLY:只读网络(客户端未适配)
  14 + dataRefresh: string;
  15 + h5uri: string; // h5URI
  16 + uri: string; // 客户端URI
  17 + locationValue: string; //
  18 + displayCount: number; //
  19 + backupDataSource: DataSourceRequest; // 备用数据源
  20 +}
  1 +export class DisplayName {
  2 + first: string;
  3 + second: string[];
  4 +}
  1 +import { ButtonDTO } from './ButtonDTO';
  2 +import { FilterCategoryDTO } from './FilterCategoryDTO';
  3 +import { ItemDTO } from './ItemDTO';
  4 +import { LabelDTO } from './LabelDTO';
  5 +import { Tab01DTO } from './Tab01DTO';
  6 +import { Tab22DTO } from './Tab22DTO';
  7 +
  8 +export class ExtraDTO extends ItemDTO {
  9 + menus?: Tab01DTO[];
  10 + tabs?: Tab22DTO[];
  11 + labels?: LabelDTO[];
  12 + buttons?: ButtonDTO[];
  13 + screenList: FilterCategoryDTO[]; // 筛选条件的种类列表/筛查
  14 + focusId?: string; // 聚焦项MenuId/导航栏id
  15 + backgroundColor?: string; // 背景颜色
  16 + backgroundImg?: string; // 背景图片
  17 + expandable?: string; // 是否可展开
  18 + tabBarExpandStyle?: string; // 导航栏展开样式
  19 + grayFilter?: string;
  20 + showWeather?: string;
  21 + subTitleIntervaltime?: string;
  22 + // paster?: any;
  23 + regulationId?: string;
  24 + mute?: string;
  25 + autoPlay?: string;
  26 + isPlaytimesForbidden?: string;
  27 +
  28 + // cards: Card[]; // SHORT_WITH_LONG 混合短带长
  29 + // isInsertCards: string;
  30 + starID?: string; // 明星Id,用于Params的extra中
  31 + showMemberResources?: string;
  32 + defaultStyle?: string;
  33 +
  34 + // memberResourcesData?: { activityId: string };
  35 + mgdbID?: string;
  36 + isNewH5Page: string;
  37 + pageURL: string;
  38 +}
  1 +/**
  2 + * CLASSIFY_FILTER_BAR-02
  3 + * 筛选条件的种类/过滤器
  4 + */
  5 +import { FilterCategoryDTO } from './FilterCategoryDTO';
  6 +import { ItemBean } from './ItemBean';
  7 +import { PairFilter } from './PairFilter';
  8 +
  9 +@Observed
  10 +export class FilterCategoryBean extends ItemBean {
  11 + categoryValue: string;
  12 + categoryKey: string;
  13 + content: PairFilter[];
  14 +
  15 + constructor(dto: FilterCategoryDTO) {
  16 + super(dto);
  17 + this.categoryValue = dto.categoryValue;
  18 + this.categoryKey = dto.categoryKey;
  19 + this.content = dto.content;
  20 + }
  21 +}
  1 +/**
  2 + * 筛选条件的种类:
  3 + * mediaType(类型)/mediaArea(地区)/mediaYear(年代)/rankingType(排序类型)/payType(付费类型)/mediaMovieForm(规格)
  4 + */
  5 +import { ItemDTO } from './ItemDTO';
  6 +import { PairFilter } from './PairFilter';
  7 +
  8 +export class FilterCategoryDTO extends ItemDTO {
  9 + categoryValue: string; // 类型/地区/年代/排序类型/付费类型/规格
  10 + categoryKey: string; // mediaType/mediaArea/mediaYear/rankingType/payType/mediaMovieForm
  11 + content: PairFilter[];
  12 +}
  1 +import { CompDTO } from './CompDTO';
  2 +import { ItemDTO } from './ItemDTO';
  3 +import { OsVersion } from './OsVersion';
  4 +
  5 +export class GroupDTO extends ItemDTO {
  6 + id: string; // group主键ID
  7 + name: string; // 名称
  8 + branchMark: boolean;
  9 + fitArea?: string[];
  10 + components: CompDTO[]; // Components集合的布局信息
  11 + platformId?: string[];
  12 + iosVersion?: OsVersion;
  13 + androidVersion?: OsVersion;
  14 + userType?: string[];
  15 + isSegmentLine?: string;
  16 + isPopup?: string;
  17 + ipadVersion?: OsVersion;
  18 + vrVersion?: OsVersion;
  19 + groupType?: string;
  20 + fitTelecomOperators?: string[];
  21 + channelCode?: string;
  22 + removeRepeat?: boolean;
  23 +}
  1 +/**
  2 + * 对应服务器返回的group数据
  3 + */
  4 +import { CompDataDTO } from './CompDataDTO';
  5 +import { ItemDTO } from './ItemDTO';
  6 +
  7 +export class GroupDataDTO extends ItemDTO {
  8 + id: string; // Group主键ID
  9 + name: string; // 名称
  10 + branchMark: boolean;
  11 + components: CompDataDTO[];
  12 +}
  1 +/**
  2 + * 绑定到组件comp/view的数据Bean
  3 + */
  4 +import { Action } from './Action';
  5 +import { ItemDTO } from './ItemDTO';
  6 +import { Pic } from './Pic';
  7 +
  8 +@Observed
  9 +export abstract class ItemBean {
  10 + action?: Action; // 事件行为
  11 + actionId?: string; // 点击事件id
  12 + pics?: Pic
  13 + h5pics: Pic;
  14 + landscapeCover?: string; // 横向低分辨封面图片
  15 + portraitCover?: string; // 竖向低分辨封面图片
  16 + highLandscapeCover?: string; // 横向高分辨封面图片
  17 + highPortraitCover?: string; // 竖向高分辨封面图片
  18 + lowResolutionV34?: string; // 低清竖图(3:4比例), 取图逻辑 3:4低清竖图-->3:4高清竖图-->低分辨率竖图-->高分辨率竖图
  19 + highResolutionV34?: string; // 高清竖图(3:4比例), 取图逻辑 3:4高清竖图-->3:4低清竖图-->高分辨率竖图-->低分辨率竖图
  20 + /**
  21 + * 是否被曝光
  22 + */
  23 + exposed: boolean;
  24 + /**
  25 + * 曝光位置
  26 + */
  27 + position: string;
  28 +
  29 + constructor(dto: ItemDTO) {
  30 + this.action = dto.action
  31 + this.actionId = dto.actionId
  32 + this.pics = dto.pics
  33 + this.h5pics = dto.h5pics
  34 +
  35 + this.landscapeCover = !dto.pics ? "" : !dto.pics.lowResolutionH ? dto.pics.highResolutionH : dto.pics.lowResolutionH;
  36 + this.portraitCover = !dto.pics ? "" : !dto.pics.lowResolutionV ? dto.pics.highResolutionV : dto.pics.lowResolutionV;
  37 + this.highLandscapeCover = !dto.pics ? "" : !dto.pics.highResolutionH ? dto.pics.lowResolutionH : dto.pics.highResolutionH;
  38 + this.highPortraitCover = !dto.pics ? "" : !dto.pics.highResolutionV ? dto.pics.lowResolutionV : dto.pics.highResolutionV;
  39 +
  40 + this.lowResolutionV34 = !dto.pics ? "" : (!dto.pics.lowResolutionV34 ? dto.pics.lowResolutionV34 : (!dto.pics.highResolutionV34 ? dto.pics.highResolutionV34 : this.portraitCover));
  41 + this.highResolutionV34 = !dto.pics ? "" : (!dto.pics.highResolutionV34 ? dto.pics.highResolutionV34 : (!dto.pics.lowResolutionV34 ? dto.pics.lowResolutionV34 : this.highPortraitCover));
  42 +
  43 + this.exposed = false
  44 + this.position = "0"
  45 + }
  46 +
  47 + public setAction(action: Action): void {
  48 + this.action = action
  49 + }
  50 +
  51 + public getAction(): Action {
  52 + return this.action ?? {} as Action
  53 + }
  54 +}
  1 +/**
  2 + * 组件comp/view对应的服务端数据
  3 + * DTO 数据传输实体类接口,所有数据传输层数据结构体需实现该接口
  4 + */
  5 +import { Action } from './Action';
  6 +import { Pic } from './Pic';
  7 +
  8 +export abstract class ItemDTO {
  9 + action?: Action; // 事件对象
  10 + actionId?: string; // 点击事件id
  11 + pics?: Pic // 图片
  12 + h5pics: Pic; // 图片
  13 +}
  1 +import { ItemBean } from './ItemBean';
  2 +import { LabelDTO } from './LabelDTO';
  3 +
  4 +@Observed
  5 +export class LabelBean extends ItemBean {
  6 + icon?: string;
  7 + defaultTextColor?: string;
  8 + label: string;
  9 + title: string;
  10 + subTitle?: string;
  11 + description?: string;
  12 + bottomColor?: string;
  13 + isShow?: boolean;
  14 +
  15 + constructor(dto: LabelDTO) {
  16 + super(dto);
  17 + this.label = dto.label;
  18 + this.title = dto.title;
  19 + this.subTitle = dto.subTitle;
  20 + }
  21 +}
  1 +/**
  2 + * 标题 —— 标题(LABEL-01)
  3 + */
  4 +import { ItemDTO } from './ItemDTO';
  5 +
  6 +export class LabelDTO extends ItemDTO {
  7 + icon?: string; // icon图片/小图标
  8 + defaultTextColor?: string; // 文本颜色
  9 + label: string; // label类型,如:主标题/子标题
  10 + title: string; // 标题,如:重磅推荐/热门视频彩铃/更多下饭剧/4K超高清/更多>/更多动画
  11 + subTitle?: string; // 副标题/二级标题
  12 + description?: string; // 描述信息
  13 + bottomColor?: string; // 标题底色
  14 + isShow?: boolean;
  15 +}
  1 +/**
  2 + * 搜索bar左边的logo图标
  3 + */
  4 +import { Action } from './Action';
  5 +
  6 +export interface Logo {
  7 + name: string;
  8 + logoLightImg: string;
  9 + logoLightImg2: string;
  10 + logoLightImgBackground: string;
  11 + logoLightImgBackground2: string;
  12 + logoDarkImg: string;
  13 + logoDarkImg2: string;
  14 + logoDarkImgBackground: string;
  15 + logoDarkImgBackground2: string;
  16 + action: Action;
  17 +}
  1 +/**
  2 + * 导航Body数据
  3 + */
  4 +import { NavigationBean } from './NavigationBean';
  5 +
  6 +export class NavBody {
  7 + isConfigData: string;
  8 + list: NavigationBean[];
  9 +}
  1 +/**
  2 + * 底部或顶部导航按钮Bean
  3 + */
  4 +import { Action } from './Action';
  5 +
  6 +export class NavButton {
  7 + // name: string; // 底导名称
  8 + displayText: string; // 展示名称
  9 + action: Action; // 跳转事件
  10 +
  11 + // bottomBar下的按钮属性
  12 + lightClieckAnimation?: string; // 浅色点击动画json串
  13 + lightDefaultImg?: string; // 浅色默认图片
  14 + lightActivatedImg?: string; // 浅色点击图片
  15 + lightDefaultTextColor?: string; // 浅色默认文字颜色
  16 + lightActivatedTextColor?: string; // 浅色点击文字颜色
  17 + lightOtherImageMode?: number; // 浅色其它图模式
  18 + lightBackgroundColor?: string; // 浅色背景颜色
  19 + darkClieckAnimation?: string; // 深色点击动画json串
  20 + darkDefaultImg?: string; // 深色模式默认图片
  21 + darkActivatedImg?: string; // 深色模式点击图片
  22 + darkDefaultTextColor?: string; // 深色文字默认颜色
  23 + darkActivatedTextColor?: string; // 深色文字点击颜色
  24 + darkOtherImageMode?: number; // 深色其它图模式 深色其它图模式 1:浅色模式 2:深色模式
  25 + darkBackgroundColor?: string; // 深色背景颜色
  26 + topBarID?: string; // 对应顶导框架ID
  27 +
  28 + // topBar下的按钮属性
  29 + buttonType?: string; // 按钮类型:FUN
  30 + lightIconImg?: string; // 浅色Icon图片
  31 + darkIconImg?: string; // 深色Icon图片
  32 +
  33 + // 其他属性
  34 + lightDefaultColor?: string;
  35 + lightSelectedColor?: string;
  36 + darkDefaultColor?: string;
  37 + darkSelectedColor?: string;
  38 + // defaultTextColor?: string;
  39 + // activatedTextColor?: string;
  40 + // defaultImg?: string;
  41 + // originPageId?: string;
  42 +}
  1 +/**
  2 + * 当前客户端底导/顶导全部数据
  3 + */
  4 +import { BottomBar } from './BottomBar';
  5 +import { TopBar } from './TopBar';
  6 +
  7 +export class NavigationBean {
  8 + id: string;
  9 + name: string;
  10 + bottomBar: BottomBar; // 底导数据
  11 + topBars: TopBar[]; // 顶导数据
  12 + updateTime?: number;
  13 + status?: number;
  14 + byVersion?: string;
  15 + beginVersion?: string;
  16 + endVersion?: string;
  17 +}
  1 +/**
  2 + * ios版本号: IosVersion
  3 + * 安卓版本号: AndroidVersion
  4 + * ipad版本号: IpadVersion
  5 + * Vr版本号: VrVersion
  6 + */
  7 +export class OsVersion {
  8 + // 是否展示:-1 不展示、1 全部版本、0 指定版本
  9 + isAllVersion?: string;
  10 +
  11 + // 最小版本号
  12 + min?: string;
  13 +
  14 + // 最大版本号
  15 + max?: string;
  16 +
  17 + // 排除的版本号
  18 + exclude?: string[];
  19 +}
  1 +import { Baseline } from './Baseline';
  2 +import { CacheTrace } from './CacheTrace';
  3 +import { ExtraDTO } from './ExtraDTO';
  4 +import { GroupDTO } from './GroupDTO';
  5 +import { OsVersion } from './OsVersion';
  6 +
  7 +export class PageDTO {
  8 + id: string; // 主键ID
  9 + name: string; // 名称
  10 + title: string; // 标题
  11 + branchMark: boolean; // 分众标志位 true表示存在分众信息
  12 + isEmbedPopupPage: string; // 是否内嵌弹出页面。0:不内嵌弹出页面 1:内嵌弹出页面
  13 + groups: GroupDTO[]; // page下的group布局信息
  14 + fitArea: string[]; //
  15 + isShared: string;
  16 + shareMainTitle?: string;
  17 + shareSubTitle?: string;
  18 + shareUrl?: string;
  19 + shareIcon?: string;
  20 + pageSearchText: string[]; // 页面顶部搜索hint文本数组
  21 + platformId: string[];
  22 + iosVersion: OsVersion;
  23 + androidVersion: OsVersion;
  24 + backgroundColor: string;
  25 + transparency: string;
  26 + extraData: ExtraDTO; // 辅助数据
  27 + ipadVersion: OsVersion;
  28 + backToTop: string;
  29 + // theme: Theme;
  30 + baseline: Baseline;
  31 + refreshTime: string;
  32 + cacheTraceVO: CacheTrace;
  33 + vrVersion: OsVersion;
  34 + grayFilter: string;
  35 + preloadingGroupCount: string;
  36 +}
  37 +
  1 +/**
  2 + * 筛选/过滤的键值对
  3 + */
  4 +export class PairFilter {
  5 + value: string;
  6 + key: string;
  7 +}
  1 +import { DataSourceRequest } from './DataSourceRequest';
  2 +import { ExtraDTO } from './ExtraDTO';
  3 +import { ReportingData } from './ReportingData';
  4 +
  5 +export class Params {
  6 + pageID: string;
  7 +
  8 + // 需要展现Fame类型,数据字典为:
  9 + // default-frame:不包含搜索栏、底部tab工具条的frame
  10 + // main-frame:包含搜索栏、底部tab工具条的frame
  11 + frameID?: string;
  12 + contentID?: string; // 如果type是节目详情类型,字段为需要播放的节目ID(必传),如:656057406
  13 + longVideoID?: string; // 关联的长视频节目ID/综艺关联正片id
  14 + path?: string; // 需要跳转/刷新的内部路径,这个路径可以是pageID,也可是compID
  15 + url?: string; // 需要跳转到的URL地址/H5打开链接
  16 + location: string; // 当前事件的发起comp路径,格式:PageID#GroupID#CompID
  17 + extra?: ExtraDTO; // 跳转时额外需要带的参数:map<String,String> 即仅有一层的json
  18 + supportRuleEngine?: boolean;
  19 + fitArea?: string[]; // 分省策略(用于埋点数据统计)
  20 + programTypeV2?: string; // 节目类型(可用于节目对应详情页映射)
  21 + albumID?: string; // 专辑壳ID(适用于某节目属于多个专辑的情况下,指定某专辑播放)
  22 + autoPlayType?: string; // 自动连播类型(沉浸式播放-VERTICAL_PLAYER;)
  23 + popType?: string; // 弹出页面类型(适用于新页面半屏弹出),数据字典为:// DEFAULT:默认类型(半屏); // FULL: 全屏
  24 + reportingData?: ReportingData; // 埋点上报数据对象:将数据埋点需要的数据上报给客户端
  25 + compstyle?: string; // COMP样式
  26 + targetComp?: string; // 需要触发操作的目标COMP
  27 + dataSourceRequest?: DataSourceRequest; // 数据源请求
  28 + crbtID?:string; // 彩铃ID(适用于彩铃节目)
  29 + crbtCopyRightID?:string; // 彩铃版权ID(适用于彩铃节目)
  30 + assetId?:string; // 媒资ID(若乐高运营的节目未查出关联媒资ID,则字段不展示。)
  31 +
  32 + tabsIndex?: number;
  33 + detailPageID?:string;
  34 +
  35 + detailPageType?:number;
  36 + mgdbId?:string; // 挂件ID
  37 + serviceId?:string; // 商品id
  38 + androidServiceid?:string; // 安卓serviceId
  39 + androidGoodscode?:string; // 安卓goodsCode
  40 + iosServiceid?:string; // ios serviceId
  41 + iosGoodscode?:string; // ios goodsCode
  42 + keywords?: string;
  43 + videoCategory?: string;
  44 +
  45 + dataSource?:string; // 事件发生的位置
  46 +
  47 + intfId?: string;
  48 +}
  1 +/**
  2 + * 图片
  3 + * Pic 同 H5pic
  4 + */
  5 +export interface Pic {
  6 + lowResolutionH?: string; //低清横图
  7 + lowResolutionV?: string; // 低清竖图
  8 + lowResolutionV34?: string; // 低清竖图(3:4比例)
  9 + highResolutionH?: string; // 高清横图
  10 + highResolutionV?: string; // 高清竖图
  11 + highResolutionV34?: string; // 高清竖图(3:4比例)
  12 + gkResolution1?: string; // g客视频1配图
  13 + gkResolution2?: string; // g客视频2配图
  14 +}
  1 +/**
  2 + * 解说员信息/节目主持人名称
  3 + */
  4 +export class Presenter {
  5 + name: string;
  6 +}
  1 +/**
  2 + * 节目/剧集Item
  3 + * CompType:
  4 + * TOP_IMG_BOTTOM_TXT
  5 + * BIG_STATIC_IMG
  6 + * BIG_PLAY_IMG
  7 + * SLIDER_IMG
  8 + * MY_HOME
  9 + */
  10 +import { ItemBean } from './ItemBean';
  11 +import { ProgrammeDTO } from './ProgrammeDTO';
  12 +import { StrategyTipMap } from './StrategyTipMap';
  13 +import { Tip } from './Tip';
  14 +
  15 +@Observed
  16 +export class ProgrammeBean extends ItemBean {
  17 + name?: string; // 节目名称
  18 + title?: string; // 标题
  19 + pID?: string // 节目ID
  20 + programTypeV2?: string; // 节目类型:
  21 + detail?: string; // 描述
  22 + // pics?: Pic; // 图片(放到父类ItemBean中)
  23 + score?: string; // 得分
  24 + updateEP?: string; // 更新集数(示例:更新至28集)
  25 + stateTime?: string; // 已完结/"每周四12:00更新1期"
  26 + programs?: ProgrammeDTO[];
  27 + index?: string; // 在剧集中的序号(从1开始)
  28 + duration?: string; // 节目时长,"02:04:27",
  29 + author?: string; // 节目上传者(若为G客内容,则DataVo 中输出该字段)
  30 + avator?: string; // 节目上传者头像(若为G客内容,则DataVo 中输出该字段)
  31 + screenType?: string; // 屏幕类型。1: 竖屏; 2: 横屏;
  32 + subTxt?: string;
  33 + strategyTipMap?: StrategyTipMap;
  34 + startTime?: string; // 开始时间,YYYYMMDDHHmm,如202311262305
  35 + endTime?: string; // 比赛结束时间/推流结束时间(YYYYMMDDHHmm,如202311270130)
  36 + tip?: Tip; // 角标,枚举类:(code, msg)
  37 + tip2?: Tip; // 清晰度角标,枚举类:(code, msg)/4K角标
  38 + showTip?: Tip;
  39 + topRightTipImgUrl?: string; // 右上角角标
  40 + topLeftTipImgUrl?: string; // 左上角角标
  41 +
  42 + constructor(dto: ProgrammeDTO) {
  43 + super(dto);
  44 + this.name = dto.name
  45 + this.title = dto.title
  46 + this.pID = dto.pID
  47 + this.programTypeV2 = dto.programTypeV2
  48 + this.detail = dto.detail
  49 + this.score = dto.score
  50 + this.updateEP = dto.updateEP
  51 + this.stateTime = dto.stateTime
  52 + this.programs = dto.programs;
  53 + this.index = dto.index;
  54 + this.duration = dto.duration
  55 + this.author = dto.author
  56 + this.avator = dto.avator
  57 + this.screenType = dto.screenType
  58 + this.subTxt = dto.subTxt?.txt
  59 + this.strategyTipMap = dto.strategyTipMap;
  60 + this.tip = dto.tip;
  61 + this.showTip = dto.showTip;
  62 + }
  63 +}
  1 +/**
  2 + * 节目/剧集Item
  3 + */
  4 +import { CopyRightVo } from './CopyRightVo';
  5 +import { DisplayName } from './DisplayName';
  6 +import { ItemDTO } from './ItemDTO';
  7 +import { Presenter } from './Presenter';
  8 +import { Resolution } from './Resolution';
  9 +import { ShieldStrategy } from './ShieldStrategy';
  10 +import { StrategyTipMap } from './StrategyTipMap';
  11 +import { SubTxt } from './SubTxt';
  12 +import { Team } from './Team';
  13 +import { Tip } from './Tip';
  14 +
  15 +export class ProgrammeDTO extends ItemDTO {
  16 + name?: string; // 节目名称
  17 + pID?: string // 节目ID
  18 + publishTime?: string; // 发布时间
  19 + updateTimeDesc?: string; // 节目更新时间描述
  20 + duration?: string; // 节目时长
  21 + assetID?: string; // 媒资ID
  22 + mediaSize?: number; // 节目文件大小(字节)
  23 + contentType?: string; // 内容形态
  24 + director?: string; // 导演
  25 + actor?: string; // 演员
  26 + year?: string; // 发布年份
  27 + contentStyle?: string; // 剧集类型,如:动作/剧情
  28 + displayName?: DisplayName;
  29 + copyRightVo?: CopyRightVo;
  30 + auth?: string; // 权限
  31 + title?: string; // 标题
  32 + subTitle?: string; // 子标题
  33 + type?: string; // 数据类型
  34 + programType?: string; // 节目类型(不再维护)
  35 +
  36 + // 节目类型:
  37 + // http://confluence.cmvideo.cn/confluence/pages/viewpage.action?pageId=55822514
  38 + // 节目为云直播时,值为LIVE
  39 + // 节目为挂件时,值为LIVE
  40 + programTypeV2?: string;
  41 + detail?: string; // 描述
  42 +
  43 + // 视频类型
  44 + // 1.GKE G客
  45 + // 2.LIVE 直播
  46 + // 3.VOD 点播
  47 + // 4.GRAPHIC 图文
  48 + videoType?: string;
  49 + source?: string; // 来源
  50 + score?: string; // 得分
  51 + subTxt?: SubTxt; // 角标右下角文字规则
  52 + updateEP?: string; // 更新集数(示例:更新至28集)
  53 + updateV?: string; // 更新集数(示例:28)
  54 + // pics?: Pic; // 图片(放到父类ItemDTO中)
  55 + // h5pics?: Pic; // 图片(放到父类ItemDTO中)
  56 + sign?: string; // 上传者简介(若为G客内容,则DataVo 中输出该字段)
  57 + gkeUserid?: string; // G客号用户id(若为G客内容,则DataVo 中输出该字段)
  58 + author?: string; // 节目上传者(若为G客内容,则DataVo 中输出该字段)
  59 + avator?: string; // 节目上传者头像(若为G客内容,则DataVo 中输出该字段)
  60 + shieldStrategy?: ShieldStrategy; // 屏蔽策略
  61 + tip?: Tip; // 角标,枚举类:(code, msg)
  62 + tip2?: Tip; // 清晰度角标,枚举类:(code, msg)/4K角标
  63 + showTip?: Tip;
  64 + downloadTip?: Tip; // 下载角标,枚举类:(code, msg)
  65 + strategyTipMap?: StrategyTipMap; // 不同策略计算第一象限默认角标时的结果。目前提供给VR客户端用。
  66 + // action?: Action; // 配置事件行为(移动到父类ItemDTO中)
  67 + // 适配多action
  68 + // actions?: {
  69 + // defaultAction: Action; // 对应原action
  70 + // CRBTAction?: Action; //对应彩铃action
  71 + // };
  72 + isGkeContent?: boolean; // 是G客节目
  73 + dataType?: number; // 数据类型枚举 // 1.点播节目,2.广告对象,3.挂件对象,4.云直播节目,5.图文,6.开路直播节目单,7.用户数据,8.直播间数据,9.通用对象
  74 + screenType?: string; // 屏幕类型。1: 竖屏; 2: 横屏;
  75 + fitArea?: string[]; // 适配地区
  76 +
  77 + branchMark?: boolean; // 分众标志位 true表示存在分众信息
  78 + programGroupId?: string;
  79 + compId?: string;
  80 + sortValue?: string;
  81 + programs?: ProgrammeDTO[]; // 剧集列表
  82 + fetchStrategy?: string;
  83 + position?: string;
  84 + label_4K?: string;
  85 + resolution?: Resolution;
  86 + index?: string; // 在剧集中的序号(从1开始)
  87 + way?: string;
  88 + displayType?: string;
  89 + isUFC?: string;
  90 + isPrevue?: string;
  91 + KEYWORDS?: string;
  92 + stateTime?: string; // 已完结/"每周四12:00更新1期"
  93 +
  94 + // 精选赛事列表的item
  95 + activityType?: string; // 活动类型(0:体育赛事;1:娱乐)
  96 + competitionType?: string; // 比赛类型(0 :非对抗赛, 1: 对抗)
  97 + competitionName?: string; // 赛事名称
  98 + logo?: string; // 非对抗赛图标
  99 + unionLogo?: string; // 联盟通标识图标
  100 + phase?: string; // 阶段信息
  101 + round?: string; // 轮次信息
  102 + teamShowType?: string; // 对阵球队展示顺序:teamShowType:0:主队在左,客队在右 1:客队在左,主队在右
  103 + teams?: Team[]; // 对阵球队信息
  104 + matchStartTime?: number; // 开赛时间/比赛开始时间(时间戳/单位:毫秒),如:1701011700000
  105 + startTime?: string; // 开始时间,YYYYMMDDHHmm,如202311262305
  106 + endTime?: string; // 比赛结束时间/推流结束时间(YYYYMMDDHHmm,如202311270130)
  107 + presenters?: Presenter[]; // 解说员信息
  108 +
  109 + mgdbBackgroundColor?: string;
  110 +}
  1 +export class ReportingData {
  2 + type: string;
  3 + detail?: string; // 上报数据,格式为json
  4 +}
  1 +export class Resolution {
  2 + mediaWidth: number;
  3 + mediaHeight: number;
  4 +}
  1 +/**
  2 + * 搜索bar数据
  3 + */
  4 +import { Action } from './Action';
  5 +
  6 +export class Searchbar {
  7 + defaultSearchText: string;
  8 + voiceAction: Action;
  9 + searchAction: Action;
  10 + lightVoiceIcon: string;
  11 + lightSearchIcon: string;
  12 + darkVoiceIcon: string;
  13 + darkSearchIcon: string;
  14 +}
  1 +/**
  2 + * 屏蔽策略
  3 + */
  4 +export class ShieldStrategy {
  5 + allowBarrage: boolean; // 允许弹幕
  6 + allowComment: boolean; // 允许评论
  7 + allowRedPacket: boolean; // 允许红包
  8 + allowShare: boolean; // 允许分享
  9 + allowLike: boolean; // 允许喜欢
  10 + allowCommentShare: boolean;
  11 +}
  1 +import { Tip } from './Tip';
  2 +
  3 +export interface StrategyTipMap {
  4 + CHARGE: Tip;
  5 +}
  1 +/**
  2 + * 角标右下角文字规则
  3 + */
  4 +export class SubTxt {
  5 + txt: string;
  6 + subTxtStyle: string;
  7 +}
  1 +/**
  2 + * NAV_BAR-01
  3 + * 导航栏(顶导/首页/体育/vip)
  4 + */
  5 +import { ItemBean } from './ItemBean';
  6 +import { Tab01DTO } from './Tab01DTO';
  7 +
  8 +@Observed
  9 +export class Tab01Bean extends ItemBean {
  10 + title: string; // 导航栏标题
  11 + tabImg?: string; // TAB图片
  12 + defaultTextColor?: string; // 导航文字默认颜色
  13 + headBackgroundImg?: string; // 头部背景色(搜索bar背景图片)
  14 + // backgroundImg?: string;
  15 + // actTextColor?: string;
  16 +
  17 + constructor(dto: Tab01DTO) {
  18 + super(dto);
  19 + this.title = dto.title
  20 + this.tabImg = dto.tabImg
  21 + this.defaultTextColor = dto.defaultTextColor
  22 + this.headBackgroundImg = dto.headBackgroundImg
  23 + // this.backgroundImg = dto.backgroundImg
  24 + // this.actTextColor = dto.actTextColor
  25 + }
  26 +}
  1 +/**
  2 + * NAV_BAR-01
  3 + * menu:导航栏(顶导/首页/体育/vip)
  4 + */
  5 +import { ItemDTO } from './ItemDTO';
  6 +
  7 +export class Tab01DTO extends ItemDTO {
  8 + icon?: string; // 导航栏icon
  9 + title: string; // 导航栏标题
  10 + defaultTextColor?: string; // 导航文字默认颜色
  11 + defTextColor?: string; // 导航文字颜色
  12 + activatedTextColor?: string; // 导航文字Active默认颜色
  13 + actTextColor?: string; // 导航文字Active颜色
  14 + headBackgroundColor?: string; // 头部背景色
  15 + backgroundImg?: string; // 背景图片
  16 + headBackgroundImg?: string; // 头部背景色(搜索bar背景图片)
  17 + tipImg?: string; // 标签图片
  18 + manageIcon?: string; // 频道管理图标
  19 + deletable?: string; // 是否可删除
  20 + recommendable?: string; // 是否主推荐
  21 + topBarId?: string; // 顶部导航栏模板
  22 + id?: string; // 导航栏id
  23 + tabImg?: string; // TAB图片
  24 + // tabImgSize?: any; // TAB图片尺寸
  25 + grayFilter?: string;
  26 + output?: string;
  27 +}
  1 +/**
  2 + * NAV_BAR-22
  3 + * 播放详情底部tab
  4 + */
  5 +import { ItemBean } from './ItemBean';
  6 +import { Tab22DTO } from './Tab22DTO';
  7 +
  8 +@Observed
  9 +export class Tab22Bean extends ItemBean {
  10 + tabText: string; // 详情/讨论/(热播榜-特惠-抽周边-有奖征集)/(赛程-热门直播)
  11 + tabType: string; // detail/discuss/H5Page/nativePage
  12 + selectedColor?: string;
  13 + unselectedColor?: string;
  14 + // showCommentCount?: string;
  15 + backgroundColor?: string;
  16 + // backgroundImg?: string;
  17 + // bottomBarBackgroundImg?: string;
  18 + // bottomBarIconUnselectedColor?: string;
  19 + // bottomBarIconSelectedColor?: string;
  20 + // bottomBarBackgroundColor?: string;
  21 +
  22 + normalTextColor?: string = "";
  23 + activeTextColor?: string = "";
  24 +
  25 + constructor(dto: Tab22DTO) {
  26 + super(dto);
  27 + this.tabText = dto.tabText
  28 + this.tabType = dto.tabType
  29 + this.selectedColor = dto.selectedColor
  30 + this.unselectedColor = dto.unselectedColor
  31 + this.backgroundColor = dto.backgroundColor
  32 + }
  33 +}
  1 +/**
  2 + * NAV_BAR-22
  3 + * 播放详情,播放器下面的tab
  4 + */
  5 +import { ItemDTO } from './ItemDTO';
  6 +
  7 +export class Tab22DTO extends ItemDTO {
  8 + tabText: string; // 详情/讨论/(热播榜-特惠-抽周边-有奖征集)/(赛程-热门直播)
  9 + tabType: string; // detail/discuss/H5Page/nativePage
  10 + selectedColor?: string; // TAB项选中文字颜色
  11 + unselectedColor?: string; // TAB项未选中文字颜色
  12 + showCommentCount?: string; //
  13 + backgroundColor?: string; // TAB背景颜色
  14 + backgroundImg?: string; // TAB背景图片
  15 + bottomBarBackgroundImg?: string;
  16 + bottomBarIconUnselectedColor?: string;
  17 + bottomBarIconSelectedColor?: string;
  18 + bottomBarBackgroundColor?: string;
  19 +}
  1 +/**
  2 + * ConfrontTeam/NBATeam.
  3 + * 赛事的对战对/对抗团队/队伍(主队/客队)
  4 + */
  5 +export class Team {
  6 + teamId?: string; // 球队id
  7 + teamName?: string; // 队伍名称
  8 + teamLogo?: string; // 队伍icon
  9 + isHome?: string; // 是否主队("1"是主队,“0”是客队)
  10 + score?: string; // 比赛队伍(当前)得分 -1表示无分数
  11 +}
  1 +/**
  2 + * 角标,枚举类:(code,msg)
  3 + */
  4 +export class Tip {
  5 + code: string;
  6 + msg: string;
  7 +}
  1 +/**
  2 + * 顶部bar数据(包含搜索bar)
  3 + */
  4 +import { Logo } from './Logo';
  5 +import { NavButton } from './NavButton';
  6 +import { Searchbar } from './Searchbar';
  7 +
  8 +export class TopBar {
  9 + id: string;
  10 + name: string;
  11 +
  12 + // type?: number; // 0-顶导 1-挂件、2-长视频播放详情页、3-短视频播放详情页、4-开路直播播放详情页。
  13 + logo: Logo; // 搜索bar左外侧的logo图标
  14 + searchbars?: Searchbar;
  15 + buttons: NavButton[];
  16 + lightBackImg?: string;
  17 +
  18 + // lightBackImgColor?:string;
  19 + darkBackImg?: string;
  20 + // darkBackImgColor?:string;
  21 + isForceUse?: number;
  22 +}
  1 +/**
  2 + * 组件Style/展示样式(字典值)
  3 + */
  4 +export const enum CompStyle {
  5 + LABEL_01 = 'LABEL-01', // 标题
  6 + BUTTON_01 = 'BUTTON-01', // 按钮/更多/更多热点/更多热播电视剧/换一换
  7 + NAV_BAR_01 = 'NAV_BAR-01', // 导航栏(顶导/首页/体育/vip)
  8 + // NAV_BAR_08 = 'NAV_BAR-08', // 导航栏(顶导/短视频tab)
  9 + NAV_BAR_22 = 'NAV_BAR-22', // 导航栏(顶导/播放详情底部tab)
  10 + NAV_BAR_03 = 'NAV_BAR-03', // 圆形按钮导航栏(横滑)
  11 + BIG_STATIC_IMG_01 = 'BIG_STATIC_IMG-01', // 静态大图
  12 + BIG_CAROUSEL_IMG_01 = 'BIG_CAROUSEL_IMG-01', // 轮播大图,即Banner/焦点图
  13 + BIG_PLAY_IMG_01 = 'BIG_PLAY_IMG-01', // 播放大图
  14 + TOP_IMG_BOTTOM_TXT_01 = 'TOP_IMG_BOTTOM_TXT-01', // 横图-上图下文/重磅推荐
  15 + TOP_IMG_BOTTOM_TXT_02 = 'TOP_IMG_BOTTOM_TXT-02', // 竖图-上图下文/大家都在看/短剧
  16 + TOP_IMG_BOTTOM_TXT_12 = 'TOP_IMG_BOTTOM_TXT-12', // 竖图-上图下文/瀑布流形式
  17 + BINGE_WATCHING_02 = 'BINGE_WATCHING-02', // 猜你在追/猜你会追(横滑)
  18 + SLIDER_IMG_16 = 'SLIDER_IMG-16', // 滑动图/(横滑)/精彩小视频/为你推荐区
  19 + MATCH_LIST_04 = 'MATCH_LIST-04', // 精选赛事列表(横滑)
  20 + // MY_HOME_INFO = 'MY_HOME-INFO', // 我的信息:头像/用户名等个人信息
  21 + // MY_HOME_SERVICE_NEW = 'MY_HOME-SERVICE_NEW', // 服务区(新)/个人服务
  22 + // MY_HOME_VERSION_NUMBER = 'MY_HOME-VERSION-NUMBER', // 客户端名称及版本号
  23 + // PLAYER_01 = 'PLAYER-01', // 播放区/播放器
  24 + PROGRAM_DESC_01 = 'PROGRAM_DESC-01', // 节目简介区
  25 + PROGRAM_SET_01 = 'PROGRAM_SET-01', // "选集区"/"剧集区"
  26 + CLASSIFY_FILTER_BAR_02 = 'CLASSIFY_FILTER_BAR-02', // 筛选条件区
  27 + WORLDCUP_PLAYBILL = 'WORLDCUP-PLAYBILL', // 赛程页
  28 +}
  1 +/**
  2 + * 组件Type/展示类型
  3 + */
  4 +export const enum CompType {
  5 + LABEL = 'LABEL', // 标题
  6 + BUTTON = 'BUTTON', // 按钮/换一换
  7 + NAV_BAR = 'NAV_BAR', // tab导航栏/按钮导航区
  8 + BIG_STATIC_IMG = 'BIG_STATIC_IMG', // 静态大图
  9 + BIG_CAROUSEL_IMG = 'BIG_CAROUSEL_IMG', // 轮播大图,即Banner/焦点图
  10 + BIG_PLAY_IMG = 'BIG_PLAY_IMG', // 播放大图
  11 + TOP_IMG_BOTTOM_TXT = 'TOP_IMG_BOTTOM_TXT', // 上图下文
  12 + BINGE_WATCHING = 'BINGE_WATCHING', // 猜你在追/猜你会追(横滑)
  13 + SLIDER_IMG = 'SLIDER_IMG', // 精彩小视频/为你推荐区
  14 + MATCH_LIST = 'MATCH_LIST', // 精选赛事列表(横滑)
  15 + MY_HOME = 'MY_HOME', // 我的
  16 + PLAYER = 'PLAYER', // 播放区
  17 + PROGRAM_DESC = 'PROGRAM_DESC', // 节目简介区
  18 + PROGRAM_SET = 'PROGRAM_SET', // "选集区"/"剧集区"
  19 + CLASSIFY_FILTER_BAR = 'CLASSIFY_FILTER_BAR', // 筛选条件区
  20 + WORLDCUP = 'WORLDCUP', // 赛程页
  21 +}
  1 +/**
  2 + * 请求网络数据状态类型/也是View Type
  3 + */
  4 +export const enum NetDataStatusType {
  5 + // 已初始化,但尚未发出请求
  6 + INITIAL = 0,
  7 + // 取消请求/或无需网络请求/或不关心请求结果/或调用方没有设置回调callback
  8 + CANCEL,
  9 + // 已发出请求,但请求尚未返回;
  10 + LOADING,
  11 + // 请求已失败返回;
  12 + FAILED,
  13 + // 请求已成功返回;
  14 + LOADED
  15 +}
  1 +/**
  2 + * 详情 的 tab item类型
  3 + */
  4 +export const enum TabType {
  5 + detail = 'detail', // 详情
  6 + discuss = 'discuss', // 讨论
  7 + H5Page = 'H5Page', // 热播榜-特惠-抽周边-有奖征集
  8 + nativePage = 'nativePage', // 赛程-热门直播
  9 +}
  1 +/**
  2 + * 主界面更多,按钮Comp
  3 + */
  4 +import { ButtonBean } from '../bean/ButtonBean';
  5 +import { CompDTO } from '../bean/CompDTO';
  6 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  7 +import { DataFromExtraComp } from './DataFromExtraComp';
  8 +import List from '@ohos.util.List';
  9 +import { ExtraDTO } from '../bean/ExtraDTO';
  10 +import { ButtonDTO } from '../bean/ButtonDTO';
  11 +import { WDGroup } from './WDGroup';
  12 +
  13 +export class ButtonComp extends DataFromExtraComp<ButtonBean> {
  14 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  15 + super(parent, compDTO, initParams);
  16 + this.status = NetDataStatusType.LOADED
  17 + }
  18 +
  19 + public getItems(): List<ButtonBean> {
  20 + return this.items;
  21 + }
  22 +
  23 + protected convertDto2Vo(extraDataDTO: ExtraDTO): List<ButtonBean> {
  24 + if (!extraDataDTO) {
  25 + return new List<ButtonBean>();
  26 + }
  27 + let beanList: List<ButtonBean> = new List<ButtonBean>();
  28 + // let dtoArray: ButtonDTO[] | undefined = extraDataDTO["buttons"]
  29 + let dtoArray: ButtonDTO[] | undefined= extraDataDTO.buttons
  30 + if (!dtoArray) {
  31 + return new List<ButtonBean>();
  32 + }
  33 + for (let index = 0; index < dtoArray.length; index = index + 1) {
  34 + let dto: ButtonDTO = dtoArray[index];
  35 + let bean: ButtonBean = new ButtonBean(dto);
  36 + beanList.add(bean);
  37 + }
  38 + return beanList;
  39 + }
  40 +}
  1 +/**
  2 + * DataFromExtraComp是指数据从comp的extraData中获取的这类comp
  3 + */
  4 +import { CompDataDTO } from '../bean/CompDataDTO';
  5 +import { CompDTO } from '../bean/CompDTO';
  6 +import { ExtraDTO } from '../bean/ExtraDTO';
  7 +import { ItemBean } from '../bean/ItemBean';
  8 +import { WDComp } from './WDComp';
  9 +import { WDGroup } from './WDGroup';
  10 +
  11 +export abstract class DataFromExtraComp<VO extends ItemBean> extends WDComp<VO, ExtraDTO> {
  12 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  13 + super(parent, compDTO, initParams);
  14 +
  15 + this.items = this.convertDto2Vo(this.compDTO.extraData ?? {} as ExtraDTO);
  16 + }
  17 +
  18 + public setData(compDataDTO: CompDataDTO): void {
  19 + }
  20 +
  21 + public loadMore(): void {
  22 + }
  23 +
  24 + public loadFirst(): void {
  25 + }
  26 +
  27 + public loadWithGroupData(): boolean {
  28 + return false;
  29 + }
  30 +
  31 + public hasMoreData(): boolean {
  32 + return false;
  33 + }
  34 +
  35 + public isLoaded(): boolean {
  36 + return true;
  37 + }
  38 +
  39 + public needCheckIntegrity(): boolean {
  40 + return false;
  41 + }
  42 +}
  1 +/**
  2 + * 瀑布流形式的comp
  3 + */
  4 +import { CompDTO } from '../bean/CompDTO';
  5 +import { ItemBean } from '../bean/ItemBean';
  6 +import { ItemDTO } from '../bean/ItemDTO';
  7 +import { WDComp } from './WDComp';
  8 +import { WDGroup } from './WDGroup';
  9 +import List from '@ohos.util.List';
  10 +import { CompDataDTO } from '../bean/CompDataDTO';
  11 +
  12 +export class FlowComp<VO extends ItemBean, DTO extends ItemDTO> extends WDComp<VO, DTO> {
  13 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  14 + super(parent, compDTO, initParams);
  15 + }
  16 +
  17 + protected convertDto2Vo(dto: DTO): List<VO> {
  18 + return new List()
  19 + }
  20 +
  21 + public setData(compDataDTO: CompDataDTO) {
  22 + }
  23 +}
  1 +/**
  2 + * 主界面更多,按钮Comp
  3 + */
  4 +import { CompDTO } from '../bean/CompDTO';
  5 +import { LabelBean } from '../bean/LabelBean';
  6 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  7 +import { DataFromExtraComp } from './DataFromExtraComp';
  8 +import List from '@ohos.util.List';
  9 +import { LabelDTO } from '../bean/LabelDTO';
  10 +import { ExtraDTO } from '../bean/ExtraDTO';
  11 +import { WDGroup } from './WDGroup';
  12 +
  13 +export class LabelComp extends DataFromExtraComp<LabelBean> {
  14 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  15 + super(parent, compDTO, initParams);
  16 + this.status = NetDataStatusType.LOADED
  17 + }
  18 +
  19 + public getItems(): List<LabelBean> {
  20 + return this.items;
  21 + }
  22 +
  23 + protected convertDto2Vo(extraDataDTO: ExtraDTO): List<LabelBean> {
  24 + if (!extraDataDTO) {
  25 + return new List<LabelBean>();
  26 + }
  27 + let beanList: List<LabelBean> = new List<LabelBean>();
  28 + // let dtoArray: LabelDTO[] | undefined = extraDataDTO["labels"]
  29 + let dtoArray: LabelDTO[] | undefined= extraDataDTO.labels
  30 + if (!dtoArray) {
  31 + return new List<LabelBean>();
  32 + }
  33 + for (let index = 0; index < dtoArray.length; index = index + 1) {
  34 + let dto: LabelDTO = dtoArray[index];
  35 + let bean: LabelBean = new LabelBean(dto);
  36 + beanList.add(bean);
  37 + }
  38 + return beanList;
  39 + }
  40 +}
  1 +/**
  2 + * Page状态监听
  3 + */
  4 +export interface PageListener {
  5 + /**
  6 + * Page数据加载完成
  7 + * @param page MGPage实例
  8 + */
  9 + onPageLoaded: (page: WDPage) => void;
  10 +
  11 + /**
  12 + * Page数据加载失败
  13 + * @param page MGPage实例
  14 + */
  15 + onPageFailed: (page: WDPage) => void;
  16 +
  17 + /**
  18 + * Group数据加载完成
  19 + * @param page 所在的MGPage实例
  20 + * @param group MGGroup实例
  21 + */
  22 + onGroupLoaded: (page: WDPage, group: WDGroup) => void;
  23 +
  24 + /**
  25 + * Group数据加载失败
  26 + * @param page 所在的MGPage实例
  27 + * @param group MGGroup实例
  28 + */
  29 + onGroupFailed: (page: WDPage, group: WDGroup) => void;
  30 +
  31 + /**
  32 + * Comp数据加载完成
  33 + * @param page 所在的MGPage实例
  34 + * @param group 所在的MGGroup实例
  35 + * @param comp MGComp实例
  36 + */
  37 + onCompLoaded: (page: WDPage, group: WDGroup, comp: WDComp<ItemBean, ItemDTO>) => void;
  38 +
  39 + /**
  40 + * Comp数据加载失败
  41 + * @param page 所在的MGPage实例
  42 + * @param group 所在的MGGroup实例
  43 + * @param comp MGComp实例
  44 + */
  45 + onCompFailed: (page: WDPage, group: WDGroup, comp: WDComp<ItemBean, ItemDTO>) => void;
  46 +
  47 +}
  1 +/**
  2 + * 剧集相关Comp,数据源无需ProgrammeComp自己加载,从MGComp中控制获得数据
  3 + * CompType:
  4 + * BIG_CAROUSEL_IMG
  5 + * TOP_IMG_BOTTOM_TXT
  6 + * BIG_STATIC_IMG
  7 + * BIG_PLAY_IMG
  8 + * SLIDER_IMG
  9 + * NAV_BAR_03
  10 + * BINGE_WATCHING
  11 + * MY_HOME
  12 + */
  13 +import { CompDataDTO } from '../bean/CompDataDTO';
  14 +import { CompDTO } from '../bean/CompDTO';
  15 +import { WDComp } from './WDComp';
  16 +import { WDGroup } from './WDGroup';
  17 +import List from '@ohos.util.List';
  18 +import { ProgrammeDTO } from '../bean/ProgrammeDTO';
  19 +import { CompType } from '../enum/CompType';
  20 +import { ProgrammeBean } from '../bean/ProgrammeBean';
  21 +import { PageUtils } from '../utils/PageUtils';
  22 +
  23 +export class ProgrammeComp extends WDComp<ProgrammeBean, CompDataDTO> {
  24 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  25 + super(parent, compDTO, initParams);
  26 + }
  27 +
  28 + protected convertDto2Vo(compDataDTO: CompDataDTO): List<ProgrammeBean> {
  29 + if (!compDataDTO || !compDataDTO.data) {
  30 + return new List<ProgrammeBean>();
  31 + }
  32 +
  33 + let programmeBeanList: List<ProgrammeBean> = new List<ProgrammeBean>();
  34 + for (let index = 0; index < compDataDTO.data.length; index = index + 1) {
  35 + let programmeData: ProgrammeDTO = compDataDTO.data[index];
  36 + let bean: ProgrammeBean = new ProgrammeBean(programmeData);
  37 + this.buildTip(bean)
  38 + programmeBeanList.add(bean);
  39 + }
  40 + if (this.getCompType() == CompType.TOP_IMG_BOTTOM_TXT) {
  41 + programmeBeanList = this.complementTrimData(programmeBeanList)
  42 + }
  43 + return programmeBeanList;
  44 + }
  45 +
  46 + /**
  47 + * build角标等数据
  48 + */
  49 + buildTip(bean: ProgrammeBean): void {
  50 + bean.topRightTipImgUrl = PageUtils.getTopRightTipImgUrl(bean)
  51 + bean.topLeftTipImgUrl = PageUtils.getTopLeftTipImgUrl(bean)
  52 + }
  53 +
  54 + public setData(compDataDTO: CompDataDTO) {
  55 + if (!compDataDTO || !compDataDTO.data) {
  56 + return;
  57 + }
  58 + this.items = this.convertDto2Vo(compDataDTO);
  59 + }
  60 +
  61 + public hasMoreData(): boolean {
  62 + return false;
  63 + }
  64 +
  65 + // public isLoaded(): boolean {
  66 + // return this.items.length > 0;
  67 + // }
  68 +}
  1 +/**
  2 + * CompStyle:NAV_BAR-01
  3 + * 导航栏(顶导/首页/体育/vip)tab
  4 + */
  5 +import { CompDTO } from '../bean/CompDTO';
  6 +import { Tab01Bean } from '../bean/Tab01Bean';
  7 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  8 +import { DataFromExtraComp } from './DataFromExtraComp';
  9 +import List from '@ohos.util.List';
  10 +import { ExtraDTO } from '../bean/ExtraDTO';
  11 +import { Tab01DTO } from '../bean/Tab01DTO';
  12 +import { CompFilterUtil } from '../utils/CompFilterUtil';
  13 +import { WDGroup } from './WDGroup';
  14 +
  15 +export class TabBar01Comp extends DataFromExtraComp<Tab01Bean> {
  16 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  17 + super(parent, compDTO, initParams);
  18 + this.status = NetDataStatusType.LOADED
  19 + }
  20 +
  21 + public getItems(): List<Tab01Bean> {
  22 + return this.items;
  23 + }
  24 +
  25 + protected convertDto2Vo(extraDataDTO: ExtraDTO): List<Tab01Bean> {
  26 + if (!extraDataDTO) {
  27 + return new List<Tab01Bean>();
  28 + }
  29 + let beanList: List<Tab01Bean> = new List<Tab01Bean>();
  30 + // let dtoArray: Tab01DTO[] | undefined = extraDataDTO["menus"]
  31 + let dtoArray: Tab01DTO[] | undefined= extraDataDTO.menus
  32 + if (!dtoArray) {
  33 + return new List<Tab01Bean>();
  34 + }
  35 + for (let index = 0; index < dtoArray.length; index = index + 1) {
  36 + let dto: Tab01DTO = dtoArray[index];
  37 + if (!CompFilterUtil.filterTab01(dto)) {
  38 + continue
  39 + }
  40 + let bean: Tab01Bean = new Tab01Bean(dto);
  41 + beanList.add(bean);
  42 + }
  43 + return beanList;
  44 + }
  45 +}
  1 +/**
  2 + * CompStyle:NAV_BAR-22
  3 + * 播放详情底部tab
  4 + */
  5 +import { CompDTO } from '../bean/CompDTO';
  6 +import { Tab22Bean } from '../bean/Tab22Bean';
  7 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  8 +import { DataFromExtraComp } from './DataFromExtraComp';
  9 +import List from '@ohos.util.List';
  10 +import { ExtraDTO } from '../bean/ExtraDTO';
  11 +import { Tab22DTO } from '../bean/Tab22DTO';
  12 +import { WDGroup } from './WDGroup';
  13 +import { TabType } from '../enum/TabType';
  14 +
  15 +export class TabBar22Comp extends DataFromExtraComp<Tab22Bean> {
  16 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  17 + super(parent, compDTO, initParams);
  18 + this.status = NetDataStatusType.LOADED
  19 + }
  20 +
  21 + public getItems(): List<Tab22Bean> {
  22 + return this.items;
  23 + }
  24 +
  25 + protected convertDto2Vo(extraDataDTO: ExtraDTO): List<Tab22Bean> {
  26 + if (!extraDataDTO) {
  27 + return new List<Tab22Bean>();
  28 + }
  29 + let beanList: List<Tab22Bean> = new List<Tab22Bean>();
  30 + // let dtoArray: Tab22DTO[] | undefined = extraDataDTO["tabs"]
  31 + let dtoArray: Tab22DTO[] | undefined = extraDataDTO.tabs
  32 + if (!dtoArray) {
  33 + return new List<Tab22Bean>();
  34 + }
  35 + for (let index = 0; index < dtoArray.length; index = index + 1) {
  36 + let dto: Tab22DTO = dtoArray[index];
  37 + if (dto.tabType != TabType.discuss) { // 过滤掉【讨论】tab
  38 + let bean: Tab22Bean = new Tab22Bean(dto);
  39 + this.buildTextColor(bean)
  40 + beanList.add(bean);
  41 + }
  42 + }
  43 + return beanList;
  44 + }
  45 +
  46 + private buildTextColor(bean: Tab22Bean): void {
  47 + let normalTextColor = bean.unselectedColor;
  48 + if (!normalTextColor) {
  49 + normalTextColor = "#666666";
  50 + }
  51 + bean.normalTextColor = normalTextColor;
  52 +
  53 + let activeTextColor = bean.selectedColor;
  54 + if (!activeTextColor) {
  55 + activeTextColor = "#333333";
  56 + }
  57 + bean.activeTextColor = activeTextColor;
  58 + return
  59 + }
  60 +}
  1 +/**
  2 + * Comp数据获取管理及相关业务逻辑处理
  3 + *
  4 + * @param <VO> 业务展示数据对象,显示Comp item的数据对象
  5 + * @param <DTO> 网络传输数据对象,与服务器端接口定义的字段一致
  6 + */
  7 +import { CompDTO } from '../bean/CompDTO';
  8 +import { ItemBean } from '../bean/ItemBean';
  9 +import { ItemDTO } from '../bean/ItemDTO';
  10 +import List from '@ohos.util.List';
  11 +import { WDGroup } from './WDGroup';
  12 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  13 +import { DataSourceRequest } from '../bean/DataSourceRequest';
  14 +import { LayoutCallback } from '../service/LayoutCallback';
  15 +
  16 +import { ArrayUtils, StringUtils } from 'wdKit';
  17 +import { CompDataDTO } from '../bean/CompDataDTO';
  18 +import { CommonDataService } from '../service/CommonDataService';
  19 +
  20 +export abstract class WDComp<VO extends ItemBean, DTO extends ItemDTO> {
  21 + protected parent: WDGroup;
  22 + protected compDTO: CompDTO;
  23 + protected initParams: Map<string, Object> = new Map<string, Object>();
  24 + // view展示的由DTO转换Bean后的数据列表
  25 + protected items: List<VO> = new List<VO>();
  26 + // 当前组件数据加载状态
  27 + protected status: number = NetDataStatusType.INITIAL;
  28 + /**
  29 + * 标记是否为需要合并请求的Comp
  30 + */
  31 + private isTeamwork: boolean = false;
  32 + private isRefresh: boolean = false;
  33 +
  34 + /**
  35 + * 标记是否为无限瀑布流
  36 + */
  37 + // private isFeed: boolean = false;
  38 + /**
  39 + * 标记是否为黑白化
  40 + */
  41 + // private isGrayMode: boolean = false;
  42 + // protected data: HashMap<String, List<VO>> = new HashMap<string, List<VO>>();
  43 + // protected dynamicData: HashMap<String, VO> = new HashMap<String, VO>();
  44 +
  45 + /**
  46 + * 构造函数
  47 + *
  48 + * @param parent WDGroup
  49 + * @param compDTO 服务器返回的CompDTO
  50 + * @param initParams 初始化参数
  51 + */
  52 + constructor(parent: WDGroup, compDTO: CompDTO, initParams: Map<string, Object>) {
  53 + this.parent = parent;
  54 + this.compDTO = compDTO;
  55 + this.initParams = initParams;
  56 +
  57 + if (parent) {
  58 + this.isTeamwork = parent.getIsTeamWork() && compDTO.dataSource == "CONTENT_POOL_PER_RECOMMAND";
  59 + // this.isGrayMode = parent.getIsGrayMode();
  60 + }
  61 + }
  62 +
  63 + /**
  64 + * 加载第一页的数据
  65 + */
  66 + public loadFirst(): void {
  67 + this.loadData();
  68 + }
  69 +
  70 + /**
  71 + * 在分页加载时,加载下一页的数据, 默认加载第一页数据, 加载更多数据时,需要重写该方法
  72 + */
  73 + public loadMore() {
  74 + this.loadFirst();
  75 + }
  76 +
  77 + /**
  78 + * 重新加载数据/切换comp数据,一般用于换一换功能
  79 + * @param params
  80 + */
  81 + public reloadData(params: Map<String, Object>): void {
  82 + this.loadFirst();
  83 + }
  84 +
  85 + /**
  86 + * 加载Comp数据
  87 + */
  88 + public loadData() {
  89 + // TODO: 调用onLoadData加载数据
  90 + if (this.isTeamWork() || this.status == NetDataStatusType.LOADING) {
  91 + return;
  92 + }
  93 +
  94 + this.onLoadData()
  95 + }
  96 +
  97 + /**
  98 + * 加载comp(默认通用)数据源
  99 + */
  100 + protected onLoadData(): void {
  101 + // TODO: 通过CommonData
  102 + if (this.dataSourceEnabled() && this.compDTO && this.compDTO.dataSourceRequest) {
  103 + // let isBackupDataSource = false;
  104 + let callback: LayoutCallback<DTO> = {
  105 + onSuccess: (dto: DTO): void => {
  106 + this.transformResponseData(dto);
  107 + if (this.items.length > 0) {
  108 + this.onLoadDataFinished()
  109 + } else {
  110 + this.onLoadDataFailed()
  111 + }
  112 + return
  113 + },
  114 + onFailed: (code: number, message: string): void => {
  115 + // todo:
  116 + this.onLoadDataFailed()
  117 + return
  118 + }
  119 + };
  120 + let service: CommonDataService = new CommonDataService();
  121 +
  122 + for (let index = 0; index < this.compDTO.dataSourceRequest.length; index++) {
  123 + let request: DataSourceRequest = this.compDTO.dataSourceRequest[index]
  124 + // request.locationValue = getLocation();
  125 + if (this.isTeamWork()) {
  126 + continue;
  127 + }
  128 + this.status = NetDataStatusType.LOADING;
  129 + service.loadDataSource<DTO>(this.compDTO, request, callback)
  130 + }
  131 + }
  132 + }
  133 +
  134 + /**
  135 + * 数据转换:转换网络请求的response DTO为业务展示的bean
  136 + *
  137 + * @param dto 网络请求的数据
  138 + */
  139 + protected transformResponseData(dto: DTO): void {
  140 + // TODO: 调用convertDto2Vo转换并记录数据
  141 + let beanList: List<VO> = this.convertDto2Vo(dto);
  142 + if (beanList && beanList.length > 0) {
  143 + if (this.isRefresh) {
  144 + this.items.clear();
  145 + this.isRefresh = false;
  146 + }
  147 + this.items = ArrayUtils.addAll(this.items, beanList)
  148 + }
  149 + }
  150 +
  151 + // 根据compDTO.displayCount字段值,在列表尾部补全数据或把列表尾部数据截断
  152 + protected complementTrimData(originalList: List<VO>): List<VO> {
  153 + let displayCount: number = this.getCompDisplayCount(); // 展示数量
  154 + if (!originalList || displayCount == 0 || originalList.length == displayCount) {
  155 + return originalList;
  156 + }
  157 +
  158 + if (originalList.length < displayCount) {
  159 + let newItemList: List<VO> = originalList;
  160 + // 在尾部补全数据
  161 + let complementCount = displayCount - originalList.length;
  162 + let complementIndex = 0
  163 + while (complementIndex < complementCount) {
  164 + // 从原有数据前(循环)依次取数据,补充到列表后部,
  165 + let itemIndex = complementIndex % originalList.length // 取模(余数)
  166 + newItemList.add(originalList.get(itemIndex))
  167 + complementIndex++
  168 + }
  169 + return newItemList;
  170 + } else if (originalList.length > displayCount) {
  171 + // 截取/截断
  172 + // return originalList.getSubList(0, displayCount); // 异常报错
  173 + let newItemList: List<VO> = new List<VO>()
  174 + let itemIndex = 0
  175 + while (itemIndex < displayCount) {
  176 + newItemList.add(originalList.get(itemIndex))
  177 + itemIndex++
  178 + }
  179 + return newItemList;
  180 + } else {
  181 + return originalList;
  182 + }
  183 + }
  184 +
  185 + /**
  186 + * 留给业务实现的数据转换
  187 + */
  188 + protected abstract convertDto2Vo(dto: DTO): List<VO>;
  189 +
  190 + /**
  191 + * 获取Comp的数据源,将一个data DTO设置为Comp的数据;设置comp对应的compDataDTO
  192 + */
  193 + public abstract setData(compDataDTO: CompDataDTO): void;
  194 +
  195 + /**
  196 + * 使用动态数据替换静态数据
  197 + * @param programme 动态数据
  198 + */
  199 + // public replaceStaticData(data: ProgrammeData): boolean {
  200 + // // TODO: 数据替换
  201 + // // let item: VO = this.dynamicData.get(data.position);
  202 + // // if (item instanceof ProgrammeBean) {
  203 + // // // item.transform(data);
  204 + // // return true;
  205 + // // } else {
  206 + // return false;
  207 + // // }
  208 + // }
  209 +
  210 + /**
  211 + * 是否正在加载中
  212 + * @returns
  213 + */
  214 + public getIsLoading(): boolean {
  215 + // TODO: 是否正在加载中
  216 + return this.status == NetDataStatusType.LOADING;
  217 + }
  218 +
  219 + /**
  220 + * 是否加载完毕
  221 + * @returns
  222 + */
  223 + public isLoaded(): boolean {
  224 + // TODO: 是否已经加载完毕
  225 + return this.status == NetDataStatusType.LOADED || this.status == NetDataStatusType.FAILED || this.status == NetDataStatusType.CANCEL;
  226 + }
  227 +
  228 + /**
  229 + * 是否(成功)加载完毕
  230 + * @returns
  231 + */
  232 + public isLoadedSuccess(): boolean {
  233 + return this.status == NetDataStatusType.LOADED;
  234 + }
  235 +
  236 + /**
  237 + * 是否还有更多数据待加载 / 判断是否还有下一页/,需要重写该方法
  238 + */
  239 + public hasMoreData(): boolean {
  240 + // TODO: 判断是否有存在更多数据
  241 + return false;
  242 + }
  243 +
  244 + /**
  245 + * Group中所有的Comp是否都已加载完毕
  246 + * @returns
  247 + */
  248 + public hasDataLoaded(): boolean {
  249 + // TODO: 所有Comp是否都已经加载完数据
  250 + return false;
  251 + }
  252 +
  253 + /**
  254 + * 是否需要加载动态数据
  255 + * @returns
  256 + */
  257 + public hasDynamicData(): boolean {
  258 + // TODO: 判断数据源的dataSourceType是否为“POMS_NODE”,是则需要加载动态数据。
  259 + if (this.compDTO && this.compDTO.dataSourceRequest && this.compDTO.dataSourceRequest.length > 0) {
  260 + for (let index = 0; index < this.compDTO.dataSourceRequest.length; index++) {
  261 + let request: DataSourceRequest = this.compDTO.dataSourceRequest[index]
  262 + if (request.dataSourceType == "POMS_NODE") {
  263 + return true;
  264 + }
  265 + }
  266 + }
  267 + return false;
  268 + }
  269 +
  270 + public isTeamWork(): boolean {
  271 + return this.isTeamwork;
  272 + }
  273 +
  274 + protected dataSourceEnabled(): boolean {
  275 + return true;
  276 + }
  277 +
  278 + /**
  279 + * 获取该comp所在的group
  280 + */
  281 + public getParent(): WDGroup {
  282 + return this.parent;
  283 + }
  284 +
  285 + /**
  286 + * 获取comp对应的compDTO
  287 + */
  288 + public getCompDTO(): CompDTO {
  289 + return this.compDTO;
  290 + }
  291 +
  292 + /**
  293 + * 获取comp Id
  294 + */
  295 + public getId(): string {
  296 + return!this.compDTO ? "" : this.compDTO.id;
  297 + }
  298 +
  299 + /**
  300 + * 获取Comp Type
  301 + */
  302 + public getCompType(): string {
  303 + return!this.compDTO ? "" : this.compDTO.compType;
  304 + }
  305 +
  306 + /**
  307 + * 获取Comp Style
  308 + */
  309 + public getCompStyle(): string {
  310 + return!this.compDTO ? "" : this.compDTO.compStyle;
  311 + }
  312 +
  313 + /**
  314 + * 获取组件DisplayCount
  315 + */
  316 + public getCompDisplayCount(): number {
  317 + if (!this.compDTO) {
  318 + return 0
  319 + }
  320 + return StringUtils.parseNumber(this.compDTO.displayCount)
  321 + }
  322 +
  323 + /**
  324 + * 检查父Group是否需要加载数据,默认为true, 某些Comp的数据源是从{@link CompDTO}的extraData或其他字段中获取,
  325 + * 如Label, button等, 则该Comp无需父group再去请求数据
  326 + */
  327 + public loadWithGroupData(): boolean {
  328 + return true;
  329 + }
  330 +
  331 + /**
  332 + * 检查是否独立加载数据
  333 + *
  334 + * @returns 如果该comp是独立加载数据的返回true, 否则返回false.
  335 + */
  336 + public separateLoad(): boolean {
  337 + if (!this.compDTO) {
  338 + return false;
  339 + }
  340 + // if (this.compDTO.compType === CompType.LABEL || this.compDTO.compType === CompType.BUTTON) {
  341 + // return false
  342 + // }
  343 + if (!this.compDTO.dataSourceRequest || this.compDTO.dataSourceRequest.length == 0) {
  344 + return false;
  345 + }
  346 + return true;
  347 + }
  348 +
  349 + // public getIsFeed(): boolean {
  350 + // return this.isFeed;
  351 + // }
  352 + //
  353 + // public setIsFeed(isFeed: boolean): void {
  354 + // this.isFeed = isFeed;
  355 + // }
  356 + //
  357 + // public getIsGrayMode(): boolean {
  358 + // return this.isGrayMode;
  359 + // }
  360 + //
  361 + // public setIsGrayMode(isGrayMode: boolean): void {
  362 + // this.isGrayMode = isGrayMode;
  363 + // }
  364 +
  365 + // public isLongFeed(): boolean {
  366 + // return this.compDTO.dataSource == "SHORT_WITH_LONG_FEED" || this.compDTO.dataSource == "FOCUS_FEED";
  367 + // }
  368 +
  369 + /**
  370 + * 获取所有的数据项
  371 + */
  372 + public getItems(): List<VO> {
  373 + return this.items;
  374 + }
  375 +
  376 + /**
  377 + * 向Comp中添加一个数据源/
  378 + * 向Comp中指定位置{@code index}位置添加一个数据源
  379 + */
  380 + public addItem(item: VO, index?: number): void {
  381 + if (item == null) {
  382 + return;
  383 + }
  384 +
  385 + if (this.items == null) {
  386 + this.items = new List<VO>();
  387 + }
  388 +
  389 + if (index == undefined) {
  390 + this.items.add(item);
  391 + } else {
  392 + if (index >= this.items.length) {
  393 + this.items.add(item);
  394 + } else if (index < 0) {
  395 + this.items.insert(item, 0);
  396 + } else {
  397 + this.items.insert(item, index);
  398 + }
  399 + }
  400 + }
  401 +
  402 + // public getPath():string {return ''}
  403 +
  404 + /**
  405 + * 获取初始化参数
  406 + */
  407 + // public getInitParams(): Map<String, Object> {
  408 + // return this.initParams;
  409 + // }
  410 +
  411 + /**
  412 + * 获取在index位置的数据项
  413 + */
  414 + public getItem(index: number): VO | null {
  415 + if (this.items == null || index >= this.items.length || index < 0) {
  416 + return null;
  417 + }
  418 +
  419 + return this.items.get(index);
  420 + }
  421 +
  422 + /**
  423 + * 获取Comp item 数量
  424 + */
  425 + public getItemCount(): number {
  426 + return this.items == null ? 0 : this.items.length;
  427 + }
  428 +
  429 + public getAllItemCount(): number {
  430 + return this.getItemCount();
  431 + }
  432 +
  433 + /**
  434 + * 判断数据是否完整,当{@link #needCheckIntegrity()} 返回true时
  435 + * @returns 如果数据完整的返回true, 否则返回false.
  436 + */
  437 + // public isDataIntegrity(): boolean {
  438 + // return this.items != null && this.items.length > 0;
  439 + // }
  440 +
  441 + /**
  442 + * 判断是否需要检查数据完整性
  443 + */
  444 + // public needCheckIntegrity(): boolean {
  445 + // return false;
  446 + // }
  447 +
  448 + // public changeProgramme( programmeBean:ProgrammeBean) :void{
  449 + // }
  450 +
  451 + /**
  452 + * 用于在合并请求的场景下请求备用数据源
  453 + */
  454 + // public loadBackupDataSource(isRefresh: boolean): void {
  455 + // if (this.getIsLoading()) {
  456 + // return;
  457 + // }
  458 + //
  459 + // this.isRefresh = isRefresh;
  460 + // this.onLoadBackupData();
  461 + // }
  462 + //
  463 + // protected onLoadBackupData(): void {
  464 + // }
  465 +
  466 + // public onDynamicDataCallback(isReplaceStaticData: boolean): void {
  467 + // }
  468 +
  469 + /**
  470 + * 是否清理group数据,默认清除
  471 + */
  472 + // public isClearItemsData(): boolean {
  473 + // return true;
  474 + // }
  475 +
  476 + // protected onDataRequestSuccess(poolId: string, items: List<VO>): void {
  477 + // }
  478 +
  479 + // public onDataLoaded(poolId: string): void {
  480 + // if (this.items.length != 0) {
  481 + // for (let index = 0; index < this.items.length; index++) {
  482 + // let item: VO = this.items[index]
  483 + // if (StringUtils.isNotEmpty(item.position)) {
  484 + // this.dynamicData.set(item.position, item);
  485 + // }
  486 + // }
  487 + // }
  488 + // if (poolId != null) {
  489 + // this.data.set(poolId, this.items);
  490 + // this.onDataRequestSuccess(poolId, this.items);
  491 + // let defaultId: string | null = this.getFirstPoolId();
  492 + // if (defaultId != null) {
  493 + // this.items = this.data.get(defaultId);
  494 + // if (defaultId == poolId) {
  495 + // this.onLoadDataFinished();
  496 + // }
  497 + // }
  498 + // } else {
  499 + // this.data.set("DEFAULT", this.items);
  500 + // this.onLoadDataFinished();
  501 + // }
  502 + // }
  503 +
  504 + // private getFirstPoolId(): string | null {
  505 + // if (!this.compDTO || this.compDTO.dataSourceRequest == null || this.compDTO.dataSourceRequest.length == 0) {
  506 + // return null;
  507 + // } else {
  508 + // return this.compDTO.dataSourceRequest[0].poolId ?? null;
  509 + // }
  510 + // }
  511 +
  512 + // protected Class getDtoCls(): {
  513 + // return null;
  514 + // }
  515 +
  516 + protected doCompDataFilter(data: DTO): DTO {
  517 + return data;
  518 + }
  519 +
  520 + public getStatus(): number {
  521 + return this.status;
  522 + }
  523 +
  524 + /**
  525 + * 获取页面位置
  526 + */
  527 + // public getLocation(): string {
  528 + // if (this.compDTO == null) {
  529 + // return "";
  530 + // }
  531 + // return this.compDTO.location;
  532 + // }
  533 +
  534 + /**
  535 + * 获取location stamp
  536 + *
  537 + * @return
  538 + */
  539 + // public getLocationStamp(): string {
  540 + // let group: WDGroup = this.getParent();
  541 + // if (group == null) {
  542 + // return "000000";
  543 + // }
  544 + // let page: MGPage = group.getParent();
  545 + //
  546 + // if (page == null) {
  547 + // return "000000";
  548 + // }
  549 + //
  550 + // let compIndex: number = group.indexOfMGComp(this) + 1;
  551 + // let groupIndex: number = page.indexOfGroup(group) + 1;
  552 + // return String.format("%03d%03d", groupIndex, compIndex);
  553 + // }
  554 +
  555 + /**
  556 + * 判断是否是瀑布流
  557 + */
  558 + // public isWaterfallFlow(): boolean {
  559 + // if (this.compDTO == null) {
  560 + // return false;
  561 + // }
  562 + //
  563 + // return "1" == this.compDTO.isWaterfallFlow;
  564 + // }
  565 +
  566 + /**
  567 + * 获取Comp所在页面的page id
  568 + */
  569 + public getPageId(): string {
  570 + if (!this.getParent() || !this.getParent().getParent()) {
  571 + return "";
  572 + }
  573 + return this.getParent().getParent().getId();
  574 + }
  575 +
  576 + // public getSessionId(): string {
  577 + // if (this.getParent() == null || this.getParent().getParent() == null) {
  578 + // return "";
  579 + // }
  580 + // return this.getParent().getParent().getSessionId();
  581 + // }
  582 +
  583 + /**
  584 + * 获取Group Id
  585 + */
  586 + public getGroupId(): string {
  587 + if (!this.getParent()) {
  588 + return "";
  589 + }
  590 + return this.getParent().getId();
  591 + }
  592 +
  593 + /**
  594 + * 判断是否包含广告
  595 + */
  596 + // public containsAd(): boolean {
  597 + // return this.compDTO != null && this.compDTO.isContainAD == 1;
  598 + // }
  599 +
  600 + // public setCompDTO(compDTO: CompDTO): void {
  601 + // this.compDTO = compDTO;
  602 + // }
  603 +
  604 + // private setLocation(dto:DTO):void { }
  605 +
  606 + // private appendLocation(url:string, location:string):string {}
  607 +
  608 + /**
  609 + * 判断comp中是否有extra data
  610 + */
  611 + // public hasExtraData(): boolean {
  612 + // if (this.compDTO == null) {
  613 + // return false;
  614 + // }
  615 + //
  616 + // return this.compDTO.extraData != null;
  617 + // }
  618 +
  619 + /**
  620 + * 获取comp的extra data
  621 + */
  622 + // public getExtraData(): ExtraData | undefined {
  623 + // if (this.compDTO == null) {
  624 + // return undefined;
  625 + // }
  626 + // return this.compDTO.extraData;
  627 + // }
  628 +
  629 + /**
  630 + * 判断是否有分割线
  631 + */
  632 + // public hasSeparator(): boolean {
  633 + // // if (this.compDTO == null) {
  634 + // return false;
  635 + // // }
  636 + // // return this.compDTO.isSegmentLine == 1;
  637 + // }
  638 +
  639 + /**
  640 + * 请求结束后通知刷新界面
  641 + */
  642 + protected onLoadDataFinished(): void {
  643 + if (!this.getParent() || !this.getParent().getParent()) {
  644 + return;
  645 + }
  646 + this.status = NetDataStatusType.LOADED;
  647 + this.getParent().getParent().notifyCompDataLoaded(this);
  648 + }
  649 +
  650 + /**
  651 + * 请求失败后通知界面
  652 + */
  653 + protected onLoadDataFailed(): void {
  654 + if (!this.getParent() || !this.getParent().getParent()) {
  655 + return;
  656 + }
  657 + this.status = NetDataStatusType.FAILED;
  658 + this.getParent().getParent().notifyCompDataFailed(this);
  659 + }
  660 +
  661 + /**
  662 + * 请求结束后异步通知刷新界面
  663 + */
  664 + // protected notifyLoadDataFinished(): void {
  665 + // this.onLoadDataFinished();
  666 + // }
  667 +
  668 +}
  1 +import { GroupDTO } from '../bean/GroupDTO';
  2 +import { LayoutService } from '../service/LayoutService';
  3 +import List from '@ohos.util.List';
  4 +import { ItemBean } from '../bean/ItemBean';
  5 +import { ItemDTO } from '../bean/ItemDTO';
  6 +import { WDComp } from './WDComp';
  7 +import { WDPage } from './WDPage';
  8 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  9 +import { LayoutCallback } from '../service/LayoutCallback';
  10 +import { GroupDataDTO } from '../bean/GroupDataDTO';
  11 +import { CompDataDTO } from '../bean/CompDataDTO';
  12 +import { CompDTO } from '../bean/CompDTO';
  13 +import { LabelComp } from './LabelComp';
  14 +import { CompType } from '../enum/CompType';
  15 +import { CompFilterUtil } from '../utils/CompFilterUtil';
  16 +import { ButtonComp } from './ButtonComp';
  17 +import { CompStyle } from '../enum/CompStyle';
  18 +import { TabBar01Comp } from './TabBar01Comp';
  19 +import { TabBar22Comp } from './TabBar22Comp';
  20 +import { ProgrammeComp } from './ProgrammeComp';
  21 +import { FlowComp } from './FlowComp';
  22 +
  23 +const TAG = 'WDGroup';
  24 +
  25 +/**
  26 + * Group数据获取管理及相关业务逻辑处理
  27 + */
  28 +export class WDGroup {
  29 + private layoutService: LayoutService;
  30 + /**
  31 + * group配置定义实体
  32 + */
  33 + private groupDTO: GroupDTO;
  34 + protected parent: WDPage;
  35 + private initParams: Map<string, Object> = new Map<string, Object>();
  36 + /**
  37 + * 所有的comp列表
  38 + */
  39 + private comps: List<WDComp<ItemBean, ItemDTO>> = new List();
  40 + /**
  41 + * 需要合并请求的comp列表
  42 + */
  43 + private teamworkCompList: List<WDComp<ItemBean, ItemDTO>>;
  44 + /**
  45 + * 标记是否包含需要合并请求Comp的Group
  46 + */
  47 + private isTeamwork: boolean = false;
  48 + /**
  49 + * 标记是否需要加载数据,当所有comp都是独立加载数据则group无需再加载数据
  50 + */
  51 + private needLoadData: boolean = false;
  52 + // /**
  53 + // * 标记是否已加载数据
  54 + // */
  55 + // private isLoaded: boolean = false;
  56 + // /**
  57 + // * 标记是否在加载数据
  58 + // */
  59 + // private isLoading: boolean = false;
  60 + // 当前group数据加载状态
  61 + protected status: number = NetDataStatusType.INITIAL;
  62 + // private IWDCompParser parser;
  63 + // private isLongFeed: boolean = false;
  64 + // private WDComp feedWDComp;
  65 + // private WDComp longWDComp;
  66 + private displayCount: number = 0;
  67 + private hasMoreGroupData: boolean = false;
  68 + // private isLongFeedLoaded: boolean = false;
  69 + // private isLongFeedLoading: boolean = false;
  70 + /**
  71 + * 标记是否为黑白化
  72 + */
  73 + private isGrayMode: boolean = false;
  74 +
  75 + /**
  76 + * 构造函数
  77 + *
  78 + * @param group 发出请求的WDGroup实例
  79 + */
  80 + constructor(page: WDPage, groupDTO: GroupDTO, initParams: Map<string, Object>) {
  81 + this.parent = page;
  82 + this.groupDTO = groupDTO;
  83 + this.initParams = initParams;
  84 + this.layoutService = new LayoutService();
  85 + this.comps = new List();
  86 + this.teamworkCompList = new List();
  87 +
  88 + if (groupDTO) {
  89 + // if (page != null && page.getTeamworkGroupIds() != null) {
  90 + // isTeamwork = page.getTeamworkGroupIds().contains(group.id);
  91 + // }
  92 + // setId(group.id);
  93 + this.initComp(groupDTO.components, initParams);
  94 + }
  95 + }
  96 +
  97 + public getParent(): WDPage {
  98 + return this.parent;
  99 + }
  100 +
  101 + public getGroupDTO(): GroupDTO {
  102 + return this.groupDTO;
  103 + }
  104 +
  105 + /**
  106 + * 获取group中的所有Comp
  107 + */
  108 + public getCompList(): List<WDComp<ItemBean, ItemDTO>> {
  109 + return this.comps;
  110 + }
  111 +
  112 + /**
  113 + * 请求Group数据
  114 + * @param isRefresh 是否为刷新
  115 + */
  116 + public sendRequest(isRefresh: boolean) {
  117 + // TODO: 通过LayoutService获取Group数据
  118 + if (this.status == NetDataStatusType.LOADING) {
  119 + return;
  120 + }
  121 +
  122 + // 当group需要请求网络加载数据时
  123 + if (this.needLoadData) {
  124 + if (this.layoutService) {
  125 + let callback: LayoutCallback<GroupDataDTO> = {
  126 + onSuccess: (groupDataDTO: GroupDataDTO): void => {
  127 + // 包含分众数据,请求分众页面
  128 + if (groupDataDTO.branchMark) {
  129 + // this.loadDynamicGroup(pageId, bean, isRefresh, layoutCallback);
  130 + } else {
  131 + this.status = NetDataStatusType.LOADED
  132 + this.parseGroup(groupDataDTO)
  133 + this.parent.notifyGroupDataLoaded(this)
  134 + }
  135 + return
  136 + },
  137 + onFailed: (code: number, message: string): void => {
  138 + // todo:
  139 + this.status = NetDataStatusType.FAILED
  140 + this.parent.notifyGroupDataFailed(this)
  141 + return
  142 + }
  143 + };
  144 + this.status = NetDataStatusType.LOADING;
  145 + this.layoutService.getGroup(this.getPageId(), this.getId(), isRefresh, callback);
  146 + } else {
  147 + // "Layout service not initialed
  148 + this.status = NetDataStatusType.FAILED;
  149 + this.parent.notifyGroupDataFailed(this)
  150 + }
  151 + //return;
  152 + }
  153 + this.loadCompData();
  154 +
  155 + this.loadDynamicData();
  156 + }
  157 +
  158 + public getPageId(): string {
  159 + if (this.getParent() == null) {
  160 + return "";
  161 + }
  162 + return this.getParent().getId();
  163 + }
  164 +
  165 + /**
  166 + * 解析Group数据
  167 + * @param groupBean Group数据对象
  168 + */
  169 + private parseGroup(groupDataDTO: GroupDataDTO) {
  170 + // TODO: 调用initGroup初始化Group对象
  171 + if (groupDataDTO.components) {
  172 + groupDataDTO.components.forEach((compDataDTO: CompDataDTO) => {
  173 + let wdComp: WDComp<ItemBean, ItemDTO> | null = this.getCompById(compDataDTO.id);
  174 + if (wdComp && !wdComp.separateLoad()) {
  175 + wdComp.setData(compDataDTO);
  176 + }
  177 + })
  178 + }
  179 + }
  180 +
  181 + /**
  182 + * 初始化WDComp对象
  183 + * @param compList Comp数据对象列表
  184 + */
  185 + private initComp(compList: CompDTO[], initParams: Map<string, Object>) {
  186 + // TODO:遍历初始化Comp
  187 + if (compList == null || compList.length == 0) {
  188 + return;
  189 + }
  190 + this.needLoadData = false;
  191 + for (let num = 0; num < compList.length; num++) {
  192 + let compDTO: CompDTO = compList[num];
  193 + let wdComp: WDComp<ItemBean, ItemDTO>;
  194 + if (!CompFilterUtil.filter(compDTO)) {
  195 + continue
  196 + }
  197 +
  198 + if (compDTO.compType == CompType.LABEL) {
  199 + wdComp = new LabelComp(this, compDTO, initParams);
  200 + } else if (compDTO.compType == CompType.BUTTON) {
  201 + wdComp = new ButtonComp(this, compDTO, initParams);
  202 + } else if (compDTO.compType == CompType.NAV_BAR) {
  203 + if (compDTO.compStyle == CompStyle.NAV_BAR_01) {
  204 + wdComp = new TabBar01Comp(this, compDTO, initParams);
  205 + } else if (compDTO.compStyle == CompStyle.NAV_BAR_22) {
  206 + wdComp = new TabBar22Comp(this, compDTO, initParams);
  207 + } else if (compDTO.compStyle == CompStyle.NAV_BAR_03) {
  208 + wdComp = new ProgrammeComp(this, compDTO, initParams);
  209 + } else {
  210 + // todo:不同的comp,临时用FlowComp
  211 + wdComp = new FlowComp(this, compDTO, initParams);
  212 + }
  213 + } else if (compDTO.compType == CompType.BIG_STATIC_IMG
  214 + || compDTO.compType == CompType.BIG_CAROUSEL_IMG
  215 + || compDTO.compType == CompType.BIG_PLAY_IMG
  216 + || compDTO.compType == CompType.TOP_IMG_BOTTOM_TXT
  217 + || compDTO.compType == CompType.BINGE_WATCHING
  218 + || compDTO.compType == CompType.SLIDER_IMG) {
  219 + wdComp = new ProgrammeComp(this, compDTO, initParams);
  220 + }else {
  221 + // todo:不同的comp,临时用FlowComp
  222 + wdComp = new FlowComp(this, compDTO, initParams);
  223 + }
  224 + if (!wdComp.separateLoad() && wdComp.loadWithGroupData()) {
  225 + // todo:临时把走获取group本身数据的逻辑屏蔽,否则逐层获取gourp数据流程会中断。
  226 + // this.needLoadData = true;
  227 + }
  228 + this.comps.add(wdComp);
  229 + if (wdComp.isTeamWork()) {
  230 + this.teamworkCompList.add(wdComp);
  231 + }
  232 + }
  233 + }
  234 +
  235 + /**
  236 + * Group是否需要加载数据
  237 + * @returns
  238 + */
  239 + public shouldLoadData(): boolean {
  240 + // TODO: 当所有comp都是独立加载数据则group无需再加载数据
  241 + if (this.needLoadData) {
  242 + return this.hasMoreData() || this.status == NetDataStatusType.INITIAL;
  243 + }
  244 +
  245 + let loaded = true;
  246 + // 若group无需请求网络加载数据时,则判断所有独立加载数据的comp是否都以完成加载
  247 + for (let num = 0; num < this.comps.length; num++) {
  248 + let wdComp: WDComp<ItemBean, ItemDTO> = this.comps[num];
  249 + if (wdComp.separateLoad() && (!wdComp.isLoaded() || wdComp.hasMoreData())) {
  250 + loaded = false;
  251 + break;
  252 + }
  253 + }
  254 + return !loaded;
  255 + }
  256 +
  257 + /**
  258 + * 是否正在加载中
  259 + * @returns
  260 + */
  261 + public isGroupLoading(): boolean {
  262 + // TODO: 遍历所有Comp是否正在加载中
  263 + if (this.status == NetDataStatusType.LOADING) {
  264 + return true;
  265 + }
  266 + for (let index = 0; index < this.comps.length; index = index + 1) {
  267 + let comp = this.comps.get(index);
  268 + if (!comp.separateLoad()) {
  269 + continue;
  270 + }
  271 +
  272 + if (comp.getIsLoading()) {
  273 + return true;
  274 + }
  275 + }
  276 +
  277 + return false;
  278 + }
  279 +
  280 + private loadCompData(): void {
  281 + for (let index = 0; index < this.comps.length; index++) {
  282 + let wdComp: WDComp<ItemBean, ItemDTO> = this.comps[index];
  283 + if (!wdComp.separateLoad()) {
  284 + continue;
  285 + }
  286 + if (!wdComp.isLoaded() || wdComp.hasMoreData()) {
  287 + wdComp.loadMore();
  288 + }
  289 + }
  290 + }
  291 +
  292 + /**
  293 + * Group中所有的Comp是否都已加载完毕
  294 + * @returns
  295 + */
  296 + public hasDataLoaded(): boolean {
  297 + // TODO: 所有Comp是否都已经加载完数据
  298 + if (this.needLoadData) {
  299 + return this.status == NetDataStatusType.LOADED || this.status == NetDataStatusType.FAILED;
  300 + } else {
  301 + // 若group无需请求网络加载数据时,则判断所有独立加载数据的Comp是否都以完成加载
  302 + for (let index = 0; index < this.comps.length; index = index + 1) {
  303 + let comp = this.comps.get(index);
  304 + if (comp.separateLoad() && !comp.isLoaded()) {
  305 + return false;
  306 + }
  307 + }
  308 + return true;
  309 + }
  310 + }
  311 +
  312 + /**
  313 + * Group中所有的Comp是否都已(成功)加载完毕
  314 + * @returns
  315 + */
  316 + public hasAllCompLoadedSuccess(): boolean {
  317 + if (this.needLoadData) {
  318 + return this.status == NetDataStatusType.LOADED;
  319 + } else {
  320 + // 若group无需请求网络加载数据时,则判断所有独立加载数据的Comp是否都以完成加载
  321 + for (let index = 0; index < this.comps.length; index = index + 1) {
  322 + let comp = this.comps.get(index);
  323 + if (comp.separateLoad() && !comp.isLoadedSuccess()) {
  324 + return false;
  325 + }
  326 + }
  327 + return true;
  328 + }
  329 + }
  330 + /**
  331 + * 是否还有更多数据待加载
  332 + */
  333 + public hasMoreData(): boolean {
  334 + // TODO: 判断是否有加载更多数据的Comp并且存在更多数据
  335 + if (this.comps == null) {
  336 + return false;
  337 + }
  338 +
  339 + for (let index = 0; index < this.comps.length; index = index + 1) {
  340 + let comp = this.comps.get(index);
  341 + if (comp.hasMoreData()) {
  342 + return true;
  343 + }
  344 + }
  345 +
  346 + return false;
  347 + }
  348 +
  349 + public loadMore(): void {
  350 + let hasMoreCompData: boolean = false;
  351 + if (this.comps && !this.comps.isEmpty()) {
  352 + for (let index = this.comps.length - 1; index >= 0; index = index - 1) {
  353 + let comp = this.comps.get(index);
  354 + if (comp) {
  355 + hasMoreCompData = comp.hasMoreData();
  356 + if (hasMoreCompData) {
  357 + break;
  358 + }
  359 + }
  360 + }
  361 + }
  362 +
  363 + if (!hasMoreCompData && this.hasMoreGroupData) {
  364 + // LogUtil.d("WDGroup[" + this.toString() + "]: loadMore");
  365 +
  366 + // requestLongFeed(false);
  367 + }
  368 + }
  369 +
  370 + /**
  371 + * 是否需要加载动态数据
  372 + * @returns
  373 + */
  374 + public needLoadDynamicData(): boolean {
  375 + // TODO: 遍历所有Comp,判断数据源的dataSourceType是否为“POMS_NODE”,是则需要加载动态数据。
  376 + return false;
  377 + }
  378 +
  379 + /**
  380 + * 加载动态数据
  381 + */
  382 + public loadDynamicData() {
  383 + // TODO: 通过LayoutService加载动态数据,通过WDComp#replaceStaticData替换静态数据。
  384 + }
  385 +
  386 + public getId(): string {
  387 + return this.groupDTO?.id ?? "";
  388 + }
  389 +
  390 + /**
  391 + * 通过Comp id查找相应的comp实例
  392 + *
  393 + * @param id comp id
  394 + */
  395 + public getCompById(id: string): WDComp<ItemBean, ItemDTO> | null {
  396 + for (let index = 0; index < this.comps.length; index++) {
  397 + let wdComp: WDComp<ItemBean, ItemDTO> = this.comps[index];
  398 + if (wdComp.getId() == id) {
  399 + return wdComp;
  400 + }
  401 + }
  402 + return null;
  403 + }
  404 +
  405 + public getIsTeamWork(): boolean {
  406 + return this.isTeamwork;
  407 + }
  408 +
  409 + public getIsGrayMode(): boolean {
  410 + return this.isGrayMode;
  411 + }
  412 +
  413 + /**
  414 + * 获取comp在Group中的位置
  415 + *
  416 + * @param comp WDComp实例
  417 + */
  418 + public indexOfComp(comp: WDComp<ItemBean, ItemDTO>): number {
  419 + if (comp == null || this.comps == null) {
  420 + return -1;
  421 + }
  422 +
  423 + return this.comps.getIndexOf(comp);
  424 + }
  425 +}
  1 +/**
  2 + * Page数据获取管理及相关业务逻辑处理
  3 + */
  4 +import { PageDTO } from '../bean/PageDTO';
  5 +import { LayoutService } from '../service/LayoutService';
  6 +import { PageListener } from './PageListener';
  7 +import { WDGroup } from './WDGroup';
  8 +import List from '@ohos.util.List';
  9 +import { LayoutCallback } from '../service/LayoutCallback';
  10 +import { GroupDTO } from '../bean/GroupDTO';
  11 +import { ItemBean } from '../bean/ItemBean';
  12 +import { ItemDTO } from '../bean/ItemDTO';
  13 +import { CompStyle } from '../enum/CompStyle';
  14 +import { WDComp } from './WDComp';
  15 +import { IGroupFilter } from './filter/IGroupFilter';
  16 +
  17 +export class WDPage {
  18 + private layoutService: LayoutService;
  19 + private listener?: PageListener;
  20 + private pageId: string;
  21 + private pageDTO?: PageDTO;
  22 + private groups: List<WDGroup> = new List();
  23 + private initParams: Map<string, Object> = new Map<string, Object>();
  24 + private groupFilters: IGroupFilter[] = [];
  25 + /**
  26 + * 标记是否在加载数据
  27 + */
  28 + private isLoading: boolean = false;
  29 + /**
  30 + * 页面顶部搜索提示文本
  31 + */
  32 + private searchText?: string;
  33 +
  34 + constructor(pageId: string, initParams: Map<string, Object>, groupFilters: IGroupFilter[]) {
  35 + this.pageId = pageId;
  36 + this.initParams = initParams;
  37 + this.groupFilters = groupFilters;
  38 + this.layoutService = new LayoutService();
  39 + }
  40 +
  41 + public setListener(listener: PageListener): void {
  42 + this.listener = listener;
  43 + }
  44 +
  45 + /**
  46 + * 请求Page数据
  47 + * @param isRefresh 是否为刷新
  48 + */
  49 + public sendRequest(isRefresh: boolean) {
  50 + // TODO: 由于PageID在构造函数中传入,所以这里的参数不需要PageID。
  51 + // TODO: 通过LayoutService获取Page数据
  52 + if (this.isLoading) {
  53 + return;
  54 + }
  55 + this.isLoading = true;
  56 + if (this.layoutService) {
  57 + let callback: LayoutCallback<PageDTO> = {
  58 + onSuccess: (pageDTO: PageDTO): void => {
  59 + this.isLoading = false;
  60 + this.parsePage(pageDTO);
  61 + if (this.listener) {
  62 + this.listener.onPageLoaded(this);
  63 + }
  64 + return
  65 + },
  66 + onFailed: (code: number, message: string): void => {
  67 + // todo:
  68 + this.isLoading = false;
  69 + if (this.listener) {
  70 + this.listener.onPageFailed(this)
  71 + }
  72 + return
  73 + }
  74 + };
  75 + this.layoutService.getPage(this.pageId, isRefresh, callback);
  76 + }
  77 + }
  78 +
  79 + /**
  80 + * 解析Page数据
  81 + * @param pageDTO Page数据对象
  82 + */
  83 + private parsePage(pageDTO: PageDTO) {
  84 + // TODO: 调用initGroup初始化Group对象
  85 + this.pageDTO = pageDTO;
  86 + if (pageDTO.groups) {
  87 + this.initGroup(pageDTO.groups, this.initParams);
  88 + }
  89 +
  90 + if (pageDTO.pageSearchText && pageDTO.pageSearchText.length > 0) {
  91 + this.searchText = pageDTO.pageSearchText[0];
  92 + } else {
  93 + // 设置searchText为空字符串表示page接口已经返回
  94 + this.searchText = "";
  95 + }
  96 + }
  97 +
  98 + public getPageDTO(): PageDTO {
  99 + return this.pageDTO ?? {} as PageDTO;
  100 + }
  101 +
  102 + public getSearchText(): string | undefined {
  103 + return this.searchText;
  104 + }
  105 +
  106 + /**
  107 + * 初始化WDGroup对象
  108 + * @param groupList Group数据对象列表
  109 + */
  110 + private initGroup(groupList: GroupDTO[], initParams: Map<string, Object>) {
  111 + if (groupList == null || groupList.length == 0) {
  112 + return;
  113 + }
  114 + // TODO:遍历初始化Group
  115 + for (let num = 0; num < groupList.length; num++) {
  116 + let groupBean: GroupDTO = groupList[num];
  117 + if (!this.filterGroup(groupBean)) {
  118 + continue;
  119 + }
  120 + let wdGroup: WDGroup = new WDGroup(this, groupBean, initParams);
  121 + if (!this.filterGroupAfterFilterComp(wdGroup)) {
  122 + continue;
  123 + }
  124 + this.groups.add(wdGroup);
  125 + }
  126 + }
  127 +
  128 + /**
  129 + * 本楼层是否被过滤掉
  130 + * @param groupBean 待过滤的GroupBean数据
  131 + * @returns 保留此项数据:返回true;否则(舍弃此项数据),返回false;
  132 + */
  133 + private filterGroup(groupBean: GroupDTO): boolean {
  134 + if (this.groupFilters == null || this.groupFilters.length <= 0) {
  135 + return true;
  136 + }
  137 +
  138 + for (let index = 0; index < this.groupFilters.length; index++) {
  139 + let filter = this.groupFilters[index];
  140 + if (!filter.filter(groupBean)) {
  141 + return false;
  142 + }
  143 + }
  144 + return true;
  145 + }
  146 +
  147 + /**
  148 + * 第二次过滤group/业务逻辑过滤/不合理过滤/本楼层是否被过滤掉
  149 + * @param WDGroup 待过滤的WDGroup数据
  150 + * @returns 保留此项数据:返回true;否则(舍弃此项数据),返回false;
  151 + */
  152 + private filterGroupAfterFilterComp(wdGroup: WDGroup): boolean {
  153 + if (!wdGroup || wdGroup.getCompList().length == 0) {
  154 + // 本楼层所有组件已被过滤掉
  155 + return false
  156 + }
  157 +
  158 + let wdComp: WDComp<ItemBean, ItemDTO> = wdGroup.getCompList().get(0)
  159 + let compStyle: string = wdComp.getCompStyle()
  160 + if (wdGroup.getCompList().length == 1) { // 楼层仅包含一个组件数据
  161 + if (compStyle === CompStyle.LABEL_01) { // 即一个楼层仅包含LABEL_01,其他的都被过滤掉时,则这个LABEL_01也要过滤掉
  162 + return false
  163 + }
  164 + if (compStyle === CompStyle.NAV_BAR_01) { //
  165 + // http://display-sc.miguvideo.com/display/v4/static/965823946cac4bf3b78c7b99b76b728b
  166 + // 目前会配置3个顶导楼层,取第2楼顶导
  167 + if (wdGroup.getParent().getGroups().length > 1) { // 若配置了多个group顶导:则过滤掉max不等于-1的group
  168 + if (wdGroup.getGroupDTO().androidVersion) {
  169 + if (wdGroup.getGroupDTO().androidVersion?.max != '-1') { // 把限制版本的顶导过滤掉 // todo:
  170 + // if (WDComp.getCompDTO()?.androidVersion?.max != '-1') { // 把限制版本的顶导过滤掉 // todo:
  171 + return false
  172 + }
  173 + }
  174 + }
  175 + }
  176 + } else { // 楼层包含多个组件数据
  177 + if (compStyle !== CompStyle.LABEL_01) {
  178 + // 但本楼层第一个组件不是label
  179 + // return false // 配置的可能是LABEL-04
  180 + }
  181 + }
  182 + return true;
  183 + }
  184 +
  185 + /**
  186 + * 获取page中所有的group
  187 + */
  188 + public getGroups(): List<WDGroup> {
  189 + return this.groups;
  190 + }
  191 +
  192 + public getId(): string {
  193 + return this.pageId ?? "";
  194 + }
  195 +
  196 + public notifyPageLayoutLoaded(): void {
  197 + if (this.listener) {
  198 + this.listener.onPageLoaded(this);
  199 +
  200 + }
  201 + }
  202 +
  203 + public notifyPageLayoutFailed(): void {
  204 + if (this.listener) {
  205 + this.listener.onPageFailed(this)
  206 + }
  207 + }
  208 +
  209 + public notifyGroupDataLoaded(group: WDGroup): void {
  210 + if (this.listener) {
  211 + this.listener.onGroupLoaded(this, group)
  212 + }
  213 + }
  214 +
  215 + public notifyGroupDataFailed(group: WDGroup): void {
  216 + if (this.listener) {
  217 + this.listener.onGroupFailed(this, group);
  218 + }
  219 + }
  220 +
  221 + public notifyCompDataLoaded(comp: WDComp<ItemBean, ItemDTO>): void {
  222 + if (this.listener) {
  223 + this.listener.onCompLoaded(this, comp.getParent(), comp)
  224 + }
  225 + }
  226 +
  227 + public notifyCompDataFailed(comp: WDComp<ItemBean, ItemDTO>): void {
  228 + if (this.listener) {
  229 + this.listener.onCompFailed(this, comp.getParent(), comp)
  230 + }
  231 + }
  232 +
  233 + /**
  234 + * Desc: 加载count个未加载的group
  235 + * @return 如果有加载未加载的group或者有正在加载数据的group则返回true,否则返回false
  236 + */
  237 + public loadNextGroups(count: number, isRefresh: boolean): boolean {
  238 + let cnt: number = count;
  239 + if (this.groups == null || this.groups.isEmpty()) {
  240 + return false;
  241 + }
  242 + let hasLoading: boolean = false;
  243 + let hasLongFeed: boolean = false;
  244 +
  245 + for (let index = 0; index < this.groups.length; index = index + 1) {
  246 + let group = this.groups.get(index);
  247 + if (count <= 0) {
  248 + return true;
  249 + }
  250 + if (group.shouldLoadData()) {
  251 + group.sendRequest(isRefresh);
  252 + --count;
  253 + } else if (!hasLoading && group.isGroupLoading()) {
  254 + hasLoading = true;
  255 + }
  256 +
  257 + group.loadMore();
  258 +
  259 + // hasLongFeed = group.getLongFeedComp() != null;
  260 + hasLongFeed = false
  261 + }
  262 + return hasLoading || cnt != count || hasLongFeed;
  263 + }
  264 +}
  1 +/**
  2 + * Comp过滤器,用于根据不同场景是否显示某个Comp,例如某些Comp只在指定的省份才显示。
  3 + */
  4 +import { CompDTO } from '../../bean/CompDTO';
  5 +
  6 +export interface ICompFilter {
  7 + /**
  8 + * 过滤逻辑的实现
  9 + * @param compDTO: 待过滤CompDTO数据
  10 + * @returns 保留此项数据:返回true;否则(舍弃此项数据),返回false;
  11 + */
  12 + filter(compDTO: CompDTO): boolean;
  13 +}
  1 +/**
  2 + * Group过滤器,用于根据不同场景是否显示某个Group,例如某些Group只在指定的省份才显示。
  3 + */
  4 +import { GroupDTO } from '../../bean/GroupDTO';
  5 +
  6 +export interface IGroupFilter {
  7 + /**
  8 + * 过滤逻辑的实现
  9 + * @param groupDTO: 待过滤GroupDTO数据
  10 + * @returns 保留此项数据:返回true;否则(舍弃此项数据),返回false;
  11 + */
  12 + filter(groupDTO: GroupDTO): boolean;
  13 +}
  1 +/**
  2 + * Group数据请求调度
  3 + * 处理MGGroup的数据请求,并同步所有包含的MGComp的请求结果并一同返回给调用者。
  4 + */
  5 +import { ItemBean } from '../bean/ItemBean';
  6 +import { ItemDTO } from '../bean/ItemDTO';
  7 +import { WDComp } from '../layout/WDComp';
  8 +import { WDGroup } from '../layout/WDGroup';
  9 +import List from '@ohos.util.List';
  10 +import { FlowComp } from '../layout/FlowComp';
  11 +
  12 +export class GroupRequest {
  13 + /**
  14 + * 发起Group数据请求
  15 + * @param isRefresh 是否为刷新
  16 + * @param group MGGroup对象
  17 + * @returns 是否发起了请求
  18 + */
  19 + public request(isRefresh: boolean, group: WDGroup): boolean {
  20 + // TODO: 通过MGGroup获取数据,或遍历所包含的MGComp获取数据。
  21 + if (group == null || group.getCompList() == null || group.getCompList().isEmpty()) {
  22 + return false;
  23 + }
  24 +
  25 + if (group.shouldLoadData()) {
  26 + group.sendRequest(isRefresh);
  27 + return true;
  28 + } else {
  29 + return false;
  30 + }
  31 + }
  32 +
  33 + /**
  34 + * 如果Group中的Comp可以加载更多数据,则加载更多数据。
  35 + * @param group MGGroup对象
  36 + * @returns 是否加载了更多数据
  37 + */
  38 + public loadMore(group: WDGroup | undefined): boolean {
  39 + // TODO: 如果Group中的Comp可以加载更多数据,通过MGComp#loadMore获取数据。
  40 + if (group != undefined) {
  41 + let compList:List<WDComp<ItemBean, ItemDTO>> = group?.getCompList();
  42 + if (compList) {
  43 + for (let i = 0; i < compList.length; i++) {
  44 + let mgComp = compList.get(i);
  45 + if (mgComp instanceof FlowComp && mgComp.hasMoreData()) {
  46 + if (!mgComp.getIsLoading()) {
  47 + mgComp.loadMore();
  48 + }
  49 + return true;
  50 + }
  51 + }
  52 +
  53 + // if (group.isHasMoreGroupData()) {
  54 + // group.requestLongFeed(false);
  55 + // return true;
  56 + // }
  57 + }
  58 + }
  59 + return false;
  60 + }
  61 +}
  1 +/**
  2 + * 乐高数据请求调度
  3 + */
  4 +import { NetDataStatusType } from '../enum/NetDataStatusType';
  5 +import { WDGroup } from '../layout/WDGroup';
  6 +import { WDPage } from '../layout/WDPage';
  7 +import { Synchronizer } from './Synchronizer';
  8 +import List from '@ohos.util.List';
  9 +import { WDComp } from '../layout/WDComp';
  10 +import { ItemBean } from '../bean/ItemBean';
  11 +import { ItemDTO } from '../bean/ItemDTO';
  12 +import { PageListener } from '../layout/PageListener';
  13 +import { LegoUtil } from '../utils/LegoUtil';
  14 +import { Logger } from 'wdKit';
  15 +import { Lego } from './LegoService';
  16 +import { GroupRequest } from './GroupRequest';
  17 +
  18 +const TAG = 'LegoRequest';
  19 +
  20 +export class LegoRequest {
  21 + /**
  22 + * 记录MGPage的数据请求状态
  23 + */
  24 + private pageStatus: number = NetDataStatusType.INITIAL;
  25 + /**
  26 + * MGPage对象,所有数据请求都是基于此对象进行。
  27 + */
  28 + private page: WDPage;
  29 + /**
  30 + * 最后一次请求的MGGroup对象
  31 + */
  32 + private lastGroup?: WDGroup;
  33 + /**
  34 + * 最后一次请求的MGGroup对象所对应的Index
  35 + */
  36 + private lastGroupIndex: number = -1;
  37 + /**
  38 + * 同步管理器
  39 + */
  40 + private synchronizer: Synchronizer;
  41 + /**
  42 + * 待处理的任务列表
  43 + */
  44 + private taskList: List<Lego.Callback> = new List();
  45 + /**
  46 + * 当前MGPage对象中所包含的所有MGGroup对象
  47 + */
  48 + private allGroupList: List<WDGroup> = new List();
  49 + /**
  50 + * 记录所有返回的MGGroup,用于判断是首次返回还是更新。
  51 + */
  52 + private callbackGroupList: List<WDGroup> = new List();
  53 + /**
  54 + * 记录所有返回的MGComp,用于判断是首次返回还是更新。
  55 + */
  56 + private callbackCompList: List<WDComp<ItemBean, ItemDTO>> = new List();
  57 +
  58 + /**
  59 + * 调试开关
  60 + */
  61 + // public static DEBUG: boolean = false;
  62 +
  63 + /**
  64 + * 构造函数:Lego数据请求统筹对象
  65 + * @param page 目标MGPage对象
  66 + */
  67 + constructor(page: WDPage) {
  68 + this.page = page;
  69 + this.synchronizer = new Synchronizer();
  70 + }
  71 +
  72 + /**
  73 + * 数据请求
  74 + * @param isRefresh 是否为刷新
  75 + * @param callback 回调
  76 + */
  77 + public request(isRefresh: boolean, legoCallback: Lego.Callback) {
  78 + // TODO: 通过MGPage#sendRequest获取Page数据,PageListener监听状态。
  79 + if (isRefresh) {
  80 + this.synchronizer = new Synchronizer();
  81 + this.lastGroup = undefined;
  82 + this.allGroupList.clear();
  83 + this.callbackGroupList.clear();
  84 + this.callbackCompList.clear();
  85 + this.pageStatus = NetDataStatusType.INITIAL;
  86 +
  87 + // 如果刷新任务过来,前面待处理的任务会被清空。
  88 + // 如果对业务产生不良影响,后续改进。
  89 + this.taskList.clear();
  90 + }
  91 + // 如果Page正在请求中,则需要等待请求结束。
  92 + if (this.pageStatus == NetDataStatusType.LOADING && !isRefresh) {
  93 + this.taskList.add(legoCallback);
  94 + }
  95 +
  96 + if (this.allGroupList.isEmpty() || isRefresh) {
  97 + let pageListener: PageListener = {
  98 + onPageLoaded: (page: WDPage): void => {
  99 + this.pageStatus = NetDataStatusType.LOADED;
  100 + // Page级别回调
  101 + legoCallback.onPageLoaded(page);
  102 +
  103 + this.allGroupList.clear();
  104 +
  105 + let groups: List<WDGroup> = this.page.getGroups();
  106 + if (groups) {
  107 + this.allGroupList = groups;
  108 + }
  109 +
  110 + if (this.allGroupList.isEmpty()) {
  111 + let msg: string = "onPageLayoutLoaded : allGroupList is empty --> PageID = " + LegoUtil.getPageId(page);
  112 + this.synchronizer.onError(page, msg, legoCallback);
  113 + } else {
  114 + this.doNext(isRefresh, legoCallback);
  115 + // 开始进行待处理的任务
  116 + if (!this.taskList.isEmpty()) {
  117 + for (let index = 0; index < this.taskList.length; index++) {
  118 + let legoCb: Lego.Callback = this.taskList[index]
  119 + this.doNext(false, legoCb);
  120 + }
  121 + }
  122 + this.taskList.clear();
  123 + }
  124 + return
  125 + },
  126 + onPageFailed: (page: WDPage): void => {
  127 + this.pageStatus = NetDataStatusType.FAILED;
  128 +
  129 + let msg: string = "onPageLayoutFailed --> PageID = " + LegoUtil.getPageId(page);
  130 + this.synchronizer.onError(page, msg, legoCallback);
  131 + return
  132 + },
  133 + onGroupLoaded: (page: WDPage, group: WDGroup): void => {
  134 + // todo:
  135 + // if (this.callbackGroupList.has(group)) {
  136 + // this.synchronizer.onGroupUpdate(group, legoCallback);
  137 + // } else {
  138 + // this.callbackGroupList.add(group);
  139 + // this.synchronizer.checkStatus("onGroupLoaded", group, legoCallback);
  140 + // }
  141 + legoCallback.onGroupUpdate(group);
  142 + return
  143 + },
  144 + onGroupFailed: (page: WDPage, group: WDGroup): void => {
  145 + if (!this.callbackGroupList.has(group)) {
  146 + this.callbackGroupList.add(group);
  147 + let msg: string = "onGroupFailed --> PageID = " + LegoUtil.getPageId(group.getParent()) + ", GroupID = " + LegoUtil.getGroupId(group);
  148 + this.synchronizer.onFailed(msg, group, legoCallback);
  149 + }
  150 + return
  151 + },
  152 + onCompLoaded: (page: WDPage, group: WDGroup, comp: WDComp<ItemBean, ItemDTO>): void => {
  153 + Logger.info(TAG, `onCompLoaded page.getId: ${page.getId()}, group.getId: ${group.getId()}, comp.getId: ${comp.getId()}`);
  154 + // if (this.callbackCompList.has(comp)) {
  155 + // this.synchronizer.onCompUpdate(comp, legoCallback);
  156 + // } else {
  157 + // this.callbackCompList.add(comp);
  158 + // this.synchronizer.checkStatus("onCompLoaded", comp.getParent(), legoCallback);
  159 + // }
  160 + if (group.hasDataLoaded()) {
  161 + if (group.hasAllCompLoadedSuccess()) {
  162 + // 回调到界面展示
  163 + legoCallback.onLoaded(group);
  164 + // legoCallback.onGroupUpdate(group);
  165 + }
  166 + // 同时请求下一个group
  167 + this.doNext(false, legoCallback)
  168 + }
  169 + return
  170 + },
  171 + onCompFailed: (page: WDPage, group: WDGroup, comp: WDComp<ItemBean, ItemDTO>): void => {
  172 + Logger.info(TAG, `onCompFailed page.getId: ${page.getId()}, group.getId: ${group.getId()}, comp.getId: ${comp.getId()}`);
  173 + // if (!this.callbackCompList.has(comp)) {
  174 + // this.callbackCompList.add(comp);
  175 + // this.synchronizer.checkStatus("onCompFailed", comp.getParent(), legoCallback);
  176 + // }
  177 + if (group.hasDataLoaded()) {
  178 + // 回调到界面展示
  179 + // legoCallback.onLoaded(group);
  180 + // legoCallback.onGroupUpdate(group);
  181 + // 同时请求下一个group
  182 + this.doNext(false, legoCallback)
  183 + }
  184 + return
  185 + }
  186 + };
  187 + this.page.setListener(pageListener);
  188 + this.pageStatus = NetDataStatusType.LOADING;
  189 + this.page.sendRequest(isRefresh);
  190 + } else {
  191 + this.doNext(false, legoCallback);
  192 + }
  193 + }
  194 +
  195 + /**
  196 + * 进行下一步处理流程
  197 + * 根据请求顺序获取待请求MGGroup,并将请求动作交给GroupRequest继续处理。
  198 + */
  199 + private doNext(isRefresh: boolean, legoCallback: Lego.Callback) {
  200 + // TODO: 通过GroupRequest获取Group数据
  201 + let groupRequest: GroupRequest = new GroupRequest();
  202 + // 加载更多
  203 + if (groupRequest.loadMore(this.lastGroup)) {
  204 + return;
  205 + }
  206 +
  207 + // 首次请求状态初始化
  208 + if (!this.lastGroup) {
  209 + this.lastGroupIndex = -1;
  210 + }
  211 + let groupIndex: number = this.lastGroupIndex + 1;
  212 + if (groupIndex < 0) {
  213 + groupIndex = 0;
  214 + }
  215 +
  216 + // 合法性校验
  217 + if (!this.checkIndex(groupIndex)) {
  218 + return;
  219 + }
  220 +
  221 + Logger.info(TAG, `doNext groupIndex: ${groupIndex}`);
  222 +
  223 + if (!this.allGroupList.isEmpty() && groupIndex < this.allGroupList.length) {
  224 + let tempGroup: WDGroup = this.allGroupList.get(groupIndex);
  225 +
  226 + // 状态记录
  227 + this.lastGroup = tempGroup;
  228 + this.lastGroupIndex = groupIndex;
  229 +
  230 + if (tempGroup) {
  231 + this.synchronizer.addGroup(tempGroup, legoCallback);
  232 +
  233 + let isRequest: boolean = groupRequest.request(isRefresh, tempGroup);
  234 +
  235 + // 如果当前Group没有可以请求的Comp则尝试下一个Group
  236 + if (!isRequest) {
  237 + // 无需请求直接返回回调
  238 + // this.synchronizer.checkStatus("groupLoaded", tempGroup, legoCallback);
  239 +
  240 + // 回调到界面展示
  241 + if (!tempGroup.getGroupDTO()?.branchMark) {
  242 + legoCallback.onLoaded(tempGroup);
  243 + }
  244 + // 同时请求下一个group
  245 + this.doNext(false, legoCallback)
  246 + }
  247 + }
  248 + } else {
  249 + // Page中所有Group已加载完毕
  250 + legoCallback.onCompleted(this.page);
  251 + }
  252 + }
  253 +
  254 + // todo
  255 + private checkIndex(groupIndex: number): boolean {
  256 + return true;
  257 + }
  258 +}
  1 +/**
  2 + * 数据模块队外接口服务
  3 + */
  4 +import { ItemBean } from '../bean/ItemBean';
  5 +import { ItemDTO } from '../bean/ItemDTO';
  6 +import { IGroupFilter } from '../layout/filter/IGroupFilter';
  7 +import { WDComp } from '../layout/WDComp';
  8 +import { WDGroup } from '../layout/WDGroup';
  9 +import { WDPage } from '../layout/WDPage';
  10 +import { LegoRequest } from './LegoRequest';
  11 +
  12 +export namespace Lego {
  13 + /**
  14 + * 乐高数据服务
  15 + */
  16 + export class LegoService {
  17 + pageId: string;
  18 + page: WDPage;
  19 + initParams: Map<string, Object> = new Map<string, Object>();
  20 + groupFilters: IGroupFilter[];
  21 + legoRequest: LegoRequest;
  22 +
  23 + constructor(builder: Builder) {
  24 + this.pageId = builder.pageId;
  25 + this.initParams = builder.initParams;
  26 + this.groupFilters = builder.groupFilters;
  27 +
  28 + // 创建MGPage对象
  29 + if (!builder.page) {
  30 + this.page = new WDPage(this.pageId, this.initParams, this.groupFilters);
  31 + } else {
  32 + this.page = builder.page;
  33 + }
  34 + this.legoRequest = new LegoRequest(this.page);
  35 + }
  36 +
  37 + /**
  38 + * 数据请求
  39 + * @param isRefresh 是否为刷新
  40 + * @param callback 回调
  41 + */
  42 + public request(isRefresh: boolean, callback: Lego.Callback) {
  43 + // TODO: 通过LegoRequest#request发出请求
  44 + this.legoRequest.request(isRefresh, callback);
  45 + }
  46 + }
  47 +
  48 + export class Builder {
  49 + pageId: string = '';
  50 + contentId: string = '';
  51 + page?: WDPage;
  52 + initParams: Map<string, Object> = new Map<string, Object>();
  53 + groupFilters: IGroupFilter[] = [];
  54 +
  55 + setPageId(pageId: string) {
  56 + this.pageId = pageId;
  57 + return this;
  58 + }
  59 +
  60 + setContentId(contentId: string) {
  61 + this.contentId = contentId;
  62 + return this;
  63 + }
  64 +
  65 + setPage(page: WDPage) {
  66 + this.page = page
  67 + return this;
  68 + }
  69 +
  70 + setParams(initParams: Map<string, Object>) {
  71 + this.initParams = initParams
  72 + return this;
  73 + }
  74 +
  75 + setGroupFilters(...groupFilters: IGroupFilter[]) {
  76 + this.groupFilters = groupFilters
  77 + return this;
  78 + }
  79 +
  80 + public build(): LegoService {
  81 + return new LegoService(this);
  82 + }
  83 + }
  84 +
  85 + /**
  86 + * 数据请求回调接口
  87 + */
  88 + export interface Callback {
  89 + /**
  90 + * 一次数据请求成功的回调
  91 + * @param group Group实例
  92 + */
  93 + onLoaded: (group: WDGroup) => void;
  94 +
  95 + /**
  96 + * 一次数据请求失败的回调
  97 + * @param group 本次请求的Group
  98 + * @param msg 失败描述
  99 + */
  100 + onFailed: (group: WDGroup, msg: String) => void;
  101 +
  102 + /**
  103 + * Page级错误回调,Page请求异常无法进行后续流程。
  104 + * @param page Page实例
  105 + * @param msg 错误描述
  106 + */
  107 + onError: (page: WDPage, msg: String) => void;
  108 +
  109 + /**
  110 + * 整个Page已全部请求完成的回调
  111 + * @param page Page实例
  112 + */
  113 + onCompleted: (page: WDPage) => void;
  114 +
  115 + /**
  116 + * Page接口请求成功的回调
  117 + * @param page Page实例
  118 + */
  119 + onPageLoaded: (page: WDPage) => void;
  120 +
  121 + /**
  122 + * Group数据更新的回调
  123 + * @param group Group实例
  124 + */
  125 + onGroupUpdate: (group: WDGroup) => void;
  126 +
  127 + /**
  128 + * Comp数据更新的回调
  129 + * @param comp Comp实例
  130 + */
  131 + onCompUpdate: (comp: WDComp<ItemBean, ItemDTO>) => void;
  132 + }
  133 +}
  1 +/**
  2 + * 同步管理器,用于同步一个MGGroup中所有MGComp的数据响应。
  3 + * 当全部MGComp数据都请求完毕后,一次性返回所有数据。
  4 + */
  5 +import { WDGroup } from '../layout/WDGroup';
  6 +import List from '@ohos.util.List';
  7 +import { Timeout } from './TimeoutManager';
  8 +import { WDPage } from '../layout/WDPage';
  9 +import { WDComp } from '../layout/WDComp';
  10 +import { ItemBean } from '../bean/ItemBean';
  11 +import { ItemDTO } from '../bean/ItemDTO';
  12 +import { LegoUtil } from '../utils/LegoUtil';
  13 +import { Lego } from './LegoService';
  14 +
  15 +export class Synchronizer {
  16 + /**
  17 + * 正在处理中的MGGroup列表,用于记录和按顺序回调给调用者。
  18 + */
  19 + private workingList: List<WDGroup> = new List();
  20 + /**
  21 + * 已经返回的MGGroup列表
  22 + */
  23 + private completedList: List<WDGroup> = new List();
  24 + private failedList: List<WDGroup> = new List();
  25 + /**
  26 + * 任务超时管理器
  27 + */
  28 + private timeoutManager: Timeout.TimeoutManager;
  29 +
  30 + /**
  31 + * 构造函数:Lego数据请求统筹对象
  32 + * @param page 目标MGPage对象
  33 + */
  34 + constructor() {
  35 + let callback: Timeout.Callback = {
  36 + onTimeout: (group: WDGroup, callback: Lego.Callback) => {
  37 + this.onTimeout(group, callback);
  38 + }
  39 + }
  40 + this.timeoutManager = new Timeout.TimeoutManager(callback)
  41 + }
  42 +
  43 + /**
  44 + * 记录正在进行中的任务
  45 + * @param group 正在进行数据请求的MGGroup对象
  46 + * @param callback 回调
  47 + */
  48 + public addGroup(group: WDGroup, legoCallback: Lego.Callback) {
  49 + // TODO: 记录Group
  50 + this.workingList.add(group);
  51 +
  52 + this.timeoutManager.addTask(group, legoCallback);
  53 + }
  54 +
  55 + /**
  56 + * 同步按顺序控制回调
  57 + * @param callback 回调
  58 + */
  59 + private syncCallback(callback: Lego.Callback) {
  60 + // TODO: 判断是否可以回调与遍历可回调Group
  61 + while (this.workingList.length > 0) {
  62 + // 严格按照任务顺序返回,若出现未完成任务,则等待下次处理。
  63 + let tempGroup: WDGroup = this.workingList.get(0)
  64 + if (this.completedList.has(tempGroup)) {
  65 + this.workingList.remove(tempGroup);
  66 + this.completedList.remove(tempGroup);
  67 + // todo
  68 + // callback.onLoaded(tempGroup);
  69 + } else if (this.failedList.has(tempGroup)) {
  70 + this.workingList.remove(tempGroup);
  71 + this.failedList.remove(tempGroup);
  72 + // todo
  73 + // callback.onFailed(tempGroup, "");
  74 + } else {
  75 + break;
  76 + }
  77 + }
  78 + }
  79 +
  80 + public onTimeout(group: WDGroup, callback: Lego.Callback): void {
  81 + // 目前简单的处理成超时则不显示该Group
  82 + this.onFailed("Timeout", group, callback);
  83 + }
  84 +
  85 + /**
  86 + * MGGroup数据加载完毕,按照顺序回调。
  87 + *
  88 + * @param group 数据请求完毕的MGGroup对象
  89 + * @param callback 回调对象
  90 + */
  91 + public onLoaded(group: WDGroup, callback: Lego.Callback): void {
  92 + this.timeoutManager.removeTask(group);
  93 + this.completedList.add(group);
  94 +
  95 + this.syncCallback(callback);
  96 + }
  97 +
  98 + /**
  99 + * MGGroup数据加载失败,按照顺序回调。
  100 + *
  101 + * @param msg 携带的描述信息,主要用于调试。
  102 + * @param group 数据请求完毕的MGGroup对象
  103 + * @param callback 回调对象
  104 + */
  105 + public onFailed(msg: string, group: WDGroup, callback: Lego.Callback): void {
  106 + this.timeoutManager.removeTask(group);
  107 + this.failedList.add(group);
  108 +
  109 + this.syncCallback(callback);
  110 + }
  111 +
  112 +
  113 + /**
  114 + * MGPage级别的错误,无法恢复。
  115 + *
  116 + * @param msg 携带的描述信息,主要用于调试。
  117 + * @param callback 回调对象
  118 + */
  119 + public onError(page: WDPage, msg: string, callback: Lego.Callback) {
  120 + callback.onError(page, msg);
  121 + }
  122 +
  123 +
  124 + /**
  125 + * MGGroup数据更新
  126 + *
  127 + * @param group 数据更新的MGGroup对象
  128 + * @param callback 回调对象
  129 + */
  130 + public onGroupUpdate(group: WDGroup, callback: Lego.Callback) {
  131 + if (!this.workingList.has(group)) {
  132 + callback.onGroupUpdate(group);
  133 + }
  134 + }
  135 +
  136 + /**
  137 + * MGComp数据更新
  138 + *
  139 + * @param comp 数据更新的MGComp对象
  140 + * @param callback 回调对象
  141 + */
  142 + public onCompUpdate(comp: WDComp<ItemBean, ItemDTO>, callback: Lego.Callback): void {
  143 + if (!this.workingList.has(comp.getParent())) {
  144 + callback.onCompUpdate(comp);
  145 + }
  146 + }
  147 +
  148 + /**
  149 + * 检查MGGroup中的所有MGComp的数据是否加载完毕
  150 + *
  151 + * @param group MGGroup实例
  152 + * @param callback 请求的回调对象
  153 + */
  154 + public checkStatus(msg: string, group: WDGroup, callback: Lego.Callback): void {
  155 + if (group) {
  156 + // 如果没有主动请求这个Group,而这个Group的comp数据返回,则不处理回调判断。
  157 + if (!this.workingList.has(group)) {
  158 + return;
  159 + }
  160 +
  161 + let compList: List<WDComp<ItemBean, ItemDTO>> = group.getCompList();
  162 + if (compList && !compList.isEmpty()) {
  163 + let isCompleted: boolean = true;
  164 + for (let i = 0; i < compList.length; i++) {
  165 + let comp: WDComp<ItemBean, ItemDTO> = compList.get(i);
  166 + // 检查是否有未加载完毕的Comp
  167 + // if (comp instanceof FlowComp) {
  168 + // let itemCount: number = comp.getItemCount()
  169 + // // let itemCount:number = ((FlowComp) comp).getItemCount();
  170 + // if (itemCount <= 0) {
  171 + // isCompleted = false;
  172 + // break;
  173 + // }
  174 + // } else
  175 + if (comp && comp.separateLoad() && !comp.isLoaded()) {
  176 + isCompleted = false;
  177 + break;
  178 + }
  179 + }
  180 + if (isCompleted) {
  181 + // this.onLoaded(group, callback);
  182 + callback.onLoaded(group)
  183 + }
  184 + } else {
  185 + msg = "checkStatus: comp list is empty -- > PageID = " + LegoUtil.getPageId(group.getParent()) + ", GroupID = " + LegoUtil.getGroupId(group);
  186 + // this.onFailed(msg, group, callback);
  187 + callback.onFailed(group, msg)
  188 + }
  189 + }
  190 + }
  191 +}
  1 +/**
  2 + * 超时控制与管理
  3 + *
  4 + * setTimeout和setInterval函数,都返回一个整数值,表示计数器编号。
  5 + *
  6 + * let timerId = setTimeout(func|code, delay);
  7 + * setTimeout函数接受两个参数,第一个参数func|code是将要推迟执行的函数名或者一段代码,第二个参数delay是推迟执行的毫秒数。
  8 + * setTimeout的第二个参数如果省略,则默认为0。
  9 + *
  10 + * 如:
  11 + * let timerId1 = setTimeout(fun1, 1000);
  12 + *
  13 + * setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
  14 + * let intervalId1 = setInterval(fun2, 1000);
  15 + * 上面代码中,每隔1000毫秒就会执行fun2函数,会无限运行下去,直到关闭当前窗口。
  16 + *
  17 + * 注意:
  18 + * setInterval指定的是“开始执行”之间的间隔,并不考虑每次任务执行本身所消耗的时间。因此实际上,两次执行之间的间隔会小于指定的时间。
  19 + * 比如,setInterval指定每 100ms 执行一次,每次执行需要 5ms,那么第一次执行结束后95毫秒,第二次执行就会开始。如果某次执行耗时特别长,比如需要105毫秒,那么它结束后,下一次执行就会立即开始。
  20 + *
  21 + *
  22 + * setTimeout和setInterval函数,都返回一个整数值,表示计数器编号。将该整数传入clearTimeout和clearInterval函数,就可以取消对应的定时器。
  23 + *
  24 + * clearTimeout(timerId1)
  25 + * clearInterval(intervalId1)
  26 + */
  27 +import { WDGroup } from '../layout/WDGroup';
  28 +import HashMap from '@ohos.util.HashMap';
  29 +import { Lego } from './LegoService';
  30 +
  31 +export namespace Timeout {
  32 +
  33 + /**
  34 + * 超时管理
  35 + */
  36 + export class TimeoutManager {
  37 + /**
  38 + * 超时时长
  39 + */
  40 + private static TASK_TIMEOUT: number = 5000;
  41 + /**
  42 + * 任务超时回调
  43 + */
  44 + private callback: Callback;
  45 + /**
  46 + * 用于存放所有进行中的任务
  47 + */
  48 + private taskMap: HashMap<WDGroup, Task>;
  49 + /**
  50 + * 超时管理器单例实例
  51 + */
  52 + private static instance: TimeoutManager;
  53 +
  54 + private intervalId:number = -1;
  55 +
  56 + /**
  57 + * 构造函数
  58 + *
  59 + * @param group 发出请求的MGGroup实例
  60 + * @param startTime 任务开始时间戳
  61 + * @param timeout 超时限制时常
  62 + */
  63 + constructor(callback: Callback) {
  64 + this.taskMap = new HashMap<WDGroup, Task>();
  65 + this.callback = callback;
  66 + // todo:
  67 + // 如果队列中没有检查消息,TASK_TIMEOUT后检查。
  68 + // if (this.intervalId == -1) {
  69 + // this.intervalId = setInterval(() => {
  70 + // this.checkTimeout();
  71 + // }, TimeoutManager.TASK_TIMEOUT);
  72 + // }
  73 + }
  74 +
  75 + /**
  76 + * 添加任务,监控超时状态。
  77 + * @param group MGGroup对象
  78 + * @param callback 回调
  79 + */
  80 + public addTask(group: WDGroup, callback: Lego.Callback) {
  81 + let task: Task = this.taskMap.get(group);
  82 + let timestamp: number = new Date().getTime(); // 单位毫秒
  83 + if (task == null) {
  84 + this.taskMap.set(group, new Task(group, callback, timestamp, TimeoutManager.TASK_TIMEOUT));
  85 + } else {
  86 + task.setStartTime(timestamp);
  87 + task.setCallback(callback);
  88 + }
  89 + }
  90 +
  91 + /**
  92 + * 移除任务,说明任务已经完成,不再监控超时状态。
  93 + * @param group MGGroup对象
  94 + */
  95 + public removeTask(group: WDGroup) {
  96 + this.taskMap.remove(group);
  97 + }
  98 +
  99 + /**
  100 + * 检查是否有已经超时的任务,如有则回调超时状态。
  101 + */
  102 + private checkTimeout() {
  103 + // TODO: 遍历任务列表检查是否有超时任务
  104 + this.taskMap.forEach((task: Task, group: WDGroup) => {
  105 + if (task == null || task.isTimeout()) {
  106 + // 超时回调
  107 + if (this.callback) {
  108 + this.callback.onTimeout(group, task.callback);
  109 + }
  110 + }
  111 + })
  112 + }
  113 + }
  114 +
  115 + /**
  116 + * 任务
  117 + */
  118 + class Task {
  119 + /**
  120 + * MGGroup实例
  121 + */
  122 + private group: WDGroup;
  123 + /**
  124 + * 请求回调
  125 + */
  126 + public callback: Lego.Callback;
  127 + /**
  128 + * 任务开始时间戳
  129 + */
  130 + private startTime: number;
  131 + /**
  132 + * 超时限制时常
  133 + */
  134 + private timeout: number;
  135 +
  136 + /**
  137 + * 构造函数
  138 + *
  139 + * @param group 发出请求的MGGroup实例
  140 + * @param startTime 任务开始时间戳
  141 + * @param timeout 超时限制时常
  142 + */
  143 + constructor(group: WDGroup, callback: Lego.Callback, startTime: number, timeout: number) {
  144 + this.group = group;
  145 + this.callback = callback;
  146 + this.startTime = startTime;
  147 + this.timeout = timeout;
  148 + }
  149 +
  150 + /**
  151 + * 更新任务开始时间戳
  152 + *
  153 + * @param startTime 任务开始时间戳
  154 + */
  155 + public setStartTime(startTime: number): void {
  156 + this.startTime = startTime;
  157 + }
  158 +
  159 + public setCallback(callback: Lego.Callback): void {
  160 + this.callback = callback;
  161 + }
  162 +
  163 + /**
  164 + * 检查任务是否超时
  165 + *
  166 + * @return 是否超时
  167 + */
  168 + public isTimeout(): boolean {
  169 + let timestamp: number = new Date().getTime(); // 单位毫秒
  170 + return timestamp - this.startTime - this.timeout >= 0;
  171 + }
  172 + }
  173 +
  174 + /**
  175 + * 超时回调
  176 + */
  177 + export interface Callback {
  178 + /**
  179 + * Group请求超时回调
  180 + * @param group MGGroup对象
  181 + * @param callback 回调';
  182 + */
  183 + onTimeout: (group: WDGroup, callback: Lego.Callback) => void;
  184 + }
  185 +}
  1 +/**
  2 + 1.主界面底部五个tab
  3 + 请求底导数据(无参数):
  4 +
  5 + 2.请求首页顶部的tab:
  6 + 请求顶导数据(参数是:当前选中的底导item的${page}):
  7 +
  8 + 3.请求页面组件列表数据(参数是:当前选中的顶导item的${path}):
  9 +
  10 + 4.请求每个组件内容列表url(参数是:PageID,groupId, compId)
  11 + */
  12 +import { ConfigConstants } from 'wdConstant';
  13 +import { WDHttp } from 'wdNetwork';
  14 +import { NavBody } from '../bean/NavBody';
  15 +import { PageDTO } from '../bean/PageDTO';
  16 +
  17 +const TAG = 'PageRepository';
  18 +
  19 +export class PageRepository {
  20 + /**
  21 + * 主界面底部五个tab:首页、体育、VIP、广场、我的
  22 + *
  23 + * @returns ResponseDTO<NavBody>
  24 + */
  25 + static fetchNavigationDataApi() {
  26 + const appId: string = ConfigConstants.appId;
  27 + const terminalId: string = ConfigConstants.terminalId;
  28 + const province: string = ConfigConstants.province;
  29 + const navigationUrl = `https://app-sc.miguvideo.com/app-management/v4/staticcache/navigation-list/${appId}/${terminalId}/${province}`
  30 + return WDHttp.Request.get<WDHttp.ResponseDTO<NavBody>>(navigationUrl)
  31 + };
  32 +
  33 + /**
  34 + * 请求/获取首页顶部导航tab菜单列表
  35 + *
  36 + * 参考fetchGroupList函数
  37 + */
  38 + static fetchMenuList(pageId: string): Promise<WDHttp.ResponseDTO<PageDTO>> {
  39 + return PageRepository.fetchGroupList(pageId)
  40 + };
  41 +
  42 + /**
  43 + * display-v4接口
  44 + * pageLayout接口(请求栏目列表)
  45 + *
  46 + * @param pageID 页面Id
  47 + * @returns ResponseDTO<BodyPage>
  48 + */
  49 + static fetchGroupList(pageID: string) {
  50 + const pageUrl: string = `${ConfigConstants.BASE_URL_VOD}${ConfigConstants.CONTENT_LIST_PATH}/${pageID}`;
  51 + return WDHttp.Request.get<WDHttp.ResponseDTO<PageDTO>>(pageUrl)
  52 + };
  53 +
  54 + /**
  55 + * display-v4接口
  56 + * 获取comp数据接口(请求栏目内容)
  57 + *
  58 + * @param pageId 页面Id
  59 + * @param groupId 区段id
  60 + * @param componentId 组件id
  61 + * @returns ResponseDTO<BodyComponent>
  62 + */
  63 + // static fetchComponentData(pageID: string, groupID: string, compID: string) {
  64 + // const pageUrl: string = `${ConfigConstants.BASE_URL_VOD}${ConfigConstants.CONTENT_LIST_PATH}/${pageID}/${groupID}/${compID}`;
  65 + // Logger.info(TAG, "getGroupList pageUrl:" + pageUrl);
  66 + // let headers: Record<string, string> = {
  67 + // 'provinceCode': ConfigConstants.province,
  68 + // 'terminalId': ConfigConstants.terminalId,
  69 + // 'appId': ConfigConstants.appId,
  70 + // };
  71 + // let options: MGHttp.RequestOptions = {
  72 + // header: headers,
  73 + // };
  74 + // return MGHttp.Request.get<MGHttp.ResponseDTO<BodyComponent>>(pageUrl, options)
  75 + // };
  76 +}
  1 +import { ConfigConstants } from 'wdConstant';
  2 +import {Logger} from 'wdKit';
  3 +import {WDHttp} from 'wdNetwork';
  4 +import { CompDataDTO } from '../bean/CompDataDTO';
  5 +import { CompDTO } from '../bean/CompDTO';
  6 +import { DataSourceRequest } from '../bean/DataSourceRequest';
  7 +import { ReplaceUtil } from '../utils/ReplaceUtil';
  8 +
  9 +const TAG = 'CompRequest';
  10 +
  11 +export class CompRequest {
  12 + static fetch(pageID: string, groupID: string, compID: string, page: number, pageSize: number, isRefresh: boolean) {
  13 + const url: string = `${ConfigConstants.BASE_URL_VOD}${ConfigConstants.CONTENT_LIST_PATH}/${pageID}/${groupID}/${compID}`;
  14 + Logger.info(TAG, "fetch url:" + url);
  15 + return WDHttp.Request.get<WDHttp.ResponseDTO<CompDataDTO>>(url)
  16 + };
  17 +
  18 + static fetchDataSource<T>(compDTO: CompDTO,dataSourceRequest: DataSourceRequest) {
  19 + // if (dataSourceRequest.dataSourceType == 'GUESS_YOU_LIKE') {}
  20 + Logger.info(TAG, "fetchDataSource url:" + dataSourceRequest.uri);
  21 + const url: string = ReplaceUtil.replaceUrl(dataSourceRequest.uri, compDTO, dataSourceRequest)
  22 + Logger.info(TAG, "new url:" + url);
  23 + let options: WDHttp.RequestOptions = {
  24 + method: dataSourceRequest.method.toUpperCase() === "POST" ? WDHttp.RequestMethod.POST : WDHttp.RequestMethod.GET,
  25 + header: ReplaceUtil.replaceHeader(dataSourceRequest.header, compDTO, dataSourceRequest),
  26 + // 读超时时间 单位s 默认60
  27 + readTimeout: dataSourceRequest.timeout,
  28 + // 连接超时时间 单位s 默认60
  29 + connectTimeout: dataSourceRequest.timeout,
  30 + params: ReplaceUtil.replaceHeader(dataSourceRequest.paramter, compDTO, dataSourceRequest)
  31 + };
  32 + Logger.info(TAG, "fetchDataSource options:" + JSON.stringify(options));
  33 + return WDHttp.Request.request<WDHttp.ResponseDTO<T>>(url, options)
  34 + };
  35 +}
  1 +import { ConfigConstants } from 'wdConstant';
  2 +import { WDHttp } from 'wdNetwork';
  3 +import { GroupDataDTO } from '../bean/GroupDataDTO';
  4 +
  5 +const TAG = 'StaticGroupRequest';
  6 +
  7 +export class StaticGroupRequest {
  8 + static fetch(pageID: string, groupID: string) {
  9 + const url: string = `${ConfigConstants.BASE_URL_VOD}${ConfigConstants.CONTENT_LIST_PATH}/${pageID}/${groupID}`;
  10 + return WDHttp.Request.get<WDHttp.ResponseDTO<GroupDataDTO>>(url)
  11 + };
  12 +}
  1 +import { ConfigConstants } from 'wdConstant';
  2 +import { WDHttp } from 'wdNetwork';
  3 +import { PageDTO } from '../bean/PageDTO';
  4 +
  5 +export class StaticPageRequest {
  6 + static fetch(pageID: string) {
  7 + const url: string = `${ConfigConstants.BASE_URL_VOD}${ConfigConstants.CONTENT_LIST_PATH}/${pageID}`;
  8 + return WDHttp.Request.get<WDHttp.ResponseDTO<PageDTO>>(url)
  9 + };
  10 +}
  1 +import { CompDTO } from '../bean/CompDTO';
  2 +import { DataSourceRequest } from '../bean/DataSourceRequest';
  3 +
  4 +import {Logger} from 'wdKit';
  5 +import {WDHttp} from 'wdNetwork';
  6 +import { LayoutCallback } from './LayoutCallback';
  7 +import { BusinessError } from '@ohos.base';
  8 +import http from '@ohos.net.http';
  9 +import { CompRequest } from '../request/CompRequest';
  10 +
  11 +const TAG = 'CommonDataService';
  12 +
  13 +/**
  14 + * 数据源服务
  15 + */
  16 +export class CommonDataService {
  17 + public loadDataSource<T>(compDTO: CompDTO, request: DataSourceRequest, callback: LayoutCallback<T>): boolean {
  18 + CompRequest.fetchDataSource<T>(compDTO, request).then((resDTO: WDHttp.ResponseDTO<T>) => {
  19 + if (!resDTO) {
  20 + Logger.error(TAG, 'loadDataSource then resDTO is empty');
  21 + if (callback) {
  22 + callback.onFailed(WDHttp.ErrorCode.FAILED, 'Empty response');
  23 + }
  24 + return
  25 + }
  26 + if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  27 + Logger.error(TAG, `loadDataSource then code:${resDTO.code}, message:${resDTO.message}`);
  28 + if (callback) {
  29 + callback.onFailed(resDTO.code, resDTO.message)
  30 + }
  31 + return
  32 + }
  33 + Logger.info(TAG, "loadDataSource then,resDTO.timeStamp:" + resDTO.timeStamp);
  34 + if (callback) {
  35 + callback.onSuccess(resDTO.body);
  36 + }
  37 + }).catch((error: BusinessError) => {
  38 + Logger.error(TAG, `loadDataSource catch, error.code : ${error.code}, error.message:${error.message}`);
  39 + if (callback) {
  40 + callback.onFailed(WDHttp.ErrorCode.FAILED, error.message);
  41 + }
  42 + })
  43 + return true;
  44 + }
  45 +
  46 +
  47 +}
  1 +/**
  2 + * LayoutService数据请求的回调接口
  3 + */
  4 +export interface LayoutCallback<T> {
  5 +
  6 + /**
  7 + * 成功
  8 + * @param data 数据
  9 + */
  10 + onSuccess: (data: T) => void;
  11 +
  12 + /**
  13 + * 失败
  14 + * @param code 错误码
  15 + * @param message 描述
  16 + */
  17 + onFailed: (code: number, message: string) => void;
  18 +
  19 +}
  1 +/**
  2 + * 用于请求乐高数据,对外提供服务。
  3 + */
  4 +import { PageDTO } from '../bean/PageDTO';
  5 +import { LayoutCallback } from './LayoutCallback';
  6 +import {Logger} from 'wdKit';
  7 +import { WDHttp } from 'wdNetwork';
  8 +import http from '@ohos.net.http';
  9 +import { BusinessError } from '@ohos.base';
  10 +import { CompDTO } from '../bean/CompDTO';
  11 +import { CompDataDTO } from '../bean/CompDataDTO';
  12 +import { GroupDataDTO } from '../bean/GroupDataDTO';
  13 +
  14 +export class LayoutService {
  15 + static readonly TAG: string = 'LayoutService';
  16 +
  17 + /**
  18 + * 获取Page数据
  19 + * @param pageId Page ID
  20 + * @param isRefresh 是否为刷新
  21 + * @param callback 回调
  22 + */
  23 + public getPage(pageId: string, isRefresh: boolean, callback: LayoutCallback<PageDTO>) {
  24 + // TODO: 调用StaticPageRequest请求数据
  25 + StaticPageRequest.fetch(pageId).then((resDTO: WDHttp.ResponseDTO<PageDTO>) => {
  26 + if (!resDTO) {
  27 + Logger.error(LayoutService.TAG, 'then pageResDTO is empty');
  28 + if (callback) {
  29 + callback.onFailed(WDHttp.ErrorCode.FAILED, 'Empty response');
  30 + }
  31 + return
  32 + }
  33 + if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  34 + Logger.error(LayoutService.TAG, `then code:${resDTO.code}, message:${resDTO.message}`);
  35 + if (callback) {
  36 + callback.onFailed(resDTO.code, resDTO.message)
  37 + }
  38 + return
  39 + }
  40 + Logger.info(LayoutService.TAG, "then,resDTO.timeStamp:" + resDTO.timeStamp);
  41 + if (callback) {
  42 + callback.onSuccess(resDTO.body);
  43 + }
  44 + }).catch((error: BusinessError) => {
  45 + Logger.error(LayoutService.TAG, `getPage catch, error.code : ${error.code}, error.message:${error.message}`);
  46 + if (callback) {
  47 + callback.onFailed(WDHttp.ErrorCode.FAILED, error.message);
  48 + }
  49 + })
  50 + }
  51 +
  52 + /**
  53 + * 获取Group数据
  54 + * @param pageId Page ID
  55 + * @param groupId Group ID
  56 + * @param isRefresh 是否为刷新
  57 + * @param callback 回调
  58 + */
  59 + public getGroup(pageId: string, groupId: string, isRefresh: boolean, callback: LayoutCallback<GroupDataDTO>) {
  60 + // TODO: 调用StaticGroupRequest请求数据
  61 + StaticGroupRequest.fetch(pageId, groupId).then((resDTO: WDHttp.ResponseDTO<GroupDataDTO>) => {
  62 + if (!resDTO) {
  63 + Logger.error(LayoutService.TAG, 'getGroup then resDTO is empty');
  64 + if (callback) {
  65 + callback.onFailed(WDHttp.ErrorCode.FAILED, 'Empty response');
  66 + }
  67 + return
  68 + }
  69 + if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  70 + Logger.error(LayoutService.TAG, `getGroup then code:${resDTO.code}, message:${resDTO.message}`);
  71 + if (callback) {
  72 + callback.onFailed(resDTO.code, resDTO.message)
  73 + }
  74 + return
  75 + }
  76 + Logger.info(LayoutService.TAG, "getGroup then,resDTO.timeStamp:" + resDTO.timeStamp);
  77 + if (callback) {
  78 + callback.onSuccess(resDTO.body);
  79 + }
  80 + }).catch((error: BusinessError) => {
  81 + Logger.error(LayoutService.TAG, `getGroup catch, error.code : ${error.code}, error.message:${error.message}`);
  82 + if (callback) {
  83 + callback.onFailed(WDHttp.ErrorCode.FAILED, error.message);
  84 + }
  85 + })
  86 + }
  87 +
  88 + /**
  89 + * 获取Comp数据
  90 + * @param pageId Page ID
  91 + * @param groupId Group ID
  92 + * @param compId Comp ID
  93 + * @param isRefresh 是否为刷新
  94 + * @param callback 回调
  95 + */
  96 + public getComp(pageId: string, groupId: string, compId: string, isRefresh: boolean, callback: LayoutCallback<CompDataDTO>) {
  97 + // TODO: 调用CompDataRequest请求数据
  98 + CompRequest.fetch(pageId, groupId, compId, -1, 10, isRefresh).then((resDTO: WDHttp.ResponseDTO<CompDataDTO>) => {
  99 + if (!resDTO) {
  100 + Logger.error(LayoutService.TAG, 'getComp then resDTO is empty');
  101 + if (callback) {
  102 + callback.onFailed(WDHttp.ErrorCode.FAILED, 'Empty response');
  103 + }
  104 + return
  105 + }
  106 + if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  107 + Logger.error(LayoutService.TAG, `getComp then code:${resDTO.code}, message:${resDTO.message}`);
  108 + if (callback) {
  109 + callback.onFailed(resDTO.code, resDTO.message)
  110 + }
  111 + return
  112 + }
  113 + Logger.info(LayoutService.TAG, "getComp then,resDTO.timeStamp:" + resDTO.timeStamp);
  114 + if (callback) {
  115 + callback.onSuccess(resDTO.body);
  116 + }
  117 + }).catch((error: BusinessError) => {
  118 + Logger.error(LayoutService.TAG, `getComp catch, error.code : ${error.code}, error.message:${error.message}`);
  119 + if (callback) {
  120 + callback.onFailed(WDHttp.ErrorCode.FAILED, error.message);
  121 + }
  122 + })
  123 + }
  124 +
  125 + /**
  126 + * 获取动态Group数据
  127 + * @param pageId Page ID
  128 + * @param groupId Group ID
  129 + * @param isRefresh 是否为刷新
  130 + * @param callback 回调
  131 + */
  132 + public getDynamicGroup(pageId: string, groupId: string, isRefresh: boolean, callback: LayoutCallback<CompDTO>) {
  133 + // TODO: 调用DynamicGroupRequest请求数据
  134 + }
  135 +}
  1 +import { AppUtils } from 'wdKit';
  2 +import { CompDTO } from '../bean/CompDTO';
  3 +import { Tab01DTO } from '../bean/Tab01DTO';
  4 +import { CompStyle } from '../enum/CompStyle';
  5 +
  6 +export class CompFilterUtil {
  7 + static whiteList: string[] = [
  8 + CompStyle.LABEL_01,
  9 + // CompStyle.BUTTON_01,
  10 + CompStyle.NAV_BAR_01,
  11 + CompStyle.NAV_BAR_22,
  12 + CompStyle.NAV_BAR_03,
  13 + CompStyle.BIG_STATIC_IMG_01,
  14 + CompStyle.BIG_CAROUSEL_IMG_01,
  15 + CompStyle.BIG_PLAY_IMG_01,
  16 + CompStyle.TOP_IMG_BOTTOM_TXT_01,
  17 + CompStyle.TOP_IMG_BOTTOM_TXT_02,
  18 + CompStyle.TOP_IMG_BOTTOM_TXT_12,
  19 + CompStyle.BINGE_WATCHING_02,
  20 + CompStyle.SLIDER_IMG_16,
  21 + CompStyle.MATCH_LIST_04,
  22 + // CompStyle.MY_HOME_INFO,
  23 + // CompStyle.MY_HOME_SERVICE_NEW,
  24 + // CompStyle.MY_HOME_VERSION_NUMBER,
  25 + CompStyle.PROGRAM_DESC_01,
  26 + CompStyle.PROGRAM_SET_01,
  27 + CompStyle.CLASSIFY_FILTER_BAR_02,
  28 + CompStyle.WORLDCUP_PLAYBILL,
  29 + ];
  30 + // 待被过滤的tab,赛程PageId与各种筛选PageId
  31 + static pathIdList: string[] = [
  32 + '7a93bb0699c5490bb5eb56bce5444582', // 关注tab
  33 + 'MATCH_SCHEDULE_LIST', // 赛程
  34 + 'af6b9358a1e94d7ba28e254fa0940fb9', // 赛程
  35 + '013d73e3fbf940b394e6b07bcc9b62ea', // 电视剧
  36 + '256c7c16a17848778fc7602fe24da95a', // 电影
  37 + '62a6103b3afd4844abb412f091a3b316', // 综艺
  38 + 'a29987d1308a4e22b153d3aeb69bf58d', // 少儿
  39 + '2a6b09068a474003bf974d14e94fd0b1', // 纪实
  40 + '047a996e72184536a99aa9496c160823',// 动漫
  41 + ];
  42 +
  43 + constructor() {
  44 + }
  45 +
  46 + // filter true需要处理,false就不需要处理
  47 + public static filter(compDTO: CompDTO): boolean {
  48 +
  49 + //临时处理comp过滤,首页轮播图和重磅推荐
  50 + let title = "";
  51 + try {
  52 + if (compDTO.extraData && compDTO.extraData.labels && compDTO.extraData.labels.length > 0) {
  53 + title = compDTO.extraData.labels[0].title ?? "";
  54 + }
  55 + } catch (e){}
  56 + if (compDTO.compStyle == CompStyle.BIG_CAROUSEL_IMG_01 || compDTO.compStyle == CompStyle.TOP_IMG_BOTTOM_TXT_01 || title == "重磅推荐") {
  57 + if (compDTO.androidVersion) {
  58 + compDTO.androidVersion.max = "-1";
  59 + }
  60 + }
  61 +
  62 + if (compDTO == null) {
  63 + return false
  64 + }
  65 +
  66 + if (compDTO.compStyle == null) {
  67 + return false
  68 + }
  69 +
  70 + if (CompFilterUtil.checkWhiteList(compDTO)) {
  71 + return CompFilterUtil.checkVersionCode(compDTO)
  72 + } else {
  73 + return false
  74 + }
  75 + }
  76 +
  77 + private static checkWhiteList(compDTO: CompDTO) {
  78 + return CompFilterUtil.whiteList.indexOf(compDTO.compStyle) != -1
  79 + }
  80 +
  81 + private static checkVersionCode(compDTO: CompDTO): boolean {
  82 + let curVersionCode = Number.parseInt(AppUtils.getAppVersionCode());
  83 + let curVersionName = AppUtils.getAppVersionName();
  84 +
  85 + let version = compDTO?.androidVersion
  86 + let isAllVersion = version?.isAllVersion
  87 + if (isAllVersion == "1"){
  88 + return true
  89 + }
  90 +
  91 + let exclusion: string[] | undefined = version?.exclude
  92 + if (exclusion) {
  93 + for (let i = 0; i < exclusion.length; i++){
  94 + let temp = exclusion[i]
  95 + if (curVersionName == temp){
  96 + return false
  97 + }
  98 + }
  99 + }
  100 + if (version && version.max && version.min) {
  101 + let maxVersionCode = Number.parseInt(version.max)
  102 + let minVersionCode = Number.parseInt(version.min)
  103 + if ((curVersionCode <= maxVersionCode || maxVersionCode == -1) && curVersionCode >= minVersionCode) {
  104 + return true
  105 + } else {
  106 + return false
  107 + }
  108 + }
  109 +
  110 + return true
  111 + }
  112 +
  113 +
  114 + /**
  115 + * 筛选/过滤
  116 + * @param dto
  117 + * @returns 保留此项数据:返回true;否则(舍弃此项数据),返回false;
  118 + */
  119 + public static filterTab01(tab01DTO: Tab01DTO): boolean {
  120 + if (!tab01DTO) {
  121 + return false;
  122 + }
  123 + // if (tab01DTO.title == '关注') { // todo:过滤掉【关注】tab
  124 + // return false;
  125 + // }
  126 + return !CompFilterUtil.pathIdList.includes(tab01DTO?.action?.params?.path ?? "")
  127 + }
  128 +}
  1 +/**
  2 + * 乐高Util。
  3 + */
  4 +import { ItemBean } from '../bean/ItemBean'
  5 +import { ItemDTO } from '../bean/ItemDTO'
  6 +import { WDComp } from '../layout/WDComp'
  7 +import { WDGroup } from '../layout/WDGroup'
  8 +import { WDPage } from '../layout/WDPage'
  9 +
  10 +export class LegoUtil {
  11 + /**
  12 + * 格式化Page的ID
  13 + * @param page MGPage
  14 + * @returns String
  15 + */
  16 + public static getPageId(page: WDPage): string {
  17 + return ''
  18 + }
  19 +
  20 + public static getGroupId(group: WDGroup): string {
  21 + return ''
  22 + }
  23 +
  24 + public static getCompId(comp: WDComp<ItemBean, ItemDTO>): string {
  25 + return ''
  26 + }
  27 +}
  1 +import { ArrayUtils, Logger } from 'wdKit';
  2 +import { CompDTO } from '../bean/CompDTO';
  3 +import { ExtraDTO } from '../bean/ExtraDTO';
  4 +import { LabelDTO } from '../bean/LabelDTO';
  5 +import { Pic } from '../bean/Pic';
  6 +import { ProgrammeBean } from '../bean/ProgrammeBean';
  7 +
  8 +const TAG = "PageUtils";
  9 +
  10 +export class PageUtils {
  11 + /**
  12 + * 选择图片
  13 + * @param data
  14 + * @param isUseVerticalImage 是否竖图;true是竖图,否则是横图
  15 + * @param isUseHighImage,是否高清,true是高清,否则不是高清
  16 + * @returns
  17 + */
  18 + static imgUrlChoose(pics: Pic | undefined, isUseVerticalImage: boolean, isUseHighImage: boolean): string {
  19 + if (!pics) {
  20 + return "";
  21 + }
  22 +
  23 + if (isUseVerticalImage) {
  24 + if (isUseHighImage) {
  25 + if (pics.highResolutionV) {
  26 + return pics.highResolutionV;
  27 + } else if (pics.lowResolutionV) {
  28 + return pics.lowResolutionV;
  29 + }
  30 + } else {
  31 + if (pics.lowResolutionV) {
  32 + return pics.lowResolutionV;
  33 + } else if (pics.highResolutionV) {
  34 + return pics.highResolutionV;
  35 + }
  36 + }
  37 + } else {
  38 + if (isUseHighImage) {
  39 + if (pics.highResolutionH) {
  40 + return pics.highResolutionH;
  41 + } else if (pics.lowResolutionH) {
  42 + return pics.lowResolutionH;
  43 + }
  44 + } else {
  45 + if (pics.lowResolutionH) {
  46 + return pics.lowResolutionH;
  47 + } else if (pics.highResolutionH) {
  48 + return pics.highResolutionH;
  49 + }
  50 + }
  51 + }
  52 +
  53 + return pics.gkResolution1 ?? "";
  54 + }
  55 +
  56 + /**
  57 + * 获取Label标题
  58 + *
  59 + * @param component 组件bean
  60 + * @return Label标题
  61 + */
  62 + static getLabelTitle(componentBean: CompDTO): string {
  63 + if (!componentBean) {
  64 + return ""
  65 + }
  66 + let extraData: ExtraDTO | undefined = componentBean.extraData;
  67 + if (!extraData) {
  68 + return ""
  69 + }
  70 +
  71 + if (!extraData.labels) {
  72 + Logger.info(TAG, 'getLabelTitle, labels is null');
  73 + return ""
  74 + }
  75 +
  76 + for (let index = 0; index < extraData.labels?.length; index++) {
  77 + let label: LabelDTO = ArrayUtils.getListElement(extraData.labels, index)
  78 + if (!label) {
  79 + // Logger.info(TAG, 'getLabelTitle, labels is null');
  80 + continue;
  81 + }
  82 + if (label.isShow != undefined && label.isShow == false) {
  83 + // Logger.info(TAG, 'getLabelTitle, isShow is false');
  84 + continue;
  85 + }
  86 + if (label.label == '主标题') {
  87 + return label.title ?? ""
  88 + }
  89 + }
  90 +
  91 + return "";
  92 + }
  93 +
  94 + /**
  95 + * 选择图片
  96 + * @param data
  97 + * @param isUseVerticalImage 是否竖图;true是竖图,否则是横图
  98 + * @param isUseHighImage,是否高清,true是高清,否则不是高清
  99 + * @returns
  100 + */
  101 + static chooseImgUrl(item: ProgrammeBean, isUseVerticalImage: boolean, isUseHighImage: boolean): string {
  102 + if (!item) {
  103 + return "";
  104 + }
  105 + if (item.programs && item.programs.length > 0) {
  106 + return PageUtils.imgUrlChoose(item.programs[0].pics, isUseVerticalImage, isUseHighImage)
  107 + } else {
  108 + return PageUtils.imgUrlChoose(item.pics, isUseVerticalImage, isUseHighImage)
  109 + }
  110 + }
  111 +
  112 + static getProgramName(item: ProgrammeBean): string {
  113 + if (!item) {
  114 + return "";
  115 + }
  116 + if (item.programs && item.programs.length > 0 && item.programs[0].name) {
  117 + return item.programs[0].name
  118 + }
  119 +
  120 + return item.name ?? "";
  121 + }
  122 +
  123 + static getProgramTitle(item: ProgrammeBean): string {
  124 + if (!item) {
  125 + return "";
  126 + }
  127 + if (item.programs && item.programs.length > 0 && item.programs[0].title) {
  128 + return item.programs[0].title
  129 + }
  130 +
  131 + return item.title ?? "";
  132 + }
  133 +
  134 + private static readonly TIP_LIVE: string = "LIVE"; // 直播
  135 +
  136 + // 获取右上角角标
  137 + static getTopRightTipImgUrl(bean: ProgrammeBean): string | undefined {
  138 + if (!bean) {
  139 + return undefined;
  140 + }
  141 +
  142 + let tipCode: string | undefined = undefined
  143 + if (bean.programTypeV2 == PageUtils.TIP_LIVE) {
  144 + if (bean.strategyTipMap?.CHARGE?.code) {
  145 + tipCode = bean.strategyTipMap?.CHARGE?.code
  146 + } else if (bean.startTime == '0' || bean.endTime == '0') {
  147 + tipCode = bean.showTip?.code ? bean.showTip?.code : bean.tip?.code
  148 + } else {
  149 + // todo:
  150 + }
  151 + } else if (bean.tip?.code || bean.showTip?.code) {
  152 + tipCode = bean.showTip?.code ? bean.showTip?.code : bean.tip?.code
  153 + } else {
  154 + }
  155 + return PageUtils.getTipImgUrl(tipCode)
  156 + }
  157 +
  158 + // 获取左上角角标
  159 + static getTopLeftTipImgUrl(bean: ProgrammeBean): string | undefined {
  160 + return PageUtils.getTipImgUrl(bean?.tip2?.code)
  161 + }
  162 +
  163 + static getTipImgUrl(tipCode: string | undefined, isSetBStyle?: boolean): string | undefined {
  164 + // todo
  165 + return undefined
  166 + }
  167 +
  168 + /**
  169 + * 获取评分的整数部分
  170 + * @param score
  171 + * @returns 整数部分
  172 + */
  173 + static getScoreInteger(score: string): string {
  174 + if (!score) {
  175 + return '';
  176 + }
  177 +
  178 + let dotIndex: number = score.indexOf(".");
  179 + dotIndex = dotIndex > 0 ? dotIndex : 0;
  180 + return score.substring(0, dotIndex)
  181 + }
  182 +
  183 + /**
  184 + * 获取评分的小数部分
  185 + * @param score
  186 + * @returns 小数部分
  187 + */
  188 + static getScoreDecimal(score: string): string {
  189 + if (!score) {
  190 + return '';
  191 + }
  192 + let dotIndex: number = score.indexOf(".");
  193 + dotIndex = dotIndex > 0 ? dotIndex : 0;
  194 + return score.substring(dotIndex, score.length)
  195 + }
  196 +}
  1 +/**
  2 + * Comp数据源通配符替换工具类
  3 + */
  4 +import { CompDTO } from '../bean/CompDTO';
  5 +import { DataSourceRequest } from '../bean/DataSourceRequest';
  6 +import {ConfigConstants} from 'wdConstant'
  7 +
  8 +export class ReplaceUtil {
  9 + private static readonly IDFA: string = "{idfa}";
  10 + private static readonly APP_ID: string = "{appId}";
  11 + private static readonly TERMINAL_ID: string = "{terminalId}";
  12 + private static readonly CLIENT_ID: string = "{clientId}";
  13 + private static readonly CLIENT_PROVINCE_CODE: string = "{clientProvinceCode}";
  14 + private static readonly PROVINCE_CODE: string = "{provinceCode}";
  15 + private static readonly CLIENT_CITY_ID: string = "{clientCityId}";
  16 + private static readonly USER_TOKEN: string = "{userToken}";
  17 + private static readonly APP_VERSION: string = "{appVersion}";
  18 + private static readonly SDK_CE_ID: string = "{SDKCEId}";
  19 + private static readonly X_UP_CLIENT_CHANNEL_ID: string = "{X-UP-CLIENT-CHANNEL-ID}";
  20 + private static readonly IMEI: string = "{imei}";
  21 + private static readonly APP_VERSION_CODE: string = "APP-VERSION-CODE";
  22 + private static readonly PHONE_INFO: string = "{Phone-Info}";
  23 + private static readonly CONTEND_ID: string = "{contentID}";
  24 + private static readonly PROGRAM_TYPE: string = "{program_type}";
  25 + private static readonly EPS_ID: string = "{epsID}";
  26 + private static readonly MSISDN: string = "{msisdn}";
  27 + private static readonly CT_INFO: string = "{ctinfo}";
  28 + private static readonly MOBILE: string = "{mobile}";
  29 + private static readonly USER_ID: string = "{userId}";
  30 + private static readonly LOCATION: string = "{pageID}#{groupID}#{compID}";
  31 + private static readonly BLOCK_NAME: string = "{blockName}";
  32 + private static readonly STAR_ID: string = "{starId}";
  33 + private static readonly FIRST_REQUEST: string = "{first_request}";
  34 + private static readonly CARDS: string = "{cards}";
  35 + private static readonly AD_ID: string = "{adID}";
  36 + private static readonly CSJANDROIDADID: string = "{csjAndroidAdID}";
  37 + private static readonly MATERIAL_STYLE: string = "{materialStyle}";
  38 + private static readonly START_POSITION_OF_AD: string = "{startPositionOfAD}";
  39 + private static readonly STEP_OF_AD: string = "{stepOfAD}";
  40 + private static readonly LOOP: string = "{loop}";
  41 + private static readonly DISPLAYED_COUNT: string = "{displayedCount}";
  42 + private static readonly ISFIRST: string = "{isFirst}";
  43 + private static readonly DYNAMIC_PUBLISHER_TIME: string = "{dynamicPublisherTime}";
  44 + private static readonly RECOMMEND_STATIS_DATA: string = "{actionData}"; //短带长、发现页feed流短视频推荐数据
  45 + private static readonly REQUEST_PENDANT: string = "{reqPendant}"; //请求挂件;0:表示不请求,1:表示请求
  46 + private static readonly REQUEST_SHORT_VIDEO: string = "{reqShortVideo}"; //是否请求短视频:1是,0否
  47 + private static readonly GUIDE_CARD_LABEL: string = "{guideCardLabel}"; //兴趣卡片
  48 + private static readonly GUIDE_CARD: string = "{guideCard}";
  49 + private static readonly EXTRA_TYPE: string = "{extraType}"; //请求额外信息类型,多个以“,”分开,直播间:liveRoom
  50 + private static readonly CLOSE_RECOMMEND: string = "{closeRecommend}"; //关闭个性推荐;0:不关闭,1:关闭
  51 + private static readonly REQLIVEROOM2STATUS: string = "{reqLiveRoom2Status}";
  52 + /**
  53 + * 精彩小视频是否清除缓存,1清除,0不清除
  54 + */
  55 + public static readonly CLEAR_EXPOSURE_KEY: string = "clearExposure_extra_video";
  56 + private static readonly CLEAR_EXPOSURE: string = "{clearExposure}";
  57 + private static KEYS: string[] = [ReplaceUtil.IDFA, ReplaceUtil.APP_ID, ReplaceUtil.TERMINAL_ID, ReplaceUtil.CLIENT_ID,
  58 + ReplaceUtil.CLIENT_PROVINCE_CODE, ReplaceUtil.PROVINCE_CODE, ReplaceUtil.CLIENT_CITY_ID, ReplaceUtil.USER_TOKEN, ReplaceUtil.APP_VERSION,
  59 + ReplaceUtil.SDK_CE_ID, ReplaceUtil.X_UP_CLIENT_CHANNEL_ID, ReplaceUtil.IMEI, ReplaceUtil.APP_VERSION_CODE, ReplaceUtil.PHONE_INFO, ReplaceUtil.CONTEND_ID, ReplaceUtil.PROGRAM_TYPE,
  60 + ReplaceUtil.EPS_ID, ReplaceUtil.MSISDN, ReplaceUtil.CT_INFO, ReplaceUtil.MOBILE, ReplaceUtil.USER_ID, ReplaceUtil.LOCATION, ReplaceUtil.BLOCK_NAME, ReplaceUtil.STAR_ID, ReplaceUtil.FIRST_REQUEST,
  61 + ReplaceUtil.CARDS, ReplaceUtil.AD_ID, ReplaceUtil.MATERIAL_STYLE, ReplaceUtil.START_POSITION_OF_AD, ReplaceUtil.STEP_OF_AD, ReplaceUtil.LOOP, ReplaceUtil.DISPLAYED_COUNT,
  62 + ReplaceUtil.DYNAMIC_PUBLISHER_TIME, ReplaceUtil.RECOMMEND_STATIS_DATA, ReplaceUtil.REQUEST_PENDANT, ReplaceUtil.REQUEST_SHORT_VIDEO,
  63 + ReplaceUtil.GUIDE_CARD_LABEL, ReplaceUtil.GUIDE_CARD, ReplaceUtil.EXTRA_TYPE, ReplaceUtil.CSJANDROIDADID, ReplaceUtil.REQLIVEROOM2STATUS, ReplaceUtil.CLEAR_EXPOSURE, ReplaceUtil.CLOSE_RECOMMEND];
  64 +
  65 + /**
  66 + * 替换URL
  67 + * @param url
  68 + * @param compDTO
  69 + * @param dataSourceBean
  70 + * @returns
  71 + */
  72 + public static replaceUrl(url: string, compDTO: CompDTO, dataSourceBean: DataSourceRequest): string {
  73 + // TODO: 根据通配符替换url
  74 + for (let index = 0; index < ReplaceUtil.KEYS.length; index++) {
  75 + url = ReplaceUtil.replaceString(url, ReplaceUtil.KEYS[index], compDTO, dataSourceBean);
  76 + }
  77 + return url;
  78 + }
  79 +
  80 + private static replaceString(str: string, key: string, compDTO: CompDTO, dataSourceBean: DataSourceRequest): string {
  81 + try {
  82 + if (str != null && str.includes(key)) {
  83 + str = str.replace(key, ReplaceUtil.getReplaceValue(key, compDTO, dataSourceBean));
  84 + }
  85 + } catch (err) {
  86 + }
  87 + return str;
  88 + }
  89 +
  90 + private static getReplaceValue(key: string, compDTO: CompDTO, dataSourceBean: DataSourceRequest): string {
  91 + if (key === ReplaceUtil.IDFA) {
  92 + return ConfigConstants.DEVICE_ID;
  93 + } else if (key === ReplaceUtil.APP_ID) {
  94 + return ConfigConstants.appId;
  95 + } else if (key === ReplaceUtil.CLEAR_EXPOSURE) {
  96 + // if (compDTO != null) {
  97 + // if (compDTO.extraData != null && compDTO.extraData.(ReplaceUtil.CLEAR_EXPOSURE_KEY)) {
  98 + // return compDTO.extraData.getString(CLEAR_EXPOSURE_KEY);
  99 + // }
  100 + // if (compDTO.extraData == null) {
  101 + // compDTO.extraData = new MasterObjectData();
  102 + // }
  103 + // compDTO.extraData.put(CLEAR_EXPOSURE_KEY, "0");
  104 + // }
  105 + return "1";
  106 + } else if (key === ReplaceUtil.TERMINAL_ID) {
  107 + return ConfigConstants.terminalId;
  108 + } else if (key === ReplaceUtil.CLIENT_ID) {
  109 + return ConfigConstants.DEVICE_ID;
  110 + } else if (key === ReplaceUtil.CLOSE_RECOMMEND) {
  111 + // return RecommendManagerUtil.isRecommendable() ? "0" : "1";
  112 + return "0"
  113 + } else if (key === ReplaceUtil.CLIENT_PROVINCE_CODE) {
  114 + // return GlobalBridge.Companion.getInstance().getProvinceService().getProvinceCode();
  115 + return ""
  116 + } else if (key === ReplaceUtil.PROVINCE_CODE) {
  117 + // return GlobalBridge.Companion.getInstance().getProvinceService().getProvinceCode();
  118 + return ""
  119 + } else if (key === ReplaceUtil.CLIENT_CITY_ID) {
  120 + // return GlobalBridge.Companion.getInstance().getProvinceService().getCityId();
  121 + return ""
  122 + } else if (key === ReplaceUtil.USER_TOKEN) {
  123 + // IUserService userService = ArouterServiceManager.provide(IUserService.class);
  124 + // if (userService != null) {
  125 + // return userService.getActiveAccountInfo().getUsertoken();
  126 + // }
  127 + return ""
  128 + } else if (key === ReplaceUtil.APP_VERSION) {
  129 + // return AppUtil.getVersionName(BaseApplicationContext.application);
  130 + return ""
  131 + } else if (key === ReplaceUtil.SDK_CE_ID) {
  132 + // return Constants.serverClientId;
  133 + return ""
  134 + } else if (key === ReplaceUtil.X_UP_CLIENT_CHANNEL_ID) {
  135 + // return ChannelUtil.getChannelId();
  136 + return ""
  137 + } else if (key === ReplaceUtil.IMEI) {
  138 + // return DeviceUtil.getIMEI();
  139 + return ""
  140 + } else if (key === ReplaceUtil.APP_VERSION_CODE) {
  141 + // return ChannelUtil.getVersionId();
  142 + return ""
  143 + } else if (key === ReplaceUtil.PHONE_INFO) {
  144 + // return DeviceUtil.getSystemModel();
  145 + return ""
  146 + } else if (key === ReplaceUtil.CONTEND_ID) {
  147 + // return GlobalBridge.Companion.getInstance().getPro().getCurrentProgramme();
  148 + return ConfigConstants.playingContentId ?? ""
  149 + } else if (key === ReplaceUtil.PROGRAM_TYPE) {
  150 + // return GlobalBridge.Companion.getInstance().getPro().getProgramType();
  151 + return ""
  152 + } else if (key === ReplaceUtil.EPS_ID) {
  153 + // String epsId = GlobalBridge.Companion.getInstance().getPro().getEpsId();
  154 + // if (!TextUtils.isEmpty(epsId)) {
  155 + // return epsId;
  156 + // } else {
  157 + // return GlobalBridge.Companion.getInstance().getPro().getCurrentProgramme();
  158 + // }
  159 + return ""
  160 + } else if (key === ReplaceUtil.MSISDN) {
  161 + // IUserService userService = ArouterServiceManager.provide(IUserService.class);
  162 + // if (userService != null) {
  163 + // return userService.getActiveAccountInfo().getUid();
  164 + // }
  165 + return ""
  166 + } else if (key === ReplaceUtil.CT_INFO) {
  167 + // return GlobalBridge.Companion.getInstance().getProvinceService().getCityId();
  168 + return ""
  169 + } else if (key === ReplaceUtil.MOBILE) {
  170 + // IUserService userService = ArouterServiceManager.provide(IUserService.class);
  171 + // if (userService != null) {
  172 + // return userService.getActiveAccountInfo().getMobile();
  173 + // }
  174 + return ""
  175 + } else if (key === ReplaceUtil.USER_ID) {
  176 + // IUserService userService = ArouterServiceManager.provide(IUserService.class);
  177 + // if (userService != null) {
  178 + // return userService.getActiveAccountInfo().getUid();
  179 + // }
  180 + return ""
  181 + } else if (key === ReplaceUtil.LOCATION) {
  182 + // if (request != null && request.locationValue != null) {
  183 + // return request.locationValue;
  184 + // }
  185 + return ""
  186 + } else if (key === ReplaceUtil.BLOCK_NAME) {
  187 + // String blockType = SPHelper.getString(Constants.FLOOR_TYPE);
  188 + // if ("1".equals(blockType) || "2".equals(blockType)) {
  189 + // String blockName = SPHelper.getString(Constants.FLOOR_BLOCK_NAME);
  190 + // if (!TextUtils.isEmpty(blockName)) {
  191 + // return blockName;
  192 + // }
  193 + // }
  194 + return ""
  195 + } else if (key === ReplaceUtil.STAR_ID) {
  196 + // String blockType = SPHelper.getString(Constants.FLOOR_TYPE);
  197 + // if ("1".equals(blockType)) {
  198 + // String blockStarId = SPHelper.getString(Constants.FLOOR_STAR_ID);
  199 + // if (!TextUtils.isEmpty(blockStarId)) {
  200 + // return blockStarId;
  201 + // }
  202 + // }
  203 + return ""
  204 + } else if (key === ReplaceUtil.FIRST_REQUEST) {
  205 + // return CommonDataUtil.getFirstFlag(compDTO.id);
  206 + return ""
  207 + } else if (key === ReplaceUtil.ISFIRST) {
  208 + // return "true".equals(CommonDataUtil.getFirstFlag(compDTO.id)) ? "1" : "0";
  209 + return ""
  210 + } else if (key === ReplaceUtil.CARDS) {
  211 + // if (compDTO != null && compDTO.extraData != null) {
  212 + // try {
  213 + // Object cards = compDTO.extraData.get("cards");
  214 + // if (cards != null) {
  215 + // return JsonUtil.toJson(cards);
  216 + // }
  217 + // } catch (Exception e) {
  218 + // e.printStackTrace();
  219 + // }
  220 + // }
  221 + return ""
  222 + } else if (key === ReplaceUtil.AD_ID) {
  223 + // if (compDTO != null && compDTO.adInfo != null) {
  224 + // List<String> adIdList = compDTO.adInfo.getObject("adID");
  225 + // if (adIdList != null) {
  226 + // StringBuilder sb = new StringBuilder();
  227 + // for (int i = 0; i < adIdList.size(); i++) {
  228 + // if (i > 0) {
  229 + // sb.append(",");
  230 + // }
  231 + // sb.append(adIdList.get(i));
  232 + // }
  233 + // return sb.toString();
  234 + // }
  235 + // }
  236 + return ""
  237 + } else if (key === ReplaceUtil.CSJANDROIDADID) {
  238 + // if (compDTO != null && compDTO.adInfo != null) {
  239 + // List<String> csjAndroidAdIdList = compDTO.adInfo.getObject("csjAndroidAdId");
  240 + // if (csjAndroidAdIdList != null) {
  241 + // StringBuilder sb = new StringBuilder();
  242 + // for (int i = 0; i < csjAndroidAdIdList.size(); i++) {
  243 + // if (i > 0) {
  244 + // sb.append(",");
  245 + // }
  246 + // sb.append(csjAndroidAdIdList.get(i));
  247 + // }
  248 + // return sb.toString();
  249 + // }
  250 + // }
  251 + return ""
  252 + } else if (key === ReplaceUtil.MATERIAL_STYLE) {
  253 + // if (compDTO != null && compDTO.adInfo != null) {
  254 + // List<String> materialStyleList = compDTO.adInfo.getObject("materialStyle");
  255 + // if (materialStyleList != null) {
  256 + // StringBuilder sb = new StringBuilder();
  257 + // for (int i = 0; i < materialStyleList.size(); i++) {
  258 + // if (i > 0) {
  259 + // sb.append(",");
  260 + // }
  261 + // sb.append(materialStyleList.get(i));
  262 + // }
  263 + // return sb.toString();
  264 + // }
  265 + // }
  266 + return ""
  267 + } else if (key === ReplaceUtil.START_POSITION_OF_AD) {
  268 + // if (compDTO != null && compDTO.adInfo != null) {
  269 + // return compDTO.adInfo.getString("startPosition");
  270 + // }
  271 + return ""
  272 + } else if (key === ReplaceUtil.STEP_OF_AD) {
  273 + // if (compDTO != null && compDTO.adInfo != null) {
  274 + // return compDTO.adInfo.getString("displayStride");
  275 + // }
  276 + return ""
  277 + } else if (key === ReplaceUtil.LOOP) {
  278 + // if (compDTO != null && compDTO.adInfo != null) {
  279 + // return compDTO.adInfo.getString("loop");
  280 + // }
  281 + return ""
  282 + } else if (key === ReplaceUtil.DISPLAYED_COUNT) {
  283 + // return String.valueOf(request.displayCount);
  284 + return ""
  285 + } else if (key === ReplaceUtil.DYNAMIC_PUBLISHER_TIME) {
  286 + // return compDTO.dynamicPublisherTime + "";
  287 + return ""
  288 + } else if (key === ReplaceUtil.RECOMMEND_STATIS_DATA) {
  289 + // String pageId = getPageId(request);
  290 + // if (!TextUtils.isEmpty(pageId)){
  291 + // return GlobalBridge.Companion.getInstance().getRecommendDataStatisManager().getRecommendData(pageId);
  292 + // }
  293 + return ""
  294 + } else if (key === ReplaceUtil.REQUEST_PENDANT) {
  295 + return "1";
  296 + } else if (key === ReplaceUtil.REQUEST_SHORT_VIDEO) {
  297 + return "1";
  298 + } else if (key === ReplaceUtil.GUIDE_CARD) {
  299 + return "1";
  300 + } else if (key === ReplaceUtil.GUIDE_CARD_LABEL) {
  301 + // String interestData = GlobalBridge.Companion.getInstance().getRecommendDataStatisManager().getInterestData();
  302 + // GlobalBridge.Companion.getInstance().getRecommendDataStatisManager().clearAllInterestData();
  303 + // return interestData;
  304 + return ""
  305 + } else if (key === ReplaceUtil.EXTRA_TYPE) {
  306 + return "liveRoom,liveRoom2";
  307 + } else if (key === ReplaceUtil.REQLIVEROOM2STATUS) {
  308 + return "1,2";
  309 + }
  310 + return "";
  311 + }
  312 +
  313 + /**
  314 + * 替换Header
  315 + * @param headers
  316 + * @param compDTO
  317 + * @param dataSourceBean
  318 + * @returns
  319 + */
  320 + public static replaceHeader(headers: Map<string, string>, compDTO: CompDTO, dataSourceBean: DataSourceRequest): Map<string, string> {
  321 + // TODO: 根据通配符替换Header
  322 + return ReplaceUtil.replaceMap(headers, compDTO, dataSourceBean);
  323 + ;
  324 + }
  325 +
  326 + /**
  327 + * 替换参数
  328 + * @param parameters
  329 + * @param compDTO
  330 + * @param dataSourceBean
  331 + * @returns
  332 + */
  333 + public static replaceParameter(parameters: Map<string, string>, compDTO: CompDTO, dataSourceBean: DataSourceRequest): Map<string, string> {
  334 + // TODO: 根据通配符替换Parameter
  335 +
  336 + return ReplaceUtil.replaceMap(parameters, compDTO, dataSourceBean);
  337 + }
  338 +
  339 + private static replaceMap(maps: Map<string, string>, compDTO: CompDTO, dataSourceBean: DataSourceRequest): Map<string, string> {
  340 + let map: Map<string, string> = new Map();
  341 + try {
  342 + // 遍历map
  343 + maps.forEach((value: string, key: string, map: Map<string, string>) => {
  344 + value = ReplaceUtil.getReplaceValue(value, compDTO, dataSourceBean)
  345 + if (value != null) {
  346 + map.set(key, value)
  347 + } else if (key != null) {
  348 + if (!key.includes("{")) {
  349 + map.set(key, value)
  350 + }
  351 + }
  352 + });
  353 + } catch (err) {
  354 +
  355 + }
  356 + return map;
  357 + }
  358 + // public makeJsonObjectRequest():DataSourceRequest{
  359 + //
  360 + //
  361 + // }
  362 +}
  1 +import { Logger } from 'wdKit';
  2 +import { WDHttp } from 'wdNetwork';
  3 +import { NavigationBean } from '../bean/NavigationBean';
  4 +import { PageRepository } from '../repository/PageRepository';
  5 +import http from '@ohos.net.http';
  6 +import { BusinessError } from '@ohos.base';
  7 +import { NavBody } from '../bean/NavBody';
  8 +
  9 +const TAG = 'PageViewModel';
  10 +
  11 +/**
  12 + * 处理返回后的数据
  13 + */
  14 +export class PageViewModel {
  15 + /**
  16 + * get Nav Data from server.
  17 + *
  18 + * Promise方式
  19 + *
  20 + * @return Button[] Nav Data List
  21 + */
  22 + static getNavData(): Promise<NavigationBean> {
  23 + return new Promise<NavigationBean>((success, error) => {
  24 + Logger.info(TAG, `getNavData start`);
  25 + PageRepository.fetchNavigationDataApi().then((navResDTO: WDHttp.ResponseDTO<NavBody>) => {
  26 + if (!navResDTO) {
  27 + Logger.error(TAG, 'getNavData then navResDTO is empty');
  28 + error('navResDTO is empty');
  29 + return
  30 + }
  31 + if (navResDTO.code != http.ResponseCode.OK) {
  32 + Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`);
  33 + error('navResDTO Response Code is failure');
  34 + return
  35 + }
  36 + if (!navResDTO.body?.list) {
  37 + error('navResDTO list is empty');
  38 + return
  39 + }
  40 + // todo:
  41 + const defaultIndex = 5;
  42 + if (navResDTO.body?.list.length <= defaultIndex) {
  43 + let navigationBean = navResDTO.body.list[0]
  44 + success(navigationBean);
  45 + return
  46 + }
  47 + // let navResStr = JSON.stringify(navResDTO);
  48 + Logger.info(TAG, "getNavData then,navResDTO.timeStamp:" + navResDTO.timeStamp);
  49 + let navigationBean = navResDTO.body.list[defaultIndex]
  50 + if (navigationBean.bottomBar.buttons.length >= 5) {
  51 + // 删除底导中的短视频tab
  52 + // 从数组中的shortVideoIndex位置开始删除1个元素,返回已删除的元素。
  53 + let shortVideoIndex = 3
  54 + navigationBean.bottomBar.buttons.splice(shortVideoIndex, 1);
  55 + }
  56 + success(navigationBean);
  57 + }).catch((err: BusinessError) => {
  58 + Logger.error(TAG, `fetchNavigationDataApi catch, error.code : ${err.code}, error.message:${err.message}`);
  59 + error(err);
  60 + })
  61 + })
  62 + }
  63 +
  64 + // /**
  65 + // * get Menu Data from server.
  66 + // *
  67 + // * Promise方式
  68 + // *
  69 + // * @return resDTO PageDTO
  70 + // */
  71 + // static getMenuList(pageId: string): Promise<PageDTO> {
  72 + // return new Promise<PageDTO>((success, error) => {
  73 + // Logger.info(TAG, `getMenuList pageId:${pageId}`);
  74 + // PageRepository.fetchMenuList(pageId).then((resDTO: MGHttp.ResponseDTO<PageDTO>) => {
  75 + // if (!resDTO) {
  76 + // Logger.error(TAG, 'getMenuList then resDTO is empty');
  77 + // error("page data is empty");
  78 + // return
  79 + // }
  80 + // if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  81 + // Logger.error(TAG, `getMenuList then code:${resDTO.code}, message:${resDTO.message}`);
  82 + // error(`get page data error code:${resDTO.code}, message:${resDTO.message}`);
  83 + // return
  84 + // }
  85 + // // let navResStr = JSON.stringify(navResBean);
  86 + // Logger.info(TAG, "getMenuList then,resDTO.timeStamp:" + resDTO.timeStamp);
  87 + // success(resDTO.body);
  88 + // }).catch((err: BusinessError) => {
  89 + // Logger.error(TAG, `getMenuList catch, error.code : ${err.code}, error.message:${err.message}`);
  90 + // error(err);
  91 + // })
  92 + // })
  93 + // }
  94 +
  95 + // static getGroupList(pageId: string): Promise<PageDTO> {
  96 + // return new Promise<PageDTO>((success, error) => {
  97 + // Logger.info(TAG, `getGroupList pageId:${pageId}`);
  98 + // PageRepository.fetchGroupList(pageId).then((resDTO: MGHttp.ResponseDTO<PageDTO>) => {
  99 + // if (!resDTO) {
  100 + // Logger.error(TAG, 'getGroupList then resDTO is empty');
  101 + // error("page data is empty");
  102 + // return
  103 + // }
  104 + // if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  105 + // Logger.error(TAG, `getGroupList then code:${resDTO.code}, message:${resDTO.message}`);
  106 + // error(`get page data error code:${resDTO.code}, message:${resDTO.message}`);
  107 + // return
  108 + // }
  109 + // // let navResStr = JSON.stringify(navResBean);
  110 + // Logger.info(TAG, "getGroupList then,resDTO.timeStamp:" + resDTO.timeStamp);
  111 + // success(resDTO.body);
  112 + // }).catch((err: BusinessError) => {
  113 + // Logger.error(TAG, `getGroupList catch, error.code : ${err.code}, error.message:${err.message}`);
  114 + // error(err);
  115 + // })
  116 + // })
  117 + // }
  118 +
  119 + // static getComponentData(pageID: string, groupID: string, compID: string): Promise<BodyComponent> {
  120 + // return new Promise<BodyComponent>((success, error) => {
  121 + // Logger.info(TAG, `getComponentData pageId:${pageID}`);
  122 + // PageRepository.fetchComponentData(pageID, groupID, compID).then((resDTO: MGHttp.ResponseDTO<BodyComponent>) => {
  123 + // if (!resDTO) {
  124 + // Logger.error(TAG, 'getComponentData then resDTO is empty');
  125 + // error("page data is empty");
  126 + // return
  127 + // }
  128 + // if (resDTO.code != http.ResponseCode.OK || !resDTO.body) {
  129 + // Logger.error(TAG, `getComponentData then code:${resDTO.code}, message:${resDTO.message}`);
  130 + // error(`get page data error code:${resDTO.code}, message:${resDTO.message}`);
  131 + // return
  132 + // }
  133 + // // let navResStr = JSON.stringify(navResBean);
  134 + // Logger.info(TAG, "getComponentData then,resDTO.timeStamp:" + resDTO.timeStamp);
  135 + // success(resDTO.body);
  136 + // }).catch((err: BusinessError) => {
  137 + // Logger.error(TAG, `getComponentData catch, error.code : ${err.code}, error.message:${err.message}`);
  138 + // error(err);
  139 + // })
  140 + // })
  141 + // }
  142 +
  143 + /**
  144 + * Get data of Component.
  145 + *
  146 + * @return {programmeData[]} compRes.body?.data.
  147 + */
  148 + // static async getProgrammeDataList(context: Context): Promise<ProgrammeDTO[]> {
  149 + // let compRes: MGHttp.ResponseDTO<BodyComponent> = await ResourcesUtils.getResourcesJson<MGHttp.ResponseDTO<BodyComponent>>(context, 'model/componentList.json');
  150 + // Logger.info(TAG, `programmeDataList getResourcesJson compRes : ${JSON.stringify(compRes)}`);
  151 + // if (!compRes.body) {
  152 + // return []
  153 + // }
  154 + // return compRes.body?.data;
  155 + // }
  156 +}
  157 +
  158 +let pageViewModel = new PageViewModel();
  159 +
  160 +export default pageViewModel as PageViewModel;
  1 +{
  2 + "module": {
  3 + "name": "wdLayout",
  4 + "type": "shared",
  5 + "description": "$string:shared_desc",
  6 + "deviceTypes": [
  7 + "phone",
  8 + "tablet",
  9 + "2in1"
  10 + ],
  11 + "deliveryWithInstall": true,
  12 + "pages": "$profile:main_pages"
  13 + }
  14 +}
  1 +{
  2 + "color": [
  3 + {
  4 + "name": "white",
  5 + "value": "#FFFFFF"
  6 + }
  7 + ]
  8 +}
  1 +{
  2 + "string": [
  3 + {
  4 + "name": "shared_desc",
  5 + "value": "description"
  6 + }
  7 + ]
  8 +}
  1 +{
  2 + "src": [
  3 + "pages/Index"
  4 + ]
  5 +}
  1 +import localUnitTest from './LocalUnit.test';
  2 +
  3 +export default function testsuite() {
  4 + localUnitTest();
  5 +}
  1 +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
  2 +
  3 +export default function localUnitTest() {
  4 + describe('localUnitTest',() => {
  5 + // Defines a test suite. Two parameters are supported: test suite name and test suite function.
  6 + beforeAll(() => {
  7 + // Presets an action, which is performed only once before all test cases of the test suite start.
  8 + // This API supports only one parameter: preset action function.
  9 + });
  10 + beforeEach(() => {
  11 + // Presets an action, which is performed before each unit test case starts.
  12 + // The number of execution times is the same as the number of test cases defined by **it**.
  13 + // This API supports only one parameter: preset action function.
  14 + });
  15 + afterEach(() => {
  16 + // Presets a clear action, which is performed after each unit test case ends.
  17 + // The number of execution times is the same as the number of test cases defined by **it**.
  18 + // This API supports only one parameter: clear action function.
  19 + });
  20 + afterAll(() => {
  21 + // Presets a clear action, which is performed after all test cases of the test suite end.
  22 + // This API supports only one parameter: clear action function.
  23 + });
  24 + it('assertContain', 0, () => {
  25 + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
  26 + let a = 'abc';
  27 + let b = 'b';
  28 + // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
  29 + expect(a).assertContain(b);
  30 + expect(a).assertEqual(a);
  31 + });
  32 + });
  33 +}
1 export { ResponseDTO } from './src/main/ets/bean/ResponseDTO' 1 export { ResponseDTO } from './src/main/ets/bean/ResponseDTO'
2 export { ResponseVO } from './src/main/ets/bean/ResponseVO' 2 export { ResponseVO } from './src/main/ets/bean/ResponseVO'
3 -export { ResultCode } from './src/main/ets/bean/ResultCode'  
  3 +export { ResultCode } from './src/main/ets/bean/ResultCode'
  4 +
  5 +export { WDHttp } from './src/main/ets/http/WDHttp'
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 "main": "Index.ets", 7 "main": "Index.ets",
8 "version": "1.0.0", 8 "version": "1.0.0",
9 "dependencies": { 9 "dependencies": {
10 - "@ohos/axios": "^2.1.1" 10 + "@ohos/axios": "^2.1.1",
  11 + "wdKit": "file:../wdKit"
11 } 12 }
12 } 13 }
  1 +import http from '@ohos.net.http';
  2 +import { BusinessError } from '@ohos.base';
  3 +import ArrayList from '@ohos.util.ArrayList';
  4 +import {Logger} from 'wdKit';
  5 +import { HttpUtils } from '../utils/HttpUtils';
  6 +
  7 +const TAG = 'WDHttp';
  8 +
  9 +export namespace WDHttp {
  10 +
  11 + export enum RequestMethod {
  12 + OPTIONS = http.RequestMethod.OPTIONS,
  13 + GET = http.RequestMethod.GET,
  14 + HEAD = http.RequestMethod.HEAD,
  15 + POST = http.RequestMethod.POST,
  16 + PUT = http.RequestMethod.PUT,
  17 + DELETE = http.RequestMethod.DELETE,
  18 + TRACE = http.RequestMethod.TRACE,
  19 + CONNECT = http.RequestMethod.CONNECT,
  20 + }
  21 +
  22 + export enum HttpParamsType {
  23 + STRING,
  24 + OBJECT,
  25 + ARRAY_BUFFER
  26 + }
  27 +
  28 + export interface RequestOptions {
  29 + // 请求方法
  30 + method?: RequestMethod;
  31 +
  32 + // 请求头
  33 + header?: object;
  34 +
  35 + // 读超时时间 单位s 默认60
  36 + readTimeout?: number;
  37 +
  38 + // 连接超时时间 单位s 默认60
  39 + connectTimeout?: number;
  40 +
  41 + // 请求参数 当请求为get请求时 该参数会自动拼接在url后面
  42 + params?: object;
  43 +
  44 + // 请求参数类型 当请求为post时有效
  45 + paramsType?: HttpParamsType;
  46 + }
  47 +
  48 + export const enum ErrorCode {
  49 + // 请求执行(查询)失败
  50 + FAILED = -1,
  51 + // 请求执行(查询)成功
  52 + SUCCESS = http.ResponseCode.OK,
  53 + // 业务错误码。。。
  54 + }
  55 +
  56 + /**
  57 + * ResponseDTO
  58 + * 微服务通用返回结构
  59 + * http://confluence.cmvideo.cn/confluence/pages/viewpage.action?pageId=4232418
  60 + */
  61 + export interface ResponseDTO<T = string> {
  62 + // 服务请求响应值/微服务响应状态码”
  63 + code: number;
  64 +
  65 + // 服务请求响应说明
  66 + message: string;
  67 +
  68 + // 响应结果
  69 + body?: T;
  70 +
  71 + // 请求响应时间戳(unix格式)
  72 + timeStamp?: number;
  73 + // timestamp?: number;
  74 +
  75 + // 返回当前时间戳,格式:yyyyMMddHHmmss,如20230918102124
  76 + dataVersion?: string;
  77 + }
  78 +
  79 + /**
  80 + * ResponseVO
  81 + * 基础服务通用返回结构
  82 + * 如PUGC错误码:http://confluence.cmvideo.cn/confluence/pages/viewpage.action?pageId=168081524
  83 + */
  84 + export interface ResponseVO<T = string> {
  85 + // 返回代码,参考附录ResultCode 即(ACCEPTED/SUCCESS/FAILED/REJECTED等)
  86 + resultCode: string;
  87 +
  88 + // 返回描述
  89 + resultDesc: string;
  90 +
  91 + // 错误码,参考附录和接口中ErrorCode(当resultCode=FAILED才有),如:"ERR_USER_NOTFOUND"
  92 + errorCode?: string;
  93 +
  94 + // 业务数据
  95 + data?: T;
  96 + }
  97 +
  98 + /**
  99 + * The Response ResultCode enum.
  100 + */
  101 + export const enum ResultCode {
  102 + // 请求执行(查询)成功
  103 + SUCCESS = 'SUCCESS',
  104 + // 请求执行(查询)失败
  105 + FAILED = 'FAILED',
  106 + // 该请求被拒绝处理,例如参数错误或非法等
  107 + REJECTED = 'REJECTED',
  108 + // 该请求已经被接收,但是本次同步返回无法知道执行结果
  109 + ACCEPTED = 'ACCEPTED',
  110 + // 参数错误
  111 + // ERR_NOT_VALID_PARAMETERS = 'ERR_NOT_VALID_PARAMETERS'
  112 + }
  113 +
  114 + export class Request {
  115 + private static globalHeaderProviders: ArrayList<() => Record<string, string>> = new ArrayList();
  116 +
  117 + static addGlobalHeaderProvider(provider: () => Record<string, string>) {
  118 + Request.globalHeaderProviders.add(provider)
  119 + }
  120 +
  121 + static initHttpHeader() {
  122 + Request.addGlobalHeaderProvider(() => {
  123 + return HttpUtils.buildHeaders();
  124 + })
  125 + }
  126 +
  127 + private static makeRequestOptions(options?: RequestOptions): http.HttpRequestOptions {
  128 + if (options) {
  129 + let op: http.HttpRequestOptions = {};
  130 + op.method = options.method!.toString() as http.RequestMethod;
  131 + op.header = options.header
  132 + op.readTimeout = (options.readTimeout ?? 60) * 1000
  133 + op.connectTimeout = (options.connectTimeout ?? 60) * 1000
  134 + if (options.method == RequestMethod.POST) {
  135 + op.extraData = options.params;
  136 + if (options.paramsType == HttpParamsType.STRING) {
  137 + op.expectDataType = http.HttpDataType.STRING;
  138 + } else if (options.paramsType == HttpParamsType.OBJECT) {
  139 + op.expectDataType = http.HttpDataType.OBJECT;
  140 + } else if (options.paramsType == HttpParamsType.ARRAY_BUFFER) {
  141 + op.expectDataType = http.HttpDataType.ARRAY_BUFFER;
  142 + }
  143 + } else if (options.method == RequestMethod.PUT) {
  144 + // todo
  145 + } else if (options.method == RequestMethod.DELETE) {
  146 + // todo
  147 + }
  148 + return op;
  149 + }
  150 + return {}
  151 + }
  152 +
  153 + private static makeUrl(url: string, options?: RequestOptions): string {
  154 + if (!options || (options.method && options.method != RequestMethod.GET)) {
  155 + return url;
  156 + }
  157 + if (!options.params) {
  158 + return url;
  159 + }
  160 + let paramStr = "";
  161 + if (typeof options.params == "string") {
  162 + paramStr = options.params;
  163 + } else if (typeof options.params == "object") {
  164 + let arr: string[] = [];
  165 + Object.entries(options.params).forEach((entry: object) => {
  166 + arr.push(`${entry[0]}=${entry[1]}`)
  167 + })
  168 + if (arr.length == 0) {
  169 + return url;
  170 + }
  171 + paramStr = arr.join("&")
  172 + }
  173 + if (url.indexOf("?") == -1) {
  174 + return url + "?" + paramStr;
  175 + } else {
  176 + if (url.endsWith("?")) {
  177 + return url + paramStr;
  178 + } else {
  179 + return url + "&" + paramStr;
  180 + }
  181 + }
  182 + }
  183 +
  184 + // 加入泛型限定,返回数据类型为T,
  185 + // static request<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {
  186 + // let httpRequest = http.createHttp();
  187 + // if (!options) {
  188 + // options = {};
  189 + // }
  190 + // if (!options.method) {
  191 + // options.method = RequestMethod.GET;
  192 + // }
  193 + // if (!options.header) {
  194 + // let header: Record<string, string> = {
  195 + // // 'Content-Type': 'text/plain'
  196 + // 'Content-Type': 'application/json;charset=utf-8'
  197 + // };
  198 + // options.header = header
  199 + // } else if (!options.header['Content-Type']) {
  200 + // options.header['Content-Type'] = 'application/json;charset=utf-8';
  201 + // }
  202 + //
  203 + // Request.globalHeaders.forEach((value, key) => {
  204 + // options!.header![key] = value;
  205 + // })
  206 + // let realUrl = Request.makeUrl(url, options);
  207 + // httpRequest.request(realUrl, Request.makeRequestOptions(options), (error, responseData: http.HttpResponse) => {
  208 + // if (callback) {
  209 + // if (error) {
  210 + // callback(error, undefined)
  211 + // } else {
  212 + // try {
  213 + // let response: ResponseDTO<T> = JSON.parse(`${responseData.result}`)
  214 + // callback(error, response)
  215 + // } catch (err) {
  216 + // callback(error, { code: responseData?.responseCode, message: responseData?.result?.toString() })
  217 + // }
  218 + // }
  219 + // }
  220 + // })
  221 + // }
  222 + //
  223 + // static get<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {
  224 + // let op = options ?? {}
  225 + // op.method = RequestMethod.GET;
  226 + // Request.request<T>(url, op, callback)
  227 + // }
  228 + //
  229 + // static post<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {
  230 + // let op = options ?? {}
  231 + // op.method = RequestMethod.POST;
  232 + // Request.request<T>(url, op, callback)
  233 + // }
  234 + //
  235 + // static put<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {
  236 + // let op = options ?? {}
  237 + // op.method = RequestMethod.PUT;
  238 + // Request.request<T>(url, op, callback)
  239 + // }
  240 + //
  241 + // static delete<T = any>(url: string, options: RequestOptions, callback?: AsyncCallback<ResponseDTO<T>>) {
  242 + // let op = options ?? {}
  243 + // op.method = RequestMethod.DELETE;
  244 + // Request.request<T>(url, op, callback)
  245 + // }
  246 + ////
  247 + static request<T = string>(url: string, options?: RequestOptions): Promise<T> {
  248 + let httpRequest = http.createHttp();
  249 + if (!options) {
  250 + options = {};
  251 + }
  252 + if (!options.method) {
  253 + options.method = RequestMethod.GET;
  254 + }
  255 + if (!options.header) {
  256 + let header: Record<string, string> = {
  257 + // 'Content-Type': 'text/plain'
  258 + 'Content-Type': 'application/json;charset=utf-8'
  259 + };
  260 + options.header = header
  261 + } else if (!options.header['Content-Type']) {
  262 + options.header['Content-Type'] = 'application/json;charset=utf-8';
  263 + }
  264 + let commonHeader: Record<string, string | number> = { };
  265 + Request.globalHeaderProviders.forEach((func) => {
  266 + let headers = func();
  267 + for (const obj of Object.entries(headers)) {
  268 + commonHeader[obj[0]] = obj[1];
  269 + }
  270 + })
  271 + let userHeader = options.header as Record<string, string | number>
  272 + for (const obj1 of Object.entries(userHeader)) {
  273 + commonHeader[obj1[0]] = obj1[1];
  274 + }
  275 + options.header = commonHeader
  276 + let realUrl = Request.makeUrl(url, options);
  277 + Logger.info(TAG, `request realUrl: ${realUrl}`);
  278 + Logger.info(TAG, `header: ${realUrl}`);
  279 + return new Promise<T>((resolve, reject) => {
  280 + httpRequest.request(realUrl, Request.makeRequestOptions(options))
  281 + .then((responseData: http.HttpResponse) => {
  282 + try {
  283 + if (responseData.responseCode == http.ResponseCode.OK) {
  284 + // todo:待处理JSON.parse只解析目标class中指定的字段
  285 + // let response = JSON.parse(`${data}`) as ResponseDTO<T>
  286 + let response: T = JSON.parse(`${responseData.result}`)
  287 + resolve(response)
  288 + } else {
  289 + // 返回码不是ok
  290 + let responseError: BusinessError = {
  291 + code: responseData?.responseCode,
  292 + message: responseData?.result?.toString(),
  293 + name: '业务错误',
  294 + }
  295 + reject(responseError)
  296 + }
  297 + } catch (err) {
  298 + // json解析异常
  299 + let responseParseError: BusinessError = {
  300 + code: responseData?.responseCode,
  301 + message: responseData?.result?.toString(),
  302 + name: '解析异常',
  303 + }
  304 + reject(responseParseError)
  305 + }
  306 + })
  307 + .catch((error: BusinessError) => {
  308 + reject(error)
  309 + })
  310 + })
  311 + }
  312 +
  313 + static get<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {
  314 + let op = options ?? {}
  315 + op.method = RequestMethod.GET;
  316 + return Request.request<T>(url, op)
  317 + }
  318 +
  319 + static post<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {
  320 + let op = options ?? {}
  321 + op.method = RequestMethod.POST;
  322 + return Request.request<T>(url, op)
  323 + }
  324 +
  325 + static put<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {
  326 + let op = options ?? {}
  327 + op.method = RequestMethod.PUT;
  328 + return Request.request<T>(url, op)
  329 + }
  330 +
  331 + static delete<T = ResponseDTO<string>>(url: string, options?: RequestOptions): Promise<T> {
  332 + let op = options ?? {}
  333 + op.method = RequestMethod.DELETE;
  334 + return Request.request<T>(url, op)
  335 + }
  336 + }
  337 +}