import { AppUtil, ArrayUtil, DeviceUtil, DisplayUtil, LogUtil, PreferencesUtil, ToastUtil } from '@pura/harmony-utils'; import TitleBar from '../view/TitleBar'; import { curves, ImmersiveMode, LengthMetrics, LevelMode, MenuModifier, router, SegmentButton, SegmentButtonOptions, SymbolGlyphModifier } from '@kit.ArkUI'; import mainViewModel, { MainViewModel } from '../viewmodel/MainViewModel'; import ItemData from '../viewmodel/ItemData'; import type { sysResource } from '../viewmodel/ItemData'; import { CommonConstants } from '../common/constants/CommonConstants'; import { EventConstants } from '../common/constants/EventConstants'; import { VideoItem } from '../viewmodel/VideoItem'; import ScreenUtil from '../common/util/ScreenUtil'; import { Utility } from '../common/util/Utility'; import { BusinessError, emitter } from '@kit.BasicServicesKit'; import { common } from '@kit.AbilityKit'; import { BreakpointSystem, BreakpointTypeEnum } from '../common/util/BreakpointSystem'; import dataStorage from '@ohos.data.storage'; import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant'; import { SettingPage } from './SettingPage'; import { deviceInfo } from '@kit.BasicServicesKit'; import { resourceManager } from '@kit.LocalizationKit'; import { systemShare } from '@kit.ShareKit'; import { uniformTypeDescriptor } from '@kit.ArkData'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { DialogHelper, DialogAction } from '@pura/harmony-dialog'; import UserUtil from '../common/util/UserUtil'; import json from '@ohos.util.json'; import { UserCenter } from './UserCenter'; import { ScanFilePage } from './ScanFilePage'; import { AboutPage, gotoShare } from './AboutPage'; import { smartMobilityCommon } from '@kit.CarKit'; import { UpdateLogManager } from '../common/util/UpdateLogManager'; import OnlineUpdateLogDialog from '../dialog/OnlineUpdateLog'; import OnlineUpdateLog from '../dialog/OnlineUpdateLog'; import { LocalMusic } from '../view/LocalMusic'; import { ChartsCount } from './ChartsCount'; import { image } from '@kit.ImageKit'; import { Playlist, PlaylistSong } from '../viewmodel/Playlist'; import PlaylistTable from '../common/util/PlaylistTable'; import { convertPlaylistSongsToVideoItems } from './PlaylistDetailPage'; import MediaTable from '../common/util/MediaTable'; import { showCreatePlaylistDialog } from '../dialog/PlaylistDialog'; import { ImagePickerUtil } from '../common/util/ImagePickerUtil'; import { WebDavMainPage } from './WebDavMainPage'; import { WebDavAccount } from '../viewmodel/WebDavAccount'; import { RemoteDriveManager } from '../common/util/RemoteDriveManager'; import { RemoteDriveAccountDialog } from '../dialog/RemoteDriveAccountDialog'; import ReqPermissionUtil from '../common/util/ReqPermissionUtil'; import { getRemoteDriveAccountLabel, getRemoteDriveDisplayLabel, getRemoteDriveProtocolLabel } from '../common/util/RemoteDriveLabel'; import { RemoteDriveType } from '../common/enums/RemoteDriveType'; // import { FFmpeg, FFProgressMessageParser } from '@sj/ffmpeg'; const TAG = 'NewIndex'; // 日志标签 /** * 首页主组件,包含顶部标题栏、主内容区(本地音乐/网络内容)、侧边抽屉菜单等。 * 支持多端适配、广告集成、导航、生命周期管理等功能。 */ @Preview @Entry @Component struct NewIndex { /** 页面上下文 */ context = this.getUIContext().getHostContext() as common.UIAbilityContext @Provide currentSongListName:string = '' //当前歌单名称 @Provide currentSongListID:string='' //当前歌单ID @State isDarkMode: boolean = false /** 列表滚动器,用于抽屉菜单列表滚动 */ private scroller: Scroller = new Scroller(); /** 应用包名 */ @State bundleName: string = '' @State appName: string = '' /** 是否显示侧边抽屉菜单 */ @Provide isShowDrawer: boolean = false; /** 抽屉菜单 X 轴偏移量,用于手势滑动动画 */ @Provide offsetX: number = 0; /** 本地视频列表,页面参数传入 */ @Provide videoLocalList: Array = [] /** Y 轴偏移量(预留) */ @State offsetY: number = 0; /** 主内容类型(0:本地音乐,1:网络内容) */ @Provide mType: number = 0 /** 模式类型(如文件夹 媒体库 艺术家、专辑等) */ @Provide modeType: number = 0 /** 是否为零状态(预留) */ @Provide('isZero') isZero: boolean = false; /** 是否显示赞助入口 */ @State isShowSponsorship: boolean = false /** 音乐是否为零状态(预留) */ @Provide('isMusicZero') isMusicZero: boolean = false; @State isShowTitleBar: boolean = false //是否显示分类导航条 /** 本地音乐列表,持久化存储 */ @StorageLink('musicLocalList') musicLocalList: Array = [] @Provide isFavMusic: boolean = false @StorageProp('windowWidth') windowWidth: number = 0; @StorageProp('windowHeight') windowHeight: number = 0; @StorageProp('isHiCarStatus') isHiCarStatus: boolean = false; @StorageProp('curDisplayIsHiCar') curDisplayIsHiCar: boolean = false; @State idDefaultMediaKu: boolean = false /** * 是否显示更新日志开关 */ @State isShowUpdateDialog: boolean = false /** 标题栏配置模型 */ @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(() => { // 打开菜单栏动画 this.getUIContext()?.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 @StorageProp('currentColorMode') currentMode: number = ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT; @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR; /** * 一多界面适配断点系统 */ private breakpointSystem: BreakpointSystem = new BreakpointSystem(); /** 当前断点类型(如大屏/小屏) */ @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD; /** 记录上一次点击返回键的时间戳,用于双击退出 */ private backTime: number = 0; @State tabOptions: SegmentButtonOptions = SegmentButtonOptions.tab({ buttons: [{ text: '分类' }, { text: '歌单' }, { text: '网盘' }], direction: Direction.Ltr, backgroundColor: $r('app.color.index_background'), selectedBackgroundColor:$r('app.color.start_window_background'), selectedFontColor: $r('app.color.text_color'), localizedTextPadding: { end: LengthMetrics.vp(10), start: LengthMetrics.vp(10) } }) @State @Watch('tabSelectedIndexesChanged') tabSelectedIndexes: number[] = [0] //当胶囊按钮的选择发生变化时调用此函数 tabSelectedIndexesChanged() { if(this.tabSelectedIndexes[0]==1){ this.mType = 0 } else if(this.tabSelectedIndexes[0]==2){ // 网盘选项卡 this.mType = 6 } } // 歌单相关状态变量 @State playlistList: Playlist[] = [] @State isShowCreatePlaylistDialog: boolean = false @State selectedPlaylist: Playlist | null = null private playlistTable: PlaylistTable | null = null // 网盘账户相关状态变量 @State webDavAccounts: WebDavAccount[] = [] private webdavManager: RemoteDriveManager = RemoteDriveManager.getInstance() private _webDavLoading: boolean = false // 防止重复加载网盘账户的标志 @State selectedAccount: WebDavAccount = new WebDavAccount() /** * 返回键处理逻辑: * - 如果不是根目录或有历史记录,发送广播通知更新列表 * - 如果是根目录,双击返回键退出应用,否则提示 */ onBackPress(): boolean | void { if (this.currentPath !== this.rootPath || this.isHistory || this.isFavMusic || (this.modeType !== 0 && this.isCanBack)) { console.info('onecold 返回键处理逻辑:发送音频广播通知更新列表'); const eventData: emitter.EventData = {}; emitter.emit({ eventId: EventConstants.EVENT_SWIPE_BACK_UPDATE }, eventData); // 发送音频广播通知更新doSwipBack }else if(this.mType > 0){ this.getUIContext()?.animateTo({ duration: 555 }, () => { // 动画闭包内控制Image组件的出现和消失 // this.isShowDrawer = !this.isShowDrawer // this.offsetX = 0 this.mType =0 }) } else { console.info('onecold 返回键处理 关闭'); if (this.isShowDrawer) { // 如果抽屉菜单打开,先关闭抽屉 this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) } else { return false } } return true; } /** * 刷新@State用户信息变量,确保UI同步 */ refreshUserInfoState() { this.isLogin = PreferencesUtil.getBooleanSync('isLogin', false); this.userId = PreferencesUtil.getNumberSync('userId', 0); this.userName = PreferencesUtil.getStringSync('userName', '未登录用户'); this.userAvatarUrl = PreferencesUtil.getStringSync('userAvatarUrl', ''); this.subscriptionName = PreferencesUtil.getStringSync('subscriptionName', ''); this.subscriptionEndDate = PreferencesUtil.getStringSync('subscriptionEndDate', ''); this.hasActiveSubscription = PreferencesUtil.getBooleanSync('hasActiveSubscription', false); } onPageShow() { LogUtil.info('heanup NewIndex', 'onPageShow 被调用,刷新歌单列表和网盘账户列表') // 加载歌单列表 this.loadPlaylistList() // 加载网盘账户列表 this.loadWebDavAccounts() } /** * 页面显示生命周期钩子 * - 注册断点系统 * - 获取页面参数 * - 设置状态栏样式 * - 初始化图片缓存 * - 判断是否显示赞助入口 */ async aboutToAppear() { ReqPermissionUtil.reqPermissionsFromUser(ReqPermissionUtil.permissions, this.context); this.isShowTitleBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_TITLTBAR, false) this.idDefaultMediaKu = PreferencesUtil.getBooleanSync('idDefaultMediaKu', false) if(this.idDefaultMediaKu){ this.modeType = 1 } Utility.enableFullScreen() this.topRectHeight = px2vp(AppUtil.getStatusBarHeight()); Utility.getAppName(getContext(this)).then((appName: string) => { this.appName = appName }) this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK this.breakpointSystem.register(); let params = router.getParams() as Record; if (params && params.videoList) { this.videoLocalList = params.videoList as VideoItem[]; LogUtil.info('heanup NewIndex', '从路由参数获取到播放列表,长度:' + this.videoLocalList.length) } else { this.videoLocalList = [] LogUtil.info('heanup NewIndex', '路由参数中没有播放列表,使用空数组') } // 检查是否从WebDavPage返回 if (params && params.fromWebDavPage) { LogUtil.info('heanup NewIndex', '从WebDavPage返回,切换到网盘标签页') this.mType = 6 this.tabSelectedIndexes = [2] // 切换到网盘标签 } // Utility.setStatusBarLight() ScreenUtil.setScreenSize(); this.bundleName = AppUtil.getBundleName() this.versionName = AppUtil.getVersionName(); // await ImageKnife.getInstance().initFileCache(this.context, 256, 256 * 1024 * 1024) this.isShowSponsorship = Utility.isOpenTime() let themeColor = PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR); hilog.info(0x0000, 'Heanup', '当前 NewIndex themeColor:' + themeColor); AppStorage.setOrCreate('themeColor', themeColor); this.themeColor = themeColor // ====== 本地会员同步提醒逻辑 ====== // this.refreshUserInfoState(); // if (this.isLogin) { // void this.fetchUserInfo(); // } await UserUtil.fetchUserInfo(); this.refreshUserInfoState(); let changeUserState: emitter.InnerEvent = { eventId: EventConstants.EVENT_USER_STATE_CHANGE } emitter.on(changeUserState, () => { this.refreshUserInfoState(); }); let eventSetting: emitter.InnerEvent = { eventId: EventConstants.EVENT_SETTING_UPDATE } // 监听广播事件(通用设置配置更新) emitter.on(eventSetting, (eventData: emitter.EventData) => { this.isShowTitleBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_TITLTBAR, true) }); console.log('getHiCarStatus isHiCarStatus:' + this.isHiCarStatus) if(this.isHiCarStatus||this.isBigScreen()){ this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = true this.offsetX = 0 }) this.isShowTitleBar = false } // 检查并显示更新日志 this.checkAndShowUpdateLog(); // 初始化歌单数据库 await this.initPlaylistTable(); // 初始化WebDAV管理器 await this.initWebDavManager(); // 监听歌单刷新事件 emitter.on({ eventId: EventConstants.EVENT_PLAYLIST_REFRESH }, (eventData: emitter.EventData) => { LogUtil.info('heanup NewIndex', '收到歌单刷新事件,开始刷新歌单列表') this.loadPlaylistList() }); } /** * 检查并显示更新日志 */ private async checkAndShowUpdateLog() { try { const shouldShow = await UpdateLogManager.checkAndShowUpdateLog(); if (shouldShow) { this.isShowUpdateDialog = !this.isShowUpdateDialog UpdateLogManager.markCurrentVersionShown() } // this.isShowUpdateDialog = true;//调试期间显示更新日志,测试完成后请删除 } catch (error) { console.error('NewIndex checkAndShowUpdateLog error:', error); } } /** * 页面消失生命周期钩子 * 注销断点系统 */ aboutToDisappear() { console.info('NewIndex aboutToDisappear'); this.breakpointSystem.unregister(); emitter.off(EventConstants.EVENT_SWIPE_BACK_UPDATE); emitter.off(EventConstants.EVENT_USER_STATE_CHANGE); // 监听歌单刷新事件 emitter.off(EventConstants.EVENT_PLAYLIST_REFRESH); // 清理WebDAV管理器订阅 if (this.webdavManager) { this.webdavManager.observers = []; } } build() { SideBarContainer(SideBarContainerType.AUTO) { Column() { this.getLeftView() } .backgroundColor(Color.Transparent) Column() { Stack() { // 本地音乐内容区 LocalMusic() .visibility(this.mType === 0 ? Visibility.Visible : Visibility.None) // 网络内容区 UserCenter() .visibility(this.mType === 1 ? Visibility.Visible : Visibility.None) ScanFilePage() .visibility(this.mType === 2 ? Visibility.Visible : Visibility.None) ChartsCount({ isShowDrawer:this.isShowDrawer, offsetX:this.offsetX }) .visibility(this.mType === 3 ? Visibility.Visible : Visibility.None) SettingPage() .visibility(this.mType === 4 ? Visibility.Visible : Visibility.None) AboutPage() .visibility(this.mType === 5 ? Visibility.Visible : Visibility.None) WebDavMainPage({ offsetX:this.offsetX, isShowDrawer:this.isShowDrawer, mType:this.mType, selectedAccount:this.selectedAccount }) .visibility(this.mType === 6 ? Visibility.Visible : Visibility.None) // 抽屉打开时的遮罩层,用于拦截点击事件 这个只能正常尺寸的手机竖屏的才能生效 if (this.isShowDrawer&&this.isPhonePortrait()) { Column() .width('100%') .height('100%') .backgroundBlurStyle(BlurStyle.BACKGROUND_THIN) .transition(TransitionEffect.OPACITY.animation({ curve: curves.springMotion(0, 1) })) .onClick(() => { // 点击遮罩层关闭抽屉 this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) }) } } .bindSheet($$this.isShowUpdateDialog, this.updateSheet(), { height: '90%', dragBar: true, preferType: this.currentBreakpoint !== BreakpointTypeEnum.SM ? SheetType.CENTER : SheetType.BOTTOM, showClose: true, blurStyle: BlurStyle.Regular, title: { title: '更新日志' } }) } .gesture(SwipeGesture({ direction: SwipeDirection.Horizontal }).onAction((event: GestureEvent) => { if (event) {//手势返回 this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = !this.isShowDrawer if(this.isShowDrawer) this.offsetX = 0 }) } })) } .showControlButton(false) .minContentWidth(0) .sideBarWidth(260) .autoHide(true) .showSideBar($$this.isShowDrawer) .onChange((value: boolean) => { this.isShowDrawer = value }) } //是不是hicar的屏幕分辨率 isHiCar() { return this.isHiCarStatus&&this.curDisplayIsHiCar; return false; } //是不是正常的手机竖屏 isPhonePortrait() { LogUtil.info('twocold this.currentHeightBreakpoint = '+this.currentHeightBreakpoint) LogUtil.info('twocold this.currentWidthBreakpoint = '+this.currentWidthBreakpoint) if(DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE &&this.currentHeightBreakpoint == HeightBreakpoint.HEIGHT_LG &&this.currentWidthBreakpoint==WidthBreakpoint.WIDTH_SM){//如果是手机横屏,返回false return true } return false } /** * 判断是否横屏 * @returns */ isBigScreen() { if (this.currentWidthBreakpoint == WidthBreakpoint.WIDTH_LG) { return true } if (DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE && this.currentWidthBreakpoint === WidthBreakpoint.WIDTH_SM && this.currentHeightBreakpoint == HeightBreakpoint.HEIGHT_LG) { return false } else { return true } return false } @Builder getLeftView() { Column() { Column() { this.getDrawerView() } .width('100%') .height('100%') .onClick((event: ClickEvent) => { // 点击抽屉内部不关闭,通过返回值阻止事件传播 return true }) } // .width(this.currentBreakpoint !== BreakpointTypeEnum.SM?'36%':'70%') .height('100%') .borderRadius({ topLeft: 0, topRight: 20, bottomLeft: 0, bottomRight: 20 }) // .backgroundColor($r('app.color.silvery')) // .backgroundColor($r('app.color.index_background')) .backgroundColor($r('app.color.user_center_card_background')) .alignItems(HorizontalAlign.Start) .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() / 15) { this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) } else { this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = true this.offsetX = 0 }) } }) ) } @State isLogin: boolean = false; @State userAvatar: Resource = $r('app.media.icon_person2'); @State userAvatarUrl: string = ''; @State isVip: boolean = false; @State userName: string = '未登录用户'; @State userId: number = 0; @State hasActiveSubscription: boolean = false; @State subscriptionName: string = ''; @State subscriptionEndDate: string = ''; // 用户信息卡片 @Builder buildUserInfoCard() { Column() { this.userInfoView() Column({ space: 20 }) { SegmentButton({ options: this.tabOptions, selectedIndexes: $tabSelectedIndexes }) } .padding({ bottom:10 }) .width('90%') } } @Builder userInfoView() { Column() { Row() { Stack({ alignContent: Alignment.BottomEnd }){ Image(this.userAvatarUrl && this.userAvatarUrl.length > 0 ? this.userAvatarUrl : this.userAvatar) .width(55) .height(55) .margin({ left: 12 }) .borderRadius('50%') .clip(true) // .fillColor(this.themeColor) // .backgroundColor(this.isDarkMode ? Color.Black : Color.White) Column() { Text('VIP') .fontSize(9) .padding(2) .textAlign(TextAlign.Center) .fontWeight(FontWeight.Bolder) .fontColor(Color.White) } .width(28) .height(16) .visibility(Utility.isNoble()?Visibility.Visible:Visibility.None) .borderRadius(15) .backgroundColor(this.themeColor) } Column() { Row() { Text(this.isLogin ? this.userName : '未登录用户') .fontSize(14) // .fontWeight(FontWeight.Bold) // .fontColor(this.isDarkMode ? Color.White : Color.Black) .textAlign(TextAlign.Start) .maxLines(1) .width(110) .margin({ right: 12 }) } .justifyContent(FlexAlign.Start) .margin({ top: 2 }) if (this.isLogin) { if (this.hasActiveSubscription) { // Text(this.subscriptionName) // .fontSize(13) // .fontColor(themeColorWithAlpha(this.themeColor, 0.8, false)) // .textAlign(TextAlign.Start) // .padding({top:5}) this.TimeTextBuilder() } else { Text('普通用户') .fontSize(13) .fontColor(this.isDarkMode ? Color.White : Color.Grey) .textAlign(TextAlign.Start) .padding({top:5}) this.TimeTextBuilder() } } else { this.TimeTextBuilder() } } .alignItems(HorizontalAlign.Start) .width(80) .margin({ left: 10 }) } .clickEffect({level:ClickEffectLevel.LIGHT, scale: 0.7}) .onClick(() => { // if (!this.isLogin) { this.mType = 1 if (!this.isBigScreen()) { this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) // } } }) .width('100%') .padding(10) } .backgroundColor($r('app.color.user_center_card_background')) .borderRadius(24) .width('86%') .padding(8) .margin({ left: 10, right: 10, top: this.topRectHeight + 10,bottom:10 }) .shadow({ radius: 8, color: 0x11000000, offsetX: 0, offsetY: 2 }) } @Builder TimeTextBuilder() { Text(Utility.getTimePeriod()) .fontSize(13) .margin({ top: 5 }) .fontColor($r('app.color.text_color')) .align(Alignment.Start) } @State ratioL: number = 1; @State isRefreshing: boolean = false; @State maxRefreshingHeight: number = 100.0; private contentNode?: ComponentContent = undefined; /** * 动态生成抽屉菜单内容 * 根据 isShowSponsorship 展示不同菜单项 */ @Builder getDrawerView() { Refresh({ refreshing: $$this.isRefreshing, refreshingContent: this.contentNode }) { List({ space: 0, scroller: this.scroller }) { ListItemGroup({ header: this.buildUserInfoCard() }) { if(this.tabSelectedIndexes[0]==0){//分类 this.buildTabCate() }else if(this.tabSelectedIndexes[0]==1){//歌单 this.buildPlaylistTab() }else if(this.tabSelectedIndexes[0]==2){//网盘 this.buildCloudStorageTab() } } } .scrollBar(BarState.Off) .width('86%') .borderRadius(20) .margin({ bottom: 20, left: 10, right: 10, top: 10 }) .alignListItem(ListItemAlign.Center) .layoutWeight(1) .backgroundColor($r('app.color.left_draw_bg')) .edgeEffect(EdgeEffect.None) // 必须设置列表为滑动到边缘无效果 } .pullDownRatio(this.ratioL) .pullToRefresh(true) .refreshOffset(0) .onOffsetChange((offset: number) => { // 越接近最大距离,下拉跟手系数越小。 this.ratioL = 1 - Math.pow((offset / this.maxRefreshingHeight), 3); }) .onStateChange((refreshStatus: RefreshStatus) => { console.info('onecold Refresh onStatueChange state is ' + refreshStatus); }) .onRefreshing(async () => { if(this.tabSelectedIndexes[0]==0){//分类 this.isRefreshing = false }else if(this.tabSelectedIndexes[0]==1){//歌单 this.loadPlaylistList() }else if(this.tabSelectedIndexes[0]==2){//网盘 this.loadWebDavAccounts() } }) } @Builder buildTabCate() { ForEach(mainViewModel.getDrawerData(), (item: ItemData, index: number) => { ListItem() { Button({ type: ButtonType.Capsule, stateEffect: true }) { Row() { // 菜单图标 if (typeof item.img === 'object' && item.img !== null && (item.img as sysResource).type === 'symbol') { SymbolGlyph((item.img as sysResource).value as Resource)// .size({ width: 22, height: 22 }) .fontSize(22) .fontColor([this.themeColor]) .effectStrategy(SymbolEffectStrategy.HIERARCHICAL) .alignSelf(ItemAlign.Center) .margin({ left: 15 }) } else { Image(item.img as Resource) .height(22) .alignSelf(ItemAlign.Center) .fillColor(this.themeColor) .margin({ left: 15 }) } // 菜单标题 Text(item.title) .margin({ left: 10, right: 20 }) .fontSize(15) .fontColor(this.isTextSelected(index) ? this.themeColor : $r('app.color.index_tab_font_color')) .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) } .backgroundColor(Color.Transparent) .clickEffect({ level: ClickEffectLevel.MIDDLE,scale:0.6 }) .onClick(async () => { // 根据 item.id 跳转或切换功能 switch (item.id) { case MainViewModel.MENU_MUSIC: this.mType = 0 this.modeType = 0 this.currentSongListID = '' this.doShowDrawer() break case MainViewModel.MENU_FILE_SCAN: this.mType = 2 this.doShowDrawer() break case MainViewModel.MENU_CHARTS: this.mType = 3 this.modeType = 0 this.doShowDrawer() break case MainViewModel.MENU_MIEDIA_KU: this.modeType = 1 this.mType = 0 this.currentSongListID = '' this.doShowDrawer() break case MainViewModel.MENU_MIEDIA_ARTIST: this.modeType = 2 this.mType = 0 this.currentSongListID = '' this.doShowDrawer() break case MainViewModel.MENU_MIEDIA_ALBUM: this.modeType = 3 this.mType = 0 this.currentSongListID = '' this.doShowDrawer() break case MainViewModel.MENU_SETTING: this.mType = 4 this.doShowDrawer() break case MainViewModel.MENU_VIP: router.pushUrl({ url: 'pages/VipPage' }, router.RouterMode.Single); break case MainViewModel.MENU_USER: this.mType = 1 this.doShowDrawer() break case MainViewModel.MENU_NET_CONNECT: this.mType = 1 this.doShowDrawer() break case MainViewModel.MENU_SIMI: router.pushUrl({ url: 'pages/VerifyPage' }); 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_ABOUT: this.mType = 5 this.doShowDrawer() 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 case MainViewModel.MENU_SHARE: gotoShare(this.context,this.appName,this.bundleName) break } }) } .transition(TransitionEffect.move(TransitionEdge.BOTTOM) .animation({ duration: 600, curve: Curve.Ease, delay: 60 * index })) .width('90%') .height(55) }) } isTextSelected(index:number):boolean{ if(this.isShowTitleBar&&!this.isHiCar()){ return this.mType ==index }else{ if(this.mType == 0){ return this.modeType == index } return this.mType+3 == index } return false } doShowDrawer(){ if (!this.isBigScreen()) { this.getUIContext()?.animateTo({ duration: 555 }, () => { this.isShowDrawer = false }) } } @Builder updateSheet() { Scroll() { Column() { OnlineUpdateLog() } } .width('100%') .height('100%') } // /** // * ================== 穿山甲广告相关 ================== // */ // /** 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 = "广告加载中..." // } @StorageProp('currentHeightBreakpoint') currentHeightBreakpoint: HeightBreakpoint | undefined = HeightBreakpoint.HEIGHT_LG; @StorageProp('currentWidthBreakpoint') currentWidthBreakpoint: WidthBreakpoint | undefined = WidthBreakpoint.WIDTH_SM; @StorageProp('topRectHeight') topRectHeight: number = px2vp(AppUtil.getStatusBarHeight()); //是否是Pura X外屏,或者小屏幕 isPuraWP() { return this.currentWidthBreakpoint === WidthBreakpoint.WIDTH_SM && this.currentHeightBreakpoint === HeightBreakpoint.HEIGHT_MD } //是否是Pura X外屏,或者小屏幕或者手机横屏 isCoverOpacity() { if (this.isPuraWP()) { return true } if (this.isPhoneLan()) { return true } if (deviceInfo.marketName.includes('Pura X') && this.currentHeightBreakpoint === HeightBreakpoint.HEIGHT_SM) { return true } return false } //是不是手机横屏 isPhoneLan() { if (DeviceUtil.getDeviceType() === resourceManager.DeviceType.DEVICE_TYPE_PHONE && this.currentBreakpoint !== BreakpointTypeEnum.SM) { if (DisplayUtil.getFoldStatus() === 0) { return true } } return false } isLoginChange() { this.refreshUserInfoState(); } /** * 构建歌单tab内容 */ @Builder buildPlaylistTab() { // 创建歌单按钮 ListItem() { Button({ type: ButtonType.Capsule, stateEffect: true }) { Row() { SymbolGlyph($r('sys.symbol.plus_circle')) .fontSize(22) .fontColor([this.themeColor]) .effectStrategy(SymbolEffectStrategy.HIERARCHICAL) .alignSelf(ItemAlign.Center) .margin({ left: 25 }) Text('创建歌单') .margin({ left: 10, right: 20 }) .fontSize(14) .fontColor($r('app.color.index_tab_font_color')) .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) } .backgroundColor(Color.Transparent) .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.6 }) .onClick(() => { this.showCreatePlaylistDialog() }) } // 歌单列表 ForEach(this.playlistList, (playlist: Playlist,index:number) => { ListItem() { Button({ type: ButtonType.Capsule, stateEffect: true }) { Row() { Image(playlist.coverPath || $r('app.media.hm_playlist')) .width(22) .height(22) .margin({ left: 25 }) .borderRadius(4) .fillColor(this.themeColor) .clip(true) Column() { Text(playlist.name) .margin({ left: 10, right: 20 }) .fontSize(15) .fontColor($r('app.color.index_tab_font_color')) .fontWeight(480) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) Text(`${playlist.songCount}首`) .margin({ left: 10, right: 20 }) .fontSize(12) .fontColor($r('app.color.index_tab_font_color')) .opacity(0.7) } .alignItems(HorizontalAlign.Start) Blank() Image($r('app.media.arrow_right')) .width(22) .height(22) .margin({ left: 20, right: 0 }) .align(Alignment.Center) } .width('100%') .height(55) } .backgroundColor(Color.Transparent) .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.6 }) .onClick(async () => { if(playlist.songCount==0){ this.openPlaylist(playlist) }else{ this.doShowDrawer(); this.mType = 0 this.modeType = 4 this.currentSongListName = playlist.name; this.currentSongListID = playlist.id; } }) .bindContextMenu(this.MenuBuilder(playlist), ResponseType.LongPress, { preview: MenuPreviewMode.IMAGE, previewAnimationOptions: { scale: [0.8, 1.0] }, }) .bindContextMenu(this.MenuBuilder(playlist), ResponseType.RightClick, { preview: MenuPreviewMode.IMAGE, previewAnimationOptions: { scale: [0.8, 1.0] }, }) } .transition(TransitionEffect.move(TransitionEdge.BOTTOM) .animation({ duration: 600, curve: Curve.Ease, delay: 60 * index })) }) } /** * 构建网盘tab内容 - 从数据库获取所有网盘账户 * 支持多种类型的网盘账户(目前支持WebDAV,将来可扩展其他类型) */ @Builder buildCloudStorageTab() { // 当前只支持网盘账户,将来可以在这里添加其他类型的网盘账户 // 例如:OneDrive, Google Drive, Dropbox等 // 添加新账户按钮 ListItem() { Button({ type: ButtonType.Capsule, stateEffect: true }) { Row() { SymbolGlyph($r('sys.symbol.plus_circle')) .fontSize(22) .fontColor([this.themeColor]) .effectStrategy(SymbolEffectStrategy.HIERARCHICAL) .alignSelf(ItemAlign.Center) .margin({ left: 25 }) Text(`添加${getRemoteDriveAccountLabel()}`) .margin({ left: 10, right: 20 }) .fontSize(14) .fontColor($r('app.color.index_tab_font_color')) .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) } .backgroundColor(Color.Transparent) .bindMenu(this.AddMenuBuilder) .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.6 }) } // 显示所有网盘账户 ForEach(this.webDavAccounts, (account: WebDavAccount,index:number) => { ListItem() { Button({ type: ButtonType.Capsule, stateEffect: true }) { Row() { // 账户封面或默认图标 Stack() { Image(account.coverPath?account.coverPath:$r('app.media.cloudDisk')) .width(25) .height(25) .borderRadius(4) .fillColor(this.themeColor) .objectFit(ImageFit.Cover) } .margin({ left: 20 }) Column() { // 账户名称 Text(account.name) .margin({ left: 8, right: 20 }) .fontSize(15) .fontColor(this.selectedAccount==account?this.themeColor:$r('app.color.text_color')) .fontWeight(480) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) Row() { // 账户类型标签 Text(getRemoteDriveDisplayLabel(account.webType)) .fontSize(10) .fontColor(this.selectedAccount==account?this.themeColor:$r('app.color.index_tab_font_color')) .opacity(0.8) .padding({ left: 8, top: 2, bottom: 2 }) .borderRadius(3) // 服务器地址 Text(`@${account.isUseLocalHost ? account.localHost : account.host}:${account.port}`) .fontSize(12) .fontColor(this.selectedAccount==account?this.themeColor:$r('app.color.index_tab_font_color')) .opacity(0.7) .maxLines(1) .padding({ right: 8, top: 2, bottom: 2 }) .textOverflow({ overflow: TextOverflow.Ellipsis }) } } .alignItems(HorizontalAlign.Start) Blank() Image($r('app.media.arrow_right')) .width(22) .height(22) .margin({ left: 20, right: 0 }) .align(Alignment.Center) } .width('100%') .height(60) } .backgroundColor(Color.Transparent) .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.8 }) .onClick(() => { console.info('heanup', '点击网盘账户:', account.name) this.selectWebDavAccount(account) }) .bindContextMenu(this.MenuDavBuilder(account), ResponseType.LongPress, { preview: MenuPreviewMode.IMAGE, previewAnimationOptions: { scale: [0.8, 1.0] }, }) .bindContextMenu(this.MenuDavBuilder(account), ResponseType.RightClick, { preview: MenuPreviewMode.IMAGE, previewAnimationOptions: { scale: [0.8, 1.0] }, }) } .transition(TransitionEffect.move(TransitionEdge.BOTTOM) .animation({ duration: 600, curve: Curve.Ease, delay: 60 * index })) }) // 如果没有账户,显示提示信息 if (this.webDavAccounts.length === 0) { ListItem() { Text(`暂无${getRemoteDriveAccountLabel()},点击上方按钮添加`) .fontSize(14) .fontColor($r('app.color.index_tab_font_color')) .opacity(0.6) .textAlign(TextAlign.Center) .width('100%') .padding(20) } } } @Builder AddMenuBuilder() { Menu() { MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.smallcircle_filled_circle')), content: $r('app.string.webdav') }) .onClick(async () => { this.showRemoteDriveAccountDialog(false,undefined,RemoteDriveType.WebDav) }) MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.smallcircle_filled_circle')), content: $r('app.string.smb') }) .onClick(async () => { this.showRemoteDriveAccountDialog(false,undefined,RemoteDriveType.Smb) }) MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.smallcircle_filled_circle')), content: $r('app.string.navidrome') }) .onClick(async () => { this.showRemoteDriveAccountDialog(false,undefined,RemoteDriveType.Navidrome) }) }.attributeModifier(new MenuModifier()) } @Builder MenuBuilder(playlist: Playlist) { Menu(){ MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.square_and_pencil')), content: '编辑歌单' }) .onClick(async() => { this.openPlaylist(playlist) }) MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.trash')), content: '删除歌单' }) .onClick(async() => { this.deletePlaylist(playlist) }) } } @Builder MenuDavBuilder(account: WebDavAccount) { Menu(){ MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.square_and_pencil')), content: '编辑' }) .onClick(async() => { this.showRemoteDriveAccountDialog(true,account) }) MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.trash')), content: '删除' }) .onClick(async() => { this.deleteWebDavAccount(account) }) } } /** * 删除网盘账户 */ async deleteWebDavAccount(account: WebDavAccount) { try { // 显示确认对话框 this.getUIContext().showAlertDialog({ title: '删除账户', message: `确定要删除webdav账户"${account.name}"吗?`, primaryButton: { value: '取消', action: () => {} }, secondaryButton: { value: '删除', fontColor: Color.Red, action: async () => { try { await this.webdavManager.removeAccount(account) ToastUtil.showToast('网盘账户删除成功') // 重新加载网盘账户列表 await this.loadWebDavAccounts() LogUtil.info('heanup NewIndex', '网盘账户删除成功:', account.name) } catch (error) { LogUtil.error('heanup NewIndex', `删除网盘账户失败: ${(error as Error).message}`) ToastUtil.showToast('删除失败') } } } }) } catch (error) { LogUtil.error('heanup NewIndex', `删除网盘账户操作失败: ${(error as Error).message}`) ToastUtil.showToast('操作失败') } } /** * 删除歌单 */ async deletePlaylist(playlist: Playlist) { if (playlist&&this.playlistTable) { // 显示确认对话框 AlertDialog.show({ title: '删除歌单', message: `确定要删除歌单"${playlist.name}"吗?此操作不可撤销。`, primaryButton: { value: '取消', action: () => {} }, secondaryButton: { value: '删除', fontColor: Color.Red, action: async () => { if (this.playlistTable) { const success = await this.playlistTable.deletePlaylist(playlist.id) if (success) { ToastUtil.showToast('歌单删除成功') // 发送刷新事件 emitter.emit({ eventId: EventConstants.EVENT_PLAYLIST_REFRESH }, {}) } else { ToastUtil.showToast('歌单删除失败') } } } } }) } } /** * 显示创建歌单对话框 */ showCreatePlaylistDialog() { if (!this.playlistTable) { ToastUtil.showToast('歌单功能初始化中,请稍后再试') return } // 使用新的歌单对话框,支持自定义封面 showCreatePlaylistDialog( async (name: string, description: string, coverPath?: string) => { // 创建歌单 const success = await this.playlistTable!.createPlaylist(name, description, coverPath) if (success) { ToastUtil.showToast('歌单创建成功') // 刷新歌单列表 await this.loadPlaylistList() // 发送歌单刷新事件 emitter.emit({ eventId: EventConstants.EVENT_PLAYLIST_REFRESH }, {}) } else { ToastUtil.showToast('歌单创建失败') } }, () => { // 取消创建歌单 } ) } /** * 打开歌单详情 */ openPlaylist(playlist: Playlist) { try { // 跳转到歌单详情页面 router.pushUrl({ url: 'pages/PlaylistDetailPage', params: { playlist: playlist } }).catch((err: Error) => { console.error('跳转到歌单详情页面失败:', err.message); ToastUtil.showToast('打开歌单失败'); }); } catch (error) { console.error('打开歌单失败:', error); ToastUtil.showToast('打开歌单失败'); } } /** * 初始化歌单数据库 */ async initPlaylistTable() { try { this.playlistTable = new PlaylistTable(this.context) console.info('onecold 歌单数据库初始化成功') // 等待数据库初始化完成后再加载数据 setTimeout(async () => { await this.loadPlaylistList() }, 500) // 延迟500ms确保数据库初始化完成 } catch (error) { console.error('初始化歌单数据库失败:', error) } } /** * 加载歌单列表 */ async loadPlaylistList() { try { LogUtil.info('heanup NewIndex', '开始加载歌单列表') if (this.playlistTable) { const playlists = await this.playlistTable.queryAllPlaylists() // 强制触发UI更新 this.playlistList = playlists.slice() LogUtil.info('heanup NewIndex', `成功加载 ${playlists.length} 个歌单`) } else { LogUtil.warn('heanup NewIndex', '歌单表未初始化') } this.isRefreshing = false } catch (error) { LogUtil.error('heanup NewIndex', `加载歌单列表失败: ${(error as Error).message}`) this.isRefreshing = false } } /** * 初始化WebDAV管理器 */ async initWebDavManager() { try { // 设置WebDAV管理器的上下文 this.webdavManager.setContext(this.context) // 创建网盘账户表 await this.webdavManager.createWebDavTableInDB() // 订阅WebDAV管理器事件 this.webdavManager.subscribe((event: string) => { LogUtil.info('heanup NewIndex', '收到WebDAV事件:', event) if (event === 'QueryAccountsSucceed') { this.webDavAccounts = this.webdavManager.getAllWebDavAccounts().slice() } }) // 首页EntryAblility去加载网盘账户了。所以这边不加载 // await this.loadWebDavAccounts() LogUtil.info('heanup NewIndex', 'WebDAV管理器初始化成功') } catch (error) { LogUtil.error('heanup NewIndex', `初始化WebDAV管理器失败: ${(error as Error).message}`) } } /** * 加载网盘账户列表 */ async loadWebDavAccounts() { try { LogUtil.info('heanup NewIndex', '开始加载网盘账户列表') await this.webdavManager.queryWebDavAccountsFromDB() // 强制触发UI更新 this.webDavAccounts = this.webdavManager.getAllWebDavAccounts().slice() this.isRefreshing = false LogUtil.info('heanup NewIndex', `成功加载 ${this.webDavAccounts.length} 个网盘账户`) } catch (error) { this.isRefreshing = false LogUtil.error('heanup NewIndex', `加载网盘账户列表失败: ${(error as Error).message}`) } } /** * 选择网盘账户 */ selectWebDavAccount(account: WebDavAccount) { try { LogUtil.info('heanup NewIndex', '选择网盘账户:', account.name) // 如果账户未激活,先激活它 if (!account.isActivate) { // 先将所有账户设为未激活 this.webDavAccounts.forEach(acc => { acc.isActivate = false }) // 激活选中的账户 account.isActivate = true // 更新数据库中的激活状态 this.webdavManager.editAccount(account).then(() => { LogUtil.info('heanup NewIndex', '网盘账户编辑成功:', account.name) }).catch((error: Error) => { LogUtil.error('heanup NewIndex', `编辑网盘账户失败: ${error.message}`) ToastUtil.showToast('编辑账户失败') }) } this.selectedAccount = account // 切换到WebDAV页面 this.mType = 6 this.doShowDrawer() } catch (error) { LogUtil.error('heanup NewIndex', `选择网盘账户失败: ${(error as Error).message}`) ToastUtil.showToast('选择账户失败') } } /** * 显示添加网盘账户对话框 */ @State addDavDialogId:number = 1 showRemoteDriveAccountDialog(isEditMode?: boolean,account?: WebDavAccount,driveType?:number) { const node: FrameNode | null = this.getUIContext().getFrameNodeById("test_text") || null; this.getUIContext().getPromptAction().openCustomDialog({ builder: () => { this.webDavAccountBuilder(isEditMode,account,driveType) }, levelMode: LevelMode.EMBEDDED, // 启用页面级弹出框 levelUniqueId: node?.getUniqueId(), // 设置页面级弹出框所在页面的任意节点ID immersiveMode: ImmersiveMode.EXTEND, // 设置页面级弹出框蒙层的显示模式 }).then((dialogId: number) => { this.addDavDialogId = dialogId; }) } @Builder webDavAccountBuilder(isEditMode?: boolean,account?: WebDavAccount,driveType?:number) { RemoteDriveAccountDialog({ isEditMode: isEditMode, account: account, driveType: driveType, onCancel: () => { // 取消添加 this.getUIContext().getPromptAction().closeCustomDialog(this.addDavDialogId) }, onConfirm: (account: WebDavAccount) => { this.getUIContext().getPromptAction().closeCustomDialog(this.addDavDialogId) if (isEditMode && account?.id) { // 编辑模式:更新现有账户 this.webdavManager.editAccount(account).then(() => { ToastUtil.showToast('修改成功') // 重新加载网盘账户列表,观察着模式去更新了,所以这里不需要更新,先注释掉 // this.loadWebDavAccounts() LogUtil.info('heanup NewIndex', '网盘账户修改成功:', account.name) }).catch((error: Error) => { LogUtil.error('heanup NewIndex', `修改网盘账户失败: ${error.message}`) ToastUtil.showToast('修改失败') }) } else { // 添加模式:创建新账户 this.webdavManager.insertAccount( account.name, account.host, account.localHost, account.isUseLocalHost, account.port, account.filepath, account.lyricFilePath, account.uploadFilePath, account.imageFilePath, account.account, account.password, account.enableHttps, account.coverPath, account.webType, account.smbShare, account.smbDomain, account.navidromeBasePath ).then(() => { ToastUtil.showToast('添加成功') // 重新加载网盘账户列表 观察着模式去更新了,所以这里不需要更新,先注释掉 // this.loadWebDavAccounts() LogUtil.info('heanup NewIndex', '网盘账户添加成功:', account.name) }).catch((error: Error) => { LogUtil.error('heanup NewIndex', `添加网盘账户失败: ${error.message}`) ToastUtil.showToast('添加失败') }) } } }); } } // 1. 工具函数:将 #RRGGBB 字符串和透明度转为 'rgba(r,g,b,a)' 字符串,深色模式下可返回深色变体 function themeColorWithAlpha(themeColor: string, alpha: number, isDarkMode: boolean = false): string { if (isDarkMode) { // 深色模式下返回更深的灰色或半透明黑色 return `rgba(34,34,34,${alpha + 0.2 > 1 ? 1 : alpha + 0.2})`; } const color = themeColor.replace('#', ''); const r = parseInt(color.substring(0, 2), 16); const g = parseInt(color.substring(2, 4), 16); const b = parseInt(color.substring(4, 6), 16); return `rgba(${r},${g},${b},${alpha})`; } // 定义接口 interface HiCarAspectRatio { context: Context; playlistId: string; }