正在显示
23 个修改的文件
包含
1160 行增加
和
0 行删除
| @@ -11,3 +11,4 @@ import "core/article.api" | @@ -11,3 +11,4 @@ import "core/article.api" | ||
| 11 | import "core/role.api" | 11 | import "core/role.api" |
| 12 | import "core/department.api" | 12 | import "core/department.api" |
| 13 | import "core/article_category.api" | 13 | import "core/article_category.api" |
| 14 | +import "core/article_security.api" |
| 1 | +@server( | ||
| 2 | + prefix: v1/system | ||
| 3 | + group: secuirty | ||
| 4 | + middleware: LoginStatusCheck,LogRequest | ||
| 5 | + jwt: SystemAuth | ||
| 6 | +) | ||
| 7 | +service Core { | ||
| 8 | + @doc "内容安全-搜索" | ||
| 9 | + @handler articleSecuritySearch | ||
| 10 | + post /article_security/search (ArticleSecuritySearchRequest) returns (ArticleSecuritySearchResponse) | ||
| 11 | + @doc "详情" | ||
| 12 | + @handler articleSecurityGet | ||
| 13 | + get /article_security/:id (ArticleSecurityGetRequest) returns (ArticleSecurityGetResponse) | ||
| 14 | + @doc "内容安全-审核" | ||
| 15 | + @handler articleSecurityAudit | ||
| 16 | + post /article_security/audit (ArticleSecurityAuditRequest) returns (ArticleSecurityAuditResponse) | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +type ( | ||
| 20 | + ArticleSecurityGetRequest { | ||
| 21 | + Id int64 `path:"id"` | ||
| 22 | + } | ||
| 23 | + ArticleSecurityGetResponse struct{ | ||
| 24 | + ArticleSecurity ArticleSecurityItem `json:"item"` | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +// ArticleSecuritySaveRequest struct{ | ||
| 28 | +// ArticleSecurity ArticleSecurityItem `json:"article_security"` | ||
| 29 | +// } | ||
| 30 | +// ArticleSecuritySaveResponse struct{} | ||
| 31 | +// | ||
| 32 | +// ArticleSecurityDeleteRequest struct{ | ||
| 33 | +// Id int64 `path:"id"` | ||
| 34 | +// } | ||
| 35 | +// ArticleSecurityDeleteResponse struct{} | ||
| 36 | +// | ||
| 37 | +// ArticleSecurityUpdateRequest struct{ | ||
| 38 | +// Id int64 `path:"id"` | ||
| 39 | +// ArticleSecurity ArticleSecurityItem `json:"article_security"` | ||
| 40 | +// } | ||
| 41 | +// ArticleSecurityUpdateResponse struct{} | ||
| 42 | + ArticleSecurityAuditRequest struct{ | ||
| 43 | + Id int64 `json:"id"` //id | ||
| 44 | + Status int `json:"status"` // 1:成功 0:失败 | ||
| 45 | + } | ||
| 46 | + ArticleSecurityAuditResponse struct{ | ||
| 47 | + | ||
| 48 | + } | ||
| 49 | + ArticleSecuritySearchRequest struct{ | ||
| 50 | + Page int `json:"page,optional"` | ||
| 51 | + Size int `json:"size,optional"` | ||
| 52 | + ReviewStatus int `json:"reviewStatus,optional"` // 审核结果 1:待审核 2:通过 3:拒绝 | ||
| 53 | + Suggest string `json:"suggest"` // 建议 通过、风险、人工审核 | ||
| 54 | + ContentType int `json:"contentType"` // 内容类型 (1:文章 2:评论) | ||
| 55 | + AuthorName string `json:"authorName"` // 作者名称 | ||
| 56 | + BeginTime int64 `json:"beginTime"` // 开始时间 | ||
| 57 | + EndTime int64 `json:"endTime"` // 结束时间 | ||
| 58 | + } | ||
| 59 | + ArticleSecuritySearchResponse{ | ||
| 60 | + List []ArticleSecurityItem `json:"list"` | ||
| 61 | + Total int64 `json:"total"` | ||
| 62 | + } | ||
| 63 | + ArticleSecurityItem struct{ | ||
| 64 | + Id int64 `json:"id"` // 唯一标识 | ||
| 65 | + ContentKeyWords string `json:"contentKeyWords"` // 内容关键字 | ||
| 66 | + Content ContentDetailItem `json:"content"` // 内容详情 | ||
| 67 | + Label string `json:"label"` // 风控标签 | ||
| 68 | + Prob int `json:"prob"` // 分值 | ||
| 69 | + Suggest string `json:"suggest"` // 建议 通过、风险、人工审核 | ||
| 70 | + Author string `json:"author"` // 发布人 | ||
| 71 | + ReleaseAt string `json:"releaseAt"` // 发布时间 | ||
| 72 | + ReviewStatus int `json:"reviewStatus"` // 审核结果 1:待审核 2:通过 3:拒绝 | ||
| 73 | + | ||
| 74 | + Reviewer string `json:"reviewer"` // 审核人 | ||
| 75 | + ReviewAt int64 `json:"reviewAt"` // 审核时间(人工处置时间) | ||
| 76 | + CheckList []CheckDetailItem `json:"checkList"` // 检查列表 | ||
| 77 | + } | ||
| 78 | + CheckDetailItem struct{ | ||
| 79 | + Label string `json:"label"` // 命中标签 | ||
| 80 | + Prob uint `json:"prob"` // 置信度。0-100,越高代表越有可能属于当前返回的标签(label) | ||
| 81 | + Suggest string `json:"suggest"` // 建议 | ||
| 82 | + } | ||
| 83 | + ContentDetailItem struct{ | ||
| 84 | + Id int64 `json:"id"` // 内容ID | ||
| 85 | + Type int `json:"type"` // 内容类型 (1:文章 2:评论) | ||
| 86 | + Text string `json:"text"` // 内容文本 | ||
| 87 | + } | ||
| 88 | +) |
| @@ -7,6 +7,7 @@ Timeout: 30000 | @@ -7,6 +7,7 @@ Timeout: 30000 | ||
| 7 | # CertFile: ./key/fjmaimaimai.com_bundle.crt | 7 | # CertFile: ./key/fjmaimaimai.com_bundle.crt |
| 8 | # KeyFile: ./key/fjmaimaimai.com.key | 8 | # KeyFile: ./key/fjmaimaimai.com.key |
| 9 | LogRequest: true # 记录详细请求日志 | 9 | LogRequest: true # 记录详细请求日志 |
| 10 | +ContentSecurityCheck: true # 内容安全检查(调用微信接口) | ||
| 10 | 11 | ||
| 11 | Log: | 12 | Log: |
| 12 | # Mode: file | 13 | # Mode: file |
| @@ -17,6 +17,7 @@ type Config struct { | @@ -17,6 +17,7 @@ type Config struct { | ||
| 17 | ApiAuth ApiService | 17 | ApiAuth ApiService |
| 18 | DebugSmsCode string `json:",optional,default=999512"` | 18 | DebugSmsCode string `json:",optional,default=999512"` |
| 19 | LogRequest bool `json:",optional,default=true"` | 19 | LogRequest bool `json:",optional,default=true"` |
| 20 | + ContentSecurityCheck bool `json:",optional,default=false"` | ||
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | type ApiService struct { | 23 | type ApiService struct { |
| @@ -11,6 +11,7 @@ import ( | @@ -11,6 +11,7 @@ import ( | ||
| 11 | department "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/department" | 11 | department "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/department" |
| 12 | message "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/message" | 12 | message "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/message" |
| 13 | role "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/role" | 13 | role "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/role" |
| 14 | + secuirty "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/secuirty" | ||
| 14 | tags "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/tags" | 15 | tags "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/tags" |
| 15 | user "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/user" | 16 | user "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/handler/user" |
| 16 | "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | 17 | "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" |
| @@ -789,4 +790,29 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { | @@ -789,4 +790,29 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { | ||
| 789 | }, | 790 | }, |
| 790 | rest.WithPrefix("/v1/system"), | 791 | rest.WithPrefix("/v1/system"), |
| 791 | ) | 792 | ) |
| 793 | + | ||
| 794 | + server.AddRoutes( | ||
| 795 | + rest.WithMiddlewares( | ||
| 796 | + []rest.Middleware{serverCtx.LoginStatusCheck, serverCtx.LogRequest}, | ||
| 797 | + []rest.Route{ | ||
| 798 | + { | ||
| 799 | + Method: http.MethodPost, | ||
| 800 | + Path: "/article_security/search", | ||
| 801 | + Handler: secuirty.ArticleSecuritySearchHandler(serverCtx), | ||
| 802 | + }, | ||
| 803 | + { | ||
| 804 | + Method: http.MethodGet, | ||
| 805 | + Path: "/article_security/:id", | ||
| 806 | + Handler: secuirty.ArticleSecurityGetHandler(serverCtx), | ||
| 807 | + }, | ||
| 808 | + { | ||
| 809 | + Method: http.MethodPost, | ||
| 810 | + Path: "/article_security/audit", | ||
| 811 | + Handler: secuirty.ArticleSecurityAuditHandler(serverCtx), | ||
| 812 | + }, | ||
| 813 | + }..., | ||
| 814 | + ), | ||
| 815 | + rest.WithJwt(serverCtx.Config.SystemAuth.AccessSecret), | ||
| 816 | + rest.WithPrefix("/v1/system"), | ||
| 817 | + ) | ||
| 792 | } | 818 | } |
| 1 | +package secuirty | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result" | ||
| 5 | + "net/http" | ||
| 6 | + | ||
| 7 | + "github.com/zeromicro/go-zero/rest/httpx" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/secuirty" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | +func ArticleSecurityAuditHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||
| 14 | + return func(w http.ResponseWriter, r *http.Request) { | ||
| 15 | + var req types.ArticleSecurityAuditRequest | ||
| 16 | + if err := httpx.Parse(r, &req); err != nil { | ||
| 17 | + httpx.ErrorCtx(r.Context(), w, err) | ||
| 18 | + return | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + l := secuirty.NewArticleSecurityAuditLogic(r.Context(), svcCtx) | ||
| 22 | + resp, err := l.ArticleSecurityAudit(&req) | ||
| 23 | + result.HttpResult(r, w, resp, err) | ||
| 24 | + } | ||
| 25 | +} |
| 1 | +package secuirty | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result" | ||
| 5 | + "net/http" | ||
| 6 | + | ||
| 7 | + "github.com/zeromicro/go-zero/rest/httpx" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/secuirty" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | +func ArticleSecurityGetHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||
| 14 | + return func(w http.ResponseWriter, r *http.Request) { | ||
| 15 | + var req types.ArticleSecurityGetRequest | ||
| 16 | + if err := httpx.Parse(r, &req); err != nil { | ||
| 17 | + httpx.ErrorCtx(r.Context(), w, err) | ||
| 18 | + return | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + l := secuirty.NewArticleSecurityGetLogic(r.Context(), svcCtx) | ||
| 22 | + resp, err := l.ArticleSecurityGet(&req) | ||
| 23 | + result.HttpResult(r, w, resp, err) | ||
| 24 | + } | ||
| 25 | +} |
| 1 | +package secuirty | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result" | ||
| 5 | + "net/http" | ||
| 6 | + | ||
| 7 | + "github.com/zeromicro/go-zero/rest/httpx" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/secuirty" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | +func ArticleSecuritySearchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { | ||
| 14 | + return func(w http.ResponseWriter, r *http.Request) { | ||
| 15 | + var req types.ArticleSecuritySearchRequest | ||
| 16 | + if err := httpx.Parse(r, &req); err != nil { | ||
| 17 | + httpx.ErrorCtx(r.Context(), w, err) | ||
| 18 | + return | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + l := secuirty.NewArticleSecuritySearchLogic(r.Context(), svcCtx) | ||
| 22 | + resp, err := l.ArticleSecuritySearch(&req) | ||
| 23 | + result.HttpResult(r, w, resp, err) | ||
| 24 | + } | ||
| 25 | +} |
| @@ -2,6 +2,7 @@ package article | @@ -2,6 +2,7 @@ package article | ||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "context" | 4 | "context" |
| 5 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/core" | ||
| 5 | "strconv" | 6 | "strconv" |
| 6 | "strings" | 7 | "strings" |
| 7 | "text/template" | 8 | "text/template" |
| @@ -198,6 +199,11 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR | @@ -198,6 +199,11 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR | ||
| 198 | if err != nil { | 199 | if err != nil { |
| 199 | return xerr.NewErrMsgErr("创建文章失败", err) | 200 | return xerr.NewErrMsgErr("创建文章失败", err) |
| 200 | } | 201 | } |
| 202 | + | ||
| 203 | + // 内容安全检查 | ||
| 204 | + if err = core.ContentSecurityCheck(l.ctx, l.svcCtx, conn, "", core.NewContentFromArticle(newArticle, sectionList)); err != nil { | ||
| 205 | + return err | ||
| 206 | + } | ||
| 201 | return nil | 207 | return nil |
| 202 | }, true) | 208 | }, true) |
| 203 | if err != nil { | 209 | if err != nil { |
| @@ -2,6 +2,7 @@ package comment | @@ -2,6 +2,7 @@ package comment | ||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "context" | 4 | "context" |
| 5 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/core" | ||
| 5 | 6 | ||
| 6 | "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message" | 7 | "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message" |
| 7 | 8 | ||
| @@ -207,6 +208,10 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini | @@ -207,6 +208,10 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini | ||
| 207 | return err | 208 | return err |
| 208 | } | 209 | } |
| 209 | 210 | ||
| 211 | + // 内容安全检查 | ||
| 212 | + if err = core.ContentSecurityCheck(l.ctx, l.svcCtx, conn, "", core.NewContentFromComment(&newComment)); err != nil { | ||
| 213 | + return err | ||
| 214 | + } | ||
| 210 | return nil | 215 | return nil |
| 211 | }, true) | 216 | }, true) |
| 212 | 217 |
| 1 | +package core | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "bytes" | ||
| 5 | + "context" | ||
| 6 | + "fmt" | ||
| 7 | + "github.com/silenceper/wechat/v2/miniprogram/security" | ||
| 8 | + "github.com/zeromicro/go-zero/core/logx" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" | ||
| 11 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" | ||
| 12 | + "time" | ||
| 13 | +) | ||
| 14 | + | ||
| 15 | +func ContentSecurityCheck(ctx context.Context, svcCtx *svc.ServiceContext, conn transaction.Conn, openId string, content ContentBody) error { | ||
| 16 | + if !svcCtx.Config.ContentSecurityCheck { | ||
| 17 | + return nil | ||
| 18 | + } | ||
| 19 | + var ( | ||
| 20 | + scene security.MsgScene | ||
| 21 | + ) | ||
| 22 | + if content.Type == 1 { | ||
| 23 | + scene = security.MsgSceneSocialLog | ||
| 24 | + } else { | ||
| 25 | + scene = security.MsgSceneComment | ||
| 26 | + } | ||
| 27 | + var ( | ||
| 28 | + resp domain.MsgCheckDetail | ||
| 29 | + ) | ||
| 30 | + respTmp, err := svcCtx.MiniProgram.GetSecurity().MsgCheck(&security.MsgCheckRequest{ | ||
| 31 | + OpenID: openId, | ||
| 32 | + Scene: scene, | ||
| 33 | + Content: content.Content, | ||
| 34 | + }) | ||
| 35 | + if err != nil { | ||
| 36 | + logx.Error(err) | ||
| 37 | + return nil | ||
| 38 | + } | ||
| 39 | + resp = domain.MsgCheckDetail(respTmp) | ||
| 40 | + var ( | ||
| 41 | + keyWords []string | ||
| 42 | + prob int | ||
| 43 | + ) | ||
| 44 | + for i := range resp.Detail { | ||
| 45 | + item := resp.Detail[i] | ||
| 46 | + if prob == 0 { | ||
| 47 | + prob = int(item.Prob) | ||
| 48 | + } | ||
| 49 | + keyWords = append(keyWords, item.Keyword) | ||
| 50 | + } | ||
| 51 | + dm := &domain.ArticleSecurity{ | ||
| 52 | + ContentKeyWords: keyWords, | ||
| 53 | + ContentType: content.Type, | ||
| 54 | + ContentId: content.Id, | ||
| 55 | + AuthorId: content.AuthorId, | ||
| 56 | + Reviewer: 0, | ||
| 57 | + ReviewStatus: domain.ReviewStatusWait, | ||
| 58 | + Label: resp.Result.Label.String(), | ||
| 59 | + Prob: prob, | ||
| 60 | + Suggest: string(resp.Result.Suggest), | ||
| 61 | + Detail: resp, | ||
| 62 | + AutoReviewAt: time.Now().Unix(), | ||
| 63 | + AutoReviewErrorCode: fmt.Sprintf("%d", resp.ErrCode), | ||
| 64 | + } | ||
| 65 | + if resp.Result.Suggest == security.CheckSuggestPass { | ||
| 66 | + dm.ReviewStatus = domain.ReviewStatusPass | ||
| 67 | + } | ||
| 68 | + if dm, err = svcCtx.ArticleSecurityRepository.Insert(ctx, conn, dm); err != nil { | ||
| 69 | + logx.Error(err) | ||
| 70 | + return nil | ||
| 71 | + } | ||
| 72 | + return HandlerSecurityContent(ctx, svcCtx, conn, content, dm.ReviewStatus) | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +func HandlerSecurityContent(ctx context.Context, svcCtx *svc.ServiceContext, conn transaction.Conn, c ContentBody, status int) error { | ||
| 76 | + if !svcCtx.Config.ContentSecurityCheck { | ||
| 77 | + return nil | ||
| 78 | + } | ||
| 79 | + var ( | ||
| 80 | + article *domain.Article | ||
| 81 | + comment *domain.ArticleComment | ||
| 82 | + err error | ||
| 83 | + ) | ||
| 84 | + if status == domain.ReviewStatusPass { | ||
| 85 | + return nil | ||
| 86 | + } | ||
| 87 | + if c.Type == domain.TypeArticle { | ||
| 88 | + if article, err = svcCtx.ArticleRepository.FindOne(ctx, conn, c.Id); err != nil { | ||
| 89 | + return fmt.Errorf("文章不存在") | ||
| 90 | + } | ||
| 91 | + article.Show = domain.ArticleShowDisable | ||
| 92 | + if _, err = svcCtx.ArticleRepository.UpdateWithVersion(ctx, conn, article); err != nil { | ||
| 93 | + return err | ||
| 94 | + } | ||
| 95 | + } else if c.Type == domain.TypeComment { | ||
| 96 | + if comment, err = svcCtx.ArticleCommentRepository.FindOne(ctx, conn, c.Id); err != nil { | ||
| 97 | + return fmt.Errorf("评论不存在") | ||
| 98 | + } | ||
| 99 | + comment.Show = domain.CommentShowDisable | ||
| 100 | + if _, err = svcCtx.ArticleCommentRepository.UpdateWithVersion(ctx, conn, comment); err != nil { | ||
| 101 | + return err | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + return nil | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +type ContentBody struct { | ||
| 108 | + Id int64 | ||
| 109 | + Type int | ||
| 110 | + Content string | ||
| 111 | + AuthorId int64 | ||
| 112 | + Summary string | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +func NewContentFromComment(c *domain.ArticleComment) ContentBody { | ||
| 116 | + return ContentBody{ | ||
| 117 | + Id: c.Id, | ||
| 118 | + Type: domain.TypeComment, | ||
| 119 | + Content: c.Content, | ||
| 120 | + AuthorId: c.FromUserId, | ||
| 121 | + Summary: c.Content, | ||
| 122 | + } | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +func NewContentFromArticle(c *domain.Article, sections []*domain.ArticleSection) ContentBody { | ||
| 126 | + content := bytes.NewBuffer(nil) | ||
| 127 | + for _, sec := range sections { | ||
| 128 | + content.WriteString(sec.Content) | ||
| 129 | + } | ||
| 130 | + return ContentBody{ | ||
| 131 | + Id: c.Id, | ||
| 132 | + Type: domain.TypeComment, | ||
| 133 | + Content: content.String(), | ||
| 134 | + AuthorId: c.AuthorId, | ||
| 135 | + Summary: c.Summary, | ||
| 136 | + } | ||
| 137 | +} |
| 1 | +package secuirty | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/core" | ||
| 6 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr" | ||
| 9 | + "time" | ||
| 10 | + | ||
| 11 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 12 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" | ||
| 13 | + | ||
| 14 | + "github.com/zeromicro/go-zero/core/logx" | ||
| 15 | +) | ||
| 16 | + | ||
| 17 | +type ArticleSecurityAuditLogic struct { | ||
| 18 | + logx.Logger | ||
| 19 | + ctx context.Context | ||
| 20 | + svcCtx *svc.ServiceContext | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +func NewArticleSecurityAuditLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ArticleSecurityAuditLogic { | ||
| 24 | + return &ArticleSecurityAuditLogic{ | ||
| 25 | + Logger: logx.WithContext(ctx), | ||
| 26 | + ctx: ctx, | ||
| 27 | + svcCtx: svcCtx, | ||
| 28 | + } | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +func (l *ArticleSecurityAuditLogic) ArticleSecurityAudit(req *types.ArticleSecurityAuditRequest) (resp *types.ArticleSecurityAuditResponse, err error) { | ||
| 32 | + var ( | ||
| 33 | + conn = l.svcCtx.DefaultDBConn() | ||
| 34 | + dm *domain.ArticleSecurity | ||
| 35 | + ) | ||
| 36 | + if dm, err = l.svcCtx.ArticleSecurityRepository.FindOne(l.ctx, conn, req.Id); err != nil { | ||
| 37 | + return nil, xerr.NewErrMsgErr("不存在", err) | ||
| 38 | + } | ||
| 39 | + // 不可编辑判断 | ||
| 40 | + if dm.ReviewStatus != domain.ReviewStatusWait { | ||
| 41 | + return nil, xerr.NewErrMsgErr("内容已审核", err) | ||
| 42 | + } | ||
| 43 | + // 赋值 | ||
| 44 | + if req.Status == 1 { | ||
| 45 | + dm.ReviewStatus = domain.ReviewStatusPass | ||
| 46 | + } else { | ||
| 47 | + dm.ReviewStatus = domain.ReviewStatusFail | ||
| 48 | + } | ||
| 49 | + dm.ReviewAt = time.Now().Unix() | ||
| 50 | + // 更新 | ||
| 51 | + if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error { | ||
| 52 | + dm, err = l.svcCtx.ArticleSecurityRepository.UpdateWithVersion(l.ctx, conn, dm) | ||
| 53 | + if err != nil { | ||
| 54 | + return err | ||
| 55 | + } | ||
| 56 | + if err = core.HandlerSecurityContent(l.ctx, l.svcCtx, conn, core.ContentBody{Id: dm.ContentId, Type: dm.ContentType}, dm.ReviewStatus); err != nil { | ||
| 57 | + return err | ||
| 58 | + } | ||
| 59 | + // 更新文章/评论可见 | ||
| 60 | + return err | ||
| 61 | + }, true); err != nil { | ||
| 62 | + return nil, xerr.NewErrMsg("更新失败") | ||
| 63 | + } | ||
| 64 | + resp = &types.ArticleSecurityAuditResponse{} | ||
| 65 | + return | ||
| 66 | +} |
| 1 | +package secuirty | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" | ||
| 6 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr" | ||
| 7 | + | ||
| 8 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" | ||
| 10 | + | ||
| 11 | + "github.com/zeromicro/go-zero/core/logx" | ||
| 12 | +) | ||
| 13 | + | ||
| 14 | +type ArticleSecurityGetLogic struct { | ||
| 15 | + logx.Logger | ||
| 16 | + ctx context.Context | ||
| 17 | + svcCtx *svc.ServiceContext | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +func NewArticleSecurityGetLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ArticleSecurityGetLogic { | ||
| 21 | + return &ArticleSecurityGetLogic{ | ||
| 22 | + Logger: logx.WithContext(ctx), | ||
| 23 | + ctx: ctx, | ||
| 24 | + svcCtx: svcCtx, | ||
| 25 | + } | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +func (l *ArticleSecurityGetLogic) ArticleSecurityGet(req *types.ArticleSecurityGetRequest) (resp *types.ArticleSecurityGetResponse, err error) { | ||
| 29 | + var ( | ||
| 30 | + conn = l.svcCtx.DefaultDBConn() | ||
| 31 | + dm *domain.ArticleSecurity | ||
| 32 | + reviewer *domain.User | ||
| 33 | + ) | ||
| 34 | + // 货号唯一 | ||
| 35 | + if dm, err = l.svcCtx.ArticleSecurityRepository.FindOne(l.ctx, conn, req.Id); err != nil { | ||
| 36 | + return nil, xerr.NewErrMsgErr("不存在", err) | ||
| 37 | + } | ||
| 38 | + if dm.Reviewer > 0 { | ||
| 39 | + if reviewer, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, dm.Reviewer); err != nil { | ||
| 40 | + return nil, err | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + resp = &types.ArticleSecurityGetResponse{ | ||
| 44 | + ArticleSecurity: NewTypesArticleSecurity(dm, reviewer), | ||
| 45 | + } | ||
| 46 | + return | ||
| 47 | +} |
| 1 | +package secuirty | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" | ||
| 6 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" | ||
| 7 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" | ||
| 8 | + "strings" | ||
| 9 | + | ||
| 10 | + "github.com/zeromicro/go-zero/core/logx" | ||
| 11 | +) | ||
| 12 | + | ||
| 13 | +type ArticleSecuritySearchLogic struct { | ||
| 14 | + logx.Logger | ||
| 15 | + ctx context.Context | ||
| 16 | + svcCtx *svc.ServiceContext | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +func NewArticleSecuritySearchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ArticleSecuritySearchLogic { | ||
| 20 | + return &ArticleSecuritySearchLogic{ | ||
| 21 | + Logger: logx.WithContext(ctx), | ||
| 22 | + ctx: ctx, | ||
| 23 | + svcCtx: svcCtx, | ||
| 24 | + } | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +func (l *ArticleSecuritySearchLogic) ArticleSecuritySearch(req *types.ArticleSecuritySearchRequest) (resp *types.ArticleSecuritySearchResponse, err error) { | ||
| 28 | + var ( | ||
| 29 | + conn = l.svcCtx.DefaultDBConn() | ||
| 30 | + dms []*domain.ArticleSecurity | ||
| 31 | + total int64 | ||
| 32 | + ) | ||
| 33 | + | ||
| 34 | + queryOptions := domain.NewQueryOptions().WithOffsetLimit(req.Page, req.Size). | ||
| 35 | + WithKV("reviewStatus", req.ReviewStatus). | ||
| 36 | + WithKV("suggest", req.Suggest). | ||
| 37 | + WithKV("contentType", req.ContentType). | ||
| 38 | + WithKV("authorName", req.AuthorName). | ||
| 39 | + WithKV("beginTime", req.BeginTime). | ||
| 40 | + WithKV("endTime", req.EndTime) | ||
| 41 | + | ||
| 42 | + total, dms, err = l.svcCtx.ArticleSecurityRepository.Find(l.ctx, conn, queryOptions) | ||
| 43 | + list := make([]types.ArticleSecurityItem, 0) | ||
| 44 | + for i := range dms { | ||
| 45 | + list = append(list, NewTypesArticleSecurity(dms[i], nil)) | ||
| 46 | + } | ||
| 47 | + resp = &types.ArticleSecuritySearchResponse{ | ||
| 48 | + List: list, | ||
| 49 | + Total: total, | ||
| 50 | + } | ||
| 51 | + return | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +func NewDomainArticleSecurity(item types.ArticleSecurityItem) *domain.ArticleSecurity { | ||
| 55 | + return &domain.ArticleSecurity{} | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +func NewTypesArticleSecurity(item *domain.ArticleSecurity, reviewer *domain.User) types.ArticleSecurityItem { | ||
| 59 | + result := types.ArticleSecurityItem{ | ||
| 60 | + Id: item.Id, | ||
| 61 | + ContentKeyWords: strings.Join(item.ContentKeyWords, ","), | ||
| 62 | + Label: item.Label, | ||
| 63 | + Prob: item.Prob, | ||
| 64 | + Suggest: describeSuggest(item.Suggest), | ||
| 65 | + Author: item.AuthorName, | ||
| 66 | + ReviewAt: item.CreatedAt, | ||
| 67 | + ReviewStatus: item.ReviewStatus, | ||
| 68 | + | ||
| 69 | + Reviewer: "", | ||
| 70 | + } | ||
| 71 | + if reviewer != nil { | ||
| 72 | + result.Reviewer = reviewer.Name | ||
| 73 | + } | ||
| 74 | + for _, detail := range item.Detail.Detail { | ||
| 75 | + result.CheckList = append(result.CheckList, types.CheckDetailItem{ | ||
| 76 | + Label: detail.Label.String(), | ||
| 77 | + Prob: detail.Prob, | ||
| 78 | + Suggest: describeSuggest(detail.Suggest), | ||
| 79 | + }) | ||
| 80 | + } | ||
| 81 | + return result | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +func describeContentType(t int) string { | ||
| 85 | + if t == domain.TypeArticle { | ||
| 86 | + return "文本-帖子" | ||
| 87 | + } | ||
| 88 | + if t == domain.TypeComment { | ||
| 89 | + return "文本-评论" | ||
| 90 | + } | ||
| 91 | + return "" | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +func describeSuggest(s string) string { | ||
| 95 | + if s == "risk" { | ||
| 96 | + return "风险" | ||
| 97 | + } | ||
| 98 | + if s == "pass" { | ||
| 99 | + return "通过" | ||
| 100 | + } | ||
| 101 | + if s == "review" { | ||
| 102 | + return "人工审核" | ||
| 103 | + } | ||
| 104 | + return "" | ||
| 105 | +} |
| @@ -36,6 +36,7 @@ type ServiceContext struct { | @@ -36,6 +36,7 @@ type ServiceContext struct { | ||
| 36 | ArticleCategoryRepository domain.ArticleCategoryRepository | 36 | ArticleCategoryRepository domain.ArticleCategoryRepository |
| 37 | ArticleAndTagRepository domain.ArticleAndTagRepository | 37 | ArticleAndTagRepository domain.ArticleAndTagRepository |
| 38 | ArticleDraftOperationRepository domain.ArticleDraftOperationRepository | 38 | ArticleDraftOperationRepository domain.ArticleDraftOperationRepository |
| 39 | + ArticleSecurityRepository domain.ArticleSecurityRepository | ||
| 39 | 40 | ||
| 40 | CompanyRepository domain.CompanyRepository | 41 | CompanyRepository domain.CompanyRepository |
| 41 | DepartmentRepository domain.DepartmentRepository | 42 | DepartmentRepository domain.DepartmentRepository |
| @@ -91,6 +92,7 @@ func NewServiceContext(c config.Config) *ServiceContext { | @@ -91,6 +92,7 @@ func NewServiceContext(c config.Config) *ServiceContext { | ||
| 91 | ArticleAndTagRepository: repository.NewArticleAndTagRepository(cache.NewCachedRepository(mlCache)), | 92 | ArticleAndTagRepository: repository.NewArticleAndTagRepository(cache.NewCachedRepository(mlCache)), |
| 92 | ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)), | 93 | ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)), |
| 93 | ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)), | 94 | ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)), |
| 95 | + ArticleSecurityRepository: repository.NewArticleSecurityRepository(cache.NewCachedRepository(mlCache)), | ||
| 94 | 96 | ||
| 95 | CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)), | 97 | CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)), |
| 96 | DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)), | 98 | DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)), |
| @@ -1804,3 +1804,62 @@ type CategoryOptionValue struct { | @@ -1804,3 +1804,62 @@ type CategoryOptionValue struct { | ||
| 1804 | Label string `json:"label"` // 名称 | 1804 | Label string `json:"label"` // 名称 |
| 1805 | Value int64 `json:"value"` // 分类ID | 1805 | Value int64 `json:"value"` // 分类ID |
| 1806 | } | 1806 | } |
| 1807 | + | ||
| 1808 | +type ArticleSecurityGetRequest struct { | ||
| 1809 | + Id int64 `path:"id"` | ||
| 1810 | +} | ||
| 1811 | + | ||
| 1812 | +type ArticleSecurityGetResponse struct { | ||
| 1813 | + ArticleSecurity ArticleSecurityItem `json:"item"` | ||
| 1814 | +} | ||
| 1815 | + | ||
| 1816 | +type ArticleSecurityAuditRequest struct { | ||
| 1817 | + Id int64 `json:"id"` //id | ||
| 1818 | + Status int `json:"status"` // 1:成功 0:失败 | ||
| 1819 | +} | ||
| 1820 | + | ||
| 1821 | +type ArticleSecurityAuditResponse struct { | ||
| 1822 | +} | ||
| 1823 | + | ||
| 1824 | +type ArticleSecuritySearchRequest struct { | ||
| 1825 | + Page int `json:"page,optional"` | ||
| 1826 | + Size int `json:"size,optional"` | ||
| 1827 | + ReviewStatus int `json:"reviewStatus,optional"` // 审核结果 1:待审核 2:通过 3:拒绝 | ||
| 1828 | + Suggest string `json:"suggest"` // 建议 通过、风险、人工审核 | ||
| 1829 | + ContentType int `json:"contentType"` // 内容类型 (1:文章 2:评论) | ||
| 1830 | + AuthorName string `json:"authorName"` // 作者名称 | ||
| 1831 | + BeginTime int64 `json:"beginTime"` // 开始时间 | ||
| 1832 | + EndTime int64 `json:"endTime"` // 结束时间 | ||
| 1833 | +} | ||
| 1834 | + | ||
| 1835 | +type ArticleSecuritySearchResponse struct { | ||
| 1836 | + List []ArticleSecurityItem `json:"list"` | ||
| 1837 | + Total int64 `json:"total"` | ||
| 1838 | +} | ||
| 1839 | + | ||
| 1840 | +type ArticleSecurityItem struct { | ||
| 1841 | + Id int64 `json:"id"` // 唯一标识 | ||
| 1842 | + ContentKeyWords string `json:"contentKeyWords"` // 内容关键字 | ||
| 1843 | + Content ContentDetailItem `json:"content"` // 内容详情 | ||
| 1844 | + Label string `json:"label"` // 风控标签 | ||
| 1845 | + Prob int `json:"prob"` // 分值 | ||
| 1846 | + Suggest string `json:"suggest"` // 建议 通过、风险、人工审核 | ||
| 1847 | + Author string `json:"author"` // 发布人 | ||
| 1848 | + ReleaseAt string `json:"releaseAt"` // 发布时间 | ||
| 1849 | + ReviewStatus int `json:"reviewStatus"` // 审核结果 1:待审核 2:通过 3:拒绝 | ||
| 1850 | + Reviewer string `json:"reviewer"` // 审核人 | ||
| 1851 | + ReviewAt int64 `json:"reviewAt"` // 审核时间(人工处置时间) | ||
| 1852 | + CheckList []CheckDetailItem `json:"checkList"` // 检查列表 | ||
| 1853 | +} | ||
| 1854 | + | ||
| 1855 | +type CheckDetailItem struct { | ||
| 1856 | + Label string `json:"label"` // 命中标签 | ||
| 1857 | + Prob uint `json:"prob"` // 置信度。0-100,越高代表越有可能属于当前返回的标签(label) | ||
| 1858 | + Suggest string `json:"suggest"` // 建议 | ||
| 1859 | +} | ||
| 1860 | + | ||
| 1861 | +type ContentDetailItem struct { | ||
| 1862 | + Id int64 `json:"id"` // 内容ID | ||
| 1863 | + Type int `json:"type"` // 内容类型 (1:文章 2:评论) | ||
| 1864 | + Text string `json:"text"` // 内容文本 | ||
| 1865 | +} |
cmd/discuss/doc/dsl/api/article_security.api
0 → 100644
| 1 | + | ||
| 2 | +syntax = "v1" | ||
| 3 | + | ||
| 4 | +info( | ||
| 5 | + title: "xx实例" | ||
| 6 | + desc: "xx实例" | ||
| 7 | + author: "author" | ||
| 8 | + email: "email" | ||
| 9 | + version: "v1" | ||
| 10 | +) | ||
| 11 | + | ||
| 12 | +@server( | ||
| 13 | + prefix: article_security/v1 | ||
| 14 | + group: article_security | ||
| 15 | + jwt: JwtAuth | ||
| 16 | +) | ||
| 17 | +service Core { | ||
| 18 | + @doc "详情" | ||
| 19 | + @handler article_securityGet | ||
| 20 | + get /article_security/:id (ArticleSecurityGetRequest) returns (ArticleSecurityGetResponse) | ||
| 21 | + @doc "保存" | ||
| 22 | + @handler article_securitySave | ||
| 23 | + post /article_security (ArticleSecuritySaveRequest) returns (ArticleSecuritySaveResponse) | ||
| 24 | + @doc "删除" | ||
| 25 | + @handler article_securityDelete | ||
| 26 | + delete /article_security/:id (ArticleSecurityDeleteRequest) returns (ArticleSecurityDeleteResponse) | ||
| 27 | + @doc "更新" | ||
| 28 | + @handler article_securityUpdate | ||
| 29 | + put /article_security/:id (ArticleSecurityUpdateRequest) returns (ArticleSecurityUpdateResponse) | ||
| 30 | + @doc "搜索" | ||
| 31 | + @handler article_securitySearch | ||
| 32 | + post /article_security/search (ArticleSecuritySearchRequest) returns (ArticleSecuritySearchResponse) | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +type ( | ||
| 36 | + ArticleSecurityGetRequest { | ||
| 37 | + Id int64 `path:"id"` | ||
| 38 | + } | ||
| 39 | + ArticleSecurityGetResponse struct{ | ||
| 40 | + ArticleSecurity ArticleSecurityItem `json:"article_security"` | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + ArticleSecuritySaveRequest struct{ | ||
| 44 | + ArticleSecurity ArticleSecurityItem `json:"article_security"` | ||
| 45 | + } | ||
| 46 | + ArticleSecuritySaveResponse struct{} | ||
| 47 | + | ||
| 48 | + ArticleSecurityDeleteRequest struct{ | ||
| 49 | + Id int64 `path:"id"` | ||
| 50 | + } | ||
| 51 | + ArticleSecurityDeleteResponse struct{} | ||
| 52 | + | ||
| 53 | + ArticleSecurityUpdateRequest struct{ | ||
| 54 | + Id int64 `path:"id"` | ||
| 55 | + ArticleSecurity ArticleSecurityItem `json:"article_security"` | ||
| 56 | + } | ||
| 57 | + ArticleSecurityUpdateResponse struct{} | ||
| 58 | + | ||
| 59 | + ArticleSecuritySearchRequest struct{ | ||
| 60 | + Page int `json:"page"` | ||
| 61 | + Size int `json:"size"` | ||
| 62 | + } | ||
| 63 | + ArticleSecuritySearchResponse{ | ||
| 64 | + List []ArticleSecurityItem `json:"list"` | ||
| 65 | + Total int64 `json:"total"` | ||
| 66 | + } | ||
| 67 | + ArticleSecurityItem struct{ | ||
| 68 | + | ||
| 69 | + } | ||
| 70 | +) | ||
| 71 | + | ||
| 72 | +// logic CRUD | ||
| 73 | +// Save | ||
| 74 | + //var ( | ||
| 75 | + // conn = l.svcCtx.DefaultDBConn() | ||
| 76 | + // dm *domain.ArticleSecurity | ||
| 77 | + //) | ||
| 78 | + //// 唯一判断 | ||
| 79 | + | ||
| 80 | + //dm = NewDomainArticleSecurity(req.ArticleSecurity) | ||
| 81 | + //if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error { | ||
| 82 | + // dm, err = l.svcCtx.ArticleSecurityRepository.Insert(l.ctx, conn, dm) | ||
| 83 | + // return err | ||
| 84 | + //}, true); err != nil { | ||
| 85 | + // return nil, xerr.NewErrMsg("保存失败") | ||
| 86 | + //} | ||
| 87 | + ////resp = &types.ArticleSecuritySaveResponse{} | ||
| 88 | + //return | ||
| 89 | + | ||
| 90 | +//func NewDomainArticleSecurity(item types.ArticleSecurityItem) *domain.ArticleSecurity { | ||
| 91 | +// return &domain.ArticleSecurity{ | ||
| 92 | + | ||
| 93 | +// } | ||
| 94 | +//} | ||
| 95 | +// | ||
| 96 | +//func NewTypesArticleSecurity(item *domain.ArticleSecurity) types.ArticleSecurityItem { | ||
| 97 | +// return types.ArticleSecurityItem{ | ||
| 98 | +// Id: item.Id, | ||
| 99 | +// } | ||
| 100 | +//} | ||
| 101 | + | ||
| 102 | +// Get | ||
| 103 | + //var ( | ||
| 104 | + // conn = l.svcCtx.DefaultDBConn() | ||
| 105 | + // dm *domain.ArticleSecurity | ||
| 106 | + //) | ||
| 107 | + //// 货号唯一 | ||
| 108 | + //if dm, err = l.svcCtx.ArticleSecurityRepository.FindOne(l.ctx, conn, req.Id); err != nil { | ||
| 109 | + // return nil, xerr.NewErrMsgErr("不存在", err) | ||
| 110 | + //} | ||
| 111 | + //resp = &types.ArticleSecurityGetResponse{ | ||
| 112 | + // ArticleSecurity: NewTypesArticleSecurity(dm), | ||
| 113 | + //} | ||
| 114 | + //return | ||
| 115 | + | ||
| 116 | +// Delete | ||
| 117 | + //var ( | ||
| 118 | + // conn = l.svcCtx.DefaultDBConn() | ||
| 119 | + // dm *domain.ArticleSecurity | ||
| 120 | + //) | ||
| 121 | + //if dm, err = l.svcCtx.ArticleSecurityRepository.FindOne(l.ctx, conn, req.Id); err != nil { | ||
| 122 | + // return nil, xerr.NewErrMsgErr("不存在", err) | ||
| 123 | + //} | ||
| 124 | + //if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error { | ||
| 125 | + // if dm, err = l.svcCtx.ArticleSecurityRepository.Delete(l.ctx, conn, dm); err != nil { | ||
| 126 | + // return err | ||
| 127 | + // } | ||
| 128 | + // return nil | ||
| 129 | + //}, true); err != nil { | ||
| 130 | + // return nil, xerr.NewErrMsgErr("移除失败", err) | ||
| 131 | + //} | ||
| 132 | + //return | ||
| 133 | + | ||
| 134 | +// Search | ||
| 135 | + //var ( | ||
| 136 | + // conn = l.svcCtx.DefaultDBConn() | ||
| 137 | + // dms []*domain.ArticleSecurity | ||
| 138 | + // total int64 | ||
| 139 | + //) | ||
| 140 | + // | ||
| 141 | + //queryOptions := domain.NewQueryOptions().WithOffsetLimit(req.Page, req.Size). | ||
| 142 | + // WithKV("", "") | ||
| 143 | + | ||
| 144 | + //total, dms, err = l.svcCtx.ArticleSecurityRepository.Find(l.ctx, conn, queryOptions) | ||
| 145 | + //list := make([]types.ArticleSecurityItem, 0) | ||
| 146 | + //for i := range dms { | ||
| 147 | + // list = append(list, NewTypesArticleSecurity(dms[i])) | ||
| 148 | + //} | ||
| 149 | + //resp = &types.ArticleSecuritySearchResponse{ | ||
| 150 | + // List: list, | ||
| 151 | + // Total: total, | ||
| 152 | + //} | ||
| 153 | + //return | ||
| 154 | + | ||
| 155 | +// Update | ||
| 156 | + //var ( | ||
| 157 | + // conn = l.svcCtx.DefaultDBConn() | ||
| 158 | + // dm *domain.ArticleSecurity | ||
| 159 | + //) | ||
| 160 | + //if dm, err = l.svcCtx.ArticleSecurityRepository.FindOne(l.ctx, conn, req.Id); err != nil { | ||
| 161 | + // return nil, xerr.NewErrMsgErr("不存在", err) | ||
| 162 | + //} | ||
| 163 | + //// 不可编辑判断 | ||
| 164 | + | ||
| 165 | + //// 赋值 | ||
| 166 | + | ||
| 167 | + //// 更新 | ||
| 168 | + //if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error { | ||
| 169 | + // dm, err = l.svcCtx.ArticleSecurityRepository.UpdateWithVersion(l.ctx, conn, dm) | ||
| 170 | + // return err | ||
| 171 | + //}, true); err != nil { | ||
| 172 | + // return nil, xerr.NewErrMsg("更新失败") | ||
| 173 | + //} | ||
| 174 | + //resp = &types.ArticleSecurityUpdateResponse{} | ||
| 175 | + //return |
| 1 | + | ||
| 2 | +syntax = "proto3"; | ||
| 3 | + | ||
| 4 | +option go_package ="./pb"; | ||
| 5 | + | ||
| 6 | +package pb; | ||
| 7 | + | ||
| 8 | +message ArticleSecurityGetReq { | ||
| 9 | + int64 Id = 1; | ||
| 10 | +} | ||
| 11 | +message ArticleSecurityGetResp{ | ||
| 12 | + ArticleSecurityItem User = 1; | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +message ArticleSecuritySaveReq { | ||
| 16 | + | ||
| 17 | +} | ||
| 18 | +message ArticleSecuritySaveResp{ | ||
| 19 | + | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +message ArticleSecurityDeleteReq { | ||
| 23 | + int64 Id = 1; | ||
| 24 | +} | ||
| 25 | +message ArticleSecurityDeleteResp{ | ||
| 26 | + | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +message ArticleSecurityUpdateReq { | ||
| 30 | + int64 Id = 1; | ||
| 31 | +} | ||
| 32 | +message ArticleSecurityUpdateResp{ | ||
| 33 | + | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +message ArticleSecuritySearchReq { | ||
| 37 | + int64 PageNumber = 1; | ||
| 38 | + int64 PageSize = 2; | ||
| 39 | +} | ||
| 40 | +message ArticleSecuritySearchResp{ | ||
| 41 | + repeated ArticleSecurityItem List =1; | ||
| 42 | + int64 Total =2; | ||
| 43 | +} | ||
| 44 | +message ArticleSecurityItem { | ||
| 45 | + | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +service ArticleSecurityService { | ||
| 49 | + rpc ArticleSecurityGet(ArticleSecurityGetReq) returns(ArticleSecurityGetResp); | ||
| 50 | + rpc ArticleSecuritySave(ArticleSecuritySaveReq) returns(ArticleSecuritySaveResp); | ||
| 51 | + rpc ArticleSecurityDelete(ArticleSecurityDeleteReq) returns(ArticleSecurityDeleteResp); | ||
| 52 | + rpc ArticleSecurityUpdate(ArticleSecurityUpdateReq) returns(ArticleSecurityUpdateResp); | ||
| 53 | + rpc ArticleSecuritySearch(ArticleSecuritySearchReq) returns(ArticleSecuritySearchResp); | ||
| 54 | +} |
| @@ -26,6 +26,7 @@ func Migrate(db *gorm.DB) { | @@ -26,6 +26,7 @@ func Migrate(db *gorm.DB) { | ||
| 26 | //&models.ArticleAndTag{}, | 26 | //&models.ArticleAndTag{}, |
| 27 | &models.ArticleDraftOperation{}, | 27 | &models.ArticleDraftOperation{}, |
| 28 | &models.ArticleCategory{}, | 28 | &models.ArticleCategory{}, |
| 29 | + &models.ArticleSecurity{}, | ||
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | db.AutoMigrate(modelsList...) | 32 | db.AutoMigrate(modelsList...) |
| 1 | +package models | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "fmt" | ||
| 5 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" | ||
| 6 | + "gorm.io/gorm" | ||
| 7 | + "gorm.io/plugin/soft_delete" | ||
| 8 | + "time" | ||
| 9 | +) | ||
| 10 | + | ||
| 11 | +type ArticleSecurity struct { | ||
| 12 | + Id int64 // 唯一标识 | ||
| 13 | + | ||
| 14 | + ContentKeyWords []string // 内容关键字 | ||
| 15 | + ContentType int `json:"contentType,omitempty"` // 内容类型 (1:文章 2:评论) | ||
| 16 | + ContentId int64 `json:"contentId,omitempty"` // 内容ID | ||
| 17 | + AuthorId int64 `json:"authorId,omitempty"` // 发布人 | ||
| 18 | + AuthorName string `json:"authorName,omitempty"` // 发布人 | ||
| 19 | + Reviewer int64 `json:"reviewer,omitempty"` // 审核人 | ||
| 20 | + ReviewStatus int `json:"reviewStatus,omitempty"` // 审核状态 0:待审核 1:通过 2:拒绝 | ||
| 21 | + Label string // 标签 | ||
| 22 | + Prob int // 分值 | ||
| 23 | + Suggest string // 建议 通过、风险、人工审核 | ||
| 24 | + Detail domain.MsgCheckDetail `gorm:"type:jsonb;serializer:json"` | ||
| 25 | + AutoReviewAt int64 `json:"autoReviewAt,omitempty"` // 自动审核时间 | ||
| 26 | + AutoReviewErrorCode string `json:"autoReviewErrorCode,omitempty"` // 自动审核错误码 | ||
| 27 | + ReviewAt int64 `json:"reviewAt,omitempty"` // 审核时间(人工处置时间) | ||
| 28 | + | ||
| 29 | + CreatedAt int64 | ||
| 30 | + UpdatedAt int64 | ||
| 31 | + DeletedAt int64 | ||
| 32 | + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` | ||
| 33 | + Version int | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +func (m *ArticleSecurity) TableName() string { | ||
| 37 | + return "article_security" | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +func (m *ArticleSecurity) BeforeCreate(tx *gorm.DB) (err error) { | ||
| 41 | + m.CreatedAt = time.Now().Unix() | ||
| 42 | + m.UpdatedAt = time.Now().Unix() | ||
| 43 | + return | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +func (m *ArticleSecurity) BeforeUpdate(tx *gorm.DB) (err error) { | ||
| 47 | + m.UpdatedAt = time.Now().Unix() | ||
| 48 | + return | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +func (m *ArticleSecurity) CacheKeyFunc() string { | ||
| 52 | + if m.Id == 0 { | ||
| 53 | + return "" | ||
| 54 | + } | ||
| 55 | + return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id) | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +func (m *ArticleSecurity) CacheKeyFuncByObject(obj interface{}) string { | ||
| 59 | + if v, ok := obj.(*ArticleSecurity); ok { | ||
| 60 | + return v.CacheKeyFunc() | ||
| 61 | + } | ||
| 62 | + return "" | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +func (m *ArticleSecurity) CachePrimaryKeyFunc() string { | ||
| 66 | + if len("") == 0 { | ||
| 67 | + return "" | ||
| 68 | + } | ||
| 69 | + return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key") | ||
| 70 | +} |
| 1 | +package repository | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "fmt" | ||
| 6 | + "github.com/jinzhu/copier" | ||
| 7 | + "github.com/pkg/errors" | ||
| 8 | + "github.com/tiptok/gocomm/pkg/cache" | ||
| 9 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models" | ||
| 10 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" | ||
| 11 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" | ||
| 12 | + "gorm.io/gorm" | ||
| 13 | +) | ||
| 14 | + | ||
| 15 | +type ArticleSecurityRepository struct { | ||
| 16 | + *cache.CachedRepository | ||
| 17 | +} | ||
| 18 | + | ||
| 19 | +func (repository *ArticleSecurityRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.ArticleSecurity) (*domain.ArticleSecurity, error) { | ||
| 20 | + var ( | ||
| 21 | + err error | ||
| 22 | + m = &models.ArticleSecurity{} | ||
| 23 | + tx = conn.DB() | ||
| 24 | + ) | ||
| 25 | + if m, err = repository.DomainModelToModel(dm); err != nil { | ||
| 26 | + return nil, err | ||
| 27 | + } | ||
| 28 | + if tx = tx.Model(m).Save(m); tx.Error != nil { | ||
| 29 | + return nil, tx.Error | ||
| 30 | + } | ||
| 31 | + dm.Id = m.Id | ||
| 32 | + return repository.ModelToDomainModel(m) | ||
| 33 | + | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +func (repository *ArticleSecurityRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.ArticleSecurity) (*domain.ArticleSecurity, error) { | ||
| 37 | + var ( | ||
| 38 | + err error | ||
| 39 | + m *models.ArticleSecurity | ||
| 40 | + tx = conn.DB() | ||
| 41 | + ) | ||
| 42 | + if m, err = repository.DomainModelToModel(dm); err != nil { | ||
| 43 | + return nil, err | ||
| 44 | + } | ||
| 45 | + queryFunc := func() (interface{}, error) { | ||
| 46 | + tx = tx.Model(m).Updates(m) | ||
| 47 | + return nil, tx.Error | ||
| 48 | + } | ||
| 49 | + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil { | ||
| 50 | + return nil, err | ||
| 51 | + } | ||
| 52 | + return repository.ModelToDomainModel(m) | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +func (repository *ArticleSecurityRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.ArticleSecurity) (*domain.ArticleSecurity, error) { | ||
| 56 | + var ( | ||
| 57 | + err error | ||
| 58 | + m *models.ArticleSecurity | ||
| 59 | + tx = transaction.DB() | ||
| 60 | + ) | ||
| 61 | + if m, err = repository.DomainModelToModel(dm); err != nil { | ||
| 62 | + return nil, err | ||
| 63 | + } | ||
| 64 | + oldVersion := dm.Version | ||
| 65 | + m.Version += 1 | ||
| 66 | + queryFunc := func() (interface{}, error) { | ||
| 67 | + tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m) | ||
| 68 | + if tx.RowsAffected == 0 { | ||
| 69 | + return nil, domain.ErrUpdateFail | ||
| 70 | + } | ||
| 71 | + return nil, tx.Error | ||
| 72 | + } | ||
| 73 | + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil { | ||
| 74 | + return nil, err | ||
| 75 | + } | ||
| 76 | + return repository.ModelToDomainModel(m) | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +func (repository *ArticleSecurityRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.ArticleSecurity) (*domain.ArticleSecurity, error) { | ||
| 80 | + var ( | ||
| 81 | + tx = conn.DB() | ||
| 82 | + m = &models.ArticleSecurity{Id: dm.Identify().(int64)} | ||
| 83 | + ) | ||
| 84 | + queryFunc := func() (interface{}, error) { | ||
| 85 | + tx = tx.Where("id = ?", m.Id).Delete(m) | ||
| 86 | + return m, tx.Error | ||
| 87 | + } | ||
| 88 | + if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil { | ||
| 89 | + return dm, err | ||
| 90 | + } | ||
| 91 | + return repository.ModelToDomainModel(m) | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +func (repository *ArticleSecurityRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.ArticleSecurity, error) { | ||
| 95 | + var ( | ||
| 96 | + err error | ||
| 97 | + tx = conn.DB() | ||
| 98 | + m = new(models.ArticleSecurity) | ||
| 99 | + ) | ||
| 100 | + queryFunc := func() (interface{}, error) { | ||
| 101 | + tx = tx.Model(m).Where("id = ?", id).First(m) | ||
| 102 | + if errors.Is(tx.Error, gorm.ErrRecordNotFound) { | ||
| 103 | + return nil, domain.ErrNotFound | ||
| 104 | + } | ||
| 105 | + return m, tx.Error | ||
| 106 | + } | ||
| 107 | + cacheModel := new(models.ArticleSecurity) | ||
| 108 | + cacheModel.Id = id | ||
| 109 | + if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil { | ||
| 110 | + return nil, err | ||
| 111 | + } | ||
| 112 | + return repository.ModelToDomainModel(m) | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +func (repository *ArticleSecurityRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.ArticleSecurity, error) { | ||
| 116 | + var ( | ||
| 117 | + tx = conn.DB() | ||
| 118 | + ms []*models.ArticleSecurity | ||
| 119 | + dms = make([]*domain.ArticleSecurity, 0) | ||
| 120 | + total int64 | ||
| 121 | + ) | ||
| 122 | + queryFunc := func() (interface{}, error) { | ||
| 123 | + tx = tx.Model(&ms).Order("id desc") | ||
| 124 | + if v, ok := queryOptions["authorName"]; ok { | ||
| 125 | + tx.Where("author_name like ? ", fmt.Sprintf("%%%v%%", v)) | ||
| 126 | + } | ||
| 127 | + if v, ok := queryOptions["contentType"]; ok { | ||
| 128 | + tx.Where("content_type = ? ", v) | ||
| 129 | + } | ||
| 130 | + if v, ok := queryOptions["reviewStatus"]; ok { | ||
| 131 | + tx.Where("review_status = ? ", v) | ||
| 132 | + } | ||
| 133 | + if v, ok := queryOptions["suggest"]; ok { | ||
| 134 | + tx.Where("suggest = ? ", v) | ||
| 135 | + } | ||
| 136 | + if v, ok := queryOptions["beginTime"]; ok { | ||
| 137 | + tx.Where("created_at >= ?", v) | ||
| 138 | + } | ||
| 139 | + if v, ok := queryOptions["endTime"]; ok { | ||
| 140 | + tx.Where("created_at < ?", v) | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil { | ||
| 144 | + return dms, tx.Error | ||
| 145 | + } | ||
| 146 | + return dms, nil | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + if _, err := repository.Query(queryFunc); err != nil { | ||
| 150 | + return 0, nil, err | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + for _, item := range ms { | ||
| 154 | + if dm, err := repository.ModelToDomainModel(item); err != nil { | ||
| 155 | + return 0, dms, err | ||
| 156 | + } else { | ||
| 157 | + dms = append(dms, dm) | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | + return total, dms, nil | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +func (repository *ArticleSecurityRepository) ModelToDomainModel(from *models.ArticleSecurity) (*domain.ArticleSecurity, error) { | ||
| 164 | + to := &domain.ArticleSecurity{} | ||
| 165 | + err := copier.Copy(to, from) | ||
| 166 | + return to, err | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +func (repository *ArticleSecurityRepository) DomainModelToModel(from *domain.ArticleSecurity) (*models.ArticleSecurity, error) { | ||
| 170 | + to := &models.ArticleSecurity{} | ||
| 171 | + err := copier.Copy(to, from) | ||
| 172 | + return to, err | ||
| 173 | +} | ||
| 174 | + | ||
| 175 | +func NewArticleSecurityRepository(cache *cache.CachedRepository) domain.ArticleSecurityRepository { | ||
| 176 | + return &ArticleSecurityRepository{CachedRepository: cache} | ||
| 177 | +} |
| 1 | +package domain | ||
| 2 | + | ||
| 3 | +import ( | ||
| 4 | + "context" | ||
| 5 | + "github.com/silenceper/wechat/v2/miniprogram/security" | ||
| 6 | + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" | ||
| 7 | +) | ||
| 8 | + | ||
| 9 | +type ArticleSecurity struct { | ||
| 10 | + Id int64 // 唯一标识 | ||
| 11 | + | ||
| 12 | + ContentKeyWords []string // 内容关键字 | ||
| 13 | + ContentType int `json:"contentType,omitempty"` // 内容类型 (1:文章 2:评论) | ||
| 14 | + ContentId int64 `json:"contentId,omitempty"` // 内容ID | ||
| 15 | + AuthorId int64 `json:"authorId,omitempty"` // 发布人 | ||
| 16 | + AuthorName string `json:"authorName,omitempty"` // 发布人 | ||
| 17 | + Reviewer int64 `json:"reviewer,omitempty"` // 审核人 | ||
| 18 | + ReviewStatus int `json:"reviewStatus,omitempty"` // 审核状态 1:待审核 2:通过 3:拒绝 | ||
| 19 | + Label string // 标签 | ||
| 20 | + Prob int // 分值 | ||
| 21 | + Suggest string // 建议 通过、风险、人工审核 | ||
| 22 | + Detail MsgCheckDetail `json:"detail,omitempty"` | ||
| 23 | + AutoReviewAt int64 `json:"autoReviewAt,omitempty"` // 自动审核时间 | ||
| 24 | + AutoReviewErrorCode string `json:"autoReviewErrorCode,omitempty"` // 自动审核错误码 | ||
| 25 | + ReviewAt int64 `json:"reviewAt,omitempty"` // 审核时间(人工处置时间) | ||
| 26 | + CreatedAt int64 `json:"createdAt,omitempty"` | ||
| 27 | + UpdatedAt int64 `json:"updatedAt,omitempty"` | ||
| 28 | + DeletedAt int64 `json:"deletedAt,omitempty"` | ||
| 29 | + Version int `json:"version,omitempty"` | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +const ( | ||
| 33 | + ReviewStatusWait = iota + 1 | ||
| 34 | + ReviewStatusPass | ||
| 35 | + ReviewStatusFail | ||
| 36 | +) | ||
| 37 | + | ||
| 38 | +const ( | ||
| 39 | + TypeArticle = 1 | ||
| 40 | + TypeComment = 2 | ||
| 41 | +) | ||
| 42 | + | ||
| 43 | +type MsgCheckDetail security.MsgCheckResponse | ||
| 44 | + | ||
| 45 | +type ArticleSecurityRepository interface { | ||
| 46 | + Insert(ctx context.Context, conn transaction.Conn, dm *ArticleSecurity) (*ArticleSecurity, error) | ||
| 47 | + Update(ctx context.Context, conn transaction.Conn, dm *ArticleSecurity) (*ArticleSecurity, error) | ||
| 48 | + UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *ArticleSecurity) (*ArticleSecurity, error) | ||
| 49 | + Delete(ctx context.Context, conn transaction.Conn, dm *ArticleSecurity) (*ArticleSecurity, error) | ||
| 50 | + FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleSecurity, error) | ||
| 51 | + Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleSecurity, error) | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +func (m *ArticleSecurity) Identify() interface{} { | ||
| 55 | + if m.Id == 0 { | ||
| 56 | + return nil | ||
| 57 | + } | ||
| 58 | + return m.Id | ||
| 59 | +} |
| @@ -37,3 +37,8 @@ CREATE TABLE `article_category` ( | @@ -37,3 +37,8 @@ CREATE TABLE `article_category` ( | ||
| 37 | `id` int(0) NOT NULL COMMENT '唯一标识', | 37 | `id` int(0) NOT NULL COMMENT '唯一标识', |
| 38 | PRIMARY KEY (`id`) USING BTREE | 38 | PRIMARY KEY (`id`) USING BTREE |
| 39 | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; | 39 | ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; |
| 40 | + | ||
| 41 | +CREATE TABLE `article_security` ( | ||
| 42 | + `id` int(0) NOT NULL COMMENT '唯一标识', | ||
| 43 | + PRIMARY KEY (`id`) USING BTREE | ||
| 44 | +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; |
-
请 注册 或 登录 后发表评论