统计不生效问题解决
This commit is contained in:
Generated
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "jog-framework",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getDashboardStats() {
|
||||
return request.get('/api/app/dashboard/stats')
|
||||
}
|
||||
|
||||
export function getAdminDashboardStats() {
|
||||
return request.get('/api/admin/dashboard/stats')
|
||||
}
|
||||
@@ -3,22 +3,35 @@
|
||||
<h2 class="page-title">管理后台仪表盘</h2>
|
||||
<el-row :gutter="20" style="margin-top: var(--spacing-xl);">
|
||||
<el-col :span="6">
|
||||
<el-card class="stat-card"><el-statistic title="用户数" :value="0" /></el-card>
|
||||
<el-card class="stat-card"><el-statistic title="用户数" :value="stats.userCount" /></el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card class="stat-card"><el-statistic title="文章数" :value="0" /></el-card>
|
||||
<el-card class="stat-card"><el-statistic title="文章数" :value="stats.articleCount" /></el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card class="stat-card"><el-statistic title="评论数" :value="0" /></el-card>
|
||||
<el-card class="stat-card"><el-statistic title="评论数" :value="stats.commentCount" /></el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card class="stat-card"><el-statistic title="今日访问" :value="0" /></el-card>
|
||||
<el-card class="stat-card"><el-statistic title="今日访问" :value="stats.todayVisits" /></el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getAdminDashboardStats } from '@/api/dashboard'
|
||||
|
||||
const stats = ref({ userCount: 0, articleCount: 0, commentCount: 0, todayVisits: 0 })
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const res = await getAdminDashboardStats()
|
||||
stats.value = res.data
|
||||
} catch (e) {
|
||||
console.error('Failed to load admin dashboard stats:', e)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
<el-col :span="8">
|
||||
<el-card class="stat-card">
|
||||
<el-icon class="stat-icon" size="24"><Document /></el-icon>
|
||||
<el-statistic title="我的文章" :value="0" />
|
||||
<el-statistic title="我的文章" :value="stats.articleCount" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card class="stat-card">
|
||||
<el-icon class="stat-icon" size="24"><View /></el-icon>
|
||||
<el-statistic title="总浏览量" :value="0" />
|
||||
<el-statistic title="总浏览量" :value="stats.totalViews" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card class="stat-card">
|
||||
<el-icon class="stat-icon" size="24"><Star /></el-icon>
|
||||
<el-statistic title="获赞数" :value="0" />
|
||||
<el-statistic title="获赞数" :value="stats.totalLikes" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -28,8 +28,23 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { getDashboardStats } from '@/api/dashboard'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const stats = ref({ articleCount: 0, totalViews: 0, totalLikes: 0 })
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
console.log('Dashboard: fetching stats...')
|
||||
const res = await getDashboardStats()
|
||||
console.log('Dashboard: stats response:', res)
|
||||
stats.value = res.data
|
||||
} catch (e) {
|
||||
console.error('Failed to load dashboard stats:', e)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package fun.nojava.module.blog.controller;
|
||||
|
||||
import fun.nojava.common.model.ApiResult;
|
||||
import fun.nojava.module.blog.dto.AdminDashboardStatsVO;
|
||||
import fun.nojava.module.blog.dto.DashboardStatsVO;
|
||||
import fun.nojava.module.blog.service.DashboardService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "用户仪表盘接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/app/dashboard")
|
||||
@RequiredArgsConstructor
|
||||
public class DashboardController {
|
||||
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
@Operation(summary = "获取用户仪表盘统计数据")
|
||||
@GetMapping("/stats")
|
||||
public ApiResult<DashboardStatsVO> getUserStats(@AuthenticationPrincipal Long userId) {
|
||||
return ApiResult.success(dashboardService.getUserStats(userId));
|
||||
}
|
||||
}
|
||||
|
||||
@Tag(name = "管理端仪表盘接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/admin/dashboard")
|
||||
@RequiredArgsConstructor
|
||||
class AdminDashboardController {
|
||||
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
@Operation(summary = "获取管理端仪表盘统计数据")
|
||||
@GetMapping("/stats")
|
||||
public ApiResult<AdminDashboardStatsVO> getAdminStats() {
|
||||
return ApiResult.success(dashboardService.getAdminStats());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package fun.nojava.module.blog.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AdminDashboardStatsVO {
|
||||
|
||||
private Long userCount;
|
||||
|
||||
private Long articleCount;
|
||||
|
||||
private Long commentCount;
|
||||
|
||||
private Long todayVisits;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package fun.nojava.module.blog.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DashboardStatsVO {
|
||||
|
||||
private Long articleCount;
|
||||
|
||||
private Long totalViews;
|
||||
|
||||
private Long totalLikes;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package fun.nojava.module.blog.service;
|
||||
|
||||
import fun.nojava.module.blog.dto.AdminDashboardStatsVO;
|
||||
import fun.nojava.module.blog.dto.DashboardStatsVO;
|
||||
|
||||
public interface DashboardService {
|
||||
|
||||
DashboardStatsVO getUserStats(Long userId);
|
||||
|
||||
AdminDashboardStatsVO getAdminStats();
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package fun.nojava.module.blog.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import fun.nojava.common.enums.ArticleStatus;
|
||||
import fun.nojava.module.blog.dto.AdminDashboardStatsVO;
|
||||
import fun.nojava.module.blog.dto.DashboardStatsVO;
|
||||
import fun.nojava.module.blog.entity.Article;
|
||||
import fun.nojava.module.blog.mapper.ArticleMapper;
|
||||
import fun.nojava.module.blog.service.DashboardService;
|
||||
import fun.nojava.module.system.mapper.UserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DashboardServiceImpl implements DashboardService {
|
||||
|
||||
private final ArticleMapper articleMapper;
|
||||
private final UserMapper userMapper;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public DashboardStatsVO getUserStats(Long userId) {
|
||||
log.info("Dashboard getUserStats called, userId={}", userId);
|
||||
|
||||
List<Article> articles = articleMapper.selectList(
|
||||
new LambdaQueryWrapper<Article>()
|
||||
.eq(Article::getUserId, userId)
|
||||
.ne(Article::getStatus, ArticleStatus.RECYCLE.getCode())
|
||||
);
|
||||
|
||||
long articleCount = articles.size();
|
||||
long totalViews = articles.stream().mapToLong(a -> a.getViewCount() != null ? a.getViewCount() : 0).sum();
|
||||
long totalLikes = articles.stream().mapToLong(a -> a.getLikeCount() != null ? a.getLikeCount() : 0).sum();
|
||||
|
||||
log.info("Dashboard stats for userId={}: articleCount={}, totalViews={}, totalLikes={}",
|
||||
userId, articleCount, totalViews, totalLikes);
|
||||
|
||||
return DashboardStatsVO.builder()
|
||||
.articleCount(articleCount)
|
||||
.totalViews(totalViews)
|
||||
.totalLikes(totalLikes)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdminDashboardStatsVO getAdminStats() {
|
||||
Long userCount = userMapper.selectCount(null);
|
||||
Long articleCount = articleMapper.selectCount(null);
|
||||
|
||||
Long commentCount;
|
||||
try {
|
||||
commentCount = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM blog_comment WHERE deleted = 0", Long.class);
|
||||
} catch (Exception e) {
|
||||
commentCount = 0L;
|
||||
}
|
||||
|
||||
return AdminDashboardStatsVO.builder()
|
||||
.userCount(userCount != null ? userCount : 0)
|
||||
.articleCount(articleCount != null ? articleCount : 0)
|
||||
.commentCount(commentCount != null ? commentCount : 0)
|
||||
.todayVisits(0L)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+6
-2
@@ -41,8 +41,12 @@ public class UserServiceImpl implements UserService {
|
||||
.type(user.getType())
|
||||
.status(user.getStatus())
|
||||
.articleCount(0)
|
||||
.followerCount(0)
|
||||
.followingCount(0)
|
||||
.followerCount(Math.toIntExact(userFollowMapper.selectCount(
|
||||
new LambdaQueryWrapper<UserFollow>()
|
||||
.eq(UserFollow::getFolloweeId, userId))))
|
||||
.followingCount(Math.toIntExact(userFollowMapper.selectCount(
|
||||
new LambdaQueryWrapper<UserFollow>()
|
||||
.eq(UserFollow::getFollowerId, userId))))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user