81 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextRequest } from 'next/server'
import { z } from 'zod'
import { prisma } from '@/src/lib/prisma'
const ExportSchema = z.object({
ids: z.array(z.string()).min(1),
format: z.enum(['csv', 'json']),
})
export async function POST(req: NextRequest) {
try {
const body = await req.json()
const parsed = ExportSchema.safeParse(body)
if (!parsed.success) return Response.json({ error: 'invalid body' }, { status: 400 })
const { ids, format } = parsed.data
const rows = await prisma.recording.findMany({
where: { id: { in: ids } },
orderBy: { timestamp: 'asc' },
// Cast select to any to accommodate freshly added fields before prisma generate
select: {
id: true,
timestamp: true,
code_data: true,
fit_a: true,
fit_b: true,
sample_count: true,
duration: true,
rec_start_ms: true,
rec_end_ms: true,
} ,
})
if (format === 'json') {
const payload = rows.map((r) => ({
id: r.id,
timestamp: new Date(r.timestamp).toISOString(),
code: r.code_data,
fit: r.fit_a != null ? { a: r.fit_a, b: r.fit_b } : undefined,
sampleCount: r.sample_count,
duration: r.duration,
}))
return new Response(JSON.stringify(payload), {
headers: {
'content-type': 'application/json; charset=utf-8',
'content-disposition': `attachment; filename="export-${Date.now()}.json"`,
},
})
}
// CSV去掉 recordId、timestamptimeSec 改为毫秒单位)
let csv = 'index,timeMs,code,force\n'
for (const r of rows) {
// 以毫秒为单位的步长
let stepMs = r.sample_count > 0 ? (r.duration * 1000) / r.sample_count : 0
if (r.rec_start_ms != null && r.rec_end_ms != null && r.sample_count > 0) {
const dtMs = Number((r.rec_end_ms as bigint) - (r.rec_start_ms as bigint))
if (Number.isFinite(dtMs) && dtMs > 0) stepMs = dtMs / r.sample_count
}
// 采样溢出时强制 1ms 步长(与 16.384s/16384 对齐)
if (r.sample_count >= 16384) stepMs = 1
const hasFit = r.fit_a != null
for (let i = 0; i < r.code_data.length; i++) {
const t = (i * stepMs).toFixed(3)
const code = r.code_data[i]
const force = hasFit ? r.fit_a! * code + (r.fit_b ?? 0) : ''
csv += `${i},${t},${code},${hasFit ? force : ''}\n`
}
}
return new Response(csv, {
headers: {
'content-type': 'text/csv; charset=utf-8',
'content-disposition': `attachment; filename="export-${Date.now()}.csv"`,
},
})
} catch (err) {
console.error(err)
return Response.json({ error: 'internal error' }, { status: 500 })
}
}