import { getServerSession } from 'next-auth' import type { Session } from 'next-auth' import { NextResponse } from 'next/server' import { authOptions } from '@/lib/auth' import { DINGTALK_PERFORMANCE_SESSION_HEADER, verifyDingtalkPerformanceSessionToken, } from '@/lib/dingtalk-performance-session' import { PerformanceSurveyApiError, createPerformanceSurveyWorkItemFromRequest, createPerformanceSurvey, cancelPerformanceSurvey, exportPerformanceSurveyCsv, getPerformanceSurveyDashboard, getPerformanceSurveyDashboardExport, getPerformanceSurveyDashboardDetail, getPerformanceSurveyAdminConfiguration, getPerformanceSurveyDetail, getPerformanceSurveyMe, getPerformanceSurveyNotificationStatus, getPerformanceSurveyResults, getPerformanceSurveyTemplates, getPerformanceSurveyPositionGroups, listPerformanceSurveyDepartments, listPerformanceSurveyNotifications, listPerformanceSurveys, retryPerformanceSurveyNotificationById, runPerformanceSurveyNotificationMaintenance, searchPerformanceSurveyEmployees, submitPerformanceSurveyWorkItemScores, submitPerformanceSurveyWorkItemScore, submitPerformanceSurveyResponse, previewPerformanceSurveyEmployeeProfiles, syncPerformanceSurveyEmployeeProfiles, updatePerformanceSurvey, savePerformanceSurveyAdminPositionGroup, publishPerformanceSurveyAdminPositionGroup, savePerformanceSurveyAdminTemplate, copyPerformanceSurveyAdminTemplateVersion, publishPerformanceSurveyAdminTemplateVersion, archivePerformanceSurveyAdminPositionAssignment, copyPerformanceSurveyAdminPositionGroup, createPerformanceSurveyAdminPositionAssignments, createPerformanceSurveyAdminPositionGroup, listPerformanceSurveyAdminConfigAuditLogs, listPerformanceSurveyAdminPositionAssignments, previewPerformanceSurveyAdminPositionGroup, removePerformanceSurveyAdminPositionGroup, removePerformanceSurveyAdminTemplate, removePerformanceSurveyPublicDashboardAssessment, updatePerformanceSurveyAdminPositionAssignment, } from '@/lib/performance-survey-service' export const runtime = 'nodejs' export const dynamic = 'force-dynamic' export const revalidate = 0 type RouteContext = { params: { path?: string[] } } function ok(data: unknown, init?: ResponseInit) { return NextResponse.json({ success: true, data }, init) } function errorResponse(error: unknown) { if (error instanceof PerformanceSurveyApiError) { return NextResponse.json({ success: false, error: error.message }, { status: error.status }) } if (error && typeof error === 'object' && typeof (error as { status?: unknown }).status === 'number') { return NextResponse.json( { success: false, error: error instanceof Error ? error.message : '请求失败' }, { status: (error as { status: number }).status }, ) } const message = error instanceof Error ? error.message : '服务器错误' console.error('[performance-survey] API error:', error) return NextResponse.json({ success: false, error: message }, { status: 500 }) } function readDingtalkPerformanceToken(request: Request) { const headerToken = request.headers.get(DINGTALK_PERFORMANCE_SESSION_HEADER) if (headerToken) { return headerToken } const authorization = request.headers.get('authorization') || '' const match = authorization.match(/^Bearer\s+(.+)$/i) return match?.[1]?.trim() || null } async function getSession(request: Request): Promise { const session = await getServerSession(authOptions) if ((session?.user as any)?.id) { return session } const payload = verifyDingtalkPerformanceSessionToken(readDingtalkPerformanceToken(request)) if (!payload) { return session } return { user: { id: payload.userId, email: payload.email, name: payload.name, avatar: payload.avatar || null, role: payload.role, department: payload.department || '', managedDepartment: payload.managedDepartment || null, isSuperAdmin: payload.isSuperAdmin ?? false, }, expires: new Date(payload.exp * 1000).toISOString(), } } function getPath(context: RouteContext) { return context.params.path || [] } export async function GET(request: Request, context: RouteContext) { try { const session = await getSession(request) const path = getPath(context) const url = new URL(request.url) if (path.length === 0 || path[0] === 'me') { return ok(await getPerformanceSurveyMe(session)) } if (path[0] === 'templates') { return ok(await getPerformanceSurveyTemplates(session, url.searchParams)) } if (path[0] === 'position-groups') { return ok(await getPerformanceSurveyPositionGroups(session, url.searchParams)) } if (path[0] === 'employees') { return ok(await searchPerformanceSurveyEmployees(session, url.searchParams)) } if (path[0] === 'departments') { return ok(await listPerformanceSurveyDepartments(session, url.searchParams)) } if (path[0] === 'dashboard' && path[1] === 'export') { return ok(await getPerformanceSurveyDashboardExport(session, url.searchParams)) } if (path[0] === 'dashboard' && path[1] === 'detail') { return ok(await getPerformanceSurveyDashboardDetail(session, url.searchParams)) } if (path[0] === 'dashboard') { return ok(await getPerformanceSurveyDashboard(session, url.searchParams)) } if (path[0] === 'surveys' && path.length === 1) { return ok(await listPerformanceSurveys(session, url.searchParams)) } if (path[0] === 'surveys' && path[1] && path.length === 2) { return ok(await getPerformanceSurveyDetail(session, path[1])) } if (path[0] === 'surveys' && path[1] && path[2] === 'results') { return ok(await getPerformanceSurveyResults(session, path[1], url.searchParams)) } if (path[0] === 'results' && path[1]) { return ok(await getPerformanceSurveyResults(session, path[1], url.searchParams)) } if (path[0] === 'admin' && path[1] === 'notifications' && path[2] === 'status') { return ok(await getPerformanceSurveyNotificationStatus(session)) } if ( path[0] === 'admin' && path[1] === 'position-groups' && path[2] && path[3] === 'preview' && path.length === 4 ) { return ok(await previewPerformanceSurveyAdminPositionGroup(session, path[2], url.searchParams)) } if (path[0] === 'admin' && path[1] === 'position-assignments' && path.length === 2) { return ok(await listPerformanceSurveyAdminPositionAssignments(session, url.searchParams)) } if (path[0] === 'admin' && path[1] === 'config-audit-logs' && path.length === 2) { return ok(await listPerformanceSurveyAdminConfigAuditLogs(session, url.searchParams)) } if (path[0] === 'admin' && path[1] === 'config') { return ok(await getPerformanceSurveyAdminConfiguration(session, url.searchParams)) } if (path[0] === 'admin' && path[1] === 'notifications') { return ok(await listPerformanceSurveyNotifications(session, url.searchParams)) } if (path[0] === 'admin' && path[1] === 'export') { const csv = await exportPerformanceSurveyCsv(session) return new NextResponse(csv, { headers: { 'Content-Type': 'text/csv; charset=utf-8', 'Content-Disposition': 'attachment; filename="performance-survey-export.csv"', }, }) } return NextResponse.json({ success: false, error: '接口不存在' }, { status: 404 }) } catch (error) { return errorResponse(error) } } export async function POST(request: Request, context: RouteContext) { try { const session = await getSession(request) const path = getPath(context) if (path[0] === 'surveys' && path[1] && path[2] === 'work-items' && path.length === 3) { return ok(await createPerformanceSurveyWorkItemFromRequest(session, path[1], request), { status: 201 }) } const body = await request.json().catch(() => ({})) if (path[0] === 'surveys' && path.length === 1) { return ok(await createPerformanceSurvey(session, body), { status: 201 }) } if (path[0] === 'surveys' && path[1] && path[2] === 'cancel' && path.length === 3) { return ok(await cancelPerformanceSurvey(session, path[1], body)) } if (path[0] === 'surveys' && path[1] && path[2] === 'responses') { return ok(await submitPerformanceSurveyResponse(session, path[1], body)) } if (path[0] === 'surveys' && path[1] && path[2] === 'work-item-scores' && path.length === 3) { return ok(await submitPerformanceSurveyWorkItemScores(session, path[1], body)) } if (path[0] === 'surveys' && path[1] && path[2] === 'work-items' && path[3] && path[4] === 'scores') { return ok(await submitPerformanceSurveyWorkItemScore(session, path[1], path[3], body)) } if ( path[0] === 'admin' && path[1] === 'sync-employees' && path[2] === 'preview' && path.length === 3 ) { return ok(await previewPerformanceSurveyEmployeeProfiles(session, body)) } if (path[0] === 'admin' && path[1] === 'sync-employees' && path.length === 2) { return ok(await syncPerformanceSurveyEmployeeProfiles(session, body)) } if (path[0] === 'admin' && path[1] === 'position-groups' && path.length === 2) { return ok(await createPerformanceSurveyAdminPositionGroup(session, body), { status: 201 }) } if ( path[0] === 'admin' && path[1] === 'position-groups' && path[2] && path[3] === 'copy' && path.length === 4 ) { return ok(await copyPerformanceSurveyAdminPositionGroup(session, path[2], body), { status: 201 }) } if ( path[0] === 'admin' && path[1] === 'position-groups' && path[2] && path[3] === 'publish' && path.length === 4 ) { return ok(await publishPerformanceSurveyAdminPositionGroup(session, path[2], body)) } if (path[0] === 'admin' && path[1] === 'position-assignments' && path.length === 2) { return ok(await createPerformanceSurveyAdminPositionAssignments(session, body), { status: 201 }) } if (path[0] === 'admin' && path[1] === 'templates' && path.length === 2) { return ok(await savePerformanceSurveyAdminTemplate(session, body), { status: 201 }) } if (path[0] === 'admin' && path[1] === 'templates' && path[2] && path[3] === 'copy') { return ok(await copyPerformanceSurveyAdminTemplateVersion(session, path[2]), { status: 201 }) } if (path[0] === 'admin' && path[1] === 'templates' && path[2] && path[3] === 'publish') { return ok(await publishPerformanceSurveyAdminTemplateVersion(session, path[2], body)) } if (path[0] === 'admin' && path[1] === 'notifications' && path[2] === 'maintenance') { return ok(await runPerformanceSurveyNotificationMaintenance(session)) } if (path[0] === 'admin' && path[1] === 'notifications' && path[2] && path[3] === 'retry') { return ok(await retryPerformanceSurveyNotificationById(session, path[2])) } return NextResponse.json({ success: false, error: '接口不存在' }, { status: 404 }) } catch (error) { return errorResponse(error) } } export async function PATCH(request: Request, context: RouteContext) { try { const session = await getSession(request) const path = getPath(context) const body = await request.json().catch(() => ({})) if (path[0] === 'surveys' && path[1] && path.length === 2) { return ok(await updatePerformanceSurvey(session, path[1], body)) } if (path[0] === 'admin' && path[1] === 'position-groups' && path[2] && path.length === 3) { return ok(await savePerformanceSurveyAdminPositionGroup(session, path[2], body)) } if (path[0] === 'admin' && path[1] === 'templates' && path[2] && path.length === 3) { return ok(await savePerformanceSurveyAdminTemplate(session, { ...body, versionId: path[2] })) } if (path[0] === 'admin' && path[1] === 'position-assignments' && path[2] && path.length === 3) { return ok(await updatePerformanceSurveyAdminPositionAssignment(session, path[2], body)) } return NextResponse.json({ success: false, error: '接口不存在' }, { status: 404 }) } catch (error) { return errorResponse(error) } } export async function DELETE(request: Request, context: RouteContext) { try { const session = await getSession(request) const path = getPath(context) const body = await request.json().catch(() => ({})) if (path[0] === 'admin' && path[1] === 'position-groups' && path[2] && path.length === 3) { return ok(await removePerformanceSurveyAdminPositionGroup(session, path[2], body)) } if (path[0] === 'admin' && path[1] === 'templates' && path[2] && path.length === 3) { return ok(await removePerformanceSurveyAdminTemplate(session, path[2], body)) } if (path[0] === 'admin' && path[1] === 'position-assignments' && path[2] && path.length === 3) { return ok(await archivePerformanceSurveyAdminPositionAssignment(session, path[2], body)) } if ( path[0] === 'dashboard' && path[1] === 'public' && path[2] === 'assessments' && path[3] && path.length === 4 ) { return ok(await removePerformanceSurveyPublicDashboardAssessment(session, path[3], body)) } return NextResponse.json({ success: false, error: '接口不存在' }, { status: 404 }) } catch (error) { return errorResponse(error) } }