作者 yangfu

Merge branch 'dev' into test

正在显示 31 个修改的文件 包含 1997 行增加43 行删除
@@ -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"
@@ -1013,6 +1013,64 @@ @@ -1013,6 +1013,64 @@
1013 ] 1013 ]
1014 } 1014 }
1015 }, 1015 },
  1016 + "v1/mini/message/subscribe/add": {
  1017 + "post": {
  1018 + "summary": "增加订阅消息次数",
  1019 + "operationId": "miniMessageSubscribeAdd",
  1020 + "responses": {
  1021 + "200": {
  1022 + "description": "A successful response.",
  1023 + "schema": {
  1024 + "$ref": "#/definitions/MessageSubscribeAddResponse"
  1025 + }
  1026 + }
  1027 + },
  1028 + "parameters": [
  1029 + {
  1030 + "name": "body",
  1031 + "description": " 增加消息订阅次数",
  1032 + "in": "body",
  1033 + "required": true,
  1034 + "schema": {
  1035 + "$ref": "#/definitions/MessageSubscribeAddRequest"
  1036 + }
  1037 + }
  1038 + ],
  1039 + "requestBody": {},
  1040 + "tags": [
  1041 + "message"
  1042 + ]
  1043 + }
  1044 + },
  1045 + "v1/mini/message/subscribe/list": {
  1046 + "post": {
  1047 + "summary": "获取订阅消息次数",
  1048 + "operationId": "miniMessageSubscribeList",
  1049 + "responses": {
  1050 + "200": {
  1051 + "description": "A successful response.",
  1052 + "schema": {
  1053 + "$ref": "#/definitions/MessageSubscribeListResponse"
  1054 + }
  1055 + }
  1056 + },
  1057 + "parameters": [
  1058 + {
  1059 + "name": "body",
  1060 + "description": "订阅消息次数详情",
  1061 + "in": "body",
  1062 + "required": true,
  1063 + "schema": {
  1064 + "$ref": "#/definitions/MessageSubscribeListRequest"
  1065 + }
  1066 + }
  1067 + ],
  1068 + "requestBody": {},
  1069 + "tags": [
  1070 + "message"
  1071 + ]
  1072 + }
  1073 + },
1016 "v1/mini/message/system": { 1074 "v1/mini/message/system": {
1017 "post": { 1075 "post": {
1018 "summary": "系统消息", 1076 "summary": "系统消息",
@@ -1661,6 +1719,52 @@ @@ -1661,6 +1719,52 @@
1661 ] 1719 ]
1662 } 1720 }
1663 }, 1721 },
  1722 + "v1/mini/wechat/bind": {
  1723 + "post": {
  1724 + "summary": "绑定微信",
  1725 + "operationId": "miniWechatBind",
  1726 + "responses": {
  1727 + "200": {
  1728 + "description": "A successful response.",
  1729 + "schema": {
  1730 + "$ref": "#/definitions/MiniWechatBindResponse"
  1731 + }
  1732 + }
  1733 + },
  1734 + "parameters": [
  1735 + {
  1736 + "name": "body",
  1737 + "in": "body",
  1738 + "required": true,
  1739 + "schema": {
  1740 + "$ref": "#/definitions/MiniWechatBindRequest"
  1741 + }
  1742 + }
  1743 + ],
  1744 + "requestBody": {},
  1745 + "tags": [
  1746 + "user"
  1747 + ]
  1748 + }
  1749 + },
  1750 + "v1/mini/wechat/info": {
  1751 + "get": {
  1752 + "summary": "检测是否绑定微信",
  1753 + "operationId": "miniWechatInfo",
  1754 + "responses": {
  1755 + "200": {
  1756 + "description": "A successful response.",
  1757 + "schema": {
  1758 + "$ref": "#/definitions/MiniWechatInfoResponse"
  1759 + }
  1760 + }
  1761 + },
  1762 + "requestBody": {},
  1763 + "tags": [
  1764 + "user"
  1765 + ]
  1766 + }
  1767 + },
1664 "v1/system/account": { 1768 "v1/system/account": {
1665 "post": { 1769 "post": {
1666 "summary": "系统新增账号", 1770 "summary": "系统新增账号",
@@ -2623,6 +2727,89 @@ @@ -2623,6 +2727,89 @@
2623 ] 2727 ]
2624 } 2728 }
2625 }, 2729 },
  2730 + "v1/system/article_security/audit": {
  2731 + "post": {
  2732 + "summary": "内容安全-审核",
  2733 + "operationId": "articleSecurityAudit",
  2734 + "responses": {
  2735 + "200": {
  2736 + "description": "A successful response.",
  2737 + "schema": {
  2738 + "$ref": "#/definitions/ArticleSecurityAuditResponse"
  2739 + }
  2740 + }
  2741 + },
  2742 + "parameters": [
  2743 + {
  2744 + "name": "body",
  2745 + "description": " ArticleSecuritySaveRequest struct{, ArticleSecurity ArticleSecurityItem `json:\"article_security\"`, }, ArticleSecuritySaveResponse struct{},, ArticleSecurityDeleteRequest struct{, Id int64 `path:\"id\"`, }, ArticleSecurityDeleteResponse struct{},, ArticleSecurityUpdateRequest struct{, Id int64 `path:\"id\"`, ArticleSecurity ArticleSecurityItem `json:\"article_security\"`, }, ArticleSecurityUpdateResponse struct{}",
  2746 + "in": "body",
  2747 + "required": true,
  2748 + "schema": {
  2749 + "$ref": "#/definitions/ArticleSecurityAuditRequest"
  2750 + }
  2751 + }
  2752 + ],
  2753 + "requestBody": {},
  2754 + "tags": [
  2755 + "secuirty"
  2756 + ]
  2757 + }
  2758 + },
  2759 + "v1/system/article_security/search": {
  2760 + "post": {
  2761 + "summary": "内容安全-搜索",
  2762 + "operationId": "articleSecuritySearch",
  2763 + "responses": {
  2764 + "200": {
  2765 + "description": "A successful response.",
  2766 + "schema": {
  2767 + "$ref": "#/definitions/ArticleSecuritySearchResponse"
  2768 + }
  2769 + }
  2770 + },
  2771 + "parameters": [
  2772 + {
  2773 + "name": "body",
  2774 + "in": "body",
  2775 + "required": true,
  2776 + "schema": {
  2777 + "$ref": "#/definitions/ArticleSecuritySearchRequest"
  2778 + }
  2779 + }
  2780 + ],
  2781 + "requestBody": {},
  2782 + "tags": [
  2783 + "secuirty"
  2784 + ]
  2785 + }
  2786 + },
  2787 + "v1/system/article_security/{id}": {
  2788 + "get": {
  2789 + "summary": "详情",
  2790 + "operationId": "articleSecurityGet",
  2791 + "responses": {
  2792 + "200": {
  2793 + "description": "A successful response.",
  2794 + "schema": {
  2795 + "$ref": "#/definitions/ArticleSecurityGetResponse"
  2796 + }
  2797 + }
  2798 + },
  2799 + "parameters": [
  2800 + {
  2801 + "name": "id",
  2802 + "in": "path",
  2803 + "required": true,
  2804 + "type": "string"
  2805 + }
  2806 + ],
  2807 + "requestBody": {},
  2808 + "tags": [
  2809 + "secuirty"
  2810 + ]
  2811 + }
  2812 + },
2626 "v1/system/article_tag": { 2813 "v1/system/article_tag": {
2627 "post": { 2814 "post": {
2628 "summary": "后台创建文章标签", 2815 "summary": "后台创建文章标签",
@@ -3765,6 +3952,16 @@ @@ -3765,6 +3952,16 @@
3765 "format": "int64" 3952 "format": "int64"
3766 }, 3953 },
3767 "description": "谁可查看" 3954 "description": "谁可查看"
  3955 + },
  3956 + "isDel": {
  3957 + "type": "integer",
  3958 + "format": "int32",
  3959 + "description": "是否删除 1-删除 0-否"
  3960 + },
  3961 + "deletedType": {
  3962 + "type": "integer",
  3963 + "format": "int32",
  3964 + "description": "类型 1-运营删除 2-用户删除"
3768 } 3965 }
3769 }, 3966 },
3770 "title": "ArticleSearchMe", 3967 "title": "ArticleSearchMe",
@@ -3778,7 +3975,9 @@ @@ -3778,7 +3975,9 @@
3778 "countRead", 3975 "countRead",
3779 "show", 3976 "show",
3780 "targetUser", 3977 "targetUser",
3781 - "whoRead" 3978 + "whoRead",
  3979 + "isDel",
  3980 + "deletedType"
