// content.js let lastContextMenuPos = null; let tooltipEl = null; let currentKeyword = null; // 현재 검색 키워드 저장 let loadingIndicator = null; // 로딩 인디케이터 요소 // 마우스 위치 추적 let currentMousePos = { x: 0, y: 0 }; document.addEventListener('mousemove', (e) => { currentMousePos = { x: e.pageX, y: e.pageY }; }); document.addEventListener("contextmenu", (e) => { lastContextMenuPos = { x: e.pageX, y: e.pageY }; }); // ESC 키로 모달 닫기 document.addEventListener("keydown", (e) => { if (e.key === "Escape") { if (tooltipEl) removeTooltip(); if (loadingIndicator) removeLoadingIndicator(); } }); // 로딩 인디케이터 생성 및 표시 function showLoadingIndicator(message, position = null) { // 기존 로딩 인디케이터가 있으면 제거 if (loadingIndicator) { removeLoadingIndicator(); } loadingIndicator = document.createElement("div"); loadingIndicator.id = "markinfo-loading"; loadingIndicator.style.cssText = ` position: fixed; z-index: 9999999; background: rgba(0, 0, 0, 0.8); color: white; padding: 12px 20px; border-radius: 8px; font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 14px; font-weight: 500; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); display: flex; align-items: center; gap: 10px; animation: fadeIn 0.3s ease-out; backdrop-filter: blur(4px); border: 1px solid rgba(255, 255, 255, 0.2); `; // 스피너 아이콘 const spinner = document.createElement("div"); spinner.style.cssText = ` width: 16px; height: 16px; border: 2px solid rgba(255, 255, 255, 0.3); border-top: 2px solid white; border-radius: 50%; animation: spin 1s linear infinite; `; // 메시지 텍스트 const messageEl = document.createElement("span"); messageEl.textContent = message; loadingIndicator.appendChild(spinner); loadingIndicator.appendChild(messageEl); // CSS 애니메이션 정의 if (!document.getElementById('markinfo-loading-styles')) { const style = document.createElement('style'); style.id = 'markinfo-loading-styles'; style.textContent = ` @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes fadeIn { 0% { opacity: 0; transform: translateY(-10px); } 100% { opacity: 1; transform: translateY(0); } } @keyframes fadeOut { 0% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(-10px); } } `; document.head.appendChild(style); } document.body.appendChild(loadingIndicator); // 위치 설정 const pos = position || getSelectionPosition() || currentMousePos; positionLoadingIndicator(loadingIndicator, pos); console.log('[content.js] 로딩 인디케이터 표시:', message); } // 로딩 인디케이터 제거 function removeLoadingIndicator() { if (loadingIndicator) { loadingIndicator.style.animation = 'fadeOut 0.3s ease-out'; setTimeout(() => { if (loadingIndicator && loadingIndicator.parentNode) { loadingIndicator.parentNode.removeChild(loadingIndicator); } loadingIndicator = null; }, 300); console.log('[content.js] 로딩 인디케이터 제거'); } } // 선택된 텍스트의 위치 가져오기 function getSelectionPosition() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const range = selection.getRangeAt(0); const rect = range.getBoundingClientRect(); if (rect.width > 0 && rect.height > 0) { return { x: rect.left + window.pageXOffset + rect.width / 2, y: rect.top + window.pageYOffset - 10 }; } } return null; } // 로딩 인디케이터 위치 설정 function positionLoadingIndicator(indicator, pos) { indicator.style.left = (pos.x - 50) + "px"; // 중앙 정렬을 위해 조정 indicator.style.top = (pos.y - 50) + "px"; // 화면 경계 체크 const rect = indicator.getBoundingClientRect(); const docWidth = document.documentElement.clientWidth; const docHeight = document.documentElement.clientHeight; if (rect.right > docWidth) { indicator.style.left = (docWidth - rect.width - 10) + "px"; } if (rect.left < 0) { indicator.style.left = "10px"; } if (rect.bottom > docHeight) { indicator.style.top = (docHeight - rect.height - 10) + "px"; } if (rect.top < 0) { indicator.style.top = "10px"; } } chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { console.log('[content.js] 메시지 수신:', message); // 핑 테스트 응답 if (message.action === "ping") { console.log('[content.js] 핑 메시지 수신, 응답 전송'); sendResponse({ status: "ready" }); return true; } // 로딩 인디케이터 표시 요청 if (message.action === "showLoading") { showLoadingIndicator(message.message, message.position); sendResponse({ success: true }); return true; } // 로딩 인디케이터 제거 요청 if (message.action === "hideLoading") { removeLoadingIndicator(); sendResponse({ success: true }); return true; } if (message.action === "showTooltip") { console.log(`[content.js] showTooltip 메시지 수신, 키워드: ${message.keyword}, 결과 개수: ${message.detailInfo?.length || 0}`); // 로딩 인디케이터 제거 removeLoadingIndicator(); // 현재 키워드 저장 currentKeyword = message.keyword; try { if (!tooltipEl) { tooltipEl = document.createElement("div"); tooltipEl.id = "markinfo-tooltip"; tooltipEl.style.position = "absolute"; tooltipEl.style.zIndex = "999999"; tooltipEl.style.background = "#fff"; tooltipEl.style.border = "1px solid #ccc"; tooltipEl.style.borderRadius = "8px"; tooltipEl.style.boxShadow = "0 4px 12px rgba(0,0,0,0.15)"; tooltipEl.style.fontFamily = "'Roboto', sans-serif"; tooltipEl.style.fontSize = "14px"; tooltipEl.style.color = "#333"; tooltipEl.style.maxWidth = "600px"; tooltipEl.style.maxHeight = "500px"; // flex 컬럼 레이아웃으로 구성 tooltipEl.style.display = "flex"; tooltipEl.style.flexDirection = "column"; // 헤더: 항상 보이는 영역 (sticky) const headerDiv = document.createElement("div"); headerDiv.id = "markinfo-tooltip-header"; headerDiv.style.position = "sticky"; headerDiv.style.top = "0"; headerDiv.style.background = "#fff"; headerDiv.style.padding = "12px 16px"; headerDiv.style.borderBottom = "1px solid #ccc"; headerDiv.style.display = "flex"; headerDiv.style.justifyContent = "space-between"; headerDiv.style.alignItems = "center"; // 헤더 내부: 검색 키워드와 제작자 정보를 수직 정렬 const headerContent = document.createElement("div"); headerContent.style.display = "flex"; headerContent.style.flexDirection = "column"; // 검색 키워드 제목 const titleElem = document.createElement("h2"); titleElem.id = "tooltip-title"; titleElem.style.margin = "0"; titleElem.style.fontSize = "20px"; titleElem.style.color = "#2c3e50"; headerContent.appendChild(titleElem); // 제작자 정보 (작은 글씨) const creatorElem = document.createElement("span"); creatorElem.id = "tooltip-creator"; creatorElem.textContent = "내차는언제타냐: 지재권 검색기 (ESC키로 닫기)"; creatorElem.style.fontSize = "12px"; creatorElem.style.color = "#7f8c8d"; headerContent.appendChild(creatorElem); headerDiv.appendChild(headerContent); // 헤더 버튼 영역 const headerButtons = document.createElement("div"); headerButtons.style.display = "flex"; headerButtons.style.gap = "8px"; // 금지어 추가 버튼 (헤더) const addBannedBtn = document.createElement("button"); addBannedBtn.id = "add-banned-word-btn"; addBannedBtn.textContent = "내 금지어에 추가"; addBannedBtn.style.padding = "6px 12px"; addBannedBtn.style.backgroundColor = "#f39c12"; addBannedBtn.style.color = "#fff"; addBannedBtn.style.border = "none"; addBannedBtn.style.borderRadius = "4px"; addBannedBtn.style.cursor = "pointer"; addBannedBtn.style.fontSize = "12px"; addBannedBtn.onclick = () => addToBannedWords(currentKeyword); headerButtons.appendChild(addBannedBtn); // 내부 닫기 버튼 (헤더 우측) const headerCloseBtn = document.createElement("button"); headerCloseBtn.textContent = "닫기"; headerCloseBtn.style.padding = "6px 10px"; headerCloseBtn.style.backgroundColor = "#e74c3c"; headerCloseBtn.style.color = "#fff"; headerCloseBtn.style.border = "none"; headerCloseBtn.style.borderRadius = "4px"; headerCloseBtn.style.cursor = "pointer"; headerCloseBtn.onclick = removeTooltip; headerButtons.appendChild(headerCloseBtn); headerDiv.appendChild(headerButtons); // 본문 영역 (스크롤 가능) const bodyDiv = document.createElement("div"); bodyDiv.id = "markinfo-tooltip-body"; bodyDiv.style.padding = "16px"; bodyDiv.style.overflowY = "auto"; bodyDiv.style.flex = "1 1 auto"; tooltipEl.appendChild(headerDiv); tooltipEl.appendChild(bodyDiv); document.body.appendChild(tooltipEl); // 글로벌 닫기 버튼 (항상 보이는 우측 상단) ensureGlobalCloseButton(); } // 업데이트: 헤더 제목에 검색 키워드 설정 document.getElementById("tooltip-title").textContent = "검색 키워드: " + message.keyword; renderDetailInfo(message.detailInfo, message.keyword); if (lastContextMenuPos) { positionTooltip(tooltipEl, lastContextMenuPos); } else { tooltipEl.style.top = "10px"; tooltipEl.style.left = "10px"; } console.log('[content.js] 툴팁 표시 완료'); // 성공 응답 전송 sendResponse({ success: true, message: "툴팁이 성공적으로 표시되었습니다." }); } catch (error) { console.error('[content.js] 툴팁 표시 중 오류:', error); // 오류 응답 전송 sendResponse({ success: false, error: error.message }); } // 비동기 응답을 위해 true 반환 return true; } // 멀티번역 결과 표시 if (message.action === "showTranslationTooltip") { console.log(`[content.js] showTranslationTooltip 메시지 수신, 원문: ${message.originalText}, 결과 개수: ${message.results?.length || 0}`); // 로딩 인디케이터 제거 removeLoadingIndicator(); try { showTranslationResults(message.originalText, message.results, message.userLevel); // 성공 응답 전송 sendResponse({ success: true, message: "번역 결과가 성공적으로 표시되었습니다." }); } catch (error) { console.error('[content.js] 번역 결과 표시 중 오류:', error); // 오류 응답 전송 sendResponse({ success: false, error: error.message }); } // 비동기 응답을 위해 true 반환 return true; } }); function positionTooltip(tooltip, pos) { tooltip.style.left = (pos.x + 10) + "px"; tooltip.style.top = (pos.y + 10) + "px"; const rect = tooltip.getBoundingClientRect(); const docWidth = document.documentElement.clientWidth; const docHeight = document.documentElement.clientHeight; if (rect.right > docWidth) { tooltip.style.left = (docWidth - rect.width - 10) + "px"; } if (rect.bottom > docHeight) { tooltip.style.top = (docHeight - rect.height - 10) + "px"; } } function removeTooltip() { if (tooltipEl && tooltipEl.parentNode) { tooltipEl.parentNode.removeChild(tooltipEl); } tooltipEl = null; const globalClose = document.getElementById("tooltip-global-close"); if (globalClose && globalClose.parentNode) { globalClose.parentNode.removeChild(globalClose); } } function ensureGlobalCloseButton() { if (!document.getElementById("tooltip-global-close")) { const btn = document.createElement("button"); btn.id = "tooltip-global-close"; btn.textContent = "닫기"; btn.style.position = "fixed"; btn.style.top = "20px"; btn.style.right = "20px"; btn.style.padding = "8px 12px"; btn.style.backgroundColor = "#e74c3c"; btn.style.color = "#fff"; btn.style.border = "none"; btn.style.borderRadius = "4px"; btn.style.cursor = "pointer"; btn.style.zIndex = "1000000"; btn.onclick = removeTooltip; document.body.appendChild(btn); } } function renderDetailInfo(results, keyword) { // 검색 결과를 전역 변수에 저장 window.currentSearchResults = results; const bodyDiv = document.getElementById("markinfo-tooltip-body"); if (!bodyDiv) return; let html = `
`; // 결과가 없을 경우 안전한 단어 표시 if (results.error) { html += `

