dev #46
|
|
@ -899,6 +899,18 @@ export class TableManagementService {
|
|||
if (search && Object.keys(search).length > 0) {
|
||||
for (const [column, value] of Object.entries(search)) {
|
||||
if (value !== null && value !== undefined && value !== "") {
|
||||
// 🎯 추가 조인 컬럼들은 실제 테이블 컬럼이 아니므로 제외
|
||||
const additionalJoinColumns = [
|
||||
"company_code_status",
|
||||
"writer_dept_code",
|
||||
];
|
||||
if (additionalJoinColumns.includes(column)) {
|
||||
logger.info(
|
||||
`🔍 추가 조인 컬럼 ${column} 검색 조건에서 제외 (실제 테이블 컬럼 아님)`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 안전한 컬럼명 검증 (SQL 인젝션 방지)
|
||||
const safeColumn = column.replace(/[^a-zA-Z0-9_]/g, "");
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
const [displayColumns, setDisplayColumns] = useState<ColumnConfig[]>([]); // 🎯 표시할 컬럼 (Entity 조인 적용됨)
|
||||
const [columnMeta, setColumnMeta] = useState<Record<string, { webType?: string; codeCategory?: string }>>({}); // 🎯 컬럼 메타정보 (웹타입, 코드카테고리)
|
||||
// 🎯 Entity 조인 최적화 훅 사용
|
||||
const { isOptimizing, metrics, optimizedConvertCode, getCacheStatus } = useEntityJoinOptimization(columnMeta, {
|
||||
const { optimizedConvertCode } = useEntityJoinOptimization(columnMeta, {
|
||||
enableBatchLoading: true,
|
||||
preloadCommonCodes: true,
|
||||
maxBatchSize: 5,
|
||||
|
|
@ -572,39 +572,6 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* 성능 상태 표시 (개발 모드에서만) */}
|
||||
{process.env.NODE_ENV === "development" && (
|
||||
<div className="flex items-center space-x-2 text-xs text-gray-500">
|
||||
{isOptimizing && (
|
||||
<div className="flex items-center space-x-1">
|
||||
<RefreshCw className="h-3 w-3 animate-spin" />
|
||||
<span>최적화 중</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center space-x-1">
|
||||
<span>캐시:</span>
|
||||
<span
|
||||
className={cn(
|
||||
"rounded px-1 py-0.5 font-mono text-xs",
|
||||
metrics.cacheHitRate > 0.8
|
||||
? "bg-green-100 text-green-700"
|
||||
: metrics.cacheHitRate > 0.5
|
||||
? "bg-yellow-100 text-yellow-700"
|
||||
: "bg-red-100 text-red-700",
|
||||
)}
|
||||
>
|
||||
{(metrics.cacheHitRate * 100).toFixed(1)}%
|
||||
</span>
|
||||
</div>
|
||||
{metrics.averageResponseTime > 0 && (
|
||||
<div className="flex items-center space-x-1">
|
||||
<span>응답:</span>
|
||||
<span className="font-mono text-xs">{metrics.averageResponseTime}ms</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 새로고침 */}
|
||||
<Button variant="outline" size="sm" onClick={handleRefresh} disabled={loading}>
|
||||
<RefreshCw className={cn("h-4 w-4", loading && "animate-spin")} />
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export const TableListDefinition = createComponentDefinition({
|
|||
filter: {
|
||||
enabled: true,
|
||||
quickSearch: true,
|
||||
showColumnSelector: true, // 검색컬럼 선택기 표시 기본값
|
||||
advancedFilter: false,
|
||||
filterableColumns: [],
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue