232 lines
6.3 KiB
TypeScript
232 lines
6.3 KiB
TypeScript
import { markDB, initMarkDB } from './db';
|
||
import { Mark } from './mark';
|
||
|
||
// Mark 服务类 - 提供业务逻辑层
|
||
export class MarkService {
|
||
private db = markDB;
|
||
|
||
// 初始化服务
|
||
async init() {
|
||
await initMarkDB();
|
||
}
|
||
|
||
// 创建新的 Mark
|
||
async createMark(markData: Omit<Mark, 'id' | 'createdAt' | 'updatedAt'>): Promise<Mark> {
|
||
return await this.db.create(markData);
|
||
}
|
||
|
||
// 根据 ID 获取 Mark
|
||
async getMark(id: string): Promise<Mark | null> {
|
||
return await this.db.getById(id);
|
||
}
|
||
|
||
// 获取所有 Marks
|
||
async getAllMarks(): Promise<Mark[]> {
|
||
return await this.db.getAll();
|
||
}
|
||
|
||
// 按用户获取 Marks
|
||
async getMarksByUser(userId: string): Promise<Mark[]> {
|
||
return await this.db.getByUserId(userId);
|
||
}
|
||
|
||
// 按类型获取 Marks
|
||
async getMarksByType(markType: string): Promise<Mark[]> {
|
||
return await this.db.getByType(markType as any);
|
||
}
|
||
|
||
// 按标签搜索 Marks
|
||
async getMarksByTag(tag: string): Promise<Mark[]> {
|
||
return await this.db.getByTag(tag);
|
||
}
|
||
|
||
// 搜索 Marks
|
||
async searchMarks(query: string): Promise<Mark[]> {
|
||
return await this.db.search(query);
|
||
}
|
||
|
||
// 更新 Mark
|
||
async updateMark(id: string, updates: Partial<Omit<Mark, 'id' | 'createdAt'>>): Promise<Mark> {
|
||
return await this.db.update(id, updates);
|
||
}
|
||
|
||
// 删除 Mark
|
||
async deleteMark(id: string): Promise<boolean> {
|
||
return await this.db.delete(id);
|
||
}
|
||
|
||
// 批量删除 Marks
|
||
async deleteMultipleMarks(ids: string[]): Promise<boolean> {
|
||
return await this.db.deleteMultiple(ids);
|
||
}
|
||
|
||
// 分页获取 Marks
|
||
async getMarksPaginated(
|
||
page: number = 1,
|
||
limit: number = 10,
|
||
filters?: {
|
||
uid?: string;
|
||
markType?: string;
|
||
tags?: string[];
|
||
}
|
||
) {
|
||
return await this.db.getPaginated(page, limit, filters);
|
||
}
|
||
|
||
// 获取统计信息
|
||
async getStats() {
|
||
return await this.db.getStats();
|
||
}
|
||
|
||
// 导出数据
|
||
async exportData(): Promise<Mark[]> {
|
||
return await this.getAllMarks();
|
||
}
|
||
|
||
// 导入数据
|
||
async importData(marks: Mark[]): Promise<number> {
|
||
let importedCount = 0;
|
||
try {
|
||
for (const mark of marks) {
|
||
const { id, createdAt, updatedAt, ...markData } = mark;
|
||
await this.createMark(markData);
|
||
importedCount++;
|
||
}
|
||
} catch (error) {
|
||
console.error('导入数据失败:', error);
|
||
}
|
||
return importedCount;
|
||
}
|
||
|
||
// 导出数据到文件
|
||
async exportToFile(filename: string = 'marks_backup.json'): Promise<void> {
|
||
try {
|
||
const marks = await this.exportData();
|
||
const exportData = {
|
||
version: '1.0',
|
||
exportTime: new Date().toISOString(),
|
||
totalCount: marks.length,
|
||
marks: marks
|
||
};
|
||
|
||
const jsonData = JSON.stringify(exportData, null, 2);
|
||
const blob = new Blob([jsonData], { type: 'application/json' });
|
||
const url = URL.createObjectURL(blob);
|
||
|
||
// 创建下载链接
|
||
const link = document.createElement('a');
|
||
link.href = url;
|
||
link.download = filename;
|
||
document.body.appendChild(link);
|
||
link.click();
|
||
document.body.removeChild(link);
|
||
URL.revokeObjectURL(url);
|
||
|
||
console.log(`成功导出 ${marks.length} 条记录到文件: ${filename}`);
|
||
} catch (error) {
|
||
console.error('导出文件失败:', error);
|
||
throw new Error('导出文件失败: ' + (error as Error).message);
|
||
}
|
||
}
|
||
|
||
// 从文件导入数据
|
||
async importFromFile(file: File): Promise<{ success: number; failed: number; total: number }> {
|
||
return new Promise((resolve, reject) => {
|
||
const reader = new FileReader();
|
||
|
||
reader.onload = async (e) => {
|
||
try {
|
||
const content = e.target?.result as string;
|
||
const importData = JSON.parse(content);
|
||
|
||
// 验证数据格式
|
||
if (!importData.marks || !Array.isArray(importData.marks)) {
|
||
throw new Error('无效的数据格式:缺少marks数组');
|
||
}
|
||
|
||
let successCount = 0;
|
||
let failedCount = 0;
|
||
const totalCount = importData.marks.length;
|
||
|
||
// 批量导入数据
|
||
for (const mark of importData.marks) {
|
||
try {
|
||
// 移除ID相关字段,让系统重新生成
|
||
const { id, createdAt, updatedAt, _id, _rev, ...markData } = mark;
|
||
await this.createMark(markData);
|
||
successCount++;
|
||
} catch (error) {
|
||
console.warn('导入单条记录失败:', error);
|
||
failedCount++;
|
||
}
|
||
}
|
||
|
||
const result = {
|
||
success: successCount,
|
||
failed: failedCount,
|
||
total: totalCount
|
||
};
|
||
|
||
console.log(`导入完成: 成功${successCount}条,失败${failedCount}条,总计${totalCount}条`);
|
||
resolve(result);
|
||
} catch (error) {
|
||
console.error('解析导入文件失败:', error);
|
||
reject(new Error('解析导入文件失败: ' + (error as Error).message));
|
||
}
|
||
};
|
||
|
||
reader.onerror = () => {
|
||
reject(new Error('读取文件失败'));
|
||
};
|
||
|
||
reader.readAsText(file);
|
||
});
|
||
}
|
||
|
||
// 清空数据库
|
||
async clearDatabase(): Promise<boolean> {
|
||
try {
|
||
await this.db.clear();
|
||
console.log('数据库已清空');
|
||
return true;
|
||
} catch (error) {
|
||
console.error('清空数据库失败:', error);
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 创建默认服务实例
|
||
export const markService = new MarkService();
|
||
|
||
// 使用示例函数
|
||
export const exampleUsage = async () => {
|
||
// 1. 初始化服务
|
||
await markService.init();
|
||
|
||
// 4. 获取所有标记
|
||
const allMarks = await markService.getAllMarks();
|
||
console.log('所有标记数量:', allMarks.length);
|
||
|
||
// 5. 搜索标记
|
||
const searchResults = await markService.searchMarks('测试');
|
||
console.log('搜索结果数量:', searchResults.length);
|
||
|
||
// 6. 按类型获取标记
|
||
const markdownMarks = await markService.getMarksByType('markdown');
|
||
console.log('Markdown 标记数量:', markdownMarks.length);
|
||
|
||
// 7. 分页获取标记
|
||
const paginatedResults = await markService.getMarksPaginated(1, 5);
|
||
console.log('分页结果:', {
|
||
currentPage: paginatedResults.page,
|
||
totalPages: paginatedResults.totalPages,
|
||
total: paginatedResults.total,
|
||
marksOnPage: paginatedResults.marks.length
|
||
});
|
||
|
||
// 8. 获取统计信息
|
||
const stats = await markService.getStats();
|
||
console.log('统计信息:', stats);
|
||
|
||
}; |