오류: ${results.error}

`; } else if (!Array.isArray(results) || results.length === 0) { html += `

지식재산권이 없는 안전한 단어

`; } else { results.forEach((result, idx) => { html += `
`; // 결과 헤더 (제목과 개별 금지어 추가 버튼) html += `
`; html += `

${idx + 1}번 결과

`; // html += ``; html += `
`; // 상세 검색 결과 (출원번호 상세 조회) if (result.detail) { html += `

상세 정보

`; const dreg = result.detail.registration_info; // 상표명 불일치 검사 및 표시 const trademarkName = dreg.trademarkName || "(상표명 없음)"; const isNameMismatch = trademarkName !== "(상표명 없음)" && keyword && trademarkName.toLowerCase() !== keyword.toLowerCase() && !trademarkName.toLowerCase().includes(keyword.toLowerCase()) && !keyword.toLowerCase().includes(trademarkName.toLowerCase()); if (isNameMismatch) { html += `

상표명: ${trademarkName} (불일치-확인필요)

`; } else { html += `

상표명: ${trademarkName}

`; } html += `

출원번호: ${dreg.applicationNum || "(출원번호 없음)"}

`; html += `

출원날짜: ${dreg.applicationDate || "(출원날짜 없음)"}

`; html += `

권리상태: ${dreg.lastDisposalCodeName || "(권리상태 없음)"}

