This commit is contained in:
oneao committed 2025-12-23 22:20:33 +08:00
1 parent 9eb5639d84
commit e9ad523fcf
19 files changed
+782 -167

No files matched your search

@@ -2,10 +2,9 @@ package cn.link56.post.controller;
import cn.link56.common.BasePageVO;
import cn.link56.common.Result;
import cn.link56.post.model.dto.AddPostDTO;
import cn.link56.post.model.dto.QueryPostDTO;
import cn.link56.post.model.dto.UpdatePostDTO;
import cn.link56.post.model.dto.*;
import cn.link56.post.model.vo.EditPostVO;
import cn.link56.post.model.vo.DashboardVO;
import cn.link56.post.model.vo.QueryPostVO;
import cn.link56.post.service.PostService;
import org.springframework.validation.annotation.Validated;
@@ -20,6 +19,12 @@ public class PostController {
@Resource
private PostService postService;
@GetMapping("/{id}")
public Result<EditPostVO> getDetail(@PathVariable("id") Long id) {
EditPostVO editPostVO = postService.getDetail(id);
return Result.success(editPostVO);
}
@PostMapping("/add")
public Result<EditPostVO> addPost(@RequestBody @Validated AddPostDTO addPostDTO) {
EditPostVO editPostVO = postService.addPost(addPostDTO);
@@ -32,9 +37,30 @@ public class PostController {
return Result.success(editPostVO);
}
@PostMapping("/update/status")
public Result<EditPostVO> updatePostStatus(@RequestBody @Validated UpdatePostStatusDTO updatePostStatusDTO){
postService.updatePostStatus(updatePostStatusDTO);
return Result.success();
}
@PostMapping("/query")
public Result<BasePageVO<QueryPostVO>> queryPost(@RequestBody QueryPostDTO queryPostDTO){
BasePageVO<QueryPostVO> data = postService.queryPost(queryPostDTO);
return Result.success(data);
}
@PostMapping("/delete")
public Result<Void> deletePost(@RequestBody @Validated DeletePostDTO deletePostDTO){
postService.deletePost(deletePostDTO);
return Result.success();
}
@GetMapping("/dashboard")
public Result<DashboardVO> getDashboardData(){
DashboardVO dashboardVO = postService.getDashboardData();
return Result.success(dashboardVO);
}
}
@@ -1,6 +1,7 @@
package cn.link56.post.mapper;
import cn.link56.post.model.po.PostPO;
import cn.link56.post.model.vo.DashboardVO;
import cn.link56.post.model.vo.QueryPostVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@@ -10,8 +11,7 @@ import java.util.List;
@Mapper
public interface PostMapper extends BaseMapper<PostPO> {
List<QueryPostVO> queryPostPage(
List<QueryPostVO> selectPostPage(
@Param("offset") int offset,
@Param("limit") int limit,
@Param("userId") Long userId,
@@ -21,11 +21,16 @@ public interface PostMapper extends BaseMapper<PostPO> {
@Param("month") String month
);
Long queryPostTotal(
Long selectPostTotal(
@Param("userId") Long userId,
@Param("title") String title,
@Param("status") Integer status,
@Param("year") String year,
@Param("month") String month
);
DashboardVO.Count selectDashboardOverview(@Param("userId") Long userId);
List<DashboardVO.Chart> selectDashboardViewStats(@Param("userId") Long userId);
List<DashboardVO.Chart> selectDashboardNumberStats(@Param("userId") Long userId);
}
@@ -0,0 +1,15 @@
package cn.link56.post.model.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeletePostDTO {
@NotNull
private Long id;
}
@@ -0,0 +1,17 @@
package cn.link56.post.model.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UpdatePostStatusDTO {
@NotNull
private Long id;
@NotNull
private Integer status;
}
@@ -8,8 +8,7 @@ import lombok.Getter;
@AllArgsConstructor
public enum PostStatusEnum {
DRAFT(0, "草稿"),
PUBLISHED(1, "已发布"),
OFFLINE(2, "已下架");
PUBLISHED(1, "已发布");
private final int code;
private final String desc;
@@ -0,0 +1,35 @@
package cn.link56.post.model.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DashboardVO {
private Count allCount;
private List<Chart> numberChart;
private List<Chart> viewChart;
private List<Chart> typeChart;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Count {
private Long postCount;
private Long viewCount;
private Long likeCount;
private Long favoriteCount;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Chart {
private String label;
private Integer value;
}
}
@@ -5,11 +5,10 @@ import cn.link56.common.context.UserContext;
import cn.link56.common.utils.snowflake.idgen.IdGenerator;
import cn.link56.company.model.po.CompanyUserPO;
import cn.link56.post.mapper.PostMapper;
import cn.link56.post.model.dto.AddPostDTO;
import cn.link56.post.model.dto.QueryPostDTO;
import cn.link56.post.model.dto.UpdatePostDTO;
import cn.link56.post.model.dto.*;
import cn.link56.post.model.enums.PostStatusEnum;
import cn.link56.post.model.po.PostPO;
import cn.link56.post.model.vo.DashboardVO;
import cn.link56.post.model.vo.EditPostVO;
import cn.link56.post.model.vo.QueryPostVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -20,81 +19,203 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class PostService extends ServiceImpl<PostMapper, PostPO> {
@Resource
private PostMapper postMapper;
@Transactional
public EditPostVO addPost(AddPostDTO addPostDTO) {
public EditPostVO addPost(AddPostDTO dto) {
PostPO postPO = new PostPO();
BeanUtils.copyProperties(addPostDTO, postPO);
postPO.setTag(StringUtils.join(addPostDTO.getTags(), ","));
postPO.setCompanyId(UserContext.getCompanyId());
if(addPostDTO.getStatus() == PostStatusEnum.PUBLISHED.getCode()){
postPO.setPublishTime(new Date());
}
BeanUtils.copyProperties(dto, postPO);
postPO.setId(IdGenerator.nextId());
postPO.setCompanyId(UserContext.getCompanyId());
postPO.setTag(joinTags(dto.getTags()));
handleUpdatePublishTime(postPO, dto.getStatus());
postMapper.insert(postPO);
EditPostVO editPostVO = new EditPostVO();
BeanUtils.copyProperties(postPO, editPostVO);
editPostVO.setTags(addPostDTO.getTags());
return editPostVO;
return buildEditPostVO(postPO);
}
public BasePageVO<QueryPostVO> queryPost(QueryPostDTO queryPostDTO) {
Integer currentPage = queryPostDTO.getCurrentPage();
Integer pageSize = queryPostDTO.getPageSize();
public EditPostVO updatePost(UpdatePostDTO dto) {
PostPO postPO = postMapper.selectById(dto.getId());
if (postPO == null) {
return null;
}
String title = queryPostDTO.getTitle();
Integer status = queryPostDTO.getStatus();
String year = queryPostDTO.getYear();
String month = queryPostDTO.getMonth();
BeanUtils.copyProperties(dto, postPO);
postPO.setTag(joinTags(dto.getTags()));
int offset = (currentPage - 1) * pageSize + 1;
int limit = currentPage * pageSize;
handleUpdatePublishTime(postPO, dto.getStatus());
List<QueryPostVO> queryPostVOS = postMapper.queryPostPage(offset, limit, UserContext.getUserId(), title, status, year, month);
Long total = postMapper.queryPostTotal(UserContext.getUserId(), title, status, year, month);
postMapper.updateById(postPO);
return buildEditPostVO(postPO);
}
BasePageVO<QueryPostVO> result = new BasePageVO<>();
result.setRecords(queryPostVOS);
result.setTotal(total);
public EditPostVO getDetail(Long id) {
PostPO postPO = postMapper.selectById(id);
if (postPO == null) {
return null;
}
return buildEditPostVO(postPO);
}
public BasePageVO<QueryPostVO> queryPost(QueryPostDTO dto) {
int offset = (dto.getCurrentPage() - 1) * dto.getPageSize() + 1;
int limit = dto.getCurrentPage() * dto.getPageSize();
List<QueryPostVO> records = postMapper.selectPostPage(
offset,
limit,
UserContext.getUserId(),
dto.getTitle(),
dto.getStatus(),
dto.getYear(),
dto.getMonth()
);
Long total = postMapper.selectPostTotal(
UserContext.getUserId(),
dto.getTitle(),
dto.getStatus(),
dto.getYear(),
dto.getMonth()
);
BasePageVO<QueryPostVO> page = new BasePageVO<>();
page.setRecords(records);
page.setTotal(total);
return page;
}
/* ================= 私有方法 ================= */
private EditPostVO buildEditPostVO(PostPO postPO) {
EditPostVO vo = new EditPostVO();
BeanUtils.copyProperties(postPO, vo);
vo.setTags(
StringUtils.isBlank(postPO.getTag())
? Collections.emptyList()
: Arrays.asList(StringUtils.split(postPO.getTag(), ","))
);
return vo;
}
private String joinTags(List<String> tags) {
return CollectionUtils.isEmpty(tags)
? null
: StringUtils.join(tags, ",");
}
private void handleUpdatePublishTime(PostPO postPO, Integer status) {
if (PostStatusEnum.PUBLISHED.getCode() == status
&& postPO.getPublishTime() == null) {
postPO.setPublishTime(new Date());
}
}
@Transactional
public void deletePost(DeletePostDTO deletePostDTO) {
postMapper.deleteById(deletePostDTO.getId());
}
@Transactional
public void updatePostStatus(UpdatePostStatusDTO updatePostStatusDTO) {
Long id = updatePostStatusDTO.getId();
Integer status = updatePostStatusDTO.getStatus();
PostPO postPO = postMapper.selectById(id);
if (postPO == null) {
return;
}
postPO.setStatus(status);
postMapper.updateById(postPO);
}
public DashboardVO getDashboardData() {
Long userId = UserContext.getUserId();
DashboardVO dashboardVO = new DashboardVO();
DashboardVO.Count count = postMapper.selectDashboardOverview(userId);
// 原始数据
List<DashboardVO.Chart> viewCharts = postMapper.selectDashboardViewStats(userId);
List<DashboardVO.Chart> numberCharts = postMapper.selectDashboardNumberStats(userId);
List<DashboardVO.Chart> typeCharts = getDashboardTypeStats(userId);
// 统一处理最近 7 天,补齐缺失值
dashboardVO.setViewChart(fillLast7Days(viewCharts));
dashboardVO.setNumberChart(fillLast7Days(numberCharts));
dashboardVO.setTypeChart(typeCharts);
dashboardVO.setAllCount(count);
return dashboardVO;
}
/**
* 填充最近7天的 chart 数据,如果 map 里没有,则补 0
*/
private List<DashboardVO.Chart> fillLast7Days(List<DashboardVO.Chart> originalCharts) {
// 转 map,方便查
Map<String, Integer> map = originalCharts.stream()
.collect(Collectors.toMap(DashboardVO.Chart::getLabel, DashboardVO.Chart::getValue, (a, b) -> b));
List<DashboardVO.Chart> result = new ArrayList<>();
for (int i = 6; i >= 0; i--) {
String date = LocalDate.now().minusDays(i).toString();
result.add(new DashboardVO.Chart(date, map.getOrDefault(date, 0)));
}
return result;
}
public EditPostVO updatePost(UpdatePostDTO updatePostDTO) {
Long id = updatePostDTO.getId();
private List<DashboardVO.Chart> getDashboardTypeStats(Long userId) {
LambdaQueryWrapper<PostPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.select(PostPO::getTag)
.eq(PostPO::getStatus, PostStatusEnum.PUBLISHED.getCode())
.eq(PostPO::getCreateBy, userId);
PostPO postPO = postMapper.selectById(id);
List<PostPO> postPOS = postMapper.selectList(queryWrapper);
System.out.println(postPO);
// 用 map 统计每个 tag 出现次数
Map<String, Integer> tagCountMap = new HashMap<>();
BeanUtils.copyProperties(updatePostDTO,postPO);
postPO.setTag(StringUtils.join(updatePostDTO.getTags(), ","));
for (PostPO postPO : postPOS) {
if (postPO == null) continue;
postMapper.updateById(postPO);
String tagsStr = postPO.getTag();
if (tagsStr == null || tagsStr.isEmpty()) continue;
EditPostVO editPostVO = new EditPostVO();
// 分割逗号,并去掉空格
String[] tags = tagsStr.split(",");
for (String tag : tags) {
tag = tag.trim();
if (tag.isEmpty()) continue;
BeanUtils.copyProperties(postPO, editPostVO);
editPostVO.setTags(updatePostDTO.getTags());
tagCountMap.put(tag, tagCountMap.getOrDefault(tag, 0) + 1);
}
}
return editPostVO;
// 转成 DashboardVO.Chart 列表
List<DashboardVO.Chart> result = new ArrayList<>();
tagCountMap.forEach((tag, count) -> result.add(new DashboardVO.Chart(tag, count)));
return result;
}
}
@@ -26,7 +26,7 @@
<result property="commentCount" column="commentCount"/>
</resultMap>
<select id="queryPostPage" resultMap="QueryPostVOMap">
<select id="selectPostPage" resultMap="QueryPostVOMap">
SELECT *
FROM (
SELECT
@@ -38,10 +38,10 @@
p.b_publish_time AS publishTime,
p.b_status AS status,
(SELECT COUNT(*) FROM b_post_view v WHERE v.b_post_id = p.b_id) AS viewCount,
(SELECT COUNT(*) FROM b_post_like l WHERE l.b_post_id = p.b_id) AS likeCount,
(SELECT COUNT(*) FROM b_post_favorite f WHERE f.b_post_id = p.b_id) AS favoriteCount,
(SELECT COUNT(*) FROM b_post_comment c WHERE c.b_post_id = p.b_id) AS commentCount,
(SELECT COUNT(1) FROM b_post_view v WHERE v.b_post_id = p.b_id) AS viewCount,
(SELECT COUNT(1) FROM b_post_like l WHERE l.b_post_id = p.b_id) AS likeCount,
(SELECT COUNT(1) FROM b_post_favorite f WHERE f.b_post_id = p.b_id) AS favoriteCount,
(SELECT COUNT(1) FROM b_post_comment c WHERE c.b_post_id = p.b_id) AS commentCount,
ROW_NUMBER() OVER (ORDER BY p.b_update_time DESC) AS rn
FROM b_post p
@@ -70,7 +70,7 @@
WHERE t.rn BETWEEN #{offset} AND #{limit}
</select>
<select id="queryPostTotal" resultType="java.lang.Long">
<select id="selectPostTotal" resultType="java.lang.Long">
SELECT COUNT(*)
FROM b_post p
<where>
@@ -95,4 +95,38 @@
</if>
</where>
</select>
<select id="selectDashboardOverview" resultType="cn.link56.post.model.vo.DashboardVO$Count">
SELECT
(SELECT COUNT(*) FROM b_post WHERE b_create_by = #{userId}) AS postCount,
(SELECT COUNT(*) FROM b_post_view WHERE b_post_id IN (SELECT b_id FROM b_post WHERE b_create_by = #{userId})) AS viewCount,
(SELECT COUNT(*) FROM b_post_like WHERE b_post_id IN (SELECT b_id FROM b_post WHERE b_create_by = #{userId})) AS likeCount,
(SELECT COUNT(*) FROM b_post_favorite WHERE b_post_id IN (SELECT b_id FROM b_post WHERE b_create_by = #{userId})) AS favoriteCount
</select>
<select id="selectDashboardViewStats" resultType="cn.link56.post.model.vo.DashboardVO$Chart">
SELECT
CONVERT(VARCHAR(10), v.b_create_time, 120) AS label,
COUNT(*) AS value
FROM b_post_view v
JOIN b_post p ON v.b_post_id = p.b_id
WHERE p.b_create_by = #{userId}
AND v.b_create_time &gt;= CONVERT(DATE, DATEADD(DAY, -6, GETDATE()))
AND v.b_create_time &lt; CONVERT(DATE, DATEADD(DAY, 1, GETDATE()))
GROUP BY CONVERT(VARCHAR(10), v.b_create_time, 120)
ORDER BY label
</select>
<select id="selectDashboardNumberStats" resultType="cn.link56.post.model.vo.DashboardVO$Chart">
SELECT
CONVERT(VARCHAR(10), p.b_create_time, 120) AS label,
COUNT(*) AS value
FROM b_post p
WHERE p.b_create_by = #{userId}
AND p.b_create_time &gt;= CONVERT(DATE, DATEADD(DAY, -6, GETDATE()))
AND p.b_create_time &lt; CONVERT(DATE, DATEADD(DAY, 1, GETDATE()))
GROUP BY CONVERT(VARCHAR(10), p.b_create_time, 120)
ORDER BY label
</select>
</mapper>