b s s m 3 jaren geleden
commit
fd9c21e1b4

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/

+ 9 - 0
.idea/lzyd-user-api.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/lzyd-user-api.iml" filepath="$PROJECT_DIR$/.idea/lzyd-user-api.iml" />
+    </modules>
+  </component>
+</project>

+ 11 - 0
Dockerfile

@@ -0,0 +1,11 @@
+FROM alpine:latest
+RUN echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories && \
+    echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories
+
+RUN apk update --no-cache && apk add --no-cache ca-certificates tzdata
+ENV TZ Asia/Shanghai
+WORKDIR $GOPATH/src/lzyd-user-api
+COPY . $GOPATH/src/lzyd-user-api
+
+EXPOSE 4003
+CMD ["./lzyd-front-user-api"]

+ 32 - 0
build.sh

@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+BUILD_PROFILE="prod"
+PORT="4003"
+LOGIN_COMMAND="login --username=admin -p=Harbor12345 121.196.188.248:5000"
+DOCKER_NAME="lzyd-front-user-api-docker-scratch"
+repo="121.196.188.248:5000/lzyd/${DOCKER_NAME}:latest"
+REMOTE_SERVER="root@121.196.31.98"
+JOB_NAME=${DOCKER_NAME}
+
+#编译
+echo start to compile
+CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o lzyd-front-user-api .
+
+# Docker
+echo Start to build docker...
+
+
+docker build -t ${DOCKER_NAME} .
+
+docker ${LOGIN_COMMAND}
+
+docker tag ${DOCKER_NAME}:latest ${repo}
+
+docker push ${repo}
+
+# Deploy
+echo deploy to remote server...
+
+
+# 本地进行远程部署
+ssh -X ${REMOTE_SERVER}  " docker ${LOGIN_COMMAND}; docker pull ${repo}; docker rm -f $JOB_NAME || true; docker run -d -p ${PORT}:${PORT} --name ${JOB_NAME} ${repo};"

+ 118 - 0
common/common.go

@@ -0,0 +1,118 @@
+package common
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"net/http"
+)
+
+type ResponseJson struct {
+	Code    uint        `yaml:"code" json:"code"`           // response code
+	Message string      `yaml:"message" json:"message"`     // response message
+	Data    interface{} `yaml:"data" json:"data,omitempty"` // response data
+}
+
+/**
+生成Response
+*/
+func GenResp(c *gin.Context, code int, message string, data interface{}) {
+	if data != nil {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    code,
+			"message": message,
+			"data":    data,
+		})
+	} else {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    code,
+			"message": message,
+		})
+	}
+}
+
+/**
+生成带错误信息的Response
+*/
+func GenMessageResp(c *gin.Context, code int, msg string, data interface{}) {
+	if data != nil {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    code,
+			"message": msg,
+			"data":    data,
+		})
+	} else {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    code,
+			"message": msg,
+		})
+	}
+}
+
+// StringsJoin string array join
+func StringsJoin(strs ...string) string {
+	var str string
+	var b bytes.Buffer
+	strsLen := len(strs)
+	if strsLen == 0 {
+		return str
+	}
+	for i := 0; i < strsLen; i++ {
+		b.WriteString(strs[i])
+	}
+	str = b.String()
+	return str
+}
+
+func Join2String(split string, strs ...interface{}) string {
+	var str string
+	var b bytes.Buffer
+	strsLen := len(strs)
+	if strsLen == 0 {
+		return str
+	}
+	for i := 0; i < strsLen; i++ {
+		var str interface{}
+		switch str.(type) {
+		case string:
+			b.WriteString(str.(string))
+		case int:
+			b.WriteString(fmt.Sprintf("%d", str.(int)))
+		case int64:
+			b.WriteString(fmt.Sprintf("%d", str.(int)))
+		}
+	}
+	str = b.String()
+	return str
+}
+
+func LogError(msg string) {
+	if LoggerInfo.Open {
+		Logger.Error(msg)
+	}
+}
+
+func LogInfo(msg string) {
+	if LoggerInfo.Open {
+		Logger.Info(msg)
+	}
+}
+
+func LogDebug(msg string) {
+	if LoggerInfo.Open {
+		Logger.Debug(msg)
+	}
+}
+
+func LogWarn(msg string) {
+	if LoggerInfo.Open {
+		Logger.Warn(msg)
+	}
+}
+
+func LogSync() error {
+	if LoggerInfo.Open {
+		return Logger.Sync()
+	}
+	return nil
+}

+ 213 - 0
common/config.go

