Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into lhj
; Please enter a commit message to explain why this merge is necessary, ; especially if it merges an updated upstream into a topic branch. ; ; Lines starting with ';' will be ignored, and an empty message aborts ; the commit.
This commit is contained in:
commit
6c75adb61d
|
|
@ -370,32 +370,13 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// 모드 전환 핸들러
|
// 모드 전환 핸들러
|
||||||
const handleModeSwitch = async () => {
|
const handleModeSwitch = () => {
|
||||||
if (isAdminMode) {
|
if (isAdminMode) {
|
||||||
// 관리자 → 사용자 모드: 선택한 회사 유지
|
// 관리자 → 사용자 모드: 선택한 회사 유지
|
||||||
router.push("/main");
|
router.push("/main");
|
||||||
} else {
|
} else {
|
||||||
// 사용자 → 관리자 모드: WACE로 복귀 필요 (SUPER_ADMIN만)
|
// 사용자 → 관리자 모드: 선택한 회사 유지 (회사 전환 없음)
|
||||||
if ((user as ExtendedUserInfo)?.userType === "SUPER_ADMIN") {
|
router.push("/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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -415,8 +415,10 @@ export const EmbeddedScreen = forwardRef<EmbeddedScreenHandle, EmbeddedScreenPro
|
||||||
maxWidth: `calc(100% - ${compPosition.x || 0}px)`,
|
maxWidth: `calc(100% - ${compPosition.x || 0}px)`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🆕 formDataVersion을 key에서 제거하여 불필요한 remount 방지
|
||||||
|
// universal-form-modal 같은 컴포넌트가 채번 후 unmount되는 문제 해결
|
||||||
return (
|
return (
|
||||||
<div key={`${component.id}-${formDataVersion}`} className="absolute" style={componentStyle}>
|
<div key={component.id} className="absolute" style={componentStyle}>
|
||||||
<DynamicComponentRenderer
|
<DynamicComponentRenderer
|
||||||
component={component}
|
component={component}
|
||||||
isInteractive={true}
|
isInteractive={true}
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,12 @@ export function UniversalFormModalComponent({
|
||||||
|
|
||||||
// 초기화 - 최초 마운트 시 또는 initialData가 변경되었을 때 실행
|
// 초기화 - 최초 마운트 시 또는 initialData가 변경되었을 때 실행
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log("[UniversalFormModal] useEffect 시작", {
|
||||||
|
initialData,
|
||||||
|
hasInitialized: hasInitialized.current,
|
||||||
|
lastInitializedId: lastInitializedId.current,
|
||||||
|
});
|
||||||
|
|
||||||
// initialData에서 ID 값 추출 (id, ID, objid 등)
|
// initialData에서 ID 값 추출 (id, ID, objid 등)
|
||||||
const currentId = initialData?.id || initialData?.ID || initialData?.objid;
|
const currentId = initialData?.id || initialData?.ID || initialData?.objid;
|
||||||
const currentIdString = currentId !== undefined ? String(currentId) : undefined;
|
const currentIdString = currentId !== undefined ? String(currentId) : undefined;
|
||||||
|
|
@ -229,9 +235,20 @@ export function UniversalFormModalComponent({
|
||||||
if (hasInitialized.current && lastInitializedId.current === currentIdString) {
|
if (hasInitialized.current && lastInitializedId.current === currentIdString) {
|
||||||
// 생성 모드에서 데이터가 새로 전달된 경우는 재초기화 필요
|
// 생성 모드에서 데이터가 새로 전달된 경우는 재초기화 필요
|
||||||
if (!createModeDataHash || capturedInitialData.current) {
|
if (!createModeDataHash || capturedInitialData.current) {
|
||||||
|
console.log("[UniversalFormModal] 초기화 스킵 - 이미 초기화됨");
|
||||||
|
// 🆕 채번 플래그가 true인데 formData에 값이 없으면 재생성 필요
|
||||||
|
// (컴포넌트 remount로 인해 state가 초기화된 경우)
|
||||||
return;
|
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가 변경된 경우 재초기화
|
// 🆕 수정 모드: initialData에 데이터가 있으면서 ID가 변경된 경우 재초기화
|
||||||
if (hasInitialized.current && currentIdString && lastInitializedId.current !== currentIdString) {
|
if (hasInitialized.current && currentIdString && lastInitializedId.current !== currentIdString) {
|
||||||
|
|
@ -252,6 +269,7 @@ export function UniversalFormModalComponent({
|
||||||
console.log("[UniversalFormModal] 초기 데이터 캡처:", capturedInitialData.current);
|
console.log("[UniversalFormModal] 초기 데이터 캡처:", capturedInitialData.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("[UniversalFormModal] initializeForm 호출 예정");
|
||||||
hasInitialized.current = true;
|
hasInitialized.current = true;
|
||||||
initializeForm();
|
initializeForm();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
|
@ -389,6 +407,94 @@ export function UniversalFormModalComponent({
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [config.sections]);
|
}, [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 () => {
|
const initializeForm = useCallback(async () => {
|
||||||
console.log("[initializeForm] 시작");
|
console.log("[initializeForm] 시작");
|
||||||
|
|
@ -585,82 +691,6 @@ export function UniversalFormModalComponent({
|
||||||
return item;
|
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(
|
const handleFieldChange = useCallback(
|
||||||
(columnName: string, value: any) => {
|
(columnName: string, value: any) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue