Răsfoiți Sursa

添加歌单增加一个文件目录布局

onecold 9 luni în urmă
părinte
comite
7fd84d093c

+ 127 - 16
entry/src/main/ets/dialog/AddSongsToPlaylistDialog.ets

@@ -7,6 +7,8 @@ import PlaylistTable from '../common/util/PlaylistTable';
 import { LazyDataSource } from '../common/util/LazyDataSource';
 import { LazyDataSource } from '../common/util/LazyDataSource';
 import { ConfigurationConstant, common } from '@kit.AbilityKit';
 import { ConfigurationConstant, common } from '@kit.AbilityKit';
 import { CommonConstants } from '../common/constants/CommonConstants';
 import { CommonConstants } from '../common/constants/CommonConstants';
+import { SegmentButton } from '@kit.ArkUI';
+import { SegmentButtonOptions, SegmentButtonItemTuple } from '@kit.ArkUI';
 
 
 // 工具函数:将 #RRGGBB 字符串和透明度转为 'rgba(r,g,b,a)' 字符串,深色模式下可返回深色变体
 // 工具函数:将 #RRGGBB 字符串和透明度转为 'rgba(r,g,b,a)' 字符串,深色模式下可返回深色变体
 function themeColorWithAlpha(themeColor: string, alpha: number, isDarkMode: boolean = false): string {
 function themeColorWithAlpha(themeColor: string, alpha: number, isDarkMode: boolean = false): string {
@@ -21,6 +23,9 @@ function themeColorWithAlpha(themeColor: string, alpha: number, isDarkMode: bool
   return `rgba(${r},${g},${b},${alpha})`;
   return `rgba(${r},${g},${b},${alpha})`;
 }
 }
 
 
+// 定义SegmentButton按钮元组类型
+const viewModeButtons: SegmentButtonItemTuple = [{ text: '全部' }, { text: '目录' }];
+
 /**
 /**
  * 添加歌曲到歌单对话框内容组件
  * 添加歌曲到歌单对话框内容组件
  */
  */
@@ -31,7 +36,7 @@ struct AddSongsToPlaylistDialogContent {
   @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
   @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
   @State isDarkMode: boolean = false
   @State isDarkMode: boolean = false
   @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
   @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
-    ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
+    ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
 
 
   onColorModeChange() {
   onColorModeChange() {
     this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
     this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
@@ -56,6 +61,22 @@ struct AddSongsToPlaylistDialogContent {
   // 回调函数
   // 回调函数
   onConfirm?: (songs: VideoItem[]) => void
   onConfirm?: (songs: VideoItem[]) => void
   onCancel?: () => void
   onCancel?: () => void
+  
+  // 添加目录浏览相关状态
+  @State viewMode: number[] = [0]; // 0: 全部歌曲, 1: 目录模式
+  @State currentPath: string = '';
+  @State folderItems: VideoItem[] = [];
+  @State selectedFolders: Set<string> = new Set();
+  @State isFolderLoading: boolean = false;
+  // SegmentButton选项配置
+  @State viewModeOptions: SegmentButtonOptions = SegmentButtonOptions.capsule({
+    buttons: viewModeButtons,
+    backgroundColor: $r('app.color.index_background'),
+    selectedBackgroundColor: $r('app.color.start_window_background'),
+    selectedFontColor: $r('app.color.text_color'),
+    buttonPadding: { top: 10, bottom: 10 },
+    multiply: false
+  });
 
 
   aboutToAppear() {
   aboutToAppear() {
     // 初始化深色模式状态
     // 初始化深色模式状态
@@ -194,6 +215,14 @@ struct AddSongsToPlaylistDialogContent {
       .backgroundColor(this.isDarkMode ? '#2C2C2E' : $r('app.color.input_background'))
       .backgroundColor(this.isDarkMode ? '#2C2C2E' : $r('app.color.input_background'))
       .borderRadius(20)
       .borderRadius(20)
 
 
+      // 视图模式切换 SegmentButton
+      SegmentButton({
+        options: this.viewModeOptions,
+        selectedIndexes: $viewMode
+      })
+        .width('100%')
+        .margin({ top: 8 })
+
       // 已选择歌曲数量
       // 已选择歌曲数量
       if (this.selectedSongs.length > 0) {
       if (this.selectedSongs.length > 0) {
         Row() {
         Row() {
@@ -236,23 +265,29 @@ struct AddSongsToPlaylistDialogContent {
         .padding({ left: 4, right: 4 })
         .padding({ left: 4, right: 4 })
       }
       }
 
 
-      // 歌曲列表
-      if (this.dataSource.dataArray.length === 0 && this.isSearchMode) {
-        Column({ space: 12 }) {
-          Image($r('app.media.music_red'))
-            .width(64)
-            .height(64)
-            .opacity(0.3)
-
-          Text(this.searchText ? '没有找到匹配的歌曲' : '没有可添加的歌曲')
-            .fontSize(14)
-            .fontColor(this.isDarkMode ? '#8E8E93' : '#999999')
+      // 歌曲列表或目录列表
+      if (this.viewMode[0] === 0) {
+        // 全部歌曲模式
+        if (this.dataSource.dataArray.length === 0 && this.isSearchMode) {
+          Column({ space: 12 }) {
+            Image($r('app.media.music_red'))
+              .width(64)
+              .height(64)
+              .opacity(0.3)
+
+            Text(this.searchText ? '没有找到匹配的歌曲' : '没有可添加的歌曲')
+              .fontSize(14)
+              .fontColor(this.isDarkMode ? '#8E8E93' : '#999999')
+          }
+          .width('100%')
+          .height(300)
+          .justifyContent(FlexAlign.Center)
+        } else {
+          this.getListView()
         }
         }
-        .width('100%')
-        .height(300)
-        .justifyContent(FlexAlign.Center)
       } else {
       } else {
-        this.getListView()
+        // 目录模式
+        this.getFolderView()
       }
       }
 
 
       // 按钮区域
       // 按钮区域
@@ -415,6 +450,82 @@ struct AddSongsToPlaylistDialogContent {
     .height(300)
     .height(300)
   }
   }
 
 
+  @Builder
+  getFolderView() {
+    Column({ space: 12 }) {
+      Text('目录视图')
+        .fontSize(16)
+        .fontColor(this.isDarkMode ? '#FFFFFF' : $r('app.color.text_color'))
+      
+      // 这里将实现目录视图的布局
+      Scroll() {
+        Column() {
+          ForEach(this.folderItems, (item: VideoItem, index: number) => {
+            Row() {
+              // 根据是否有parentPath判断是目录还是文件
+              Text(item.parentPath ? '📁' : '🎵')
+                .fontSize(20)
+              
+              Column({ space: 2 }) {
+                Text(item.name || '未知歌曲')
+                  .fontSize(14)
+                  .fontColor(this.isDarkMode ? '#FFFFFF' : $r('app.color.text_color'))
+                  .maxLines(1)
+                  .textOverflow({ overflow: TextOverflow.Ellipsis })
+                
+                // 显示艺术家和时长信息
+                if (item.artist) {
+                  Text(item.artist + '  ' + (item.duration || ''))
+                    .fontSize(12)
+                    .fontColor(this.isDarkMode ? '#8E8E93' : '#999999')
+                    .maxLines(1)
+                    .textOverflow({ overflow: TextOverflow.Ellipsis })
+                }
+              }
+              .layoutWeight(1)
+              .margin({ left: 8 })
+              
+              // 显示选择框
+              Checkbox({ name: 'folder_item_' + item.id })
+                .select(this.selectedSongs.some((s: VideoItem) => s.id === item.id))
+                .selectedColor($r('app.color.theme_color'))
+                .onChange((checked: boolean) => {
+                  if (checked) {
+                    if (!this.selectedSongs.some((s: VideoItem) => s.id === item.id)) {
+                      this.selectedSongs.push(item);
+                    }
+                  } else {
+                    const index: number = this.selectedSongs.findIndex((s: VideoItem) => s.id === item.id);
+                    if (index > -1) {
+                      this.selectedSongs.splice(index, 1);
+                    }
+                  }
+                })
+            }
+            .width('100%')
+            .padding(12)
+            .backgroundColor(this.isDarkMode ? '#2C2C2E' : '#F8F8F8')
+            .borderRadius(8)
+            .margin({ bottom: 4 })
+            .onClick(() => {
+              const isSelected: boolean = this.selectedSongs.some((s: VideoItem) => s.id === item.id);
+              if (isSelected) {
+                const index: number = this.selectedSongs.findIndex((s: VideoItem) => s.id === item.id);
+                if (index > -1) {
+                  this.selectedSongs.splice(index, 1);
+                }
+              } else {
+                this.selectedSongs.push(item);
+              }
+            })
+          }, (item: VideoItem) => item.id)
+        }
+      }
+      .height(300)
+    }
+    .width('100%')
+  }
+
   // 改进的 footer Builder
   // 改进的 footer Builder
   @Builder
   @Builder
   footer() {
   footer() {

+ 2 - 47
entry/src/main/ets/pages/PlaylistDetailPage.ets

@@ -553,7 +553,7 @@ export struct PlaylistDetailPage {
         // 排序/完成按钮
         // 排序/完成按钮
         Text(this.isSortMode ? '完成' : '排序')
         Text(this.isSortMode ? '完成' : '排序')
           .fontSize(16)
           .fontSize(16)
-          .fontColor(Color.White)
+          .fontColor($r('app.color.text_color'))
           .margin({ right: 12 })
           .margin({ right: 12 })
           .onClick(() => {
           .onClick(() => {
             if (this.isSortMode) {
             if (this.isSortMode) {
@@ -574,52 +574,7 @@ export struct PlaylistDetailPage {
     Column() {
     Column() {
       // 顶部安全区和标题栏
       // 顶部安全区和标题栏
       this.topTitleBar()
       this.topTitleBar()
-      // Column() {
-      //   Blank()
-      //     .height(this.topRectHeight+5)
-      //     .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
-      //     .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
-      //
-      //   // 标题栏
-      //   Row() {
-      //     Image($r('app.media.back'))
-      //       .width(24)
-      //       .height(24)
-      //       .margin({ left: 12, right: 8 })
-      //       .onClick(() => {
-      //         // 如果在排序模式,先退出排序模式
-      //         if (this.isSortMode) {
-      //           this.exitSortMode()
-      //         } else {
-      //           router.back()
-      //         }
-      //       })
-      //
-      //     Text(this.isSortMode ? '排序模式' : (this.playlist?.name || '歌单详情'))
-      //       .fontSize(18)
-      //       .fontColor(Color.White)
-      //       .fontWeight(FontWeight.Medium)
-      //       .layoutWeight(1)
-      //       .textAlign(TextAlign.Center)
-      //
-      //     // 排序/完成按钮
-      //     Text(this.isSortMode ? '完成' : '排序')
-      //       .fontSize(16)
-      //       .fontColor(Color.White)
-      //       .margin({ right: 12 })
-      //       .onClick(() => {
-      //         if (this.isSortMode) {
-      //           this.exitSortMode()
-      //         } else {
-      //           this.enterSortMode()
-      //         }
-      //       })
-      //   }
-      //   .height(48)
-      //   .width('100%')
-      //   .alignItems(VerticalAlign.Center)
-      //   .backgroundColor(this.isDarkMode ? $r('app.color.title_bar_bg') : this.themeColor)
-      // }
+
 
 
       if (this.isLoading) {
       if (this.isLoading) {
         // 加载状态
         // 加载状态

+ 1 - 1
entry/src/main/ets/pages/UploadMusicPage.ets

@@ -20,7 +20,7 @@ import { SegmentButtonOptions, SegmentButtonItemTuple } from '@kit.ArkUI';
 
 
 const TAG = 'heanup UploadMusicPage';
 const TAG = 'heanup UploadMusicPage';
 
 
-interface LocalFileItem {
+export interface LocalFileItem {
   name: string;
   name: string;
   path: string;
   path: string;
   isDirectory: boolean;
   isDirectory: boolean;

+ 9 - 2
entry/src/main/ets/pages/WebDavMainPage.ets

@@ -74,6 +74,7 @@ function decodeUrlEncodedString(encodedStr: string): string {
 @Entry
 @Entry
 @Component
 @Component
 export struct WebDavMainPage {
 export struct WebDavMainPage {
+  private listScroller: ListScroller = new ListScroller()
   @StorageProp('bottomSafeHeight') bottomSafeHeight: number = 0;
   @StorageProp('bottomSafeHeight') bottomSafeHeight: number = 0;
   searchController: SearchController = new SearchController()
   searchController: SearchController = new SearchController()
   @StorageProp('animationState') animationState: AnimationStatus= AnimationStatus.Running
   @StorageProp('animationState') animationState: AnimationStatus= AnimationStatus.Running
@@ -128,6 +129,12 @@ export struct WebDavMainPage {
       this.doSortType(this.sortType)
       this.doSortType(this.sortType)
     }
     }
     this.dataSource.pushArrayData(mList)
     this.dataSource.pushArrayData(mList)
+    if(mList.length > 0){
+      setTimeout(() => {
+        this.listScroller.scrollToIndex(0)
+      },200)
+
+    }
   }
   }
 
 
   // 更新可见文件夹列表
   // 更新可见文件夹列表
@@ -251,7 +258,7 @@ export struct WebDavMainPage {
         break;
         break;
       case RemoteDriveManagerStates.LoadFilesInfoFailed:
       case RemoteDriveManagerStates.LoadFilesInfoFailed:
         this.isLoading = false;
         this.isLoading = false;
-        this.getUIContext().getPromptAction().showToast({ message: '加载失败' });
+        // this.getUIContext().getPromptAction().showToast({ message: '加载失败' });
         break;
         break;
       case RemoteDriveManagerStates.InsertAccountSucceed:
       case RemoteDriveManagerStates.InsertAccountSucceed:
       case RemoteDriveManagerStates.EditAccountSucceed:
       case RemoteDriveManagerStates.EditAccountSucceed:
@@ -1116,7 +1123,7 @@ export struct WebDavMainPage {
 
 
       // 文件列表(文件夹 + 歌曲)
       // 文件列表(文件夹 + 歌曲)
       if (this.webDavFiles.length > 0) {
       if (this.webDavFiles.length > 0) {
-        List({ space: 0 }) {
+        List({ scroller: this.listScroller ,space: 0 }) {
           // 显示文件夹 - 只显示当前目录下的直接子文件夹
           // 显示文件夹 - 只显示当前目录下的直接子文件夹
           ForEach(this.isSearchMode ? this.filteredFolderList : this.visibleFoldersState, (folder: FileInfo) => {
           ForEach(this.isSearchMode ? this.filteredFolderList : this.visibleFoldersState, (folder: FileInfo) => {
             ListItem() {
             ListItem() {