feat: 자재 분류 시스템 개선 및 상세 테이블 추가

- 모든 자재 카테고리별 상세 테이블 생성 (fitting, valve, flange, bolt, gasket, instrument)
- PIPE, FITTING, VALVE 분류 결과를 각 상세 테이블에 저장하는 로직 구현
- 프론트엔드 라우팅 정리 및 BOM 현황 페이지 기능 개선
- 자재확인 페이지 에러 처리 개선

TODO: FLANGE, BOLT, GASKET, INSTRUMENT 저장 로직 추가 필요
This commit is contained in:
Hyungi Ahn
2025-07-17 10:44:19 +09:00
parent ea111433e4
commit 5f7a6f0b3a
30 changed files with 3963 additions and 923 deletions

View File

@@ -388,20 +388,20 @@ function FileUpload({ selectedProject, onUploadSuccess }) {
📊 업로드 결과
</Typography>
<List dense>
<ListItem>
<ListItemIcon>
<ListItem>
<ListItemIcon>
<Description />
</ListItemIcon>
<ListItemText
</ListItemIcon>
<ListItemText
primary="파일명"
secondary={uploadResult.original_filename}
/>
</ListItem>
<ListItem>
/>
</ListItem>
<ListItem>
<ListItemIcon>
<CheckCircle />
</ListItemIcon>
<ListItemText
<ListItemText
primary="파싱된 자재 수"
secondary={`${uploadResult.parsed_materials_count}`}
/>
@@ -413,9 +413,9 @@ function FileUpload({ selectedProject, onUploadSuccess }) {
<ListItemText
primary="저장된 자재 수"
secondary={`${uploadResult.saved_materials_count}`}
/>
</ListItem>
</List>
/>
</ListItem>
</List>
</Grid>
<Grid item xs={12} md={6}>
@@ -434,11 +434,11 @@ function FileUpload({ selectedProject, onUploadSuccess }) {
/>
<Typography variant="body2">
{stat.count} ({stat.percentage}%)
</Typography>
</Typography>
</Box>
))}
</Box>
)}
))}
</Box>
)}
</Grid>
</Grid>
@@ -470,67 +470,67 @@ function FileUpload({ selectedProject, onUploadSuccess }) {
</Box>
</CardContent>
</Card>
) : (
<>
<Paper
{...getRootProps()}
) : (
<>
<Paper
{...getRootProps()}
onClick={() => console.log('드래그 앤 드롭 영역 클릭됨')}
sx={{
p: 4,
textAlign: 'center',
border: 2,
borderStyle: 'dashed',
borderColor: isDragActive ? 'primary.main' : 'grey.300',
bgcolor: isDragActive ? 'primary.50' : 'grey.50',
cursor: 'pointer',
transition: 'all 0.2s ease',
'&:hover': {
borderColor: 'primary.main',
bgcolor: 'primary.50'
}
}}
>
<input {...getInputProps()} />
<CloudUpload sx={{
fontSize: 64,
color: isDragActive ? 'primary.main' : 'grey.400',
mb: 2
}} />
<Typography variant="h6" gutterBottom>
{isDragActive
? "파일을 여기에 놓으세요!"
: "Excel 파일을 드래그하거나 클릭하여 선택"
}
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
지원 형식: .xlsx, .xls, .csv (최대 10MB)
</Typography>
<Button
variant="contained"
startIcon={<AttachFile />}
component="span"
sx={{
p: 4,
textAlign: 'center',
border: 2,
borderStyle: 'dashed',
borderColor: isDragActive ? 'primary.main' : 'grey.300',
bgcolor: isDragActive ? 'primary.50' : 'grey.50',
cursor: 'pointer',
transition: 'all 0.2s ease',
'&:hover': {
borderColor: 'primary.main',
bgcolor: 'primary.50'
}
}}
>
<input {...getInputProps()} />
<CloudUpload sx={{
fontSize: 64,
color: isDragActive ? 'primary.main' : 'grey.400',
mb: 2
}} />
<Typography variant="h6" gutterBottom>
{isDragActive
? "파일을 여기에 놓으세요!"
: "Excel 파일을 드래그하거나 클릭하여 선택"
}
</Typography>
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
지원 형식: .xlsx, .xls, .csv (최대 10MB)
</Typography>
<Button
variant="contained"
startIcon={<AttachFile />}
component="span"
disabled={uploading}
onClick={() => console.log('파일 선택 버튼 클릭됨')}
>
>
{uploading ? '업로드 중...' : '파일 선택'}
</Button>
</Paper>
</Button>
</Paper>
<Box sx={{ mt: 2 }}>
<Typography variant="body2" color="textSecondary">
<Box sx={{ mt: 2 }}>
<Typography variant="body2" color="textSecondary">
💡 <strong>업로드 분류 프로세스:</strong>
</Typography>
<Typography variant="body2" color="textSecondary">
BOM(Bill of Materials) 파일을 업로드하면 자동으로 자재 정보를 추출합니다
</Typography>
<Typography variant="body2" color="textSecondary">
</Typography>
<Typography variant="body2" color="textSecondary">
BOM(Bill of Materials) 파일을 업로드하면 자동으로 자재 정보를 추출합니다
</Typography>
<Typography variant="body2" color="textSecondary">
자재는 8가지 분류기(볼트, 플랜지, 피팅, 가스켓, 계기, 파이프, 밸브, 재질) 자동 분류됩니다
</Typography>
<Typography variant="body2" color="textSecondary">
분류 결과는 신뢰도 점수와 함께 저장되며, 필요시 수동 검증이 가능합니다
</Typography>
</Box>
</>
</Typography>
</Box>
</>
)}
</Box>
);

View File

@@ -0,0 +1,31 @@
import React from 'react';
import { Card, CardContent, Typography, Box } from '@mui/material';
const PipeDetailsCard = ({ material, fileId }) => {
// 간단한 테스트 버전
return (
<Card sx={{ mt: 2, backgroundColor: '#f5f5f5' }}>
<CardContent>
<Typography variant="h6" gutterBottom>
PIPE 상세 정보 (테스트)
</Typography>
<Box>
<Typography variant="body2">
자재명: {material.original_description}
</Typography>
<Typography variant="body2">
분류: {material.classified_category}
</Typography>
<Typography variant="body2">
사이즈: {material.size_spec || '정보 없음'}
</Typography>
<Typography variant="body2">
수량: {material.quantity} {material.unit}
</Typography>
</Box>
</CardContent>
</Card>
);
};
export default PipeDetailsCard;