| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880 |
- import { relationalStore } from '@kit.ArkData';
- import { Context } from '@kit.AbilityKit';
- import Logger from './Logger';
- import RdbUtils from './RdbUtils';
- import { Playlist, PlaylistSong } from '../../viewmodel/Playlist';
- import {
- PlaylistBackupData,
- PlaylistBackupItem,
- PlaylistSongBackupItem,
- ImportResult,
- ConflictResolution,
- BACKUP_FORMAT_VERSION
- } from '../../viewmodel/PlaylistBackup';
- import { AppUtil } from '@pura/harmony-utils';
- /**
- * 歌单数据库操作类
- */
- export default class PlaylistTable {
- private context: Context;
- private rdbStore: relationalStore.RdbStore | null = null;
- private initPromise: Promise<void>;
- constructor(context: Context) {
- this.context = context;
- this.initPromise = this.initRdbStore();
- }
- /**
- * 确保数据库已初始化
- */
- private async ensureInitialized(): Promise<void> {
- await this.initPromise;
- }
- /**
- * 初始化数据库
- */
- private async initRdbStore(): Promise<void> {
- try {
- const config: relationalStore.StoreConfig = {
- name: 'PlaylistStore.db',
- securityLevel: relationalStore.SecurityLevel.S1 // 使用标准安全级别
- };
- this.rdbStore = await relationalStore.getRdbStore(this.context, config);
- // 创建表
- await this.createTables();
- Logger.info('heanup PlaylistTable', '数据库初始化成功');
- } catch (error) {
- Logger.error('heanup PlaylistTable', `初始化数据库失败: ${error.message}`);
- }
- }
- /**
- * 创建表
- */
- private async createTables(): Promise<void> {
- if (!this.rdbStore) {
- return;
- }
- try {
- // 创建歌单表
- await this.rdbStore.executeSql(RdbUtils.PLAYLIST_TABLE.sqlCreate);
-
- // 创建歌单歌曲关联表
- await this.rdbStore.executeSql(RdbUtils.PLAYLIST_SONG_TABLE.sqlCreate);
-
- Logger.info('heanup PlaylistTable', '数据库表创建成功');
- } catch (error) {
- Logger.error('heanup PlaylistTable', `创建表失败: ${error.message}`);
- }
- }
- /**
- * 生成唯一ID
- */
- private generateId(): string {
- return Date.now().toString() + Math.random().toString(36).substr(2, 9);
- }
- /**
- * 创建歌单
- */
- async createPlaylist(name: string, description?: string, coverPath?: string): Promise<boolean> {
- await this.ensureInitialized();
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', '数据库未初始化');
- return false;
- }
- try {
- const id = this.generateId();
- const now = new Date().toISOString();
- const sql = 'INSERT INTO playlistTable (id, name, coverPath, description, createTime, updateTime, songCount, sortOrder) VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
- const params = [id, name, coverPath || null, description || null, now, now, 0, 0];
- await this.rdbStore.executeSql(sql, params);
- Logger.info('heanup PlaylistTable', `歌单创建成功: ${name}`);
- this.triggerAutoBackup();
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `创建歌单失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 删除歌单及其所有歌曲
- */
- async deletePlaylist(playlistId: string): Promise<boolean> {
- if (!this.rdbStore) {
- return false;
- }
- try {
- // 先删除歌单歌曲关联
- const deleteSongsSql = 'DELETE FROM playlistSongTable WHERE playlistId = ?';
- await this.rdbStore.executeSql(deleteSongsSql, [playlistId]);
-
- // 再删除歌单
- const deletePlaylistSql = 'DELETE FROM playlistTable WHERE id = ?';
- await this.rdbStore.executeSql(deletePlaylistSql, [playlistId]);
-
- Logger.info('heanup PlaylistTable', `歌单删除成功: ${playlistId}`);
- this.triggerAutoBackup();
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `删除歌单失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 更新歌单信息
- */
- async updatePlaylist(playlistId: string, name?: string, description?: string, coverPath?: string): Promise<boolean> {
- if (!this.rdbStore) {
- return false;
- }
- try {
- const updateTime = new Date().toISOString();
- const updates: string[] = [];
- const params: (string | number | null)[] = [];
- if (name !== undefined) {
- updates.push('name = ?');
- params.push(name);
- }
- if (description !== undefined) {
- updates.push('description = ?');
- params.push(description);
- }
- if (coverPath !== undefined) {
- updates.push('coverPath = ?');
- params.push(coverPath);
- }
-
- updates.push('updateTime = ?');
- params.push(updateTime);
- params.push(playlistId);
- const sql = `UPDATE playlistTable SET ${updates.join(', ')} WHERE id = ?`;
- await this.rdbStore.executeSql(sql, params);
-
- Logger.info('heanup PlaylistTable', `歌单更新成功: ${playlistId}`);
- this.triggerAutoBackup();
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `更新歌单失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 查询所有歌单
- */
- async queryAllPlaylists(): Promise<Playlist[]> {
- await this.ensureInitialized();
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', '数据库未初始化');
- return [];
- }
- try {
- const sql = 'SELECT * FROM playlistTable ORDER BY sortOrder ASC, createTime DESC';
- Logger.info('heanup PlaylistTable', '开始查询所有歌单');
- const resultSet = await this.rdbStore.querySql(sql);
-
- const playlists: Playlist[] = [];
- if (resultSet.goToFirstRow()) {
- do {
- const playlistId = resultSet.getString(resultSet.getColumnIndex('id'));
- const playlistName = resultSet.getString(resultSet.getColumnIndex('name'));
- const songCount = resultSet.getLong(resultSet.getColumnIndex('songCount'));
- Logger.info('heanup PlaylistTable', `queryAllPlaylists: 从数据库读取 - ID: ${playlistId}, 名称: ${playlistName}, 歌曲数: ${songCount}`);
- const playlist = new Playlist(
- playlistId,
- playlistName,
- resultSet.getString(resultSet.getColumnIndex('createTime')),
- resultSet.getString(resultSet.getColumnIndex('updateTime')),
- songCount,
- resultSet.getLong(resultSet.getColumnIndex('sortOrder')),
- resultSet.getString(resultSet.getColumnIndex('coverPath')),
- resultSet.getString(resultSet.getColumnIndex('description'))
- );
- playlists.push(playlist);
- } while (resultSet.goToNextRow());
- }
-
- resultSet.close();
- Logger.info('heanup PlaylistTable', `查询到 ${playlists.length} 个歌单`);
- return playlists;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `查询歌单失败: ${error.message}`);
- return [];
- }
- }
- /**
- * 根据名称查询最近更新的歌单
- */
- async queryPlaylistByName(name: string): Promise<Playlist | null> {
- await this.ensureInitialized();
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', '数据库未初始化');
- return null;
- }
- try {
- const sql = 'SELECT * FROM playlistTable WHERE name = ? ORDER BY updateTime DESC LIMIT 1';
- const resultSet = await this.rdbStore.querySql(sql, [name]);
- if (resultSet.goToFirstRow()) {
- const playlist = new Playlist(
- resultSet.getString(resultSet.getColumnIndex('id')),
- resultSet.getString(resultSet.getColumnIndex('name')),
- resultSet.getString(resultSet.getColumnIndex('createTime')),
- resultSet.getString(resultSet.getColumnIndex('updateTime')),
- resultSet.getLong(resultSet.getColumnIndex('songCount')),
- resultSet.getLong(resultSet.getColumnIndex('sortOrder')),
- resultSet.getString(resultSet.getColumnIndex('coverPath')),
- resultSet.getString(resultSet.getColumnIndex('description'))
- );
- resultSet.close();
- return playlist;
- }
- resultSet.close();
- return null;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `queryPlaylistByName失败: ${error.message}`);
- return null;
- }
- }
- /**
- * 根据ID查询歌单
- */
- async queryPlaylistById(playlistId: string): Promise<Playlist | null> {
- if (!this.rdbStore) {
- return null;
- }
- try {
- const sql = 'SELECT * FROM playlistTable WHERE id = ?';
- const resultSet = await this.rdbStore.querySql(sql, [playlistId]);
-
- if (resultSet.goToFirstRow()) {
- const playlist = new Playlist(
- resultSet.getString(resultSet.getColumnIndex('id')),
- resultSet.getString(resultSet.getColumnIndex('name')),
- resultSet.getString(resultSet.getColumnIndex('createTime')),
- resultSet.getString(resultSet.getColumnIndex('updateTime')),
- resultSet.getLong(resultSet.getColumnIndex('songCount')),
- resultSet.getLong(resultSet.getColumnIndex('sortOrder')),
- resultSet.getString(resultSet.getColumnIndex('coverPath')),
- resultSet.getString(resultSet.getColumnIndex('description'))
- );
- resultSet.close();
- return playlist;
- }
-
- resultSet.close();
- return null;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `查询歌单失败: ${error.message}`);
- return null;
- }
- }
- /**
- * 添加歌曲到歌单
- */
- async addSongToPlaylist(playlistId: string, songFilePath: string): Promise<boolean> {
- await this.ensureInitialized();
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', '数据库未初始化');
- return false;
- }
- try {
- Logger.info('heanup PlaylistTable', `开始添加歌曲到歌单: playlistId=${playlistId}, songFilePath=${songFilePath}`);
- // 检查歌曲是否已在歌单中
- const isInPlaylist = await this.isSongInPlaylist(playlistId, songFilePath);
- if (isInPlaylist) {
- Logger.info('heanup PlaylistTable', '歌曲已在歌单中');
- return false;
- }
- const id = this.generateId();
- const addTime = new Date().toISOString();
- const sql = 'INSERT INTO playlistSongTable (id, playlistId, songFilePath, addTime, sortOrder) VALUES (?, ?, ?, ?, ?)';
- const params = [id, playlistId, songFilePath, addTime, 0];
- Logger.info('heanup PlaylistTable', `执行SQL插入: ${sql}`);
- await this.rdbStore.executeSql(sql, params);
- Logger.info('heanup PlaylistTable', '歌曲插入成功');
- // 更新歌单歌曲数量
- Logger.info('heanup PlaylistTable', '开始更新歌单歌曲数量');
- await this.updatePlaylistSongCount(playlistId);
- Logger.info('heanup PlaylistTable', `歌曲添加到歌单成功: ${songFilePath}`);
- this.triggerAutoBackup();
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `添加歌曲到歌单失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 批量添加歌曲到歌单
- */
- async addSongsToPlaylist(playlistId: string, songFilePaths: string[]): Promise<boolean> {
- await this.ensureInitialized();
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', '数据库未初始化');
- return false;
- }
- if (!songFilePaths || songFilePaths.length === 0) {
- Logger.error('heanup PlaylistTable', '歌曲路径列表为空');
- return false;
- }
- try {
- Logger.info('heanup PlaylistTable', `开始批量添加歌曲到歌单: playlistId=${playlistId}, 歌曲数量=${songFilePaths.length}`);
- let successCount = 0;
- for (const songFilePath of songFilePaths) {
- try {
- // 检查歌曲是否已在歌单中
- const isInPlaylist = await this.isSongInPlaylist(playlistId, songFilePath);
- if (isInPlaylist) {
- Logger.info('heanup PlaylistTable', `歌曲已在歌单中,跳过: ${songFilePath}`);
- continue;
- }
- const id = this.generateId();
- const addTime = new Date().toISOString();
- const sql = 'INSERT INTO playlistSongTable (id, playlistId, songFilePath, addTime, sortOrder) VALUES (?, ?, ?, ?, ?)';
- const params = [id, playlistId, songFilePath, addTime, 0];
- await this.rdbStore.executeSql(sql, params);
- successCount++;
- Logger.info('heanup PlaylistTable', `成功添加歌曲: ${songFilePath}`);
- } catch (error) {
- Logger.error('heanup PlaylistTable', `添加歌曲失败: ${songFilePath}, 错误: ${error.message}`);
- }
- }
- // 更新歌单歌曲数量
- Logger.info('heanup PlaylistTable', '开始更新歌单歌曲数量');
- await this.updatePlaylistSongCount(playlistId);
- Logger.info('heanup PlaylistTable', `批量添加歌曲完成,成功添加 ${successCount} 首,共 ${songFilePaths.length} 首`);
- return successCount > 0;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `批量添加歌曲到歌单失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 从歌单中移除歌曲
- */
- async removeSongFromPlaylist(playlistId: string, songFilePath: string): Promise<boolean> {
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', 'removeSongFromPlaylist: 数据库未初始化');
- return false;
- }
- try {
- Logger.info('heanup PlaylistTable', `removeSongFromPlaylist: 开始删除歌曲 ${songFilePath} 从歌单 ${playlistId}`);
- const sql = 'DELETE FROM playlistSongTable WHERE playlistId = ? AND songFilePath = ?';
- await this.rdbStore.executeSql(sql, [playlistId, songFilePath]);
- Logger.info('heanup PlaylistTable', `removeSongFromPlaylist: 数据库删除操作完成`);
- // 更新歌单歌曲数量
- Logger.info('heanup PlaylistTable', `removeSongFromPlaylist: 开始更新歌单数量`);
- await this.updatePlaylistSongCount(playlistId);
- Logger.info('heanup PlaylistTable', `removeSongFromPlaylist: 歌曲从歌单移除成功: ${songFilePath}`);
- this.triggerAutoBackup();
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `removeSongFromPlaylist: 从歌单移除歌曲失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 从所有歌单中移除指定歌曲(当歌曲文件被删除时调用)
- */
- async removeSongFromAllPlaylists(songFilePath: string): Promise<string[]> {
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', 'removeSongFromAllPlaylists: 数据库未初始化');
- return [];
- }
- try {
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 开始处理歌曲 ${songFilePath}`);
- // 1. 先查询这首歌在哪些歌单中
- const sql = 'SELECT DISTINCT playlistId FROM playlistSongTable WHERE songFilePath = ?';
- const resultSet = await this.rdbStore.querySql(sql, [songFilePath]);
- const affectedPlaylistIds: string[] = [];
- if (resultSet.goToFirstRow()) {
- do {
- const playlistId = resultSet.getString(0);
- affectedPlaylistIds.push(playlistId);
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 找到歌单 ${playlistId}`);
- } while (resultSet.goToNextRow());
- }
- resultSet.close();
- if (affectedPlaylistIds.length === 0) {
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 歌曲不在任何歌单中: ${songFilePath}`);
- return [];
- }
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 歌曲在 ${affectedPlaylistIds.length} 个歌单中`);
- // 2. 从所有歌单中删除这首歌
- const deleteSql = 'DELETE FROM playlistSongTable WHERE songFilePath = ?';
- await this.rdbStore.executeSql(deleteSql, [songFilePath]);
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 已从数据库删除歌曲记录`);
- // 3. 更新所有受影响歌单的歌曲数量
- for (const playlistId of affectedPlaylistIds) {
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 开始更新歌单 ${playlistId} 的数量`);
- await this.updatePlaylistSongCount(playlistId);
- }
- Logger.info('heanup PlaylistTable', `removeSongFromAllPlaylists: 歌曲已从 ${affectedPlaylistIds.length} 个歌单中移除: ${songFilePath}`);
- return affectedPlaylistIds;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `removeSongFromAllPlaylists: 从所有歌单移除歌曲失败: ${error.message}`);
- return [];
- }
- }
- /**
- * 查询歌单中的歌曲
- */
- async queryPlaylistSongs(playlistId: string): Promise<PlaylistSong[]> {
- await this.ensureInitialized();
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', '数据库未初始化');
- return [];
- }
- try {
- const sql = 'SELECT * FROM playlistSongTable WHERE playlistId = ? ORDER BY sortOrder ASC, addTime ASC';
- Logger.info('heanup PlaylistTable', `queryPlaylistSongs: 开始查询歌单歌曲, playlistId=${playlistId}`);
- Logger.info('heanup PlaylistTable', `queryPlaylistSongs: SQL=${sql}`);
-
- const resultSet = await this.rdbStore.querySql(sql, [playlistId]);
- Logger.info('heanup PlaylistTable', `queryPlaylistSongs: 查询执行完成, rowCount=${resultSet.rowCount}`);
-
- const songs: PlaylistSong[] = [];
- if (resultSet.goToFirstRow()) {
- Logger.info('heanup PlaylistTable', 'queryPlaylistSongs: 移动到第一行成功');
- do {
- const song = new PlaylistSong(
- resultSet.getString(resultSet.getColumnIndex('id')),
- resultSet.getString(resultSet.getColumnIndex('playlistId')),
- resultSet.getString(resultSet.getColumnIndex('songFilePath')),
- resultSet.getString(resultSet.getColumnIndex('addTime')),
- resultSet.getLong(resultSet.getColumnIndex('sortOrder'))
- );
- songs.push(song);
- Logger.info('heanup PlaylistTable', `queryPlaylistSongs: 添加歌曲, songFilePath=${song.songFilePath}`);
- } while (resultSet.goToNextRow());
- } else {
- Logger.info('heanup PlaylistTable', 'queryPlaylistSongs: 没有数据,无法移动到第一行');
- }
-
- resultSet.close();
- Logger.info('heanup PlaylistTable', `queryPlaylistSongs: 查询到 ${songs.length} 首歌曲`);
- return songs;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `queryPlaylistSongs: 查询歌单歌曲失败: ${error.message}`);
- Logger.error('heanup PlaylistTable', `queryPlaylistSongs: 错误堆栈: ${error.stack || '无堆栈信息'}`);
- return [];
- }
- }
- /**
- * 检查歌曲是否在歌单中
- */
- async isSongInPlaylist(playlistId: string, songFilePath: string): Promise<boolean> {
- if (!this.rdbStore) {
- return false;
- }
- try {
- const sql = 'SELECT COUNT(*) as count FROM playlistSongTable WHERE playlistId = ? AND songFilePath = ?';
- const resultSet = await this.rdbStore.querySql(sql, [playlistId, songFilePath]);
-
- let isInPlaylist = false;
- if (resultSet.goToFirstRow()) {
- const count = resultSet.getLong(resultSet.getColumnIndex('count'));
- isInPlaylist = count > 0;
- }
-
- resultSet.close();
- return isInPlaylist;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `检查歌曲是否在歌单中失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 更新歌单歌曲数量
- */
- private async updatePlaylistSongCount(playlistId: string): Promise<void> {
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', 'updatePlaylistSongCount: 数据库未初始化');
- return;
- }
- try {
- Logger.info('heanup PlaylistTable', `updatePlaylistSongCount: 开始更新歌单 ${playlistId} 的歌曲数量`);
- const countSql = 'SELECT COUNT(*) as count FROM playlistSongTable WHERE playlistId = ?';
- const resultSet = await this.rdbStore.querySql(countSql, [playlistId]);
- let count = 0;
- if (resultSet.goToFirstRow()) {
- count = resultSet.getLong(resultSet.getColumnIndex('count'));
- }
- resultSet.close();
- Logger.info('heanup PlaylistTable', `updatePlaylistSongCount: 统计到 ${count} 首歌曲`);
- const updateSql = 'UPDATE playlistTable SET songCount = ?, updateTime = ? WHERE id = ?';
- const updateTime = new Date().toISOString();
- await this.rdbStore.executeSql(updateSql, [count, updateTime, playlistId]);
- Logger.info('heanup PlaylistTable', `updatePlaylistSongCount: 数据库更新成功,songCount = ${count}`);
- } catch (error) {
- Logger.error('heanup PlaylistTable', `updatePlaylistSongCount: 更新歌单歌曲数量失败: ${error.message}`);
- }
- }
- /**
- * 强制同步歌单歌曲数量(公开方法,用于修复数据不一致)
- */
- async syncPlaylistSongCount(playlistId: string): Promise<void> {
- await this.ensureInitialized();
- await this.updatePlaylistSongCount(playlistId);
- Logger.info('heanup PlaylistTable', `已强制同步歌单 ${playlistId} 的歌曲数量`);
- }
- /**
- * 清理歌单中无效的歌曲记录(歌曲文件已不存在)
- */
- async removeInvalidSongFromPlaylist(playlistId: string, songFilePath: string): Promise<boolean> {
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', 'removeInvalidSongFromPlaylist: 数据库未初始化');
- return false;
- }
- try {
- Logger.info('heanup PlaylistTable', `removeInvalidSongFromPlaylist: 开始清理无效歌曲 ${songFilePath} 从歌单 ${playlistId}`);
- const sql = 'DELETE FROM playlistSongTable WHERE playlistId = ? AND songFilePath = ?';
- await this.rdbStore.executeSql(sql, [playlistId, songFilePath]);
- Logger.info('heanup PlaylistTable', `removeInvalidSongFromPlaylist: 数据库删除操作完成`);
- // 更新歌单歌曲数量
- Logger.info('heanup PlaylistTable', `removeInvalidSongFromPlaylist: 开始更新歌单数量`);
- await this.updatePlaylistSongCount(playlistId);
- Logger.info('heanup PlaylistTable', `removeInvalidSongFromPlaylist: 无效歌曲从歌单清理成功: ${songFilePath}`);
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `removeInvalidSongFromPlaylist: 清理无效歌曲失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 更新歌单排序
- */
- async updatePlaylistSortOrder(playlistId: string, sortOrder: number): Promise<boolean> {
- if (!this.rdbStore) {
- return false;
- }
- try {
- const updateTime = new Date().toISOString();
- const sql = 'UPDATE playlistTable SET sortOrder = ?, updateTime = ? WHERE id = ?';
- await this.rdbStore.executeSql(sql, [sortOrder, updateTime, playlistId]);
-
- Logger.info('heanup PlaylistTable', `歌单排序更新成功: ${playlistId}`);
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `更新歌单排序失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 更新歌单歌曲排序
- */
- async updatePlaylistSongSortOrder(playlistId: string, songFilePath: string, sortOrder: number): Promise<boolean> {
- if (!this.rdbStore) {
- Logger.info('heanup PlaylistTable', `rdbStore未初始化: ${songFilePath}`);
- return false;
- }
- try {
- const sql = 'UPDATE playlistSongTable SET sortOrder = ? WHERE playlistId = ? AND songFilePath = ?';
- await this.rdbStore.executeSql(sql, [sortOrder, playlistId, songFilePath]);
-
- Logger.info('heanup PlaylistTable', `歌单歌曲排序更新成功: ${songFilePath}`);
- return true;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `更新歌单歌曲排序失败: ${error.message}`);
- return false;
- }
- }
- /**
- * 导出所有歌单及其歌曲为备份数据
- */
- async exportAllPlaylists(): Promise<PlaylistBackupData> {
- await this.ensureInitialized();
- const backupData: PlaylistBackupData = {
- version: BACKUP_FORMAT_VERSION,
- exportTime: new Date().toISOString(),
- appVersion: AppUtil.getVersionName(),
- playlists: []
- };
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', 'exportAllPlaylists: 数据库未初始化');
- return backupData;
- }
- try {
- const playlists = await this.queryAllPlaylists();
- Logger.info('heanup PlaylistTable', `exportAllPlaylists: 开始导出 ${playlists.length} 个歌单`);
- for (let i = 0; i < playlists.length; i++) {
- const playlist = playlists[i];
- const songs = await this.queryPlaylistSongs(playlist.id);
- const songBackups: PlaylistSongBackupItem[] = [];
- for (let j = 0; j < songs.length; j++) {
- const song = songs[j];
- songBackups.push({
- songFilePath: song.songFilePath,
- addTime: song.addTime,
- sortOrder: song.sortOrder
- });
- }
- const playlistBackup: PlaylistBackupItem = {
- id: playlist.id,
- name: playlist.name,
- coverPath: playlist.coverPath || '',
- description: playlist.description || '',
- createTime: playlist.createTime,
- updateTime: playlist.updateTime,
- songCount: playlist.songCount,
- sortOrder: playlist.sortOrder,
- songs: songBackups
- };
- backupData.playlists.push(playlistBackup);
- }
- Logger.info('heanup PlaylistTable', `exportAllPlaylists: 导出完成, ${backupData.playlists.length} 个歌单`);
- return backupData;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `exportAllPlaylists: 导出失败: ${(error as Error).message}`);
- return backupData;
- }
- }
- /**
- * 从备份数据导入歌单
- * @param backupData 备份数据
- * @param conflictStrategy 冲突解决策略(null 表示需要逐一询问,由调用方处理)
- * @param conflictsToSkip 需要跳过的歌单名称集合
- * @param conflictsToOverwrite 需要覆盖的歌单名称集合
- * @param conflictsToRename 需要重命名的歌单名称集合
- */
- async importPlaylists(
- backupData: PlaylistBackupData,
- conflictsToSkip: Set<string>,
- conflictsToOverwrite: Set<string>,
- conflictsToRename: Set<string>
- ): Promise<ImportResult> {
- await this.ensureInitialized();
- const result: ImportResult = {
- totalPlaylists: backupData.playlists.length,
- importedPlaylists: 0,
- skippedPlaylists: 0,
- overwrittenPlaylists: 0,
- renamedPlaylists: 0,
- totalSongs: 0,
- importedSongs: 0,
- importedAccounts: 0,
- skippedAccounts: 0,
- settingsImported: false
- };
- if (!this.rdbStore) {
- Logger.error('heanup PlaylistTable', 'importPlaylists: 数据库未初始化');
- return result;
- }
- try {
- for (let i = 0; i < backupData.playlists.length; i++) {
- const playlistItem = backupData.playlists[i];
- result.totalSongs += playlistItem.songs.length;
- const existingPlaylist = await this.queryPlaylistByName(playlistItem.name);
- if (existingPlaylist) {
- // 存在同名歌单,按策略处理
- if (conflictsToSkip.has(playlistItem.name)) {
- result.skippedPlaylists++;
- Logger.info('heanup PlaylistTable', `importPlaylists: 跳过歌单: ${playlistItem.name}`);
- continue;
- } else if (conflictsToOverwrite.has(playlistItem.name)) {
- // 覆盖:先删除旧歌单
- await this.deletePlaylist(existingPlaylist.id);
- result.overwrittenPlaylists++;
- Logger.info('heanup PlaylistTable', `importPlaylists: 覆盖歌单: ${playlistItem.name}`);
- } else if (conflictsToRename.has(playlistItem.name)) {
- // 重命名
- const newName = await this.generateUniqueName(playlistItem.name);
- playlistItem.name = newName;
- result.renamedPlaylists++;
- Logger.info('heanup PlaylistTable', `importPlaylists: 重命名歌单为: ${newName}`);
- } else {
- // 默认跳过
- result.skippedPlaylists++;
- continue;
- }
- }
- // 创建歌单
- const created = await this.createPlaylist(
- playlistItem.name,
- playlistItem.description,
- playlistItem.coverPath
- );
- if (!created) {
- Logger.error('heanup PlaylistTable', `importPlaylists: 创建歌单失败: ${playlistItem.name}`);
- continue;
- }
- // 查询刚创建的歌单
- const newPlaylist = await this.queryPlaylistByName(playlistItem.name);
- if (!newPlaylist) {
- Logger.error('heanup PlaylistTable', `importPlaylists: 找不到新建歌单: ${playlistItem.name}`);
- continue;
- }
- result.importedPlaylists++;
- // 导入歌曲关联
- const songPaths: string[] = [];
- for (let j = 0; j < playlistItem.songs.length; j++) {
- songPaths.push(playlistItem.songs[j].songFilePath);
- }
- if (songPaths.length > 0) {
- const addResult = await this.addSongsToPlaylist(newPlaylist.id, songPaths);
- if (addResult) {
- result.importedSongs += songPaths.length;
- }
- }
- Logger.info('heanup PlaylistTable', `importPlaylists: 导入歌单成功: ${playlistItem.name}, ${songPaths.length} 首歌曲`);
- }
- Logger.info('heanup PlaylistTable', `importPlaylists: 导入完成, 共 ${result.importedPlaylists} 个歌单, ${result.importedSongs} 首歌曲`);
- return result;
- } catch (error) {
- Logger.error('heanup PlaylistTable', `importPlaylists: 导入失败: ${(error as Error).message}`);
- return result;
- }
- }
- /**
- * 生成不重复的歌单名称
- */
- private async generateUniqueName(baseName: string): Promise<string> {
- let suffix = 2;
- let candidateName = `${baseName} (${suffix})`;
- while (true) {
- const existing = await this.queryPlaylistByName(candidateName);
- if (!existing) {
- return candidateName;
- }
- suffix++;
- candidateName = `${baseName} (${suffix})`;
- }
- }
- /**
- * 检测备份数据中与现有歌单的冲突
- */
- async detectConflicts(backupData: PlaylistBackupData): Promise<string[]> {
- await this.ensureInitialized();
- const conflicts: string[] = [];
- for (let i = 0; i < backupData.playlists.length; i++) {
- const playlistItem = backupData.playlists[i];
- const existing = await this.queryPlaylistByName(playlistItem.name);
- if (existing) {
- conflicts.push(playlistItem.name);
- }
- }
- return conflicts;
- }
- /**
- * 自动备份回调(由 PlaylistBackupManager 注册,避免循环依赖)
- */
- private static autoBackupCallback: (() => void) | null = null;
- static registerAutoBackupCallback(callback: () => void): void {
- PlaylistTable.autoBackupCallback = callback;
- }
- /**
- * 触发自动备份
- */
- private triggerAutoBackup(): void {
- if (PlaylistTable.autoBackupCallback) {
- PlaylistTable.autoBackupCallback();
- }
- }
- }
|