Files
live_recorder/frontend/src/components/ui/MetricCard.vue
T
nanxunandClaude Fable 5 9df174bb0b feat: add OpenList upload support and upload tasks monitoring page
Backend:
- Add OpenListRecordArtifactUploader implementing AList-compatible API upload
- Add Uploading status to RecordArtifactUploadStatus enum
- Add MarkUploadStarted() to RecordResult entity for upload progress tracking
- Add ListUploadStatus API endpoint with pagination and status filtering
- Add UploadTaskItemDto and UploadTaskListResponse models
- Add upload segment count stats (uploaded/failed/uploading) to session DTO
- Add OpenListUploadSettingsDto and upload target type OpenList

Frontend:
- Add UploadTasksView page with route /upload-tasks
- Add upload status labels and UploadTaskItem types
- Refactor MainLayout navigation and clean up main.css
- Polish DashboardView, MetricCard, StatusBadge, RightDrawer components
- Update SettingsView to support OpenList upload configuration

Build:
- Add frontend/Dockerfile.arm64 for ARM64 frontend image
- Update build-arm64-image.sh script

Other:
- Add segment_completed_openlist.sh trigger script
- Add prototype/ directory with UI mockups
- Add frontend .dockerignore refinements

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 21:14:50 +08:00

35 lines
1013 B
Vue

<script setup lang="ts">
import type { Component } from "vue";
withDefaults(
defineProps<{
label: string;
value: string | number;
description?: string;
icon?: Component | null;
}>(),
{ description: "", icon: null }
);
</script>
<template>
<article class="stat-card">
<div class="stat-card__top" style="display:flex;align-items:center;justify-content:space-between">
<span class="stat-card__label">{{ label }}</span>
<span v-if="icon" class="stat-card__ic">
<el-icon :size="18"><component :is="icon" /></el-icon>
</span>
</div>
<div class="stat-card__value">{{ value }}</div>
<div v-if="description" class="stat-card__hint">{{ description }}</div>
</article>
</template>
<style scoped>
.stat-card__top { display: flex; align-items: center; justify-content: space-between; }
.stat-card__ic {
width: 36px; height: 36px; border-radius: 8px; display: grid; place-items: center;
background: var(--accent-soft); color: var(--accent);
}
</style>