`; html += `

공고번호: ${dreg.publicationNum || "(공고번호 없음)"}

`; html += `

등록번호: ${dreg.registerNum || "(등록번호 없음)"}

`; html += `

권리정보

`; if (result.detail.rights_info && Object.keys(result.detail.rights_info).length > 0) { for (let key in result.detail.rights_info) { html += `

카테고리 코드: ${key}

`; result.detail.rights_info[key].forEach(item => { html += `

- 지정상품명: ${item.asignProductName || ""}

`; html += `

  영문: ${item.asignProductNameEn || ""}

`; html += `

  유사군코드: ${item.similarCodes || ""}

`; }); } } else { html += `

(권리정보 없음)

`; } html += `

출원인 정보

`; if (result.detail.applicant_info && result.detail.applicant_info.mapping) { const mapping = result.detail.applicant_info.mapping; html += `

국가명: ${mapping.nationalCodeName || "(없음)"}

`; html += `

출원인명: ${mapping.applicantName || "(없음)"}

`; } else { html += `

(출원인 정보 없음)

`; } } else if (result.detailError) { html += `

상세 정보 검색 오류: ${result.detailError}

`; } html += `
`; }); } html += `
`; bodyDiv.innerHTML = html; } // 금지어 추가 함수 async function addToBannedWords(keyword) { try { console.log(`[content.js] 금지어 추가 시작: ${keyword}`); // Grade 선택 모달 표시 const selectedGrade = await showGradeSelectionModal(keyword); if (!selectedGrade) { console.log('[content.js] 사용자가 금지어 추가를 취소했습니다.'); return; } // 백그라운드 스크립트에 금지어 추가 요청 chrome.runtime.sendMessage({ action: "addBannedWord", keyword: keyword, grade: selectedGrade, searchResults: getCurrentSearchResults() }, (response) => { if (chrome.runtime.lastError) { console.error('[content.js] 금지어 추가 메시지 전송 실패:', chrome.runtime.lastError); alert('금지어 추가 중 오류가 발생했습니다.'); return; } if (response && response.success) { console.log('[content.js] 금지어 추가 성공'); alert(`"${keyword}"이(가) 금지어 목록에 추가되었습니다. (등급: ${selectedGrade})`); // 금지어 추가 버튼 비활성화 const addBtn = document.getElementById("add-banned-word-btn"); if (addBtn) { addBtn.textContent = "추가 완료"; addBtn.disabled = true; addBtn.style.backgroundColor = "#95a5a6"; addBtn.style.cursor = "not-allowed"; } } else { console.error('[content.js] 금지어 추가 실패:', response?.error); alert(`금지어 추가 실패: ${response?.error || '알 수 없는 오류'}`); } }); } catch (error) { console.error('[content.js] 금지어 추가 중 오류:', error); alert('금지어 추가 중 오류가 발생했습니다.'); } } // Grade 선택 모달 함수 function showGradeSelectionModal(keyword) { return new Promise((resolve) => { // 모달 배경 const modalOverlay = document.createElement('div'); modalOverlay.style.position = 'fixed'; modalOverlay.style.top = '0'; modalOverlay.style.left = '0'; modalOverlay.style.width = '100%'; modalOverlay.style.height = '100%'; modalOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; modalOverlay.style.zIndex = '1000000'; modalOverlay.style.display = 'flex'; modalOverlay.style.justifyContent = 'center'; modalOverlay.style.alignItems = 'center'; // 모달 컨테이너 const modalContainer = document.createElement('div'); modalContainer.style.backgroundColor = '#fff'; modalContainer.style.borderRadius = '8px'; modalContainer.style.padding = '24px'; modalContainer.style.maxWidth = '400px'; modalContainer.style.width = '90%'; modalContainer.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)'; modalContainer.style.fontFamily = "'Roboto', sans-serif"; // 제목 const title = document.createElement('h3'); title.textContent = '금지어 등급 선택'; title.style.margin = '0 0 16px 0'; title.style.color = '#2c3e50'; title.style.fontSize = '18px'; modalContainer.appendChild(title); // 키워드 표시 const keywordLabel = document.createElement('p'); keywordLabel.textContent = `키워드: "${keyword}"`; keywordLabel.style.margin = '0 0 16px 0'; keywordLabel.style.color = '#7f8c8d'; keywordLabel.style.fontSize = '14px'; modalContainer.appendChild(keywordLabel); // 설명 const description = document.createElement('p'); description.textContent = '이 키워드의 금지 등급을 선택해주세요:'; description.style.margin = '0 0 12px 0'; description.style.color = '#34495e'; description.style.fontSize = '14px'; modalContainer.appendChild(description); // Grade 선택 드롭박스 const gradeSelect = document.createElement('select'); gradeSelect.style.width = '100%'; gradeSelect.style.padding = '8px 12px'; gradeSelect.style.border = '1px solid #bdc3c7'; gradeSelect.style.borderRadius = '4px'; gradeSelect.style.fontSize = '14px'; gradeSelect.style.marginBottom = '20px'; // 옵션 추가 const gradeOptions = [ { value: '비허용', text: '비허용(단어제거)' }, { value: '금지', text: '금지(상품금지)' } ]; gradeOptions.forEach(option => { const optionElement = document.createElement('option'); optionElement.value = option.value; optionElement.textContent = option.text; if (option.value === '비허용') { optionElement.selected = true; // 기본값: 비허용 } gradeSelect.appendChild(optionElement); }); modalContainer.appendChild(gradeSelect); // 버튼 컨테이너 const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'flex-end'; buttonContainer.style.gap = '8px'; // 취소 버튼 const cancelButton = document.createElement('button'); cancelButton.textContent = '취소'; cancelButton.style.padding = '8px 16px'; cancelButton.style.backgroundColor = '#95a5a6'; cancelButton.style.color = '#fff'; cancelButton.style.border = 'none'; cancelButton.style.borderRadius = '4px'; cancelButton.style.cursor = 'pointer'; cancelButton.style.fontSize = '14px'; cancelButton.onclick = () => { document.body.removeChild(modalOverlay); resolve(null); // 취소 }; // 확인 버튼 const confirmButton = document.createElement('button'); confirmButton.textContent = '추가'; confirmButton.style.padding = '8px 16px'; confirmButton.style.backgroundColor = '#f39c12'; confirmButton.style.color = '#fff'; confirmButton.style.border = 'none'; confirmButton.style.borderRadius = '4px'; confirmButton.style.cursor = 'pointer'; confirmButton.style.fontSize = '14px'; confirmButton.onclick = () => { const selectedGrade = gradeSelect.value; document.body.removeChild(modalOverlay); resolve(selectedGrade); }; buttonContainer.appendChild(cancelButton); buttonContainer.appendChild(confirmButton); modalContainer.appendChild(buttonContainer); // ESC 키로 닫기 const handleKeyDown = (e) => { if (e.key === 'Escape') { document.body.removeChild(modalOverlay); document.removeEventListener('keydown', handleKeyDown); resolve(null); } }; document.addEventListener('keydown', handleKeyDown); modalOverlay.appendChild(modalContainer); document.body.appendChild(modalOverlay); // 드롭박스에 포커스 gradeSelect.focus(); }); } // 현재 검색 결과 데이터 가져오기 function getCurrentSearchResults() { // 현재 표시된 검색 결과 데이터를 반환 // 이 데이터는 renderDetailInfo에서 사용된 results와 동일해야 함 return window.currentSearchResults || []; } // 번역 결과 모달 표시 function showTranslationResults(originalText, results, userLevel) { console.log('[content.js] 번역 결과 표시 시작'); let translationTooltip = document.getElementById("translation-tooltip"); if (!translationTooltip) { translationTooltip = document.createElement("div"); translationTooltip.id = "translation-tooltip"; translationTooltip.style.position = "fixed"; translationTooltip.style.zIndex = "9999999"; translationTooltip.style.background = "#fff"; translationTooltip.style.border = "2px solid #3498db"; translationTooltip.style.borderRadius = "12px"; translationTooltip.style.boxShadow = "0 8px 24px rgba(0,0,0,0.2)"; translationTooltip.style.fontFamily = "'Roboto', sans-serif"; translationTooltip.style.fontSize = "14px"; translationTooltip.style.color = "#333"; translationTooltip.style.minWidth = "400px"; translationTooltip.style.maxWidth = "800px"; translationTooltip.style.maxHeight = "600px"; translationTooltip.style.display = "flex"; translationTooltip.style.flexDirection = "column"; // 헤더 const header = document.createElement("div"); header.style.background = "linear-gradient(135deg, #3498db, #2980b9)"; header.style.color = "#fff"; header.style.padding = "16px 20px"; header.style.borderRadius = "10px 10px 0 0"; header.style.display = "flex"; header.style.justifyContent = "space-between"; header.style.alignItems = "center"; // 헤더 내용 const headerContent = document.createElement("div"); const titleElem = document.createElement("h2"); titleElem.style.margin = "0"; titleElem.style.fontSize = "18px"; titleElem.textContent = "멀티번역 결과"; headerContent.appendChild(titleElem); const subtitleElem = document.createElement("div"); subtitleElem.style.fontSize = "12px"; subtitleElem.style.opacity = "0.9"; subtitleElem.style.marginTop = "4px"; subtitleElem.textContent = `회원등급: ${userLevel || 'Basic'} | ESC키로 닫기`; headerContent.appendChild(subtitleElem); header.appendChild(headerContent); // 닫기 버튼 const closeBtn = document.createElement("button"); closeBtn.textContent = "×"; closeBtn.style.background = "none"; closeBtn.style.border = "2px solid #fff"; closeBtn.style.color = "#fff"; closeBtn.style.borderRadius = "50%"; closeBtn.style.width = "30px"; closeBtn.style.height = "30px"; closeBtn.style.cursor = "pointer"; closeBtn.style.fontSize = "18px"; closeBtn.style.lineHeight = "1"; closeBtn.onclick = removeTranslationTooltip; header.appendChild(closeBtn); // 본문 const body = document.createElement("div"); body.id = "translation-body"; body.style.padding = "20px"; body.style.overflowY = "auto"; body.style.flex = "1 1 auto"; translationTooltip.appendChild(header); translationTooltip.appendChild(body); document.body.appendChild(translationTooltip); // ESC 키로 닫기 document.addEventListener("keydown", function(e) { if (e.key === "Escape") { removeTranslationTooltip(); } }); } // 본문 업데이트 renderTranslationResults(originalText, results, userLevel); // 위치 설정 (화면 중앙) translationTooltip.style.top = "50%"; translationTooltip.style.left = "50%"; translationTooltip.style.transform = "translate(-50%, -50%)"; console.log('[content.js] 번역 결과 표시 완료'); } // 번역 결과 렌더링 function renderTranslationResults(originalText, results, userLevel) { const body = document.getElementById("translation-body"); if (!body) return; let html = ''; // 원문 표시 html += `