3782 ] 3981 ]
3783 }, 3982 },
3784 "ArticleSection": { 3983 "ArticleSection": {
@@ -3812,6 +4011,199 @@ @@ -3812,6 +4011,199 @@
3812 "totalComment" 4011 "totalComment"
3813 ] 4012 ]
3814 }, 4013 },
  4014 + "ArticleSecurityAuditRequest": {
  4015 + "type": "object",
  4016 + "properties": {
  4017 + "id": {
  4018 + "type": "integer",
  4019 + "format": "int64",
  4020 + "description": "id"
  4021 + },
  4022 + "status": {
  4023 + "type": "integer",
  4024 + "format": "int32",
  4025 + "description": " 1:成功 0:失败"
  4026 + }
  4027 + },
  4028 + "title": "ArticleSecurityAuditRequest",
  4029 + "required": [
  4030 + "id",
  4031 + "status"
  4032 + ]
  4033 + },
  4034 + "ArticleSecurityAuditResponse": {
  4035 + "type": "object",
  4036 + "title": "ArticleSecurityAuditResponse"
  4037 + },
  4038 + "ArticleSecurityGetRequest": {
  4039 + "type": "object",
  4040 + "properties": {
  4041 + "id": {
  4042 + "type": "integer",
  4043 + "format": "int64"
  4044 + }
  4045 + },
  4046 + "title": "ArticleSecurityGetRequest",
  4047 + "required": [
  4048 + "id"
  4049 + ]
  4050 + },
  4051 + "ArticleSecurityGetResponse": {
  4052 + "type": "object",
  4053 + "properties": {
  4054 + "item": {
  4055 + "$ref": "#/definitions/ArticleSecurityItem"
  4056 + }
  4057 + },
  4058 + "title": "ArticleSecurityGetResponse",
  4059 + "required": [
  4060 + "item"
  4061 + ]
  4062 + },
  4063 + "ArticleSecurityItem": {
  4064 + "type": "object",
  4065 + "properties": {
  4066 + "id": {
  4067 + "type": "integer",
  4068 + "format": "int64",
  4069 + "description": " 唯一标识"
  4070 + },
  4071 + "contentKeyWords": {
  4072 + "type": "string",
  4073 + "description": " 内容关键字"
  4074 + },
  4075 + "content": {
  4076 + "$ref": "#/definitions/ContentDetailItem",
  4077 + "description": " 内容详情"
  4078 + },
  4079 + "label": {
  4080 + "type": "string",
  4081 + "description": " 风控标签"
  4082 + },
  4083 + "prob": {
  4084 + "type": "integer",
  4085 + "format": "int32",
  4086 + "description": " 分值"
  4087 + },
  4088 + "suggest": {
  4089 + "type": "string",
  4090 + "description": " 建议 通过、风险、人工审核"
  4091 + },
  4092 + "author": {
  4093 + "type": "string",
  4094 + "description": " 发布人"
  4095 + },
  4096 + "releaseAt": {
  4097 + "type": "string",
  4098 + "description": " 发布时间"
  4099 + },
  4100 + "reviewStatus": {
  4101 + "type": "integer",
  4102 + "format": "int32",
  4103 + "description": " 审核结果 1:待审核 2:通过 3:拒绝"
  4104 + },
  4105 + "reviewer": {
  4106 + "type": "string",
  4107 + "description": " 审核人"
  4108 + },
  4109 + "reviewAt": {
  4110 + "type": "integer",
  4111 + "format": "int64",
  4112 + "description": " 审核时间(人工处置时间)"
  4113 + },
  4114 + "checkList": {
  4115 + "type": "array",
  4116 + "items": {
  4117 + "$ref": "#/definitions/CheckDetailItem"
  4118 + },
  4119 + "description": " 检查列表"
  4120 + }
  4121 + },
  4122 + "title": "ArticleSecurityItem",
  4123 + "required": [
  4124 + "id",
  4125 + "contentKeyWords",
  4126 + "content",
  4127 + "label",
  4128 + "prob",
  4129 + "suggest",
  4130 + "author",
  4131 + "releaseAt",
  4132 + "reviewStatus",
  4133 + "reviewer",
  4134 + "reviewAt",
  4135 + "checkList"
  4136 + ]
  4137 + },
  4138 + "ArticleSecuritySearchRequest": {
  4139 + "type": "object",
  4140 + "properties": {
  4141 + "page": {
  4142 + "type": "integer",
  4143 + "format": "int32"
  4144 + },
  4145 + "size": {
  4146 + "type": "integer",
  4147 + "format": "int32"
  4148 + },
  4149 + "reviewStatus": {
  4150 + "type": "integer",
  4151 + "format": "int32",
  4152 + "description": " 审核结果 1:待审核 2:通过 3:拒绝"
  4153 + },
  4154 + "suggest": {
  4155 + "type": "string",
  4156 + "description": " 建议 通过、风险、人工审核"
  4157 + },
  4158 + "contentType": {
  4159 + "type": "integer",
  4160 + "format": "int32",
  4161 + "description": " 内容类型 (1:文章 2:评论)"
  4162 + },
  4163 + "authorName": {
  4164 + "type": "string",
  4165 + "description": " 作者名称"
  4166 + },
  4167 + "beginTime": {
  4168 + "type": "integer",
  4169 + "format": "int64",
  4170 + "description": " 开始时间"
  4171 + },
  4172 + "endTime": {
  4173 + "type": "integer",
  4174 + "format": "int64",
  4175 + "description": " 结束时间"
  4176 + }
  4177 + },
  4178 + "title": "ArticleSecuritySearchRequest",
  4179 + "required": [
  4180 + "suggest",
  4181 + "contentType",
  4182 + "authorName",
  4183 + "beginTime",
  4184 + "endTime"
  4185 + ]
  4186 + },
  4187 + "ArticleSecuritySearchResponse": {
  4188 + "type": "object",
  4189 + "properties": {
  4190 + "list": {
  4191 + "type": "array",
  4192 + "items": {
  4193 + "$ref": "#/definitions/ArticleSecurityItem"
  4194 + }
  4195 + },
  4196 + "total": {
  4197 + "type": "integer",
  4198 + "format": "int64"
  4199 + }
  4200 + },
  4201 + "title": "ArticleSecuritySearchResponse",
  4202 + "required": [
  4203 + "list",
  4204 + "total"
  4205 + ]
  4206 + },
3815 "ArticleTagCount": { 4207 "ArticleTagCount": {
3816 "type": "object", 4208 "type": "object",
3817 "properties": { 4209 "properties": {
@@ -3967,12 +4359,18 @@ @@ -3967,12 +4359,18 @@
3967 "label": { 4359 "label": {
3968 "type": "string", 4360 "type": "string",
3969 "description": " 分组名称" 4361 "description": " 分组名称"
  4362 + },
  4363 + "enable": {
  4364 + "type": "integer",
  4365 + "format": "int32",
  4366 + "description": " 启用状态 1:启用"
3970 } 4367 }
3971 }, 4368 },
3972 "title": "CategoryOptions", 4369 "title": "CategoryOptions",
3973 "required": [ 4370 "required": [
3974 "value", 4371 "value",
3975 - "label" 4372 + "label",
  4373 + "enable"
3976 ] 4374 ]
3977 }, 4375 },
3978 "CategoryOptionsRequest": { 4376 "CategoryOptionsRequest": {
@@ -4001,6 +4399,29 @@ @@ -4001,6 +4399,29 @@
4001 "options" 4399 "options"
4002 ] 4400 ]
4003 }, 4401 },
  4402 + "CheckDetailItem": {
  4403 + "type": "object",
  4404 + "properties": {
  4405 + "label": {
  4406 + "type": "string",
  4407 + "description": " 命中标签"
  4408 + },
  4409 + "prob": {
  4410 + "$ref": "#/definitions/uint",
  4411 + "description": " 置信度。0-100,越高代表越有可能属于当前返回的标签(label)"
  4412 + },
  4413 + "suggest": {
  4414 + "type": "string",
  4415 + "description": " 建议"
  4416 + }
  4417 + },
  4418 + "title": "CheckDetailItem",
  4419 + "required": [
  4420 + "label",
  4421 + "prob",
  4422 + "suggest"
  4423 + ]
  4424 + },
4004 "CommentAtWho": { 4425 "CommentAtWho": {
4005 "type": "object", 4426 "type": "object",
4006 "properties": { 4427 "properties": {
@@ -4200,6 +4621,31 @@ @@ -4200,6 +4621,31 @@
4200 "type": "object", 4621 "type": "object",
4201 "title": "CompanyVisibleSwitchResponse" 4622 "title": "CompanyVisibleSwitchResponse"
4202 }, 4623 },
  4624 + "ContentDetailItem": {
  4625 + "type": "object",
  4626 + "properties": {
  4627 + "id": {
  4628 + "type": "integer",
  4629 + "format": "int64",
  4630 + "description": " 内容ID"
  4631 + },
  4632 + "type": {
  4633 + "type": "integer",
  4634 + "format": "int32",
  4635 + "description": " 内容类型 (1:文章 2:评论)"
  4636 + },
  4637 + "text": {
  4638 + "type": "string",
  4639 + "description": " 内容文本"
  4640 + }
  4641 + },
  4642 + "title": "ContentDetailItem",
  4643 + "required": [
  4644 + "id",
  4645 + "type",
  4646 + "text"
  4647 + ]
  4648 + },
4203 "Department": { 4649 "Department": {
4204 "type": "object", 4650 "type": "object",
4205 "properties": { 4651 "properties": {
@@ -4229,6 +4675,11 @@ @@ -4229,6 +4675,11 @@
4229 "format": "int64" 4675 "format": "int64"
4230 }, 4676 },
4231 "description": " 部门下的用户" 4677 "description": " 部门下的用户"
  4678 + },
  4679 + "totalUser": {
  4680 + "type": "integer",
  4681 + "format": "int32",
  4682 + "description": " 累计用户"
4232 } 4683 }
4233 }, 4684 },
4234 "title": "Department", 4685 "title": "Department",
@@ -4237,7 +4688,8 @@ @@ -4237,7 +4688,8 @@
4237 "companyId", 4688 "companyId",
4238 "parentId", 4689 "parentId",
4239 "name", 4690 "name",
4240 - "userIds" 4691 + "userIds",
  4692 + "totalUser"
