镜像自地址
https://github.com/lhly/cloud-drive-renamer.git
已同步 2026-10-20 13:47:47 +08:00
fix(quark): 修复从URL hash中提取目录ID的问题并支持文件夹
修改QuarkAdapter以正确处理URL hash路径中的目录ID,并支持在文件列表中包含文件夹
这个提交包含在:
父节点
19837f1da8
当前提交
4d2e08f9bc
@ -162,18 +162,16 @@ export class QuarkAdapter extends BasePlatformAdapter {
|
|||||||
|
|
||||||
const pageFiles = result.data.list;
|
const pageFiles = result.data.list;
|
||||||
|
|
||||||
// Filter out folders (only return files)
|
// Include both files and folders (folders have empty extension)
|
||||||
const files = pageFiles
|
const files = pageFiles.map((item): FileItem => {
|
||||||
.filter(f => f.file && !f.dir)
|
const ext = item.file ? parseFileName(item.file_name).ext : '';
|
||||||
.map((file): FileItem => {
|
|
||||||
const { ext } = parseFileName(file.file_name);
|
|
||||||
return {
|
return {
|
||||||
id: file.fid,
|
id: item.fid,
|
||||||
name: file.file_name,
|
name: item.file_name,
|
||||||
ext: ext,
|
ext,
|
||||||
parentId: file.pdir_fid,
|
parentId: item.pdir_fid,
|
||||||
size: file.size,
|
size: item.size,
|
||||||
mtime: file.updated_at,
|
mtime: item.updated_at,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -337,10 +335,44 @@ export class QuarkAdapter extends BasePlatformAdapter {
|
|||||||
return dirId;
|
return dirId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 夸克网盘使用 hash 路由 (例如: #/list/folder/12345 或 #/list/all/12345-xxxx)
|
||||||
|
// 支持嵌套路径: #/list/all/parent-name/child1-name/child2-name
|
||||||
|
const hash = window.location.hash || '';
|
||||||
|
if (hash) {
|
||||||
|
// Remove query string portion in hash (if any)
|
||||||
|
const hashPath = hash.split('?')[0];
|
||||||
|
|
||||||
|
// 🔧 FIX: 提取整个路径,取最后一个 segment(当前目录)
|
||||||
|
// 移除前缀 #/list/folder/ 或 #/list/all/
|
||||||
|
const normalized = hashPath
|
||||||
|
.replace(/^#/, '')
|
||||||
|
.replace(/^\/list\/(?:all|folder)/, '')
|
||||||
|
.replace(/^\/+/, '')
|
||||||
|
.replace(/\/+$/, '');
|
||||||
|
|
||||||
|
if (normalized) {
|
||||||
|
// 分割路径,取最后一个 segment(当前目录)
|
||||||
|
const segments = normalized.split('/').filter(Boolean);
|
||||||
|
if (segments.length > 0) {
|
||||||
|
const lastSegment = segments[segments.length - 1];
|
||||||
|
// 提取 ID(-之前的部分)
|
||||||
|
// 例如: "e1446ca1c77f4061b470c07961369e2d-第一章:机器学习与深度学习理论基础"
|
||||||
|
// -> "e1446ca1c77f4061b470c07961369e2d"
|
||||||
|
const idMatch = lastSegment.match(/^([a-z0-9]+)/);
|
||||||
|
if (idMatch && idMatch[1]) {
|
||||||
|
return idMatch[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 尝试从 DOM 中提取
|
// 尝试从 DOM 中提取
|
||||||
const dirElement = document.querySelector('[data-dir-id]');
|
const dirElement = document.querySelector('[data-dir-id]');
|
||||||
if (dirElement) {
|
if (dirElement) {
|
||||||
return dirElement.getAttribute('data-dir-id') || '';
|
const domDirId = dirElement.getAttribute('data-dir-id');
|
||||||
|
if (domDirId) {
|
||||||
|
return domDirId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认返回根目录标识
|
// 默认返回根目录标识
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
* 1. Edit version in package.json
|
* 1. Edit version in package.json
|
||||||
* 2. Run: npm run sync:version (or automatically via prebuild/predev)
|
* 2. Run: npm run sync:version (or automatically via prebuild/predev)
|
||||||
*
|
*
|
||||||
* Generated at: 2025-12-26T07:59:11.768Z
|
* Generated at: 2025-12-26T14:21:45.285Z
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -182,6 +182,81 @@ describe('QuarkAdapter', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getAllFiles方法', () => {
|
||||||
|
it('应该返回当前目录下的文件和文件夹', async () => {
|
||||||
|
// Avoid real 800ms rate limiting delay in unit test
|
||||||
|
vi.spyOn(adapter as any, 'rateLimit').mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
Object.defineProperty(window, 'location', {
|
||||||
|
value: {
|
||||||
|
search: '',
|
||||||
|
hash: '#/list/folder/12345',
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
mockFetch.mockResolvedValue({
|
||||||
|
json: async () => ({
|
||||||
|
status: 200,
|
||||||
|
code: 0,
|
||||||
|
message: 'success',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
data: {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
fid: 'file-1',
|
||||||
|
file_name: 'a.txt',
|
||||||
|
pdir_fid: '12345',
|
||||||
|
size: 10,
|
||||||
|
updated_at: 111,
|
||||||
|
file: true,
|
||||||
|
dir: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fid: 'dir-1',
|
||||||
|
file_name: 'folderA',
|
||||||
|
pdir_fid: '12345',
|
||||||
|
size: 0,
|
||||||
|
updated_at: 222,
|
||||||
|
file: false,
|
||||||
|
dir: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const files = await adapter.getAllFiles();
|
||||||
|
|
||||||
|
expect(files).toEqual([
|
||||||
|
{
|
||||||
|
id: 'file-1',
|
||||||
|
name: 'a.txt',
|
||||||
|
ext: '.txt',
|
||||||
|
parentId: '12345',
|
||||||
|
size: 10,
|
||||||
|
mtime: 111,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'dir-1',
|
||||||
|
name: 'folderA',
|
||||||
|
ext: '',
|
||||||
|
parentId: '12345',
|
||||||
|
size: 0,
|
||||||
|
mtime: 222,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining('pdir_fid=12345'),
|
||||||
|
expect.objectContaining({
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'include',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('renameFile方法', () => {
|
describe('renameFile方法', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
@ -683,6 +758,52 @@ describe('QuarkAdapter', () => {
|
|||||||
expect(files).toHaveLength(1);
|
expect(files).toHaveLength(1);
|
||||||
expect(files[0].parentId).toBe('0');
|
expect(files[0].parentId).toBe('0');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('应该从URL hash中提取folder路径的目录ID', async () => {
|
||||||
|
Object.defineProperty(window, 'location', {
|
||||||
|
value: {
|
||||||
|
search: '',
|
||||||
|
hash: '#/list/folder/12345',
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.innerHTML = `
|
||||||
|
<table>
|
||||||
|
<tr data-file-id="file-1" data-size="1024" data-mtime="1639584000000">
|
||||||
|
<td class="ant-checkbox-checked"></td>
|
||||||
|
<td class="file-name">test.txt</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const files = await adapter.getSelectedFiles();
|
||||||
|
expect(files).toHaveLength(1);
|
||||||
|
expect(files[0].parentId).toBe('12345');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('应该从URL hash中提取all路径的目录ID并去掉后缀', async () => {
|
||||||
|
Object.defineProperty(window, 'location', {
|
||||||
|
value: {
|
||||||
|
search: '',
|
||||||
|
hash: '#/list/all/98765-extra-info',
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.innerHTML = `
|
||||||
|
<table>
|
||||||
|
<tr data-file-id="file-1" data-size="1024" data-mtime="1639584000000">
|
||||||
|
<td class="ant-checkbox-checked"></td>
|
||||||
|
<td class="file-name">test.txt</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const files = await adapter.getSelectedFiles();
|
||||||
|
expect(files).toHaveLength(1);
|
||||||
|
expect(files[0].parentId).toBe('98765');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('配置和平台属性', () => {
|
describe('配置和平台属性', () => {
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户