MediaTable.ets 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. import relationalStore from '@ohos.data.relationalStore';
  2. import { LogUtil, StrUtil } from '@pura/harmony-utils';
  3. import { VideoItem } from '../../viewmodel/VideoItem';
  4. import Logger from './Logger';
  5. import RdbUtils from './RdbUtils';
  6. import { Utility } from './Utility';
  7. /**
  8. * 数据库字段常量接口定义
  9. */
  10. interface DBColumnsInterface {
  11. ID: string;
  12. NAME: string;
  13. FILE_PATH: string;
  14. TYPE: string;
  15. VIDEO_SIZE: string;
  16. C_TIME: string;
  17. PARENT_PATH: string;
  18. IS_FAV: string;
  19. PIXEL_MAP_PATH: string;
  20. ARTIST: string;
  21. ALBUM: string;
  22. FILE_NAME: string;
  23. SIZE: string;
  24. DURATION: string;
  25. MIME_TYPE: string;
  26. TRACK_COUNT: string;
  27. SAMPLE_RATE: string;
  28. LAST_PLAYED_STR: string;
  29. PLAY_COUNT: string;
  30. LYRIC_CONTENT: string;
  31. }
  32. /**
  33. * 数据库字段常量,避免硬编码
  34. */
  35. const DB_COLUMNS: DBColumnsInterface = {
  36. ID: 'id',
  37. NAME: 'name',
  38. FILE_PATH: 'filePath',
  39. TYPE: 'mtype',
  40. VIDEO_SIZE: 'videoSize',
  41. C_TIME: 'cTime',
  42. PARENT_PATH: 'parentPath',
  43. IS_FAV: 'isFav',
  44. PIXEL_MAP_PATH: 'pixelMapPath',
  45. ARTIST: 'artist',
  46. ALBUM: 'album',
  47. FILE_NAME: 'fileName',
  48. SIZE: 'size',
  49. DURATION: 'duration',
  50. MIME_TYPE: 'mimeType',
  51. TRACK_COUNT: 'trackCount',
  52. SAMPLE_RATE: 'sampleRate',
  53. LAST_PLAYED_STR: 'lastPlayedStr',
  54. PLAY_COUNT: 'playCount',
  55. LYRIC_CONTENT: 'lyricContent'
  56. };
  57. export default class MediaTable {
  58. private accountTable = new RdbUtils(RdbUtils.MEDIA_TABLE.tableName, RdbUtils.MEDIA_TABLE.sqlCreate,
  59. RdbUtils.MEDIA_TABLE.columns);
  60. constructor(context:Context,callback: Function = () => {
  61. }) {
  62. this.accountTable.getRdbStore(context,callback);
  63. }
  64. getRdbStore(context:Context,callback: Function = () => {
  65. }) {
  66. this.accountTable.getRdbStore(context,callback);
  67. }
  68. insert(item: VideoItem, callback: Function,cover_api?:string) {
  69. const valueBucket: relationalStore.ValuesBucket = generateBucket(item);
  70. this.accountTable.insertData(valueBucket, callback,cover_api);
  71. }
  72. deleteData(item: VideoItem, callback: Function) {
  73. let predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  74. predicates.equalTo('id', item.id);
  75. this.accountTable.deleteData(predicates, callback);
  76. }
  77. deleteDataFilePath(filePath: string, callback: Function) {
  78. let predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  79. predicates.equalTo('filePath', filePath);
  80. this.accountTable.deleteData(predicates, callback);
  81. }
  82. deleteDataForParentPath(parentPath:string, callback: Function) {
  83. let predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  84. predicates.equalTo('parentPath', parentPath);
  85. this.accountTable.deleteData(predicates, callback);
  86. }
  87. //更新音乐封面地址
  88. public updatePixelMapPath(filePath: string, newPixelMapPath: string, callback: Function) {
  89. // Step 1: 构建查询条件验证文件存在性
  90. const queryPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  91. queryPredicates.equalTo('filePath', filePath);
  92. // Step 2: 执行存在性验证
  93. this.accountTable.query(queryPredicates, (resultSet: relationalStore.ResultSet) => {
  94. if (resultSet.rowCount === 0) {
  95. callback(false, 'Error: Target file not found in database');
  96. resultSet.close();
  97. return;
  98. }
  99. resultSet.close();
  100. // Step 3: 构建更新条件与数据
  101. const updatePredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  102. updatePredicates.equalTo('filePath', filePath);
  103. const valueBucket: relationalStore.ValuesBucket = {
  104. pixelMapPath: newPixelMapPath
  105. };
  106. // Step 4: 执行原子化更新操作
  107. this.accountTable.updateData(updatePredicates, valueBucket, (success: boolean) => {
  108. callback(success, success ? null : 'Database update operation failed');
  109. });
  110. });
  111. }
  112. updateData(item: VideoItem, callback: Function) {
  113. const valueBucket: relationalStore.ValuesBucket = generateBucket(item);
  114. let predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  115. predicates.equalTo('id', item.id);
  116. this.accountTable.updateData(predicates, valueBucket, callback);
  117. }
  118. //编辑歌曲的信息更新数据库
  119. public updateMediaInfo(filePath: string, title: string, artist: string, album: string,
  120. lyricContent:string,year:string,genre:string,track:string,
  121. ALBUMARTIST:string,COMPOSER:string,LYRICIST:string,COMMENT:string,disc:string,
  122. callback: Function) {
  123. if (!callback || typeof callback !== 'function') {
  124. Logger.info(RdbUtils.RDB_TAG, 'updateMediaInfo() has no valid callback!');
  125. return;
  126. }
  127. if (!this.accountTable) {
  128. Logger.error(RdbUtils.RDB_TAG, 'RdbStore is not initialized.');
  129. callback(false);
  130. return;
  131. }
  132. // Step 1: Create a predicate to find the record by filePath
  133. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  134. predicates.equalTo('filePath', filePath);
  135. // Step 2: Query the database to check if the record exists
  136. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  137. if (resultSet.rowCount === 0) {
  138. Logger.info(RdbUtils.RDB_TAG, `No record found with filePath ${filePath}.`);
  139. callback(false);
  140. resultSet.close();
  141. return;
  142. }
  143. // Step 3: Prepare the values to update
  144. const valuesToUpdate: relationalStore.ValuesBucket = {};
  145. if (title !== '') {
  146. valuesToUpdate.name = title;
  147. }
  148. if (artist !== '') {
  149. valuesToUpdate.artist = artist;
  150. }
  151. if (album !== '') {
  152. valuesToUpdate.album = album;
  153. }
  154. if (lyricContent !== '') {
  155. valuesToUpdate.lyricContent = lyricContent;
  156. }
  157. if (year !== '') {
  158. valuesToUpdate.year = year;
  159. }
  160. if (genre !== '') {
  161. valuesToUpdate.genre = genre;
  162. }
  163. if (track !== '') {
  164. valuesToUpdate.track = track;
  165. }
  166. if (ALBUMARTIST !== '') {
  167. valuesToUpdate.ALBUMARTIST = ALBUMARTIST;
  168. }
  169. if (COMPOSER !== '') {
  170. valuesToUpdate.COMPOSER = COMPOSER;
  171. }
  172. if (LYRICIST !== '') {
  173. valuesToUpdate.LYRICIST = LYRICIST;
  174. }
  175. if (COMMENT !== '') {
  176. valuesToUpdate.COMMENT = COMMENT;
  177. }
  178. if (disc !== '') {
  179. valuesToUpdate.disc = disc;
  180. }
  181. resultSet.close();
  182. // Step 4: Update the record if there are values to update
  183. if (Object.keys(valuesToUpdate).length > 0) {
  184. this.accountTable.updateData(predicates, valuesToUpdate, (success: boolean) => {
  185. callback(success, success ? null : 'Database update operation failed');
  186. });
  187. } else {
  188. Logger.info(RdbUtils.RDB_TAG, 'No fields to update.');
  189. callback(false);
  190. }
  191. });
  192. }
  193. //更新重命名数据操作
  194. public updateRename(newName: string, oldPath: string, newPath: string, callback: Function) {
  195. // Step 1: 查询原始记录
  196. const queryPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  197. queryPredicates.equalTo('filePath', oldPath);
  198. this.accountTable.query(queryPredicates, (resultSet: relationalStore.ResultSet) => {
  199. if (resultSet.rowCount === 0) {
  200. callback(false, 'Error: File not found');
  201. return;
  202. }
  203. resultSet.goToFirstRow();
  204. // Step 3: 构建更新数据
  205. const currentName = resultSet.getString(resultSet.getColumnIndex('name'));
  206. const currentFileName = resultSet.getString(resultSet.getColumnIndex('fileName'));
  207. let obj: relationalStore.ValuesBucket = {};
  208. obj.id = newPath
  209. obj.filePath = newPath;
  210. if (currentName === currentFileName) {
  211. obj.name = newName;
  212. obj.fileName = newName;
  213. } else {
  214. obj.fileName = newName;
  215. }
  216. obj.mtype = resultSet.getDouble(resultSet.getColumnIndex('mtype'));
  217. obj.videoSize = resultSet.getDouble(resultSet.getColumnIndex('videoSize'));
  218. obj.cTime = resultSet.getString(resultSet.getColumnIndex('cTime'));
  219. obj.parentPath = resultSet.getString(resultSet.getColumnIndex('parentPath'));
  220. // obj.pixelMapToString = resultSet.getString(resultSet.getColumnIndex('pixelMapToString'));
  221. obj.artist = resultSet.getString(resultSet.getColumnIndex('artist'));
  222. obj.album = resultSet.getString(resultSet.getColumnIndex('album'));
  223. obj.isFav = resultSet.getDouble(resultSet.getColumnIndex('isFav'));
  224. obj.pixelMapPath = resultSet.getString(resultSet.getColumnIndex('pixelMapPath'));
  225. obj.duration = resultSet.getString(resultSet.getColumnIndex('duration'));
  226. obj.mimeType = resultSet.getString(resultSet.getColumnIndex('mimeType'));
  227. obj.trackCount = resultSet.getString(resultSet.getColumnIndex('trackCount'));
  228. obj.sampleRate = resultSet.getString(resultSet.getColumnIndex('sampleRate'));
  229. obj.lastPlayedStr = resultSet.getString(resultSet.getColumnIndex('lastPlayedStr'));
  230. obj.playCount = resultSet.getDouble(resultSet.getColumnIndex('playCount'));
  231. obj.lyricContent = resultSet.getString(resultSet.getColumnIndex('lyricContent'));
  232. obj.md5Str = resultSet.getString(resultSet.getColumnIndex('md5Str'));
  233. obj.extra_json = resultSet.getString(resultSet.getColumnIndex('extra_json'));
  234. obj.pyStr = resultSet.getString(resultSet.getColumnIndex('pyStr'));
  235. obj.bit_rate = resultSet.getString(resultSet.getColumnIndex('bit_rate'));
  236. obj.probe_score = resultSet.getDouble(resultSet.getColumnIndex('probe_score'));
  237. obj.year = resultSet.getString(resultSet.getColumnIndex('year'));
  238. obj.nb_streams = resultSet.getDouble(resultSet.getColumnIndex('nb_streams'));
  239. obj.nb_programs = resultSet.getDouble(resultSet.getColumnIndex('nb_programs'));
  240. obj.genre = resultSet.getString(resultSet.getColumnIndex('genre'));
  241. obj.track = resultSet.getString(resultSet.getColumnIndex('track'));
  242. obj.bits_per_raw_sample = resultSet.getString(resultSet.getColumnIndex('bits_per_raw_sample'));
  243. obj.channels = resultSet.getString(resultSet.getColumnIndex('channels'));
  244. obj.channel_layout = resultSet.getString(resultSet.getColumnIndex('channel_layout'));
  245. obj.start_time = resultSet.getString(resultSet.getColumnIndex('start_time'));
  246. obj.ALBUMARTIST = resultSet.getString(resultSet.getColumnIndex('ALBUMARTIST'));
  247. obj.COMPOSER = resultSet.getString(resultSet.getColumnIndex('COMPOSER'));
  248. obj.LYRICIST = resultSet.getString(resultSet.getColumnIndex('LYRICIST'));
  249. obj.COMMENT = resultSet.getString(resultSet.getColumnIndex('COMMENT'));
  250. obj.disc = resultSet.getString(resultSet.getColumnIndex('disc'));
  251. const valueBucket: relationalStore.ValuesBucket = obj
  252. // Step 4: 执行更新
  253. const updatePredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  254. updatePredicates.equalTo('filePath', oldPath);
  255. this.accountTable.updateData(updatePredicates, valueBucket, (success: boolean) => {
  256. callback(success, success ? null : 'Update failed');
  257. });
  258. resultSet.close()
  259. });
  260. }
  261. // 根据isFav查询数据
  262. public queryByisFav(isFav: number, callback: (result: VideoItem[]) => void) {
  263. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  264. predicates.equalTo('isFav', isFav);
  265. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  266. const result = this.parseResultSetToVideoItems(resultSet);
  267. callback(result);
  268. });
  269. }
  270. // 根据filePath更新isFav的值
  271. public updateIsFavByFilePath(filePath: string, isFav: number, callback: (success: boolean, error?: string) => void) {
  272. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  273. predicates.equalTo('filePath', filePath);
  274. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  275. if (resultSet.rowCount === 0) {
  276. callback(false, 'Error: File not found');
  277. resultSet.close();
  278. return;
  279. }
  280. resultSet.close();
  281. const valueBucket: relationalStore.ValuesBucket = { isFav: isFav };
  282. this.accountTable.updateData(predicates, valueBucket, (success: boolean) => {
  283. callback(success, success ? '' : 'Update failed');
  284. });
  285. });
  286. }
  287. // 查询全部,或者某个id(查询的字段,回调,是否查询全部)
  288. query(id: number, callback: Function, isAll: boolean = true) {
  289. let predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  290. if (!isAll) {
  291. predicates.equalTo('id', id);
  292. }
  293. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  294. let count: number = resultSet.rowCount;
  295. if (count === 0 || typeof count === 'string') {
  296. console.log(`${RdbUtils.RDB_TAG}` + 'Query no results!');
  297. callback([]);
  298. } else {
  299. const result = this.parseResultSetToVideoItems(resultSet);
  300. callback(result);
  301. }
  302. });
  303. }
  304. // 新增方法:根据parentPath查询数据
  305. public queryByParentPath(path: string, callback: (result: VideoItem[]) => void) {
  306. try {
  307. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  308. predicates.equalTo('parentPath', path);
  309. LogUtil.info('onecold parentPath = '+path)
  310. // 2. 执行查询并处理结果
  311. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  312. // 3. 复用已有的解析逻辑
  313. const result = this.parseResultSetToVideoItems(resultSet);
  314. callback(result);
  315. });
  316. }catch (err) {
  317. Logger.error(` onecold testtag queryByParentPath: ${err.code} - ${err.message}`);
  318. }
  319. // 1. 构建查询条件
  320. }
  321. // 查询所有艺术家及其歌曲(返回Map结构:artist -> VideoItem[])
  322. public queryArtistsWithSongs(callback: (result: Map<string, VideoItem[]>) => void) {
  323. // 1. 查询去重的艺术家列表(非空)
  324. const artistPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  325. artistPredicates.isNotNull('artist').distinct();
  326. this.accountTable.query(artistPredicates, (resultSet: relationalStore.ResultSet) => {
  327. const artists: string[] = this.parseDistinctColumn(resultSet, 'artist');
  328. // 2. 遍历每个艺术家,查询其歌曲
  329. const resultMap = new Map<string, VideoItem[]>();
  330. let processedCount = 0;
  331. if (artists.length === 0) {
  332. callback(resultMap);
  333. return;
  334. }
  335. artists.forEach(artist => {
  336. const songPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  337. songPredicates.equalTo('artist', artist);
  338. this.accountTable.query(songPredicates, (songResultSet: relationalStore.ResultSet) => {
  339. const songs = this.parseResultSetToVideoItems(songResultSet);
  340. resultMap.set(artist, songs);
  341. processedCount++;
  342. // 3. 全部查询完成后回调
  343. if (processedCount === artists.length) {
  344. callback(resultMap);
  345. }
  346. });
  347. });
  348. });
  349. }
  350. // 查询所有专辑及其歌曲(返回Map结构:album -> VideoItem[])
  351. public queryAlbumsWithSongs(callback: (result: Map<string, VideoItem[]>) => void) {
  352. // 1. 查询去重的专辑列表(非空)
  353. const albumPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  354. albumPredicates.isNotNull('album').distinct();
  355. this.accountTable.query(albumPredicates, (resultSet: relationalStore.ResultSet) => {
  356. const albums: string[] = this.parseDistinctColumn(resultSet, 'album');
  357. // 2. 遍历每个专辑,查询其歌曲
  358. const resultMap = new Map<string, VideoItem[]>();
  359. let processedCount = 0;
  360. if (albums.length === 0) {
  361. callback(resultMap);
  362. return;
  363. }
  364. albums.forEach(album => {
  365. const songPredicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  366. songPredicates.equalTo('album', album);
  367. this.accountTable.query(songPredicates, (songResultSet: relationalStore.ResultSet) => {
  368. const songs = this.parseResultSetToVideoItems(songResultSet);
  369. resultMap.set(album, songs);
  370. processedCount++;
  371. // 3. 全部查询完成后回调
  372. if (processedCount === albums.length) {
  373. callback(resultMap);
  374. }
  375. });
  376. });
  377. });
  378. }
  379. // 解析去重列数据(如artist/album)
  380. private parseDistinctColumn(resultSet: relationalStore.ResultSet, columnName: string): string[] {
  381. const uniqueValues = new Set<string>(); // 使用Set特性自动去重
  382. if (resultSet.rowCount > 0) {
  383. resultSet.goToFirstRow();
  384. for (let i = 0; i < resultSet.rowCount; i++) {
  385. const value = resultSet.getString(resultSet.getColumnIndex(columnName))?.trim(); // 处理空格
  386. if (value) { // 过滤空值
  387. uniqueValues.add(value);
  388. }
  389. if (i < resultSet.rowCount - 1) { // 避免最后一行越界
  390. resultSet.goToNextRow();
  391. }
  392. }
  393. }
  394. resultSet.close();
  395. return Array.from(uniqueValues); // Set转数组
  396. }
  397. // 将ResultSet解析为VideoItem数组(复用原有逻辑)
  398. private parseResultSetToVideoItems(resultSet: relationalStore.ResultSet): VideoItem[] {
  399. const items: VideoItem[] = [];
  400. try {
  401. // 检查结果集是否有效
  402. if (resultSet && resultSet.rowCount > 0) {
  403. while (resultSet.goToNextRow()) {
  404. const item = this.buildVideoItem(resultSet);
  405. items.push(item);
  406. }
  407. }
  408. } catch (err) {
  409. Logger.error(`解析结果集出错: ${err.message}`);
  410. } finally {
  411. // 确保结果集被关闭
  412. if (resultSet) {
  413. resultSet.close();
  414. }
  415. }
  416. return items;
  417. }
  418. // 根据filePath更新lastPlayedStr的值同时playCount值加1
  419. public updateLastPlayedStrByFilePath(filePath: string, lastPlayedStr: string, callback: (success: boolean, error?: string) => void) {
  420. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  421. predicates.equalTo('filePath', filePath);
  422. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  423. if (resultSet.rowCount === 0) {
  424. callback(false, 'Error: File not found');
  425. resultSet.close();
  426. return;
  427. }
  428. // 获取当前的 playCount 值
  429. let currentPlayCount = 0;
  430. if (resultSet.goToFirstRow()) {
  431. currentPlayCount = resultSet.getLong(resultSet.getColumnIndex('playCount'));
  432. }
  433. resultSet.close();
  434. // 计算新的 playCount 值
  435. const newPlayCount = currentPlayCount + 1;
  436. // 准备要更新的值
  437. const valueBucket: relationalStore.ValuesBucket = {
  438. lastPlayedStr: lastPlayedStr,
  439. playCount: newPlayCount
  440. };
  441. // 更新数据
  442. this.accountTable.updateData(predicates, valueBucket, (success: boolean) => {
  443. callback(success, success ? '' : 'Update failed');
  444. });
  445. });
  446. }
  447. // 根据最近播放时间查询指定数量的记录
  448. public queryRecentPlayedRecords(count: number, callback: (result: VideoItem[]) => void) {
  449. try {
  450. // 1. 构建查询条件:按lastPlayedStr降序排列,限制返回条数,且lastPlayedStr不为空
  451. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  452. // 添加筛选条件,确保lastPlayedStr不为空
  453. predicates.isNotNull('lastPlayedStr');
  454. predicates.notEqualTo('lastPlayedStr', ''); // 排除空字符串
  455. // 使用 orderByDesc 方法进行降序排序
  456. predicates.orderByDesc('lastPlayedStr');
  457. // 使用 limit 方法限制返回的记录数量
  458. predicates.limitAs(count);
  459. // 2. 执行查询并处理结果
  460. this.accountTable.query(predicates, (resultSet: relationalStore.ResultSet) => {
  461. // 3. 复用已有的解析逻辑
  462. const result = this.parseResultSetToVideoItems(resultSet);
  463. callback(result);
  464. });
  465. } catch (err) {
  466. Logger.error(`queryRecentPlayedRecords error: ${err.code} - ${err.message}`);
  467. callback([]);
  468. }
  469. }
  470. // 清空播放历史记录
  471. public clearPlayHistory(callback: (success: boolean, error?: string) => void) {
  472. // 1. 构建查询条件:筛选lastPlayedStr非空的记录
  473. const predicates = new relationalStore.RdbPredicates(RdbUtils.MEDIA_TABLE.tableName);
  474. predicates.isNotNull('lastPlayedStr');
  475. // 2. 准备更新数据:将lastPlayedStr设为空字符串
  476. const valueBucket: relationalStore.ValuesBucket = {
  477. lastPlayedStr: ''
  478. };
  479. // 3. 执行批量更新操作
  480. this.accountTable.updateData(predicates, valueBucket, (success: boolean) => {
  481. // 将 null 替换为 undefined
  482. callback(success, success ? 'Clear play history success' : 'Clear play history operation failed');
  483. });
  484. }
  485. private buildVideoItem(rs: relationalStore.ResultSet): VideoItem {
  486. // 添加空值保护
  487. const safeGet = (col: string) => {
  488. const index = rs.getColumnIndex(col);
  489. return index >= 0 ? rs.getString(index) || '' : '';
  490. };
  491. const safeGetNumber = (col: string) => {
  492. const index = rs.getColumnIndex(col);
  493. return index >= 0 ? rs.getDouble(index) || 0 : 0;
  494. };
  495. let item = new VideoItem(
  496. safeGet(DB_COLUMNS.NAME),
  497. safeGet(DB_COLUMNS.ID),
  498. safeGet(DB_COLUMNS.FILE_PATH),
  499. safeGetNumber(DB_COLUMNS.TYPE),
  500. safeGetNumber(DB_COLUMNS.VIDEO_SIZE),
  501. safeGet(DB_COLUMNS.C_TIME),
  502. undefined,
  503. safeGet(DB_COLUMNS.SIZE),
  504. safeGet(DB_COLUMNS.PIXEL_MAP_PATH),
  505. safeGet(DB_COLUMNS.ARTIST),
  506. safeGet(DB_COLUMNS.ALBUM),
  507. safeGet(DB_COLUMNS.FILE_NAME)
  508. );
  509. // 设置额外属性,添加安全检查
  510. item.isFav = safeGetNumber(DB_COLUMNS.IS_FAV);
  511. item.duration = safeGet(DB_COLUMNS.DURATION);
  512. item.mimeType = safeGet(DB_COLUMNS.MIME_TYPE);
  513. item.trackCount = safeGet(DB_COLUMNS.TRACK_COUNT);
  514. item.sampleRate = safeGet(DB_COLUMNS.SAMPLE_RATE);
  515. item.lastPlayedStr = safeGet(DB_COLUMNS.LAST_PLAYED_STR);
  516. item.playCount = safeGetNumber(DB_COLUMNS.PLAY_COUNT);
  517. item.lyricContent = safeGet(DB_COLUMNS.LYRIC_CONTENT);
  518. item.md5Str = safeGet('md5Str');
  519. item.extra_json = safeGet('extra_json');
  520. item.pyStr = safeGet('pyStr');
  521. item.bit_rate = safeGet('bit_rate');
  522. item.probe_score = safeGetNumber('probe_score');
  523. item.year = safeGet('year');
  524. item.nb_streams = safeGetNumber('nb_streams');
  525. item.nb_programs = safeGetNumber('nb_programs');
  526. item.genre = safeGet('genre');
  527. item.track = safeGet('track');
  528. item.bits_per_raw_sample = safeGet('bits_per_raw_sample');
  529. item.channels = safeGet('channels');
  530. item.channel_layout = safeGet('channel_layout');
  531. item.start_time = safeGet('start_time');
  532. item.ALBUMARTIST = safeGet('ALBUMARTIST');
  533. item.COMPOSER = safeGet('COMPOSER');
  534. item.LYRICIST = safeGet('LYRICIST');
  535. item.COMMENT = safeGet('COMMENT');
  536. item.disc = safeGet('disc');
  537. return item;
  538. }
  539. }
  540. function generateBucket(item: VideoItem): relationalStore.ValuesBucket {
  541. let obj: relationalStore.ValuesBucket = {};
  542. obj.id = item.id
  543. obj.name = item.name;
  544. obj.filePath = item.filePath;
  545. obj.mtype = item.type;
  546. obj.videoSize = item.videoSize;
  547. obj.cTime = item.cTime;
  548. obj.parentPath = item.parentPath;
  549. obj.isFav = item.isFav;
  550. // if(item.pixelMapToString){
  551. // obj.pixelMapToString = item.pixelMapToString;
  552. // }
  553. if(item.artist){
  554. obj.artist = item.artist;
  555. }
  556. if(item.album){
  557. obj.album = item.album;
  558. }
  559. if(item.fileName){
  560. obj.fileName = item.fileName;
  561. }
  562. if(item.size){
  563. obj.size = item.size;
  564. }
  565. if(item.pixelMapPath){
  566. obj.pixelMapPath = item.pixelMapPath;
  567. }
  568. if(item.duration){
  569. obj.duration = item.duration;
  570. }
  571. if(item.mimeType){
  572. obj.mimeType = item.mimeType;
  573. }
  574. if(item.trackCount){
  575. obj.trackCount = item.trackCount;
  576. }
  577. if(item.sampleRate){
  578. obj.sampleRate = item.sampleRate;
  579. }
  580. if(item.lastPlayedStr){
  581. obj.lastPlayedStr = item.lastPlayedStr;
  582. }
  583. if(item.playCount){
  584. obj.playCount = item.playCount;
  585. }
  586. if(item.lyricContent){
  587. obj.lyricContent = item.lyricContent;
  588. }
  589. if(item.md5Str){
  590. obj.md5Str = item.md5Str;
  591. }
  592. if(item.extra_json){
  593. obj.extra_json = item.extra_json;
  594. }
  595. if(item.pyStr){
  596. obj.pyStr = item.pyStr;
  597. }
  598. if(item.bit_rate){
  599. obj.bit_rate = item.bit_rate;
  600. }
  601. if(item.probe_score){
  602. obj.probe_score = item.probe_score;
  603. }
  604. if(item.year){
  605. obj.year = item.year;
  606. }
  607. if(item.nb_streams){
  608. obj.nb_streams = item.nb_streams;
  609. }
  610. if(item.nb_programs){
  611. obj.nb_programs = item.nb_programs;
  612. }
  613. if(item.genre){
  614. obj.genre = item.genre;
  615. }
  616. if(item.track){
  617. obj.track = item.track;
  618. }
  619. if(item.bits_per_raw_sample){
  620. obj.bits_per_raw_sample = item.bits_per_raw_sample;
  621. }
  622. if(item.channels){
  623. obj.channels = item.channels;
  624. }
  625. if(item.channel_layout){
  626. obj.channel_layout = item.channel_layout;
  627. }
  628. if(item.start_time){
  629. obj.start_time = item.start_time;
  630. }
  631. if(item.ALBUMARTIST){
  632. obj.ALBUMARTIST = item.ALBUMARTIST;
  633. }
  634. if(item.COMPOSER){
  635. obj.COMPOSER = item.COMPOSER;
  636. }
  637. if(item.LYRICIST){
  638. obj.LYRICIST = item.LYRICIST;
  639. }
  640. if(item.COMMENT){
  641. obj.COMMENT = item.COMMENT;
  642. }
  643. if(item.disc){
  644. obj.disc = item.disc;
  645. }
  646. return obj;
  647. }