4241 ] 4693 ]
4242 }, 4694 },
4243 "DepartmentAddRequest": { 4695 "DepartmentAddRequest": {
@@ -4297,6 +4749,16 @@ @@ -4297,6 +4749,16 @@
4297 "size": { 4749 "size": {
4298 "type": "integer", 4750 "type": "integer",
4299 "format": "int32" 4751 "format": "int32"
  4752 + },
  4753 + "includeRootCompany": {
  4754 + "type": "boolean",
  4755 + "format": "boolean",
  4756 + "description": " 包含公司(把公司当作部门作为顶级节点 部门ID:0)"
  4757 + },
  4758 + "includeDefaultDepartment": {
  4759 + "type": "boolean",
  4760 + "format": "boolean",
  4761 + "description": " 包含默认分组"
4300 } 4762 }
4301 }, 4763 },
4302 "title": "DepartmentListRequest", 4764 "title": "DepartmentListRequest",
@@ -4497,6 +4959,89 @@ @@ -4497,6 +4959,89 @@
4497 "size" 4959 "size"
4498 ] 4960 ]
4499 }, 4961 },
  4962 + "MessageSubscribeAddRequest": {
  4963 + "type": "object",
  4964 + "properties": {
  4965 + "types": {
  4966 + "type": "array",
  4967 + "items": {
  4968 + "type": "integer",
  4969 + "format": "int32"
  4970 + },
  4971 + "description": " 订阅消息类型"
  4972 + }
  4973 + },
  4974 + "title": "MessageSubscribeAddRequest",
  4975 + "required": [
  4976 + "types"
  4977 + ]
  4978 + },
  4979 + "MessageSubscribeAddResponse": {
  4980 + "type": "object",
  4981 + "properties": {
  4982 + "items": {
  4983 + "type": "array",
  4984 + "items": {
  4985 + "$ref": "#/definitions/MessageSubscribeItem"
  4986 + }
  4987 + }
  4988 + },
  4989 + "title": "MessageSubscribeAddResponse",
  4990 + "required": [
  4991 + "items"
  4992 + ]
  4993 + },
  4994 + "MessageSubscribeItem": {
  4995 + "type": "object",
  4996 + "properties": {
  4997 + "type": {
  4998 + "type": "integer",
  4999 + "format": "int32",
  5000 + "description": " 订阅消息类型"
  5001 + },
  5002 + "count": {
  5003 + "type": "integer",
  5004 + "format": "int32",
  5005 + "description": " 订阅次数"
  5006 + },
  5007 + "userId": {
  5008 + "type": "integer",
  5009 + "format": "int64",
  5010 + "description": " 用户ID"
  5011 + },
  5012 + "companyId": {
  5013 + "type": "integer",
  5014 + "format": "int64",
  5015 + "description": " 公司ID"
  5016 + }
  5017 + },
  5018 + "title": "MessageSubscribeItem",
  5019 + "required": [
  5020 + "type",
  5021 + "count",
  5022 + "userId",
  5023 + "companyId"
  5024 + ]
  5025 + },
  5026 + "MessageSubscribeListRequest": {
  5027 + "type": "object",
  5028 + "title": "MessageSubscribeListRequest"
  5029 + },
  5030 + "MessageSubscribeListResponse": {
  5031 + "type": "object",
  5032 + "properties": {
  5033 + "items": {
  5034 + "type": "array",
  5035 + "items": {
  5036 + "$ref": "#/definitions/MessageSubscribeItem"
  5037 + }
  5038 + }
  5039 + },
  5040 + "title": "MessageSubscribeListResponse",
  5041 + "required": [
  5042 + "items"
  5043 + ]
  5044 + },
4500 "MessageSystemItem": { 5045 "MessageSystemItem": {
4501 "type": "object", 5046 "type": "object",
4502 "properties": { 5047 "properties": {
@@ -6975,10 +7520,89 @@ @@ -6975,10 +7520,89 @@
6975 "keywords": { 7520 "keywords": {
6976 "type": "string", 7521 "type": "string",
6977 "description": " 按关键字搜索(名称)" 7522 "description": " 按关键字搜索(名称)"
  7523 + },
  7524 + "departmentId": {
  7525 + "$ref": "#/definitions/int64",
  7526 + "description": " 按部门过滤"
6978 } 7527 }
6979 }, 7528 },
6980 "title": "MiniUsersListRequest" 7529 "title": "MiniUsersListRequest"
6981 }, 7530 },
  7531 + "MiniWechatBindRequest": {
  7532 + "type": "object",
  7533 + "properties": {
  7534 + "wechatAuthcode": {
  7535 + "type": "string",
  7536 + "description": " 微信登录 授权码"
  7537 + },
  7538 + "wechatEncryptedData": {
  7539 + "type": "string",
  7540 + "description": " 微信登录 加密数据"
  7541 + },
  7542 + "wechatIV": {
  7543 + "type": "string",
  7544 + "description": " 微信登录 加密算法初始向量"
  7545 + }
  7546 + },
  7547 + "title": "MiniWechatBindRequest",
  7548 + "required": [
  7549 + "wechatAuthcode",
  7550 + "wechatEncryptedData",
  7551 + "wechatIV"
  7552 + ]
  7553 + },
  7554 + "MiniWechatBindResponse": {
  7555 + "type": "object",
  7556 + "properties": {
  7557 + "bind": {
  7558 + "type": "boolean",
  7559 + "format": "boolean",
  7560 + "description": " 绑定结果 true-已绑定 false-未绑定"
  7561 + },
  7562 + "openId": {
  7563 + "type": "string",
  7564 + "description": " 绑定的微信openId"
  7565 + },
  7566 + "phone": {
  7567 + "type": "string",
  7568 + "description": " 绑定手机号"
  7569 + }
  7570 + },
  7571 + "title": "MiniWechatBindResponse",
  7572 + "required": [
  7573 + "bind",
  7574 + "openId",
  7575 + "phone"
  7576 + ]
  7577 + },
  7578 + "MiniWechatInfoRequest": {
  7579 + "type": "object",
  7580 + "title": "MiniWechatInfoRequest"
  7581 + },
  7582 + "MiniWechatInfoResponse": {
  7583 + "type": "object",
  7584 + "properties": {
  7585 + "bind": {
  7586 + "type": "boolean",
  7587 + "format": "boolean",
  7588 + "description": " 绑定结果 true-已绑定 false-未绑定"
  7589 + },
  7590 + "openId": {
  7591 + "type": "string",
  7592 + "description": " 绑定的微信openId"
  7593 + },
  7594 + "phone": {
  7595 + "type": "string",
  7596 + "description": " 绑定手机号"
  7597 + }
  7598 + },
  7599 + "title": "MiniWechatInfoResponse",
  7600 + "required": [
  7601 + "bind",
  7602 + "openId",
  7603 + "phone"
  7604 + ]
  7605 + },
6982 "MyBeLikedItem": { 7606 "MyBeLikedItem": {
6983 "type": "object", 7607 "type": "object",
6984 "properties": { 7608 "properties": {
@@ -7828,11 +8452,16 @@ @@ -7828,11 +8452,16 @@
7828 "type": "integer", 8452 "type": "integer",
7829 "format": "int64", 8453 "format": "int64",
7830 "description": "id" 8454 "description": "id"
  8455 + },
  8456 + "AccessToken": {
  8457 + "type": "string",
  8458 + "description": " 授权token"
7831 } 8459 }
7832 }, 8460 },
7833 "title": "SystemArticleDeleteRequest", 8461 "title": "SystemArticleDeleteRequest",
7834 "required": [ 8462 "required": [
7835 - "id" 8463 + "id",
  8464 + "x-mmm-accesstoken"
7836 ] 8465 ]
7837 }, 8466 },
7838 "SystemArticleDeleteResponse": { 8467 "SystemArticleDeleteResponse": {
@@ -7866,11 +8495,16 @@ @@ -7866,11 +8495,16 @@
7866 "type": "integer", 8495 "type": "integer",
7867 "format": "int64", 8496 "format": "int64",
7868 "description": "ID" 8497 "description": "ID"
  8498 + },
  8499 + "AccessToken": {
  8500 + "type": "string",
  8501 + "description": " 授权token"
7869 } 8502 }
7870 }, 8503 },
7871 "title": "SystemArticleDeletedRestoreRequest", 8504 "title": "SystemArticleDeletedRestoreRequest",
7872 "required": [ 8505 "required": [
7873 - "id" 8506 + "id",
  8507 + "x-mmm-accesstoken"
7874 ] 8508 ]
7875 }, 8509 },
7876 "SystemArticleDeletedRestoreResponse": { 8510 "SystemArticleDeletedRestoreResponse": {
@@ -10180,6 +10814,10 @@ @@ -10180,6 +10814,10 @@
10180 }, 10814 },
10181 "code": { 10815 "code": {
10182 "type": "string" 10816 "type": "string"
  10817 + },
  10818 + "companyVisible": {
  10819 + "type": "boolean",
  10820 + "format": "boolean"
10183 } 10821 }
10184 }, 10822 },
10185 "title": "SystemUserInfoResponse", 10823 "title": "SystemUserInfoResponse",
@@ -10189,7 +10827,8 @@ @@ -10189,7 +10827,8 @@
10189 "avatar", 10827 "avatar",
10190 "companyId", 10828 "companyId",
10191 "companyName", 10829 "companyName",
10192 - "code" 10830 + "code",
  10831 + "companyVisible"
