You've already forked Nano-Banana-AI-Image-Editor
208 lines
6.1 KiB
TypeScript
208 lines
6.1 KiB
TypeScript
import { Generation, Edit } from '../types';
|
|
|
|
// 数据库配置
|
|
const DB_NAME = 'NanoBananaDB';
|
|
const DB_VERSION = 1;
|
|
const GENERATIONS_STORE = 'generations';
|
|
const EDITS_STORE = 'edits';
|
|
|
|
// IndexedDB实例
|
|
let db: IDBDatabase | null = null;
|
|
|
|
/**
|
|
* 初始化数据库
|
|
*/
|
|
export const initDB = (): Promise<void> => {
|
|
return new Promise((resolve, reject) => {
|
|
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
|
|
request.onerror = () => {
|
|
console.error('数据库打开失败:', request.error);
|
|
reject(request.error);
|
|
};
|
|
|
|
request.onsuccess = () => {
|
|
db = request.result;
|
|
resolve();
|
|
};
|
|
|
|
request.onupgradeneeded = (event) => {
|
|
const db = (event.target as IDBOpenDBRequest).result;
|
|
|
|
// 创建生成记录存储
|
|
if (!db.objectStoreNames.contains(GENERATIONS_STORE)) {
|
|
const genStore = db.createObjectStore(GENERATIONS_STORE, { keyPath: 'id' });
|
|
genStore.createIndex('timestamp', 'timestamp', { unique: false });
|
|
}
|
|
|
|
// 创建编辑记录存储
|
|
if (!db.objectStoreNames.contains(EDITS_STORE)) {
|
|
const editStore = db.createObjectStore(EDITS_STORE, { keyPath: 'id' });
|
|
editStore.createIndex('timestamp', 'timestamp', { unique: false });
|
|
editStore.createIndex('parentGenerationId', 'parentGenerationId', { unique: false });
|
|
}
|
|
};
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 获取数据库实例
|
|
*/
|
|
const getDB = (): IDBDatabase => {
|
|
if (!db) {
|
|
throw new Error('数据库未初始化');
|
|
}
|
|
return db;
|
|
};
|
|
|
|
/**
|
|
* 添加生成记录
|
|
*/
|
|
export const addGeneration = async (generation: Generation): Promise<void> => {
|
|
const db = getDB();
|
|
const transaction = db.transaction([GENERATIONS_STORE], 'readwrite');
|
|
const store = transaction.objectStore(GENERATIONS_STORE);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const request = store.add(generation);
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 添加编辑记录
|
|
*/
|
|
export const addEdit = async (edit: Edit): Promise<void> => {
|
|
const db = getDB();
|
|
const transaction = db.transaction([EDITS_STORE], 'readwrite');
|
|
const store = transaction.objectStore(EDITS_STORE);
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const request = store.add(edit);
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 获取所有生成记录(按时间倒序)
|
|
*/
|
|
export const getAllGenerations = async (): Promise<Generation[]> => {
|
|
const db = getDB();
|
|
const transaction = db.transaction([GENERATIONS_STORE], 'readonly');
|
|
const store = transaction.objectStore(GENERATIONS_STORE);
|
|
const index = store.index('timestamp');
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const request = index.getAll();
|
|
request.onsuccess = () => {
|
|
// 按时间倒序排列
|
|
const generations = request.result.sort((a, b) => b.timestamp - a.timestamp);
|
|
resolve(generations);
|
|
};
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 获取所有编辑记录(按时间倒序)
|
|
*/
|
|
export const getAllEdits = async (): Promise<Edit[]> => {
|
|
const db = getDB();
|
|
const transaction = db.transaction([EDITS_STORE], 'readonly');
|
|
const store = transaction.objectStore(EDITS_STORE);
|
|
const index = store.index('timestamp');
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const request = index.getAll();
|
|
request.onsuccess = () => {
|
|
// 按时间倒序排列
|
|
const edits = request.result.sort((a, b) => b.timestamp - a.timestamp);
|
|
resolve(edits);
|
|
};
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 根据父生成ID获取编辑记录
|
|
*/
|
|
export const getEditsByParentGenerationId = async (parentGenerationId: string): Promise<Edit[]> => {
|
|
const db = getDB();
|
|
const transaction = db.transaction([EDITS_STORE], 'readonly');
|
|
const store = transaction.objectStore(EDITS_STORE);
|
|
const index = store.index('parentGenerationId');
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const request = index.getAll(IDBKeyRange.only(parentGenerationId));
|
|
request.onsuccess = () => {
|
|
// 按时间倒序排列
|
|
const edits = request.result.sort((a, b) => b.timestamp - a.timestamp);
|
|
resolve(edits);
|
|
};
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 删除最旧的记录以保持限制
|
|
*/
|
|
export const cleanupOldRecords = async (limit: number = 1000): Promise<void> => {
|
|
const db = getDB();
|
|
|
|
// 清理生成记录
|
|
const genTransaction = db.transaction([GENERATIONS_STORE], 'readwrite');
|
|
const genStore = genTransaction.objectStore(GENERATIONS_STORE);
|
|
const genIndex = genStore.index('timestamp');
|
|
|
|
// 清理编辑记录
|
|
const editTransaction = db.transaction([EDITS_STORE], 'readwrite');
|
|
const editStore = editTransaction.objectStore(EDITS_STORE);
|
|
const editIndex = editStore.index('timestamp');
|
|
|
|
// 获取所有记录并按时间排序
|
|
const allGenerations = await getAllGenerations();
|
|
const allEdits = await getAllEdits();
|
|
|
|
// 计算需要删除的记录数量
|
|
if (allGenerations.length > limit) {
|
|
const toDelete = allGenerations.slice(limit);
|
|
for (const gen of toDelete) {
|
|
genStore.delete(gen.id);
|
|
}
|
|
}
|
|
|
|
if (allEdits.length > limit) {
|
|
const toDelete = allEdits.slice(limit);
|
|
for (const edit of toDelete) {
|
|
editStore.delete(edit.id);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 清空所有记录
|
|
*/
|
|
export const clearAllRecords = async (): Promise<void> => {
|
|
const db = getDB();
|
|
|
|
const genTransaction = db.transaction([GENERATIONS_STORE], 'readwrite');
|
|
const genStore = genTransaction.objectStore(GENERATIONS_STORE);
|
|
|
|
const editTransaction = db.transaction([EDITS_STORE], 'readwrite');
|
|
const editStore = editTransaction.objectStore(EDITS_STORE);
|
|
|
|
return Promise.all([
|
|
new Promise<void>((resolve, reject) => {
|
|
const request = genStore.clear();
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error);
|
|
}),
|
|
new Promise<void>((resolve, reject) => {
|
|
const request = editStore.clear();
|
|
request.onsuccess = () => resolve();
|
|
request.onerror = () => reject(request.error);
|
|
})
|
|
]).then(() => undefined);
|
|
}; |