Browse Source

first commit

b s s m 3 years ago
commit
285c05ec9c
55 changed files with 269734 additions and 0 deletions
  1. 8 0
      .idea/.gitignore
  2. 9 0
      .idea/health-live-front-api.iml
  3. 8 0
      .idea/modules.xml
  4. 7 0
      Dockerfile
  5. 32 0
      build.sh
  6. 46 0
      common/common.go
  7. 136 0
      common/config.go
  8. 37 0
      common/const.go
  9. 29 0
      common/error.go
  10. 23 0
      common/logging/file.go
  11. 91 0
      common/logging/log.go
  12. 16 0
      common/variables.go
  13. 14 0
      conf/config.yml
  14. 351 0
      controllers/chatroom.go
  15. 33 0
      controllers/chatroom_manager.go
  16. 313 0
      controllers/message.go
  17. 604 0
      docs/docs.go
  18. 537 0
      docs/swagger.json
  19. 349 0
      docs/swagger.yaml
  20. 421 0
      docs/swagger/swagger.json
  21. 275 0
      docs/swagger/swagger.yaml
  22. 259986 0
      logs/lzyd-message-api.log
  23. BIN
      lzyd-front-message-api
  24. 92 0
      main.go
  25. 26 0
      middleware/cors.go
  26. 205 0
      middleware/sign.go
  27. 52 0
      models/cache.go
  28. 175 0
      models/chatroom.go
  29. 94 0
      models/chatroom_manager.go
  30. 109 0
      models/message.go
  31. 8 0
      models/model.go
  32. 6 0
      models/page.go
  33. 6 0
      models/resp.go
  34. 35 0
      models/time.go
  35. 64 0
      models/user.go
  36. 54 0
      router/router.go
  37. 30 0
      services/chatroom.go
  38. 96 0
      services/chatroom_manager.go
  39. 406 0
      services/message.go
  40. 20 0
      services/mqtt.go
  41. 136 0
      services/user.go
  42. 19 0
      tingyun.json
  43. 3673 0
      tingyun.log
  44. 24 0
      utils/md5.go
  45. 80 0
      utils/oss.go
  46. 26 0
      utils/page.go
  47. 60 0
      utils/strings.go
  48. 40 0
      utils/util.go
  49. 207 0
      utils/validator.go
  50. 95 0
      utils/wx_login.go
  51. 156 0
      utils/wx_share.go
  52. 170 0
      wrapper/client.go
  53. 56 0
      wrapper/logger.go
  54. 35 0
      wrapper/message.go
  55. 154 0
      wrapper/mqtt.go

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 数据源本地存储已忽略文件
+/dataSources/
+/dataSources.local.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/

+ 9 - 0
.idea/health-live-front-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/health-live-front-api.iml" filepath="$PROJECT_DIR$/.idea/health-live-front-api.iml" />
+    </modules>
+  </component>
+</project>

+ 7 - 0
Dockerfile

@@ -0,0 +1,7 @@
+FROM alpine:latest
+
+WORKDIR $GOPATH/src/lzyd-message-api
+COPY . $GOPATH/src/lzyd-message-api
+
+EXPOSE 4004
+CMD ["./lzyd-front-message-api"]

+ 32 - 0
build.sh

@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+BUILD_PROFILE="prod"
+PORT="4004"
+LOGIN_COMMAND="login --username=admin -p=Harbor12345 121.196.188.248:5000"
+DOCKER_NAME="lzyd-front-message-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-message-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};"

+ 46 - 0
common/common.go

@@ -0,0 +1,46 @@
+package common
+
+import (
+	"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 ReturnSuccess(c *gin.Context, data interface{}) {
+	if data != nil {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    200,
+			"message": "SUCCESS",
+			"data":    data,
+		})
+	} else {
+		c.JSON(http.StatusOK, gin.H{
+			"code":    200,
+			"message": "SUCCESS",
+		})
+	}
+}
+
+/**
+返回失败Response
+*/
+func ReturnFailure(c *gin.Context, code int) {
+	c.JSON(http.StatusOK, gin.H{
+		"code":    code,
+		"message": ErrorMap[code],
+	})
+}
+func ReturnFailureMsg(c *gin.Context, code int, msg string) {
+	c.JSON(http.StatusOK, gin.H{
+		"code":    code,
+		"message": msg,
+	})
+}

+ 136 - 0
common/config.go

@@ -0,0 +1,136 @@
+package common
+
+import (
+	"fmt"
+	"github.com/aiscrm/redisgo"
+	"github.com/jinzhu/gorm"
+	_ "github.com/jinzhu/gorm/dialects/mysql"
+	"gopkg"
+	"gopkg.in/yaml.v2"
+	"io/ioutil"
+	"log"
+	"lzyd-message-api/wrapper"
+	"os"
+	"path"
+)
+
+//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
+}
+
+//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"`
+}
+
+type configModel struct {
+	Server *serverModel `yaml:"server"`
+	Log    *logModel    `yaml:"log"`
+}
+
+// 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
+	// log information
+	LoggerInfo = ConfigInfo.Log
+
+	// log config load
+	logPath := LoggerInfo.Path   //log path
+	logLevel := LoggerInfo.Level // log level
+	isDebug := true              // log mode
+	if ServerInfo.Mode == "release" {
+		isDebug = false
+	}
+	wrapper.LoggerInit(logLevel, logPath, isDebug)
+	log.SetFlags(log.Lmicroseconds | log.Lshortfile | log.LstdFlags)
+
+	// init db
+	err = initDatabase("yuedong")
+	if err != nil || DB == nil {
+		fmt.Printf("database connect failed: %s", err)
+		os.Exit(-1)
+	}
+
+	// init redis
+	err = initRedisCacher()
+	if err != nil || Cacher == nil {
+		fmt.Printf("Redis connect failed: %s", err)
+		os.Exit(-1)
+	}
+
+	// 初始化jwt中间件
+	err = initJwtMiddleware(DB, Cacher)
+	if err != nil {
+		fmt.Printf("jwt middleware load error: %s", err)
+		os.Exit(-1)
+	}
+
+	return
+}
+
+func initDatabase(dbname string) error {
+	var err error
+	//内网地址:rm-bp1cbq48ara8ex330.mysql.rds.aliyuncs.com
+	//外网地址:rm-bp1cbq48ara8ex3309o.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,
+	})
+	return err
+}
+
+func initRedisCacher() error {
+	//内网地址:r-bp15zxt342rl5rhrx9.redis.rds.aliyuncs.com
+	//外网地址:r-bp15zxt342rl5rhrx9pd.redis.rds.aliyuncs.com
+	var err error
+	Cacher, err = redisgo.New(redisgo.Options{
+		// prod
+		//Addr:     "r-bp15zxt342rl5rhrx9.redis.rds.aliyuncs.com:6379",
+		//Password: "AwCDT09m*SportRedis",
+
+		// dev
+		Addr:     "127.0.0.1:6379",
+		Password: "",
+		Db:       0,
+	})
+	return err
+}
+
+func initJwtMiddleware(db *gorm.DB, redis *redisgo.Cacher) error {
+	return nil
+}

+ 37 - 0
common/const.go

@@ -0,0 +1,37 @@
+package common
+
+/// MQTT基本配置
+const (
+	MqttServerTopic  = "root/topic/liveroom"
+	MqttClientPrefix = "root/topic/"
+	MqttServerUrl    = "tcp://121.196.31.98:1883"
+	MqttUserName     = "lzyd"
+	MqttPassword     = "j5ysE9DduHV14ioN"
+	MqttQos          = 0
+)
+
+const (
+	MessageTypeEnterChatroom = "joinroom"   // 进入房间
+	MessageTypeLeaveChatroom = "leaveroom"  // 离开房间
+	MessageTypeChatRooms     = "chatrooms"  // 给聊天室发送消息
+	MessageTypeChatGroups    = "chatgroups" // 给群组发送消息
+	MessageTypeChatUsers     = "chatusers"  // 给用户发送消息
+)
+
+const (
+	MQTTClientPrefixH5      = "liveh5"      // 前端H5
+	MQTTClientPrefixIOS     = "liveios"     // 苹果
+	MQTTClientPrefixAndroid = "liveandroid" // 安卓
+	MQTTClientPrefixMP      = "livemp"      // 小程序
+	MQTTClientPrefixServ    = "liveserv"    // 后端
+)
+
+
+const (
+	AccessKeyIdOSS  = "LTAI4FySYnBk5ME5AvbcgGmx"
+	AccessSecretOss = "AsYT0SPtPXPe1YYAmHFi1Tfcq1Pww5"
+	Endpoint     = "oss-cn-hangzhou.aliyuncs.com"
+	BucketName   = "health-live"
+	RoleArn = "acs:ram::1704590461526393:role/ramossrole"
+	SessionName = "health-uploader"
+)

+ 29 - 0
common/error.go

@@ -0,0 +1,29 @@
+package common
+
+const (
+	Success           = 200  // 返回正常
+	InternalError     = 500  // 内部错误
+	InvalidParameters = 1001 // 参数无效
+	InvalidRoom       = 1002 // 无效的房间
+	InvalidUser       = 1003 // 无效的用户
+	RecordNotFound    = 1004 // 未查询到记录
+	UserIsNotInRoom   = 1005 // 用户不在此房间
+	SendMessageError  = 1006 // 发送消息失败
+	SaveMessageError  = 1007 // 消息保存失败
+	UserIsNotAttention = 1008 // 用户没有互相关注
+	UserIsBlackAtten  = 1009 // 已拉黑
+)
+
+var ErrorMap = map[int]string{
+	Success:           "SUCCESS",
+	InternalError:     "内部错误",
+	InvalidParameters: "无效的参数",
+	InvalidRoom:       "无效的房间",
+	InvalidUser:       "无效的用户",
+	RecordNotFound:    "未查询到记录",
+	UserIsNotInRoom:   "该用户不在此房间",
+	SendMessageError:  "消息发送失败",
+	SaveMessageError:  "消息保存失败",
+	UserIsNotAttention: "用户没有互相关注",
+	UserIsBlackAtten: "存在拉黑",
+}

+ 23 - 0
common/logging/file.go

@@ -0,0 +1,23 @@
+package logging
+
+import (
+	"fmt"
+	"time"
+)
+
+// getLogFilePath get the log file save path
+func getLogFilePath() string {
+	return fmt.Sprintf("%s%s", "runtime/", "logs/")
+}
+
+// getLogFileName get the save name of the log file
+func getLogFileName() string {
+	year, month, day := time.Now().Date()
+	formatStr := fmt.Sprintf("%d%d%d", year, month, day)
+
+	return fmt.Sprintf("%s%s.%s",
+		"log-",
+		formatStr,
+		"log",
+	)
+}

+ 91 - 0
common/logging/log.go

@@ -0,0 +1,91 @@
+package logging
+
+import (
+	"fmt"
+	"github.com/EDDYCJY/go-gin-example/pkg/file"
+	"log"
+	"os"
+	"path/filepath"
+	"runtime"
+)
+
+type Level int
+
+var (
+	F *os.File
+
+	DefaultPrefix      = ""
+	DefaultCallerDepth = 2
+
+	logger     *log.Logger
+	logPrefix  = ""
+	levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
+)
+
+const (
+	DEBUG Level = iota
+	INFO
+	WARNING
+	ERROR
+	FATAL
+)
+
+// Setup initialize the log instance
+func Setup() {
+	var err error
+	filePath := getLogFilePath()
+	fileName := getLogFileName()
+	F, err = file.MustOpen(fileName, filePath)
+	if err != nil {
+		log.Fatalf("logging.Setup err: %v", err)
+	}
+
+	logger = log.New(F, DefaultPrefix, log.LstdFlags)
+}
+
+// Debug output logs at debug level
+func Debug(v ...interface{}) {
+	setPrefix(DEBUG)
+	logger.Println(v)
+	log.Println(v)
+}
+
+// Info output logs at info level
+func Info(v ...interface{}) {
+	setPrefix(INFO)
+	logger.Println(v)
+	log.Println(v)
+}
+
+// Warn output logs at warn level
+func Warn(v ...interface{}) {
+	setPrefix(WARNING)
+	logger.Println(v)
+	log.Println(v)
+}
+
+// Error output logs at error level
+func Error(v ...interface{}) {
+	setPrefix(ERROR)
+	logger.Println(v)
+	log.Println(v)
+}
+
+// Fatal output logs at fatal level
+func Fatal(v ...interface{}) {
+	setPrefix(FATAL)
+	logger.Fatalln(v)
+	log.Println(v)
+}
+
+// setPrefix set the prefix of the log output
+func setPrefix(level Level) {
+	_, file, line, ok := runtime.Caller(DefaultCallerDepth)
+	if ok {
+		logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
+	} else {
+		logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
+	}
+
+	logger.SetPrefix(logPrefix)
+}

+ 16 - 0
common/variables.go

@@ -0,0 +1,16 @@
+package common
+
+import (
+	"github.com/aiscrm/redisgo"
+	"github.com/jinzhu/gorm"
+	"lzyd-message-api/wrapper"
+)
+
+var (
+	ConfigInfo *configModel    // all server config information
+	ServerInfo *serverModel    // server config information
+	LoggerInfo *logModel       // log config information
+	MQTTClient *wrapper.Client // mqtt client instance
+	DB         *gorm.DB        // database contains
+	Cacher     *redisgo.Cacher // redis connection
+)

+ 14 - 0
conf/config.yml

@@ -0,0 +1,14 @@
+# config information
+
+# server config information
+server:
+  mode: debug # debug,release
+  host: 0.0.0.0
+  port: 4004
+
+# log config information
+log:
+  open: true
+  level: INFO # DEBUG,ERROR,INFO
+  file: logs/lzyd-message-api.log # log file path container log file name
+

+ 351 - 0
controllers/chatroom.go

