Skip to content

Commit 13e9e08

Browse files
committed
feat: 批量删除后端化
新增 BatchDelete 端点,删除全部后只重扫一次; 替换前端逐曲循环删除(原先每曲触发一次全量重扫)
1 parent 7256d7e commit 13e9e08

6 files changed

Lines changed: 76 additions & 4 deletions

File tree

ChuChartManager/Controllers/MusicController.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,58 @@ public ActionResult DeleteMusic([FromQuery] int id, [FromQuery] string assetDir)
13571357
return Ok();
13581358
}
13591359

1360+
public record BatchDeleteResult(int Id, string AssetDir, bool Ok, string? Error);
1361+
1362+
[HttpPost]
1363+
public ActionResult<List<BatchDeleteResult>> BatchDelete([FromBody] BatchMusicIdDto dto)
1364+
{
1365+
var scanner = scannerService.Scanner;
1366+
if (scanner == null) return NotFound();
1367+
1368+
var results = new List<BatchDeleteResult>();
1369+
foreach (var item in dto.Ids)
1370+
{
1371+
try
1372+
{
1373+
if (item.AssetDir == "A000")
1374+
{
1375+
results.Add(new BatchDeleteResult(item.Id, item.AssetDir, false, "不能删除 A000 的曲目"));
1376+
continue;
1377+
}
1378+
1379+
var music = FindMusic(scanner, item.Id, item.AssetDir);
1380+
if (music == null)
1381+
{
1382+
results.Add(new BatchDeleteResult(item.Id, item.AssetDir, false, "曲目不存在"));
1383+
continue;
1384+
}
1385+
1386+
if (Directory.Exists(music.MusicDirectory))
1387+
Directory.Delete(music.MusicDirectory, true);
1388+
1389+
var optRoot = ResolveOptRoot(item.AssetDir);
1390+
if (optRoot != null)
1391+
{
1392+
var cueDir = Path.Combine(optRoot, "cueFile", $"cueFile{item.Id:D6}");
1393+
if (Directory.Exists(cueDir))
1394+
Directory.Delete(cueDir, true);
1395+
}
1396+
1397+
results.Add(new BatchDeleteResult(item.Id, item.AssetDir, true, null));
1398+
}
1399+
catch (Exception ex)
1400+
{
1401+
results.Add(new BatchDeleteResult(item.Id, item.AssetDir, false, ex.Message));
1402+
}
1403+
}
1404+
1405+
var newScanner = new MusicScanner(StaticSettings.GamePath);
1406+
newScanner.ScanAll();
1407+
StaticSettings.Scanner = newScanner;
1408+
1409+
return Ok(results);
1410+
}
1411+
13601412
[HttpPost]
13611413
public ActionResult OpenExplorer([FromQuery] int id, [FromQuery] string assetDir)
13621414
{

ChuChartManager/Front/src/api/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,18 @@ export async function getIdConflicts(id: number, assetDir: string): Promise<stri
7171
return data
7272
}
7373

74+
export interface BatchDeleteResult {
75+
id: number
76+
assetDir: string
77+
ok: boolean
78+
error?: string
79+
}
80+
81+
export async function batchDelete(items: { id: number; assetDir: string }[]): Promise<BatchDeleteResult[]> {
82+
const { data } = await apiClient.post('/api/Music/BatchDelete', { ids: items })
83+
return data
84+
}
85+
7486
export async function getSources(): Promise<string[]> {
7587
const { data } = await apiClient.get('/api/Music/GetSources')
7688
return data

ChuChartManager/Front/src/locales/en.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ batch:
390390
executing: Executing…
391391
noMusicSelected: Please select music first
392392
done: Done
393+
deletePartial: "Delete finished: {ok} succeeded, {fail} failed"
393394
downloading: Downloading…
394395
next: Next
395396
previous: Previous

ChuChartManager/Front/src/locales/ja.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ batch:
381381
executing: 実行中…
382382
noMusicSelected: 楽曲を選択してください
383383
done: 完了
384+
deletePartial: "削除完了:成功 {ok} 件、失敗 {fail} 件"
384385
downloading: ダウンロード中…
385386
next: 次へ
386387
previous: 戻る

ChuChartManager/Front/src/locales/zh.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ batch:
390390
executing: 执行中…
391391
noMusicSelected: 请先选择曲目
392392
done: 完成
393+
deletePartial: "删除完成:成功 {ok} 个,失败 {fail} 个"
393394
downloading: 正在下载…
394395
next: 下一步
395396
previous: 上一步

ChuChartManager/Front/src/views/BatchAction/ChooseAction.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import { Button, Radio, Select, Popover, addToast } from '@munet/ui'
33
import type { SelectOption } from '@munet/ui'
44
import { useI18n } from 'vue-i18n'
55
import { useStorage } from '@vueuse/core'
6-
import { apiClient, getMusicList, type MusicListItem } from '@/api'
7-
import { deleteMusic } from '@/api/customResource'
6+
import { apiClient, getMusicList, batchDelete, type MusicListItem } from '@/api'
87
import { STEP } from './index'
98
import remoteExport from './remoteExport'
109

@@ -72,8 +71,14 @@ export default defineComponent({
7271
case OPTIONS.Delete: {
7372
loading.value = true
7473
try {
75-
for (const m of props.selectedMusic) await deleteMusic(m.id, m.assetDir)
76-
addToast({ message: t('batch.done'), type: 'success' })
74+
const items = props.selectedMusic.map(m => ({ id: m.id, assetDir: m.assetDir }))
75+
const results = await batchDelete(items)
76+
const failed = results.filter(r => !r.ok)
77+
if (failed.length) {
78+
addToast({ message: t('batch.deletePartial', { ok: results.length - failed.length, fail: failed.length }), type: 'error' })
79+
} else {
80+
addToast({ message: t('batch.done'), type: 'success' })
81+
}
7782
props.onListUpdated(await getMusicList())
7883
props.continue(STEP.Select)
7984
} catch (e: any) {

0 commit comments

Comments
 (0)