|
|
@@ -103,6 +103,8 @@ export interface PageQueryResult {
|
|
|
export interface RandomSongQueryOptions {
|
|
|
type?: number;
|
|
|
excludeFilePaths?: string[];
|
|
|
+ parentPath?: string; // 文件夹路径(用于首页模式随机播放)
|
|
|
+ playlistSongFilePaths?: string[]; // 歌单歌曲路径列表(用于歌单模式随机播放)
|
|
|
}
|
|
|
|
|
|
export default class MediaTable {
|
|
|
@@ -1106,16 +1108,41 @@ export default class MediaTable {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 从数据库随机获取一首歌曲(可选条件:类型、排除路径)
|
|
|
+ * 从数据库随机获取一首歌曲(可选条件:类型、排除路径、文件夹、歌单)
|
|
|
*/
|
|
|
public async queryRandomSong(options?: RandomSongQueryOptions): Promise<VideoItem | null> {
|
|
|
try {
|
|
|
+ // 优先处理歌单模式
|
|
|
+ if (options?.playlistSongFilePaths && options.playlistSongFilePaths.length > 0) {
|
|
|
+ Logger.info(RdbUtils.RDB_TAG, `queryRandomSong: 歌单模式,歌曲数量=${options.playlistSongFilePaths.length}`);
|
|
|
+ // 过滤掉排除的路径
|
|
|
+ let availablePaths = options.playlistSongFilePaths;
|
|
|
+ if (options.excludeFilePaths && options.excludeFilePaths.length > 0) {
|
|
|
+ const excludeSet = new Set(options.excludeFilePaths);
|
|
|
+ availablePaths = availablePaths.filter(path => !excludeSet.has(path));
|
|
|
+ }
|
|
|
+ if (availablePaths.length === 0) {
|
|
|
+ Logger.warn(RdbUtils.RDB_TAG, 'queryRandomSong: 歌单中没有可用歌曲');
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 随机选择一个路径
|
|
|
+ const randomPath = availablePaths[Math.floor(Math.random() * availablePaths.length)];
|
|
|
+ return await this.queryVideoByFilePath(randomPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 文件夹模式或全局模式
|
|
|
const conditions: string[] = [];
|
|
|
const params: Array<string | number> = [];
|
|
|
if (options?.type !== undefined) {
|
|
|
conditions.push(`${DB_COLUMNS.TYPE} = ?`);
|
|
|
params.push(options.type);
|
|
|
}
|
|
|
+ // 文件夹条件
|
|
|
+ if (options?.parentPath) {
|
|
|
+ conditions.push(`${DB_COLUMNS.PARENT_PATH} = ?`);
|
|
|
+ params.push(options.parentPath);
|
|
|
+ }
|
|
|
+ // 排除路径条件
|
|
|
if (options?.excludeFilePaths && options.excludeFilePaths.length > 0) {
|
|
|
const normalizedPaths = options.excludeFilePaths.map(path => normalizeFilePath(path));
|
|
|
const placeholders = normalizedPaths.map(() => '?').join(', ');
|
|
|
@@ -1128,6 +1155,8 @@ export default class MediaTable {
|
|
|
}
|
|
|
sql += ' ORDER BY RANDOM() LIMIT 1';
|
|
|
|
|
|
+ Logger.info(RdbUtils.RDB_TAG, `queryRandomSong: SQL=${sql}, params=${JSON.stringify(params)}`);
|
|
|
+
|
|
|
const resultSet = await this.accountTable.querySql(sql, params);
|
|
|
try {
|
|
|
if (resultSet.rowCount === 0) {
|