陈剑华

Merge remote-tracking branch 'origin/main'

# Conflicts:
#	sight_harmony/features/wdComponent/src/main/ets/components/CompParser.ets
Showing 37 changed files with 648 additions and 111 deletions
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="18" height="18" viewBox="0 0 18 18"><g><g><path d="M3.998507,2.688617622937622L6.59851,3.338617682937622C6.68754,3.360875682937622,6.75,3.440872682937622,6.75,3.532645682937622L6.75,15.870288682937622C6.75,16.000488682937622,6.62772,16.09588868293762,6.50149,16.064388682937622L3.901493,15.414388682937622C3.8124595,15.392088682937622,3.75,15.312088682937622,3.75,15.220288682937623L3.75,2.8826466829376223C3.75,2.752531882937622,3.872278,2.657060282937622,3.998507,2.688617622937622M11.49851,2.688617622937622L14.0985,3.338617682937622C14.1875,3.360875682937622,14.25,3.440872682937622,14.25,3.532645682937622L14.25,15.870288682937622C14.25,16.000488682937622,14.1277,16.09588868293762,14.0015,16.064388682937622L11.401489999999999,15.414388682937622C11.31246,15.392088682937622,11.25,15.312088682937622,11.25,15.220288682937623L11.25,2.8826466829376223C11.25,2.752531882937622,11.37228,2.657060282937622,11.49851,2.688617622937622" fill-rule="evenodd" fill="#ED2800" fill-opacity="1"/></g></g></svg>
\ No newline at end of file
... ...
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_21088_095014"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_21088_095014)"><g><path d="M5,3.3522614375L5,20.6458234375C5,20.8012234375,5.169594,20.8972234375,5.302899,20.8173234375L19.714199999999998,12.1705234375C19.843600000000002,12.0928434375,19.843600000000002,11.9052034375,19.714199999999998,11.8275234375L5.302899,3.1807634375C5.169594,3.1007804375,5,3.1968024375,5,3.3522614375" fill-rule="evenodd" fill="#ED2800" fill-opacity="1"/></g></g></svg>
\ No newline at end of file
... ...
... ... @@ -13,7 +13,7 @@ export class HttpUrlUtils {
*/
static readonly BOTTOM_NAV_PATH: string = "/api/rmrb-bff-display-zh/display/zh/c/bottomNavGroup";
/**
* 导详情接口
* 导详情接口
*/
static readonly BOTTOM_NAV_DETAIL_PATH: string = "/api/rmrb-bff-display-zh/display/zh/c/bottomNavGroup/detail";
/**
... ...
... ... @@ -101,3 +101,5 @@ export { viewBlogItemInsightIntentShare } from './src/main/ets/utils/InsightInte
export { CommentListDialogView } from './src/main/ets/components/comment/view/CommentListDialog';
export { CustomPullToRefresh } from './src/main/ets/components/reusable/CustomPullToRefresh';
export { MorningEveningViewModel } from './src/main/ets/viewmodel/MorningEveningViewModel'
\ No newline at end of file
... ...
... ... @@ -40,6 +40,10 @@ export struct FeedBackActivity {
@State pics: PhotoListBean[] = [this.addPic] as PhotoListBean[]
@State toastText:ResourceStr = ""
// @Provide bottomSafeHeight: number = AppStorage.get<number>('bottomSafeHeight') || 0
@Provide topSafeHeight: number = AppStorage.get<number>('topSafeHeight') || 0
dialogToast: CustomDialogController = new CustomDialogController({
builder: CustomToast({
bgColor:$r("app.color.color_B3000000"),
... ... @@ -60,6 +64,7 @@ export struct FeedBackActivity {
build() {
Column() {
Blank().height(`${this.topSafeHeight}px`)
//标题栏目
CustomTitleUI({ titleName: $r('app.string.feedback') })
Stack({ alignContent: Alignment.Bottom }) {
... ... @@ -285,7 +290,7 @@ export struct FeedBackActivity {
.height(CommonConstants.FULL_HEIGHT)
.scrollBar(BarState.Off)
.alignSelf(ItemAlign.Start)
.padding({ bottom: 44 })
.padding({ bottom: 64+64 })
Column(){
Text($r('app.string.submit'))
.textAlign(TextAlign.Center)
... ... @@ -301,10 +306,9 @@ export struct FeedBackActivity {
}
this.reportCommit()
})
.margin({bottom:64})
.margin({bottom:64+64})
}
}
// .margin({bottom:64})
}
.backgroundColor($r('app.color.color_fff'))
}
... ...
... ... @@ -27,6 +27,7 @@ import TrackingPageBrowseUtils from '../../utils/TrackingPageBrowseUtils'
import {TrackConstants,TrackParamConvert}from 'wdTracking/Index'
import { ColorUtils } from '../../utils/ColorUtils';
import { EmptyComponent,WDViewDefaultType } from '../view/EmptyComponent';
import { EmitterEventId, EmitterUtils } from 'wdKit/Index'
const TAG = 'MorningEveningPaperComponent';
... ... @@ -71,6 +72,7 @@ export struct MorningEveningPaperComponent {
@State bottomSafeHeight: number = 0;
@State isHasTopView: boolean = false;
@State scrollOffset: number = 0
@State currentStatus: number | string |undefined = 0;
private audioDataList: AudioDataList[] = []
private playerController: WDPlayerController = new WDPlayerController();
... ... @@ -182,6 +184,10 @@ export struct MorningEveningPaperComponent {
}
EmitterUtils.receiveEvent(EmitterEventId.AUDIO_CHANGE_STATUS, (val: number | string | undefined) => {
this.currentStatus = val
})
}
// 批量查询内容当前用户点赞、收藏状态评论个数
... ... @@ -338,7 +344,7 @@ export struct MorningEveningPaperComponent {
.height('100%')
.objectFit(ImageFit.Contain)
Image($r('app.media.ic_red_triangle'))
Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause_svg") : $r("app.media.icon_audio_playing_svg"))
.width(24)
.height(24)
.margin({ left: 10 })// .alignSelf(ItemAlign.Center)
... ...
... ... @@ -113,7 +113,7 @@ export struct TopNavigationComponentNew {
'middle': { 'anchor': '__container__', 'align': HorizontalAlign.Center },
'bottom': { 'anchor': '__container__', 'align': VerticalAlign.Bottom }
})
.onAnimationStart((curIndex: number, index: number)=>{
.onAnimationStart((curIndex: number, index: number) => {
Logger.info(TAG, `onAnimationStart ${curIndex} ${index}`);
if (curIndex === index) {
return
... ... @@ -233,7 +233,7 @@ export struct TopNavigationComponentNew {
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.None)
.padding({ left: 8, top: 6, right: 0 })
.padding({ left: 8, top:0, right: 0 })
.height($r('app.float.top_tab_bar_height'))
.backgroundColor(this.barBackgroundColor)
.onAreaChange((oldValue: Area, newValue: Area) => {
... ... @@ -278,13 +278,12 @@ export struct TopNavigationComponentNew {
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.None)
.height($r('app.float.top_tab_bar_height_common'))
.backgroundColor(this.barBackgroundColor)
.margin({ top: 10 })
.onAreaChange((oldValue: Area, newValue: Area) => {
let width = Number.parseFloat(newValue.width.toString())
this.tabsWidth = Number.isNaN(width) ? 0 : width
})
.height($r('app.float.top_tab_bar_height_common'))
.backgroundColor(this.barBackgroundColor)
.id('tabList')
.alignRules({
'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
... ... @@ -327,12 +326,13 @@ export struct TopNavigationComponentNew {
minWidth: $r('app.float.top_tab_item_min_width'),
maxWidth: $r('app.float.top_tab_item_max_width')
})
.height('100%')
// .backgroundColor(Color.Transparent)
.padding({
left: $r('app.float.top_tab_item_padding_horizontal'),
right: $r('app.float.top_tab_item_padding_horizontal'),
bottom: 2,
})
.justifyContent(FlexAlign.Center)
.id(`col_tabBar${index}`)
// .margin({ right: this.myChannelList.length === index + 1 ? 36 : 0 })
.onClick(() => {
... ... @@ -497,7 +497,7 @@ export struct TopNavigationComponentNew {
Logger.info(TAG, `currentTopNavSelectedIndex : ${this.currentTopNavSelectedIndex}、${this.currentBottomNavName}`);
// 顶部tab埋点
if(this.currentBottomNavName === '新闻') {
if (this.currentBottomNavName === '新闻') {
const tab = this.myChannelList[this.currentTopNavSelectedIndex]
Logger.info(TAG, `新闻tab埋点: ${JSON.stringify(tab)}`);
... ... @@ -507,7 +507,7 @@ export struct TopNavigationComponentNew {
"pageId": tab.pageId,
}
Tracking.event("home_page_tab_click ", params)
} else if(this.currentBottomNavName === '人民号') {
} else if (this.currentBottomNavName === '人民号') {
const tab = this.topNavList[this.currentTopNavSelectedIndex]
Logger.info(TAG, `人民号tab埋点: ${JSON.stringify(tab)}`);
... ... @@ -519,6 +519,7 @@ export struct TopNavigationComponentNew {
Tracking.event("People_account_page_tab_click", params)
}
}
onAutoRefresh() {
if (this.bottomNavIndex != this._currentNavIndex) {
return
... ... @@ -619,32 +620,32 @@ export struct TopNavigationComponentNew {
return null
}
private getTextInfo(index: number): Record<string, number> {
let strJson = getInspectorByKey(index.toString())
try {
let obj: Record<string, string> = JSON.parse(strJson)
let rectInfo: number[][] = JSON.parse('[' + obj.$rect + ']')
return { 'left': px2vp(rectInfo[0][0]), 'width': px2vp(rectInfo[1][0] - rectInfo[0][0]) }
} catch (error) {
return { 'left': 0, 'width': 0 }
}
}
private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
let nextIndex = index
if (index > 0 && event.currentOffset > 0) {
nextIndex--
} else if (index < 3 && event.currentOffset < 0) {
nextIndex++
}
let indexInfo = this.getTextInfo(index)
let nextIndexInfo = this.getTextInfo(nextIndex)
let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth)
let currentIndex = swipeRatio > 0.5 ? nextIndex : index // 页面滑动超过一半,tabBar切换到下一页。
let currentLeft = indexInfo.left + (nextIndexInfo.left - indexInfo.left) * swipeRatio
let currentWidth = indexInfo.width + (nextIndexInfo.width - indexInfo.width) * swipeRatio
return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth }
}
// private getTextInfo(index: number): Record<string, number> {
// let strJson = getInspectorByKey(index.toString())
// try {
// let obj: Record<string, string> = JSON.parse(strJson)
// let rectInfo: number[][] = JSON.parse('[' + obj.$rect + ']')
// return { 'left': px2vp(rectInfo[0][0]), 'width': px2vp(rectInfo[1][0] - rectInfo[0][0]) }
// } catch (error) {
// return { 'left': 0, 'width': 0 }
// }
// }
// private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
// let nextIndex = index
// if (index > 0 && event.currentOffset > 0) {
// nextIndex--
// } else if (index < 3 && event.currentOffset < 0) {
// nextIndex++
// }
// let indexInfo = this.getTextInfo(index)
// let nextIndexInfo = this.getTextInfo(nextIndex)
// let swipeRatio = Math.abs(event.currentOffset / this.tabsWidth)
// let currentIndex = swipeRatio > 0.5 ? nextIndex : index // 页面滑动超过一半,tabBar切换到下一页。
// let currentLeft = indexInfo.left + (nextIndexInfo.left - indexInfo.left) * swipeRatio
// let currentWidth = indexInfo.width + (nextIndexInfo.width - indexInfo.width) * swipeRatio
// return { 'index': currentIndex, 'left': currentLeft, 'width': currentWidth }
// }
private startAnimateTo(duration: number, leftMargin: number, width: number) {
animateTo({
... ...
... ... @@ -24,7 +24,7 @@ export struct PeopleShipHomeListComponent {
// 列表
else if (this.publishCount == 0) {
// 无数据展示
EmptyComponent({emptyType: 12}).height('100%')
EmptyComponent({emptyType: 12}).height('60%')
} else {
Column() {
Stack({ alignContent: Alignment.Top }){
... ...
... ... @@ -20,7 +20,7 @@ import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import ResponseCode from '@ohos.net.http';
const resourceMgs: resourceManager.ResourceManager = getContext(this).resourceManager;
// const resourceMgs: resourceManager.ResourceManager = getContext(this).resourceManager;
const PIXEL_MAP_SIZE_WIDTH: number = 40;
const PIXEL_MAP_SIZE_HEIGHT: number = 40;
... ... @@ -29,19 +29,19 @@ const PIXEL_MAP_SIZE_HEIGHT: number = 40;
* @param icon 图片地址,模拟数据存放于rawfile文件夹中
* @returns 图片转换的PixelMap对象
*/
export async function image2PixelMap(icon: string): Promise<image.PixelMap> {
// 读取rawfile文件夹下的文件
const rawFileDescriptor: resourceManager.RawFileDescriptor = resourceMgs.getRawFdSync(icon);
const imageSource: image.ImageSource = image.createImageSource(rawFileDescriptor);
// 通过ImageSource对象创建PixelMap对象,使用BGRA_8888格式,由4个字节表示一个像素
const pixelMap: Promise<PixelMap> = imageSource.createPixelMap({
editable: false,
desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
// 高性能知识点:经测试,将图片的宽和高设置为40像素时,既可以保证提取颜色的准确性,也可以保证计算颜色的速度。
desiredSize: { width: PIXEL_MAP_SIZE_WIDTH, height: PIXEL_MAP_SIZE_HEIGHT }
})
return pixelMap;
}
// export async function image2PixelMap(icon: string): Promise<image.PixelMap> {
// // 读取rawfile文件夹下的文件
// const rawFileDescriptor: resourceManager.RawFileDescriptor = resourceMgs.getRawFdSync(icon);
// const imageSource: image.ImageSource = image.createImageSource(rawFileDescriptor);
// // 通过ImageSource对象创建PixelMap对象,使用BGRA_8888格式,由4个字节表示一个像素
// const pixelMap: Promise<PixelMap> = imageSource.createPixelMap({
// editable: false,
// desiredPixelFormat: image.PixelMapFormat.BGRA_8888,
// // 高性能知识点:经测试,将图片的宽和高设置为40像素时,既可以保证提取颜色的准确性,也可以保证计算颜色的速度。
// desiredSize: { width: PIXEL_MAP_SIZE_WIDTH, height: PIXEL_MAP_SIZE_HEIGHT }
// })
// return pixelMap;
// }
/**
* 通过http的request方法从网络下载图片资源
... ...
... ... @@ -16,6 +16,7 @@ export class AudioSuspensionModel {
private url: string = ''
private expandWidth: number = vp2px(243)
private expandHeight: number = vp2px(60)
private initMoveX = vp2px(12)
// 窗口是否最小化
private isMinimize: SubscribedAbstractProperty<boolean> = AppStorage.link<boolean>('isMinimize')
constructor() {
... ... @@ -27,7 +28,7 @@ export class AudioSuspensionModel {
private initPlayerController() {
if(this.playerController === undefined) {
Logger.info(TAG, 'playerController undefined')
AppStorage.setOrCreate('playerController', new WDPlayerController());
AppStorage.setOrCreate('playerController', new WDPlayerController({loop: false}));
this.playerController = AppStorage.link<WDPlayerController>('playerController')
Logger.info(TAG, 'playerController create success')
this.playerController.get().onStatusChange = (status: number) => {
... ... @@ -42,8 +43,8 @@ export class AudioSuspensionModel {
* 配置音频地址
*/
public setPlayerUrl(url: string, srcTitle: string) {
// console.log(TAG,'this.url', this.url)
// console.log(TAG,'url', url)
/*console.log(TAG,'this.url', this.url)
console.log(TAG,'url', url)*/
if (this.url === url) {
this.isMinimize = AppStorage.link<boolean>('isMinimize')
console.log(TAG, 'this.isMinimize', this.isMinimize?.get())
... ... @@ -60,7 +61,7 @@ export class AudioSuspensionModel {
}
this.srcTitle = srcTitle
EmitterUtils.sendEvent(EmitterEventId.AUDIO_CHANGE_TITLe, this.srcTitle)
this.resizeWindow(this.expandWidth, this.expandHeight)
EmitterUtils.sendEvent(EmitterEventId.AUDIO_WINDOW_EXPAND, 1)
}
this.showWindow()
}
... ... @@ -99,9 +100,8 @@ export class AudioSuspensionModel {
console.info(TAG, 'floatWindowClass Succeeded in changing the window size.');
});
}
public moveWindow(y: number) {
this.floatWindowClass.get().moveWindowTo(0, vp2px(y), (err: BusinessError) => {
public moveWindow(y: number) {
this.floatWindowClass.get().moveWindowTo(this.initMoveX, vp2px(y), (err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
console.error('floatWindowClass Failed to move the window. Cause:' + JSON.stringify(err));
... ...
... ... @@ -6,6 +6,33 @@ import { PageRepository } from '../repository/PageRepository';
const TAG = 'MorningEveningViewModel'
export class MorningEveningViewModel {
static async getDailyPaperTopic(): Promise<PageInfoBean> {
return new Promise<PageInfoBean>((success, error) => {
Logger.info(TAG, `getDailyPaperTopic pageInfo start`);
PageRepository.fetchDailyPaperTopic()
.then((resDTO: ResponseDTO<PageInfoBean>) => {
if (!resDTO || !resDTO.data) {
Logger.error(TAG, 'getDailyPaperTopic then navResDTO is empty');
error('resDTO is empty');
return
}
if (resDTO.code != 0) {
Logger.error(TAG, `getDailyPaperTopic then code:${resDTO.code}, message:${resDTO.message}`);
error('resDTO Response Code is failure');
return
}
// let navResStr = JSON.stringify(navResDTO);
Logger.info(TAG, "getDailyPaperTopic then,navResDTO.timestamp:" + resDTO.timestamp);
success(resDTO.data);
})
.catch((err: Error) => {
Logger.error(TAG, `getDailyPaperTopic catch, error.name : ${err.name}, error.message:${err.message}`);
error(err);
})
})
}
static async getMorningEveningPageInfo(pageId: string): Promise<PageInfoBean> {
return new Promise<PageInfoBean>((success, error) => {
Logger.info(TAG, `getMorningEveningPageInfo pageInfo start`);
... ...
... ... @@ -55,6 +55,7 @@ export struct PlayerProgressView {
}
.width('100%')
.zIndex(2000)
.height(10)
.visibility(this.showLoading ? Visibility.Visible: Visibility.Hidden)
.margin({ bottom: 10 })
// .markAnchor({ x: 0, y: '100%' })
... ...
... ... @@ -7,13 +7,17 @@ import { TrackingPlay } from 'wdTracking/Index';
import { ParamType } from 'wdTracking/Index';
import { DateTimeUtils } from 'wdKit/Index';
interface obj {
loop: boolean
}
@Observed
export class WDPlayerController {
private initPromise: Promise<void>;
private avPlayer?: media.AVPlayer;
private duration: number = 0;
private status: number = PlayerConstants.STATUS_IDLE;
private loop: boolean = false;
private loop: boolean = true;
private url: string = '';
private surfaceId: string = ''; // 若播放音频,无需设置surfaceId
private playSpeed: number = 1;
... ... @@ -41,9 +45,12 @@ export class WDPlayerController {
constructor() {
constructor(obj?: obj) {
Logger.error("初始化")
this.initPromise = this.createAVPlayer();
if(obj?.loop === false) {
this.loop = false
}
}
/**
... ... @@ -103,6 +110,7 @@ export class WDPlayerController {
if (this.onCanplay) {
this.onCanplay()
}
this.avPlayer.loop = this.loop
break;
case AVPlayerStatus.PLAYING:
if(this.onLoaded) {
... ... @@ -122,9 +130,13 @@ export class WDPlayerController {
if (this.continue) {
this.continue();
} else {
this.duration = 0;
this.url = this.avPlayer.url || '';
this.avPlayer.reset();
if(this.loop) {
this.duration = 0;
this.url = this.avPlayer.url || '';
this.avPlayer.reset();
}
this.status = PlayerConstants.STATUS_COMPLETION;
this.watchStatus();
}
break;
case AVPlayerStatus.RELEASED:
... ... @@ -396,7 +408,7 @@ export class WDPlayerController {
watchStatus() {
console.log('watchStatus', this.status)
if(this.status == 1){
if(this.status == PlayerConstants.STATUS_START){
console.log('播放视频')
console.log('播放视频prepareTime',JSON.stringify(this.prepareTime))
console.log('播放视频pageName',JSON.stringify(this.pageName))
... ... @@ -404,7 +416,7 @@ export class WDPlayerController {
// 播放埋点
TrackingPlay.videoPositivePlay(Number(this.prepareTime),this.pageName, this.pageName, this.pageParam)
}
if(this.status == 2){
if(this.status == PlayerConstants.STATUS_COMPLETION){
let initDuration = Math.floor(Number(this.duration)/1000)
console.log('播放结束')
console.log('播放结束currentPlayTime',JSON.stringify(this.currentPlayTime))
... ...
export { WDShare } from './src/main/ets/WDShare'
export { DeepLinkUtil } from "./src/main/ets/utils/DeepLinkUtil"
\ No newline at end of file
... ...
import { ContentDetailDTO, ContentDTO } from 'wdBean/Index';
import { ContentDetailDTO, ContentDTO, FrontLinkObject } from 'wdBean/Index';
import { BreakpointSystem } from 'wdKit/Index';
import { ContentType } from 'wdRouter/Index';
... ... @@ -16,6 +16,10 @@ export class DeepLinkUtil {
return DeepLinkUtil.generate(Number(content.objectType), content.objectId +'', content.relId, content.linkUrl)
}
static generateDeepLinkWithFrontObjectLink(content: FrontLinkObject) {
return DeepLinkUtil.generate(Number(content.newsType), content.newsId +'', content.newsRelId + '', content.linkUrl)
}
private static generate(contentType: number, contentId?: string, relId?: string, link?: string): string {
let deeplink = DeepLinkUtil.DEEP_LINK_PREFIX
... ...
... ... @@ -20,6 +20,7 @@
"wdJsBridge": "file:../../commons/wdJsBridge",
"wdLogin": "file:../../features/wdLogin",
"wdTracking": "file:../../features/wdTracking",
"wdPlayer": "file:../../features/wdPlayer"
"wdPlayer": "file:../../features/wdPlayer",
"wdShare": "file:../../features/wdShare",
}
}
... ...
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
import { Logger, NetworkManager, SPHelper, StringUtils } from 'wdKit/Index';
import { BusinessError } from '@kit.BasicServicesKit';
import { FormDataType, NewspaperDataFetcher } from './NewspaperDataFetcher';
import { JSON } from '@kit.ArkTS';
import { FormNewspaperPaperType } from '../dailynewspaperwidget/common/NewspaperWidgetData';
import { HostEnum, HostManager, WDHttp } from 'wdNetwork/Index';
const TAG = "DailyNewspaperFormAbility"
export default class DailyNewspaperFormAbility extends FormExtensionAbility {
onAddForm(want: Want) {
Logger.debug(TAG, "onAddForm with " + JSON.stringify(want))
this.initApp()
if (want.parameters) {
let formId = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string
let isTempCard = want.parameters[formInfo.FormParam.TEMPORARY_KEY] as boolean
if (isTempCard === false) { // 如果为常态卡片,直接进行信息持久化
Logger.debug(TAG, "开始刷新数据");
NewspaperDataFetcher.refreshDailyPaper().then((data) => {
let formData = formBindingData.createFormBindingData(data);
formProvider.updateForm(formId, formData).catch((err: BusinessError) => {
Logger.debug(TAG, ` xFailed to updateForm. Code: ${err.code}, message: ${err.message}`);
});
})
}
}
let obj: FormDataType = {}
obj.paperType = FormNewspaperPaperType.unknown
let formData = formBindingData.createFormBindingData(obj);
return formData;
}
onCastToNormalForm(formId: string) {
// 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理
Logger.debug(TAG, `onCastToNormalForm, formId: ${formId}`);
}
onUpdateForm(formId: string) {
// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新
Logger.debug(TAG, 'onUpdateForm ' + formId);
NewspaperDataFetcher.refreshDailyPaper().then((data) => {
let formData = formBindingData.createFormBindingData(data);
formProvider.updateForm(formId, formData).catch((err: BusinessError) => {
Logger.debug(TAG, ` xFailed to updateForm. Code: ${err.code}, message: ${err.message}`);
});
})
}
onFormEvent(formId: string, message: string) {
// 若卡片支持触发事件,则需要重写该方法并实现对事件的触发
Logger.debug(TAG, 'onFormEvent:' +" formId =>" + formId + " message =>" + message);
}
onRemoveForm(formId: string) {
// 当对应的卡片删除时触发的回调,入参是被删除的卡片ID
Logger.debug(TAG, 'onRemoveForm');
}
// onConfigurationUpdate(config: Configuration) {
// // 当前formExtensionAbility存活时更新系统配置信息时触发的回调。
// // 需注意:formExtensionAbility创建后5秒内无操作将会被清理。
// Logger.debug(TAG, 'onConfigurationUpdate:' + JSON.stringify(config));
// }
onAcquireFormState(want: Want) {
// 卡片提供方接收查询卡片状态通知接口,默认返回卡片初始状态。
return formInfo.FormState.READY;
}
initApp() {
// KV存储
SPHelper.init(this.context);
// 网络模块
NetworkManager.getInstance().init()
// App环境
const spHostUrl = SPHelper.default.getSync('hostUrl', '') as string
if (StringUtils.isNotEmpty(spHostUrl)) {
HostManager.changeHost(spHostUrl as HostEnum)
}
Logger.debug(TAG, "App 网络 初始化")
WDHttp.initHttpHeader()
}
};
\ No newline at end of file
... ...
import { CompInfoBean, ContentDTO, PageInfoBean } from 'wdBean/Index';
import { MorningEveningViewModel } from 'wdComponent/Index';
import { Logger } from 'wdKit/Index';
import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork/Index';
import { DeepLinkUtil } from 'wdShare/Index'
import { FormNewspaperPaperType, FormNewspaperPaperInfo, FormNewspaperPaperContent } from "../dailynewspaperwidget/common/NewspaperWidgetData"
const TAG = "NewspaperDataFetcher"
export type FormDataType = Record<string, FormNewspaperPaperType | FormNewspaperPaperInfo | FormNewspaperPaperContent[]>
export class NewspaperDataFetcher {
public static async refreshDailyPaper(): Promise<FormDataType> {
return new Promise<FormDataType>(async (reslove, fail) => {
let data: FormDataType = { 'paperType': FormNewspaperPaperType.unknown }
data.paperInfo = { showLeftImage: false }
try {
let page: PageInfoBean = await MorningEveningViewModel.getDailyPaperTopic()
data.paperType = page.topicInfo?.frontFlag || FormNewspaperPaperType.unknown
let currentTime = new Date().getTime()
let compInfo = await MorningEveningViewModel.getMorningEveningCompInfo(
page.id,
page.groups[0]?.id,
currentTime + "",
page.topicInfo?.topicId
)
if (page.topicInfo.frontLinkObject) {
data.paperInfo.showLeftImage = true
data.paperInfo.leftImageUrl = page.topicInfo.frontLinkObject.coverUrl
data.paperInfo.leftTitle = page.topicInfo.frontLinkObject.title
data.paperInfo.leftDeepLink = DeepLinkUtil.generateDeepLinkWithFrontObjectLink(page.topicInfo.frontLinkObject)
}
let contents: ContentDTO[] = compInfo.compList[0].operDataList as ContentDTO[]
if (contents && contents.length) {
data.paperContents = contents.map((contentDTO) => {
let content : FormNewspaperPaperContent = {
title: contentDTO.newsTitle,
coverUrl: contentDTO.coverUrl,
deepLink: DeepLinkUtil.generateDeepLinkWithProgram(contentDTO)
}
return content
})
}
} catch (e) {
Logger.debug(TAG, "刷新早晚报数据失败" + JSON.stringify(e))
fail(e)
// reslove(NewspaperDataFetcher.fakeData())
return
}
Logger.debug(TAG, "refresh Data " + JSON.stringify(data))
reslove(data)
})
}
static fakeData(): FormDataType {
let data : FormNewspaperPaperContent = {
title: "标题标题标题标题标题标题标题标题",
coverUrl: "https://"
} as FormNewspaperPaperContent
return {
'paperType': FormNewspaperPaperType.unknown,
"paperInfo": {
showLeftImage: true,
leftTitle: "leftTitleleftTitleleftTitleleftTitleleftTitleleftTitle"
},
"paperContents": [data, data, data]
}
}
}
\ No newline at end of file
... ...
export namespace NewspaperWidgetCommon {
export enum JumpParam {
DeepLinkKey = "newspaper.widget.jump.deeplink",
FromNewspaperWidgetKey = "newspaper.widget.jump.fromNewspaperWidget"
}
export enum PosterCardAction {
ActionRouter = "router",
ActionCaller = "caller",
MainAbilityName = "EntryAbility"
}
}
\ No newline at end of file
... ...
export enum FormNewspaperPaperType {
unknown = 0,
morning = 1,
noon = 2,
evening = 3
}
export class FormNewspaperPaperInfo {
showLeftImage: boolean = false
leftImageUrl?: string
leftTitle?: string
leftDeepLink?: string
rightContentHasAnyImage?: boolean = false
}
export class FormNewspaperPaperContent {
title: string = ""
coverUrl?: string
deepLink: string = ""
}
... ...
import { FormNewspaperPaperType, FormNewspaperPaperInfo, FormNewspaperPaperContent } from "../common/NewspaperWidgetData"
import { FormTopComponent } from "./FormTopComponent"
import { NewspaperWidgetCommon } from "../common/NewspaperWidgetCommon"
const TAG = "DailyNewspaperWidgetCard"
let storageWidgetImageUpdate = new LocalStorage();
@Entry(storageWidgetImageUpdate)
@Component
struct DailyNewspaperWidgetCard {
@LocalStorageProp('paperType') paperType: FormNewspaperPaperType = FormNewspaperPaperType.unknown;
@LocalStorageProp('paperInfo') paperInfo: FormNewspaperPaperInfo = {} as FormNewspaperPaperInfo;
@LocalStorageProp('paperContents') paperContents: FormNewspaperPaperContent[] = [];
private DAILY_NEWSPAPER_DEEP_LINK = "rmrbapp://rmrb.app/openwith?type=topic&subType=moring_evening_news&pageId=&relId=&skipType=1"
build() {
Column() {
FormTopComponent({
paperType: this.paperType
})
.width("100%").height(36)
// .margin({top: 3})
.onClick(() => {
jumpWithDeepLink(this.DAILY_NEWSPAPER_DEEP_LINK, this)
})
Row() {
if (this.paperInfo.showLeftImage) {
this.leftImageView()
}
if (this.paperContents.length) {
this.listView()
} else {
EmptyView()
}
}.width("100%")
.layoutWeight(1)
}
}
@Builder leftImageView() {
Stack({ alignContent: Alignment.Bottom }) {
Image(this.paperInfo.leftImageUrl)
// Image($r("app.media.desktop_card_comp_place_holder_16_9"))
.alt($r("app.media.desktop_card_comp_place_holder_16_9"))
.objectFit(ImageFit.Cover)
.aspectRatio(87/116)
.autoResize(true)
.borderRadius(6)
.onClick(() => {
jumpWithDeepLink(this.paperInfo.leftDeepLink || "", this)
})
Text(this.paperInfo.leftTitle)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize(11)
.fontWeight(800)
.lineHeight(14)
.maxLines(2)
.fontColor(Color.White)
.padding({left: 4 + 4, bottom:6, right: 4 + 4})
}
.margin({left: 12, top: 2, bottom: 12})
// .backgroundColor(Color.Red)
.width(87)
}
@Builder listView() {
List() {
ForEach(this.paperContents, (item: FormNewspaperPaperContent, index: number) => {
ListItem() {
ContentCellView({content: item, index: index, hasImage: (item.coverUrl && item.coverUrl.length > 0 ? true : false)})
}
}, (item: FormNewspaperPaperContent, index) => index + JSON.stringify(item))
}
.divider(
{strokeWidth: 0.5,
color: "#f5f5f5",
startMargin: 0,
endMargin: 0})
.width("100%")
.margin({left: this.paperInfo.showLeftImage ? 8 : 12, top: 0, bottom: 12, right: 12})
.layoutWeight(1)
}
}
@Component
struct ContentCellView {
@Prop content: FormNewspaperPaperContent
private index : number = 0
private hasImage: boolean = false
build() {
Row() {
Text(this.content.title)
.maxLines((this.content.coverUrl && this.content.coverUrl.length > 0 ? 2 : 1))
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontSize(14)
.lineHeight(20)
.fontWeight(FontWeight.Medium)
.fontColor(Color.Black)
.layoutWeight(1)
// .backgroundColor(Color.Red)
.offset({y: this.hasImage && this.index == 0 ? -3 : 0})
.margin({
top: this.hasImage ? 0 : 4,
bottom: this.hasImage ? 0 : 6})
if (this.hasImage) {
Image(this.content.coverUrl)
// Image($r("app.media.desktop_card_comp_place_holder_3_4"))
.alt($r("app.media.desktop_card_comp_place_holder_3_4"))
.objectFit(ImageFit.Cover)
.height(40)
.aspectRatio(75/50)
.borderRadius(4)
.margin({left: 10, bottom: 8, top: this.index == 0 ? 2 : 8, right: 0})
.autoResize(true)
}
}
.justifyContent(FlexAlign.Start)
.onClick(() => {
jumpWithDeepLink(this.content.deepLink || "", this)
})
}
}
@Component
struct EmptyView {
build() {
Row() {
Image($r("app.media.desktop_card_empty_bg"))
.objectFit(ImageFit.Fill)
// .width("100%")
// .height("100%")
.margin({left: 12, bottom: 12, right: 12, top: 4})
}
.height("100%")
.width("100%")
// .backgroundColor(Color.Red)
}
}
function jumpWithDeepLink(deepLink: string, component: Object) {
console.log(TAG + "jumpWithDeepLink: " + deepLink)
if (deepLink.length == 0) {
return
}
const deepLinkKey: string = NewspaperWidgetCommon.JumpParam.DeepLinkKey
const fromDailyNewspaperKey: string = NewspaperWidgetCommon.JumpParam.FromNewspaperWidgetKey
postCardAction(component, {
action: NewspaperWidgetCommon.PosterCardAction.ActionRouter,
abilityName: NewspaperWidgetCommon.PosterCardAction.MainAbilityName,
params: {
deepLinkKey: deepLink,
fromDailyNewspaperKey: true
}
});
}
\ No newline at end of file
... ...
import { FormNewspaperPaperType } from "../common/NewspaperWidgetData"
@Component
export struct FormTopComponent {
@Prop paperType: FormNewspaperPaperType
build() {
Row() {
if (this.paperType == FormNewspaperPaperType.noon) {
Image($r("app.media.desktop_card_newspaper_noon"))
.fancy()
} else if (this.paperType == FormNewspaperPaperType.evening) {
Image($r("app.media.desktop_card_newspaper_evening"))
.fancy()
} else {
Image($r("app.media.desktop_card_newspaper_moring"))
.fancy()
}
Image($r("app.media.desktop_card_peopledaily_logo"))
.width(213).height(18)
.offset({right: -10})
}
.justifyContent(FlexAlign.SpaceBetween)
.alignItems(VerticalAlign.Center)
.width("100%").height("100%")
}
}
@Extend(Image) function fancy() {
.width(58)
.height(20)
.margin({left: 12})
}
\ No newline at end of file
... ...
... ... @@ -57,8 +57,9 @@ export default class EntryAbility extends UIAbility {
AppStorage.setOrCreate('topSafeHeight', topSafeHeight);
AppStorage.setOrCreate('windowWidth', width);
AppStorage.setOrCreate('windowHeight', height);
// 音频悬浮窗初始移动位置604为ui高度
let initMoveY = vp2px(604)
// 音频悬浮窗初始移动位置604为ui高度, 下面的初始位置根据mate60 pro手动调整
let initMoveY = vp2px(576)
let initMoveX = vp2px(12)
this.onWindowSetup(windowClass)
... ... @@ -81,7 +82,7 @@ export default class EntryAbility extends UIAbility {
floatWindowClass = data;
AppStorage.setOrCreate('floatWindowClass', floatWindowClass);
// 2.悬浮窗窗口创建成功后,设置悬浮窗的位置、大小及相关属性等。
floatWindowClass.moveWindowTo(0, initMoveY, (err: BusinessError) => {
floatWindowClass.moveWindowTo(initMoveX, initMoveY, (err: BusinessError) => {
let errCode: number = err.code;
if (errCode) {
Logger.error('floatWindowClass Failed to move the window. Cause:' + JSON.stringify(err));
... ...
... ... @@ -40,11 +40,11 @@ struct Index {
EmitterUtils.receiveEvent(EmitterEventId.AUDIO_CHANGE_STATUS, (val: number | string | undefined) => {
// val 2 pause
if(val === 2) {
console.log(TAG,'this.currentStatus 2 ', val)
if(val === PlayerConstants.STATUS_PAUSE || val === PlayerConstants.STATUS_COMPLETION) {
console.log(TAG,'AUDIO_CHANGE_STATUS this.currentStatus 2 ', val)
lottie.pause(this.name)
} else if(val === 1) {
console.log(TAG,'this.currentStatus 1 ', val)
} else if(val === PlayerConstants.STATUS_START) {
console.log(TAG,'AUDIO_CHANGE_STATUS this.currentStatus 1 ', val)
lottie.play(this.name)
}
this.currentStatus = val
... ... @@ -76,7 +76,7 @@ struct Index {
build() {
Stack({ alignContent: Alignment.End }) {
if(this.isExpand) {
Stack({ alignContent: Alignment.End }) {
Column() { //标题 时间 进度条
Marquee({
start: true,
... ... @@ -89,6 +89,8 @@ struct Index {
.height(20)
.fontColor('#222222')
.fontSize(14)
.fontFamily('PingFang SC-Medium')
.fontWeight(500)
.alignSelf(ItemAlign.Start)
.onStart(() => {
console.info('Marquee animation complete onStart')
... ... @@ -129,7 +131,7 @@ struct Index {
.justifyContent(FlexAlign.Start)
Row() {
Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause") : $r("app.media.icon_audio_playing"))
Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause_svg") : $r("app.media.icon_audio_playing_svg"))
.objectFit(ImageFit.Contain)
.width(24)
.height(24)
... ... @@ -156,21 +158,23 @@ struct Index {
}
.width(80)
.height(60)
} else {
Row() {
LottieView({
name: this.name,
path: "lottie/audio_animation_playing.json",
lottieWidth: 24,
lottieHeight: 24,
autoplay: false,
loop: true
})
}
.justifyContent(FlexAlign.Center)
.width(60)
.height(60)
}
.visibility(this.isExpand ? Visibility.Visible : Visibility.Hidden)
Row() {
LottieView({
name: this.name,
path: "lottie/audio_animation_playing.json",
lottieWidth: 24,
lottieHeight: 24,
autoplay: false,
loop: true
})
}
.justifyContent(FlexAlign.Center)
.width(60)
.height(60)
.visibility(!this.isExpand ? Visibility.Visible : Visibility.Hidden)
}
.parallelGesture(
GestureGroup(GestureMode.Parallel,
... ...
import { BottomNavi, CommonConstants, DisplayDirection } from 'wdConstant';
import { BottomNavDTO, NavigationBodyDTO, NavigationDetailDTO, TopNavDTO } from 'wdBean';
import { EmitterEventId, EmitterUtils, Logger, StringUtils } from 'wdKit';
import { BottomNavi, DisplayDirection } from 'wdConstant';
import { BottomNavDTO, NavigationBodyDTO, TopNavDTO } from 'wdBean';
import { EmitterEventId, EmitterUtils, Logger } from 'wdKit';
import { HttpUtils } from 'wdNetwork/Index';
import HomeChannelUtils, { AssignChannelParam } from 'wdRouter/Index';
import { MinePageComponent } from 'wdComponent/src/main/ets/components/page/MinePageComponent';
import { CompUtils, TopNavigationComponentNew } from 'wdComponent/Index';
import { VideoChannelPage } from './VideoChannelPage';
import ChannelViewModel from 'wdComponent/src/main/ets/viewmodel/ChannelViewModel';
import { ALL, ImageKnifeComponent, ImageKnifeOption, NONE } from '@ohos/imageknife';
import { ALL, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife';
import { ParamType, Tracking } from 'wdTracking/Index';
const TAG = 'BottomNavigationComponent';
... ... @@ -102,7 +102,6 @@ export struct BottomNavigationComponent {
}
.tabBar(this.tabBarBuilder(navItem, index))
// .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
});
}
... ...
... ... @@ -125,7 +125,6 @@ export struct VideoChannelPage {
}, (item: TopNavDTO) => item.channelId + '')
}
.width('100%')
.justifyContent(FlexAlign.Center)
// 搜索按钮
... ... @@ -182,7 +181,7 @@ export struct VideoChannelPage {
channelId: item.channelId + '',
autoRefresh: this.autoRefresh
})
.padding({ top: px2vp(this.topSafeHeight) + 55 })
.padding({ top: px2vp(this.topSafeHeight) + 44 })
.backgroundColor(Color.White)
}
}, (item: TopNavDTO) => item.channelId + '')
... ...
... ... @@ -15,7 +15,8 @@
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility", // 这里不能改动,和后台推送有绑定
"name": "EntryAbility",
// 这里不能改动,和后台推送有绑定
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:app_icon_layer",
... ... @@ -32,20 +33,24 @@
"action.system.home",
"com.test.pushaction"
],
"uris" : [{
"scheme": 'rmrbapp',
"host": 'rmrb.app',
'port': '8080',
"path": 'openwith'
}]
"uris": [
{
"scheme": 'rmrbapp',
"host": 'rmrb.app',
'port': '8080',
"path": 'openwith'
}
]
}
]
}
],
"metadata": [{
"name": "client_id",
"value": "110737325"
}],
"metadata": [
{
"name": "client_id",
"value": "110737325"
}
],
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
... ... @@ -100,6 +105,22 @@
{
"name": "ohos.permission.INTERNET"
},
],
"extensionAbilities": [
{
"name": "DailyNewspaperFormAbility",
"srcEntry": "./ets/dailynewspaperformability/DailyNewspaperFormAbility.ets",
"label": "$string:DailyNewspaperFormAbility_label",
"description": "$string:DailyNewspaperFormAbility_desc",
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
],
}
]
}
}
\ No newline at end of file
... ...
... ... @@ -63,6 +63,22 @@
{
"name": "reason_read_write_media",
"value": "user_grant"
},
{
"name": "DailyNewspaperFormAbility_desc",
"value": "早晚报卡片"
},
{
"name": "DailyNewspaperFormAbility_label",
"value": "早晚报卡片"
},
{
"name": "DailyNewspaperWidget_desc",
"value": "有品质的新闻"
},
{
"name": "DailyNewspaperWidget_display_name",
"value": "早晚报"
}
]
}
\ No newline at end of file
... ...
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="316" height="116" viewBox="0 0 316 116"><g><g><rect x="0" y="7" width="214" height="14" rx="0" fill="#F5F5F5" fill-opacity="1"/></g><g><rect x="0" y="73" width="214" height="14" rx="0" fill="#F5F5F5" fill-opacity="1"/></g><g><rect x="0" y="29" width="150" height="14" rx="0" fill="#F5F5F5" fill-opacity="1"/></g><g><rect x="0" y="95" width="150" height="14" rx="0" fill="#F5F5F5" fill-opacity="1"/></g><g><g><rect x="241" y="0" width="75" height="50" rx="4" fill="#F5F5F5" fill-opacity="1"/></g></g><g><g><rect x="241" y="66" width="75" height="50" rx="4" fill="#F5F5F5" fill-opacity="1"/></g></g><g><line x1="0" y1="57.75" x2="316.0000305175781" y2="57.75" fill-opacity="0" stroke-opacity="1" stroke="#EDEDED" fill="none" stroke-width="0.5"/></g></g></svg>
\ No newline at end of file
... ...
{
"forms": [
{
"name": "DailyNewspaperWidget",
"displayName": "$string:DailyNewspaperWidget_display_name",
"description": "$string:DailyNewspaperWidget_desc",
"src": "./ets/dailynewspaperwidget/pages/DailyNewspaperWidgetCard.ets",
"uiSyntax": "arkts",
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "light",
"isDynamic": true,
"isDefault": true,
"updateEnabled": true,
"scheduledUpdateTime": "10:30",
"updateDuration": 1,
"defaultDimension": "2*4",
"supportDimensions": [
"2*4"
]
}
]
}
\ No newline at end of file
... ...