bluebell社区分类列表接口实现1
route
v1.GET("/community", controller.CommunityHandler)
controller
func CommunityHandler(c *gin.Context) {
// 查询到所有的社区(community_id, community_name) 以列表的形式返回
data, err := logic.GetCommunityList()
if err != nil {
zap.L().Error("logic.GetCommunityList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy) // 不轻易把服务端报错暴露给外面
return
}
ResponseSuccess(c, data)
}
logic
func GetCommunityList() ([]*models.Community, error) {
// 查数据库 查找到所有的community 并返回
return mysql.GetCommunityList()
}
mysql/Communit
func GetCommunityList() (communityList []*models.Community, err error) {
sqlStr := "select community_id, community_name from community"
if err := db.Select(&communityList, sqlStr); err != nil {
if err == sql.ErrNoRows {
zap.L().Warn("there is no community in db")
err = nil
}
}
return
}
model
type Community struct {
ID int64 `json:"id" db:"community_id"`
Name string `json:"name" db:"community_name"`
}
bluebell社区分类列表接口实现2
route
v1.GET("/community/:id", controller.CommunityDetailHandler)
controller
// CommunityDetailHandler 社区分类详情
func CommunityDetailHandler(c *gin.Context) {
// 1. 获取社区id
idStr := c.Param("id") // 获取URL参数
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
ResponseError(c, CodeInvalidParam)
return
}
// 2. 根据id获取社区详情
data, err := logic.GetCommunityDetail(id)
if err != nil {
zap.L().Error("logic.GetCommunityList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy) // 不轻易把服务端报错暴露给外面
return
}
ResponseSuccess(c, data)
}
logic
func GetCommunityDetail(id int64) (*models.CommunityDetail, error) {
return mysql.GetCommunityDetailByID(id)
}
mysql/community
// GetCommunityDetailByID 根据ID查询社区详情
func GetCommunityDetailByID(id int64) (community *models.CommunityDetail, err error) {
community = new(models.CommunityDetail)
sqlStr := `select
community_id, community_name, introduction, create_time
from community
where community_id = ?
`
if err := db.Get(community, sqlStr, id); err != nil {
if err == sql.ErrNoRows {
err = ErrorInvalidID
}
}
return community, err
}
model
type CommunityDetail struct {
ID int64 `json:"id" db:"community_id"`
Name string `json:"name" db:"community_name"`
Introduction string `json:"introduction,omitempty" db:"introduction"`
CreateTime time.Time `json:"create_time" db:"create_time"`
}
bluebell创建帖子功能
route
v1.POST("/post", controller.CreatePostHandler)
controller
// CreatePostHandler 创建帖子的处理函数
func CreatePostHandler(c *gin.Context) {
// 1. 获取参数及参数的校验
//c.ShouldBindJSON() // validator --> binding tag
p := new(models.Post)
if err := c.ShouldBindJSON(p); err != nil {
zap.L().Debug("c.ShouldBindJSON(p) error", zap.Any("err", err))
zap.L().Error("create post with invalid param")
ResponseError(c, CodeInvalidParam)
return
}
// 从 c 取到当前发请求的用户的ID
userID, err := getCurrentUserID(c)
if err != nil {
ResponseError(c, CodeNeedLogin)
return
}
p.AuthorID = userID
// 2. 创建帖子
if err := logic.CreatePost(p); err != nil {
zap.L().Error("logic.CreatePost(p) failed", zap.Error(err))
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, nil)
}
logic
func CreatePost(p *models.Post) (err error) {
// 1. 生成post id
p.ID = snowflake.GenID()
// 2. 保存到数据库
err = mysql.CreatePost(p)
if err != nil {
return err
}
err = redis.CreatePost(p.ID, p.CommunityID)
return
// 3. 返回
}
mysql
// CreatePost 创建帖子
func CreatePost(p *models.Post) (err error) {
sqlStr := `insert into post(
post_id, title, content, author_id, community_id)
values (?, ?, ?, ?, ?)
`
_, err = db.Exec(sqlStr, p.ID, p.Title, p.Content, p.AuthorID, p.CommunityID)
return
}
model
type Post struct {
ID int64 `json:"id,string" db:"post_id"` // 帖子id
AuthorID int64 `json:"author_id" db:"author_id"` // 作者id
CommunityID int64 `json:"community_id" db:"community_id" binding:"required"` // 社区id
Status int32 `json:"status" db:"status"` // 帖子状态
Title string `json:"title" db:"title" binding:"required"` // 帖子标题
Content string `json:"content" db:"content" binding:"required"` // 帖子内容
CreateTime time.Time `json:"create_time" db:"create_time"` // 帖子创建时间
}
帖子详情功能
route
v1.GET("/post/:id", controller.GetPostDetailHandler)
controller
// GetPostDetailHandler 获取帖子详情的处理函数
func GetPostDetailHandler(c *gin.Context) {
// 1. 获取参数(从URL中获取帖子的id)
pidStr := c.Param("id")
pid, err := strconv.ParseInt(pidStr, 10, 64)
if err != nil {
zap.L().Error("get post detail with invalid param", zap.Error(err))
ResponseError(c, CodeInvalidParam)
return
}
// 2. 根据id取出帖子数据(查数据库)
data, err := logic.GetPostById(pid)
if err != nil {
zap.L().Error("logic.GetPostById(pid) failed", zap.Error(err))
ResponseError(c, CodeServerBusy)
return
}
// 3. 返回响应
ResponseSuccess(c, data)
}
logic
// GetPostById 根据帖子id查询帖子详情数据
func GetPostById(pid int64) (data *models.ApiPostDetail, err error) {
// 查询并组合我们接口想用的数据
post, err := mysql.GetPostById(pid)
if err != nil {
zap.L().Error("mysql.GetPostById(pid) failed",
zap.Int64("pid", pid),
zap.Error(err))
return
}
// 根据作者id查询作者信息
user, err := mysql.GetUserById(post.AuthorID)
if err != nil {
zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
zap.Int64("author_id", post.AuthorID),
zap.Error(err))
return
}
// 根据社区id查询社区详细信息
community, err := mysql.GetCommunityDetailByID(post.CommunityID)
if err != nil {
zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
zap.Int64("community_id", post.CommunityID),
zap.Error(err))
return
}
// 接口数据拼接
data = &models.ApiPostDetail{
AuthorName: user.Username,
Post: post,
CommunityDetail: community,
}
return
}
mysql
// GetPostById 根据id查询单个贴子数据
func GetPostById(pid int64) (post *models.Post, err error) {
post = new(models.Post)
sqlStr := `select
post_id, title, content, author_id, community_id, create_time
from post
where post_id = ?
`
err = db.Get(post, sqlStr, pid)
return
}
bluebell实现分页展示帖子列表
route
v1.GET("/posts", controller.GetPostListHandler)
controller
// GetPostListHandler 获取帖子列表的处理函数
func GetPostListHandler(c *gin.Context) {
// 获取分页参数
page, size := getPageInfo(c)
// 获取数据
data, err := logic.GetPostList(page, size)
if err != nil {
zap.L().Error("logic.GetPostList() failed", zap.Error(err))
ResponseError(c, CodeServerBusy)
return
}
ResponseSuccess(c, data)
// 返回响应
}
logic
// GetPostList 获取帖子列表
func GetPostList(page, size int64) (data []*models.ApiPostDetail, err error) {
posts, err := mysql.GetPostList(page, size)
if err != nil {
return nil, err
}
data = make([]*models.ApiPostDetail, 0, len(posts))
for _, post := range posts {
// 根据作者id查询作者信息
user, err := mysql.GetUserById(post.AuthorID)
if err != nil {
zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
zap.Int64("author_id", post.AuthorID),
zap.Error(err))
continue
}
// 根据社区id查询社区详细信息
community, err := mysql.GetCommunityDetailByID(post.CommunityID)
if err != nil {
zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
zap.Int64("community_id", post.CommunityID),
zap.Error(err))
continue
}
postDetail := &models.ApiPostDetail{
AuthorName: user.Username,
Post: post,
CommunityDetail: community,
}
data = append(data, postDetail)
}
return
}
mysql
// GetPostList 查询帖子列表函数
func GetPostList(page, size int64) (posts []*models.Post, err error) {
sqlStr := `select
post_id, title, content, author_id, community_id, create_time
from post
ORDER BY create_time
DESC
limit ?,?
`
posts = make([]*models.Post, 0, 2) // 不要写成make([]*models.Post, 2)
err = db.Select(&posts, sqlStr, (page-1)*size, size)
return
}
model
// ApiPostDetail 帖子详情接口的结构体
type ApiPostDetail struct {
AuthorName string `json:"author_name"` // 作者
VoteNum int64 `json:"vote_num"` // 投票数
*Post // 嵌入帖子结构体
*CommunityDetail `json:"community"` // 嵌入社区信息
}
获取分页函数getPageInfo
func getPageInfo(c *gin.Context) (int64, int64) {
pageStr := c.Query("page")
sizeStr := c.Query("size")
var (
page int64
size int64
err error
)
page, err = strconv.ParseInt(pageStr, 10, 64)
if err != nil {
page = 1
}
size, err = strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
size = 10
}
return page, size
}