feat: add transcode workspace and media browser
This commit is contained in:
@@ -1,22 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useViewport } from "@/composables/useViewport";
|
||||
import { ElMessage } from "element-plus";
|
||||
import axios from "axios";
|
||||
import apiClient, { getApiErrorMessage } from "@/api/client";
|
||||
import type { DailyReviewReport } from "@/types";
|
||||
import { useViewport } from "@/composables/useViewport";
|
||||
import type {
|
||||
DailyReviewPushResult,
|
||||
DailyReviewReport,
|
||||
PushDailyReviewRequest
|
||||
} from "@/types";
|
||||
|
||||
const router = useRouter();
|
||||
const { isMobile } = useViewport();
|
||||
|
||||
const loading = ref(false);
|
||||
const pushing = ref(false);
|
||||
const pushDialogVisible = ref(false);
|
||||
const loadError = ref("");
|
||||
const selectedDate = ref(defaultReviewDate());
|
||||
const report = ref<DailyReviewReport | null>(null);
|
||||
const roomTableHeight = computed(() => (isMobile.value ? undefined : 420));
|
||||
const momentTableHeight = computed(() => (isMobile.value ? undefined : 360));
|
||||
const pushChannels = reactive({
|
||||
webhook: true,
|
||||
email: false
|
||||
});
|
||||
|
||||
async function loadReport() {
|
||||
loading.value = true;
|
||||
@@ -40,16 +49,39 @@ async function loadReport() {
|
||||
}
|
||||
}
|
||||
|
||||
function openPushDialog() {
|
||||
pushDialogVisible.value = true;
|
||||
}
|
||||
|
||||
async function pushReport() {
|
||||
const channels = Object.entries(pushChannels)
|
||||
.filter(([, enabled]) => enabled)
|
||||
.map(([channel]) => channel);
|
||||
if (channels.length === 0) {
|
||||
ElMessage.warning("请至少选择一种推送方式。");
|
||||
return;
|
||||
}
|
||||
|
||||
pushing.value = true;
|
||||
try {
|
||||
const { data } = await apiClient.post("/reports/daily/push", null, {
|
||||
params: {
|
||||
date: selectedDate.value,
|
||||
utcOffsetMinutes: getLocalUtcOffsetMinutes()
|
||||
}
|
||||
});
|
||||
ElMessage.success(data.message);
|
||||
const payload: PushDailyReviewRequest = {
|
||||
date: selectedDate.value,
|
||||
utcOffsetMinutes: getLocalUtcOffsetMinutes(),
|
||||
channels
|
||||
};
|
||||
const { data } = await apiClient.post<DailyReviewPushResult>("/reports/daily/push", payload);
|
||||
const successCount = data.results.filter((item) => item.success).length;
|
||||
const summary = data.results.map((item) => `${item.channel}: ${item.message}`).join(" | ");
|
||||
|
||||
if (successCount === data.results.length) {
|
||||
ElMessage.success(summary);
|
||||
} else if (successCount > 0) {
|
||||
ElMessage.warning(summary);
|
||||
} else {
|
||||
ElMessage.error(summary);
|
||||
}
|
||||
|
||||
pushDialogVisible.value = false;
|
||||
} catch (error) {
|
||||
ElMessage.error(getApiErrorMessage(error, "日报推送失败。"));
|
||||
} finally {
|
||||
@@ -107,7 +139,7 @@ onMounted(loadReport);
|
||||
<div>
|
||||
<h1 class="page-title">回顾日报</h1>
|
||||
<p class="page-subtitle">
|
||||
按天聚合录制时长、异常和弹幕热度。支持手动推送到已配置的 Webhook。
|
||||
按天聚合录制时长、异常和弹幕热度。支持手动推送到已配置的 Webhook 或邮件。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -122,7 +154,7 @@ onMounted(loadReport);
|
||||
@change="loadReport"
|
||||
/>
|
||||
<el-button @click="loadReport">刷新日报</el-button>
|
||||
<el-button type="primary" :loading="pushing" :disabled="!report" @click="pushReport">推送日报</el-button>
|
||||
<el-button type="primary" :disabled="!report" @click="openPushDialog">推送日报</el-button>
|
||||
</el-space>
|
||||
</div>
|
||||
|
||||
@@ -275,6 +307,24 @@ onMounted(loadReport);
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<el-dialog
|
||||
v-model="pushDialogVisible"
|
||||
title="推送日报"
|
||||
width="420px"
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="push-dialog">
|
||||
<p class="push-dialog__hint">选择要推送的通道。第一版支持 Webhook 和邮件,可同时勾选。</p>
|
||||
<el-checkbox v-model="pushChannels.webhook">Webhook</el-checkbox>
|
||||
<el-checkbox v-model="pushChannels.email">邮件</el-checkbox>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="pushDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="pushing" @click="pushReport">开始推送</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -292,16 +342,6 @@ onMounted(loadReport);
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 18px;
|
||||
padding-bottom: 18px;
|
||||
border-bottom: 1px solid var(--border-subtle);
|
||||
}
|
||||
|
||||
.highlight-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
@@ -373,6 +413,17 @@ onMounted(loadReport);
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.push-dialog {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.push-dialog__hint {
|
||||
margin: 0;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.highlight-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
@@ -405,4 +456,3 @@ onMounted(loadReport);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user