208 lines
5.8 KiB
TypeScript

import { NextRequest } from 'next/server'
import { prisma } from '@/lib/prisma'
import { rewriteStorageUrlForClient } from '@/lib/url-rewrite'
import {
API_ERROR,
errorResponse,
getApiKeyFromRequest,
getClientIp,
logApiCall,
successResponse,
validateApiKey,
} from '@/lib/external-api'
interface BarcodeImageItem {
materialId: string
assetId: string
taskNo: string | null
productModel: string
categoryName: string
shopName: string
sceneName: string
skuCode: string | null
barcodes: string[]
previewUrl: string
fileName: string
sortOrder: number
uploadedAt: string
updatedAt: string
uploaderName: string
isLatest: boolean
}
export async function GET(request: NextRequest) {
const startTime = Date.now()
const apiKey = getApiKeyFromRequest(request)
const rawBarcode = request.nextUrl.searchParams.get('barcode')
const barcode = String(rawBarcode || '').trim()
const keyRecord = await validateApiKey(apiKey)
if (!keyRecord) {
return errorResponse(API_ERROR.INVALID_API_KEY)
}
if (!barcode) {
await logApiCall({
apiKeyId: keyRecord.id,
endpoint: '/api/external/product-barcode-images',
method: 'GET',
queryType: 'barcode',
queryValue: rawBarcode || undefined,
statusCode: 400,
duration: Date.now() - startTime,
ipAddress: getClientIp(request),
userAgent: request.headers.get('user-agent') || undefined,
})
return errorResponse(API_ERROR.INVALID_BARCODE)
}
try {
const matches = await prisma.materialAssetBarcode.findMany({
where: {
barcode,
asset: {
assetType: 'sku-preview',
material: {
materialType: '任务-详情',
taskDetailPrivate: false,
deletedAt: null,
},
},
},
select: {
assetId: true,
barcode: true,
asset: {
select: {
id: true,
fileUrl: true,
fileName: true,
sortOrder: true,
skuCode: true,
createdAt: true,
updatedAt: true,
barcodes: {
select: {
barcode: true,
},
},
material: {
select: {
id: true,
taskNo: true,
productModel: true,
categoryName: true,
sceneName: true,
authorName: true,
user: {
select: {
realName: true,
username: true,
},
},
},
},
},
},
},
})
const items = matches
.map((match): BarcodeImageItem | null => {
const asset = match.asset
const material = asset?.material
if (!asset || !material) {
return null
}
return {
materialId: String(material.id),
assetId: String(asset.id),
taskNo: material.taskNo || null,
productModel: String(material.productModel || ''),
categoryName: String(material.categoryName || ''),
shopName: String(material.categoryName || ''),
sceneName: String(material.sceneName || ''),
skuCode: asset.skuCode || null,
barcodes: Array.from(
new Set((asset.barcodes || []).map((item: any) => String(item.barcode || '').trim()).filter(Boolean)),
),
previewUrl: rewriteStorageUrlForClient(asset.fileUrl, request) || String(asset.fileUrl || ''),
fileName: String(asset.fileName || ''),
sortOrder: Number(asset.sortOrder || 0),
uploadedAt: asset.createdAt.toISOString(),
updatedAt: asset.updatedAt.toISOString(),
uploaderName:
material.user?.realName || material.user?.username || material.authorName || '',
isLatest: false,
}
})
.filter((item): item is BarcodeImageItem => Boolean(item))
.sort((left, right) => {
const uploadedAtDiff =
new Date(right.uploadedAt).getTime() - new Date(left.uploadedAt).getTime()
if (uploadedAtDiff !== 0) {
return uploadedAtDiff
}
return left.sortOrder - right.sortOrder
})
if (items.length === 0) {
await logApiCall({
apiKeyId: keyRecord.id,
endpoint: '/api/external/product-barcode-images',
method: 'GET',
queryType: 'barcode',
queryValue: barcode,
statusCode: 404,
duration: Date.now() - startTime,
ipAddress: getClientIp(request),
userAgent: request.headers.get('user-agent') || undefined,
})
return errorResponse(API_ERROR.BARCODE_NOT_FOUND)
}
const latestAssetId = items[0].assetId
const responseData = {
barcode,
total: items.length,
items: items.map((item) => ({
...item,
isLatest: item.assetId === latestAssetId,
})),
}
await logApiCall({
apiKeyId: keyRecord.id,
endpoint: '/api/external/product-barcode-images',
method: 'GET',
taskNo: responseData.items[0]?.taskNo || undefined,
queryType: 'barcode',
queryValue: barcode,
statusCode: 200,
duration: Date.now() - startTime,
ipAddress: getClientIp(request),
userAgent: request.headers.get('user-agent') || undefined,
})
return successResponse(responseData)
} catch (error) {
console.error('[external/product-barcode-images] GET error:', error)
await logApiCall({
apiKeyId: keyRecord.id,
endpoint: '/api/external/product-barcode-images',
method: 'GET',
queryType: 'barcode',
queryValue: barcode,
statusCode: 500,
duration: Date.now() - startTime,
ipAddress: getClientIp(request),
userAgent: request.headers.get('user-agent') || undefined,
})
return errorResponse(API_ERROR.SERVER_ERROR)
}
}