2025-06-22 11:34:32 +08:00

216 lines
6.2 KiB
TypeScript
Raw Permalink 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, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
interface BatchComponentData {
name: string
brand: string
model: string
price: number
description?: string
imageUrl?: string
stock: number
specifications?: string
componentTypeId?: string
typeName?: string
type?: string
}
interface BatchResult {
success: boolean
item: BatchComponentData
error?: string
componentId?: string
}
export async function POST(request: NextRequest) {
try {
// 这个API需要管理员权限实际应用中需要验证
const { components } = await request.json()
if (!Array.isArray(components) || components.length === 0) {
return NextResponse.json(
{ message: '请提供有效的配件数据数组' },
{ status: 400 }
)
}
const results: BatchResult[] = []
const createdTypes: { [key: string]: string } = {} // 缓存新创建的类型
// 获取现有的配件类型,用于匹配
const existingTypes = await prisma.componentType.findMany()
const typeMap = new Map(existingTypes.map(type => [type.name.toLowerCase(), type.id]))
for (const componentData of components) {
try {
// 验证必需字段
if (!componentData.name || !componentData.brand || !componentData.model) {
results.push({
success: false,
item: componentData,
error: '缺少必需字段: name, brand, model'
})
continue
}
// 处理价格和库存
const price = typeof componentData.price === 'string'
? parseFloat(componentData.price)
: componentData.price
const stock = typeof componentData.stock === 'string'
? parseInt(componentData.stock)
: componentData.stock
if (isNaN(price) || price < 0) {
results.push({
success: false,
item: componentData,
error: '价格必须是有效的正数'
})
continue
}
if (isNaN(stock) || stock < 0) {
results.push({
success: false,
item: componentData,
error: '库存必须是有效的非负整数'
})
continue
}
// 处理配件类型
let componentTypeId = componentData.componentTypeId
if (!componentTypeId) {
const typeName = componentData.typeName || componentData.type
if (!typeName) {
results.push({
success: false,
item: componentData,
error: '缺少配件类型信息 (componentTypeId, typeName 或 type)'
})
continue
}
const lowerTypeName = typeName.toLowerCase()
// 检查是否已存在
if (typeMap.has(lowerTypeName)) {
componentTypeId = typeMap.get(lowerTypeName)
} else if (createdTypes[lowerTypeName]) {
// 检查本次批量导入中是否已创建
componentTypeId = createdTypes[lowerTypeName]
} else {
// 创建新的配件类型
try {
const newType = await prisma.componentType.create({
data: {
name: typeName,
description: `自动创建的${typeName}类型`
}
})
componentTypeId = newType.id
createdTypes[lowerTypeName] = newType.id
typeMap.set(lowerTypeName, newType.id)
} catch (typeError) {
results.push({
success: false,
item: componentData,
error: `创建配件类型失败: ${typeError instanceof Error ? typeError.message : '未知错误'}`
})
continue
}
}
}
// 验证配件类型ID
if (!componentTypeId) {
results.push({
success: false,
item: componentData,
error: '无法确定配件类型'
})
continue
}
// 检查是否已存在相同的配件
const existingComponent = await prisma.component.findFirst({
where: {
name: componentData.name,
brand: componentData.brand,
model: componentData.model
}
})
if (existingComponent) {
results.push({
success: false,
item: componentData,
error: `配件已存在: ${componentData.name} - ${componentData.brand} ${componentData.model}`
})
continue
}
// 创建配件
const newComponent = await prisma.component.create({
data: {
name: componentData.name.trim(),
brand: componentData.brand.trim(),
model: componentData.model.trim(),
price,
description: componentData.description?.trim() || '',
imageUrl: componentData.imageUrl?.trim() || '',
stock,
specifications: componentData.specifications?.trim() || '',
componentTypeId
},
include: {
componentType: true
}
})
results.push({
success: true,
item: componentData,
componentId: newComponent.id
})
} catch (error) {
console.error('处理单个配件时出错:', error)
results.push({
success: false,
item: componentData,
error: error instanceof Error ? error.message : '创建配件失败'
})
}
}
// 统计结果
const successCount = results.filter(r => r.success).length
const failCount = results.filter(r => !r.success).length
return NextResponse.json({
success: true,
results,
summary: {
total: components.length,
successful: successCount,
failed: failCount,
newTypesCreated: Object.keys(createdTypes).length
}
})
} catch (error) {
console.error('批量导入配件失败:', error)
return NextResponse.json(
{
success: false,
message: '批量导入失败',
error: error instanceof Error ? error.message : '未知错误'
},
{ status: 500 }
)
}
}