official.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "strings"
  6. "time"
  7. "go-common/app/admin/main/member/model"
  8. "go-common/app/service/main/member/model/block"
  9. spymodel "go-common/app/service/main/spy/model"
  10. "go-common/library/ecode"
  11. "go-common/library/log"
  12. "go-common/library/queue/databus/report"
  13. xtime "go-common/library/time"
  14. "github.com/pkg/errors"
  15. )
  16. const (
  17. _logActionAudit = "official_doc_audit"
  18. _logActionEdit = "official_doc_edit"
  19. _logActionEditName = "official_doc_edit_name"
  20. )
  21. func i64Toi8(in []int64) []int8 {
  22. out := make([]int8, 0, len(in))
  23. for _, i := range in {
  24. out = append(out, int8(i))
  25. }
  26. return out
  27. }
  28. func i8Toi64(in []int8) []int64 {
  29. out := make([]int64, 0, len(in))
  30. for _, i := range in {
  31. out = append(out, int64(i))
  32. }
  33. return out
  34. }
  35. func actOr(act ...string) string {
  36. return strings.Join(act, ",")
  37. }
  38. func (s *Service) officialName(ctx context.Context, ofs []*model.Official) {
  39. mids := make([]int64, 0, len(ofs))
  40. for _, o := range ofs {
  41. mids = append(mids, o.Mid)
  42. }
  43. ofds, err := s.dao.OfficialDocsByMids(ctx, mids)
  44. if err != nil {
  45. log.Error("Failed to s.dao.OfficialDocsByMids(%+v): %+v", mids, err)
  46. return
  47. }
  48. for _, o := range ofs {
  49. od, ok := ofds[o.Mid]
  50. if !ok {
  51. continue
  52. }
  53. o.Name = od.Name
  54. }
  55. }
  56. // Officials is.
  57. func (s *Service) Officials(ctx context.Context, arg *model.ArgOfficial) ([]*model.Official, int, error) {
  58. if len(arg.Role) == 0 {
  59. arg.Role = i8Toi64(model.AllRoles)
  60. }
  61. if arg.ETime == 0 {
  62. arg.ETime = xtime.Time(time.Now().Unix())
  63. }
  64. ofs, total, err := s.dao.Officials(ctx, arg.Mid, i64Toi8(arg.Role), arg.STime.Time(), arg.ETime.Time(), arg.Pn, arg.Ps)
  65. if err != nil {
  66. return nil, 0, err
  67. }
  68. // 需要展示昵称
  69. s.officialName(ctx, ofs)
  70. return ofs, total, err
  71. }
  72. func (s *Service) blockResult(ctx context.Context, mid int64) (*model.BlockResult, error) {
  73. info, err := s.memberRPC.BlockInfo(ctx, &block.RPCArgInfo{MID: mid})
  74. if err != nil {
  75. err = errors.Wrapf(err, "%v", mid)
  76. return nil, err
  77. }
  78. block := &model.BlockResult{
  79. MID: info.MID,
  80. BlockStatus: info.BlockStatus,
  81. StartTime: info.StartTime,
  82. EndTime: info.EndTime,
  83. }
  84. return block, nil
  85. }
  86. // OfficialDoc is.
  87. 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) {
  88. if od, err = s.dao.OfficialDoc(ctx, mid); err != nil {
  89. return
  90. }
  91. if od == nil {
  92. od = &model.OfficialDoc{
  93. Mid: mid,
  94. OfficialExtra: &model.OfficialExtra{},
  95. }
  96. }
  97. logs, err = s.dao.SearchLog(ctx, 0, mid, "", actOr(_logActionAudit, _logActionEdit))
  98. if err != nil {
  99. log.Error("Failed to s.dao.SearchLog(%+v): %+v", mid, err)
  100. return
  101. }
  102. block, err = s.blockResult(ctx, mid)
  103. if err != nil {
  104. log.Error("Failed to s.blockResult(%+v): %+v", mid, err)
  105. return
  106. }
  107. arg := &spymodel.ArgStat{Mid: mid}
  108. spys, err = s.spyRPC.StatByID(ctx, arg)
  109. if err != nil {
  110. log.Error("Failed to s.spyRPC.StatByID: mid(%d): %+v", od.Mid, err)
  111. return
  112. }
  113. realname, err = s.officialRealname(ctx, mid)
  114. if err != nil {
  115. log.Error("Failed to get official realname with mid: %d: %+v", od.Mid, err)
  116. return
  117. }
  118. // 查询使用相同社会信用代码的mid
  119. sameCreditCodeMids = make([]int64, 0)
  120. if od.OfficialExtra.CreditCode != "" {
  121. func() {
  122. addits, err := s.OfficialDocAddits(ctx, "credit_code", od.OfficialExtra.CreditCode)
  123. if err != nil {
  124. log.Error("Failed to get official addit with mid: %d: %+v", od.Mid, err)
  125. return
  126. }
  127. for _, addit := range addits {
  128. if addit.Mid != od.Mid {
  129. sameCreditCodeMids = append(sameCreditCodeMids, addit.Mid)
  130. }
  131. }
  132. }()
  133. }
  134. return
  135. }
  136. func (s *Service) officialRealname(ctx context.Context, mid int64) (*model.Realname, error) {
  137. realname := &model.Realname{
  138. State: model.RealnameApplyStateNone,
  139. }
  140. dr, err := s.dao.RealnameInfo(ctx, mid)
  141. if err != nil {
  142. log.Error("Failed to get realname info with mid: %d: %+v", mid, err)
  143. return realname, nil
  144. }
  145. if dr != nil {
  146. realname.ParseInfo(dr)
  147. }
  148. imagesByMain := func() {
  149. apply, err := s.dao.LastPassedRealnameMainApply(ctx, mid)
  150. if err != nil {
  151. log.Error("Failed to get last passed realname main apply with mid: %d: %+v", mid, err)
  152. return
  153. }
  154. images, err := s.dao.RealnameApplyIMG(ctx, []int64{apply.HandIMG, apply.FrontIMG, apply.BackIMG})
  155. if err != nil {
  156. log.Error("Failed to get realname apply image by apply: %+v: %+v", apply, err)
  157. return
  158. }
  159. for _, image := range images {
  160. realname.ParseDBApplyIMG(image.IMGData)
  161. }
  162. }
  163. imagesByAlipay := func() {
  164. apply, err := s.dao.LastPassedRealnameAlipayApply(ctx, mid)
  165. if err != nil {
  166. log.Error("Failed to get last passed realname alipay apply with mid: %d: %+v", mid, err)
  167. return
  168. }
  169. realname.ParseDBApplyIMG(apply.IMG)
  170. }
  171. switch dr.Channel {
  172. case model.ChannelMain.DBChannel():
  173. imagesByMain()
  174. case model.ChannelAlipay.DBChannel():
  175. imagesByAlipay()
  176. default:
  177. log.Error("Failed to get realname apply images by realname info: %+v", dr)
  178. }
  179. return realname, nil
  180. }
  181. // OfficialDocs is.
  182. func (s *Service) OfficialDocs(ctx context.Context, arg *model.ArgOfficialDoc) ([]*model.OfficialDoc, int, error) {
  183. if len(arg.Role) == 0 {
  184. arg.Role = i8Toi64(model.AllRoles)
  185. }
  186. if len(arg.State) == 0 {
  187. arg.State = i8Toi64(model.AllStates)
  188. }
  189. if arg.ETime == 0 {
  190. arg.ETime = xtime.Time(time.Now().Unix())
  191. }
  192. 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)
  193. }
  194. // OfficialDocAudit is.
  195. func (s *Service) OfficialDocAudit(ctx context.Context, arg *model.ArgOfficialAudit) (err error) {
  196. od, err := s.dao.OfficialDoc(ctx, arg.Mid)
  197. if err != nil {
  198. return
  199. }
  200. if arg.State == model.OfficialStatePass {
  201. if err = s.updateUname(ctx, od.Mid, od.Name, arg.UID, arg.Uname); err != nil {
  202. log.Error("Failed to update uname: mid(%d), name(%s): %+v", od.Mid, od.Name, err)
  203. return
  204. }
  205. }
  206. if err = s.dao.OfficialDocAudit(ctx, arg.Mid, arg.State, arg.Uname, arg.IsInternal, arg.Reason); err != nil {
  207. return
  208. }
  209. od, err = s.dao.OfficialDoc(ctx, arg.Mid)
  210. if err != nil {
  211. return
  212. }
  213. role := int8(model.OfficialRoleUnauth)
  214. cnt := `对不起,您的官方认证申请未通过,未通过原因:"` + arg.Reason + `,重新申请点#{这里}{"https://account.bilibili.com/account/official/home"}`
  215. if arg.State == model.OfficialStatePass {
  216. role = od.Role
  217. cnt = "恭喜,您的官方认证申请已经通过啦!o(* ̄▽ ̄*)o"
  218. }
  219. if _, err = s.dao.OfficialEdit(ctx, arg.Mid, role, od.Title, od.Desc); err != nil {
  220. return
  221. }
  222. if err = s.dao.Message(ctx, "官方认证审核通知", cnt, []int64{arg.Mid}); err != nil {
  223. log.Error("Failed to send message: %+v", err)
  224. err = nil
  225. }
  226. report.Manager(&report.ManagerInfo{
  227. Uname: arg.Uname,
  228. UID: arg.UID,
  229. Business: model.ManagerLogID,
  230. Type: 0,
  231. Oid: arg.Mid,
  232. Action: _logActionAudit,
  233. Ctime: time.Now(),
  234. // extra
  235. Index: []interface{}{arg.State, int64(od.CTime), od.Role, od.Name, od.Title, od.Desc},
  236. Content: map[string]interface{}{
  237. "reason": arg.Reason,
  238. "name": od.Name,
  239. "extra": od.Extra,
  240. "role": od.Role,
  241. "title": od.Title,
  242. "desc": od.Desc,
  243. "state": arg.State,
  244. "doc_ctime": int64(od.CTime),
  245. },
  246. })
  247. return
  248. }
  249. // OfficialDocEdit is.
  250. func (s *Service) OfficialDocEdit(ctx context.Context, arg *model.ArgOfficialEdit) (err error) {
  251. od, _ := s.dao.OfficialDoc(ctx, arg.Mid)
  252. if od == nil {
  253. od = &model.OfficialDoc{
  254. Mid: arg.Mid,
  255. Role: arg.Role,
  256. OfficialExtra: &model.OfficialExtra{},
  257. }
  258. }
  259. od.State = int8(model.OfficialStatePass)
  260. if arg.Role == model.OfficialRoleUnauth {
  261. od.State = int8(model.OfficialStateNoPass)
  262. }
  263. od.Name = arg.Name
  264. od.Uname = arg.Uname
  265. od.Telephone = arg.Telephone
  266. od.Email = arg.Email
  267. od.Address = arg.Address
  268. od.Supplement = arg.Supplement
  269. od.Company = arg.Company
  270. od.Operator = arg.Operator
  271. od.CreditCode = arg.CreditCode
  272. od.Organization = arg.Organization
  273. od.OrganizationType = arg.OrganizationType
  274. od.BusinessLicense = arg.BusinessLicense
  275. od.BusinessLevel = arg.BusinessLevel
  276. od.BusinessScale = arg.BusinessScale
  277. od.BusinessAuth = arg.BusinessAuth
  278. od.OfficalSite = arg.OfficalSite
  279. od.RegisteredCapital = arg.RegisteredCapital
  280. extra, err := json.Marshal(od.OfficialExtra)
  281. if err != nil {
  282. err = errors.Wrap(err, "official doc edit")
  283. return
  284. }
  285. if err = s.updateUname(ctx, arg.Mid, arg.Name, arg.UID, arg.Uname); err != nil {
  286. log.Error("Failed to update uname: mid(%d), name(%s): %+v", arg.Mid, arg.Name, err)
  287. err = ecode.MemberNameFormatErr
  288. return
  289. }
  290. 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 {
  291. log.Error("Failed to update official doc: %+v", err)
  292. err = ecode.RequestErr
  293. return
  294. }
  295. if _, err = s.dao.OfficialEdit(ctx, arg.Mid, arg.Role, arg.Title, arg.Desc); err != nil {
  296. return
  297. }
  298. report.Manager(&report.ManagerInfo{
  299. Uname: arg.Uname,
  300. UID: arg.UID,
  301. Business: model.ManagerLogID,
  302. Type: 0,
  303. Oid: arg.Mid,
  304. Action: _logActionEdit,
  305. Ctime: time.Now(),
  306. // extra
  307. Index: []interface{}{od.State, int64(od.CTime), arg.Role, arg.Name, arg.Title, arg.Desc},
  308. Content: map[string]interface{}{
  309. "extra": string(extra),
  310. "name": arg.Name,
  311. "role": arg.Role,
  312. "title": arg.Title,
  313. "desc": arg.Desc,
  314. "state": od.State,
  315. "doc_ctime": int64(od.CTime),
  316. },
  317. })
  318. if arg.SendMessage {
  319. if merr := s.dao.Message(ctx, arg.MessageTitle, arg.MessageContent, []int64{arg.Mid}); merr != nil {
  320. log.Error("Failed to send message: %+v", merr)
  321. }
  322. }
  323. return
  324. }
  325. // OfficialDocSubmit is.
  326. func (s *Service) OfficialDocSubmit(ctx context.Context, arg *model.ArgOfficialSubmit) (err error) {
  327. od := &model.OfficialDoc{
  328. Mid: arg.Mid,
  329. Name: arg.Name,
  330. State: int8(model.OfficialStateWait),
  331. Role: arg.Role,
  332. Title: arg.Title,
  333. Desc: arg.Desc,
  334. Uname: arg.Uname,
  335. IsInternal: arg.IsInternal,
  336. SubmitSource: arg.SubmitSource,
  337. OfficialExtra: &model.OfficialExtra{
  338. Realname: arg.Realname,
  339. Operator: arg.Operator,
  340. Telephone: arg.Telephone,
  341. Email: arg.Email,
  342. Address: arg.Address,
  343. Company: arg.Company,
  344. CreditCode: arg.CreditCode,
  345. Organization: arg.Organization,
  346. OrganizationType: arg.OrganizationType,
  347. BusinessLicense: arg.BusinessLicense,
  348. BusinessScale: arg.BusinessScale,
  349. BusinessLevel: arg.BusinessLevel,
  350. BusinessAuth: arg.BusinessAuth,
  351. Supplement: arg.Supplement,
  352. Professional: arg.Professional,
  353. Identification: arg.Identification,
  354. OfficalSite: arg.OfficalSite,
  355. RegisteredCapital: arg.RegisteredCapital,
  356. },
  357. }
  358. if !od.Validate() {
  359. log.Error("Failed to validate official doc: %+v", od)
  360. err = ecode.RequestErr
  361. return
  362. }
  363. 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)
  364. }
  365. func (s *Service) updateUname(ctx context.Context, mid int64, name string, adminID int64, adminName string) error {
  366. b, err := s.dao.Base(ctx, mid)
  367. if err != nil {
  368. return err
  369. }
  370. if b.Name == name {
  371. return nil
  372. }
  373. if err := s.dao.UpdateUname(ctx, mid, name); err != nil {
  374. log.Error("Failed to update uname to aso: mid(%d), name(%s): %+v", mid, name, err)
  375. return err
  376. }
  377. if err := s.dao.UpName(ctx, mid, name); err != nil {
  378. log.Error("Failed to update uname to member: mid(%d), name(%s): %+v", mid, name, err)
  379. return err
  380. }
  381. report.Manager(&report.ManagerInfo{
  382. Uname: adminName,
  383. UID: adminID,
  384. Business: model.ManagerLogID,
  385. Type: 0,
  386. Oid: mid,
  387. Action: _logActionEditName,
  388. Ctime: time.Now(),
  389. // extra
  390. Index: []interface{}{0, 0, 0, "", "", ""},
  391. Content: map[string]interface{}{
  392. "old_name": b.Name,
  393. "new_name": name,
  394. },
  395. })
  396. return nil
  397. }
  398. // OfficialDocAddits find mids by property and value
  399. func (s *Service) OfficialDocAddits(ctx context.Context, property string, vstring string) ([]*model.OfficialDocAddit, error) {
  400. if property == "" {
  401. return nil, ecode.RequestErr
  402. }
  403. addits, err := s.dao.OfficialDocAddits(ctx, property, vstring)
  404. return addits, err
  405. }