fix typeerror
This commit is contained in:
@@ -8,7 +8,7 @@ import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { SimpleCrypto } from '@/lib/crypto';
|
||||
import { db } from '@/lib/db';
|
||||
import { CURRENT_VERSION } from '@/lib/version';
|
||||
import { updateProgress, clearProgress } from '../progress/route';
|
||||
import { updateProgress, clearProgress } from '@/lib/data-migration-progress';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -36,6 +36,8 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json({ error: '权限不足,只有站长可以导出数据' }, { status: 401 });
|
||||
}
|
||||
|
||||
const username = authInfo.username; // 存储到局部变量以便 TypeScript 类型推断
|
||||
|
||||
const config = await db.getAdminConfig();
|
||||
if (!config) {
|
||||
return NextResponse.json({ error: '无法获取配置' }, { status: 500 });
|
||||
@@ -80,7 +82,7 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// 为每个用户收集数据(只导出V2用户)- 使用并行处理
|
||||
console.log(`开始并行导出 ${allUsers.length} 个用户的数据...`);
|
||||
updateProgress(authInfo.username, 'export', 'collecting', 0, allUsers.length, '开始收集用户数据...');
|
||||
updateProgress(username, 'export', 'collecting', 0, allUsers.length, '开始收集用户数据...');
|
||||
|
||||
// 分块处理用户,每批处理数量可通过环境变量配置
|
||||
const CHUNK_SIZE = parseInt(process.env.DATA_MIGRATION_CHUNK_SIZE || '10', 10);
|
||||
@@ -160,7 +162,7 @@ export async function POST(req: NextRequest) {
|
||||
exportedCount++;
|
||||
// 每处理完一个用户就更新进度
|
||||
updateProgress(
|
||||
authInfo.username,
|
||||
username,
|
||||
'export',
|
||||
'collecting',
|
||||
exportedCount,
|
||||
@@ -176,15 +178,15 @@ export async function POST(req: NextRequest) {
|
||||
console.log(`成功导出 ${exportedCount} 个用户的数据`);
|
||||
|
||||
// 将数据转换为JSON字符串
|
||||
updateProgress(authInfo.username, 'export', 'serializing', exportedCount, exportedCount, '正在序列化数据...');
|
||||
updateProgress(username, 'export', 'serializing', exportedCount, exportedCount, '正在序列化数据...');
|
||||
const jsonData = JSON.stringify(exportData);
|
||||
|
||||
// 先压缩数据
|
||||
updateProgress(authInfo.username, 'export', 'compressing', exportedCount, exportedCount, '正在压缩数据...');
|
||||
updateProgress(username, 'export', 'compressing', exportedCount, exportedCount, '正在压缩数据...');
|
||||
const compressedData = await gzipAsync(jsonData);
|
||||
|
||||
// 使用提供的密码加密压缩后的数据
|
||||
updateProgress(authInfo.username, 'export', 'encrypting', exportedCount, exportedCount, '正在加密数据...');
|
||||
updateProgress(username, 'export', 'encrypting', exportedCount, exportedCount, '正在加密数据...');
|
||||
const encryptedData = SimpleCrypto.encrypt(compressedData.toString('base64'), password);
|
||||
|
||||
// 生成文件名
|
||||
@@ -193,8 +195,8 @@ export async function POST(req: NextRequest) {
|
||||
const filename = `moontv-backup-${timestamp}.dat`;
|
||||
|
||||
// 清除进度信息
|
||||
updateProgress(authInfo.username, 'export', 'completed', exportedCount, exportedCount, '导出完成!');
|
||||
setTimeout(() => clearProgress(authInfo.username, 'export'), 3000);
|
||||
updateProgress(username, 'export', 'completed', exportedCount, exportedCount, '导出完成!');
|
||||
setTimeout(() => clearProgress(username, 'export'), 3000);
|
||||
|
||||
// 返回加密的数据作为文件下载
|
||||
return new NextResponse(encryptedData, {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { configSelfCheck, setCachedConfig } from '@/lib/config';
|
||||
import { SimpleCrypto } from '@/lib/crypto';
|
||||
import { db } from '@/lib/db';
|
||||
import { updateProgress, clearProgress } from '../progress/route';
|
||||
import { updateProgress, clearProgress } from '@/lib/data-migration-progress';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
@@ -36,6 +36,8 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json({ error: '权限不足,只有站长可以导入数据' }, { status: 401 });
|
||||
}
|
||||
|
||||
const username = authInfo.username; // 存储到局部变量以便 TypeScript 类型推断
|
||||
|
||||
// 解析表单数据
|
||||
const formData = await req.formData();
|
||||
const file = formData.get('file') as File;
|
||||
@@ -79,7 +81,7 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
// 开始导入数据 - 先清空现有数据
|
||||
updateProgress(authInfo.username, 'import', 'clearing', 0, 1, '正在清空现有数据...');
|
||||
updateProgress(username, 'import', 'clearing', 0, 1, '正在清空现有数据...');
|
||||
await db.clearAllData();
|
||||
|
||||
// 额外清除所有V2用户(clearAllData可能只清除旧版用户)
|
||||
@@ -111,7 +113,7 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
const userCount = Object.keys(userData).length;
|
||||
console.log(`准备导入 ${userCount} 个用户的数据`);
|
||||
updateProgress(authInfo.username, 'import', 'importing', 0, userCount, '开始导入用户数据...');
|
||||
updateProgress(username, 'import', 'importing', 0, userCount, '开始导入用户数据...');
|
||||
|
||||
// 分块处理用户,每批处理数量可通过环境变量配置
|
||||
const CHUNK_SIZE = parseInt(process.env.DATA_MIGRATION_CHUNK_SIZE || '10', 10);
|
||||
@@ -122,7 +124,7 @@ export async function POST(req: NextRequest) {
|
||||
const chunk = usernames.slice(i, i + CHUNK_SIZE);
|
||||
console.log(`处理第 ${Math.floor(i / CHUNK_SIZE) + 1} 批用户 (${chunk.length} 个)`);
|
||||
updateProgress(
|
||||
authInfo.username,
|
||||
username,
|
||||
'import',
|
||||
'importing',
|
||||
importedCount,
|
||||
@@ -268,7 +270,7 @@ export async function POST(req: NextRequest) {
|
||||
for (let j = 0; j < reversed.length; j += DATA_BATCH_SIZE) {
|
||||
const batch = reversed.slice(j, j + DATA_BATCH_SIZE);
|
||||
await Promise.all(
|
||||
batch.map(keyword => db.addSearchHistory(username, keyword))
|
||||
batch.map((keyword: string) => db.addSearchHistory(username, keyword))
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -328,7 +330,7 @@ export async function POST(req: NextRequest) {
|
||||
for (let j = 0; j < playlist.songs.length; j += DATA_BATCH_SIZE) {
|
||||
const batch = playlist.songs.slice(j, j + DATA_BATCH_SIZE);
|
||||
await Promise.all(
|
||||
batch.map(song =>
|
||||
batch.map((song: any) =>
|
||||
db.addSongToPlaylist(playlist.id, {
|
||||
platform: song.platform,
|
||||
id: song.id,
|
||||
@@ -360,7 +362,7 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
console.log(`已完成 ${importedCount}/${userCount} 个用户`);
|
||||
updateProgress(
|
||||
authInfo.username,
|
||||
username,
|
||||
'import',
|
||||
'importing',
|
||||
importedCount,
|
||||
@@ -370,8 +372,8 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
console.log(`成功导入 ${importedCount} 个用户的user:info`);
|
||||
updateProgress(authInfo.username, 'import', 'completed', importedCount, userCount, '导入完成!');
|
||||
setTimeout(() => clearProgress(authInfo.username, 'import'), 3000);
|
||||
updateProgress(username, 'import', 'completed', importedCount, userCount, '导入完成!');
|
||||
setTimeout(() => clearProgress(username, 'import'), 3000);
|
||||
|
||||
return NextResponse.json({
|
||||
message: '数据导入成功',
|
||||
|
||||
@@ -3,28 +3,10 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
|
||||
import { getAuthInfoFromCookie } from '@/lib/auth';
|
||||
import { getProgress } from '@/lib/data-migration-progress';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
|
||||
// 存储进度信息的 Map
|
||||
const progressStore = new Map<string, {
|
||||
phase: string;
|
||||
current: number;
|
||||
total: number;
|
||||
message: string;
|
||||
timestamp: number;
|
||||
}>();
|
||||
|
||||
// 清理过期的进度信息(超过5分钟)
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [key, value] of progressStore.entries()) {
|
||||
if (now - value.timestamp > 5 * 60 * 1000) {
|
||||
progressStore.delete(key);
|
||||
}
|
||||
}
|
||||
}, 60 * 1000);
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
// 验证身份和权限
|
||||
const authInfo = getAuthInfoFromCookie(req);
|
||||
@@ -36,6 +18,8 @@ export async function GET(req: NextRequest) {
|
||||
return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
|
||||
const username = authInfo.username; // 存储到局部变量以便 TypeScript 类型推断
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
const operation = searchParams.get('operation'); // 'export' or 'import'
|
||||
|
||||
@@ -43,8 +27,6 @@ export async function GET(req: NextRequest) {
|
||||
return new Response('Missing operation parameter', { status: 400 });
|
||||
}
|
||||
|
||||
const progressKey = `${authInfo.username}:${operation}`;
|
||||
|
||||
// 创建 SSE 响应
|
||||
const encoder = new TextEncoder();
|
||||
let interval: NodeJS.Timeout | null = null;
|
||||
@@ -54,7 +36,7 @@ export async function GET(req: NextRequest) {
|
||||
start(controller) {
|
||||
const sendProgress = () => {
|
||||
try {
|
||||
const progress = progressStore.get(progressKey);
|
||||
const progress = getProgress(username, operation as 'export' | 'import');
|
||||
if (progress) {
|
||||
const data = JSON.stringify(progress);
|
||||
controller.enqueue(encoder.encode(`data: ${data}\n\n`));
|
||||
@@ -97,28 +79,3 @@ export async function GET(req: NextRequest) {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 辅助函数:更新进度
|
||||
export function updateProgress(
|
||||
username: string,
|
||||
operation: 'export' | 'import',
|
||||
phase: string,
|
||||
current: number,
|
||||
total: number,
|
||||
message: string
|
||||
) {
|
||||
const progressKey = `${username}:${operation}`;
|
||||
progressStore.set(progressKey, {
|
||||
phase,
|
||||
current,
|
||||
total,
|
||||
message,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
// 辅助函数:清除进度
|
||||
export function clearProgress(username: string, operation: 'export' | 'import') {
|
||||
const progressKey = `${username}:${operation}`;
|
||||
progressStore.delete(progressKey);
|
||||
}
|
||||
|
||||
50
src/lib/data-migration-progress.ts
Normal file
50
src/lib/data-migration-progress.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
// 存储进度信息的 Map
|
||||
const progressStore = new Map<string, {
|
||||
phase: string;
|
||||
current: number;
|
||||
total: number;
|
||||
message: string;
|
||||
timestamp: number;
|
||||
}>();
|
||||
|
||||
// 清理过期的进度信息(超过5分钟)
|
||||
setInterval(() => {
|
||||
const now = Date.now();
|
||||
const entries = Array.from(progressStore.entries());
|
||||
for (const [key, value] of entries) {
|
||||
if (now - value.timestamp > 5 * 60 * 1000) {
|
||||
progressStore.delete(key);
|
||||
}
|
||||
}
|
||||
}, 60 * 1000);
|
||||
|
||||
// 辅助函数:更新进度
|
||||
export function updateProgress(
|
||||
username: string,
|
||||
operation: 'export' | 'import',
|
||||
phase: string,
|
||||
current: number,
|
||||
total: number,
|
||||
message: string
|
||||
) {
|
||||
const progressKey = `${username}:${operation}`;
|
||||
progressStore.set(progressKey, {
|
||||
phase,
|
||||
current,
|
||||
total,
|
||||
message,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
// 辅助函数:清除进度
|
||||
export function clearProgress(username: string, operation: 'export' | 'import') {
|
||||
const progressKey = `${username}:${operation}`;
|
||||
progressStore.delete(progressKey);
|
||||
}
|
||||
|
||||
// 辅助函数:获取进度
|
||||
export function getProgress(username: string, operation: 'export' | 'import') {
|
||||
const progressKey = `${username}:${operation}`;
|
||||
return progressStore.get(progressKey);
|
||||
}
|
||||
Reference in New Issue
Block a user