첨부파일 기능 완료

This commit is contained in:
leeheejin 2025-12-11 15:46:05 +09:00
parent 99fd8336a5
commit a489e2c155
3 changed files with 56 additions and 7 deletions

View File

@ -32,7 +32,7 @@ export const uploadFiles = async (params: {
files: FileList | File[];
tableName?: string;
fieldName?: string;
recordId?: string;
recordId?: string | number;
docType?: string;
docTypeName?: string;
targetObjid?: string;
@ -43,6 +43,7 @@ export const uploadFiles = async (params: {
columnName?: string;
isVirtualFileColumn?: boolean;
companyCode?: string; // 🔒 멀티테넌시: 회사 코드
isRecordMode?: boolean; // 🆕 레코드 모드 플래그
}): Promise<FileUploadResponse> => {
const formData = new FormData();
@ -55,7 +56,7 @@ export const uploadFiles = async (params: {
// 추가 파라미터들 추가
if (params.tableName) formData.append("tableName", params.tableName);
if (params.fieldName) formData.append("fieldName", params.fieldName);
if (params.recordId) formData.append("recordId", params.recordId);
if (params.recordId) formData.append("recordId", String(params.recordId));
if (params.docType) formData.append("docType", params.docType);
if (params.docTypeName) formData.append("docTypeName", params.docTypeName);
if (params.targetObjid) formData.append("targetObjid", params.targetObjid);
@ -66,6 +67,8 @@ export const uploadFiles = async (params: {
if (params.columnName) formData.append("columnName", params.columnName);
if (params.isVirtualFileColumn !== undefined) formData.append("isVirtualFileColumn", params.isVirtualFileColumn.toString());
if (params.companyCode) formData.append("companyCode", params.companyCode); // 🔒 멀티테넌시
// 🆕 레코드 모드 플래그 추가 (백엔드에서 attachments 컬럼 자동 업데이트용)
if (params.isRecordMode !== undefined) formData.append("isRecordMode", params.isRecordMode.toString());
const response = await apiClient.post("/files/upload", formData, {
headers: {

View File

@ -603,10 +603,16 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
targetObjid,
});
// 🔑 레코드 모드일 때는 effectiveTableName을 우선 사용
// formData.linkedTable이 'screen_files' 같은 기본값일 수 있으므로 레코드 모드에서는 무시
const finalLinkedTable = effectiveIsRecordMode
? effectiveTableName
: (formData?.linkedTable || effectiveTableName);
const uploadData = {
// 🎯 formData에서 백엔드 API 설정 가져오기
autoLink: formData?.autoLink || true,
linkedTable: formData?.linkedTable || effectiveTableName,
linkedTable: finalLinkedTable,
recordId: effectiveRecordId || `temp_${component.id}`,
columnName: effectiveColumnName,
isVirtualFileColumn: formData?.isVirtualFileColumn || true,
@ -620,13 +626,27 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
// 🆕 레코드 모드 플래그
isRecordMode: effectiveIsRecordMode,
};
console.log("📤 [FileUploadComponent] uploadData 최종:", {
isRecordMode: effectiveIsRecordMode,
linkedTable: finalLinkedTable,
recordId: effectiveRecordId,
columnName: effectiveColumnName,
targetObjid,
});
console.log("🚀 [FileUploadComponent] uploadFiles API 호출 직전:", {
filesCount: filesToUpload.length,
uploadData,
});
const response = await uploadFiles({
files: filesToUpload,
...uploadData,
});
console.log("📥 [FileUploadComponent] uploadFiles API 응답:", response);
if (response.success) {
// FileUploadResponse 타입에 맞게 files 배열 사용

View File

@ -1683,6 +1683,19 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
// console.log(` - uniqueItemNumbers: ${JSON.stringify(uniqueItemNumbers)}`);
// console.log(` - isDuplicated: ${itemNumbers.length !== uniqueItemNumbers.length}`);
// 🔍 디버그: attachments 컬럼 데이터 확인
if (response.data && response.data.length > 0) {
const firstRow = response.data[0];
if ('attachments' in firstRow) {
console.log("📎 [TableList] attachments 데이터 확인:", {
tableName: tableConfig.selectedTable,
firstRowAttachments: firstRow.attachments,
type: typeof firstRow.attachments,
isArray: Array.isArray(firstRow.attachments),
});
}
}
setData(response.data || []);
setTotalPages(response.totalPages || 0);
setTotalItems(response.total || 0);
@ -3971,17 +3984,30 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
}
// 📎 첨부파일 타입: 파일 아이콘과 개수 표시
if (inputType === "file" || inputType === "attachment" || column.columnName === "attachments") {
// 컬럼명이 'attachments'를 포함하거나, inputType이 file/attachment인 경우
const isAttachmentColumn =
inputType === "file" ||
inputType === "attachment" ||
column.columnName === "attachments" ||
column.columnName?.toLowerCase().includes("attachment") ||
column.columnName?.toLowerCase().includes("file");
if (isAttachmentColumn) {
// JSONB 배열 또는 JSON 문자열 파싱
let files: any[] = [];
try {
if (typeof value === "string") {
files = JSON.parse(value);
if (typeof value === "string" && value.trim()) {
const parsed = JSON.parse(value);
files = Array.isArray(parsed) ? parsed : [];
} else if (Array.isArray(value)) {
files = value;
} else if (value && typeof value === "object") {
// 단일 객체인 경우 배열로 변환
files = [value];
}
} catch {
} catch (e) {
// 파싱 실패 시 빈 배열
console.warn("📎 [TableList] 첨부파일 파싱 실패:", { columnName: column.columnName, value, error: e });
}
if (!files || files.length === 0) {