完善论坛模块 评论css展示

This commit is contained in:
2026-02-05 23:15:21 +08:00
parent b88198f0f8
commit e79d2e877c
6 changed files with 94 additions and 11 deletions

View File

@@ -54,6 +54,7 @@ type ForumPostsViewReq struct {
// ForumPostsViewRes 查看帖子响应 // ForumPostsViewRes 查看帖子响应
type ForumPostsViewRes struct { type ForumPostsViewRes struct {
UserName string `json:"name" description:"发帖用户昵称"`
model.ForumPostViewParams model.ForumPostViewParams
} }

View File

@@ -30,9 +30,6 @@ func (s *sForumPosts) Create(ctx context.Context, req *v1.ForumPostsCreateReq) (
if len(req.Title) < 5 || len(req.Title) > 100 { if len(req.Title) < 5 || len(req.Title) > 100 {
return nil, gerror.New("标题长度要在5-100之间") return nil, gerror.New("标题长度要在5-100之间")
} }
if len(req.Content) < 5 || len(req.Content) > 10000 {
return nil, gerror.New("内容长度要在5-10000之间")
}
if req.BoardId == 0 { if req.BoardId == 0 {
return nil, gerror.New("板块ID不能为空") return nil, gerror.New("板块ID不能为空")
} }
@@ -107,7 +104,17 @@ func (s *sForumPosts) View(ctx context.Context, req *v1.ForumPostsViewReq) (res
if err != nil { if err != nil {
return nil, gerror.Wrap(err, "查询帖子失败") return nil, gerror.Wrap(err, "查询帖子失败")
} }
// 查询用户名称
type User struct {
Name string `json:"name" orm:"nickname" description:"用户昵称"`
}
var user User
err = dao.Users.Ctx(ctx).Where(dao.Users.Columns().Id, post.UserId).Scan(&user)
if err != nil {
return nil, gerror.Wrap(err, "查询用户昵称失败")
}
return &v1.ForumPostsViewRes{ return &v1.ForumPostsViewRes{
UserName: user.Name,
ForumPostViewParams: post, ForumPostViewParams: post,
}, nil }, nil
} }
@@ -159,6 +166,46 @@ func (s *sForumPosts) List(ctx context.Context, req *v1.ForumPostsListReq) (res
if err != nil { if err != nil {
return nil, gerror.Wrap(err, "查询帖子列表失败") return nil, gerror.Wrap(err, "查询帖子列表失败")
} }
// 查询用户名称
if len(list) > 0 {
type User struct {
Id uint64 `json:"id" orm:"id"`
Name string `json:"name" orm:"nickname"`
}
var users []User
// 构造去重后的用户 ID 切片
idSet := make(map[uint64]struct{}, len(list))
for _, item := range list {
idSet[item.UserId] = struct{}{}
}
userIds := make([]uint64, 0, len(idSet))
for id := range idSet {
userIds = append(userIds, id)
}
err = dao.Users.Ctx(ctx).
Fields(dao.Users.Columns().Id, dao.Users.Columns().Nickname).
Where(dao.Users.Columns().Id, userIds).
Scan(&users)
if err != nil {
return nil, gerror.Wrap(err, "查询用户名称失败")
}
// 建立 userId -> name 映射
userMap := make(map[uint64]string, len(users))
for _, user := range users {
userMap[user.Id] = user.Name
}
// 关联用户名称
for _, item := range list {
if name, ok := userMap[item.UserId]; ok {
item.Name = name
}
}
}
return &v1.ForumPostsListRes{ return &v1.ForumPostsListRes{
PageResult: response.PageResult{ PageResult: response.PageResult{
Total: total, Total: total,

View File

@@ -58,6 +58,7 @@ type ForumPostViewParams struct {
Id uint64 `json:"id" description:"帖子ID"` Id uint64 `json:"id" description:"帖子ID"`
BoardId uint64 `json:"boardId" description:"所属版块ID"` BoardId uint64 `json:"boardId" description:"所属版块ID"`
UserId uint64 `json:"userId" description:"发帖用户ID"` UserId uint64 `json:"userId" description:"发帖用户ID"`
Name string `json:"name" description:"发帖用户名称"`
Title string `json:"title" description:"帖子标题"` Title string `json:"title" description:"帖子标题"`
Content string `json:"content" description:"帖子正文"` Content string `json:"content" description:"帖子正文"`
CoverImage string `json:"coverImage" description:"帖子封面图URL"` CoverImage string `json:"coverImage" description:"帖子封面图URL"`

View File

@@ -1,4 +1,6 @@
export interface TrangleAgentApiForumV1ForumPostsViewRes { export interface TrangleAgentApiForumV1ForumPostsViewRes {
/** 发帖用户名称 */
name?: string;
/** 帖子ID */ /** 帖子ID */
id?: number; id?: number;
/** 所属版块ID */ /** 所属版块ID */

View File

@@ -5,6 +5,8 @@ export interface TrangleAgentInternalModelForumPostViewParams {
boardId?: number; boardId?: number;
/** 发帖用户ID */ /** 发帖用户ID */
userId?: number; userId?: number;
/** 发帖用户名称 */
name?: string;
/** 帖子标题 */ /** 帖子标题 */
title?: string; title?: string;
/** 帖子正文 */ /** 帖子正文 */

View File

@@ -3,7 +3,7 @@
<div class="page-header"> <div class="page-header">
<div class="header-content"> <div class="header-content">
<div class="title-section"> <div class="title-section">
<h1 class="page-title">通讯频道 // FORUM</h1> <h1 class="page-title">冷冻酸奶茶水间</h1>
<p class="page-subtitle">内部情报交换与讨论终端</p> <p class="page-subtitle">内部情报交换与讨论终端</p>
</div> </div>
<div class="actions"> <div class="actions">
@@ -22,10 +22,11 @@
</div> </div>
</div> </div>
<!-- 帖子列表 -->
<div class="forum-content"> <div class="forum-content">
<div class="post-list-container" v-loading="loading"> <div class="post-list-container" v-loading="loading">
<a-empty v-if="!loading && posts.length === 0" description="暂无情报记录" /> <a-empty v-if="!loading && posts.length === 0" description="暂无情报记录" />
<!-- 帖子卡片 -->
<div <div
v-for="post in posts" v-for="post in posts"
:key="post.id" :key="post.id"
@@ -34,8 +35,11 @@
> >
<div class="post-header"> <div class="post-header">
<div class="post-title">{{ post.title }}</div> <div class="post-title">{{ post.title }}</div>
<div class="post-author">
<UserOutlined />
<span class="author-name">{{ post.name || '匿名用户' }}</span>
</div>
<div class="post-meta"> <div class="post-meta">
<span class="meta-item"><UserOutlined /> ID: {{ post.userId }}</span>
<span class="meta-item"><ClockCircleOutlined /> {{ formatTime(post.createdAt) }}</span> <span class="meta-item"><ClockCircleOutlined /> {{ formatTime(post.createdAt) }}</span>
</div> </div>
</div> </div>
@@ -51,7 +55,7 @@
<div class="status-tag" :class="post.status">{{ post.status || 'NORMAL' }}</div> <div class="status-tag" :class="post.status">{{ post.status || 'NORMAL' }}</div>
</div> </div>
</div> </div>
<!-- 分页器 -->
<div class="pagination-wrapper" v-if="total > 0"> <div class="pagination-wrapper" v-if="total > 0">
<a-pagination <a-pagination
v-model:current="pagination.page" v-model:current="pagination.page"
@@ -101,7 +105,6 @@
<div v-if="currentPost" class="post-detail"> <div v-if="currentPost" class="post-detail">
<h2 class="detail-title">{{ currentPost.title }}</h2> <h2 class="detail-title">{{ currentPost.title }}</h2>
<div class="detail-meta"> <div class="detail-meta">
<span>发布者ID: {{ currentPost.userId }}</span>
<span>{{ formatTime(currentPost.createdAt) }}</span> <span>{{ formatTime(currentPost.createdAt) }}</span>
</div> </div>
@@ -115,7 +118,6 @@
<a-empty v-if="comments.length === 0" description="暂无评论" /> <a-empty v-if="comments.length === 0" description="暂无评论" />
<div v-for="comment in comments" :key="comment.id" class="comment-item"> <div v-for="comment in comments" :key="comment.id" class="comment-item">
<div class="comment-header"> <div class="comment-header">
<span class="comment-user">ID: {{ comment.userId }}</span>
<span class="comment-time">{{ formatTime(comment.createdAt) }}</span> <span class="comment-time">{{ formatTime(comment.createdAt) }}</span>
</div> </div>
<div class="comment-body"> <div class="comment-body">
@@ -419,8 +421,7 @@ onMounted(async () => {
.post-header { .post-header {
display: flex; display: flex;
justify-content: space-between; align-items: center;
align-items: flex-start;
margin-bottom: 12px; margin-bottom: 12px;
} }
@@ -428,6 +429,35 @@ onMounted(async () => {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: #e2e8f0; color: #e2e8f0;
flex: 1;
margin-right: 16px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.post-author {
display: flex;
align-items: center;
gap: 6px;
color: #94a3b8;
font-size: 13px;
margin-right: 16px;
background: rgba(255, 255, 255, 0.05);
padding: 4px 10px;
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.05);
transition: all 0.3s ease;
}
.post-author:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.1);
color: #e2e8f0;
}
.author-name {
font-weight: 500;
} }
.post-meta { .post-meta {