diff --git a/my-project-backend/src/main/java/com/example/config/WebConfiguration.java b/my-project-backend/src/main/java/com/example/config/WebConfiguration.java index ccd70ca..7dd2cb1 100644 --- a/my-project-backend/src/main/java/com/example/config/WebConfiguration.java +++ b/my-project-backend/src/main/java/com/example/config/WebConfiguration.java @@ -1,11 +1,13 @@ package com.example.config; +import com.baomidou.mybatisplus.annotation.DbType; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; /** * 一般Web服务相关配置 @@ -22,4 +24,11 @@ public class WebConfiguration implements WebMvcConfigurer { public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } + + @Bean + public PaginationInnerInterceptor paginationInterceptor() { + PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); + paginationInnerInterceptor.setMaxLimit(100L); + return paginationInnerInterceptor; + } } diff --git a/my-project-backend/src/main/java/com/example/controller/ForumController.java b/my-project-backend/src/main/java/com/example/controller/ForumController.java index 5d2a18b..a53530b 100644 --- a/my-project-backend/src/main/java/com/example/controller/ForumController.java +++ b/my-project-backend/src/main/java/com/example/controller/ForumController.java @@ -2,10 +2,7 @@ package com.example.controller; import com.example.entity.RestBean; import com.example.entity.vo.request.TopicCreateVO; -import com.example.entity.vo.response.TopicPreviewVO; -import com.example.entity.vo.response.TopicTopVO; -import com.example.entity.vo.response.TopicTypeVO; -import com.example.entity.vo.response.WeatherVO; +import com.example.entity.vo.response.*; import com.example.service.TopicService; import com.example.service.WeatherService; import com.example.utils.Const; @@ -13,11 +10,13 @@ import com.example.utils.ControllerUtils; import jakarta.annotation.Resource; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; //论坛相关接口都在这里 +@Validated @RestController @RequestMapping("/api/forum") public class ForumController { @@ -56,11 +55,16 @@ public class ForumController { @GetMapping("/list-topic") public RestBean> listTopic(@RequestParam @Min(0) int page, @RequestParam @Min(0) int type) { - return RestBean.success(topicService.listTopicByPage(page, type)); + return RestBean.success(topicService.listTopicByPage(page + 1, type)); } @GetMapping("/top-topic") public RestBean> topTopic() { return RestBean.success(topicService.topTopics()); } + + @GetMapping("topic") + public RestBean topic(@RequestParam @Min(0) int tid){ + return RestBean.success(topicService.getTopic(tid)); + } } diff --git a/my-project-backend/src/main/java/com/example/entity/dto/AccountPrivacy.java b/my-project-backend/src/main/java/com/example/entity/dto/AccountPrivacy.java index 5f9871a..e91f3b3 100644 --- a/my-project-backend/src/main/java/com/example/entity/dto/AccountPrivacy.java +++ b/my-project-backend/src/main/java/com/example/entity/dto/AccountPrivacy.java @@ -6,6 +6,10 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.example.entity.BaseData; import lombok.Data; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + @Data @TableName("db_account_privacy") public class AccountPrivacy implements BaseData { @@ -16,4 +20,16 @@ public class AccountPrivacy implements BaseData { boolean wx = true; boolean qq = true; boolean gender = true; + + public String[] hiddenFields(){ + List strings = new ArrayList<>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + try { + if(field.getType().equals(boolean.class) && !field.getBoolean(this)) + strings.add(field.getName()); + } catch (Exception ignored) {} + } + return strings.toArray(String[]::new); + } } diff --git a/my-project-backend/src/main/java/com/example/entity/dto/Topic.java b/my-project-backend/src/main/java/com/example/entity/dto/Topic.java index b42aa4d..f9438f6 100644 --- a/my-project-backend/src/main/java/com/example/entity/dto/Topic.java +++ b/my-project-backend/src/main/java/com/example/entity/dto/Topic.java @@ -17,6 +17,4 @@ public class Topic { Integer type; Date time; Integer uid; - String username; - String avatar; } diff --git a/my-project-backend/src/main/java/com/example/entity/vo/response/TopicDetailVO.java b/my-project-backend/src/main/java/com/example/entity/vo/response/TopicDetailVO.java new file mode 100644 index 0000000..b555bdc --- /dev/null +++ b/my-project-backend/src/main/java/com/example/entity/vo/response/TopicDetailVO.java @@ -0,0 +1,28 @@ +package com.example.entity.vo.response; + +import lombok.Data; + +import java.util.Date; + +@Data +public class TopicDetailVO { + Integer id; + String title; + String content; + Integer type; + Date time; + User user; + + @Data + public static class User { + Integer uid; + String username; + String avatar; + String desc; + boolean gender; + String qq; + String wx; + String phone; + String email; + } +} diff --git a/my-project-backend/src/main/java/com/example/mapper/TopicMapper.java b/my-project-backend/src/main/java/com/example/mapper/TopicMapper.java index 3e0fea2..66c860c 100644 --- a/my-project-backend/src/main/java/com/example/mapper/TopicMapper.java +++ b/my-project-backend/src/main/java/com/example/mapper/TopicMapper.java @@ -3,22 +3,7 @@ package com.example.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.entity.dto.Topic; import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -import java.util.List; @Mapper public interface TopicMapper extends BaseMapper { - @Select(""" - select * from db_topic left join db_account on uid = db_account.id - order by `time` desc limit ${page}, 10 - """) - List topicList(int page); - - @Select(""" - select * from db_topic left join db_account on uid = db_account.id - where type = #{type} - order by `time` desc limit ${page}, 10 - """) - List topicListByType(int page, int type); } diff --git a/my-project-backend/src/main/java/com/example/service/TopicService.java b/my-project-backend/src/main/java/com/example/service/TopicService.java index a77f569..c7f804d 100644 --- a/my-project-backend/src/main/java/com/example/service/TopicService.java +++ b/my-project-backend/src/main/java/com/example/service/TopicService.java @@ -6,6 +6,7 @@ import com.example.entity.dto.TopicType; import com.example.entity.vo.request.TopicCreateVO; import com.example.entity.vo.response.TopicPreviewVO; import com.example.entity.vo.response.TopicTopVO; +import com.example.entity.vo.response.TopicDetailVO; import java.util.List; @@ -14,4 +15,5 @@ public interface TopicService extends IService { String createTopic(int uid, TopicCreateVO vo); List listTopicByPage(int pageNumber, int type); List topTopics(); + TopicDetailVO getTopic(int tid); } diff --git a/my-project-backend/src/main/java/com/example/service/impl/TopicServiceImpl.java b/my-project-backend/src/main/java/com/example/service/impl/TopicServiceImpl.java index 335ebf8..f19f60b 100644 --- a/my-project-backend/src/main/java/com/example/service/impl/TopicServiceImpl.java +++ b/my-project-backend/src/main/java/com/example/service/impl/TopicServiceImpl.java @@ -3,14 +3,14 @@ package com.example.service.impl; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.example.entity.dto.Topic; -import com.example.entity.dto.TopicType; +import com.example.entity.dto.*; import com.example.entity.vo.request.TopicCreateVO; +import com.example.entity.vo.response.TopicDetailVO; import com.example.entity.vo.response.TopicPreviewVO; import com.example.entity.vo.response.TopicTopVO; -import com.example.mapper.TopicMapper; -import com.example.mapper.TopicTypeMapper; +import com.example.mapper.*; import com.example.service.TopicService; import com.example.utils.CacheUtils; import com.example.utils.Const; @@ -27,6 +27,15 @@ public class TopicServiceImpl extends ServiceImpl implements @Resource TopicTypeMapper typeMapper; + @Resource + AccountMapper accountMapper; + + @Resource + AccountDetailsMapper accountDetailsMapper; + + @Resource + AccountPrivacyMapper accountPrivacyMapper; + @Resource FlowUtils flowUtils; @@ -63,11 +72,12 @@ public class TopicServiceImpl extends ServiceImpl implements List list = cacheUtils.takeListFromCache(key, TopicPreviewVO.class); if(list != null) return list; //无缓存从数据库读取 - List topics; + Page page = Page.of(pageNumber, 10); if(type == 0) - topics = baseMapper.topicList(pageNumber * 10); + baseMapper.selectPage(page, Wrappers.query().orderByDesc("time")); else - topics = baseMapper.topicListByType(pageNumber * 10, type); + baseMapper.selectPage(page, Wrappers.query().eq("type", type).orderByDesc("time")); + List topics = page.getRecords(); if(topics.isEmpty()) return null; list = topics.stream().map(this::resolveToPreview).toList(); cacheUtils.saveListToCache(key, list, 20); //进缓存 @@ -87,8 +97,30 @@ public class TopicServiceImpl extends ServiceImpl implements }).toList(); } + @Override + public TopicDetailVO getTopic(int tid) { + TopicDetailVO vo = new TopicDetailVO(); + Topic topic = baseMapper.selectById(tid); + BeanUtils.copyProperties(topic, vo); + TopicDetailVO.User user = new TopicDetailVO.User(); + BeanUtils.copyProperties(topic, user); + vo.setUser(this.fillUserDetailsByPrivacy(user, topic.getUid())); + return vo; + } + + private T fillUserDetailsByPrivacy(T target, int uid) { + AccountDetails details = accountDetailsMapper.selectById(uid); + Account account = accountMapper.selectById(uid); + AccountPrivacy privacy = accountPrivacyMapper.selectById(uid); + String[] ignores = privacy.hiddenFields(); + BeanUtils.copyProperties(account, target, ignores); + BeanUtils.copyProperties(details, target, ignores); + return target; + } + private TopicPreviewVO resolveToPreview(Topic topic) { TopicPreviewVO vo = new TopicPreviewVO(); + BeanUtils.copyProperties(accountMapper.selectById(topic.getUid()), vo); BeanUtils.copyProperties(topic, vo); List images = new ArrayList<>(); StringBuilder previewText = new StringBuilder(); diff --git a/my-project-frontend/src/router/index.js b/my-project-frontend/src/router/index.js index 1579849..b708215 100644 --- a/my-project-frontend/src/router/index.js +++ b/my-project-frontend/src/router/index.js @@ -30,8 +30,12 @@ const router = createRouter({ children: [ { path: '', - name: 'post-list', + name: 'topics', component: () => import('@/views/forum/TopicList.vue') + }, { + path: 'post-detail/:tid', + name: 'post-detail', + component: () => import('@/views/forum/TopicDetail.vue') }, { path: 'user-setting', name: 'user-setting', diff --git a/my-project-frontend/src/views/forum/TopicDetail.vue b/my-project-frontend/src/views/forum/TopicDetail.vue new file mode 100644 index 0000000..738ca03 --- /dev/null +++ b/my-project-frontend/src/views/forum/TopicDetail.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/my-project-frontend/src/views/forum/TopicList.vue b/my-project-frontend/src/views/forum/TopicList.vue index c804237..8bf79fd 100644 --- a/my-project-frontend/src/views/forum/TopicList.vue +++ b/my-project-frontend/src/views/forum/TopicList.vue @@ -19,6 +19,7 @@ import {ElMessage} from "element-plus"; import TopicEditor from "@/components/TopicEditor.vue"; import {useStore} from "@/store"; import axios from "axios"; +import router from "@/router"; const store = useStore() @@ -134,7 +135,8 @@ navigator.geolocation.getCurrentPosition(position => {
- +