@@ -0,0 +1,213 @@
+package common
+
+import (
+	"encoding/json"
+	"fmt"
+	_ "github.com/jinzhu/gorm/dialects/mssql"
+	_ "github.com/jinzhu/gorm/dialects/mysql"
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+	gopkg "gopkg"
+	"gopkg.in/yaml.v2"
+	"io/ioutil"
+	"log"
+	"os"
+	"path"
+	"runtime"
+	"time"
+)
+
+//serverModel get server information from config.yml
+type serverModel struct {
+	Mode              string        `yaml:"mode"`                 // run mode
+	Host              string        `yaml:"host"`                 // server host
+	Port              string        `yaml:"port"`                 // server port
+	EnableHttps       bool          `yaml:"enable_https"`         // enable https
+	CertFile          string        `yaml:"cert_file"`            // cert file path
+	KeyFile           string        `yaml:"key_file"`             // key file path
+	JwtPubKeyPath     string        `yaml:"jwt_public_key_path"`  // jwt public key path
+	JwtPriKeyPath     string        `yaml:"jwt_private_key_path"` // jwt private key path
+	TokenExpireSecond time.Duration `yaml:"token_expire_second"`  // token expire second
+}
+
+//databaseModel get database information from config.yml
+type databaseModel struct {
+	DBType   string `yaml:"type"`     // db type
+	Host     string `yaml:"host"`     // db host
+	Port     int    `yaml:"port"`     // db port
+	UserName string `yaml:"username"` // user name
+	Password string `yaml:"password"` // password
+	Database string `yaml:"database"` // database
+	MaxIdle  int    `yaml:"max_idle"` // db max idle connections
+	MaxOpen  int    `yaml:"max_open"` // db max open connections
+}
+
+//redisModel get redis information from config.yml
+type redisModel struct {
+	Host string `yaml:"host"`
+	Port int    `yaml:"port"`
+}
+
+//logModel get log information from config.yml
+type logModel struct {
+	Open  bool   `yaml:"open"`
+	Mode  string `yaml:"mode"`
+	Path  string `yaml:"file"`
+	Level string `yaml:"level"`
+}
+
+//imageModel get image information from config.yml
+type imageModel struct {
+	BasePath  string `yaml:"base_path"`
+	OutputDir string `yaml:"output_dir"`
+	PrefixURL string `yaml:"prefix_url"`
+	MaxSize   int64  `yaml:"max_size"`
+}
+
+//systemModel get system information from config.yml
+type systemModel struct {
+	Avatar string `yaml:"avatar"`
+	Sync   bool   `yaml:"sync"`
+	Valid  bool   `yaml:"valid"`
+}
+
+type configModel struct {
+	Server   *serverModel   `yaml:"server"`
+	Database *databaseModel `yaml:"database"`
+	Redis    *redisModel    `yaml:"redis"`
+	Image    *imageModel    `yaml:"image"`
+	Log      *logModel      `yaml:"log"`
+	System   *systemModel   `yaml:"system"`
+}
+
+// LoadConfigInformation load config information for application
+func LoadConfigInformation(configPath string) (err error) {
+
+	var (
+		filePath string
+		wr       string
+	)
+
+	if configPath == "" {
+		wr, _ = os.Getwd()
+		wr = path.Join(wr, "conf")
+	} else {
+		wr = configPath
+	}
+	filePath = path.Join(wr, "config.yml")
+	configData, err := ioutil.ReadFile(filePath)
+	if err != nil {
+		fmt.Printf(" config file read failed: %s", err)
+		os.Exit(-1)
+	}
+
+	err = yaml.Unmarshal(configData, &ConfigInfo)
+	if err != nil {
+		fmt.Printf(" config parse failed: %s", err)
+		os.Exit(-1)
+	}
+
+	// server information
+	ServerInfo = ConfigInfo.Server
+	// image information
+	ImageInfo = ConfigInfo.Image
+	// log information
+	LoggerInfo = ConfigInfo.Log
+	// system information
+	SystemInfo = ConfigInfo.System
+
+	// log config load
+	logPath := LoggerInfo.Path   //log path
+	logLevel := LoggerInfo.Level // log level
+	isDebug := true              // log mode
+	if ServerInfo.Mode == "release" {
+		isDebug = false
+	}
+	initBasicLogger(logLevel, logPath, isDebug)
+	log.SetFlags(log.Lmicroseconds | log.Lshortfile | log.LstdFlags)
+
+	// mysql连接
+	err = initDatabase("yuedong")
+	if err != nil {
+		fmt.Printf("database connect failed: %s\n", err)
+		os.Exit(-1)
+	}
+
+	// 创建图片与文件目录
+	if runtime.GOOS == "windows" {
+		// TODO:
+	} else {
+		err = initSaveDirectory(ImageInfo.BasePath + "/" + ImageInfo.OutputDir)
+		if err != nil {
+			fmt.Printf("creat directory error: %s", err)
+		}
+	}
+
+	return
+}
+
+func initDatabase(dbname string) error {
+	var err error
+	//内网地址:rm-bp1rxj4r7a204ujhn.mysql.rds.aliyuncs.com
+	//外网地址:rm-bp1rxj4r7a204ujhnio.mysql.rds.aliyuncs.com
+	DB, err = gopkg.OpenMysqlWithConfig(gopkg.MysqlConfig{
+		Host:     "rm-bp1cbq48ara8ex330.mysql.rds.aliyuncs.com",
+		Port:     "3306",
+		UserName: "yuedong",
+		Password: "Yuedong2020",
+		Database: dbname,
+	})
+	DB.SingularTable(true)
+	return err
+}
+func initBasicLogger(logLevel string, logPath string, isDebug bool) {
+
+	if _, err := os.Open(logPath); err != nil && os.IsNotExist(err) {
+		p, _ := os.Getwd()
+		logPath = path.Join(p, logPath)
+		_, err = os.Create(logPath)
+	}
+
+	var js string
+	if isDebug {
+		js = fmt.Sprintf(`{
+              "level": "%s",
+              "encoding": "json",
+              "outputPaths": ["stdout","%s"],
+              "errorOutputPaths": ["stdout"]
+              }`, logLevel, logPath)
+	} else {
+		js = fmt.Sprintf(`{
+              "level": "%s",
+              "encoding": "json",
+              "outputPaths": ["%s"],
+              "errorOutputPaths": ["%s"]
+              }`, logLevel, logPath, logPath)
+	}
+
+	var cfg zap.Config
+	if err := json.Unmarshal([]byte(js), &cfg); err != nil {
+		panic(err)
+	}
+	cfg.EncoderConfig = zap.NewProductionEncoderConfig()
+	cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
+	var err error
+	Logger, err = cfg.Build()
+	if err != nil {
+		//Logger.Error("init logger error: ", zap.String("err", err.Error()))
+	} else {
+		Logger.Info("log init")
+		_ = Logger.Sync()
+	}
+}
+
+func initSaveDirectory(path string) error {
+	_, err := os.Stat(path)
+	if notExist := os.IsNotExist(err); notExist == true {
+		err := os.MkdirAll(path, os.ModePerm)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}

+ 109 - 0
common/const.go

@@ -0,0 +1,109 @@
+package common
+
+const (
+
+	// success
+	Success = 200
+
+	// parameters invalid
+	InvalidParametes = 1001
+
+	// 记录创建失败
+	DbInsertErr = 1011
+	// 记录更新失败
+	DbUpdateErr = 1012
+	// 记录删除失败
+	DbDeleteErr = 1013
+	// 记录查询失败
+	DbRecordNotFound = 1014
+
+	// 系统用户不存在
+	SystemHasNoUser = 1022
+	// 手机号码重复
+	MobileRepeat = 1023
+	// 手机号无效或密码错误
+	MobileInvalidPwdError = 1024
+	// 无效的验证码
+	SmsCodeInvalid = 1025
+	// 验证码已失效
+	SmsCodeExpired = 1026
+	// 手机号码格式有误
+	MobileFormatError = 1027
+
+	// 无效的文件内容
+	InvalidFileContent = 1031
+	// 文件大小超出最大限制
+	FileSizeOverLimit = 1032
+	// 文件保存失败
+	FileSaveFailed = 1033
+)
+
+const (
+	QueryStateSuccess = 0 // 从myssql中查询到了记录
+	QueryStateNone    = 2 // 未查询到任何记录
+)
+
+const (
+	// sms expire seconds
+	SmsExpiredSeconds = 600
+	// default gender
+	GenderUnknow = 0
+)
+
+const (
+	SmsTypeRegister   = 1 // 注册
+	SmsTypeGetback    = 2 // 找回密码
+	SmsTypeBindMobile = 3 // 绑定手机号
+	SmsTypeQuickLogin = 4 // 快捷登录
+)
+
+const (
+	LoginTypeMobile     = 1 // 手机号登录
+	LoginTypeQuick      = 2 // 快捷登录
+	LoginTypeThirdParty = 3 // 第三方登录
+)
+
+const (
+	BindTypeWechat = 10 // 绑定微信
+	BindTypeQQ     = 11 // 绑定QQ
+	BindTypeWeibo  = 12 // 绑定微博
+)
+
+// 微信第三方登录必备
+const (
+	WxAppId     = "wx88fe165b2e4236b6"
+	WxAppSecret = "647520760882a91fe2754cffded4b1f5"
+)
+
+/// 阿里短信配置
+const (
+	RegionId     = "cn-hangzhou"
+	AccessKeyId  = "LTAI4GEM9Zz2Tsvb8nicmwXV"
+	AccessSecret = "kNVHucWT57Wl7PP1ds2QCxilTSjaY0"
+	SignName     = "荔枝悦动"
+)
+
+/// 腾讯云短信配置
+const (
+	SdkAppId   = "1400081008"
+	SdkAppKey  = "83427541ad50e54450725d789cf396eb"
+	SdkSmsUrl  = "https://yun.tim.qq.com/v5/tlssmssvr/sendsms"
+	SdkTemplId = 105107
+)
+
+/// 阿里云短信模板定义
+const (
+	TemplateCodeRegister   = "SMS_193055376"
+	TemplateCodeFindPwd    = "SMS_193055375"
+	TemplateCodeBindMobile = "SMS_196618124"
+	TemplateCodeLogin      = "SMS_193055378"
+)
+
+var SmsTemplateCodeMap = map[int]string{
+	SmsTypeRegister:   TemplateCodeRegister,
+	SmsTypeGetback:    TemplateCodeFindPwd,
+	SmsTypeBindMobile: TemplateCodeBindMobile,
+	SmsTypeQuickLogin: TemplateCodeLogin,
+}
+
+const SmsValidSeconds = 60

+ 30 - 0
common/path.go

@@ -0,0 +1,30 @@
+package common
+
+import (
+	"lzyd-user-api/utils"
+	"path"
+	"time"
+)
+
+func GetImagePath(filename string) string {
+	if len(filename) > 0 {
+		savePath := path.Join(ImageInfo.BasePath, ImageInfo.OutputDir)
+		savePath = path.Join(savePath, time.Now().Format("2006-01"))
+		if err := utils.IsNotExistMkDirAll(savePath); err == nil {
+			suffix := path.Ext(filename)
+			if len(suffix) == 0 {
+				suffix = ".jpg"
+			}
+			return path.Join(savePath, utils.RandImageName(12)+suffix)
+		}
+	}
+	return ""
+}
+
+func GetImageURLFromPath(path string) string {
+	if len(path) > 0 {
+		length := len(ImageInfo.BasePath)
+		return ImageInfo.PrefixURL + path[length:]
+	}
+	return ""
+}

+ 16 - 0
common/variables.go

@@ -0,0 +1,16 @@
+package common
+
+import (
+	"github.com/jinzhu/gorm"
+	"go.uber.org/zap"
+)
+
+var (
+	ConfigInfo *configModel // all server config information
+	ServerInfo *serverModel // server config information
+	ImageInfo  *imageModel  // image config information
+	LoggerInfo *logModel    // log config information
+	SystemInfo *systemModel // system config information
+	DB         *gorm.DB     // database contains
+	Logger     *zap.Logger  // log instance
+)

+ 30 - 0
conf/config.yml

@@ -0,0 +1,30 @@
+# config information
+
+# server config information
+server:
+  mode: debug # debug,release
+  host: 0.0.0.0
+  port: 4003
+  token_expire_second: 360000
+  enable_https: false  # 后台开启https
+
+# log config information
+log:
+  open: true
+  mode: basic # advanced,basic
+  level: INFO # DEBUG,ERROR,INFO
+  file: logs/gouser.log # log file path container log file name
+
+# image config information
+image:
+  base_path: /Users/bssm/go/src/lzyd-images
+#  base_path: /bssm/go/src/lzyd-images
+  output_dir: images/
+  prefix_url: https://lzyd-image.lizhiyuedong.com/
+  max_size: 2  # unit MB
+
+# system config information
+system:
+  avatar: http://lz2019-image.lzwg.com/images/cusimg.png
+  sync: false
+  valid: true

+ 65 - 0
controllers/area.go

@@ -0,0 +1,65 @@
+package controllers
+
+import (
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/services"
+	"regexp"
+)
+
+// @tags  area
+// @Description  获取省市区
+// @Summary  获取省市区
+// @Produce  json
+// @Param p_code query string false "地区code"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}"
+// @Router /area/getArea [get]
+func GetArea(c *gin.Context) {
+
+	PCode := c.Query("p_code")
+	var (
+		code  = common.Success
+	)
+
+	if len(PCode) == 0 {
+		var (
+			model []models.ReqProvince
+		)
+		model = services.QueryProvinceCode()
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+	//PCode_int, _ := strconv.Atoi(PCode)
+	reg := regexp.MustCompile(`0000`)
+	fmt.Println(reg.FindAllString(PCode, -1))
+	if len(reg.FindAllString(PCode, -1)) > 0 {
+		var (
+			model []models.ReqCity
+		)
+		model = services.QueryCityCode(PCode)
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+	if len(reg.FindAllString(PCode, -1)) == 0 {
+		var (
+			model []models.ReqArea
+		)
+		model = services.QueryAreaCode(PCode)
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+	//model = services.QueryAreaCode(PCode)
+	//if model.Id == 0 {
+	//	code = common.SystemHasNoUser
+	//}
+	//if common.Success == code {
+	//	// 修改上一次登录时间
+	//	//_ = model.UpdateLoginTime()
+	//	common.GenResp(c, code, "SUCCESS", model)
+	//} else {
+	//	common.GenResp(c, code, "内部错误", nil)
+	//}
+}
+

+ 55 - 0
controllers/cert.go

@@ -0,0 +1,55 @@
+package controllers
+
+import (
+	"github.com/gin-gonic/gin"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/services"
+)
+
+// @tags  cert
+// @Description  获取证书列表
+// @Summary  获取证书列表
+// @Produce  json
+// @Param type query string false "类型:传1"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}"
+// @Router /cert/list [get]
+func GetCertList(c *gin.Context) {
+
+	Ctype := c.Query("type")
+	var (
+		code  = common.Success
+	)
+
+	if len(Ctype) == 1 {
+		var (
+			model []models.LzydCert
+		)
+		model = services.QueryCertList(common.DB, Ctype)
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+}
+// @tags  cert
+// @Description  获取用户获得证书列表
+// @Summary  获取用户获得证书列表
+// @Produce  json
+// @Param userId query string false "用户id"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}"
+// @Router /cert/userList [get]
+func GetUserCertList(c *gin.Context) {
+
+	userId := c.Query("userId")
+	var (
+		code  = common.Success
+	)
+
+	if len(userId) > 1 {
+		var (
+			model []models.LzydCertUser
+		)
+		model = services.QueryUserCertList(userId)
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+}

+ 55 - 0
controllers/medal.go

@@ -0,0 +1,55 @@
+package controllers
+
+import (
+	"github.com/gin-gonic/gin"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/services"
+)
+
+// @tags  medal
+// @Description  获取勋章列表
+// @Summary  获取勋章列表
+// @Produce  json
+// @Param type query string false "类型:传1"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}"
+// @Router /medal/list [get]
+func GetMedalList(c *gin.Context) {
+
+	Ctype := c.Query("type")
+	var (
+		code  = common.Success
+	)
+
+	if len(Ctype) == 1 {
+		var (
+			model []models.LzydMedal
+		)
+		model = services.QueryMedalList(common.DB, Ctype)
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+}
+// @tags  medal
+// @Description  获取用户获得勋章列表
+// @Summary  获取用户获得勋章列表
+// @Produce  json
+// @Param userId query string false "用户id"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}"
+// @Router /medal/userList [get]
+func GetUserMedalList(c *gin.Context) {
+
+	userId := c.Query("userId")
+	var (
+		code  = common.Success
+	)
+
+	if len(userId) > 1 {
+		var (
+			model []models.LzydMedalUser
+		)
+		model = services.QueryUserMedalList(userId)
+		common.GenResp(c, code, "SUCCESS", model)
+		return
+	}
+}

+ 126 - 0
controllers/passport.go

@@ -0,0 +1,126 @@
+package controllers
+
+import (
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"gopkg"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/services"
+	"lzyd-user-api/utils"
+	"time"
+)
+
+
+
+// @tags  Passport
+// @Description  登录注册
+// @Summary  登录注册
+// @Accept  json
+// @Produce  json
+// @Param body body models.QuickLoginReq true "快捷登录请求内容"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","user":{}}}"
+// @Router /passport/quickLogin [post]
+// @Security ApiKeyAuth
+func QuickLogin(c *gin.Context) {
+
+	var req models.QuickLoginReq
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		panic(err)
+	}
+
+	tokenStr := c.GetHeader("x-app-id")
+	if tokenStr != "lzyd" {
+		common.GenMessageResp(c, common.InvalidParametes, "非法操作", nil)
+		return
+	}
+	//common.LogInfo("")
+	//common.LogInfo(fmt.Sprintf("-------- [%s]快捷登录START --------", req.MobilePhone))
+
+	if len(req.MobilePhone) == 0 || len(req.ValidCode) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+	if len(req.MobilePhone) != 11 {
+		common.GenResp(c, common.MobileFormatError, "手机号码格式有误", nil)
+		return
+	}
+
+	var (
+		model     models.UserInfo
+		queryStat int
+		code      = common.Success
+	)
+	userSms := services.GetValidSmsUser(common.DB, req.MobilePhone)
+	SmsTypeLogin := common.LoginTypeMobile
+	if len(userSms.MobilePhone) == 0 {
+		SmsTypeLogin = common.LoginTypeMobile
+	}
+
+	sms := services.GetValidSms(common.DB, req.MobilePhone, req.ValidCode, SmsTypeLogin)
+	if sms.SmsId == 0 {
+		code = common.SmsCodeInvalid
+	} else {
+		if time.Now().Unix()-common.SmsExpiredSeconds > sms.CreateAt {
+			fmt.Println(time.Now().Unix()-common.SmsExpiredSeconds,sms.CreateAt)
+			code = common.SmsCodeExpired
+		} else {
+			model, queryStat = services.LoginWithMobileOnly(req.MobilePhone)
+			fmt.Println("LoginWithMobileOnly",model, queryStat)
+			switch queryStat {
+			case common.QueryStateSuccess:
+				if err := model.Login(common.DB); err != nil {
+					code = common.DbInsertErr
+				}
+			case common.QueryStateNone:
+				model.UserId = gopkg.GenUUID()
+				model.RealName = utils.KeepSecretForMobile(req.MobilePhone)
+				model.UserName = services.UniqueName(model.UserName)
+				model.UserAvatar = common.SystemInfo.Avatar
+				model.Gender = common.GenderUnknow
+				model.MobilePhone = req.MobilePhone
+				model.IsDelete = common.GenderUnknow
+				model.AppId = tokenStr
+				//model.Password = utils.DESEncryptString("888888", true) /// 设置默认密码`888888`
+				//common.LogInfo(fmt.Sprintf("没查到记录,插入记录: %v", model))
+				if err := model.Register(common.DB); err != nil {
+					code = common.DbInsertErr
+				}
+			}
+		}
+	}
+
+	if code != common.Success {
+		msg := ""
+		if code == common.SmsCodeInvalid {
+			msg = "无效的短信验证码"
+		} else if code == common.DbInsertErr {
+			msg = "插入记录时发生错误"
+		} else if code == common.SmsCodeExpired {
+			msg = "验证码已失效"
+		} else {
+			msg = "未知错误"
+		}
+		common.GenResp(c, -1, msg, nil)
+		return
+	}
+
+	//common.LogInfo(fmt.Sprintf("-------- [%s]快捷登录END --------", req.MobilePhone))
+
+	// 返回结果处理
+	var ret = models.UserResp{
+		Id:       		model.Id,
+		UserId:     	model.UserId,
+		UserName:     	model.UserName,
+		MobilePhone:    model.MobilePhone,
+		UserAvatar:     model.UserAvatar,
+		Gender:         model.Gender,
+		Birthday:       model.Birthday,
+		Area:           model.Area,
+		RegisterTime:   model.RegisterTime,
+		AppId:          model.AppId,
+	}
+	common.GenResp(c, code, "SUCCESS", ret)
+}
+

+ 174 - 0
controllers/sms.go

@@ -0,0 +1,174 @@
+package controllers
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"gopkg"
+	"io/ioutil"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/services"
+	"lzyd-user-api/utils"
+	"net/http"
+	"strconv"
+	"time"
+)
+
+// @tags  Sms
+// @Summary  获取短信验证码
+// @Description  获取短信验证码
+// @Produce  json
+// @Param mobile query string true "手机号码"
+// @Param type query int true "短信验证码类型(1=注册登录)" Enums(1, 2, 3, 4) default(1)
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /sms/get [get]
+// @Security ApiKeyAuth
+func GetSms(c *gin.Context) {
+
+	mobile := c.Query("mobile")
+	smsType, _ := strconv.Atoi(c.Query("type"))
+
+	tokenStr := c.GetHeader("x-app-id")
+	if tokenStr != "lzyd" {
+		common.GenMessageResp(c, common.InvalidParametes, "非法操作", nil)
+		return
+	}
+	// 先校验手机号与短信类型
+	if !gopkg.ValidMobilePhone(mobile) {
+		common.GenMessageResp(c, common.InvalidParametes, "无效的手机号码", nil)
+		return
+	}
+
+	if smsType < 1 || smsType > 5 {
+		common.GenMessageResp(c, common.InvalidParametes, "不支持的短信类型", nil)
+		return
+	}
+
+	// 校验手机号是否已被注册, 已被注册的手机号不下发短信
+	//if smsType == 1 {
+	//	if services.ExistedMobile(mobile) {
+	//		common.GenMessageResp(c, common.InvalidParametes, "手机号码已被注册", nil)
+	//		return
+	//	}
+	//}
+
+
+	// 限制发送总量
+	count := services.CountOfToday(common.DB, "lzyd_sms_valid")
+	fmt.Println(count)
+	if count > 5000 {
+		common.GenMessageResp(c, 500, "超过短信限制", nil)
+		return
+	}
+
+	// 先查看该手机号码的最后一条短信是否在一分钟分钟内
+	var sms models.ValidSms
+	sms = services.GetLastValidSms(common.DB, mobile, smsType)
+	if time.Now().Unix()-common.SmsValidSeconds < sms.CreateAt {
+		common.GenResp(c, -1, "发送频繁", nil)
+		return
+	}
+
+	// 调用模板发送短信
+	validCode, err := services.SendSingleSms(mobile, smsType)
+	if err != nil {
+		common.GenMessageResp(c, 500, err.Error(), nil)
+		return
+	}
+	// 发送成功后插入数据
+	sms.Mobile = mobile
+	sms.ValidCode = validCode
+	sms.SmsType = smsType
+	if err := sms.Save(common.DB); err != nil {
+		common.GenMessageResp(c, -1, err.Error(), nil)
+		return
+	}
+
+	common.GenResp(c, 200, "SUCCESS", nil)
+}
+
+// @tags  Sms
+// @Summary  发送提醒短信
+// @Description  发送提醒短信
+// @Accept  json
+// @Produce  json
+// @Param body body models.SendSmsReq true "短信请求内容"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /sms/remind [post]
+// @Security ApiKeyAuth
+func SendRemindSms(c *gin.Context) {
+	tokenStr := c.GetHeader("x-app-id")
+	fmt.Println(tokenStr)
+	if tokenStr != "lzyd" {
+		common.GenMessageResp(c, common.InvalidParametes, "非法操作", nil)
+		return
+	}
+	var req models.SendSmsReq
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		panic(err)
+	}
+
+	// 限制发送总量
+	count := services.CountOfToday(common.DB, "sms_remind_info")
+	if count > 2000 {
+		common.GenMessageResp(c, -1, "超过下发次数", nil)
+		return
+	}
+
+	timeUnix := time.Now().Unix()
+	random := strconv.FormatInt(timeUnix, 10)
+	url := common.SdkSmsUrl + "?sdkappid=" + common.SdkAppId + "&random=" + random
+
+	// 请求包体
+	var templ models.SmsTempl
+	templ.Ext = ""
+	templ.Extend = ""
+	templ.Params = []string{req.Content}
+	templ.Sig = utils.CalculateSigForTempl(common.SdkAppKey, random, []string{req.Mobile}, timeUnix)
+	templ.Sign = ""
+	templ.Time = timeUnix
+	templ.TplID = common.SdkTemplId
+	templ.Tel.NationCode = "86"
+	templ.Tel.Mobile = req.Mobile
+
+	// 请求腾讯云短信API
+	jsonBytes, _ := json.Marshal(templ)
+	resp, err := http.Post(url, "application/x-www-form-urlencoded", bytes.NewReader(jsonBytes))
+	if err != nil {
+		common.GenResp(c, 500, err.Error(), nil)
+		return
+	}
+
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		common.GenResp(c, 500, err.Error(), nil)
+		return
+	}
+
+	// 发送成功后插入数据
+	sms := &models.RemindSms{
+		Mobile:  req.Mobile,
+		SmsType: 1,
+		Content: req.Content,
+		IpAddr:  gopkg.GetRemoteIP(c.Request),
+	}
+	if err := sms.Save(common.DB); err != nil {
+		common.GenMessageResp(c, 500, err.Error(), nil)
+		return
+	}
+
+	//fmt.Println(string(body))
+	var smsResp models.SmsTemplResp
+	_ = json.Unmarshal(body, &smsResp)
+	if smsResp.Result == 0 {
+		common.GenResp(c, common.Success, "SUCCESS", nil)
+	} else {
+		common.GenResp(c, 500, smsResp.ErrMsg, nil)
+	}
+}

+ 318 - 0
controllers/user.go

@@ -0,0 +1,318 @@
+package controllers
+
+import (
+	"fmt"
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+	"github.com/gin-gonic/gin"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/services"
+	"os"
+	"strings"
+)
+
+// @tags  Customer
+// @Description  获取用户详细信息
+// @Summary  获取用户详细信息
+// @Produce  json
+// @Param user_id query string true "用户ID"
+// @Param other_id query string false "另一个用户id"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}"
+// @Router /customer/getInfo [get]
+func GetCustomerInfo(c *gin.Context) {
+	userCode := c.Query("user_id")
+
+	if len(userCode) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+	var (
+		model models.UserInfo
+		code  = common.Success
+	)
+	otherCode := c.Query("other_id")
+
+	model = services.QueryUserByCode(userCode)
+	if model.Id == 0 {
+		code = common.SystemHasNoUser
+	}
+	if len(otherCode) != 0 {
+		relation := services.UserRelation(userCode,otherCode)
+		fmt.Println(relation)
+		if len(relation) > 0 {
+			model.AttentionUserId = relation
+		}
+	}
+	if common.Success == code {
+		// 修改上一次登录时间
+		//_ = model.UpdateLoginTime()
+		common.GenResp(c, code, "SUCCESS", model)
+	} else {
+		common.GenResp(c, code, "内部错误", nil)
+	}
+}
+
+// @tags  Customer
+// @Description  修改用户资料
+// @Summary  修改用户资料
+// @Produce  json
+// @Param body body models.UpdateProfileReq true "修改用户资料请求内容"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{}}"
+// @Router /customer/updateProfile [post]
+func UpdateProfile(c *gin.Context) {
+
+	var req models.UpdateProfileReq
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		panic(err)
+	}
+
+	if len(req.UserId) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+
+	var (
+		model models.UserInfo
+		code  = common.Success
+	)
+
+	model = services.QueryUserByCode(req.UserId)
+	if model.Id == 0 {
+		code = common.SystemHasNoUser
+		common.GenResp(c, code, "系统不存在该用户", nil)
+		return
+	}
+	fmt.Println(req)
+	if len(req.UserName) > 0 {
+		model.UserName = req.UserName
+	}
+	if len(req.Birthday) > 0 {
+		model.Birthday = req.Birthday
+	}
+	if len(req.Area) > 0 {
+		model.Area = req.Area
+	}
+	if req.Gender > 0 {
+		model.Gender = req.Gender
+	}
+	if req.Height > 0 {
+		model.Height = req.Height
+	}
+	if req.Weight > 0 {
+		model.Weight = req.Weight
+	}
+	if len(req.UserAvatar) > 0 {
+		model.UserAvatar = req.UserAvatar
+	}
+	if err := model.UpdateProfile(common.DB); err != nil {
+		code = common.DbUpdateErr
+	}
+
+	if common.Success == code {
+		if len(model.UserAvatar) == 0 {
+			model.UserAvatar = common.SystemInfo.Avatar
+		}
+		// 修改成功后的处理
+		var ret = models.UserResp{
+			Id:     model.Id,
+			UserId:   model.UserId,
+			UserName:   model.UserName,
+			RealName:   model.RealName,
+			UserAvatar:   model.UserAvatar,
+			Gender:     model.Gender,
+			Birthday:   model.Birthday,
+			Area:       model.Area,
+			Weight: model.Weight,
+			Height: model.Height,
+			AppId: model.AppId,
+		}
+		common.GenResp(c, code, "SUCCESS", ret)
+	} else {
+		common.GenResp(c, code, "内部错误", nil)
+	}
+}
+
+// @tags  Customer
+// @Description  获取用户黑白名单列表
+// @Summary  获取用户黑白名单列表
+// @Produce  json
+// @Param body body models.GetBlackListReq true "获取黑白名单列表"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","username":"","user_avatar":"https://"}}}"
+// @Router /customer/getBlacklist [post]
+func GetBlacklist(c *gin.Context) {
+	var req models.GetBlackListReq
+
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		panic(err)
+	}
+
+	if len(req.UserId) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+	var (
+		model []models.BlackListReq
+		code  = common.Success
+	)
+
+	model = services.QueryBlackByCode(req.UserId,req.Type)
+
+	if common.Success == code {
+		// 修改上一次登录时间
+		//_ = model.UpdateLoginTime()
+		common.GenResp(c, code, "SUCCESS", model)
+	} else {
+		common.GenResp(c, code, "内部错误", nil)
+	}
+}
+
+
+// @tags  Customer
+// @Description  获取赛事订单
+// @Summary  获取赛事订单
+// @Produce  json
+// @Param user_id query string true "用户ID"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}"
+// @Router /customer/order [get]
+func GetCompetitionOrder(c *gin.Context) {
+	userCode := c.Query("user_id")
+
+	if len(userCode) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+	var (
+		model []models.Competition
+		code  = common.Success
+	)
+
+	model = services.QueryCompetitionOrder(userCode)
+	//if len(model.DealSn) == 0 {
+	//	code = common.SystemHasNoUser
+	//}
+	if common.Success == code {
+		// 修改上一次登录时间
+		//_ = model.UpdateLoginTime()
+		common.GenResp(c, code, "SUCCESS", model)
+	} else {
+		common.GenResp(c, code, "内部错误", nil)
+	}
+}
+
+// @tags  Customer
+// @Description  获取排位赛列表
+// @Summary  获取排位赛列表
+// @Produce  json
+// @Param user_id query string true "用户ID"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}"
+// @Router /customer/qualifying [get]
+func GetQualifying(c *gin.Context) {
+	userCode := c.Query("user_id")
+
+	if len(userCode) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+	var (
+		model models.QualifyingList
+		code  = common.Success
+	)
+
+	model = services.QueryQualifyingList(userCode)
+	//if len(model.DealSn) == 0 {
+	//	code = common.SystemHasNoUser
+	//}
+	if common.Success == code {
+		// 修改上一次登录时间
+		//_ = model.UpdateLoginTime()
+		common.GenResp(c, code, "SUCCESS", model)
+	} else {
+		common.GenResp(c, code, "内部错误", nil)
+	}
+}
+
+// @tags  Customer
+// @Description  上传base64图片
+// @Summary  上传base64图片
+// @Produce  json
+// @Param body body models.UploadBaseReq true "修改用户资料请求内容"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{}}"
+// @Router /customer/uploadBase64 [post]
+func UploadBase64(c *gin.Context) {
+	var req models.UploadBaseReq
+	err := c.ShouldBindJSON(&req)
+
+	if err != nil {
+		panic(err)
+	}
+
+	if len(req.Base64) == 0 {
+		common.GenResp(c, common.InvalidParametes, "无效的参数", nil)
+		return
+	}
+	var (
+		model  models.UploadBaseErr
+		code  = common.Success
+	)
+
+	model.TaskId = req.TaskId
+	model.UserId = req.UserId
+	dir,_ := os.Getwd() //获取文件绝对路径
+	//fmt.Println("当前路径:",dir)
+	//fmt.Println(req.Base64)
+	var urls =  services.WriteFile(dir+"/images",req.Base64)
+	var urls1 =  services.WriteFile(dir+"/maps",req.MapBase)
+	//if len(model.DealSn) == 0 {
+	//	code = common.SystemHasNoUser
+	//}
+	// 创建OSSClient实例。
+	client, err := oss.New("oss-cn-hangzhou.aliyuncs.com", "LTAI4FySYnBk5ME5AvbcgGmx", "AsYT0SPtPXPe1YYAmHFi1Tfcq1Pww5")
+	client1, err1 := oss.New("oss-cn-hangzhou.aliyuncs.com", "LTAI4FySYnBk5ME5AvbcgGmx", "AsYT0SPtPXPe1YYAmHFi1Tfcq1Pww5")
+	if err != nil && err1 != nil {
+		fmt.Println("Error:", err)
+		os.Exit(-1)
+	}
+
+	// 获取存储空间。
+	bucket, err := client.Bucket("lzyd-sport-img")
+	bucket1, err1 := client1.Bucket("lzyd-sport-img")
+	if err != nil && err1 != nil {
+		fmt.Println("Error:", err)
+		os.Exit(-1)
+	}
+	urlsName := strings.Split(urls,"images/")
+	urlsName1 := strings.Split(urls1,"maps/")
+	fmt.Println(urlsName[1])
+	fmt.Println(urlsName1[1])
+	// 上传本地文件。
+	err = bucket.PutObjectFromFile(urlsName[1], urls)
+	err1 = bucket1.PutObjectFromFile(urlsName1[1], urls1)
+	if err != nil && err1 != nil {
+		fmt.Println("Error:", err)
+		os.Exit(-1)
+	}else {
+		err := os.Remove(urls)
+		err1 := os.Remove(urls1)
+		if err != nil && err1 != nil {
+			// 删除失败
+		} else {
+			// 删除成功
+		}
+	}
+	urls = "https://lzyd-sport-img.oss-cn-hangzhou.aliyuncs.com/" + urlsName[1]
+	urls1 = "https://lzyd-sport-img.oss-cn-hangzhou.aliyuncs.com/" + urlsName1[1]
+
+	model.MapUrl = urls
+	model.MapBase = urls1
+	if err := model.InsetMaps(common.DB,req.TaskId); err != nil {
+		code = common.DbInsertErr
+	}
+	if common.Success == code {
+
+		common.GenResp(c, code, "SUCCESS", model)
+	} else {
+		common.GenResp(c, code, "内部错误", nil)
+	}
+}

+ 629 - 0
docs/docs.go

@@ -0,0 +1,629 @@
+// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+// This file was generated by swaggo/swag
+
+package docs
+
+import (
+	"bytes"
+	"encoding/json"
+	"strings"
+
+	"github.com/alecthomas/template"
+	"github.com/swaggo/swag"
+)
+
+var doc = `{
+    "schemes": {{ marshal .Schemes }},
+    "swagger": "2.0",
+    "info": {
+        "description": "{{.Description}}",
+        "title": "{{.Title}}",
+        "contact": {},
+        "version": "{{.Version}}"
+    },
+    "host": "{{.Host}}",
+    "basePath": "{{.BasePath}}",
+    "paths": {
+        "/area/getArea": {
+            "get": {
+                "description": "获取省市区",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "area"
+                ],
+                "summary": "获取省市区",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "地区code",
+                        "name": "p_code",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/cert/list": {
+            "get": {
+                "description": "获取证书列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "cert"
+                ],
+                "summary": "获取证书列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "类型:传1",
+                        "name": "type",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/cert/userList": {
+            "get": {
+                "description": "获取用户获得证书列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "cert"
+                ],
+                "summary": "获取用户获得证书列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/getBlacklist": {
+            "post": {
+                "description": "获取用户黑白名单列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取用户黑白名单列表",
+                "parameters": [
+                    {
+                        "description": "获取黑白名单列表",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.GetBlackListReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"username\":\"\",\"user_avatar\":\"https://\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/getInfo": {
+            "get": {
+                "description": "获取用户详细信息",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取用户详细信息",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_id",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "另一个用户id",
+                        "name": "other_id",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/order": {
+            "get": {
+                "description": "获取赛事订单",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取赛事订单",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/qualifying": {
+            "get": {
+                "description": "获取排位赛列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取排位赛列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/updateProfile": {
+            "post": {
+                "description": "修改用户资料",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "修改用户资料",
+                "parameters": [
+                    {
+                        "description": "修改用户资料请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.UpdateProfileReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/uploadBase64": {
+            "post": {
+                "description": "上传base64图片",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "上传base64图片",
+                "parameters": [
+                    {
+                        "description": "修改用户资料请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.UploadBaseReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/medal/list": {
+            "get": {
+                "description": "获取勋章列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "medal"
+                ],
+                "summary": "获取勋章列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "类型:传1",
+                        "name": "type",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/medal/userList": {
+            "get": {
+                "description": "获取用户获得勋章列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "medal"
+                ],
+                "summary": "获取用户获得勋章列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/quickLogin": {
+            "post": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "登录注册",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "登录注册",
+                "parameters": [
+                    {
+                        "description": "快捷登录请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.QuickLoginReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"user\":{}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/sms/get": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "获取短信验证码",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Sms"
+                ],
+                "summary": "获取短信验证码",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "手机号码",
+                        "name": "mobile",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "enum": [
+                            1,
+                            2,
+                            3,
+                            4
+                        ],
+                        "type": "integer",
+                        "default": 1,
+                        "description": "短信验证码类型(1=注册登录)",
+                        "name": "type",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/sms/remind": {
+            "post": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "发送提醒短信",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Sms"
+                ],
+                "summary": "发送提醒短信",
+                "parameters": [
+                    {
+                        "description": "短信请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.SendSmsReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "models.GetBlackListReq": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "description": "类型",
+                    "type": "integer"
+                },
+                "user_id": {
+                    "description": "用户ID",
+                    "type": "string"
+                }
+            }
+        },
+        "models.QuickLoginReq": {
+            "type": "object",
+            "properties": {
+                "mobile_phone": {
+                    "type": "string"
+                },
+                "valid_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.SendSmsReq": {
+            "type": "object",
+            "properties": {
+                "content": {
+                    "type": "string"
+                },
+                "mobile": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.UpdateProfileReq": {
+            "type": "object",
+            "properties": {
+                "area": {
+                    "description": "地区",
+                    "type": "string"
+                },
+                "birthday": {
+                    "description": "生日",
+                    "type": "string"
+                },
+                "gender": {
+                    "description": "性别",
+                    "type": "integer"
+                },
+                "height": {
+                    "description": "用户身高",
+                    "type": "integer"
+                },
+                "user_avatar": {
+                    "description": "地区",
+                    "type": "string"
+                },
+                "user_id": {
+                    "description": "用户代码",
+                    "type": "string"
+                },
+                "username": {
+                    "description": "会员昵称",
+                    "type": "string"
+                },
+                "weight": {
+                    "description": "用户体重",
+                    "type": "integer"
+                }
+            }
+        },
+        "models.UploadBaseReq": {
+            "type": "object",
+            "properties": {
+                "base64": {
+                    "description": "base64字符串",
+                    "type": "string"
+                },
+                "map_base": {
+                    "description": "mapBase64",
+                    "type": "string"
+                },
+                "task_id": {
+                    "description": "任务id",
+                    "type": "string"
+                },
+                "user_id": {
+                    "description": "用户id",
+                    "type": "string"
+                }
+            }
+        }
+    },
+    "securityDefinitions": {
+        "ApiKeyAuth": {
+            "type": "apiKey",
+            "name": "x-app-id",
+            "in": "header"
+        }
+    }
+}`
+
+type swaggerInfo struct {
+	Version     string
+	Host        string
+	BasePath    string
+	Schemes     []string
+	Title       string
+	Description string
+}
+
+// SwaggerInfo holds exported Swagger Info so clients can modify it
+var SwaggerInfo = swaggerInfo{
+	Version:     "0.0.1",
+	Host:        "",
+	BasePath:    "/",
+	Schemes:     []string{},
+	Title:       "gin-blog API",
+	Description: "This is a gin blog example",
+}
+
+type s struct{}
+
+func (s *s) ReadDoc() string {
+	sInfo := SwaggerInfo
+	sInfo.Description = strings.Replace(sInfo.Description, "\n", "\\n", -1)
+
+	t, err := template.New("swagger_info").Funcs(template.FuncMap{
+		"marshal": func(v interface{}) string {
+			a, _ := json.Marshal(v)
+			return string(a)
+		},
+	}).Parse(doc)
+	if err != nil {
+		return doc
+	}
+
+	var tpl bytes.Buffer
+	if err := t.Execute(&tpl, sInfo); err != nil {
+		return doc
+	}
+
+	return tpl.String()
+}
+
+func init() {
+	swag.Register(swag.Name, &s{})
+}

+ 566 - 0
docs/swagger.json

@@ -0,0 +1,566 @@
+{
+    "swagger": "2.0",
+    "info": {
+        "description": "This is a gin blog example",
+        "title": "gin-blog API",
+        "contact": {},
+        "version": "0.0.1"
+    },
+    "basePath": "/",
+    "paths": {
+        "/area/getArea": {
+            "get": {
+                "description": "获取省市区",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "area"
+                ],
+                "summary": "获取省市区",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "地区code",
+                        "name": "p_code",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/cert/list": {
+            "get": {
+                "description": "获取证书列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "cert"
+                ],
+                "summary": "获取证书列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "类型:传1",
+                        "name": "type",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/cert/userList": {
+            "get": {
+                "description": "获取用户获得证书列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "cert"
+                ],
+                "summary": "获取用户获得证书列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/getBlacklist": {
+            "post": {
+                "description": "获取用户黑白名单列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取用户黑白名单列表",
+                "parameters": [
+                    {
+                        "description": "获取黑白名单列表",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.GetBlackListReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"username\":\"\",\"user_avatar\":\"https://\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/getInfo": {
+            "get": {
+                "description": "获取用户详细信息",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取用户详细信息",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_id",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "另一个用户id",
+                        "name": "other_id",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/order": {
+            "get": {
+                "description": "获取赛事订单",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取赛事订单",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/qualifying": {
+            "get": {
+                "description": "获取排位赛列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取排位赛列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/updateProfile": {
+            "post": {
+                "description": "修改用户资料",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "修改用户资料",
+                "parameters": [
+                    {
+                        "description": "修改用户资料请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.UpdateProfileReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/uploadBase64": {
+            "post": {
+                "description": "上传base64图片",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "上传base64图片",
+                "parameters": [
+                    {
+                        "description": "修改用户资料请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.UploadBaseReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/medal/list": {
+            "get": {
+                "description": "获取勋章列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "medal"
+                ],
+                "summary": "获取勋章列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "类型:传1",
+                        "name": "type",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/medal/userList": {
+            "get": {
+                "description": "获取用户获得勋章列表",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "medal"
+                ],
+                "summary": "获取用户获得勋章列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"id\":\"\",\"code\":\"\",\"name\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/quickLogin": {
+            "post": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "登录注册",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "登录注册",
+                "parameters": [
+                    {
+                        "description": "快捷登录请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.QuickLoginReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"user\":{}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/sms/get": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "获取短信验证码",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Sms"
+                ],
+                "summary": "获取短信验证码",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "手机号码",
+                        "name": "mobile",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "enum": [
+                            1,
+                            2,
+                            3,
+                            4
+                        ],
+                        "type": "integer",
+                        "default": 1,
+                        "description": "短信验证码类型(1=注册登录)",
+                        "name": "type",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/sms/remind": {
+            "post": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "发送提醒短信",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Sms"
+                ],
+                "summary": "发送提醒短信",
+                "parameters": [
+                    {
+                        "description": "短信请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.SendSmsReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "models.GetBlackListReq": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "description": "类型",
+                    "type": "integer"
+                },
+                "user_id": {
+                    "description": "用户ID",
+                    "type": "string"
+                }
+            }
+        },
+        "models.QuickLoginReq": {
+            "type": "object",
+            "properties": {
+                "mobile_phone": {
+                    "type": "string"
+                },
+                "valid_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.SendSmsReq": {
+            "type": "object",
+            "properties": {
+                "content": {
+                    "type": "string"
+                },
+                "mobile": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.UpdateProfileReq": {
+            "type": "object",
+            "properties": {
+                "area": {
+                    "description": "地区",
+                    "type": "string"
+                },
+                "birthday": {
+                    "description": "生日",
+                    "type": "string"
+                },
+                "gender": {
+                    "description": "性别",
+                    "type": "integer"
+                },
+                "height": {
+                    "description": "用户身高",
+                    "type": "integer"
+                },
+                "user_avatar": {
+                    "description": "地区",
+                    "type": "string"
+                },
+                "user_id": {
+                    "description": "用户代码",
+                    "type": "string"
+                },
+                "username": {
+                    "description": "会员昵称",
+                    "type": "string"
+                },
+                "weight": {
+                    "description": "用户体重",
+                    "type": "integer"
+                }
+            }
+        },
+        "models.UploadBaseReq": {
+            "type": "object",
+            "properties": {
+                "base64": {
+                    "description": "base64字符串",
+                    "type": "string"
+                },
+                "map_base": {
+                    "description": "mapBase64",
+                    "type": "string"
+                },
+                "task_id": {
+                    "description": "任务id",
+                    "type": "string"
+                },
+                "user_id": {
+                    "description": "用户id",
+                    "type": "string"
+                }
+            }
+        }
+    },
+    "securityDefinitions": {
+        "ApiKeyAuth": {
+            "type": "apiKey",
+            "name": "x-app-id",
+            "in": "header"
+        }
+    }
+}

+ 370 - 0
docs/swagger.yaml

@@ -0,0 +1,370 @@
+basePath: /
+definitions:
+  models.GetBlackListReq:
+    properties:
+      type:
+        description: 类型
+        type: integer
+      user_id:
+        description: 用户ID
+        type: string
+    type: object
+  models.QuickLoginReq:
+    properties:
+      mobile_phone:
+        type: string
+      valid_code:
+        type: string
+    type: object
+  models.SendSmsReq:
+    properties:
+      content:
+        type: string
+      mobile:
+        type: string
+    type: object
+  models.UpdateProfileReq:
+    properties:
+      area:
+        description: 地区
+        type: string
+      birthday:
+        description: 生日
+        type: string
+      gender:
+        description: 性别
+        type: integer
+      height:
+        description: 用户身高
+        type: integer
+      user_avatar:
+        description: 地区
+        type: string
+      user_id:
+        description: 用户代码
+        type: string
+      username:
+        description: 会员昵称
+        type: string
+      weight:
+        description: 用户体重
+        type: integer
+    type: object
+  models.UploadBaseReq:
+    properties:
+      base64:
+        description: base64字符串
+        type: string
+      map_base:
+        description: mapBase64
+        type: string
+      task_id:
+        description: 任务id
+        type: string
+      user_id:
+        description: 用户id
+        type: string
+    type: object
+info:
+  contact: {}
+  description: This is a gin blog example
+  title: gin-blog API
+  version: 0.0.1
+paths:
+  /area/getArea:
+    get:
+      description: 获取省市区
+      parameters:
+      - description: 地区code
+        in: query
+        name: p_code
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}'
+          schema:
+            type: string
+      summary: 获取省市区
+      tags:
+      - area
+  /cert/list:
+    get:
+      description: 获取证书列表
+      parameters:
+      - description: 类型:传1
+        in: query
+        name: type
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}'
+          schema:
+            type: string
+      summary: 获取证书列表
+      tags:
+      - cert
+  /cert/userList:
+    get:
+      description: 获取用户获得证书列表
+      parameters:
+      - description: 用户id
+        in: query
+        name: userId
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}'
+          schema:
+            type: string
+      summary: 获取用户获得证书列表
+      tags:
+      - cert
+  /customer/getBlacklist:
+    post:
+      description: 获取用户黑白名单列表
+      parameters:
+      - description: 获取黑白名单列表
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.GetBlackListReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","username":"","user_avatar":"https://"}}}'
+          schema:
+            type: string
+      summary: 获取用户黑白名单列表
+      tags:
+      - Customer
+  /customer/getInfo:
+    get:
+      description: 获取用户详细信息
+      parameters:
+      - description: 用户ID
+        in: query
+        name: user_id
+        required: true
+        type: string
+      - description: 另一个用户id
+        in: query
+        name: other_id
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}'
+          schema:
+            type: string
+      summary: 获取用户详细信息
+      tags:
+      - Customer
+  /customer/order:
+    get:
+      description: 获取赛事订单
+      parameters:
+      - description: 用户ID
+        in: query
+        name: user_id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}'
+          schema:
+            type: string
+      summary: 获取赛事订单
+      tags:
+      - Customer
+  /customer/qualifying:
+    get:
+      description: 获取排位赛列表
+      parameters:
+      - description: 用户ID
+        in: query
+        name: user_id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}'
+          schema:
+            type: string
+      summary: 获取排位赛列表
+      tags:
+      - Customer
+  /customer/updateProfile:
+    post:
+      description: 修改用户资料
+      parameters:
+      - description: 修改用户资料请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.UpdateProfileReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{}}'
+          schema:
+            type: string
+      summary: 修改用户资料
+      tags:
+      - Customer
+  /customer/uploadBase64:
+    post:
+      description: 上传base64图片
+      parameters:
+      - description: 修改用户资料请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.UploadBaseReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{}}'
+          schema:
+            type: string
+      summary: 上传base64图片
+      tags:
+      - Customer
+  /medal/list:
+    get:
+      description: 获取勋章列表
+      parameters:
+      - description: 类型:传1
+        in: query
+        name: type
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}'
+          schema:
+            type: string
+      summary: 获取勋章列表
+      tags:
+      - medal
+  /medal/userList:
+    get:
+      description: 获取用户获得勋章列表
+      parameters:
+      - description: 用户id
+        in: query
+        name: userId
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"id":"","code":"","name":""}}}'
+          schema:
+            type: string
+      summary: 获取用户获得勋章列表
+      tags:
+      - medal
+  /passport/quickLogin:
+    post:
+      consumes:
+      - application/json
+      description: 登录注册
+      parameters:
+      - description: 快捷登录请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.QuickLoginReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","user":{}}}'
+          schema:
+            type: string
+      security:
+      - ApiKeyAuth: []
+      summary: 登录注册
+      tags:
+      - Passport
+  /sms/get:
+    get:
+      description: 获取短信验证码
+      parameters:
+      - description: 手机号码
+        in: query
+        name: mobile
+        required: true
+        type: string
+      - default: 1
+        description: 短信验证码类型(1=注册登录)
+        enum:
+        - 1
+        - 2
+        - 3
+        - 4
+        in: query
+        name: type
+        required: true
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      security:
+      - ApiKeyAuth: []
+      summary: 获取短信验证码
+      tags:
+      - Sms
+  /sms/remind:
+    post:
+      consumes:
+      - application/json
+      description: 发送提醒短信
+      parameters:
+      - description: 短信请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.SendSmsReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      security:
+      - ApiKeyAuth: []
+      summary: 发送提醒短信
+      tags:
+      - Sms
+securityDefinitions:
+  ApiKeyAuth:
+    in: header
+    name: x-app-id
+    type: apiKey
+swagger: "2.0"

+ 731 - 0
docs/swagger/swagger.json

@@ -0,0 +1,731 @@
+{
+    "swagger": "2.0",
+    "info": {
+        "description": "lzyd user server api",
+        "title": "lzyd user server api",
+        "contact": {},
+        "license": {},
+        "version": "1.0"
+    },
+    "paths": {
+        "/app/launch": {
+            "get": {
+                "description": "获取App启动配置",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Config"
+                ],
+                "summary": "获取App启动配置",
+                "parameters": [
+                    {
+                        "type": "integer",
+                        "description": "客户端标识 1=iOS 2=Android 3=小程序",
+                        "name": "client",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\":\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/editCard": {
+            "post": {
+                "description": "修改身份证信息",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "修改身份证信息",
+                "parameters": [
+                    {
+                        "description": "修改身份证请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.EditCardReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/getInfo": {
+            "get": {
+                "description": "获取用户详细信息",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取用户详细信息",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_code",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"customer\":{\"user_id\":\"\",\"mobile_phone\":\"\",\"user_name\":\"靓妆会员\",\"avatar\":\"https://\",\"gender\":2,\"birthday\":\"\",\"area\":\"江苏省-南京市-鼓楼区\",\"email\":\"\",\"customer_level\":0,\"user_point\":0,\"user_money\":0.00,\"register_time\":\"\"}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/getPoints": {
+            "get": {
+                "description": "获取用户总积分",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "获取用户总积分",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "user_code",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/updateAvatar": {
+            "post": {
+                "description": "修改用户的头像",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "修改用户的头像",
+                "parameters": [
+                    {
+                        "description": "修改用户头像请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.UpdateAvatarReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/updateProfile": {
+            "post": {
+                "description": "修改用户资料",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "修改用户资料",
+                "parameters": [
+                    {
+                        "description": "修改用户资料请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.UpdateProfileReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/customer/updatePwd": {
+            "post": {
+                "description": "修改密码",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Customer"
+                ],
+                "summary": "修改密码",
+                "parameters": [
+                    {
+                        "description": "修改密码请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.UpdatePwdReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/bindMobile": {
+            "post": {
+                "description": "绑定手机号",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "绑定手机号",
+                "parameters": [
+                    {
+                        "description": "绑定手机号请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.BindMobileReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/getbackPwd": {
+            "post": {
+                "description": "密码找回",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "密码找回",
+                "parameters": [
+                    {
+                        "description": "密码找回请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.GetbackPwdReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/loginByThirdParty": {
+            "post": {
+                "description": "第三方登录",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "第三方登录",
+                "parameters": [
+                    {
+                        "description": "第三方登录请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.ThirdLoginReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/quickLogin": {
+            "post": {
+                "description": "快捷登录",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "快捷登录",
+                "parameters": [
+                    {
+                        "description": "快捷登录请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.QuickLoginReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"user\":{}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/register": {
+            "post": {
+                "description": "用户注册",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "用户注册",
+                "parameters": [
+                    {
+                        "description": "注册请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.RegisterReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"user\":{}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/passport/wechatLogin": {
+            "post": {
+                "description": "微信手机号码登录",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Passport"
+                ],
+                "summary": "微信手机号码登录",
+                "parameters": [
+                    {
+                        "description": "微信手机登录请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.WxLoginReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{\"token\":\"\",\"user\":{}}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/sms/get": {
+            "get": {
+                "description": "指定模板单发短信",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Sms"
+                ],
+                "summary": "指定模板单发短信",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "手机号码",
+                        "name": "mobile",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "enum": [
+                            1,
+                            2,
+                            3,
+                            4
+                        ],
+                        "type": "integer",
+                        "default": 1,
+                        "description": "短信验证码类型(1=注册 2=找回密码 3=绑定手机号 4=快捷登录)",
+                        "name": "type",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/sms/remind": {
+            "post": {
+                "description": "发送提醒短信",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Sms"
+                ],
+                "summary": "发送提醒短信",
+                "parameters": [
+                    {
+                        "description": "短信请求内容",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.SendSmsReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/upload/image": {
+            "post": {
+                "description": "单图片上传接口, name=image",
+                "consumes": [
+                    "multipart/form-data"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "Upload"
+                ],
+                "summary": "图片上传",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "上传者的用户ID",
+                        "name": "user_code",
+                        "in": "formData",
+                        "required": true
+                    },
+                    {
+                        "type": "file",
+                        "description": "上传的图片",
+                        "name": "image",
+                        "in": "formData",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":\"http://image.bitekun.xin/images/2019-03/test.png\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "models.BindMobileReq": {
+            "type": "object",
+            "properties": {
+                "mobile": {
+                    "type": "string"
+                },
+                "user_code": {
+                    "type": "string"
+                },
+                "valid_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.EditCardReq": {
+            "type": "object",
+            "properties": {
+                "card_back": {
+                    "type": "string"
+                },
+                "card_front": {
+                    "type": "string"
+                },
+                "card_id": {
+                    "type": "string"
+                },
+                "user_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.GetbackPwdReq": {
+            "type": "object",
+            "properties": {
+                "mobile": {
+                    "type": "string"
+                },
+                "password": {
+                    "type": "string"
+                },
+                "valid_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.QuickLoginReq": {
+            "type": "object",
+            "properties": {
+                "mobile": {
+                    "type": "string"
+                },
+                "valid_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.RegisterReq": {
+            "type": "object",
+            "properties": {
+                "area": {
+                    "type": "string"
+                },
+                "birthday": {
+                    "type": "string"
+                },
+                "gender": {
+                    "type": "integer"
+                },
+                "mobile": {
+                    "type": "string"
+                },
+                "password": {
+                    "type": "string"
+                },
+                "user_name": {
+                    "type": "string"
+                },
+                "valid_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.SendSmsReq": {
+            "type": "object",
+            "properties": {
+                "content": {
+                    "type": "string"
+                },
+                "mobile": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.ThirdLoginReq": {
+            "type": "object",
+            "properties": {
+                "avatar": {
+                    "type": "string"
+                },
+                "open_id": {
+                    "type": "string"
+                },
+                "user_name": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.UpdateAvatarReq": {
+            "type": "object",
+            "properties": {
+                "avatar": {
+                    "type": "string"
+                },
+                "user_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.UpdateProfileReq": {
+            "type": "object",
+            "properties": {
+                "area": {
+                    "type": "string"
+                },
+                "birthday": {
+                    "type": "string"
+                },
+                "city": {
+                    "type": "string"
+                },
+                "gender": {
+                    "type": "integer"
+                },
+                "identify": {
+                    "type": "string"
+                },
+                "nickname": {
+                    "type": "string"
+                },
+                "province": {
+                    "type": "string"
+                },
+                "user_code": {
+                    "type": "string"
+                },
+                "user_height": {
+                    "type": "integer"
+                },
+                "user_weight": {
+                    "type": "integer"
+                }
+            }
+        },
+        "models.UpdatePwdReq": {
+            "type": "object",
+            "properties": {
+                "new_pwd": {
+                    "type": "string"
+                },
+                "old_pwd": {
+                    "type": "string"
+                },
+                "user_code": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.WxLoginReq": {
+            "type": "object",
+            "properties": {
+                "mobile": {
+                    "type": "string"
+                }
+            }
+        }
+    }
+}

+ 480 - 0
docs/swagger/swagger.yaml

@@ -0,0 +1,480 @@
+definitions:
+  models.BindMobileReq:
+    properties:
+      mobile:
+        type: string
+      user_code:
+        type: string
+      valid_code:
+        type: string
+    type: object
+  models.EditCardReq:
+    properties:
+      card_back:
+        type: string
+      card_front:
+        type: string
+      card_id:
+        type: string
+      user_code:
+        type: string
+    type: object
+  models.GetbackPwdReq:
+    properties:
+      mobile:
+        type: string
+      password:
+        type: string
+      valid_code:
+        type: string
+    type: object
+  models.QuickLoginReq:
+    properties:
+      mobile:
+        type: string
+      valid_code:
+        type: string
+    type: object
+  models.RegisterReq:
+    properties:
+      area:
+        type: string
+      birthday:
+        type: string
+      gender:
+        type: integer
+      mobile:
+        type: string
+      password:
+        type: string
+      user_name:
+        type: string
+      valid_code:
+        type: string
+    type: object
+  models.SendSmsReq:
+    properties:
+      content:
+        type: string
+      mobile:
+        type: string
+    type: object
+  models.ThirdLoginReq:
+    properties:
+      avatar:
+        type: string
+      open_id:
+        type: string
+      user_name:
+        type: string
+    type: object
+  models.UpdateAvatarReq:
+    properties:
+      avatar:
+        type: string
+      user_code:
+        type: string
+    type: object
+  models.UpdateProfileReq:
+    properties:
+      area:
+        type: string
+      birthday:
+        type: string
+      city:
+        type: string
+      gender:
+        type: integer
+      identify:
+        type: string
+      nickname:
+        type: string
+      province:
+        type: string
+      user_code:
+        type: string
+      user_height:
+        type: integer
+      user_weight:
+        type: integer
+    type: object
+  models.UpdatePwdReq:
+    properties:
+      new_pwd:
+        type: string
+      old_pwd:
+        type: string
+      user_code:
+        type: string
+    type: object
+  models.WxLoginReq:
+    properties:
+      mobile:
+        type: string
+    type: object
+info:
+  contact: {}
+  description: lzyd user server api
+  license: {}
+  title: lzyd user server api
+  version: "1.0"
+paths:
+  /app/launch:
+    get:
+      description: 获取App启动配置
+      parameters:
+      - description: 客户端标识 1=iOS 2=Android 3=小程序
+        in: query
+        name: client
+        required: true
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success":"data":{}}'
+          schema:
+            type: string
+      summary: 获取App启动配置
+      tags:
+      - Config
+  /customer/editCard:
+    post:
+      description: 修改身份证信息
+      parameters:
+      - description: 修改身份证请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.EditCardReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success"}'
+          schema:
+            type: string
+      summary: 修改身份证信息
+      tags:
+      - Customer
+  /customer/getInfo:
+    get:
+      description: 获取用户详细信息
+      parameters:
+      - description: 用户ID
+        in: query
+        name: user_code
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","customer":{"user_id":"","mobile_phone":"","user_name":"靓妆会员","avatar":"https://","gender":2,"birthday":"","area":"江苏省-南京市-鼓楼区","email":"","customer_level":0,"user_point":0,"user_money":0.00,"register_time":""}}}'
+          schema:
+            type: string
+      summary: 获取用户详细信息
+      tags:
+      - Customer
+  /customer/getPoints:
+    get:
+      description: 获取用户总积分
+      parameters:
+      - description: 用户ID
+        in: query
+        name: user_code
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{}}'
+          schema:
+            type: string
+      summary: 获取用户总积分
+      tags:
+      - Customer
+  /customer/updateAvatar:
+    post:
+      description: 修改用户的头像
+      parameters:
+      - description: 修改用户头像请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.UpdateAvatarReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success"}'
+          schema:
+            type: string
+      summary: 修改用户的头像
+      tags:
+      - Customer
+  /customer/updateProfile:
+    post:
+      description: 修改用户资料
+      parameters:
+      - description: 修改用户资料请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.UpdateProfileReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{}}'
+          schema:
+            type: string
+      summary: 修改用户资料
+      tags:
+      - Customer
+  /customer/updatePwd:
+    post:
+      description: 修改密码
+      parameters:
+      - description: 修改密码请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.UpdatePwdReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success"}'
+          schema:
+            type: string
+      summary: 修改密码
+      tags:
+      - Customer
+  /passport/bindMobile:
+    post:
+      consumes:
+      - application/json
+      description: 绑定手机号
+      parameters:
+      - description: 绑定手机号请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.BindMobileReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success"}'
+          schema:
+            type: string
+      summary: 绑定手机号
+      tags:
+      - Passport
+  /passport/getbackPwd:
+    post:
+      consumes:
+      - application/json
+      description: 密码找回
+      parameters:
+      - description: 密码找回请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.GetbackPwdReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success"}'
+          schema:
+            type: string
+      summary: 密码找回
+      tags:
+      - Passport
+  /passport/loginByThirdParty:
+    post:
+      consumes:
+      - application/json
+      description: 第三方登录
+      parameters:
+      - description: 第三方登录请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.ThirdLoginReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{}}'
+          schema:
+            type: string
+      summary: 第三方登录
+      tags:
+      - Passport
+  /passport/quickLogin:
+    post:
+      consumes:
+      - application/json
+      description: 快捷登录
+      parameters:
+      - description: 快捷登录请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.QuickLoginReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","user":{}}}'
+          schema:
+            type: string
+      summary: 快捷登录
+      tags:
+      - Passport
+  /passport/register:
+    post:
+      consumes:
+      - application/json
+      description: 用户注册
+      parameters:
+      - description: 注册请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.RegisterReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","user":{}}}'
+          schema:
+            type: string
+      summary: 用户注册
+      tags:
+      - Passport
+  /passport/wechatLogin:
+    post:
+      consumes:
+      - application/json
+      description: 微信手机号码登录
+      parameters:
+      - description: 微信手机登录请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.WxLoginReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{"token":"","user":{}}}'
+          schema:
+            type: string
+      summary: 微信手机号码登录
+      tags:
+      - Passport
+  /sms/get:
+    get:
+      description: 指定模板单发短信
+      parameters:
+      - description: 手机号码
+        in: query
+        name: mobile
+        required: true
+        type: string
+      - default: 1
+        description: 短信验证码类型(1=注册 2=找回密码 3=绑定手机号 4=快捷登录)
+        enum:
+        - 1
+        - 2
+        - 3
+        - 4
+        in: query
+        name: type
+        required: true
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 指定模板单发短信
+      tags:
+      - Sms
+  /sms/remind:
+    post:
+      consumes:
+      - application/json
+      description: 发送提醒短信
+      parameters:
+      - description: 短信请求内容
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.SendSmsReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 发送提醒短信
+      tags:
+      - Sms
+  /upload/image:
+    post:
+      consumes:
+      - multipart/form-data
+      description: 单图片上传接口, name=image
+      parameters:
+      - description: 上传者的用户ID
+        in: formData
+        name: user_code
+        required: true
+        type: string
+      - description: 上传的图片
+        in: formData
+        name: image
+        required: true
+        type: file
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":"http://image.bitekun.xin/images/2019-03/test.png"}'
+          schema:
+            type: string
+      summary: 图片上传
+      tags:
+      - Upload
+swagger: "2.0"

File diff suppressed because it is too large
+ 7489 - 0
logs/gouser.log


BIN
lzyd-front-user-api


+ 81 - 0
main.go

@@ -0,0 +1,81 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	//"github.com/zsais/go-gin-prometheus"
+	"lzyd-user-api/common"
+	"lzyd-user-api/router"
+	"os"
+	"path"
+	"github.com/TingYunAPM/go"
+)
+
+// @title lzyd user server api
+// @version 1.0
+// @description lzyd user server api
+// @title gin-blog API
+// @version 0.0.1
+// @description This is a gin blog example
+// @securityDefinitions.apikey ApiKeyAuth
+// @in header
+// @name x-app-id
+// @BasePath /
+func main() {
+
+	var err error
+	fPath, _ := os.Getwd()
+	fPath = path.Join(fPath, "conf")
+	configPath := flag.String("c", fPath, "config file path")
+	flag.Parse()
+	err = common.LoadConfigInformation(*configPath)
+	if err != nil {
+		return
+	}
+
+	//初始化tingyun: 应用名称、帐号等在tingyun.json中配置
+
+	tingyun.AppInit("tingyun.json")
+
+	defer tingyun.AppStop()
+
+	//原有业务逻辑
+
+	if common.ServerInfo.Mode == "debug" {
+		gin.SetMode(gin.DebugMode)
+
+	} else if common.ServerInfo.Mode == "release" {
+		gin.SetMode(gin.ReleaseMode)
+	}
+
+	defer func() {
+		_ = common.LogSync()
+	}()
+
+	//router init
+	router := router.InitRouter()
+	//p := ginprometheus.NewPrometheus("gin")
+	//p.Use(router)
+
+	server := common.ServerInfo
+	serverInfo := server.Host + ":" + server.Port
+
+	// restart
+	if server.EnableHttps {
+		fmt.Println("server start https")
+		err := router.RunTLS(serverInfo, server.CertFile, server.KeyFile)
+		fmt.Println(err)
+		if err != nil {
+			common.LogError("server start failed: " + err.Error())
+		}
+	} else {
+		fmt.Printf("server start info: %s\n", serverInfo)
+		common.LogInfo("server start info: " + serverInfo)
+		common.LogSync()
+		err := router.Run(serverInfo)
+		if err != nil {
+			common.LogError("server start failed: " + err.Error())
+		}
+	}
+}

+ 26 - 0
middleware/cors.go

@@ -0,0 +1,26 @@
+package middleware
+
+import (
+	"github.com/gin-gonic/gin"
+	"net/http"
+)
+
+// 处理跨域请求,支持options访问
+func Cors() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		method := c.Request.Method
+		c.Header("Access-Control-Allow-Origin", "*")
+		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id\"")
+		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
+		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
+		c.Header("Access-Control-Allow-Credentials", "true")
+
+		// 放行所有OPTIONS方法
+		if method == "OPTIONS" {
+			c.AbortWithStatus(http.StatusNoContent)
+		}
+
+		// 处理请求
+		c.Next()
+	}
+}

+ 205 - 0
middleware/sign.go

@@ -0,0 +1,205 @@
+package middleware
+
+import (
+	"bytes"
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/json"
+	"github.com/gin-gonic/gin"
+	"io/ioutil"
+	"lzyd-user-api/utils"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+)
+
+/**
+Sign的格式如下:
+所有的请求参数加上appkey=lzwg-app-N78ya51qaz2wsx!排序后,再MD5
+*/
+const AppKey string = "lzyd-sign-7c423d19cb2b"
+
+func ValidSign(forceValid bool) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		// 暂时不对swagger做强校验
+		if strings.Contains(c.Request.RequestURI, "swagger") {
+			c.Next()
+			return
+		}
+		if strings.Contains(c.Request.Header.Get("Referer"), "swagger") {
+			c.Next()
+			return
+		}
+		if !forceValid {
+			c.Next()
+			return
+		}
+		validSign(c, AppKey)
+	}
+}
+
+//从Header验证参数
+func ValidHeaderParams() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		//判断是否合法请求
+		client := c.Request.Header.Get("client")
+		guid := c.Request.Header.Get("guid")
+		timestamp := c.Request.Header.Get("timestamp")
+		sig := c.Request.Header.Get("sig")
+		if client == "2" { //wap鉴权
+			//sig:md5(client+'lz2019_random'+uuid+timestamp)
+			_sig := Md5Encode(client + "lz2019_random" + guid + timestamp)
+			if _sig == sig { //鉴权通过
+				//fmt.Println("_sig == sig")
+				//c.JSON(http.StatusOK, gin.H{"message": "授权成功"})
+				c.Next()
+			} else { //请求非法
+				//fmt.Println("_sig != sig")
+				c.Abort()
+				c.JSON(http.StatusForbidden, gin.H{"message": "访问未授权"})
+				// return可省略, 只要前面执行Abort()就可以让后面的handler函数不再执行
+				return
+			}
+		} else {
+			c.Next()
+		}
+	}
+}
+
+func validSign(c *gin.Context, appKey string) {
+
+	var (
+		inSign  string
+		outSign string
+	)
+
+	if c.Request.Method == "GET" {
+		values := c.Request.URL.Query()
+		if len(values) <= 0 {
+			c.Next()
+			return
+		}
+		inSign = values.Get("sign")
+		if len(inSign) == 0 {
+			c.JSON(http.StatusOK, gin.H{
+				"code":    -1,
+				"message": "未传入签名参数",
+			})
+			c.Abort()
+			return
+		}
+		outSign = calculateSignFromValues(values, appKey)
+	} else {
+		c.Request.ParseMultipartForm(32 << 20)
+		formData := c.Request.PostForm
+		if len(formData) > 0 {
+			inSign = formData.Get("sign")
+			if len(inSign) == 0 {
+				c.JSON(http.StatusOK, gin.H{
+					"code":    -1,
+					"message": "未传入签名参数",
+				})
+				c.Abort()
+				return
+			}
+			outSign = calculateSignFromValues(formData, appKey)
+		} else {
+			var params map[string]interface{}
+			data, _ := c.GetRawData()
+			err := json.Unmarshal(data, &params)
+			if err != nil {
+				panic(err)
+			}
+			inSign = utils.Interface2String(params["sign"])
+			if len(inSign) == 0 {
+				c.JSON(http.StatusOK, gin.H{
+					"code":    -1,
+					"message": "未传入签名参数",
+				})
+				c.Abort()
+				return
+			}
+			outSign = calculateSignFromJsonBody(params, appKey)
+
+			// 很关键,把读过的字节流重新放到body
+			c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data))
+		}
+	}
+	if outSign != inSign {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    -1,
+			"message": "签名验证错误",
+		})
+		c.Abort()
+	}
+
+	c.Next()
+}
+
+func calculateSignFromValues(values url.Values, appKey string) string {
+	values.Del("sign")
+	values.Add("secret", appKey)
+	if len(values) > 0 {
+		// 先对Key进行排序
+		var keywords []string
+		for key, _ := range values {
+			keywords = append(keywords, key)
+		}
+		sort.Strings(keywords)
+		// 再根据Key查找参数Map, 并拼接成字符串
+		var stringBuffer bytes.Buffer
+		keywordsCnt := len(keywords)
+		for i := 0; i < keywordsCnt-1; i++ {
+			keyword := keywords[i]
+			stringBuffer.WriteString(keyword + "=" + values.Get(keyword))
+			stringBuffer.WriteString("&")
+		}
+		lastKeyword := keywords[keywordsCnt-1]
+		stringBuffer.WriteString(lastKeyword + "=" + values.Get(lastKeyword))
+		// 最后MD5加密
+		hash := md5.New()
+		hash.Write(stringBuffer.Bytes())
+		return hex.EncodeToString(hash.Sum(nil))
+	}
+	return ""
+}
+
+func calculateSignFromJsonBody(params map[string]interface{}, appKey string) string {
+	delete(params, "sign")
+	params["secret"] = appKey
+	if len(params) > 0 {
+		// 先对Key进行排序
+		var keywords []string
+		for key, _ := range params {
+			keywords = append(keywords, key)
+		}
+		sort.Strings(keywords)
+		// 再根据Key查找参数Map, 并拼接成字符串
+		var stringBuffer bytes.Buffer
+		keywordsCnt := len(keywords)
+		for i := 0; i < keywordsCnt-1; i++ {
+			keyword := keywords[i]
+			stringBuffer.WriteString(keyword + "=" + utils.Interface2String(params[keyword]))
+			stringBuffer.WriteString("&")
+		}
+		lastKeyword := keywords[keywordsCnt-1]
+		stringBuffer.WriteString(lastKeyword + "=" + utils.Interface2String(params[lastKeyword]))
+		// 最后MD5加密
+		hash := md5.New()
+		hash.Write(stringBuffer.Bytes())
+		return hex.EncodeToString(hash.Sum(nil))
+	}
+	return ""
+}
+
+
+// 生成32位md5字串
+func Md5Encode(s string) string {
+	h := md5.New()
+	h.Write([]byte(s))
+	return hex.EncodeToString(h.Sum(nil))
+}
+
+
+

+ 23 - 0
models/area.go

@@ -0,0 +1,23 @@
+package models
+
+
+/**
+请求地区数据返回参数
+*/
+type ReqProvince struct {
+	Id     string `json:"id"`             // 用户代码
+	Code     string `json:"code"`             // 用户代码
+	Name     string `json:"name"`             // 用户代码
+}
+type ReqCity struct {
+	Id     string `json:"id"`             // 用户代码
+	Code     string `json:"code"`             // 用户代码
+	Name     string `json:"name"`             // 用户代码
+	ProvinceCode     string `json:"province_code"`             // 用户代码
+}
+type ReqArea struct {
+	Id     string `json:"id"`             // 用户代码
+	Code     string `json:"code"`             // 用户代码
+	Name     string `json:"name"`             // 用户代码
+	CityCode     string `json:"province_code"`             // 用户代码
+}

+ 29 - 0
models/cert.go

@@ -0,0 +1,29 @@
+package models
+
+
+/**
+请求地区数据返回参数
+*/
+type LzydCert struct {
+	Id         string `json:"id"`             // 序列id
+	CertId     string `json:"cert_id"`             // 证书id
+	Name       string `json:"name"`             // 证书简称
+	Content    string `json:"content"`             // 证书详细内容
+	Rule       string `json:"rule"`             // 证书规则
+	Picture    string `json:"picture"`             // 证书图片
+	Sponsor    string `json:"sponsor"`             // 证书主办方
+	Council    string `json:"council"`             // 证书委员会
+	CertType   string `json:"cert_type"`             // 证书类型
+	FullName   string `json:"full_name"`             // 证书全称
+	CreatedAt  string `json:"created_at"`             // 证书创建时间
+	UpdatedAt  string `json:"updated_at"`             // 证书更新时间
+	DeletedAt  string `json:"deleted_at"`             // 证书删除时间
+	Icon       string `json:"icon"`             // 证书简称
+	GetIcon    string `json:"get_icon"`             // 证书简称
+}
+type LzydCertUser struct {
+	Id          string `json:"id"`             // 序列id
+	CertId      string `json:"cert_id"`             // 证书id
+	UserId      string `json:"user_id"`             // 证书id
+	GetCertTime string `json:"get_cert_time"`             // 证书id
+}

+ 21 - 0
models/err.go

@@ -0,0 +1,21 @@
+package models
+
+type Error struct {
+	Code    int
+	Message string
+}
+
+func New(code int, msg string) *Error {
+	return &Error{
+		Code:    code,
+		Message: msg,
+	}
+}
+
+func (e *Error) ErrCode() int {
+	return e.Code
+}
+
+func (e *Error) ErrMessage() string {
+	return e.Message
+}

+ 15 - 0
models/imageinfo.go

@@ -0,0 +1,15 @@
+package models
+
+import "github.com/jinzhu/gorm"
+
+type ImageInfo struct {
+	UserId string `json:"user_id"`
+	Path   string `json:"path"`
+	URL    string `json:"url"`
+}
+
+func (image *ImageInfo) Save(db *gorm.DB) error {
+	sql := "INSERT INTO image_info(user_id, path, url) VALUES (?,?,?)"
+	err := db.Exec(sql, image.UserId, image.Path, image.URL).Error
+	return err
+}

+ 50 - 0
models/launch.go

@@ -0,0 +1,50 @@
+package models
+
+type SystemItem struct {
+	Name  string
+	Value string
+	Type  string
+}
+type SystemDict []*SystemItem
+
+type AppConfig struct {
+	ServicePhone string      `json:"service_phone"` /// 客服电话
+	URLInfo      URLInfo     `json:"url_info"`      /// 返回Web地址信息
+	ShareInfo    ShareInfo   `json:"share_info"`    /// 返回App分享信息
+	VersionInfo  VersionInfo `json:"version_info"`  /// 返回版本信息
+}
+
+type URLInfo struct {
+	Feedback       string `json:"feedback"`        /// 意见反馈地址
+	Agreement      string `json:"agreement"`       /// 隐私协议
+	AppIntro       string `json:"app_intro"`       /// App介绍
+	AboutUs        string `json:"about_us"`        /// 关于我们
+	Sign           string `json:"sign"`            /// 签到
+	Statement      string `json:"statement"`       /// 免责声明
+	VideoAgreement string `json:"video_agreement"` /// 商品上传协议
+}
+
+type ShareInfo struct {
+	Title   string `json:"title"`
+	Summary string `json:"summary"`
+	Icon    string `json:"icon"`
+	URL     string `json:"url"`
+}
+
+type VersionInfo struct {
+	Client      int    `json:"client"`       // 客户端标识  1:ios 2=android
+	Number      string `json:"number"`       // 版本号
+	Content     string `json:"content"`      // 更新内容
+	ForceUpdate int    `json:"force_update"` // 是否强制更新
+	DownloadUrl string `json:"download_url"` // 下载地址
+}
+
+// 获取值
+func (m SystemDict) GetValue(name string) string {
+	for _, item := range m {
+		if item.Name == name {
+			return item.Value
+		}
+	}
+	return ""
+}

+ 44 - 0
models/logger.go

@@ -0,0 +1,44 @@
+package models
+
+type LoginLog struct {
+	UserId    string  `json:"user_id"`
+	LoginType int     `json:"login_type"`
+	LoginIP   string  `json:"login_ip"`
+	Address   string  `json:"address"`
+	Latitude  float64 `json:"latitude"`
+	Longitude float64 `json:"longitude"`
+}
+
+type TaskLog struct {
+	TaskID   int64  `json:"task_id"`
+	TaskType int    `json:"task_type"`
+	UserId   string `json:"user_id"`
+}
+
+type CustomerTmp struct {
+	SourceType int    `json:"source_type"`
+	SourceID   string `json:"source_id"`
+	Extend     string `json:"extend"`
+	TotalPoint int64  `json:"total_point"`
+}
+
+/**
+保存登录日志
+*/
+/*
+func (log *LoginLog) Save(db *gorm.DB) error {
+	// 先校验今天是否已经记录了登录日志
+	var (
+		sql   string
+		count int
+	)
+	sql = "SELECT COUNT(login_id) as count FROM user_login_log WHERE user_id = ? AND UNIX_TIMESTAMP(CAST(login_time AS DATE)) = UNIX_TIMESTAMP(CAST(SYSDATE() AS DATE))"
+	db.Raw(sql, log.UserId).Count(&count)
+	if count > 0 {
+		return nil
+	}
+	sql = `INSERT INTO user_login_log(user_id, login_ip, address, login_type, latitude, longitude) VALUES(?,?,?,?,?,?)`
+	err := db.Exec(sql, log.UserId, log.LoginIP, log.Address, log.LoginType, log.Latitude, log.Longitude).Error
+	return err
+}
+*/

+ 26 - 0
models/medal.go

@@ -0,0 +1,26 @@
+package models
+
+
+/**
+请求地区数据返回参数
+*/
+type LzydMedal struct {
+	Id     string `json:"id"`             // 序列id
+	MedalId     string `json:"cert_id"`             // 证书id
+	Name     string `json:"name"`             // 勋章简称
+	Content     string `json:"content"`             // 勋章详细内容
+	Rule     string `json:"rule"`             // 勋章规则
+	CertType     string `json:"cert_type"`             // 勋章类型
+	FullName     string `json:"full_name"`             // 勋章全称
+	CreatedAt     string `json:"created_at"`             // 勋章创建时间
+	UpdatedAt     string `json:"updated_at"`             // 勋章更新时间
+	DeletedAt     string `json:"deleted_at"`             // 勋章删除时间
+	Icon     string `json:"icon"`             // 勋章简称
+	GetIcon     string `json:"get_icon"`             // 勋章简称
+}
+type LzydMedalUser struct {
+	Id     string `json:"id"`             // 序列id
+	MedalId     string `json:"cert_id"`             // 勋章id
+	UserId     string `json:"user_id"`             // 用户id
+	GetCertTime   string `json:"get_cert_time"`             // 获得勋章时间
+}

+ 144 - 0
models/passport.go

@@ -0,0 +1,144 @@
+package models
+
+import (
+	"github.com/jinzhu/gorm"
+	"lzyd-user-api/common"
+	"net/http"
+	"time"
+)
+
+/**
+注册请求参数
+*/
+type RegisterReq struct {
+	Mobile    string `json:"mobile"`
+	Password  string `json:"password"`
+	ValidCode string `json:"valid_code"`
+	UserName  string `json:"user_name"`
+	Gender    int    `json:"gender,omitempty"`
+	Birthday  string `json:"birthday,omitempty"`
+	Area      string `json:"area,omitempty"`
+}
+
+/**
+手动注册请求参数
+*/
+type RegisterManualReq struct {
+	Mobile string `json:"mobile"`
+}
+
+/**
+账号密码登录请求参数
+*/
+type LoginReq struct {
+	Mobile   string `json:"mobile"`
+	Password string `json:"password"`
+}
+
+/**
+手机号码登录请求参数
+*/
+type WxLoginReq struct {
+	Mobile string `json:"mobile"`
+}
+
+/**
+快捷登录请求参数
+*/
+type QuickLoginReq struct {
+	MobilePhone    string `json:"mobile_phone"`
+	ValidCode string `json:"valid_code"`
+}
+
+/**
+手机号登录请求参数
+*/
+type MobileLoginReq struct {
+	Mobile string `json:"mobile"`
+}
+
+/**
+第三方登录请求参数
+*/
+type ThirdLoginReq struct {
+	OpenId   string `json:"open_id"`
+	UserName string `json:"user_name,omitempty"`
+	Avatar   string `json:"avatar,omitempty"`
+}
+
+/**
+找回密码请求参数
+*/
+type GetbackPwdReq struct {
+	Mobile    string `json:"mobile"`
+	ValidCode string `json:"valid_code"`
+	Password  string `json:"password"`
+}
+
+/**
+绑定手机号请求参数
+*/
+type BindMobileReq struct {
+	UserCode  string `json:"user_code"`
+	Mobile    string `json:"mobile"`
+	ValidCode string `json:"valid_code"`
+}
+
+/**
+登录信息返回
+*/
+type LoginResp struct {
+	UserId    int64  `json:"user_id"`
+	UserCode  string `json:"user_code"`
+	Mobile    string `json:"mobile"`
+	OpenID    string `json:"open_id"`
+	LoginType int    `json:"login_type"`
+}
+
+/**
+查询的手机号与密码信息
+*/
+type LoginInfo struct {
+	UserId   string `json:"user_id"`
+	Mobile   string `json:"mobile"`
+	Password string `json:"password"`
+}
+
+/**
+[Mysql]修改最后一次登录时间
+*/
+func (u *UserInfo) UpdateLoginTime() error {
+	sql := "UPDATE lzyd_user SET login_time = ? WHERE user_id = ?"
+	err := common.DB.Exec(sql, time.Now(), u.UserId).Error
+	return err
+}
+
+/**
+[Mysql]登录后处理
+*/
+func (u *UserInfo) LoginHandler(r *http.Request, loginType int) error {
+	if err := u.UpdateLoginTime(); err != nil {
+		return err
+	}
+	return nil
+}
+
+/**
+[Mysql]绑定用户手机号
+*/
+func (u *UserInfo) UpdateBindTel(db *gorm.DB) error {
+	sql := "UPDATE lzyd_user SET mobile = ? WHERE user_id = ?"
+	err := db.Exec(sql, u.MobilePhone, u.UserId).Error
+	return err
+}
+
+/**
+[Mysql]修改用户密码
+*/
+func (u *LoginInfo) UpdatePwd(db *gorm.DB, pwd string) error {
+	sql := "UPDATE lzyd_user SET password = ? WHERE user_id = ?"
+	err := db.Exec(sql, pwd, u.UserId).Error
+	return err
+}
+
+

+ 72 - 0
models/sms.go

@@ -0,0 +1,72 @@
+package models
+
+import (
+	"github.com/jinzhu/gorm"
+	"time"
+)
+
+type SendSmsReq struct {
+	Mobile  string `json:"mobile"`
+	Content string `json:"content"`
+}
+
+type ValidSms struct {
+	SmsId        int64  `json:"sms_id"`
+	Mobile    string `json:"mobile"`
+	ValidCode string `json:"valid_code"`
+	SmsType   int    `json:"sms_type"`
+	CreateAt  int64  `json:"create_at"`
+}
+
+type SmsUser struct {
+	isDelete  int64  `json:"is_delete"`
+	MobilePhone    string `json:"mobile_phone"`
+	CreateAt  int64  `json:"create_at"`
+}
+
+type RemindSms struct {
+	ID      int64 `gorm:"column:id"`
+	Mobile  string
+	SmsType int
+	Content string
+	IpAddr  string
+}
+
+/// 定义腾讯短信模板结构
+type Tel struct {
+	Mobile     string `json:"mobile"`     // 手机号码
+	NationCode string `json:"nationcode"` // 国家码
+}
+type SmsTempl struct {
+	Ext    string   `json:"ext"`    // 用户的 session 内容,腾讯 server 回包中会原样返回,可选字段,不需要就填空
+	Extend string   `json:"extend"` // 短信码号扩展号,格式为纯数字串,其他格式无效
+	Params []string `json:"params"` // 模板参数,若模板没有参数,请提供为空数组
+	Sig    string   `json:"sig"`    // App凭证,sig字段根据公式sha256(appkey=$appkey&random=$random&time=$time&mobile=$mobile)生成
+	Sign   string   `json:"sign"`   // 短信签名,如果使用默认签名,该字段可缺省
+	Tel    Tel      `json:"tel"`    // 电话号码
+	Time   int64    `json:"time"`   // 请求发起时间,UNIX 时间戳(单位:秒),如果和系统时间相差超过10分钟则会返回失败
+	TplID  int64    `json:"tpl_id"` // 模板ID,在控制台审核通过的模板ID
+}
+
+/// 定义腾讯云短信响应内容
+type SmsTemplResp struct {
+	Result int    `json:"result"` // 0表示成功 非0表示失败
+	ErrMsg string `json:"errmsg"` // 错误消息,result 非0时的具体错误信息
+	SID    string `json:"sid"`    // 本次发送标识id,标识一次短信下发记录
+}
+
+/**
+[数据库操作]插入短信验证码数据
+*/
+func (sms *ValidSms) Save(db *gorm.DB) error {
+	sql := `INSERT INTO lzyd_sms_valid(mobile_phone, valid_code, sms_type, create_at) VALUES (?,?,?,?)`
+	err := db.Exec(sql, sms.Mobile, sms.ValidCode, sms.SmsType, time.Now().Unix()).Error
+	return err
+}
+
+func (sms *RemindSms) Save(db *gorm.DB) error {
+	sql := "INSERT INTO sms_remind_info(mobile, sms_type, content, ip_addr) VALUES(?,?,?,?)"
+	err := db.Exec(sql, sms.Mobile, sms.SmsType, sms.Content, sms.IpAddr).Error
+	return err
+}
+

+ 587 - 0
models/user.go

@@ -0,0 +1,587 @@
+package models
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/jinzhu/gorm"
+	"gopkg"
+	"lzyd-user-api/common"
+	"math/rand"
+	"strconv"
+	"time"
+)
+
+/**
+修改用户信息请求参数
+*/
+type UpdateProfileReq struct {
+	UserId     string `json:"user_id"`             // 用户代码
+	UserName   string `json:"username"`              // 会员昵称
+	Birthday   string `json:"birthday"`    // 生日
+	Height 	   int    `json:"height,omitempty"` // 用户身高
+	Weight     int    `json:"weight,omitempty"` // 用户体重
+	Gender     int    `json:"gender,omitempty"`      // 性别
+	Area       string `json:"area"`        // 地区
+	UserAvatar	   string `json:"user_avatar"`        // 地区
+}
+
+type UserRelationResp struct {
+	AttentionUserId   string   `json:"attention_user_id"   gorm:"column:attention_user_id"`
+}
+
+type TaskList struct {
+	TaskId   string   `json:"task_id"   gorm:"column:task_id"`
+}
+
+/**
+修改用户头像请求参数
+*/
+type UpdateAvatarReq struct {
+	UserId       string `json:"user_id"` // 用户代码
+	UserAvatar   string `json:"user_avatar"`    // 头像
+}
+
+/**
+上传身份证图片请求参数
+*/
+type EditCardReq struct {
+	UserCode  string `json:"user_code"`  // 用户代码
+	CardId    string `json:"card_id"`    // 身份证号码
+	CardFront string `json:"card_front"` // 身份证正面照
+	CardBack  string `json:"card_back"`  // 身份证反面照
+}
+
+/**
+修改用户密码请求参数
+*/
+type UpdatePwdReq struct {
+	UserCode string `json:"user_code"` // 用户代码
+	OldPwd   string `json:"old_pwd"`   // 旧密码
+	NewPwd   string `json:"new_pwd"`   // 新密码
+}
+
+/**
+修改绑定手机号请求参数
+*/
+type UpdateMobileReq struct {
+	UserCode  string `json:"user_code"`  // 用户代码
+	OldMobile string `json:"old_mobile"` // 旧的手机号码
+	NewMobile string `json:"new_mobile"` // 需要绑定的手机号
+	ValidCode string `json:"valid_code"` // 手机验证码
+}
+
+/**
+验证手机号请求参数
+*/
+type ValidMobileReq struct {
+	Mobile    string `json:"mobile"`     // 手机号码
+	ValidCode string `json:"valid_code"` // 手机验证码
+}
+
+
+type YuedongCode struct {
+	YuedongId  string  `gorm:"yuedong_id:id;" json:"yuedong_id"`     // 悦动id
+}
+
+/**
+获取黑白名单请求参数
+*/
+type GetBlackListReq struct {
+	UserId    string `json:"user_id"`     // 用户ID
+	Type 	  int `json:"type"` 		  // 类型
+}
+
+/**
+绑定微信请求参数
+*/
+type BindOpenIdReq struct {
+	UserId string `json:"user_id"` // 用户代码
+	OpenID   string `json:"open_id"`   // 微信号码
+	BindType int    `json:"bind_type"` // 绑定类型(10=微信,11=QQ,12=微博)
+}
+
+/**
+获取黑名单列表
+*/
+type BlackListReq struct {
+	UserId string `json:"user_id"` // 用户代码
+	UserAvatar   string `json:"user_avatar"`   // 用户头像
+	Username string    `json:"username"` // 用户昵称
+	FansNum  int 		`json:"fans_num"` // 用户粉丝数
+	VideosNum  int 		`json:"videos_num"` // 用户粉丝数
+}
+
+/**
+获取黑名单列表
+*/
+type VideoListReq struct {
+	UserId string `json:"user_id"` // 用户代码
+}
+
+/**
+获取黑名单信息
+*/
+type BlackListResp struct {
+	UserId string `json:"user_code"` // 用户代码
+	UserAvatar   string `json:"user_avatar"`   // 用户头像
+	UserName string    `json:"user_name"` // 用户昵称
+}
+
+/**
+客户信息
+*/
+type UserResp struct {
+	Id     int64  `gorm:"column:id;primary_key;auto_increment" json:"id"` //自增ID
+	UserId     string `gorm:"column:user_id" json:"user_id"`  //用户ID
+	UserName     string `gorm:"column:username" json:"username"`  //昵称
+	Password     string `gorm:"column:password" json:"password"`//密码
+	RealName     string `gorm:"column:real_name" json:"real_name"`//真实姓名
+	UserAvatar       string `gorm:"column:user_avatar" json:"user_avatar"`//头像
+	MobilePhone       string `gorm:"column:mobile_phone" json:"mobile_phone"`//手机号
+	Gender       int    `gorm:"column:gender" json:"gender"`//性别
+	Height   int    `gorm:"column:hieght" json:"height"`//身高
+	Weight   int    `gorm:"column:weight" json:"weight"`//体重
+	Birthday     string `gorm:"column:birthday" json:"birthday"`//生日
+	Address         string `gorm:"column:address" json:"address"`//详细地址
+	Area         string `gorm:"column:area" json:"area"`//地区
+	QrCode     string `gorm:"column:qr_code" json:"qr_code"` //二维码
+	UserGrade     string    `gorm:"column:user_grade" json:"user_grade"`//排位赛等级
+	LoginTime  string  `gorm:"column:login_time" json:"login_time"`//登录时间
+	RegisterTime  string  `gorm:"column:register_time" json:"register_time"`//注册时间
+	LikeNum  int64  `gorm:"column:like_num" json:"like_num"`//点赞数
+	FansNum  int64  `gorm:"column:fans_num" json:"fans_num"`//粉丝数
+	AttenNum  int64  `gorm:"column:atten_num" json:"atten_num"`//关注数
+	TotalDistance  int  `gorm:"column:total_distance" json:"total_distance"`//总公里数
+	TimesMarathon  int  `gorm:"column:times_marathon" json:"times_marathon"`//马拉松场次
+	TimesQualifier  int  `gorm:"column:times_qualifier" json:"times_qualifier"`//排位赛场次
+	CreateTime  string  `gorm:"column:create_time" json:"create_time"`//创建时间
+	UpdateTime  string  `gorm:"column:update_time" json:"update_time"`//更新时间
+	IsDelete  int64  `gorm:"column:is_delete" json:"is_delete"`//是否删除
+	Status  int64  `gorm:"column:status" json:"status"`//账号状态
+	UserPoint  int64  `gorm:"column:user_point" json:"user_point"`//积分
+	Role  int64  `gorm:"column:role" json:"role"`//账号类型
+	UserMoney  int64  `gorm:"column:user_money" json:"user_money"`//账号余额
+	LoginType  int64  `gorm:"column:login_type" json:"login_type"`//登录方式
+	AppId string `gorm:"column:app_id" json:"app_id"`//appid
+}
+
+type UserUpload struct {
+	UserName     string `gorm:"column:username" json:"username"`  //昵称
+	UserAvatar       string `gorm:"column:user_avatar" json:"user_avatar"`//头像
+	Gender       int    `gorm:"column:gender" json:"gender"`//性别
+	Height   int    `gorm:"column:hieght" json:"height"`//身高
+	Weight   int    `gorm:"column:weight" json:"weight"`//体重
+	Birthday     string `gorm:"column:birthday" json:"birthday"`//生日
+	Area         string `gorm:"column:area" json:"area"`//地区
+}
+
+/// 用于插入user_info表中的数据
+type UserInfo struct {
+	Id     int64  `gorm:"column:id;primary_key;auto_increment" json:"id"` //自增ID
+	UserId     string `gorm:"column:user_id" json:"user_id"`  //用户ID
+	YuedongId     string `gorm:"column:yuedong_id" json:"yuedong_id"`  //用户ID
+	UserName     string `gorm:"column:username" json:"username"`  //昵称
+	Password     string `gorm:"column:password" json:"password"`//密码
+	RealName     string `gorm:"column:real_name" json:"real_name"`//真实姓名
+	UserAvatar       string `gorm:"column:user_avatar" json:"user_avatar"`//头像
+	MobilePhone       string `gorm:"column:mobile_phone" json:"mobile_phone"`//手机号
+	Gender       int    `gorm:"column:gender" json:"gender"`//性别
+	Height   int    `gorm:"column:height" json:"height"`//身高
+	Weight   int    `gorm:"column:weight" json:"weight"`//体重
+	Birthday     string `gorm:"column:birthday" json:"birthday"`//生日
+	Address         string `gorm:"column:address" json:"address"`//详细地址
+	Area         string `gorm:"column:area" json:"area"`//地区
+	QrCode     string `gorm:"column:qr_code" json:"qr_code"` //二维码
+	UserGrade     string    `gorm:"column:user_grade" json:"user_grade"`//排位赛等级
+	LoginTime  string  `gorm:"column:login_time" json:"login_time"`//登录时间
+	RegisterTime  string  `gorm:"column:register_time" json:"register_time"`//注册时间
+	LikeNum  int64  `gorm:"column:like_num" json:"like_num"`//点赞数
+	FansNum  int64  `gorm:"column:fans_num" json:"fans_num"`//粉丝数
+	AttenNum  int64  `gorm:"column:atten_num" json:"atten_num"`//关注数
+	TotalDistance  int  `gorm:"column:total_distance" json:"total_distance"`//总公里数
+	TimesMarathon  int  `gorm:"column:times_marathon" json:"times_marathon"`//马拉松场次
+	TimesQualifier  int  `gorm:"column:times_qualifier" json:"times_qualifier"`//排位赛场次
+	CreateTime  string  `gorm:"column:create_time" json:"create_time"`//创建时间
+	UpdateTime  string  `gorm:"column:update_time" json:"update_time"`//更新时间
+	IsDelete  int64  `gorm:"column:is_delete" json:"is_delete"`//是否删除
+	Status  int64  `gorm:"column:status" json:"status"`//账号状态
+	UserPoint  int64  `gorm:"column:user_point" json:"user_point"`//积分
+	Role  int64  `gorm:"column:role" json:"role"`//账号类型
+	UserMoney  int64  `gorm:"column:user_money" json:"user_money"`//账号余额
+	LoginType  int64  `gorm:"column:login_type" json:"login_type"`//登录方式
+	AppId string `gorm:"column:app_id" json:"app_id"`//appid
+	AttentionUserId string `gorm:"column:attention_user_id" json:"attention_user_id"`//attention_user_id
+}
+
+type TotalDistances struct {
+	TotalDistance  int  `gorm:"column:course" json:"course"`//总公里数
+	MarathonId string  `gorm:"column:marathon_id" json:"marathon_id"`//总马拉松数
+	QualifyingId string  `gorm:"column:qualifying_id" json:"qualifying_id"`//总排位赛数
+}
+
+func (u UserInfo) ToResp() *UserResp {
+	return &UserResp{
+		Id:     u.Id,
+		UserId:       u.UserId,
+		UserName:     u.UserName,
+		RealName:     u.RealName,
+		UserAvatar:       u.UserAvatar,
+		MobilePhone:       u.MobilePhone,
+		Gender:       u.Gender,
+		Height:   u.Height,
+		Weight:   u.Weight,
+		Birthday:     u.Birthday,
+		Address:     u.Address,
+		Area:         u.Area,
+		QrCode:  u.QrCode,
+		UserGrade:     u.UserGrade,
+		LoginTime:     u.LoginTime,
+		RegisterTime:  u.RegisterTime,
+		LikeNum: u.LikeNum,
+		FansNum: u.FansNum,
+		AttenNum: u.AttenNum,
+		TotalDistance: u.TotalDistance,
+		TimesMarathon: u.TimesMarathon,
+		TimesQualifier: u.TimesQualifier,
+		CreateTime: u.CreateTime,
+		UpdateTime: u.UpdateTime,
+		IsDelete: u.IsDelete,
+		Status: u.Status,
+		UserPoint: u.UserPoint,
+		Role: u.Role,
+		UserMoney: u.UserMoney,
+		LoginType: u.LoginType,
+		AppId: u.AppId,
+	}
+}
+
+/**
+赛事订单列表
+*/
+type Competition struct {
+	MarathonId     string `json:"marathon_id"`         // 马拉松id
+	//UserId   	   string `json:"user_id"`             // 用户id
+	Name   	   	   string `json:"name"`             // 用户id
+	RecvMan 	   string    `json:"recv_man"` 			// 收件人名称
+	DealStatus     int    `json:"deal_status"` 			// 订单状态
+	PostNumber     string    `json:"post_number"`      	// 快递单号
+	PostCompany    string `json:"post_company"`        // 快递公司名称
+	RecvPhone	   string `json:"recv_phone"`        	// 收件人手机号
+	PayMoney	   float64 `json:"pay_money"`        	// 支付金额
+	DealSn		   string `json:"deal_sn"`        	// 订单id
+	List []CompetitionGoodsList `json:"list"`
+}
+
+/**
+赛事订单商品
+*/
+type CompetitionGoodsList struct {
+	PkgName      	   string `json:"pkg_name"`        		// 商品名称
+	SpecId      	   string `json:"spec_id"`        		// 商品名称
+	Amout		   int `json:"amout"`        		// 数量
+	Spec		   string `json:"spec"`        			// 规格
+	Price		   float64 `json:"price"`        		// 商品价格
+	Cover   	   string `json:"cover"`        				// 商品图片
+}
+
+/**
+排位赛列表
+*/
+type QualifyingList struct {
+	First int `json:"first"`
+	TopThree int `json:"top_three"`
+	Average int `json:"average"`
+	TenAverage int `json:"ten_average"`
+	List []QualifyingResp `json:"list"`
+}
+
+type QualifyingResp struct {
+	QualifyingId    string `json:"qualifying_id"`         // 排位赛id
+	UserId   		string `json:"user_id"`             // 用户id
+	Rank   		    string `json:"rank"`    			// 赛事排名
+	Name 	   	    string    `json:"name"` 			// 赛事名称
+	UpdateAt 	   	string    `json:"update_at"` 			// 赛事更新时间
+}
+
+type UploadBaseReq struct {
+	Base64    		string `json:"base64"`         		// base64字符串
+	MapBase			string `json:"map_base"`         	// mapBase64
+	UserId   		string `json:"user_id"`             // 用户id
+	TaskId   		string `json:"task_id"`             // 任务id
+}
+
+type UploadBaseErr struct {
+	MapUrl    		string `json:"map_url"`         		// base64字符串
+	MapBase			string `json:"map_base"`         	// mapBase64
+	UserId   		string `json:"user_id"`             // 用户id
+	TaskId   		string `json:"task_id"`             // 任务id
+}
+
+type UploadBaseResp struct {
+	Url    string `json:"url"`         // 返回的图片url
+}
+
+/**
+[Mysql]获取黑名单列表
+*/
+func (u BlackListReq) BlackToResp() interface{} {
+	return &BlackListResp{
+		UserId:       	u.UserId,
+		UserName:     	u.Username,
+		UserAvatar:     u.UserAvatar,
+	}
+}
+
+/**
+[Mysql]修改用户密码
+*/
+func (u *UserInfo) UpdatePwd(db *gorm.DB) error {
+	sql := "UPDATE lzyd_user SET password = ? WHERE user_code = ? AND user_status IN (1, 4)"
+	err := db.Exec(sql, u.Password, u.UserId).Error
+	return err
+}
+
+/**
+[Mysql]修改用户头像
+*/
+func (u *UserInfo) UpdateAvatar(db *gorm.DB) error {
+	// 修改用户头像
+	sql := "UPDATE lzyd_user SET avatar = ? WHERE user_code = ? AND user_status IN (1, 4)"
+	err := db.Exec(sql, u.UserAvatar, u.UserId).Error
+	if err != nil {
+		common.LogInfo(fmt.Sprintf("Update lzyd_user error : %s", err.Error()))
+		return err
+	}
+	return nil
+}
+
+/**
+修改用户身份证正反面照片
+*/
+//func (u *UserInfo) UpdateCard(db *gorm.DB) error {
+//	sql := "UPDATE lzyd_user SET card_id = ?, card_front = ?, card_backend = ? WHERE user_code = ? AND user_status IN (1, 4)"
+//	return db.Exec(sql, u.CardId, u.CardFront, u.CardBack, u.UserCode).Error
+//}
+
+/**
+[Mysql]修改用户资料
+*/
+func (u *UserInfo) UpdateProfile(db *gorm.DB) error {
+	// 修改用户信息
+	var model UserUpload
+	sqlUser := "select username,gender,birthday,user_avatar,area,height,weight from lzyd_user where user_id = ?"
+	common.DB.Raw(sqlUser, u.UserId).First(&model)
+	//fmt.Println("你输入的是:", u)
+	//fmt.Println("你输入的是:", model)
+	var sqlBuf bytes.Buffer
+	sqlBuf.WriteString("UPDATE lzyd_user SET ")
+	if len(u.UserName) > 0 {
+		sqlBuf.WriteString("username='" + u.UserName + "',")
+	}else {
+		sqlBuf.WriteString("username='" + model.UserName + "',")
+	}
+
+	if u.Gender > 0 {
+		sqlBuf.WriteString("gender=" + strconv.Itoa(u.Gender) + ",")
+	}else {
+		sqlBuf.WriteString("gender=" + strconv.Itoa(model.Gender) + ",")
+	}
+
+
+	if len(u.Birthday) > 0 {
+		sqlBuf.WriteString("birthday='" + u.Birthday + "',")
+	}else {
+		sqlBuf.WriteString("birthday='" + model.Birthday + "',")
+	}
+
+	if len(u.UserAvatar) > 0 {
+		sqlBuf.WriteString("user_avatar='" + u.UserAvatar + "',")
+	}else {
+		sqlBuf.WriteString("user_avatar='" + model.UserAvatar + "',")
+	}
+
+	if len(u.Area) > 0 {
+		sqlBuf.WriteString("area='" + u.Area + "',")
+	}else {
+		sqlBuf.WriteString("area='" + model.Area + "',")
+	}
+
+	if u.Height > 0 {
+		sqlBuf.WriteString("height=" + strconv.Itoa(u.Height) + ",")
+	}else {
+		sqlBuf.WriteString("height=" + strconv.Itoa(model.Height) + ",")
+	}
+
+	if u.Weight > 0 {
+		sqlBuf.WriteString("weight=" + strconv.Itoa(u.Weight))
+	}else {
+		sqlBuf.WriteString("weight=" + strconv.Itoa(model.Weight))
+	}
+
+	sqlBuf.WriteString(" WHERE user_id = ?")
+	err := db.Exec(sqlBuf.String(), u.UserId).Error
+	//fmt.Println("你输入的是:", err,u.UserId,sqlBuf.String())
+	if err != nil {
+		common.LogInfo(fmt.Sprintf("Update lzyd_user error : %s", err.Error()))
+		return err
+	}
+	return nil
+}
+
+func CreateCaptcha() string {
+	return "1" + fmt.Sprintf("%08v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100000000))
+}
+
+func YueDongId(randomNum string) bool {
+	var yuedongCode YuedongCode
+	yuedongId:= randomNum
+	yuedongIdSql := "SELECT yuedong_id from lzyd_user WHERE yuedong_id = ?"
+	common.DB.Raw(yuedongIdSql,yuedongId).Find(&yuedongCode)
+	//common.db.Raw(yuedongIdSql,yuedongId).Find(&yuedongCode)
+	//fmt.Println(111,randomNum,len(yuedongCode.YuedongId))
+	if len(yuedongCode.YuedongId) == 0 {
+		return true
+	}else {
+		return false
+	}
+}
+
+/**
+[Mysql]修改已实名认证
+*/
+func (u *UserInfo) UpdateIsValid(db *gorm.DB) error {
+	sql := "UPDATE lzyd_user SET realname_valid = 1 WHERE user_code = ? AND user_status IN (1, 4)"
+	err := db.Exec(sql, u.UserId).Error
+	if err != nil {
+		common.LogInfo(fmt.Sprintf("Update user_status error : %s", err.Error()))
+		return err
+	}
+	return nil
+}
+
+/**
+[Mysql]绑定手机号
+*/
+func (u *UserInfo) BindMobile(db *gorm.DB) error {
+	sql := "UPDATE lzyd_user SET mobile_phone = ? WHERE user_id = ? AND status IN (1, 4)"
+	return db.Exec(sql, u.MobilePhone, u.UserId).Error
+}
+
+/**
+[Mysql]删除指定账号
+*/
+func (u *UserInfo) Rem(db *gorm.DB) error {
+	sql := "UPDATE lzyd_user SET status = 3 WHERE user_id = ?"
+	return db.Exec(sql, u.UserId).Error
+}
+
+/**
+[Mysql]注册用户信息
+*/
+func (cus *UserInfo) Register(db *gorm.DB) error {
+	fmt.Println(cus)
+	now := time.Now()
+
+	var (
+		insertLoginSql   string
+		insertInfoSql    string
+		insertLoginErr   error
+		insertInfoErr    error
+	)
+
+	yuedongId := CreateCaptcha()
+	yueDongerr := YueDongId(yuedongId)
+	//fmt.Println(111,yueDongerr)
+	if yueDongerr == false {
+		yuedongId = CreateCaptcha()
+		yueDongerr = YueDongId(CreateCaptcha())
+	}
+	// 使用事务提交数据, 方便数据回滚
+	tx := db.Begin()
+	// 插入数据信息
+	insertInfoSql = "INSERT INTO lzyd_user(user_id, username, user_avatar, mobile_phone, gender, birthday, register_time, login_time, app_id,yuedong_id) VALUES (?,?,?,?,?,?,?,?,?,?)"
+	insertInfoErr = db.Exec(insertInfoSql, cus.UserId, cus.UserName, cus.UserAvatar, cus.MobilePhone, cus.Gender, cus.Birthday, now, now, cus.AppId,yuedongId).Error
+
+
+	// 插入登录信息
+	insertLoginSql = "INSERT INTO lzyd_user_login(user_id, mobile_phone, login_type, app_id, status) VALUES(?,?,?,?,?)"
+	insertLoginErr = db.Exec(insertLoginSql, cus.UserId, cus.MobilePhone, cus.LoginType, cus.AppId,  1).Error
+	//fmt.Println()
+	if insertLoginErr != nil || insertInfoErr != nil {
+		tx.Rollback()
+		//return errors.New(common.ErrorInfo[common.DbInsertErr])
+	}
+	tx.Commit()
+
+	return nil
+}
+
+/**
+[Mysql]登录用户信息
+*/
+func (cus *UserInfo) Login(db *gorm.DB) error {
+	//now := time.Now()
+	var (
+		insertLoginSql string
+		insertLoginErr error
+		insertInfoErr  error
+	)
+	// 使用事务提交数据, 方便数据回滚
+	tx := db.Begin()
+
+	// 插入登录信息
+	insertLoginSql = "INSERT INTO lzyd_user_login(user_id, mobile_phone, login_type, app_id, status) VALUES(?,?,?,?,?)"
+	insertLoginErr = db.Exec(insertLoginSql, cus.UserId, cus.MobilePhone, cus.LoginType, cus.AppId,  1).Error
+
+
+	if insertLoginErr != nil || insertInfoErr != nil {
+		tx.Rollback()
+		//return errors.New(common.ErrorInfo[common.DbInsertErr])
+	}
+	tx.Commit()
+
+	return nil
+}
+
+/**
+[Mysql]运动图片存入数据库
+*/
+func (cus *UploadBaseErr) InsetMaps(db *gorm.DB,taskId string) error {
+	fmt.Println(cus)
+	now := time.Now()
+	var (
+		insertInfoSql  string
+		insertInfoErr  error
+		task_id TaskList
+	)
+
+	yuedongIdSql := "SELECT task_id from lzyd_user_maps WHERE task_id = ?"
+	common.DB.Raw(yuedongIdSql,taskId).First(&task_id)
+	fmt.Println(1111,task_id)
+	tx := db.Begin()
+	if len(task_id.TaskId) > 0 {
+
+
+		insertInfoSql = "UPDATE lzyd_user_maps SET map_url = ?,map_line_url =? WHERE task_id = ?"
+		insertInfoErr = db.Exec(insertInfoSql,cus.MapUrl,cus.MapBase,taskId ).Error
+	}else {
+		mapId := gopkg.GenUUID()
+		// 使用事务提交数据, 方便数据回滚
+
+
+		insertInfoSql = "INSERT INTO lzyd_user_maps(user_id, task_id, map_id,map_url,map_line_url, create_at, app_id) VALUES (?,?,?,?,?,?,?)"
+		insertInfoErr = db.Exec(insertInfoSql, cus.UserId, cus.TaskId, mapId, cus.MapUrl,cus.MapBase,now, "lzyd").Error
+	}
+
+
+
+	if insertInfoErr != nil {
+		tx.Rollback()
+		//return errors.New(common.ErrorInfo[common.DbInsertErr])
+	}
+	return nil
+}
+
+
+
+

+ 59 - 0
router/router.go

@@ -0,0 +1,59 @@
+package router
+
+import (
+	tingyun_gin "github.com/TingYunAPM/go/framework/gin"
+	"github.com/gin-gonic/gin"
+	ginSwagger "github.com/swaggo/gin-swagger"
+	"github.com/swaggo/gin-swagger/swaggerFiles"
+	"gopkg"
+	"lzyd-user-api/common"
+	"lzyd-user-api/controllers"
+	_ "lzyd-user-api/docs" // docs is generated by Swag CLI, you have to import it.
+	"lzyd-user-api/utils"
+)
+
+func InitRouter() *tingyun_gin.WrapEngine {
+	router := tingyun_gin.Default()
+
+	router.Use(gin.Recovery())
+	router.Use(gopkg.CORSMiddleware())
+	router.Use(utils.ValidSign(common.SystemInfo.Valid))
+	router.Use(utils.ValidHeaderParams())
+
+	// use ginSwagger middleware to
+	router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
+
+	/// App
+	//router.GET("/app/launch", controllers.GetAppLaunch)
+
+	/// Passport
+	//router.POST("passport/register", controllers.Register)
+	//router.POST("passport/login", controllers.LoginWithMobileAndPass)
+	//router.POST("passport/wechatLogin", controllers.WechatLogin)
+	router.POST("passport/quickLogin", controllers.QuickLogin)
+
+	/// Customer
+	router.GET("customer/getInfo", controllers.GetCustomerInfo)
+	router.POST("customer/getBlacklist", controllers.GetBlacklist)
+	router.POST("customer/updateProfile", controllers.UpdateProfile)
+	router.GET("customer/order", controllers.GetCompetitionOrder)
+	router.GET("customer/qualifying", controllers.GetQualifying)
+	router.POST("customer/uploadBase64", controllers.UploadBase64)
+	//router.POST("customer/editCard", controllers.EditCard)
+	//router.POST("customer/updatePwd", controllers.UpdatePwd)
+
+	/// Sms
+	router.GET("sms/get", controllers.GetSms)
+	router.POST("sms/remind", controllers.SendRemindSms)
+
+	/// Area
+	router.GET("/area/getArea", controllers.GetArea)
+
+	/// mine
+	router.GET("/cert/list", controllers.GetCertList)
+	router.GET("/cert/userList", controllers.GetUserCertList)
+	router.GET("/medal/list", controllers.GetMedalList)
+	router.GET("/medal/userList", controllers.GetUserMedalList)
+
+	return router
+}

+ 45 - 0
services/area.go

@@ -0,0 +1,45 @@
+package services
+
+import (
+	"fmt"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+)
+
+/**
+获取所有省份
+*/
+func QueryProvinceCode() []models.ReqProvince {
+	var province []models.ReqProvince
+	sql := `SELECT id, code, name
+			FROM province`
+	common.DB.Raw(sql).Find(&province)
+	fmt.Println("你获取的是:", province)
+	return province
+}
+
+/**
+根据省code查询市
+*/
+func QueryCityCode(code string) []models.ReqCity {
+	var city []models.ReqCity
+	sql := `SELECT id, code, name, province_code
+			FROM city 
+			WHERE province_code = ?`
+	common.DB.Raw(sql, code).Find(&city)
+	fmt.Println("你获取的是:", city)
+	return city
+}
+
+/**
+根据市code查询区
+*/
+func QueryAreaCode(code string) []models.ReqArea {
+	var area []models.ReqArea
+	sql := `SELECT id, code, name, city_code
+			FROM area 
+			WHERE city_code = ?`
+	common.DB.Raw(sql, code).Find(&area)
+	fmt.Println("你获取的是:", area)
+	return area
+}

+ 33 - 0
services/cert.go

@@ -0,0 +1,33 @@
+package services
+
+import (
+	"fmt"
+	"github.com/jinzhu/gorm"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+)
+
+/**
+获取所有证书
+*/
+func QueryCertList(db *gorm.DB, cType string) []models.LzydCert {
+	var cert []models.LzydCert
+	//sql := `SELECT id FROM lzyd_cert`
+	err := db.Find(&cert).Error
+	if err != nil {
+		//fmt.Println(111)
+		fmt.Println(err.Error())
+	}
+	//fmt.Println("你获取的是:", province)
+	return cert
+}
+/**
+获取所有用户获得的证书
+*/
+func QueryUserCertList(userId string) []models.LzydCertUser {
+//func QueryUserCertList(userId string) []models.LzydCertUser {
+	var userCert []models.LzydCertUser
+	sql := `SELECT * FROM lzyd_cert_user WHERE user_id = ?`
+	common.DB.Raw(sql, userId).Find(&userCert)
+	return userCert
+}

+ 22 - 0
services/launch.go

@@ -0,0 +1,22 @@
+package services
+
+import (
+	"github.com/jinzhu/gorm"
+	"lzyd-user-api/models"
+)
+
+// 获取系统字典
+func GetSystemDict(db *gorm.DB) models.SystemDict {
+	var dict models.SystemDict
+	sql := "SELECT `name`, `value`, `type` FROM system_dict WHERE deleted_at IS NULL"
+	db.Raw(sql).Find(&dict)
+	return dict
+}
+
+// 获取版本信息
+func GetVersionInfo(db *gorm.DB, client int) models.VersionInfo {
+	var versionInfo models.VersionInfo
+	sql := "SELECT number, download_url, content, force_update, client FROM version_info WHERE client = ? AND delete_at IS NULL"
+	db.Raw(sql, client).Find(&versionInfo)
+	return versionInfo
+}

+ 33 - 0
services/medal.go

@@ -0,0 +1,33 @@
+package services
+
+import (
+	"fmt"
+	"github.com/jinzhu/gorm"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+)
+
+/**
+获取所有证书
+*/
+func QueryMedalList(db *gorm.DB, cType string) []models.LzydMedal {
+	var medal []models.LzydMedal
+	//sql := `SELECT id FROM lzyd_cert`
+	err := db.Find(&medal).Error
+	if err != nil {
+		//fmt.Println(111)
+		fmt.Println(err.Error())
+	}
+	//fmt.Println("你获取的是:", province)
+	return medal
+}
+/**
+获取所有用户获得的证书
+*/
+func QueryUserMedalList(userId string) []models.LzydMedalUser {
+	//func QueryUserCertList(userId string) []models.LzydCertUser {
+	var userMedal []models.LzydMedalUser
+	sql := `SELECT * FROM lzyd_cert_user WHERE user_id = ?`
+	common.DB.Raw(sql, userId).Find(&userMedal)
+	return userMedal
+}

+ 85 - 0
services/sms.go

@@ -0,0 +1,85 @@
+package services
+
+import (
+	"errors"
+	"fmt"
+	"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
+	"github.com/jinzhu/gorm"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/utils"
+)
+
+/**
+[Mysql]根据手机号及用户输入的验证码去查询数据
+*/
+func GetValidSms(db *gorm.DB, mobile, code string, smsType int) models.ValidSms {
+
+	var sms models.ValidSms
+	sql := `SELECT sms_id, mobile_phone, valid_code, sms_type, create_at 
+			FROM lzyd_sms_valid
+			WHERE mobile_phone = ? AND valid_code = ? AND sms_type = ? 
+			ORDER BY create_at DESC LIMIT 1`
+
+	db.Raw(sql, mobile, code, smsType).Find(&sms)
+	//fmt.Println(1111,sms)
+	return sms
+}
+
+/**
+[Mysql]根据手机号及用户输入的验证码去查询是否存在用户
+*/
+func GetValidSmsUser (db *gorm.DB, mobile string) models.SmsUser {
+	var smsU models.SmsUser
+	sql := `SELECT mobile_phone,is_delete 
+			FROM lzyd_user
+			WHERE mobile_phone = ? AND is_delete = 0`
+	db.Raw(sql, mobile).Find(&smsU)
+	fmt.Println(smsU)
+	return smsU
+}
+
+/**
+根据手机号与类型匹配最近的一条短信记录
+*/
+func GetLastValidSms(db *gorm.DB, mobile string, smsType int) models.ValidSms {
+	var sms models.ValidSms
+	sql := "SELECT `sms_id`, valid_code, create_at FROM lzyd_sms_valid WHERE mobile_phone = ? AND sms_type = ? ORDER BY create_at DESC LIMIT 1"
+	db.Raw(sql, mobile, smsType).Find(&sms)
+	return sms
+}
+
+/**
+获取每天发送短信的总量
+*/
+func CountOfToday(db *gorm.DB, tableName string) int64 {
+	var count int64
+	sql := fmt.Sprintf("SELECT COUNT(`sms_id`) FROM %s WHERE create_at > UNIX_TIMESTAMP(CAST(SYSDATE() AS DATE))", tableName)
+	db.Raw(sql).Count(&count)
+	return count
+}
+
+/**
+调用模板发送短信
+*/
+func SendSingleSms(mobile string, typ int) (string, error) {
+	random := utils.GenRandomCode()
+	client, err := dysmsapi.NewClientWithAccessKey(common.RegionId, common.AccessKeyId, common.AccessSecret)
+	if err != nil {
+		return "", err
+	}
+	request := dysmsapi.CreateSendSmsRequest()
+	request.Scheme = "http"
+	request.PhoneNumbers = mobile
+	request.SignName = common.SignName
+	request.TemplateCode = common.SmsTemplateCodeMap[typ]
+	request.TemplateParam = "{\"code\": \"" + random + "\"}"
+	response, err := client.SendSms(request)
+	if err != nil {
+		return "", err
+	}
+	if response.Code == "OK" && response.Message == "OK" {
+		return random, nil
+	}
+	return "", errors.New(response.Message)
+}

+ 314 - 0
services/user.go

@@ -0,0 +1,314 @@
+package services
+
+import (
+	"encoding/base64"
+	"fmt"
+	"io/ioutil"
+	"lzyd-user-api/common"
+	"lzyd-user-api/models"
+	"lzyd-user-api/utils"
+	"math/rand"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+/**
+[Mysql]根据用户手机号去匹配用户信息
+*/
+func GetOneByMobileOnly(mobile string) models.UserInfo {
+	var model models.UserInfo
+	sql := `SELECT user_id, user_code, username, nickname, avatar, mobile, password, is_authen, 
+			DATE_FORMAT(register_time, '%Y-%m-%d %H:%i:%S') as register_time 
+			FROM sports_user 
+		    WHERE user_status IN (1, 4) AND mobile = ? AND is_delete = 0`
+	common.DB.Raw(sql, mobile).First(&model)
+	return model
+}
+
+
+/**
+[Mysql]检查用户名是否重复
+*/
+func DuplicatedUserName(username string) bool {
+	var count int
+	sql := "SELECT COUNT(user_id) FROM sports_user WHERE username = ?"
+	common.DB.Raw(sql, username).Count(&count)
+	return count > 0
+}
+
+/**
+手机号+密码登录
+*/
+func LoginWithMobileAndPass(mobile, password string) (models.UserInfo, int) {
+	var user models.UserInfo
+	sql := `SELECT user_id, user_code, username, nickname, avatar, mobile, password, is_authen, 
+			DATE_FORMAT(register_time, '%Y-%m-%d %H:%i:%S') as register_time 
+			FROM sports_user 
+		    WHERE user_status IN (1, 4) AND mobile = ? AND password = ?`
+	common.DB.Raw(sql, mobile, password).First(&user)
+	if user.Id > 0 {
+		return user, common.QueryStateSuccess
+	}
+	return user, common.QueryStateNone
+}
+
+/**
+只用手机号登录
+*/
+func LoginWithMobileOnly(mobile_phone string) (models.UserInfo, int) {
+	var user models.UserInfo
+	sql := `SELECT id, user_id, username, real_name, user_avatar, mobile_phone, app_id,
+			DATE_FORMAT(register_time, '%Y-%m-%d %H:%i:%S') as register_time 
+			FROM lzyd_user
+		    WHERE mobile_phone = ?`
+	common.DB.Raw(sql, mobile_phone).Limit(1).Find(&user)
+
+
+	if user.Id > 0 {
+		return user, common.QueryStateSuccess
+	}
+	return user, common.QueryStateNone
+}
+
+/**
+根据用户id查询用户信息
+*/
+func QueryUserByCode(code string) models.UserInfo {
+	var user models.UserInfo
+	var totalDistances []models.TotalDistances
+	var marathons []models.TotalDistances
+	var qualifying []models.TotalDistances
+	var allCourse int
+	// total_distance, times_marathon,times_qualifier,
+	sql := `SELECT id, user_id, username, like_num, atten_num, real_name, user_avatar, mobile_phone, birthday, fans_num, user_point, app_id,
+			height, weight, gender, address, area,
+			DATE_FORMAT(register_time, '%Y-%m-%d %H:%i:%S') as register_time 
+			FROM lzyd_user 
+		    WHERE user_id = ? AND is_delete = 0`
+	common.DB.Raw(sql, code).Limit(1).Find(&user)
+	sql1 := `SELECT course FROM lzyd_sport_log WHERE user_id = ?`
+	common.DB.Raw(sql1, code).Find(&totalDistances)
+	sql2 := `SELECT marathon_id FROM lzyd_marathon_user WHERE user_id = ? && is_cancel = 0`
+	common.DB.Raw(sql2, code).Find(&marathons)
+	sql3 := `SELECT qualifying_id FROM lzyd_qualifying_user WHERE user_id = ?`
+	common.DB.Raw(sql3, code).Find(&qualifying)
+	fmt.Println(totalDistances,marathons,qualifying)
+	for i := 0; i < len(totalDistances); i++ {
+		allCourse = totalDistances[i].TotalDistance + allCourse
+	}
+	user.TotalDistance = allCourse
+	user.TimesMarathon = len(marathons)
+	user.TimesQualifier = len(qualifying)
+	//fmt.Println("你输入的是:", user)
+	return user
+}
+
+/**
+根据用户id查询用户赛事订单
+*/
+func QueryCompetitionOrder(code string) []models.Competition {
+	var order []models.Competition
+	var goodsList []models.CompetitionGoodsList
+	sql := `SELECT u.deal_sn,u.marathon_id,u.pay_type,u.order_money,u.recv_man,u.pay_money,u.deal_status,u.is_paied,v.name
+			from lzyd_marathon_order_master u
+			LEFT JOIN lzyd_marathon v ON u.marathon_id = v.marathon_id
+			WHERE u.user_id = ? AND u.is_delete = 0`
+	common.DB.Raw(sql, code).Find(&order)
+	for i:=0;i< len(order); i++ {
+		sql1 := `SELECT u.pkg_id,u.pkg_name,u.spec,u.price,u.amout,v.cover,u.spec_id
+				from lzyd_marathon_order_detail u
+				LEFT JOIN lzyd_marathon_pkg_spec x ON u.spec_id = x.spec_id
+				LEFT JOIN lzyd_marathon_pkg_cert v ON v.pkg_id = x.pkg_id
+				WHERE deal_sn = ?`
+		common.DB.Raw(sql1,order[i].DealSn ).Find(&goodsList)
+		order[i].List = goodsList
+	}
+	fmt.Println(order)
+	//fmt.Println("你输入的是:", order)
+	return order
+}
+
+/**
+根据用户id查询用户排位赛信息
+*/
+func QueryQualifyingList(code string) models.QualifyingList {
+	var qualify models.QualifyingList
+	var qualifying []models.QualifyingResp
+	sql := `SELECT u.user_id, u.qualifying_id, v.name, u.rank, v.update_at
+			FROM lzyd_qualifying_user u
+			LEFT JOIN lzyd_qualifying v ON v.qualifying_id = u.qualifying_id 
+			WHERE u.user_id = ?`
+	common.DB.Raw(sql, code).Find(&qualifying)
+	qualify.List = qualifying
+	var FirstCode = 0
+	var TopThreeCode = 0
+	var AverageCode = 0
+	var TenAverageCode = 0
+
+	fmt.Println(len(qualifying))
+	for i := 0; i < len(qualifying); i++ {
+		ch := qualifying[i]
+		fmt.Println(ch)
+		Chint, err := strconv.Atoi(ch.Rank)
+		fmt.Println(err)
+		fmt.Println(111,Chint)
+		if Chint == 1 {
+			FirstCode += 1
+		}
+		if Chint <= 3 && 0 < Chint {
+			TopThreeCode += 1
+		}
+		AverageCode += Chint
+		if i <= 10{
+			TenAverageCode += Chint
+		}
+	}
+	if len(qualifying) > 0 {
+		AverageCode = AverageCode/len(qualifying)
+		if len(qualifying) <= 10{
+			TenAverageCode = TenAverageCode/len(qualifying)
+		}else {
+			TenAverageCode = TenAverageCode/10
+		}
+	}else {
+		AverageCode = 0
+		TenAverageCode = 0
+	}
+
+	qualify.First = FirstCode
+	qualify.TopThree = TopThreeCode
+	qualify.Average = AverageCode
+	qualify.TenAverage = TenAverageCode
+	//fmt.Println("你输入的是:", order)
+	return qualify
+}
+
+/**
+根据用户id查询用户黑名单
+*/
+func QueryBlackByCode(code string,listType int) []models.BlackListReq {
+	var user []models.BlackListReq
+	sql := `select u.user_id,u.user_avatar,u.fans_num, u.username from lzyd_user u
+			left join lzyd_video_attention v on v.attention_user_id=u.user_id
+			where v.user_id= ? and v.status = ?`
+
+
+
+	common.DB.Raw(sql, code, listType).Find(&user)
+	for i := 0; i < len(user); i++ {
+		var videoList []models.VideoListReq
+		sqlVideo := `select user_id from lzyd_video_upload where user_id= ?`
+		common.DB.Raw(sqlVideo, user[i].UserId).Find(&videoList)
+		user[i].VideosNum = len(videoList)
+	}
+	//fmt.Println("你输入的是:", user)
+	return user
+}
+
+/**
+[Mysql]根据OpenID去匹配用户信息
+*/
+func QueryUserByOpenId(openId string) (models.UserInfo, int) {
+	var user models.UserInfo
+	sql := `SELECT user_id, user_code, username, nickname, avatar, mobile, password, is_authen, 
+			DATE_FORMAT(register_time, '%Y-%m-%d %H:%i:%S') as register_time 
+			FROM sports_user 
+		    WHERE user_status IN (1, 4) AND wechat_id = ? AND is_delete = 0`
+	common.DB.Raw(sql, openId).First(&user)
+	if user.Id > 0 {
+		return user, common.QueryStateSuccess
+	}
+	return user, common.QueryStateNone
+}
+
+/**
+[Mysql]获取第三方绑定信息
+*/
+func GetBindInfoByUserId(uid string) models.UserInfo {
+	var model models.UserInfo
+	sql := "SELECT id, wxid FROM lzyd_user WHERE user_id = ? AND user_status IN (1, 4)"
+	common.DB.Raw(sql, uid).First(&model)
+	return model
+}
+
+// 判断手机号是否已存在
+func ExistedMobile(mobile string) bool {
+	var count int
+	sql := "SELECT COUNT(user_id) FROM lzyd_user WHERE mobile_phone = ?"
+	common.DB.Raw(sql, mobile).Count(&count)
+	return count > 0
+}
+
+/**
+用户昵称唯一处理
+*/
+func UniqueName(name string) string {
+	name = strings.TrimSpace(name)
+	if len(name) == 0 {
+		return "悦动" + "_" + utils.GenUserIdentifier()
+	}
+	if DuplicatedUserName(name) {
+		return name + "_" + utils.GenUserIdentifier()
+	}
+	return name
+}
+
+/**
+查询是否关注
+*/
+func UserRelation(userCode string,otherCode string) string {
+	var noticeRead models.UserRelationResp
+	//var noticeRead2 models.UserRelationResp
+	//var noticeRead3 models.UserRelationResp
+	//var noticeRead4 models.UserRelationResp
+
+	// sql1与sql2 查询用户之前互相关注
+	sql := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 0`
+	common.DB.Raw(sql,otherCode,userCode).Find(&noticeRead)
+	//fmt.Println(noticeRead)
+	//sql2 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 0`
+	//common.DB.Raw(sql2,bCreatorId,creatorId).Find(&noticeRead2)
+	return noticeRead.AttentionUserId
+}
+
+//写入文件,保存
+func WriteFile(path string, base64_image_content string) string {
+	b, _ := regexp.MatchString(`^data:\s*image\/(\w+);base64,`, base64_image_content)
+	if !b {
+
+	}
+	re, _ := regexp.Compile(`^data:\s*image\/(\w+);base64,`)
+	allData := re.FindAllSubmatch([]byte(base64_image_content), 2)
+	fileType := string(allData[0][1]) //png ,jpeg 后缀获取
+
+	base64Str := re.ReplaceAllString(base64_image_content, "")
+
+	//date := time.Now().Format("20060102")
+	//if ok := IsFileExist(path + "/" + date); !ok {
+	//	os.Mkdir(path+"/"+date, 0666)
+	//}
+	//+ "/" + date
+
+	var file string = path  + "/" + strconv.FormatInt(time.Now().Unix(),10) + strconv.Itoa(rand.Intn(999999-100000)+100000) + "." + fileType
+	byte, _ := base64.StdEncoding.DecodeString(base64Str)
+
+	err := ioutil.WriteFile(file, byte, 0666)
+	if err != nil {
+		return file
+	}
+	return file
+}
+
+//判断文件是否存在
+
+func IsFileExist(filename string) bool {
+	_, err := os.Stat(filename)
+	if os.IsNotExist(err) {
+		return false
+	}
+	return true
+}
+

+ 19 - 0
tingyun.json

@@ -0,0 +1,19 @@
+{
+
+  "nbs.app_name" : "lzyd_user_api",
+
+  "nbs.agent_enabled" : true,
+
+  "nbs.license_key" : "01f3aa1fb07e1d3d06db45648cb68bbe",
+
+  "nbs.log_file_name" : "tingyun.log",
+
+  "nbs.audit" : true,
+
+  "nbs.max_log_count": 3,
+
+  "nbs.max_log_size": 9,
+
+  "nbs.ssl" : true
+
+}

File diff suppressed because it is too large
+ 1136 - 0
tingyun.log


+ 75 - 0
utils/crypto.go

@@ -0,0 +1,75 @@
+package utils
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"encoding/base64"
+	"encoding/hex"
+	"strings"
+)
+
+const (
+	KEY_LENGTH = 8
+)
+
+func encrypt(block cipher.Block, src, key, iv []byte) []byte {
+	blockSize := block.BlockSize()
+	src = pkcs5Padding(src, blockSize)
+	mode := cipher.NewCBCEncrypter(block, genBytes(iv, blockSize))
+	crypted := make([]byte, len(src))
+	mode.CryptBlocks(crypted, src)
+	return crypted
+}
+
+func decrypt(block cipher.Block, encrypted, key, iv []byte) []byte {
+	mode := cipher.NewCBCDecrypter(block, genBytes(iv, block.BlockSize()))
+	src := make([]byte, len(encrypted))
+	mode.CryptBlocks(src, encrypted)
+	return pkcs5UnPadding(src)
+}
+
+func pkcs5Padding(data []byte, blockSize int) []byte {
+	padding := blockSize - len(data)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(data, padtext...)
+}
+
+func pkcs5UnPadding(data []byte) []byte {
+	length := len(data)
+	// 去掉最后一个字节 unpadding 次
+	unpadding := int(data[length-1])
+	return data[:(length - unpadding)]
+}
+
+func genBytes(originalBytes []byte, length int) []byte {
+	tmp := make([]byte, length)
+	if len(originalBytes) < length {
+		for i := 0; i < length; i++ {
+			tmp[i] = originalBytes[i%len(originalBytes)]
+		}
+	} else {
+		for i := 0; i < length; i++ {
+			tmp[i] = originalBytes[i]
+		}
+	}
+	return tmp
+}
+
+func bytes2String(data []byte, base64Encoding bool) string {
+	if base64Encoding {
+		return base64.StdEncoding.EncodeToString(data)
+	} else {
+		return strings.ToUpper(hex.EncodeToString(data))
+	}
+}
+
+func string2Bytes(data string, base64Encoding bool) ([]byte, error) {
+	var tmp []byte
+	var err error
+	if base64Encoding {
+		tmp, err = base64.StdEncoding.DecodeString(data)
+	} else {
+		tmp, err = hex.DecodeString(data)
+	}
+	return tmp, err
+}

+ 56 - 0
utils/des.go

@@ -0,0 +1,56 @@
+package utils
+
+import (
+	"crypto/cipher"
+	"crypto/des"
+	"fmt"
+)
+
+type DES struct {
+	block   cipher.Block
+	key, iv []byte
+}
+
+// 定义Key与向量的值
+var DES_KEY = []byte{102, 16, 93, 156, 78, 4, 218, 32}
+var DES_IV = []byte{55, 103, 246, 79, 36, 99, 167, 3}
+
+func DESEncrypt(src []byte) []byte {
+	des, err := newDESInstance(DES_KEY, DES_IV)
+	if err != nil {
+		fmt.Println("DES Encrypt Error: ", err)
+		return nil
+	}
+	return encrypt(des.block, src, des.key, des.iv)
+}
+
+func DESEncryptString(src string, base64Encoding bool) string {
+	tmp := DESEncrypt([]byte(src))
+	return bytes2String(tmp, base64Encoding)
+}
+
+func DESDecrypt(encrypted []byte) []byte {
+	des, err := newDESInstance(DES_KEY, DES_IV)
+	if err != nil {
+		fmt.Println("DES Encrypt Error: ", err)
+		return nil
+	}
+	return decrypt(des.block, encrypted, des.key, des.iv)
+}
+
+func DESDecryptString(encrypted string, base64Encoding bool) (string, error) {
+	tmp, err := string2Bytes(encrypted, base64Encoding)
+	if err != nil {
+		return "", err
+	}
+	return string(DESDecrypt(tmp)), err
+}
+
+func newDESInstance(key, iv []byte) (*DES, error) {
+	key = genBytes(key, KEY_LENGTH)
+	block, err := des.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	return &DES{block: block, key: key, iv: iv}, err
+}

+ 23 - 0
utils/md5.go

@@ -0,0 +1,23 @@
+package utils
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+)
+
+func MD5EncodeBytes(str string) []byte {
+	md5Ctx := md5.New()
+	md5Ctx.Write([]byte(str))
+	return md5Ctx.Sum(nil)
+}
+
+func MD5EncodeString(str string) string {
+	bytes := MD5EncodeBytes(str)
+	return string(bytes)
+}
+// 生成32位md5字串
+func Md5Encode(s string) string {
+	h := md5.New()
+	h.Write([]byte(s))
+	return hex.EncodeToString(h.Sum(nil))
+}

+ 193 - 0
utils/mw_vaild.go

@@ -0,0 +1,193 @@
+package utils
+
+import (
+	"bytes"
+	"crypto/md5"
+	"encoding/hex"
+	"encoding/json"
+	"github.com/gin-gonic/gin"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"sort"
+	"strings"
+)
+
+/**
+Sign的格式如下:
+所有的请求参数加上appkey=lzwg-app-N78ya51qaz2wsx!排序后,再MD5
+*/
+const AppKey string = "lzyd-sign-7c423d19cb2b"
+
+func ValidSign(forceValid bool) gin.HandlerFunc {
+	return func(c *gin.Context) {
+		// 暂时不对swagger做强校验
+		if strings.Contains(c.Request.RequestURI, "swagger") {
+			c.Next()
+			return
+		}
+		if strings.Contains(c.Request.Header.Get("Referer"), "swagger") {
+			c.Next()
+			return
+		}
+		if !forceValid {
+			c.Next()
+			return
+		}
+		validSign(c, AppKey)
+	}
+}
+
+//从Header验证参数
+func ValidHeaderParams() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		//判断是否合法请求
+		client := c.Request.Header.Get("client")
+		guid := c.Request.Header.Get("guid")
+		timestamp := c.Request.Header.Get("timestamp")
+		sig := c.Request.Header.Get("sig")
+		if client == "2" { //wap鉴权
+			//sig:md5(client+'lz2019_random'+uuid+timestamp)
+			_sig := Md5Encode(client + "lz2019_random" + guid + timestamp)
+			if _sig == sig { //鉴权通过
+				//fmt.Println("_sig == sig")
+				//c.JSON(http.StatusOK, gin.H{"message": "授权成功"})
+				c.Next()
+			} else { //请求非法
+				//fmt.Println("_sig != sig")
+				c.Abort()
+				c.JSON(http.StatusForbidden, gin.H{"message": "访问未授权"})
+				// return可省略, 只要前面执行Abort()就可以让后面的handler函数不再执行
+				return
+			}
+		} else {
+			c.Next()
+		}
+	}
+}
+
+func validSign(c *gin.Context, appKey string) {
+
+	var (
+		inSign  string
+		outSign string
+	)
+
+	if c.Request.Method == "GET" {
+		values := c.Request.URL.Query()
+		if len(values) <= 0 {
+			c.Next()
+			return
+		}
+		inSign = values.Get("sign")
+		if len(inSign) == 0 {
+			c.JSON(http.StatusOK, gin.H{
+				"code":    -1,
+				"message": "未传入签名参数",
+			})
+			c.Abort()
+			return
+		}
+		outSign = calculateSignFromValues(values, appKey)
+	} else {
+		c.Request.ParseMultipartForm(32 << 20)
+		formData := c.Request.PostForm
+		if len(formData) > 0 {
+			inSign = formData.Get("sign")
+			if len(inSign) == 0 {
+				c.JSON(http.StatusOK, gin.H{
+					"code":    -1,
+					"message": "未传入签名参数",
+				})
+				c.Abort()
+				return
+			}
+			outSign = calculateSignFromValues(formData, appKey)
+		} else {
+			var params map[string]interface{}
+			data, _ := c.GetRawData()
+			err := json.Unmarshal(data, &params)
+			if err != nil {
+				panic(err)
+			}
+			inSign = Interface2String(params["sign"])
+			if len(inSign) == 0 {
+				c.JSON(http.StatusOK, gin.H{
+					"code":    -1,
+					"message": "未传入签名参数",
+				})
+				c.Abort()
+				return
+			}
+			outSign = calculateSignFromJsonBody(params, appKey)
+
+			// 很关键,把读过的字节流重新放到body
+			c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data))
+		}
+	}
+	if outSign != inSign {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    -1,
+			"message": "签名验证错误",
+		})
+		c.Abort()
+	}
+
+	c.Next()
+}
+
+func calculateSignFromValues(values url.Values, appKey string) string {
+	values.Del("sign")
+	values.Add("secret", appKey)
+	if len(values) > 0 {
+		// 先对Key进行排序
+		var keywords []string
+		for key, _ := range values {
+			keywords = append(keywords, key)
+		}
+		sort.Strings(keywords)
+		// 再根据Key查找参数Map, 并拼接成字符串
+		var stringBuffer bytes.Buffer
+		keywordsCnt := len(keywords)
+		for i := 0; i < keywordsCnt-1; i++ {
+			keyword := keywords[i]
+			stringBuffer.WriteString(keyword + "=" + values.Get(keyword))
+			stringBuffer.WriteString("&")
+		}
+		lastKeyword := keywords[keywordsCnt-1]
+		stringBuffer.WriteString(lastKeyword + "=" + values.Get(lastKeyword))
+		// 最后MD5加密
+		hash := md5.New()
+		hash.Write(stringBuffer.Bytes())
+		return hex.EncodeToString(hash.Sum(nil))
+	}
+	return ""
+}
+
+func calculateSignFromJsonBody(params map[string]interface{}, appKey string) string {
+	delete(params, "sign")
+	params["secret"] = appKey
+	if len(params) > 0 {
+		// 先对Key进行排序
+		var keywords []string
+		for key, _ := range params {
+			keywords = append(keywords, key)
+		}
+		sort.Strings(keywords)
+		// 再根据Key查找参数Map, 并拼接成字符串
+		var stringBuffer bytes.Buffer
+		keywordsCnt := len(keywords)
+		for i := 0; i < keywordsCnt-1; i++ {
+			keyword := keywords[i]
+			stringBuffer.WriteString(keyword + "=" + Interface2String(params[keyword]))
+			stringBuffer.WriteString("&")
+		}
+		lastKeyword := keywords[keywordsCnt-1]
+		stringBuffer.WriteString(lastKeyword + "=" + Interface2String(params[lastKeyword]))
+		// 最后MD5加密
+		hash := md5.New()
+		hash.Write(stringBuffer.Bytes())
+		return hex.EncodeToString(hash.Sum(nil))
+	}
+	return ""
+}

+ 134 - 0
utils/util.go

@@ -0,0 +1,134 @@
+package utils
+
+import (
+	"bytes"
+	"crypto/sha256"
+	"encoding/hex"
+	"fmt"
+	"github.com/skip2/go-qrcode"
+	"github.com/segmentio/ksuid"
+	"math/rand"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type Error struct {
+	Code int    `json:"code"`
+	Desc string `json:"desc"`
+}
+
+/**
+生成一个随机的不重复的用户ID
+*/
+func GenUUID() string {
+	uuid, _ := ksuid.NewRandomWithTime(time.Now())
+	return uuid.String()
+}
+
+/**
+隐藏手机号码中间4位
+*/
+func KeepSecretForMobile(mobile string) string {
+	if len(mobile) > 0 {
+		var sqlBuf bytes.Buffer
+		sqlBuf.WriteString(mobile[0:3])
+		sqlBuf.WriteString("****")
+		sqlBuf.WriteString(mobile[7:11])
+		return sqlBuf.String()
+	}
+	return ""
+}
+
+/**
+生成一个随机的不重复的数字
+*/
+func GenUserIdentifier() string {
+	random := rand.New(rand.NewSource(time.Now().UnixNano()))
+	return fmt.Sprintf("%08v", random.Int31n(100000000))
+}
+
+/**
+产生随机验证码
+*/
+func GenRandomCode() string {
+	random := rand.New(rand.NewSource(time.Now().UnixNano()))
+	return fmt.Sprintf("%06v", random.Int31n(1000000))
+}
+
+/**
+用户头像处理
+*/
+func CompleteAvatar(avatar, defaultAvatar string) string {
+	if len(avatar) > 0 && (strings.HasPrefix(avatar, "http://") || strings.HasPrefix(avatar, "https://")) {
+		return avatar
+	}
+	return defaultAvatar
+}
+
+/**
+生成二维码
+*/
+func main() {
+	qrcode.WriteFile("http://www.flysnow.org/",qrcode.Medium,256,"./blog_qrcode.png")
+
+}
+
+// 如果不存在指定的目录, 则直接创建一个
+func IsNotExistMkDirAll(path string) error {
+	_, err := os.Stat(path)
+	if notExist := os.IsNotExist(err); notExist == true {
+		err := os.MkdirAll(path, os.ModePerm)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+/**
+随机文件名, 防止文件名重复
+*/
+func RandImageName(len int) string {
+	b := make([]byte, len)
+	rand.Read(b)
+	return fmt.Sprintf("%x", b) + strconv.FormatInt(time.Now().Unix(), 10)
+}
+
+/**
+生成签名Sig
+*/
+func CalculateSigForTempl(appkey string, random string, mobiles []string, time int64) string {
+	cnt := len(mobiles)
+	if cnt == 0 {
+		return ""
+	}
+	var buffer bytes.Buffer
+	buffer.WriteString(mobiles[0])
+	for i := 1; i < cnt; i++ {
+		buffer.WriteString(",")
+		buffer.WriteString(mobiles[i])
+	}
+	str := "appkey=" + appkey + "&random=" + random + "&time=" + strconv.FormatInt(time, 10) + "&mobile=" + buffer.String()
+	hash := sha256.New()
+	hash.Write([]byte(str))
+	hashInBytes := hash.Sum(nil)
+	return hex.EncodeToString(hashInBytes)
+}
+
+func Interface2String(inter interface{}) string {
+	switch inter.(type) {
+	case string:
+		return inter.(string)
+	case int:
+		return strconv.Itoa(inter.(int))
+	case int64:
+		return strconv.FormatInt(inter.(int64), 10)
+	case float64:
+		return strconv.FormatFloat(inter.(float64), 'f', -1, 64)
+	case bool:
+		return strconv.FormatBool(inter.(bool))
+	}
+	return ""
+}