Просмотр исходного кода

实现百度网盘的新建文件夹功能

onecold 8 месяцев назад
Родитель
Сommit
9c0910fe29

+ 83 - 0
entry/src/main/ets/common/network/BaiduPanClient.ets

@@ -344,3 +344,86 @@ export async function ensureAudioStreamReady(
   }
   throw new Error('百度音频流暂不可用,请稍后重试');
 }
+
+export interface BaiduCreateFolderResponse {
+  errno: number;
+  fs_id?: number;
+  path?: string;
+  ctime?: number;
+  mtime?: number;
+  isdir?: number;
+  category?: number;
+  status?: number;
+}
+
+export async function createFolder(
+  accessToken: string,
+  path: string,
+  rtype: number = 1
+): Promise<BaiduCreateFolderResponse> {
+  if (!accessToken) {
+    throw new Error('缺少百度网盘access_token');
+  }
+  if (!path) {
+    throw new Error('缺少文件夹路径');
+  }
+
+  // 确保路径以 / 开头
+  const normalizedPath = path.startsWith('/') ? path : `/${path}`;
+
+  const requestUrl = `${BaiduConstants.PAN_BASE}/rest/2.0/xpan/file?method=create&access_token=${accessToken}`;
+
+  // 构建请求体参数
+  const bodyParams = [
+    `path=${encodeURIComponent(normalizedPath)}`,
+    `isdir=1`,
+    `rtype=${rtype}`
+  ].join('&');
+
+  const httpRequest = http.createHttp();
+  const options: http.HttpRequestOptions = {
+    method: http.RequestMethod.POST,
+    connectTimeout: 10000,
+    readTimeout: 10000,
+    expectDataType: http.HttpDataType.STRING,
+    header: {
+      'User-Agent': BaiduConstants.USER_AGENT,
+      'Content-Type': 'application/x-www-form-urlencoded'
+    },
+    extraData: bodyParams
+  };
+
+  try {
+    Logger.info(TAG, `百度网盘创建文件夹请求: ${requestUrl}`);
+    Logger.info(TAG, `百度网盘创建文件夹参数: ${bodyParams}`);
+
+    const response = await httpRequest.request(requestUrl, options);
+    const payload = parseResponseBody(response);
+    Logger.info(TAG, `百度网盘创建文件夹响应: ${payload}`);
+
+    const parsed = await parseJson<BaiduCreateFolderResponse>(payload);
+    if (parsed.errno !== 0) {
+      // 根据错误码返回具体错误信息
+      let errorMessage = `创建文件夹失败 errno=${parsed.errno}`;
+      switch (parsed.errno) {
+        case -7:
+          errorMessage = '文件或目录名错误或无权访问';
+          break;
+        case -8:
+          errorMessage = '文件或目录已存在';
+          break;
+        case -10:
+          errorMessage = '云端容量已满';
+          break;
+        default:
+          errorMessage = `创建文件夹失败 errno=${parsed.errno}`;
+      }
+      throw new Error(errorMessage);
+    }
+
+    Logger.info(TAG, `百度网盘创建文件夹成功: path=${parsed.path}, fs_id=${parsed.fs_id}`);
+    return parsed;
+  } finally {
+    httpRequest.destroy();
+  }
+}

+ 50 - 1
entry/src/main/ets/common/util/RemoteDriveManager.ets

@@ -23,7 +23,7 @@ import { WebDavUrlUtil } from './WebDavUrlUtil';
 import MediaTable from './MediaTable';
 import { FtpClient, FileInfo as FtpEntryInfo, StringEncoding, AccessOptions } from '@liuzhosoft/ftp4h';
 import { BaiduConstants } from '../constants/BaiduConstants';
-import { appendAccessTokenToDlink, BaiduListEntry, BaiduFileMeta, buildAudioStreamingUrl, deleteFiles as deleteBaiduFiles, ensureAudioStreamReady, fetchFileMetas as fetchBaiduFileMetas, listDirectory as listBaiduDirectory, refreshAccessToken as refreshBaiduAccessToken } from '../network/BaiduPanClient';
+import { appendAccessTokenToDlink, BaiduListEntry, BaiduFileMeta, buildAudioStreamingUrl, createFolder, deleteFiles as deleteBaiduFiles, ensureAudioStreamReady, fetchFileMetas as fetchBaiduFileMetas, listDirectory as listBaiduDirectory, refreshAccessToken as refreshBaiduAccessToken } from '../network/BaiduPanClient';
 import { ServerLogUtil } from './ServerLogUtil';
 
 const TAG = 'heanup RemoteDriveManager';
@@ -2802,6 +2802,55 @@ export class RemoteDriveManager {
     return authInfo;
   }
 
