258 lines
6.3 KiB
Go
258 lines
6.3 KiB
Go
package services
|
|
|
|
import (
|
|
"errors"
|
|
"platform/pkg/u"
|
|
"platform/web/core"
|
|
m "platform/web/models"
|
|
q "platform/web/queries"
|
|
"time"
|
|
|
|
"gorm.io/gen/field"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var Article = &articleService{}
|
|
|
|
type articleService struct{}
|
|
|
|
func (s *articleService) Page(req *PageArticleReq) (result []*m.Article, count int64, err error) {
|
|
do := q.Article.Where()
|
|
if req.Keyword != nil && *req.Keyword != "" {
|
|
do = do.Where(q.Article.Title.Like("%" + *req.Keyword + "%"))
|
|
}
|
|
if req.GroupID != nil {
|
|
do = do.Where(q.Article.GroupID.Eq(*req.GroupID))
|
|
}
|
|
if req.Status != nil {
|
|
do = do.Where(q.Article.Status.Eq(int(*req.Status)))
|
|
}
|
|
|
|
return q.Article.
|
|
Preload(q.Article.Group).
|
|
Where(do).
|
|
Omit(q.Article.Content).
|
|
Order(q.Article.Sort, q.Article.CreatedAt).
|
|
FindByPage(req.GetOffset(), req.GetLimit())
|
|
}
|
|
|
|
type PageArticleReq struct {
|
|
core.PageReq
|
|
Keyword *string `json:"keyword,omitempty"`
|
|
GroupID *int32 `json:"group_id,omitempty"`
|
|
Status *m.ArticleStatus `json:"status,omitempty"`
|
|
}
|
|
|
|
func (s *articleService) GetByAdmin(id int32) (*m.Article, error) {
|
|
article, err := q.Article.
|
|
Preload(q.Article.Group).
|
|
Where(q.Article.ID.Eq(id)).
|
|
Take()
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, core.NewBizErr("文档不存在")
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return article, nil
|
|
}
|
|
|
|
func (s *articleService) Create(data CreateArticleData) error {
|
|
if err := s.ensureGroupExists(data.GroupID); err != nil {
|
|
return err
|
|
}
|
|
|
|
return q.Article.Create(&m.Article{
|
|
GroupID: data.GroupID,
|
|
Title: data.Title,
|
|
Content: data.Content,
|
|
Sort: u.Else(data.Sort, 0),
|
|
Status: u.Else(data.Status, m.ArticleStatusEnabled),
|
|
})
|
|
}
|
|
|
|
type CreateArticleData struct {
|
|
GroupID int32 `json:"group_id" validate:"required"`
|
|
Title string `json:"title" validate:"required"`
|
|
Content *string `json:"content"`
|
|
Sort *int32 `json:"sort"`
|
|
Status *m.ArticleStatus `json:"status"`
|
|
}
|
|
|
|
func (s *articleService) Update(data UpdateArticleData) error {
|
|
if data.GroupID != nil {
|
|
if err := s.ensureGroupExists(*data.GroupID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
do := make([]field.AssignExpr, 0)
|
|
if data.GroupID != nil {
|
|
do = append(do, q.Article.GroupID.Value(*data.GroupID))
|
|
}
|
|
if data.Title != nil {
|
|
do = append(do, q.Article.Title.Value(*data.Title))
|
|
}
|
|
if data.Content != nil {
|
|
do = append(do, q.Article.Content.Value(*data.Content))
|
|
}
|
|
if data.Sort != nil {
|
|
do = append(do, q.Article.Sort.Value(*data.Sort))
|
|
}
|
|
if data.Status != nil {
|
|
do = append(do, q.Article.Status.Value(int(*data.Status)))
|
|
}
|
|
if len(do) == 0 {
|
|
return nil
|
|
}
|
|
|
|
r, err := q.Article.Where(q.Article.ID.Eq(data.ID)).UpdateSimple(do...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if r.RowsAffected == 0 {
|
|
return core.NewBizErr("文档状态已过期")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type UpdateArticleData struct {
|
|
ID int32 `json:"id" validate:"required"`
|
|
GroupID *int32 `json:"group_id"`
|
|
Title *string `json:"title"`
|
|
Content *string `json:"content"`
|
|
Sort *int32 `json:"sort"`
|
|
Status *m.ArticleStatus `json:"status"`
|
|
}
|
|
|
|
func (s *articleService) Delete(id int32) error {
|
|
r, err := q.Article.Where(q.Article.ID.Eq(id)).UpdateColumn(q.Article.DeletedAt, time.Now())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if r.RowsAffected == 0 {
|
|
return core.NewBizErr("文档状态已过期")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *articleService) Nav() ([]*ArticleNavGroup, error) {
|
|
groups, err := q.ArticleGroup.
|
|
Where(q.ArticleGroup.Status.Eq(int(m.ArticleGroupStatusEnabled))).
|
|
Order(q.ArticleGroup.Sort, q.ArticleGroup.CreatedAt).
|
|
Find()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(groups) == 0 {
|
|
return []*ArticleNavGroup{}, nil
|
|
}
|
|
|
|
groupIDs := make([]int32, 0, len(groups))
|
|
result := make([]*ArticleNavGroup, 0, len(groups))
|
|
groupMap := make(map[int32]*ArticleNavGroup, len(groups))
|
|
for _, group := range groups {
|
|
groupIDs = append(groupIDs, group.ID)
|
|
item := &ArticleNavGroup{
|
|
ID: group.ID,
|
|
Name: group.Name,
|
|
Code: group.Code,
|
|
Articles: []*ArticleNavArticle{},
|
|
}
|
|
result = append(result, item)
|
|
groupMap[group.ID] = item
|
|
}
|
|
|
|
articles, err := q.Article.
|
|
Where(
|
|
q.Article.GroupID.In(groupIDs...),
|
|
q.Article.Status.Eq(int(m.ArticleStatusEnabled)),
|
|
).
|
|
Omit(q.Article.Content).
|
|
Order(q.Article.Sort, q.Article.CreatedAt).
|
|
Find()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, article := range articles {
|
|
group := groupMap[article.GroupID]
|
|
if group == nil {
|
|
continue
|
|
}
|
|
group.Articles = append(group.Articles, &ArticleNavArticle{
|
|
ID: article.ID,
|
|
Title: article.Title,
|
|
UpdatedAt: article.UpdatedAt,
|
|
})
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
type ArticleNavGroup struct {
|
|
ID int32 `json:"id"`
|
|
Name string `json:"name"`
|
|
Code string `json:"code"`
|
|
Articles []*ArticleNavArticle `json:"articles"`
|
|
}
|
|
|
|
type ArticleNavArticle struct {
|
|
ID int32 `json:"id"`
|
|
Title string `json:"title"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
func (s *articleService) GetPublic(id int32) (*ArticlePublicDetail, error) {
|
|
article, err := q.Article.
|
|
Preload(q.Article.Group).
|
|
Where(
|
|
q.Article.ID.Eq(id),
|
|
q.Article.Status.Eq(int(m.ArticleStatusEnabled)),
|
|
).
|
|
Take()
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, core.NewBizErr("文档不存在")
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if article.Group == nil || article.Group.Status != m.ArticleGroupStatusEnabled {
|
|
return nil, core.NewBizErr("文档不存在")
|
|
}
|
|
|
|
return &ArticlePublicDetail{
|
|
ID: article.ID,
|
|
Title: article.Title,
|
|
Content: article.Content,
|
|
UpdatedAt: article.UpdatedAt,
|
|
Group: &ArticlePublicGroup{
|
|
ID: article.Group.ID,
|
|
Name: article.Group.Name,
|
|
Code: article.Group.Code,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
type ArticlePublicDetail struct {
|
|
ID int32 `json:"id"`
|
|
Title string `json:"title"`
|
|
Content *string `json:"content,omitempty"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
Group *ArticlePublicGroup `json:"group"`
|
|
}
|
|
|
|
type ArticlePublicGroup struct {
|
|
ID int32 `json:"id"`
|
|
Name string `json:"name"`
|
|
Code string `json:"code"`
|
|
}
|
|
|
|
func (s *articleService) ensureGroupExists(groupID int32) error {
|
|
_, err := q.ArticleGroup.Where(q.ArticleGroup.ID.Eq(groupID)).Take()
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return core.NewBizErr("文档分组不存在")
|
|
}
|
|
return err
|
|
}
|