141 lines
5.1 KiB
TypeScript
141 lines
5.1 KiB
TypeScript
import { DatabaseInterface, UploadTask } from './types';
|
||
|
||
// Web 环境下的 SQLite 数据库实现(实际使用 localStorage)
|
||
export class SQLiteDatabase implements DatabaseInterface {
|
||
private getStorageKey(table: string): string {
|
||
return `memowake_${table}`;
|
||
}
|
||
|
||
private getUploadTasksFromStorage(): UploadTask[] {
|
||
const data = localStorage.getItem(this.getStorageKey('upload_tasks'));
|
||
return data ? JSON.parse(data) : [];
|
||
}
|
||
|
||
private saveUploadTasks(tasks: UploadTask[]): void {
|
||
localStorage.setItem(this.getStorageKey('upload_tasks'), JSON.stringify(tasks));
|
||
}
|
||
|
||
private getAppStateData(): Record<string, string> {
|
||
const data = localStorage.getItem(this.getStorageKey('app_state'));
|
||
return data ? JSON.parse(data) : {};
|
||
}
|
||
|
||
private saveAppStateData(state: Record<string, string>): void {
|
||
localStorage.setItem(this.getStorageKey('app_state'), JSON.stringify(state));
|
||
}
|
||
|
||
async initUploadTable(): Promise<void> {
|
||
console.log('Initializing web storage tables (SQLite fallback)...');
|
||
// Web端不需要初始化表结构,localStorage会自动处理
|
||
}
|
||
|
||
async insertUploadTask(task: Omit<UploadTask, 'created_at'>): Promise<void> {
|
||
console.log('Inserting upload task:', task.uri);
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
const existingIndex = tasks.findIndex(t => t.uri === task.uri);
|
||
const newTask: UploadTask = {
|
||
...task,
|
||
created_at: Math.floor(Date.now() / 1000)
|
||
};
|
||
|
||
if (existingIndex >= 0) {
|
||
tasks[existingIndex] = newTask;
|
||
} else {
|
||
tasks.push(newTask);
|
||
}
|
||
|
||
this.saveUploadTasks(tasks);
|
||
}
|
||
|
||
async getUploadTaskStatus(uri: string): Promise<UploadTask | null> {
|
||
console.log('Checking upload task status for:', uri);
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
return tasks.find(t => t.uri === uri) || null;
|
||
}
|
||
|
||
async updateUploadTaskStatus(uri: string, status: UploadTask['status'], file_id?: string): Promise<void> {
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
const taskIndex = tasks.findIndex(t => t.uri === uri);
|
||
if (taskIndex >= 0) {
|
||
tasks[taskIndex].status = status;
|
||
if (file_id) {
|
||
tasks[taskIndex].file_id = file_id;
|
||
}
|
||
this.saveUploadTasks(tasks);
|
||
}
|
||
}
|
||
|
||
async updateUploadTaskProgress(uri: string, progress: number): Promise<void> {
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
const taskIndex = tasks.findIndex(t => t.uri === uri);
|
||
if (taskIndex >= 0) {
|
||
tasks[taskIndex].progress = progress;
|
||
this.saveUploadTasks(tasks);
|
||
}
|
||
}
|
||
|
||
async getUploadTasks(): Promise<UploadTask[]> {
|
||
console.log('Fetching all upload tasks... time:', new Date().toLocaleString());
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
return tasks.sort((a, b) => b.created_at - a.created_at);
|
||
}
|
||
|
||
async cleanUpUploadTasks(): Promise<void> {
|
||
console.log('Cleaning up completed/failed upload tasks...');
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
const filteredTasks = tasks.filter(t =>
|
||
t.status !== 'success' && t.status !== 'failed' && t.status !== 'skipped'
|
||
);
|
||
this.saveUploadTasks(filteredTasks);
|
||
}
|
||
|
||
async getUploadTasksSince(timestamp: number): Promise<UploadTask[]> {
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
const filteredTasks = tasks.filter(t => t.created_at >= timestamp);
|
||
return filteredTasks.sort((a, b) => b.created_at - a.created_at);
|
||
}
|
||
|
||
async exist_pending_tasks(): Promise<boolean> {
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
return tasks.some(t => t.status === 'pending' || t.status === 'uploading');
|
||
}
|
||
|
||
async filterExistingFiles(fileUris: string[]): Promise<string[]> {
|
||
if (fileUris.length === 0) {
|
||
return [];
|
||
}
|
||
|
||
const tasks = this.getUploadTasksFromStorage();
|
||
const successfulUris = new Set(
|
||
tasks.filter(t => t.status === 'success').map(t => t.uri)
|
||
);
|
||
|
||
const newFileUris = fileUris.filter(uri => !successfulUris.has(uri));
|
||
|
||
console.log(`[WebDB] Total files: ${fileUris.length}, Existing successful files: ${successfulUris.size}, New files to upload: ${newFileUris.length}`);
|
||
|
||
return newFileUris;
|
||
}
|
||
|
||
async setAppState(key: string, value: string | null): Promise<void> {
|
||
console.log(`Setting app state: ${key} = ${value}`);
|
||
const state = this.getAppStateData();
|
||
if (value === null) {
|
||
delete state[key];
|
||
} else {
|
||
state[key] = value;
|
||
}
|
||
this.saveAppStateData(state);
|
||
}
|
||
|
||
async getAppState(key: string): Promise<string | null> {
|
||
const state = this.getAppStateData();
|
||
return state[key] || null;
|
||
}
|
||
|
||
async executeSql(sql: string, params: any[] = []): Promise<any> {
|
||
console.warn('SQL execution not supported in web environment:', sql);
|
||
return { error: 'SQL execution not supported in web environment' };
|
||
}
|
||
}
|