mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
fix: 多个页面共享同一 indexedDB 库导致异常(#111)
This commit is contained in:
parent
f19ca86283
commit
7b07629a58
13
src/App.vue
13
src/App.vue
@ -8,6 +8,7 @@
|
||||
import { defineComponent, onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useScreenStore, useMainStore, useSnapshotStore } from '@/store'
|
||||
import { LOCALSTORAGE_KEY_DISCARDED_DB } from '@/configs/storage'
|
||||
import { isPC } from './utils/common'
|
||||
|
||||
import Editor from './views/Editor/index.vue'
|
||||
@ -24,6 +25,7 @@ export default defineComponent({
|
||||
setup() {
|
||||
const mainStore = useMainStore()
|
||||
const snapshotStore = useSnapshotStore()
|
||||
const { databaseId } = storeToRefs(mainStore)
|
||||
const { screening } = storeToRefs(useScreenStore())
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
@ -35,6 +37,17 @@ export default defineComponent({
|
||||
mainStore.setAvailableFonts()
|
||||
})
|
||||
|
||||
// 应用注销时向 localStorage 中记录下本次 indexedDB 的数据库ID,用于之后清除数据库
|
||||
window.addEventListener('unload', () => {
|
||||
const discardedDB = localStorage.getItem(LOCALSTORAGE_KEY_DISCARDED_DB)
|
||||
const discardedDBList: string[] = discardedDB ? JSON.parse(discardedDB) : []
|
||||
|
||||
discardedDBList.push(databaseId.value)
|
||||
|
||||
const newDiscardedDB = JSON.stringify(discardedDBList)
|
||||
localStorage.setItem(LOCALSTORAGE_KEY_DISCARDED_DB, newDiscardedDB)
|
||||
})
|
||||
|
||||
return {
|
||||
screening,
|
||||
isPC: isPC(),
|
||||
|
1
src/configs/storage.ts
Normal file
1
src/configs/storage.ts
Normal file
@ -0,0 +1 @@
|
||||
export const LOCALSTORAGE_KEY_DISCARDED_DB = 'PPTIST_DISCARDED_DB'
|
@ -1,3 +1,4 @@
|
||||
import { customAlphabet } from 'nanoid'
|
||||
import { defineStore } from 'pinia'
|
||||
import { CreatingElement } from '@/types/edit'
|
||||
import { ToolbarStates } from '@/types/toolbar'
|
||||
@ -8,8 +9,6 @@ import { isSupportFont } from '@/utils/font'
|
||||
|
||||
import { useSlidesStore } from './slides'
|
||||
|
||||
|
||||
|
||||
export interface MainState {
|
||||
activeElementIdList: string[];
|
||||
handleElementId: string;
|
||||
@ -31,8 +30,12 @@ export interface MainState {
|
||||
selectedTableCells: string[];
|
||||
selectedSlidesIndex: number[];
|
||||
dialogForExport: DialogForExportTypes;
|
||||
databaseId: string;
|
||||
}
|
||||
|
||||
const nanoid = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')
|
||||
export const databaseId = nanoid(10)
|
||||
|
||||
export const useMainStore = defineStore('main', {
|
||||
state: (): MainState => ({
|
||||
activeElementIdList: [], // 被选中的元素ID集合,包含 handleElementId
|
||||
@ -55,6 +58,7 @@ export const useMainStore = defineStore('main', {
|
||||
isScaling: false, // 正在进行元素缩放
|
||||
selectedSlidesIndex: [], // 当前被选中的页面索引集合
|
||||
dialogForExport: '', // 导出面板
|
||||
databaseId, // 标识当前应用的indexedDB数据库ID
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { IndexableTypeArray } from 'dexie'
|
||||
import { snapshotDB, Snapshot } from '@/utils/database'
|
||||
import { db, deleteDiscardedDB, Snapshot } from '@/utils/database'
|
||||
|
||||
import { useSlidesStore } from './slides'
|
||||
import { useMainStore } from './main'
|
||||
@ -36,18 +36,13 @@ export const useSnapshotStore = defineStore('snapshot', {
|
||||
async initSnapshotDatabase() {
|
||||
const slidesStore = useSlidesStore()
|
||||
|
||||
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
|
||||
const lastSnapshot = snapshots.slice(-1)[0]
|
||||
|
||||
if (lastSnapshot) {
|
||||
snapshotDB.snapshots.clear()
|
||||
}
|
||||
await deleteDiscardedDB()
|
||||
|
||||
const newFirstSnapshot = {
|
||||
index: slidesStore.slideIndex,
|
||||
slides: slidesStore.slides,
|
||||
}
|
||||
await snapshotDB.snapshots.add(newFirstSnapshot)
|
||||
await db.snapshots.add(newFirstSnapshot)
|
||||
this.setSnapshotCursor(0)
|
||||
this.setSnapshotLength(1)
|
||||
},
|
||||
@ -56,7 +51,7 @@ export const useSnapshotStore = defineStore('snapshot', {
|
||||
const slidesStore = useSlidesStore()
|
||||
|
||||
// 获取当前indexeddb中全部快照的ID
|
||||
const allKeys = await snapshotDB.snapshots.orderBy('id').keys()
|
||||
const allKeys = await db.snapshots.orderBy('id').keys()
|
||||
|
||||
let needDeleteKeys: IndexableTypeArray = []
|
||||
|
||||
@ -72,7 +67,7 @@ export const useSnapshotStore = defineStore('snapshot', {
|
||||
index: slidesStore.slideIndex,
|
||||
slides: slidesStore.slides,
|
||||
}
|
||||
await snapshotDB.snapshots.add(snapshot)
|
||||
await db.snapshots.add(snapshot)
|
||||
|
||||
// 计算当前快照长度,用于设置快照指针的位置(此时指针应该处在最后一位,即:快照长度 - 1)
|
||||
let snapshotLength = allKeys.length - needDeleteKeys.length + 1
|
||||
@ -87,10 +82,10 @@ export const useSnapshotStore = defineStore('snapshot', {
|
||||
// 快照数大于1时,需要保证撤回操作后维持页面焦点不变:也就是将倒数第二个快照对应的索引设置为当前页的索引
|
||||
// https://github.com/pipipi-pikachu/PPTist/issues/27
|
||||
if (snapshotLength >= 2) {
|
||||
snapshotDB.snapshots.update(allKeys[snapshotLength - 2] as number, { index: slidesStore.slideIndex })
|
||||
db.snapshots.update(allKeys[snapshotLength - 2] as number, { index: slidesStore.slideIndex })
|
||||
}
|
||||
|
||||
await snapshotDB.snapshots.bulkDelete(needDeleteKeys)
|
||||
await db.snapshots.bulkDelete(needDeleteKeys)
|
||||
|
||||
this.setSnapshotCursor(snapshotLength - 1)
|
||||
this.setSnapshotLength(snapshotLength)
|
||||
@ -103,7 +98,7 @@ export const useSnapshotStore = defineStore('snapshot', {
|
||||
const mainStore = useMainStore()
|
||||
|
||||
const snapshotCursor = this.snapshotCursor - 1
|
||||
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
|
||||
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
||||
const snapshot = snapshots[snapshotCursor]
|
||||
const { index, slides } = snapshot
|
||||
|
||||
@ -122,7 +117,7 @@ export const useSnapshotStore = defineStore('snapshot', {
|
||||
const mainStore = useMainStore()
|
||||
|
||||
const snapshotCursor = this.snapshotCursor + 1
|
||||
const snapshots: Snapshot[] = await snapshotDB.snapshots.orderBy('id').toArray()
|
||||
const snapshots: Snapshot[] = await db.snapshots.orderBy('id').toArray()
|
||||
const snapshot = snapshots[snapshotCursor]
|
||||
const { index, slides } = snapshot
|
||||
|
||||
|
@ -1,16 +1,46 @@
|
||||
import Dexie from 'dexie'
|
||||
import { databaseId } from '@/store/main'
|
||||
import { Slide } from '@/types/slides'
|
||||
import { LOCALSTORAGE_KEY_DISCARDED_DB } from '@/configs/storage'
|
||||
|
||||
export interface Snapshot {
|
||||
index: number;
|
||||
slides: Slide[];
|
||||
}
|
||||
|
||||
class SnapshotDatabase extends Dexie {
|
||||
const databaseNamePrefix = 'PPTist'
|
||||
|
||||
// 删除失效/过期的数据库
|
||||
// 应用关闭时(关闭或刷新浏览器),会将其数据库ID记录在 localStorage 中,表示该ID指向的数据库已失效
|
||||
// 当应用初始化时,检查当前所有数据库,将被记录失效的数据库删除
|
||||
// 另外,距离初始化时间超过12小时的数据库也将被删除(这是为了防止出现因以外未被正确删除的库)
|
||||
export const deleteDiscardedDB = async () => {
|
||||
const now = new Date().getTime()
|
||||
|
||||
const localStorageDiscardedDB = localStorage.getItem(LOCALSTORAGE_KEY_DISCARDED_DB)
|
||||
const localStorageDiscardedDBList: string[] = localStorageDiscardedDB ? JSON.parse(localStorageDiscardedDB) : []
|
||||
|
||||
const databaseNames = await Dexie.getDatabaseNames()
|
||||
const discardedDBNames = databaseNames.filter(name => {
|
||||
if (name.indexOf(databaseNamePrefix) === -1) return false
|
||||
|
||||
const [prefix, id, time] = name.split('_')
|
||||
if (prefix !== databaseNamePrefix || !id || !time) return true
|
||||
if (localStorageDiscardedDBList.includes(id)) return true
|
||||
if (now - (+time) >= 1000 * 60 * 60 * 12) return true
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
for (const name of discardedDBNames) Dexie.delete(name)
|
||||
localStorage.removeItem(LOCALSTORAGE_KEY_DISCARDED_DB)
|
||||
}
|
||||
|
||||
class PPTistDB extends Dexie {
|
||||
public snapshots: Dexie.Table<Snapshot, number>
|
||||
|
||||
public constructor() {
|
||||
super('SnapshotDatabase')
|
||||
super(`${databaseNamePrefix}_${databaseId}_${new Date().getTime()}`)
|
||||
this.version(1).stores({
|
||||
snapshots: '++id'
|
||||
})
|
||||
@ -18,4 +48,4 @@ class SnapshotDatabase extends Dexie {
|
||||
}
|
||||
}
|
||||
|
||||
export const snapshotDB = new SnapshotDatabase()
|
||||
export const db = new PPTistDB()
|
Loading…
x
Reference in New Issue
Block a user