diff --git a/frontend/index.html b/frontend/index.html index f6bf2d6..dfb2d60 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -83,16 +83,16 @@

字幕容器 (container)

- +
- - 85% + + 0%
- +
@@ -124,7 +124,7 @@
- +
@@ -165,7 +165,7 @@
- +
@@ -206,7 +206,7 @@
- +
@@ -247,7 +247,7 @@
- +
diff --git a/frontend/scripts/main.js b/frontend/scripts/main.js index edfea53..b00b1c2 100644 --- a/frontend/scripts/main.js +++ b/frontend/scripts/main.js @@ -391,13 +391,14 @@ function applyCaptionStyle() { return; } - captionContainer.style.backgroundColor = hexToRgba( - elements.containerBgColor.value, - elements.containerBgOpacity.value / 100 - ); - captionContainer.style.borderColor = elements.containerBorderColor.value; - captionContainer.style.borderRadius = `${elements.containerBorderRadius.value}px`; - captionContainer.style.padding = `${elements.containerPadding.value}px`; + const containerStyles = { + backgroundColor: hexToRgba(elements.containerBgColor.value, elements.containerBgOpacity.value / 100), + borderColor: elements.containerBorderColor.value, + borderRadius: `${elements.containerBorderRadius.value}px`, + padding: `${elements.containerPadding.value}px` + }; + + Object.assign(captionContainer.style, containerStyles); const tipEl = captionContainer.querySelector('.layout-hub-tip'); if (tipEl) { @@ -405,10 +406,7 @@ function applyCaptionStyle() { tipEl.style.fontWeight = elements.tipFontWeight.value; tipEl.style.color = elements.tipColor.value; tipEl.style.lineHeight = elements.tipLineHeight.value; - tipEl.style.backgroundColor = hexToRgba( - elements.tipBgColor.value, - elements.tipBgOpacity.value / 100 - ); + tipEl.style.backgroundColor = hexToRgba(elements.tipBgColor.value, elements.tipBgOpacity.value / 100); tipEl.style.borderRadius = `${elements.tipBorderRadius.value}px`; tipEl.style.padding = `${elements.tipPadding.value}px`; } @@ -419,10 +417,7 @@ function applyCaptionStyle() { item.style.fontWeight = elements.messageFontWeight.value; item.style.color = elements.messageColor.value; item.style.lineHeight = elements.messageLineHeight.value; - item.style.backgroundColor = hexToRgba( - elements.messageBgColor.value, - elements.messageBgOpacity.value / 100 - ); + item.style.backgroundColor = hexToRgba(elements.messageBgColor.value, elements.messageBgOpacity.value / 100); item.style.borderRadius = `${elements.messageBorderRadius.value}px`; item.style.padding = `${elements.messagePadding.value}px`; }); @@ -433,10 +428,7 @@ function applyCaptionStyle() { hotTitleEl.style.fontWeight = elements.hotTitleFontWeight.value; hotTitleEl.style.color = elements.hotTitleColor.value; hotTitleEl.style.lineHeight = elements.hotTitleLineHeight.value; - hotTitleEl.style.backgroundColor = hexToRgba( - elements.hotTitleBgColor.value, - elements.hotTitleBgOpacity.value / 100 - ); + hotTitleEl.style.backgroundColor = hexToRgba(elements.hotTitleBgColor.value, elements.hotTitleBgOpacity.value / 100); hotTitleEl.style.borderRadius = `${elements.hotTitleBorderRadius.value}px`; hotTitleEl.style.padding = `${elements.hotTitlePadding.value}px`; } @@ -447,10 +439,7 @@ function applyCaptionStyle() { hotIssuesEl.style.fontWeight = elements.hotIssuesFontWeight.value; hotIssuesEl.style.color = elements.hotIssuesColor.value; hotIssuesEl.style.lineHeight = elements.hotIssuesLineHeight.value; - hotIssuesEl.style.backgroundColor = hexToRgba( - elements.hotIssuesBgColor.value, - elements.hotIssuesBgOpacity.value / 100 - ); + hotIssuesEl.style.backgroundColor = hexToRgba(elements.hotIssuesBgColor.value, elements.hotIssuesBgOpacity.value / 100); hotIssuesEl.style.borderRadius = `${elements.hotIssuesBorderRadius.value}px`; hotIssuesEl.style.padding = `${elements.hotIssuesPadding.value}px`; } @@ -458,6 +447,153 @@ function applyCaptionStyle() { logger.info('字幕样式已应用'); } +function updateSingleStyle(inputId) { + const captionContainer = document.querySelector('.caption-container-hub'); + if (!captionContainer) return; + + const updateMap = { + containerBgColor: () => { + captionContainer.style.backgroundColor = hexToRgba(elements.containerBgColor.value, elements.containerBgOpacity.value / 100); + }, + containerBgOpacity: () => { + captionContainer.style.backgroundColor = hexToRgba(elements.containerBgColor.value, elements.containerBgOpacity.value / 100); + }, + containerBorderColor: () => { + captionContainer.style.borderColor = elements.containerBorderColor.value; + }, + containerBorderRadius: () => { + captionContainer.style.borderRadius = `${elements.containerBorderRadius.value}px`; + }, + containerPadding: () => { + captionContainer.style.padding = `${elements.containerPadding.value}px`; + }, + tipFontSize: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.fontSize = `${elements.tipFontSize.value}px`; + }, + tipFontWeight: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.fontWeight = elements.tipFontWeight.value; + }, + tipColor: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.color = elements.tipColor.value; + }, + tipLineHeight: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.lineHeight = elements.tipLineHeight.value; + }, + tipBgColor: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.backgroundColor = hexToRgba(elements.tipBgColor.value, elements.tipBgOpacity.value / 100); + }, + tipBgOpacity: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.backgroundColor = hexToRgba(elements.tipBgColor.value, elements.tipBgOpacity.value / 100); + }, + tipBorderRadius: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.borderRadius = `${elements.tipBorderRadius.value}px`; + }, + tipPadding: () => { + const el = captionContainer.querySelector('.layout-hub-tip'); + if (el) el.style.padding = `${elements.tipPadding.value}px`; + }, + messageFontSize: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.fontSize = `${elements.messageFontSize.value}px`); + }, + messageFontWeight: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.fontWeight = elements.messageFontWeight.value); + }, + messageColor: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.color = elements.messageColor.value); + }, + messageLineHeight: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.lineHeight = elements.messageLineHeight.value); + }, + messageBgColor: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.backgroundColor = hexToRgba(elements.messageBgColor.value, elements.messageBgOpacity.value / 100)); + }, + messageBgOpacity: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.backgroundColor = hexToRgba(elements.messageBgColor.value, elements.messageBgOpacity.value / 100)); + }, + messageBorderRadius: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.borderRadius = `${elements.messageBorderRadius.value}px`); + }, + messagePadding: () => { + captionContainer.querySelectorAll('.message-item .item-content').forEach(el => el.style.padding = `${elements.messagePadding.value}px`); + }, + hotTitleFontSize: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.fontSize = `${elements.hotTitleFontSize.value}px`; + }, + hotTitleFontWeight: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.fontWeight = elements.hotTitleFontWeight.value; + }, + hotTitleColor: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.color = elements.hotTitleColor.value; + }, + hotTitleLineHeight: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.lineHeight = elements.hotTitleLineHeight.value; + }, + hotTitleBgColor: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.backgroundColor = hexToRgba(elements.hotTitleBgColor.value, elements.hotTitleBgOpacity.value / 100); + }, + hotTitleBgOpacity: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.backgroundColor = hexToRgba(elements.hotTitleBgColor.value, elements.hotTitleBgOpacity.value / 100); + }, + hotTitleBorderRadius: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.borderRadius = `${elements.hotTitleBorderRadius.value}px`; + }, + hotTitlePadding: () => { + const el = captionContainer.querySelector('.layout-hub-hot-title'); + if (el) el.style.padding = `${elements.hotTitlePadding.value}px`; + }, + hotIssuesFontSize: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.fontSize = `${elements.hotIssuesFontSize.value}px`; + }, + hotIssuesFontWeight: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.fontWeight = elements.hotIssuesFontWeight.value; + }, + hotIssuesColor: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.color = elements.hotIssuesColor.value; + }, + hotIssuesLineHeight: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.lineHeight = elements.hotIssuesLineHeight.value; + }, + hotIssuesBgColor: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.backgroundColor = hexToRgba(elements.hotIssuesBgColor.value, elements.hotIssuesBgOpacity.value / 100); + }, + hotIssuesBgOpacity: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.backgroundColor = hexToRgba(elements.hotIssuesBgColor.value, elements.hotIssuesBgOpacity.value / 100); + }, + hotIssuesBorderRadius: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.borderRadius = `${elements.hotIssuesBorderRadius.value}px`; + }, + hotIssuesPadding: () => { + const el = captionContainer.querySelector('.layout-hub-hot-issues'); + if (el) el.style.padding = `${elements.hotIssuesPadding.value}px`; + } + }; + + if (updateMap[inputId]) { + updateMap[inputId](); + } +} + function hexToRgba(hex, alpha) { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); @@ -475,23 +611,32 @@ function loadCaptionStyleFromContainer() { const containerRadius = containerStyles.borderRadius; const containerPad = containerStyles.padding; - if (containerBg && containerBg !== 'transparent') { + if (containerBg) { const rgbaMatch = containerBg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/); if (rgbaMatch) { elements.containerBgColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3])); - elements.containerBgOpacity.value = rgbaMatch[4] ? Math.round(parseFloat(rgbaMatch[4]) * 100) : 100; + if (rgbaMatch[4]) { + elements.containerBgOpacity.value = Math.round(parseFloat(rgbaMatch[4]) * 100); + } + } else if (containerBg === 'transparent' || containerBg === 'rgba(0, 0, 0, 0)') { + elements.containerBgColor.value = '#000000'; + elements.containerBgOpacity.value = 0; } } - if (containerBorder && containerBorder !== 'transparent' && containerBorder !== 'rgba(0, 0, 0, 0)') { + if (containerBorder) { const rgbaMatch = containerBorder.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/); if (rgbaMatch) { elements.containerBorderColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3])); } } - elements.containerBorderRadius.value = parseInt(containerRadius) || 8; - elements.containerPadding.value = parseInt(containerPad) || 10; + if (containerRadius) { + elements.containerBorderRadius.value = parseInt(containerRadius) || 8; + } + if (containerPad) { + elements.containerPadding.value = parseInt(containerPad) || 10; + } updateRangeValue(elements.containerBgOpacity); @@ -504,39 +649,66 @@ function loadCaptionStyleFromContainer() { sections.forEach(section => { const el = captionContainer.querySelector(section.selector); - if (!el) return; + if (!el) { + logger.warn(`loadCaptionStyleFromContainer: 元素 ${section.selector} 未找到`); + return; + } const styles = window.getComputedStyle(el); - section.elements.fontSize.value = parseInt(styles.fontSize) || 14; - section.elements.fontWeight.value = styles.fontWeight === 'bold' ? 'bold' : 'normal'; - section.elements.color.value = parseColor(styles.color); - section.elements.lineHeight.value = parseFloat(styles.lineHeight) || 1.5; - if (styles.backgroundColor && styles.backgroundColor !== 'transparent') { - const rgbaMatch = styles.backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/); - if (rgbaMatch) { - section.elements.bgColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3])); - section.elements.bgOpacity.value = rgbaMatch[4] ? Math.round(parseFloat(rgbaMatch[4]) * 100) : 100; + if (styles.fontSize) { + section.elements.fontSize.value = parseInt(styles.fontSize) || 14; + } + if (styles.fontWeight) { + section.elements.fontWeight.value = styles.fontWeight === 'bold' || styles.fontWeight === '700' ? 'bold' : 'normal'; + } + if (styles.color) { + const parsedColor = parseColor(styles.color); + if (parsedColor) { + section.elements.color.value = parsedColor; } } - section.elements.borderRadius.value = parseInt(styles.borderRadius) || 4; - section.elements.padding.value = parseInt(styles.padding) || 6; + if (styles.backgroundColor && styles.backgroundColor !== 'transparent' && styles.backgroundColor !== 'rgba(0, 0, 0, 0)') { + const rgbaMatch = styles.backgroundColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/); + if (rgbaMatch) { + section.elements.bgColor.value = rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3])); + if (rgbaMatch[4]) { + section.elements.bgOpacity.value = Math.round(parseFloat(rgbaMatch[4]) * 100); + } + } + } - updateRangeValue(section.elements.bgOpacity); + if (styles.borderRadius) { + section.elements.borderRadius.value = parseInt(styles.borderRadius) || 4; + } + if (styles.padding) { + section.elements.padding.value = parseInt(styles.padding) || 6; + } + + if (section.elements.bgOpacity) { + updateRangeValue(section.elements.bgOpacity); + } }); logger.info('已从字幕容器加载样式'); } function parseColor(colorStr) { - if (!colorStr) return '#ffffff'; + if (!colorStr) return null; if (colorStr.startsWith('#')) return colorStr; + + const rgbMatch = colorStr.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/); + if (rgbMatch) { + return rgbToHex(parseInt(rgbMatch[1]), parseInt(rgbMatch[2]), parseInt(rgbMatch[3])); + } + const rgbaMatch = colorStr.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/); if (rgbaMatch) { return rgbToHex(parseInt(rgbaMatch[1]), parseInt(rgbaMatch[2]), parseInt(rgbaMatch[3])); } - return '#ffffff'; + + return null; } function rgbToHex(r, g, b) { @@ -657,6 +829,9 @@ function initCaptionDragAndResize(container) { logger.info('字幕容器拖拽和缩放已启用'); } +let captionStyleObserver = null; +let captionStyleApplied = false; + function watchCaptionContainer() { const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { @@ -670,6 +845,11 @@ function watchCaptionContainer() { captionContainer.style.zIndex = '9999'; initCaptionDragAndResize(captionContainer); loadCaptionStyleFromContainer(); + if (captionStyleApplied) { + setTimeout(applyCaptionStyle, 100); + } + } else if (captionContainer && captionStyleApplied) { + setTimeout(applyCaptionStyle, 100); } } } @@ -687,6 +867,30 @@ function watchCaptionContainer() { logger.info('已启动字幕容器监听'); } +function watchCaptionContentChanges() { + const captionContainer = document.querySelector('.caption-container-hub'); + if (!captionContainer) return; + + if (captionStyleObserver) { + captionStyleObserver.disconnect(); + } + + captionStyleObserver = new MutationObserver(() => { + if (captionStyleApplied) { + setTimeout(applyCaptionStyle, 50); + } + }); + + captionStyleObserver.observe(captionContainer, { + childList: true, + subtree: true, + attributes: true, + attributeFilter: ['style', 'class'] + }); + + logger.info('已启动字幕内容变化监听'); +} + function calculateScale() { const container = elements.digitalHumanBox; const sdkContainer = container.querySelector('.digital-intelligent-interaction'); @@ -741,7 +945,11 @@ function bindEvents() { elements.initBtn.addEventListener('click', initializeSDK); elements.destroyBtn.addEventListener('click', destroySDK); elements.getOnceCodeBtn.addEventListener('click', handleGetOnceCode); - elements.applyCaptionStyleBtn.addEventListener('click', applyCaptionStyle); + elements.applyCaptionStyleBtn.addEventListener('click', () => { + applyCaptionStyle(); + captionStyleApplied = true; + watchCaptionContentChanges(); + }); document.querySelectorAll('input[type="range"]').forEach(slider => { slider.addEventListener('input', (e) => { @@ -749,6 +957,22 @@ function bindEvents() { if (valueSpan && valueSpan.classList.contains('range-value')) { valueSpan.textContent = `${e.target.value}%`; } + updateSingleStyle(e.target.id); + captionStyleApplied = true; + watchCaptionContentChanges(); + }); + }); + + document.querySelectorAll('#captionPanel input[type="number"], #captionPanel input[type="color"], #captionPanel select').forEach(input => { + input.addEventListener('input', (e) => { + updateSingleStyle(e.target.id); + captionStyleApplied = true; + watchCaptionContentChanges(); + }); + input.addEventListener('change', (e) => { + updateSingleStyle(e.target.id); + captionStyleApplied = true; + watchCaptionContentChanges(); }); }); diff --git a/frontend/styles/main.css b/frontend/styles/main.css index 822b701..b942449 100644 --- a/frontend/styles/main.css +++ b/frontend/styles/main.css @@ -636,36 +636,36 @@ body { /* ===== 覆盖 SDK 字体大小 ===== */ .digital-intelligent-interaction { - font-size: 14px !important; + font-size: 14px; } .digital-intelligent-interaction .ai-chat-btn .ai-chat-btn-content { - font-size: 16px !important; + font-size: 16px; } .digital-intelligent-interaction .message-item .rich-text-card .content { - font-size: 16px !important; - line-height: 24px !important; + font-size: 16px; + line-height: 24px; } .digital-intelligent-interaction .stop-chat-btn.normal .stop-chat-btn-content { - font-size: 16px !important; + font-size: 16px; } .digital-intelligent-interaction .toast-container .toast-content .toast-text { - font-size: 12px !important; + font-size: 12px; } .digital-intelligent-interaction .layout-hub-tip { - font-size: 16px !important; + font-size: 16px; } .digital-intelligent-interaction .layout-hub-hot-title { - font-size: 16px !important; + font-size: 16px; } .digital-intelligent-interaction .layout-hub-hot-issues { - font-size: 16px !important; + font-size: 16px; } /* ===== 滚动条样式 ===== */