데이터 테이블 첨부파일 연계

This commit is contained in:
kjs
2025-09-06 00:16:27 +09:00
parent d73be8a4d3
commit 0b38f349aa
10 changed files with 1015 additions and 166 deletions

View File

@@ -7,16 +7,23 @@ import { Checkbox } from "@/components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { Badge } from "@/components/ui/badge";
import { FileComponent } from "@/types/screen";
import { FileComponent, TableInfo } from "@/types/screen";
import { Plus, X } from "lucide-react";
import { Button } from "@/components/ui/button";
interface FileComponentConfigPanelProps {
component: FileComponent;
onUpdateProperty: (componentId: string, path: string, value: any) => void;
currentTable?: TableInfo; // 현재 화면의 테이블 정보
currentTableName?: string; // 현재 화면의 테이블명
}
export const FileComponentConfigPanel: React.FC<FileComponentConfigPanelProps> = ({ component, onUpdateProperty }) => {
export const FileComponentConfigPanel: React.FC<FileComponentConfigPanelProps> = ({
component,
onUpdateProperty,
currentTable,
currentTableName,
}) => {
// 로컬 상태
const [localInputs, setLocalInputs] = useState({
docType: component.fileConfig.docType || "DOCUMENT",
@@ -25,12 +32,15 @@ export const FileComponentConfigPanel: React.FC<FileComponentConfigPanelProps> =
maxSize: component.fileConfig.maxSize || 10,
maxFiles: component.fileConfig.maxFiles || 5,
newAcceptType: "", // 새 파일 타입 추가용
linkedTable: component.fileConfig.linkedTable || "", // 연결 테이블
linkedField: component.fileConfig.linkedField || "", // 연결 필드
});
const [localValues, setLocalValues] = useState({
multiple: component.fileConfig.multiple ?? true,
showPreview: component.fileConfig.showPreview ?? true,
showProgress: component.fileConfig.showProgress ?? true,
autoLink: component.fileConfig.autoLink ?? false, // 자동 연결
});
const [acceptTypes, setAcceptTypes] = useState<string[]>(component.fileConfig.accept || []);
@@ -44,12 +54,15 @@ export const FileComponentConfigPanel: React.FC<FileComponentConfigPanelProps> =
maxSize: component.fileConfig.maxSize || 10,
maxFiles: component.fileConfig.maxFiles || 5,
newAcceptType: "",
linkedTable: component.fileConfig.linkedTable || "",
linkedField: component.fileConfig.linkedField || "",
});
setLocalValues({
multiple: component.fileConfig.multiple ?? true,
showPreview: component.fileConfig.showPreview ?? true,
showProgress: component.fileConfig.showProgress ?? true,
autoLink: component.fileConfig.autoLink ?? false,
});
setAcceptTypes(component.fileConfig.accept || []);
@@ -332,6 +345,114 @@ export const FileComponentConfigPanel: React.FC<FileComponentConfigPanelProps> =
<Label htmlFor="showProgress"> </Label>
</div>
</div>
{/* 테이블 연결 설정 섹션 */}
<div className="mt-6 rounded-lg border bg-blue-50 p-4">
<h4 className="mb-3 text-sm font-semibold text-blue-900">📎 </h4>
<div className="space-y-3">
<div className="flex items-center space-x-2">
<Checkbox
id="autoLink"
checked={localValues.autoLink}
onCheckedChange={(checked) => {
setLocalValues((prev) => ({ ...prev, autoLink: checked as boolean }));
onUpdateProperty(component.id, "fileConfig.autoLink", checked);
// 자동 연결이 활성화되면 현재 화면의 테이블 정보를 자동 설정
if (checked && currentTableName && currentTable) {
// 기본키 추정 로직 (일반적인 패턴들)
const primaryKeyGuesses = [
`${currentTableName}_id`, // table_name + "_id"
`${currentTableName.replace(/_/g, "")}_id`, // undercore 제거 + "_id"
currentTableName.endsWith("_info") || currentTableName.endsWith("_mng")
? currentTableName.replace(/_(info|mng)$/, "_code") // _info, _mng -> _code
: `${currentTableName}_code`, // table_name + "_code"
"id", // 단순 "id"
"objid", // "objid"
];
// 실제 테이블 컬럼에서 기본키로 추정되는 컬럼 찾기
let detectedPrimaryKey = "";
for (const guess of primaryKeyGuesses) {
const foundColumn = currentTable.columns.find(
(col) => col.columnName.toLowerCase() === guess.toLowerCase(),
);
if (foundColumn) {
detectedPrimaryKey = foundColumn.columnName;
break;
}
}
// 찾지 못한 경우 첫 번째 컬럼을 기본키로 사용
if (!detectedPrimaryKey && currentTable.columns.length > 0) {
detectedPrimaryKey = currentTable.columns[0].columnName;
}
console.log("🔗 자동 테이블 연결 설정:", {
tableName: currentTableName,
detectedPrimaryKey,
availableColumns: currentTable.columns.map((c) => c.columnName),
});
// 자동으로 테이블명과 기본키 설정
setLocalInputs((prev) => ({
...prev,
linkedTable: currentTableName,
linkedField: detectedPrimaryKey,
}));
onUpdateProperty(component.id, "fileConfig.linkedTable", currentTableName);
onUpdateProperty(component.id, "fileConfig.linkedField", detectedPrimaryKey);
}
}}
/>
<Label htmlFor="autoLink"> </Label>
</div>
{localValues.autoLink && (
<>
<div className="space-y-2">
<Label htmlFor="linkedTable"> </Label>
<Input
id="linkedTable"
value={localInputs.linkedTable}
readOnly
className="bg-gray-50 text-gray-700"
placeholder="자동으로 설정됩니다"
/>
<div className="text-xs text-green-600"> </div>
</div>
<div className="space-y-2">
<Label htmlFor="linkedField"> ()</Label>
<Input
id="linkedField"
value={localInputs.linkedField}
readOnly
className="bg-gray-50 text-gray-700"
placeholder="자동으로 감지됩니다"
/>
<div className="text-xs text-green-600"> </div>
</div>
<div className="rounded bg-blue-100 p-2 text-xs text-blue-600">
💡 .
<br />
{currentTableName && localInputs.linkedField ? (
<>
: {currentTableName} {localInputs.linkedField} "값123"
<br />
target_objid가 "{currentTableName}:값123" .
</>
) : (
<> .</>
)}
</div>
</>
)}
</div>
</div>
</div>
</div>
);