파일 컴포넌트 분리

This commit is contained in:
kjs
2025-09-05 21:52:19 +09:00
parent e0fd624078
commit d73be8a4d3
21 changed files with 1999 additions and 556 deletions

View File

@@ -1292,8 +1292,10 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
try {
console.log("📥 파일 다운로드 시작:", fileInfo);
// serverFilename이 없는 경우 처리
if (!fileInfo.serverFilename) {
// serverFilename이 없는 경우 파일 경로에서 추출 시도
const serverFilename = fileInfo.serverFilename || (fileInfo.path ? fileInfo.path.split("/").pop() : null);
if (!serverFilename) {
// _file 속성이 있는 경우 로컬 파일로 다운로드
if ((fileInfo as any)._file) {
console.log("📁 로컬 파일 다운로드 시도:", fileInfo.name);
@@ -1337,8 +1339,8 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
toast.loading(`${fileInfo.name} 다운로드 중...`);
await downloadFile({
fileId: fileInfo.id,
serverFilename: fileInfo.serverFilename,
fileId: fileInfo.objid || fileInfo.id,
serverFilename: serverFilename,
originalName: fileInfo.name,
});
@@ -1367,39 +1369,94 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
// file_path 컬럼은 강제로 파일 타입으로 처리 (임시 해결책)
const isFileColumn = column.widgetType === "file" || column.columnName === "file_path";
switch (column.widgetType) {
case "file":
console.log("🗂️ 파일 타입 컬럼 처리 중:", value);
if (value) {
try {
// file_path 컬럼도 파일 타입으로 처리
if (isFileColumn) {
console.log("🗂️ 파일 타입 컬럼 처리 중:", value);
if (value) {
try {
let fileData;
// 파일 경로 문자열인지 확인 (/uploads/로 시작하는 경우)
if (typeof value === "string" && value.startsWith("/uploads/")) {
// 파일 경로 문자열인 경우 단일 파일로 처리
const fileName = value.split("/").pop() || "파일";
const fileExt = fileName.split(".").pop()?.toLowerCase() || "";
fileData = {
files: [
{
name: fileName.replace(/^\d+_/, ""), // 타임스탬프 제거
path: value,
objid: Date.now().toString(), // 임시 objid
size: 0, // 크기 정보 없음
type:
fileExt === "jpg" || fileExt === "jpeg"
? "image/jpeg"
: fileExt === "png"
? "image/png"
: fileExt === "gif"
? "image/gif"
: fileExt === "pdf"
? "application/pdf"
: "application/octet-stream",
extension: fileExt,
regdate: new Date().toISOString(), // 등록일 추가
writer: "시스템", // 기본 등록자
},
],
totalCount: 1,
totalSize: 0,
regdate: new Date().toISOString(), // 파일 데이터 전체에도 등록일 추가
};
} else {
// JSON 문자열이면 파싱
const fileData = typeof value === "string" ? JSON.parse(value) : value;
console.log("📁 파싱된 파일 데이터:", fileData);
fileData = typeof value === "string" ? JSON.parse(value) : value;
if (fileData?.files && Array.isArray(fileData.files) && fileData.files.length > 0) {
return (
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
className="h-8 px-2 text-blue-600 hover:bg-blue-50 hover:text-blue-800"
onClick={() => openFileModal(fileData, column)}
>
<File className="mr-1 h-4 w-4" />
{fileData.totalCount === 1 ? "파일 1개" : `파일 ${fileData.totalCount}`}
</Button>
<Badge variant="secondary" className="text-xs">
{(fileData.totalSize / 1024 / 1024).toFixed(1)}MB
</Badge>
</div>
);
// regdate가 없는 경우 기본값 설정
if (!fileData.regdate) {
fileData.regdate = new Date().toISOString();
}
} catch (error) {
console.warn("파일 데이터 파싱 오류:", error);
}
}
return <span className="text-sm text-gray-400 italic"> </span>;
// 개별 파일들에도 regdate와 writer가 없는 경우 추가
if (fileData.files && Array.isArray(fileData.files)) {
fileData.files.forEach((file: any) => {
if (!file.regdate) {
file.regdate = new Date().toISOString();
}
if (!file.writer) {
file.writer = "시스템";
}
});
}
}
console.log("📁 파싱된 파일 데이터:", fileData);
if (fileData?.files && Array.isArray(fileData.files) && fileData.files.length > 0) {
return (
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
className="h-8 px-2 text-blue-600 hover:bg-blue-50 hover:text-blue-800"
onClick={() => openFileModal(fileData, column)}
>
<File className="mr-1 h-4 w-4" />
{fileData.totalCount === 1 ? "파일 1개" : `파일 ${fileData.totalCount}`}
</Button>
<Badge variant="secondary" className="text-xs">
{(fileData.totalSize / 1024 / 1024).toFixed(1)}MB
</Badge>
</div>
);
}
} catch (error) {
console.warn("파일 데이터 파싱 오류:", error);
}
}
return <span className="text-sm text-gray-400 italic"> </span>;
}
switch (column.widgetType) {
case "date":
if (value) {
try {
@@ -1840,14 +1897,11 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
<span>: {fileInfo.type || "알 수 없음"}</span>
</div>
<div className="flex items-center gap-4">
<span>: {fileInfo.extension || "N/A"}</span>
<span>: {new Date(fileInfo.uploadedAt).toLocaleString("ko-KR")}</span>
{fileInfo.regdate && (
<span>: {new Date(fileInfo.regdate).toLocaleString("ko-KR")}</span>
)}
{fileInfo.writer && <span>: {fileInfo.writer}</span>}
</div>
{fileInfo.lastModified && (
<div>
<span>: {new Date(fileInfo.lastModified).toLocaleString("ko-KR")}</span>
</div>
)}
</div>
</div>
@@ -1896,11 +1950,6 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
{" "}
{(currentFileData.totalSize / 1024 / 1024).toFixed(2)} MB
</div>
<div className="col-span-2">
<span className="font-medium"> :</span>
{" "}
{new Date(currentFileData.lastModified).toLocaleString("ko-KR")}
</div>
</div>
</div>
)}