10193 ] 10832 ]
10194 }, 10833 },
10195 "SystemUserSearchRequest": { 10834 "SystemUserSearchRequest": {
@@ -10221,8 +10860,7 @@ @@ -10221,8 +10860,7 @@
10221 "description": " 启用状态 1:启用 2:禁用" 10860 "description": " 启用状态 1:启用 2:禁用"
10222 }, 10861 },
10223 "departmentId": { 10862 "departmentId": {
10224 - "type": "integer",  
10225 - "format": "int64", 10863 + "$ref": "#/definitions/int64",
10226 "description": " 所属部门" 10864 "description": " 所属部门"
10227 } 10865 }
10228 }, 10866 },
  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 int64 `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"
@@ -809,4 +810,29 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { @@ -809,4 +810,29 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
809 }, 810 },
810 rest.WithPrefix("/v1/system"), 811 rest.WithPrefix("/v1/system"),
811 ) 812 )
  813 +
  814 + server.AddRoutes(
  815 + rest.WithMiddlewares(
  816 + []rest.Middleware{serverCtx.LoginStatusCheck, serverCtx.LogRequest},
  817 + []rest.Route{
  818 + {
  819 + Method: http.MethodPost,
  820 + Path: "/article_security/search",
  821 + Handler: secuirty.ArticleSecuritySearchHandler(serverCtx),
  822 + },
  823 + {
  824 + Method: http.MethodGet,
  825 + Path: "/article_security/:id",
  826 + Handler: secuirty.ArticleSecurityGetHandler(serverCtx),
  827 + },
  828 + {
  829 + Method: http.MethodPost,
  830 + Path: "/article_security/audit",
  831 + Handler: secuirty.ArticleSecurityAuditHandler(serverCtx),
  832 + },
  833 + }...,
  834 + ),
  835 + rest.WithJwt(serverCtx.Config.SystemAuth.AccessSecret),
  836 + rest.WithPrefix("/v1/system"),
  837 + )
812 } 838 }
  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 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message" 6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
6 "strconv" 7 "strconv"
7 "strings" 8 "strings"
@@ -205,6 +206,11 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -205,6 +206,11 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
205 if err != nil { 206 if err != nil {
206 return xerr.NewErrMsgErr("创建文章失败", err) 207 return xerr.NewErrMsgErr("创建文章失败", err)
207 } 208 }
  209 +
  210 + // 内容安全检查
  211 + if err = core.ContentSecurityCheck(l.ctx, l.svcCtx, c, author, core.NewContentFromArticle(newArticle, sectionList)); err != nil {
  212 + return err
  213 + }
208 return nil 214 return nil
209 }, true) 215 }, true)
210 if err != nil { 216 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
@@ -211,6 +212,11 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini @@ -211,6 +212,11 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
211 if err != nil { 212 if err != nil {
212 return err 213 return err
213 } 214 }
  215 +
  216 + // 内容安全检查
  217 + if err = core.ContentSecurityCheck(l.ctx, l.svcCtx, conn, fromUser, core.NewContentFromComment(&newComment)); err != nil {
  218 + return err
  219 + }
214 return nil 220 return nil
215 }, true) 221 }, true)
216 222
  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/executors"
  9 + "github.com/zeromicro/go-zero/core/logx"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  11 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  12 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  13 + "time"
  14 +)
  15 +
  16 +func ContentSecurityCheck(ctx context.Context, svcCtx *svc.ServiceContext, conn transaction.Conn, toUser *domain.User, content ContentBody) error {
  17 + if !svcCtx.Config.ContentSecurityCheck {
  18 + return nil
  19 + }
  20 + var (
  21 + scene security.MsgScene
  22 + )
  23 + if content.Type == 1 {
  24 + scene = security.MsgSceneSocialLog
  25 + } else {
  26 + scene = security.MsgSceneComment
  27 + }
  28 + var (
  29 + resp domain.MsgCheckDetail
  30 + userWechat *domain.UserWechat
  31 + )
  32 + if userWechat, _ = svcCtx.UserWechatRepository.FindOneByPhone(ctx, conn, toUser.Phone); userWechat == nil {
  33 + logx.Debug(fmt.Sprintf("用户%s(%s)未绑定微信,无法进行内容检查", toUser.Name, toUser.Phone))
  34 + return nil
  35 + }
  36 + respTmp, err := svcCtx.MiniProgram.GetSecurity().MsgCheck(&security.MsgCheckRequest{
  37 + OpenID: userWechat.OpenId,
  38 + Scene: scene,
  39 + Content: content.Content,
  40 + })
  41 + if err != nil {
  42 + logx.Error(err)
  43 + return nil
  44 + }
  45 + resp = domain.MsgCheckDetail(respTmp)
  46 + var (
  47 + keyWords = make([]string, 0)
  48 + prob int
  49 + )
  50 + for i := range resp.Detail {
  51 + item := resp.Detail[i]
  52 + if prob == 0 {
  53 + prob = int(item.Prob)
  54 + }
  55 + if item.Keyword == "" {
  56 + continue
  57 + }
  58 + keyWords = append(keyWords, item.Keyword)
  59 + }
  60 + dm := &domain.ArticleSecurity{
  61 + CompanyId: toUser.CompanyId,
  62 + ContentKeyWords: keyWords,
  63 + ContentType: content.Type,
  64 + ContentId: content.Id,
  65 + AuthorId: content.AuthorId,
  66 + AuthorName: toUser.Name,
  67 + Reviewer: 0,
  68 + ReviewStatus: domain.ReviewStatusWait,
  69 + Label: resp.Result.Label.String(),
  70 + Prob: prob,
  71 + Suggest: string(resp.Result.Suggest),
  72 + Detail: resp,
  73 + AutoReviewAt: time.Now().Unix(),
  74 + AutoReviewErrorCode: fmt.Sprintf("%d", resp.ErrCode),
  75 + }
  76 + if resp.Result.Suggest == security.CheckSuggestPass {
  77 + dm.ReviewStatus = domain.ReviewStatusPass
  78 + }
  79 + // 延迟任务(认定为风险的、人工审核),帖子或评论先隐藏,状态改为非法
  80 + if resp.Result.Suggest == security.CheckSuggestRisky || resp.Result.Suggest == security.CheckSuggestReview {
  81 + executors.NewDelayExecutor(func() {
  82 + HandlerSecurityContent(ctx, svcCtx, svcCtx.DefaultDBConn(), content, dm.ReviewStatus)
  83 + }, time.Second*5).Trigger()
  84 + }
  85 + if dm, err = svcCtx.ArticleSecurityRepository.Insert(ctx, conn, dm); err != nil {
  86 + logx.Error(err)
  87 + return nil
  88 + }
  89 + return nil
  90 +}
  91 +
  92 +func HandlerSecurityContent(ctx context.Context, svcCtx *svc.ServiceContext, conn transaction.Conn, c ContentBody, status int) error {
  93 + if !svcCtx.Config.ContentSecurityCheck {
  94 + return nil
  95 + }
  96 + var (
  97 + article *domain.Article
  98 + comment *domain.ArticleComment
  99 + err error
  100 + show = int(domain.ArticleShowIllegal)
  101 + )
  102 + if status == domain.ReviewStatusPass {
  103 + show = int(domain.ArticleShowEnable)
  104 + }
  105 + mnl := NewMessageNoticeLogic(ctx, svcCtx)
  106 + if c.Type == domain.TypeArticle {
  107 + if article, err = svcCtx.ArticleRepository.FindOne(ctx, conn, c.Id); err != nil {
  108 + return fmt.Errorf("文章不存在")
  109 + }
  110 + article.Show = domain.ArticleShow(show)
  111 + if _, err = svcCtx.ArticleRepository.UpdateWithVersion(ctx, conn, article); err != nil {
  112 + return err
  113 + }
  114 + if show == int(domain.ArticleShowIllegal) {
  115 + mnl.ArticleIllegal(conn, article.CompanyId, article.AuthorId, time.Unix(article.CreatedAt, 0).Format("2006-01-02 15:04"), article.Title)
  116 + }
  117 + } else if c.Type == domain.TypeComment {
  118 + if comment, err = svcCtx.ArticleCommentRepository.FindOne(ctx, conn, c.Id); err != nil {
  119 + return fmt.Errorf("评论不存在")
  120 + }
  121 + comment.Show = domain.CommentShow(show)
  122 + if _, err = svcCtx.ArticleCommentRepository.UpdateWithVersion(ctx, conn, comment); err != nil {
  123 + return err
  124 + }
  125 + if show == int(domain.CommentShowIllegal) {
  126 + mnl.ArticleIllegal(conn, comment.CompanyId, comment.FromUserId, time.Unix(comment.CreatedAt, 0).Format("2006-01-02 15:04"), comment.Content)
  127 + }
  128 + }
  129 + return nil
  130 +}
  131 +
  132 +type ContentBody struct {
  133 + Id int64
  134 + Type int
  135 + Content string
  136 + AuthorId int64
  137 + Summary string
  138 +}
  139 +
  140 +func NewContentFromComment(c *domain.ArticleComment) ContentBody {
  141 + return ContentBody{
  142 + Id: c.Id,
  143 + Type: domain.TypeComment,
  144 + Content: c.Content,
  145 + AuthorId: c.FromUserId,
  146 + Summary: c.Content,
  147 + }
  148 +}
  149 +
  150 +func NewContentFromArticle(c *domain.Article, sections []*domain.ArticleSection) ContentBody {
  151 + content := bytes.NewBuffer(nil)
  152 + for _, sec := range sections {
  153 + content.WriteString(sec.Content)
  154 + }
  155 + return ContentBody{
  156 + Id: c.Id,
  157 + Type: domain.TypeArticle,
  158 + Content: content.String(),
  159 + AuthorId: c.AuthorId,
  160 + Summary: c.Summary,
  161 + }
  162 +}
  1 +package core
  2 +
  3 +import (
  4 + "context"
  5 + "fmt"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  9 +)
  10 +
  11 +type MessageNotice struct {
  12 + ctx context.Context
  13 + svcCtx *svc.ServiceContext
  14 +}
  15 +
  16 +func NewMessageNoticeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MessageNotice {
  17 + return &MessageNotice{
  18 + ctx: ctx,
  19 + svcCtx: svcCtx,
  20 + }
  21 +}
  22 +
  23 +func (l *MessageNotice) ArticleIllegal(conn transaction.Conn, companyId, at int64, createdTime, title string) (err error) {
  24 + return l.createMessage(conn, companyId, at, domain.MsgTypeIllegal, "文本内容违规", fmt.Sprintf("你于%v发布的帖子[%v]含有违规信息,未通过审核,已被禁止发布。请自觉遵守相关规定,若有疑问,请咨询运营管理员了解详情。", createdTime, title))
  25 +}
  26 +
  27 +// CommentIllegal 评论违规
  28 +func (l *MessageNotice) CommentIllegal(conn transaction.Conn, at int64, companyId int64, createdTime, title string) (err error) {
  29 + return l.createMessage(conn, companyId, at, domain.MsgTypeIllegal, "文本内容违规", fmt.Sprintf("你于%v发布的评论[%v]含有违规信息,未通过审核,已被禁止发布。请自觉遵守相关规定,若有疑问,请咨询运营管理员了解详情。", createdTime, title))
  30 +}
  31 +
  32 +func (l *MessageNotice) createMessage(conn transaction.Conn, companyId, at int64, msgType domain.MsgSystemType, title string, content string) (err error) {
  33 + var msg = &domain.MessageSystem{
  34 + Type: msgType,
  35 + CompanyId: companyId,
  36 + RecipientId: at,
  37 + Title: title,
  38 + Content: content,
  39 + }
  40 + msg, err = l.svcCtx.MessageSystemRepository.Insert(l.ctx, conn, msg)
  41 + return err
  42 +}
@@ -54,8 +54,8 @@ func (l *MiniSubscribeLogic) getOpenId(conn transaction.Conn, userId int64) (str @@ -54,8 +54,8 @@ func (l *MiniSubscribeLogic) getOpenId(conn transaction.Conn, userId int64) (str
54 return userWechat.OpenId, nil 54 return userWechat.OpenId, nil
55 } 55 }
56 56
57 -// saveMessage 保存订阅消息  
58 -func (l *MiniSubscribeLogic) saveMessage(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message, sendErr error) error { 57 +// sendAndDecrease 保存并扣减订阅消息
  58 +func (l *MiniSubscribeLogic) sendAndDecrease(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message) error {
59 templateData := make(map[string]interface{}) 59 templateData := make(map[string]interface{})
60 _ = copier.Copy(&templateData, msg.Data) 60 _ = copier.Copy(&templateData, msg.Data)
61 subscribeMessage := &domain.MessageSubscribe{ 61 subscribeMessage := &domain.MessageSubscribe{
@@ -66,14 +66,34 @@ func (l *MiniSubscribeLogic) saveMessage(conn transaction.Conn, companyId, userI @@ -66,14 +66,34 @@ func (l *MiniSubscribeLogic) saveMessage(conn transaction.Conn, companyId, userI
66 TemplateId: msg.TemplateID, 66 TemplateId: msg.TemplateID,
67 TemplateData: templateData, 67 TemplateData: templateData,
68 } 68 }
  69 + //获取订阅次数
  70 + userSubscribe, err := l.svcCtx.UserSubscribeRepository.FindOneByType(l.ctx, conn, companyId, userId, mType)
  71 + if err != nil || userSubscribe.Count <= 0 {
  72 + subscribeMessage.Result = "fail"
  73 + subscribeMessage.Error = "订阅次数已用完"
  74 + } else {
  75 + //扣减订阅次数
  76 + userSubscribe.Count = userSubscribe.Count - 1
  77 + _, err = l.svcCtx.UserSubscribeRepository.Update(l.ctx, conn, userSubscribe)
  78 + if err != nil {
  79 + return err
  80 + }
  81 + //发送订阅消息
  82 + subCtx := l.getSubScribe()
  83 + sendErr := subCtx.Send(msg)
69 if sendErr != nil { 84 if sendErr != nil {
70 subscribeMessage.Result = "fail" 85 subscribeMessage.Result = "fail"
71 subscribeMessage.Error = sendErr.Error() 86 subscribeMessage.Error = sendErr.Error()
72 } else { 87 } else {
73 subscribeMessage.Result = "ok" 88 subscribeMessage.Result = "ok"
74 } 89 }
75 - _, err := l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage) 90 + }
  91 + //保存订阅结果
  92 + _, err = l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage)
  93 + if err != nil {
76 return err 94 return err
  95 + }
  96 + return nil
77 } 97 }
78 98
79 func (l *MiniSubscribeLogic) messageSubscribe(companyId, userId int64, mType int) *domain.MessageSubscribe { 99 func (l *MiniSubscribeLogic) messageSubscribe(companyId, userId int64, mType int) *domain.MessageSubscribe {
@@ -109,7 +129,6 @@ func (l *MiniSubscribeLogic) getReplyCommentUserInfo(conn transaction.Conn, comp @@ -109,7 +129,6 @@ func (l *MiniSubscribeLogic) getReplyCommentUserInfo(conn transaction.Conn, comp
109 // @param article 文章 129 // @param article 文章
110 // @param comment 评论 130 // @param comment 评论
111 func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain.Article, comment *domain.ArticleComment) error { 131 func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain.Article, comment *domain.ArticleComment) error {
112 - subCtx := l.getSubScribe()  
113 //评论用户+职位 例: 张三-董事办 132 //评论用户+职位 例: 张三-董事办
114 fromUserName, err := l.getReplyCommentUserInfo(conn, comment.CompanyId, comment.FromUserId) 133 fromUserName, err := l.getReplyCommentUserInfo(conn, comment.CompanyId, comment.FromUserId)
115 if err != nil { 134 if err != nil {
@@ -124,7 +143,7 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain @@ -124,7 +143,7 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain
124 //评论内容 143 //评论内容
125 "thing2": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()}, 144 "thing2": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
126 //评论时间 145 //评论时间
127 - "thing3": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")}, 146 + "time3": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
128 //评论用户 147 //评论用户
129 "thing5": &subscribe.DataItem{Value: fromUserName}, 148 "thing5": &subscribe.DataItem{Value: fromUserName},
130 //备注 149 //备注
@@ -139,10 +158,10 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain @@ -139,10 +158,10 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain
139 msg.ToUser = openId 158 msg.ToUser = openId
140 msg.Page = fmt.Sprintf("/pages/detail/more-comment?id=%v", article.Id) //跳转页面 帖子评论聚合页 159 msg.Page = fmt.Sprintf("/pages/detail/more-comment?id=%v", article.Id) //跳转页面 帖子评论聚合页
141 //备注 160 //备注
142 - msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", article.CountComment)} 161 + userCount, err := l.svcCtx.ArticleCommentRepository.CommentUserCount(l.ctx, conn, comment.CompanyId, comment.ArticleId)
  162 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", userCount)}
143 //发送微信订阅消息 163 //发送微信订阅消息
144 - err = subCtx.Send(msg)  
145 - err = l.saveMessage(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg, err) 164 + err = l.sendAndDecrease(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg)
146 if err != nil { 165 if err != nil {
147 return xerr.NewErrMsgErr("评论失败", err) 166 return xerr.NewErrMsgErr("评论失败", err)
148 } 167 }
@@ -154,12 +173,11 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain @@ -154,12 +173,11 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain
154 msg.ToUser = toOpenId 173 msg.ToUser = toOpenId
155 msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面评论聚合页 174 msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面评论聚合页
156 //备注 175 //备注
157 - parent, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Pid)  
158 - if err == nil && parent.Id > 0 {  
159 - msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", parent.CountReply)} 176 + replyCount, err := l.svcCtx.ArticleCommentRepository.ReplyUserCount(l.ctx, conn, comment.CompanyId, comment.Pid)
  177 + if err == nil {
  178 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", replyCount)}
160 //发送微信订阅消息 179 //发送微信订阅消息
161 - err = subCtx.Send(msg)  
162 - err = l.saveMessage(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg, err) 180 + err = l.sendAndDecrease(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg)
163 if err != nil { 181 if err != nil {
164 return xerr.NewErrMsgErr("评论失败", err) 182 return xerr.NewErrMsgErr("评论失败", err)
165 } 183 }
@@ -179,8 +197,7 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain @@ -179,8 +197,7 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain
179 //备注 197 //备注
180 msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("%v在评论中提到了你", comment.FromUser.Name)} 198 msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("%v在评论中提到了你", comment.FromUser.Name)}
181 //发送微信订阅消息 199 //发送微信订阅消息
182 - err = subCtx.Send(msg)  
183 - err = l.saveMessage(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg, err) 200 + err = l.sendAndDecrease(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg)
184 if err != nil { 201 if err != nil {
185 return xerr.NewErrMsgErr("评论失败", err) 202 return xerr.NewErrMsgErr("评论失败", err)
186 } 203 }
@@ -191,11 +208,14 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain @@ -191,11 +208,14 @@ func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain
191 208
192 // LikeArticle 帖子点赞订阅消息 209 // LikeArticle 帖子点赞订阅消息
193 func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error { 210 func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error {
194 - subCtx := l.getSubScribe()  
195 openId, err := l.getOpenId(conn, article.AuthorId) 211 openId, err := l.getOpenId(conn, article.AuthorId)
196 if err != nil || openId == "" { 212 if err != nil || openId == "" {
197 return nil 213 return nil
198 } 214 }
  215 + newArticle, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, article.Id)
  216 + if err != nil {
  217 + return xerr.NewErrMsgErr("未获取到帖子信息", err)
  218 + }
199 msg := &subscribe.Message{ 219 msg := &subscribe.Message{
200 ToUser: openId, 220 ToUser: openId,
201 TemplateID: domain.SubscribeTemplateLike, 221 TemplateID: domain.SubscribeTemplateLike,
@@ -204,18 +224,17 @@ func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain. @@ -204,18 +224,17 @@ func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.
204 //点赞用户 224 //点赞用户
205 "name1": &subscribe.DataItem{Value: userInfo.Name}, 225 "name1": &subscribe.DataItem{Value: userInfo.Name},
206 //点赞时间 226 //点赞时间
207 - "data2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")}, 227 + "date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
208 //动态内容 228 //动态内容
209 "thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()}, 229 "thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
210 //被赞次数 230 //被赞次数
211 - "number4": &subscribe.DataItem{Value: article.CountLove}, 231 + "number4": &subscribe.DataItem{Value: newArticle.CountLove},
212 //温馨提示 232 //温馨提示
213 "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"}, 233 "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
214 }, 234 },
215 MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv, 235 MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
216 } 236 }
217 - err = subCtx.Send(msg)  
218 - err = l.saveMessage(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg, err) 237 + err = l.sendAndDecrease(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg)
219 if err != nil { 238 if err != nil {
220 return xerr.NewErrMsgErr("点赞失败", err) 239 return xerr.NewErrMsgErr("点赞失败", err)
221 } 240 }
@@ -224,11 +243,15 @@ func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain. @@ -224,11 +243,15 @@ func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.
224 243
225 // LikeComment 点赞评论订阅消息 244 // LikeComment 点赞评论订阅消息
226 func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error { 245 func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error {
227 - subCtx := l.getSubScribe()  
228 openId, err := l.getOpenId(conn, comment.FromUserId) 246 openId, err := l.getOpenId(conn, comment.FromUserId)
229 if err != nil || openId == "" { 247 if err != nil || openId == "" {
230 return nil 248 return nil
231 } 249 }
  250 + //获取被赞次数
  251 + newComment, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Id)
  252 + if err != nil {
  253 + return xerr.NewErrMsgErr("未获取到评论信息", err)
  254 + }
232 msg := &subscribe.Message{ 255 msg := &subscribe.Message{
233 ToUser: openId, 256 ToUser: openId,
234 TemplateID: domain.SubscribeTemplateLike, 257 TemplateID: domain.SubscribeTemplateLike,
@@ -237,18 +260,17 @@ func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain. @@ -237,18 +260,17 @@ func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.
237 //点赞用户 260 //点赞用户
238 "name1": &subscribe.DataItem{Value: userInfo.Name}, 261 "name1": &subscribe.DataItem{Value: userInfo.Name},
239 //点赞时间 262 //点赞时间
240 - "data2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")}, 263 + "date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
241 //动态内容 264 //动态内容
242 "thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()}, 265 "thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
243 //被赞次数 266 //被赞次数
244 - "number4": &subscribe.DataItem{Value: comment.CountUserLove}, 267 + "number4": &subscribe.DataItem{Value: newComment.CountUserLove},
245 //温馨提示 268 //温馨提示
246 "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"}, 269 "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
247 }, 270 },
248 MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv, 271 MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
249 } 272 }
250 - err = subCtx.Send(msg)  
251 - err = l.saveMessage(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg, err) 273 + err = l.sendAndDecrease(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg)
252 if err != nil { 274 if err != nil {
253 return xerr.NewErrMsgErr("点赞失败", err) 275 return xerr.NewErrMsgErr("点赞失败", err)
254 } 276 }
@@ -257,7 +279,6 @@ func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain. @@ -257,7 +279,6 @@ func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.
257 279
258 // FollowArticle 发帖关注更新提醒 280 // FollowArticle 发帖关注更新提醒
259 func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error { 281 func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error {
260 - subCtx := l.getSubScribe()  
261 //获取关注帖子作者的人员 282 //获取关注帖子作者的人员
262 _, userInfo, err := l.svcCtx.UserFollowRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("toUserIds", []int64{article.AuthorId})) 283 _, userInfo, err := l.svcCtx.UserFollowRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("toUserIds", []int64{article.AuthorId}))
263 if err == nil && len(userInfo) > 0 { 284 if err == nil && len(userInfo) > 0 {
@@ -278,14 +299,13 @@ func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domai @@ -278,14 +299,13 @@ func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domai
278 //内容摘要 299 //内容摘要
279 "thing5": &subscribe.DataItem{Value: ""}, 300 "thing5": &subscribe.DataItem{Value: ""},
280 //发布时间 301 //发布时间
281 - "thing6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")}, 302 + "time6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
282 //温馨提示 303 //温馨提示
283 "thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"}, 304 "thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"},
284 }, 305 },
285 MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv, 306 MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
286 } 307 }
287 - err = subCtx.Send(msg)  
288 - err = l.saveMessage(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg, err) 308 + err = l.sendAndDecrease(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg)
289 if err != nil { 309 if err != nil {
290 return xerr.NewErrMsgErr("保存订阅消息失败", err) 310 return xerr.NewErrMsgErr("保存订阅消息失败", err)
291 } 311 }
@@ -62,6 +62,11 @@ func (l *MiniSystemLogic) ArticleDeleted(conn transaction.Conn, companyId, at in @@ -62,6 +62,11 @@ func (l *MiniSystemLogic) ArticleDeleted(conn transaction.Conn, companyId, at in
62 return l.createMessage(conn, companyId, at, domain.MsgTypeDeleted, "帖子已删除", fmt.Sprintf("你于%v发布的帖子[%v]已被删除,如有疑问,请联系运营管理员了解详情。", createdTime, title)) 62 return l.createMessage(conn, companyId, at, domain.MsgTypeDeleted, "帖子已删除", fmt.Sprintf("你于%v发布的帖子[%v]已被删除,如有疑问,请联系运营管理员了解详情。", createdTime, title))
63 } 63 }
64 64
  65 +// ArticleIllegal 帖子违规
  66 +func (l *MiniSystemLogic) ArticleIllegal(conn transaction.Conn, companyId, at int64, createdTime, title string) (err error) {
  67 + return l.createMessage(conn, companyId, at, domain.MsgTypeDeleted, "文本内容违规", fmt.Sprintf("你于%v发布的帖子[%v]含有违规信息,未通过审核,已被禁止发布。请自觉遵守相关规定,若有疑问,请咨询运营管理员了解详情。", createdTime, title))
  68 +}
  69 +
65 //// ArticleAuth 文章权限变更 70 //// ArticleAuth 文章权限变更
66 //func (l *MiniSystemLogic) ArticleAuth(conn transaction.Conn, companyId, at int64, item string) (err error) { 71 //func (l *MiniSystemLogic) ArticleAuth(conn transaction.Conn, companyId, at int64, item string) (err error) {
67 // return l.createMessage(conn, companyId, at, domain.MsgTypeAbnormal, "权限变更", fmt.Sprintf("您的帖子[%s]可见权限已添加,如有疑问,请联系运营管理员了解详情。", item)) 72 // return l.createMessage(conn, companyId, at, domain.MsgTypeAbnormal, "权限变更", fmt.Sprintf("您的帖子[%s]可见权限已添加,如有疑问,请联系运营管理员了解详情。", item))
@@ -92,6 +97,11 @@ func (l *MiniSystemLogic) AbnormalCommentHidden(conn transaction.Conn, companyId @@ -92,6 +97,11 @@ func (l *MiniSystemLogic) AbnormalCommentHidden(conn transaction.Conn, companyId
92 return l.createMessage(conn, companyId, at, domain.MsgTypeAbnormal, "评论被隐藏", fmt.Sprintf("您的评论[%s]已被隐藏,如有疑问,请联系运营管理员了解详情。", item)) 97 return l.createMessage(conn, companyId, at, domain.MsgTypeAbnormal, "评论被隐藏", fmt.Sprintf("您的评论[%s]已被隐藏,如有疑问,请联系运营管理员了解详情。", item))
93 } 98 }
94 99
  100 +// CommentIllegal 评论违规
  101 +func (l *MiniSystemLogic) CommentIllegal(conn transaction.Conn, at int64, companyId int64, createdTime, title string) (err error) {
  102 + return l.createMessage(conn, companyId, at, domain.MsgTypeIllegal, "文本内容违规", fmt.Sprintf("你于%v发布的评论[%v]含有违规信息,未通过审核,已被禁止发布。请自觉遵守相关规定,若有疑问,请咨询运营管理员了解详情。", createdTime, title))
  103 +}
  104 +
95 func (l *MiniSystemLogic) createMessage(conn transaction.Conn, companyId, at int64, msgType domain.MsgSystemType, title string, content string) (err error) { 105 func (l *MiniSystemLogic) createMessage(conn transaction.Conn, companyId, at int64, msgType domain.MsgSystemType, title string, content string) (err error) {
96 var msg = &domain.MessageSystem{ 106 var msg = &domain.MessageSystem{
97 Type: msgType, 107 Type: msgType,
  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 + article *domain.Article
  34 + comment *domain.ArticleComment
  35 + )
  36 + // 货号唯一
  37 + if dm, err = l.svcCtx.ArticleSecurityRepository.FindOne(l.ctx, conn, req.Id); err != nil {
  38 + return nil, xerr.NewErrMsgErr("不存在", err)
  39 + }
  40 + if dm.Reviewer > 0 {
  41 + if reviewer, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, dm.Reviewer); err != nil {
  42 + return nil, err
  43 + }
  44 + }
  45 + resp = &types.ArticleSecurityGetResponse{
  46 + ArticleSecurity: NewTypesArticleSecurity(dm, reviewer),
  47 + }
  48 + if dm.ContentType == domain.TypeArticle {
  49 + if article, _ = l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, dm.ContentId); article != nil {
  50 + resp.ArticleSecurity.Content.Text = article.Summary
  51 + }
  52 + } else if dm.ContentType == domain.TypeComment {
  53 + if comment, _ = l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, dm.ContentId); comment != nil {
  54 + resp.ArticleSecurity.Content.Text = comment.Content
  55 + }
  56 + }
  57 + return
  58 +}
  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 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  9 + "strings"
  10 +
  11 + "github.com/zeromicro/go-zero/core/logx"
  12 +)
  13 +
  14 +type ArticleSecuritySearchLogic struct {
  15 + logx.Logger
  16 + ctx context.Context
  17 + svcCtx *svc.ServiceContext
  18 +}
  19 +
  20 +func NewArticleSecuritySearchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ArticleSecuritySearchLogic {
  21 + return &ArticleSecuritySearchLogic{
  22 + Logger: logx.WithContext(ctx),
  23 + ctx: ctx,
  24 + svcCtx: svcCtx,
  25 + }
  26 +}
  27 +
  28 +func (l *ArticleSecuritySearchLogic) ArticleSecuritySearch(req *types.ArticleSecuritySearchRequest) (resp *types.ArticleSecuritySearchResponse, err error) {
  29 + var (
  30 + conn = l.svcCtx.DefaultDBConn()
  31 + dms []*domain.ArticleSecurity
  32 + total int64
  33 + userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  34 + )
  35 +
  36 + queryOptions := domain.IndexCompanyId(userToken.CompanyId)().WithOffsetLimit(req.Page, req.Size).
  37 + WithKV("reviewStatus", req.ReviewStatus).
  38 + WithKV("suggest", req.Suggest).
  39 + WithKV("contentType", req.ContentType).
  40 + WithKV("authorName", req.AuthorName).
  41 + WithKV("beginTime", req.BeginTime).
  42 + WithKV("endTime", req.EndTime)
  43 +
  44 + total, dms, err = l.svcCtx.ArticleSecurityRepository.Find(l.ctx, conn, queryOptions)
  45 + list := make([]types.ArticleSecurityItem, 0)
  46 + for i := range dms {
  47 + list = append(list, NewTypesArticleSecurity(dms[i], nil))
  48 + }
  49 + resp = &types.ArticleSecuritySearchResponse{
  50 + List: list,
  51 + Total: total,
  52 + }
  53 + return
  54 +}
  55 +
  56 +func NewDomainArticleSecurity(item types.ArticleSecurityItem) *domain.ArticleSecurity {
  57 + return &domain.ArticleSecurity{}
  58 +}
  59 +
  60 +func NewTypesArticleSecurity(item *domain.ArticleSecurity, reviewer *domain.User) types.ArticleSecurityItem {
  61 + result := types.ArticleSecurityItem{
  62 + Id: item.Id,
  63 + Content: types.ContentDetailItem{
  64 + Id: item.ContentId,
  65 + Type: item.ContentType,
  66 + },
  67 + ContentKeyWords: strings.Join(item.ContentKeyWords, ","),
  68 + Label: item.Label,
  69 + Prob: item.Prob,
  70 + Suggest: describeSuggest(item.Suggest),
  71 + Author: item.AuthorName,
  72 + ReviewAt: item.CreatedAt,
  73 + ReviewStatus: item.ReviewStatus,
  74 + ReleaseAt: item.CreatedAt,
  75 + Reviewer: "",
  76 + }
  77 + if reviewer != nil {
  78 + result.Reviewer = reviewer.Name
  79 + }
  80 + for _, detail := range item.Detail.Detail {
  81 + if detail.Label.String() == "0" {
  82 + continue
  83 + }
  84 + result.CheckList = append(result.CheckList, types.CheckDetailItem{
  85 + Label: detail.Label.String(),
  86 + Prob: detail.Prob,
  87 + Suggest: describeSuggest(detail.Suggest),
  88 + })
  89 + }
  90 + return result
  91 +}
  92 +
  93 +func describeContentType(t int) string {
  94 + if t == domain.TypeArticle {
  95 + return "文本-帖子"
  96 + }
  97 + if t == domain.TypeComment {
  98 + return "文本-评论"
  99 + }
  100 + return ""
  101 +}
  102 +
  103 +func describeSuggest(s string) string {
  104 + if s == "risk" {
  105 + return "风险"
  106 + }
  107 + if s == "pass" {
  108 + return "通过"
  109 + }
  110 + if s == "review" {
  111 + return "人工审核"
  112 + }
  113 + return ""
  114 +}
@@ -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
@@ -94,6 +95,7 @@ func NewServiceContext(c config.Config) *ServiceContext { @@ -94,6 +95,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
94 ArticleAndTagRepository: repository.NewArticleAndTagRepository(cache.NewCachedRepository(mlCache)), 95 ArticleAndTagRepository: repository.NewArticleAndTagRepository(cache.NewCachedRepository(mlCache)),
95 ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)), 96 ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)),
96 ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)), 97 ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)),
  98 + ArticleSecurityRepository: repository.NewArticleSecurityRepository(cache.NewCachedRepository(mlCache)),
97 99
98 CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)), 100 CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)),
99 DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)), 101 DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)),
@@ -1849,3 +1849,62 @@ type CategoryOptionValue struct { @@ -1849,3 +1849,62 @@ type CategoryOptionValue struct {
1849 Label string `json:"label"` // 名称 1849 Label string `json:"label"` // 名称
1850 Value int64 `json:"value"` // 分类ID 1850 Value int64 `json:"value"` // 分类ID
1851 } 1851 }
  1852 +
  1853 +type ArticleSecurityGetRequest struct {
  1854 + Id int64 `path:"id"`
  1855 +}
  1856 +
  1857 +type ArticleSecurityGetResponse struct {
  1858 + ArticleSecurity ArticleSecurityItem `json:"item"`
  1859 +}
  1860 +
  1861 +type ArticleSecurityAuditRequest struct {
  1862 + Id int64 `json:"id"` //id
  1863 + Status int `json:"status"` // 1:成功 0:失败
  1864 +}
  1865 +
  1866 +type ArticleSecurityAuditResponse struct {
  1867 +}
  1868 +
  1869 +type ArticleSecuritySearchRequest struct {
  1870 + Page int `json:"page,optional"`
  1871 + Size int `json:"size,optional"`
  1872 + ReviewStatus int `json:"reviewStatus,optional"` // 审核结果 1:待审核 2:通过 3:拒绝
  1873 + Suggest string `json:"suggest"` // 建议 通过、风险、人工审核
  1874 + ContentType int `json:"contentType"` // 内容类型 (1:文章 2:评论)
  1875 + AuthorName string `json:"authorName"` // 作者名称
  1876 + BeginTime int64 `json:"beginTime"` // 开始时间
  1877 + EndTime int64 `json:"endTime"` // 结束时间
  1878 +}
  1879 +
  1880 +type ArticleSecuritySearchResponse struct {
  1881 + List []ArticleSecurityItem `json:"list"`
  1882 + Total int64 `json:"total"`
  1883 +}
  1884 +
  1885 +type ArticleSecurityItem struct {
  1886 + Id int64 `json:"id"` // 唯一标识
  1887 + ContentKeyWords string `json:"contentKeyWords"` // 内容关键字
  1888 + Content ContentDetailItem `json:"content"` // 内容详情
  1889 + Label string `json:"label"` // 风控标签
  1890 + Prob int `json:"prob"` // 分值
  1891 + Suggest string `json:"suggest"` // 建议 通过、风险、人工审核
  1892 + Author string `json:"author"` // 发布人
  1893 + ReleaseAt int64 `json:"releaseAt"` // 发布时间
  1894 + ReviewStatus int `json:"reviewStatus"` // 审核结果 1:待审核 2:通过 3:拒绝
  1895 + Reviewer string `json:"reviewer"` // 审核人
  1896 + ReviewAt int64 `json:"reviewAt"` // 审核时间(人工处置时间)
  1897 + CheckList []CheckDetailItem `json:"checkList"` // 检查列表
  1898 +}
  1899 +
  1900 +type CheckDetailItem struct {
  1901 + Label string `json:"label"` // 命中标签
  1902 + Prob uint `json:"prob"` // 置信度。0-100,越高代表越有可能属于当前返回的标签(label)
  1903 + Suggest string `json:"suggest"` // 建议
  1904 +}
  1905 +
  1906 +type ContentDetailItem struct {
  1907 + Id int64 `json:"id"` // 内容ID
  1908 + Type int `json:"type"` // 内容类型 (1:文章 2:评论)
  1909 + Text string `json:"text"` // 内容文本
  1910 +}
  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,9 +26,12 @@ func Migrate(db *gorm.DB) { @@ -26,9 +26,12 @@ 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.UserSubscribe{},  
30 - &models.MessageSubscribe{},  
31 - &models.UserWechat{}, 29 + //&models.UserSubscribe{},
  30 + //&models.MessageSubscribe{},
  31 + //&models.UserWechat{},
  32 + //&models.ArticleDraftOperation{},
  33 + //&models.ArticleCategory{},
  34 + &models.ArticleSecurity{},
32 } 35 }
33 36
34 db.AutoMigrate(modelsList...) 37 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 + CompanyId int64
  14 + ContentKeyWords []string `gorm:"type:jsonb;serializer:json"` // 内容关键字
  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 +}
@@ -437,6 +437,28 @@ func (repository *ArticleCommentRepository) CustomSearchBy(ctx context.Context, @@ -437,6 +437,28 @@ func (repository *ArticleCommentRepository) CustomSearchBy(ctx context.Context,
437 437
438 } 438 }
439 439
  440 +// CommentUserCount 统计评论人数
  441 +func (repository *ArticleCommentRepository) CommentUserCount(ctx context.Context, conn transaction.Conn, companyId int64, articleId int64) (int64, error) {
  442 + var (
  443 + err error
  444 + tx = conn.DB()
  445 + c int64
  446 + )
  447 + err = tx.Model(&models.ArticleComment{}).Where("company_id = ? and article_id = ?", companyId, articleId).Group("from_user_id").Count(&c).Error
  448 + return c, err
  449 +}
  450 +
  451 +// ReplyUserCount 统计回复人数
  452 +func (repository *ArticleCommentRepository) ReplyUserCount(ctx context.Context, conn transaction.Conn, companyId int64, commentId int64) (int64, error) {
  453 + var (
  454 + err error
  455 + tx = conn.DB()
  456 + c int64
  457 + )
  458 + err = tx.Model(&models.ArticleComment{}).Where("company_id = ? and pid = ?", companyId, commentId).Group("from_user_id").Count(&c).Error
  459 + return c, err
  460 +}
  461 +
440 func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository { 462 func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository {
441 return &ArticleCommentRepository{CachedRepository: cache} 463 return &ArticleCommentRepository{CachedRepository: cache}
442 } 464 }
  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["companyId"]; ok {
  125 + tx.Where("company_id = ?", v)
  126 + }
  127 + if v, ok := queryOptions["authorName"]; ok {
  128 + tx.Where("author_name like ? ", fmt.Sprintf("%%%v%%", v))
  129 + }
  130 + if v, ok := queryOptions["contentType"]; ok {
  131 + tx.Where("content_type = ? ", v)
  132 + }
  133 + if v, ok := queryOptions["reviewStatus"]; ok {
  134 + tx.Where("review_status = ? ", v)
  135 + }
  136 + if v, ok := queryOptions["suggest"]; ok {
  137 + tx.Where("suggest = ? ", v)
  138 + }
  139 + if v, ok := queryOptions["beginTime"]; ok {
  140 + tx.Where("created_at >= ?", v)
  141 + }
  142 + if v, ok := queryOptions["endTime"]; ok {
  143 + tx.Where("created_at < ?", v)
  144 + }
  145 +
  146 + if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
  147 + return dms, tx.Error
  148 + }
  149 + return dms, nil
  150 + }
  151 +
  152 + if _, err := repository.Query(queryFunc); err != nil {
  153 + return 0, nil, err
  154 + }
  155 +
  156 + for _, item := range ms {
  157 + if dm, err := repository.ModelToDomainModel(item); err != nil {
  158 + return 0, dms, err
  159 + } else {
  160 + dms = append(dms, dm)
  161 + }
  162 + }
  163 + return total, dms, nil
  164 +}
  165 +
  166 +func (repository *ArticleSecurityRepository) ModelToDomainModel(from *models.ArticleSecurity) (*domain.ArticleSecurity, error) {
  167 + to := &domain.ArticleSecurity{}
  168 + err := copier.Copy(to, from)
  169 + return to, err
  170 +}
  171 +
  172 +func (repository *ArticleSecurityRepository) DomainModelToModel(from *domain.ArticleSecurity) (*models.ArticleSecurity, error) {
  173 + to := &models.ArticleSecurity{}
  174 + err := copier.Copy(to, from)
  175 + return to, err
  176 +}
  177 +
  178 +func NewArticleSecurityRepository(cache *cache.CachedRepository) domain.ArticleSecurityRepository {
  179 + return &ArticleSecurityRepository{CachedRepository: cache}
  180 +}
@@ -95,6 +95,7 @@ type ArticleShow int @@ -95,6 +95,7 @@ type ArticleShow int
95 const ( 95 const (
96 ArticleShowEnable ArticleShow = 1 96 ArticleShowEnable ArticleShow = 1
97 ArticleShowDisable ArticleShow = 2 97 ArticleShowDisable ArticleShow = 2
  98 + ArticleShowIllegal ArticleShow = 3
98 ) 99 )
99 100
100 func (a ArticleShow) Named() string { 101 func (a ArticleShow) Named() string {
@@ -103,6 +104,8 @@ func (a ArticleShow) Named() string { @@ -103,6 +104,8 @@ func (a ArticleShow) Named() string {
103 return "显示" 104 return "显示"
104 case ArticleShowDisable: 105 case ArticleShowDisable:
105 return "隐藏" 106 return "隐藏"
  107 + case ArticleShowIllegal:
  108 + return "违规"
106 } 109 }
107 return "" 110 return ""
108 } 111 }
@@ -39,6 +39,7 @@ type CommentShow int @@ -39,6 +39,7 @@ type CommentShow int
39 const ( 39 const (
40 CommentShowEnable CommentShow = 1 40 CommentShowEnable CommentShow = 1
41 CommentShowDisable CommentShow = 2 41 CommentShowDisable CommentShow = 2
  42 + CommentShowIllegal CommentShow = 3
42 ) 43 )
43 44
44 func (show CommentShow) Named() string { 45 func (show CommentShow) Named() string {
@@ -47,6 +48,8 @@ func (show CommentShow) Named() string { @@ -47,6 +48,8 @@ func (show CommentShow) Named() string {
47 return "显示" 48 return "显示"
48 case CommentShowDisable: 49 case CommentShowDisable:
49 return "隐藏" 50 return "隐藏"
  51 + case CommentShowIllegal:
  52 + return "违规"
50 } 53 }
51 return "" 54 return ""
52 } 55 }
@@ -80,6 +83,10 @@ type ArticleCommentRepository interface { @@ -80,6 +83,10 @@ type ArticleCommentRepository interface {
80 // 特定的查询 83 // 特定的查询
81 CustomSearchBy(ctx context.Context, conn transaction.Conn, companyId int64, page int, size int, 84 CustomSearchBy(ctx context.Context, conn transaction.Conn, companyId int64, page int, size int,
82 topId int64, articleTitle string, contentLike string, fromUserId int64, show int, createdAtRange [2]int64) (int, []*ArticleCommentShow, error) 85 topId int64, articleTitle string, contentLike string, fromUserId int64, show int, createdAtRange [2]int64) (int, []*ArticleCommentShow, error)
  86 + // CommentUserCount 统计帖子评论人数
  87 + CommentUserCount(ctx context.Context, conn transaction.Conn, companyId int64, articleId int64) (int64, error)
  88 + // ReplyUserCount 统计评论回复人数
  89 + ReplyUserCount(ctx context.Context, conn transaction.Conn, companyId int64, commentId int64) (int64, error)
83 } 90 }
84 91
85 // 运营点数 填写的最大值 92 // 运营点数 填写的最大值
  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 + CompanyId int64
  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 +}
@@ -21,9 +21,10 @@ type MessageSystem struct { @@ -21,9 +21,10 @@ type MessageSystem struct {
21 type MsgSystemType int 21 type MsgSystemType int
22 22
23 const ( 23 const (
24 - MsgTypeNormal MsgSystemType = 1 //1业务正常通知  
25 - MsgTypeAbnormal MsgSystemType = 2 //2业务异常通知  
26 - MsgTypeDeleted MsgSystemType = 3 //3帖子删除通知 24 + MsgTypeNormal MsgSystemType = 1 //1 业务正常通知(帖子定性)
  25 + MsgTypeAbnormal MsgSystemType = 2 //2 业务异常通知(评论删除)
  26 + MsgTypeDeleted MsgSystemType = 3 //3 帖子删除通知(帖子删除)
  27 + MsgTypeIllegal MsgSystemType = 4 //4 内容违规
27 ) 28 )
28 29
29 type MessageSystemRepository interface { 30 type MessageSystemRepository interface {
@@ -63,3 +63,8 @@ CREATE TABLE `user_wechat` @@ -63,3 +63,8 @@ CREATE TABLE `user_wechat`
63 `id` int(0) NOT NULL COMMENT '唯一标识', 63 `id` int(0) NOT NULL COMMENT '唯一标识',
64 PRIMARY KEY (`id`) USING BTREE 64 PRIMARY KEY (`id`) USING BTREE
65 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 65 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  66 +
  67 +CREATE TABLE `article_security` (
  68 + `id` int(0) NOT NULL COMMENT '唯一标识',
  69 + PRIMARY KEY (`id`) USING BTREE
  70 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;