diff --git a/entry/cronetlib/cronet_api.jar b/entry/cronetlib/cronet_api.jar deleted file mode 100644 index b7a63bbc..00000000 Binary files a/entry/cronetlib/cronet_api.jar and /dev/null differ diff --git a/entry/cronetlib/cronet_impl_common_java.jar b/entry/cronetlib/cronet_impl_common_java.jar deleted file mode 100644 index 4bbe0a8d..00000000 Binary files a/entry/cronetlib/cronet_impl_common_java.jar and /dev/null differ diff --git a/entry/cronetlib/cronet_impl_native_java.jar b/entry/cronetlib/cronet_impl_native_java.jar deleted file mode 100644 index 842cdea6..00000000 Binary files a/entry/cronetlib/cronet_impl_native_java.jar and /dev/null differ diff --git a/entry/cronetlib/cronet_impl_platform_java.jar b/entry/cronetlib/cronet_impl_platform_java.jar deleted file mode 100644 index 05468748..00000000 Binary files a/entry/cronetlib/cronet_impl_platform_java.jar and /dev/null differ diff --git a/entry/cronetlib/cronet_shared_java.jar b/entry/cronetlib/cronet_shared_java.jar deleted file mode 100644 index 2700521b..00000000 Binary files a/entry/cronetlib/cronet_shared_java.jar and /dev/null differ diff --git a/entry/src/main/ets/database/AppDatabase/index.ets b/entry/src/main/ets/database/AppDatabase/index.ets new file mode 100644 index 00000000..0ae4c8fe --- /dev/null +++ b/entry/src/main/ets/database/AppDatabase/index.ets @@ -0,0 +1,2380 @@ +import { AppDataBaseType } from '../types/AppDatabaseType' + +export default { + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "6e17b5366286b868f2912c12d6d8e467", + "entities": [ + { + "tableName": "books", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` ( `id` INTEGER NOT NULL, `bookUrl` TEXT, `toUrl` TEXT, `origin` TEXT, `originName` TEXT, `bookName` TEXT NOT NULL, `author` TEXT, `cover` TEXT, `customTag` TEXT, `coverUrl` TEXT, `customCoverUrl` TEXT, `intro` TEXT, `customIntro` TEXT, `charset` TEXT, `bookGroup` INTEGER NOT NULL DEFAULT 3, `latestChapterTitle` TEXT, `latestChapterTime` INTEGER NOT NULL DEFAULT 0, `lastCheckTime` INTEGER NOT NULL DEFAULT 0, `lastCheckCount` INTEGER NOT NULL DEFAULT 0, `totalChapterNum` INTEGER NOT NULL DEFAULT 0, `durChapterTitle` TEXT, `durChapterIndex` INTEGER NOT NULL DEFAULT 0, `durChapterPos` INTEGER NOT NULL DEFAULT 0, `durChapterTime` INTEGER NOT NULL DEFAULT 0, `wordCount` TEXT, `canUpdate` INTEGER NOT NULL DEFAULT 1, `sort` INTEGER NOT NULL DEFAULT 0, `originOrder` INTEGER NOT NULL DEFAULT 0, `syncTime` INTEGER NOT NULL DEFAULT 0, `bookType` INTEGER NOT NULL DEFAULT 0, `isTop` INTEGER NOT NULL DEFAULT 0, `createTime` INTEGER NOT NULL DEFAULT 0,`updateTime` INTEGER NOT NULL DEFAULT 0,`isJoin` INTEGER NOT NULL DEFAULT 1, `isLocalBook` INTEGER NOT NULL DEFAULT 0,PRIMARY KEY ( `id` ))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "toUrl", + "columnName": "toUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "originName", + "columnName": "originName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookName", + "columnName": "bookName", + "affinity": "TEXT", + "notNull": true, + "defaultValue":"" + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "" + }, + { + "fieldPath": "cover", + "columnName": "cover", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customTag", + "columnName": "customTag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverUrl", + "columnName": "coverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customCoverUrl", + "columnName": "customCoverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "intro", + "columnName": "intro", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customIntro", + "columnName": "customIntro", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "charset", + "columnName": "charset", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookGroup", + "columnName": "bookGroup", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "3" + }, + { + "fieldPath": "latestChapterTitle", + "columnName": "latestChapterTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "latestChapterTime", + "columnName": "latestChapterTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "lastCheckTime", + "columnName": "lastCheckTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "lastCheckCount", + "columnName": "lastCheckCount", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "totalChapterNum", + "columnName": "totalChapterNum", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterTitle", + "columnName": "durChapterTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "durChapterIndex", + "columnName": "durChapterIndex", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterPos", + "columnName": "durChapterPos", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterTime", + "columnName": "durChapterTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "wordCount", + "columnName": "wordCount", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "canUpdate", + "columnName": "canUpdate", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "originOrder", + "columnName": "originOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "syncTime", + "columnName": "syncTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "bookType", + "columnName": "bookType", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "isTop", + "columnName": "isTop", + "affinity": "isTop", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "createTime", + "columnName": "createTime", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "updateTime", + "columnName": "updateTime", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "isJoin", + "columnName": "isJoin", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "isLocalBook", + "columnName": "isLocalBook", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_books_bookName_author", + "unique": true, + "columnNames": [ + "bookName", + "author" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_books_bookName_author` ON `${TABLE_NAME}` (`bookName`, `author`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "book_groups", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `groupName` TEXT NOT NULL, `coverUrl` TEXT, `groupDescribe` TEXT, `sort` INTEGER NOT NULL, `enableRefresh` INTEGER NOT NULL DEFAULT 1, `show` INTEGER NOT NULL DEFAULT 1, `groupType` INTEGER NOT NULL DEFAULT 0, `createTime` INTEGER NOT NULL DEFAULT 0, `updateTime` INTEGER NOT NULL DEFAULT 0, `bookSort` INTEGER NOT NULL DEFAULT -1, `canUpdate` INTEGER NOT NULL DEFAULT 0, `coverOnly` INTEGER NOT NULL DEFAULT 0, `coverType` INTEGER NOT NULL DEFAULT 0, `canDelete` INTEGER NOT NULL DEFAULT 1, `isTop` INTEGER NOT NULL DEFAULT 0,`isSystem` INTEGER NOT NULL DEFAULT 0,`bookIds` TEXT,PRIMARY KEY(`groupId`))", + "fields": [ + { + "fieldPath": "groupId", + "columnName": "groupId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "groupName", + "columnName": "groupName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "coverUrl", + "columnName": "coverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath":"groupDescribe", + "columnName": "groupDescribe", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enableRefresh", + "columnName": "enableRefresh", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "show", + "columnName": "show", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "groupType", + "columnName": "groupType", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "createTime", + "columnName": "createTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "updateTime", + "columnName": "updateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "bookSort", + "columnName": "bookSort", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + }, + { + "fieldPath": "coverOnly", + "columnName": "coverOnly", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "coverType", + "columnName": "coverType", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + , + { + "fieldPath": "canUpdate", + "columnName": "canUpdate", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "canDelete", + "columnName": "canDelete", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "isTop", + "columnName": "isTop", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "isSystem", + "columnName": "isSystem", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "bookIds", + "columnName": "bookIds", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "groupId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "book_sources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookSourceUrl` TEXT NOT NULL, `bookSourceName` TEXT NOT NULL, `bookSourceGroup` TEXT, `bookSourceType` INTEGER NOT NULL, `bookUrlPattern` TEXT, `bookSourceGrade` INTEGER NOT NULL DEFAULT 2, `isTop` INTEGER NOT NULL DEFAULT 0, `showExplore` INTEGER NOT NULL DEFAULT 1, `showRecentIcon` INTEGER NOT NULL DEFAULT 1, `bookSourceScore` TEXT NOT NULL DEFAULT `5.0分`, `customOrder` INTEGER NOT NULL DEFAULT 0, `enabled` INTEGER NOT NULL DEFAULT 1, `enabledExplore` INTEGER NOT NULL DEFAULT 1, `jsLib` TEXT, `enabledCookieJar` INTEGER DEFAULT 0, `concurrentRate` TEXT, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `coverDecodeJs` TEXT, `bookSourceComment` TEXT, `variableComment` TEXT, `lastUpdateTime` INTEGER NOT NULL, `respondTime` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `exploreUrl` TEXT, `exploreScreen` TEXT, `ruleExplore` TEXT, `searchUrl` TEXT, `ruleSearch` TEXT, `ruleBookInfo` TEXT, `ruleToc` TEXT, `ruleContent` TEXT, `ruleReview` TEXT, PRIMARY KEY(`bookSourceUrl`))", + "fields": [ + { + "fieldPath": "bookSourceUrl", + "columnName": "bookSourceUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookSourceName", + "columnName": "bookSourceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookSourceGroup", + "columnName": "bookSourceGroup", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookSourceType", + "columnName": "bookSourceType", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookUrlPattern", + "columnName": "bookUrlPattern", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookSourceGrade", + "columnName": "bookSourceGrade", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookSourceScore", + "columnName": "bookSourceScore", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "enabledExplore", + "columnName": "enabledExplore", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "jsLib", + "columnName": "jsLib", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabledCookieJar", + "columnName": "enabledCookieJar", + "affinity": "INTEGER", + "boolean": true, + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "concurrentRate", + "columnName": "concurrentRate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "header", + "columnName": "header", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUrl", + "columnName": "loginUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverDecodeJs", + "columnName": "coverDecodeJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookSourceComment", + "columnName": "bookSourceComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variableComment", + "columnName": "variableComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "respondTime", + "columnName": "respondTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exploreUrl", + "columnName": "exploreUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "exploreScreen", + "columnName": "exploreScreen", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleExplore", + "columnName": "ruleExplore", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "searchUrl", + "columnName": "searchUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleSearch", + "columnName": "ruleSearch", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleBookInfo", + "columnName": "ruleBookInfo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleToc", + "columnName": "ruleToc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleContent", + "columnName": "ruleContent", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleReview", + "columnName": "ruleReview", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isTop", + "columnName": "isTop", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "showRecentIcon", + "columnName": "showRecentIcon", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "showExplore", + "columnName": "showExplore", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bookSourceUrl" + ] + }, + "indices": [ + { + "name": "index_book_sources_bookSourceUrl", + "unique": false, + "columnNames": [ + "bookSourceUrl" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_book_sources_bookSourceUrl` ON `${TABLE_NAME}` (`bookSourceUrl`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "chapters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `title` TEXT NOT NULL, `isVolume` INTEGER NOT NULL, `baseUrl` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `index` INTEGER NOT NULL, `isVip` INTEGER NOT NULL, `isPay` INTEGER NOT NULL, `resourceUrl` TEXT, `tag` TEXT, `start` INTEGER, `end` INTEGER, `startFragmentId` TEXT, `endFragmentId` TEXT, `variable` TEXT, PRIMARY KEY(`url`, `bookUrl`), FOREIGN KEY(`bookUrl`) REFERENCES `books`(`bookUrl`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isVolume", + "columnName": "isVolume", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "baseUrl", + "columnName": "baseUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "index", + "columnName": "index", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isVip", + "columnName": "isVip", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPay", + "columnName": "isPay", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "resourceUrl", + "columnName": "resourceUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "startFragmentId", + "columnName": "startFragmentId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "endFragmentId", + "columnName": "endFragmentId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "url", + "bookUrl" + ] + }, + "indices": [ + { + "name": "index_chapters_bookUrl", + "unique": false, + "columnNames": [ + "bookUrl" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_chapters_bookUrl` ON `${TABLE_NAME}` (`bookUrl`)" + }, + { + "name": "index_chapters_bookUrl_index", + "unique": true, + "columnNames": [ + "bookUrl", + "index" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapters_bookUrl_index` ON `${TABLE_NAME}` (`bookUrl`, `index`)" + } + ], + "foreignKeys": [ + { + "table": "books", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bookUrl" + ], + "referencedColumns": [ + "bookUrl" + ] + } + ] + }, + { + "tableName": "replace_rules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL DEFAULT '', `group` TEXT, `pattern` TEXT NOT NULL DEFAULT '', `replacement` TEXT NOT NULL DEFAULT '', `scope` TEXT, `scopeTitle` INTEGER NOT NULL DEFAULT 0, `scopeContent` INTEGER NOT NULL DEFAULT 1, `excludeScope` TEXT, `isEnabled` INTEGER NOT NULL DEFAULT 1, `isRegex` INTEGER NOT NULL DEFAULT 1, `timeoutMillisecond` INTEGER NOT NULL DEFAULT 3000, `sortOrder` INTEGER NOT NULL DEFAULT 0)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pattern", + "columnName": "pattern", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "replacement", + "columnName": "replacement", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "scope", + "columnName": "scope", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "scopeTitle", + "columnName": "scopeTitle", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "scopeContent", + "columnName": "scopeContent", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "excludeScope", + "columnName": "excludeScope", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isEnabled", + "columnName": "isEnabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "isRegex", + "columnName": "isRegex", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "timeoutMillisecond", + "columnName": "timeoutMillisecond", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "3000" + }, + { + "fieldPath": "order", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_replace_rules_id", + "unique": false, + "columnNames": [ + "id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_replace_rules_id` ON `${TABLE_NAME}` (`id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "searchBooks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookUrl` TEXT NOT NULL, `origin` TEXT NOT NULL, `originName` TEXT NOT NULL, `type` INTEGER NOT NULL, `name` TEXT NOT NULL, `author` TEXT NOT NULL, `kind` TEXT, `coverUrl` TEXT, `intro` TEXT, `wordCount` TEXT, `latestChapterTitle` TEXT, `tocUrl` TEXT NOT NULL, `time` INTEGER NOT NULL, `variable` TEXT, `originOrder` INTEGER NOT NULL, `chapterWordCountText` TEXT, `chapterWordCount` INTEGER NOT NULL DEFAULT -1, `respondTime` INTEGER NOT NULL DEFAULT -1, PRIMARY KEY(`bookUrl`), FOREIGN KEY(`origin`) REFERENCES `book_sources`(`bookSourceUrl`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "originName", + "columnName": "originName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverUrl", + "columnName": "coverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "intro", + "columnName": "intro", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "wordCount", + "columnName": "wordCount", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "latestChapterTitle", + "columnName": "latestChapterTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tocUrl", + "columnName": "tocUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "originOrder", + "columnName": "originOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "chapterWordCountText", + "columnName": "chapterWordCountText", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "chapterWordCount", + "columnName": "chapterWordCount", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + }, + { + "fieldPath": "respondTime", + "columnName": "respondTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bookUrl" + ] + }, + "indices": [ + { + "name": "index_searchBooks_bookUrl", + "unique": true, + "columnNames": [ + "bookUrl" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_searchBooks_bookUrl` ON `${TABLE_NAME}` (`bookUrl`)" + }, + { + "name": "index_searchBooks_origin", + "unique": false, + "columnNames": [ + "origin" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_searchBooks_origin` ON `${TABLE_NAME}` (`origin`)" + } + ], + "foreignKeys": [ + { + "table": "book_sources", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "origin" + ], + "referencedColumns": [ + "bookSourceUrl" + ] + } + ] + }, + { + "tableName": "search_keywords", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`word` TEXT NOT NULL, `usage` INTEGER NOT NULL, `lastUseTime` INTEGER NOT NULL, PRIMARY KEY(`word`))", + "fields": [ + { + "fieldPath": "word", + "columnName": "word", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "usage", + "columnName": "usage", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUseTime", + "columnName": "lastUseTime", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "word" + ] + }, + "indices": [ + { + "name": "index_search_keywords_word", + "unique": true, + "columnNames": [ + "word" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_search_keywords_word` ON `${TABLE_NAME}` (`word`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "cookies", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `cookie` TEXT NOT NULL, PRIMARY KEY(`url`))", + "fields": [ + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "cookie", + "columnName": "cookie", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "url" + ] + }, + "indices": [ + { + "name": "index_cookies_url", + "unique": true, + "columnNames": [ + "url" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_cookies_url` ON `${TABLE_NAME}` (`url`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "rssSources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `sourceType` INTEGER NOT NULL ,`sourceUrl` TEXT NOT NULL, `sourceName` TEXT NOT NULL, `sourceIcon` TEXT NOT NULL, `sourceGroup` TEXT, `sourceComment` TEXT, `enabled` INTEGER NOT NULL, `variableComment` TEXT, `jsLib` TEXT, `enabledCookieJar` INTEGER DEFAULT 0, `concurrentRate` TEXT, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `coverDecodeJs` TEXT, `sortUrl` TEXT, `singleUrl` INTEGER NOT NULL, `articleStyle` INTEGER NOT NULL DEFAULT 0, `ruleArticles` TEXT, `ruleNextPage` TEXT, `ruleTitle` TEXT, `rulePubDate` TEXT, `ruleDescription` TEXT, `ruleImage` TEXT, `ruleLink` TEXT, `ruleContent` TEXT, `contentWhitelist` TEXT, `contentBlacklist` TEXT, `shouldOverrideUrlLoading` TEXT, `style` TEXT, `enableJs` INTEGER NOT NULL DEFAULT 1, `loadWithBaseUrl` INTEGER NOT NULL DEFAULT 1, `injectJs` TEXT, `lastUpdateTime` INTEGER NOT NULL DEFAULT 0,`variable` TEXT, `rssListRule` TEXT,`rssWebViewRule` TEXT,`sourceIconIsUrl` INTEGER ,`showRecentIcon` INTEGER NOT NULL DEFAULT 1, `customOrder` INTEGER NOT NULL DEFAULT 0, `customizeTitle` TEXT, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sourceType", + "columnName": "sourceType", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "sourceUrl", + "columnName": "sourceUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceName", + "columnName": "sourceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceIcon", + "columnName": "sourceIcon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceGroup", + "columnName": "sourceGroup", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sourceComment", + "columnName": "sourceComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "variableComment", + "columnName": "variableComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsLib", + "columnName": "jsLib", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabledCookieJar", + "columnName": "enabledCookieJar", + "affinity": "INTEGER", + "boolean": true, + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "concurrentRate", + "columnName": "concurrentRate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "header", + "columnName": "header", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUrl", + "columnName": "loginUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverDecodeJs", + "columnName": "coverDecodeJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sortUrl", + "columnName": "sortUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "singleUrl", + "columnName": "singleUrl", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "articleStyle", + "columnName": "articleStyle", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "ruleArticles", + "columnName": "ruleArticles", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleNextPage", + "columnName": "ruleNextPage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleTitle", + "columnName": "ruleTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rulePubDate", + "columnName": "rulePubDate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleDescription", + "columnName": "ruleDescription", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleImage", + "columnName": "ruleImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleLink", + "columnName": "ruleLink", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleContent", + "columnName": "ruleContent", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentWhitelist", + "columnName": "contentWhitelist", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentBlacklist", + "columnName": "contentBlacklist", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "shouldOverrideUrlLoading", + "columnName": "shouldOverrideUrlLoading", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "style", + "columnName": "style", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enableJs", + "columnName": "enableJs", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "loadWithBaseUrl", + "columnName": "loadWithBaseUrl", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "injectJs", + "columnName": "injectJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sourceIconIsUrl", + "columnName": "sourceIconIsUrl", + "affinity": "INTEGER", + "boolean": true, + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rssListRule", + "columnName": "rssListRule", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rssWebViewRule", + "columnName": "rssWebViewRule", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "showRecentIcon", + "columnName": "showRecentIcon", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "customizeTitle", + "columnName": "customizeTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "autoComplete", + "columnName": "autoComplete", + "affinity": "INTEGER", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_rssSources_sourceUrl", + "unique": false, + "columnNames": [ + "sourceUrl" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rssSources_sourceUrl` ON `${TABLE_NAME}` (`sourceUrl`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "bookmarks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`time` INTEGER NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `chapterPos` INTEGER NOT NULL, `chapterName` TEXT NOT NULL, `bookText` TEXT NOT NULL, `content` TEXT NOT NULL, PRIMARY KEY(`time`))", + "fields": [ + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookName", + "columnName": "bookName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookAuthor", + "columnName": "bookAuthor", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "chapterIndex", + "columnName": "chapterIndex", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "chapterPos", + "columnName": "chapterPos", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "chapterName", + "columnName": "chapterName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookText", + "columnName": "bookText", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "time" + ] + }, + "indices": [ + { + "name": "index_bookmarks_bookName_bookAuthor", + "unique": false, + "columnNames": [ + "bookName", + "bookAuthor" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_bookmarks_bookName_bookAuthor` ON `${TABLE_NAME}` (`bookName`, `bookAuthor`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "rssArticles", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`origin` TEXT NOT NULL, `sort` TEXT NOT NULL, `title` TEXT NOT NULL, `order` INTEGER NOT NULL, `link` TEXT NOT NULL, `pubDate` TEXT, `description` TEXT, `content` TEXT, `image` TEXT, `read` INTEGER NOT NULL, `variable` TEXT, PRIMARY KEY(`origin`, `link`))", + "fields": [ + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "link", + "columnName": "link", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pubDate", + "columnName": "pubDate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "read", + "columnName": "read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "origin", + "link" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "rssReadRecords", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record` TEXT NOT NULL, `read` INTEGER NOT NULL, PRIMARY KEY(`record`))", + "fields": [ + { + "fieldPath": "record", + "columnName": "record", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "read", + "columnName": "read", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "record" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "rssStars", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`origin` TEXT NOT NULL, `sort` TEXT NOT NULL, `title` TEXT NOT NULL, `starTime` INTEGER NOT NULL, `link` TEXT NOT NULL, `pubDate` TEXT, `description` TEXT, `content` TEXT, `image` TEXT, `variable` TEXT, PRIMARY KEY(`origin`, `link`))", + "fields": [ + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "starTime", + "columnName": "starTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "link", + "columnName": "link", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pubDate", + "columnName": "pubDate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "origin", + "link" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "txtTocRules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `rule` TEXT NOT NULL, `example` TEXT, `serialNumber` INTEGER NOT NULL, `enable` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rule", + "columnName": "rule", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "example", + "columnName": "example", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serialNumber", + "columnName": "serialNumber", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enable", + "columnName": "enable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "readRecord", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `readTime` INTEGER NOT NULL DEFAULT 0, `lastRead` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`deviceId`, `bookName`))", + "fields": [ + { + "fieldPath": "deviceId", + "columnName": "deviceId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookName", + "columnName": "bookName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "readTime", + "columnName": "readTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "lastRead", + "columnName": "lastRead", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "deviceId", + "bookName" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "httpTTS", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `contentType` TEXT, `concurrentRate` TEXT DEFAULT '0', `loginUrl` TEXT, `loginUi` TEXT, `header` TEXT, `jsLib` TEXT, `enabledCookieJar` INTEGER DEFAULT 0, `loginCheckJs` TEXT, `lastUpdateTime` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contentType", + "columnName": "contentType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "concurrentRate", + "columnName": "concurrentRate", + "affinity": "TEXT", + "notNull": false, + "defaultValue": "'0'" + }, + { + "fieldPath": "loginUrl", + "columnName": "loginUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "header", + "columnName": "header", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsLib", + "columnName": "jsLib", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabledCookieJar", + "columnName": "enabledCookieJar", + "affinity": "INTEGER", + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "caches", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` TEXT, `deadline` INTEGER NOT NULL, PRIMARY KEY(`key`))", + "fields": [ + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "deadline", + "columnName": "deadline", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "key" + ] + }, + "indices": [ + { + "name": "index_caches_key", + "unique": true, + "columnNames": [ + "key" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_caches_key` ON `${TABLE_NAME}` (`key`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "ruleSubs", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `type` INTEGER NOT NULL, `customOrder` INTEGER NOT NULL, `autoUpdate` INTEGER NOT NULL, `update` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "autoUpdate", + "columnName": "autoUpdate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "update", + "columnName": "update", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "dictRules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `urlRule` TEXT NOT NULL, `showRule` TEXT NOT NULL, `enabled` INTEGER NOT NULL DEFAULT 1, `sortNumber` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`name`))", + "fields": [ + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "urlRule", + "columnName": "urlRule", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "showRule", + "columnName": "showRule", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "sortNumber", + "columnName": "sortNumber", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "name" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "keyboardAssists", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` INTEGER NOT NULL DEFAULT 0, `key` TEXT NOT NULL DEFAULT '', `value` TEXT NOT NULL DEFAULT '', `serialNo` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`type`, `key`))", + "fields": [ + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "serialNo", + "columnName": "serialNo", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "type", + "key" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "servers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `type` TEXT NOT NULL, `config` TEXT, `sortNumber` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "config", + "columnName": "config", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sortNumber", + "columnName": "sortNumber", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "rss_sources_history", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceType` INTEGER NOT NULL ,`sourceGroup` TEXT,`sourceUrl` TEXT NOT NULL, `sourceName` TEXT NOT NULL, `sourceIcon` TEXT NOT NULL,`lastUpdateTime` INTEGER NOT NULL DEFAULT 0,`sourceIconIsUrl` INTEGER ,`showRecentIcon` INTEGER NOT NULL DEFAULT 1 ,`autoComplete` INTEGER NOT NULL DEFAULT 0,`customizeTitle` TEXT, PRIMARY KEY(`sourceUrl`))", + "fields": [ + { + "fieldPath": "sourceType", + "columnName": "sourceType", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "sourceUrl", + "columnName": "sourceUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceGroup", + "columnName": "sourceGroup", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceName", + "columnName": "sourceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceIcon", + "columnName": "sourceIcon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceIconIsUrl", + "columnName": "sourceIconIsUrl", + "affinity": "INTEGER", + "boolean": true, + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "showRecentIcon", + "columnName": "showRecentIcon", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "customizeTitle", + "columnName": "customizeTitle", + "affinity": "TEXT", + "notNull": false + }, + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "sourceUrl" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "works_lists", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`worksId` INTEGER NOT NULL, `worksName` TEXT NOT NULL, `worksDescribe` TEXT NOT NULL, `worksRemark` TEXT NOT NULL, `worksCoverUrl` TEXT NOT NULL, `createTime` INTEGER NOT NULL, `updateTime` INTEGER NOT NULL, `worksType` INTEGER NOT NULL, `worksBookNum` INTEGER NOT NULL, `worksBookList` TEXT, `isTop` INTEGER NOT NULL DEFAULT 0,PRIMARY KEY(`worksId`))", + "fields": [ + { + "fieldPath": "worksId", + "columnName": "worksId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "worksName", + "columnName": "worksName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "worksDescribe", + "columnName": "worksDescribe", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "worksRemark", + "columnName": "worksRemark", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "worksCoverUrl", + "columnName": "worksCoverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "createTime", + "columnName": "createTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "updateTime", + "columnName": "updateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "worksType", + "columnName": "worksType", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "worksBookNum", + "columnName": "worksBookNum", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "worksBookList", + "columnName": "worksBookList", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isTop", + "columnName": "isTop", + "affinity": "isTop", + "boolean": true, + "notNull": true, + "defaultValue": "0" + }, + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "worksId" + ] + }, + "indices": [ + { + "name": "index_works_lists_worksName", + "unique": false, + "columnNames": [ + "worksName" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_works_lists_worksName` ON `${TABLE_NAME}` (`worksName`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "book_history", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `bookName` TEXT NOT NULL, `author` TEXT NOT NULL, `durChapterTime` INTEGER NOT NULL, `durChapterIndex` INTEGER NOT NULL,`durChapterTitle` TEXT NOT NULL, `durChapterContent` TEXT NOT NULL,`sort` INTEGER NOT NULL, `bookType` INTEGER, `originBookId` INTEGER , `createTime` INTEGER NOT NULL, `updateTime` INTEGER NOT NULL,`bookUrl` TEXT NOT NULL,`coverUrl` TEXT NOT NULL,PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookName", + "columnName": "bookName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "durChapterTime", + "columnName": "durChapterTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterIndex", + "columnName": "durChapterIndex", + "affinity": "INTEGER", + "notNull": true, + "defaultValue":"0" + }, + { + "fieldPath": "durChapterTitle", + "columnName": "durChapterTitle", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "durChapterContent", + "columnName": "durChapterContent", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "bookType", + "columnName": "bookType", + "affinity": "INTEGER" + }, + { + "fieldPath": "originBookId", + "columnName": "originBookId", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "createTime", + "columnName": "createTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "updateTime", + "columnName": "updateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "coverUrl", + "columnName": "coverUrl", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6e17b5366286b868f2912c12d6d8e467')" + ] + } +} as AppDataBaseType \ No newline at end of file diff --git a/entry/src/main/ets/database/AppDatabaseUtil.ets b/entry/src/main/ets/database/AppDatabaseUtil.ets new file mode 100644 index 00000000..61fbc549 --- /dev/null +++ b/entry/src/main/ets/database/AppDatabaseUtil.ets @@ -0,0 +1,69 @@ +import { FieldsType } from './types/AppDatabaseType' +import { ColumnInfo, ColumnValue, ColumnType } from './types/ColumnInfo' +import AppDatabase from './AppDatabase' +import DbUtil from '../common/utils/DbUtil' + +class AppDatabaseUtil { + getCreateSql(tableName: string) { + const entities = AppDatabase.database.entities + const tableInfo = entities.find(item => item.tableName === tableName) + return tableInfo?.createSql.replace('${TABLE_NAME}', tableName) + } + + getFields(tableName: string): FieldsType[] | undefined { + const entities = AppDatabase.database.entities + const tableInfo = entities.find(item => item.tableName === tableName) + return tableInfo?.fields + } + + // 检测表中的字段是否缺失,若是缺失则新增 + async existsTable(tableName: string) { + try { + const rowNames = await DbUtil.queryRowNames(tableName); + const fields = this.getFields(tableName) + if (!fields?.length) return + for (let index = 0; index < fields.length; index++) { + const element = fields[index]; + if (!rowNames.includes(element.columnName)) { + console.info(`TagInfo 数据表【${tableName}】缺失字段,开始新增字段:`, element.columnName) + let executeSql = `ALTER TABLE '${tableName}' ADD COLUMN '${element.columnName}' ${element.affinity}` + if (element.defaultValue) { + executeSql += ` DEFAULT '${element.defaultValue}'` + } + await DbUtil.executeSql(executeSql) + console.info('TagInfo', `数据表【${tableName}】新增字段【${element.columnName}】成功`) + } + } + } catch (e) { + console.info('TagInfo Error:', JSON.stringify(e)) + } + } + + getColumn(tableName: string) { + const entities = AppDatabase.database.entities + const tableInfo = entities.find(item => item.tableName === tableName) + return this.fieldsToColumnInfo(tableInfo?.fields || []) + } + + getAssignColumn(tableName: string, assignColumn: string[]) { + const columns = this.getColumn(tableName) + return columns.filter(item => assignColumn.includes(item.columnName)) + } + + fieldsToColumnInfo(fields: FieldsType[]): ColumnInfo[] { + return fields.map(item => { + const columnInfo: ColumnInfo = { + name: item.fieldPath, + // 数据库列名 + columnName: item.columnName, + // 列类型 + type: item.boolean ? ColumnType.BOOLEAN : ColumnValue[item.affinity], + defaultValue: item.defaultValue + } + return columnInfo + }) + } +} + +const appDatabaseUtil = new AppDatabaseUtil(); +export default appDatabaseUtil as AppDatabaseUtil; \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/BookGroupsDao.ets b/entry/src/main/ets/database/dao/BookGroupsDao.ets new file mode 100644 index 00000000..168d3f97 --- /dev/null +++ b/entry/src/main/ets/database/dao/BookGroupsDao.ets @@ -0,0 +1,398 @@ +/** + * @author 2008 + * @datetime 2024/7/24 21:16 + * @className: BookGroupsDao + */ +import DbUtil from '../../common/utils/DbUtil'; +import AppDatabaseUtil from '../AppDatabaseUtil'; +import { BookGroupDb, BookGroups, ToBookGroups, ToBookGroupsDb } from '../entities/BookGroups'; +import { BookGroupTypeParams } from '../types/BookGroupType'; +import { ColumnInfo } from '../types/ColumnInfo'; + +class BookGroupsDao{ + TABLE_NAME: string = 'book_groups' + + // 创建books数据表 + async initGroupTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql) + await AppDatabaseUtil.existsTable(this.TABLE_NAME) + this.initGroupData() + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + + } + + async search(params?:BookGroupTypeParams) { + const type = params?.type + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (type !== undefined){ + whereClause.push(`groupType = ${type} OR groupType = 123`); + } + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + + sql += ` + ORDER BY + isSystem DESC, + isTop DESC, + sort ASC +`; + const groupDbList = await DbUtil.querySqlForList(sql, column); + const groupList = groupDbList.map((item): BookGroups => ToBookGroups(item)); + console.log("TagInfo", '书籍:' + groupDbList.length) + return groupList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async searchHide(params?:BookGroupTypeParams) { + const type = params?.type + const show = params?.show + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + + if (type !== undefined){ + whereClause.push(`groupType = ${type}`); + } + if (show !== undefined){ + whereClause.push(`show = ${show}`); + } + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + + sql += ` + ORDER BY + sort ASC +`; + const groupDbList = await DbUtil.querySqlForList(sql, column); + const groupList = groupDbList.map((item): BookGroups => ToBookGroups(item)); + console.log("TagInfo", '书籍:' + groupList.length) + return groupList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + + async batchInsert(group: BookGroups[]) { + try { + for (let index = 0; index < group.length; index++) { + const data = group[index]; + await this.insert(data) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async insert(group: BookGroups) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + if (group.groupId) { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', group.groupId) + const count = await DbUtil.queryForCount(predicates, column) + if (count > 0) { + this.update(group) + return true + } + } + const bookGroupsDb = ToBookGroupsDb(group) + bookGroupsDb.createTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, bookGroupsDb, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(group: BookGroups) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', group.groupId) + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0) { + this.insert(group) + return true + } + const bookGroupsDb = ToBookGroupsDb(group) + bookGroupsDb.updateTime = Date.now() + await DbUtil.update(predicates, bookGroupsDb, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + + } + + //删除订阅源历史记录 + async deleteBook(id: number[]) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('groupId', id) + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //置顶 + async isUpdateGroupTop(id: number, isTop: boolean) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', id) + const count = await DbUtil.queryForList(predicates, column) + if (column.length > 0) { + count.forEach((item) => { + item.isTop = isTop + item.updateTime = Date.now() + this.update(item) + }) + return true + } + return false + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //更新分组显示状态 + async updateGroupShow(id: number, show?: boolean) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', id) + const count = await DbUtil.queryForList(predicates, column) + if (column.length > 0) + count.forEach((item) => { + item.show = show||!item.show + item.updateTime = Date.now() + this.update(item) + }) + } catch (e){ + console.log('TagInfo, Error, ', JSON.stringify(e)) + } + } + + //系统初始分组数据 + async initGroupData() { + let initGroup = ['分组','全部','未分组','本地','书单'] + try { + const groupList = await this.search() + if (groupList.length > 0) { + return + } + for (let index = 0; index < initGroup.length; index++) { + let group = new BookGroups() + group.groupName = initGroup[index] + group.sort = 0 + group.show = true + group.groupType = 123 + group.canDelete = false + group.isSystem = true + group.isTop = true + group.bookIds = [] + await bookGroupsDao.insert(group) + } + }catch (e){ + console.log('TagInfo, Error, ', JSON.stringify(e)) + } + } + //根据分组groupId更新bookIds书籍id存在不做更新 + updateAddBookIds(groupId: number, bookIds: string[]) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', groupId) + //查询出来只有一个值 + DbUtil.queryForList(predicates, column).then((data) => { + data.forEach((item) => { + const groupList = ToBookGroups(item); + bookIds.forEach((bookId) => { + //存在将bookId不做添加 + if (groupList.bookIds?.includes(bookId)) { + return + } + if (groupList.bookIds) { + groupList.bookIds.push(bookId) + } else { + groupList.bookIds = [bookId] + } + }) + this.update(groupList) + console.log("TagInfo", '书籍bookIds:' + groupList.bookIds?.length + JSON.stringify(groupList.bookIds)) + }) + }) + } catch (e){ + console.log('TagInfo, Error, ', JSON.stringify(e)) + } + } + //同时在更新后将旧的分组的bookIds中的书籍id移除 + async updateMoveBookIdsByGroupId(data: Record) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + + const bookIds = Object.keys(data); + + for (const bookIdStr of bookIds) { + const bookId = Number(bookIdStr); + const oldGroupId = data[bookId]; + + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', oldGroupId); + + // 查询旧分组 + const groups = await DbUtil.queryForList(predicates, column); + if (groups.length > 0) { + const group = groups[0]; + const groupList = ToBookGroups(group); + + if (groupList.bookIds?.includes(bookId.toString())) { + // 移除旧分组中的 bookId + groupList.bookIds = groupList.bookIds.filter(item => item !== bookId.toString()); + await this.update(groupList); + } + } + } + } catch (e) { + console.log('updateMoveBookIdsByGroupId, Error, ', JSON.stringify(e)); + } + } + + async updateMoveGroupBookIds(ids: number[]) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + // 确保 ids 数组的每个元素都是数字 + const validIds = ids.filter(id => typeof id === 'number'); + predicates.in('groupId', validIds); // 使用 in 条件一次性查找多个 id + // 执行一次查询获取所有匹配的分组 + const groups = await DbUtil.queryForList(predicates, column); + + if (groups.length > 0) { + for (const group of groups) { + const groupList = ToBookGroups(group); + groupList.bookIds = []; + await this.update(groupList); // 确保逐个更新 + } + } + } catch (e) { + console.log('updateMoveBookIdsByGroupId, Error, ', JSON.stringify(e)); + } + } + //校验唯一性,同时进行更新 + async onlyGroupUpdateName(groupId: number, newGroupName: string) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupName', newGroupName) + const groups = await DbUtil.queryForList(predicates, column); + if (groups.length > 1) return false + if (groups.length === 0){ + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', groupId) + const groupDate = await DbUtil.queryForList(predicates, column); + groupDate[0].groupName = newGroupName + return await this.update(ToBookGroups(groupDate[0])) + } + if ((groups.length === 1 && groups[0].groupId && groups[0].groupId === groupId)) { + groups[0].groupName = newGroupName + return await this.update(ToBookGroups(groups[0])) + } + return false + } catch (e){ + console.log('onlyGroupName, Error, ', JSON.stringify(e)) + return false + } + } + /** + * 分组id查询分组下的书籍Id然后去重 + * @param ids + */ + async queryBookByGroup(ids:number[]){ + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + const validIds = ids.filter(id => typeof id === 'number'); + predicates.in('groupId', validIds); + const groups = await DbUtil.queryForList(predicates, column); + const bookIds:number[] = [] + if (groups.length > 0) { + groups.forEach((item) => { + ToBookGroups(item).bookIds?.forEach((bookId) => { + if (!bookIds.includes(Number(bookId))) { + bookIds.push(Number(bookId)) + } + }) + }) + } + return bookIds + } catch (e){ + console.log('queryBookByGroup, Error, ', JSON.stringify(e)) + return [] + } + } + + async updatePartialGroup(group: BookGroups) { + // if (!(group instanceof BookGroups)) { + // console.warn('Invalid group instance.'); + // return; + // } + + const column = this.getPartialColumn(); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('groupId', group.groupId); + + try { + const count = await DbUtil.queryForCount(predicates, column); + if (count > 0) { + await DbUtil.update(predicates, ToBookGroupsDb(group), column); + } else { + console.warn('No records found for update.'); + } + } catch (err) { + console.error('Error in partialUpdate:', err); + } + } + + getPartialColumn(): ColumnInfo[] { + return AppDatabaseUtil.getAssignColumn(this.TABLE_NAME, ['groupId', + 'groupName', 'coverOnly', 'coverType','coverUrl','groupDescribe', + 'enableRefresh','canUpdate' + ]); + } + +} + +const bookGroupsDao = new BookGroupsDao() +export default bookGroupsDao as BookGroupsDao \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/BookHistoryDao.ets b/entry/src/main/ets/database/dao/BookHistoryDao.ets new file mode 100644 index 00000000..405c4b33 --- /dev/null +++ b/entry/src/main/ets/database/dao/BookHistoryDao.ets @@ -0,0 +1,153 @@ +/** + * @author 2008 + * @datetime 2024/8/05 22:34 + * @className: BookHistoryDao + * 书籍浏览历史 + */ +import DbUtil from '../../common/utils/DbUtil'; +import AppDatabaseUtil from '../AppDatabaseUtil'; +import { BookHistory } from '../entities/BookHistory'; +import { rssSourcesHistory } from '../entities/rssSourcesHistory'; +import { BookHistoryTypeParams } from '../types/BookHistoryType'; +import { ColumnInfo } from '../types/ColumnInfo'; + +class BookHistoryDao { + TABLE_NAME: string = 'book_history' + + // 创建book_history数据表 + async initBookHistoryTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql) + AppDatabaseUtil.existsTable(this.TABLE_NAME) + return + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + } + + async search(params?:BookHistoryTypeParams) { + const type = params?.type + const sort = params?.sort + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (type !== undefined){ + whereClause.push(`bookType = ${type} OR bookType = 123`); + } + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + sql += ` ORDER BY`; + if (sort !== undefined) { + sql += ` ${sort === 0 ? 'durChapterTime' : 'updateTime'} DESC` + } else { + sql += ` durChapterTime DESC`; + } + const bookHistoryDbList = await DbUtil.querySqlForList(sql, column); + + return bookHistoryDbList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + async searchLimit() { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + sql += ` + ORDER BY + durChapterTime DESC + LIMIT 1 +`; + const bookHistoryDbList = await DbUtil.querySqlForList(sql, column); + return bookHistoryDbList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async insert(bookHistory: BookHistory) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', bookHistory.id) + const count = await DbUtil.queryForCount(predicates, column) + if (count > 0) { + this.update(bookHistory) + return true + } + bookHistory.createTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, bookHistory, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(bookHistory: BookHistory) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', bookHistory.id) + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0 && bookHistory instanceof BookHistory) { + this.insert(bookHistory) + return true + } + bookHistory.updateTime = Date.now() + bookHistory.durChapterTime = Date.now() + await DbUtil.update(predicates, bookHistory, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //删除阅读历史记录 + async deleteBookHistory(id: number) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', id) + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async deleteAllBookHistory() { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + +} + + +const bookHistoryDao = new BookHistoryDao() +export default bookHistoryDao as BookHistoryDao \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/BookSourceDao.ets b/entry/src/main/ets/database/dao/BookSourceDao.ets new file mode 100644 index 00000000..3bee72c5 --- /dev/null +++ b/entry/src/main/ets/database/dao/BookSourceDao.ets @@ -0,0 +1,340 @@ +import { ColumnInfo, ColumnType } from '../types/ColumnInfo'; +import { BookSource, BookSourceDb, ToBookSource, ToBookSourceDb, ToBookSourcePart } from '../entities/BookSource'; +import AppDatabaseUtil from '../AppDatabaseUtil' +import { JSON } from '@kit.ArkTS'; +import DbUtil from '../../common/utils/DbUtil'; +import { BookSourcePart } from '../entities/BookSourcePart'; +import { BookSourceSearchParams } from '../types/BookSourceType'; + +class BookSourceDao { + TABLE_NAME: string = 'book_sources' + + // 创建book_source数据表 + async initBookSourceTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql); + AppDatabaseUtil.existsTable(this.TABLE_NAME) + return + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + } + + getFlowColumn() { + const column: ColumnInfo[] = AppDatabaseUtil.getAssignColumn(this.TABLE_NAME, + ['bookSourceUrl', 'bookSourceName', 'bookSourceGroup', 'bookSourceGrade', 'bookSourceScore', 'customOrder', + 'enabled', 'enabledExplore', 'lastUpdateTime', 'respondTime', 'weight', 'isTop', 'showRecentIcon', + 'showExplore']); + column.push(...[ + { + name: 'hasLoginUrl', + columnName: 'hasLoginUrl', + type: ColumnType.BOOLEAN + }, + { + name: 'hasExploreUrl', + columnName: 'hasExploreUrl', + type: ColumnType.BOOLEAN + } + ] as ColumnInfo[]) + return column; + } + + async flowAll(): Promise { + try { + const sql = `select bookSourceUrl, bookSourceName, bookSourceGroup, bookSourceGrade, bookSourceScore, customOrder, enabled, enabledExplore, + trim(loginUrl) <> '' hasLoginUrl, lastUpdateTime, respondTime, weight, trim(exploreUrl) <> '' hasExploreUrl, isTop, showRecentIcon, showExplore + from book_sources order by customOrder asc` + const column: ColumnInfo[] = this.getFlowColumn() + return await DbUtil.querySqlForList(sql, column) + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async getEnabledPartByGroup() { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const sql = `SELECT * FROM book_sources WHERE enabled = 1 AND enabledExplore = 1 ORDER BY customOrder ASC` + const bookSourceDbList = await DbUtil.querySqlForList(sql, column); + const bookSourceList = bookSourceDbList.map((item): BookSource => ToBookSource(item)); + return bookSourceList + } catch (e){ + console.log("TagInfo", JSON.stringify(e)) + return [] + } + } + + async flowSearch(searchParams?: BookSourceSearchParams): Promise { + const searchKey = searchParams?.searchKey ?? ''; + const type = searchParams?.type; + const enabled = searchParams?.enabled; + const bookSourceGrade = searchParams?.bookSourceGrade; + const hasLoginUrl = searchParams?.hasLoginUrl; + const showExplore = searchParams?.showExplore; + const order = searchParams?.order; + try { + let sql = ` + SELECT + bookSourceUrl, + bookSourceName, + bookSourceGroup, + bookSourceGrade, + bookSourceScore, + customOrder, + enabled, + enabledExplore, + trim(loginUrl) <> '' AS hasLoginUrl, + lastUpdateTime, + respondTime, + weight, + trim(exploreUrl) <> '' AS hasExploreUrl, + isTop, + showRecentIcon, + showExplore + FROM + book_sources +`; + + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (type !== undefined) { + whereClause.push(`bookSourceType = ${type}`); + } + if (enabled !== undefined) { + whereClause.push(`enabled = ${enabled ? 1 : 0}`); + } + if (showExplore !== undefined) { + whereClause.push(`showExplore = ${showExplore ? 1 : 0}`); + } + if (bookSourceGrade !== undefined) { + whereClause.push(`bookSourceGrade = ${bookSourceGrade}`); + } + if (hasLoginUrl !== undefined) { + whereClause.push(`COALESCE(loginUrl, '') ${hasLoginUrl ? '<>' : '='} ''`); + } + if (searchKey) { // 确保 searchKey 不为空或未定义 + whereClause.push(`( + bookSourceName LIKE '%${searchKey}%' + OR bookSourceGroup LIKE '%${searchKey}%' + OR bookSourceUrl LIKE '%${searchKey}%' + OR bookSourceComment LIKE '%${searchKey}%' + )`); + } + + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + + sql += ` ORDER BY`; + if (order !== undefined) { + sql += ` ${order === 0 ? 'bookSourceGroup' : 'lastUpdateTime'} DESC` + } else { + sql += ` isTop DESC, customOrder ASC`; + } + const column: ColumnInfo[] = this.getFlowColumn() + return await DbUtil.querySqlForList(sql, column) + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async search(searchParams?: BookSourceSearchParams) { + const searchKey = searchParams?.searchKey ?? ''; + const type = searchParams?.type; + const enabled = searchParams?.enabled; + const hasExploreUrl = searchParams?.hasExploreUrl; + const showExplore = searchParams?.showExplore; + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM book_sources`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (type !== undefined) { + whereClause.push(`bookSourceType = ${type}`); + } + if (enabled !== undefined) { + whereClause.push(`enabled = ${enabled ? 1 : 0}`); + } + if (hasExploreUrl !== undefined) { + whereClause.push(`COALESCE(exploreUrl, '') ${hasExploreUrl ? '<>' : '='} ''`); + } + if (showExplore !== undefined) { + whereClause.push(`showExplore = ${showExplore ? 1 : 0}`); + } + if (searchKey) { // 确保 searchKey 不为空或未定义 + whereClause.push(`( + bookSourceName LIKE '%${searchKey}%' + OR bookSourceGroup LIKE '%${searchKey}%' + OR bookSourceUrl LIKE '%${searchKey}%' + OR bookSourceComment LIKE '%${searchKey}%' + )`); + } + + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + + sql += ` + ORDER BY + isTop DESC, customOrder ASC +`; + const bookSourceDbList = await DbUtil.querySqlForList(sql, column); + const bookSourceList = bookSourceDbList.map((item): BookSource => ToBookSource(item)); + console.log("TagInfo", '书源数量:' + bookSourceList.length) + return bookSourceList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async getBookSource(key: string): Promise { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookSourceUrl', key) + const bookSourceDbList = await DbUtil.queryForList(predicates, column); + const bookSourceList = bookSourceDbList.map((item): BookSource => ToBookSource(item)); + if (bookSourceList.length > 0) { + if (bookSourceList[0].showRecentIcon) { + this.updateRecentIcon(ToBookSourcePart(bookSourceList[0])) + } + return bookSourceList[0] + } + return null + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return null + } + } + + async insert(bookSource: BookSource) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookSourceUrl', bookSource.bookSourceUrl) + const count = await DbUtil.queryForCount(predicates, column) + if (count !== 0) { + this.update(bookSource) + return true + } + const bookSourceDb = ToBookSourceDb(bookSource) + bookSourceDb.lastUpdateTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, bookSourceDb, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async batchInsert(bookSources: BookSource[]) { + try { + for (let index = 0; index < bookSources.length; index++) { + const bookSource = bookSources[index]; + await this.insert(bookSource) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async updateFlow(bookSource: BookSourcePart) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookSourceUrl', bookSource.bookSourceUrl) + bookSource.lastUpdateTime = Date.now() + const columnPart: ColumnInfo[] = this.getFlowColumn().slice(0, -2) + await DbUtil.update(predicates, bookSource, columnPart) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(bookSource: BookSource) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookSourceUrl', bookSource.bookSourceUrl) + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0) { + this.insert(bookSource) + return true + } + const bookSourceDb = ToBookSourceDb(bookSource) + bookSourceDb.lastUpdateTime = Date.now() + await DbUtil.update(predicates, bookSourceDb, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async batchUpdateFlow(bookSources: BookSourcePart[]) { + try { + for (let index = 0; index < bookSources.length; index++) { + const bookSource = bookSources[index]; + await this.updateFlow(bookSource) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async updateRecentIcon(bookSources: BookSourcePart) { + try { + bookSources.showRecentIcon = false + this.updateFlow(bookSources) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async delete(key: string) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookSourceUrl', key) + await DbUtil.delete(predicates); + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async batchDelete(keys: string[]) { + try { + for (let index = 0; index < keys.length; index++) { + const key = keys[index]; + await this.delete(key) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } +} + +const bookSourceDao = new BookSourceDao() + +export default bookSourceDao as BookSourceDao \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/BooksDao.ets b/entry/src/main/ets/database/dao/BooksDao.ets new file mode 100644 index 00000000..7031f822 --- /dev/null +++ b/entry/src/main/ets/database/dao/BooksDao.ets @@ -0,0 +1,462 @@ +import booksUtils from '../../common/utils/booksUtils'; +import DbUtil from '../../common/utils/DbUtil'; +import toolsUtils from '../../common/utils/ToolsUtils'; +import AppDatabaseUtil from '../AppDatabaseUtil'; +import { Books } from '../entities/Books'; +import { BooksTypeSearchParams } from '../types/BooksType'; +import { ColumnInfo } from '../types/ColumnInfo'; + +class BooksDao { + TABLE_NAME: string = 'books' + + // 创建books数据表 + async initBooksTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql) + AppDatabaseUtil.existsTable(this.TABLE_NAME) + return + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + } + + async search(param?:BooksTypeSearchParams) { + let searchKey = param?.searchKey ?? ''; + let type = param?.type; + let bookGroup = param?.bookGroup; + let order = param?.order; + let sort = 0 + if (order !== undefined){ + sort = booksUtils.getOrder(order) + } + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (type !== undefined) { + whereClause.push(`bookType = ${type}`); + } + if (bookGroup !== undefined && bookGroup !== 2) { + whereClause.push(`bookGroup = ${bookGroup}`); + } + if (searchKey) { + whereClause.push(`( + bookName LIKE '%${searchKey}%' + OR author LIKE '%${searchKey}%' + OR originName LIKE '%${searchKey}%' + )`); + + } + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + sql += ` ORDER BY`; + if (order !== undefined) { + switch (sort){ + case 0: + sql += ` isTop DESC, durChapterTime DESC`; + break; + case 1: + sql += ` isTop DESC, latestChapterTime DESC`; + break; + case 2: + sql += ` isTop DESC, sort ASC`; + break; + } + } else { + sql += ` isTop DESC, createTime DESC`; + } + + const bookDbList = await DbUtil.querySqlForList(sql, column); + console.log("TagInfo", '书籍:' + bookDbList.length) + return bookDbList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + //获取书籍总数量 + async getBookCount(param?: BooksTypeSearchParams) { + let type = param?.type; + let bookGroup = param?.bookGroup; + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookType', type) + if (bookGroup !== undefined && bookGroup !== 2) { + predicates.equalTo('bookGroup', bookGroup) + } + const count = await DbUtil.queryForCount(predicates, column) + return count + } catch (e){ + console.log("TagInfo", JSON.stringify(e)) + return 0 + } + } + + async searchPage(param?: BooksTypeSearchParams, pageNumber: number = 1, pageSize: number = 21) { + let searchKey = param?.searchKey ?? ''; + let type = param?.type; + let bookGroup = param?.bookGroup; + let order = param?.order; + let sort = 0; + if (order !== undefined) { + sort = booksUtils.getOrder(order); + } + + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + let whereClause: string[] = []; + + if (type !== undefined) { + whereClause.push(`bookType = ${type}`); + } + if (bookGroup !== undefined && bookGroup !== 2) { + if (bookGroup === 4) { + whereClause.push(`bookGroup = ${bookGroup} or isLocalBook = ${true}`); + } else { + whereClause.push(`bookGroup = ${bookGroup}`); + } + } + if (searchKey) { + whereClause.push(`( + bookName LIKE '%${searchKey}%' + OR author LIKE '%${searchKey}%' + OR originName LIKE '%${searchKey}%' + )`); + } + + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + + sql += ` ORDER BY`; + if (order !== undefined) { + switch (sort) { + case 0: + sql += ` isTop DESC, durChapterTime DESC, createTime DESC`; + break; + case 1: + sql += ` isTop DESC, latestChapterTime DESC,updateTime DESC`; + break; + case 2: + sql += ` isTop DESC, sort ASC`; + break; + } + } else { + sql += ` isTop DESC, createTime DESC`; + } + + const offset = (pageNumber - 1) * pageSize; + sql += ` LIMIT ${pageSize} OFFSET ${offset}`; + + const bookDbList = await DbUtil.querySqlForList(sql, column); + console.log("TagInfo", '书籍:' + bookDbList.length) + return bookDbList; + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return []; + } + } + + async batchInsert(books: Books[]) { + try { + for (let index = 0; index < books.length; index++) { + const book = books[index]; + await this.insert(book) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async insert(books: Books) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + if (books.id) { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', books.id) + const count = await DbUtil.queryForCount(predicates, column) + if (count > 0) { + this.update(books) + return true + } + } + books.createTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, books, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(books: Books) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', books.id) + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0 && books instanceof Books) { + this.insert(books) + return true + } + await DbUtil.update(predicates, books, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + //置顶 + async isUpdateBookTop(id: number, isTop: boolean) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', id) + const count = await DbUtil.queryForList(predicates, column) + if (column.length > 0) { + count.forEach((item) => { + item.isTop = isTop + item.updateTime = Date.now() + this.update(item) + }) + return true + } + return false + } catch (err) { + console.log('isUpdateBookTop, Error, ', JSON.stringify(err)) + return false + } + } + //批量更新书籍分组 + async batchUpdateBookGroup(id: number[],groupId:number) { + try { + for (let index = 0; index < id.length; index++) { + this.updateBookGroup(id[index],groupId) + } + return true + } catch (err) { + console.log('batchUpdateBookGroup, Error, ', JSON.stringify(err)) + return false + } + } + //更新书籍分组 + async updateBookGroup(bookIds: number|number[],groupId:number) { + try { + let Ids: number[] = toolsUtils.numberArrays(bookIds) + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const validIds = Ids.filter(id => typeof id === 'number'); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('id', validIds) + const count = await DbUtil.queryForList(predicates, column) + if (count.length > 0) { + count.forEach(async (item) => { + item.bookGroup = groupId + await this.update(item) + }) + return true + } + return false + } catch (err) { + console.log('updateBookGroup, Error, ', JSON.stringify(err)) + return false + } + } + + //根据书籍获取旧的分组Id + async getBookIdsByGroupId(ids: number[]) { + let BookGroupId: Record = {}; + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + + // 确保 ids 数组的每个元素都是数字 + const validIds = ids.filter(id => typeof id === 'number'); + + // 创建查询条件,查找所有给定的 id + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('id', validIds); // 使用 in 条件一次性查找多个 id + + // 执行一次查询获取所有匹配的书籍 + const books = await DbUtil.queryForList(predicates, column); + + // 遍历查询结果,将书籍的 bookGroup 分组 + books.forEach(book => { + const bookId = book.id; // 获取书籍的 id + if (bookId !== undefined) { + if (!BookGroupId[bookId]) { + BookGroupId[bookId] = 0; + } + BookGroupId[bookId] = book.bookGroup ?? 0; + } + }); + + return BookGroupId; + } catch (e) { + console.log('getBookIdsByGroupId, Error, ', JSON.stringify(e)); + return []; + } + } + + //根据分组获取书籍id + async queryBooksByGroupId(groupId: number[]){ + let GroupBookId: number[] = []; + try { + // 确保 ids 数组的每个元素都是数字 + const validIds = groupId.filter(id => typeof id === 'number'); + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('bookGroup', validIds) + // 执行一次查询获取所有匹配的书籍 + const books = await DbUtil.queryForList(predicates, column); + // 遍历查询结果,将书籍的 bookGroup 分组 + books.forEach(book => { + const bookId = book.id; // 获取书籍的 id + if (bookId !== undefined) { + GroupBookId.push(bookId) + } + }); + return GroupBookId + } catch (e) { + console.log('queryBooksByGroupId, Error, ', JSON.stringify(e)); + return [] + } + } + + //删除订阅源历史记录 + async deleteBook(id: number[]) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('id', id) + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //根据分组id统计书籍数量 + async countBookByGroup(groupId: number) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookGroup', groupId) + const count = await DbUtil.queryForCount(predicates, column) + return count + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return 0 + } + } + + //分组删除情况下根据删除分组id查询书籍更新未分组 + async queryBookByGroup(groupId: number[],updateGroupId: number) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('bookGroup', groupId) + const bookDbList = await DbUtil.queryForList(predicates, column) + if (bookDbList.length > 0) { + bookDbList.forEach((item) => { + item.bookGroup = updateGroupId + this.update(item) + }) + } + } catch (e) { + console.log('TagInfo, Error, ', JSON.stringify(e)) + } + } + + // 校验当前书籍是否存在书架中 + async isExistBooks(bookUrl?: string, bookName?: string): Promise { + if (!bookUrl || !bookName) { + console.warn('bookUrl or bookName is missing.'); + return []; + } + + const column = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('bookUrl', bookUrl); + predicates.equalTo('bookName', bookName); + + try { + const books = await DbUtil.queryForList(predicates, column); + return books || []; + } catch (err) { + console.error('isExistBooks, Error:', err); + return []; + } + } + + + //根据书籍Id获取书籍 + async getBookByIds(ids: number[]) { + + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + + // 确保 ids 数组的每个元素都是数字 + const validIds = ids.filter(id => typeof id === 'number'); + if (validIds.length === 0) return [] + // 创建查询条件,查找所有给定的 id + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('id', validIds); // 使用 in 条件一次性查找多个 id + + // 执行一次查询获取所有匹配的书籍 + const books = await DbUtil.queryForList(predicates, column); + + return books; + } catch (e) { + console.log('getBookIds, Error, ', JSON.stringify(e)); + return []; + } + } + //部分更新 + async partialUpdate(books: Books) { + if (!(books instanceof Books)) { + console.warn('Invalid Books instance.'); + return; + } + + const column = this.getPartialColumn(); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('id', books.id); + + try { + const count = await DbUtil.queryForCount(predicates, column); + + if (count > 0) { + await DbUtil.update(predicates, books, column); + } else { + console.warn('No records found for update.'); + } + } catch (err) { + console.error('Error in partialUpdate:', err); + } + } + + getPartialColumn(): ColumnInfo[] { + return AppDatabaseUtil.getAssignColumn(this.TABLE_NAME, ['id', + 'latestChapterTitle', 'latestChapterTime', 'lastCheckTime', + 'lastCheckCount', 'totalChapterNum', 'durChapterTitle', + 'durChapterIndex', 'durChapterPos', 'durChapterTime', + 'wordCount', 'syncTime', 'updateTime' + ]); + } +} + + +const booksDao = new BooksDao() +export default booksDao as BooksDao \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/RssSourcesHistoryDao.ets b/entry/src/main/ets/database/dao/RssSourcesHistoryDao.ets new file mode 100644 index 00000000..2183e151 --- /dev/null +++ b/entry/src/main/ets/database/dao/RssSourcesHistoryDao.ets @@ -0,0 +1,141 @@ +/** + * @author 2008 + * @datetime 2024/7/20 16:34 + * @className: rssSourcesHistoryDao + * 订阅源 + */ +import DbUtil from '../../common/utils/DbUtil'; +import AppDatabaseUtil from '../AppDatabaseUtil'; +import { rssSourcesHistory } from '../entities/rssSourcesHistory'; +import { ColumnInfo } from '../types/ColumnInfo'; + +class RssSourcesHistoryDao { + TABLE_NAME: string = 'rss_sources_history' + + async initRssSourcesHistoryTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql) + AppDatabaseUtil.existsTable(this.TABLE_NAME) + return + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + } + + async search(sourceUrl?:string) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (sourceUrl) { + whereClause.push(`( + sourceUrl LIKE '%${sourceUrl}%' + )`); + + } + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + sql += ` + ORDER BY + lastUpdateTime DESC +`; + const rssSourcesDbList = await DbUtil.querySqlForList(sql, column); + console.log("TagInfo", '书源数量:' + rssSourcesDbList.length) + return rssSourcesDbList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async batchInsert(history: rssSourcesHistory[]) { + try { + for (let index = 0; index < history.length; index++) { + const rssHistory = history[index]; + await this.insert(rssHistory) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async insert(rssHistory: rssSourcesHistory) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('sourceUrl', rssHistory.sourceUrl) + const count = await DbUtil.queryForCount(predicates, column) + if (count > 0) { + this.update(rssHistory) + return true + } + rssHistory.lastUpdateTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, rssHistory, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(rssHistory: rssSourcesHistory) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('sourceUrl', rssHistory.sourceUrl) + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0 && rssHistory instanceof rssSourcesHistory) { + this.insert(rssHistory) + return true + } + rssHistory.lastUpdateTime = Date.now() + rssHistory.showRecentIcon = true + await DbUtil.update(predicates, rssHistory, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + + } + + //批量删除订阅源历史记录 + async deleteRssSourcesHistoryList(rssHistory: rssSourcesHistory[]) { + try { + for (let index = 0; index < rssHistory.length; index++) { + await this.deleteRssSourcesHistory(rssHistory[index].sourceUrl) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //删除订阅源历史记录 + async deleteRssSourcesHistory(rssHistoryUrl: string) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('sourceUrl', rssHistoryUrl) + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } +} + + +const rssSourcesHistoryDao = new RssSourcesHistoryDao() +export default rssSourcesHistoryDao as RssSourcesHistoryDao \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/SubscriptionDao.ets b/entry/src/main/ets/database/dao/SubscriptionDao.ets new file mode 100644 index 00000000..98f1f65d --- /dev/null +++ b/entry/src/main/ets/database/dao/SubscriptionDao.ets @@ -0,0 +1,288 @@ +/** + * @author 2008 + * @datetime 2024/7/15 1:34 + * @className: SubscriptionDao + * 订阅源 + */ +import DbUtil from '../../common/utils/DbUtil'; +import rssSourcesUtils from '../../common/utils/rssSourcesUtils'; +import AppDatabaseUtil from '../AppDatabaseUtil'; +import { rssSourceDb, rssSources, ToRssSources, ToRssSourcesDb } from '../entities/rssSources'; +import { ColumnInfo } from '../types/ColumnInfo'; +import { rssSourcesTypeParams } from '../types/rssSourcesType'; +import rssSourcesHistoryDao from './RssSourcesHistoryDao'; + +interface delParams { + url: string, + id:number +} + +class SubscriptionDao { + TABLE_NAME: string = 'rssSources' + + // 创建book_subscription数据表 + async initSubscriptionTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql) + AppDatabaseUtil.existsTable(this.TABLE_NAME) + return + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + } + + async search(searchParams?: rssSourcesTypeParams) { + const searchKey = searchParams?.searchKey ?? ''; + + const enabled = searchParams?.enabled; + + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + + if (enabled !== undefined) { + whereClause.push(`enabled = ${enabled ? 1 : 0}`); + } + + if (searchKey) { // 确保 searchKey 不为空或未定义 + whereClause.push(`( + sourceName LIKE '%${searchKey}%' + OR sourceGroup LIKE '%${searchKey}%' + )`); + } + + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + + sql += ` + ORDER BY + lastUpdateTime DESC, + customOrder ASC +`; + const rssSourcesDbList = await DbUtil.querySqlForList(sql, column); + const rssSourcesList = rssSourcesDbList.map((item): rssSources => ToRssSources(item)); + console.log("TagInfo", '书源数量:' + rssSourcesList.length) + return rssSourcesList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async batchInsert(rssSources: rssSources[]) { + try { + for (let index = 0; index < rssSources.length; index++) { + const rssSource = rssSources[index]; + await this.insert(rssSource) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async insert(rssSource: rssSources) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + if (rssSource.id !== 0 && rssSource.id !== undefined) { + predicates.equalTo('id', rssSource.id) + } else { + predicates.equalTo('sourceUrl', rssSource.sourceUrl) + } + const count = await DbUtil.queryForCount(predicates, column) + if (count !== 0) { + this.update(rssSource) + return true + } + const rssSourceDb = ToRssSourcesDb(rssSource) + rssSourceDb.lastUpdateTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, rssSourceDb, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(rssSource: rssSources) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + if (rssSource.id !== 0 && rssSource.id !== undefined) { + predicates.equalTo('id', rssSource.id) + } else { + predicates.equalTo('sourceUrl', rssSource.sourceUrl) + } + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0 && rssSource instanceof rssSources) { + this.insert(rssSource) + return true + } + const rssSourceDb = ToRssSourcesDb(rssSource) + rssSourceDb.lastUpdateTime = Date.now() + rssSourceDb.showRecentIcon = true + await DbUtil.update(predicates, rssSourceDb, column) + rssSourcesHistoryDao.search(rssSource.sourceUrl).then(async (value) => { + if (value.length > 0) { + await rssSourcesUtils.pushRssSourcesHistory(rssSource) + } + }) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + + } + + async updateRecentIcon(rssSource: rssSources) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + if (rssSource.id !== 0 && rssSource.id !== undefined) { + predicates.equalTo('id', rssSource.id) + } else { + predicates.equalTo('sourceUrl', rssSource.sourceUrl) + } + const rssSourceDb = ToRssSourcesDb(rssSource) + rssSourceDb.showRecentIcon = false + await DbUtil.update(predicates, rssSourceDb, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + + } + + //批量删除订阅源 + async deleteRssSourcesList(rssSources: rssSources[]) { + try { + for (let index = 0; index < rssSources.length; index++) { + await this.deleteRssSources(rssSources[index]) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //删除书源 + async deleteRssSources(rssSource: rssSources) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + if (rssSource.id !== 0 && rssSource.id !== undefined) { + predicates.equalTo('id', rssSource.id) + } else { + predicates.equalTo('sourceUrl', rssSource.sourceUrl) + } + rssSourcesHistoryDao.deleteRssSourcesHistory(rssSource.sourceUrl) + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //置顶 + async isTopRssSources(rssSources: rssSources){ + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + if (rssSources.id !== 0 && rssSources.id !== undefined) { + predicates.equalTo('id', rssSources.id) + } else { + predicates.equalTo('sourceUrl', rssSources.sourceUrl) + } + const rssSourceDb = ToRssSourcesDb(rssSources) + rssSourceDb.lastUpdateTime = Date.now() + rssSourceDb.customOrder = 0 + await DbUtil.update(predicates, rssSourceDb, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async getRssSources(key: string): Promise { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('sourceUrl', key) + const rssDbList = await DbUtil.queryForList(predicates, column); + const rss = rssDbList.map((item): rssSources => ToRssSources(item)); + if (rss.length > 0) { + return rss[0] + } + return null + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return null + } + } + + //校验是否存在收藏 + async queryByUrl(url: string) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.like('sourceUrl', url) + const rssDbList = await DbUtil.queryForList(predicates, column); + const rss = rssDbList.map((item): rssSources => ToRssSources(item)); + if (rss.length > 0) { + return true + } else { + return false + } + } catch (e){ + console.log("TagInfo", JSON.stringify(e)) + return false + } + } + + //订阅源id删除或者sourceUrl进行删除 + async deleteRssSourcesById(param?:delParams) { + let id = param?.id + let sourceUrl = param?.url + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + if (id !== 0) { + predicates.equalTo('id', id) + } else { + predicates.equalTo('sourceUrl', sourceUrl) + } + await DbUtil.delete(predicates) + } catch (e) { + console.log("TagInfo", JSON.stringify(e)) + } + } + + getFlowColumn() { + const column: ColumnInfo[] = AppDatabaseUtil.getAssignColumn(this.TABLE_NAME, + ['sourceName', 'sourceUrl', 'sourceGroup', 'sourceGroup', 'enabled', 'variableComment', + 'sortUrl', 'singleUrl', 'lastUpdateTime','customOrder','variable','sourceType','showRecentIcon',]); + return column; + } +} + + + + + + +const subscriptionDao = new SubscriptionDao() +export default subscriptionDao as SubscriptionDao \ No newline at end of file diff --git a/entry/src/main/ets/database/dao/WorksListsDao.ets b/entry/src/main/ets/database/dao/WorksListsDao.ets new file mode 100644 index 00000000..80eac5ec --- /dev/null +++ b/entry/src/main/ets/database/dao/WorksListsDao.ets @@ -0,0 +1,159 @@ +import DbUtil from '../../common/utils/DbUtil'; +import AppDatabaseUtil from '../AppDatabaseUtil'; +import { ToWorksLists, ToWorksListsDb, WorksLists, worksListsDb } from '../entities/WorksLists'; +import { ColumnInfo } from '../types/ColumnInfo'; +import { WorksListsTypeSearchParams } from '../types/WorksListsType'; + +/** + * 书单db操作 + */ +class WorksListsDao { + TABLE_NAME: string = 'works_lists' + + // 创建works_lists数据表 + async initWorksListsTable() { + try { + const createSql = AppDatabaseUtil.getCreateSql(this.TABLE_NAME); + if (!createSql) { + return + } + await DbUtil.createTable(createSql) + AppDatabaseUtil.existsTable(this.TABLE_NAME) + return + } catch (err) { + console.info('TagInfo', JSON.stringify(err)) + } + } + + async search(param?:WorksListsTypeSearchParams) { + let searchKey = param?.searchKey ?? ''; + let type = param?.type; + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + let sql = `SELECT * FROM ${this.TABLE_NAME}`; + // 动态添加 WHERE 子句 + let whereClause: string[] = []; + if (type !== undefined) { + whereClause.push(`worksType = ${type}`); + } + if (searchKey) { + whereClause.push(`( + worksName LIKE '%${searchKey}%' + worksDescribe LIKE '%${searchKey}%' + )`); + } + // 如果有 where 子句,添加 WHERE 关键字 + if (whereClause.length > 0) { + sql += ` WHERE ${whereClause.join(' AND ')}`; + } + sql += ` + ORDER BY + isTop DESC, createTime DESC +`; + const workDbList = await DbUtil.querySqlForList(sql, column); + const worksList = workDbList.map((item): WorksLists => ToWorksLists(item)); + console.log("TagInfo", '书单:' + worksList.length) + return worksList + } catch (err) { + console.log("TagInfo", JSON.stringify(err)) + return [] + } + } + + async batchInsert(works: WorksLists[]) { + try { + for (let index = 0; index < works.length; index++) { + const work = works[index]; + await this.insert(work) + } + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async insert(works: WorksLists) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + if (works.worksId) { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('worksId', works.worksId) + const count = await DbUtil.queryForCount(predicates, column) + if (count > 0) { + this.update(works) + return true + } + } + const worksListsDb = ToWorksListsDb(works) + worksListsDb.worksBookNum = works.worksBookList?.length ?? 0 + worksListsDb.createTime = Date.now() + await DbUtil.insert(this.TABLE_NAME, worksListsDb, column) + console.log('TagInfo', '创建成功') + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + async update(works: WorksLists) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('worksId', works.worksId) + const count = await DbUtil.queryForCount(predicates, column) + if (count === 0 && works instanceof WorksLists) { + this.insert(works) + return true + } + const worksListsDb = ToWorksListsDb(works) + worksListsDb.createTime = Date.now() + worksListsDb.worksBookNum = works.worksBookList?.length ?? 0 + await DbUtil.update(predicates, worksListsDb, column) + return true + } catch (err) { + console.log('TagInfo, Error, ', JSON.stringify(err)) + return false + } + } + + //置顶 + async isUpdateWorksTop(worksId: number, isTop: boolean) { + try { + const column: ColumnInfo[] = AppDatabaseUtil.getColumn(this.TABLE_NAME); + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.equalTo('worksId', worksId) + const count = await DbUtil.queryForList(predicates, column) + if (column.length > 0) { + count.forEach((item) => { + item.isTop = isTop + item.updateTime = Date.now() + this.update(item) + }) + return true + } + return false + } catch (err) { + console.log('isUpdateWorksTop, Error, ', JSON.stringify(err)) + return false + } + } + + //删除书单记录 + async deleteWorks(worksId: number[]) { + try { + const predicates = DbUtil.getPredicates(this.TABLE_NAME); + predicates.in('worksId', worksId) + await DbUtil.delete(predicates) + return true + } catch (err) { + console.log('deleteBook, Error, ', JSON.stringify(err)) + return false + } + } +} + + +const worksListsDao = new WorksListsDao() +export default worksListsDao as WorksListsDao \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/BookGroups.ets b/entry/src/main/ets/database/entities/BookGroups.ets new file mode 100644 index 00000000..17ac8f29 --- /dev/null +++ b/entry/src/main/ets/database/entities/BookGroups.ets @@ -0,0 +1,107 @@ +/** + * @author 2008 + * @datetime 2024/7/22 22:39 + * @className: BookGroup + * 书籍分组 + */ +@Observed +export class BookGroups { + //分组Id + groupId?:number; + //分组名称 + groupName:string = ""; + //封面是否仅用当前分组 + coverOnly:boolean = false; + //封面样式类型 0默认1自定义2全图 + coverType:number = 0; + //分组封面 + coverUrl?:string; + //分组描述 + groupDescribe?:string; + //排序 + sort:number = 1; + //是否自动刷新 + enableRefresh:boolean = true; + //是否显示 + show:boolean = true; + //小说0/漫画1/有声2 + groupType:number = 0; + //创建时间 + createTime:number = 0; + //更新时间 + updateTime:number = 0; + //书籍排序 + bookSort:number = -1; + //更新提醒 + canUpdate:boolean = false + //是否可删除 + canDelete:boolean = true + //是否置顶 + isTop:boolean = false + //是否系统参数 + isSystem:boolean = false + //书籍Id + bookIds?:string[] +} + +export interface BookGroupDb extends Omit { + // 存在当前分组下的书籍id + bookIds?: string +} + +export const ToBookGroups = (bookGroupsDb: BookGroupDb) => { + let bookIds = bookGroupsDb.bookIds?.split(',') + const bookGroups: BookGroups = { + groupId: bookGroupsDb.groupId, + groupName: bookGroupsDb.groupName, + coverOnly: bookGroupsDb.coverOnly, + coverType: bookGroupsDb.coverType, + coverUrl: bookGroupsDb.coverUrl, + groupDescribe: bookGroupsDb.groupDescribe, + sort: bookGroupsDb.sort, + enableRefresh: bookGroupsDb.enableRefresh, + show: bookGroupsDb.show, + groupType: bookGroupsDb.groupType, + createTime: bookGroupsDb.createTime, + updateTime: bookGroupsDb.updateTime, + bookSort: bookGroupsDb.bookSort, + canUpdate: bookGroupsDb.canUpdate, + canDelete: bookGroupsDb.canDelete, + isTop: bookGroupsDb.isTop, + isSystem: bookGroupsDb.isSystem, + bookIds + } + return bookGroups +} + +export const ToBookGroupsDb = (bookGroups: BookGroups) => { + let bookIds:string = '' + if (Array.isArray(bookGroups.bookIds)) { + bookIds = bookGroups.bookIds.join(',') + } else { + if (bookGroups.bookIds) { + bookIds = bookGroups.bookIds + } + } + const bookGroupsDb: BookGroupDb = { + groupId: bookGroups.groupId, + groupName: bookGroups.groupName, + coverOnly: bookGroups.coverOnly, + coverType: bookGroups.coverType, + coverUrl: bookGroups.coverUrl, + groupDescribe: bookGroups.groupDescribe, + sort: bookGroups.sort, + enableRefresh: bookGroups.enableRefresh, + show: bookGroups.show, + groupType: bookGroups.groupType, + createTime: bookGroups.createTime, + updateTime: bookGroups.updateTime, + bookSort: bookGroups.bookSort, + canUpdate: bookGroups.canUpdate, + canDelete: bookGroups.canDelete, + isTop: bookGroups.isTop, + isSystem: bookGroups.isSystem, + bookIds + } + return bookGroupsDb +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/BookHistory.ets b/entry/src/main/ets/database/entities/BookHistory.ets new file mode 100644 index 00000000..ccf9efe4 --- /dev/null +++ b/entry/src/main/ets/database/entities/BookHistory.ets @@ -0,0 +1,50 @@ +/** + * @author 2008 + * @datetime 2024/8/5 21:15 + * @className: BookHistory + * 书籍浏览历史 + */ +@Observed +export class BookHistory { + id?:number + // 书籍名称 + bookName:string = '' + // 作者名称 + author: string = '' + //阅读地址 + bookUrl:string = '' + //封面地址 + coverUrl:string = '' + //最近一次阅读书籍的时间(打开正文的时间) + durChapterTime:number = 0 + //最近一次阅读章节的序号 + durChapterIndex:number = 0 + //最近一次阅读章节的标题 + durChapterTitle:string = '' + //最近一次阅读章节进度 + durChapterContent:string = '' + //排序 + sort:number = 0 + //小说0/漫画1/有声2 + bookType?:number + //源书籍ID + originBookId?:number + //创建时间 + createTime?:number = 0 + //更新时间 + updateTime?:number = 0 + + constructor(bookHistory?:BookHistory) { + if (bookHistory) { + this.id = bookHistory.id + this.bookName = bookHistory.bookName + this.author = bookHistory.author + this.durChapterTime = bookHistory.durChapterTime + this.durChapterIndex = bookHistory.durChapterIndex + this.durChapterTitle = bookHistory.durChapterTitle + this.durChapterContent = bookHistory.durChapterContent + this.sort = bookHistory.sort + this.bookType = bookHistory.bookType + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/BookSource.ets b/entry/src/main/ets/database/entities/BookSource.ets new file mode 100644 index 00000000..992a01f8 --- /dev/null +++ b/entry/src/main/ets/database/entities/BookSource.ets @@ -0,0 +1,234 @@ +import { GSON } from '../../common/utils/utils' +import { BookSourcePart } from './BookSourcePart' +import { BookInfoRule, ContentRule, ExploreRule, ReviewRule, SearchRule, TocRule } from './rule' + +@Observed +export class BookSource { + // 地址,包括 http/https + bookSourceUrl: string = "" + // 名称 + bookSourceName: string = "" + // 分组 + bookSourceGroup?: string + // 类型,0 文本,1 音频, 2 图片, 3 文件(指的是类似知轩藏书只提供下载的网站) + bookSourceType: number = 0 + bookSourceGrade?: number = 2 + bookSourceScore?: string + // 详情页url正则 + bookUrlPattern?: string + // 手动排序编号 + customOrder: number = 0 + // 是否启用 + enabled: boolean = true + // 启用发现 + enabledExplore: boolean = true + // js库 + jsLib?: string + // 启用okhttp CookieJAr 自动保存每次请求的cookie + enabledCookieJar?: boolean = true + // 并发率 + concurrentRate?: string + // 请求头 + header?: string + // 登录地址 + loginUrl?: string + // 登录UI + loginUi?: string + // 登录检测js + loginCheckJs?: string + // 封面解密js + coverDecodeJs?: string + // 注释 + bookSourceComment?: string + // 自定义变量说明 + variableComment?: string + // 最后更新时间,用于排序 + lastUpdateTime: number = 0 + // 响应时间,用于排序 + respondTime: number = 180000 + // 智能排序的权重 + weight: number = 0 + // 发现url + exploreUrl?: string + // 发现筛选规则 + exploreScreen?: string + // 搜索url + searchUrl?: string + // 发现规则 + ruleExplore?: ExploreRule + // 搜索规则 + ruleSearch?: SearchRule + // 书籍信息页规则 + ruleBookInfo?: BookInfoRule + // 目录页规则 + ruleToc?: TocRule + // 正文页规则 + ruleContent?: ContentRule + // 段评规则 + ruleReview?: ReviewRule + // 是否置顶 + isTop: boolean = false + //是否新增或则更新点击过 + showRecentIcon: boolean = true + showExplore: boolean = true +} + +export interface GroupList { + title: string + list: BookSource[] +} + +export interface GroupPartList { + title: string + list: BookSourcePart[] +} + + +export const GRADE_TYPE: Record = { + 0: '常规', + 1: '优质', + 2: '精品' +} + +export const BOOK_SOURCE_TYPE: Record = { + 0 : '小说', + 2 : '漫画', + 1 : '有声' +} +export const SOURCE_SCORE_ARR = ['5.0分', '4.0分', '3.0分', '2.0分', '1.0分'] +export const SOURCE_GROUP_MAP: Record = { + 0: ['男频', '女频', '综合', '出版', '下载', '正版', '轻文', '网络', '其他'], + 1: ['听书', '音乐', '正版', '其他'], + 2: ['国漫', '日漫', '韩漫', '美漫', '综合', '网络', '正版', '其他'] +} + +export interface BookSourceDb extends Omit { + // 发现规则 + ruleExplore?: string + // 搜索规则 + ruleSearch?: string + // 书籍信息页规则 + ruleBookInfo?: string + // 目录页规则 + ruleToc?: string + // 正文页规则 + ruleContent?: string + // 段评规则 + ruleReview?: string +} + +export const ToBookSource = (bookSourceDb: BookSourceDb) => { + const ruleExplore = GSON.toJson(bookSourceDb.ruleExplore); + const ruleSearch = GSON.toJson(bookSourceDb.ruleSearch); + const ruleBookInfo = GSON.toJson(bookSourceDb.ruleBookInfo); + const ruleToc = GSON.toJson(bookSourceDb.ruleToc); + const ruleContent = GSON.toJson(bookSourceDb.ruleContent); + const ruleReview = GSON.toJson(bookSourceDb.ruleReview); + const bookSource: BookSource = { + bookSourceUrl: bookSourceDb.bookSourceUrl, + bookSourceName: bookSourceDb.bookSourceName, + bookSourceGroup: bookSourceDb.bookSourceGroup, + bookSourceType: bookSourceDb.bookSourceType, + bookSourceGrade: bookSourceDb.bookSourceGrade, + bookSourceScore: bookSourceDb.bookSourceScore, + bookUrlPattern: bookSourceDb.bookUrlPattern, + customOrder: bookSourceDb.customOrder, + enabled: bookSourceDb.enabled, + enabledExplore: bookSourceDb.enabledExplore, + jsLib: bookSourceDb.jsLib, + enabledCookieJar: bookSourceDb.enabledCookieJar, + concurrentRate: bookSourceDb.concurrentRate, + header: bookSourceDb.header, + loginUrl: bookSourceDb.loginUrl, + loginUi: bookSourceDb.loginUi, + loginCheckJs: bookSourceDb.loginCheckJs, + coverDecodeJs: bookSourceDb.coverDecodeJs, + bookSourceComment: bookSourceDb.bookSourceComment, + variableComment: bookSourceDb.variableComment, + lastUpdateTime: bookSourceDb.lastUpdateTime, + respondTime: bookSourceDb.respondTime, + weight: bookSourceDb.weight, + exploreUrl: bookSourceDb.exploreUrl, + exploreScreen: bookSourceDb.exploreScreen, + searchUrl: bookSourceDb.searchUrl, + isTop: bookSourceDb.isTop, + showRecentIcon: bookSourceDb.showRecentIcon, + showExplore: bookSourceDb.showExplore, + ruleExplore, + ruleSearch, + ruleBookInfo, + ruleToc, + ruleContent, + ruleReview + } + return bookSource +} + +export const ToBookSourceDb = (bookSource: BookSource) => { + const ruleExplore = GSON.toString(bookSource.ruleExplore); + const ruleSearch = GSON.toString(bookSource.ruleSearch); + const ruleBookInfo = GSON.toString(bookSource.ruleBookInfo); + const ruleToc = GSON.toString(bookSource.ruleToc); + const ruleContent = GSON.toString(bookSource.ruleContent); + const ruleReview = GSON.toString(bookSource.ruleReview); + const bookSourceDb: BookSourceDb = { + bookSourceUrl: bookSource.bookSourceUrl, + bookSourceName: bookSource.bookSourceName, + bookSourceGroup: bookSource.bookSourceGroup, + bookSourceType: bookSource.bookSourceType, + bookSourceGrade: bookSource.bookSourceGrade, + bookSourceScore: bookSource.bookSourceScore, + bookUrlPattern: bookSource.bookUrlPattern, + customOrder: bookSource.customOrder, + enabled: bookSource.enabled, + enabledExplore: bookSource.enabledExplore, + jsLib: bookSource.jsLib, + enabledCookieJar: bookSource.enabledCookieJar, + concurrentRate: bookSource.concurrentRate, + header: bookSource.header, + loginUrl: bookSource.loginUrl, + loginUi: bookSource.loginUi, + loginCheckJs: bookSource.loginCheckJs, + coverDecodeJs: bookSource.coverDecodeJs, + bookSourceComment: bookSource.bookSourceComment, + variableComment: bookSource.variableComment, + lastUpdateTime: bookSource.lastUpdateTime, + respondTime: bookSource.respondTime, + weight: bookSource.weight, + exploreUrl: bookSource.exploreUrl, + exploreScreen: bookSource.exploreScreen, + searchUrl: bookSource.searchUrl, + isTop: bookSource.isTop, + showRecentIcon: bookSource.showRecentIcon, + showExplore: bookSource.showExplore, + ruleExplore, + ruleSearch, + ruleBookInfo, + ruleToc, + ruleContent, + ruleReview + } + return bookSourceDb +} + +export const ToBookSourcePart = (bookSource: BookSource) => { + const bookSourcePart: BookSourcePart = { + bookSourceUrl: bookSource.bookSourceUrl, + bookSourceName: bookSource.bookSourceName, + bookSourceGroup: bookSource.bookSourceGroup, + bookSourceGrade: bookSource.bookSourceGrade, + bookSourceScore: bookSource.bookSourceScore, + customOrder: bookSource.customOrder, + enabled: bookSource.enabled, + enabledExplore: bookSource.enabledExplore, + lastUpdateTime: bookSource.lastUpdateTime, + respondTime: bookSource.respondTime, + weight: bookSource.weight, + isTop: bookSource.isTop, + showRecentIcon: bookSource.showRecentIcon, + showExplore: bookSource.showExplore, + hasLoginUrl: false, + hasExploreUrl: false + } + return bookSourcePart +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/BookSourcePart.ets b/entry/src/main/ets/database/entities/BookSourcePart.ets new file mode 100644 index 00000000..5e71bcd6 --- /dev/null +++ b/entry/src/main/ets/database/entities/BookSourcePart.ets @@ -0,0 +1,32 @@ +@Observed +export class BookSourcePart { + // 地址,包括 http/https + bookSourceUrl: string = "" + // 名称 + bookSourceName: string = "" + // 分组 + bookSourceGroup?: string + bookSourceGrade?: number = 2 + bookSourceScore?: string + // 手动排序编号 + customOrder: number = 0 + // 是否启用 + enabled: boolean = true + // 启用发现 + enabledExplore: boolean = true + // 是否有登录地址 + hasLoginUrl: boolean = false + // 最后更新时间,用于排序 + lastUpdateTime: number = 0 + // 响应时间,用于排序 + respondTime: number = 180000 + // 智能排序的权重 + weight: number = 0 + // 是否有发现url + hasExploreUrl: boolean = false + // 是否置顶 + isTop: boolean = false + //是否新增或则更新点击过 + showRecentIcon: boolean = true + showExplore: boolean = true +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/Books.ets b/entry/src/main/ets/database/entities/Books.ets new file mode 100644 index 00000000..15dd9a8f --- /dev/null +++ b/entry/src/main/ets/database/entities/Books.ets @@ -0,0 +1,99 @@ +/** + * @author 2008 + * @datetime 2024/7/22 21:21 + * @className: Books + * 书籍 + */ +import { BookSource } from './BookSource'; + +@Observed +export class Books { + //书籍ID + id?:number; + //书籍存储路径 + bookUrl?:string + //目录页Url + toUrl?:string + // 书源URL + origin?:string + //书源名称 or 本地书籍文件名 + originName?:string + // 书籍名称(书源获取) 或则自定义书籍名称 + bookName:string = "" + // // 作者名称(书源获取) + author: string = "" + //分类信息(书源获取) + cover?:string + //分类信息 + customTag?:string + //封面Url(书源获取) + coverUrl?:string + //自定义封面Url + customCoverUrl?:string + //简介内容(书源获取) + intro?:string + //简介内容(用户修改) + customIntro?:string + //自定义字符集名称(仅适用于本地书籍) + charset?:string + //在导入的情况下或则未分组默认为2 未分组 + bookGroup:number = 3; + // 最新章节标题 + latestChapterTitle?:string + // 最新章节标题更新时间 + latestChapterTime:number = 0; + //最近一次更新书籍信息的时间 + lastCheckTime?:number + //最近一次发现新章节的数量 + lastCheckCount?:number + //书籍目录总数 + totalChapterNum:number = 0; + //当前章节名称 + durChapterTitle?:string + //当前章节索引 + durChapterIndex:number = 0 + //当前阅读的进度(首行字符的索引位置) + durChapterPos:number = 0 + //最近一次阅读书籍的时间(打开正文的时间) + durChapterTime:number = 0 + //字数 + wordCount?:string + //刷新书架时更新书籍信息 + canUpdate:boolean = true + //排序 + sort:number = 0 + //书源排序 + originOrder:number = 0 + //同步时间 + syncTime:number = 0 + //小说0/漫画1/有声2 + bookType:number = 0 + //是否置顶 + isTop:boolean = false + //创建时间 + createTime?:number = 0 + //更新时间 + updateTime?:number = 0 + //是否加入书架 + isJoin:boolean = false + //是否本地导入 + isLocalBook:boolean = false + source?:BookSource + sourceList?:BookSource[] = [] +} + +export class bookShelfImport{ + name: string = "" + author: string = "" + intro: string = "" + bookUrl:string = "" + + constructor(bookShelf:bookShelfImport) { + this.name = bookShelf.name + this.author = bookShelf.author + this.intro = bookShelf.intro + this.bookUrl = bookShelf.bookUrl + } +} + +export const BOOK_SEARCH_TYPE: string[] = ['最近阅读', '更新排序', '手动排序'] \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/SearchBook.ets b/entry/src/main/ets/database/entities/SearchBook.ets new file mode 100644 index 00000000..a8b9112c --- /dev/null +++ b/entry/src/main/ets/database/entities/SearchBook.ets @@ -0,0 +1,36 @@ +/** + * @author 2008 + * @datetime 2024/8/14 20:56 + * @className: SearchBook + */ +import { BookSource } from './BookSource' + +@Observed +export class SearchBook { + bookUrl: string = "" + /** 书源 */ + origin: string = "" + originName: string = "" + /** BookType */ + type: string = "" + name: string = "" + author: string = "" + kind?:string + coverUrl?: string + intro?: string + wordCount?:string + latestChapterTitle:string = "" + /** 目录页Url (toc=table of Contents) */ + tocUrl?:string = "" + time:number = Date.now() + variable?:string + originOrder?:number = 0 + chapterWordCountText?:string + chapterWordCount?: number = -1 + respondTime?: number = -1 + //数量 + belongCount:number = 1 + source?:BookSource + sourceList:BookSource[] = [] + bookType:number = 0 +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/WorksBookList.ets b/entry/src/main/ets/database/entities/WorksBookList.ets new file mode 100644 index 00000000..fd326093 --- /dev/null +++ b/entry/src/main/ets/database/entities/WorksBookList.ets @@ -0,0 +1,22 @@ +/** + * @author 2008 + * @datetime 2024/8/1 13:10 + * @className: markBookList + * 书单书籍列信息 + */ +@Observed +export class WorksBookList{ + //书单书籍Id + bookId?:number; + //推荐理由 + recommend?:string + //书籍标签 + tag?:string + + constructor(book?:WorksBookList) { + if (!book) return; + this.bookId = book.bookId; + this.recommend = book.recommend; + this.tag = book.tag; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/WorksLists.ets b/entry/src/main/ets/database/entities/WorksLists.ets new file mode 100644 index 00000000..5580e557 --- /dev/null +++ b/entry/src/main/ets/database/entities/WorksLists.ets @@ -0,0 +1,80 @@ +import { GSON } from '../../common/utils/utils'; +import { WorksBookList } from './WorksBookList'; +/** + * @author 2008 + * @datetime 2024/8/1 13:10 + * @className: WorksLists + * 书单 + */ +@Observed +export class WorksLists { + //书单Id + worksId?:number; + //书单名称 + worksName:string = ""; + //书单描述 + worksDescribe:string = ""; + //备注 + worksRemark:string = ""; + //封面 + worksCoverUrl:string = ""; + //创建时间 + createTime:number = 0; + //更新时间 + updateTime:number = 0; + //小说0/漫画1/有声2 + worksType:number = 0 + //书籍数量 + worksBookNum:number = 0; + //置顶 + isTop:boolean = false; + //书单书籍信息 + worksBookList?:WorksBookList[]; +} + +export interface worksListsDb extends Omit { + //列表 + worksBookList?: string +} + +export const ToWorksLists = (worksListsDb: worksListsDb) => { + const worksBookList = GSON.toJson(worksListsDb.worksBookList); + const worksLists: WorksLists = { + worksId: worksListsDb.worksId, + worksName: worksListsDb.worksName, + worksDescribe: worksListsDb.worksDescribe, + worksRemark: worksListsDb.worksRemark, + worksCoverUrl: worksListsDb.worksCoverUrl, + createTime: worksListsDb.createTime, + updateTime: worksListsDb.updateTime, + worksType: worksListsDb.worksType, + worksBookNum: worksListsDb.worksBookNum, + isTop: worksListsDb.isTop, + worksBookList + } + return worksLists +} + +export const ToWorksListsDb = (worksLists: WorksLists) => { + const worksBookList = GSON.toString(worksLists.worksBookList); + const worksListsDb: worksListsDb = { + worksId: worksLists.worksId, + worksName: worksLists.worksName, + worksDescribe: worksLists.worksDescribe, + worksRemark: worksLists.worksRemark, + worksCoverUrl: worksLists.worksCoverUrl, + createTime: worksLists.createTime, + updateTime: worksLists.updateTime, + worksType: worksLists.worksType, + worksBookNum: worksLists.worksBookNum, + isTop: worksLists.isTop, + worksBookList + } + return worksListsDb +} + +export const WORK_BOOK_LIST_STATUS: Record ={ + 0: '新建书单', + 1: '', + 2: '编辑书单' +} diff --git a/entry/src/main/ets/database/entities/rssSources.ets b/entry/src/main/ets/database/entities/rssSources.ets new file mode 100644 index 00000000..b352bfd1 --- /dev/null +++ b/entry/src/main/ets/database/entities/rssSources.ets @@ -0,0 +1,217 @@ +/** + * @author 2008 + * @datetime 2024/7/14 23:19 + * @className: rssSources + * 订阅源Date + */ +import { GSON } from '../../common/utils/utils' +import { rssListRule } from './rule/rssListRule' +import { rssWebViewRule } from './rule/rssWebViewRule' + +@Observed +export class rssSources{ + id?:number + //订阅源类型0.常规网站 1.订阅源 + sourceType:number = 0 + //名称 + sourceName:string = '' + //地址url + sourceUrl:string = '' + //图标 + sourceIcon:string = '' + // 图标是否使用链接 + sourceIconIsUrl:boolean = false + // 分组 + sourceGroup:string = SUBSCRIPTION_GROUP_TYPE[4] + //源注解 + sourceComment?:string + //是否启用 + enabled: boolean = true + // 自定义变量说明 + variableComment?:string + // js库 + jsLib?:string + // 启用okhttp CookieJAr 自动保存每次请求的cookie + enabledCookieJar:boolean = false + // 并发率 + concurrentRate?:string + // 请求头 + header?:string + // 登录地址 + loginUrl?:string + // 登录UI + loginUi?:string + // 登录检测js + loginCheckJs?:string + // 封面解密js + coverDecodeJs?:string + // 分类地址 + sortUrl?:string + // 单URL + singleUrl:boolean = true + // 文章样式 + articleStyle?:string + //最后更新时间 + lastUpdateTime:number = 0 + // 排序编号 + customOrder:number = 0 + //设置源变量 + variable?:string + //是否新增或则更新点击过 + showRecentIcon:boolean = true + //自动补全 + autoComplete:boolean = true + //自定义文字 + customizeTitle:string = '' + //列表 + rssListRule?:rssListRule + //webView + rssWebViewRule?:rssWebViewRule +} + +export interface rssGroupList { + title: string + list: rssSources[] +} + +export class rssArticles{ + origin:string = '' + sort:string = '' + title:string = '' + order:number = 0 + link:string = '' + pubDate:string = '' + description?:string + content?:string + image?:string + read:number = 0 + variable?:string +} + +export class rssReadRecords{ + record:string = '' + read:number = 0 +} + + +export class rssStars { + origin:string = '' + sort:string = '' + title:string = '' + starTime?:Date + link:string = '' + pubDate:string = '' + description?:string + content?:string + image?:string + read:number = 0 + variable?:string +} + +//订阅源分组类别 +export const SUBSCRIPTION_GROUP_TYPE: Record ={ + 0: '小说', + 1: '漫画', + 2: '影视', + 3: '资讯', + 4: '收藏夹' +} + +//订阅源分组类别 +export const SUBSCRIPTION_TYPE: Record ={ + 0: '常规网站', + 1: '订阅源' +} + +export const WEB_USER_AGENT: string[] = [ + 'Mozilla/5.0 (Linux; Android 13; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Mobile Safari/537.36', + 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36', + 'Mozilla/5.0 (Custom Device; Custom OS 1.0; Custom Build) AppleWebKit/537.36 (KHTML, like Gecko) CustomBrowser/1.0 CustomSafari/537.36' +] + + +export interface rssSourceDb extends Omit { + //列表 + rssListRule?: string + //webView + rssWebViewRule?: string +} + + +export const ToRssSources = (rssSourceDb: rssSourceDb) => { + const rssListRule = GSON.toJson(rssSourceDb.rssListRule); + const rssWebViewRule = GSON.toJson(rssSourceDb.rssWebViewRule); + const rssSources: rssSources = { + id: rssSourceDb.id, + sourceType: rssSourceDb.sourceType, + sourceName: rssSourceDb.sourceName, + sourceUrl: rssSourceDb.sourceUrl, + sourceIcon: rssSourceDb.sourceIcon, + sourceIconIsUrl: rssSourceDb.sourceIconIsUrl, + sourceGroup: rssSourceDb.sourceGroup, + sourceComment: rssSourceDb.sourceComment, + enabled: rssSourceDb.enabled, + variableComment: rssSourceDb.variableComment, + jsLib: rssSourceDb.jsLib, + enabledCookieJar: rssSourceDb.enabledCookieJar, + concurrentRate: rssSourceDb.concurrentRate, + header: rssSourceDb.header, + loginUrl: rssSourceDb.loginUrl, + loginUi: rssSourceDb.loginUi, + loginCheckJs: rssSourceDb.loginCheckJs, + coverDecodeJs: rssSourceDb.coverDecodeJs, + sortUrl: rssSourceDb.sortUrl, + singleUrl: rssSourceDb.singleUrl, + articleStyle: rssSourceDb.articleStyle, + lastUpdateTime: rssSourceDb.lastUpdateTime, + customOrder: rssSourceDb.customOrder, + variable: rssSourceDb.variable, + autoComplete: rssSourceDb.autoComplete, + showRecentIcon:rssSourceDb.showRecentIcon, + customizeTitle:rssSourceDb.customizeTitle, + rssListRule, + rssWebViewRule + } + return rssSources +} + + +export const ToRssSourcesDb = (rssSource: rssSources) => { + const rssListRule = GSON.toString(rssSource.rssListRule); + const rssWebViewRule = GSON.toString(rssSource.rssWebViewRule); + const rssSourcesDb: rssSourceDb = { + id: rssSource.id, + sourceType: rssSource.sourceType, + sourceName: rssSource.sourceName, + sourceUrl: rssSource.sourceUrl, + sourceIcon: rssSource.sourceIcon, + sourceIconIsUrl: rssSource.sourceIconIsUrl, + sourceGroup: rssSource.sourceGroup, + sourceComment: rssSource.sourceComment, + enabled: rssSource.enabled, + variableComment: rssSource.variableComment, + jsLib: rssSource.jsLib, + enabledCookieJar: rssSource.enabledCookieJar, + concurrentRate: rssSource.concurrentRate, + header: rssSource.header, + loginUrl: rssSource.loginUrl, + loginUi: rssSource.loginUi, + loginCheckJs: rssSource.loginCheckJs, + coverDecodeJs: rssSource.coverDecodeJs, + sortUrl: rssSource.sortUrl, + singleUrl: rssSource.singleUrl, + articleStyle: rssSource.articleStyle, + lastUpdateTime: rssSource.lastUpdateTime, + customOrder: rssSource.customOrder, + variable: rssSource.variable, + autoComplete: rssSource.autoComplete, + showRecentIcon: rssSource.showRecentIcon, + customizeTitle: rssSource.customizeTitle, + rssListRule, + rssWebViewRule + } + return rssSourcesDb +} + + diff --git a/entry/src/main/ets/database/entities/rssSourcesHistory.ets b/entry/src/main/ets/database/entities/rssSourcesHistory.ets new file mode 100644 index 00000000..a4152066 --- /dev/null +++ b/entry/src/main/ets/database/entities/rssSourcesHistory.ets @@ -0,0 +1,28 @@ +/** + * @author 2008 + * @datetime 2024/7/20 15:51 + * @className: rssSourcesHistory + */ +import { SUBSCRIPTION_GROUP_TYPE } from './rssSources' + +@Observed +export class rssSourcesHistory{ + //订阅源类型0.常规网站 1.订阅源 + sourceType:number = 0 + //名称 + sourceName:string = '' + //地址url + sourceUrl:string = '' + //图标 + sourceIcon:string = '' + // 图标是否使用链接 + sourceIconIsUrl:boolean = false + // 分组 + sourceGroup:string = SUBSCRIPTION_GROUP_TYPE[0] + //最后更新时间 + lastUpdateTime:number = 0 + //是否新增或则更新点击过 + showRecentIcon:boolean = true + //自定义文字 + customizeTitle:string = '' +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rssSourcesPart.ets b/entry/src/main/ets/database/entities/rssSourcesPart.ets new file mode 100644 index 00000000..bc14ab74 --- /dev/null +++ b/entry/src/main/ets/database/entities/rssSourcesPart.ets @@ -0,0 +1,36 @@ +/** + * @author 2008 + * @datetime 2024/7/14 23:19 + * @className: rssSources + * 订阅源Part + */ +@Observed +export class rssSourcesPart { + //名称 + sourceName:string = '' + //地址url + sourceUrl:string = '' + // 分组 + sourceGroup?:string + + //是否启用 + enabled?: boolean = true + // 自定义变量说明 + variableComment?:string + // 分类地址 + sortUrl?:string + // 单URL + singleUrl?:boolean + //最后更新时间 + lastUpdateTime:number = 0 + // 排序编号 + customOrder:number = 0 + //设置源变量 + variable?:string + //订阅源类型0.常规网站 1.订阅源 + sourceType?: number = 1 + + showRecentIcon:boolean = true +} + + diff --git a/entry/src/main/ets/database/entities/rule/BookInfoRule.ets b/entry/src/main/ets/database/entities/rule/BookInfoRule.ets new file mode 100644 index 00000000..f6c4dfb1 --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/BookInfoRule.ets @@ -0,0 +1,33 @@ +/** + * 书籍详情页规则 + */ +export class BookInfoRule { + init?: string + name?: string + author?: string + intro?: string + kind?: string + lastChapter?: string + updateTime?: string + coverUrl?: string + tocUrl?: string + wordCount?: string + canReName?: string + downloadUrls?: string + + constructor(bookInfo?: BookInfoRule) { + if (!bookInfo) return; + this.init = bookInfo.init; + this.name = bookInfo.name; + this.author = bookInfo.author; + this.intro = bookInfo.intro; + this.kind = bookInfo.kind; + this.lastChapter = bookInfo.lastChapter; + this.updateTime = bookInfo.updateTime; + this.coverUrl = bookInfo.coverUrl; + this.tocUrl = bookInfo.tocUrl; + this.wordCount = bookInfo.wordCount; + this.canReName = bookInfo.canReName; + this.downloadUrls = bookInfo.downloadUrls; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/ContentRule.ets b/entry/src/main/ets/database/entities/rule/ContentRule.ets new file mode 100644 index 00000000..5b5c7580 --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/ContentRule.ets @@ -0,0 +1,14 @@ +/** + * 正文处理规则 + */ +export class ContentRule { + content?: string + title?: string //有些网站只能在正文中获取标题 + nextContentUrl?: string + webJs?: string + sourceRegex?: string + replaceRegex?: string //替换规则 + imageStyle?: string //默认大小居中,FULL最大宽度 + imageDecode?: string //图片bytes二次解密js, 返回解密后的bytes + payAction?: string //购买操作,js或者包含{{js}}的url +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/ExploreRule.ets b/entry/src/main/ets/database/entities/rule/ExploreRule.ets new file mode 100644 index 00000000..46c2bd8c --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/ExploreRule.ets @@ -0,0 +1,15 @@ +/** + * 发现结果规则 + */ +export class ExploreRule { + bookList?: string + name?: string + author?: string + intro?: string + kind?: string + lastChapter?: string + updateTime?: string + bookUrl?: string + coverUrl?: string + wordCount?: string +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/ReviewRule.ets b/entry/src/main/ets/database/entities/rule/ReviewRule.ets new file mode 100644 index 00000000..79d6fa4a --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/ReviewRule.ets @@ -0,0 +1,17 @@ +/** + * 段评规则 + */ +export class ReviewRule { + reviewUrl?: string // 段评URL + avatarRule?: string // 段评发布者头像 + contentRule?: string // 段评内容 + postTimeRule?: string // 段评发布时间 + reviewQuoteUrl?: string // 获取段评回复URL + + // 这些功能将在以上功能完成以后实现 + voteUpUrl?: string // 点赞URL + voteDownUrl?: string // 点踩URL + postReviewUrl?: string // 发送回复URL + postQuoteUrl?: string // 发送回复段评URL + deleteUrl?: string // 删除段评URL +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/SearchRule.ets b/entry/src/main/ets/database/entities/rule/SearchRule.ets new file mode 100644 index 00000000..f22955d7 --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/SearchRule.ets @@ -0,0 +1,17 @@ +/** + * 搜索结果处理规则 + */ +export class SearchRule { + /**校验关键字**/ + checkKeyWord?: string + bookList?: string + name?: string + author?: string + intro?: string + kind?: string + lastChapter?: string + updateTime?: string + bookUrl?: string + coverUrl?: string + wordCount?: string +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/TocRule.ets b/entry/src/main/ets/database/entities/rule/TocRule.ets new file mode 100644 index 00000000..1b8cc5bb --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/TocRule.ets @@ -0,0 +1,15 @@ +/** + * 目录规则 + */ +export class TocRule { + preUpdateJs?: string + chapterList?: string + chapterName?: string + chapterUrl?: string + formatJs?: string + isVolume?: string + isVip?: string + isPay?: string + updateTime?: string + nextTocUrl?: string +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/index.ets b/entry/src/main/ets/database/entities/rule/index.ets new file mode 100644 index 00000000..c659d96a --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/index.ets @@ -0,0 +1,6 @@ +export * from './BookInfoRule' +export * from './ContentRule' +export * from './ExploreRule' +export * from './ReviewRule' +export * from './SearchRule' +export * from './TocRule' \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/rssListRule.ets b/entry/src/main/ets/database/entities/rule/rssListRule.ets new file mode 100644 index 00000000..a628ce07 --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/rssListRule.ets @@ -0,0 +1,22 @@ +/** + * @author 2008 + * @datetime 2024/7/15 14:56 + * @className: rssListRule + * 列表 + */ +export class rssListRule{ + // 列表规则 + ruleArticles?:string + // 翻页规则 + ruleNextPage?:string + //标题规则 + ruleTitle?:string + //时间规则 + rulePubDate?:string + //描述规则 + ruleDescription?:string + //图片规则 + ruleImage?:string + //链接规则 + ruleLink?:string +} \ No newline at end of file diff --git a/entry/src/main/ets/database/entities/rule/rssWebViewRule.ets b/entry/src/main/ets/database/entities/rule/rssWebViewRule.ets new file mode 100644 index 00000000..a4b19a05 --- /dev/null +++ b/entry/src/main/ets/database/entities/rule/rssWebViewRule.ets @@ -0,0 +1,23 @@ +/** + * @author 2008 + * @datetime 2024/7/15 14:59 + * @className: rssWebViewRule + */ +export class rssWebViewRule{ + //启用JavaScript + enableJs:boolean = true + //加载 BaseUrl + loadWithBaseUrl:boolean = true + //内容规则 + ruleContent?:string + //样式规则 + style?:string + //注入规则 + injectJs?:string + //白名单 + contentWhitelist?:string + //黑名单 + contentBlacklist?:string + //链接拦截 + shouldOverrideUrlLoading?:string +} \ No newline at end of file diff --git a/entry/src/main/ets/database/index.ets b/entry/src/main/ets/database/index.ets new file mode 100644 index 00000000..9429c738 --- /dev/null +++ b/entry/src/main/ets/database/index.ets @@ -0,0 +1,23 @@ +import BookGroupsDao from './dao/BookGroupsDao' +import bookHistoryDao from './dao/BookHistoryDao' +import BooksDao from './dao/BooksDao' +import BookSourceDao from './dao/BookSourceDao' +import rssSourcesHistoryDao from './dao/RssSourcesHistoryDao' +import SubscriptionDao from './dao/SubscriptionDao' +import worksListsDao from './dao/WorksListsDao' + +class DataBase { + async initAllTable() { + await BookSourceDao.initBookSourceTable() + await rssSourcesHistoryDao.initRssSourcesHistoryTable() + await SubscriptionDao.initSubscriptionTable() + await BooksDao.initBooksTable() + await BookGroupsDao.initGroupTable() + await worksListsDao.initWorksListsTable() + await bookHistoryDao.initBookHistoryTable() + } +} + +const dataBase = new DataBase() + +export default dataBase as DataBase \ No newline at end of file diff --git a/entry/src/main/ets/database/initData/BookGroupsData.ets b/entry/src/main/ets/database/initData/BookGroupsData.ets new file mode 100644 index 00000000..a76502d7 --- /dev/null +++ b/entry/src/main/ets/database/initData/BookGroupsData.ets @@ -0,0 +1,57 @@ +/** + * @author 2008 + * @datetime 2024/7/22 22:42 + * @className: BookGroup + * 书籍分组 + */ +@Observed +export class BookGroupsData { + //分组Id + groupId?:number; + //分组名称 + groupName:string = ""; + //封面是否仅用当前分组 + coverOnly:boolean = false; + //封面样式类型 0默认1自定义2全图 + coverType:number = 0; + //分组封面 + coverUrl?:string; + //分组描述 + groupDescribe?:string; + //排序 + sort:number = 1; + //是否自动刷新 + enableRefresh:boolean = true; + //是否显示 + show:boolean = true; + //小说0/漫画1/有声2 + groupType:number = 0; + //创建时间 + createTime:number = 0; + //更新时间 + updateTime:number = 0; + //书籍排序 + bookSort:number = -1; + //更新提醒 + canUpdate:boolean = false + //是否可删除 + canDelete:boolean = true + + constructor(bookGroupsData?:BookGroupsData) { + if (!bookGroupsData) return; + this.groupName = bookGroupsData.groupName; + this.coverOnly = bookGroupsData.coverOnly; + this.coverType = bookGroupsData.coverType; + this.coverUrl = bookGroupsData.coverUrl; + this.groupDescribe = bookGroupsData.groupDescribe; + this.sort = bookGroupsData.sort; + this.enableRefresh = bookGroupsData.enableRefresh; + this.show = bookGroupsData.show; + this.groupType = bookGroupsData.groupType; + this.createTime = bookGroupsData.createTime; + this.updateTime = bookGroupsData.updateTime; + this.bookSort = bookGroupsData.bookSort; + this.canUpdate = bookGroupsData.canUpdate; + this.canDelete = bookGroupsData.canDelete; + } +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/AppDatabaseType.ets b/entry/src/main/ets/database/types/AppDatabaseType.ets new file mode 100644 index 00000000..b5190441 --- /dev/null +++ b/entry/src/main/ets/database/types/AppDatabaseType.ets @@ -0,0 +1,53 @@ +import { ColumnKeys } from './ColumnInfo' + +export interface FieldsType { + fieldPath: string + columnName: string + affinity: ColumnKeys + boolean?: boolean, + notNull: boolean + defaultValue?: string +} + +export interface PrimaryKeyType { + autoGenerate: boolean + columnNames: string[] +} + +export interface IndicesType { + name: string + unique: boolean + columnNames: string[] + orders: string[] + createSql: string +} + +export interface ForeignKeysType { + table: string + onDelete: string + onUpdate: string + columns: string[] + referencedColumns: string[] +} + +export interface EntitiesType { + tableName: string + createSql: string + fields: FieldsType[] + primaryKey: PrimaryKeyType + indices: IndicesType[] + foreignKeys: ForeignKeysType[] +} + +export interface DatabaseType { + version: number + identityHash: string + entities: EntitiesType[] + views: string[] + setupQueries: string[] +} + +export interface AppDataBaseType { + formatVersion: number + database: DatabaseType +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/BookGroupType.ets b/entry/src/main/ets/database/types/BookGroupType.ets new file mode 100644 index 00000000..81676bd2 --- /dev/null +++ b/entry/src/main/ets/database/types/BookGroupType.ets @@ -0,0 +1,10 @@ +/** + * @author 2008 + * @datetime 2024/7/24 22:03 + * @className: BookGroupType + */ +export interface BookGroupTypeParams { + //类型 0 小说;1 漫画;2 有声书; + type?: number, + show?: boolean +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/BookHistoryType.ets b/entry/src/main/ets/database/types/BookHistoryType.ets new file mode 100644 index 00000000..c3eced72 --- /dev/null +++ b/entry/src/main/ets/database/types/BookHistoryType.ets @@ -0,0 +1,11 @@ +/** + * @author 2008 + * @datetime 2024/7/24 22:03 + * @className: BookGroupType + */ +export interface BookHistoryTypeParams { + //类型 0 小说;1 漫画;2 有声书; + type?: number, + //排序 + sort?: number +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/BookSourceType.ets b/entry/src/main/ets/database/types/BookSourceType.ets new file mode 100644 index 00000000..e2517299 --- /dev/null +++ b/entry/src/main/ets/database/types/BookSourceType.ets @@ -0,0 +1,45 @@ +export interface BookSourceSearchParams { + // 搜索关键词 + searchKey?: string, + // 源类型 0 小说;1 漫画;2 有声书; + type?: number, + // 是否启用 + enabled?: boolean, + // 排序 0 按评分排序 1 按时间排序 + order?: number, + // 等级 + bookSourceGrade?: number, + // TODO 校验,还未实现 + verify?: number, + // 是否存在登录 + hasLoginUrl?: boolean, + // 是否存在发现 + hasExploreUrl?: boolean + // 是否显示的发现 + showExplore?: boolean +} + +export interface ExploreQuery { + url: string, + pageSize: number, + bookList?: string + name?: string + author?: string + intro?: string + kind?: string + lastChapter?: string + bookUrl?: string + coverUrl?: string + wordCount?: string +} + +export interface ExploreItemStyle { + layout_flexGrow?: number; + layout_flexBasisPercent?: number; +} + +export interface ExploreItem { + title: string, + url: string, + style?: ExploreItemStyle +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/BooksType.ets b/entry/src/main/ets/database/types/BooksType.ets new file mode 100644 index 00000000..a7314006 --- /dev/null +++ b/entry/src/main/ets/database/types/BooksType.ets @@ -0,0 +1,15 @@ +/** + * @author 2008 + * @datetime 2024/7/23 11:02 + * @className: BooksType + */ +export interface BooksTypeSearchParams { + // 搜索关键词书源名称/书籍名称/author + searchKey?: string, + // 源类型 0 小说;1 漫画;2 有声书; + type?: number, + //分组 + bookGroup?: number, + //排序方式 + order?: string +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/ColumnInfo.ets b/entry/src/main/ets/database/types/ColumnInfo.ets new file mode 100644 index 00000000..f5e3081f --- /dev/null +++ b/entry/src/main/ets/database/types/ColumnInfo.ets @@ -0,0 +1,31 @@ +/** + * Copyright (C), 2024-06-22 + * @author LinXun + * @date 2024-06-22 10:08 + * @version 1.0 + * @description: 数据库列接口 + */ +export interface ColumnInfo{ + // 实体属性名 + name: string + // 数据库列名 + columnName: string + // 列类型 + type: ColumnType + defaultValue?: string | number +} +// 数据类型 +export enum ColumnType{ + LONG, + DOUBLE, + STRING, + BLOB, + BOOLEAN +} + +export type ColumnKeys = 'INTEGER' | 'TEXT' + +export const ColumnValue: Record = { + 'INTEGER': ColumnType.LONG, + 'TEXT': ColumnType.STRING +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/WorksListsType.ets b/entry/src/main/ets/database/types/WorksListsType.ets new file mode 100644 index 00000000..0e155510 --- /dev/null +++ b/entry/src/main/ets/database/types/WorksListsType.ets @@ -0,0 +1,11 @@ +/** + * @author 2008 + * @datetime 2024/8/1 11:02 + * @className: WorkListsType + */ +export interface WorksListsTypeSearchParams { + // 搜索关键词 + searchKey?: string, + // 源类型 0 小说;1 漫画;2 有声书; + type?: number +} \ No newline at end of file diff --git a/entry/src/main/ets/database/types/rssSourcesType.ets b/entry/src/main/ets/database/types/rssSourcesType.ets new file mode 100644 index 00000000..bb930062 --- /dev/null +++ b/entry/src/main/ets/database/types/rssSourcesType.ets @@ -0,0 +1,11 @@ +/** + * @author 2008 + * @datetime 2024/7/15 16:38 + * @className: rssSourcesType + */ +export interface rssSourcesTypeParams { + // 搜索关键词 + searchKey?: string, + // 是否启用 + enabled?: boolean +} \ No newline at end of file