feat: improve recording recovery and upload workflow
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { useRoute } from "vue-router";
|
||||
import apiClient, { getApiErrorMessage } from "@/api/client";
|
||||
import EmptyState from "@/components/ui/EmptyState.vue";
|
||||
import MetricCard from "@/components/ui/MetricCard.vue";
|
||||
import PlatformMark from "@/components/ui/PlatformMark.vue";
|
||||
import RightDrawer from "@/components/ui/RightDrawer.vue";
|
||||
import SafeAvatar from "@/components/ui/SafeAvatar.vue";
|
||||
import StatusBadge from "@/components/ui/StatusBadge.vue";
|
||||
@@ -25,6 +27,7 @@ import { House, RefreshRight, SwitchButton, VideoCamera } from "@element-plus/ic
|
||||
|
||||
const inheritValue = "__inherit__";
|
||||
const AUTO_REFRESH_INTERVAL_MS = 15000;
|
||||
const route = useRoute();
|
||||
|
||||
const loading = ref(false);
|
||||
const submitLoading = ref(false);
|
||||
@@ -687,6 +690,7 @@ function nullableStringFromSelect(value: string | number) {
|
||||
|
||||
onMounted(async () => {
|
||||
await loadRooms();
|
||||
if (route.query.action === "create") openCreateDialog();
|
||||
startAutoRefresh();
|
||||
document.addEventListener("visibilitychange", handleVisibilityChange);
|
||||
});
|
||||
@@ -787,7 +791,7 @@ onBeforeUnmount(() => {
|
||||
:status="row.currentRecordingState"
|
||||
context="recording"
|
||||
/>
|
||||
<StatusBadge :label="row.platformName || '--'" :status="row.platformName || 'unknown'" />
|
||||
<PlatformMark :name="row.platformName" />
|
||||
<StatusBadge v-if="row.isPinned" label="置顶" status="completed" size="sm" />
|
||||
<StatusBadge v-if="row.isPriority" label="重点" status="retrying" size="sm" />
|
||||
</div>
|
||||
@@ -892,7 +896,7 @@ onBeforeUnmount(() => {
|
||||
<div class="cell-title">{{ row.title || row.anchorName || row.roomId }}</div>
|
||||
<div class="cell-subtitle">{{ row.anchorName || "未知主播" }}</div>
|
||||
<div class="config-summary">
|
||||
<span>{{ row.platformName || "--" }}</span>
|
||||
<PlatformMark :name="row.platformName" />
|
||||
<span>{{ row.roomId || "--" }}</span>
|
||||
<span>{{ formatPollingInterval(row.pollingIntervalSecondsOverride) }}</span>
|
||||
</div>
|
||||
@@ -1025,7 +1029,7 @@ onBeforeUnmount(() => {
|
||||
:status="activeRoom.currentRecordingState"
|
||||
context="recording"
|
||||
/>
|
||||
<StatusBadge :label="activeRoom.platformName || '--'" :status="activeRoom.platformName || 'unknown'" />
|
||||
<PlatformMark :name="activeRoom.platformName" />
|
||||
</div>
|
||||
|
||||
<el-descriptions :column="1" border class="detail-panel__descriptions">
|
||||
@@ -1033,7 +1037,7 @@ onBeforeUnmount(() => {
|
||||
{{ activeRoom.title || activeRoom.anchorName || activeRoom.roomId || "--" }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="平台 + Room ID">
|
||||
{{ activeRoom.platformName || "--" }} · {{ activeRoom.roomId || "--" }}
|
||||
<span class="platform-room-id"><PlatformMark :name="activeRoom.platformName" /><span>· {{ activeRoom.roomId || "--" }}</span></span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="直播状态">
|
||||
{{ roomAvailabilityLabel(activeRoom) }}
|
||||
@@ -1453,6 +1457,7 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.platform-room-id { display: inline-flex; align-items: center; gap: 6px; }
|
||||
.page-stack {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
@@ -1691,6 +1696,10 @@ onBeforeUnmount(() => {
|
||||
background: var(--surface-muted);
|
||||
}
|
||||
|
||||
.detail-panel__hero > div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.detail-panel__title {
|
||||
color: var(--text-primary);
|
||||
font-size: 18px;
|
||||
@@ -1922,6 +1931,17 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.detail-panel__hero {
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.detail-panel__descriptions :deep(.el-descriptions__label) {
|
||||
width: 104px;
|
||||
min-width: 104px;
|
||||
}
|
||||
|
||||
.header-actions :deep(.el-space__item) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user