Showing
28 changed files
with
542 additions
and
26 deletions
| 1 | +<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> |
| 1 | +<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> |
| @@ -101,3 +101,5 @@ export { viewBlogItemInsightIntentShare } from './src/main/ets/utils/InsightInte | @@ -101,3 +101,5 @@ export { viewBlogItemInsightIntentShare } from './src/main/ets/utils/InsightInte | ||
| 101 | export { CommentListDialogView } from './src/main/ets/components/comment/view/CommentListDialog'; | 101 | export { CommentListDialogView } from './src/main/ets/components/comment/view/CommentListDialog'; |
| 102 | 102 | ||
| 103 | export { CustomPullToRefresh } from './src/main/ets/components/reusable/CustomPullToRefresh'; | 103 | export { CustomPullToRefresh } from './src/main/ets/components/reusable/CustomPullToRefresh'; |
| 104 | + | ||
| 105 | +export { MorningEveningViewModel } from './src/main/ets/viewmodel/MorningEveningViewModel' |
| @@ -40,6 +40,10 @@ export struct FeedBackActivity { | @@ -40,6 +40,10 @@ export struct FeedBackActivity { | ||
| 40 | @State pics: PhotoListBean[] = [this.addPic] as PhotoListBean[] | 40 | @State pics: PhotoListBean[] = [this.addPic] as PhotoListBean[] |
| 41 | 41 | ||
| 42 | @State toastText:ResourceStr = "" | 42 | @State toastText:ResourceStr = "" |
| 43 | + | ||
| 44 | + // @Provide bottomSafeHeight: number = AppStorage.get<number>('bottomSafeHeight') || 0 | ||
| 45 | + @Provide topSafeHeight: number = AppStorage.get<number>('topSafeHeight') || 0 | ||
| 46 | + | ||
| 43 | dialogToast: CustomDialogController = new CustomDialogController({ | 47 | dialogToast: CustomDialogController = new CustomDialogController({ |
| 44 | builder: CustomToast({ | 48 | builder: CustomToast({ |
| 45 | bgColor:$r("app.color.color_B3000000"), | 49 | bgColor:$r("app.color.color_B3000000"), |
| @@ -60,6 +64,7 @@ export struct FeedBackActivity { | @@ -60,6 +64,7 @@ export struct FeedBackActivity { | ||
| 60 | 64 | ||
| 61 | build() { | 65 | build() { |
| 62 | Column() { | 66 | Column() { |
| 67 | + Blank().height(`${this.topSafeHeight}px`) | ||
| 63 | //标题栏目 | 68 | //标题栏目 |
| 64 | CustomTitleUI({ titleName: $r('app.string.feedback') }) | 69 | CustomTitleUI({ titleName: $r('app.string.feedback') }) |
| 65 | Stack({ alignContent: Alignment.Bottom }) { | 70 | Stack({ alignContent: Alignment.Bottom }) { |
| @@ -285,7 +290,7 @@ export struct FeedBackActivity { | @@ -285,7 +290,7 @@ export struct FeedBackActivity { | ||
| 285 | .height(CommonConstants.FULL_HEIGHT) | 290 | .height(CommonConstants.FULL_HEIGHT) |
| 286 | .scrollBar(BarState.Off) | 291 | .scrollBar(BarState.Off) |
| 287 | .alignSelf(ItemAlign.Start) | 292 | .alignSelf(ItemAlign.Start) |
| 288 | - .padding({ bottom: 44 }) | 293 | + .padding({ bottom: 64+64 }) |
| 289 | Column(){ | 294 | Column(){ |
| 290 | Text($r('app.string.submit')) | 295 | Text($r('app.string.submit')) |
| 291 | .textAlign(TextAlign.Center) | 296 | .textAlign(TextAlign.Center) |
| @@ -301,10 +306,9 @@ export struct FeedBackActivity { | @@ -301,10 +306,9 @@ export struct FeedBackActivity { | ||
| 301 | } | 306 | } |
| 302 | this.reportCommit() | 307 | this.reportCommit() |
| 303 | }) | 308 | }) |
| 304 | - .margin({bottom:64}) | 309 | + .margin({bottom:64+64}) |
| 305 | } | 310 | } |
| 306 | } | 311 | } |
| 307 | - // .margin({bottom:64}) | ||
| 308 | } | 312 | } |
| 309 | .backgroundColor($r('app.color.color_fff')) | 313 | .backgroundColor($r('app.color.color_fff')) |
| 310 | } | 314 | } |
| @@ -344,7 +344,7 @@ export struct MorningEveningPaperComponent { | @@ -344,7 +344,7 @@ export struct MorningEveningPaperComponent { | ||
| 344 | .height('100%') | 344 | .height('100%') |
| 345 | .objectFit(ImageFit.Contain) | 345 | .objectFit(ImageFit.Contain) |
| 346 | 346 | ||
| 347 | - Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause") : $r("app.media.icon_audio_playing")) | 347 | + Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause_svg") : $r("app.media.icon_audio_playing_svg")) |
| 348 | .width(24) | 348 | .width(24) |
| 349 | .height(24) | 349 | .height(24) |
| 350 | .margin({ left: 10 })// .alignSelf(ItemAlign.Center) | 350 | .margin({ left: 10 })// .alignSelf(ItemAlign.Center) |
| @@ -20,7 +20,7 @@ import { http } from '@kit.NetworkKit'; | @@ -20,7 +20,7 @@ import { http } from '@kit.NetworkKit'; | ||
| 20 | import { BusinessError } from '@kit.BasicServicesKit'; | 20 | import { BusinessError } from '@kit.BasicServicesKit'; |
| 21 | import ResponseCode from '@ohos.net.http'; | 21 | import ResponseCode from '@ohos.net.http'; |
| 22 | 22 | ||
| 23 | -const resourceMgs: resourceManager.ResourceManager = getContext(this).resourceManager; | 23 | +// const resourceMgs: resourceManager.ResourceManager = getContext(this).resourceManager; |
| 24 | const PIXEL_MAP_SIZE_WIDTH: number = 40; | 24 | const PIXEL_MAP_SIZE_WIDTH: number = 40; |
| 25 | const PIXEL_MAP_SIZE_HEIGHT: number = 40; | 25 | const PIXEL_MAP_SIZE_HEIGHT: number = 40; |
| 26 | 26 | ||
| @@ -29,19 +29,19 @@ const PIXEL_MAP_SIZE_HEIGHT: number = 40; | @@ -29,19 +29,19 @@ const PIXEL_MAP_SIZE_HEIGHT: number = 40; | ||
| 29 | * @param icon 图片地址,模拟数据存放于rawfile文件夹中 | 29 | * @param icon 图片地址,模拟数据存放于rawfile文件夹中 |
| 30 | * @returns 图片转换的PixelMap对象 | 30 | * @returns 图片转换的PixelMap对象 |
| 31 | */ | 31 | */ |
| 32 | -export async function image2PixelMap(icon: string): Promise<image.PixelMap> { | ||
| 33 | - // 读取rawfile文件夹下的文件 | ||
| 34 | - const rawFileDescriptor: resourceManager.RawFileDescriptor = resourceMgs.getRawFdSync(icon); | ||
| 35 | - const imageSource: image.ImageSource = image.createImageSource(rawFileDescriptor); | ||
| 36 | - // 通过ImageSource对象创建PixelMap对象,使用BGRA_8888格式,由4个字节表示一个像素 | ||
| 37 | - const pixelMap: Promise<PixelMap> = imageSource.createPixelMap({ | ||
| 38 | - editable: false, | ||
| 39 | - desiredPixelFormat: image.PixelMapFormat.BGRA_8888, | ||
| 40 | - // 高性能知识点:经测试,将图片的宽和高设置为40像素时,既可以保证提取颜色的准确性,也可以保证计算颜色的速度。 | ||
| 41 | - desiredSize: { width: PIXEL_MAP_SIZE_WIDTH, height: PIXEL_MAP_SIZE_HEIGHT } | ||
| 42 | - }) | ||
| 43 | - return pixelMap; | ||
| 44 | -} | 32 | +// export async function image2PixelMap(icon: string): Promise<image.PixelMap> { |
| 33 | +// // 读取rawfile文件夹下的文件 | ||
| 34 | +// const rawFileDescriptor: resourceManager.RawFileDescriptor = resourceMgs.getRawFdSync(icon); | ||
| 35 | +// const imageSource: image.ImageSource = image.createImageSource(rawFileDescriptor); | ||
| 36 | +// // 通过ImageSource对象创建PixelMap对象,使用BGRA_8888格式,由4个字节表示一个像素 | ||
| 37 | +// const pixelMap: Promise<PixelMap> = imageSource.createPixelMap({ | ||
| 38 | +// editable: false, | ||
| 39 | +// desiredPixelFormat: image.PixelMapFormat.BGRA_8888, | ||
| 40 | +// // 高性能知识点:经测试,将图片的宽和高设置为40像素时,既可以保证提取颜色的准确性,也可以保证计算颜色的速度。 | ||
| 41 | +// desiredSize: { width: PIXEL_MAP_SIZE_WIDTH, height: PIXEL_MAP_SIZE_HEIGHT } | ||
| 42 | +// }) | ||
| 43 | +// return pixelMap; | ||
| 44 | +// } | ||
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| 47 | * 通过http的request方法从网络下载图片资源 | 47 | * 通过http的request方法从网络下载图片资源 |
| @@ -6,6 +6,33 @@ import { PageRepository } from '../repository/PageRepository'; | @@ -6,6 +6,33 @@ import { PageRepository } from '../repository/PageRepository'; | ||
| 6 | const TAG = 'MorningEveningViewModel' | 6 | const TAG = 'MorningEveningViewModel' |
| 7 | 7 | ||
| 8 | export class MorningEveningViewModel { | 8 | export class MorningEveningViewModel { |
| 9 | + | ||
| 10 | + static async getDailyPaperTopic(): Promise<PageInfoBean> { | ||
| 11 | + return new Promise<PageInfoBean>((success, error) => { | ||
| 12 | + Logger.info(TAG, `getDailyPaperTopic pageInfo start`); | ||
| 13 | + PageRepository.fetchDailyPaperTopic() | ||
| 14 | + .then((resDTO: ResponseDTO<PageInfoBean>) => { | ||
| 15 | + if (!resDTO || !resDTO.data) { | ||
| 16 | + Logger.error(TAG, 'getDailyPaperTopic then navResDTO is empty'); | ||
| 17 | + error('resDTO is empty'); | ||
| 18 | + return | ||
| 19 | + } | ||
| 20 | + if (resDTO.code != 0) { | ||
| 21 | + Logger.error(TAG, `getDailyPaperTopic then code:${resDTO.code}, message:${resDTO.message}`); | ||
| 22 | + error('resDTO Response Code is failure'); | ||
| 23 | + return | ||
| 24 | + } | ||
| 25 | + // let navResStr = JSON.stringify(navResDTO); | ||
| 26 | + Logger.info(TAG, "getDailyPaperTopic then,navResDTO.timestamp:" + resDTO.timestamp); | ||
| 27 | + success(resDTO.data); | ||
| 28 | + }) | ||
| 29 | + .catch((err: Error) => { | ||
| 30 | + Logger.error(TAG, `getDailyPaperTopic catch, error.name : ${err.name}, error.message:${err.message}`); | ||
| 31 | + error(err); | ||
| 32 | + }) | ||
| 33 | + }) | ||
| 34 | + } | ||
| 35 | + | ||
| 9 | static async getMorningEveningPageInfo(pageId: string): Promise<PageInfoBean> { | 36 | static async getMorningEveningPageInfo(pageId: string): Promise<PageInfoBean> { |
| 10 | return new Promise<PageInfoBean>((success, error) => { | 37 | return new Promise<PageInfoBean>((success, error) => { |
| 11 | Logger.info(TAG, `getMorningEveningPageInfo pageInfo start`); | 38 | Logger.info(TAG, `getMorningEveningPageInfo pageInfo start`); |
| 1 | -import { ContentDetailDTO, ContentDTO } from 'wdBean/Index'; | 1 | +import { ContentDetailDTO, ContentDTO, FrontLinkObject } from 'wdBean/Index'; |
| 2 | import { BreakpointSystem } from 'wdKit/Index'; | 2 | import { BreakpointSystem } from 'wdKit/Index'; |
| 3 | import { ContentType } from 'wdRouter/Index'; | 3 | import { ContentType } from 'wdRouter/Index'; |
| 4 | 4 | ||
| @@ -16,6 +16,10 @@ export class DeepLinkUtil { | @@ -16,6 +16,10 @@ export class DeepLinkUtil { | ||
| 16 | return DeepLinkUtil.generate(Number(content.objectType), content.objectId +'', content.relId, content.linkUrl) | 16 | return DeepLinkUtil.generate(Number(content.objectType), content.objectId +'', content.relId, content.linkUrl) |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | + static generateDeepLinkWithFrontObjectLink(content: FrontLinkObject) { | ||
| 20 | + return DeepLinkUtil.generate(Number(content.newsType), content.newsId +'', content.newsRelId + '', content.linkUrl) | ||
| 21 | + } | ||
| 22 | + | ||
| 19 | private static generate(contentType: number, contentId?: string, relId?: string, link?: string): string { | 23 | private static generate(contentType: number, contentId?: string, relId?: string, link?: string): string { |
| 20 | let deeplink = DeepLinkUtil.DEEP_LINK_PREFIX | 24 | let deeplink = DeepLinkUtil.DEEP_LINK_PREFIX |
| 21 | 25 |
| @@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
| 20 | "wdJsBridge": "file:../../commons/wdJsBridge", | 20 | "wdJsBridge": "file:../../commons/wdJsBridge", |
| 21 | "wdLogin": "file:../../features/wdLogin", | 21 | "wdLogin": "file:../../features/wdLogin", |
| 22 | "wdTracking": "file:../../features/wdTracking", | 22 | "wdTracking": "file:../../features/wdTracking", |
| 23 | - "wdPlayer": "file:../../features/wdPlayer" | 23 | + "wdPlayer": "file:../../features/wdPlayer", |
| 24 | + "wdShare": "file:../../features/wdShare", | ||
| 24 | } | 25 | } |
| 25 | } | 26 | } |
sight_harmony/products/phone/src/main/ets/dailynewspaperformability/DailyNewspaperFormAbility.ets
0 → 100644
| 1 | +import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit'; | ||
| 2 | +import { Want } from '@kit.AbilityKit'; | ||
| 3 | +import { Logger, NetworkManager, SPHelper, StringUtils } from 'wdKit/Index'; | ||
| 4 | +import { BusinessError } from '@kit.BasicServicesKit'; | ||
| 5 | +import { FormDataType, NewspaperDataFetcher } from './NewspaperDataFetcher'; | ||
| 6 | +import { JSON } from '@kit.ArkTS'; | ||
| 7 | +import { FormNewspaperPaperType } from '../dailynewspaperwidget/common/NewspaperWidgetData'; | ||
| 8 | +import { HostEnum, HostManager, WDHttp } from 'wdNetwork/Index'; | ||
| 9 | + | ||
| 10 | +const TAG = "DailyNewspaperFormAbility" | ||
| 11 | + | ||
| 12 | +export default class DailyNewspaperFormAbility extends FormExtensionAbility { | ||
| 13 | + onAddForm(want: Want) { | ||
| 14 | + Logger.debug(TAG, "onAddForm with " + JSON.stringify(want)) | ||
| 15 | + | ||
| 16 | + this.initApp() | ||
| 17 | + | ||
| 18 | + if (want.parameters) { | ||
| 19 | + let formId = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string | ||
| 20 | + let isTempCard = want.parameters[formInfo.FormParam.TEMPORARY_KEY] as boolean | ||
| 21 | + if (isTempCard === false) { // 如果为常态卡片,直接进行信息持久化 | ||
| 22 | + | ||
| 23 | + Logger.debug(TAG, "开始刷新数据"); | ||
| 24 | + NewspaperDataFetcher.refreshDailyPaper().then((data) => { | ||
| 25 | + | ||
| 26 | + let formData = formBindingData.createFormBindingData(data); | ||
| 27 | + formProvider.updateForm(formId, formData).catch((err: BusinessError) => { | ||
| 28 | + Logger.debug(TAG, ` xFailed to updateForm. Code: ${err.code}, message: ${err.message}`); | ||
| 29 | + }); | ||
| 30 | + }) | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + let obj: FormDataType = {} | ||
| 35 | + obj.paperType = FormNewspaperPaperType.unknown | ||
| 36 | + let formData = formBindingData.createFormBindingData(obj); | ||
| 37 | + return formData; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + onCastToNormalForm(formId: string) { | ||
| 41 | + // 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理 | ||
| 42 | + Logger.debug(TAG, `onCastToNormalForm, formId: ${formId}`); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + onUpdateForm(formId: string) { | ||
| 46 | + // 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新 | ||
| 47 | + Logger.debug(TAG, 'onUpdateForm ' + formId); | ||
| 48 | + NewspaperDataFetcher.refreshDailyPaper().then((data) => { | ||
| 49 | + | ||
| 50 | + let formData = formBindingData.createFormBindingData(data); | ||
| 51 | + formProvider.updateForm(formId, formData).catch((err: BusinessError) => { | ||
| 52 | + Logger.debug(TAG, ` xFailed to updateForm. Code: ${err.code}, message: ${err.message}`); | ||
| 53 | + }); | ||
| 54 | + }) | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + onFormEvent(formId: string, message: string) { | ||
| 58 | + // 若卡片支持触发事件,则需要重写该方法并实现对事件的触发 | ||
| 59 | + Logger.debug(TAG, 'onFormEvent:' +" formId =>" + formId + " message =>" + message); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + onRemoveForm(formId: string) { | ||
| 63 | + // 当对应的卡片删除时触发的回调,入参是被删除的卡片ID | ||
| 64 | + Logger.debug(TAG, 'onRemoveForm'); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + // onConfigurationUpdate(config: Configuration) { | ||
| 68 | + // // 当前formExtensionAbility存活时更新系统配置信息时触发的回调。 | ||
| 69 | + // // 需注意:formExtensionAbility创建后5秒内无操作将会被清理。 | ||
| 70 | + // Logger.debug(TAG, 'onConfigurationUpdate:' + JSON.stringify(config)); | ||
| 71 | + // } | ||
| 72 | + | ||
| 73 | + onAcquireFormState(want: Want) { | ||
| 74 | + // 卡片提供方接收查询卡片状态通知接口,默认返回卡片初始状态。 | ||
| 75 | + return formInfo.FormState.READY; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + initApp() { | ||
| 79 | + // KV存储 | ||
| 80 | + SPHelper.init(this.context); | ||
| 81 | + | ||
| 82 | + // 网络模块 | ||
| 83 | + NetworkManager.getInstance().init() | ||
| 84 | + | ||
| 85 | + // App环境 | ||
| 86 | + const spHostUrl = SPHelper.default.getSync('hostUrl', '') as string | ||
| 87 | + if (StringUtils.isNotEmpty(spHostUrl)) { | ||
| 88 | + HostManager.changeHost(spHostUrl as HostEnum) | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + Logger.debug(TAG, "App 网络 初始化") | ||
| 92 | + WDHttp.initHttpHeader() | ||
| 93 | + } | ||
| 94 | +}; |
sight_harmony/products/phone/src/main/ets/dailynewspaperformability/NewspaperDataFetcher.ets
0 → 100644
| 1 | +import { CompInfoBean, ContentDTO, PageInfoBean } from 'wdBean/Index'; | ||
| 2 | +import { MorningEveningViewModel } from 'wdComponent/Index'; | ||
| 3 | +import { Logger } from 'wdKit/Index'; | ||
| 4 | +import { HttpUrlUtils, ResponseDTO, WDHttp } from 'wdNetwork/Index'; | ||
| 5 | +import { DeepLinkUtil } from 'wdShare/Index' | ||
| 6 | +import { FormNewspaperPaperType, FormNewspaperPaperInfo, FormNewspaperPaperContent } from "../dailynewspaperwidget/common/NewspaperWidgetData" | ||
| 7 | + | ||
| 8 | +const TAG = "NewspaperDataFetcher" | ||
| 9 | + | ||
| 10 | +export type FormDataType = Record<string, FormNewspaperPaperType | FormNewspaperPaperInfo | FormNewspaperPaperContent[]> | ||
| 11 | + | ||
| 12 | +export class NewspaperDataFetcher { | ||
| 13 | + | ||
| 14 | + public static async refreshDailyPaper(): Promise<FormDataType> { | ||
| 15 | + return new Promise<FormDataType>(async (reslove, fail) => { | ||
| 16 | + | ||
| 17 | + let data: FormDataType = { 'paperType': FormNewspaperPaperType.unknown } | ||
| 18 | + data.paperInfo = { showLeftImage: false } | ||
| 19 | + | ||
| 20 | + try { | ||
| 21 | + let page: PageInfoBean = await MorningEveningViewModel.getDailyPaperTopic() | ||
| 22 | + data.paperType = page.topicInfo?.frontFlag || FormNewspaperPaperType.unknown | ||
| 23 | + | ||
| 24 | + let currentTime = new Date().getTime() | ||
| 25 | + let compInfo = await MorningEveningViewModel.getMorningEveningCompInfo( | ||
| 26 | + page.id, | ||
| 27 | + page.groups[0]?.id, | ||
| 28 | + currentTime + "", | ||
| 29 | + page.topicInfo?.topicId | ||
| 30 | + ) | ||
| 31 | + | ||
| 32 | + if (page.topicInfo.frontLinkObject) { | ||
| 33 | + data.paperInfo.showLeftImage = true | ||
| 34 | + data.paperInfo.leftImageUrl = page.topicInfo.frontLinkObject.coverUrl | ||
| 35 | + data.paperInfo.leftTitle = page.topicInfo.frontLinkObject.title | ||
| 36 | + data.paperInfo.leftDeepLink = DeepLinkUtil.generateDeepLinkWithFrontObjectLink(page.topicInfo.frontLinkObject) | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + let contents: ContentDTO[] = compInfo.compList[0].operDataList as ContentDTO[] | ||
| 40 | + if (contents && contents.length) { | ||
| 41 | + data.paperContents = contents.map((contentDTO) => { | ||
| 42 | + let content : FormNewspaperPaperContent = { | ||
| 43 | + title: contentDTO.newsTitle, | ||
| 44 | + coverUrl: contentDTO.coverUrl, | ||
| 45 | + deepLink: DeepLinkUtil.generateDeepLinkWithProgram(contentDTO) | ||
| 46 | + } | ||
| 47 | + return content | ||
| 48 | + }) | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + } catch (e) { | ||
| 52 | + Logger.debug(TAG, "刷新早晚报数据失败" + JSON.stringify(e)) | ||
| 53 | + fail(e) | ||
| 54 | + // reslove(NewspaperDataFetcher.fakeData()) | ||
| 55 | + return | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + Logger.debug(TAG, "refresh Data " + JSON.stringify(data)) | ||
| 59 | + reslove(data) | ||
| 60 | + }) | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + static fakeData(): FormDataType { | ||
| 64 | + let data : FormNewspaperPaperContent = { | ||
| 65 | + title: "标题标题标题标题标题标题标题标题", | ||
| 66 | + coverUrl: "https://" | ||
| 67 | + } as FormNewspaperPaperContent | ||
| 68 | + return { | ||
| 69 | + 'paperType': FormNewspaperPaperType.unknown, | ||
| 70 | + "paperInfo": { | ||
| 71 | + showLeftImage: true, | ||
| 72 | + leftTitle: "leftTitleleftTitleleftTitleleftTitleleftTitleleftTitle" | ||
| 73 | + }, | ||
| 74 | + "paperContents": [data, data, data] | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | +} |
sight_harmony/products/phone/src/main/ets/dailynewspaperwidget/common/NewspaperWidgetCommon.ets
0 → 100644
| 1 | +export namespace NewspaperWidgetCommon { | ||
| 2 | + | ||
| 3 | + export enum JumpParam { | ||
| 4 | + DeepLinkKey = "newspaper.widget.jump.deeplink", | ||
| 5 | + FromNewspaperWidgetKey = "newspaper.widget.jump.fromNewspaperWidget" | ||
| 6 | + } | ||
| 7 | + | ||
| 8 | + export enum PosterCardAction { | ||
| 9 | + | ||
| 10 | + ActionRouter = "router", | ||
| 11 | + ActionCaller = "caller", | ||
| 12 | + | ||
| 13 | + MainAbilityName = "EntryAbility" | ||
| 14 | + } | ||
| 15 | +} |
sight_harmony/products/phone/src/main/ets/dailynewspaperwidget/common/NewspaperWidgetData.ets
0 → 100644
| 1 | + | ||
| 2 | +export enum FormNewspaperPaperType { | ||
| 3 | + unknown = 0, | ||
| 4 | + morning = 1, | ||
| 5 | + noon = 2, | ||
| 6 | + evening = 3 | ||
| 7 | +} | ||
| 8 | + | ||
| 9 | +export class FormNewspaperPaperInfo { | ||
| 10 | + | ||
| 11 | + showLeftImage: boolean = false | ||
| 12 | + | ||
| 13 | + leftImageUrl?: string | ||
| 14 | + leftTitle?: string | ||
| 15 | + leftDeepLink?: string | ||
| 16 | + | ||
| 17 | + rightContentHasAnyImage?: boolean = false | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +export class FormNewspaperPaperContent { | ||
| 21 | + title: string = "" | ||
| 22 | + coverUrl?: string | ||
| 23 | + deepLink: string = "" | ||
| 24 | +} |
sight_harmony/products/phone/src/main/ets/dailynewspaperwidget/pages/DailyNewspaperWidgetCard.ets
0 → 100644
| 1 | +import { FormNewspaperPaperType, FormNewspaperPaperInfo, FormNewspaperPaperContent } from "../common/NewspaperWidgetData" | ||
| 2 | +import { FormTopComponent } from "./FormTopComponent" | ||
| 3 | +import { NewspaperWidgetCommon } from "../common/NewspaperWidgetCommon" | ||
| 4 | + | ||
| 5 | +const TAG = "DailyNewspaperWidgetCard" | ||
| 6 | +let storageWidgetImageUpdate = new LocalStorage(); | ||
| 7 | + | ||
| 8 | +@Entry(storageWidgetImageUpdate) | ||
| 9 | +@Component | ||
| 10 | +struct DailyNewspaperWidgetCard { | ||
| 11 | + @LocalStorageProp('paperType') paperType: FormNewspaperPaperType = FormNewspaperPaperType.unknown; | ||
| 12 | + @LocalStorageProp('paperInfo') paperInfo: FormNewspaperPaperInfo = {} as FormNewspaperPaperInfo; | ||
| 13 | + @LocalStorageProp('paperContents') paperContents: FormNewspaperPaperContent[] = []; | ||
| 14 | + | ||
| 15 | + private DAILY_NEWSPAPER_DEEP_LINK = "rmrbapp://rmrb.app/openwith?type=topic&subType=moring_evening_news&pageId=&relId=&skipType=1" | ||
| 16 | + | ||
| 17 | + build() { | ||
| 18 | + | ||
| 19 | + Column() { | ||
| 20 | + FormTopComponent({ | ||
| 21 | + paperType: this.paperType | ||
| 22 | + }) | ||
| 23 | + .width("100%").height(36) | ||
| 24 | + // .margin({top: 3}) | ||
| 25 | + .onClick(() => { | ||
| 26 | + jumpWithDeepLink(this.DAILY_NEWSPAPER_DEEP_LINK, this) | ||
| 27 | + }) | ||
| 28 | + | ||
| 29 | + Row() { | ||
| 30 | + if (this.paperInfo.showLeftImage) { | ||
| 31 | + this.leftImageView() | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + if (this.paperContents.length) { | ||
| 35 | + this.listView() | ||
| 36 | + } else { | ||
| 37 | + EmptyView() | ||
| 38 | + } | ||
| 39 | + }.width("100%") | ||
| 40 | + .layoutWeight(1) | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + @Builder leftImageView() { | ||
| 45 | + Stack({ alignContent: Alignment.Bottom }) { | ||
| 46 | + Image(this.paperInfo.leftImageUrl) | ||
| 47 | + // Image($r("app.media.desktop_card_comp_place_holder_16_9")) | ||
| 48 | + .alt($r("app.media.desktop_card_comp_place_holder_16_9")) | ||
| 49 | + .objectFit(ImageFit.Cover) | ||
| 50 | + .aspectRatio(87/116) | ||
| 51 | + .autoResize(true) | ||
| 52 | + .borderRadius(6) | ||
| 53 | + .onClick(() => { | ||
| 54 | + jumpWithDeepLink(this.paperInfo.leftDeepLink || "", this) | ||
| 55 | + }) | ||
| 56 | + | ||
| 57 | + Text(this.paperInfo.leftTitle) | ||
| 58 | + .textOverflow({ overflow: TextOverflow.Ellipsis }) | ||
| 59 | + .fontSize(11) | ||
| 60 | + .fontWeight(800) | ||
| 61 | + .lineHeight(14) | ||
| 62 | + .maxLines(2) | ||
| 63 | + .fontColor(Color.White) | ||
| 64 | + .padding({left: 4 + 4, bottom:6, right: 4 + 4}) | ||
| 65 | + } | ||
| 66 | + .margin({left: 12, top: 2, bottom: 12}) | ||
| 67 | + // .backgroundColor(Color.Red) | ||
| 68 | + .width(87) | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @Builder listView() { | ||
| 72 | + List() { | ||
| 73 | + ForEach(this.paperContents, (item: FormNewspaperPaperContent, index: number) => { | ||
| 74 | + ListItem() { | ||
| 75 | + ContentCellView({content: item, index: index, hasImage: (item.coverUrl && item.coverUrl.length > 0 ? true : false)}) | ||
| 76 | + } | ||
| 77 | + }, (item: FormNewspaperPaperContent, index) => index + JSON.stringify(item)) | ||
| 78 | + } | ||
| 79 | + .divider( | ||
| 80 | + {strokeWidth: 0.5, | ||
| 81 | + color: "#f5f5f5", | ||
| 82 | + startMargin: 0, | ||
| 83 | + endMargin: 0}) | ||
| 84 | + .width("100%") | ||
| 85 | + .margin({left: this.paperInfo.showLeftImage ? 8 : 12, top: 0, bottom: 12, right: 12}) | ||
| 86 | + .layoutWeight(1) | ||
| 87 | + } | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +@Component | ||
| 91 | +struct ContentCellView { | ||
| 92 | + @Prop content: FormNewspaperPaperContent | ||
| 93 | + private index : number = 0 | ||
| 94 | + private hasImage: boolean = false | ||
| 95 | + build() { | ||
| 96 | + Row() { | ||
| 97 | + Text(this.content.title) | ||
| 98 | + .maxLines((this.content.coverUrl && this.content.coverUrl.length > 0 ? 2 : 1)) | ||
| 99 | + .textOverflow({ overflow: TextOverflow.Ellipsis }) | ||
| 100 | + .fontSize(14) | ||
| 101 | + .lineHeight(20) | ||
| 102 | + .fontWeight(FontWeight.Medium) | ||
| 103 | + .fontColor(Color.Black) | ||
| 104 | + .layoutWeight(1) | ||
| 105 | + // .backgroundColor(Color.Red) | ||
| 106 | + .offset({y: this.hasImage && this.index == 0 ? -3 : 0}) | ||
| 107 | + .margin({ | ||
| 108 | + top: this.hasImage ? 0 : 4, | ||
| 109 | + bottom: this.hasImage ? 0 : 6}) | ||
| 110 | + | ||
| 111 | + if (this.hasImage) { | ||
| 112 | + Image(this.content.coverUrl) | ||
| 113 | + // Image($r("app.media.desktop_card_comp_place_holder_3_4")) | ||
| 114 | + .alt($r("app.media.desktop_card_comp_place_holder_3_4")) | ||
| 115 | + .objectFit(ImageFit.Cover) | ||
| 116 | + .height(40) | ||
| 117 | + .aspectRatio(75/50) | ||
| 118 | + .borderRadius(4) | ||
| 119 | + .margin({left: 10, bottom: 8, top: this.index == 0 ? 2 : 8, right: 0}) | ||
| 120 | + .autoResize(true) | ||
| 121 | + } | ||
| 122 | + } | ||
| 123 | + .justifyContent(FlexAlign.Start) | ||
| 124 | + .onClick(() => { | ||
| 125 | + jumpWithDeepLink(this.content.deepLink || "", this) | ||
| 126 | + }) | ||
| 127 | + } | ||
| 128 | +} | ||
| 129 | + | ||
| 130 | +@Component | ||
| 131 | +struct EmptyView { | ||
| 132 | + build() { | ||
| 133 | + Row() { | ||
| 134 | + Image($r("app.media.desktop_card_empty_bg")) | ||
| 135 | + .objectFit(ImageFit.Fill) | ||
| 136 | + // .width("100%") | ||
| 137 | + // .height("100%") | ||
| 138 | + .margin({left: 12, bottom: 12, right: 12, top: 4}) | ||
| 139 | + } | ||
| 140 | + .height("100%") | ||
| 141 | + .width("100%") | ||
| 142 | + | ||
| 143 | + // .backgroundColor(Color.Red) | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +function jumpWithDeepLink(deepLink: string, component: Object) { | ||
| 150 | + console.log(TAG + "jumpWithDeepLink: " + deepLink) | ||
| 151 | + if (deepLink.length == 0) { | ||
| 152 | + return | ||
| 153 | + } | ||
| 154 | + const deepLinkKey: string = NewspaperWidgetCommon.JumpParam.DeepLinkKey | ||
| 155 | + const fromDailyNewspaperKey: string = NewspaperWidgetCommon.JumpParam.FromNewspaperWidgetKey | ||
| 156 | + postCardAction(component, { | ||
| 157 | + action: NewspaperWidgetCommon.PosterCardAction.ActionRouter, | ||
| 158 | + abilityName: NewspaperWidgetCommon.PosterCardAction.MainAbilityName, | ||
| 159 | + params: { | ||
| 160 | + deepLinkKey: deepLink, | ||
| 161 | + fromDailyNewspaperKey: true | ||
| 162 | + } | ||
| 163 | + }); | ||
| 164 | +} |
sight_harmony/products/phone/src/main/ets/dailynewspaperwidget/pages/FormTopComponent.ets
0 → 100644
| 1 | +import { FormNewspaperPaperType } from "../common/NewspaperWidgetData" | ||
| 2 | + | ||
| 3 | +@Component | ||
| 4 | +export struct FormTopComponent { | ||
| 5 | + @Prop paperType: FormNewspaperPaperType | ||
| 6 | + | ||
| 7 | + build() { | ||
| 8 | + | ||
| 9 | + Row() { | ||
| 10 | + | ||
| 11 | + if (this.paperType == FormNewspaperPaperType.noon) { | ||
| 12 | + Image($r("app.media.desktop_card_newspaper_noon")) | ||
| 13 | + .fancy() | ||
| 14 | + } else if (this.paperType == FormNewspaperPaperType.evening) { | ||
| 15 | + Image($r("app.media.desktop_card_newspaper_evening")) | ||
| 16 | + .fancy() | ||
| 17 | + } else { | ||
| 18 | + Image($r("app.media.desktop_card_newspaper_moring")) | ||
| 19 | + .fancy() | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + Image($r("app.media.desktop_card_peopledaily_logo")) | ||
| 23 | + .width(213).height(18) | ||
| 24 | + .offset({right: -10}) | ||
| 25 | + } | ||
| 26 | + .justifyContent(FlexAlign.SpaceBetween) | ||
| 27 | + .alignItems(VerticalAlign.Center) | ||
| 28 | + .width("100%").height("100%") | ||
| 29 | + } | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +@Extend(Image) function fancy() { | ||
| 33 | + .width(58) | ||
| 34 | + .height(20) | ||
| 35 | + .margin({left: 12}) | ||
| 36 | +} |
| @@ -89,6 +89,8 @@ struct Index { | @@ -89,6 +89,8 @@ struct Index { | ||
| 89 | .height(20) | 89 | .height(20) |
| 90 | .fontColor('#222222') | 90 | .fontColor('#222222') |
| 91 | .fontSize(14) | 91 | .fontSize(14) |
| 92 | + .fontFamily('PingFang SC-Medium') | ||
| 93 | + .fontWeight(500) | ||
| 92 | .alignSelf(ItemAlign.Start) | 94 | .alignSelf(ItemAlign.Start) |
| 93 | .onStart(() => { | 95 | .onStart(() => { |
| 94 | console.info('Marquee animation complete onStart') | 96 | console.info('Marquee animation complete onStart') |
| @@ -129,7 +131,7 @@ struct Index { | @@ -129,7 +131,7 @@ struct Index { | ||
| 129 | .justifyContent(FlexAlign.Start) | 131 | .justifyContent(FlexAlign.Start) |
| 130 | 132 | ||
| 131 | Row() { | 133 | Row() { |
| 132 | - Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause") : $r("app.media.icon_audio_playing")) | 134 | + Image(this.currentStatus === PlayerConstants.STATUS_START ? $r("app.media.icon_audio_pause_svg") : $r("app.media.icon_audio_playing_svg")) |
| 133 | .objectFit(ImageFit.Contain) | 135 | .objectFit(ImageFit.Contain) |
| 134 | .width(24) | 136 | .width(24) |
| 135 | .height(24) | 137 | .height(24) |
| @@ -15,7 +15,8 @@ | @@ -15,7 +15,8 @@ | ||
| 15 | "pages": "$profile:main_pages", | 15 | "pages": "$profile:main_pages", |
| 16 | "abilities": [ | 16 | "abilities": [ |
| 17 | { | 17 | { |
| 18 | - "name": "EntryAbility", // 这里不能改动,和后台推送有绑定 | 18 | + "name": "EntryAbility", |
| 19 | + // 这里不能改动,和后台推送有绑定 | ||
| 19 | "srcEntry": "./ets/entryability/EntryAbility.ets", | 20 | "srcEntry": "./ets/entryability/EntryAbility.ets", |
| 20 | "description": "$string:EntryAbility_desc", | 21 | "description": "$string:EntryAbility_desc", |
| 21 | "icon": "$media:app_icon_layer", | 22 | "icon": "$media:app_icon_layer", |
| @@ -32,20 +33,24 @@ | @@ -32,20 +33,24 @@ | ||
| 32 | "action.system.home", | 33 | "action.system.home", |
| 33 | "com.test.pushaction" | 34 | "com.test.pushaction" |
| 34 | ], | 35 | ], |
| 35 | - "uris" : [{ | 36 | + "uris": [ |
| 37 | + { | ||
| 36 | "scheme": 'rmrbapp', | 38 | "scheme": 'rmrbapp', |
| 37 | "host": 'rmrb.app', | 39 | "host": 'rmrb.app', |
| 38 | 'port': '8080', | 40 | 'port': '8080', |
| 39 | "path": 'openwith' | 41 | "path": 'openwith' |
| 40 | - }] | 42 | + } |
| 43 | + ] | ||
| 41 | } | 44 | } |
| 42 | ] | 45 | ] |
| 43 | } | 46 | } |
| 44 | ], | 47 | ], |
| 45 | - "metadata": [{ | 48 | + "metadata": [ |
| 49 | + { | ||
| 46 | "name": "client_id", | 50 | "name": "client_id", |
| 47 | "value": "110737325" | 51 | "value": "110737325" |
| 48 | - }], | 52 | + } |
| 53 | + ], | ||
| 49 | "requestPermissions": [ | 54 | "requestPermissions": [ |
| 50 | { | 55 | { |
| 51 | "name": "ohos.permission.CAMERA", | 56 | "name": "ohos.permission.CAMERA", |
| @@ -100,6 +105,22 @@ | @@ -100,6 +105,22 @@ | ||
| 100 | { | 105 | { |
| 101 | "name": "ohos.permission.INTERNET" | 106 | "name": "ohos.permission.INTERNET" |
| 102 | }, | 107 | }, |
| 108 | + ], | ||
| 109 | + "extensionAbilities": [ | ||
| 110 | + { | ||
| 111 | + "name": "DailyNewspaperFormAbility", | ||
| 112 | + "srcEntry": "./ets/dailynewspaperformability/DailyNewspaperFormAbility.ets", | ||
| 113 | + "label": "$string:DailyNewspaperFormAbility_label", | ||
| 114 | + "description": "$string:DailyNewspaperFormAbility_desc", | ||
| 115 | + "type": "form", | ||
| 116 | + "metadata": [ | ||
| 117 | + { | ||
| 118 | + "name": "ohos.extension.form", | ||
| 119 | + "resource": "$profile:form_config" | ||
| 120 | + } | ||
| 121 | + ], | ||
| 122 | + | ||
| 123 | + } | ||
| 103 | ] | 124 | ] |
| 104 | } | 125 | } |
| 105 | } | 126 | } |
| @@ -63,6 +63,22 @@ | @@ -63,6 +63,22 @@ | ||
| 63 | { | 63 | { |
| 64 | "name": "reason_read_write_media", | 64 | "name": "reason_read_write_media", |
| 65 | "value": "user_grant" | 65 | "value": "user_grant" |
| 66 | + }, | ||
| 67 | + { | ||
| 68 | + "name": "DailyNewspaperFormAbility_desc", | ||
| 69 | + "value": "早晚报卡片" | ||
| 70 | + }, | ||
| 71 | + { | ||
| 72 | + "name": "DailyNewspaperFormAbility_label", | ||
| 73 | + "value": "早晚报卡片" | ||
| 74 | + }, | ||
| 75 | + { | ||
| 76 | + "name": "DailyNewspaperWidget_desc", | ||
| 77 | + "value": "有品质的新闻" | ||
| 78 | + }, | ||
| 79 | + { | ||
| 80 | + "name": "DailyNewspaperWidget_display_name", | ||
| 81 | + "value": "早晚报" | ||
| 66 | } | 82 | } |
| 67 | ] | 83 | ] |
| 68 | } | 84 | } |
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_comp_place_holder_16_9.png
0 → 100644
12.5 KB
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_comp_place_holder_3_4.png
0 → 100644
20.8 KB
| 1 | +<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> |
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_newspaper_evening.png
0 → 100644
9.63 KB
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_newspaper_front_cover.png
0 → 100644
1.6 MB
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_newspaper_moring.png
0 → 100644
9.3 KB
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_newspaper_noon.png
0 → 100644
9.11 KB
sight_harmony/products/phone/src/main/resources/base/media/desktop_card_peopledaily_logo.png
0 → 100644
14.9 KB
| 1 | +{ | ||
| 2 | + "forms": [ | ||
| 3 | + { | ||
| 4 | + "name": "DailyNewspaperWidget", | ||
| 5 | + "displayName": "$string:DailyNewspaperWidget_display_name", | ||
| 6 | + "description": "$string:DailyNewspaperWidget_desc", | ||
| 7 | + "src": "./ets/dailynewspaperwidget/pages/DailyNewspaperWidgetCard.ets", | ||
| 8 | + "uiSyntax": "arkts", | ||
| 9 | + "window": { | ||
| 10 | + "designWidth": 720, | ||
| 11 | + "autoDesignWidth": true | ||
| 12 | + }, | ||
| 13 | + "colorMode": "light", | ||
| 14 | + "isDynamic": true, | ||
| 15 | + "isDefault": true, | ||
| 16 | + "updateEnabled": true, | ||
| 17 | + "scheduledUpdateTime": "10:30", | ||
| 18 | + "updateDuration": 1, | ||
| 19 | + "defaultDimension": "2*4", | ||
| 20 | + "supportDimensions": [ | ||
| 21 | + "2*4" | ||
| 22 | + ] | ||
| 23 | + } | ||
| 24 | + ] | ||
| 25 | +} |
-
Please register or login to post a comment