作者 庄敏学

文章恢复

... ... @@ -1225,6 +1225,60 @@
]
}
},
"v1/system/article/history/{id}": {
"get": {
"summary": "管理后台帖子历史详情",
"operationId": "SystemArticleGetHistory",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/SystemArticleGetHistoryResponse"
}
}
},
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "string"
}
],
"requestBody": {},
"tags": [
"article"
]
}
},
"v1/system/article/restore": {
"post": {
"summary": "管理后台文章恢复",
"operationId": "SystemArticleRestore",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/SystemArticleRestoreResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/SystemArticleRestoreRequest"
}
}
],
"requestBody": {},
"tags": [
"article"
]
}
},
"v1/system/article/search": {
"post": {
"summary": "管理后台获取文章列表",
... ... @@ -4891,6 +4945,125 @@
"total"
]
},
"SystemArticleGetHistoryRequest": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "id"
},
"": {
"type": "integer",
"format": "int64"
}
},
"title": "SystemArticleGetHistoryRequest",
"required": [
"id"
]
},
"SystemArticleGetHistoryResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": " id"
},
"articleId": {
"type": "integer",
"format": "int64",
"description": " 文章ID"
},
"title": {
"type": "string",
"description": " 标题"
},
"createdAt": {
"type": "integer",
"format": "int64",
"description": " 文章的发布时间"
},
"section": {
"type": "array",
"items": {
"$ref": "#/definitions/ArticleSection"
},
"description": " 文章的文本内容"
},
"images": {
"type": "array",
"items": {
"type": "string"
},
"description": " 图片"
},
"whoRead": {
"type": "array",
"items": {
"type": "integer",
"format": "int64"
},
"description": " 谁可查看"
},
"whoReadInfo": {
"type": "array",
"items": {
"$ref": "#/definitions/UserShowName"
},
"description": " 谁可查看"
},
"whoReview": {
"type": "array",
"items": {
"type": "integer",
"format": "int64"
},
"description": " 谁可评论"
},
"whoReviewInfo": {
"type": "array",
"items": {
"$ref": "#/definitions/UserShowName"
},
"description": " 谁可评论"
},
"location": {
"$ref": "#/definitions/Location",
"description": " 定位坐标"
},
"targetUser": {
"type": "integer",
"format": "int32",
"description": " 分发方式 [0分发给所有人、1分发给指定的人]"
},
"tags": {
"type": "array",
"items": {
"type": "integer",
"format": "int64"
},
"description": " 标签"
}
},
"title": "SystemArticleGetHistoryResponse",
"required": [
"id",
"articleId",
"title",
"createdAt",
"section",
"images",
"whoRead",
"whoReadInfo",
"whoReview",
"whoReviewInfo",
"location",
"targetUser",
"tags"
]
},
"SystemArticleGetRequest": {
"type": "object",
"properties": {
... ... @@ -5002,6 +5175,13 @@
"type": "integer",
"format": "int32",
"description": " 评论的展示状态(0显示、1不显示)"
},
"tags": {
"type": "array",
"items": {
"$ref": "#/definitions/ArticleTagItem"
},
"description": "标签"
}
},
"title": "SystemArticleGetResponse",
... ... @@ -5021,7 +5201,8 @@
"countLove",
"countComment",
"countRead",
"show"
"show",
"tags"
]
},
"SystemArticleHistory": {
... ... @@ -5114,6 +5295,45 @@
"list"
]
},
"SystemArticleRestoreRequest": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "ID"
},
"AccessToken": {
"type": "string",
"description": " 授权token"
}
},
"title": "SystemArticleRestoreRequest",
"required": [
"id",
"x-mmm-accesstoken"
]
},
"SystemArticleRestoreResponse": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "ID"
},
"articleId": {
"type": "integer",
"format": "int64",
"description": "文章ID"
}
},
"title": "SystemArticleRestoreResponse",
"required": [
"id",
"articleId"
]
},
"SystemArticleSearch": {
"type": "object",
"properties": {
... ... @@ -5263,6 +5483,14 @@
"format": "int64",
"description": "结束时间"
},
"tags": {
"type": "array",
"items": {
"type": "integer",
"format": "int64"
},
"description": "标签"
},
"page": {
"type": "integer",
"format": "int32",
... ... @@ -5358,6 +5586,14 @@
"type": "integer",
"format": "int32",
"description": "分发方式 [0分发给所有人、1分发给指定的人]"
},
"tags": {
"type": "array",
"items": {
"type": "integer",
"format": "int64"
},
"description": " 标签"
}
},
"title": "SystemArticleUpdateRequest",
... ... @@ -5370,7 +5606,8 @@
"whoRead",
"whoReview",
"location",
"targetUser"
"targetUser",
"tags"
]
},
"SystemArticleUpdateResponse": {
... ... @@ -5419,7 +5656,8 @@
"tags": {
"type": "array",
"items": {
"type": "string"
"type": "integer",
"format": "int64"
},
"description": "标签"
},
... ...
... ... @@ -105,4 +105,7 @@ service Core {
@handler SystemArticleSearchMe
post /article/search/me (SystemArticleSearchMeRequest) returns (SystemArticleSearchMeResponse)
@doc "管理后台文章恢复"
@handler SystemArticleRestore
post /article/restore (SystemArticleRestoreRequest) returns (SystemArticleRestoreResponse)
}
\ No newline at end of file
... ...
... ... @@ -398,8 +398,9 @@ type (
WhoRead []int64 `json:"whoRead"` // 谁可以看
WhoReview []int64 `json:"whoReview"` // 评论人
Location Location `json:"location"` // 坐标
TargetUser int `json:"targetUser"` //分发方式 [0分发给所有人、1分发给指定的人]
TargetUser int `json:"targetUser"` // 分发方式 [0分发给所有人、1分发给指定的人]
Tags []int64 `json:"tags"` // 标签
AccessToken string `header:"x-mmm-accesstoken"` // 授权token
}
SystemArticleUpdateResponse {
Id int64 `json:"id"` //id
... ... @@ -408,7 +409,7 @@ type (
Images []string `json:"images"` //图片
CreatedAt int64 `json:"createdAt"` //文章的创建日期
CountLove int `json:"countLove"` //点赞数量
CountComment int `json:"CountComment"` //评论数量
CountComment int `json:"countComment"` //评论数量
Show int `json:"show"` //是否隐藏 [0显示、1不显示]
Tags []int64 `json:"tags"` //标签
TargetUser int `json:"targetUser"` //分发方式 [0分发给所有人、1分发给指定的人]
... ... @@ -440,8 +441,6 @@ type (
Id int64 `json:"id"` // id
ArticleId int64 `json:"articleId"` // 文章ID
Title string `json:"title"` // 标题
AuthorId int64 `json:"authorId"` // 发布人id
Author ArticleAuthor `json:"author"` // 发布人
CreatedAt int64 `json:"createdAt"` // 文章的发布时间
Section []ArticleSection `json:"section"` // 文章的文本内容
Images []string `json:"images"` // 图片
... ... @@ -450,10 +449,15 @@ type (
WhoReview []int64 `json:"whoReview"` // 谁可评论
WhoReviewInfo []UserShowName `json:"whoReviewInfo"` // 谁可评论
Location Location `json:"location"` // 定位坐标
CountLove int `json:"countLove"` // 点赞数量
CountComment int `json:"countComment"` // 评论数量
CountRead int `json:"countRead"` // 浏览数量
Show int `json:"show"` // 评论的展示状态(0显示、1不显示)
TargetUser int `json:"targetUser"` //分发方式 [0分发给所有人、1分发给指定的人]
TargetUser int `json:"targetUser"` // 分发方式 [0分发给所有人、1分发给指定的人]
Tags []int64 `json:"tags"` // 标签
}
SystemArticleRestoreRequest {
Id int64 `json:"id"` //ID
AccessToken string `header:"x-mmm-accesstoken"` // 授权token
}
SystemArticleRestoreResponse {
Id int64 `json:"id"` //ID
ArticleId int64 `json:"articleId"` //文章ID
}
)
\ No newline at end of file
... ...
package article
import (
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
)
func SystemArticleRestoreHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.SystemArticleRestoreRequest
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := article.NewSystemArticleRestoreLogic(r.Context(), svcCtx)
resp, err := l.SystemArticleRestore(&req)
result.HttpResult(r, w, resp, err)
}
}
... ...
... ... @@ -18,7 +18,7 @@ func SystemUpdateArticleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return
}
l := article.NewSystemUpdateArticleLogic(r.Context(), svcCtx)
resp, err := l.SystemUpdateArticle(&req, r.Header.Get("x-mmm-accesstoken"))
resp, err := l.SystemUpdateArticle(&req)
result.HttpResult(r, w, resp, err)
}
}
... ...
... ... @@ -401,6 +401,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/article/search/me",
Handler: article.SystemArticleSearchMeHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/article/restore",
Handler: article.SystemArticleRestoreHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.SystemAuth.AccessSecret),
rest.WithPrefix("/v1/system"),
... ...
... ... @@ -2,6 +2,9 @@ package article
import (
"context"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
... ... @@ -24,7 +27,67 @@ func NewSystemArticleGetHistoryLogic(ctx context.Context, svcCtx *svc.ServiceCon
}
func (l *SystemArticleGetHistoryLogic) SystemArticleGetHistory(req *types.SystemArticleGetHistoryRequest) (resp *types.SystemArticleGetHistoryResponse, err error) {
//var conn = l.svcCtx.DefaultDBConn()
var conn = l.svcCtx.DefaultDBConn()
backup, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.Id)
if err != nil {
return nil, xerr.NewErrMsgErr("获取编辑历史记录失败", err)
}
resp = &types.SystemArticleGetHistoryResponse{
Id: backup.Id,
ArticleId: backup.ArticleId,
Title: backup.Title,
CreatedAt: backup.CreatedAt,
Section: make([]types.ArticleSection, 0),
Images: make([]string, 0),
WhoRead: backup.WhoRead,
WhoReadInfo: make([]types.UserShowName, 0),
WhoReview: backup.WhoReview,
WhoReviewInfo: make([]types.UserShowName, 0),
Location: types.Location{
Longitude: backup.Location.Longitude,
Latitude: backup.Location.Latitude,
Descript: backup.Location.Descript,
},
TargetUser: int(backup.TargetUser),
Tags: backup.Tags,
}
//文章段落内容
lo.ForEach(backup.Section, func(item domain.ArticleSection, index int) {
resp.Section = append(resp.Section, types.ArticleSection{
Id: item.Id,
Content: item.Content,
SortBy: item.SortBy,
TotalComment: item.TotalComment,
})
})
//图片
lo.ForEach(backup.Images, func(item domain.Image, index int) {
resp.Images = append(resp.Images, item.Url)
})
//用户
userIds := lo.Union(resp.WhoRead, resp.WhoReview)
if len(userIds) > 0 {
_, users, err := l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("ids", userIds))
if err != nil {
return nil, xerr.NewErrMsgErr("获取帖子异常", err)
}
userSlices := make(map[int64]types.UserShowName)
lo.ForEach(users, func(user *domain.User, index int) {
userSlices[user.Id] = types.UserShowName{
Id: int(user.Id),
Name: user.Name,
}
})
lo.ForEach(resp.WhoRead, func(userId int64, index int) {
if value, ok := userSlices[userId]; ok {
resp.WhoReadInfo = append(resp.WhoReadInfo, value)
}
})
lo.ForEach(resp.WhoReview, func(userId int64, index int) {
if value, ok := userSlices[userId]; ok {
resp.WhoReviewInfo = append(resp.WhoReviewInfo, value)
}
})
}
return
}
... ...
package article
import (
"context"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type SystemArticleRestoreLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewSystemArticleRestoreLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SystemArticleRestoreLogic {
return &SystemArticleRestoreLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SystemArticleRestoreLogic) SystemArticleRestore(req *types.SystemArticleRestoreRequest) (resp *types.SystemArticleRestoreResponse, err error) {
var conn = l.svcCtx.DefaultDBConn()
backup, err := l.svcCtx.ArticleBackupRepository.FindOne(l.ctx, conn, req.Id)
if err != nil {
return nil, xerr.NewErrMsgErr("获取编辑历史记录失败", err)
}
article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, backup.ArticleId)
if err != nil {
return nil, xerr.NewErrMsgErr("获取文章失败", err)
}
article.Version = article.Version + 1
article.Images = backup.Images
article.Title = backup.Title
articleSections := make([]domain.ArticleSection, 0)
lo.ForEach(backup.Section, func(item domain.ArticleSection, index int) {
articleSections = append(articleSections, domain.ArticleSection{
Id: item.Id,
CompanyId: item.CompanyId,
Version: article.Version,
ArticleId: article.Id,
Content: item.Content,
SortBy: item.SortBy,
})
})
//获取当前用户信息
userToken := contextdata.GetUserTokenFromCtx(l.ctx)
userMe, err := l.svcCtx.ApiAuthService.MeInfo(l.ctx, authlib.RequestUserMeQuery{Token: req.AccessToken})
if err != nil {
return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
}
err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
//保存文章
_, err = l.svcCtx.ArticleRepository.Update(ctx, c, article)
if err != nil {
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
//保存段落
updateSectionIds := []int64{}
for _, item := range articleSections {
section, err := l.svcCtx.ArticleSectionRepository.FindOne(ctx, c, item.Id)
if err == nil && section.Id > 0 {
section.Content = item.Content
section.SortBy = item.SortBy
section.Version = item.Version
_, err = l.svcCtx.ArticleSectionRepository.Update(ctx, c, section)
if err != nil {
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
} else {
_, err = l.svcCtx.ArticleSectionRepository.Insert(ctx, c, &item)
if err != nil {
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
}
updateSectionIds = append(updateSectionIds, item.Id)
}
if len(updateSectionIds) > 0 {
err = l.svcCtx.ArticleSectionRepository.DeleteBy(ctx, c, domain.NewQueryOptions().WithKV("articleId", article.Id).WithKV("notIds", updateSectionIds))
if err != nil {
return xerr.NewErrMsgErr("保存文章内容失败", err)
}
}
//备份数据
newBackUp := article.MakeBackup(domain.UserSimple{
Id: userToken.UserId,
Name: userMe.User.NickName,
Avatar: userMe.User.Avatar,
CompanyId: userToken.CompanyId,
Company: userMe.CurrentCompany.Name,
}, articleSections)
newBackUp.Action = "恢复"
_, err = l.svcCtx.ArticleBackupRepository.Insert(ctx, c, newBackUp)
if err != nil {
return xerr.NewErrMsgErr("恢复文章版本失败", err)
}
return nil
}, true)
resp = &types.SystemArticleRestoreResponse{
Id: req.Id,
ArticleId: article.Id,
}
return
}
... ...
... ... @@ -29,7 +29,7 @@ func NewSystemUpdateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext
}
}
func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleUpdateRequest, accessToken string) (resp *types.SystemArticleUpdateResponse, err error) {
func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleUpdateRequest) (resp *types.SystemArticleUpdateResponse, err error) {
var conn = l.svcCtx.DefaultDBConn()
userToken := contextdata.GetUserTokenFromCtx(l.ctx)
article, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.Id)
... ... @@ -84,7 +84,7 @@ func (l *SystemUpdateArticleLogic) SystemUpdateArticle(req *types.SystemArticleU
article.Summary = req.Section[0].Content[0:stringIndex]
}
//获取当前用户信息
userMe, err := l.svcCtx.ApiAuthService.MeInfo(l.ctx, authlib.RequestUserMeQuery{Token: accessToken})
userMe, err := l.svcCtx.ApiAuthService.MeInfo(l.ctx, authlib.RequestUserMeQuery{Token: req.AccessToken})
if err != nil {
return nil, xerr.NewErrMsgErr("获取当前用户信息失败", err)
}
... ...
... ... @@ -932,8 +932,9 @@ type SystemArticleUpdateRequest struct {
WhoRead []int64 `json:"whoRead"` // 谁可以看
WhoReview []int64 `json:"whoReview"` // 评论人
Location Location `json:"location"` // 坐标
TargetUser int `json:"targetUser"` //分发方式 [0分发给所有人、1分发给指定的人]
TargetUser int `json:"targetUser"` // 分发方式 [0分发给所有人、1分发给指定的人]
Tags []int64 `json:"tags"` // 标签
AccessToken string `header:"x-mmm-accesstoken"` // 授权token
}
type SystemArticleUpdateResponse struct {
... ... @@ -943,7 +944,7 @@ type SystemArticleUpdateResponse struct {
Images []string `json:"images"` //图片
CreatedAt int64 `json:"createdAt"` //文章的创建日期
CountLove int `json:"countLove"` //点赞数量
CountComment int `json:"CountComment"` //评论数量
CountComment int `json:"countComment"` //评论数量
Show int `json:"show"` //是否隐藏 [0显示、1不显示]
Tags []int64 `json:"tags"` //标签
TargetUser int `json:"targetUser"` //分发方式 [0分发给所有人、1分发给指定的人]
... ... @@ -979,8 +980,6 @@ type SystemArticleGetHistoryResponse struct {
Id int64 `json:"id"` // id
ArticleId int64 `json:"articleId"` // 文章ID
Title string `json:"title"` // 标题
AuthorId int64 `json:"authorId"` // 发布人id
Author ArticleAuthor `json:"author"` // 发布人
CreatedAt int64 `json:"createdAt"` // 文章的发布时间
Section []ArticleSection `json:"section"` // 文章的文本内容
Images []string `json:"images"` // 图片
... ... @@ -989,11 +988,18 @@ type SystemArticleGetHistoryResponse struct {
WhoReview []int64 `json:"whoReview"` // 谁可评论
WhoReviewInfo []UserShowName `json:"whoReviewInfo"` // 谁可评论
Location Location `json:"location"` // 定位坐标
CountLove int `json:"countLove"` // 点赞数量
CountComment int `json:"countComment"` // 评论数量
CountRead int `json:"countRead"` // 浏览数量
Show int `json:"show"` // 评论的展示状态(0显示、1不显示)
TargetUser int `json:"targetUser"` //分发方式 [0分发给所有人、1分发给指定的人]
TargetUser int `json:"targetUser"` // 分发方式 [0分发给所有人、1分发给指定的人]
Tags []int64 `json:"tags"` // 标签
}
type SystemArticleRestoreRequest struct {
Id int64 `json:"id"` //ID
AccessToken string `header:"x-mmm-accesstoken"` // 授权token
}
type SystemArticleRestoreResponse struct {
Id int64 `json:"id"` //ID
ArticleId int64 `json:"articleId"` //文章ID
}
type RoleGetRequest struct {
... ...