11---
22import { Image } from ' astro:assets'
3+
34import commentFlag from ' @/assets/other/comment_flag.png'
45import config from ' @/site-config'
56
@@ -35,14 +36,16 @@ if (serverURL) {
3536 <span id =' danmaku-status' class =' running' >running</span >
3637 </div >
3738 <div class =' terminal-controls' >
38- <button class =' control-btn' id =' danmaku-toggle' >PAUSE</button >
39- <button class =' control-btn' id =' danmaku-clear' >CLEAR</button >
40- <!-- <button class='control-btn' id='danmaku-theme'>THEME</button> -->
39+ <!-- <button class='control-btn' id='danmaku-toggle'>暂停</button> -->
4140 </div >
4241 </div >
4342
4443 <div class =' terminal-screen' >
45- <Image src ={ commentFlag } alt =" Welcome to leave comments" class =" absolute bottom-4 left-4 w-[120px] h-auto opacity-70 pointer-events-none" />
44+ <Image
45+ src ={ commentFlag }
46+ alt =' Welcome to leave comments'
47+ class =' absolute bottom-4 left-4 w-[120px] h-auto pointer-events-none'
48+ />
4649 <div class =' danmaku-track' ></div >
4750 <div class =' danmaku-track' ></div >
4851 <div class =' danmaku-track' ></div >
@@ -53,7 +56,7 @@ if (serverURL) {
5356
5457 <div class =' status-line' >
5558 <span >Lines: <span id =' danmaku-lineCount' >0</span ></span >
56- <span id =' danmaku-keyboard-shortcuts' >Press SPACE to pause, C to clear</span >
59+ <span id =' danmaku-keyboard-shortcuts' >Press < kbd >Space</ kbd > to play , < kbd >C</ kbd > to clear</span >
5760 </div >
5861</div >
5962
@@ -68,16 +71,10 @@ if (serverURL) {
6871 }
6972
7073 let isPlaying = true
71- let trackLastTime = [0, 0, 0, 0, 0, 0]
72- let lineCount = 0
74+ const trackLastTime = [0, 0, 0, 0, 0, 0]
7375 let loopTimeoutId = null
7476 let commentIndex = 0
75-
76- function toggleTheme() {
77- const current = document.documentElement.getAttribute('data-theme')
78- const newTheme = current === 'dark' ? 'light' : 'dark'
79- document.documentElement.setAttribute('data-theme', newTheme)
80- }
77+ let lineCount = 0
8178
8279 function selectBestTrack() {
8380 let bestTrack = 0
@@ -91,6 +88,48 @@ if (serverURL) {
9188 return bestTrack
9289 }
9390
91+ function truncateHtmlInline(html, maxLen) {
92+ // 去掉换行,避免输出换行
93+ html = html.replace(/^<p>|<\/p>$/g, '')
94+
95+ const tagRegex = /<\/?[^>]+>/g
96+ let textLen = 0
97+ let result = ''
98+ let lastIndex = 0
99+ let match
100+
101+ while ((match = tagRegex.exec(html)) !== null) {
102+ // 标签前的纯文字
103+ if (lastIndex < match.index) {
104+ const text = html.slice(lastIndex, match.index)
105+ if (textLen + text.length < maxLen) {
106+ result += text
107+ textLen += text.length
108+ } else {
109+ const remaining = maxLen - textLen
110+ result += text.slice(0, remaining) + '...'
111+ return result
112+ }
113+ }
114+
115+ // 保留标签本身(比如 <img>)
116+ result += match[0]
117+ lastIndex = tagRegex.lastIndex
118+ }
119+
120+ // 标签后的最后一段纯文字
121+ if (lastIndex < html.length && textLen < maxLen) {
122+ const text = html.slice(lastIndex)
123+ if (textLen + text.length <= maxLen) {
124+ result += text
125+ } else {
126+ result += text.slice(0, maxLen - textLen) + '...'
127+ }
128+ }
129+
130+ return result
131+ }
132+
94133 function createDanmaku(data) {
95134 if (!isPlaying) return
96135 const trackIndex = selectBestTrack()
@@ -99,36 +138,31 @@ if (serverURL) {
99138
100139 const danmaku = document.createElement('div')
101140 danmaku.className = 'danmaku-item not-prose'
102- // Add admin class if applicable
103141 if (data.type === 'administrator') {
104142 danmaku.classList.add('is-admin')
105143 }
106144
107- const cleanComment = data.comment.replace(/^<p>|<\/p>$/g, '')
145+ const cleanComment = truncateHtmlInline(data.comment, 30)
146+ const likeHtml = data.like > 0 ? `<span class="danmaku-like">👍 ${data.like}</span>` : ''
108147
109- // New badge-like structure
110148 danmaku.innerHTML = `
111149 <img class="danmaku-avatar" src="${data.avatar}" alt="" onerror="this.style.display='none'">
112- <span class="danmaku-nick">${data.nick}$ </span>
150+ <span class="danmaku-nick">${data.nick}</span>
113151 <span class="danmaku-comment not-prose">${cleanComment}</span>
152+ ${likeHtml}
114153 `
115154
116155 let duration
117156 if (window.innerWidth < 600) {
118- // 移动端 6-10秒
119157 duration = Math.random() * 4 + 6
120158 } else {
121- // PC端 16-24秒
122159 duration = Math.random() * 8 + 16
123160 }
124161 danmaku.style.animationDuration = `${duration}s`
125- // const duration = Math.random() * 4 + 6 // 6-10s duration
126- // danmaku.style.animationDuration = `${duration}s`
127162
128163 track.appendChild(danmaku)
129164 trackLastTime[trackIndex] = Date.now()
130165
131- lineCount++
132166 const lineCountEl = document.getElementById('danmaku-lineCount')
133167 if (lineCountEl) lineCountEl.textContent = lineCount.toString()
134168
@@ -139,45 +173,36 @@ if (serverURL) {
139173 }
140174
141175 function startDanmakuLoop() {
142- if (!isPlaying) return
176+ if (!isPlaying || comments.length === 0 ) return
143177 const commentData = comments[commentIndex]
144178 createDanmaku(commentData)
179+ lineCount++
145180 commentIndex = (commentIndex + 1) % comments.length
146181 loopTimeoutId = setTimeout(startDanmakuLoop, 3000)
147182 }
148183
149184 function toggleDanmaku() {
150185 isPlaying = !isPlaying
151- const btn = document.getElementById('danmaku-toggle')
152186 const status = document.getElementById('danmaku-status')
153- if (btn) btn.textContent = isPlaying ? 'PAUSE' : 'PLAY'
154187 if (status) {
155188 status.textContent = isPlaying ? 'running' : 'paused'
156189 status.classList.toggle('running', isPlaying)
157190 status.classList.toggle('paused', !isPlaying)
158191 }
159- if (isPlaying) startDanmakuLoop()
160- else clearTimeout(loopTimeoutId)
192+ if (isPlaying) {
193+ startDanmakuLoop()
194+ } else {
195+ clearTimeout(loopTimeoutId)
196+ }
161197 }
162198
163199 function clearDanmaku() {
164200 container.querySelectorAll('.danmaku-track').forEach((track) => {
165201 track.innerHTML = ''
166202 })
167203 trackLastTime.fill(0)
168- lineCount = 0
169- const lineCountEl = document.getElementById('danmaku-lineCount')
170- if (lineCountEl) lineCountEl.textContent = '0'
171204 }
172205
173- const toggleBtn = document.getElementById('danmaku-toggle')
174- const clearBtn = document.getElementById('danmaku-clear')
175- const themeBtn = document.getElementById('danmaku-theme')
176-
177- if (toggleBtn) toggleBtn.addEventListener('click', toggleDanmaku)
178- if (clearBtn) clearBtn.addEventListener('click', clearDanmaku)
179- if (themeBtn) themeBtn.addEventListener('click', toggleTheme)
180-
181206 document.addEventListener('keydown', (e) => {
182207 if (document.activeElement !== document.body && document.activeElement !== container) return
183208 switch (e.key.toLowerCase()) {
@@ -196,7 +221,7 @@ if (serverURL) {
196221 startDanmakuLoop()
197222 }
198223
199- setTimeout(initializeDanmaku, 0 )
224+ setTimeout(initializeDanmaku, 1000 )
200225</script >
201226
202227<style >
@@ -374,14 +399,20 @@ if (serverURL) {
374399 }
375400 :global(.danmaku-comment) {
376401 padding-right: 12px;
377- max-width: 40ch;
378402 overflow: hidden;
379403 text-overflow: ellipsis;
380404 white-space: nowrap;
381405 display: inline-flex;
382406 align-items: center;
383407 color: var(--text);
384408 }
409+ :global(.danmaku-like) {
410+ opacity: 0.8;
411+ font-size: 12px;
412+ margin-left: 8px;
413+ color: var(--text-secondary);
414+ flex-shrink: 0;
415+ }
385416 :global(.danmaku-comment p) {
386417 display: inline;
387418 margin: 0;
@@ -447,5 +478,4 @@ if (serverURL) {
447478 .danmaku-comment img[height] {
448479 height: 28px !important;
449480 }
450-
451481</style >
0 commit comments