diff --git a/src/webapp/src/component/file-list/file-list.css b/src/webapp/src/component/file-list/file-list.css index e2c5a48..8921222 100644 --- a/src/webapp/src/component/file-list/file-list.css +++ b/src/webapp/src/component/file-list/file-list.css @@ -55,6 +55,40 @@ height: 100%; } +/* 弹幕统计栏 */ +.danmaku-stats { + display: flex; + align-items: center; + gap: 24px; + padding: 8px 16px; + background: #1a1a1a; + border-top: 1px solid #303030; + color: #ffffffd9; + font-size: 13px; + flex-shrink: 0; +} + +.danmaku-stats .stat-item { + display: flex; + align-items: center; + gap: 4px; +} + +.danmaku-stats .stat-icon { + font-size: 14px; +} + +.danmaku-stats b { + color: #fff; + font-weight: 600; + margin-left: 2px; +} + +.danmaku-stats .stat-amount { + color: #faad14; + font-weight: 600; +} + .file-table-row { cursor: pointer; transition: background-color 0.2s; diff --git a/src/webapp/src/component/file-list/index.tsx b/src/webapp/src/component/file-list/index.tsx index c5a384e..d5ee038 100644 --- a/src/webapp/src/component/file-list/index.tsx +++ b/src/webapp/src/component/file-list/index.tsx @@ -396,6 +396,7 @@ const FileList: React.FC = () => { const [currentPlayingName, setCurrentPlayingName] = useState(""); const artRef = useRef(null); const danmakuRef = useRef(null); + const [danmakuStats, setDanmakuStats] = useState<{ danmaku: number; gift: number; guard: number; sc: number; scAmount: number } | null>(null); // 重命名相关状态 const [isRenameModalVisible, setIsRenameModalVisible] = useState(false); @@ -456,6 +457,7 @@ const FileList: React.FC = () => { } setIsPlayerVisible(false); setCurrentPlayingName(""); + setDanmakuStats(null); }, []); // 监听 ESC 键退出播放 @@ -711,6 +713,21 @@ const FileList: React.FC = () => { const { items, scrollTime } = parseAss(text); if (items.length === 0) return; + // 统计弹幕类型 + let danmakuCount = 0, giftCount = 0, guardCount = 0, scCount = 0, scAmount = 0; + for (const item of items) { + if (item.style === 'Danmaku') danmakuCount++; + else if (item.style === 'Gift') giftCount++; + else if (item.style === 'Guard') guardCount++; + else if (item.style.startsWith('SC')) { + scCount++; + // 从文本中提取金额: [SC ¥100] ... + const m = item.text.match(/\[SC ¥(\d+)\]/); + if (m) scAmount += parseInt(m[1]); + } + } + setDanmakuStats({ danmaku: danmakuCount, gift: giftCount, guard: guardCount, sc: scCount, scAmount }); + // 找到 Artplayer 内部容器,将覆盖层插入其中(和 video 同级) const artContainer = document.getElementById('art-container'); if (!artContainer) return; @@ -894,6 +911,27 @@ const FileList: React.FC = () => {
+ {danmakuStats && ( +
+ + 💬 + 弹幕 {danmakuStats.danmaku} + + + 🎁 + 礼物 {danmakuStats.gift} + + + 💰 + SC {danmakuStats.sc} + {danmakuStats.scAmount > 0 && ¥{danmakuStats.scAmount}} + + + ⚓ + 上舰 {danmakuStats.guard} + +
+ )} ); };