完善论坛模块 评论css展示
This commit is contained in:
@@ -54,6 +54,7 @@ type ForumPostsViewReq struct {
|
|||||||
|
|
||||||
// ForumPostsViewRes 查看帖子响应
|
// ForumPostsViewRes 查看帖子响应
|
||||||
type ForumPostsViewRes struct {
|
type ForumPostsViewRes struct {
|
||||||
|
UserName string `json:"name" description:"发帖用户昵称"`
|
||||||
model.ForumPostViewParams
|
model.ForumPostViewParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export interface TrangleAgentApiForumV1ForumPostsViewRes {
|
export interface TrangleAgentApiForumV1ForumPostsViewRes {
|
||||||
|
/** 发帖用户名称 */
|
||||||
|
name?: string;
|
||||||
/** 帖子ID */
|
/** 帖子ID */
|
||||||
id?: number;
|
id?: number;
|
||||||
/** 所属版块ID */
|
/** 所属版块ID */
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ export interface TrangleAgentInternalModelForumPostViewParams {
|
|||||||
boardId?: number;
|
boardId?: number;
|
||||||
/** 发帖用户ID */
|
/** 发帖用户ID */
|
||||||
userId?: number;
|
userId?: number;
|
||||||
|
/** 发帖用户名称 */
|
||||||
|
name?: string;
|
||||||
/** 帖子标题 */
|
/** 帖子标题 */
|
||||||
title?: string;
|
title?: string;
|
||||||
/** 帖子正文 */
|
/** 帖子正文 */
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user