203 lines
6.3 KiB
TypeScript
203 lines
6.3 KiB
TypeScript
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,
|
|
createPerformanceSurvey,
|
|
exportPerformanceSurveyCsv,
|
|
getPerformanceSurveyDetail,
|
|
getPerformanceSurveyMe,
|
|
getPerformanceSurveyNotificationStatus,
|
|
getPerformanceSurveyResults,
|
|
getPerformanceSurveyTemplates,
|
|
listPerformanceSurveyDepartments,
|
|
listPerformanceSurveyNotifications,
|
|
listPerformanceSurveys,
|
|
retryPerformanceSurveyNotificationById,
|
|
runPerformanceSurveyNotificationMaintenance,
|
|
searchPerformanceSurveyEmployees,
|
|
submitPerformanceSurveyResponse,
|
|
syncPerformanceSurveyEmployeeProfiles,
|
|
updatePerformanceSurvey,
|
|
} 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 })
|
|
}
|
|
|
|
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<Session | null> {
|
|
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))
|
|
}
|
|
|
|
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] === '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] === '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)
|
|
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] === 'responses') {
|
|
return ok(await submitPerformanceSurveyResponse(session, path[1], body))
|
|
}
|
|
|
|
if (path[0] === 'admin' && path[1] === 'sync-employees') {
|
|
return ok(await syncPerformanceSurveyEmployeeProfiles(session, 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))
|
|
}
|
|
|
|
return NextResponse.json({ success: false, error: '接口不存在' }, { status: 404 })
|
|
} catch (error) {
|
|
return errorResponse(error)
|
|
}
|
|
}
|