437 lines
12 KiB
Go
437 lines
12 KiB
Go
|
package service
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"encoding/json"
|
|||
|
"strings"
|
|||
|
"time"
|
|||
|
|
|||
|
"go-common/app/admin/main/member/model"
|
|||
|
"go-common/app/service/main/member/model/block"
|
|||
|
spymodel "go-common/app/service/main/spy/model"
|
|||
|
"go-common/library/ecode"
|
|||
|
"go-common/library/log"
|
|||
|
"go-common/library/queue/databus/report"
|
|||
|
xtime "go-common/library/time"
|
|||
|
|
|||
|
"github.com/pkg/errors"
|
|||
|
)
|
|||
|
|
|||
|
const (
|
|||
|
_logActionAudit = "official_doc_audit"
|
|||
|
_logActionEdit = "official_doc_edit"
|
|||
|
_logActionEditName = "official_doc_edit_name"
|
|||
|
)
|
|||
|
|
|||
|
func i64Toi8(in []int64) []int8 {
|
|||
|
out := make([]int8, 0, len(in))
|
|||
|
for _, i := range in {
|
|||
|
out = append(out, int8(i))
|
|||
|
}
|
|||
|
return out
|
|||
|
}
|
|||
|
|
|||
|
func i8Toi64(in []int8) []int64 {
|
|||
|
out := make([]int64, 0, len(in))
|
|||
|
for _, i := range in {
|
|||
|
out = append(out, int64(i))
|
|||
|
}
|
|||
|
return out
|
|||
|
}
|
|||
|
|
|||
|
func actOr(act ...string) string {
|
|||
|
return strings.Join(act, ",")
|
|||
|
}
|
|||
|
|
|||
|
func (s *Service) officialName(ctx context.Context, ofs []*model.Official) {
|
|||
|
mids := make([]int64, 0, len(ofs))
|
|||
|
for _, o := range ofs {
|
|||
|
mids = append(mids, o.Mid)
|
|||
|
}
|
|||
|
ofds, err := s.dao.OfficialDocsByMids(ctx, mids)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to s.dao.OfficialDocsByMids(%+v): %+v", mids, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, o := range ofs {
|
|||
|
od, ok := ofds[o.Mid]
|
|||
|
if !ok {
|
|||
|
continue
|
|||
|
}
|
|||
|
o.Name = od.Name
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Officials is.
|
|||
|
func (s *Service) Officials(ctx context.Context, arg *model.ArgOfficial) ([]*model.Official, int, error) {
|
|||
|
if len(arg.Role) == 0 {
|
|||
|
arg.Role = i8Toi64(model.AllRoles)
|
|||
|
}
|
|||
|
if arg.ETime == 0 {
|
|||
|
arg.ETime = xtime.Time(time.Now().Unix())
|
|||
|
}
|
|||
|
ofs, total, err := s.dao.Officials(ctx, arg.Mid, i64Toi8(arg.Role), arg.STime.Time(), arg.ETime.Time(), arg.Pn, arg.Ps)
|
|||
|
if err != nil {
|
|||
|
return nil, 0, err
|
|||
|
}
|
|||
|
// 需要展示昵称
|
|||
|
s.officialName(ctx, ofs)
|
|||
|
return ofs, total, err
|
|||
|
}
|
|||
|
|
|||
|
func (s *Service) blockResult(ctx context.Context, mid int64) (*model.BlockResult, error) {
|
|||
|
info, err := s.memberRPC.BlockInfo(ctx, &block.RPCArgInfo{MID: mid})
|
|||
|
if err != nil {
|
|||
|
err = errors.Wrapf(err, "%v", mid)
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
block := &model.BlockResult{
|
|||
|
MID: info.MID,
|
|||
|
BlockStatus: info.BlockStatus,
|
|||
|
StartTime: info.StartTime,
|
|||
|
EndTime: info.EndTime,
|
|||
|
}
|
|||
|
return block, nil
|
|||
|
}
|
|||
|
|
|||
|
// OfficialDoc is.
|
|||
|
func (s *Service) OfficialDoc(ctx context.Context, mid int64) (od *model.OfficialDoc, logs *model.SearchLogResult, block *model.BlockResult, spys []*spymodel.Statistics, realname *model.Realname, sameCreditCodeMids []int64, err error) {
|
|||
|
if od, err = s.dao.OfficialDoc(ctx, mid); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if od == nil {
|
|||
|
od = &model.OfficialDoc{
|
|||
|
Mid: mid,
|
|||
|
OfficialExtra: &model.OfficialExtra{},
|
|||
|
}
|
|||
|
}
|
|||
|
logs, err = s.dao.SearchLog(ctx, 0, mid, "", actOr(_logActionAudit, _logActionEdit))
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to s.dao.SearchLog(%+v): %+v", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
block, err = s.blockResult(ctx, mid)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to s.blockResult(%+v): %+v", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
arg := &spymodel.ArgStat{Mid: mid}
|
|||
|
spys, err = s.spyRPC.StatByID(ctx, arg)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to s.spyRPC.StatByID: mid(%d): %+v", od.Mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
realname, err = s.officialRealname(ctx, mid)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get official realname with mid: %d: %+v", od.Mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 查询使用相同社会信用代码的mid
|
|||
|
sameCreditCodeMids = make([]int64, 0)
|
|||
|
if od.OfficialExtra.CreditCode != "" {
|
|||
|
func() {
|
|||
|
addits, err := s.OfficialDocAddits(ctx, "credit_code", od.OfficialExtra.CreditCode)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get official addit with mid: %d: %+v", od.Mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
for _, addit := range addits {
|
|||
|
if addit.Mid != od.Mid {
|
|||
|
sameCreditCodeMids = append(sameCreditCodeMids, addit.Mid)
|
|||
|
}
|
|||
|
}
|
|||
|
}()
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
func (s *Service) officialRealname(ctx context.Context, mid int64) (*model.Realname, error) {
|
|||
|
realname := &model.Realname{
|
|||
|
State: model.RealnameApplyStateNone,
|
|||
|
}
|
|||
|
dr, err := s.dao.RealnameInfo(ctx, mid)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get realname info with mid: %d: %+v", mid, err)
|
|||
|
return realname, nil
|
|||
|
}
|
|||
|
if dr != nil {
|
|||
|
realname.ParseInfo(dr)
|
|||
|
}
|
|||
|
|
|||
|
imagesByMain := func() {
|
|||
|
apply, err := s.dao.LastPassedRealnameMainApply(ctx, mid)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get last passed realname main apply with mid: %d: %+v", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
images, err := s.dao.RealnameApplyIMG(ctx, []int64{apply.HandIMG, apply.FrontIMG, apply.BackIMG})
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get realname apply image by apply: %+v: %+v", apply, err)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
for _, image := range images {
|
|||
|
realname.ParseDBApplyIMG(image.IMGData)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
imagesByAlipay := func() {
|
|||
|
apply, err := s.dao.LastPassedRealnameAlipayApply(ctx, mid)
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to get last passed realname alipay apply with mid: %d: %+v", mid, err)
|
|||
|
return
|
|||
|
}
|
|||
|
realname.ParseDBApplyIMG(apply.IMG)
|
|||
|
}
|
|||
|
|
|||
|
switch dr.Channel {
|
|||
|
case model.ChannelMain.DBChannel():
|
|||
|
imagesByMain()
|
|||
|
case model.ChannelAlipay.DBChannel():
|
|||
|
imagesByAlipay()
|
|||
|
default:
|
|||
|
log.Error("Failed to get realname apply images by realname info: %+v", dr)
|
|||
|
}
|
|||
|
|
|||
|
return realname, nil
|
|||
|
}
|
|||
|
|
|||
|
// OfficialDocs is.
|
|||
|
func (s *Service) OfficialDocs(ctx context.Context, arg *model.ArgOfficialDoc) ([]*model.OfficialDoc, int, error) {
|
|||
|
if len(arg.Role) == 0 {
|
|||
|
arg.Role = i8Toi64(model.AllRoles)
|
|||
|
}
|
|||
|
if len(arg.State) == 0 {
|
|||
|
arg.State = i8Toi64(model.AllStates)
|
|||
|
}
|
|||
|
if arg.ETime == 0 {
|
|||
|
arg.ETime = xtime.Time(time.Now().Unix())
|
|||
|
}
|
|||
|
return s.dao.OfficialDocs(ctx, arg.Mid, i64Toi8(arg.Role), i64Toi8(arg.State), arg.Uname, arg.STime.Time(), arg.ETime.Time(), arg.Pn, arg.Ps)
|
|||
|
}
|
|||
|
|
|||
|
// OfficialDocAudit is.
|
|||
|
func (s *Service) OfficialDocAudit(ctx context.Context, arg *model.ArgOfficialAudit) (err error) {
|
|||
|
od, err := s.dao.OfficialDoc(ctx, arg.Mid)
|
|||
|
if err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if arg.State == model.OfficialStatePass {
|
|||
|
if err = s.updateUname(ctx, od.Mid, od.Name, arg.UID, arg.Uname); err != nil {
|
|||
|
log.Error("Failed to update uname: mid(%d), name(%s): %+v", od.Mid, od.Name, err)
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if err = s.dao.OfficialDocAudit(ctx, arg.Mid, arg.State, arg.Uname, arg.IsInternal, arg.Reason); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
od, err = s.dao.OfficialDoc(ctx, arg.Mid)
|
|||
|
if err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
role := int8(model.OfficialRoleUnauth)
|
|||
|
cnt := `对不起,您的官方认证申请未通过,未通过原因:"` + arg.Reason + `,重新申请点#{这里}{"https://account.bilibili.com/account/official/home"}`
|
|||
|
if arg.State == model.OfficialStatePass {
|
|||
|
role = od.Role
|
|||
|
cnt = "恭喜,您的官方认证申请已经通过啦!o(* ̄▽ ̄*)o"
|
|||
|
}
|
|||
|
if _, err = s.dao.OfficialEdit(ctx, arg.Mid, role, od.Title, od.Desc); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if err = s.dao.Message(ctx, "官方认证审核通知", cnt, []int64{arg.Mid}); err != nil {
|
|||
|
log.Error("Failed to send message: %+v", err)
|
|||
|
err = nil
|
|||
|
}
|
|||
|
report.Manager(&report.ManagerInfo{
|
|||
|
Uname: arg.Uname,
|
|||
|
UID: arg.UID,
|
|||
|
Business: model.ManagerLogID,
|
|||
|
Type: 0,
|
|||
|
Oid: arg.Mid,
|
|||
|
Action: _logActionAudit,
|
|||
|
Ctime: time.Now(),
|
|||
|
// extra
|
|||
|
Index: []interface{}{arg.State, int64(od.CTime), od.Role, od.Name, od.Title, od.Desc},
|
|||
|
Content: map[string]interface{}{
|
|||
|
"reason": arg.Reason,
|
|||
|
"name": od.Name,
|
|||
|
"extra": od.Extra,
|
|||
|
"role": od.Role,
|
|||
|
"title": od.Title,
|
|||
|
"desc": od.Desc,
|
|||
|
"state": arg.State,
|
|||
|
"doc_ctime": int64(od.CTime),
|
|||
|
},
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// OfficialDocEdit is.
|
|||
|
func (s *Service) OfficialDocEdit(ctx context.Context, arg *model.ArgOfficialEdit) (err error) {
|
|||
|
od, _ := s.dao.OfficialDoc(ctx, arg.Mid)
|
|||
|
if od == nil {
|
|||
|
od = &model.OfficialDoc{
|
|||
|
Mid: arg.Mid,
|
|||
|
Role: arg.Role,
|
|||
|
OfficialExtra: &model.OfficialExtra{},
|
|||
|
}
|
|||
|
}
|
|||
|
od.State = int8(model.OfficialStatePass)
|
|||
|
if arg.Role == model.OfficialRoleUnauth {
|
|||
|
od.State = int8(model.OfficialStateNoPass)
|
|||
|
}
|
|||
|
od.Name = arg.Name
|
|||
|
od.Uname = arg.Uname
|
|||
|
od.Telephone = arg.Telephone
|
|||
|
od.Email = arg.Email
|
|||
|
od.Address = arg.Address
|
|||
|
od.Supplement = arg.Supplement
|
|||
|
od.Company = arg.Company
|
|||
|
od.Operator = arg.Operator
|
|||
|
od.CreditCode = arg.CreditCode
|
|||
|
od.Organization = arg.Organization
|
|||
|
od.OrganizationType = arg.OrganizationType
|
|||
|
od.BusinessLicense = arg.BusinessLicense
|
|||
|
od.BusinessLevel = arg.BusinessLevel
|
|||
|
od.BusinessScale = arg.BusinessScale
|
|||
|
od.BusinessAuth = arg.BusinessAuth
|
|||
|
od.OfficalSite = arg.OfficalSite
|
|||
|
od.RegisteredCapital = arg.RegisteredCapital
|
|||
|
extra, err := json.Marshal(od.OfficialExtra)
|
|||
|
if err != nil {
|
|||
|
err = errors.Wrap(err, "official doc edit")
|
|||
|
return
|
|||
|
}
|
|||
|
if err = s.updateUname(ctx, arg.Mid, arg.Name, arg.UID, arg.Uname); err != nil {
|
|||
|
log.Error("Failed to update uname: mid(%d), name(%s): %+v", arg.Mid, arg.Name, err)
|
|||
|
err = ecode.MemberNameFormatErr
|
|||
|
return
|
|||
|
}
|
|||
|
if err = s.dao.OfficialDocEdit(ctx, arg.Mid, arg.Name, arg.Role, od.State, arg.Title, arg.Desc, string(extra), arg.Uname, arg.IsInternal); err != nil {
|
|||
|
log.Error("Failed to update official doc: %+v", err)
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
if _, err = s.dao.OfficialEdit(ctx, arg.Mid, arg.Role, arg.Title, arg.Desc); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
report.Manager(&report.ManagerInfo{
|
|||
|
Uname: arg.Uname,
|
|||
|
UID: arg.UID,
|
|||
|
Business: model.ManagerLogID,
|
|||
|
Type: 0,
|
|||
|
Oid: arg.Mid,
|
|||
|
Action: _logActionEdit,
|
|||
|
Ctime: time.Now(),
|
|||
|
// extra
|
|||
|
Index: []interface{}{od.State, int64(od.CTime), arg.Role, arg.Name, arg.Title, arg.Desc},
|
|||
|
Content: map[string]interface{}{
|
|||
|
"extra": string(extra),
|
|||
|
"name": arg.Name,
|
|||
|
"role": arg.Role,
|
|||
|
"title": arg.Title,
|
|||
|
"desc": arg.Desc,
|
|||
|
"state": od.State,
|
|||
|
"doc_ctime": int64(od.CTime),
|
|||
|
},
|
|||
|
})
|
|||
|
if arg.SendMessage {
|
|||
|
if merr := s.dao.Message(ctx, arg.MessageTitle, arg.MessageContent, []int64{arg.Mid}); merr != nil {
|
|||
|
log.Error("Failed to send message: %+v", merr)
|
|||
|
}
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// OfficialDocSubmit is.
|
|||
|
func (s *Service) OfficialDocSubmit(ctx context.Context, arg *model.ArgOfficialSubmit) (err error) {
|
|||
|
od := &model.OfficialDoc{
|
|||
|
Mid: arg.Mid,
|
|||
|
Name: arg.Name,
|
|||
|
State: int8(model.OfficialStateWait),
|
|||
|
Role: arg.Role,
|
|||
|
Title: arg.Title,
|
|||
|
Desc: arg.Desc,
|
|||
|
|
|||
|
Uname: arg.Uname,
|
|||
|
IsInternal: arg.IsInternal,
|
|||
|
SubmitSource: arg.SubmitSource,
|
|||
|
|
|||
|
OfficialExtra: &model.OfficialExtra{
|
|||
|
Realname: arg.Realname,
|
|||
|
Operator: arg.Operator,
|
|||
|
Telephone: arg.Telephone,
|
|||
|
Email: arg.Email,
|
|||
|
Address: arg.Address,
|
|||
|
Company: arg.Company,
|
|||
|
CreditCode: arg.CreditCode,
|
|||
|
Organization: arg.Organization,
|
|||
|
OrganizationType: arg.OrganizationType,
|
|||
|
BusinessLicense: arg.BusinessLicense,
|
|||
|
BusinessScale: arg.BusinessScale,
|
|||
|
BusinessLevel: arg.BusinessLevel,
|
|||
|
BusinessAuth: arg.BusinessAuth,
|
|||
|
Supplement: arg.Supplement,
|
|||
|
Professional: arg.Professional,
|
|||
|
Identification: arg.Identification,
|
|||
|
OfficalSite: arg.OfficalSite,
|
|||
|
RegisteredCapital: arg.RegisteredCapital,
|
|||
|
},
|
|||
|
}
|
|||
|
if !od.Validate() {
|
|||
|
log.Error("Failed to validate official doc: %+v", od)
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
return s.dao.OfficialDocSubmit(ctx, od.Mid, od.Name, od.Role, int8(model.OfficialStateWait), od.Title, od.Desc, od.OfficialExtra.String(), od.Uname, od.IsInternal, od.SubmitSource)
|
|||
|
}
|
|||
|
|
|||
|
func (s *Service) updateUname(ctx context.Context, mid int64, name string, adminID int64, adminName string) error {
|
|||
|
b, err := s.dao.Base(ctx, mid)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
if b.Name == name {
|
|||
|
return nil
|
|||
|
}
|
|||
|
if err := s.dao.UpdateUname(ctx, mid, name); err != nil {
|
|||
|
log.Error("Failed to update uname to aso: mid(%d), name(%s): %+v", mid, name, err)
|
|||
|
return err
|
|||
|
}
|
|||
|
if err := s.dao.UpName(ctx, mid, name); err != nil {
|
|||
|
log.Error("Failed to update uname to member: mid(%d), name(%s): %+v", mid, name, err)
|
|||
|
return err
|
|||
|
}
|
|||
|
report.Manager(&report.ManagerInfo{
|
|||
|
Uname: adminName,
|
|||
|
UID: adminID,
|
|||
|
Business: model.ManagerLogID,
|
|||
|
Type: 0,
|
|||
|
Oid: mid,
|
|||
|
Action: _logActionEditName,
|
|||
|
Ctime: time.Now(),
|
|||
|
// extra
|
|||
|
Index: []interface{}{0, 0, 0, "", "", ""},
|
|||
|
Content: map[string]interface{}{
|
|||
|
"old_name": b.Name,
|
|||
|
"new_name": name,
|
|||
|
},
|
|||
|
})
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
// OfficialDocAddits find mids by property and value
|
|||
|
func (s *Service) OfficialDocAddits(ctx context.Context, property string, vstring string) ([]*model.OfficialDocAddit, error) {
|
|||
|
if property == "" {
|
|||
|
return nil, ecode.RequestErr
|
|||
|
}
|
|||
|
addits, err := s.dao.OfficialDocAddits(ctx, property, vstring)
|
|||
|
return addits, err
|
|||
|
}
|