feat: localize quality labels and add quality template token
This commit is contained in:
@@ -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<HTMLElement>(".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<HTMLElement>(".el-table__body table")?.scrollWidth ?? 0,
|
||||
shell.querySelector<HTMLElement>(".el-table__header table")?.scrollWidth ?? 0
|
||||
];
|
||||
|
||||
const wrapRect = wrap.getBoundingClientRect();
|
||||
let maxRight = 0;
|
||||
|
||||
shell.querySelectorAll<HTMLElement>(
|
||||
".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(() => {
|
||||
<div style="grid-column: 1 / -1;">
|
||||
<dt>房间配置</dt>
|
||||
<dd>
|
||||
{{ 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(() => {
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="房间配置" min-width="240">
|
||||
<el-table-column label="房间配置" width="280">
|
||||
<template #default="{ row }">
|
||||
<div class="config-summary">
|
||||
<span>画质 {{ row.effectiveSettings.preferredQuality }}</span>
|
||||
<span>画质 {{ getQualityLabel(row.effectiveSettings.preferredQuality) }}</span>
|
||||
<span>{{ outputFormatLabelMap[row.effectiveSettings.outputFormat] }}</span>
|
||||
<span>{{ saveModeLabelMap[row.effectiveSettings.saveMode] }}</span>
|
||||
<span>{{ row.effectiveSettings.enableDanmakuRecording ? "弹幕开" : "弹幕关" }}</span>
|
||||
@@ -1012,7 +1048,7 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="320">
|
||||
<el-table-column label="操作" width="380">
|
||||
<template #default="{ row }">
|
||||
<div class="room-actions-cell">
|
||||
<el-button size="small" @click="refreshRoom(row)">刷新</el-button>
|
||||
@@ -1172,10 +1208,17 @@ onBeforeUnmount(() => {
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="清晰度">
|
||||
<el-select v-model="recordForm.preferredQuality">
|
||||
<el-option v-for="option in qualityOptions" :key="option" :label="option" :value="option" />
|
||||
<el-option
|
||||
v-for="option in qualityOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<div class="field-help">{{ qualitySupportHint }}</div>
|
||||
|
||||
<el-form-item label="输出格式">
|
||||
<el-select v-model="recordForm.outputFormat">
|
||||
<el-option
|
||||
@@ -1241,10 +1284,17 @@ onBeforeUnmount(() => {
|
||||
<el-form-item label="默认画质">
|
||||
<el-select v-model="settingsForm.preferredQualityOverride">
|
||||
<el-option label="跟随全局" :value="inheritValue" />
|
||||
<el-option v-for="option in qualityOptions" :key="option" :label="option" :value="option" />
|
||||
<el-option
|
||||
v-for="option in qualityOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<div class="field-help field-help--full">{{ qualitySupportHint }}</div>
|
||||
|
||||
<el-form-item label="默认输出格式">
|
||||
<el-select v-model="settingsForm.outputFormatOverride">
|
||||
<el-option label="跟随全局" :value="inheritValue" />
|
||||
@@ -1454,7 +1504,7 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.rooms-table {
|
||||
min-width: 1380px;
|
||||
min-width: 1920px;
|
||||
}
|
||||
|
||||
.rooms-table :deep(.el-table__cell) {
|
||||
@@ -1462,7 +1512,7 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.rooms-table :deep(.cell) {
|
||||
overflow: visible;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.room-avatar {
|
||||
@@ -1557,16 +1607,29 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.room-actions-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, max-content));
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.room-actions-cell :deep(.el-button) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.field-help {
|
||||
margin-top: -8px;
|
||||
margin-bottom: 14px;
|
||||
color: var(--text-muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.field-help--full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.settings-note {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
|
||||
Reference in New Issue
Block a user