Merge branch 'feature/screen-management' of http://39.117.244.52:3000/kjs/ERP-node into feature/screen-management
This commit is contained in:
commit
12baad75c9
|
|
@ -370,32 +370,13 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|||
};
|
||||
|
||||
// 모드 전환 핸들러
|
||||
const handleModeSwitch = async () => {
|
||||
const handleModeSwitch = () => {
|
||||
if (isAdminMode) {
|
||||
// 관리자 → 사용자 모드: 선택한 회사 유지
|
||||
router.push("/main");
|
||||
} else {
|
||||
// 사용자 → 관리자 모드: WACE로 복귀 필요 (SUPER_ADMIN만)
|
||||
if ((user as ExtendedUserInfo)?.userType === "SUPER_ADMIN") {
|
||||
const currentCompanyCode = (user as ExtendedUserInfo)?.companyCode;
|
||||
|
||||
// 이미 WACE("*")가 아니면 WACE로 전환 후 관리자 페이지로 이동
|
||||
if (currentCompanyCode !== "*") {
|
||||
const result = await switchCompany("*");
|
||||
if (result.success) {
|
||||
// 페이지 새로고침 (관리자 페이지로 이동)
|
||||
window.location.href = "/admin";
|
||||
} else {
|
||||
toast.error("WACE로 전환 실패");
|
||||
}
|
||||
} else {
|
||||
// 이미 WACE면 바로 관리자 페이지로 이동
|
||||
router.push("/admin");
|
||||
}
|
||||
} else {
|
||||
// 일반 관리자는 바로 관리자 페이지로 이동
|
||||
router.push("/admin");
|
||||
}
|
||||
// 사용자 → 관리자 모드: 선택한 회사 유지 (회사 전환 없음)
|
||||
router.push("/admin");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -415,8 +415,10 @@ export const EmbeddedScreen = forwardRef<EmbeddedScreenHandle, EmbeddedScreenPro
|
|||
maxWidth: `calc(100% - ${compPosition.x || 0}px)`,
|
||||
};
|
||||
|
||||
// 🆕 formDataVersion을 key에서 제거하여 불필요한 remount 방지
|
||||
// universal-form-modal 같은 컴포넌트가 채번 후 unmount되는 문제 해결
|
||||
return (
|
||||
<div key={`${component.id}-${formDataVersion}`} className="absolute" style={componentStyle}>
|
||||
<div key={component.id} className="absolute" style={componentStyle}>
|
||||
<DynamicComponentRenderer
|
||||
component={component}
|
||||
isInteractive={true}
|
||||
|
|
|
|||
|
|
@ -216,6 +216,12 @@ export function UniversalFormModalComponent({
|
|||
|
||||
// 초기화 - 최초 마운트 시 또는 initialData가 변경되었을 때 실행
|
||||
useEffect(() => {
|
||||
console.log("[UniversalFormModal] useEffect 시작", {
|
||||
initialData,
|
||||
hasInitialized: hasInitialized.current,
|
||||
lastInitializedId: lastInitializedId.current,
|
||||
});
|
||||
|
||||
// initialData에서 ID 값 추출 (id, ID, objid 등)
|
||||
const currentId = initialData?.id || initialData?.ID || initialData?.objid;
|
||||
const currentIdString = currentId !== undefined ? String(currentId) : undefined;
|
||||
|
|
@ -229,9 +235,20 @@ export function UniversalFormModalComponent({
|
|||
if (hasInitialized.current && lastInitializedId.current === currentIdString) {
|
||||
// 생성 모드에서 데이터가 새로 전달된 경우는 재초기화 필요
|
||||
if (!createModeDataHash || capturedInitialData.current) {
|
||||
console.log("[UniversalFormModal] 초기화 스킵 - 이미 초기화됨");
|
||||
// 🆕 채번 플래그가 true인데 formData에 값이 없으면 재생성 필요
|
||||
// (컴포넌트 remount로 인해 state가 초기화된 경우)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 🆕 컴포넌트 remount 감지: hasInitialized가 true인데 formData가 비어있으면 재초기화
|
||||
// (React의 Strict Mode나 EmbeddedScreen 리렌더링으로 인한 remount)
|
||||
if (hasInitialized.current && !currentIdString) {
|
||||
console.log("[UniversalFormModal] 컴포넌트 remount 감지 - 채번 플래그 초기화");
|
||||
numberingGeneratedRef.current = false;
|
||||
isGeneratingRef.current = false;
|
||||
}
|
||||
|
||||
// 🆕 수정 모드: initialData에 데이터가 있으면서 ID가 변경된 경우 재초기화
|
||||
if (hasInitialized.current && currentIdString && lastInitializedId.current !== currentIdString) {
|
||||
|
|
@ -252,6 +269,7 @@ export function UniversalFormModalComponent({
|
|||
console.log("[UniversalFormModal] 초기 데이터 캡처:", capturedInitialData.current);
|
||||
}
|
||||
|
||||
console.log("[UniversalFormModal] initializeForm 호출 예정");
|
||||
hasInitialized.current = true;
|
||||
initializeForm();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -389,6 +407,94 @@ export function UniversalFormModalComponent({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [config.sections]);
|
||||
|
||||
// 채번규칙 자동 생성 (중복 호출 방지)
|
||||
// 중요: initializeForm에서 호출되므로 반드시 initializeForm보다 먼저 선언해야 함
|
||||
const numberingGeneratedRef = useRef(false);
|
||||
const isGeneratingRef = useRef(false); // 진행 중 플래그 추가
|
||||
|
||||
const generateNumberingValues = useCallback(
|
||||
async (currentFormData: FormDataState) => {
|
||||
// 이미 생성되었거나 진행 중이면 스킵
|
||||
if (numberingGeneratedRef.current) {
|
||||
console.log("[채번] 이미 생성됨 - 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGeneratingRef.current) {
|
||||
console.log("[채번] 생성 진행 중 - 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
isGeneratingRef.current = true; // 진행 중 표시
|
||||
console.log("[채번] 생성 시작", { sectionsCount: config.sections.length });
|
||||
|
||||
const updatedData = { ...currentFormData };
|
||||
let hasChanges = false;
|
||||
|
||||
for (const section of config.sections) {
|
||||
console.log("[채번] 섹션 검사:", section.title, { type: section.type, repeatable: section.repeatable, fieldsCount: section.fields?.length });
|
||||
if (section.repeatable || section.type === "table") continue;
|
||||
|
||||
for (const field of (section.fields || [])) {
|
||||
// generateOnOpen은 기본값 true (undefined일 경우 true로 처리)
|
||||
const shouldGenerateOnOpen = field.numberingRule?.generateOnOpen !== false;
|
||||
console.log("[채번] 필드 검사:", field.columnName, {
|
||||
hasNumberingRule: !!field.numberingRule,
|
||||
enabled: field.numberingRule?.enabled,
|
||||
generateOnOpen: field.numberingRule?.generateOnOpen,
|
||||
shouldGenerateOnOpen,
|
||||
ruleId: field.numberingRule?.ruleId,
|
||||
currentValue: updatedData[field.columnName],
|
||||
});
|
||||
if (
|
||||
field.numberingRule?.enabled &&
|
||||
shouldGenerateOnOpen &&
|
||||
field.numberingRule?.ruleId &&
|
||||
!updatedData[field.columnName]
|
||||
) {
|
||||
try {
|
||||
console.log(`[채번 미리보기 API 호출] ${field.columnName}, ruleId: ${field.numberingRule.ruleId}`);
|
||||
// generateOnOpen: 미리보기만 표시 (DB 시퀀스 증가 안 함)
|
||||
const response = await previewNumberingCode(field.numberingRule.ruleId);
|
||||
if (response.success && response.data?.generatedCode) {
|
||||
updatedData[field.columnName] = response.data.generatedCode;
|
||||
|
||||
// 저장 시 실제 할당을 위해 ruleId 저장 (TextInput과 동일한 키 형식)
|
||||
const ruleIdKey = `${field.columnName}_numberingRuleId`;
|
||||
updatedData[ruleIdKey] = field.numberingRule.ruleId;
|
||||
|
||||
hasChanges = true;
|
||||
numberingGeneratedRef.current = true; // 생성 완료 표시
|
||||
console.log(
|
||||
`[채번 미리보기 완료] ${field.columnName} = ${response.data.generatedCode} (저장 시 실제 할당)`,
|
||||
);
|
||||
console.log(`[채번 규칙 ID 저장] ${ruleIdKey} = ${field.numberingRule.ruleId}`);
|
||||
|
||||
// 부모 컴포넌트에도 ruleId 전달 (ModalRepeaterTable → ScreenModal)
|
||||
if (onChange) {
|
||||
onChange({
|
||||
...updatedData,
|
||||
[ruleIdKey]: field.numberingRule.ruleId,
|
||||
});
|
||||
console.log(`[채번] 부모에게 ruleId 전달: ${ruleIdKey}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`채번규칙 미리보기 실패 (${field.columnName}):`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isGeneratingRef.current = false; // 진행 완료
|
||||
|
||||
if (hasChanges) {
|
||||
setFormData(updatedData);
|
||||
}
|
||||
},
|
||||
[config, onChange],
|
||||
);
|
||||
|
||||
// 폼 초기화
|
||||
const initializeForm = useCallback(async () => {
|
||||
console.log("[initializeForm] 시작");
|
||||
|
|
@ -585,82 +691,6 @@ export function UniversalFormModalComponent({
|
|||
return item;
|
||||
};
|
||||
|
||||
// 채번규칙 자동 생성 (중복 호출 방지)
|
||||
const numberingGeneratedRef = useRef(false);
|
||||
const isGeneratingRef = useRef(false); // 진행 중 플래그 추가
|
||||
|
||||
const generateNumberingValues = useCallback(
|
||||
async (currentFormData: FormDataState) => {
|
||||
// 이미 생성되었거나 진행 중이면 스킵
|
||||
if (numberingGeneratedRef.current) {
|
||||
console.log("[채번] 이미 생성됨 - 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGeneratingRef.current) {
|
||||
console.log("[채번] 생성 진행 중 - 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
isGeneratingRef.current = true; // 진행 중 표시
|
||||
console.log("[채번] 생성 시작");
|
||||
|
||||
const updatedData = { ...currentFormData };
|
||||
let hasChanges = false;
|
||||
|
||||
for (const section of config.sections) {
|
||||
if (section.repeatable || section.type === "table") continue;
|
||||
|
||||
for (const field of (section.fields || [])) {
|
||||
if (
|
||||
field.numberingRule?.enabled &&
|
||||
field.numberingRule?.generateOnOpen &&
|
||||
field.numberingRule?.ruleId &&
|
||||
!updatedData[field.columnName]
|
||||
) {
|
||||
try {
|
||||
console.log(`[채번 미리보기 API 호출] ${field.columnName}, ruleId: ${field.numberingRule.ruleId}`);
|
||||
// generateOnOpen: 미리보기만 표시 (DB 시퀀스 증가 안 함)
|
||||
const response = await previewNumberingCode(field.numberingRule.ruleId);
|
||||
if (response.success && response.data?.generatedCode) {
|
||||
updatedData[field.columnName] = response.data.generatedCode;
|
||||
|
||||
// 저장 시 실제 할당을 위해 ruleId 저장 (TextInput과 동일한 키 형식)
|
||||
const ruleIdKey = `${field.columnName}_numberingRuleId`;
|
||||
updatedData[ruleIdKey] = field.numberingRule.ruleId;
|
||||
|
||||
hasChanges = true;
|
||||
numberingGeneratedRef.current = true; // 생성 완료 표시
|
||||
console.log(
|
||||
`[채번 미리보기 완료] ${field.columnName} = ${response.data.generatedCode} (저장 시 실제 할당)`,
|
||||
);
|
||||
console.log(`[채번 규칙 ID 저장] ${ruleIdKey} = ${field.numberingRule.ruleId}`);
|
||||
|
||||
// 부모 컴포넌트에도 ruleId 전달 (ModalRepeaterTable → ScreenModal)
|
||||
if (onChange) {
|
||||
onChange({
|
||||
...updatedData,
|
||||
[ruleIdKey]: field.numberingRule.ruleId,
|
||||
});
|
||||
console.log(`[채번] 부모에게 ruleId 전달: ${ruleIdKey}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`채번규칙 미리보기 실패 (${field.columnName}):`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isGeneratingRef.current = false; // 진행 완료
|
||||
|
||||
if (hasChanges) {
|
||||
setFormData(updatedData);
|
||||
}
|
||||
},
|
||||
[config, onChange],
|
||||
);
|
||||
|
||||
// 필드 값 변경 핸들러
|
||||
const handleFieldChange = useCallback(
|
||||
(columnName: string, value: any) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue