NewIndex.ets 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. import { AppUtil, DeviceUtil, DisplayUtil, LogUtil, PreferencesUtil, ToastUtil } from '@pura/harmony-utils';
  2. import TitleBar from '../view/TitleBar';
  3. import { router } from '@kit.ArkUI';
  4. import mainViewModel, { MainViewModel } from '../viewmodel/MainViewModel';
  5. import ItemData from '../viewmodel/ItemData';
  6. import type { sysResource } from '../viewmodel/ItemData';
  7. import { CommonConstants } from '../common/constants/CommonConstants';
  8. import { VideoItem } from '../viewmodel/VideoItem';
  9. import ScreenUtil from '../common/util/ScreenUtil';
  10. import { Utility } from '../common/util/Utility';
  11. import { BusinessError, emitter } from '@kit.BasicServicesKit';
  12. import { common } from '@kit.AbilityKit';
  13. // import { AdSlot, AdSlotBuilder,
  14. // CSJAdCreator,
  15. // CSJAdSdk, CSJNativeExpressAd, NativeExpressAdListener } from '@csj/openadsdk';
  16. import { PrintBiddingTokenUtils } from '../common/util/PrintBiddintTokenUtils';
  17. import { ArrayList } from '@kit.ArkTS';
  18. import { CSJUtil } from '../common/util/CSJUtil';
  19. import { LocalMusic } from '../view/LocalMusic';
  20. import { StreamContent } from '../view/StreamContent';
  21. import { AvSessionController } from '../controller/AvSessionController';
  22. import { BreakpointSystem, BreakpointTypeEnum } from '../common/util/BreakpointSystem';
  23. import dataStorage from '@ohos.data.storage';
  24. import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant';
  25. import { SettingPage } from './SettingPage';
  26. import { deviceInfo } from '@kit.BasicServicesKit';
  27. import { resourceManager } from '@kit.LocalizationKit';
  28. import { systemShare } from '@kit.ShareKit';
  29. import { uniformTypeDescriptor } from '@kit.ArkData';
  30. import { hilog } from '@kit.PerformanceAnalysisKit';
  31. import { DialogHelper } from '@pura/harmony-dialog';
  32. import UserUtil from '../common/util/UserUtil';
  33. import json from '@ohos.util.json';
  34. import { UserCenter } from './UserCenter';
  35. import { ScanFilePage } from './ScanFilePage';
  36. import { AboutPage } from './AboutPage';
  37. const TAG = 'NewIndex'; // 日志标签
  38. /**
  39. * 首页主组件,包含顶部标题栏、主内容区(本地音乐/网络内容)、侧边抽屉菜单等。
  40. * 支持多端适配、广告集成、导航、生命周期管理等功能。
  41. */
  42. @Preview
  43. @Entry
  44. @Component
  45. struct NewIndex {
  46. /** 列表滚动器,用于抽屉菜单列表滚动 */
  47. private scroller: Scroller = new Scroller();
  48. /** 应用包名 */
  49. @State bundleName: string = ''
  50. @State appName: string = ''
  51. /** 是否显示侧边抽屉菜单 */
  52. @Provide isShowDrawer: boolean = false;
  53. /** 抽屉菜单 X 轴偏移量,用于手势滑动动画 */
  54. @Provide offsetX: number = 0;
  55. /** 本地视频列表,页面参数传入 */
  56. @Provide videoLocalList: Array<VideoItem> = []
  57. /** Y 轴偏移量(预留) */
  58. @State offsetY: number = 0;
  59. /** 主内容类型(0:本地音乐,1:网络内容) */
  60. @Provide mType: number = 0
  61. /** 模式类型(如歌手、专辑等) */
  62. @Provide modeType: number = 0
  63. /** 是否为零状态(预留) */
  64. @Provide('isZero') isZero: boolean = false;
  65. /** 是否显示赞助入口 */
  66. @State isShowSponsorship: boolean = false
  67. /** 页面上下文 */
  68. context = getContext(this);
  69. /** 音乐是否为零状态(预留) */
  70. @Provide('isMusicZero') isMusicZero: boolean = false;
  71. /** 本地音乐列表,持久化存储 */
  72. @StorageLink('musicLocalList') musicLocalList: Array<VideoItem> = []
  73. @Provide isFavMusic: boolean = false
  74. /** 标题栏配置模型 */
  75. @State titleBarModel: TitleBar.Model = new TitleBar.Model()
  76. .setTitleTextStyle(FontStyle.Normal)
  77. .setTitleBarStyle(TitleBar.BarStyle.TRANSPARENT)
  78. .setLeftIcon($r('app.media.menu'))
  79. .setLeftIconWidth(28)
  80. .setLeftIconHeight(28)
  81. .setTitleBarMinHeight(64)
  82. .setTitleName('首页')// .setRightIcon($r('app.media.add'))
  83. .setTitleFontSize(19)
  84. .setTitleFontColor(Color.White)
  85. .setTitleBarBackground($r('app.color.title_bar_bg'))
  86. .setLeftTitleBackground($r('app.color.title_bar_bg'))
  87. .setOnLeftClickListener(() => {
  88. // 打开菜单栏动画
  89. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  90. this.isShowDrawer = true
  91. this.offsetX = 0
  92. })
  93. })
  94. .setRightTitleBackground($r('app.color.title_bar_bg'))
  95. // .setOnRightClickListener(()=>{
  96. // // this.goSelectVideo()
  97. // this.showSheelDialog()
  98. // })
  99. /** 应用版本号 */
  100. @State versionName: string = ''
  101. /** 音频根目录路径 */
  102. @Provide rootPath: string = ''
  103. /** 当前路径 */
  104. @Provide currentPath: string = ''
  105. /** 是否为历史记录页面 */
  106. @Provide isHistory: boolean = false
  107. /** 是否可以返回上一级 */
  108. @Provide isCanBack: boolean = false
  109. @StorageProp('currentColorMode') currentMode: number = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  110. @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
  111. /**
  112. * 一多界面适配断点系统
  113. */
  114. private breakpointSystem: BreakpointSystem = new BreakpointSystem();
  115. /** 当前断点类型(如大屏/小屏) */
  116. @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD;
  117. /** 记录上一次点击返回键的时间戳,用于双击退出 */
  118. private backTime: number = 0;
  119. /**
  120. * 返回键处理逻辑:
  121. * - 如果不是根目录或有历史记录,发送广播通知更新列表
  122. * - 如果是根目录,双击返回键退出应用,否则提示
  123. */
  124. onBackPress(): boolean | void {
  125. if (this.currentPath !== this.rootPath || this.isHistory || this.isFavMusic ||
  126. (this.modeType !== 0 && this.isCanBack)) {
  127. const eventData: emitter.EventData = {};
  128. emitter.emit({ eventId: 888 }, eventData); // 发送音频广播通知更新doSwipBack
  129. } else {
  130. let nowtime = Date.now();
  131. if (nowtime - this.backTime < 1000) {
  132. const mContext = getContext(this) as common.UIAbilityContext
  133. mContext.terminateSelf(); // 关闭应用
  134. AvSessionController.getInstance(true).unregisterSessionListener()
  135. } else {
  136. if (this.isShowDrawer) {
  137. // 如果抽屉菜单打开,先关闭抽屉
  138. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  139. this.isShowDrawer = false
  140. })
  141. } else {
  142. this.backTime = nowtime;
  143. ToastUtil.showToast("再按一次将退出当前应用")
  144. }
  145. }
  146. }
  147. return true;
  148. }
  149. /**
  150. * 刷新@State用户信息变量,确保UI同步
  151. */
  152. refreshUserInfoState() {
  153. this.isLogin = PreferencesUtil.getBooleanSync('isLogin', false);
  154. this.userId = PreferencesUtil.getNumberSync('userId', 0);
  155. this.userName = PreferencesUtil.getStringSync('userName', '未登录用户');
  156. this.userAvatarUrl = PreferencesUtil.getStringSync('userAvatarUrl', '');
  157. this.subscriptionName = PreferencesUtil.getStringSync('subscriptionName', '');
  158. this.subscriptionEndDate = PreferencesUtil.getStringSync('subscriptionEndDate', '');
  159. this.hasActiveSubscription = PreferencesUtil.getBooleanSync('hasActiveSubscription', false);
  160. }
  161. /**
  162. * 页面显示生命周期钩子
  163. * - 注册断点系统
  164. * - 获取页面参数
  165. * - 设置状态栏样式
  166. * - 初始化图片缓存
  167. * - 判断是否显示赞助入口
  168. */
  169. async aboutToAppear() {
  170. Utility.enableFullScreen()
  171. this.topRectHeight = px2vp(AppUtil.getStatusBarHeight());
  172. Utility.getAppName(getContext(this)).then((appName: string) => {
  173. this.appName = appName
  174. })
  175. this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
  176. this.breakpointSystem.register();
  177. let params = router.getParams() as Record<string, Object>;
  178. this.videoLocalList = params.videoList as VideoItem[];
  179. // Utility.setStatusBarLight()
  180. ScreenUtil.setScreenSize();
  181. this.bundleName = AppUtil.getBundleName()
  182. this.versionName = AppUtil.getVersionName();
  183. // await ImageKnife.getInstance().initFileCache(this.context, 256, 256 * 1024 * 1024)
  184. this.isShowSponsorship = Utility.isOpenTime()
  185. let themeColor = PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR);
  186. hilog.info(0x0000, 'Heanup', '当前 NewIndex themeColor:' + themeColor);
  187. AppStorage.setOrCreate('themeColor', themeColor);
  188. this.themeColor = themeColor
  189. // ====== 本地会员同步提醒逻辑 ======
  190. // this.refreshUserInfoState();
  191. // if (this.isLogin) {
  192. // void this.fetchUserInfo();
  193. // }
  194. console.log('Heanup isLogin:' + this.isLogin)
  195. console.log('Heanup Utility.isNobleForOld():' + Utility.isNobleForOld())
  196. await UserUtil.fetchUserInfo();
  197. this.refreshUserInfoState();
  198. let changeUserState: emitter.InnerEvent = { eventId: 1001 }
  199. emitter.on(changeUserState, () => {
  200. this.refreshUserInfoState();
  201. });
  202. }
  203. /**
  204. * 页面消失生命周期钩子
  205. * 注销断点系统
  206. */
  207. aboutToDisappear() {
  208. console.info('NewIndex aboutToDisappear');
  209. this.breakpointSystem.unregister();
  210. emitter.off(888);
  211. emitter.off(1001);
  212. }
  213. build() {
  214. SideBarContainer(SideBarContainerType.AUTO) {
  215. Column() {
  216. this.getLeftView()
  217. }
  218. // .backgroundColor(Color.Transparent)
  219. Column() {
  220. Stack() {
  221. // 本地音乐内容区
  222. LocalMusic()
  223. .visibility(this.mType === 0 ? Visibility.Visible : Visibility.None)
  224. // 网络内容区
  225. UserCenter()
  226. .visibility(this.mType === 1 ? Visibility.Visible : Visibility.None)
  227. ScanFilePage()
  228. .visibility(this.mType === 2 ? Visibility.Visible : Visibility.None)
  229. SettingPage()
  230. .visibility(this.mType === 3 ? Visibility.Visible : Visibility.None)
  231. AboutPage()
  232. .visibility(this.mType === 4 ? Visibility.Visible : Visibility.None)
  233. // 抽屉打开时的遮罩层,用于拦截点击事件 这个只能正常尺寸的手机竖屏的才能生效
  234. if (this.isShowDrawer&&this.isPhonePortrait()) {
  235. Column()
  236. .width('100%')
  237. .height('100%')
  238. .backgroundColor(Color.Transparent)
  239. .onClick(() => {
  240. // 点击遮罩层关闭抽屉
  241. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  242. this.isShowDrawer = false
  243. })
  244. })
  245. }
  246. }
  247. }
  248. }
  249. .showControlButton(false)
  250. .minContentWidth(0)
  251. .sideBarWidth(this.isBigScreen() ? 300 : 270)
  252. .autoHide(true)
  253. .showSideBar($$this.isShowDrawer)
  254. .onChange((value: boolean) => {
  255. this.isShowDrawer = value
  256. })
  257. }
  258. //是不是正常的手机竖屏
  259. isPhonePortrait() {
  260. LogUtil.info('twocold this.currentHeightBreakpoint = '+this.currentHeightBreakpoint)
  261. LogUtil.info('twocold this.currentWidthBreakpoint = '+this.currentWidthBreakpoint)
  262. if(DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE
  263. &&this.currentHeightBreakpoint == HeightBreakpoint.HEIGHT_LG
  264. &&this.currentWidthBreakpoint==WidthBreakpoint.WIDTH_SM){//如果是手机横屏,返回false
  265. return true
  266. }
  267. return false
  268. }
  269. /**
  270. * 判断是否横屏
  271. * @returns
  272. */
  273. isBigScreen() {
  274. if (this.currentWidthBreakpoint == WidthBreakpoint.WIDTH_LG) {
  275. return true
  276. }
  277. if (DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE
  278. && this.currentWidthBreakpoint === WidthBreakpoint.WIDTH_SM
  279. && this.currentHeightBreakpoint == HeightBreakpoint.HEIGHT_LG) {
  280. return false
  281. } else {
  282. return true
  283. }
  284. return false
  285. }
  286. @Builder
  287. getLeftView() {
  288. Column() {
  289. Column() {
  290. this.buildUserInfoCard()
  291. this.getDrawerView()
  292. }
  293. .width('100%')
  294. .height('100%')
  295. .onClick((event: ClickEvent) => {
  296. // 点击抽屉内部不关闭,通过返回值阻止事件传播
  297. return true
  298. })
  299. }
  300. // .width(this.currentBreakpoint !== BreakpointTypeEnum.SM?'36%':'70%')
  301. .height('100%')
  302. .borderRadius({
  303. topLeft: 0,
  304. topRight: 20,
  305. bottomLeft: 0,
  306. bottomRight: 20
  307. })
  308. // .backgroundColor($r('app.color.silvery'))
  309. .backgroundColor($r('app.color.index_background'))
  310. .alignItems(HorizontalAlign.Start)
  311. .translate({ x: this.offsetX, y: 0, z: 0 })
  312. .transition({ type: TransitionType.Insert, translate: { x: -DisplayUtil.getWidth(), y: 0 } })
  313. .transition({ type: TransitionType.Delete, translate: { x: -DisplayUtil.getWidth(), y: 0 } })
  314. .gesture(
  315. PanGesture()
  316. .onActionUpdate((event: GestureEvent) => {
  317. // 手势滑动更新抽屉偏移
  318. if (event.offsetX < 0) {
  319. this.offsetX = event.offsetX;
  320. }
  321. })
  322. .onActionEnd(() => {
  323. // 手势结束判断是否关闭抽屉
  324. if (this.offsetX < -DisplayUtil.getWidth() / 15) {
  325. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  326. this.isShowDrawer = false
  327. })
  328. } else {
  329. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  330. this.isShowDrawer = true
  331. this.offsetX = 0
  332. })
  333. }
  334. })
  335. )
  336. }
  337. @State isLogin: boolean = false;
  338. @State userAvatar: Resource = $r('app.media.icon_person2');
  339. @State userAvatarUrl: string = '';
  340. @State isVip: boolean = false;
  341. @State isDarkMode: boolean = false
  342. @State userName: string = '未登录用户';
  343. @State userId: number = 0;
  344. @State hasActiveSubscription: boolean = false;
  345. @State subscriptionName: string = '';
  346. @State subscriptionEndDate: string = '';
  347. // 用户信息卡片
  348. @Builder
  349. buildUserInfoCard() {
  350. Column() {
  351. Row() {
  352. Stack({ alignContent: Alignment.BottomEnd }){
  353. Image(this.userAvatarUrl && this.userAvatarUrl.length > 0 ? this.userAvatarUrl : this.userAvatar)
  354. .width(55)
  355. .height(55)
  356. .margin({ left: 12 })
  357. .borderRadius('50%')
  358. .clip(true)
  359. // .fillColor(this.themeColor)
  360. .backgroundColor(this.isDarkMode ? Color.Black : Color.White)
  361. Column() {
  362. Text('VIP')
  363. .fontSize(9)
  364. .padding(2)
  365. .textAlign(TextAlign.Center)
  366. .fontWeight(FontWeight.Bolder)
  367. .fontColor(Color.White)
  368. }
  369. .width(28)
  370. .height(16)
  371. .visibility(Utility.isNoble()?Visibility.Visible:Visibility.None)
  372. .borderRadius(15)
  373. .backgroundColor(this.themeColor)
  374. }
  375. Column() {
  376. Row() {
  377. Text(this.isLogin ? this.userName : '未登录用户')
  378. .fontSize(14)
  379. // .fontWeight(FontWeight.Bold)
  380. .fontColor(this.isDarkMode ? Color.White : Color.Black)
  381. .textAlign(TextAlign.Start)
  382. .maxLines(1)
  383. .width(110)
  384. .margin({ right: 12 })
  385. }
  386. .justifyContent(FlexAlign.Start)
  387. .margin({ top: 2 })
  388. if (this.isLogin) {
  389. if (this.hasActiveSubscription) {
  390. // Text(this.subscriptionName)
  391. // .fontSize(13)
  392. // .fontColor(themeColorWithAlpha(this.themeColor, 0.8, false))
  393. // .textAlign(TextAlign.Start)
  394. // .padding({top:5})
  395. this.TimeTextBuilder()
  396. } else {
  397. Text('普通用户')
  398. .fontSize(13)
  399. .fontColor(this.isDarkMode ? Color.White : Color.Grey)
  400. .textAlign(TextAlign.Start)
  401. .padding({top:5})
  402. this.TimeTextBuilder()
  403. }
  404. } else {
  405. this.TimeTextBuilder()
  406. }
  407. }
  408. .alignItems(HorizontalAlign.Start)
  409. .width(80)
  410. .margin({ left: 10 })
  411. }
  412. .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.7})
  413. .onClick(() => {
  414. // if (!this.isLogin) {
  415. this.mType = 1
  416. if (!this.isBigScreen()) {
  417. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  418. this.isShowDrawer = false
  419. })
  420. // }
  421. }
  422. })
  423. .width('100%')
  424. .padding(10)
  425. }
  426. .backgroundColor($r('app.color.user_center_card_background'))
  427. .borderRadius(24)
  428. .width('86%')
  429. .padding(8)
  430. .margin({ left: 10, right: 10, top: this.topRectHeight + 10,bottom:10 })
  431. .shadow({
  432. radius: 8,
  433. color: 0x11000000,
  434. offsetX: 0,
  435. offsetY: 2
  436. })
  437. }
  438. @Builder
  439. TimeTextBuilder() {
  440. Text(Utility.getTimePeriod())
  441. .fontSize(13)
  442. .margin({ top: 5 })
  443. .fontColor($r('app.color.text_color'))
  444. .align(Alignment.Start)
  445. }
  446. /**
  447. * 动态生成抽屉菜单内容
  448. * 根据 isShowSponsorship 展示不同菜单项
  449. */
  450. @Builder
  451. getDrawerView() {
  452. List({ space: 0, scroller: this.scroller }) {
  453. ForEach(mainViewModel.getDrawerData2(), (item: ItemData, index: number) => {
  454. ListItem() {
  455. Button({ type: ButtonType.Capsule, stateEffect: true }) {
  456. Row() {
  457. // 菜单图标
  458. if (typeof item.img === 'object' && item.img !== null && (item.img as sysResource).type === 'symbol') {
  459. SymbolGlyph((item.img as sysResource).value as Resource)// .size({ width: 22, height: 22 })
  460. .fontSize(22)
  461. .fontColor([this.themeColor])
  462. .alignSelf(ItemAlign.Center)
  463. .margin({ left: 25 })
  464. } else {
  465. Image(item.img as Resource)
  466. .height(22)
  467. .alignSelf(ItemAlign.Center)
  468. .fillColor(this.themeColor)
  469. .margin({ left: 25 })
  470. }
  471. // 菜单标题
  472. Text(item.title)
  473. .margin({ left: 10, right: 20 })
  474. .fontSize(15)
  475. .fontColor(this.mType == index ? this.themeColor : $r('app.color.index_tab_font_color'))
  476. .fontWeight(480)
  477. Blank()
  478. // 右侧箭头
  479. Image($r('app.media.arrow_right'))
  480. .width(22)
  481. .height(22)
  482. .margin({ left: 20, right: 0 })
  483. .align(Alignment.Center)
  484. }
  485. .width('100%')
  486. .height(55)
  487. }
  488. .backgroundColor(Color.Transparent)
  489. .onClick(async () => {
  490. // 根据 item.id 跳转或切换功能
  491. switch (item.id) {
  492. case MainViewModel.MENU_MUSIC:
  493. this.mType = 0
  494. if (!this.isBigScreen()) {
  495. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  496. this.isShowDrawer = false
  497. })
  498. }
  499. break
  500. case MainViewModel.MENU_FILE_SCAN:
  501. this.mType = 2
  502. if (!this.isBigScreen()) {
  503. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  504. this.isShowDrawer = false
  505. })
  506. }
  507. break
  508. // case MainViewModel.MENU_HOME:
  509. // this.mType = 0
  510. // this.modeType = 0
  511. // this.getUIContext()?.animateTo({ duration: 555 }, () => {
  512. // this.isShowDrawer = false
  513. // })
  514. // break
  515. case MainViewModel.MENU_MIEDIA_KU:
  516. this.modeType = 1
  517. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  518. this.isShowDrawer = false
  519. })
  520. break
  521. case MainViewModel.MENU_MIEDIA_ARTIST:
  522. this.modeType = 2
  523. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  524. this.isShowDrawer = false
  525. })
  526. break
  527. case MainViewModel.MENU_MIEDIA_ALBUM:
  528. this.modeType = 3
  529. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  530. this.isShowDrawer = false
  531. })
  532. break
  533. case MainViewModel.MENU_SETTING:
  534. this.mType = 3
  535. if (!this.isBigScreen()) {
  536. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  537. this.isShowDrawer = false
  538. })
  539. }
  540. // router.pushUrl({
  541. // url: 'pages/SettingPage'
  542. // }, router.RouterMode.Single);
  543. break
  544. case MainViewModel.MENU_VIP:
  545. router.pushUrl({
  546. url: 'pages/VipPage'
  547. }, router.RouterMode.Single);
  548. break
  549. case MainViewModel.MENU_USER:
  550. this.mType = 1
  551. if (!this.isBigScreen()) {
  552. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  553. this.isShowDrawer = false
  554. })
  555. }
  556. // router.pushUrl({
  557. // url: 'pages/UserCenter'
  558. // }, router.RouterMode.Single);
  559. break
  560. case MainViewModel.MENU_NET_CONNECT:
  561. this.mType = 1
  562. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  563. this.isShowDrawer = false
  564. })
  565. break
  566. case MainViewModel.MENU_SIMI:
  567. router.pushUrl({
  568. url: 'pages/VerifyPage'
  569. });
  570. break
  571. case MainViewModel.MENU_LIKE:
  572. router.pushUrl({
  573. url: 'pages/LikeVideoPage'
  574. });
  575. break
  576. case MainViewModel.MENU_DUTY:
  577. router.pushUrl({
  578. url: 'pages/WebIndex',
  579. params: { titleName: '用户协议', webUrl: CommonConstants.NEW_DUTY }
  580. });
  581. break
  582. case MainViewModel.MENU_HAOPING:
  583. Utility.gotoMarket(getContext(this) as common.UIAbilityContext, this.bundleName)
  584. break
  585. case MainViewModel.MENU_TEST_SPEED:
  586. router.pushUrl({
  587. url: 'pages/SpeedIndex'
  588. });
  589. break
  590. case MainViewModel.MENU_OPTIMIZE:
  591. router.pushUrl({
  592. url: 'pages/AddSpeedPage'
  593. });
  594. break
  595. case MainViewModel.MENU_ABOUT:
  596. this.mType = 4
  597. if (!this.isBigScreen()) {
  598. this.getUIContext()?.animateTo({ duration: 555 }, () => {
  599. this.isShowDrawer = false
  600. })
  601. }
  602. // router.pushUrl({
  603. // url: 'pages/AboutPage'
  604. // }, router.RouterMode.Single);
  605. break
  606. case MainViewModel.MENU_UPDATE:
  607. AlertDialog.show({
  608. title: '版本更新',
  609. message: '当前版本为最新版本:' + this.versionName,
  610. autoCancel: true,
  611. alignment: DialogAlignment.Center,
  612. offset: { dx: 0, dy: -20 }, //在Y轴方向上的编译量
  613. confirm: {
  614. value: '确定',
  615. fontColor: Color.White,
  616. backgroundColor: $r('app.color.title_bar_bg'),
  617. action: () => {
  618. }
  619. }
  620. })
  621. break
  622. case MainViewModel.MENU_YSZC:
  623. router.pushUrl({
  624. url: 'pages/WebIndex',
  625. params: { titleName: '隐私政策', webUrl: CommonConstants.NEW_YS_HW }
  626. });
  627. break
  628. case MainViewModel.MENU_SHARE:
  629. this.gotoShare()
  630. break
  631. }
  632. })
  633. }
  634. .clickEffect({ level: ClickEffectLevel.HEAVY })
  635. .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
  636. .animation({ duration: 600, curve: Curve.Ease, delay: 60 * index }))
  637. .width('90%')
  638. .height(55)
  639. })
  640. }
  641. .width('86%')
  642. .borderRadius(20)
  643. .margin({
  644. bottom: 20,
  645. left: 10,
  646. right: 10,
  647. top: 10
  648. })
  649. .alignListItem(ListItemAlign.Center)
  650. .layoutWeight(1)
  651. .backgroundColor($r('app.color.silvery'))
  652. .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果
  653. }
  654. gotoShare() {
  655. let shareData: systemShare.SharedData = new systemShare.SharedData({
  656. utd: uniformTypeDescriptor.UniformDataType.TEXT,
  657. content: 'https://appgallery.huawei.com/app/detail?id=' + this.bundleName,
  658. title: this.appName, // 不传title字段时,显示content
  659. description: '精心雕琢的无损音乐播放器',
  660. // thumbnail: new Uint8Array() // 推荐传入适合的缩略图 不传则显示默认text图标
  661. });
  662. // 进行分享面板显示
  663. let controller: systemShare.ShareController = new systemShare.ShareController(shareData);
  664. let context = getContext(this) as common.UIAbilityContext;
  665. controller.show(context, {
  666. selectionMode: systemShare.SelectionMode.SINGLE,
  667. previewMode: systemShare.SharePreviewMode.DETAIL,
  668. }).then(() => {
  669. console.info('ShareController show success.');
  670. }).catch((error: BusinessError) => {
  671. console.error(`ShareController show error. code: ${error.code}, message: ${error.message}`);
  672. });
  673. }
  674. // /**
  675. // * ================== 穿山甲广告相关 ==================
  676. // */
  677. // /** Banner广告对象 */
  678. // private declare bannerAd: CSJNativeExpressAd;
  679. // /** 广告加载状态 */
  680. // @State private status: string = "未加载"
  681. // /** 是否展示广告 */
  682. // @State private isShowAd: boolean = false
  683. // /** 广告位配置信息 */
  684. // private declare mAdSlot: AdSlot;
  685. // /** 服务端bidding广告内容(可选) */
  686. // private mBiddingAdm = ''
  687. // /** 广告加载监听器 */
  688. // private expressLoadAdListener: NativeExpressAdListener = {
  689. // /**
  690. // * 广告加载失败回调
  691. // */
  692. // onError: (code: number, message: string) => {
  693. // console.error("加载广告失败,code=" + code + ",message=" + message);
  694. // this.status = "加载广告失败,code=" + code + ",message=" + message;
  695. // },
  696. // /**
  697. // * 广告加载成功回调
  698. // * @param ads 返回的广告列表
  699. // */
  700. // onNativeExpressAdLoad: (ads: ArrayList<CSJNativeExpressAd>) => {
  701. // console.log("BannerExpressAdPage==onNativeExpressAdLoad......success");
  702. // if (ads && ads.length > 0) {
  703. // ads.forEach((ad: CSJNativeExpressAd, idx: number) => {
  704. // // 设置广告交互监听
  705. // ad.setExpressInteractionListener({
  706. // /** 广告点击回调 */
  707. // onAdClicked: (type: number) => {
  708. // console.log("BannerExpressAdPage==onAdClicked......");
  709. // },
  710. // /** 广告展示回调 */
  711. // onAdShow: (type: number) => {
  712. // console.log("BannerExpressAdPage==onAdShow......");
  713. // },
  714. // /** 模板渲染失败回调 */
  715. // onRenderFail: (code: number, msg: string) => {
  716. // console.log("BannerExpressAdPage==onRenderFail...code=" + code + ",msg=" + msg);
  717. // },
  718. // /** 模板渲染成功回调 */
  719. // onRenderSuccess: (width: number, height: number) => {
  720. // console.log("BannerExpressAdPage==onRenderSuccess......width=" + width + ",height=" + height);
  721. // this.bannerAd = ad;
  722. // this.status = "广告加载完成待展示";
  723. // this.showBannerAd()
  724. // }
  725. // })
  726. // // 设置广告轮播时间
  727. // ad.setSlideIntervalTime(30 * 1000);//设置轮播时间长
  728. // this.setDislikeCallback(ad); //设置dislike
  729. // ad.render(this.getUIContext()) // 开始渲染广告
  730. // this.status = "广告加载中...";
  731. // });
  732. // }
  733. // }
  734. // }
  735. //
  736. // /**
  737. // * 设置广告 dislike 回调
  738. // * @param ad 广告对象
  739. // */
  740. // private setDislikeCallback(ad: CSJNativeExpressAd) {
  741. // ad.setDislikeCallback({
  742. // /** dislike 弹窗显示 */
  743. // onShow: () => {
  744. // console.log("BannerExpressAdPage==dislike......show");
  745. // },
  746. // /** 选择 dislike 选项 */
  747. // onSelected: (position: number, value: string, enforceRemove: boolean) => {
  748. // this.isShowAd = false;
  749. // console.log("BannerExpressAdPage==dislike......onSelected:position=" + position + ",value:" + value + ",enforce=" + enforceRemove);
  750. // },
  751. // /** 点击取消 dislike */
  752. // onCancel: () => {
  753. // console.log("BannerExpressAdPage==dislike......onCancel");
  754. // }
  755. // })
  756. // }
  757. //
  758. // /**
  759. // * 加载Banner广告
  760. // * @param rit 广告位ID
  761. // */
  762. // loadBannerAd(rit: string) {
  763. // // 仅在满足条件时加载广告
  764. // if(!Utility.isNoble()){
  765. // return
  766. // }
  767. // if(!Utility.isPassInstallTime(2)){
  768. // return
  769. // }
  770. // this.isShowAd = false;
  771. // let adCreator:CSJAdCreator = CSJAdSdk.getAdCreator()
  772. // this.mAdSlot = new AdSlotBuilder()
  773. // .setCodeId(rit)
  774. // .setAcceptSize(CSJUtil.BANNER_WIGTH, CSJUtil.BANNER_HEIGHT)
  775. // .setAdCount(1)
  776. // .setBidAdm(this.mBiddingAdm)
  777. // .build()
  778. // PrintBiddingTokenUtils.printBiddingToken(this.mAdSlot, adCreator);
  779. // adCreator.loadBannerAd(this.mAdSlot, this.expressLoadAdListener)
  780. // this.status = "广告加载中..."
  781. // }
  782. @StorageProp('currentHeightBreakpoint') currentHeightBreakpoint: HeightBreakpoint | undefined =
  783. HeightBreakpoint.HEIGHT_LG;
  784. @StorageProp('currentWidthBreakpoint') currentWidthBreakpoint: WidthBreakpoint | undefined = WidthBreakpoint.WIDTH_SM;
  785. @StorageProp('topRectHeight') topRectHeight: number = px2vp(AppUtil.getStatusBarHeight());
  786. //是否是Pura X外屏,或者小屏幕
  787. isPuraWP() {
  788. return this.currentWidthBreakpoint === WidthBreakpoint.WIDTH_SM
  789. && this.currentHeightBreakpoint === HeightBreakpoint.HEIGHT_MD
  790. }
  791. //是否是Pura X外屏,或者小屏幕或者手机横屏
  792. isCoverOpacity() {
  793. if (this.isPuraWP()) {
  794. return true
  795. }
  796. if (this.isPhoneLan()) {
  797. return true
  798. }
  799. if (deviceInfo.marketName.includes('Pura X')
  800. && this.currentHeightBreakpoint === HeightBreakpoint.HEIGHT_SM) {
  801. return true
  802. }
  803. return false
  804. }
  805. //是不是手机横屏
  806. isPhoneLan() {
  807. if (DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE
  808. && this.currentBreakpoint !== BreakpointTypeEnum.SM) {
  809. if (DisplayUtil.getFoldStatus() === 0) {
  810. return true
  811. }
  812. }
  813. return false
  814. }
  815. isLoginChange() {
  816. this.refreshUserInfoState();
  817. }
  818. }
  819. // 1. 工具函数:将 #RRGGBB 字符串和透明度转为 'rgba(r,g,b,a)' 字符串,深色模式下可返回深色变体
  820. function themeColorWithAlpha(themeColor: string, alpha: number, isDarkMode: boolean = false): string {
  821. if (isDarkMode) {
  822. // 深色模式下返回更深的灰色或半透明黑色
  823. return `rgba(34,34,34,${alpha + 0.2 > 1 ? 1 : alpha + 0.2})`;
  824. }
  825. const color = themeColor.replace('#', '');
  826. const r = parseInt(color.substring(0, 2), 16);
  827. const g = parseInt(color.substring(2, 4), 16);
  828. const b = parseInt(color.substring(4, 6), 16);
  829. return `rgba(${r},${g},${b},${alpha})`;
  830. }