From a489e2c1553b3e24bb104b23e2efeaf108cdf001 Mon Sep 17 00:00:00 2001 From: leeheejin Date: Thu, 11 Dec 2025 15:46:05 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B2=A8=EB=B6=80=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/api/file.ts | 7 ++-- .../file-upload/FileUploadComponent.tsx | 22 +++++++++++- .../table-list/TableListComponent.tsx | 34 ++++++++++++++++--- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/frontend/lib/api/file.ts b/frontend/lib/api/file.ts index 318f26fb..4908b381 100644 --- a/frontend/lib/api/file.ts +++ b/frontend/lib/api/file.ts @@ -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 => { 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: { diff --git a/frontend/lib/registry/components/file-upload/FileUploadComponent.tsx b/frontend/lib/registry/components/file-upload/FileUploadComponent.tsx index 805fe755..dd4f4c6b 100644 --- a/frontend/lib/registry/components/file-upload/FileUploadComponent.tsx +++ b/frontend/lib/registry/components/file-upload/FileUploadComponent.tsx @@ -603,10 +603,16 @@ const FileUploadComponent: React.FC = ({ 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 = ({ // ๐Ÿ†• ๋ ˆ์ฝ”๋“œ ๋ชจ๋“œ ํ”Œ๋ž˜๊ทธ 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 ๋ฐฐ์—ด ์‚ฌ์šฉ diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index f68b8383..a12bf494 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -1683,6 +1683,19 @@ export const TableListComponent: React.FC = ({ // 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 = ({ } // ๐Ÿ“Ž ์ฒจ๋ถ€ํŒŒ์ผ ํƒ€์ž…: ํŒŒ์ผ ์•„์ด์ฝ˜๊ณผ ๊ฐœ์ˆ˜ ํ‘œ์‹œ - 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) {