@@ -0,0 +1,351 @@
+package controllers
+
+import (
+	"github.com/gin-gonic/gin"
+	"gopkg"
+	"lzyd-message-api/common"
+	"lzyd-message-api/models"
+	"lzyd-message-api/services"
+)
+
+// @tags  房间管理
+// @Description  加入房间
+// @Summary  加入房间
+// @Accept  json
+// @Produce  json
+// @Param body body models.JoinChatroomParam true "加入房间请求body"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/join [post]
+func JoinChatroom(c *gin.Context) {
+
+	var req models.JoinChatroomParam
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+	if len(req.RoomId) <= 0 || len(req.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 判断用户是否存在
+	user := services.GetUser(common.DB, req.UserId)
+	if len(user.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+
+	// 判断房间是否存在
+	room := services.GetChatroom(common.DB, req.RoomId)
+	if len(room.RoomId) <= 0 {
+		common.ReturnFailure(c, common.InvalidRoom)
+		return
+	}
+
+	chatroomUser := services.GetChatroomUser(common.DB, room.ID, req.UserId)
+
+	// 如果没有离开房间, 直接返回成功
+	if chatroomUser.ID > 0 && chatroomUser.LeaveTime == nil {
+		common.ReturnSuccess(c, nil)
+		return
+	}
+
+	// 如果离开了房间, 需要添加一条加入房间的记录
+	chatroomUser.RoomId = req.RoomId
+	chatroomUser.UserId = req.UserId
+	if err = chatroomUser.Join(common.DB); err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+
+	common.ReturnSuccess(c, nil)
+}
+
+// @tags  房间管理
+// @Description  离开房间
+// @Summary  离开房间
+// @Accept  json
+// @Produce  json
+// @Param body body models.LeaveChatroomParam true "离开房间请求body"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/leave [post]
+func LeaveChatroom(c *gin.Context) {
+
+	var req models.LeaveChatroomParam
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+	if len(req.RoomId) <= 0 || len(req.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 判断用户是否存在
+	user := services.GetUser(common.DB, req.UserId)
+	if len(user.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+
+	// 判断房间是否存在
+	room := services.GetChatroom(common.DB, req.RoomId)
+	if len(room.RoomId) <= 0 {
+		common.ReturnFailure(c, common.InvalidRoom)
+		return
+	}
+
+	chatroomUser := services.GetChatroomUser(common.DB, room.ID, req.UserId)
+
+	// 如果已经离开房间, 直接返回成功
+	if chatroomUser.LeaveTime != nil {
+		common.ReturnSuccess(c, nil)
+		return
+	}
+
+	// 如果没有离开了房间, 需要修改对应的记录, 把离开房间的时间设置为当前时间
+	if err = chatroomUser.Leave(common.DB,req.UserId); err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+
+	common.ReturnSuccess(c, nil)
+}
+
+// @tags  房间管理
+// @Description  创建聊天室
+// @Summary  创建聊天室
+// @Accept  json
+// @Produce  json
+// @Param body body models.CreateChatroomReq true "创建聊天室请求body"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/create [post]
+func CreateChatroom(c *gin.Context) {
+
+	var req models.CreateChatroomReq
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+	if len(req.BCreatorId) <= 0 || len(req.CreatorId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 判断用户是否存在
+	creatorId := services.GetUser(common.DB, req.CreatorId)
+	if len(creatorId.UserId) <= 0 {
+		//fmt.Println(111)
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+	bCreatorId := services.GetUser(common.DB, req.BCreatorId)
+	if len(bCreatorId.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+
+	var (
+		model     models.ChatroomInfo
+		code      = common.Success
+	)
+	model.RoomId = gopkg.GenUUID()
+	model.CreatorId = req.CreatorId
+	model.BCreatorId = req.BCreatorId
+	model.UserCount = 2
+	model.CreatorName = creatorId.UserName
+	model.BCreatorName = bCreatorId.UserName
+	model.CreatorAvatar = creatorId.UserAvatar
+	model.BCreatorAvatar = bCreatorId.UserAvatar
+
+	if err := model.CreateRoom(common.DB); err != nil {
+		code = common.InvalidParameters
+	}
+
+	if code != common.Success {
+		return
+	}
+	var ret = models.ChatroomInfo{
+		RoomId: model.RoomId,
+		CreatorId:     	model.CreatorId,
+		CreatorName:    model.CreatorName,
+		CreatorAvatar:    model.CreatorAvatar,
+		BCreatorId:     model.BCreatorId,
+		BCreatorName:    model.BCreatorName,
+		BCreatorAvatar:    model.BCreatorAvatar,
+		UserCount:      model.UserCount,
+	}
+	common.ReturnSuccess(c, ret)
+}
+
+// @tags  房间管理
+// @Description  获取聊天室列表
+// @Summary  获取聊天室列表
+// @Accept  json
+// @Produce  json
+// @Param userId query string true "用户ID"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/list [get]
+func GetChatroomList(c *gin.Context) {
+	userId := c.Query("userId")
+	if len(userId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 判断用户是否存在
+	creatorId := services.GetUser(common.DB, userId)
+	if len(creatorId.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+
+	var (
+		model      []models.ChatroomInfo
+	)
+	model = services.FindUser(common.DB, userId)
+	common.ReturnSuccess(c, model)
+}
+
+// @tags  房间管理
+// @Description  删除聊天室
+// @Summary  删除聊天室
+// @Accept  json
+// @Produce  json
+// @Param userId query string true "用户ID"
+// @Param roomId query string true "房间ID"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/delete [get]
+func DeleteChatroom(c *gin.Context) {
+	userId := c.Query("userId")
+	roomId := c.Query("roomId")
+
+	if len(userId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 判断用户是否存在
+	creatorId := services.GetUser(common.DB, userId)
+	if len(creatorId.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+	deleteRoom := services.DeleteRoom(common.DB,userId,roomId)
+	if deleteRoom {
+		common.ReturnSuccess(c, common.Success)
+	}
+
+}
+
+// @tags  房间管理
+// @Description  创建并加入房间
+// @Summary  创建并加入房间
+// @Accept  json
+// @Produce  json
+// @Param body body models.JoinChatroomReq true "创建并加入房间请求body"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/joinCreate [post]
+func JoinCreateChatroom(c *gin.Context) {
+
+	var req models.JoinChatroomReq
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+	if  len(req.CreatorId) <= 0 || len(req.BCreatorId) <= 0{
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 获取创建人信息
+	creatorId := services.GetUser(common.DB, req.CreatorId)
+	//fmt.Println(creatorId)
+	if len(creatorId.UserId) <= 0 {
+		//fmt.Println(111)
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+	// 获取被创建人信息
+	bCreatorId := services.GetUser(common.DB, req.BCreatorId)
+	if len(bCreatorId.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+	var (
+		model     models.ChatroomInfo
+		code      = common.Success
+	)
+
+	model.CreatorId = req.CreatorId
+	model.BCreatorId = req.BCreatorId
+	model.UserCount = req.UserCount
+	model.CreatorName = creatorId.UserName
+	model.BCreatorName = bCreatorId.UserName
+	model.CreatorAvatar = creatorId.UserAvatar
+	model.BCreatorAvatar = bCreatorId.UserAvatar
+
+	// 判断当前两用户是否存在对应房间
+	exist := services.UserInRoom(req.CreatorId,req.BCreatorId)
+	// 存在则赋值roomid
+	if exist != nil {
+		model.RoomId = exist.RoomId
+		if err := model.UploadLiveUser(common.DB); err != nil {
+			code = common.InvalidParameters
+		}
+	}else {
+		// 不存在就创建一个room
+		model.RoomId = gopkg.GenUUID()
+		if err := model.CreateRoom(common.DB); err != nil {
+			code = common.InvalidParameters
+		}else {
+			if code != common.Success {
+				return
+			}
+		}
+	}
+	var ret = models.ChatroomInfo{
+		RoomId: model.RoomId,
+		CreatorId:     	model.CreatorId,
+		CreatorName:    model.CreatorName,
+		CreatorAvatar:    model.CreatorAvatar,
+		BCreatorId:     model.BCreatorId,
+		BCreatorName:    model.BCreatorName,
+		BCreatorAvatar:    model.BCreatorAvatar,
+		UserCount:      model.UserCount,
+	}
+	// 判断用户是否存在
+	//user := services.GetUser(common.DB, req.CreatorId)
+	//buser := services.GetUser(common.DB, req.BCreatorId)
+	//
+	//fmt.Println(user)
+	//fmt.Println(buser)
+	// 判断房间是否存在
+	room := services.GetChatroom(common.DB, model.RoomId)
+	//if len(room.RoomId) <= 0 {
+	//	common.ReturnFailure(c, common.InvalidRoom)
+	//	return
+	//}
+
+	chatroomUser := services.GetChatroomUser(common.DB, room.ID, req.CreatorId)
+
+	// 如果没有离开房间, 直接返回成功
+	if chatroomUser.ID > 0 && chatroomUser.LeaveTime == nil {
+		common.ReturnSuccess(c, ret)
+		return
+	}
+
+	// 如果离开了房间, 需要添加一条加入房间的记录
+	chatroomUser.RoomId = ret.RoomId
+	chatroomUser.UserId = req.CreatorId
+	if err = chatroomUser.Join(common.DB); err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+
+	common.ReturnSuccess(c, ret)
+}

+ 33 - 0
controllers/chatroom_manager.go

@@ -0,0 +1,33 @@
+package controllers
+
+import (
+	//"fmt"
+	"github.com/gin-gonic/gin"
+	"lzyd-message-api/common"
+	"lzyd-message-api/services"
+)
+
+
+// @tags  房间操作
+// @Description  获取房间详情
+// @Summary  获取房间详情
+// @Accept  json
+// @Produce  json
+// @Param room_id query string true "房间id"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/chatroom/detail [get]
+func ChatroomDetail(c *gin.Context) {
+	roomId := c.Query("room_id")
+	if roomId == "" || roomId == "0"{
+		common.ReturnFailureMsg(c, common.InternalError, "room_id 不能为空")
+		return
+	}
+	err,data := services.ChatroomDetail(common.DB, roomId)
+	if err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+	common.ReturnSuccess(c, data)
+}
+
+

+ 313 - 0
controllers/message.go

@@ -0,0 +1,313 @@
+package controllers
+
+import (
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/jinzhu/gorm"
+	"lzyd-message-api/common"
+	"lzyd-message-api/models"
+	"lzyd-message-api/services"
+	"lzyd-message-api/utils"
+	"lzyd-message-api/wrapper"
+	"strings"
+)
+
+// @tags  消息管理
+// @Description  发送消息
+// @Summary  发送消息
+// @Accept  json
+// @Produce  json
+// @Param body body models.MessageParam true "发送请求body"
+// @Success 200 {string} json "{"code":200, "message":"success"}"
+// @Router /api/message/send [post]
+func SendMessage(c *gin.Context) {
+
+	var req models.MessageParam
+	err := c.ShouldBindJSON(&req)
+	//fmt.Println(err)
+	if err != nil {
+		common.ReturnFailureMsg(c, common.InternalError, err.Error())
+		return
+	}
+	if len(req.Message) <= 0 || len(req.UserId) <= 0 || len(req.Message) <= 0 || len(req.RoomId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+
+	// 判断用户是否存在
+	user := services.GetUser(common.DB, req.UserId)
+	//fmt.Println(req.UserId,user)
+	if len(user.UserId) <= 0 {
+		common.ReturnFailure(c, common.InvalidUser)
+		return
+	}
+	//room := services.GetUser(common.DB, req.RoomId)
+	//if len(room.UserId) <= 0 {
+	//	common.ReturnFailure(c, common.InvalidUser)
+	//	return
+	//}
+
+	// 判断房间是否存在
+	//fmt.Println(1,req.RoomId)
+	room := services.GetChatroom(common.DB, req.RoomId)
+	//fmt.Println(room)
+	if len(room.RoomId) <= 0 {
+		common.ReturnFailure(c, common.InvalidRoom)
+		return
+	}
+
+	// 判断该用户是否在这个房间
+	state := models.ChatroomUser{RoomId: req.RoomId, UserId: req.UserId}
+	if !state.IsInChatroom(common.DB) {
+		common.ReturnFailure(c, common.UserIsNotInRoom)
+		return
+	}
+
+	// userBlack 为true 表示双方存在一方有拉黑对方
+	userBlack := services.UserBlack(room.CreatorId,room.BCreatorId)
+	if userBlack {
+		common.ReturnFailure(c, common.UserIsBlackAtten)
+		return
+	}else {
+		// relation 为true 表示双方互相关注
+		relation := services.UserRelation(room.CreatorId,room.BCreatorId,req.UserId)
+		if !relation {
+			counts := services.UserSendNum(room.RoomId,req.UserId)
+			// counts 表示发送者给接收方发送的消息数量
+			if counts >= 3 {
+				common.ReturnFailure(c, common.UserIsNotAttention)
+				return
+			}
+		}
+		// 打开双方的聊天列表可见
+		liveUser := services.UploadLiveUser(room.RoomId,room.CreatorId,room.BCreatorId)
+		if liveUser {
+
+		}
+	}
+
+	// 记录到数据库
+	reviewState := 0
+	if user.Role == 1 {
+		reviewState = 1 // 直接审核通过
+	}
+	messageObject := services.MessageSql{
+		Content:     req.Message,
+		MsgType:     req.MessageType,
+		FromUid:     req.UserId,
+		TargetId:    req.RoomId,
+		TargetType:  "chatroom",
+		ReviewState: reviewState,
+	}
+
+	message := messageObject.SaveMessage(common.DB,req.UserId,req.RoomId)
+	//if len(room.RoomId) <= 0 {
+	//	common.ReturnFailure(c, common.InvalidRoom)
+	//	return
+	//}
+
+	//if err := common.DB.Save(&messageObject).Error; err != nil {
+	//	common.ReturnFailure(c, common.SaveMessageError)
+	//	return
+	//}
+
+	// 发送消息
+	// 如果是真实用户, 发送的消息需要先审核才能显示, 此时不需要发送到房间, 只单发给该用户即可
+	// 如果是模拟用户, 直接发送
+	//if user.Type == 0 {
+	//	p2pmsg := wrapper.NewMessage()
+	//	p2pmsg.Target = req.UserId
+	//	p2pmsg.MsgType = req.MessageType
+	//	p2pmsg.TargetType = "user"
+	//	p2pmsg.Msg = req.Message
+	//	p2pmsg.From = req.UserId
+	//	p2pmsg.FromName = user.Nickname
+	//	p2pmsg.FromAvatar = user.Avatar
+	//	if err = services.Publish(common.MQTTClient, p2pmsg); err != nil {
+	//		common.ReturnFailure(c, common.SendMessageError)
+	//	} else {
+	//		common.ReturnSuccess(c, nil)
+	//	}
+	//	return
+	//}
+
+	roomMsg := wrapper.NewMessage()
+	roomMsg.Target = req.RoomId
+	roomMsg.MsgType = req.MessageType
+	roomMsg.TargetType = "liveroom"
+	roomMsg.Msg = req.Message
+	roomMsg.From = req.UserId
+	roomMsg.FromName = user.UserName
+	roomMsg.FromAvatar = user.UserAvatar
+	roomMsg.MsgId = message.MsgId
+	//tmp := "2006-01-02 15:04:05"
+	//res, _ := time.ParseInLocation(tmp,message.CreatedAt, time.Local)
+	timeRes := strings.Split(message.CreatedAt,"Z")
+	timeRes = strings.Split(timeRes[0],"T")
+	var timeRes3 string
+	timeRes3 = timeRes[0]+" "+timeRes[1]
+	//fmt.Println(timeRes3)
+	//timestamp := time.Now().Unix()
+	//fmt.Println(timestamp)
+	//timeLayout := "2006-01-02 15:04:05"
+	//roomMsg.CreatedAt = time.Unix(timestamp, 0).Format(timeLayout)
+	roomMsg.CreatedAt = timeRes3
+	fmt.Println(3,message.CreatedAt)
+	if err = services.Publish(common.MQTTClient, roomMsg); err != nil {
+		common.ReturnFailure(c, common.SendMessageError)
+		return
+	}
+	common.ReturnSuccess(c, roomMsg)
+}
+
+// @tags  消息管理
+// @Summary  获取历史消息记录
+// @Description  获取历史消息记录
+// @Produce  json
+// @Param userId query string false "用户id"
+// @Param roomId query string true "房间id"
+// @Param pageIndex query int true "当前页"
+// @Param pageSize query int true "每页数量"
+// @Success 200 {string} json "{"code":200, "message":"success", "data":{}}"
+// @Router /api/message/timeline [get]
+func GetMessages(c *gin.Context) {
+
+	userId := c.Query("userId")
+	roomId := c.Query("roomId")
+	if len(userId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+	if len(roomId) <= 0 {
+		common.ReturnFailure(c, common.InvalidParameters)
+		return
+	}
+	pageIndex := utils.GetPageIndex(c)
+	pageSize := utils.GetPageSize(c)
+
+	// 判断房间是否存在
+	room := services.GetChatroom(common.DB, roomId)
+	if len(room.RoomId) <= 0 {
+		common.ReturnFailure(c, common.InvalidRoom)
+		return
+	}
+
+	var db *gorm.DB
+
+	// 获取数量
+	var count int64
+	db = common.DB.Table("lzyd_live_message")
+	if len(userId) > 0 {
+		db = db.Where("(review_state = 1 OR from_uid = ?)", userId)
+	} else {
+		db = db.Where("review_state = 1")
+	}
+	db.Where("target_id = ?", roomId).
+		Where("target_type = ?", "chatroom").
+		Where("deleted_at IS NULL").
+		Count(&count)
+	
+	var messages models.Messages
+	db = common.DB.
+		Select(`lzyd_live_message.content, lzyd_live_message.msg_type, lzyd_live_message.created_at, 
+			lzyd_user.user_id, lzyd_user.username, lzyd_user.user_avatar`).
+		Joins("JOIN lzyd_user ON lzyd_user.user_id = lzyd_live_message.from_uid")
+	//if len(userId) > 0 {
+	//	db = db.Where("(lzyd_live_message.review_state = 1 OR lzyd_live_message.from_uid = ?)", userId)
+	//} else {
+	//	db = db.Where("lzyd_live_message.review_state = 1")
+	//}
+	db.Debug().Where("lzyd_live_message.target_id = ?", roomId).
+		Where("lzyd_live_message.target_type = ?", "chatroom").
+		Where("lzyd_live_message.deleted_at IS NULL").
+		Order("lzyd_live_message.id DESC").
+		Limit(pageSize).Offset((pageIndex - 1) * pageSize).
+		Find(&messages)
+	common.ReturnSuccess(c, &models.ListResp{
+		Total: count,
+		List:  messages,
+	})
+}
+
+// @tags  消息管理
+// @Summary  获取公告
+// @Description  获取公告
+// @Produce  json
+// @Param userId query string false "用户id"
+// @Success 200 {string} json "{"code":200, "message":"success", "data":{}}"
+// @Router /api/message/notice [get]
+func GetNoticeType(c *gin.Context) {
+	userCode := c.Query("userId")
+	//if len(userCode) <= 0 {
+	//	common.ReturnFailure(c, common.InvalidParameters)
+	//	return
+	//}
+	fmt.Println(userCode)
+	var (
+		model models.NoticeTypeResp
+	)
+	model = services.QueryNoticeType(userCode)
+	common.ReturnSuccess(c, model)
+	return
+}
+
+// @tags  消息管理
+// @Description  公告阅读
+// @Summary  公告阅读
+// @Produce  json
+// @Param body body models.NoticeReadReq true "阅读公告"
+// @Success 200 {string} json "{"code":200,"message":"success","data":{}}"
+// @Router /api/message/notice/read [post]
+func ReadNotice(c *gin.Context) {
+	var req models.NoticeReadReq
+	err := c.ShouldBindJSON(&req)
+	if err != nil {
+		panic(err)
+	}
+
+	services.QueryReadNotice(req.NoticeId,req.UserId,req.AppId)
+	common.ReturnSuccess(c, nil)
+	return
+}
+
+// @tags  消息管理
+// @Summary  获取互动
+// @Description  获取互动
+// @Produce  json
+// @Param userId query string true "用户id"
+// @Success 200 {string} json "{"code":200, "message":"success", "data":{}}"
+// @Router /api/message/interact [get]
+func GetInteract(c *gin.Context) {
+	userCode := c.Query("userId")
+	//if len(userCode) <= 0 {
+	//	common.ReturnFailure(c, common.InvalidParameters)
+	//	return
+	//}
+	var (
+		model []models.InteractResp
+	)
+
+	model = services.QueryInteract(userCode)
+	common.ReturnSuccess(c, model)
+	return
+}
+
+// @tags  消息管理
+// @Summary  互动删除
+// @Description  互动删除
+// @Produce  json
+// @Param id query string true "id"
+// @Param int_type query string true "互动类型"
+// @Success 200 {string} json "{"code":200, "message":"success", "data":{}}"
+// @Router /api/message/deleteInteract [get]
+func DeleteInteract(c *gin.Context) {
+	id := c.Query("id")
+	intType := c.Query("int_type")
+
+
+	err := services.UpdateInteract(id,intType)
+	if err {
+		common.ReturnSuccess(c, common.Success)
+	}
+	return
+}

+ 604 - 0
docs/docs.go

@@ -0,0 +1,604 @@
+// 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": {
+        "/api/chatroom/create": {
+            "post": {
+                "description": "创建聊天室",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "创建聊天室",
+                "parameters": [
+                    {
+                        "description": "创建聊天室请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.CreateChatroomReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/delete": {
+            "get": {
+                "description": "删除聊天室",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "删除聊天室",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "房间ID",
+                        "name": "roomId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/detail": {
+            "get": {
+                "description": "获取房间详情",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间操作"
+                ],
+                "summary": "获取房间详情",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "room_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/join": {
+            "post": {
+                "description": "加入房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "加入房间",
+                "parameters": [
+                    {
+                        "description": "加入房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.JoinChatroomParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/joinCreate": {
+            "post": {
+                "description": "创建并加入房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "创建并加入房间",
+                "parameters": [
+                    {
+                        "description": "创建并加入房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.JoinChatroomReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/leave": {
+            "post": {
+                "description": "离开房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "离开房间",
+                "parameters": [
+                    {
+                        "description": "离开房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.LeaveChatroomParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/list": {
+            "get": {
+                "description": "获取聊天室列表",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "获取聊天室列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/deleteInteract": {
+            "get": {
+                "description": "互动删除",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "互动删除",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "互动类型",
+                        "name": "int_type",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/interact": {
+            "get": {
+                "description": "获取互动",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取互动",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/notice": {
+            "get": {
+                "description": "获取公告",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取公告",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/notice/read": {
+            "post": {
+                "description": "公告阅读",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "公告阅读",
+                "parameters": [
+                    {
+                        "description": "阅读公告",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.NoticeReadReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/send": {
+            "post": {
+                "description": "发送消息",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "发送消息",
+                "parameters": [
+                    {
+                        "description": "发送请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.MessageParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/timeline": {
+            "get": {
+                "description": "获取历史消息记录",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取历史消息记录",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "roomId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "当前页",
+                        "name": "pageIndex",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "每页数量",
+                        "name": "pageSize",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "models.CreateChatroomReq": {
+            "type": "object",
+            "properties": {
+                "bCreatorId": {
+                    "type": "string"
+                },
+                "creatorId": {
+                    "type": "string"
+                },
+                "userCount": {
+                    "type": "integer"
+                }
+            }
+        },
+        "models.JoinChatroomParam": {
+            "type": "object",
+            "properties": {
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.JoinChatroomReq": {
+            "type": "object",
+            "properties": {
+                "bCreatorId": {
+                    "type": "string"
+                },
+                "creatorId": {
+                    "type": "string"
+                },
+                "userCount": {
+                    "type": "integer"
+                }
+            }
+        },
+        "models.LeaveChatroomParam": {
+            "type": "object",
+            "properties": {
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.MessageParam": {
+            "type": "object",
+            "properties": {
+                "message": {
+                    "type": "string"
+                },
+                "messageType": {
+                    "type": "string"
+                },
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.NoticeReadReq": {
+            "type": "object",
+            "properties": {
+                "app_id": {
+                    "type": "string"
+                },
+                "notice_id": {
+                    "type": "string"
+                },
+                "user_id": {
+                    "type": "string"
+                }
+            }
+        }
+    }
+}`
+
+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:     "",
+	Host:        "",
+	BasePath:    "",
+	Schemes:     []string{},
+	Title:       "",
+	Description: "",
+}
+
+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{})
+}

+ 537 - 0
docs/swagger.json

@@ -0,0 +1,537 @@
+{
+    "swagger": "2.0",
+    "info": {
+        "contact": {}
+    },
+    "paths": {
+        "/api/chatroom/create": {
+            "post": {
+                "description": "创建聊天室",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "创建聊天室",
+                "parameters": [
+                    {
+                        "description": "创建聊天室请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.CreateChatroomReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/delete": {
+            "get": {
+                "description": "删除聊天室",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "删除聊天室",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "房间ID",
+                        "name": "roomId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/detail": {
+            "get": {
+                "description": "获取房间详情",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间操作"
+                ],
+                "summary": "获取房间详情",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "room_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/join": {
+            "post": {
+                "description": "加入房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "加入房间",
+                "parameters": [
+                    {
+                        "description": "加入房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.JoinChatroomParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/joinCreate": {
+            "post": {
+                "description": "创建并加入房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "创建并加入房间",
+                "parameters": [
+                    {
+                        "description": "创建并加入房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.JoinChatroomReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/leave": {
+            "post": {
+                "description": "离开房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "离开房间",
+                "parameters": [
+                    {
+                        "description": "离开房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.LeaveChatroomParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/list": {
+            "get": {
+                "description": "获取聊天室列表",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "获取聊天室列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户ID",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/deleteInteract": {
+            "get": {
+                "description": "互动删除",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "互动删除",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "id",
+                        "name": "id",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "互动类型",
+                        "name": "int_type",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/interact": {
+            "get": {
+                "description": "获取互动",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取互动",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/notice": {
+            "get": {
+                "description": "获取公告",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取公告",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/notice/read": {
+            "post": {
+                "description": "公告阅读",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "公告阅读",
+                "parameters": [
+                    {
+                        "description": "阅读公告",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.NoticeReadReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200,\"message\":\"success\",\"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/send": {
+            "post": {
+                "description": "发送消息",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "发送消息",
+                "parameters": [
+                    {
+                        "description": "发送请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/models.MessageParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/timeline": {
+            "get": {
+                "description": "获取历史消息记录",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取历史消息记录",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "roomId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "当前页",
+                        "name": "pageIndex",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "每页数量",
+                        "name": "pageSize",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "models.CreateChatroomReq": {
+            "type": "object",
+            "properties": {
+                "bCreatorId": {
+                    "type": "string"
+                },
+                "creatorId": {
+                    "type": "string"
+                },
+                "userCount": {
+                    "type": "integer"
+                }
+            }
+        },
+        "models.JoinChatroomParam": {
+            "type": "object",
+            "properties": {
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.JoinChatroomReq": {
+            "type": "object",
+            "properties": {
+                "bCreatorId": {
+                    "type": "string"
+                },
+                "creatorId": {
+                    "type": "string"
+                },
+                "userCount": {
+                    "type": "integer"
+                }
+            }
+        },
+        "models.LeaveChatroomParam": {
+            "type": "object",
+            "properties": {
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.MessageParam": {
+            "type": "object",
+            "properties": {
+                "message": {
+                    "type": "string"
+                },
+                "messageType": {
+                    "type": "string"
+                },
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.NoticeReadReq": {
+            "type": "object",
+            "properties": {
+                "app_id": {
+                    "type": "string"
+                },
+                "notice_id": {
+                    "type": "string"
+                },
+                "user_id": {
+                    "type": "string"
+                }
+            }
+        }
+    }
+}

+ 349 - 0
docs/swagger.yaml

@@ -0,0 +1,349 @@
+definitions:
+  models.CreateChatroomReq:
+    properties:
+      bCreatorId:
+        type: string
+      creatorId:
+        type: string
+      userCount:
+        type: integer
+    type: object
+  models.JoinChatroomParam:
+    properties:
+      roomId:
+        type: string
+      userId:
+        type: string
+    type: object
+  models.JoinChatroomReq:
+    properties:
+      bCreatorId:
+        type: string
+      creatorId:
+        type: string
+      userCount:
+        type: integer
+    type: object
+  models.LeaveChatroomParam:
+    properties:
+      roomId:
+        type: string
+      userId:
+        type: string
+    type: object
+  models.MessageParam:
+    properties:
+      message:
+        type: string
+      messageType:
+        type: string
+      roomId:
+        type: string
+      userId:
+        type: string
+    type: object
+  models.NoticeReadReq:
+    properties:
+      app_id:
+        type: string
+      notice_id:
+        type: string
+      user_id:
+        type: string
+    type: object
+info:
+  contact: {}
+paths:
+  /api/chatroom/create:
+    post:
+      consumes:
+      - application/json
+      description: 创建聊天室
+      parameters:
+      - description: 创建聊天室请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.CreateChatroomReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 创建聊天室
+      tags:
+      - 房间管理
+  /api/chatroom/delete:
+    get:
+      consumes:
+      - application/json
+      description: 删除聊天室
+      parameters:
+      - description: 用户ID
+        in: query
+        name: userId
+        required: true
+        type: string
+      - description: 房间ID
+        in: query
+        name: roomId
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 删除聊天室
+      tags:
+      - 房间管理
+  /api/chatroom/detail:
+    get:
+      consumes:
+      - application/json
+      description: 获取房间详情
+      parameters:
+      - description: 房间id
+        in: query
+        name: room_id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 获取房间详情
+      tags:
+      - 房间操作
+  /api/chatroom/join:
+    post:
+      consumes:
+      - application/json
+      description: 加入房间
+      parameters:
+      - description: 加入房间请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.JoinChatroomParam'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 加入房间
+      tags:
+      - 房间管理
+  /api/chatroom/joinCreate:
+    post:
+      consumes:
+      - application/json
+      description: 创建并加入房间
+      parameters:
+      - description: 创建并加入房间请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.JoinChatroomReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 创建并加入房间
+      tags:
+      - 房间管理
+  /api/chatroom/leave:
+    post:
+      consumes:
+      - application/json
+      description: 离开房间
+      parameters:
+      - description: 离开房间请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.LeaveChatroomParam'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 离开房间
+      tags:
+      - 房间管理
+  /api/chatroom/list:
+    get:
+      consumes:
+      - application/json
+      description: 获取聊天室列表
+      parameters:
+      - description: 用户ID
+        in: query
+        name: userId
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 获取聊天室列表
+      tags:
+      - 房间管理
+  /api/message/deleteInteract:
+    get:
+      description: 互动删除
+      parameters:
+      - description: id
+        in: query
+        name: id
+        required: true
+        type: string
+      - description: 互动类型
+        in: query
+        name: int_type
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success", "data":{}}'
+          schema:
+            type: string
+      summary: 互动删除
+      tags:
+      - 消息管理
+  /api/message/interact:
+    get:
+      description: 获取互动
+      parameters:
+      - description: 用户id
+        in: query
+        name: userId
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success", "data":{}}'
+          schema:
+            type: string
+      summary: 获取互动
+      tags:
+      - 消息管理
+  /api/message/notice:
+    get:
+      description: 获取公告
+      parameters:
+      - description: 用户id
+        in: query
+        name: userId
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success", "data":{}}'
+          schema:
+            type: string
+      summary: 获取公告
+      tags:
+      - 消息管理
+  /api/message/notice/read:
+    post:
+      description: 公告阅读
+      parameters:
+      - description: 阅读公告
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.NoticeReadReq'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200,"message":"success","data":{}}'
+          schema:
+            type: string
+      summary: 公告阅读
+      tags:
+      - 消息管理
+  /api/message/send:
+    post:
+      consumes:
+      - application/json
+      description: 发送消息
+      parameters:
+      - description: 发送请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.MessageParam'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 发送消息
+      tags:
+      - 消息管理
+  /api/message/timeline:
+    get:
+      description: 获取历史消息记录
+      parameters:
+      - description: 用户id
+        in: query
+        name: userId
+        type: string
+      - description: 房间id
+        in: query
+        name: roomId
+        required: true
+        type: string
+      - description: 当前页
+        in: query
+        name: pageIndex
+        required: true
+        type: integer
+      - description: 每页数量
+        in: query
+        name: pageSize
+        required: true
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success", "data":{}}'
+          schema:
+            type: string
+      summary: 获取历史消息记录
+      tags:
+      - 消息管理
+swagger: "2.0"

+ 421 - 0
docs/swagger/swagger.json

@@ -0,0 +1,421 @@
+{
+    "swagger": "2.0",
+    "info": {
+        "contact": {},
+        "license": {}
+    },
+    "paths": {
+        "/api/chatroom/classification": {
+            "get": {
+                "description": "房间分类列表",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间操作"
+                ],
+                "summary": "房间分类列表",
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/detail": {
+            "get": {
+                "description": "获取房间详情",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间操作"
+                ],
+                "summary": "获取房间详情",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "room_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/join": {
+            "post": {
+                "description": "加入房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "加入房间",
+                "parameters": [
+                    {
+                        "description": "加入房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.JoinChatroomParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/leave": {
+            "post": {
+                "description": "离开房间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间管理"
+                ],
+                "summary": "离开房间",
+                "parameters": [
+                    {
+                        "description": "离开房间请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.LeaveChatroomParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/list": {
+            "post": {
+                "description": "房间列表",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间操作"
+                ],
+                "summary": "房间列表",
+                "parameters": [
+                    {
+                        "description": "房间请求列表body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.ChatRoomListReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/chatroom/view": {
+            "get": {
+                "description": "进入直播间",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "房间操作"
+                ],
+                "summary": "进入直播间",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "room_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/graphic/list": {
+            "get": {
+                "description": "图文列表",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "直播间图文"
+                ],
+                "summary": "图文列表",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "room_id",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/send": {
+            "post": {
+                "description": "发送消息",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "发送消息",
+                "parameters": [
+                    {
+                        "description": "发送请求body",
+                        "name": "body",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/models.MessageParam"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/message/timeline": {
+            "get": {
+                "description": "获取历史消息记录",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "消息管理"
+                ],
+                "summary": "获取历史消息记录",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "用户id",
+                        "name": "userId",
+                        "in": "query"
+                    },
+                    {
+                        "type": "string",
+                        "description": "房间id",
+                        "name": "roomId",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "当前页",
+                        "name": "pageIndex",
+                        "in": "query",
+                        "required": true
+                    },
+                    {
+                        "type": "integer",
+                        "description": "每页数量",
+                        "name": "pageSize",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\", \"data\":{}}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/api/wx/share": {
+            "get": {
+                "description": "微信自定义分享",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户操作"
+                ],
+                "summary": "分享",
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/wx/h5/login": {
+            "get": {
+                "description": "登录",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "用户操作"
+                ],
+                "summary": "登录",
+                "responses": {
+                    "200": {
+                        "description": "{\"code\":200, \"message\":\"success\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "models.ChatRoomListReq": {
+            "type": "object",
+            "properties": {
+                "category": {
+                    "type": "string"
+                },
+                "name": {
+                    "type": "string"
+                },
+                "page": {
+                    "type": "integer"
+                },
+                "pageSize": {
+                    "type": "integer"
+                }
+            }
+        },
+        "models.JoinChatroomParam": {
+            "type": "object",
+            "properties": {
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.LeaveChatroomParam": {
+            "type": "object",
+            "properties": {
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        },
+        "models.MessageParam": {
+            "type": "object",
+            "properties": {
+                "message": {
+                    "type": "string"
+                },
+                "messageType": {
+                    "type": "string"
+                },
+                "roomId": {
+                    "type": "string"
+                },
+                "userId": {
+                    "type": "string"
+                }
+            }
+        }
+    }
+}

+ 275 - 0
docs/swagger/swagger.yaml

@@ -0,0 +1,275 @@
+definitions:
+  models.ChatRoomListReq:
+    properties:
+      category:
+        type: string
+      name:
+        type: string
+      page:
+        type: integer
+      pageSize:
+        type: integer
+    type: object
+  models.JoinChatroomParam:
+    properties:
+      roomId:
+        type: string
+      userId:
+        type: string
+    type: object
+  models.LeaveChatroomParam:
+    properties:
+      roomId:
+        type: string
+      userId:
+        type: string
+    type: object
+  models.MessageParam:
+    properties:
+      message:
+        type: string
+      messageType:
+        type: string
+      roomId:
+        type: string
+      userId:
+        type: string
+    type: object
+info:
+  contact: {}
+  license: {}
+paths:
+  /api/chatroom/classification:
+    get:
+      consumes:
+      - application/json
+      description: 房间分类列表
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 房间分类列表
+      tags:
+      - 房间操作
+  /api/chatroom/detail:
+    get:
+      consumes:
+      - application/json
+      description: 获取房间详情
+      parameters:
+      - description: 房间id
+        in: query
+        name: room_id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 获取房间详情
+      tags:
+      - 房间操作
+  /api/chatroom/join:
+    post:
+      consumes:
+      - application/json
+      description: 加入房间
+      parameters:
+      - description: 加入房间请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.JoinChatroomParam'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 加入房间
+      tags:
+      - 房间管理
+  /api/chatroom/leave:
+    post:
+      consumes:
+      - application/json
+      description: 离开房间
+      parameters:
+      - description: 离开房间请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.LeaveChatroomParam'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 离开房间
+      tags:
+      - 房间管理
+  /api/chatroom/list:
+    post:
+      consumes:
+      - application/json
+      description: 房间列表
+      parameters:
+      - description: 房间请求列表body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.ChatRoomListReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 房间列表
+      tags:
+      - 房间操作
+  /api/chatroom/view:
+    get:
+      consumes:
+      - application/json
+      description: 进入直播间
+      parameters:
+      - description: 房间id
+        in: query
+        name: room_id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 进入直播间
+      tags:
+      - 房间操作
+  /api/graphic/list:
+    get:
+      consumes:
+      - application/json
+      description: 图文列表
+      parameters:
+      - description: 房间id
+        in: query
+        name: room_id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 图文列表
+      tags:
+      - 直播间图文
+  /api/message/send:
+    post:
+      consumes:
+      - application/json
+      description: 发送消息
+      parameters:
+      - description: 发送请求body
+        in: body
+        name: body
+        required: true
+        schema:
+          $ref: '#/definitions/models.MessageParam'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 发送消息
+      tags:
+      - 消息管理
+  /api/message/timeline:
+    get:
+      description: 获取历史消息记录
+      parameters:
+      - description: 用户id
+        in: query
+        name: userId
+        type: string
+      - description: 房间id
+        in: query
+        name: roomId
+        required: true
+        type: string
+      - description: 当前页
+        in: query
+        name: pageIndex
+        required: true
+        type: integer
+      - description: 每页数量
+        in: query
+        name: pageSize
+        required: true
+        type: integer
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success", "data":{}}'
+          schema:
+            type: string
+      summary: 获取历史消息记录
+      tags:
+      - 消息管理
+  /api/wx/share:
+    get:
+      consumes:
+      - application/json
+      description: 微信自定义分享
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 分享
+      tags:
+      - 用户操作
+  /wx/h5/login:
+    get:
+      consumes:
+      - application/json
+      description: 登录
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"code":200, "message":"success"}'
+          schema:
+            type: string
+      summary: 登录
+      tags:
+      - 用户操作
+swagger: "2.0"

File diff suppressed because it is too large
+ 259986 - 0
logs/lzyd-message-api.log


BIN
lzyd-front-message-api


+ 92 - 0
main.go

@@ -0,0 +1,92 @@
+package main
+
+import (
+	"flag"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"go.uber.org/zap"
+	"lzyd-message-api/common"
+	"lzyd-message-api/models"
+	"lzyd-message-api/router"
+	"lzyd-message-api/wrapper"
+	"os"
+	"path"
+	"time"
+	"github.com/TingYunAPM/go"
+)
+
+func main() {
+	models.MemoryCacheVar = new(models.MemoryCache)
+	models.MemoryCacheVar.Items = make(map[string]*models.Item)
+
+	//初始化tingyun: 应用名称、帐号等在tingyun.json中配置
+
+	tingyun.AppInit("tingyun.json")
+
+	defer tingyun.AppStop()
+
+	//原有业务逻辑
+
+	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
+	}
+
+	// 先启动MQTT服务
+	go StartMQTTServer()
+
+	if common.ServerInfo.Mode == "debug" {
+		gin.SetMode(gin.DebugMode)
+
+	} else if common.ServerInfo.Mode == "release" {
+		gin.SetMode(gin.ReleaseMode)
+	}
+
+	defer func() {
+		_ = wrapper.Logger.Sync()
+	}()
+
+	//router init
+	r := router.InitRouter()
+
+	server := common.ServerInfo
+	serverInfo := server.Host + ":" + server.Port
+
+	// restart
+	wrapper.Logger.Info("server start info: " + serverInfo)
+	err = r.Run(serverInfo)
+	if err != nil {
+		wrapper.Logger.Error("server start failed: " + err.Error())
+	}
+}
+
+func StartMQTTServer() {
+
+	clientId := common.MQTTClientPrefixServ + "-" + time.Now().Format("20060102150405")
+	common.MQTTClient = wrapper.NewClient(common.MqttServerUrl, common.MqttUserName, common.MqttPassword, clientId)
+	common.MQTTClient.SetQOS(byte(common.MqttQos))
+	common.MQTTClient.SetkeepAliveInterval(time.Second * 30)
+	common.MQTTClient.SetPingTimeout(time.Second * 1)
+
+	//Start the MQTT client.
+	err := common.MQTTClient.Start()
+	if err != nil {
+		fmt.Printf("MQTT启动失败: %s \n", err.Error())
+	}
+
+
+		err = common.MQTTClient.Subscribe(common.MqttServerTopic, func(topic string, msg *wrapper.Message) {
+			//services.MqttMessageHandler(msg)
+		})
+		if err != nil {
+			wrapper.Logger.Info("[MQTT]订阅失败", zap.String("error", err.Error()))
+		} else {
+			wrapper.Logger.Info("[MQTT]订阅成功", zap.String("topic", common.MqttServerTopic))
+		}
+
+}

+ 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-message-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))
+}
+
+
+

+ 52 - 0
models/cache.go

@@ -0,0 +1,52 @@
+package models
+
+import (
+	"sync"
+	"time"
+)
+
+var MemoryCacheVar  *MemoryCache
+
+// 数据缓存处理
+type Item struct {
+	Value      string
+	CreateTime time.Time
+	LifeTime   time.Duration
+}
+
+type MemoryCache struct {
+	sync.RWMutex
+	Items map[string]*Item
+}
+
+
+func (mc *MemoryCache) Put(key string, value string, lifeTime time.Duration) {
+	mc.Lock()
+	defer mc.Unlock()
+	mc.Items[key] = &Item{
+		LifeTime:   lifeTime,
+		Value:      value,
+		CreateTime: time.Now(),
+	}
+}
+
+func (mc *MemoryCache) Get(key string) interface{} {
+	mc.RLock()
+	defer mc.RUnlock()
+	if e, ok := mc.Items[key]; ok {
+		if !e.isExpire() {
+			return e
+		} else {
+			delete(mc.Items, key)
+		}
+	}
+	return nil
+}
+
+func (e *Item) isExpire() bool {
+	if e.LifeTime == 0 {
+		return false
+	}
+	//根据创建时间和生命周期判断元素是否失效
+	return time.Now().Sub(e.CreateTime) > e.LifeTime
+}

+ 175 - 0
models/chatroom.go

@@ -0,0 +1,175 @@
+package models
+
+import (
+	"fmt"
+	"github.com/jinzhu/gorm"
+	"lzyd-message-api/common"
+	"time"
+)
+
+type JoinChatroomParam struct {
+	RoomId string `json:"roomId"`
+	UserId string `json:"userId"`
+}
+
+type LeaveChatroomParam struct {
+	RoomId string `json:"roomId"`
+	UserId string `json:"userId"`
+}
+
+type CreateChatroomReq struct {
+	CreatorId string `json:"creatorId"`
+	BCreatorId string `json:"bCreatorId"`
+	UserCount int `json:"userCount"`
+}
+
+type JoinChatroomReq struct {
+	CreatorId string `json:"creatorId"`
+	BCreatorId string `json:"bCreatorId"`
+	UserCount int `json:"userCount"`
+}
+
+type ChatroomInfo struct {
+	RoomId     string    `gorm:"column:room_id" json:"room_id"`
+	Name       string    `gorm:"column:name" json:"name"`
+	CreatorId    string    `gorm:"column:creator_id" json:"creator_id"`
+	BCreatorId   string    `gorm:"column:b_creator_id" json:"b_creator_id"`
+	UserCount  int    `gorm:"column:user_count" json:"user_count"`
+	CreatorName string    `gorm:"column:creator_name" json:"creator_name"`
+	BCreatorName string    `gorm:"column:b_creator_name" json:"b_creator_name"`
+	CreatorAvatar string    `gorm:"column:creator_avatar" json:"creator_avatar"`
+	BCreatorAvatar string    `gorm:"column:b_creator_avatar" json:"b_creator_avatar"`
+	Count 	int    `gorm:"column:Count" json:"count"`
+	NewContent string `gorm:"column:new_content" json:"new_content"`
+	MsgTime string `gorm:"column:msg_time" json:"msg_time"`
+	UpdatedAt string `gorm:"column:updated_at" json:"updated_at"`
+	IsShow int `gorm:"column:is_show" json:"is_show"`
+}
+
+type ChatroomUser struct {
+	ID        int64     `gorm:"column:id" json:"id"`
+	RoomId    string    `gorm:"column:room_id" json:"room_id"`
+	UserId    string    `gorm:"column:user_id" json:"user_id"`
+	JoinTime  *JSONTime `gorm:"column:join_time" json:"join_time"`
+	LeaveTime *JSONTime `gorm:"column:leave_time" json:"leave_time"`
+}
+
+type UsersInRoom struct {
+	RoomId string `gorm:"column:room_id" json:"room_id"`
+}
+
+type RoomUsers struct {
+	CreatorId     string `json:"creator_id"      gorm:"column:creator_id"`
+	BCreatorId     string `json:"b_creator_id"     gorm:"column:b_creator_id"`
+	LeaveTime  string `json:"leave_time"     gorm:"column:leave_time"`
+}
+
+type Chatroom struct {
+	Model
+	RoomId string `gorm:"column:room_id" json:"room_id"`
+	Name   string `gorm:"column:name" json:"name"`
+	CreatorId string `gorm:"column:creator_id" json:"creator_id"`
+	BCreatorId string `gorm:"column:b_creator_id" json:"b_creator_id"`
+}
+
+func (Chatroom) TableName() string {
+	return "lzyd_live_chatroom"
+}
+
+func (ChatroomUser) TableName() string {
+	return "lzyd_live_chatroom_user"
+}
+
+func (p ChatroomUser) Join(db *gorm.DB) error {
+	sql := "INSERT INTO lzyd_live_chatroom_user(room_id, user_id, join_time) VALUES(?,?,NOW())"
+	err := db.Exec(sql, p.RoomId, p.UserId).Error
+
+	var roomUser RoomUsers
+	sql1 := "SELECT creator_id, b_creator_id from lzyd_live_chatroom WHERE room_id=?"
+	common.DB.Raw(sql1, p.RoomId).Find(&roomUser)
+	var user string
+	if roomUser.CreatorId == p.UserId {
+		user = roomUser.BCreatorId
+	}else {
+		user = roomUser.CreatorId
+	}
+	//fmt.Println(user)
+	sql2 := "UPDATE lzyd_live_message SET status = 1 WHERE target_id = ? && from_uid = ? "
+	err2 := db.Exec(sql2, p.RoomId, user).Error
+	fmt.Println(err2)
+
+	return err
+}
+
+func (ChatroomUser) Leave(db *gorm.DB, UserId string) error {
+	fmt.Println(111,UserId)
+	var user ChatroomUser
+	err := db.Where("user_id=?", UserId).Last(&user).Update("leave_time", time.Now()).Error
+	//sql := "UPDATE lzyd_live_chatroom_user SET leave_time = NOW() WHERE user_id = ?"
+	//err := db.Exec(sql, UserId).Error
+	return err
+}
+
+func (p ChatroomUser) IsInChatroom(db *gorm.DB) bool {
+	var count int
+	sql := "SELECT COUNT(id) AS count FROM lzyd_live_chatroom_user WHERE room_id = ? AND user_id = ? AND leave_time IS NULL"
+	db.Raw(sql, p.RoomId, p.UserId).Count(&count)
+	fmt.Println(count)
+	return count > 0
+}
+
+func (p ChatroomInfo) CreateRoom(db *gorm.DB)error {
+	now := time.Now()
+	tx := db.Begin()
+	//fmt.Println(111,now)
+	var (
+		insertInfoSql  string
+		insertInfoErr  error
+		insertRoom1Sql  string
+		insertRoom1Err  error
+		insertRoom2Sql  string
+		insertRoom2Err  error
+	)
+	insertInfoSql = "INSERT INTO lzyd_live_chatroom(room_id, creator_id, b_creator_id, creator_name, b_creator_name,creator_avatar,b_creator_avatar, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?)"
+	insertInfoErr = db.Exec(insertInfoSql, p.RoomId, p.CreatorId, p.BCreatorId, p.CreatorName, p.BCreatorName, p.CreatorAvatar, p.BCreatorAvatar, now, now).Error
+
+	insertRoom1Sql = "INSERT INTO lzyd_live_user(room_id, user_id, status, created_at, updated_at) VALUES (?,?,?,?,?)"
+	insertRoom1Err = db.Exec(insertRoom1Sql, p.RoomId, p.CreatorId,1, now, now).Error
+
+	insertRoom2Sql = "INSERT INTO lzyd_live_user(room_id, user_id, status, created_at, updated_at) VALUES (?,?,?,?,?)"
+	insertRoom2Err = db.Exec(insertRoom2Sql, p.RoomId, p.BCreatorId,1, now, now).Error
+
+	if insertInfoErr != nil && insertRoom1Err != nil && insertRoom2Err != nil {
+		tx.Rollback()
+		//return errors.New(common.ErrorInfo[common.DbInsertErr])
+	}
+	tx.Commit()
+
+	return nil
+}
+
+func (p ChatroomInfo) UploadLiveUser(db *gorm.DB) error {
+	tx := db.Begin()
+
+	var (
+		upDateInfoSql1  string
+		upDateInfoErr1  error
+		//upDateInfoSql2  string
+		//upDateInfoErr2  error
+	)
+	fmt.Println(p)
+	upDateInfoSql1 = "UPDATE lzyd_live_user SET status = 1 WHERE user_id = ? && room_id = ?"
+	upDateInfoErr1 = db.Exec(upDateInfoSql1, p.CreatorId, p.RoomId).Error
+	//upDateInfoSql2 = "UPDATE lzyd_live_user SET status = 1 WHERE user_id = ? && room_id = ?"
+	//upDateInfoErr2 = db.Exec(upDateInfoSql2, p.BCreatorId, p.RoomId).Error
+
+
+	//if upDateInfoErr1 != nil && upDateInfoErr2 != nil {
+	//	tx.Rollback()
+	//}
+	if upDateInfoErr1 != nil {
+		tx.Rollback()
+	}
+	tx.Commit()
+	return nil
+}

+ 94 - 0
models/chatroom_manager.go

@@ -0,0 +1,94 @@
+package models
+
+type PageInfo struct {
+	Page     int `json:"page" form:"page"`
+	PageSize int `json:"pageSize" form:"pageSize"`
+}
+
+type PageResult struct {
+	List     interface{} `json:"list"`
+	Total    int         `json:"total"`
+	Page     int         `json:"page"`
+	PageSize int         `json:"pageSize"`
+}
+
+type Count struct {
+	Count    int		 `json:"count"`
+}
+
+type ViewCount struct {
+	ViewCount		int 		`json:"view_count"`
+}
+
+type ChatRoomCreateReq struct {
+	Name   			 string 			`json:"name"`   		// 房间名称
+	Url 			 string 			`json:"url"` 			// url 地址
+	Cover 		 	 string 			`json:"cover"`  		// 封面
+	Intro        	 string 			`json:"intro"`  		// 简介
+	Category 		 int 				`json:"category"` 		// 分类
+	WithGraphic  	 int 				`json:"with_graphic"`	// 是否带有图文直播
+	WithChatRoom 	 int 				`json:"with_chatroom"`  // 是否带有聊天室
+	State  			 int 				`json:"state"`			// 直播状态(1预告2直播3回放)
+	StartTime 	     string 			`json:"start_time"`
+	EndTime 		 string 			`json:"end_time"`
+	SenderName       string 			`json:"sender_name"` 	 // 发送者名称
+	SenderAvatar 	 string 			`json:"sender_avatar"`	 // 发送者头像
+}
+
+
+type ChatRoomDelReq struct {
+	RoomId 				int   			`json:"room_id"`
+}
+
+
+type ChatRoomListReq struct {
+	Name 			string 			`json:"name"`      // 匹配标题
+	Category 	    string 			`json:"category"`  // 分类
+	PageInfo
+}
+
+type GraphicDetail struct {
+	Id 				 int 				`json:"id"`
+	GraphicId 		 int 				`json:"graphic_id"`
+	Type 			 int				`json:"type"`
+	Content 		 string				`json:"content"`
+	CreatedAt 		 string 			`json:"created_at"`
+	UpdatedAt 		 string 			`json:"updated_at"`
+}
+
+type GraphicListDataRes struct {
+	GraphicId 		 int 				`json:"graphic_id"`
+	SenderName		 string 			`json:"sender_name"`
+	SenderAvatar	 string 			`json:"sender_avatar"`
+	List 			 []GraphicDetail
+	CreatedAt 		 string 			`json:"created_at"`
+	UpdatedAt 		 string 			`json:"updated_at"`
+}
+
+
+type ChatRoomListRes struct {
+	Id 				 int 				`json:"id"`
+	RoomId 			 int 				`json:"room_id"`
+	Name   			 string 			`json:"name"`   		// 房间名称
+	Url 			 string 			`json:"url"` 			// url 地址
+	Cover 		 	 string 			`json:"cover"`  		// 封面
+	Intro        	 string 			`json:"intro"`  		// 简介
+	Category 		 string 			`json:"category"` 		// 分类
+	WithGraphic  	 int 				`json:"with_graphic"`	// 是否带有图文直播
+	WithChatRoom 	 int 				`json:"with_chat_room"`  // 是否带有聊天室
+	State  			 int 				`json:"state"`			// 直播状态(1预告2直播3回放)
+	StartTime 	     string 			`json:"start_time"`
+	EndTime 		 string 			`json:"end_time"`
+	SenderName       string 			`json:"sender_name"` 	 // 发送者名称
+	SenderAvatar 	 string 			`json:"sender_avatar"`	 // 发送者头像
+	ViewCount 		 string 			`json:"view_count"`		 // 直播观看数
+	CreatedAt 		 string 			`json:"created_at"`
+	UpdatedAt 		 string 			`json:"updated_at"`
+}
+
+type ChatRoomClassificationRes struct {
+	Id 				 int 				`json:"id"`
+	Name 			 string 			`json:"name"`
+	CreatedAt 		 string 			`json:"created_at"`
+	UpdatedAt 		 string 			`json:"updated_at"`
+}

+ 109 - 0
models/message.go

@@ -0,0 +1,109 @@
+package models
+
+type MessageParam struct {
+	UserId      string `json:"userId"`
+	RoomId      string `json:"roomId"`
+	Message     string `json:"message"`
+	MessageType string `json:"messageType"`
+}
+
+type Message struct {
+	Content     string `json:"content"      gorm:"column:content"`
+	MsgType     string `json:"msg_type"     gorm:"column:msg_type"`
+	FromUid     string `json:"from_uid"     gorm:"column:from_uid"`
+	TargetId    string `json:"target_id"    gorm:"column:target_id"`
+	TargetType  string `json:"target_type"  gorm:"column:target_type"`
+	ReviewState int    `json:"review_state" gorm:"column:review_state"`
+}
+
+type RoomUser struct {
+	CreatorId     string `json:"creator_id"      gorm:"column:creator_id"`
+	BCreatorId     string `json:"b_creator_id"     gorm:"column:b_creator_id"`
+	LeaveTime  string `json:"leave_time"     gorm:"column:leave_time"`
+}
+
+type MessageResp struct {
+	Content   string   `json:"msg"    gorm:"column:content"`
+	MsgType   string   `json:"msg_type"   gorm:"column:msg_type"`
+	UserId    string   `json:"from"    gorm:"column:user_id"`
+	Username  string   `json:"from_name"   gorm:"column:username"`
+	UserAvatar    string   `json:"from_avatar"     gorm:"column:user_avatar"`
+	UserType  int      `json:"user_type"  gorm:"column:user_type"`
+	CreatedAt JSONTime `json:"created_at" gorm:"column:created_at"`
+}
+
+type NoticeResp struct {
+	Content    string   `json:"content"     gorm:"column:content"`
+	NoticeId   string   `json:"notice_id"   gorm:"column:notice_id"`
+	AppId      string   `json:"app_id"      gorm:"column:app_id"`
+	Title      string   `json:"title"       gorm:"column:title"`
+	UpdateAt   string   `json:"update_at"   gorm:"column:update_at"`
+	DeleteAt   string      `json:"delete_at"   gorm:"column:delete_at"`
+	NoticeSkipType   int      `json:"notice_skip_type"   gorm:"column:notice_skip_type"`
+	NoticeTypeId   string      `json:"notice_type_id"   gorm:"column:notice_type_id"`
+	LinkUrl   string      `json:"link_url"   gorm:"column:link_url"`
+	Status    int      `json:"status"   gorm:"column:status"`
+}
+
+type NoticeTypeResp struct {
+	NoticeAvatar    string   `json:"notice_avatar"     gorm:"column:notice_avatar"`
+	NoticeName   string   `json:"notice_name"   gorm:"column:notice_name"`
+	NoticeTypeId      string   `json:"notice_type_id"      gorm:"column:notice_type_id"`
+	Title      string   `json:"title"      gorm:"column:title"`
+	Content   string   `json:"content"   gorm:"column:content"`
+	UpdateAt   string      `json:"update_at"   gorm:"column:update_at"`
+	List []NoticeResp `json:"list"`
+}
+
+type NewContent struct {
+	Title      string   `json:"title"      gorm:"column:title"`
+	Content   string   `json:"content"   gorm:"column:content"`
+	UpdateAt   string      `json:"update_at"   gorm:"column:update_at"`
+}
+
+type InteractResp struct {
+	Id 	int   `json:"id"     gorm:"column:id"`
+	UserAvatar  string   `json:"user_avatar"     gorm:"column:user_avatar"`
+	Username   string   `json:"username"   gorm:"column:username"`
+	VideoId      string   `json:"video_id"      gorm:"column:video_id"`
+	UserId      string   `json:"user_id"      gorm:"column:user_id"`
+	CommentId      string   `json:"comment_id"      gorm:"column:comment_id"`
+	CommentContent      string   `json:"comment_content"      gorm:"column:content"`
+	VideoCover string   `json:"video_cover"      gorm:"column:cover"`
+	ResourceId string   `json:"resource_id"      gorm:"column:resource_id"`
+	IntType      string   `json:"int_type"      gorm:"column:int_type"`  // 0点赞 1转发 2不感兴趣 3评论 4关注 5回复评论
+	UpdateAt   string   `json:"updated_at"   gorm:"column:updated_at"`
+}
+
+type InteractRespList []InteractResp
+
+type NoticeReadResp struct {
+	NoticeId   string   `json:"notice_id"   gorm:"column:notice_id"`
+	UserId    string   `json:"user_id"    gorm:"column:user_id"`
+}
+
+type UserRelationResp struct {
+	AttentionUserId   string   `json:"attention_user_id"   gorm:"column:attention_user_id"`
+}
+
+type UserSendResp struct {
+	TargetId   string   `json:"target_id"   gorm:"column:target_id"`
+}
+
+type NoticeReadReq struct {
+	NoticeId   string   `json:"notice_id"`
+	UserId    string   `json:"user_id" `
+	AppId      string   `json:"app_id" `
+}
+
+type Messages []*MessageResp
+
+func (Message) TableName() string {
+	return "lzyd_live_message"
+}
+
+func (MessageResp) TableName() string {
+	return "lzyd_live_message"
+}
+
+

+ 8 - 0
models/model.go

@@ -0,0 +1,8 @@
+package models
+
+type Model struct {
+	ID        int64    `gorm:"column:id;primary_key;auto_increment;"`
+	CreatedAt JSONTime `gorm:"column:created_at"`
+	UpdatedAt JSONTime `gorm:"column:updated_at"`
+	DeletedAt JSONTime `gorm:"column:deleted_at"`
+}

+ 6 - 0
models/page.go

@@ -0,0 +1,6 @@
+package models
+
+type PageQuery struct {
+	PageIndex int
+	PageSize  int
+}

+ 6 - 0
models/resp.go

@@ -0,0 +1,6 @@
+package models
+
+type ListResp struct {
+	Total int64       `json:"total"`
+	List  interface{} `json:"list"`
+}

+ 35 - 0
models/time.go

@@ -0,0 +1,35 @@
+package models
+
+import (
+	"database/sql/driver"
+	"fmt"
+	"time"
+)
+
+type JSONTime time.Time
+
+func (t JSONTime) MarshalJSON() ([]byte, error) {
+	ti := time.Time(t)
+	tune := ti.Format(`"2006-01-02 15:04:05"`)
+	return []byte(tune), nil
+}
+
+// Value insert timestamp into mysql need this function.
+func (t JSONTime) Value() (driver.Value, error) {
+	var zeroTime time.Time
+	ti := time.Time(t)
+	if ti.UnixNano() == zeroTime.UnixNano() {
+		return nil, nil
+	}
+	return ti, nil
+}
+
+// Scan ValueOf time.Time
+func (t *JSONTime) Scan(v interface{}) error {
+	ti, ok := v.(time.Time) // NOT directly assertion v.(JSONTime)
+	if ok {
+		*t = JSONTime(ti)
+		return nil
+	}
+	return fmt.Errorf("can not convert %v to timestamp", v)
+}

+ 64 - 0
models/user.go

@@ -0,0 +1,64 @@
+package models
+
+type User 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:"user_name"`  //昵称
+	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  float64  `gorm:"column:total_distance" json:"total_distance"`//总公里数
+	TimesMarathon  int64  `gorm:"column:times_marathon" json:"times_marathon"`//马拉松场次
+	TimesQualifier  int64  `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
+}
+
+func (User) TableName() string {
+	return "lzyd_user"
+}
+
+type LoginReq struct {
+	WxCode string `json:"wx_code"`
+}
+
+type UserInfoRes struct {
+	Id        int    `json:"id"`
+	UserId    string `json:"user_id"`
+	UserName  string `json:"username"`
+	Mobile    string `json:"mobile_phone"`
+	RealName  string `json:"real_name"`
+	UserAvatar    string `json:"user_avatar"`
+}
+
+type MessageList struct {
+	Content   string  `gorm:"column:content;" json:"content"`
+	NewContent string  `gorm:"column:new_content;" json:"new_content"`
+	UpdatedAt  string  `gorm:"column:updated_at;" json:"updated_at"`
+}
+
+type IsShow struct {
+	IsShow   int  `gorm:"column:status;" json:"is_show"`
+}
+

+ 54 - 0
router/router.go

@@ -0,0 +1,54 @@
+package router
+
+import (
+	tingyun_gin "github.com/TingYunAPM/go/framework/gin"
+	"github.com/gin-gonic/gin"
+	"github.com/swaggo/gin-swagger"
+	"github.com/swaggo/gin-swagger/swaggerFiles"
+	"gopkg"
+	"lzyd-message-api/controllers"
+	_ "lzyd-message-api/docs" // docs is generated by Swag CLI, you have to import it.
+	"lzyd-message-api/middleware"
+)
+
+func InitRouter() *tingyun_gin.WrapEngine {
+
+	// Creates a gin router with default middleware:
+	// logger and recovery (crash-free) middleware
+	router := tingyun_gin.Default()
+	router.Use(gin.Recovery())
+	router.Use(gopkg.CORSMiddleware())
+
+	// use ginSwagger middleware to
+	router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
+
+	// 微信授权
+	//wx := router.Group("/wx")
+	//wx.GET("/h5/login", controllers.Login)
+
+	api := router.Group("/api")
+	api.Use(middleware.ValidSign(true))
+	// api.Use(middleware.ValidHeaderParams(true))
+
+	/// 房间管理
+	api.POST("/chatroom/join", controllers.JoinChatroom)
+	api.POST("/chatroom/leave", controllers.LeaveChatroom)
+	api.POST("/chatroom/create", controllers.CreateChatroom)
+	api.GET("/chatroom/list", controllers.GetChatroomList)
+	api.GET("/chatroom/delete", controllers.DeleteChatroom)
+	api.POST("/chatroom/joinCreate", controllers.JoinCreateChatroom)
+
+	// 消息管理
+	api.POST("/message/send", controllers.SendMessage)
+	api.GET("/message/timeline", controllers.GetMessages)
+	api.GET("/message/notice", controllers.GetNoticeType)
+	api.POST("/message/notice/read", controllers.ReadNotice)
+	api.GET("/message/interact", controllers.GetInteract)
+	api.GET("/message/deleteInteract", controllers.DeleteInteract)
+
+	// 直播间
+	api.GET("/chatroom/detail", controllers.ChatroomDetail)
+
+
+	return router
+}

+ 30 - 0
services/chatroom.go

@@ -0,0 +1,30 @@
+package services
+
+import (
+	"github.com/jinzhu/gorm"
+	"lzyd-message-api/common"
+	"lzyd-message-api/models"
+)
+
+func GetChatroom(db *gorm.DB, roomId string) *models.Chatroom {
+	var chatroom models.Chatroom
+	db.Where("room_id = ?", roomId).Find(&chatroom)
+	return &chatroom
+}
+
+func GetChatroomUser(db *gorm.DB, roomId int64, userId string) *models.ChatroomUser {
+	var model models.ChatroomUser
+	db.Where("room_id = ?", roomId).Where("user_id = ?", userId).Order("join_time DESC").First(&model)
+	return &model
+}
+
+func UserInRoom(creatorId string, bCreatorId string) *models.UsersInRoom {
+	var user models.UsersInRoom
+	sql := `select room_id from lzyd_live_chatroom where creator_id = ? && b_creator_id=? || creator_id = ? && b_creator_id=?`
+	common.DB.Raw(sql, creatorId,bCreatorId,bCreatorId,creatorId).First(&user)
+	//fmt.Println(222,user,creatorId,bCreatorId)
+	if len(user.RoomId) <= 0  {
+		return nil
+	}
+	return &user
+}

+ 96 - 0
services/chatroom_manager.go

@@ -0,0 +1,96 @@
+package services
+
+import (
+	"github.com/jinzhu/gorm"
+	"lzyd-message-api/models"
+)
+
+func ChatRoomList(db *gorm.DB, r *models.ChatRoomListReq) (err error, list interface{}, total int) {
+	var roomList []models.ChatRoomListRes
+	var count models.Count
+
+	sql := `SELECT id,room_id,name,url,cover,intro,category,with_graphic,with_chatroom as with_chat_room,state,
+		    start_time,end_time,sender_name,sender_avatar,view_count,created_at,updated_at FROM live_entity  
+			WHERE name like ? AND if("" = ?, true, category = ?) AND is_delete=0 ORDER BY created_at desc`
+	sqlCount := `SELECT COUNT(*) as count FROM live_entity
+			WHERE name like ? AND if("" = ?, true, category = ?) AND is_delete=0`
+	limit := r.PageSize
+	offset := r.PageSize * (r.Page - 1)
+	err = db.Raw(sql, "%" + r.Name+"%", r.Category, r.Category).Limit(limit).Offset(offset).Find(&roomList).Error
+	if err != nil {
+		return err, list, total
+	}
+	err = db.Raw(sqlCount, "%" + r.Name+ "%", r.Category, r.Category).Find(&count).Error
+	if err != nil {
+		return err, list, total
+	}
+	return err, roomList, count.Count
+}
+
+func ChatroomDetail(db *gorm.DB, roomId string) (err error, data interface{}) {
+	var room []models.ChatRoomListRes
+	sqlRoom := `SELECT id,room_id,name,url,cover,intro,category,with_graphic,with_chatroom as with_chat_room,state,
+		start_time,end_time,sender_name,sender_avatar,view_count,created_at,updated_at
+		FROM live_entity WHERE room_id = ?`
+	err = db.Raw(sqlRoom, roomId).Find(&room).Error
+	return err, room[0]
+}
+
+
+func ChatroomView(db *gorm.DB, roomId string) (err error) {
+	var count models.ViewCount
+	sqlRoom := `SELECT view_count FROM live_entity WHERE room_id = ?`
+	err = db.Raw(sqlRoom, roomId).Find(&count).Error
+	if err != nil {
+		return err
+	}
+	sql := `UPDATE live_entity SET view_count=? WHERE room_id = ?`
+	err = db.Exec(sql, count.ViewCount+1, roomId).Error
+	return err
+}
+
+
+func ChatroomClassification(db *gorm.DB, t string) (err error, list interface{}) {
+	var classification []*models.ChatRoomClassificationRes
+	sql := `SELECT id,name,created_at,updated_at FROM live_classification WHERE is_delete=0 AND type =?`
+	err = db.Raw(sql, t).Find(&classification).Error
+	return err, classification
+}
+
+
+func GraphicList(db *gorm.DB, roomId string) (err error, list interface{}) {
+	var GraphficListRes  []models.GraphicListDataRes
+	var GraphicListDetail []models.GraphicDetail
+
+	sqlGraphicMaster := `SELECT lg.graphic_id,le.sender_name,le.sender_avatar,lg.created_at,lg.updated_at FROM live_graphictext lg
+	LEFT JOIN live_entity le ON le.room_id = lg.live_id WHERE lg.live_id = ? AND lg.is_delete=0  ORDER BY created_at desc`
+	sqlCraphicDetail := `SELECT lg.graphic_id,lf.id,lf.type,lf.content,lf.created_at,lf.updated_at FROM live_graphictext lg
+	LEFT JOIN live_fragment lf ON lf.graphic_id = lg.graphic_id WHERE lg.live_id = ? AND lf.is_delete=0 ORDER BY created_at desc`
+
+	err = db.Raw(sqlGraphicMaster, roomId).Find(&GraphficListRes).Error
+	if err != nil {
+		return err, list
+	}
+	err = db.Raw(sqlCraphicDetail, roomId).Find(&GraphicListDetail).Error
+	if err != nil {
+		return err, list
+	}
+
+	var data []interface{}
+	for _, item := range GraphficListRes {
+		for _, child := range GraphicListDetail {
+			if item.GraphicId == child.GraphicId {
+				// 判断 图文直播是否有oss视频,有需私有读取
+				//if strings.Contains(child.Content, "oss-cn-hangzhou.aliyuncs.com") && item.type == 3 {
+				//	objKey := strings.Replace(child.Content, "https://health-live.oss-cn-hangzhou.aliyuncs.com/", "", 1)
+				//	child.Content = utils.GetVideoSignedURL(objKey)
+				//	child.Content = child.Content + "," + utils.GetSnapVideoSignedURL(objKey)
+				//}
+				item.List = append(item.List, child)
+			}
+		}
+		data = append(data, item)
+	}
+
+	return err, data
+}

+ 406 - 0
services/message.go

@@ -0,0 +1,406 @@
+package services
+
+import (
+	"fmt"
+	"github.com/jinzhu/gorm"
+	"gopkg"
+	"lzyd-message-api/common"
+	"lzyd-message-api/models"
+	"sort"
+	"time"
+)
+type MessageSql struct {
+	Content     string `json:"content"      gorm:"column:content"`
+	MsgType     string `json:"msg_type"     gorm:"column:msg_type"`
+	FromUid     string `json:"from_uid"     gorm:"column:from_uid"`
+	TargetId    string `json:"target_id"    gorm:"column:target_id"`
+	TargetType  string `json:"target_type"  gorm:"column:target_type"`
+	ReviewState int    `json:"review_state" gorm:"column:review_state"`
+	CreatedAt 	string `json:"created_at"   gorm:"column:created_at"`
+	MsgId	string `json:"msg_id"   gorm:"column:msg_id"`
+}
+
+type NoticeResp struct {
+	Content    string   `json:"content"     gorm:"column:content"`
+	NoticeId   string   `json:"notice_id"   gorm:"column:notice_id"`
+	AppId      string   `json:"app_id"      gorm:"column:app_id"`
+	Title      string   `json:"title"       gorm:"column:title"`
+	UpdateAt   string   `json:"update_at"   gorm:"column:update_at"`
+	DeleteAt   string      `json:"delete_at"   gorm:"column:delete_at"`
+	NoticeSkipType   int      `json:"notice_skip_type"   gorm:"column:notice_skip_type"`
+	NoticeTypeId   string      `json:"notice_type_id"   gorm:"column:notice_type_id"`
+	LinkUrl   string      `json:"link_url"   gorm:"column:link_url"`
+}
+
+type InteractRespList []models.InteractResp
+
+func (p * MessageSql) SaveMessage(db *gorm.DB, userCode string,roomId string) MessageSql {
+	var roomUser models.RoomUser
+	var messageData MessageSql
+	now := time.Now()
+	sql1 := `SELECT creator_id,b_creator_id from lzyd_live_chatroom WHERE  room_id = ?`
+	common.DB.Raw(sql1,roomId).Find(&roomUser)
+	var userId string
+	if roomUser.CreatorId == userCode {
+		userId = roomUser.BCreatorId
+	}else if roomUser.BCreatorId == userCode {
+		userId = roomUser.CreatorId
+	}
+	sql2 := `SELECT leave_time from lzyd_live_chatroom_user WHERE user_id = ? AND id = (select max(id) from lzyd_live_chatroom_user)`
+	common.DB.Raw(sql2,userId).Last(&roomUser)
+	fmt.Println("leave_time",roomUser)
+	sql3 := "UPDATE lzyd_live_chatroom SET updated_at = ? WHERE room_id = ?"
+	err3 := db.Exec(sql3, now, roomId).Error
+	if err3 != nil {
+
+	}
+
+	if len(roomUser.LeaveTime) <= 0  {
+		fmt.Println("status=1",roomUser.LeaveTime)
+		msgId := gopkg.GenUUID()
+		sql := `INSERT INTO lzyd_live_message(msg_id,content, msg_type, from_uid, target_id,target_type, review_state,status) VALUES (?,?,?,?,?,?,?,?)`
+		err := db.Exec(sql,msgId, p.Content, p.MsgType, p.FromUid, p.TargetId,p.TargetType,p.ReviewState,1).Error
+		sql1 := `SELECT created_at,msg_id FROM lzyd_live_message where msg_id = ?`
+		common.DB.Raw(sql1,msgId).Find(&messageData)
+		fmt.Println(err)
+		return messageData
+	}else {
+		fmt.Println("status=0",roomUser.LeaveTime)
+		msgId := gopkg.GenUUID()
+		sql := `INSERT INTO lzyd_live_message(msg_id,content, msg_type, from_uid, target_id,target_type, review_state,status) VALUES (?,?,?,?,?,?,?,?)`
+		err := db.Exec(sql, msgId,p.Content, p.MsgType, p.FromUid, p.TargetId,p.TargetType,p.ReviewState,0).Error
+		sql1 := `SELECT created_at,msg_id FROM lzyd_live_message where msg_id = ?`
+		common.DB.Raw(sql1,msgId).Find(&messageData)
+		fmt.Println(err)
+		return messageData
+	}
+}
+
+func QueryNoticeList(noticeCode string) []models.NoticeResp{
+	var notice []models.NoticeResp
+	sql := `SELECT content, notice_id, app_id, title,update_at, delete_at,notice_skip_type,notice_type_id,link_url FROM lzyd_notice where notice_type_id = ?`
+	common.DB.Raw(sql,noticeCode).Find(&notice)
+
+	//err := db.Exec(sql, notice.Content, p.NoticeId, p.AppId, p.Title,p.UpdateAt,p.DeleteAt).Error
+	return notice
+}
+
+func QueryNoticeType(userCode string) models.NoticeTypeResp{
+	var noticeType models.NoticeTypeResp
+	var noticeList []models.NoticeResp
+	var noticeReadList []models.NoticeReadResp
+	//var newContent models.NewContent
+
+	sqlType := `SELECT notice_type_id, notice_avatar, notice_name,update_at, delete_at FROM lzyd_notice_genre`
+	common.DB.Raw(sqlType).Find(&noticeType)
+	sqlList := `SELECT content, notice_id, app_id, title,update_at,notice_skip_type,notice_type_id,link_url FROM lzyd_notice where  is_delete = 0`
+	common.DB.Raw(sqlList).Find(&noticeList)
+	sqlReadList := `SELECT user_id, notice_id FROM lzyd_notice_user where user_id = ?`
+	common.DB.Raw(sqlReadList,userCode).Find(&noticeReadList)
+
+	sqlContent := `SELECT title,content,update_at FROM lzyd_notice WHERE is_delete = 0 AND notice_type_id = ? order by id desc limit 1`
+	common.DB.Raw(sqlContent,"111").Find(&noticeType)
+
+		for k := 0; k < len(noticeList); k++ {
+			if noticeType.NoticeTypeId == noticeList[k].NoticeTypeId {
+				//var temp = noticeList[k]
+				//noticeType[i].List = append(noticeType[i].List, temp)
+				for q := 0; q < len(noticeReadList); q++{
+					//fmt.Println(noticeList[k].NoticeId , noticeReadList[q].NoticeId)
+					if noticeList[k].NoticeId == noticeReadList[q].NoticeId {
+						fmt.Println(noticeList[k].NoticeId , noticeReadList[q].NoticeId)
+						noticeList[k].Status = 1
+
+						var temp = noticeList[k]
+						noticeType.List = append(noticeType.List, temp)
+						//noticeType[i].list =
+					}else {
+						noticeList[k].Status = 0
+					}
+				}
+			}
+		}
+
+		//noticeType[i].List = noticeList
+
+	//err := db.Exec(sql, notice.Content, p.NoticeId, p.AppId, p.Title,p.UpdateAt,p.DeleteAt).Error
+	return noticeType
+}
+
+func QueryNoticeType1(userCode string) []models.NoticeTypeResp{
+	var noticeType []models.NoticeTypeResp
+	var noticeList []models.NoticeResp
+	var noticeReadList []models.NoticeReadResp
+
+	sqlType := `SELECT notice_type_id, notice_avatar, notice_name,update_at, delete_at FROM lzyd_notice_genre`
+	common.DB.Raw(sqlType).Find(&noticeType)
+	sqlList := `SELECT content, notice_id, app_id, title,update_at, delete_at,notice_skip_type,notice_type_id,link_url FROM lzyd_notice`
+	common.DB.Raw(sqlList).Find(&noticeList)
+	sqlReadList := `SELECT user_id, notice_id FROM lzyd_notice_user where user_id = ?`
+	common.DB.Raw(sqlReadList,userCode).Find(&noticeReadList)
+	for i := 0; i < len(noticeType); i++ {
+		for k := 0; k < len(noticeList); k++ {
+			if noticeType[i].NoticeTypeId == noticeList[k].NoticeTypeId {
+				//var temp = noticeList[k]
+				//noticeType[i].List = append(noticeType[i].List, temp)
+				for q := 0; q < len(noticeReadList); q++{
+					//fmt.Println(noticeList[k].NoticeId , noticeReadList[q].NoticeId)
+					if noticeList[k].NoticeId == noticeReadList[q].NoticeId {
+						fmt.Println(noticeList[k].NoticeId , noticeReadList[q].NoticeId)
+						noticeList[k].Status = 1
+
+						var temp = noticeList[k]
+						noticeType[i].List = append(noticeType[i].List, temp)
+						//noticeType[i].list =
+					}else {
+						noticeList[k].Status = 0
+					}
+				}
+			}
+		}
+
+		//noticeType[i].List = noticeList
+	}
+	//err := db.Exec(sql, notice.Content, p.NoticeId, p.AppId, p.Title,p.UpdateAt,p.DeleteAt).Error
+	return noticeType
+}
+
+
+func QueryInteract(userCode string) []models.InteractResp{
+	fmt.Println("QueryInteract.inargs is:",userCode)
+	var interact1 models.InteractRespList
+	var interact2 models.InteractRespList
+	var interact3 models.InteractRespList
+	var interact4 models.InteractRespList
+	var interact5 models.InteractRespList
+	var interact6 models.InteractRespList
+	var totalList = make(models.InteractRespList, 0)
+	// 评论点赞
+	sqlType1 := `SELECT u.id,u.comment_user_id,u.comment_id, v.user_id , v.username, v.user_avatar, x.content,u.comment_id,DATE_FORMAT(x.updated_at, '%Y-%m-%d %H:%i:%S' ) as updated_at,n.cover,n.video_id
+				FROM lzyd_comment_record u
+				LEFT JOIN lzyd_user v ON  u.user_id = v.user_id
+				LEFT JOIN lzyd_video_comment x ON x.comment_id = u.comment_id
+				LEFT JOIN lzyd_video_master n ON n.video_id = x.resource_id
+				WHERE u.comment_user_id = ? && u.type = 0 && u.status = 1`
+	common.DB.Raw(sqlType1,userCode).Find(&interact1)
+	// 评论
+	sqlType2 := `SELECT u.id,u.comment_user_id,u.comment_id, v.user_id , v.username, v.user_avatar, x.content,u.comment_id,DATE_FORMAT(x.updated_at, '%Y-%m-%d %H:%i:%S' ) as updated_at,n.cover,n.video_id
+				FROM lzyd_comment_record u
+				LEFT JOIN lzyd_user v ON  u.user_id = v.user_id
+				LEFT JOIN lzyd_video_comment x ON x.comment_id = u.comment_id
+				LEFT JOIN lzyd_video_master n ON n.video_id = x.resource_id
+				WHERE u.comment_user_id = ? && u.type = 1 && u.comment_type = 1 && u.status = 1`
+	common.DB.Raw(sqlType2,userCode).Find(&interact2)
+	// 关注
+	sqlType3 := `SELECT u.id,u.user_id, v.user_avatar, v.username,DATE_FORMAT(u.updated_at, '%Y-%m-%d %H-%i-%S' ) as updated_at,u.status
+				FROM lzyd_video_attention u
+				LEFT JOIN lzyd_user v ON u.user_id = v.user_id
+				WHERE u.attention_user_id = ? && u.status = 0 && is_show = 1`
+	common.DB.Raw(sqlType3,userCode).Find(&interact3)
+	// 评论回复
+	sqlType4 := `SELECT u.id,u.comment_user_id,u.comment_id, v.user_id , v.username, v.user_avatar, x.content,u.comment_id,DATE_FORMAT(x.updated_at, '%Y-%m-%d %H:%i:%S' ) as updated_at,k.video_id,k.cover
+				FROM lzyd_comment_record u
+				LEFT JOIN lzyd_user v ON  u.user_id = v.user_id
+				LEFT JOIN lzyd_video_reply_comment x ON x.comment_id = u.comment_id
+				LEFT JOIN lzyd_video_comment n ON n.comment_id = x.comment_id
+				LEFT JOIN lzyd_video_master k ON k.video_id = n.resource_id
+				WHERE u.comment_user_id = ? && u.type = 1 && u.comment_type = 2 && u.status = 1`
+	common.DB.Raw(sqlType4,userCode).Find(&interact4)
+	// 视频点赞
+	sqlType5 := `SELECT u.id,u.user_id, v.user_avatar, v.username,DATE_FORMAT(u.updated_at, '%Y-%m-%d %H:%i:%S' ) as updated_at,u.video_id,n.cover
+				FROM lzyd_video_record u
+				LEFT JOIN lzyd_user v ON u.user_id = v.user_id
+				LEFT JOIN lzyd_video_master n ON n.video_id = u.video_id
+				WHERE u.video_user_id = ? && u.status = 1 && u.is_delete = 0 && u.type = 0`
+	common.DB.Raw(sqlType5,userCode).Find(&interact5)
+	// 视频转发
+	sqlType6 := `SELECT u.id,u.user_id, v.user_avatar, v.username,DATE_FORMAT(u.updated_at,'%Y-%m-%d %H:%i:%S' ) as updated_at,u.video_id,n.cover
+				FROM lzyd_video_record u
+				LEFT JOIN lzyd_user v ON u.user_id = v.user_id
+				LEFT JOIN lzyd_video_master n ON n.video_id = u.video_id
+				WHERE u.video_user_id = ? && u.status = 1 && u.is_delete = 0 && u.type = 1`
+	common.DB.Raw(sqlType6,userCode).Find(&interact6)
+	//fmt.Println(interact1,interact2)
+
+	// 1评论点赞// 2评论// 3关注// 4评论回复// 5视频点赞// 6视频转发
+	//totalList = append(totalList, interact1...)
+	for _, resp := range interact1 {
+		resp.IntType = "1"
+		totalList = append(totalList, resp)
+	}
+
+	for _, resp := range interact2 {
+		resp.IntType = "2"
+		totalList = append(totalList, resp)
+	}
+	//totalList = append(totalList, interact3...)
+
+	for _, resp := range interact3 {
+		resp.IntType = "3"
+		totalList = append(totalList, resp)
+	}
+
+	for _, resp := range interact4 {
+		resp.IntType = "4"
+		totalList = append(totalList, resp)
+	}
+
+	for _, resp := range interact5 {
+		resp.IntType = "5"
+		totalList = append(totalList, resp)
+	}
+
+	for _, resp := range interact6 {
+		resp.IntType = "6"
+		totalList = append(totalList, resp)
+	}
+
+
+
+	//for i:=0;i<len(totalList);i++ {
+	//	timeRes := strings.Split(totalList[i].UpdateAt,"")
+	//	timeRes = strings.Split(timeRes[0],"T")
+	//	var timeRes3 string
+	//	timeRes3 = timeRes[0]+" "+timeRes[1]
+	//	totalList[i].UpdateAt = timeRes3
+	//}
+	//interact := append(append(interact1,interact2...),interact3...)
+	//for i := 0; i < len(interact2); i++ {
+	//
+	//}
+	//err := db.Exec(sql, notice.Content, p.NoticeId, p.AppId, p.Title,p.UpdateAt,p.DeleteAt).Error
+	sort.Sort(InteractRespList(totalList))
+	fmt.Println(totalList)
+	return totalList
+}
+
+
+func UpdateInteract(id string,intType string) bool{
+	var (
+		upDateInfoSql  string
+		upDateInfoErr  error
+	)
+	//fmt.Println(p)
+	if intType == "1" || intType == "2" || intType == "4" {
+		upDateInfoSql = "UPDATE lzyd_comment_record SET status = 0 WHERE id = ?"
+		upDateInfoErr = common.DB.Exec(upDateInfoSql, id).Error
+	}else if intType == "3" {
+		upDateInfoSql = "UPDATE lzyd_video_attention SET is_show = 0 WHERE id = ?"
+		upDateInfoErr = common.DB.Exec(upDateInfoSql, id).Error
+	}else if intType == "5" || intType == "6" {
+		upDateInfoSql = "UPDATE lzyd_video_record SET status = 0 WHERE id = ?"
+		upDateInfoErr = common.DB.Exec(upDateInfoSql, id).Error
+	}
+
+
+	if upDateInfoErr != nil{
+		return false
+	}
+
+	return true
+
+}
+
+func QueryReadNotice(noticeCode string,userCode string,appCode string) models.NoticeReadResp{
+	var noticeRead models.NoticeReadResp
+
+	sql := `SELECT notice_id, app_id, user_id FROM lzyd_notice_user where notice_id = ? AND user_id = ? AND app_id = ?`
+	common.DB.Raw(sql,noticeCode,userCode,appCode).Find(&noticeRead)
+	fmt.Println(len(noticeRead.NoticeId))
+	if len(noticeRead.NoticeId) == 0 {
+		sqlRead := "INSERT INTO lzyd_notice_user(user_id, app_id, notice_id) VALUES (?,?,?)"
+		errRead := common.DB.Exec(sqlRead,userCode,appCode,noticeCode).Error
+		fmt.Println(errRead)
+		//insertReadSql = db.Exec(insertReadSql, cus.UserId, cus.UserName, cus.UserAvatar, cus.MobilePhone, cus.Gender, cus.Birthday, now, now, cus.AppId).Error
+	}else {
+		return noticeRead
+	}
+	return noticeRead
+}
+
+func (list InteractRespList) Len() int {
+	return len(list)
+}
+func (list InteractRespList) Less(i, j int) bool {
+	return list[i].UpdateAt > list[j].UpdateAt
+}
+func (list InteractRespList) Swap(i, j int) {
+	list[i], list[j] = list[j], list[i]
+}
+
+func UploadLiveUser (roomId string,creatorId string,bCreatorId string ) bool {
+
+	var (
+		upDateInfoSql1  string
+		upDateInfoErr1  error
+		upDateInfoSql2  string
+		upDateInfoErr2  error
+	)
+	//fmt.Println(p)
+	upDateInfoSql1 = "UPDATE lzyd_live_user SET status = 1 WHERE user_id = ? && room_id = ?"
+	upDateInfoErr1 = common.DB.Exec(upDateInfoSql1, creatorId, roomId).Error
+	upDateInfoSql2 = "UPDATE lzyd_live_user SET status = 1 WHERE user_id = ? && room_id = ?"
+	upDateInfoErr2 = common.DB.Exec(upDateInfoSql2, bCreatorId, roomId).Error
+
+
+	if upDateInfoErr1 != nil && upDateInfoErr2 != nil {
+		return false
+	}
+
+	return true
+}
+
+func UserRelation(creatorId string,bCreatorId string,userId string) bool{
+	var noticeRead1 models.UserRelationResp
+	var noticeRead2 models.UserRelationResp
+	//var noticeRead3 models.UserRelationResp
+	//var noticeRead4 models.UserRelationResp
+
+	// sql1与sql2 查询用户之前互相关注
+	sql1 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 0`
+	common.DB.Raw(sql1,creatorId,bCreatorId).Find(&noticeRead1)
+	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)
+	// sql3与sql4 查询用户之前互相拉黑
+	//sql3 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 2`
+	//common.DB.Raw(sql3,bCreatorId,creatorId).Find(&noticeRead3)
+	//sql4 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 2`
+	//common.DB.Raw(sql4,bCreatorId,creatorId).Find(&noticeRead4)
+
+	if noticeRead1.AttentionUserId == bCreatorId && noticeRead2.AttentionUserId == creatorId {
+		return true
+	}
+	return false
+}
+
+func UserBlack(creatorId string,bCreatorId string) bool{
+	var noticeRead3 models.UserRelationResp
+	var noticeRead4 models.UserRelationResp
+
+	// sql1与sql2 查询用户之前互相关注
+	//sql1 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 0`
+	//common.DB.Raw(sql1,creatorId,bCreatorId).Find(&noticeRead1)
+	//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)
+	// sql3与sql4 查询用户之前互相拉黑
+	sql3 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 2`
+	common.DB.Raw(sql3,bCreatorId,creatorId).Find(&noticeRead3)
+	sql4 := `SELECT attention_user_id FROM lzyd_video_attention where user_id = ? AND attention_user_id = ? AND status = 2`
+	common.DB.Raw(sql4,bCreatorId,creatorId).Find(&noticeRead4)
+
+	if noticeRead3.AttentionUserId == bCreatorId || noticeRead4.AttentionUserId == creatorId {
+		return true
+	}
+	return false
+}
+
+func UserSendNum(roomId string,userId string) int{
+	var messageRead []models.UserSendResp
+
+
+	sql1 := `SELECT target_id FROM lzyd_live_message where from_uid = ? AND target_id=?`
+	common.DB.Raw(sql1,userId,roomId).Find(&messageRead)
+
+
+	return len(messageRead)
+}

+ 20 - 0
services/mqtt.go

@@ -0,0 +1,20 @@
+package services
+
+import (
+	"lzyd-message-api/common"
+	"lzyd-message-api/wrapper"
+	"strings"
+)
+
+func Publish(client *wrapper.Client, msg *wrapper.Message) error {
+	// Topic规则: root/topic/liveroom/roomId`
+	//name := "/typd" + strings.ToLower(msg.TargetType) + "/" + msg.Target
+	name := strings.ToLower(msg.TargetType) + "/" + msg.Target
+
+	topic := common.MqttClientPrefix + name
+	err := client.Publish(topic, msg)
+	if err != nil {
+		return err
+	}
+	return nil
+}

+ 136 - 0
services/user.go

@@ -0,0 +1,136 @@
+package services
+
+import (
+	"github.com/jinzhu/gorm"
+	"lzyd-message-api/common"
+	"lzyd-message-api/models"
+	"sort"
+	"strings"
+)
+
+type ChatroomList []models.ChatroomInfo
+
+func GetUser(db *gorm.DB, userId string) *models.User {
+	var user models.User
+	db.Where("user_id = ?", userId).Find(&user)
+	return &user
+}
+
+func DeleteRoom(db *gorm.DB,userId string,roomId string) bool {
+	sql := "UPDATE lzyd_live_user SET status = 0 WHERE room_id = ? && user_id = ? "
+	err := db.Exec(sql, roomId, userId).Error
+	if err != nil {
+		return false
+	}
+	return true
+}
+
+func FindUser(db *gorm.DB, userId string) []models.ChatroomInfo {
+	//var sql string
+	var Chatroom []models.ChatroomInfo
+	var messageContent []models.MessageList
+	var messageList []models.MessageList
+	var userInfo models.User
+
+	db.Table("lzyd_live_chatroom").Select("*").Where("creator_id = ? || b_creator_id = ?",userId, userId).Find(&Chatroom)
+	for i := 0; i < len(Chatroom); i++ {
+		if Chatroom[i].CreatorId == userId {
+			creatorName := Chatroom[i].CreatorName
+			creatorAvatar := Chatroom[i].CreatorAvatar
+			creatorId := Chatroom[i].CreatorId
+
+			Chatroom[i].CreatorName = Chatroom[i].BCreatorName
+			Chatroom[i].CreatorAvatar = Chatroom[i].BCreatorAvatar
+			Chatroom[i].CreatorId = Chatroom[i].BCreatorId
+
+			Chatroom[i].BCreatorName = creatorName
+			Chatroom[i].BCreatorAvatar = creatorAvatar
+			Chatroom[i].BCreatorId = creatorId
+		}
+
+		sql := `SELECT content from lzyd_live_message WHERE target_id = ? && status = ? && from_uid != ?`
+		common.DB.Raw(sql,Chatroom[i].RoomId,0,userId).Find(&messageList)
+		Chatroom[i].Count = len(messageList)
+
+		sql2 := `SELECT user_id, user_avatar, username from lzyd_user WHERE user_id = ?`
+		common.DB.Raw(sql2,Chatroom[i].CreatorId).Find(&userInfo)
+		Chatroom[i].CreatorAvatar = userInfo.UserAvatar
+		Chatroom[i].CreatorName = userInfo.UserName
+
+		sql3 := `SELECT user_id, user_avatar, username from lzyd_user WHERE user_id = ?`
+		common.DB.Raw(sql3,Chatroom[i].BCreatorId).Find(&userInfo)
+		Chatroom[i].BCreatorAvatar = userInfo.UserAvatar
+		Chatroom[i].BCreatorName = userInfo.UserName
+
+		sql1 := `SELECT content,updated_at from lzyd_live_message WHERE target_id = ?`
+		common.DB.Raw(sql1,Chatroom[i].RoomId).Find(&messageContent)
+		//fmt.Println(len(messageContent))
+		if len(messageContent) > 0 {
+			//fmt.Println(messageContent)
+			Chatroom[i].NewContent = messageContent[(len(messageContent)-1)].Content
+			Chatroom[i].MsgTime = messageContent[(len(messageContent)-1)].UpdatedAt
+		}
+
+		var isShow models.IsShow
+		sql4 := `SELECT status from lzyd_live_user WHERE room_id = ? && user_id = ?`
+		common.DB.Raw(sql4,Chatroom[i].RoomId,userId).Find(&isShow)
+		//fmt.Println(Chatroom[i].RoomId,userId,isShow)
+		Chatroom[i].IsShow = isShow.IsShow
+	}
+	var chatrooms []models.ChatroomInfo
+	sort.Sort(ChatroomList(Chatroom))
+	for i :=0;i<len(Chatroom);i++ {
+		if Chatroom[i].IsShow == 1 {
+			chatrooms = append(chatrooms,Chatroom[i])
+		}
+
+	}
+	for i :=0;i<len(chatrooms);i++ {
+		timeRes := strings.Split(chatrooms[i].UpdatedAt,"Z")
+		timeRes = strings.Split(timeRes[0],"T")
+		var timeRes3 string
+		timeRes3 = timeRes[0]+" "+timeRes[1]
+		chatrooms[i].UpdatedAt = timeRes3
+	}
+
+	//fmt.Println(chatrooms)
+	return chatrooms
+}
+
+func (list ChatroomList) Len() int {
+	return len(list)
+}
+func (list ChatroomList) Less(i, j int) bool {
+	return list[i].UpdatedAt > list[j].UpdatedAt
+}
+func (list ChatroomList) Swap(i, j int) {
+	list[i], list[j] = list[j], list[i]
+}
+
+//func Login(db *gorm.DB, userId string) (err error, data *models.UserInfoRes) {
+//	var user models.UserInfoRes
+//	err = db.Raw("SELECT * FROM live_user WHERE user_id = ? AND is_delete=0", userId).Find(&user).Error
+//	return err, &user
+//}
+
+//func Register(db *gorm.DB, userInfo *utils.WxUserInfoDetail) (err error, data *models.UserInfoRes) {
+//	var user models.UserInfoRes
+//	NotRecord := db.Raw("SELECT * FROM live_user WHERE wx_id = ? AND is_delete=0", userInfo.OpenId).Find(&user).RecordNotFound()
+//	if !NotRecord {
+//		return err, &user
+//	} else {
+//		UId, _ := uuid.NewV4()
+//		UserId := fmt.Sprintf("%s", UId)
+//		userName := utils.GenerateSubString()
+//		passWord := utils.MD5V([]byte("888888"))
+//		sql := `INSERT INTO live_user(user_id, username, password, nickname, avatar, wx_id) VALUES(?,?,?,?,?,?)`
+//		err = db.Exec(sql, UserId, userName, passWord, userInfo.NickName, userInfo.HeadImgUrl, userInfo.OpenId).Error
+//		if err != nil {
+//			return err, data
+//		}
+//		user.UserId = UserId
+//		user.Nickname = userInfo.NickName
+//		user.Avatar = userInfo.HeadImgUrl
+//		return err, &user
+//	}
+//}

+ 19 - 0
tingyun.json

@@ -0,0 +1,19 @@
+{
+
+  "nbs.app_name" : "lzyd_message_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
+ 3673 - 0
tingyun.log


+ 24 - 0
utils/md5.go

@@ -0,0 +1,24 @@
+package utils
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+)
+
+func MD5V(str []byte) string {
+	h := md5.New()
+	h.Write(str)
+	return hex.EncodeToString(h.Sum(nil))
+}
+
+
+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)
+}

+ 80 - 0
utils/oss.go

@@ -0,0 +1,80 @@
+package utils
+
+import (
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+	"lzyd-message-api/common"
+	"os"
+	"time"
+)
+
+func GetVideoSignedURL(strs string) string {
+	// 创建OSSClient实例。
+	client, err := oss.New(common.Endpoint, common.AccessKeyIdOSS, common.AccessSecretOss)
+	if err != nil {
+		os.Exit(-1)
+	}
+	// 获取存储空间。
+	bucket, err := client.Bucket(common.BucketName)
+	if err != nil {
+		os.Exit(-1)
+	}
+	// 上传文件流。
+	signedURL, err := bucket.SignURL(strs, oss.HTTPGet, 60*20)
+	if err != nil {
+		os.Exit(-1)
+	}
+	return signedURL
+}
+
+
+func GetSnapVideoSignedURL(strs string) string {
+	// 创建OSSClient实例。
+	client, err := oss.New(common.Endpoint, common.AccessKeyIdOSS, common.AccessSecretOss)
+	if err != nil {
+		os.Exit(-1)
+	}
+	// 获取存储空间。
+	bucket, err := client.Bucket(common.BucketName)
+	if err != nil {
+		os.Exit(-1)
+	}
+	// 上传文件流。
+	signedURL, err := bucket.SignURL(strs, oss.HTTPGet, 60*20, oss.AddParam("x-oss-process", "video/snapshot,t_7000,f_jpg,m_fast"))
+	if err != nil {
+		os.Exit(-1)
+	}
+	return signedURL
+}
+
+
+var expire_time int64 = 30
+var host string = "http://cloudsport-video.oss-cn-hangzhou.aliyuncs.com"
+
+
+type ConfigStruct struct {
+	Expiration string     `json:"expiration"`
+	Conditions [][]string `json:"conditions"`
+}
+
+
+func get_gmt_iso8601(expire_end int64) string {
+	var tokenExpire = time.Unix(expire_end, 0).Format("2006-01-02T15:04:05Z")
+	return tokenExpire
+}
+
+type CallbackParam struct {
+	CallbackUrl      string `json:"callbackUrl"`
+	CallbackBody     string `json:"callbackBody"`
+	CallbackBodyType string `json:"callbackBodyType"`
+}
+
+type PolicyToken struct {
+	AccessKeyId string `json:"accessid"`
+	Host        string `json:"host"`
+	Expire      int64  `json:"expire"`
+	Signature   string `json:"signature"`
+	Policy      string `json:"policy"`
+	Directory   string `json:"dir"`
+	Callback    string `json:"callback"`
+}
+

+ 26 - 0
utils/page.go

@@ -0,0 +1,26 @@
+package utils
+
+import "github.com/gin-gonic/gin"
+
+// GetPageIndex 获取分页的页索引
+func GetPageIndex(c *gin.Context) int {
+	if v := c.Query("pageIndex"); v != "" {
+		if iv := S(v).Int(); iv > 0 {
+			return iv
+		}
+	}
+	return 1
+}
+
+// GetPageSize 获取分页的页大小(最大50)
+func GetPageSize(c *gin.Context) int {
+	if v := c.Query("pageSize"); v != "" {
+		if iv := S(v).Int(); iv > 0 {
+			if iv > 50 {
+				iv = 50
+			}
+			return iv
+		}
+	}
+	return 10
+}

+ 60 - 0
utils/strings.go

@@ -0,0 +1,60 @@
+package utils
+
+import (
+	"encoding/json"
+	"strconv"
+)
+
+// S 字符串类型转换
+type S string
+
+func (s S) String() string {
+	return string(s)
+}
+
+// Bytes 转换为[]byte
+func (s S) Bytes() []byte {
+	return []byte(s)
+}
+
+// Int64 转换为int64
+func (s S) Int64() int64 {
+	i, err := strconv.ParseInt(s.String(), 10, 64)
+	if err != nil {
+		return 0
+	}
+	return i
+}
+
+// Int 转换为int
+func (s S) Int() int {
+	return int(s.Int64())
+}
+
+// Uint 转换为uint
+func (s S) Uint() uint {
+	return uint(s.Uint64())
+}
+
+// Uint64 转换为uint64
+func (s S) Uint64() uint64 {
+	i, err := strconv.ParseUint(s.String(), 10, 64)
+	if err != nil {
+		return 0
+	}
+	return i
+}
+
+// Float64 转换为float64
+func (s S) Float64() float64 {
+	f, err := strconv.ParseFloat(s.String(), 64)
+	if err != nil {
+		return 0
+	}
+	return f
+}
+
+// ToJSON 转换为JSON
+func (s S) ToJSON(v interface{}) error {
+	return json.Unmarshal(s.Bytes(), v)
+}

+ 40 - 0
utils/util.go

@@ -0,0 +1,40 @@
+package utils
+
+import (
+	"fmt"
+	"math/rand"
+	"strconv"
+	"time"
+)
+
+func GenCustomerIdentifier() string {
+	random := rand.New(rand.NewSource(time.Now().UnixNano()))
+	return fmt.Sprintf("%08v", random.Int31n(100000000))
+}
+
+// 生成随机字符串
+func GenerateSubString() string {
+	var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
+	var n = 12
+	b := make([]rune, n)
+	for i := range b {
+		b[i] = letterRunes[rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(letterRunes))]
+	}
+	return string(b)
+}
+
+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 ""
+}

+ 207 - 0
utils/validator.go

@@ -0,0 +1,207 @@
+package utils
+
+import (
+	"errors"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+type Rules map[string][]string
+
+type RulesMap map[string]Rules
+
+var CustomizeMap = make(map[string]Rules)
+
+// 注册自定义规则方案建议在路由初始化层即注册
+func RegisterRule(key string, rule Rules) (err error) {
+	if CustomizeMap[key] != nil {
+		return errors.New(key + "已注册,无法重复注册")
+	} else {
+		CustomizeMap[key] = rule
+		return nil
+	}
+}
+
+// 非空 不能为其对应类型的0值
+func NotEmpty() string {
+	return "notEmpty"
+}
+
+// 小于入参(<) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
+func Lt(mark string) string {
+	return "lt=" + mark
+}
+
+// 小于等于入参(<=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
+func Le(mark string) string {
+	return "le=" + mark
+}
+
+// 等于入参(==) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
+func Eq(mark string) string {
+	return "eq=" + mark
+}
+
+// 不等于入参(!=)  如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
+func Ne(mark string) string {
+	return "ne=" + mark
+}
+
+// 大于等于入参(>=) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
+func Ge(mark string) string {
+	return "ge=" + mark
+}
+
+// 大于入参(>) 如果为string array Slice则为长度比较 如果是 int uint float 则为数值比较
+func Gt(mark string) string {
+	return "gt=" + mark
+}
+
+// 校验方法 接收两个参数  入参实例,规则map
+func Verify(st interface{}, roleMap Rules) (err error) {
+	compareMap := map[string]bool{
+		"lt": true,
+		"le": true,
+		"eq": true,
+		"ne": true,
+		"ge": true,
+		"gt": true,
+	}
+
+	typ := reflect.TypeOf(st)
+	val := reflect.ValueOf(st) // 获取reflect.Type类型
+
+	kd := val.Kind() // 获取到st对应的类别
+	if kd != reflect.Struct {
+		return errors.New("expect struct")
+	}
+	num := val.NumField()
+	// 遍历结构体的所有字段
+	for i := 0; i < num; i++ {
+		tagVal := typ.Field(i)
+		val := val.Field(i)
+		if len(roleMap[tagVal.Name]) > 0 {
+			for _, v := range roleMap[tagVal.Name] {
+				switch {
+				case v == "notEmpty":
+					if isBlank(val) {
+						return errors.New(tagVal.Name + "值不能为空")
+					}
+				case compareMap[strings.Split(v, "=")[0]]:
+					if !compareVerify(val, v) {
+						return errors.New(tagVal.Name + "长度或值不在合法范围," + v)
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// 长度和数字的校验方法 根据类型自动校验
+func compareVerify(value reflect.Value, VerifyStr string) bool {
+	switch value.Kind() {
+	case reflect.String, reflect.Slice, reflect.Array:
+		return compare(value.Len(), VerifyStr)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return compare(value.Uint(), VerifyStr)
+	case reflect.Float32, reflect.Float64:
+		return compare(value.Float(), VerifyStr)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return compare(value.Int(), VerifyStr)
+	default:
+		return false
+	}
+}
+
+// 非空校验
+func isBlank(value reflect.Value) bool {
+	switch value.Kind() {
+	case reflect.String:
+		return value.Len() == 0
+	case reflect.Bool:
+		return !value.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return value.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return value.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return value.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return value.IsNil()
+	}
+	return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
+}
+
+func compare(value interface{}, VerifyStr string) bool {
+	VerifyStrArr := strings.Split(VerifyStr, "=")
+	val := reflect.ValueOf(value)
+	switch val.Kind() {
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		VInt, VErr := strconv.ParseInt(VerifyStrArr[1], 10, 64)
+		if VErr != nil {
+			return false
+		}
+		switch {
+		case VerifyStrArr[0] == "lt":
+			return val.Int() < VInt
+		case VerifyStrArr[0] == "le":
+			return val.Int() <= VInt
+		case VerifyStrArr[0] == "eq":
+			return val.Int() == VInt
+		case VerifyStrArr[0] == "ne":
+			return val.Int() != VInt
+		case VerifyStrArr[0] == "ge":
+			return val.Int() >= VInt
+		case VerifyStrArr[0] == "gt":
+			return val.Int() > VInt
+		default:
+			return false
+		}
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		VInt, VErr := strconv.Atoi(VerifyStrArr[1])
+		if VErr != nil {
+			return false
+		}
+		switch {
+		case VerifyStrArr[0] == "lt":
+			return val.Uint() < uint64(VInt)
+		case VerifyStrArr[0] == "le":
+			return val.Uint() <= uint64(VInt)
+		case VerifyStrArr[0] == "eq":
+			return val.Uint() == uint64(VInt)
+		case VerifyStrArr[0] == "ne":
+			return val.Uint() != uint64(VInt)
+		case VerifyStrArr[0] == "ge":
+			return val.Uint() >= uint64(VInt)
+		case VerifyStrArr[0] == "gt":
+			return val.Uint() > uint64(VInt)
+		default:
+			return false
+		}
+	case reflect.Float32, reflect.Float64:
+		VFloat, VErr := strconv.ParseFloat(VerifyStrArr[1], 64)
+		if VErr != nil {
+			return false
+		}
+		switch {
+		case VerifyStrArr[0] == "lt":
+			return val.Float() < VFloat
+		case VerifyStrArr[0] == "le":
+			return val.Float() <= VFloat
+		case VerifyStrArr[0] == "eq":
+			return val.Float() == VFloat
+		case VerifyStrArr[0] == "ne":
+			return val.Float() != VFloat
+		case VerifyStrArr[0] == "ge":
+			return val.Float() >= VFloat
+		case VerifyStrArr[0] == "gt":
+			return val.Float() > VFloat
+		default:
+			return false
+		}
+	default:
+		return false
+	}
+}

+ 95 - 0
utils/wx_login.go

@@ -0,0 +1,95 @@
+package utils
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"strings"
+)
+
+type WXLoginResp struct {
+	AccessToken    	 string 		`json:"access_token"`
+	OpenId			 string 		`json:"openid"`
+}
+
+type WxUserInfoDetail struct {
+	OpenId			 string 		`json:"openid"`
+	NickName		 string 		`json:"nickname"`
+	Sex 			 int 			`json:"sex"`
+	City 			 string 		`json:"city"`
+	Province		 string 		`json:"province"`
+	HeadImgUrl 		 string 		`json:"headimgurl"`
+}
+
+
+// const WxAuth = "https://api.weixin.qq.com/sns/jscode2session?appid=wx47b83b24cf3b5e25&secret=bbcbc2cafbcf6e9cfe9a15aef5444d28&grant_type=authorization_code"
+
+func GetWxOpendidFromoauth2(code string) (data *WxUserInfoDetail, err error) {
+	requestLine := strings.Join([]string{"https://api.weixin.qq.com/sns/oauth2/access_token",
+		// dev wx6a3a89799a8b2e5b
+		// dev 98f52bb55689faff10756650cc04776a
+
+		// prod wx47b83b24cf3b5e25
+		// prod bbcbc2cafbcf6e9cfe9a15aef5444d28
+
+		"?appid=", "wx47b83b24cf3b5e25",
+		"&secret=", "bbcbc2cafbcf6e9cfe9a15aef5444d28",
+		"&code=", code,
+		"&grant_type=authorization_code"}, "")
+
+	resp, err := http.Get(requestLine)
+	if err != nil || resp.StatusCode != http.StatusOK {
+		fmt.Println("发送get请求获取 openid 错误", err)
+		return data, err
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		fmt.Println("发送get请求获取 openid 读取返回body错误", err)
+		return data, err
+	}
+
+	if bytes.Contains(body, []byte("errcode")) {
+		//fmt.Println(string(body))
+		ater := &WXLoginResp{}
+		err = json.Unmarshal(body, &ater)
+
+		if err != nil {
+			fmt.Printf("发送get请求获取 openid 的错误信息 %+v\n", ater)
+			return data, err
+		}
+		return data, err
+
+	} else {
+		atr := &WXLoginResp{}
+		err = json.Unmarshal(body, &atr)
+		if err != nil {
+			fmt.Println("发送get请求获取 openid 返回数据json解析错误", err)
+			return data, err
+		}
+		wxInfoUrl := "https://api.weixin.qq.com/sns/userinfo?access_token=" + atr.AccessToken + "&openid=" + atr.OpenId + "&lang=zh_CN"
+		resData, err := http.Get(wxInfoUrl)
+		if err != nil || resData.StatusCode != http.StatusOK {
+			fmt.Println("发送get请求获取 openid 错误", err)
+			return data, err
+		}
+
+		defer resData.Body.Close()
+		bodyByte, err := ioutil.ReadAll(resData.Body)
+		if err != nil {
+			fmt.Println("发送get请求获取 用户信息 读取返回body错误", err)
+			return data, err
+		}
+
+		userInfo := &WxUserInfoDetail{}
+		err = json.Unmarshal(bodyByte, &userInfo)
+		if err != nil {
+			fmt.Println("发送get请求获取 openid 返回数据json解析错误", err)
+			return data, err
+		}
+
+		return userInfo, err
+	}
+}

+ 156 - 0
utils/wx_share.go

@@ -0,0 +1,156 @@
+package utils
+
+import (
+	"crypto/sha1"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"lzyd-message-api/models"
+	mathRand "math/rand"
+	"net/http"
+	"strconv"
+	"time"
+)
+
+var (
+	AppID           string = "wx47b83b24cf3b5e25"
+	AppSecret       string = "bbcbc2cafbcf6e9cfe9a15aef5444d28"
+	AccessTokenHost string = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appID=" + AppID + "&secret=" + AppSecret
+	JsAPITicketHost string = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"
+)
+
+
+func GetWxSign(url string) (err error, data WxSignature){
+	var (
+		noncestr, jsapi_ticket, timestamp, signature, signatureStr, access_token string
+		wxAccessToken                                                                 WxAccessToken
+		wxJsApiTicket                                                                 WxJsApiTicket
+		wxSignature                                                                   WxSignature
+		wxSignRtn WxSignRtn
+	)
+
+	noncestr = RandStringBytes(16)
+	timestamp = strconv.FormatInt(time.Now().Unix(), 10)
+
+	//获取access_token,如果缓存中有,则直接取出数据使用;否则重新调用微信端接口获取
+	client := &http.Client{}
+	if models.MemoryCacheVar.Get("access_token") == nil {
+		request, _ := http.NewRequest("GET", AccessTokenHost, nil)
+		response, _ := client.Do(request)
+		defer response.Body.Close()
+		body, err := ioutil.ReadAll(response.Body)
+		if err != nil {
+			wxSignRtn.Code = 1
+			wxSignRtn.Msg = err.Error()
+			return err, data
+		}
+		err = json.Unmarshal(body, &wxAccessToken)
+		if err != nil {
+			wxSignRtn.Code = 1
+			wxSignRtn.Msg = err.Error()
+			return err, data
+		}
+		if wxAccessToken.Errcode == 0 {
+			access_token = wxAccessToken.Access_token
+		} else {
+			wxSignRtn.Code = 1
+			wxSignRtn.Msg = wxAccessToken.Errmsg
+			return err, data
+		}
+		models.MemoryCacheVar.Put("access_token", access_token, time.Duration(wxAccessToken.Expires_in)*time.Second)
+
+		//获取 jsapi_ticket
+		requestJs, _ := http.NewRequest("GET", JsAPITicketHost+"?access_token="+access_token+"&type=jsapi", nil)
+		responseJs, _ := client.Do(requestJs)
+		defer responseJs.Body.Close()
+		bodyJs, err := ioutil.ReadAll(responseJs.Body)
+		if err != nil {
+			wxSignRtn.Code = 1
+			wxSignRtn.Msg = err.Error()
+			return err, data
+		}
+		err = json.Unmarshal(bodyJs, &wxJsApiTicket)
+		if err != nil {
+			wxSignRtn.Code = 1
+			wxSignRtn.Msg = err.Error()
+			return err, data
+		}
+		if wxJsApiTicket.Errcode == 0 {
+			jsapi_ticket = wxJsApiTicket.Ticket
+		} else {
+			wxSignRtn.Code = 1
+			wxSignRtn.Msg = wxJsApiTicket.Errmsg
+			return err, data
+		}
+		models.MemoryCacheVar.Put("jsapi_ticket", jsapi_ticket, time.Duration(wxJsApiTicket.Expires_in)*time.Second)
+	} else {
+		//缓存中存在access_token,直接读取
+		access_token = models.MemoryCacheVar.Get("access_token").(*models.Item).Value
+		jsapi_ticket = models.MemoryCacheVar.Get("jsapi_ticket").(*models.Item).Value
+	}
+	//fmt.Println("access_token:",access_token)
+	//fmt.Println("jsapi_ticket:",jsapi_ticket)
+
+	// 获取 signature
+	signatureStr = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url
+	signature = GetSha1(signatureStr)
+
+	wxSignature.Url = url
+	wxSignature.Noncestr = noncestr
+	wxSignature.Timestamp = timestamp
+	wxSignature.Signature = signature
+	wxSignature.AppID = AppID
+
+	// 返回前端需要的数据
+	//wxSignRtn.Code = 0
+	//wxSignRtn.Msg = "success"
+	//wxSignRtn.Data = wxSignature
+
+	return err, wxSignature
+}
+
+//生成指定长度的字符串
+func RandStringBytes(n int) string {
+	const letterBytes = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	b := make([]byte, n)
+	for i := range b {
+		b[i] = letterBytes[mathRand.Intn(len(letterBytes))]
+	}
+	return string(b)
+}
+
+//SHA1加密
+func GetSha1(data string) string {
+	t := sha1.New()
+	io.WriteString(t, data)
+	return fmt.Sprintf("%x", t.Sum(nil))
+}
+
+type WxAccessToken struct {
+	Access_token string `json:"access_token"`
+	Expires_in   int    `json:"expires_in"`
+	Errcode      int    `json:"errcode"`
+	Errmsg       string `json:"errmsg"`
+}
+type WxJsApiTicket struct {
+	Ticket     string `json:"ticket"`
+	Expires_in int    `json:"expires_in"`
+	Errcode    int    `json:"errcode"`
+	Errmsg     string `json:"errmsg"`
+}
+type WxSignature struct {
+	Noncestr  string `json:"noncestr"`
+	Timestamp string `json:"timestamp"`
+	Url       string `json:"url"`
+	Signature string `json:"signature"`
+	AppID     string `json:"appId"`
+}
+
+type WxSignRtn struct {
+	Code int         `json:"code"`
+	Msg  string      `json:"msg"`
+	Data WxSignature `json:"data"`
+}
+
+

+ 170 - 0
wrapper/client.go

@@ -0,0 +1,170 @@
+package wrapper
+
+import (
+	"crypto/tls"
+	"errors"
+	"fmt"
+	"github.com/eclipse/paho.mqtt.golang"
+	"go.uber.org/zap"
+	"time"
+)
+
+const (
+	MqttClientDisconnected = "Disconnected"
+	MqttClientConnected    = "Connected"
+	RetryCount             = 5
+	CloudAccessSleep       = 5
+)
+
+type Client struct {
+	// scheme://host:port
+	// Where "scheme" is one of "tcp", "ssl", or "ws", "host" is the ip-address (or hostname)
+	// and "port" is the port on which the broker is accepting connections.
+	Host         string
+	User, Passwd string
+	// the client id to be used by this client when
+	// connecting to the MQTT broker.
+	ClientID string
+	// the amount of time (in seconds) that the client
+	// should wait before sending a PING request to the broker.
+	// default as 120s.
+	keepAliveInterval time.Duration
+	// the amount of time (in seconds) that the client
+	// will wait after sending a PING request to the broker.
+	// default as 120s
+	PingTimeout time.Duration
+	//the size of the internal queue that holds messages while the
+	// client is temporairily offline.
+	MessageCacheDepth uint
+	//0: QOSAtMostOnce, 1: QOSAtLeastOnce, 2: QOSExactlyOnce.
+	QOS byte
+	//if the flag set true, server will store the message and
+	//can be delivered to future subscribers.
+	Retain bool
+	//the state of client.
+	State string
+	// tls config
+	tlsConfig *tls.Config
+	client    *MQTTClient
+}
+
+func NewClient(host, user, passwd, clientID string) *Client {
+	if host == "" || clientID == "" {
+		return nil
+	}
+	client := &Client{
+		Host:              host,
+		User:              user,
+		Passwd:            passwd,
+		ClientID:          clientID,
+		keepAliveInterval: 120 * time.Second,
+		PingTimeout:       120 * time.Second,
+		State:             MqttClientDisconnected,
+		MessageCacheDepth: 100,
+		QOS:               byte(2),
+		Retain:            false,
+	}
+	return client
+}
+
+func (c *Client) SetkeepAliveInterval(k time.Duration) {
+	c.keepAliveInterval = k
+}
+
+func (c *Client) SetPingTimeout(k time.Duration) {
+	c.PingTimeout = k
+}
+
+func (c *Client) SetTlsConfig(config *tls.Config) {
+	c.tlsConfig = config
+}
+
+func (c *Client) SetQOS(qos byte) {
+	c.QOS = qos
+}
+
+func (c *Client) SetMessageCacheDepth(depth uint) {
+	c.MessageCacheDepth = depth
+}
+
+func (c *Client) SetRetain(ret bool) {
+	c.Retain = ret
+}
+
+func (c *Client) Start() error {
+
+	// Create mqtt client.
+	client := &MQTTClient{
+		Host:                c.Host,
+		User:                c.User,
+		Passwd:              c.Passwd,
+		ClientID:            c.ClientID,
+		Order:               false,
+		KeepAliveInterval:   c.keepAliveInterval,
+		PingTimeout:         c.PingTimeout,
+		MessageChannelDepth: c.MessageCacheDepth,
+		CleanSession:        true,
+		FileStorePath:       "memory",
+		OnConnect:           c.ClientOnConnect,
+		OnLost:              c.ClientOnLost,
+		WillTopic:           "", //no will topic.
+		TLSConfig:           c.tlsConfig,
+	}
+
+	c.client = client
+
+	//Start the mqtt client
+	c.client.Start()
+
+	var (
+		i   int
+		err error
+	)
+	for i = 0; i < RetryCount; i++ {
+		//Logger.Info(fmt.Sprintf("正在尝试第 %d 次连接MQTT", i + 1))
+		err = c.client.Connect()
+		if err != nil {
+			Logger.Info(fmt.Sprintf("MQTT连接失败[%s], 5s后重试...", err.Error()))
+		} else {
+			//Logger.Info("MQTT连接成功!!!")
+			break
+		}
+		time.Sleep(CloudAccessSleep * time.Second)
+	}
+
+	if i >= RetryCount-1 && err != nil {
+		return errors.New("超过重试次数")
+	} else {
+		return nil
+	}
+}
+
+func (c *Client) Publish(topic string, msg *Message) error {
+	return c.client.Publish(topic, c.QOS, c.Retain, msg)
+}
+
+func (c *Client) Subscribe(topic string, fn func(topic string, msg *Message)) error {
+	return c.client.Subscribe(topic, c.QOS, fn)
+}
+
+func (c *Client) Unsubscribe(topics string) error {
+	return c.client.Unsubscribe(topics)
+}
+
+func (c *Client) Close() {
+	c.client.Close()
+}
+
+func (c *Client) ClientOnConnect(client mqtt.Client) {
+	Logger.Info("[MQTT]连接成功", zap.String("client_id", c.ClientID))
+	c.State = MqttClientConnected
+}
+
+func (c *Client) ClientOnLost(client mqtt.Client, err error) {
+	Logger.Info("[MQTT]失去连接", zap.String("client_id", c.ClientID), zap.String("error", err.Error()))
+	c.State = MqttClientDisconnected
+	time.Sleep(CloudAccessSleep * time.Second)
+	go func() {
+		_ = c.Start()
+	}()
+}

+ 56 - 0
wrapper/logger.go

@@ -0,0 +1,56 @@
+package wrapper
+
+import (
+	"encoding/json"
+	"fmt"
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+	"os"
+	"path"
+)
+
+var Logger *zap.Logger
+
+func LoggerInit(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")
+	}
+}
+
+func InitLogger(logPath string) {
+
+}

+ 35 - 0
wrapper/message.go

@@ -0,0 +1,35 @@
+package wrapper
+
+type Message struct {
+	MsgId      string `json:"msg_id"`
+	Target     string `json:"target"`      // 发送的目标 给群组发送时,元素是groupid;给房间发消息,元素是roomid
+	TargetType string `json:"target_type"` // 发送的目标类型 user:给用户发消息,chatgroup:给群发消息,chatroom:给聊天室发消息
+	MsgType    string `json:"msg_type"`    // 消息类型 txt:文本消息|img:图片消息|loc:位置消息|audio:语音消息|video:视频消息(暂时只支持文本消息)
+	Msg        string `json:"msg"`         // 发送的消息内容
+	From       string `json:"from"`        // 表示消息发送者
+	FromName   string `json:"from_name"`   // 发送者的昵称
+	FromAvatar string `json:"from_avatar"` // 发送者的头像
+	Timestamp  int64  `json:"timestamp"`
+	CreatedAt  string `json:"created_at"`
+}
+
+// GetID returns message ID
+func (msg *Message) GetMsgId() string {
+	return msg.MsgId
+}
+
+// NewRawMessage returns a new raw message:
+// model.NewRawMessage().BuildHeader().BuildRouter().FillBody()
+func NewRawMessage() *Message {
+	return &Message{}
+}
+
+// NewMessage returns a new basic message:
+// model.NewMessage().BuildHeader().FillBody()
+func NewMessage() *Message {
+	msg := NewRawMessage()
+	//u, _ := uuid.NewV4()
+	//msg.MsgId = u.String()
+
+	return msg
+}

+ 154 - 0
wrapper/mqtt.go

@@ -0,0 +1,154 @@
+package wrapper
+
+import (
+	"crypto/tls"
+	"encoding/json"
+	"errors"
+	"github.com/eclipse/paho.mqtt.golang"
+	"strings"
+	"time"
+)
+
+type MQTTClient struct {
+	Host                string
+	User, Passwd        string
+	ClientID            string
+	CleanSession        bool
+	Order               bool
+	KeepAliveInterval   time.Duration
+	PingTimeout         time.Duration
+	MessageChannelDepth uint
+	OnConnect           mqtt.OnConnectHandler
+	OnLost              mqtt.ConnectionLostHandler
+	FileStorePath       string
+	WillTopic           string
+	WillMessage         string
+	WillQOS             byte
+	WillRetained        bool
+	TLSConfig           *tls.Config
+	client              mqtt.Client
+}
+
+func NewMQTTClient() *MQTTClient {
+	return &MQTTClient{}
+}
+
+func (mc *MQTTClient) Start() {
+
+	opts := mqtt.NewClientOptions()
+
+	opts.AddBroker(mc.Host)
+	opts.SetClientID(mc.ClientID)
+
+	opts.SetUsername(mc.User)
+	opts.SetPassword(mc.Passwd)
+
+	opts.SetAutoReconnect(true)
+	opts.SetCleanSession(mc.CleanSession)
+
+	if mc.TLSConfig != nil {
+		//common.LogInfo("SSL/TLS is enabled!")
+		opts.SetTLSConfig(mc.TLSConfig)
+	}
+	if strings.Compare(mc.FileStorePath, "memory") != 0 {
+		//common.LogInfo("Use File Store!")
+		opts.SetStore(mqtt.NewFileStore(mc.FileStorePath))
+	}
+	if mc.OnConnect != nil {
+		opts.SetOnConnectHandler(mc.OnConnect)
+	}
+	if mc.OnLost != nil {
+		opts.SetConnectionLostHandler(mc.OnLost)
+	}
+	if strings.Compare(mc.WillTopic, "") != 0 {
+		opts.SetWill(mc.WillTopic, mc.WillMessage, mc.WillQOS, mc.WillRetained)
+	}
+	if mc.Order != false {
+		opts.SetOrderMatters(true)
+	}
+
+	opts.SetKeepAlive(mc.KeepAliveInterval)
+	opts.SetPingTimeout(mc.PingTimeout)
+	opts.SetMessageChannelDepth(mc.MessageChannelDepth)
+
+	// Create mqtt client.
+	client := mqtt.NewClient(opts)
+	mc.client = client
+}
+
+func (mc *MQTTClient) Connect() error {
+	if mc.client == nil {
+		return errors.New("未创建MQTT客户端")
+	}
+	if token := mc.client.Connect(); token.Wait() && token.Error() != nil {
+		return token.Error()
+	}
+	return nil
+}
+
+//Publish
+// We Encode this model message and publish it.
+func (mc *MQTTClient) Publish(topic string, qos byte, retained bool, msg *Message) error {
+	if msg == nil {
+		return errors.New("消息不可为空")
+	}
+	if mc.client == nil {
+		return errors.New("未创建MQTT客户端")
+	}
+	if !mc.client.IsConnectionOpen() {
+		return errors.New("未连接到 Mqtt Broker")
+	}
+	//rawData, err := translator.NewTransCoding().Encode(msg)
+	rawData, err := json.Marshal(msg)
+	if err != nil {
+		return err
+	}
+	if token := mc.client.Publish(topic, qos, retained, rawData); token.Wait() && token.Error() != nil {
+		return token.Error()
+	}
+	return nil
+}
+
+//Subscribe
+// We Override the function for the fn can process the model message.
+func (mc *MQTTClient) Subscribe(topic string, qos byte, fn func(tpc string, msg *Message)) error {
+	if mc.client == nil {
+		return errors.New("未创建MQTT客户端")
+	}
+	if !mc.client.IsConnectionOpen() {
+		return errors.New("未连接到 Mqtt Broker")
+	}
+	callback := func(client mqtt.Client, message mqtt.Message) {
+		msg := &Message{}
+		rawData := message.Payload()
+		//Logger.Info("Raw Data: ", zap.String("msg", string(rawData)))
+		//err := translator.NewTransCoding().Decode(rawData, msg)
+		err := json.Unmarshal(rawData, msg)
+		if err != nil {
+			Logger.Info("Error message format, Ignored!")
+			return
+		}
+		fn(message.Topic(), msg)
+	}
+	if token := mc.client.Subscribe(topic, qos, callback); token.Wait() && token.Error() != nil {
+		return token.Error()
+	}
+	return nil
+}
+
+func (mc *MQTTClient) Unsubscribe(topics string) error {
+	if mc.client == nil {
+		return errors.New("未创建MQTT客户端")
+	}
+	if !mc.client.IsConnectionOpen() {
+		return errors.New("未连接")
+	}
+	if token := mc.client.Unsubscribe(topics); token.Wait() && token.Error() != nil {
+		return token.Error()
+	}
+	return nil
+}
+
+func (mc *MQTTClient) Close() {
+	mc.client.Disconnect(250)
+}