自媒体内容分类功能和tag功能实现
This commit is contained in:
@@ -34,7 +34,7 @@ func Init() {
|
||||
}
|
||||
// 自动迁移
|
||||
err = DB.AutoMigrate(model.WeMediaUser{}, model.UserFans{}, model.UserBlacklist{})
|
||||
err = DB.AutoMigrate(model.Moment{}, model.MomentFile{}, model.MomentLike{}, model.MomentComment{}, model.CommentFile{}, model.MomentCollect{})
|
||||
err = DB.AutoMigrate(model.Moment{}, model.MomentFile{}, model.MomentLike{}, model.MomentComment{}, model.CommentFile{}, model.MomentCollect{}, model.Category{}, model.MomentCategory{}, model.Tag{}, model.MomentTag{})
|
||||
if err != nil {
|
||||
hlog.Error("AutoMigrate failed: " + err.Error())
|
||||
return
|
||||
|
@@ -761,3 +761,366 @@ func findAllChildCommentIDs(tx *gorm.DB, parentID int64) ([]uint, error) {
|
||||
|
||||
return childIDs, nil
|
||||
}
|
||||
|
||||
// CreateTag 创建tag
|
||||
func CreateTag(req moment.CreateTagRequest) error {
|
||||
if req.UserID == "" || req.TagName == "" {
|
||||
return errors.New("缺少必须参数")
|
||||
}
|
||||
db := DB
|
||||
db.Model(&model.Tag{}).Create(&model.Tag{
|
||||
TagName: req.TagName,
|
||||
UserID: req.UserID,
|
||||
})
|
||||
return db.Error
|
||||
}
|
||||
|
||||
// DeleteTag 删除tag
|
||||
func DeleteTag(req moment.DeleteTagRequest) error {
|
||||
if req.UserID == "" || req.TagName == "" {
|
||||
return errors.New("缺少必须参数")
|
||||
}
|
||||
db := DB
|
||||
db.Model(&model.Tag{}).
|
||||
Where("tag_name = ? AND user_id = ?", req.TagName, req.UserID).
|
||||
Delete(&model.Tag{})
|
||||
return db.Error
|
||||
}
|
||||
|
||||
// ListTag 获取tag列表
|
||||
func ListTag(req moment.ListTagRequest) ([]*moment.TagInfo, int32, error) {
|
||||
// 参数验证
|
||||
if req.Page < 1 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize < 1 {
|
||||
req.PageSize = 10
|
||||
}
|
||||
if req.PageSize > 100 { // 限制最大分页大小,防止恶意请求
|
||||
req.PageSize = 100
|
||||
}
|
||||
|
||||
db := DB
|
||||
var total int64
|
||||
var result []*moment.TagInfo
|
||||
|
||||
// 先查询总数
|
||||
if err := db.Model(&model.Tag{}).Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("查询tag总数失败: %v", err)
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
offset := int(req.PageSize * (req.Page - 1))
|
||||
|
||||
// 再查询当前页数据
|
||||
if err := db.Model(&model.Tag{}).
|
||||
Select("id,tag_name").
|
||||
Offset(int(offset)).
|
||||
Limit(int(req.PageSize)).
|
||||
Order("created_at DESC"). // 按时间倒序,最新创建的在前
|
||||
Find(&result).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return result, int32(total), nil
|
||||
}
|
||||
|
||||
// FindTag 模糊搜索tag列表
|
||||
func FindTag(keyword *string, page, pageSize int32) ([]*moment.TagInfo, int32, error) {
|
||||
// 校验分页参数合理性
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 { // 限制最大页大小,防止查询过大
|
||||
pageSize = 20
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
db := DB.Model(&model.Tag{})
|
||||
var total int64
|
||||
var result []*moment.TagInfo
|
||||
|
||||
// 处理关键词查询
|
||||
if keyword != nil && len(*keyword) > 0 {
|
||||
likePattern := "%" + *keyword + "%"
|
||||
// 多字段模糊匹配,使用括号确保OR条件正确分组
|
||||
db = db.Where("tag_name LIKE ?", likePattern)
|
||||
}
|
||||
|
||||
// 获取总条数,用于分页计算
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("获取tags总数失败: %w", err)
|
||||
}
|
||||
|
||||
// 执行分页查询
|
||||
if err := db.
|
||||
Model(model.Tag{}).
|
||||
Select("id,tag_name").
|
||||
Offset(int(offset)).
|
||||
Limit(int(pageSize)).
|
||||
Order("created_at DESC"). // 按创建时间倒序,最新的在前
|
||||
Find(&result).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("查询tag列表失败: %w", err)
|
||||
}
|
||||
|
||||
return result, int32(total), nil
|
||||
}
|
||||
|
||||
// BindTag 文章绑定标签
|
||||
func BindTag(req moment.BindTagRequest) error {
|
||||
// 参数校验
|
||||
if len(req.MomentID) == 0 || req.TagID == 0 {
|
||||
return errors.New("缺少必须参数")
|
||||
}
|
||||
|
||||
// 使用事务确保数据一致性
|
||||
return DB.Transaction(func(tx *gorm.DB) error {
|
||||
// 转换TagID类型
|
||||
tagID := uint(req.TagID)
|
||||
|
||||
// 遍历所有需要绑定的文章ID
|
||||
for _, momentID := range req.MomentID {
|
||||
mID := uint(momentID)
|
||||
|
||||
// 检查是否已绑定,避免重复绑定
|
||||
var count int64
|
||||
if err := tx.Model(&model.MomentTag{}).
|
||||
Where("moment_id = ? AND tag_id = ?", mID, tagID).
|
||||
Count(&count).Error; err != nil {
|
||||
return fmt.Errorf("检查绑定关系失败: %w", err)
|
||||
}
|
||||
|
||||
// 如果未绑定,则创建关联
|
||||
if count == 0 {
|
||||
if err := tx.Create(&model.MomentTag{
|
||||
MomentID: mID,
|
||||
TagID: tagID,
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("创建绑定关系失败: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ListMomentsByTag 获取指定标签的文章列表
|
||||
func ListMomentsByTag(req moment.ListMomentsByTagRequest) ([]*moment.Moment, int32, error) {
|
||||
// 1. 参数校验
|
||||
if req.Tag == "" {
|
||||
return nil, 0, errors.New("标签ID不能为空")
|
||||
}
|
||||
|
||||
// 处理分页参数
|
||||
page := req.Page
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := req.PageSize
|
||||
if pageSize < 1 || pageSize > 50 {
|
||||
pageSize = 10 // 限制最大页大小,避免查询压力过大
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
// 2. 构建查询:通过标签关联表查询对应的文章
|
||||
// 先查询关联关系表,再关联文章主表
|
||||
db := DB.Model(&model.MomentTag{}).
|
||||
Joins("JOIN moment ON moment_tag.moment_id = moment.id").
|
||||
Where("moment_tag.tag_id = ?", req.Tag)
|
||||
//Where("moment.status = 0") // 只查询正常状态的文章
|
||||
|
||||
// 3. 统计符合条件的总条数
|
||||
var total int64
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("统计标签下文章总数失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 分页查询文章基本信息
|
||||
var moments []*moment.Moment
|
||||
if err := db.
|
||||
Select(`moment.id, moment.user_id, moment.content, moment.visibility,
|
||||
moment.location, moment.like_count, moment.collect_count,
|
||||
moment.comment_count, moment.created_at`).
|
||||
Offset(int(offset)).
|
||||
Limit(int(pageSize)).
|
||||
Order("moment.created_at DESC"). // 按文章发布时间倒序
|
||||
Scan(&moments).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return []*moment.Moment{}, 0, nil // 无数据时返回空列表
|
||||
}
|
||||
return nil, 0, fmt.Errorf("查询标签下文章列表失败: %w", err)
|
||||
}
|
||||
|
||||
// 5. 批量查询文章图片(优化N+1查询问题)
|
||||
if len(moments) > 0 {
|
||||
// 收集所有文章ID
|
||||
var momentIDs []uint64
|
||||
for _, m := range moments {
|
||||
momentIDs = append(momentIDs, uint64(m.ID))
|
||||
}
|
||||
|
||||
// 一次查询所有文章的图片
|
||||
var files []*model.MomentFile
|
||||
if err := DB.Where("moment_id IN (?)", momentIDs).Find(&files).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("查询文章图片失败: %w", err)
|
||||
}
|
||||
|
||||
// 建立文章ID到图片的映射
|
||||
fileMap := make(map[uint64][]*moment.MomentFile)
|
||||
for _, f := range files {
|
||||
dtoFile := &moment.MomentFile{
|
||||
ID: int64(f.ID),
|
||||
MomentID: int64(f.MomentID),
|
||||
FileURL: f.FileURL,
|
||||
FileType: f.FileType,
|
||||
SortOrder: int8(f.SortOrder),
|
||||
}
|
||||
fileMap[uint64(f.MomentID)] = append(fileMap[uint64(f.MomentID)], dtoFile)
|
||||
}
|
||||
|
||||
// 为每个文章分配图片
|
||||
for _, m := range moments {
|
||||
m.Files = fileMap[uint64(m.ID)]
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 转换总条数为int32返回
|
||||
return moments, int32(total), nil
|
||||
}
|
||||
|
||||
// ListCategory 获取分类列表
|
||||
func ListCategory() ([]*moment.CategoryInfo, error) {
|
||||
db := DB
|
||||
var result []*moment.CategoryInfo
|
||||
|
||||
// 查询数据
|
||||
if err := db.Model(&model.Category{}).
|
||||
Select("id,category_name").
|
||||
Find(&result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// BindCategory 文章绑定分类
|
||||
func BindCategory(req moment.BindCategoryRequest) error {
|
||||
// 参数校验
|
||||
if len(req.MomentID) == 0 || req.CategoryID == 0 {
|
||||
return errors.New("缺少必须参数")
|
||||
}
|
||||
|
||||
// 使用事务确保数据一致性
|
||||
return DB.Transaction(func(tx *gorm.DB) error {
|
||||
// 转换类型
|
||||
categoryID := uint(req.CategoryID)
|
||||
|
||||
// 遍历所有需要绑定的文章ID
|
||||
for _, momentID := range req.MomentID {
|
||||
mID := uint(momentID)
|
||||
|
||||
// 检查是否已绑定,避免重复绑定
|
||||
var count int64
|
||||
if err := tx.Model(&model.MomentCategory{}).
|
||||
Where("moment_id = ? AND category_id = ?", mID, categoryID).
|
||||
Count(&count).Error; err != nil {
|
||||
return fmt.Errorf("检查绑定关系失败: %w", err)
|
||||
}
|
||||
|
||||
// 如果未绑定,则创建关联
|
||||
if count == 0 {
|
||||
if err := tx.Create(&model.MomentCategory{
|
||||
MomentID: mID,
|
||||
CategoryID: categoryID,
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("创建绑定关系失败: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ListMomentsByCategory 获取指定标签的文章列表
|
||||
func ListMomentsByCategory(req moment.ListMomentsByCategoryRequest) ([]*moment.Moment, int32, error) {
|
||||
// 1. 参数校验
|
||||
if req.CategoryID == 0 {
|
||||
return nil, 0, errors.New("分类不能为空")
|
||||
}
|
||||
|
||||
// 处理分页参数
|
||||
page := req.Page
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := req.PageSize
|
||||
if pageSize < 1 || pageSize > 50 {
|
||||
pageSize = 10 // 限制最大页大小,避免查询压力过大
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
|
||||
// 2. 构建查询:通过标签关联表查询对应的文章
|
||||
// 先查询关联关系表,再关联文章主表
|
||||
db := DB.Model(&model.MomentCategory{}).
|
||||
Joins("JOIN moment ON moment_category.moment_id = moment.id").
|
||||
Where("moment_category.category_id = ?", req.CategoryID)
|
||||
//Where("moment.status = 0") // 只查询正常状态的文章
|
||||
|
||||
// 3. 统计符合条件的总条数
|
||||
var total int64
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("统计标签下文章总数失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 分页查询文章基本信息
|
||||
var moments []*moment.Moment
|
||||
if err := db.
|
||||
Select(`moment.id, moment.user_id, moment.content, moment.visibility,
|
||||
moment.location, moment.like_count, moment.collect_count,
|
||||
moment.comment_count, moment.created_at`).
|
||||
Offset(int(offset)).
|
||||
Limit(int(pageSize)).
|
||||
Order("moment.created_at DESC"). // 按文章发布时间倒序
|
||||
Scan(&moments).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return []*moment.Moment{}, 0, nil // 无数据时返回空列表
|
||||
}
|
||||
return nil, 0, fmt.Errorf("查询标签下文章列表失败: %w", err)
|
||||
}
|
||||
|
||||
// 5. 批量查询文章图片(优化N+1查询问题)
|
||||
if len(moments) > 0 {
|
||||
// 收集所有文章ID
|
||||
var momentIDs []uint64
|
||||
for _, m := range moments {
|
||||
momentIDs = append(momentIDs, uint64(m.ID))
|
||||
}
|
||||
|
||||
// 一次查询所有文章的图片
|
||||
var files []*model.MomentFile
|
||||
if err := DB.Where("moment_id IN (?)", momentIDs).Find(&files).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("查询文章图片失败: %w", err)
|
||||
}
|
||||
|
||||
// 建立文章ID到图片的映射
|
||||
fileMap := make(map[uint64][]*moment.MomentFile)
|
||||
for _, f := range files {
|
||||
dtoFile := &moment.MomentFile{
|
||||
ID: int64(f.ID),
|
||||
MomentID: int64(f.MomentID),
|
||||
FileURL: f.FileURL,
|
||||
FileType: f.FileType,
|
||||
SortOrder: int8(f.SortOrder),
|
||||
}
|
||||
fileMap[uint64(f.MomentID)] = append(fileMap[uint64(f.MomentID)], dtoFile)
|
||||
}
|
||||
|
||||
// 为每个文章分配图片
|
||||
for _, m := range moments {
|
||||
m.Files = fileMap[uint64(m.ID)]
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 转换总条数为int32返回
|
||||
return moments, int32(total), nil
|
||||
}
|
||||
|
@@ -311,3 +311,190 @@ func ListUserCollects(ctx context.Context, c *app.RequestContext) {
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// CreateTag .
|
||||
// @router /v1/weMedia/moments/tag/ [POST]
|
||||
func CreateTag(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.CreateTagRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
err = mysql.CreateTag(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.CreateTagResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// DeleteTag .
|
||||
// @router /v1/weMedia/moments/tag/ [DELETE]
|
||||
func DeleteTag(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.DeleteTagRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
err = mysql.DeleteTag(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.DeleteTagResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListTag .
|
||||
// @router /v1/weMedia/moments/tag/ [GET]
|
||||
func ListTag(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.ListTagRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
tag, total, err := mysql.ListTag(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.ListTagResponse)
|
||||
resp.Tags = tag
|
||||
resp.Total = int32(total)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// FandTag .
|
||||
// @router /v1/weMedia/moments/tag/find/ [GET]
|
||||
func FandTag(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.FindTagRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
data, total, err := mysql.FindTag(&req.Keyword, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.FindTagResponse)
|
||||
resp.Tags = data
|
||||
resp.Total = total
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// BindTag .
|
||||
// @router /v1/weMedia/moments/tag/bind/ [POST]
|
||||
func BindTag(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.BindTagRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
err = mysql.BindTag(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.BindTagResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListMomentsByTag .
|
||||
// @router /v1/weMedia/moments/tag/list/ [GET]
|
||||
func ListMomentsByTag(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.ListMomentsByTagRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
data, total, err := mysql.ListMomentsByTag(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp := new(moment.ListMomentsByTagResponse)
|
||||
resp.Moments = data
|
||||
resp.Total = total
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListCategory .
|
||||
// @router /v1/weMedia/moments/category/ [GET]
|
||||
func ListCategory(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.ListCategoryRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
category, err := mysql.ListCategory()
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.ListCategoryResponse)
|
||||
resp.Categorys = category
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// BindCategory .
|
||||
// @router /v1/weMedia/moments/category/ [POST]
|
||||
func BindCategory(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.BindCategoryRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
err = mysql.BindCategory(req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
resp := new(moment.BindCategoryResponse)
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListMomentsByCategory .
|
||||
// @router /v1/weMedia/moments/category/list/ [GET]
|
||||
func ListMomentsByCategory(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req moment.ListMomentsByCategoryRequest
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
category, tatol, err := mysql.ListMomentsByCategory(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp := new(moment.ListMomentsByCategoryResponse)
|
||||
resp.Moments = category
|
||||
resp.Total = tatol
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,34 @@ type CommentFile struct {
|
||||
SortOrder int `gorm:"column:sort_order;type:int;default:0;comment:'文件排序'"`
|
||||
}
|
||||
|
||||
// Category 分类表
|
||||
type Category struct {
|
||||
gorm.Model
|
||||
CategoryName string `gorm:"column:category_name;size:50;not null;unique;comment:'分类名'"` // 分类名称
|
||||
ParentID uint `gorm:"column:parent_id;type:bigint unsigned;not null;comment:'父分类ID'"` // 父分类ID
|
||||
}
|
||||
|
||||
// MomentCategory 分类关系表
|
||||
type MomentCategory struct {
|
||||
gorm.Model
|
||||
MomentID uint `gorm:"column:moment_id;type:bigint unsigned;not null;comment:'动态ID'"`
|
||||
CategoryID uint `gorm:"column:category_id;type:bigint unsigned;not null;comment:'分类ID'"`
|
||||
}
|
||||
|
||||
// Tag 标签表
|
||||
type Tag struct {
|
||||
gorm.Model
|
||||
TagName string `gorm:"column:tag_name;size:50;not null;unique;comment:'标签名'"` // 标签名称
|
||||
UserID string `gorm:"column:user_id;type:varchar(32);not null;comment:'创建者Id'"`
|
||||
}
|
||||
|
||||
// MomentTag 标签关系表
|
||||
type MomentTag struct {
|
||||
gorm.Model
|
||||
MomentID uint `gorm:"column:moment_id;type:bigint unsigned;not null;comment:'动态ID'"`
|
||||
TagID uint `gorm:"column:tag_id;type:bigint unsigned;not null;comment:'标签ID'"`
|
||||
}
|
||||
|
||||
func (Moment) TableName() string {
|
||||
return "moment"
|
||||
}
|
||||
@@ -85,3 +113,19 @@ func (MomentCollect) TableName() string {
|
||||
func (CommentFile) TableName() string {
|
||||
return "moment_comment_file"
|
||||
}
|
||||
|
||||
func (Category) TableName() string {
|
||||
return "category"
|
||||
}
|
||||
|
||||
func (MomentCategory) TableName() string {
|
||||
return "moment_category"
|
||||
}
|
||||
|
||||
func (Tag) TableName() string {
|
||||
return "tag"
|
||||
}
|
||||
|
||||
func (MomentTag) TableName() string {
|
||||
return "moment_tag"
|
||||
}
|
||||
|
@@ -165,3 +165,78 @@ func _listuserlikesMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _categoryMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _listcategoryMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _bindcategoryMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _listmomentsbycategoryMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _tagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _deletetagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _listtagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _createtagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _bindMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _bindtagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _findMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _fandtagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _listmomentsbytagMw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _list5Mw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
||||
func _list6Mw() []app.HandlerFunc {
|
||||
// your code...
|
||||
return nil
|
||||
}
|
||||
|
@@ -25,6 +25,15 @@ func Register(r *server.Hertz) {
|
||||
_moments := _wemedia.Group("/moments", _momentsMw()...)
|
||||
_moments.DELETE("/", append(_deletemomentMw(), moment.DeleteMoment)...)
|
||||
_moments.POST("/", append(_createmomentMw(), moment.CreateMoment)...)
|
||||
{
|
||||
_category := _moments.Group("/category", _categoryMw()...)
|
||||
_category.GET("/", append(_listcategoryMw(), moment.ListCategory)...)
|
||||
_category.POST("/", append(_bindcategoryMw(), moment.BindCategory)...)
|
||||
{
|
||||
_list := _category.Group("/list", _listMw()...)
|
||||
_list.GET("/", append(_listmomentsbycategoryMw(), moment.ListMomentsByCategory)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
_collect := _moments.Group("/collect", _collectMw()...)
|
||||
_collect.POST("/", append(_collectmomentMw(), moment.CollectMoment)...)
|
||||
@@ -34,8 +43,8 @@ func Register(r *server.Hertz) {
|
||||
_comment.DELETE("/", append(_deletecommentMw(), moment.DeleteComment)...)
|
||||
_comment.POST("/", append(_commentmomentMw(), moment.CommentMoment)...)
|
||||
{
|
||||
_list := _comment.Group("/list", _listMw()...)
|
||||
_list.GET("/", append(_listmomentcommentsMw(), moment.ListMomentComments)...)
|
||||
_list0 := _comment.Group("/list", _list0Mw()...)
|
||||
_list0.GET("/", append(_listmomentcommentsMw(), moment.ListMomentComments)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -46,13 +55,31 @@ func Register(r *server.Hertz) {
|
||||
_like := _moments.Group("/like", _likeMw()...)
|
||||
_like.POST("/", append(_likemomentMw(), moment.LikeMoment)...)
|
||||
{
|
||||
_list0 := _like.Group("/list", _list0Mw()...)
|
||||
_list0.GET("/", append(_listmomentlikesMw(), moment.ListMomentLikes)...)
|
||||
_list1 := _like.Group("/list", _list1Mw()...)
|
||||
_list1.GET("/", append(_listmomentlikesMw(), moment.ListMomentLikes)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
_list1 := _moments.Group("/list", _list1Mw()...)
|
||||
_list1.GET("/", append(_listmomentsMw(), moment.ListMoments)...)
|
||||
_list2 := _moments.Group("/list", _list2Mw()...)
|
||||
_list2.GET("/", append(_listmomentsMw(), moment.ListMoments)...)
|
||||
}
|
||||
{
|
||||
_tag := _moments.Group("/tag", _tagMw()...)
|
||||
_tag.DELETE("/", append(_deletetagMw(), moment.DeleteTag)...)
|
||||
_tag.GET("/", append(_listtagMw(), moment.ListTag)...)
|
||||
_tag.POST("/", append(_createtagMw(), moment.CreateTag)...)
|
||||
{
|
||||
_bind := _tag.Group("/bind", _bindMw()...)
|
||||
_bind.POST("/", append(_bindtagMw(), moment.BindTag)...)
|
||||
}
|
||||
{
|
||||
_find := _tag.Group("/find", _findMw()...)
|
||||
_find.GET("/", append(_fandtagMw(), moment.FandTag)...)
|
||||
}
|
||||
{
|
||||
_list3 := _tag.Group("/list", _list3Mw()...)
|
||||
_list3.GET("/", append(_listmomentsbytagMw(), moment.ListMomentsByTag)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
_uncollect := _moments.Group("/unCollect", _uncollectMw()...)
|
||||
@@ -61,22 +88,22 @@ func Register(r *server.Hertz) {
|
||||
{
|
||||
_user := _moments.Group("/user", _userMw()...)
|
||||
{
|
||||
_list2 := _user.Group("/list", _list2Mw()...)
|
||||
_list2.GET("/", append(_listmomentsappointMw(), moment.ListMomentsAppoint)...)
|
||||
_list4 := _user.Group("/list", _list4Mw()...)
|
||||
_list4.GET("/", append(_listmomentsappointMw(), moment.ListMomentsAppoint)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
_usercollects := _moments.Group("/userCollects", _usercollectsMw()...)
|
||||
{
|
||||
_list3 := _usercollects.Group("/list", _list3Mw()...)
|
||||
_list3.GET("/", append(_listusercollectsMw(), moment.ListUserCollects)...)
|
||||
_list5 := _usercollects.Group("/list", _list5Mw()...)
|
||||
_list5.GET("/", append(_listusercollectsMw(), moment.ListUserCollects)...)
|
||||
}
|
||||
}
|
||||
{
|
||||
_userlike := _moments.Group("/userlike", _userlikeMw()...)
|
||||
{
|
||||
_list4 := _userlike.Group("/list", _list4Mw()...)
|
||||
_list4.GET("/", append(_listuserlikesMw(), moment.ListUserLikes)...)
|
||||
_list6 := _userlike.Group("/list", _list6Mw()...)
|
||||
_list6.GET("/", append(_listuserlikesMw(), moment.ListUserLikes)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -261,6 +261,119 @@ struct ListMomentsAppointResponse {
|
||||
3: i32 total // 总数量
|
||||
}
|
||||
|
||||
struct TagInfo{
|
||||
1: i32 id
|
||||
2: string tag_name
|
||||
}
|
||||
|
||||
struct CreateTagResponse {
|
||||
1: Code code
|
||||
2: string msg
|
||||
}
|
||||
|
||||
struct CreateTagRequest {
|
||||
1: string tag_name
|
||||
2: string user_id
|
||||
}
|
||||
|
||||
struct DeleteTagResponse {
|
||||
1: Code code
|
||||
2: string msg
|
||||
}
|
||||
|
||||
struct DeleteTagRequest {
|
||||
1: string tag_name
|
||||
2: string user_id
|
||||
}
|
||||
|
||||
struct ListTagResponse{
|
||||
1: Code code
|
||||
2: string msg
|
||||
3: list<TagInfo> tags
|
||||
4: i32 total
|
||||
}
|
||||
|
||||
struct ListTagRequest{
|
||||
1: string user_id
|
||||
2: i32 page // 页码,默认1
|
||||
3: i32 page_size // 每页数量
|
||||
}
|
||||
|
||||
struct FindTagRequest{
|
||||
1: string keyword // 关键字
|
||||
2: i32 page // 页码,默认1
|
||||
3: i32 page_size // 每页数量
|
||||
}
|
||||
|
||||
struct FindTagResponse{
|
||||
1: Code code
|
||||
2: list<TagInfo> tags
|
||||
3: i32 total
|
||||
}
|
||||
|
||||
struct BindTagResponse{
|
||||
1: Code code
|
||||
2: string msg
|
||||
}
|
||||
|
||||
struct BindTagRequest{
|
||||
1: list<i32> moment_id
|
||||
2: i32 tag_id
|
||||
}
|
||||
|
||||
// 获取指定tag动态列表请求
|
||||
struct ListMomentsByTagRequest {
|
||||
1: string tag
|
||||
2: i32 page // 页码,默认1
|
||||
3: i32 page_size // 每页数量,默认10
|
||||
}
|
||||
|
||||
// 获取指定tag动态列表响应
|
||||
struct ListMomentsByTagResponse {
|
||||
1: Code code
|
||||
2: list<Moment> moments // 动态列表
|
||||
3: i32 total // 总数量
|
||||
}
|
||||
|
||||
struct CategoryInfo{
|
||||
1: i32 id
|
||||
2: string category_name
|
||||
}
|
||||
|
||||
struct ListCategoryResponse{
|
||||
1: Code code
|
||||
2: string msg
|
||||
3: list<CategoryInfo> categorys
|
||||
}
|
||||
|
||||
struct ListCategoryRequest{
|
||||
1: string user_id
|
||||
}
|
||||
|
||||
struct BindCategoryResponse{
|
||||
1: Code code
|
||||
2: string msg
|
||||
}
|
||||
|
||||
struct BindCategoryRequest{
|
||||
1: list<i32> moment_id
|
||||
2: i32 category_id
|
||||
}
|
||||
|
||||
// 获取指定分类动态列表请求
|
||||
struct ListMomentsByCategoryRequest {
|
||||
1: i32 category_id
|
||||
2: i32 page // 页码,默认1
|
||||
3: i32 page_size // 每页数量,默认10
|
||||
}
|
||||
|
||||
// 获取指定分类动态列表响应
|
||||
struct ListMomentsByCategoryResponse {
|
||||
1: Code code
|
||||
2: list<Moment> moments // 动态列表
|
||||
3: i32 total // 总数量
|
||||
}
|
||||
|
||||
// 动态服务接口
|
||||
service MomentsService {
|
||||
// 发布动态
|
||||
@@ -304,4 +417,31 @@ service MomentsService {
|
||||
|
||||
// 删除评论
|
||||
DeleteCommentResponse DeleteComment(1: DeleteCommentRequest req)(api.delete="/v1/weMedia/moments/comment/")
|
||||
|
||||
//新增tag
|
||||
CreateTagResponse CreateTag(1: CreateTagRequest req)(api.post="/v1/weMedia/moments/tag/")
|
||||
|
||||
//删除tag
|
||||
DeleteTagResponse DeleteTag(1: DeleteTagRequest req)(api.delete="/v1/weMedia/moments/tag/")
|
||||
|
||||
//获取tag列表
|
||||
ListTagResponse ListTag(1: ListTagRequest req)(api.get="/v1/weMedia/moments/tag/")
|
||||
|
||||
//获取tag列表
|
||||
FindTagResponse FandTag(1: FindTagRequest req)(api.get="/v1/weMedia/moments/tag/find/")
|
||||
|
||||
//绑定tag
|
||||
BindTagResponse BindTag(1: BindTagRequest req)(api.post="/v1/weMedia/moments/tag/bind/")
|
||||
|
||||
//通过tag获取文章列表
|
||||
ListMomentsByTagResponse ListMomentsByTag(1: ListMomentsByTagRequest req)(api.get="/v1/weMedia/moments/tag/list/")
|
||||
|
||||
//获取分类列表
|
||||
ListCategoryResponse ListCategory(1: ListCategoryRequest req)(api.get="/v1/weMedia/moments/category/")
|
||||
|
||||
//绑定分类
|
||||
BindCategoryResponse BindCategory(1: BindCategoryRequest req)(api.post="/v1/weMedia/moments/category/")
|
||||
|
||||
//通过分类获取文章列表
|
||||
ListMomentsByCategoryResponse ListMomentsByCategory(1: ListMomentsByCategoryRequest req)(api.get="/v1/weMedia/moments/category/list/")
|
||||
}
|
Reference in New Issue
Block a user