diff --git a/src/pages/User/GachaB.vue b/src/pages/User/GachaB.vue index f1a9532d..55a923b6 100644 --- a/src/pages/User/GachaB.vue +++ b/src/pages/User/GachaB.vue @@ -315,14 +315,17 @@ async function deleteGacha(): Promise { } } await showLoading.start("正在删除祈愿数据", `UID:${uidCur.value}`); + const label = `已成功删除 ${uidCur.value} 的颂愿数据,即将刷新页面`; await TSUserGachaB.deleteRecords(uidCur.value); await TGLogger.Info( `[UserGachaB][${uidCur.value}][deleteGacha] 成功删除 ${gachaListCur.value.length} 条祈愿数据`, ); - showSnackbar.success(`已成功删除 ${uidCur.value} 的祈愿数据,即将刷新页面`); await reloadUid(); await loadGachaBList(); await showLoading.end(); + showSnackbar.success(label); + await new Promise((resolve) => setTimeout(resolve, 1500)); + window.location.reload(); } async function importUigf(): Promise { diff --git a/src/plugins/Sqlite/modules/userGacha.ts b/src/plugins/Sqlite/modules/userGacha.ts index d0e5993f..d2fba979 100644 --- a/src/plugins/Sqlite/modules/userGacha.ts +++ b/src/plugins/Sqlite/modules/userGacha.ts @@ -8,7 +8,7 @@ import showLoading from "@comp/func/loading.js"; import showSnackbar from "@comp/func/snackbar.js"; import Database from "@tauri-apps/plugin-sql"; import { getUtc8Time, getWikiBrief, timestampToDate } from "@utils/toolFunc.js"; -import { ref, Ref } from "vue"; +import { ref, type Ref } from "vue"; import TGSqlite from "../index.js"; diff --git a/src/plugins/Sqlite/modules/userGachaB.ts b/src/plugins/Sqlite/modules/userGachaB.ts index af72ff70..f8f79b97 100644 --- a/src/plugins/Sqlite/modules/userGachaB.ts +++ b/src/plugins/Sqlite/modules/userGachaB.ts @@ -1,57 +1,99 @@ /** * 千星奇域祈愿模块 - * @since Beta v0.9.5 + * @since Beta v0.9.8 */ +import showDialog from "@comp/func/dialog.js"; import showLoading from "@comp/func/loading.js"; import TGSqlite from "@Sql/index.js"; +import Database from "@tauri-apps/plugin-sql"; import { getUtc8Time, timestampToDate } from "@utils/toolFunc.js"; +import { ref, type Ref } from "vue"; import { AppGachaBData } from "@/data/index.js"; /** - * 插入颂愿数据 - * @since Beta v0.9.5 - * @param uid - UID - * @param item - 颂愿数据 - * @returns 无返回值 + * 批量插入颂愿数据 + * @since Beta v0.9.8 + * @param db - 数据库 + * @param uid - 用户UID + * @param data - 祈愿数据 + * @param size - batchSize + * @param cnt - cntRef */ -async function insertGachaItem(uid: string, item: TGApp.Plugins.UIGF.GachaItemB): Promise { - const db = await TGSqlite.getDB(); - const gachaType = item.op_gacha_type === "1000" ? "1000" : "2000"; - const updateTime = timestampToDate(Date.now()); - await db.execute( - ` - INSERT INTO GachaBRecords(id, uid, scheduleId, gachaType, opGachaType, time, - itemId, name, type, rank, updated) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) - ON CONFLICT (id) - DO UPDATE - SET uid = $2, - scheduleId = $3, - gachaType = $4, - opGachaType = $5, - time = $6, - itemId = $7, - name = $8, - type = $9, - rank = $10, - updated = $11; - `, - [ - item.id, - uid, - item.schedule_id, - gachaType, - item.op_gacha_type, - item.time, - item.item_id, - item.item_name, - item.item_type, - item.rank_type, - updateTime, - ], - ); +async function insertGachaBList( + db: Database, + uid: string, + data: Array, + size: number, + cnt?: Ref, +): Promise { + await db.execute("PRAGMA busy_timeout = 5000;"); + for (let i = 0; i < data.length; i += size) { + await db.execute("BEGIN IMMEDIATE;"); + try { + const batch = data.slice(i, i + size); + let batchSql = ""; + const batchParams = []; + for (const item of batch) { + const updateTime = timestampToDate(Date.now()); + const gachaType = item.op_gacha_type === "1000" ? "1000" : "2000"; + batchSql += ` + INSERT INTO GachaBRecords(id, uid, scheduleId, gachaType, opGachaType, time, + itemId, name, type, rank, updated) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(id) + DO UPDATE + SET uid=?, + scheduleId=?, + gachaType=?, + opGachaType=?, + time=?, + itemId=?, + name=?, + type=?, + rank=?, + updated=?; + `; + batchParams.push( + item.id, + uid, + item.schedule_id, + gachaType, + item.op_gacha_type, + item.time, + item.item_id, + item.item_name, + item.item_type, + item.rank_type, + updateTime, + // update 部分 + uid, + item.schedule_id, + gachaType, + item.op_gacha_type, + item.time, + item.item_id, + item.item_name, + item.item_type, + item.rank_type, + updateTime, + ); + if (cnt) cnt.value++; + } + await db.execute(batchSql, batchParams); + await db.execute("COMMIT;"); + } catch (e) { + const msg = String(e); + if (/BUSY|LOCKED|SQLITE_BUSY|SQLITE_LOCKED/i.test(msg)) { + await showDialog.check(`数据库锁定`, `请刷新页面(F5)后重试操作`); + return; + } + // 其他错误直接抛出 + await db.execute("ROLLBACK;"); + throw e; + } + } } /** @@ -66,20 +108,7 @@ async function insertGachaList( list: Array, ): Promise { const db = await TGSqlite.getDB(); - const BATCH_SIZE = 500; - for (let i = 0; i < list.length; i += BATCH_SIZE) { - const batch = list.slice(i, i + BATCH_SIZE); - await db.execute("BEGIN TRANSACTION;"); - try { - for (const gacha of batch) { - await insertGachaItem(uid, gacha); - } - await db.execute("COMMIT;"); - } catch (e) { - await db.execute("ROLLBACK;"); - throw e; - } - } + await insertGachaBList(db, uid, list, 100); } /** @@ -120,35 +149,21 @@ async function mergeUIGF4( ): Promise { const db = await TGSqlite.getDB(); const len = data.list.length; - let cnt: number = 0; + const cnt = ref(0); let timer: NodeJS.Timeout | null = null; if (showProgress) { timer = setInterval(async () => { - const progress = Math.round((cnt / len) * 100 * 100) / 100; - const current = data.list[cnt].time ?? ""; - const name = data.list[cnt].item_name ?? ""; - const rank = data.list[cnt].rank_type ?? "0"; + const progress = Math.round((cnt.value / len) * 100 * 100) / 100; + const current = data.list[cnt.value].time ?? ""; + const name = data.list[cnt.value].item_name ?? ""; + const rank = data.list[cnt.value].rank_type ?? "0"; await showLoading.update(`[${progress}%][${current}] ${"⭐".repeat(Number(rank))}-${name}`, { timeout: 0, }); }, 1000); } - const uid = data.uid.toString(); - const BATCH_SIZE = 500; - for (let i = 0; i < data.list.length; i += BATCH_SIZE) { - const batch = data.list.slice(i, i + BATCH_SIZE); - await db.execute("BEGIN TRANSACTION;"); - try { - for (const gacha of batch) { - await insertGachaItem(uid, transGacha(gacha, data.timezone)); - cnt++; - } - await db.execute("COMMIT;"); - } catch (e) { - await db.execute("ROLLBACK;"); - throw e; - } - } + const transformed = data.list.map((g) => transGacha(g)); + await insertGachaBList(db, data.uid.toString(), transformed, 100, cnt); if (timer) { clearInterval(timer); await showLoading.update(`[100%] 完成`, { timeout: 0 });