zhangbo1_wd

新增首页底导缓存

... ... @@ -16,7 +16,6 @@ export class KVStoreHelper {
private kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
private constructor() {
Logger.error(TAG, 'constructor')
}
static init(context: Context) {
... ...
/**
* 接口数据存储封装类
*/
import { DateTimeUtils, StringUtils } from 'wdKit/Index';
import { CacheDataSaveUtil } from './CacheDataSaveUtil';
import { JSON } from '@kit.ArkTS';
/**
* 接口数据存储封装类
*/
export class CacheData {
/**
* 底部导航栏缓存的数据key
*/
static bottomCacheKey = 'bottom_cache_data_key'
/**
* 头部频道缓存的数据key
*/
static channelCacheDataKey = 'channel_data_cache_id_'
/**
* 页面page组件的数据key
*/
static comPageInfoCacheKey = 'com_pageInfo_cache_id_'
/**
* 页面组件的数据key
*/
static compGroupInfoDataCacheKey = 'com_data_info_cache_id_'
// 接口返回数据
networkData?: object;
// 数据更新时间戳
... ... @@ -48,16 +65,20 @@ export class CacheData {
success(null)
return
}
let ll = CacheDataSaveUtil.get(key)
if (ll instanceof Promise) {
ll.then((data) => {
let str = data as string
let cache = JSON.parse(str) as CacheData
success(cache)
})
} else {
CacheDataSaveUtil.get(key).then((data) => {
let str = data as string
let cache = JSON.parse(str) as CacheData
success(cache)
}).catch(() => {
success(null)
}
})
})
}
static getNetworkData(data: CacheData): string {
if (data.networkData) {
return JSON.stringify(data.networkData);
}
return "";
}
}
\ No newline at end of file
... ...
... ... @@ -11,10 +11,18 @@ export class CacheDataSaveUtil {
KVStoreHelper.default.put(key, value)
}
static get(key: string) {
if (StringUtils.isEmpty(key)) {
return ''
}
return KVStoreHelper.default.get(key, '')
static get(key: string): Promise<string> {
return new Promise<string>((success) => {
if (StringUtils.isEmpty(key)) {
success('')
} else {
KVStoreHelper.default.get(key, '').then((data) => {
let str = data as string
success(str)
}).catch(() => {
success('')
})
}
})
}
}
\ No newline at end of file
... ...
import HomeChannelUtils from './src/main/ets/utils/HomeChannelUtils';
export default HomeChannelUtils;
export { WDRouterRule } from './src/main/ets/router/WDRouterRule'
export { WDRouterPage } from './src/main/ets/router/WDRouterPage'
... ... @@ -6,4 +10,6 @@ export { registerRouter } from './src/main/ets/router/Action2Page'
export { ProcessUtils } from './src/main/ets/utils/ProcessUtils'
export { AssignChannelParam } from './src/main/ets/utils/HomeChannelUtils';
export { RouterJumpInterceptor, JumpInterceptorAction } from './src/main/ets/router/RouterJumpInterceptor'
\ No newline at end of file
... ...
... ... @@ -2,7 +2,6 @@ import { BottomNavDTO, NavigationBodyDTO, TopNavDTO } from 'wdBean/Index';
import { EmitterEventId, EmitterUtils, StringUtils } from 'wdKit/Index';
import { WDRouterPage } from '../router/WDRouterPage';
import { WDRouterRule } from '../router/WDRouterRule';
import { HashMap } from '@kit.ArkTS';
/**
* 首页、频道相关跳转、处理
... ...
... ... @@ -4,17 +4,20 @@ import { TopNavDTO } from './TopNavDTO';
/**
* 导航Body数据
*/
export interface NavigationBodyDTO {
backgroundColor: string; // 迭代二新增-底部导航背景色(信息流频道)
bottomNavList: BottomNavDTO[];
export class NavigationBodyDTO {
backgroundColor: string = ''; // 迭代二新增-底部导航背景色(信息流频道)
bottomNavList: BottomNavDTO[] = [];
// greyBottomNav: GreyBottomNav; // 灰度皮肤
immersiveBackgroundColor: string; // 迭代二新增-底部导航背景色(沉浸式频道)
nightBackgroundColor: string; // 迭代三新增-底部导航背景色(夜间模式)
immersiveBackgroundColor: string = ''; // 迭代二新增-底部导航背景色(沉浸式频道)
nightBackgroundColor: string = ''; // 迭代三新增-底部导航背景色(夜间模式)
md5: string = ''
}
export interface NavigationDetailDTO {
id: string; // 迭代二新增-底部导航背景色(信息流频道)
bottomNavCompList: BottomNavCompDTO[];
topNavChannelList: TopNavDTO[];
export class NavigationDetailDTO {
id: string = ''; // 迭代二新增-底部导航背景色(信息流频道)
bottomNavCompList: BottomNavCompDTO[] = [];
topNavChannelList: TopNavDTO[] = [];
md5: string = ''
}
... ...
/**
* 顶导
*/
export interface TopNavDTO {
channelId: number;
channelStyle: number;
channelType: number; // 频道样式;1-沉浸式;2-信息流;3-特殊频道(跳转指定页面的,如版面)
defaultPermitted: number;
delPermitted: number;
fontCColor: string; // 频道展示样式颜色(选中状态)
fontColor: string; // 频道展示样式颜色(未选中状态)
headlinesOn: number;
homeChannel: string;
iconUrlSize: string;
iconCUrlSize: string;
iconUrl: string; // 频道图片展示样式图片相对地址(未选中状态)
iconCUrl: string; //频道图片展示样式图片相对地址(选中状态
localChannel: string;
moreChannel: string;
movePermitted: number;
myChannel: string;
name: string;
num: number;
pageId: number;
pageType: string;
underlineCColor: string; // 选中下划线颜色
export class TopNavDTO {
channelId: number = 0;
channelStyle: number = 0;
channelType: number = 0; // 频道样式;1-沉浸式;2-信息流;3-特殊频道(跳转指定页面的,如版面)
defaultPermitted: number = 0;
delPermitted: number = 0;
fontCColor: string = ''; // 频道展示样式颜色(选中状态)
fontColor: string = ''; // 频道展示样式颜色(未选中状态)
headlinesOn: number = 0;
homeChannel: string = '';
iconUrlSize: string = '';
iconCUrlSize: string = '';
iconUrl: string = ''; // 频道图片展示样式图片相对地址(未选中状态)
iconCUrl: string = ''; //频道图片展示样式图片相对地址(选中状态
localChannel: string = '';
moreChannel: string = '';
movePermitted: number = 0;
myChannel: string = '';
name: string = '';
num: number = 0;
pageId: number = 0;
pageType: string = '';
underlineCColor: string = ''; // 选中下划线颜色
}
... ...
import { BottomNavi, CommonConstants } from 'wdConstant';
import { BottomNavDTO, TopNavDTO } from 'wdBean';
import { DateTimeUtils, EmitterEventId, EmitterUtils, Logger } from 'wdKit';
import { BottomNavDTO, NavigationBodyDTO, TopNavDTO } from 'wdBean';
import { EmitterEventId, EmitterUtils, Logger } from 'wdKit';
import { TopNavigationComponent } from './TopNavigationComponent';
import { MinePageComponent } from './MinePageComponent';
import { CompUtils } from '../../utils/CompUtils';
import PageViewModel from '../../viewmodel/PageViewModel';
import HomeChannelUtils, { AssignChannelParam } from 'wdRouter/src/main/ets/utils/HomeChannelUtils';
import { Message } from 'wdJsBridge/src/main/ets/bean/Message';
import ChannelViewModel from '../../viewmodel/ChannelViewModel';
import HomeChannelUtils, { AssignChannelParam } from 'wdRouter';
import { VideoChannelPage } from './VideoChannelPage';
const TAG = 'BottomNavigationComponent';
... ... @@ -46,18 +45,12 @@ export struct BottomNavigationComponent {
@State assignChannel: AssignChannelParam = new AssignChannelParam()
// 自动刷新触发(双击tab自动刷新)
@State autoRefresh: number = 0
// 顶导数据,从接口获取 TODO 顶导业务逻辑没看懂,暂时不替换顶导list。频道管理数据待梳理
@State topNavMap: Record<string, TopNavDTO[]> = {}
async aboutToAppear() {
Logger.info(TAG, `aboutToAppear currentNavIndex: ${this.currentNavIndex}`);
let bottomNav = await PageViewModel.getBottomNavData(getContext(this))
if (bottomNav && bottomNav.bottomNavList != null) {
Logger.info(TAG, `aboutToAppear, bottomNav.length: ${bottomNav.bottomNavList.length}`);
// 使用filter方法移除name为'服务'的项
bottomNav.bottomNavList = bottomNav.bottomNavList.filter(item => item.name !== '服务');
this.bottomNavList = bottomNav.bottomNavList
}
this.getTopNavList(this.bottomNavList[0]?.id)
HomeChannelUtils.setBottomNavData(bottomNav)
this.getBottomData()
EmitterUtils.receiveEvent(EmitterEventId.JUMP_HOME_CHANNEL, (str?: string) => {
Logger.debug(TAG, 'receiveEvent JUMP_HOME_CHANNEL: ' + str)
... ... @@ -170,7 +163,7 @@ export struct BottomNavigationComponent {
//请求顶导数据
async getTopNavList(id: number) {
let bottomNavDetail = await PageViewModel.getBottomNavDetailData(id)
let bottomNavDetail = await ChannelViewModel.getBottomNavDetailData(id)
this.topNavList = bottomNavDetail?.topNavChannelList || []
}
... ... @@ -203,4 +196,62 @@ export struct BottomNavigationComponent {
this.assignChannel.bottomNavId = assignChannel.bottomNavId
}, 20)
}
private async getBottomData() {
Logger.debug(TAG, 'getBottomData')
// 1、缓存底导数据
let bottomCache = await ChannelViewModel.getBottomNavCacheData()
if (bottomCache && bottomCache.bottomNavList != null) {
Logger.debug(TAG, 'getBottomData cache success')
this.setData(bottomCache)
this.getBottomDetail()
}
// TODO 2、预置底导数据
// 3、接口底导数据
let bottomNav = await ChannelViewModel.getBottomNavData()
if (bottomNav && bottomNav.bottomNavList != null) {
Logger.debug(TAG, 'getBottomNavData')
HomeChannelUtils.setBottomNavData(bottomNav)
if (this.bottomNavList == null || this.bottomNavList.length <= 0) {
// 底导没展示,则用接口数据(接口数据回来,不去覆盖缓存数据,没有缓存才加载)
this.setData(bottomNav)
this.getBottomDetail()
}
// 将数据保存本地
ChannelViewModel.saveBottomData(bottomNav)
}
}
private getBottomDetail() {
// 1、获取顶导缓存数据
// this.bottomNavList.forEach((value) => {
// // 先用底导带回的list初始化
// this.topNavMap[value.id] = value.topNavChannelList
// ChannelViewModel.getBottomNavDetailData(value?.id).then((bottomNavDetail) => {
// let list = bottomNavDetail?.topNavChannelList || []
// // 将顶导数据,单独存储
// this.topNavMap[value.id] = list
// })
// })
// // 2、获取顶导接口数据,返回后需要覆盖缓存数据
// this.bottomNavList.forEach((value) => {
// ChannelViewModel.getBottomNavDetailData(value?.id).then((bottomNavDetail) => {
// let list = bottomNavDetail?.topNavChannelList || []
// // 将顶导数据,单独存储
// this.topNavMap[value.id] = list
// // 存储缓存
// ChannelViewModel.saveBottomDetailData(bottomNavDetail)
// })
// })
}
private setData(data: NavigationBodyDTO) {
Logger.debug(TAG, 'setData')
if (data && data.bottomNavList != null) {
Logger.info(TAG, `setData, bottomNav.length: ${data.bottomNavList.length}`);
// 使用filter方法移除name为'服务'的项
data.bottomNavList = data.bottomNavList.filter(item => item.name !== '服务');
this.bottomNavList = data.bottomNavList
}
}
}
\ No newline at end of file
... ...
import { NavigationBodyDTO, NavigationDetailDTO, } from 'wdBean';
import { Logger } from 'wdKit';
import { CacheData, ResponseDTO } from 'wdNetwork';
import { PageRepository } from '../repository/PageRepository';
const TAG = 'ChannelViewModel';
/**
* 首页底导、顶导相关
*/
export class ChannelViewModel {
/**
* 获取底导缓存数据
*/
async getBottomNavCacheData(): Promise<NavigationBodyDTO | null> {
Logger.info(TAG, `getBottomNavCacheData start`);
return new Promise<NavigationBodyDTO | null>((success) => {
CacheData.getLocalCacheData(CacheData.bottomCacheKey).then((data) => {
// Logger.debug(TAG, 'getBottomNavCacheData 333 ' + JSON.stringify(data));
if (data) {
let navBean = JSON.parse(CacheData.getNetworkData(data)) as NavigationBodyDTO
success(navBean)
} else {
success(null)
}
}).catch((err: object) => {
Logger.error(TAG, 'getBottomNavCacheData catch err: ' + JSON.stringify(err));
success(null)
})
});
}
/**
* 保存底导数据到缓存
*/
saveBottomData(data: NavigationBodyDTO) {
CacheData.saveCacheData(CacheData.bottomCacheKey, data, data.md5)
}
/**
* 获取底导详情(顶导)缓存数据
*/
getBottomNavDetailCacheData(id: number): Promise<NavigationDetailDTO | null> {
return new Promise<NavigationDetailDTO | null>((success) => {
CacheData.getLocalCacheData(CacheData.channelCacheDataKey + id).then((data) => {
if (data) {
let navBean = JSON.parse(CacheData.getNetworkData(data)) as NavigationDetailDTO
success(navBean)
} else {
success(null)
}
}).catch((err: object) => {
Logger.error(TAG, 'getBottomNavDetailCacheData catch err: ' + JSON.stringify(err));
success(null)
})
})
}
/**
* 保存底导详情数据到缓存
*/
saveBottomDetailData(data: NavigationDetailDTO) {
CacheData.saveCacheData(CacheData.channelCacheDataKey + data?.id, data, data.md5)
}
/**
* 获取底导接口数据
*/
async getBottomNavData(): Promise<NavigationBodyDTO> {
Logger.info(TAG, `getBottomNavData start`);
return this.getNavData();
}
/**
* 获取底导详情(顶导)接口数据
*/
async getBottomNavDetailData(id: number): Promise<NavigationDetailDTO> {
Logger.info(TAG, `getBottomNavDetailData start`);
return this.getNavDetailData(id);
}
private getNavData(): Promise<NavigationBodyDTO> {
return new Promise<NavigationBodyDTO>((success, error) => {
Logger.info(TAG, `getNavData start`);
PageRepository.fetchNavigationDataApi().then((navResDTO: ResponseDTO<NavigationBodyDTO>) => {
if (!navResDTO || !navResDTO.data) {
Logger.error(TAG, 'getNavData then navResDTO is empty');
error('navResDTO is empty');
return
}
if (navResDTO.code != 0) {
Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`);
error('navResDTO Response Code is failure');
return
}
// let navResStr = JSON.stringify(navResDTO);
Logger.info(TAG, "getNavData then,navResDTO.timestamp:" + navResDTO.timestamp);
navResDTO.data.md5 = navResDTO.meta?.md5 || ''
success(navResDTO.data);
}).catch((err: Error) => {
Logger.error(TAG, `fetchNavigationDataApi catch, error.name : ${err.name}, error.message:${err.message}`);
error(err);
})
})
}
private getNavDetailData(id: number): Promise<NavigationDetailDTO> {
return new Promise<NavigationDetailDTO>((success, error) => {
Logger.info(TAG, `getNavData start`);
PageRepository.fetchNavigationDetailDataApi(id).then((navResDTO: ResponseDTO<NavigationDetailDTO>) => {
if (!navResDTO || !navResDTO.data) {
Logger.error(TAG, 'getNavData then navResDTO is empty');
error('navResDTO is empty');
return
}
if (navResDTO.code != 0) {
Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`);
error('navResDTO Response Code is failure');
return
}
// let navResStr = JSON.stringify(navResDTO);
Logger.info(TAG, "getNavData then,navResDTO.timestamp:" + navResDTO.timestamp);
navResDTO.data.md5 = navResDTO.meta?.md5 || ''
success(navResDTO.data);
}).catch((err: Error) => {
Logger.error(TAG, `fetchNavigationDataApi catch, error.name : ${err.name}, error.message:${err.message}`);
error(err);
})
})
}
}
let channelViewModel = new ChannelViewModel();
export default channelViewModel as ChannelViewModel;
\ No newline at end of file
... ...
... ... @@ -22,11 +22,6 @@ import { PageRepository } from '../repository/PageRepository';
import { BaseViewModel } from './BaseViewModel';
const TAG = 'PageViewModel';
/**
* mock数据开关,默认关。
* mock数据是本地json数据,可自行修改内容(‘entry\src\main\resources\rawfile\’目录)
*/
const mock_switch = false;
/**
* 处理返回后的数据
... ... @@ -37,111 +32,10 @@ export class PageViewModel extends BaseViewModel {
}
/**
* get Nav Data from Resource .
*
* @return BottomNavBean[] Nav Data List
*/
async getBottomNavData(context: Context): Promise<NavigationBodyDTO> {
Logger.info(TAG, `getBottomNavData start`);
if (mock_switch) {
return this.getBottomNavDataMock(context);
}
return this.getNavData();
}
async getBottomNavDetailData(id: number): Promise<NavigationDetailDTO> {
Logger.info(TAG, `getBottomNavDetailData start`);
return this.getNavDetailData(id);
}
async getBottomNavDataMock(context: Context): Promise<NavigationBodyDTO> {
Logger.info(TAG, `getBottomNavDataMock start`);
let compRes: ResponseDTO<NavigationBodyDTO> | null =
await ResourcesUtils.getResourcesJson<ResponseDTO<NavigationBodyDTO>>(context, 'bottom_nav.json');
if (!compRes || !compRes.data) {
Logger.info(TAG, `getBottomNavDataMock compRes bottomNavList is empty`);
return {} as NavigationBodyDTO
}
Logger.info(TAG, `getBottomNavDataMock getResourcesJsonSync compRes : ${JSON.stringify(compRes)}`);
return compRes.data
}
private getNavData(): Promise<NavigationBodyDTO> {
return new Promise<NavigationBodyDTO>((success, error) => {
Logger.info(TAG, `getNavData start`);
PageRepository.fetchNavigationDataApi().then((navResDTO: ResponseDTO<NavigationBodyDTO>) => {
if (!navResDTO || !navResDTO.data) {
Logger.error(TAG, 'getNavData then navResDTO is empty');
error('navResDTO is empty');
return
}
if (navResDTO.code != 0) {
Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`);
error('navResDTO Response Code is failure');
return
}
// let navResStr = JSON.stringify(navResDTO);
Logger.info(TAG, "getNavData then,navResDTO.timestamp:" + navResDTO.timestamp);
success(navResDTO.data);
}).catch((err: Error) => {
Logger.error(TAG, `fetchNavigationDataApi catch, error.name : ${err.name}, error.message:${err.message}`);
error(err);
})
})
}
private getNavDetailData(id: number): Promise<NavigationDetailDTO> {
return new Promise<NavigationDetailDTO>((success, error) => {
Logger.info(TAG, `getNavData start`);
PageRepository.fetchNavigationDetailDataApi(id).then((navResDTO: ResponseDTO<NavigationDetailDTO>) => {
if (!navResDTO || !navResDTO.data) {
Logger.error(TAG, 'getNavData then navResDTO is empty');
error('navResDTO is empty');
return
}
if (navResDTO.code != 0) {
Logger.error(TAG, `getNavData then code:${navResDTO.code}, message:${navResDTO.message}`);
error('navResDTO Response Code is failure');
return
}
// let navResStr = JSON.stringify(navResDTO);
Logger.info(TAG, "getNavData then,navResDTO.timestamp:" + navResDTO.timestamp);
success(navResDTO.data);
}).catch((err: Error) => {
Logger.error(TAG, `fetchNavigationDataApi catch, error.name : ${err.name}, error.message:${err.message}`);
error(err);
})
})
}
/**
* Get PageDTO data.
*
* @return {GroupDTO} compRes.data
*/
private async getPageData1(currentPage: number, context: Context): Promise<PageDTO> {
if (currentPage > 1) {
// 加载更多,返回无数据
return {} as PageDTO
}
let compRes: ResponseDTO<PageDTO> | null =
await ResourcesUtils.getResourcesJson<ResponseDTO<PageDTO>>(context, 'comp_list0.json');
if (!compRes || !compRes.data) {
Logger.info(TAG, `getCompList compRes is empty`);
return {} as PageDTO
}
Logger.info(TAG, `getCompList getResourcesJson compRes : ${JSON.stringify(compRes)}`);
return compRes.data
}
/**
* 获取【早晚报】数据
*/
async getMorningEveningPaperData(pageId: string): Promise<MorningEveningPaperDTO> {
Logger.debug(TAG, 'getPageData pageId: ' + pageId);
// if (mock_switch) {
// return this.getPageData3(currentPage, context);
// }
return new Promise<MorningEveningPaperDTO>((success, error) => {
PageRepository.fetchMorningEveningPaperData(pageId)
... ... @@ -166,18 +60,6 @@ export class PageViewModel extends BaseViewModel {
})
}
private async getPageData2(context: Context): Promise<PageDTO> {
let compRes: ResponseDTO<PageDTO> | null =
await ResourcesUtils.getResourcesJson<ResponseDTO<PageDTO>>(context, 'comp_list2.json');
if (!compRes || !compRes.data) {
Logger.info(TAG, `getCompList compRes is empty`);
return {} as PageDTO
}
// router.push('')
Logger.info(TAG, `getCompList getResourcesJson compRes : ${JSON.stringify(compRes)}`);
return compRes.data
}
/**
* 获取页面楼层的组件信息
* @param pageModel
... ... @@ -309,36 +191,6 @@ export class PageViewModel extends BaseViewModel {
});
}
/**
* @deprecated
*/
private resetInteract(interact: InteractDataDTO[], compList: CompDTO[]) {
if (interact == null || interact.length == 0) {
return
}
interact.forEach((interactData) => {
let id = interactData.contentId;
outer: for (let i = 0; i < compList.length; i++) {
let comp = compList[i];
if (comp == null || comp.operDataList == null || comp.operDataList.length == 0) {
continue;
}
for (let j = 0; j < comp.operDataList.length; j++) {
let content = comp.operDataList[j];
if (content == null) {
continue;
}
if (id == content.objectId) {
content.interactData = interactData;
// TODO 测试代码,待删除
// content.interactData.likeNum = Math.floor(Math.random() * Math.floor(999));;
break outer;
}
}
}
})
}
private getInteractParams(compList: CompDTO[]): InteractParam {
if (compList == null || compList.length == 0) {
return {} as InteractParam;
... ... @@ -482,7 +334,6 @@ export class PageViewModel extends BaseViewModel {
})
})
}
}
... ...
... ... @@ -3,6 +3,7 @@ import { WDPushNotificationManager } from 'wdHwAbility/Index'
import { DeviceUtil,
EmitterEventId,
EmitterUtils,
KVStoreHelper,
Logger,
MpaasUtils, NetworkManager,
NetworkType,
... ... @@ -38,7 +39,8 @@ export class StartupManager {
// KV存储
SPHelper.init(context);
// KV存储(较大数据,value<4M)(首页接口数据缓存用到)
KVStoreHelper.init(context)
// 路由注册
registerRouter();
... ...