ReportPreview.vue
2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<script setup lang="ts">
import type { ReportTask } from '@/types'
import { statusTone } from '@/utils/format'
defineProps<{
selectedTask: ReportTask | null
previewUrl: string
}>()
</script>
<template>
<div class="preview-shell">
<div class="preview-head archive-panel">
<div>
<p class="archive-kicker">Preview Canvas</p>
<h3 class="archive-card-title">{{ selectedTask?.query || '等待选择报告任务' }}</h3>
<p class="archive-copy">
{{ selectedTask?.error_message || '生成完成后,会在这里以纸面化的形式展示当前报告内容。' }}
</p>
</div>
<span v-if="selectedTask" class="archive-chip" :data-tone="statusTone(selectedTask.status)">
<span class="archive-chip__dot" />
{{ selectedTask.status }} · {{ selectedTask.progress }}%
</span>
</div>
<div class="preview-paper">
<div class="preview-paper__header">
<div>
<p class="archive-kicker">Internal Operations Report</p>
<strong>{{ selectedTask?.query || 'Venue Operations Report' }}</strong>
</div>
<span>{{ selectedTask?.task_id || 'N/A' }}</span>
</div>
<iframe v-if="previewUrl" class="preview-frame" :src="previewUrl" title="报告预览" />
<div v-else class="preview-empty">
<strong>暂无可预览的报告</strong>
<p class="archive-copy">生成完成后会自动显示在这里,历史任务也可以随时重新打开。</p>
</div>
</div>
</div>
</template>
<style scoped>
.preview-shell {
display: grid;
gap: 18px;
min-width: 0;
}
.preview-head {
display: flex;
justify-content: space-between;
gap: 18px;
align-items: flex-start;
}
.preview-paper {
min-height: 920px;
padding: 22px;
border: 1px solid rgba(24, 35, 31, 0.08);
border-radius: 28px;
background:
linear-gradient(180deg, rgba(244, 238, 228, 0.88), rgba(248, 243, 236, 0.82));
box-shadow: var(--shadow-soft);
}
.preview-paper__header {
display: flex;
justify-content: space-between;
gap: 18px;
align-items: end;
padding: 0 6px 18px;
border-bottom: 3px solid rgba(22, 52, 45, 0.18);
}
.preview-paper__header strong {
display: block;
margin-top: 6px;
font-family: var(--font-display);
font-size: clamp(28px, 3vw, 40px);
color: var(--primary);
}
.preview-paper__header span {
font-family: var(--font-mono);
color: var(--text-soft);
letter-spacing: 0.12em;
text-transform: uppercase;
}
.preview-frame {
width: 100%;
min-height: 820px;
margin-top: 20px;
border: 0;
border-radius: 18px;
background: #fff;
}
.preview-empty {
display: grid;
place-items: center;
gap: 10px;
min-height: 820px;
padding: 32px;
text-align: center;
}
@media (max-width: 820px) {
.preview-head,
.preview-paper__header {
flex-direction: column;
align-items: flex-start;
}
}
</style>