瀏覽代碼

feat: 添加首页统计数据 API

- 后端新增 GET /api/v1/templates/stats 接口
  返回 reportCount, templateCount, variableCount, sourceFileCount
- 前端 Home.vue 调用 API 获取真实统计数据
- 更新统计卡片显示内容
何文松 1 月之前
父節點
當前提交
c6f11b1168

+ 8 - 0
backend/extract-service/src/main/java/com/lingyue/extract/controller/TemplateController.java

@@ -107,6 +107,14 @@ public class TemplateController {
         return AjaxResult.success(result);
     }
     
+    @GetMapping("/stats")
+    @Operation(summary = "获取统计数据", description = "获取首页展示的统计数据")
+    public AjaxResult<?> getStats() {
+        String userId = getCurrentUserId();
+        java.util.Map<String, Object> stats = templateService.getStats(userId);
+        return AjaxResult.success(stats);
+    }
+    
     @PutMapping("/{id}")
     @Operation(summary = "更新模板", description = "更新模板基本信息")
     public AjaxResult<?> updateTemplate(

+ 42 - 0
backend/extract-service/src/main/java/com/lingyue/extract/service/TemplateService.java

@@ -342,4 +342,46 @@ public class TemplateService {
         return template.getUserId().equals(userId) || 
                (Boolean.TRUE.equals(template.getIsPublic()) && Template.STATUS_PUBLISHED.equals(template.getStatus()));
     }
+    
+    /**
+     * 获取首页统计数据
+     */
+    public java.util.Map<String, Object> getStats(String userId) {
+        java.util.Map<String, Object> stats = new java.util.HashMap<>();
+        
+        // 获取用户的生成任务数(报告数)
+        LambdaQueryWrapper<Generation> generationQuery = new LambdaQueryWrapper<>();
+        generationQuery.eq(Generation::getUserId, userId);
+        long reportCount = generationRepository.selectCount(generationQuery);
+        stats.put("reportCount", reportCount);
+        
+        // 获取可用模板数(用户自己的 + 公开已发布的)
+        LambdaQueryWrapper<Template> templateQuery = new LambdaQueryWrapper<>();
+        templateQuery.and(wrapper -> wrapper
+                .eq(Template::getUserId, userId)
+                .or()
+                .and(w -> w.eq(Template::getIsPublic, true).eq(Template::getStatus, Template.STATUS_PUBLISHED))
+        );
+        long templateCount = templateRepository.selectCount(templateQuery);
+        stats.put("templateCount", templateCount);
+        
+        // 获取变量总数(用户模板中的变量)
+        List<Template> userTemplates = templateRepository.selectList(
+                new LambdaQueryWrapper<Template>().eq(Template::getUserId, userId));
+        long variableCount = 0;
+        for (Template t : userTemplates) {
+            variableCount += variableRepository.countByTemplateId(t.getId());
+        }
+        stats.put("variableCount", variableCount);
+        
+        // 来源文件数
+        long sourceFileCount = 0;
+        for (Template t : userTemplates) {
+            sourceFileCount += sourceFileRepository.selectCount(
+                    new LambdaQueryWrapper<SourceFile>().eq(SourceFile::getTemplateId, t.getId()));
+        }
+        stats.put("sourceFileCount", sourceFileCount);
+        
+        return stats;
+    }
 }

+ 5 - 0
frontend/vue-demo/src/api/index.js

@@ -44,6 +44,11 @@ export const templateApi = {
     return api.get('/templates', { params: { page, size } })
   },
 
+  // 获取首页统计数据
+  getStats() {
+    return api.get('/templates/stats')
+  },
+
   // 搜索模板
   search(keyword) {
     return api.get('/templates/search', { params: { keyword } })

+ 25 - 18
frontend/vue-demo/src/views/Home.vue

@@ -12,8 +12,8 @@
         <div class="stat-card card" @click="router.push('/generations')">
           <div class="stat-icon blue">📄</div>
           <div class="stat-value">{{ stats.reportCount }}</div>
-          <div class="stat-label">我的报告</div>
-          <div class="stat-trend up">↑ 3 本周新增</div>
+          <div class="stat-label">生成任务</div>
+          <div class="stat-trend">报告生成记录</div>
         </div>
       </el-col>
       <el-col :span="6">
@@ -21,23 +21,23 @@
           <div class="stat-icon purple">🎨</div>
           <div class="stat-value">{{ stats.templateCount }}</div>
           <div class="stat-label">可用模板</div>
-          <div class="stat-trend up">↑ 2 新增</div>
+          <div class="stat-trend">包含公开模板</div>
         </div>
       </el-col>
       <el-col :span="6">
         <div class="stat-card card">
-          <div class="stat-icon green">📚</div>
-          <div class="stat-value">{{ stats.documentCount }}</div>
-          <div class="stat-label">知识文档</div>
-          <div class="stat-trend">📁 1.2GB</div>
+          <div class="stat-icon green">📊</div>
+          <div class="stat-value">{{ stats.variableCount }}</div>
+          <div class="stat-label">定义变量</div>
+          <div class="stat-trend">模板变量总数</div>
         </div>
       </el-col>
       <el-col :span="6">
         <div class="stat-card card">
-          <div class="stat-icon orange">💰</div>
-          <div class="stat-value">¥{{ stats.monthCost }}</div>
-          <div class="stat-label">本月消耗</div>
-          <div class="stat-trend">↓ 12%</div>
+          <div class="stat-icon orange">📁</div>
+          <div class="stat-value">{{ stats.sourceFileCount }}</div>
+          <div class="stat-label">来源文件</div>
+          <div class="stat-trend">数据来源定义</div>
         </div>
       </el-col>
     </el-row>
@@ -174,6 +174,7 @@ import { useRouter } from 'vue-router'
 import { Promotion, UploadFilled } from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
 import { useTemplateStore } from '@/stores/template'
+import { templateApi } from '@/api'
 
 const router = useRouter()
 const templateStore = useTemplateStore()
@@ -184,10 +185,10 @@ const showUploadDialog = ref(false)
 const showCreateDialog = ref(false)
 
 const stats = reactive({
-  reportCount: 12,
-  templateCount: 15,
-  documentCount: 48,
-  monthCost: 127.50
+  reportCount: 0,
+  templateCount: 0,
+  variableCount: 0,
+  sourceFileCount: 0
 })
 
 const newTemplate = reactive({
@@ -203,6 +204,14 @@ const templateIcons = ['📊', '🏢', '📅', '💼', '📋', '📈', '🎯', '
 
 onMounted(async () => {
   try {
+    // 获取统计数据
+    const statsData = await templateApi.getStats()
+    stats.reportCount = statsData.reportCount || 0
+    stats.templateCount = statsData.templateCount || 0
+    stats.variableCount = statsData.variableCount || 0
+    stats.sourceFileCount = statsData.sourceFileCount || 0
+    
+    // 获取模板列表
     await templateStore.fetchTemplates()
     // 取前3个模板作为推荐
     recommendTemplates.value = templateStore.templates.slice(0, 3).map((t, i) => ({
@@ -213,10 +222,8 @@ onMounted(async () => {
       isOfficial: t.isPublic,
       isHot: i < 2
     }))
-    // 更新统计
-    stats.templateCount = templateStore.templates.length
   } catch (error) {
-    console.error('获取模板失败:', error)
+    console.error('获取数据失败:', error)
   }
 })