TTeamDesk 学习手册

src/app/api/exports/[id]/route.ts

此代码来自构建时的仓库快照。修改源码后重新构建即可更新。

ts
import { TRPCError } from '@trpc/server';
import { getAuth } from '@/server/auth';
import { getDb } from '@/server/db';
import { downloadExport } from '@/server/services/tasks';
import { taskIdSchema } from '@/shared/tasks';

export async function GET(
  request: Request,
  { params }: { params: Promise<{ id: string }> },
) {
  const session = await getAuth().api.getSession({ headers: request.headers });
  if (!session) return Response.json({ message: '请先登录' }, { status: 401 });
  const parsed = taskIdSchema.safeParse(await params);
  if (!parsed.success)
    return Response.json({ message: '文件不存在' }, { status: 404 });
  try {
    // 文件没有公开 URL;每次下载都重新检查会话、团队成员、任务所有者和有效期。
    const csv = await downloadExport(getDb(), session.user.id, parsed.data.id);
    return new Response(csv, {
      headers: {
        'Content-Type': 'text/csv; charset=utf-8',
        'Content-Disposition': `attachment; filename="tickets-${parsed.data.id}.csv"`,
        'Cache-Control': 'private, no-store',
        'X-Content-Type-Options': 'nosniff',
      },
    });
  } catch (error) {
    const status =
      error instanceof TRPCError
        ? error.code === 'FORBIDDEN'
          ? 403
          : 404
        : 500;
    return Response.json(
      {
        message:
          status === 500 ? '文件暂时不可用' : '文件不存在、已过期或无权访问',
      },
      { status, headers: { 'Cache-Control': 'no-store' } },
    );
  }
}

搜索教程

输入关键词,搜索全部章节。

阅读设置

外观
正文字号

从一张工单出发,读懂数据如何流转。

设置与进度仅保存在当前浏览器。