+  /**
+   * 在百度网盘中创建文件夹
+   * @param account 百度网盘账户
+   * @param folderName 要创建的文件夹名称
+   * @param parentPath 父级路径,默认为当前路径
+   * @returns Promise<string> 创建成功后的完整路径
+   */
+  public async createBaiduFolder(account: WebDavAccount, folderName: string, parentPath?: string): Promise<string> {
+    if (!account || account.webType !== RemoteDriveType.Baidu) {
+      throw new Error('只支持在百度网盘账户中创建文件夹');
+    }
+
+    if (!folderName || folderName.trim().length === 0) {
+      throw new Error('文件夹名称不能为空');
+    }
+
+    // 检查文件夹名称是否包含非法字符
+    const invalidChars = /[\\/:*?"<>|]/;
+    if (invalidChars.test(folderName.trim())) {
+      throw new Error('文件夹名称不能包含 \\ / : * ? " < > | 字符');
+    }
+
+    const accessToken = account.baiduAccessToken;
+    if (!accessToken) {
+      throw new Error('百度网盘授权已过期,请重新登录');
+    }
+
+    // 确定父级路径
+    const basePath = parentPath || this.currentPath;
+
+    // 构建完整的文件夹路径
+    const fullPath = basePath === '' || basePath === '/'
+      ? `/${folderName.trim()}`
+      : `${basePath.replace(/\/$/, '')}/${folderName.trim()}`;
+
+    Logger.info(TAG, `heanup 准备在百度网盘创建文件夹: ${fullPath}`);
+
+    try {
+      const result = await createFolder(accessToken, fullPath, 1); // rtype=1表示自动重命名
+
+      Logger.info(TAG, `heanup 百度网盘文件夹创建成功: ${result.path}`);
+      return result.path || fullPath;
+    } catch (error) {
+      const err = error as Error;
+      Logger.error(TAG, `heanup 百度网盘文件夹创建失败: ${err.message}`);
+      throw err;
+    }
+  }
+
 }
 
 

+ 105 - 0
entry/src/main/ets/pages/WebDavMainPage.ets

@@ -22,6 +22,7 @@ import { RemoteDriveType } from '../common/enums/RemoteDriveType';
 import { Utility } from '../common/util/Utility';
 import { SettingPage } from './SettingPage';
 import { getCloudDiskIcon } from '../dialog/RemoteDriveAccountDialog';
+import { CreateFolderDialog } from '../dialog/CreateFolderDialog';
 
 /**
  * 歌单播放事件数据
@@ -865,6 +866,15 @@ export struct WebDavMainPage {
           this.navigateToUploadPage();
         })
 
+      MenuItem({
+        symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.folder_badge_plus')),
+        content: $r('app.string.create_foder')
+      })
+        .onClick(async () => {
+            this.showCreateFolderDialog();
+
+        })
+
     }.attributeModifier(new MenuModifier())
   }
 
@@ -1559,4 +1569,99 @@ export struct WebDavMainPage {
       this.enterMultiSelect(song);
     }))
   }
+
+  
+  
+  // 对话框控制器
+  private createFolderDialogController: CustomDialogController | null = null;
+
+  /**
+   * 显示创建文件夹对话框
+   */
+  private showCreateFolderDialog(): void {
+    if (!this.selectedAccount) {
+      this.getUIContext().getPromptAction().showToast({ message: `请先选择${getRemoteDriveAccountLabel()}` });
+      return;
+    }
+
+    // 获取当前主题色
+    const currentThemeColor = this.themeColor;
+
+    // 创建自定义对话框
+    this.createFolderDialogController = new CustomDialogController({
+      builder: CreateFolderDialog({
+        onConfirm: (folderName: string) => {
+          if (folderName.trim().length > 0) {
+            void this.createFolder(folderName.trim());
+          } else {
+            this.getUIContext().getPromptAction().showToast({ message: '文件夹名称不能为空' });
+          }
+        },
+        onCancel: () => {
+          // 用户取消创建
+        },
+        initialName: '',
+        themeColor: currentThemeColor
+      }),
+      autoCancel: true,
+      alignment: DialogAlignment.Center,
+      customStyle: false
+    });
+
+    this.createFolderDialogController.open();
+  }
+
+  /**
+   * 创建文件夹的实际方法
+   * @param folderName 文件夹名称
+   */
+  private async createFolder(folderName: string): Promise<void> {
+    if (!this.selectedAccount) {
+      this.getUIContext().getPromptAction().showToast({ message: `请先选择${getRemoteDriveAccountLabel()}` });
+      return;
+    }
+
+    if (folderName.length === 0) {
+      this.getUIContext().getPromptAction().showToast({ message: '文件夹名称不能为空' });
+      return;
+    }
+
+    try {
+      Logger.info(TAG, `heanup 开始创建文件夹: ${folderName}`);
+
+      // 显示加载状态
+      this.isLoading = true;
+      if(this.selectedAccount.webType==RemoteDriveType.Baidu){
+        // 调用RemoteDriveManager的createBaiduFolder方法
+        const createdPath = await this.webdavManager.createBaiduFolder(this.selectedAccount, folderName);
+
+        // 创建成功后刷新当前目录
+        await this.webdavManager.loadFilesInfoFromAccount(this.selectedAccount, this.webdavManager.currentPath);
+      }else if(this.selectedAccount.webType==RemoteDriveType.WebDav){
+        // 这里帮我实现调用RemoteDriveManager的createWebDavFolder方法
+
+      }
+
+
+      this.getUIContext().getPromptAction().showToast({
+        message: `文件夹 "${folderName}" 创建成功`
+      });
+
+      Logger.info(TAG, `heanup 文件夹创建成功`);
+
+    } catch (error) {
+      const err = error as Error;
+      Logger.error(TAG, `heanup 创建文件夹失败: ${err.message}`);
+
+      // 显示具体的错误信息
+      this.getUIContext().getPromptAction().showToast({
+        message: `创建失败: ${err.message}`
+      });
+    } finally {
+      this.isLoading = false;
+    }
+  }
 }
+
+
+

+ 4 - 0
entry/src/main/resources/base/element/string.json

@@ -714,6 +714,10 @@
     {
       "name": "lyric_setting",
       "value": "歌词设置"
+    },
+    {
+      "name": "create_foder",
+      "value": "新建文件夹"
     }
 
   ]