<template>
  <div class="post-detail">
    <button @click="goBack">返回列表</button>

    <h2>{{ post?.title }}</h2>
    <p>作者ID: {{ post?.userId }}</p>
    <p>发布时间: {{ post?.createdAt }}</p>
    <p style="white-space: pre-wrap">{{ post?.content }}</p>

    <hr />

    <h3>评论区</h3>

    <div v-if="loadingComments">加载评论中...</div>
    <div v-else>
      <ul>
        <li
            v-for="comment in comments"
            :key="comment.id"
            :style="{ marginBottom: '10px', paddingLeft: `${20 * getCommentLevel(comment)}px` }"
        >
          <div>
            <b>用户ID: {{ comment.userId }}</b>
            <span v-if="comment.parentId && findParentUserId(comment)">
              回复 <b>{{ findParentUserId(comment) }}</b>
            </span>
            评论时间 {{ comment.createdAt }}

            <button
                v-if="comment.userId == userId"
                @click="deleteComment(comment.id)"
                style="margin-left: 10px; color: red;"
            >
              删除
            </button>
            <button @click="startReply(comment.id)">回复</button>
          </div>

          <p style="white-space: pre-wrap">{{ comment.content }}</p>

          <div v-if="replyingTo === comment.id" style="margin-top: 5px;">
            <textarea
                v-model="replyContent"
                rows="2"
                style="width: 100%;"
                placeholder="回复内容"
            ></textarea>
            <button @click="submitReply(comment.id)">回复</button>
            <button @click="cancelReply">取消</button>
          </div>
        </li>
      </ul>

      <hr />
      <h4>发表评论</h4>
      <textarea
          v-model="newComment"
          rows="3"
          style="width: 100%;"
          placeholder="请输入评论内容"
      ></textarea>
      <button @click="submitComment">提交评论</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'

const route = useRoute()
const router = useRouter()

const postId = Number(route.params.id)
const post = ref(null)
const comments = ref([])
const loadingComments = ref(false)
const userId = localStorage.getItem('userId')

const newComment = ref('')
const replyingTo = ref(null)
const replyContent = ref('')

// 获取帖子详情
const fetchPost = async () => {
  try {
    const res = await axios.get(`http://localhost:8080/forum/post/${postId}`)
    post.value = res.data
  } catch (err) {
    ElMessage.error('加载帖子详情失败')
    router.back()
  }
}

// 获取评论（包含回复）
const fetchComments = async () => {
  loadingComments.value = true
  try {
    const res = await axios.get(`http://localhost:8080/forum/comments/${postId}`)
    comments.value = res.data
  } catch (err) {
    ElMessage.error('加载评论失败')
  } finally {
    loadingComments.value = false
  }
}

// 返回列表
const goBack = () => {
  router.back()
}

// 提交新评论（一级评论，parentId为null）
const submitComment = async () => {
  const content = newComment.value.trim()
  if (!content) {
    ElMessage.warning('请输入评论内容')
    return
  }

  try {
    await axios.post('http://localhost:8080/forum/comment', {
      postId,
      userId,
      content,
      parentId: null
    })
    ElMessage.success('评论成功')
    newComment.value = ''
    fetchComments()
  } catch (err) {
    ElMessage.error('发表评论失败')
  }
}

// 开始回复某条评论
const startReply = (commentId) => {
  replyingTo.value = commentId
  replyContent.value = ''
}

// 取消回复
const cancelReply = () => {
  replyingTo.value = null
  replyContent.value = ''
}

// 提交回复（parentId 为被回复评论的id）
const submitReply = async (parentId) => {
  const content = replyContent.value.trim()
  if (!content) {
    ElMessage.warning('请输入回复内容')
    return
  }
  try {
    await axios.post('http://localhost:8080/forum/comment', {
      postId,
      userId,
      content,
      parentId
    })
    ElMessage.success('回复成功')
    cancelReply()
    fetchComments()
  } catch (err) {
    ElMessage.error('回复失败')
  }
}