원문

${originalText}

`; // 번역 결과가 있을 경우 if (results && results.length > 0) { html += '
'; results.forEach((result, index) => { const engineName = getEngineDisplayName(result.engine); const isSuccess = result.success; // 각 번역 결과 카드 html += `

${engineName}

${isSuccess ? '성공' : '실패'}
${isSuccess ? `

${result.translatedText}

` : `

${result.error || '번역 실패'}

` }
`; }); html += '
'; } else { // 번역 결과가 없는 경우 html += `

번역 결과가 없습니다.

다시 시도해 주세요.

`; } // 회원등급별 가이드 메시지 html += `

💡 ${userLevel || 'Basic'} 회원으로 이용 중입니다. ${getUserLevelGuide(userLevel)}

`; body.innerHTML = html; } // 엔진 이름 표시용 변환 function getEngineDisplayName(engine) { const displayNames = { 'google': '구글 번역', 'deepl': 'DeepL', 'openai': 'ChatGPT', 'gemini': 'Google Gemini', 'mymemory': 'MyMemory' }; return displayNames[engine] || engine; } // 회원등급별 가이드 메시지 function getUserLevelGuide(userLevel) { const normalizedLevel = (userLevel || 'basic').toLowerCase(); switch(normalizedLevel) { case 'vip': return '모든 번역 엔진을 이용할 수 있습니다!'; case 'premium': return '무료 번역과 DeepL을 이용할 수 있습니다. VIP로 업그레이드하면 ChatGPT, Gemini도 이용 가능합니다.'; case 'basic': default: return '현재 무료 번역만 이용 가능합니다. 프리미엄 회원으로 업그레이드하면 더 많은 번역 엔진을 이용할 수 있습니다.'; } } // 번역 툴팁 제거 function removeTranslationTooltip() { const translationTooltip = document.getElementById("translation-tooltip"); if (translationTooltip) { translationTooltip.remove(); console.log('[content.js] 번역 툴팁 제거됨'); } }