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
|
||
}
|