diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-10-30 09:52:25 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-10-30 09:52:25 +0000 |
| commit | 0f9976751134107dfa53f68dd361f0d66836d37e (patch) | |
| tree | f55c7bb1c966c99ae7d54c25d74fd56d53dfdad2 /lib | |
| parent | 9462d93d01ad51d58b22921a1a0a509cf9768299 (diff) | |
(임수민) 기본계약문서 자동 서명란 수정
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/basic-contract/viewer/basic-contract-sign-viewer.tsx | 227 |
1 files changed, 103 insertions, 124 deletions
diff --git a/lib/basic-contract/viewer/basic-contract-sign-viewer.tsx b/lib/basic-contract/viewer/basic-contract-sign-viewer.tsx index b6024b29..246c5200 100644 --- a/lib/basic-contract/viewer/basic-contract-sign-viewer.tsx +++ b/lib/basic-contract/viewer/basic-contract-sign-viewer.tsx @@ -127,89 +127,63 @@ class AutoSignatureFieldDetector { private async createSignatureFieldAtText(searchText: string): Promise<string | null> { const { Core } = this.instance; - const { documentViewer, annotationManager } = Core; - const document = documentViewer.getDocument(); - - if (!document) return null; - + const { documentViewer, annotationManager, Annotations } = Core; + const doc = documentViewer.getDocument(); + if (!doc) return null; + try { - // 모든 페이지에서 텍스트 검색 - const searchMode = Core.Search.Mode.PAGE_STOP | Core.Search.Mode.HIGHLIGHT; - const searchOptions = { - fullSearch: true, - onResult: null, - }; - - // 텍스트 검색 시작 - const textSearchIterator = await document.getTextSearchIterator(); - textSearchIterator.begin(searchText, searchMode); - - let searchResult = await textSearchIterator.next(); - - // 검색 결과가 있는 경우 - if (searchResult && searchResult.resultCode === Core.Search.ResultCode.FOUND) { - const pageNumber = searchResult.pageNum; - const quads = searchResult.quads; - - if (quads && quads.length > 0) { - // 첫 번째 검색 결과의 위치 가져오기 - const quad = quads[0]; - - // 쿼드의 좌표를 기반으로 서명 필드 위치 계산 - const x = Math.min(quad.x1, quad.x2, quad.x3, quad.x4); - const y = Math.min(quad.y1, quad.y2, quad.y3, quad.y4); - const textWidth = Math.abs(quad.x2 - quad.x1); - const textHeight = Math.abs(quad.y3 - quad.y1); - - // 서명 필드 생성 - const fieldName = `signature_at_text_${Date.now()}`; - const flags = new Core.Annotations.WidgetFlags(); - flags.set('Required', true); - - const field = new Core.Annotations.Forms.Field(fieldName, { - type: 'Sig', - flags - }); - - const widget = new Core.Annotations.SignatureWidgetAnnotation(field, { - Width: 150, - Height: 50 - }); - - widget.setPageNumber(pageNumber); - - // 텍스트 바로 아래 또는 오른쪽에 서명 필드 배치 - // 옵션 1: 텍스트 바로 아래 - widget.setX(x); - widget.setY(y + textHeight + 5); // 텍스트 아래 5픽셀 간격 - - // 옵션 2: 텍스트 오른쪽 (필요시 아래 주석 해제) - // widget.setX(x + textWidth + 10); // 텍스트 오른쪽 10픽셀 간격 - // widget.setY(y); - - widget.setWidth(150); - widget.setHeight(50); - - // 필드 매니저에 추가 - const fm = annotationManager.getFieldManager(); - fm.addField(field); - annotationManager.addAnnotation(widget); - annotationManager.drawAnnotationsFromList([widget]); - - console.log(`📌 서명 필드를 페이지 ${pageNumber}의 "${searchText}" 위치에 생성`); - - return fieldName; - } + const pageCount = documentViewer.getPageCount(); + + for (let pageNumber = 1; pageNumber <= pageCount; pageNumber++) { + // 1) 페이지 텍스트 로드 + const pageText = await doc.loadPageText(pageNumber); + + // 2) 해당 페이지에서 검색어 위치 찾기 (첫 매치만 사용) + const startIndex = pageText.indexOf(searchText); + if (startIndex === -1) continue; + + const endIndex = startIndex + searchText.length; + + // 3) 검색어의 문자 단위 Quads 얻기 + const quads = await doc.getTextPosition(pageNumber, startIndex, endIndex); + if (!quads || quads.length === 0) continue; + + // 첫 글자의 quad만 사용해 대략적인 위치 산출 + const q = quads[0]; + const x = Math.min(q.x1, q.x2, q.x3, q.x4); + const y = Math.min(q.y1, q.y2, q.y3, q.y4); + const textHeight = Math.abs(q.y3 - q.y1); + + // 4) 서명 필드 생성 + const fieldName = `signature_at_text_${Date.now()}`; + const flags = new Annotations.WidgetFlags(); + flags.set('Required', true); + + const field = new Core.Annotations.Forms.Field(fieldName, { type: 'Sig', flags }); + const widget = new Annotations.SignatureWidgetAnnotation(field, { Width: 150, Height: 50 }); + + widget.setPageNumber(pageNumber); + // 텍스트 바로 아래에 배치 (필요하면 오른쪽 배치로 바꿀 수 있음) + widget.setX(x); + widget.setY(y + textHeight + 5); + widget.setWidth(150); + widget.setHeight(50); + + const fm = annotationManager.getFieldManager(); + fm.addField(field); + annotationManager.addAnnotation(widget); + annotationManager.drawAnnotationsFromList([widget]); + + return fieldName; } - - console.log(`⚠️ "${searchText}" 텍스트를 찾을 수 없음`); + + // 모든 페이지에서 못 찾으면 null return null; - - } catch (error) { - console.error(`📛 텍스트 검색 중 오류: ${error}`); + } catch (e) { + console.error('텍스트 기반 서명 필드 생성 중 오류', e); return null; } - } + } private async createSimpleSignatureField(): Promise<string> { const { Core } = this.instance; @@ -259,56 +233,61 @@ class AutoSignatureFieldDetector { const applyBuyerSignatureAutomatically = async (instance: WebViewerInstance) => { const { Core } = instance; - const { documentViewer, annotationManager } = Core; - const document = documentViewer.getDocument(); - - if (!document) return; + const { documentViewer, annotationManager, Annotations } = Core; + const doc = documentViewer.getDocument(); + if (!doc) return; try { - console.log('🔍 구매자 서명란 자동 서명 시작...'); - - // "삼성중공업_서명란" 텍스트 검색 - const searchText = '삼성중공업_서명란'; - const textSearchIterator = await document.getTextSearchIterator(); - textSearchIterator.begin(searchText, Core.Search.Mode.PAGE_STOP | Core.Search.Mode.HIGHLIGHT); - - let searchResult = await textSearchIterator.next(); - - if (searchResult && searchResult.resultCode === Core.Search.ResultCode.FOUND) { - const pageNumber = searchResult.pageNum; - const quads = searchResult.quads; - - if (quads && quads.length > 0) { - const quad = quads[0]; - const x = Math.min(quad.x1, quad.x2, quad.x3, quad.x4); - const y = Math.min(quad.y1, quad.y2, quad.y3, quad.y4); - const textHeight = Math.abs(quad.y3 - quad.y1); - - // 구매자 서명 이미지 가져오기 - const buyerSignature = await getBuyerSignatureFileWithFallback(); - - if (buyerSignature) { - // 스탬프 어노테이션 생성 - const stamp = new Core.Annotations.StampAnnotation(); - stamp.PageNumber = pageNumber; - stamp.X = x; - stamp.Y = y + textHeight + 5; // 텍스트 아래 5픽셀 - stamp.Width = 150; - stamp.Height = 50; - - await stamp.setImageData(buyerSignature.data.dataUrl); - - // 어노테이션 추가 - annotationManager.addAnnotation(stamp); - annotationManager.drawAnnotationsFromList([stamp]); - - console.log('✅ 구매자 서명 자동 적용 완료'); - toast.info('삼성중공업 서명이 자동으로 적용되었습니다.', { - duration: 3000 - }); - } + console.log('🔍 구매자 자동 서명: "삼성중공업_서명란"만 검색'); + + const TARGET = '삼성중공업_서명란'; // ✅ 정확히 이 문자열만 허용 + const pageCount = documentViewer.getPageCount(); + + for (let pageNumber = 1; pageNumber <= pageCount; pageNumber++) { + const pageText = await doc.loadPageText(pageNumber); + if (!pageText) continue; + + const startIndex = pageText.indexOf(TARGET); + if (startIndex === -1) continue; + + const endIndex = startIndex + TARGET.length; + + // 문자 쿼드 → 바운딩 박스 + const quads = await doc.getTextPosition(pageNumber, startIndex, endIndex); + if (!quads?.length) continue; + + const xs: number[] = [], ys: number[] = []; + quads.forEach(q => { xs.push(q.x1, q.x2, q.x3, q.x4); ys.push(q.y1, q.y2, q.y3, q.y4); }); + const minX = Math.min(...xs), maxY = Math.max(...ys); + + // 텍스트 바로 아래에 스탬프(서명 이미지) 배치 + const widgetX = minX; + const widgetY = maxY + 5; + const widgetW = 150; + const widgetH = 50; + + const buyerSignature = await getBuyerSignatureFileWithFallback(); // 기존 프로젝트 함수 그대로 사용 + if (!buyerSignature?.data?.dataUrl) { + console.warn('⚠️ 구매자 서명 이미지가 없습니다.'); + return; } + + const stamp = new Annotations.StampAnnotation(); + stamp.PageNumber = pageNumber; + stamp.X = widgetX; + stamp.Y = widgetY; + stamp.Width = widgetW; + stamp.Height = widgetH; + await stamp.setImageData(buyerSignature.data.dataUrl); + + annotationManager.addAnnotation(stamp); + annotationManager.drawAnnotationsFromList([stamp]); + + console.log('✅ "삼성중공업_서명란" 위치에 자동 서명 적용 완료'); + return; // 첫 매치만 처리 } + + console.warn('⚠️ 문서에서 "삼성중공업_서명란"을 찾지 못했습니다.'); } catch (error) { console.error('구매자 자동 서명 처리 실패:', error); } |
