import { AppUtil, ArrayUtil, DisplayUtil, GlobalContext, JSONUtil, PickerUtil, PreferencesUtil, StrUtil, ToastUtil } from '@pura/harmony-utils'; import TitleBar from '../view/TitleBar'; import { router } from '@kit.ArkUI'; import mainViewModel, { MainViewModel } from '../viewmodel/MainViewModel'; import ItemData from '../viewmodel/ItemData'; import { CommonConstants } from '../common/constants/CommonConstants'; import { ToolView } from '../view/ToolView'; import { VideoItem } from '../viewmodel/VideoItem'; import ScreenUtil from '../common/util/ScreenUtil'; import Logger from '../common/util/Logger'; import { Utility } from '../common/util/Utility'; import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { BusinessError, emitter } from '@kit.BasicServicesKit'; import { common } from '@kit.AbilityKit'; import { AdSlot, AdSlotBuilder, CSJAdCreator, CSJAdSdk, CSJNativeExpressAd, NativeExpressAdListener } from '@csj/openadsdk'; import { PrintBiddingTokenUtils } from '../common/util/PrintBiddintTokenUtils'; import { ArrayList } from '@kit.ArkTS'; import { CSJUtil } from '../common/util/CSJUtil'; import { LocalMusic } from '../view/LocalMusic'; import { StreamContent } from '../view/StreamContent'; import { AvSessionController } from '../controller/AvSessionController'; import { ImageKnife } from '@ohos/imageknife'; import { BreakpointSystem, BreakpointTypeEnum } from '../common/util/BreakpointSystem'; import { bundleManager } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; const TAG = 'NewIndex'; // 日志标签 /** * 首页主组件,包含顶部标题栏、主内容区(本地音乐/网络内容)、侧边抽屉菜单等。 * 支持多端适配、广告集成、导航、生命周期管理等功能。 */ @Preview @Entry @Component struct NewIndex{ /** 列表滚动器,用于抽屉菜单列表滚动 */ private scroller: Scroller = new Scroller(); /** 应用包名 */ @State bundleName:string = '' /** 是否显示侧边抽屉菜单 */ @Provide isShowDrawer:boolean = false; /** 抽屉菜单 X 轴偏移量,用于手势滑动动画 */ @Provide offsetX: number = 0; /** 本地视频列表,页面参数传入 */ @Provide videoLocalList: Array = [] /** Y 轴偏移量(预留) */ @State offsetY: number = 0; /** 主内容类型(0:本地音乐,1:网络内容) */ @State mType:number = 0 /** 模式类型(如歌手、专辑等) */ @Provide modeType:number = 0 /** 是否为零状态(预留) */ @Provide('isZero') isZero:boolean = false; /** 是否显示赞助入口 */ @State isShowSponsorship:boolean = false /** 页面上下文 */ context = getContext(this); /** 音乐是否为零状态(预留) */ @Provide('isMusicZero') isMusicZero:boolean = false; /** 本地音乐列表,持久化存储 */ @StorageLink('musicLocalList') musicLocalList: Array = [] /** 标题栏配置模型 */ @State titleBarModel: TitleBar.Model = new TitleBar.Model() .setTitleTextStyle(FontStyle.Normal) .setTitleBarStyle(TitleBar.BarStyle.TRANSPARENT) .setLeftIcon($r('app.media.menu')) .setLeftIconWidth(28) .setLeftIconHeight(28) .setTitleBarMinHeight(64) .setTitleName('首页') // .setRightIcon($r('app.media.add')) .setTitleFontSize(19) .setTitleFontColor(Color.White) .setTitleBarBackground($r('app.color.title_bar_bg')) .setLeftTitleBackground($r('app.color.title_bar_bg')) .setOnLeftClickListener(() => { // 打开菜单栏动画 animateTo({ duration: 555 }, () => { this.isShowDrawer = true this.offsetX = 0 }) }) .setRightTitleBackground($r('app.color.title_bar_bg')) // .setOnRightClickListener(()=>{ // // this.goSelectVideo() // this.showSheelDialog() // }) /** 应用版本号 */ @State versionName:string ='' /** 音频根目录路径 */ @Provide rootPath:string = '' /** 当前路径 */ @Provide currentPath:string = '' /** 是否为历史记录页面 */ @Provide isHistory:boolean = false /** 是否可以返回上一级 */ @Provide isCanBack:boolean= false /** * 一多界面适配断点系统 */ private breakpointSystem: BreakpointSystem = new BreakpointSystem(); /** 当前断点类型(如大屏/小屏) */ @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD; /** 记录上一次点击返回键的时间戳,用于双击退出 */ private backTime:number=0; /** * 返回键处理逻辑: * - 如果不是根目录或有历史记录,发送广播通知更新列表 * - 如果是根目录,双击返回键退出应用,否则提示 */ onBackPress(): boolean | void { if(this.currentPath !== this.rootPath||this.isHistory||(this.modeType!==0&&this.isCanBack)){ const eventData: emitter.EventData = {}; emitter.emit({ eventId: 888 }, eventData); // 发送音频广播通知更新doSwipBack }else{ let nowtime = Date.now(); if(nowtime - this.backTime < 1000){ const mContext = getContext(this) as common.UIAbilityContext mContext.terminateSelf(); // 关闭应用 AvSessionController.getInstance(true).unregisterSessionListener() }else { if(this.isShowDrawer){ // 如果抽屉菜单打开,先关闭抽屉 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) }else{ this.backTime=nowtime; ToastUtil.showToast("再按一次将退出当前应用") } } } return true; } /** * 页面显示生命周期钩子 * - 注册断点系统 * - 获取页面参数 * - 设置状态栏样式 * - 初始化图片缓存 * - 判断是否显示赞助入口 */ async aboutToAppear() { this.breakpointSystem.register(); let params = router.getParams() as Record; this.videoLocalList = params.videoList as VideoItem[]; Utility.setStatusBarLight() // ScreenUtil 设置屏幕尺寸信息 ScreenUtil.setScreenSize(); this.bundleName = await AppUtil.getBundleName() this.versionName = await AppUtil.getVersionName(); // 初始化图片缓存 await ImageKnife.getInstance().initFileCache(this.context, 256, 256 * 1024 * 1024) // 判断是否显示赞助入口 this.isShowSponsorship = Utility.isOpenTime() } /** * 页面消失生命周期钩子 * 注销断点系统 */ aboutToDisappear() { console.info('NewIndex aboutToDisappear'); this.breakpointSystem.unregister(); } /** * 构建主页面结构,包括顶部横线、主内容区和抽屉菜单 */ build() { Stack({ alignContent: Alignment.TopStart }) { // 顶部横线 Column(){ Line() .width('100%') .height(1) } .backgroundColor($r('app.color.title_bar_bg')) .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP]) // 主内容区 Column() { Stack(){ // 本地音乐内容区 LocalMusic() .visibility(this.mType===0?Visibility.Visible:Visibility.None) // 网络内容区 StreamContent() .visibility(this.mType===1?Visibility.Visible:Visibility.None) } } .width('100%') .height('100%') .justifyContent(FlexAlign.Start) // 侧边抽屉菜单 if(this.isShowDrawer){ Column() { Column() { // 抽屉顶部背景图 Image($r('app.media.bg_music')) .width('100%') .height(180) // 动态生成抽屉菜单内容 this.getDrawerView() } .width(this.currentBreakpoint !== BreakpointTypeEnum.SM?'40%':'80%') .height('100%') .backgroundColor(Color.White) .onClick((event:ClickEvent)=>{ // 阻止事件冒泡 }) } .width('100%') .height('100%') .backgroundColor($r('app.color.ban_touming')) .alignItems(HorizontalAlign.Start) .onClick((event:ClickEvent)=>{ // 点击抽屉外部关闭抽屉 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) }) .translate({ x: this.offsetX, y: 0, z: 0 }) .transition({ type: TransitionType.Insert, translate: { x: -DisplayUtil.getWidth(), y: 0 } }) .transition({ type: TransitionType.Delete, translate: { x: -DisplayUtil.getWidth(), y: 0 } }) .gesture( PanGesture() .onActionUpdate((event:GestureEvent)=>{ // 手势滑动更新抽屉偏移 if(event.offsetX<0){ this.offsetX = event.offsetX; } }) .onActionEnd(() => { // 手势结束判断是否关闭抽屉 if(this.offsetX<-DisplayUtil.getWidth()/9){ animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) }else{ animateTo({ duration: 555 }, () => { this.isShowDrawer = true this.offsetX = 0 }) } }) ) } } } /** * 动态生成抽屉菜单内容 * 根据 isShowSponsorship 展示不同菜单项 */ @Builder getDrawerView(){ List({space: 0, scroller: this.scroller}){ ForEach(this.isShowSponsorship?mainViewModel.getDrawerData2():mainViewModel.getDrawerData(),(item: ItemData)=>{ ListItem(){ Row() { // 菜单图标 Image(item.img) .height(22) .alignSelf(ItemAlign.Center) .margin({ left: 2 }) // 菜单标题 Text(item.title) .margin({ left: 10, right: 20 }) .fontSize(15) .fontColor(Color.Gray) .fontWeight(480) Blank() // 右侧箭头 Image($r('app.media.arrow_right')) .width(22) .height(22) .margin({ left: 20, right: 0 }) .align(Alignment.Center) } .width('100%') .height(55) .onClick(async () => { // 根据 item.id 跳转或切换功能 switch (item.id) { case MainViewModel.MENU_MUSIC: this.mType = 0 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) break case MainViewModel.MENU_FILE_SCAN: router.pushUrl({ url: 'pages/ScanFilePage' }); break case MainViewModel.MENU_HOME: this.mType = 0 this.modeType = 0 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) break case MainViewModel.MENU_MIEDIA_KU: this.modeType = 1 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) break case MainViewModel.MENU_MIEDIA_ARTIST: this.modeType = 2 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) break case MainViewModel.MENU_MIEDIA_ALBUM: this.modeType = 3 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) break case MainViewModel.MENU_SETTING: router.pushUrl({ url: 'pages/SettingPage' }, router.RouterMode.Single); break case MainViewModel.MENU_VIP: router.pushUrl({ url: 'pages/VipPage' }, router.RouterMode.Single); break case MainViewModel.MENU_NET_CONNECT: this.mType = 1 animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) break case MainViewModel.MENU_SIMI: router.pushUrl({ url: 'pages/VerifyPage' }); break case MainViewModel.MENU_LIKE: router.pushUrl({ url: 'pages/LikeVideoPage' }); break case MainViewModel.MENU_DUTY: router.pushUrl({ url: 'pages/WebIndex', params: { titleName: '用户协议', webUrl: CommonConstants.NEW_DUTY } }); break case MainViewModel.MENU_HAOPING: Utility.gotoMarket(getContext(this) as common.UIAbilityContext,this.bundleName) break case MainViewModel.MENU_TEST_SPEED: router.pushUrl({ url: 'pages/SpeedIndex' }); break case MainViewModel.MENU_OPTIMIZE: router.pushUrl({ url: 'pages/AddSpeedPage' }); break case MainViewModel.MENU_ABOUT: router.pushUrl({ url: 'pages/AboutPage' }, router.RouterMode.Single); break case MainViewModel.MENU_UPDATE: AlertDialog.show({title:'版本更新',message:'当前版本为最新版本:'+this.versionName, autoCancel:true, alignment:DialogAlignment.Center, offset:{dx:0,dy:-20},//在Y轴方向上的编译量 confirm:{ value:'确定',fontColor:Color.White,backgroundColor:$r('app.color.title_bar_bg'), action:()=>{ } } }) break case MainViewModel.MENU_YSZC: router.pushUrl({ url: 'pages/WebIndex', params: { titleName: '隐私政策', webUrl: CommonConstants.NEW_YS_HW } }); break } }) } .width('90%') .height(55) }) } .width('100%') .alignListItem(ListItemAlign.Center) .backgroundColor($r('app.color.white')) .layoutWeight(1) .divider({strokeWidth: 1, color: '#ffe9f0f0'}) .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果 } /** * ================== 穿山甲广告相关 ================== */ /** Banner广告对象 */ private declare bannerAd: CSJNativeExpressAd; /** 广告加载状态 */ @State private status: string = "未加载" /** 是否展示广告 */ @State private isShowAd: boolean = false /** 广告位配置信息 */ private declare mAdSlot: AdSlot; /** 服务端bidding广告内容(可选) */ private mBiddingAdm = '' /** 广告加载监听器 */ private expressLoadAdListener: NativeExpressAdListener = { /** * 广告加载失败回调 */ onError: (code: number, message: string) => { console.error("加载广告失败,code=" + code + ",message=" + message); this.status = "加载广告失败,code=" + code + ",message=" + message; }, /** * 广告加载成功回调 * @param ads 返回的广告列表 */ onNativeExpressAdLoad: (ads: ArrayList) => { console.log("BannerExpressAdPage==onNativeExpressAdLoad......success"); if (ads && ads.length > 0) { ads.forEach((ad: CSJNativeExpressAd, idx: number) => { // 设置广告交互监听 ad.setExpressInteractionListener({ /** 广告点击回调 */ onAdClicked: (type: number) => { console.log("BannerExpressAdPage==onAdClicked......"); }, /** 广告展示回调 */ onAdShow: (type: number) => { console.log("BannerExpressAdPage==onAdShow......"); }, /** 模板渲染失败回调 */ onRenderFail: (code: number, msg: string) => { console.log("BannerExpressAdPage==onRenderFail...code=" + code + ",msg=" + msg); }, /** 模板渲染成功回调 */ onRenderSuccess: (width: number, height: number) => { console.log("BannerExpressAdPage==onRenderSuccess......width=" + width + ",height=" + height); this.bannerAd = ad; this.status = "广告加载完成待展示"; this.showBannerAd() } }) // 设置广告轮播时间 ad.setSlideIntervalTime(30 * 1000);//设置轮播时间长 this.setDislikeCallback(ad); //设置dislike ad.render(this.getUIContext()) // 开始渲染广告 this.status = "广告加载中..."; }); } } } /** * 设置广告 dislike 回调 * @param ad 广告对象 */ private setDislikeCallback(ad: CSJNativeExpressAd) { ad.setDislikeCallback({ /** dislike 弹窗显示 */ onShow: () => { console.log("BannerExpressAdPage==dislike......show"); }, /** 选择 dislike 选项 */ onSelected: (position: number, value: string, enforceRemove: boolean) => { this.isShowAd = false; console.log("BannerExpressAdPage==dislike......onSelected:position=" + position + ",value:" + value + ",enforce=" + enforceRemove); }, /** 点击取消 dislike */ onCancel: () => { console.log("BannerExpressAdPage==dislike......onCancel"); } }) } /** * 加载Banner广告 * @param rit 广告位ID */ loadBannerAd(rit: string) { // 仅在满足条件时加载广告 if(!Utility.isNoble()){ return } if(!Utility.isPassInstallTime(2)){ return } this.isShowAd = false; let adCreator:CSJAdCreator = CSJAdSdk.getAdCreator() this.mAdSlot = new AdSlotBuilder() .setCodeId(rit) .setAcceptSize(CSJUtil.BANNER_WIGTH, CSJUtil.BANNER_HEIGHT) .setAdCount(1) .setBidAdm(this.mBiddingAdm) .build() PrintBiddingTokenUtils.printBiddingToken(this.mAdSlot, adCreator); adCreator.loadBannerAd(this.mAdSlot, this.expressLoadAdListener) this.status = "广告加载中..." } /** * 展示Banner广告 */ showBannerAd() { if (!this.bannerAd) { return } this.isShowAd = true this.status = "已展示" } /** * ================== 穿山甲广告相关结束 ================== */ // geIDD() { // // 获取应用签名等信息示例代码 // let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION | // bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO; // try { // bundleManager.getBundleInfoForSelf(bundleFlags).then((data) => { // hilog.info(0x0000, 'testTag11', 'getBundleInfoForSelf successfully. Data: %{public}s', JSON.stringify(data)); // }).catch((err: BusinessError) => { // hilog.error(0x0000, 'testTag11', 'getBundleInfoForSelf failed. Cause: %{public}s', err.message); // }); // } catch (err) { // let message = (err as BusinessError).message; // hilog.error(0x0000, 'testTag33', 'getBundleInfoForSelf failed: %{public}s', message); // } // } }