|
@@ -0,0 +1,323 @@
|
|
|
|
|
+import relationalStore from '@ohos.data.relationalStore';
|
|
|
|
|
+import { BusinessError } from '@kit.BasicServicesKit';
|
|
|
|
|
+import { hilog } from '@kit.PerformanceAnalysisKit';
|
|
|
|
|
+import { Context } from '@kit.AbilityKit';
|
|
|
|
|
+import { WidgetDataInfo } from '../viewmodel/WidgetDataInfo';
|
|
|
|
|
+
|
|
|
|
|
+const TAG = 'WidgetDataRdbHelper';
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Widget数据数据库操作助手类
|
|
|
|
|
+ */
|
|
|
|
|
+export class WidgetDataRdbHelper {
|
|
|
|
|
+ private static instance: WidgetDataRdbHelper | null = null;
|
|
|
|
|
+ private rdbStore: relationalStore.RdbStore | null = null;
|
|
|
|
|
+ private context: Context | null = null;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 数据库配置
|
|
|
|
|
+ */
|
|
|
|
|
+ private static readonly STORE_CONFIG: relationalStore.StoreConfig = {
|
|
|
|
|
+ name: 'WidgetDataDatabase.db',
|
|
|
|
|
+ securityLevel: relationalStore.SecurityLevel.S1,
|
|
|
|
|
+ encrypt: false
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 表名
|
|
|
|
|
+ */
|
|
|
|
|
+ private static readonly WIDGET_DATA_TABLE = 'widget_data_info';
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 创建表的SQL语句
|
|
|
|
|
+ */
|
|
|
|
|
+ private static readonly CREATE_TABLE_SQL = `CREATE TABLE IF NOT EXISTS ${WidgetDataRdbHelper.WIDGET_DATA_TABLE} (
|
|
|
|
|
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
+ song_id TEXT NOT NULL,
|
|
|
|
|
+ name TEXT NOT NULL,
|
|
|
|
|
+ artist TEXT NOT NULL,
|
|
|
|
|
+ album TEXT NOT NULL,
|
|
|
|
|
+ pixel_map_path TEXT,
|
|
|
|
|
+ duration INTEGER DEFAULT 0,
|
|
|
|
|
+ file_path TEXT,
|
|
|
|
|
+ img_name TEXT,
|
|
|
|
|
+ image_color_hex TEXT DEFAULT '2A2A2A',
|
|
|
|
|
+ is_favorite INTEGER DEFAULT 0,
|
|
|
|
|
+ is_playing INTEGER DEFAULT 0,
|
|
|
|
|
+ is_paused INTEGER DEFAULT 1,
|
|
|
|
|
+ is_loading INTEGER DEFAULT 0,
|
|
|
|
|
+ current_position INTEGER DEFAULT 0,
|
|
|
|
|
+ has_next INTEGER DEFAULT 0,
|
|
|
|
|
+ has_previous INTEGER DEFAULT 0,
|
|
|
|
|
+ play_mode INTEGER DEFAULT 0,
|
|
|
|
|
+ current_index INTEGER DEFAULT 0,
|
|
|
|
|
+ total_count INTEGER DEFAULT 0,
|
|
|
|
|
+ current_time_text TEXT DEFAULT '',
|
|
|
|
|
+ total_time_text TEXT DEFAULT '',
|
|
|
|
|
+ progress_percentage REAL DEFAULT 0,
|
|
|
|
|
+ create_time TEXT NOT NULL,
|
|
|
|
|
+ update_time TEXT NOT NULL
|
|
|
|
|
+ )`;
|
|
|
|
|
+
|
|
|
|
|
+ private constructor() {}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取单例实例
|
|
|
|
|
+ */
|
|
|
|
|
+ static getInstance(context?: Context): WidgetDataRdbHelper {
|
|
|
|
|
+ if (!WidgetDataRdbHelper.instance) {
|
|
|
|
|
+ WidgetDataRdbHelper.instance = new WidgetDataRdbHelper();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (context && !WidgetDataRdbHelper.instance.context) {
|
|
|
|
|
+ WidgetDataRdbHelper.instance.context = context;
|
|
|
|
|
+ }
|
|
|
|
|
+ return WidgetDataRdbHelper.instance;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 初始化数据库
|
|
|
|
|
+ */
|
|
|
|
|
+ private async initDatabase(): Promise<void> {
|
|
|
|
|
+ if (this.rdbStore) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.context) {
|
|
|
|
|
+ throw new Error('Context is not available');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.rdbStore = await relationalStore.getRdbStore(this.context, WidgetDataRdbHelper.STORE_CONFIG);
|
|
|
|
|
+ await this.rdbStore.executeSql(WidgetDataRdbHelper.CREATE_TABLE_SQL);
|
|
|
|
|
+ hilog.info(0x0000, TAG, 'Widget data database initialized successfully');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to initialize widget data database: ${businessError.message}`);
|
|
|
|
|
+ throw new Error(businessError.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取数据库实例
|
|
|
|
|
+ */
|
|
|
|
|
+ private async getRdbStore(): Promise<relationalStore.RdbStore> {
|
|
|
|
|
+ if (!this.rdbStore) {
|
|
|
|
|
+ await this.initDatabase();
|
|
|
|
|
+ }
|
|
|
|
|
+ return this.rdbStore!;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 插入或更新Widget数据信息
|
|
|
|
|
+ * 使用 REPLACE INTO 语句,如果记录存在则更新,不存在则插入
|
|
|
|
|
+ */
|
|
|
|
|
+ async insertOrUpdateWidgetData(widgetDataInfo: WidgetDataInfo): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const store = await this.getRdbStore();
|
|
|
|
|
+
|
|
|
|
|
+ // 先删除现有记录(只保留最新的widget数据)
|
|
|
|
|
+ await this.clearAllWidgetData();
|
|
|
|
|
+
|
|
|
|
|
+ const valueBucket: relationalStore.ValuesBucket = {
|
|
|
|
|
+ 'song_id': widgetDataInfo.songId,
|
|
|
|
|
+ 'name': widgetDataInfo.name,
|
|
|
|
|
+ 'artist': widgetDataInfo.artist,
|
|
|
|
|
+ 'album': widgetDataInfo.album,
|
|
|
|
|
+ 'pixel_map_path': widgetDataInfo.pixelMapPath,
|
|
|
|
|
+ 'duration': widgetDataInfo.duration,
|
|
|
|
|
+ 'file_path': widgetDataInfo.filePath,
|
|
|
|
|
+ 'img_name': widgetDataInfo.imgName,
|
|
|
|
|
+ 'image_color_hex': widgetDataInfo.imageColorHex,
|
|
|
|
|
+ 'is_favorite': widgetDataInfo.isFavorite ? 1 : 0,
|
|
|
|
|
+ 'is_playing': widgetDataInfo.isPlaying ? 1 : 0,
|
|
|
|
|
+ 'is_paused': widgetDataInfo.isPaused ? 1 : 0,
|
|
|
|
|
+ 'is_loading': widgetDataInfo.isLoading ? 1 : 0,
|
|
|
|
|
+ 'current_position': widgetDataInfo.currentPosition,
|
|
|
|
|
+ 'has_next': widgetDataInfo.hasNext ? 1 : 0,
|
|
|
|
|
+ 'has_previous': widgetDataInfo.hasPrevious ? 1 : 0,
|
|
|
|
|
+ 'play_mode': widgetDataInfo.playMode,
|
|
|
|
|
+ 'current_index': widgetDataInfo.currentIndex,
|
|
|
|
|
+ 'total_count': widgetDataInfo.totalCount,
|
|
|
|
|
+ 'current_time_text': widgetDataInfo.currentTimeText,
|
|
|
|
|
+ 'total_time_text': widgetDataInfo.totalTimeText,
|
|
|
|
|
+ 'progress_percentage': widgetDataInfo.progressPercentage,
|
|
|
|
|
+ 'create_time': widgetDataInfo.createTime,
|
|
|
|
|
+ 'update_time': new Date().toISOString(),
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ await store.insert(WidgetDataRdbHelper.WIDGET_DATA_TABLE, valueBucket);
|
|
|
|
|
+ hilog.info(0x0000, TAG, `Widget data inserted successfully for song: ${widgetDataInfo.name}`);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to insert widget data: ${businessError.message}`);
|
|
|
|
|
+ throw new Error(businessError.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取最新的Widget数据信息
|
|
|
|
|
+ */
|
|
|
|
|
+ async getLatestWidgetData(): Promise<WidgetDataInfo | undefined> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const store = await this.getRdbStore();
|
|
|
|
|
+ const predicates = new relationalStore.RdbPredicates(WidgetDataRdbHelper.WIDGET_DATA_TABLE);
|
|
|
|
|
+ predicates.orderByDesc('update_time');
|
|
|
|
|
+
|
|
|
|
|
+ const resultSet = await store.query(predicates);
|
|
|
|
|
+ if (resultSet.rowCount === 0) {
|
|
|
|
|
+ resultSet.close();
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ resultSet.goToFirstRow();
|
|
|
|
|
+ const widgetDataInfo = this.mapRowToWidgetDataInfo(resultSet);
|
|
|
|
|
+ resultSet.close();
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, TAG, `Latest widget data retrieved: ${widgetDataInfo.name}`);
|
|
|
|
|
+ return widgetDataInfo;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to query latest widget data: ${businessError.message}`);
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据歌曲ID查询Widget数据信息
|
|
|
|
|
+ */
|
|
|
|
|
+ async queryWidgetDataBySongId(songId: string): Promise<WidgetDataInfo | undefined> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const store = await this.getRdbStore();
|
|
|
|
|
+ const predicates = new relationalStore.RdbPredicates(WidgetDataRdbHelper.WIDGET_DATA_TABLE);
|
|
|
|
|
+ predicates.equalTo('song_id', songId);
|
|
|
|
|
+
|
|
|
|
|
+ const resultSet = await store.query(predicates);
|
|
|
|
|
+ if (resultSet.rowCount === 0) {
|
|
|
|
|
+ resultSet.close();
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ resultSet.goToFirstRow();
|
|
|
|
|
+ const widgetDataInfo = this.mapRowToWidgetDataInfo(resultSet);
|
|
|
|
|
+ resultSet.close();
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, TAG, `Widget data queried successfully for song: ${songId}`);
|
|
|
|
|
+ return widgetDataInfo;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to query widget data by song ID: ${businessError.message}`);
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询所有Widget数据信息
|
|
|
|
|
+ */
|
|
|
|
|
+ async queryAllWidgetData(): Promise<WidgetDataInfo[]> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const store = await this.getRdbStore();
|
|
|
|
|
+ const predicates = new relationalStore.RdbPredicates(WidgetDataRdbHelper.WIDGET_DATA_TABLE);
|
|
|
|
|
+ predicates.orderByDesc('update_time');
|
|
|
|
|
+
|
|
|
|
|
+ const resultSet = await store.query(predicates);
|
|
|
|
|
+
|
|
|
|
|
+ const widgetDataList: WidgetDataInfo[] = [];
|
|
|
|
|
+ if (resultSet.rowCount > 0) {
|
|
|
|
|
+ resultSet.goToFirstRow();
|
|
|
|
|
+ do {
|
|
|
|
|
+ const widgetDataInfo = this.mapRowToWidgetDataInfo(resultSet);
|
|
|
|
|
+ widgetDataList.push(widgetDataInfo);
|
|
|
|
|
+ } while (resultSet.goToNextRow());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ resultSet.close();
|
|
|
|
|
+ hilog.info(0x0000, TAG, `Queried ${widgetDataList.length} widget data records`);
|
|
|
|
|
+ return widgetDataList;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to query all widget data: ${businessError.message}`);
|
|
|
|
|
+ throw new Error(businessError.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 删除Widget数据信息
|
|
|
|
|
+ */
|
|
|
|
|
+ async deleteWidgetData(songId: string): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const store = await this.getRdbStore();
|
|
|
|
|
+ const predicates = new relationalStore.RdbPredicates(WidgetDataRdbHelper.WIDGET_DATA_TABLE);
|
|
|
|
|
+ predicates.equalTo('song_id', songId);
|
|
|
|
|
+
|
|
|
|
|
+ await store.delete(predicates);
|
|
|
|
|
+ hilog.info(0x0000, TAG, `Widget data deleted successfully for song: ${songId}`);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to delete widget data: ${businessError.message}`);
|
|
|
|
|
+ throw new Error(businessError.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 清空所有Widget数据信息
|
|
|
|
|
+ */
|
|
|
|
|
+ async clearAllWidgetData(): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const store = await this.getRdbStore();
|
|
|
|
|
+ const predicates = new relationalStore.RdbPredicates(WidgetDataRdbHelper.WIDGET_DATA_TABLE);
|
|
|
|
|
+
|
|
|
|
|
+ await store.delete(predicates);
|
|
|
|
|
+ hilog.info(0x0000, TAG, 'All widget data cleared successfully');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ hilog.error(0x0000, TAG, `Failed to clear all widget data: ${businessError.message}`);
|
|
|
|
|
+ throw new Error(businessError.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 将查询结果映射为WidgetDataInfo对象
|
|
|
|
|
+ */
|
|
|
|
|
+ private mapRowToWidgetDataInfo(resultSet: relationalStore.ResultSet): WidgetDataInfo {
|
|
|
|
|
+ const widgetDataInfo = new WidgetDataInfo();
|
|
|
|
|
+
|
|
|
|
|
+ widgetDataInfo.id = resultSet.getLong(resultSet.getColumnIndex('id'));
|
|
|
|
|
+ widgetDataInfo.songId = resultSet.getString(resultSet.getColumnIndex('song_id'));
|
|
|
|
|
+ widgetDataInfo.name = resultSet.getString(resultSet.getColumnIndex('name'));
|
|
|
|
|
+ widgetDataInfo.artist = resultSet.getString(resultSet.getColumnIndex('artist'));
|
|
|
|
|
+ widgetDataInfo.album = resultSet.getString(resultSet.getColumnIndex('album'));
|
|
|
|
|
+ widgetDataInfo.pixelMapPath = resultSet.getString(resultSet.getColumnIndex('pixel_map_path'));
|
|
|
|
|
+ widgetDataInfo.duration = resultSet.getLong(resultSet.getColumnIndex('duration'));
|
|
|
|
|
+ widgetDataInfo.filePath = resultSet.getString(resultSet.getColumnIndex('file_path'));
|
|
|
|
|
+ widgetDataInfo.imgName = resultSet.getString(resultSet.getColumnIndex('img_name'));
|
|
|
|
|
+ widgetDataInfo.imageColorHex = resultSet.getString(resultSet.getColumnIndex('image_color_hex'));
|
|
|
|
|
+ widgetDataInfo.isFavorite = resultSet.getLong(resultSet.getColumnIndex('is_favorite')) === 1;
|
|
|
|
|
+ widgetDataInfo.isPlaying = resultSet.getLong(resultSet.getColumnIndex('is_playing')) === 1;
|
|
|
|
|
+ widgetDataInfo.isPaused = resultSet.getLong(resultSet.getColumnIndex('is_paused')) === 1;
|
|
|
|
|
+ widgetDataInfo.isLoading = resultSet.getLong(resultSet.getColumnIndex('is_loading')) === 1;
|
|
|
|
|
+ widgetDataInfo.currentPosition = resultSet.getLong(resultSet.getColumnIndex('current_position'));
|
|
|
|
|
+ widgetDataInfo.hasNext = resultSet.getLong(resultSet.getColumnIndex('has_next')) === 1;
|
|
|
|
|
+ widgetDataInfo.hasPrevious = resultSet.getLong(resultSet.getColumnIndex('has_previous')) === 1;
|
|
|
|
|
+ widgetDataInfo.playMode = resultSet.getLong(resultSet.getColumnIndex('play_mode'));
|
|
|
|
|
+ widgetDataInfo.currentIndex = resultSet.getLong(resultSet.getColumnIndex('current_index'));
|
|
|
|
|
+ widgetDataInfo.totalCount = resultSet.getLong(resultSet.getColumnIndex('total_count'));
|
|
|
|
|
+ widgetDataInfo.currentTimeText = resultSet.getString(resultSet.getColumnIndex('current_time_text'));
|
|
|
|
|
+ widgetDataInfo.totalTimeText = resultSet.getString(resultSet.getColumnIndex('total_time_text'));
|
|
|
|
|
+ widgetDataInfo.progressPercentage = resultSet.getDouble(resultSet.getColumnIndex('progress_percentage'));
|
|
|
|
|
+ widgetDataInfo.createTime = resultSet.getString(resultSet.getColumnIndex('create_time'));
|
|
|
|
|
+ widgetDataInfo.updateTime = resultSet.getString(resultSet.getColumnIndex('update_time'));
|
|
|
|
|
+
|
|
|
|
|
+ return widgetDataInfo;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 关闭数据库
|
|
|
|
|
+ */
|
|
|
|
|
+ async close(): Promise<void> {
|
|
|
|
|
+ if (this.rdbStore) {
|
|
|
|
|
+ await this.rdbStore.close();
|
|
|
|
|
+ this.rdbStore = null;
|
|
|
|
|
+ hilog.info(0x0000, TAG, 'Widget data database closed');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|