358 lines
7.7 KiB
Go
358 lines
7.7 KiB
Go
|
package http
|
|||
|
|
|||
|
import (
|
|||
|
"bytes"
|
|||
|
"encoding/csv"
|
|||
|
"fmt"
|
|||
|
"io/ioutil"
|
|||
|
"net/http"
|
|||
|
"strconv"
|
|||
|
"time"
|
|||
|
|
|||
|
"go-common/app/admin/main/member/model"
|
|||
|
"go-common/library/ecode"
|
|||
|
"go-common/library/log"
|
|||
|
bm "go-common/library/net/http/blademaster"
|
|||
|
|
|||
|
"github.com/pkg/errors"
|
|||
|
)
|
|||
|
|
|||
|
func realnameList(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameList{}
|
|||
|
list []*model.RespRealnameApply
|
|||
|
total int
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if arg.PN <= 0 {
|
|||
|
arg.PN = 1
|
|||
|
}
|
|||
|
if arg.PS <= 0 || arg.PS > 100 {
|
|||
|
arg.PS = 10
|
|||
|
}
|
|||
|
// 没有指定实名认证申请状态State,默认查询所有
|
|||
|
if arg.State == "" {
|
|||
|
arg.State = model.RealnameApplyStateAll
|
|||
|
}
|
|||
|
// 如果没有使用 mid || card 则取默认7天前作为 TSFrom
|
|||
|
if arg.MID == 0 && arg.Card == "" {
|
|||
|
if arg.TSFrom <= 0 {
|
|||
|
arg.TSFrom = time.Now().Add(-time.Hour * 24 * 7).Unix()
|
|||
|
}
|
|||
|
}
|
|||
|
// 如果使用 mid 或 card 进行查询,则查询所有时间段对应的数据
|
|||
|
if arg.MID != 0 || arg.Card != "" {
|
|||
|
arg.TSFrom = 0
|
|||
|
arg.TSTo = 0
|
|||
|
}
|
|||
|
|
|||
|
if list, total, err = svc.RealnameList(ctx, arg); err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
res := map[string]interface{}{
|
|||
|
"list": list,
|
|||
|
"page": map[string]int{
|
|||
|
"num": arg.PN,
|
|||
|
"size": arg.PS,
|
|||
|
"total": total,
|
|||
|
},
|
|||
|
}
|
|||
|
ctx.JSON(res, nil)
|
|||
|
}
|
|||
|
|
|||
|
func realnamePendingList(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnamePendingList{}
|
|||
|
list []*model.RespRealnameApply
|
|||
|
total int
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if arg.PN <= 0 {
|
|||
|
arg.PN = 1
|
|||
|
}
|
|||
|
if arg.PS <= 0 || arg.PS > 100 {
|
|||
|
arg.PS = 10
|
|||
|
}
|
|||
|
if list, total, err = svc.RealnamePendingList(ctx, arg); err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
res := map[string]interface{}{
|
|||
|
"list": list,
|
|||
|
"page": map[string]int{
|
|||
|
"num": arg.PN,
|
|||
|
"size": arg.PS,
|
|||
|
"total": total,
|
|||
|
},
|
|||
|
}
|
|||
|
ctx.JSON(res, nil)
|
|||
|
}
|
|||
|
|
|||
|
func realnameAuditApply(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameAuditApply{}
|
|||
|
adminName string
|
|||
|
adminID int64
|
|||
|
data interface{}
|
|||
|
ok bool
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
// 驳回必须有reason
|
|||
|
if arg.Action == model.RealnameActionReject && arg.Reason == "" {
|
|||
|
ctx.JSON(nil, ecode.RequestErr)
|
|||
|
return
|
|||
|
}
|
|||
|
if data, ok = ctx.Get("username"); !ok {
|
|||
|
ctx.JSON(nil, ecode.AccessDenied)
|
|||
|
return
|
|||
|
}
|
|||
|
if adminName, ok = data.(string); !ok {
|
|||
|
ctx.JSON(nil, ecode.ServerErr)
|
|||
|
return
|
|||
|
}
|
|||
|
if data, ok = ctx.Get("uid"); !ok {
|
|||
|
ctx.JSON(nil, ecode.AccessDenied)
|
|||
|
return
|
|||
|
}
|
|||
|
if adminID, ok = data.(int64); !ok {
|
|||
|
ctx.JSON(nil, ecode.ServerErr)
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.JSON(nil, svc.RealnameAuditApply(ctx, arg, adminName, adminID))
|
|||
|
}
|
|||
|
|
|||
|
func realnameReasonList(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameReasonList{}
|
|||
|
list []string
|
|||
|
total int
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if arg.PN <= 0 {
|
|||
|
arg.PN = 1
|
|||
|
}
|
|||
|
if arg.PS <= 0 || arg.PS > 100 {
|
|||
|
arg.PS = 20
|
|||
|
}
|
|||
|
if list, total, err = svc.RealnameReasonList(ctx, arg); err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
res := map[string]interface{}{
|
|||
|
"list": list,
|
|||
|
"page": map[string]int{
|
|||
|
"num": arg.PN,
|
|||
|
"size": arg.PS,
|
|||
|
"total": total,
|
|||
|
},
|
|||
|
}
|
|||
|
ctx.JSON(res, nil)
|
|||
|
}
|
|||
|
|
|||
|
func realnameSetReason(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameSetReason{}
|
|||
|
)
|
|||
|
if err := ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.JSON(nil, svc.RealnameSetReason(ctx, arg))
|
|||
|
}
|
|||
|
|
|||
|
func realnameImage(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameImage{}
|
|||
|
img []byte
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if img, err = svc.FetchRealnameImage(ctx, arg.Token); err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.Bytes(http.StatusOK, http.DetectContentType(img), img)
|
|||
|
}
|
|||
|
|
|||
|
func realnameImagePreview(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameImagePreview{}
|
|||
|
img []byte
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if arg.BorderSize <= 0 {
|
|||
|
arg.BorderSize = 1000
|
|||
|
}
|
|||
|
if img, err = svc.RealnameImagePreview(ctx, arg.Token, arg.BorderSize); err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.Bytes(http.StatusOK, http.DetectContentType(img), img)
|
|||
|
}
|
|||
|
|
|||
|
func realnameSearchCard(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgRealnameSearchCard{}
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if len(arg.Cards) > 50 {
|
|||
|
err = ecode.RequestErr
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.JSON(svc.RealnameSearchCard(ctx, arg.Cards, arg.CardType, arg.Country))
|
|||
|
}
|
|||
|
|
|||
|
func realnameUnbind(ctx *bm.Context) {
|
|||
|
var (
|
|||
|
arg = &model.ArgMid{}
|
|||
|
adminName string
|
|||
|
adminID int64
|
|||
|
data interface{}
|
|||
|
ok bool
|
|||
|
err error
|
|||
|
)
|
|||
|
if err = ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if data, ok = ctx.Get("username"); !ok {
|
|||
|
ctx.JSON(nil, ecode.AccessDenied)
|
|||
|
return
|
|||
|
}
|
|||
|
if adminName, ok = data.(string); !ok {
|
|||
|
ctx.JSON(nil, ecode.ServerErr)
|
|||
|
return
|
|||
|
}
|
|||
|
if data, ok = ctx.Get("uid"); !ok {
|
|||
|
ctx.JSON(nil, ecode.AccessDenied)
|
|||
|
return
|
|||
|
}
|
|||
|
if adminID, ok = data.(int64); !ok {
|
|||
|
ctx.JSON(nil, ecode.ServerErr)
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.JSON(nil, svc.RealnameUnbind(ctx, arg.Mid, adminName, adminID))
|
|||
|
}
|
|||
|
|
|||
|
func realnameExport(ctx *bm.Context) {
|
|||
|
arg := &model.ArgMids{}
|
|||
|
if err := ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
if len(arg.Mid) > 1000 {
|
|||
|
ctx.JSON(nil, ecode.RequestErr)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
realnameExports, err := svc.RealnameExcel(ctx, arg.Mid)
|
|||
|
if err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
data := make([][]string, 0, len(realnameExports))
|
|||
|
data = append(data, []string{"用户uid", "用户名", "昵称", "姓名", "手机号", "证件类型", "证件号"})
|
|||
|
for _, user := range realnameExports {
|
|||
|
fields := []string{
|
|||
|
strconv.FormatInt(user.Mid, 10),
|
|||
|
user.UserID,
|
|||
|
user.Uname,
|
|||
|
user.Realname,
|
|||
|
user.Tel,
|
|||
|
model.CardTypeString(user.CardType),
|
|||
|
avoidescape(user.CardNum),
|
|||
|
}
|
|||
|
data = append(data, fields)
|
|||
|
}
|
|||
|
buf := bytes.NewBuffer(nil)
|
|||
|
w := csv.NewWriter(buf)
|
|||
|
for _, record := range data {
|
|||
|
if err := w.Write(record); err != nil {
|
|||
|
ctx.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
w.Flush()
|
|||
|
res := buf.Bytes()
|
|||
|
ctx.Writer.Header().Set("Content-Type", "application/csv")
|
|||
|
ctx.Writer.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.csv", "实名认证导出"))
|
|||
|
ctx.Writer.Write([]byte("\xEF\xBB\xBF")) // 写 UTF-8 的 BOM 头,别删,删了客服就找上门了
|
|||
|
ctx.Writer.Write(res)
|
|||
|
}
|
|||
|
|
|||
|
func avoidescape(in string) string {
|
|||
|
return fmt.Sprintf("%s,", in)
|
|||
|
}
|
|||
|
|
|||
|
func realnameSubmit(ctx *bm.Context) {
|
|||
|
arg := &model.ArgRealnameSubmit{}
|
|||
|
if err := ctx.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
ctx.JSON(nil, svc.RealnameSubmit(ctx, arg))
|
|||
|
}
|
|||
|
|
|||
|
func realnameFileUpload(c *bm.Context) {
|
|||
|
arg := &model.ArgMid{}
|
|||
|
if err := c.Bind(arg); err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
mid := arg.Mid
|
|||
|
defer c.Request.Form.Del("img") // 防止日志不出现
|
|||
|
c.Request.ParseMultipartForm(32 << 20)
|
|||
|
imgBytes, err := func() ([]byte, error) {
|
|||
|
img := c.Request.FormValue("img")
|
|||
|
if img != "" {
|
|||
|
log.Info("Succeeded to parse img file from form value: mid: %d, length: %d", mid, len(img))
|
|||
|
return []byte(img), nil
|
|||
|
}
|
|||
|
log.Warn("Failed to parse img file from form value, fallback to form file: mid: %d", mid)
|
|||
|
f, _, err := c.Request.FormFile("img")
|
|||
|
if err != nil {
|
|||
|
return nil, errors.Wrapf(err, "parse img form file: mid: %d", mid)
|
|||
|
}
|
|||
|
defer f.Close()
|
|||
|
data, err := ioutil.ReadAll(f)
|
|||
|
if err != nil {
|
|||
|
return nil, errors.Wrapf(err, "read img form file: mid: %d", mid)
|
|||
|
}
|
|||
|
if len(data) <= 0 {
|
|||
|
return nil, errors.Wrapf(err, "form file data: mid: %d, length: %d", mid, len(data))
|
|||
|
}
|
|||
|
log.Info("Succeeded to parse file from form file: mid: %d, length: %d", mid, len(data))
|
|||
|
return data, nil
|
|||
|
}()
|
|||
|
if err != nil {
|
|||
|
log.Error("Failed to parse realname upload file: mid: %d: %+v", mid, err)
|
|||
|
c.JSON(nil, ecode.RequestErr)
|
|||
|
return
|
|||
|
}
|
|||
|
var resData struct {
|
|||
|
SRC string `json:"token"`
|
|||
|
}
|
|||
|
if resData.SRC, err = svc.RealnameFileUpload(c, arg.Mid, imgBytes); err != nil {
|
|||
|
log.Error("%+v", err)
|
|||
|
c.JSON(nil, err)
|
|||
|
return
|
|||
|
}
|
|||
|
c.JSON(resData, nil)
|
|||
|
}
|