fix: use report title as certificate material name
This commit is contained in:
parent
d2337b960e
commit
846b8c601b
@ -63,6 +63,13 @@ describe('检测报告初始化', () => {
|
||||
expect(prisma.material.create).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('成品即使有 SPU,上传时也必须填写报告名称', async () => {
|
||||
const response = await POST(request({ ...input, reportKind: '成品', productModel: 'SPU-001', reportTitle: ' ' }))
|
||||
expect(response.status).toBe(400)
|
||||
await expect(response.json()).resolves.toEqual({ error: '请填写报告名称 / 检测对象' })
|
||||
expect(prisma.material.create).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('到期时间早于检测日期时不写入素材', async () => {
|
||||
const response = await POST(request({ ...input, certificateExpiresOn: '2027-09-22' }))
|
||||
expect(response.status).toBe(400)
|
||||
|
||||
@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getServerSession } from 'next-auth'
|
||||
import { authOptions } from '@/lib/auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { CERTIFICATE_REPORT_MATERIAL_TYPE, normalizeReportTitle, validateCertificateReportMetadata } from '@/lib/certificate-report'
|
||||
import { CERTIFICATE_REPORT_KIND, CERTIFICATE_REPORT_MATERIAL_TYPE, normalizeReportTitle, validateCertificateReportMetadata } from '@/lib/certificate-report'
|
||||
import { INCOMPLETE_SHELL_CREATE_DATA } from '@/lib/material-query'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
@ -17,6 +17,9 @@ export async function POST(request: NextRequest) {
|
||||
const reportTitle = normalizeReportTitle(body.reportTitle)
|
||||
const productCategoryName = String(body.productCategoryName || '').trim()
|
||||
const platformName = String(body.platformName || '').trim()
|
||||
if (body.reportKind === CERTIFICATE_REPORT_KIND.FINISHED && !reportTitle) {
|
||||
return NextResponse.json({ error: '请填写报告名称 / 检测对象' }, { status: 400 })
|
||||
}
|
||||
const metadata = validateCertificateReportMetadata({
|
||||
reportKind: body.reportKind,
|
||||
productModel,
|
||||
|
||||
@ -594,7 +594,6 @@ export default function SharePage() {
|
||||
? getCertificateReportDisplayTitle({
|
||||
productModel: material.productModel,
|
||||
reportTitle: material.reportTitle,
|
||||
reportKind: material.reportKind,
|
||||
})
|
||||
: ''
|
||||
|
||||
|
||||
@ -156,6 +156,14 @@ describe('MaterialCard', () => {
|
||||
expect(notice.parentElement).not.toHaveClass('bg-[#fafafa]/55')
|
||||
})
|
||||
|
||||
test.each([
|
||||
['成品检测报告', '成品检测报告'],
|
||||
[null, 'SPU-001'],
|
||||
])('检测报告卡片优先使用报告名称,缺失时保留旧 SPU (%s)', (reportTitle, expectedTitle) => {
|
||||
render(<MaterialCard {...defaultProps} material={{ ...baseMaterial, materialType: '证书-检测报告', reportKind: '成品', reportTitle }} />)
|
||||
expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent(expectedTitle)
|
||||
})
|
||||
|
||||
test('视频卡片初始只加载封面,悬停时才挂载视频预览', () => {
|
||||
const { container } = render(
|
||||
<MaterialCard
|
||||
|
||||
@ -175,7 +175,6 @@ export default function MaterialCard({
|
||||
const materialDisplayTitle = getCertificateReportDisplayTitle({
|
||||
productModel: material.productModel,
|
||||
reportTitle: material.reportTitle,
|
||||
reportKind: material.reportKind,
|
||||
})
|
||||
|
||||
// 素材切换时回到封面态;视频只在用户悬停时加载,避免列表首屏并发预载全部视频。
|
||||
|
||||
@ -5,6 +5,20 @@ import { DEFAULT_CERTIFICATE_REPORT_USAGE_RULES } from '@/lib/certificate-report
|
||||
|
||||
jest.mock('@/lib/chunk-upload', () => ({ chunkUpload: jest.fn() }))
|
||||
|
||||
test('成品只填写 SPU 时不能上传,须先填写报告名称', () => {
|
||||
const originalFetch = global.fetch
|
||||
global.fetch = jest.fn()
|
||||
try {
|
||||
render(<CertificateReportUploader onSuccess={jest.fn()} onCancel={jest.fn()} productCategories={[]} />)
|
||||
fireEvent.change(screen.getByLabelText('SPU'), { target: { value: 'SPU-001' } })
|
||||
fireEvent.click(screen.getByRole('button', { name: '创建分享素材' }))
|
||||
expect(screen.getByText('请填写报告名称 / 检测对象')).toBeInTheDocument()
|
||||
expect(global.fetch).not.toHaveBeenCalled()
|
||||
} finally {
|
||||
global.fetch = originalFetch
|
||||
}
|
||||
})
|
||||
|
||||
test.each([['成品', true], ['成品', false], ['原材料', true], ['原材料', false]] as const)('%s上传说明与日期:手动到期时间 %s', async (kind, manualExpiry) => {
|
||||
const originalFetch = global.fetch
|
||||
jest.useFakeTimers().setSystemTime(new Date('2026-09-27T12:00:00'))
|
||||
@ -12,6 +26,12 @@ test.each([['成品', true], ['成品', false], ['原材料', true], ['原材料
|
||||
try {
|
||||
expect(screen.getByLabelText('成品')).toBeChecked()
|
||||
fireEvent.click(screen.getByLabelText(kind))
|
||||
const reportTitleInput = screen.getByLabelText('报告名称 / 检测对象 *')
|
||||
expect(reportTitleInput).toBeRequired()
|
||||
if (kind === '成品') {
|
||||
expect(reportTitleInput.compareDocumentPosition(screen.getByLabelText('SPU')) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy()
|
||||
}
|
||||
expect(screen.getByText('上传后将作为素材名称显示')).toBeInTheDocument()
|
||||
fireEvent.change(screen.getByLabelText(/报告名称 \/ 检测对象/), { target: { value: '板材检测报告' } })
|
||||
fireEvent.change(screen.getByLabelText('品类 *'), { target: { value: '板材' } })
|
||||
fireEvent.change(screen.getByLabelText('证书编号 *'), { target: { value: 'CMA-001' } })
|
||||
|
||||
@ -122,6 +122,10 @@ export default function CertificateReportUploader({
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const submittedProductModel = reportKind === CERTIFICATE_REPORT_KIND.RAW ? '' : productModel.trim()
|
||||
if (reportKind === CERTIFICATE_REPORT_KIND.FINISHED && !reportTitle.trim()) {
|
||||
setError('请填写报告名称 / 检测对象')
|
||||
return
|
||||
}
|
||||
const metadata = validateCertificateReportMetadata({
|
||||
reportKind,
|
||||
productModel: submittedProductModel,
|
||||
@ -280,6 +284,23 @@ export default function CertificateReportUploader({
|
||||
</fieldset>
|
||||
|
||||
<div className={`grid grid-cols-1 gap-4 ${reportKind === CERTIFICATE_REPORT_KIND.FINISHED ? 'md:grid-cols-2' : ''}`}>
|
||||
<div>
|
||||
<label htmlFor="certificate-report-title" className={fieldLabelClass}>
|
||||
报告名称 / 检测对象 *
|
||||
</label>
|
||||
<input
|
||||
id="certificate-report-title"
|
||||
type="text"
|
||||
value={reportTitle}
|
||||
onChange={(event) => setReportTitle(event.target.value)}
|
||||
placeholder="例如:E0级颗粒板检测报告"
|
||||
className={fieldControlClass}
|
||||
required
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500">
|
||||
上传后将作为素材名称显示
|
||||
</p>
|
||||
</div>
|
||||
{reportKind === CERTIFICATE_REPORT_KIND.FINISHED && (
|
||||
<div>
|
||||
<label htmlFor="certificate-report-spu" className={fieldLabelClass}>SPU</label>
|
||||
@ -293,24 +314,6 @@ export default function CertificateReportUploader({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<label htmlFor="certificate-report-title" className={fieldLabelClass}>
|
||||
报告名称 / 检测对象{reportKind === CERTIFICATE_REPORT_KIND.RAW ? ' *' : ''}
|
||||
</label>
|
||||
<input
|
||||
id="certificate-report-title"
|
||||
type="text"
|
||||
value={reportTitle}
|
||||
onChange={(event) => setReportTitle(event.target.value)}
|
||||
placeholder="例如:E0级颗粒板检测报告"
|
||||
className={fieldControlClass}
|
||||
required={reportKind === CERTIFICATE_REPORT_KIND.RAW}
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500">
|
||||
{reportKind === CERTIFICATE_REPORT_KIND.RAW ? '原材料检测报告必须填写报告名称' : 'SPU 和这个字段至少填写一个'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
|
||||
@ -41,12 +41,16 @@ describe('检测报告字段规则', () => {
|
||||
reportTitle: '板材检测报告',
|
||||
})).toHaveProperty('value.reportKind', '原材料')
|
||||
expect(getCertificateReportDisplayTitle({
|
||||
reportKind: '原材料',
|
||||
productModel: '旧 SPU',
|
||||
reportTitle: '板材检测报告',
|
||||
})).toBe('板材检测报告')
|
||||
})
|
||||
|
||||
test('成品有报告名称时优先显示,旧记录缺少名称时显示 SPU', () => {
|
||||
expect(getCertificateReportDisplayTitle({ productModel: 'SPU-001', reportTitle: '成品检测报告' })).toBe('成品检测报告')
|
||||
expect(getCertificateReportDisplayTitle({ productModel: 'SPU-001', reportTitle: null })).toBe('SPU-001')
|
||||
})
|
||||
|
||||
test('检测日期必须是真实的 YYYY-MM-DD 日期', () => {
|
||||
expect(parseCertificateDate('2027-02-28')?.toISOString().slice(0, 10)).toBe('2027-02-28')
|
||||
expect(parseCertificateDate('2027-02-30')).toBeNull()
|
||||
|
||||
@ -153,21 +153,15 @@ export function validateCertificateReportMetadata(input: {
|
||||
export function getCertificateReportDisplayTitle(input: {
|
||||
productModel?: string | null
|
||||
reportTitle?: string | null
|
||||
reportKind?: string | null
|
||||
}): string {
|
||||
const productModel = String(input.productModel || '').trim()
|
||||
const reportTitle = String(input.reportTitle || '').trim()
|
||||
if (input.reportKind === CERTIFICATE_REPORT_KIND.RAW && reportTitle) {
|
||||
if (reportTitle) {
|
||||
return reportTitle
|
||||
}
|
||||
if (productModel) {
|
||||
return productModel
|
||||
}
|
||||
|
||||
if (reportTitle) {
|
||||
return reportTitle
|
||||
}
|
||||
|
||||
return '未命名报告'
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user