// 删除评论
const deleteComment = async (commentId) => {
  try {
    await ElMessageBox.confirm('确定删除此评论吗?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    await axios.delete(`http://localhost:8080/forum/comment/${commentId}`)
    ElMessage.success('删除成功')
    fetchComments()
  } catch (err) {
    if (err !== 'cancel') {
      ElMessage.error('删除失败')
    }
  }
}

// 计算评论缩进层级（根据 parentId 递归）
const getCommentLevel = (comment) => {
  let level = 0
  let current = comment
  while (current.parentId) {
    level++
    current = comments.value.find((c) => c.id === current.parentId)
    if (!current) break
  }
  return level
}

// 找到被回复的用户ID，用于显示“回复 XXX”
const findParentUserId = (comment) => {
  if (!comment.parentId) return null
  const parentComment = comments.value.find((c) => c.id === comment.parentId)
  return parentComment ? parentComment.userId : null
}

onMounted(() => {
  fetchPost()
  fetchComments()
})
</script>

<style scoped>
.post-detail {
  max-width: 800px;
  margin: auto;
  padding: 20px;
}
</style>
package com.example.springboot.controller;


import com.example.springboot.entity.Forum.Comment;
import com.example.springboot.entity.Forum.Post;
import com.example.springboot.service.ForumService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/forum")
public class ForumController {

    @Resource
    private ForumService forumService;

    // 发布帖子
    @PostMapping("/post")
    public String createPost(@RequestBody Post post) {
        int result = forumService.createPost(post);
        return result > 0 ? "Post created successfully" : "Post creation failed";
    }

    // 删除帖子（普通用户需要在业务层验证是否本人）
    @DeleteMapping("/post/{id}")
    public String deletePost(@PathVariable Integer id) {
        int result = forumService.deletePost(id);
        return result > 0 ? "Post deleted successfully" : "Post deletion failed";
    }

    // 修改帖子
    @PutMapping("/post")
    public String updatePost(@RequestBody Post post) {
        int result = forumService.updatePost(post);
        return result > 0 ? "Post updated successfully" : "Post update failed";
    }

    // 根据帖子ID获取帖子详情
    @GetMapping("/post/{id}")
    public Post getPostById(@PathVariable Integer id) {
        return forumService.getPostById(id);
    }

    // 模糊查询帖子标题
    @GetMapping("/posts")
    public List<Post> searchPostsByTitle(@RequestParam String title) {
        return forumService.searchPostsByTitle(title);
    }

    // 新增评论
    @PostMapping("/comment")
    public String createComment(@RequestBody Comment comment) {
        int result = forumService.createComment(comment);
        return result > 0 ? "Comment added successfully" : "Comment adding failed";
    }

    // 删除评论
    @DeleteMapping("/comment/{id}")
    public String deleteComment(@PathVariable Integer id) {
        int result = forumService.deleteComment(id);
        return result > 0 ? "Comment deleted successfully" : "Comment deletion failed";
    }

    // 修改评论
    @PutMapping("/comment")
    public String updateComment(@RequestBody Comment comment) {
        int result = forumService.updateComment(comment);
        return result > 0 ? "Comment updated successfully" : "Comment update failed";
    }

    // 获取某帖子的评论列表（包含回复）
    @GetMapping("/comments/{postId}")
    public List<Comment> getCommentsByPostId(@PathVariable Integer postId) {
        return forumService.getCommentsByPostId(postId);
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.springboot.mapper.ForumMapper">

    <!-- 插入帖子 -->
    <insert id="insertPost" parameterType="com.example.springboot.entity.Forum.Post" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO post(user_id,title,content,created_at,updated_at)
        VALUES(#{userId}, #{title}, #{content}, NOW(), NOW())
    </insert>

    <!-- 删除帖子 -->
    <delete id="deletePostById" parameterType="int">
        DELETE FROM post WHERE id = #{id}
    </delete>

    <!-- 更新帖子 -->
    <update id="updatePost" parameterType="com.example.springboot.entity.Forum.Post">
        UPDATE post
        SET title = #{title}, content = #{content}, updated_at = NOW()
        WHERE id = #{id}
    </update>

    <!-- 根据id查询帖子 -->
    <select id="selectPostById" parameterType="int" resultType="com.example.springboot.entity.Forum.Post">
        SELECT id, user_id, title, content, created_at, updated_at
        FROM post
        WHERE id = #{id}
    </select>

    <!-- 模糊搜索帖子的标题 -->
    <select id="selectPostsByTitleLike" parameterType="string" resultType="com.example.springboot.entity.Forum.Post">
        SELECT id, user_id, title, content, created_at, updated_at
        FROM post
        WHERE title LIKE CONCAT('%', #{title}, '%')
        ORDER BY created_at DESC
    </select>

    <!--  评论 -->

    <!-- 新增评论 -->
    <insert id="insertComment" parameterType="com.example.springboot.entity.Forum.Comment" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO comment(post_id, user_id, parent_comment_id, content, created_at, updated_at)
        VALUES(#{postId}, #{userId}, #{parentCommentId}, #{content}, NOW(), NOW())
    </insert>

    <!-- 删除评论 -->
    <delete id="deleteCommentById" parameterType="int">
        DELETE FROM comment WHERE id = #{id}
    </delete>

    <!-- 修改评论内容 -->
    <update id="updateComment" parameterType="com.example.springboot.entity.Forum.Comment">
        UPDATE comment
        SET content = #{content}, updated_at = NOW()
        WHERE id = #{id}
    </update>

    <!-- 查询某帖子下所有评论 -->
    <select id="selectCommentsByPostId" parameterType="int" resultType="com.example.springboot.entity.Forum.Comment">
        SELECT id, post_id, user_id, parent_comment_id, content, created_at, updated_at
        FROM comment
        WHERE post_id = #{postId}
        ORDER BY created_at ASC
    </select>

</mapper>
为什么显示的时间是2025-06-11T16:25:17？我想显示2025年06月11日16:25:17。
还有为什么// 找到被回复的用户ID，用于显示“回复 XXX”
const findParentUserId = (comment) => {
  if (!comment.parentId) return null
  const parentComment = comments.value.find((c) => c.id === comment.parentId)
  return parentComment ? parentComment.userId : null
}
这个功能没有实现，依旧是
测试帖子
作者ID: 2
发布时间: 2025-06-11T16:12:15
1111
________________________________________
评论区
•	用户ID: 2 评论时间 2025-06-11T16:42:00 回复
222222
•	用户ID: 6 评论时间 2025-06-11T16:42:22 删除回复
33333
不应该是用户id：6回复用户id：2吗？

还有为什么不显示username？

CREATE TABLE user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    password VARCHAR(100) NOT NULL,
    phone VARCHAR(11) NOT NULL UNIQUE
);