From f0f9ed345638396466de463192536e14e6e73343 Mon Sep 17 00:00:00 2001 From: nanxun Date: Fri, 1 May 2026 07:16:03 +0800 Subject: [PATCH] feat: localize quality labels and add quality template token --- frontend/src/types.ts | 22 +++++ frontend/src/views/LiveRoomsView.vue | 93 ++++++++++++++++--- .../src/views/RecordSessionDetailView.vue | 3 +- frontend/src/views/RecordTaskDetailView.vue | 3 +- frontend/src/views/RecordTasksView.vue | 6 +- frontend/src/views/SettingsView.vue | 30 ++++-- .../Models/Settings/SettingsModels.cs | 4 +- .../Services/RecordService.cs | 15 ++- .../Services/SystemSettingsService.cs | 2 +- 9 files changed, 147 insertions(+), 31 deletions(-) diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 5aac1c4..73198de 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -572,6 +572,28 @@ export const recordingTemplateLabelMap: Record = { 2: "归档 TS" }; +export const qualityLabelMap: Record = { + origin: "原画", + FULL_HD: "超清", + HD: "高清", + SD: "标清" +}; + +export const qualityOptionList = [ + { value: "origin", label: qualityLabelMap.origin }, + { value: "FULL_HD", label: qualityLabelMap.FULL_HD }, + { value: "HD", label: qualityLabelMap.HD }, + { value: "SD", label: qualityLabelMap.SD } +] as const; + +export function formatQualityLabel(value?: string | null) { + if (!value) { + return "-"; + } + + return qualityLabelMap[value] ?? value; +} + export const autoStartDecisionLabelMap: Record = { started: "已启动", skipped_disabled: "已禁用", diff --git a/frontend/src/views/LiveRoomsView.vue b/frontend/src/views/LiveRoomsView.vue index f611364..87b8953 100644 --- a/frontend/src/views/LiveRoomsView.vue +++ b/frontend/src/views/LiveRoomsView.vue @@ -6,9 +6,11 @@ import { useViewport } from "@/composables/useViewport"; import type { BatchLiveRoomsResult, ImportLiveRoomsRequest, ImportLiveRoomsResult, LiveRoom, RecordTask } from "@/types"; import { autoStartDecisionLabelMap, + formatQualityLabel, availabilityLabelMap, currentRecordingStateLabelMap, outputFormatLabelMap, + qualityOptionList, recordingTemplateLabelMap, saveModeLabelMap } from "@/types"; @@ -89,7 +91,8 @@ const platformOptions = [ { label: "虎牙", value: 3 } ]; -const qualityOptions = ["origin", "FULL_HD", "HD", "SD"]; +const qualityOptions = qualityOptionList; +const qualitySupportHint = "抖音和 Bilibili 支持按画质选流;虎牙暂未实现。若目标档位不可用,平台会自动回退到最接近的可用画质。"; const booleanOverrideOptions = [ { label: "跟随全局", value: inheritValue }, { label: "开启", value: "true" }, @@ -143,6 +146,35 @@ function getRoomsTableScrollWrap() { shell.querySelector(".el-table__body-wrapper"); } +function getRoomsTableContentWidth(wrap: HTMLElement) { + const shell = roomsTableShellRef.value; + + if (!shell) { + return wrap.scrollWidth; + } + + const widths = [ + wrap.scrollWidth, + wrap.firstElementChild?.scrollWidth ?? 0, + shell.querySelector(".el-table__body table")?.scrollWidth ?? 0, + shell.querySelector(".el-table__header table")?.scrollWidth ?? 0 + ]; + + const wrapRect = wrap.getBoundingClientRect(); + let maxRight = 0; + + shell.querySelectorAll( + ".el-table__header th, .el-table__body td, .room-actions-cell, .config-summary, .auto-start-cell" + ).forEach((element) => { + const rect = element.getBoundingClientRect(); + maxRight = Math.max(maxRight, rect.right - wrapRect.left + wrap.scrollLeft); + }); + + widths.push(Math.ceil(maxRight) + 24); + + return Math.max(...widths); +} + function handleRoomsTableBodyScroll() { if (syncingRoomsTableProxy) { return; @@ -235,11 +267,11 @@ async function syncRoomsTableProxyScroll() { return; } - const scrollWidth = Math.max(wrap.scrollWidth, wrap.firstElementChild?.scrollWidth ?? 0); + const scrollWidth = getRoomsTableContentWidth(wrap); const clientWidth = wrap.clientWidth; const canScrollHorizontally = scrollWidth > clientWidth + 1; - roomsTableProxyInnerWidth.value = scrollWidth; + roomsTableProxyInnerWidth.value = canScrollHorizontally ? scrollWidth : 0; showRoomsTableProxyScroll.value = canScrollHorizontally; if (canScrollHorizontally && proxy && Math.abs(proxy.scrollLeft - wrap.scrollLeft) > 1) { @@ -653,6 +685,10 @@ function getRoomAvatarText(room: LiveRoom) { return source.slice(0, 1).toUpperCase(); } +function getQualityLabel(quality?: string | null) { + return formatQualityLabel(quality); +} + function autoStartDecisionLabel(code?: string) { if (!code) { return "未记录"; @@ -862,7 +898,7 @@ onBeforeUnmount(() => {
房间配置
- {{ row.effectiveSettings.preferredQuality }} · + {{ getQualityLabel(row.effectiveSettings.preferredQuality) }} · {{ outputFormatLabelMap[row.effectiveSettings.outputFormat] }} · {{ saveModeLabelMap[row.effectiveSettings.saveMode] }} · {{ row.effectiveSettings.enableDanmakuRecording ? "弹幕开" : "弹幕关" }} @@ -914,7 +950,7 @@ onBeforeUnmount(() => { v-loading="loading" :height="tableHeight" class="premium-table rooms-table" - table-layout="auto" + table-layout="fixed" row-key="id" @selection-change="handleRoomSelectionChange" > @@ -982,10 +1018,10 @@ onBeforeUnmount(() => { - + - +