:eq or :nth-child

本文探讨了JavaScript中使用`:eq`和`:nth-child`选择器的用法,具体展示了如何通过这些选择器来实现隐藏表格中特定列的`<span>`元素。代码示例清晰地说明了如何定位并操作表格内的元素。

 

$("td:eq(1)> span" ).hide();

 这段代码无效,原因不明。

 

 我的理解是循环TR 下第二列,但是实际情况没有循环

 

 

$("td:nth-child(2) > span" ).hide();
<thead><tr role="row" style="height: 10px;"><th colspan="1" rowspan="2" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 100px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">事业部</div></th><th colspan="1" rowspan="2" style="background-color: rgb(249, 221, 96); padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 80px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">大区</div></th><th colspan="1" rowspan="2" style="display: none; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 180px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">经销商</div></th><th colspan="1" rowspan="2" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">燃料<br>类型 </div></th><th colspan="5" rowspan="1" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 300px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">线索(跟进中)</div></th><th colspan="5" rowspan="1" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 300px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">进店</div></th><th colspan="5" rowspan="1" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 300px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">试驾</div></th><th colspan="5" rowspan="1" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 300px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">下订</div></th><th colspan="5" rowspan="1" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 300px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">零售</div></th><th colspan="5" rowspan="1" style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 300px;"><div class="dataTables_sizing" style="height:0;overflow:hidden;">批发</div></th><th colspan="1" rowspan="2" style="display: none; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">说明实际值</div></th><th colspan="1" rowspan="2" style="display: none; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">区域</div></th><th colspan="1" rowspan="2" style="background-color: rgb(249, 221, 96); padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 120px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">说明</div></th><th colspan="1" rowspan="2" style="display: none; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled"><div class="dataTables_sizing" style="height:0;overflow:hidden;">序号</div></th></tr><tr role="row" style="height: 0px;"><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月进度</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月进度</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月进度</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月进度</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月进度</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>目标</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月累<br>实绩</div></th><th style="background-color: rgb(249, 221, 96); font-family: "Microsoft YaHei"; font-size: 12px; font-weight: bold; padding-top: 0px; padding-bottom: 0px; border-top-width: 0px; border-bottom-width: 0px; height: 0px; width: 60px;" class="sorting_disabled" rowspan="1" colspan="1"><div class="dataTables_sizing" style="height:0;overflow:hidden;">月进度</div></th></tr></thead> 就是这部分
12-29
package com.example.job.controller.api; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.example.job.entity.Comment; import com.example.job.entity.FavoritePost; import com.example.job.entity.Post; import com.example.job.entity.ReplyComment; import com.example.job.entity.Student; import com.example.job.service.ICommentService; import com.example.job.service.IFavoritePostService; import com.example.job.service.IPostService; import com.example.job.service.IReplyCommentService; import com.example.job.service.IStudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * 小程序端 - 论坛帖子接口 */ @RestController @RequestMapping("/api/posts") public class PostApiController { @Autowired private IPostService postService; @Autowired private ICommentService commentService; @Autowired private IReplyCommentService replyCommentService; @Autowired private IFavoritePostService favoritePostService; @Autowired private IStudentService studentService; /** * 获取帖子列表 (分页 + 搜索) * @param page 页码 * @param size 每页数量 * @param keyword 搜索关键词 (匹配标题或内容, 可选) * @return 分页后的帖子列表 */ @GetMapping public ResponseEntity<?> getPosts( @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size, @RequestParam(required = false) String keyword) { Page<Post> postPage = new Page<>(page, size); QueryWrapper<Post> queryWrapper = new QueryWrapper<>(); // 只查询已发布的帖子 queryWrapper.eq("show_state", "已发布"); // 添加关键词搜索 if (StringUtils.hasText(keyword)) { queryWrapper.and(qw -> qw.like("title", keyword).or().like("content", keyword)); } // 按发布日期降序排列 queryWrapper.orderByDesc("publish_date"); Page<Post> resultPage = postService.page(postPage, queryWrapper); // 批量查发帖人信息,防止IN ()报错 Set<Integer> stuidSet = resultPage.getRecords().stream() .map(Post::getStuid) .filter(java.util.Objects::nonNull) .collect(java.util.stream.Collectors.toSet()); Map<Integer, Student> studentMap = stuidSet.isEmpty() ? new HashMap<>() : studentService.listByIds(stuidSet) .stream().collect(java.util.stream.Collectors.toMap(Student::getStuid, s -> s)); // 组装DTO List<Map<String, Object>> dtoList = resultPage.getRecords().stream().map(post -> { Map<String, Object> dto = new HashMap<>(); dto.put("post", post); Student stu = studentMap.get(post.getStuid()); dto.put("userName", stu != null ? stu.getName() : "未知用户"); dto.put("userAvatar", "/static/avatar/default.png"); // 默认头像 return dto; }).collect(java.util.stream.Collectors.toList()); Map<String, Object> pageResult = new HashMap<>(); pageResult.put("records", dtoList); pageResult.put("total", resultPage.getTotal()); pageResult.put("size", resultPage.getSize()); pageResult.put("current", resultPage.getCurrent()); return ResponseEntity.ok(pageResult); } /** * 获取帖子详情 * @param postid 帖子ID * @param stuid 学生ID (可选),用于判断是否已收藏 * @return 帖子详情 */ @GetMapping("/{postid}") public ResponseEntity<?> getPostDetail(@PathVariable Integer postid, @RequestParam(required = false) Integer stuid) { Post post = postService.getById(postid); if (post != null && "已发布".equals(post.getShowState())) { Student student = studentService.getById(post.getStuid()); Map<String, Object> result = new HashMap<>(); result.put("post", post); result.put("userName", student != null ? student.getName() : "未知用户"); result.put("userAvatar", "/static/avatar/default.png"); // 默认头像 // 检查当前用户是否已收藏该帖子 if (stuid != null) { QueryWrapper<FavoritePost> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("postid", postid).eq("stuid", stuid); boolean isFavorited = favoritePostService.count(queryWrapper) > 0; result.put("isFavorited", isFavorited); } else { result.put("isFavorited", false); } return ResponseEntity.ok(result); } else { return ResponseEntity.notFound().build(); } } /** * 发布新帖子 * @param post 帖子内容 (需要包含 title, content) * @param stuid 学生ID (实际应用中应从认证信息获取) * @return 创建的帖子信息 */ @PostMapping public ResponseEntity<?> createPost(@RequestBody Post post, @RequestParam Integer stuid) { if (!StringUtils.hasText(post.getTitle()) || !StringUtils.hasText(post.getContent())) { return ResponseEntity.badRequest().body("标题和内容不能为空"); } post.setStuid(stuid); post.setPublishDate(LocalDate.now()); post.setShowState("已发布"); // 默认直接发布 // post.setAdminid(null); // 管理员ID默认为空 // post.setHideDate(null); boolean success = postService.save(post); // 返回创建后的帖子,包含生成的 postid return success ? ResponseEntity.ok(post) : ResponseEntity.internalServerError().body("发布失败"); } // --- 收藏相关 --- /** * 收藏帖子 * @param postid 帖子ID * @param stuid 学生ID * @return 操作结果 */ @PostMapping("/{postid}/favorite") public ResponseEntity<?> favoritePost(@PathVariable Integer postid, @RequestParam Integer stuid) { QueryWrapper<FavoritePost> checkWrapper = new QueryWrapper<>(); checkWrapper.eq("postid", postid).eq("stuid", stuid); if (favoritePostService.count(checkWrapper) > 0) { return ResponseEntity.badRequest().body("已收藏该帖子"); } FavoritePost favoritePost = new FavoritePost(); favoritePost.setPostid(postid); favoritePost.setStuid(stuid); favoritePost.setFavoriteDate(LocalDate.now()); boolean success = favoritePostService.save(favoritePost); return success ? ResponseEntity.ok("收藏成功") : ResponseEntity.internalServerError().body("收藏失败"); } /** * 取消收藏帖子 * @param postid 帖子ID * @param stuid 学生ID * @return 操作结果 */ @DeleteMapping("/{postid}/favorite") public ResponseEntity<?> unfavoritePost(@PathVariable Integer postid, @RequestParam Integer stuid) { QueryWrapper<FavoritePost> deleteWrapper = new QueryWrapper<>(); deleteWrapper.eq("postid", postid).eq("stuid", stuid); boolean success = favoritePostService.remove(deleteWrapper); return success ? ResponseEntity.ok("取消收藏成功") : ResponseEntity.internalServerError().body("取消收藏失败"); } // --- 评论相关 --- /** * 获取帖子的评论列表 (分页) * @param postid 帖子ID * @param page 页码 * @param size 每页数量 * @return 评论列表 */ @GetMapping("/{postid}/comments") public ResponseEntity<?> getComments( @PathVariable Integer postid, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) { Page<Comment> commentPage = new Page<>(page, size); QueryWrapper<Comment> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("postid", postid); queryWrapper.eq("show_state", "已发布"); // 只显示已发布的评论 queryWrapper.orderByAsc("publish_date"); // 按发布时间升序 Page<Comment> resultPage = commentService.page(commentPage, queryWrapper); // 批量查评论人信息,防止IN ()报错 Set<Integer> stuidSet = resultPage.getRecords().stream() .map(Comment::getStuid) .filter(java.util.Objects::nonNull) .collect(java.util.stream.Collectors.toSet()); Map<Integer, Student> studentMap = stuidSet.isEmpty() ? new HashMap<>() : studentService.listByIds(stuidSet) .stream().collect(java.util.stream.Collectors.toMap(Student::getStuid, s -> s)); // 组装DTO List<Map<String, Object>> dtoList = resultPage.getRecords().stream().map(comment -> { Map<String, Object> dto = new HashMap<>(); dto.put("comment", comment); Student stu = studentMap.get(comment.getStuid()); dto.put("userName", stu != null ? stu.getName() : "匿名用户"); dto.put("userAvatar", "/static/avatar/default.png"); // 默认头像 return dto; }).collect(java.util.stream.Collectors.toList()); Map<String, Object> pageResult = new HashMap<>(); pageResult.put("records", dtoList); pageResult.put("total", resultPage.getTotal()); pageResult.put("size", resultPage.getSize()); pageResult.put("current", resultPage.getCurrent()); return ResponseEntity.ok(pageResult); } /** * 发布评论 * @param postid 帖子ID * @param comment 评论内容 (需要包含 content) * @param stuid 学生ID * @return 创建的评论信息 */ @PostMapping("/{postid}/comments") public ResponseEntity<?> createComment(@PathVariable Integer postid, @RequestBody Comment comment, @RequestParam Integer stuid) { if (!StringUtils.hasText(comment.getContent())) { return ResponseEntity.badRequest().body("评论内容不能为空"); } comment.setPostid(postid); comment.setStuid(stuid); comment.setPublishDate(LocalDate.now()); comment.setShowState("已发布"); boolean success = commentService.save(comment); return success ? ResponseEntity.ok(comment) : ResponseEntity.internalServerError().body("评论失败"); } // --- 回复评论相关 --- /** * 获取评论的回复列表 (分页) * @param commentid 评论ID * @param page 页码 * @param size 每页数量 * @return 回复列表 */ @GetMapping("/comments/{commentid}/replies") public ResponseEntity<?> getReplies( @PathVariable Integer commentid, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) { Page<ReplyComment> replyPage = new Page<>(page, size); QueryWrapper<ReplyComment> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("comid", commentid); queryWrapper.eq("show_state", "已发布"); queryWrapper.orderByAsc("reply_date"); Page<ReplyComment> resultPage = replyCommentService.page(replyPage, queryWrapper); // 批量查学生信息,防止IN ()报错 Set<Integer> stuidSet = resultPage.getRecords().stream() .map(ReplyComment::getStuid) .filter(java.util.Objects::nonNull) .collect(java.util.stream.Collectors.toSet()); Map<Integer, Student> studentMap = stuidSet.isEmpty() ? new HashMap<>() : studentService.listByIds(stuidSet) .stream().collect(java.util.stream.Collectors.toMap(Student::getStuid, s -> s)); // 组装DTO List<Map<String, Object>> dtoList = resultPage.getRecords().stream().map(reply -> { Map<String, Object> dto = new HashMap<>(); dto.put("replyid", reply.getStuid()); dto.put("content", reply.getContent()); dto.put("replyDate", reply.getReplyDate()); Student stu = studentMap.get(reply.getStuid()); dto.put("userName", stu != null ? stu.getName() : "匿名用户"); return dto; }).collect(java.util.stream.Collectors.toList()); Map<String, Object> pageResult = new HashMap<>(); pageResult.put("records", dtoList); pageResult.put("total", resultPage.getTotal()); pageResult.put("size", resultPage.getSize()); pageResult.put("current", resultPage.getCurrent()); return ResponseEntity.ok(pageResult); } /** * 回复评论 * @param commentid 评论ID * @param reply 回复内容 (需要包含 content) * @param stuid 学生ID * @return 创建的回复信息 */ @PostMapping("/comments/{commentid}/replies") public ResponseEntity<?> createReply(@PathVariable Integer commentid, @RequestBody ReplyComment reply, @RequestParam Integer stuid) { if (!StringUtils.hasText(reply.getContent())) { return ResponseEntity.badRequest().body("回复内容不能为空"); } // 检查父评论是否存在且可见 Comment parentComment = commentService.getById(commentid); if (parentComment == null || !"已发布".equals(parentComment.getShowState())) { return ResponseEntity.badRequest().body("评论不存在或已被隐藏"); } reply.setComid(commentid); reply.setStuid(stuid); reply.setReplyDate(LocalDate.now()); reply.setShowState("已发布"); boolean success = replyCommentService.save(reply); return success ? ResponseEntity.ok(reply) : ResponseEntity.internalServerError().body("回复失败"); } /** * 获取当前学生发布的帖子列表(分页) * @param stuid 学生ID * @param page 页码 * @param size 每页数量 * @return 分页后的帖子列表(带userName、userAvatar等) */ @GetMapping("/my") public ResponseEntity<?> getMyPosts( @RequestParam Integer stuid, @RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) { Page<Post> postPage = new Page<>(page, size); QueryWrapper<Post> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("stuid", stuid); queryWrapper.eq("show_state", "已发布"); queryWrapper.orderByDesc("publish_date"); Page<Post> resultPage = postService.page(postPage, queryWrapper); // 查学生信息 Student stu = studentService.getById(stuid); String userName = stu != null ? stu.getName() : "未知用户"; String userAvatar = "/static/avatar/default.png"; // 组装DTO List<Map<String, Object>> dtoList = resultPage.getRecords().stream().map(post -> { Map<String, Object> dto = new HashMap<>(); dto.put("postid", post.getPostid()); dto.put("title", post.getTitle()); dto.put("content", post.getContent()); dto.put("publishTime", post.getPublishDate()); dto.put("stuid", post.getStuid()); dto.put("showState", post.getShowState()); dto.put("adminid", post.getAdminid()); dto.put("hideDate", post.getHideDate()); dto.put("userName", userName); dto.put("userAvatar", userAvatar); return dto; }).collect(java.util.stream.Collectors.toList()); Map<String, Object> pageResult = new HashMap<>(); pageResult.put("records", dtoList); pageResult.put("total", resultPage.getTotal()); pageResult.put("size", resultPage.getSize()); pageResult.put("current", resultPage.getCurrent()); return ResponseEntity.ok(pageResult); } } <template> <view class="container"> <view class="post-detail-card"> <!-- 头部:文字头像、用户名、发布时间 --> <view class="card-header"> <TextAvatar :userName="post.userName" class="main-avatar" /> <view class="user-info"> <text class="username">{{ post.userName }}</text> <text class="publish-time">{{ post.publishTime }}</text> </view> </view> <!-- 帖子标题 --> <text class="post-title">{{ post.title }}</text> <!-- 内容 --> <view class="card-content"> <text class="content-text">{{ post.content }}</text> </view> <!-- 图片 --> <view class="card-images" v-if="post.images && post.images.length > 0"> <image v-for="(img, idx) in post.images" :key="idx" :src="img" mode="aspectFill" class="post-image"></image> </view> </view> <!-- 操作栏:只保留收藏和评论,图标样式 --> <view class="icon-action-bar"> <uni-icons type="star" size="28" :color="isFavorited ? '#ffc107' : '#bbb'" @click="toggleFavorite" class="icon-btn"></uni-icons> <uni-icons type="chatbubble" size="28" color="#9BC6FC" class="icon-btn" @click="onToggleCommentInput"></uni-icons> </view> <!-- 评论列表 --> <view class="comment-section"> <view v-for="item in commentList" :key="item.comment.comid" class="comment-item"> <TextAvatar :userName="item.userName" :isSmall="true" class="comment-avatar" /> <view class="comment-content" @click="onCommentClick(item)"> <text class="comment-username">{{ item.userName }}</text> <text class="comment-text">{{ item.comment.content }}</text> <text class="comment-time">{{ item.comment.publishDate }}</text> <!-- 回复区 --> <view v-if="item.replies && item.replies.length" class="reply-list"> <view v-for="reply in item.replies" :key="reply.replyid" class="reply-item"> <TextAvatar :userName="reply.userName" :isSmall="true" class="reply-avatar" /> <text class="reply-username">{{ reply.userName }}</text> <text class="reply-content">{{ reply.content }}</text> <text class="reply-time">{{ reply.replyDate }}</text> </view> </view> </view> </view> <view v-if="!commentList.length && !loadingComments" class="no-comment">暂无评论</view> </view> <!-- 评论输入框 --> <view class="comment-input-bar" v-if="showCommentInput"> <input v-model="commentContent" placeholder="写下你的评论..." class="comment-input"/> <button class="send-btn" @click="submitComment">发送</button> </view> <!-- 回复输入框,仅发帖人可见 --> <view class="reply-input-bar" v-if="showReplyInput"> <input v-model="replyContent" placeholder="回复内容..." class="reply-input" /> <button class="send-btn" @click="submitReply">发送</button> </view> </view> </template> <script> import { getPostDetail, favoritePost, unfavoritePost, getComments, createComment, getReplies } from '@/api/index.js'; import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'; import TextAvatar from '@/components/TextAvatar.vue'; export default { components: { uniIcons, TextAvatar }, data() { return { postId: null, post: {}, defaultAvatar: '/static/avatar/default.png', isFavorited: false, commentList: [], commentContent: '', loadingComments: false, showCommentInput: false, replyToCommentId: null, // 当前要回复的评论ID replyContent: '', // 回复内容 showReplyInput: false // 是否显示回复输入框 }; }, onLoad(options) { this.postId = options.id; this.fetchPostDetail(this.postId); }, methods: { async fetchPostDetail(id) { try { const stuid = uni.getStorageSync('stuid'); const res = await getPostDetail(id, stuid); // 适配后端返回结构 this.post = { id: res.post?.postid || res.postid || res.id, stuid: res.post?.stuid || res.stuid || '', title: res.post?.title || res.title || '', userName: res.userName || res.username || '匿名用户', publishTime: res.post?.publishDate || res.publishDate || res.publishTime || '', content: res.post?.content || res.content, images: res.post?.images || res.images || [] }; // 明确处理收藏状态 this.isFavorited = res.isFavorited === true; this.fetchComments(); if (this.post.userName) { uni.setNavigationBarTitle({ title: this.post.userName + '的帖子' }); } } catch (err) { uni.showToast({ title: '获取帖子详情失败', icon: 'none' }); } }, async toggleFavorite() { const stuid = uni.getStorageSync('stuid') || 10001; try { if (!this.isFavorited) { await favoritePost(this.postId, stuid); this.isFavorited = true; uni.showToast({ title: '收藏成功', icon: 'none' }); } else { await unfavoritePost(this.postId, stuid); this.isFavorited = false; uni.showToast({ title: '取消收藏', icon: 'none' }); } } catch (err) { uni.showToast({ title: '操作失败', icon: 'none' }); } }, async fetchComments() { this.loadingComments = true; try { const res = await getComments(this.postId, { page: 1, size: 20 }); const commentArr = res.records || res.data || []; // 并发获取每条评论的回复 await Promise.all(commentArr.map(async (item) => { const replyRes = await getReplies(item.comment.comid, { page: 1, size: 10 }); item.replies = (replyRes.records || replyRes.data || []).map(r => ({ ...r, userName: r.userName || '匿名用户' })); })); this.commentList = commentArr; } catch (err) { uni.showToast({ title: '获取评论失败', icon: 'none' }); } finally { this.loadingComments = false; } }, async submitComment() { if (!this.commentContent.trim()) { uni.showToast({ title: '评论不能为空', icon: 'none' }); return; } const stuid = uni.getStorageSync('stuid') || 10001; try { await createComment(this.postId, { content: this.commentContent, stuid }); this.commentContent = ''; this.fetchComments(); uni.showToast({ title: '评论成功', icon: 'success' }); } catch (err) { uni.showToast({ title: '评论失败', icon: 'none' }); } }, // 点击评论图标 onToggleCommentInput() { if (this.showReplyInput) { // 如果回复框已显示,先关闭回复框 this.showReplyInput = false; this.replyContent = ''; } // 切换评论框显示状态 this.showCommentInput = !this.showCommentInput; }, // 点击评论内容,显示回复输入框 onCommentClick(item) { console.log('点击了评论内容', item); // 只有发帖人才可以回复 const stuid = uni.getStorageSync('stuid'); console.log('当前登录stuid:', stuid, '帖子stuid:', this.post.stuid); if (stuid && String(stuid) === String(this.post.stuid)) { console.log('允许回复,显示回复输入框'); // 如果评论框已显示,先关闭评论框 if (this.showCommentInput) { this.showCommentInput = false; this.commentContent = ''; } this.replyToCommentId = item.comment.comid; this.showReplyInput = true; this.replyContent = ''; } else { console.log('非发帖人点击,不做任何操作'); // 非发帖人点击不做任何操作 return; } }, // 发送回复 async submitReply() { if (!this.replyContent.trim()) { uni.showToast({ title: '回复不能为空', icon: 'none' }); return; } const stuid = uni.getStorageSync('stuid'); try { await this.$api.createReply(this.replyToCommentId, { content: this.replyContent, stuid }); this.replyContent = ''; this.showReplyInput = false; this.fetchComments(); uni.showToast({ title: '回复成功', icon: 'success' }); } catch (err) { uni.showToast({ title: '回复失败', icon: 'none' }); } } } } </script> <style lang="scss" scoped> .container { background-color: #f8f8f8; min-height: 100vh; padding-bottom: 70px; } .post-detail-card { background-color: #fff; border-radius: 8px; padding: 15px; margin: 15px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); } .post-title { display: block; font-size: 17px; font-weight: bold; color: #222; margin-bottom: 10px; letter-spacing: 1px; margin-top: 2px; } .card-header { display: flex; align-items: center; margin-bottom: 6px; .main-avatar { width: 40px; height: 40px; font-size: 18px; margin-right: 10px; } .user-info { flex: 1; display: flex; flex-direction: column; } .username { font-size: 14px; font-weight: bold; color: #333; margin-bottom: 2px; } .publish-time { font-size: 12px; color: #999; } } .card-content { margin-bottom: 10px; .content-text { display: block; font-size: 15px; color: #333; line-height: 1.6; } } .card-images { margin-bottom: 10px; display: flex; flex-wrap: wrap; .post-image { max-width: 48%; margin-right: 2%; margin-bottom: 8px; max-height: 200px; border-radius: 6px; background-color: #f0f0f0; } .post-image:nth-child(2n) { margin-right: 0; } } .icon-action-bar { display: flex; justify-content: flex-start; align-items: center; margin: 10px 20px 10px 20px; .icon-btn { margin-right: 28px; cursor: pointer; transition: color 0.2s; } .icon-btn:active { color: #9BC6FC; } } .comment-section { margin: 10px 0; padding: 0 16px; .comment-item { display: flex; align-items: flex-start; margin-bottom: 14px; padding-left: 2px; padding-right: 2px; .comment-avatar { /* 由TextAvatar的small类控制尺寸 */ } .comment-content { flex: 1; display: flex; flex-direction: column; justify-content: center; .comment-username { font-size: 12px; font-weight: bold; color: #333; margin-bottom: 2px; } .comment-text { font-size: 12px; color: #444; margin-bottom: 2px; display: block; margin-top: 4px; margin-left: 2px; } .comment-time { font-size: 10px; color: #aaa; margin-top: 2px; } } } .no-comment { color: #aaa; text-align: center; padding: 20px 0; } } .comment-input-bar { display: flex; align-items: center; padding: 10px 15px; background-color: #ffffff; border-top: 1px solid #eeeeee; position: fixed; bottom: 0; left: 0; right: 0; z-index: 100; .comment-input { flex: 1; border: 1px solid #eee; border-radius: 16px; padding: 6px 12px; margin-right: 8px; } .send-btn { background: #9BC6FC; color: #fff; border-radius: 16px; padding: 0 20px; height: 36px; line-height: 36px; border: none; font-weight: bold; box-shadow: 0 1px 3px rgba(155,198,252,0.08); transition: background 0.2s; } .send-btn:active { background: #7bb0f7; } } .reply-input-bar { display: flex; align-items: center; padding: 8px 16px; background: #f7f7f7; border-top: 1px solid #eee; .reply-input { flex: 1; height: 32px; border: 1px solid #ddd; border-radius: 16px; padding: 0 12px; font-size: 14px; margin-right: 8px; background: #fff; } .send-btn { background: #9BC6FC; color: #fff; border: none; border-radius: 16px; padding: 0 16px; height: 32px; font-size: 14px; } } .reply-list { margin-top: 6px; padding-left: 32px; border-left: 2px solid #f0f0f0; } .reply-item { display: flex; align-items: center; margin-bottom: 4px; .reply-avatar { width: 20px; height: 20px; font-size: 10px; margin-right: 6px; } .reply-username { font-size: 11px; color: #6a8bad; font-weight: bold; margin-right: 4px; } .reply-content { font-size: 11px; color: #666; margin-right: 4px; } .reply-time { font-size: 10px; color: #bbb; } } </style> 回复失败,什么原因,怎么解决
05-11
【SCI复现】基于纳什博弈的多微网主体电热双层共享策略研究(Matlab代码实现)内容概要:本文围绕“基于纳什博弈的多微网主体电热双层共享策略研究”展开,结合Matlab代码实现,复现了SCI级别的科研成果。研究聚焦于多个微网主体之间的能源共享问题,引入纳什博弈理论构建双层优化模型,上层为各微网间的非合作博弈策略,下层为各微网内部电热联合优化调度,实现能源高效利用与经济性目标的平衡。文中详细阐述了模型构建、博弈均衡求解、约束处理及算法实现过程,并通过Matlab编程进行仿真验证,展示了多微网在电热耦合条件下的运行特性和共享效益。; 适合人群:具备一定电力系统、优化理论和博弈论基础知识的研究生、科研人员及从事能源互联网、微电网优化等相关领域的工程师。; 使用场景及目标:① 学习如何将纳什博弈应用于多主体能源系统优化;② 掌握双层优化模型的建模与求解方法;③ 复现SCI论文中的仿真案例,提升科研实践能力;④ 为微电网集群协同调度、能源共享机制设计提供技术参考。; 阅读建议:建议读者结合Matlab代码逐行理解模型实现细节,重点关注博弈均衡的求解过程与双层结构的迭代逻辑,同时可尝试修改参数或扩展模型以适应不同应用场景,深化对多主体协同优化机制的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值