feat: Phase 3-5 - workflow, labeling, reports, dashboard enhancement, tests

This commit is contained in:
hiderfong
2026-04-22 17:22:11 +08:00
parent e71b13fe39
commit fb4aaad9fc
50 changed files with 741 additions and 323 deletions
+53 -7
View File
@@ -1,6 +1,14 @@
<template>
<div class="page-container">
<h2 class="page-title">报表统计</h2>
<div class="page-header">
<h2 class="page-title">报表统计</h2>
<el-select v-model="selectedProject" placeholder="选择项目生成报告" clearable style="width: 260px">
<el-option v-for="p in projects" :key="p.id" :label="p.name" :value="p.id" />
</el-select>
<el-button type="primary" :disabled="!selectedProject" @click="downloadReport">
<el-icon><Download /></el-icon>下载报告
</el-button>
</div>
<el-row :gutter="16" class="chart-row">
<el-col :xs="24" :md="12">
@@ -35,15 +43,20 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ref, onMounted } from 'vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { PieChart, BarChart, LineChart } from 'echarts/charts'
import { TooltipComponent, LegendComponent, GridComponent } from 'echarts/components'
import VChart from 'vue-echarts'
import { Download } from '@element-plus/icons-vue'
import { getProjects } from '@/api/project'
use([CanvasRenderer, PieChart, BarChart, LineChart, TooltipComponent, LegendComponent, GridComponent])
const selectedProject = ref<number | undefined>(undefined)
const projects = ref<any[]>([])
const levelOption = ref({
tooltip: { trigger: 'item' },
legend: { bottom: '0%', left: 'center' },
@@ -114,14 +127,48 @@ const trendOption = ref({
},
],
})
function downloadReport() {
if (!selectedProject.value) return
const token = localStorage.getItem('pdg_token')
const url = `/api/v1/reports/projects/${selectedProject.value}/download`
const a = document.createElement('a')
a.href = url
a.download = `report_project_${selectedProject.value}.docx`
if (token) {
a.setAttribute('data-token', token)
}
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
async function fetchProjects() {
try {
const res: any = await getProjects({ page: 1, page_size: 100 })
projects.value = res?.data || []
} catch (e) {
// ignore
}
}
onMounted(fetchProjects)
</script>
<style scoped lang="scss">
.page-title {
font-size: 20px;
font-weight: 600;
.page-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
color: #303133;
flex-wrap: wrap;
.page-title {
font-size: 20px;
font-weight: 600;
color: #303133;
margin-right: auto;
}
}
.chart-row {
@@ -130,7 +177,6 @@ const trendOption = ref({
.chart-card {
padding: 20px;
margin-bottom: 16px;
background: #fff;
border-radius: 8px;