折叠和展开字幕去掉
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 1m53s

This commit is contained in:
libingxiang 2026-06-24 09:16:14 +08:00
parent 1a9cd283a1
commit c3ec7b63c3

View File

@ -135,39 +135,12 @@
<div <div
class="bubble-text" class="bubble-text"
:class="{ :class="{
collapsed: isCollapsed(msg.id) && isLongText(msg.content),
'text-user': msg.role === 'user', 'text-user': msg.role === 'user',
'text-ai': msg.role === 'ai', 'text-ai': msg.role === 'ai',
}" }"
:ref="(el) => setMsgRef(msg.id, el)"
> >
{{ msg.content }} {{ msg.content }}
</div> </div>
<button
v-if="isLongText(msg.content)"
class="expand-btn"
@click="toggleCollapse(msg.id)"
>
{{ isCollapsed(msg.id) ? "展开全部" : "收起" }}
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
:style="{
transform: isCollapsed(msg.id)
? 'rotate(0deg)'
: 'rotate(180deg)',
transition: 'transform 0.2s',
}"
>
<polyline points="6 9 12 15 18 9" />
</svg>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -202,76 +175,14 @@
class="merged-bubble" class="merged-bubble"
> >
<div v-if="pair.user" class="merged-user-section"> <div v-if="pair.user" class="merged-user-section">
<div <div class="merged-text text-user">
class="merged-text text-user"
:class="{
collapsed:
isCollapsed(pair.user.id) && isLongText(pair.user.content),
}"
>
{{ pair.user.content }} {{ pair.user.content }}
</div> </div>
<button
v-if="isLongText(pair.user.content)"
class="expand-btn"
@click="toggleCollapse(pair.user.id)"
>
{{ isCollapsed(pair.user.id) ? "展开全部" : "收起" }}
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
:style="{
transform: isCollapsed(pair.user.id)
? 'rotate(0deg)'
: 'rotate(180deg)',
transition: 'transform 0.2s',
}"
>
<polyline points="6 9 12 15 18 9" />
</svg>
</button>
</div> </div>
<div v-if="pair.ai" class="merged-ai-section"> <div v-if="pair.ai" class="merged-ai-section">
<div <div class="merged-text text-ai">
class="merged-text text-ai"
:class="{
collapsed:
isCollapsed(pair.ai.id) && isLongText(pair.ai.content),
}"
>
{{ pair.ai.content }} {{ pair.ai.content }}
</div> </div>
<button
v-if="isLongText(pair.ai.content)"
class="expand-btn"
@click="toggleCollapse(pair.ai.id)"
>
{{ isCollapsed(pair.ai.id) ? "展开全部" : "收起" }}
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
:style="{
transform: isCollapsed(pair.ai.id)
? 'rotate(0deg)'
: 'rotate(180deg)',
transition: 'transform 0.2s',
}"
>
<polyline points="6 9 12 15 18 9" />
</svg>
</button>
</div> </div>
</div> </div>
</div> </div>
@ -391,29 +302,6 @@ const scrollAIToBottom = () => {
} }
}; };
// ===== / =====
const COLLAPSE_THRESHOLD = 120; // 120
const collapsedIds = ref<Set<string>>(new Set());
const msgRefs = new Map<string, HTMLElement>();
const isLongText = (text: string): boolean => text.length > COLLAPSE_THRESHOLD;
const isCollapsed = (id: string): boolean => collapsedIds.value.has(id);
const toggleCollapse = (id: string) => {
if (collapsedIds.value.has(id)) {
collapsedIds.value.delete(id);
} else {
collapsedIds.value.add(id);
}
//
collapsedIds.value = new Set(collapsedIds.value);
};
const setMsgRef = (id: string, el: any) => {
if (el) msgRefs.set(id, el as HTMLElement);
};
// ===== ===== // ===== =====
const modeOptions = [ const modeOptions = [
{ value: "ai-only" as SubtitleMode, label: "AI字幕", icon: "💬" }, { value: "ai-only" as SubtitleMode, label: "AI字幕", icon: "💬" },
@ -532,21 +420,10 @@ watch(
}, },
); );
// + //
watch( watch(
() => props.messages.length, () => props.messages.length,
(newLen, oldLen) => { () => {
//
if (newLen > (oldLen ?? 0)) {
for (let i = oldLen ?? 0; i < newLen; i++) {
const msg = props.messages[i];
if (msg && isLongText(msg.content)) {
collapsedIds.value.add(msg.id);
}
}
collapsedIds.value = new Set(collapsedIds.value);
}
nextTick(() => { nextTick(() => {
scrollToBottom(); scrollToBottom();
}); });
@ -861,45 +738,6 @@ const scrollToBottom = () => {
color: #ffffff; color: #ffffff;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
} }
&.collapsed {
max-height: 4.8em;
position: relative;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2em;
background: linear-gradient(transparent, rgba(10, 14, 30, 0.5));
pointer-events: none;
border-radius: 0 0 8px 8px;
}
}
}
/* ===== 展开/收起按钮 ===== */
.expand-btn {
display: inline-flex;
align-items: center;
gap: 4px;
margin-top: 6px;
padding: 3px 10px;
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
color: rgba(255, 255, 255, 0.55);
font-size: 11px;
cursor: pointer;
transition: all 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.8);
border-color: rgba(255, 255, 255, 0.2);
}
} }
/* ===== 模式3合并气泡 ===== */ /* ===== 模式3合并气泡 ===== */
@ -946,22 +784,6 @@ const scrollToBottom = () => {
color: #ffffff; color: #ffffff;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
} }
&.collapsed {
max-height: 4.8em;
position: relative;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 2em;
background: linear-gradient(transparent, rgba(10, 14, 30, 0.5));
pointer-events: none;
}
}
} }
/* ===== 1440×2560 分辨率专用样式 ===== */ /* ===== 1440×2560 分辨率专用样式 ===== */
@ -991,12 +813,6 @@ const scrollToBottom = () => {
font-weight: 500; font-weight: 500;
} }
/* 三级辅助:展开按钮 */
.expand-btn {
font-size: 17px;
padding: 6px 18px;
}
/* 字幕容器:背景与边框适配大字号 */ /* 字幕容器:背景与边框适配大字号 */
.ai-subtitle-bar { .ai-subtitle-bar {
padding: 18px 24px; padding: 18px 24px;
@ -1076,16 +892,5 @@ const scrollToBottom = () => {
.bubble-text { .bubble-text {
font-size: 28px !important; font-size: 28px !important;
} }
/* 折叠高度适配(按新字号比例) */
.bubble-text.collapsed,
.merged-text.collapsed {
max-height: 6em;
}
.bubble-text.collapsed::after,
.merged-text.collapsed::after {
height: 3em;
}
} }
</style> </style>