fuwencai 3 years ago
parent
commit
319f4e50ae

+ 29 - 0
api/internal/handler/markreadhandler.go

@@ -0,0 +1,29 @@
+package handler
+
+import (
+	"net/http"
+
+	"app.yhyue.com/moapp/MessageCenter/api/internal/logic"
+	"app.yhyue.com/moapp/MessageCenter/api/internal/svc"
+	"app.yhyue.com/moapp/MessageCenter/api/internal/types"
+
+	"github.com/tal-tech/go-zero/rest/httpx"
+)
+
+func MarkReadHandler(ctx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.MarkReadReq
+		if err := httpx.Parse(r, &req); err != nil {
+			httpx.Error(w, err)
+			return
+		}
+
+		l := logic.NewMarkReadLogic(r.Context(), ctx)
+		resp, err := l.MarkRead(req)
+		if err != nil {
+			httpx.Error(w, err)
+		} else {
+			httpx.OkJson(w, resp)
+		}
+	}
+}

+ 5 - 0
api/internal/handler/routes.go

@@ -47,6 +47,11 @@ func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
 				Path:    "/message/messageType",
 				Handler: MessageTypeHandler(serverCtx),
 			},
+			{
+				Method:  http.MethodPost,
+				Path:    "/message/markRead",
+				Handler: MarkReadHandler(serverCtx),
+			},
 		},
 	)
 }

+ 46 - 0
api/internal/logic/markreadlogic.go

@@ -0,0 +1,46 @@
+package logic
+
+import (
+	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
+	"context"
+	"log"
+
+	"app.yhyue.com/moapp/MessageCenter/api/internal/svc"
+	"app.yhyue.com/moapp/MessageCenter/api/internal/types"
+
+	"github.com/tal-tech/go-zero/core/logx"
+)
+
+type MarkReadLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewMarkReadLogic(ctx context.Context, svcCtx *svc.ServiceContext) MarkReadLogic {
+	return MarkReadLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx,
+	}
+}
+
+func (l *MarkReadLogic) MarkRead(req types.MarkReadReq) (*types.MarkReadRes, error) {
+	// todo: add your logic here and delete this line
+	result := &types.MarkReadRes{}
+	log.Println(req)
+	lsi := l.svcCtx.MessageCenter
+	resp, err := lsi.ChangeReadStatus(l.ctx, &messageclient.ChangeReadStatusRequest{
+		Appid:      req.AppId,
+		ReadStatus: 1,
+		Id:         req.MsgId,
+	})
+	if err != nil {
+		return nil, err
+	}
+	log.Println(resp,"8989898")
+	result.Code = 1
+	result.Data = resp.Code
+	result.Message = resp.Message
+	return result, nil
+}

+ 1 - 1
api/internal/logic/messagedeletelogic.go

@@ -25,7 +25,7 @@ func NewMessageDeleteLogic(ctx context.Context, svcCtx *svc.ServiceContext) Mess
 	}
 }
 
-func (l *MessageDeleteLogic) MessageDelete(req types.MessageDeleteReq) (*types.MessageDeleteResp, error) {
+func (l *MessageDeleteLogic) MessageDelete(req types.MessageDeleteReq) (*types.Response, error) {
 	// todo: add your logic here and delete this line
 	result := &types.Response{}
 	log.Println(req)

+ 1 - 1
api/internal/logic/messagedetaillogic.go

@@ -26,7 +26,7 @@ func NewMessageDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) Mess
 }
 
 func (l *MessageDetailLogic) MessageDetail(req types.MessageDetailReq) (*types.MessageDetailResp, error) {
-	result := &types.Response{}
+	//result := &types.Response{}
 	log.Println(req)
 	lsi := l.svcCtx.MessageCenter
 	resp, err := lsi.FindMessageDetail(l.ctx, &messageclient.MessageDetailReq{

+ 0 - 1
api/internal/logic/messagefindlogic.go

@@ -47,7 +47,6 @@ func (l *MessageFindLogic) MessageFind(req types.MessageFindReq) (*types.Message
 	result.Code = resp.Code
 	result.Message = resp.Message
 	result.Total = resp.Count
-	result.Status = 0
 	for _, v := range resp.Data {
 		result.Data = append(result.Data, map[string]interface{}{
 			"id":           v.Id,

+ 18 - 15
api/internal/logic/messagegetlastlogic.go

@@ -38,24 +38,27 @@ func (l *MessageGetLastLogic) MessageGetLast(req types.MessageGetLastReq) (*type
 		return nil, err
 	}
 	//data := make([]map[string]interface{}, 0)
-
+	log.Println(result,99999999)
+	log.Println(resp)
 	result.Code = resp.Code
 	result.Message = resp.Message
-	result.Status = 0
-	result.Data = map[string]interface{}{
-		"id":           resp.Data.Id,
-		"appid":        resp.Data.Appid,
-		"receive_name": resp.Data.ReceiveName,
-		"send_userid":  resp.Data.SendUserId,
-		"send_name":    resp.Data.SendName,
-		"createtime":   resp.Data.Createtime,
-		"title":        resp.Data.Title,
-		"msg_type":     resp.Data.MsgType,
-		"link":         resp.Data.Link,
-		"cite_id":      resp.Data.CiteId,
-		"content":      resp.Data.Content,
-		"isRead":       resp.Data.IsRead,
+	if result.Data!=nil{
+		result.Data = map[string]interface{}{
+			"id":           resp.Data.Id,
+			"appid":        resp.Data.Appid,
+			"receive_name": resp.Data.ReceiveName,
+			"send_userid":  resp.Data.SendUserId,
+			"send_name":    resp.Data.SendName,
+			"createtime":   resp.Data.Createtime,
+			"title":        resp.Data.Title,
+			"msg_type":     resp.Data.MsgType,
+			"link":         resp.Data.Link,
+			"cite_id":      resp.Data.CiteId,
+			"content":      resp.Data.Content,
+			"isRead":       resp.Data.IsRead,
+		}
 	}
 
+	log.Println(result)
 	return result, nil
 }

+ 2 - 3
api/internal/logic/messagetypelogic.go

@@ -25,9 +25,9 @@ func NewMessageTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) Messag
 	}
 }
 
-func (l *MessageTypeLogic) MessageType(req types.MessageTypeReq) (*types.MessageTypeReqRes, error) {
+func (l *MessageTypeLogic) MessageType(req types.MessageTypeReq) (*types.MessageTypeRes, error) {
 	// todo: add your logic here and delete this line
-	result := &types.MessageTypeReqRes{}
+	result := &types.MessageTypeRes{}
 	log.Println(req)
 	lsi := l.svcCtx.MessageCenter
 	resp, err := lsi.GetMsgType(l.ctx, &messageclient.GetMsgTypeReq{
@@ -41,7 +41,6 @@ func (l *MessageTypeLogic) MessageType(req types.MessageTypeReq) (*types.Message
 
 	result.Code = resp.Code
 	result.Message = resp.Message
-	result.Status = 0
 	result.Data = resp.Data
 
 	return result, nil

+ 1 - 1
api/internal/logic/messageunreadclasscountlogic.go

@@ -34,6 +34,7 @@ func (l *MessageUnreadClassCountLogic) MessageUnreadClassCount(req types.Message
 		Appid:  req.AppId,
 		UserId: req.UserId,
 	})
+	log.Println(resp,888888)
 	if err != nil {
 		return nil, err
 	}
@@ -41,7 +42,6 @@ func (l *MessageUnreadClassCountLogic) MessageUnreadClassCount(req types.Message
 
 	result.Code = resp.Code
 	result.Message = resp.Message
-	result.Status = 0
 	for _, v := range resp.Data {
 		result.Data = append(result.Data, map[string]interface{}{
 			"type":  v.MsgType,

+ 0 - 1
api/internal/logic/messageunreadcountlogic.go

@@ -41,7 +41,6 @@ func (l *MessageUnreadCountLogic) MessageUnreadCount(req types.MessageUnreadCoun
 
 	result.Code = resp.Code
 	result.Message = resp.Message
-	result.Status = 0
 	result.Data = map[string]interface{}{
 		"count": resp.Count,
 	}

+ 12 - 6
api/internal/types/types.go

@@ -31,7 +31,6 @@ type MessageGetLastRes struct {
 	Code    int64                  `json:"code"`
 	Message string                 `json:"message"`
 	Data    map[string]interface{} `json:"data"`
-	Status  int64                  `json:"isOk"`
 }
 
 type MessageFindReq struct {
@@ -47,7 +46,6 @@ type MessageFindReq struct {
 type MessageFindRes struct {
 	Code    int64                    `json:"code"`
 	Message string                   `json:"message"`
-	Status  int64                    `json:"isOk"`
 	Data    []map[string]interface{} `json:"data"`
 	Total   int64                    `json:"total"`
 }
@@ -59,7 +57,6 @@ type MessageUnreadClassCountReq struct {
 
 type MessageUnreadClassCountRes struct {
 	Code    int64                    `json:"code"`
-	Status  int64                    `json:"isOk"`
 	Message string                   `json:"message"`
 	Data    []map[string]interface{} `json:"data"`
 	Info    []map[string]interface{} `json:"info"`
@@ -72,7 +69,6 @@ type MessageUnreadCountReq struct {
 
 type MessageUnreadCountRes struct {
 	Code    int64                  `json:"code"`
-	Status  int64                  `json:"isOk"`
 	Message string                 `json:"message"`
 	Data    map[string]interface{} `json:"data"`
 }
@@ -82,9 +78,19 @@ type MessageTypeReq struct {
 	AppId  string `form:"appId"`
 }
 
-type MessageTypeReqRes struct {
+type MessageTypeRes struct {
 	Code    int64   `json:"code"`
-	Status  int64   `json:"isOk"`
 	Message string  `json:"message"`
 	Data    []int64 `json:"data"`
 }
+
+type MarkReadReq struct {
+	MsgId int64  `form:"msgId"`
+	AppId string `form:"appId"`
+}
+
+type MarkReadRes struct {
+	Code    int64  `json:"code"`
+	Message string `json:"message"`
+	Data    int64  `json:"data"`
+}

+ 15 - 9
api/message.api

@@ -35,7 +35,6 @@ type MessageGetLastRes {
 	Code    int64                  `json:"code"`
 	Message string                 `json:"message"`
 	Data    map[string]interface{} `json:"data"`
-	Status  int64                  `json:"isOk"`
 }
 type MessageFindReq {
 	UserId string `form:"userId"`
@@ -50,7 +49,6 @@ type MessageFindReq {
 type MessageFindRes {
 	Code    int64                    `json:"code"`
 	Message string                   `json:"message"`
-	Status  int64                    `json:"isOk"`
 	Data    []map[string]interface{} `json:"data"`
 	Total   int64                    `json:"total"`
 }
@@ -61,7 +59,6 @@ type MessageUnreadClassCountReq {
 
 type MessageUnreadClassCountRes {
 	Code    int64                    `json:"code"`
-	Status  int64                    `json:"isOk"`
 	Message string                   `json:"message"`
 	Data    []map[string]interface{} `json:"data"`
 	Info    []map[string]interface{} `json:"info"`
@@ -72,7 +69,6 @@ type MessageUnreadCountReq {
 }
 type MessageUnreadCountRes {
 	Code    int64                  `json:"code"`
-	Status  int64                  `json:"isOk"`
 	Message string                 `json:"message"`
 	Data    map[string]interface{} `json:"data"`
 }
@@ -80,19 +76,27 @@ type MessageTypeReq {
 	UserId string `form:"userId"`
 	AppId  string `form:"appId"`
 }
-type MessageTypeReqRes {
+type MessageTypeRes {
 	Code    int64   `json:"code"`
-	Status  int64   `json:"isOk"`
 	Message string  `json:"message"`
 	Data    []int64 `json:"data"`
 }
+type MarkReadReq {
+	MsgId int64  `form:"msgId"`
+	AppId string `form:"appId"`
+}
+type MarkReadRes {
+	Code    int64  `json:"code"`
+	Message string `json:"message"`
+	Data    int64  `json:"data"`
+}
 service message-api {
 	//删除消息
 	@handler MessageDeleteHandler // TODO: set handler name and delete this comment
-	get /message/messageDelete(MessageDeleteReq) returns(response)
+	get /message/messageDelete (MessageDeleteReq) returns (response)
 	//查询消息详情
 	@handler MessageDetailHandler // TODO: set handler name and delete this comment
-	get /message/messageDetail(MessageDetailReq) returns(MessageDetailResp)
+	get /message/messageDetail (MessageDetailReq) returns (MessageDetailResp)
 	@handler MessageGetLastHandler // 获取指定类型的最新一条未读消息
 	post /message/messageGetLast (MessageGetLastReq) returns (MessageGetLastRes)
 	@handler MessageFindHandler // 获取指定用户的历史消息  条件可选 消息类型 是否未读
@@ -102,5 +106,7 @@ service message-api {
 	@handler MessageUnreadCountHandler // 获取用户未读消息数量
 	post /message/messageUnreadCount (MessageUnreadCountReq) returns (MessageUnreadCountRes)
 	@handler MessageTypeHandler // 获取用户未读消息数量
-	post /message/messageType (MessageTypeReq) returns (MessageTypeReqRes)
+	post /message/messageType (MessageTypeReq) returns (MessageTypeRes)
+	@handler MarkReadHandler // 标记为已读
+	post /message/markRead (MarkReadReq) returns (MarkReadRes)
 }

+ 25 - 0
api/test/message_test.go

@@ -0,0 +1,25 @@
+package test
+
+import (
+	"app.yhyue.com/moapp/MessageCenter/rpc/messageclient"
+	"context"
+	"github.com/tal-tech/go-zero/core/discov"
+	"github.com/tal-tech/go-zero/zrpc"
+	"log"
+	"testing"
+	"time"
+)
+
+func  Test_ChangeReadStatus(t *testing.T)  {
+	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
+	std := messageclient.NewMessage(zrpc.MustNewClient(zrpc.RpcClientConf{Etcd: discov.EtcdConf{Hosts: []string{"127.0.0.1:2379"}, Key: "message.rpc"}}))
+	//std := stdlibclient.NewStdlib(zrpc.MustNewClient(zrpc.RpcClientConf{Etcd: discov.EtcdConf{Hosts: []string{"127.0.0.1:2379"}, Key: "jydocs.stdlib.rpc"}}))
+	req := &messageclient.ChangeReadStatusRequest{Id: 1,ReadStatus: 1,Appid: "10000"}
+	res, err := std.ChangeReadStatus(ctx, req)
+	log.Println("err ", err,res)
+	//if res.State == true {
+	//	log.Println("req true")
+	//} else {
+	//	log.Println("req false", res)
+	//}
+}

+ 2 - 0
rpc/internal/logic/getlastmessagelogic.go

@@ -3,6 +3,7 @@ package logic
 import (
 	"app.yhyue.com/moapp/MessageCenter/service"
 	"context"
+	"log"
 
 	"app.yhyue.com/moapp/MessageCenter/rpc/internal/svc"
 	"app.yhyue.com/moapp/MessageCenter/rpc/message"
@@ -34,6 +35,7 @@ func (l *GetLastMessageLogic) GetLastMessage(in *message.GetLastMessageReq) (*me
 	if err == nil{
 		code = 1
 	}
+	log.Println(data,"666666666",code)
 	return &message.GetLastMessageRes{
 		Code: int64(code),
 		Message: msg,

+ 12 - 12
rpc/messageclient/message.go

@@ -14,26 +14,26 @@ import (
 )
 
 type (
-	ResCount                     = message.ResCount
-	Response                     = message.Response
-	GetUnreadClassCountRes       = message.GetUnreadClassCountRes
 	GetLastMessageReq            = message.GetLastMessageReq
-	GetLastMessageRes            = message.GetLastMessageRes
+	GetUnreadClassCountReq       = message.GetUnreadClassCountReq
 	DeleteSingleMessageRequest   = message.DeleteSingleMessageRequest
 	GetUnreadCountRequest        = message.GetUnreadCountRequest
 	FindUserMsgReq               = message.FindUserMsgReq
-	GetClassUnreadCountReq       = message.GetClassUnreadCountReq
-	GetMsgTypeReq                = message.GetMsgTypeReq
-	SendMsgRequest               = message.SendMsgRequest
-	ChangeReadStatusRequest      = message.ChangeReadStatusRequest
 	Messages                     = message.Messages
-	MessageDetailReq             = message.MessageDetailReq
-	GetUnreadClassCountReq       = message.GetUnreadClassCountReq
-	GetMsgTypeRes                = message.GetMsgTypeRes
-	DeleteMultipleMessageRequest = message.DeleteMultipleMessageRequest
 	GetUnreadCountResponse       = message.GetUnreadCountResponse
 	FindUserMsgRes               = message.FindUserMsgRes
+	GetLastMessageRes            = message.GetLastMessageRes
+	GetMsgTypeReq                = message.GetMsgTypeReq
+	GetClassUnreadCountReq       = message.GetClassUnreadCountReq
 	MessageDetailResp            = message.MessageDetailResp
+	GetUnreadClassCountRes       = message.GetUnreadClassCountRes
+	GetMsgTypeRes                = message.GetMsgTypeRes
+	SendMsgRequest               = message.SendMsgRequest
+	ChangeReadStatusRequest      = message.ChangeReadStatusRequest
+	ResCount                     = message.ResCount
+	DeleteMultipleMessageRequest = message.DeleteMultipleMessageRequest
+	Response                     = message.Response
+	MessageDetailReq             = message.MessageDetailReq
 
 	Message interface {
 		//  修改消息阅读状态

+ 1 - 1
service/messageService.go

@@ -128,7 +128,7 @@ func (service *MessageService) ClassCountAndMessage(userId string, appId string)
 	log.Println("123")
 	defer orm.Close()
 	//m := []*message.Messages{}
-	query, err := orm.QueryInterface("select count(*) as count,msg_type from message where receive_userid=? and isdel=1 and appid=? and isRead=0 group by msg_type", userId, appId)
+	query, err := orm.QueryInterface("SELECT msg_type,COUNT(CASE WHEN isRead=0 THEN 1 END) as count  FROM message receive_userid=? and isdel=1 and appid=? and isRead=0 GROUP BY msg_type  ORDER BY FIELD(`msg_type`,\"1\",\"2\",\"3\")", userId, appId)
 	if err != nil {
 		return nil, nil, err
 	}

+ 33 - 0
src/config.json

@@ -0,0 +1,33 @@
+{
+	"webport": "8086",
+	"webdomain":"http://web-jydev-wh.jianyu360.cn",
+	"mongodb": {
+		"main": {
+			"address": "192.168.3.206:27080",
+	 		"size": 5,
+	 		"dbName": "qfw"
+		},
+		"log": {
+			"address": "192.168.3.206:27080",
+	 		"size": 5,
+	 		"dbName": "qfw",
+			"userName": "admin",
+			"password": "123456"
+		}
+	},
+    "redis": {
+    	"main": {
+			"address": "other=192.168.3.206:1712,session=192.168.3.206:1712"
+		}
+    },
+    "mysql": {
+	    "main": {
+	        "dbName": "jianyu",
+	        "address": "192.168.3.11:3366",
+	        "userName": "root",
+	        "passWord": "Topnet123",
+			"maxOpenConns": 20,
+			"maxIdleConns": 20
+	    }
+    }
+}

+ 17 - 0
src/main.go

@@ -0,0 +1,17 @@
+package main
+
+import (
+	"github.com/go-xweb/xweb"
+	"net/http"
+	_ "service/a"
+	_ "service/action"
+	"service/config"
+	_ "service/filter"
+	_ "service/public"
+	_ "timetask"
+)
+
+func main() {
+	mux1 := http.NewServeMux()
+	xweb.RunBase(":"+config.Sysconfig.Webport, mux1)
+}

+ 21 - 0
src/service/a/init.go

@@ -0,0 +1,21 @@
+package init
+
+import (
+	"time"
+
+	"github.com/go-xweb/httpsession"
+	"github.com/go-xweb/xweb"
+)
+
+func init() {
+	httpsession.IsRedisSessionStore = true
+	xweb.Config.Profiler = true
+	xweb.RootApp().AppConfig.StaticFileVersion = false
+	xweb.RootApp().AppConfig.CheckXsrf = false
+	xweb.RootApp().AppConfig.EnableHttpCache = false
+	xweb.RootApp().AppConfig.Mode = xweb.Product
+	xweb.RootApp().AppConfig.SessionTimeout = 7 * 24 * time.Hour
+	xweb.RootApp().Logger.SetOutputLevel(1) //输出日志,改为4则不输出任何日志
+	xweb.RootApp().AppConfig.StaticDir = "web/staticres"
+	xweb.RootApp().BasePath = "/distribution"
+}

+ 1 - 0
src/service/action/message.go

@@ -0,0 +1 @@
+package action

+ 143 - 0
src/service/config/config.go

@@ -0,0 +1,143 @@
+package config
+
+import (
+	"log"
+	m "mongodb"
+	mg "qfw/mongodb"
+	"qfw/util"
+	"qfw/util/mail"
+	"qfw/util/mysql"
+	"qfw/util/redis"
+)
+
+type config struct {
+	Webport   string
+	Webdomain string
+	Mail      *[]mailConf
+	Mongodb   struct {
+		Main *mgoConf
+		Log  *mgoConf
+		Ent  *mgoConf
+	}
+	Elasticsearch struct {
+		Main *esConf
+	}
+	Redis struct {
+		Main  *redisConf
+		Login *redisConf
+	}
+	Mysql struct {
+		Main *mysqlConf
+		Push *mysqlConf
+	}
+	WorkerNum          int
+	JobNum             int
+	Modular            map[string]interface{}
+	UploadPath         string
+	CatchoutTimesMonth int64
+	AuthCost           float64
+	TermValidity       int
+	SourceCenter       string
+}
+
+type BalanceRes struct {
+	Code    int64                    `json:"code"`
+	Message string                   `json:"message"`
+	Data    []map[string]interface{} `json:"data"`
+}
+
+type mgoConf struct {
+	Address  string
+	Size     int
+	DbName   string
+	UserName string
+	Password string
+}
+
+type esConf struct {
+	Address string
+	Size    int
+}
+type redisConf struct {
+	Address string
+}
+type mysqlConf struct {
+	DbName       string
+	Address      string
+	UserName     string
+	PassWord     string
+	MaxOpenConns int
+	MaxIdleConns int
+}
+type mailConf struct {
+	Addr string
+	Port int
+	Pwd  string
+	User string
+}
+
+var (
+	Sysconfig *config
+	Mysql     *mysql.Mysql
+	MQFW      mg.MongodbSim
+	Mgo_Log   m.MongodbSim
+	GmailAuth []*mail.GmailAuth
+)
+
+func init() {
+	util.ReadConfig(&Sysconfig)
+	if Sysconfig != nil {
+		//初始化redis
+		if Sysconfig.Redis.Main != nil {
+			log.Println("初始化 redis")
+			redis.InitRedisBySize(Sysconfig.Redis.Main.Address, 100, 30, 300)
+		}
+		//
+		if Sysconfig.Mongodb.Main != nil {
+			log.Println("初始化 mongodb main")
+			MQFW = mg.MongodbSim{
+				MongodbAddr: Sysconfig.Mongodb.Main.Address,
+				Size:        Sysconfig.Mongodb.Main.Size,
+				DbName:      Sysconfig.Mongodb.Main.DbName,
+			}
+			MQFW.InitPool()
+		}
+		if Sysconfig.Mongodb.Log != nil {
+			log.Println("初始化 mongodb log")
+			Mgo_Log = m.MongodbSim{
+				MongodbAddr: Sysconfig.Mongodb.Log.Address,
+				Size:        Sysconfig.Mongodb.Log.Size,
+				DbName:      Sysconfig.Mongodb.Log.DbName,
+				UserName:    Sysconfig.Mongodb.Log.UserName,
+				Password:    Sysconfig.Mongodb.Log.Password,
+			}
+			Mgo_Log.InitPool()
+		}
+		if Sysconfig.Mysql.Main != nil {
+			log.Println("初始化 mysql")
+			Mysql = &mysql.Mysql{
+				Address:      Sysconfig.Mysql.Main.Address,
+				UserName:     Sysconfig.Mysql.Main.UserName,
+				PassWord:     Sysconfig.Mysql.Main.PassWord,
+				DBName:       Sysconfig.Mysql.Main.DbName,
+				MaxOpenConns: Sysconfig.Mysql.Main.MaxOpenConns,
+				MaxIdleConns: Sysconfig.Mysql.Main.MaxIdleConns,
+			}
+			Mysql.Init()
+		}
+		//
+		if Sysconfig.Mail != nil {
+			log.Println("初始化 Mail")
+			mailConfigArrMap := Sysconfig.Mail
+			for _, v := range *mailConfigArrMap {
+				mail := &mail.GmailAuth{
+					SmtpHost: v.Addr,
+					SmtpPort: v.Port,
+					User:     v.User,
+					Pwd:      v.Pwd,
+				}
+				GmailAuth = append(GmailAuth, mail)
+			}
+		}
+	}
+}

+ 6 - 0
src/service/filter/filter.go

@@ -0,0 +1,6 @@
+package filter
+
+func init() {
+/*	xweb.AddFilter(&logfilter{App: xweb.RootApp()})
+	xweb.AddFilter(&sessionfilter{App: xweb.RootApp()})*/
+}

+ 96 - 0
src/service/filter/logfilter.go

@@ -0,0 +1,96 @@
+package filter
+
+import (
+	"encoding/json"
+	"log"
+	"net/http"
+	"qfw/util"
+	. "service/config"
+	"sync"
+	"time"
+
+	"github.com/go-xweb/httpsession"
+	"github.com/go-xweb/xweb"
+)
+
+//日志过滤器
+type logfilter struct {
+	App         *xweb.App
+	SessionName string
+}
+
+//继承过滤器方法
+func (l *logfilter) Do(w http.ResponseWriter, req *http.Request) bool {
+	req.Proto = util.GetIp(req)
+	session := l.App.SessionManager.Session(req, w)
+	go func() {
+		addLog(l, session, req)
+	}()
+	return true
+}
+
+//定时保存日志
+func SaveLogTask() {
+	lock.Lock()
+	if len(arr) >= 1 {
+		tmp := arr
+		arr = make([]map[string]interface{}, 0)
+		go func() {
+			log.Println("timer..save..visit..log", len(tmp))
+			Mgo_Log.SaveBulk("distribution_logs", tmp...)
+		}()
+	}
+
+	lock.Unlock()
+	time.AfterFunc(5*time.Minute, SaveLogTask)
+}
+
+//内存缓存日志数量,超过此数量存库
+var nc = 500
+
+//内存缓存日志map
+var arr = make([]map[string]interface{}, 0)
+
+//对map的同步
+var lock sync.Mutex
+
+func addLog(l *logfilter, session *httpsession.Session, req *http.Request) {
+	userName := session.Get(l.SessionName)
+	hasSession := (userName != nil)
+	timeNow := time.Now()
+	agent := req.Header.Get("user-agent")
+	s_url := req.RequestURI
+	md, _ := json.Marshal(req.Form)
+	str := string(md)
+	logs := map[string]interface{}{
+		"date":      timeNow.Unix(),
+		"ip":        req.Proto,
+		"refer":     req.Referer(),
+		"year":      timeNow.Year(),
+		"month":     timeNow.Month(),
+		"day":       timeNow.Day(),
+		"hour":      timeNow.Hour(),
+		"minutes":   timeNow.Minute(),
+		"mdescribe": str,
+		"client":    agent,
+		"os":        util.GetOS(agent),
+		"browse":    util.GetBrowse(agent),
+		"method":    req.Method,
+		"url":       s_url,
+	}
+	if hasSession {
+		logs["userid"] = session.Get("userId")
+		logs["uname"] = userName
+	}
+	lock.Lock()
+	arr = append(arr, logs)
+	if len(arr) >= nc {
+		tmp := arr
+		arr = make([]map[string]interface{}, 0)
+		go func() {
+			log.Println("save..visit..log", len(tmp))
+			Mgo_Log.SaveBulk("distribution_logs", tmp...)
+		}()
+	}
+	lock.Unlock()
+}

+ 27 - 0
src/service/filter/sessionfilter.go

@@ -0,0 +1,27 @@
+package filter
+
+import (
+	. "api"
+	"github.com/go-xweb/xweb"
+	"net/http"
+	"strings"
+)
+
+//登录限制
+type sessionfilter struct {
+	App *xweb.App
+}
+
+//继承过滤器方法
+func (l *sessionfilter) Do(w http.ResponseWriter, req *http.Request) bool {
+	rqu := req.URL.Path
+	if strings.HasPrefix(rqu, "/distribution/share/getWordInfo") || strings.HasPrefix(rqu, "/distribution/logo/*") || strings.HasPrefix(rqu, "/share/shareLink") {
+		return true
+	}
+	session := l.App.SessionManager.Session(req, w)
+	if session.Get("userId") == nil {
+		R.ServeJson(w, req, &Result{Error_code_1001, Error_msg_1001, nil})
+		return false
+	}
+	return true
+}

+ 89 - 0
src/service/public/random.go

@@ -0,0 +1,89 @@
+package public
+
+import (
+	"bytes"
+	cr "crypto/rand"
+	"math/big"
+	"math/rand"
+	"qfw/util/redis"
+	"service/config"
+	"strings"
+	"sync"
+	"time"
+)
+
+var VarLSCPool = &LSCPool{
+	JobQueue:  make(chan string, config.Sysconfig.JobNum),
+	WorkerNum: config.Sysconfig.WorkerNum,
+	Lock:      &sync.Mutex{},
+	Randoms:   "",
+}
+
+type LSCPool struct {
+	JobQueue  chan string //待取的口令
+	WorkerNum int         //当前工作的协程数
+	Lock      *sync.Mutex //口令锁
+	Randoms   string      //口令集合
+}
+
+func (this *LSCPool) GetJob() string {
+	return <-this.JobQueue
+}
+
+var r *rand.Rand
+
+func init() {
+	r = rand.New(rand.NewSource(time.Now().Unix()))
+	for i := 0; i < VarLSCPool.WorkerNum/2; i++ {
+		go func() {
+			for {
+				VarLSCPool.JobQueue <- VarLSCPool.GetRandom()
+			}
+		}()
+	}
+}
+
+//获取随机字符串
+func (this *LSCPool) GetRandom() string {
+	this.Lock.Lock()
+	defer this.Lock.Unlock()
+	//如果使用过了 重新获取
+	for {
+		LSC := this.SpecialChar(0) + this.LetterRandom(8)
+		if strings.Contains(this.Randoms, LSC) {
+			continue
+		}
+		this.Randoms += LSC + "|"
+		ok, _ := redis.Exists("other", "DIS_"+LSC)
+		if ok {
+			continue
+		}
+		// log.Println("获取口令:", LSC)
+		return LSC
+	}
+	return ""
+}
+
+//字母随机串
+func (this *LSCPool) LetterRandom(LL int) (LR string) {
+	bytes := make([]byte, LL)
+	for i := 0; i < LL; i++ {
+		b := r.Intn(26) + 65
+		bytes[i] = byte(b)
+	}
+	LR = string(bytes)
+	return
+}
+
+//特殊字符随机串
+func (this *LSCPool) SpecialChar(LL int) (SC string) {
+	var str = "$#"
+	b := bytes.NewBufferString(str)
+	length := b.Len()
+	bigInt := big.NewInt(int64(length))
+	for i := 0; i < LL; i++ {
+		randomInt, _ := cr.Int(cr.Reader, bigInt)
+		SC += string(str[randomInt.Int64()])
+	}
+	return
+}

+ 6 - 0
src/timetask.json

@@ -0,0 +1,6 @@
+{
+	"settlement":{
+		"day":6,
+		"time":"00:00"
+	}
+}

+ 437 - 0
src/timetask/timetask.go

@@ -0,0 +1,437 @@
+package timetask
+
+import (
+	"bytes"
+	"database/sql"
+	"fmt"
+	"log"
+	"math/rand"
+	"qfw/util"
+	"qfw/util/jy"
+	. "service/config"
+	"strconv"
+	"strings"
+	"time"
+	. "util"
+
+	"github.com/tealeg/xlsx"
+)
+
+type timetaskConf struct {
+	Settlement struct {
+		Day  int
+		Time string
+	}
+	ToCashout struct {
+		Day  int
+		Time string
+	}
+	FlyerUserTime string
+	ShareAutoInc  map[string][]*shareAutoInc
+	Finance       struct {
+		ReTry int
+		From  string
+		Title string
+		Fname string
+		Mails []string
+	}
+}
+type shareAutoInc struct {
+	Hour     string
+	Inc      string
+	Duration string
+}
+
+var (
+	TimetaskConf *timetaskConf
+)
+
+func init() {
+	util.ReadConfig("./timetask.json", &TimetaskConf)
+}
+
+var ShareUser []map[string]interface{}
+
+type myWrite struct {
+	Byte *bytes.Buffer
+}
+
+func (m *myWrite) Write(p []byte) (n int, err error) {
+	n, err = m.Byte.Write(p)
+	return
+}
+
+type settlementFx struct {
+	name       string  //姓名
+	idcard     string  //身份证号
+	commission float64 //佣金
+	tax        float64 //个税
+}
+
+var fx *xlsx.File
+
+func init() {
+	//20号把已结算的佣金转入可提现金额
+	go toCashOut()
+	//虚拟分享次数
+	go func() {
+		for k, v := range TimetaskConf.ShareAutoInc {
+			shareCount(k, v)
+			time.Sleep(50 * time.Millisecond)
+		}
+	}()
+	//介绍页用户头像姓名
+	//go util.SimpleCrontab(true, TimetaskConf.FlyerUserTime, Getshareinfo)
+}
+
+
+
+/*
+应纳税额计算方法
+
+劳务报酬所得
+级数 预扣预缴应纳税所得额        预扣税率 速算扣除数
+1   不超过20000元的部分         20%       0
+2   超过20000元至50000元的部分   30%     2000
+3   超过50000元的部分           40%     7000
+
+预扣预缴应纳税所得额的计算方式:
+预扣预缴应纳税所得额=劳务报酬(小于4000元)-800元
+预扣预缴应纳税所得额=劳务报酬(超过4000元)*(1-20%)
+应纳税额的计算公式:
+应纳税额=预扣预缴应纳税所得额*适用税率-速算扣除数
+备注:
+1.劳务报酬所得在800元以下的,不需要缴纳个人所得税
+2.劳务报酬所得大于800元且没有超过4000元,可减除800元的扣除费用
+3.劳务报酬所得超过4000元的,可减除劳务报酬收入20%的扣除费用
+
+举例:
+1.劳务报酬收入为2000
+预扣预缴应纳税所得额=2000-800=1200
+应纳税额=1200*20%=240
+
+2.劳务报酬收入为4500
+预扣预缴应纳税所得额=4500*(1-20%)=3600
+应纳税额=3600*20%=720
+
+3.劳务报酬收入为30000
+预扣预缴应纳税所得额=30000*(1*20%)=24000
+应纳税额=24000*30%-2000=5200
+*/
+func TaxPayable(commission float64) int64 {
+	var tax_cash float64 //应纳税额
+	var ynssde float64   //预扣预缴应纳税所得额
+	if commission > 800 && commission <= 4000 {
+		ynssde = commission - 800
+	} else if commission > 4000 {
+		ynssde = commission * 0.8
+	}
+	if ynssde > 0 {
+		sysl := 0.2       //适用税率
+		var sskcs float64 //速算扣除数
+		if ynssde > 20000 && ynssde <= 50000 {
+			sysl = 0.3
+			sskcs = 2000
+		} else if ynssde > 50000 {
+			sysl = 0.4
+			sskcs = 7000
+		}
+		tax_cash = ynssde*sysl - sskcs
+	}
+	return int64(util.RetainDecimal(tax_cash, 2) * 100)
+}
+
+//虚拟分享次数
+func shareCount(product string, shareAutoIncs []*shareAutoInc) {
+	defer util.Catch()
+	hour := time.Now().Hour()
+	for _, v := range shareAutoIncs {
+		hour_array := strings.Split(v.Hour, "-")
+		if len(hour_array) != 2 {
+			log.Println("配置项 hour error")
+			continue
+		}
+		hour_min, err := strconv.Atoi(hour_array[0])
+		if err != nil {
+			log.Println("配置项 hour_min error", err)
+			continue
+		}
+		hour_max, err := strconv.Atoi(hour_array[1])
+		if err != nil {
+			log.Println("配置项 hour_max error", err)
+			continue
+		}
+		if hour < hour_min || hour > hour_max {
+			continue
+		}
+		inc_array := strings.Split(v.Inc, "-")
+		if len(inc_array) != 2 {
+			log.Println("配置项 inc error")
+			continue
+		}
+		duration_array := strings.Split(v.Duration, "-")
+		if len(duration_array) != 2 {
+			log.Println("配置项 duration error")
+			continue
+		}
+		//
+		inc_min, err := strconv.Atoi(inc_array[0])
+		if err != nil {
+			log.Println("配置项 inc_min error", err)
+			continue
+		}
+		inc_max, err := strconv.Atoi(inc_array[1])
+		if err != nil {
+			log.Println("配置项 inc_max error", err)
+			continue
+		}
+		//
+		duration_min, err := strconv.Atoi(duration_array[0])
+		if err != nil {
+			log.Println("配置项 duration_min error", err)
+			continue
+		}
+		duration_max, err := strconv.Atoi(duration_array[1])
+		if err != nil {
+			log.Println("配置项 duration_max error", err)
+			continue
+		}
+		//
+		r := rand.New(rand.NewSource(time.Now().UnixNano()))
+		inc := r.Intn(inc_max)
+		if inc < inc_min {
+			inc += inc_min
+		}
+		duration_m := r.Intn(duration_max)
+		if duration_m < duration_min {
+			duration_m += duration_min
+		}
+		duration_s := r.Intn(duration_max)
+		if duration_s < duration_min {
+			duration_s += duration_min
+		}
+		d := time.Duration(duration_m)*time.Minute + time.Duration(duration_s)*time.Second
+		MQFW.Update("dis_product", map[string]interface{}{
+			"s_name": product,
+		}, map[string]interface{}{
+			"$inc": map[string]interface{}{
+				"i_shareCount": inc,
+			},
+		}, false, false)
+		log.Println(product, "分享次数自增", "hour", hour, "inc", inc, "duration", d)
+		time.AfterFunc(d, func() {
+			shareCount(product, shareAutoIncs)
+		})
+		return
+	}
+	log.Println("没有符合条件的配置项,请检查配置项!")
+}
+
+func Getshareinfo() {
+	log.Println("开始获取1000名用户头像")
+	ShareUser = []map[string]interface{}{}
+	data, ok := MQFW.Find("user", map[string]interface{}{
+		"$or": []map[string]interface{}{
+			map[string]interface{}{"s_headimageurl": map[string]interface{}{"$exists": true}},
+			map[string]interface{}{"s_headimage": map[string]interface{}{"$exists": true}},
+		},
+		"i_appid": 2,
+	}, `{"l_registedate":-1}`, `{"s_headimageurl":1,"s_headimage":1,"s_phone":1,"s_m_phone":1,"s_nickname":1}`, false, 0, 300)
+	if ok && data != nil && *data != nil {
+		for _, v := range *data {
+			nickname := ""
+			info := map[string]interface{}{}
+			if s_phone, _ := v["s_phone"].(string); s_phone != "" {
+				nickname = s_phone
+			} else if s_m_phone, _ := v["s_m_phone"].(string); s_m_phone != "" {
+				nickname = s_m_phone
+			} else if s_nickname, _ := v["s_nickname"].(string); s_nickname != "" {
+				nickname = s_nickname
+			}
+			if s_headimageurl, _ := v["s_headimageurl"].(string); s_headimageurl != "" {
+				info["headimageurl"] = s_headimageurl
+			} else if s_headimage, _ := v["s_headimage"].(string); s_headimage != "" {
+				info["headimageurl"] = Sysconfig.Webdomain + s_headimage
+			}
+			info["nickname"] = EncryptionInfo(nickname)
+			if util.ObjToString(info["nickname"]) == "" || util.ObjToString(info["headimageurl"]) == "" {
+				continue
+			}
+			ShareUser = append(ShareUser, info)
+		}
+	}
+}
+
+func EncryptionInfo(s string) string {
+	if jy.IsPhone(s) {
+		s = string(s[0:3]) + "****" + string(s[len(s)-4:])
+	} else {
+		strArray := []rune(s)
+		length := strings.Count(s, "") - 1
+		if length > 2 {
+			star := ""
+			for i := 0; i < length-2; i++ {
+				star += "*"
+			}
+			s = string(strArray[0:1]) + star + string(strArray[len(strArray)-1:])
+		} else if length == 2 {
+			s = string(strArray[0:1]) + "*"
+		} else {
+			s = ""
+		}
+	}
+	return s
+}
+
+func createSettlementFx(sFxs []*settlementFx) []byte {
+	fx_sheet := fx.Sheets[0]
+	var index = 0
+	var count_commission float64 //合计佣金
+	var count_tax float64        //合计个税
+	for _, v := range sFxs {
+		index++
+		var row *xlsx.Row
+		if index < len(fx_sheet.Rows) {
+			row = fx_sheet.Rows[index]
+		} else {
+			row = fx_sheet.AddRow()
+		}
+		var cell *xlsx.Cell
+		//姓名
+		if len(row.Cells) > 0 {
+			cell = row.Cells[0]
+		} else {
+			cell = row.AddCell()
+		}
+		cell.SetValue(v.name)
+		//身份证号
+		if len(row.Cells) > 1 {
+			cell = row.Cells[1]
+		} else {
+			cell = row.AddCell()
+		}
+		cell.SetValue(v.idcard)
+		//佣金
+		if len(row.Cells) > 2 {
+			cell = row.Cells[2]
+		} else {
+			cell = row.AddCell()
+		}
+		cell.SetValue(fmt.Sprintf("%.2f", v.commission))
+		count_commission += v.commission
+		//个税
+		cell = row.AddCell()
+		if len(row.Cells) > 3 {
+			cell = row.Cells[3]
+		} else {
+			cell = row.AddCell()
+		}
+		cell.SetValue(fmt.Sprintf("%.2f", v.tax))
+		count_tax += v.tax
+	}
+	index += 3
+	fx_sheet.AddRow()
+	fx_sheet.AddRow()
+	fx_sheet.AddRow()
+	//小计上面空三行
+	//小计
+	index++
+	var row *xlsx.Row
+	if index < len(fx_sheet.Rows) {
+		row = fx_sheet.Rows[index]
+	} else {
+		row = fx_sheet.AddRow()
+	}
+	//姓名
+	if len(row.Cells) == 0 {
+		row.AddCell()
+	}
+	//身份证号
+	if len(row.Cells) == 1 {
+		row.AddCell()
+	}
+	var cell *xlsx.Cell
+	//合计佣金
+	if len(row.Cells) > 2 {
+		cell = row.Cells[2]
+	} else {
+		cell = row.AddCell()
+	}
+	cell.SetValue(fmt.Sprintf("小计:%.2f", count_commission))
+	//合计个税
+	cell = row.AddCell()
+	if len(row.Cells) > 3 {
+		cell = row.Cells[3]
+	} else {
+		cell = row.AddCell()
+	}
+	cell.SetValue(fmt.Sprintf("小计:%.2f", count_tax))
+	fpath := "./res/settlement/" + util.NowFormat("20060102150405") + ".xlsx"
+	//
+	w := &myWrite{
+		Byte: &bytes.Buffer{},
+	}
+	if err := fx.Write(w); err != nil {
+		log.Println(fpath, "获取结算列表xlsx文件的byte出错", err)
+	} else {
+		log.Println(fpath, "成功获取结算列表xlsx文件的byte", len(w.Byte.Bytes()))
+	}
+	//
+	if err := fx.Save(fpath); err != nil {
+		log.Println(fpath, "生成结算列表xlsx出错", err)
+	} else {
+		log.Println(fpath, "成功生成结算列表xlsx")
+	}
+	return w.Byte.Bytes()
+}
+
+//20号把已结算的佣金转入可提现金额
+func toCashOut() {
+	util.SimpleCrontab(false, TimetaskConf.ToCashout.Time, func() {
+		defer util.Catch()
+		now := time.Now()
+		if TimetaskConf.ToCashout.Day != now.Day() {
+			return
+		}
+		log.Println("开始执行转入可提现定时任务。。。")
+		stmtOut, err := Mysql.DB.Prepare(`select id,uid,count_cash from dis_count where count_status=0`)
+		if err != nil {
+			log.Println(err)
+			return
+		}
+		defer stmtOut.Close()
+		rows, err := stmtOut.Query()
+		if err != nil {
+			log.Println(err)
+			return
+		}
+		if rows != nil {
+			defer rows.Close()
+		}
+		for rows.Next() {
+			var id int64
+			var uid_uint8 []uint8 //用户id
+			var count_cash int64  //结算金额
+			err = rows.Scan(&id, &uid_uint8, &count_cash)
+			if err != nil {
+				log.Println(err)
+				break
+			}
+			uid := string(uid_uint8)
+			nowFormat := util.NowFormat(util.Date_Full_Layout)
+			if Mysql.ExecTx("转入可提现定时任务", func(tx *sql.Tx) bool {
+				ok_1 := int64(1)
+				if count_cash > 0 {
+					ok_1 = Mysql.UpdateOrDeleteBySqlByTx(tx, `update account set money=money+? where uid=?`, count_cash, uid)
+				}
+				ok_2 := Mysql.UpdateOrDeleteBySqlByTx(tx, `update dis_count set count_status=1,timestamp=? where id=?`, nowFormat, id)
+				return ok_1 > 0 && ok_2 > 0
+			}) {
+				log.Println("转入可提现成功", uid, "id", id, "结算金额", count_cash)
+			} else {
+				log.Println("转入可提现失败", uid, "id", id, "结算金额", count_cash)
+			}
+		}
+		log.Println("转入可提现定时任务执行完成。。。")
+	})
+}

+ 89 - 0
src/util/util.go

@@ -0,0 +1,89 @@
+package pay
+
+import (
+	"fmt"
+	"log"
+	qutil "qfw/util"
+	"qfw/util/mail"
+	. "service/config"
+	"sync"
+	"time"
+)
+
+var VarOrderCode *orderCode
+
+type orderCode struct {
+	pool chan string
+	all  *sync.Map
+	lock *sync.Mutex
+}
+
+func init() {
+	VarOrderCode = &orderCode{
+		pool: make(chan string, 20),
+		all:  &sync.Map{},
+		lock: &sync.Mutex{},
+	}
+	VarOrderCode.gc()
+	for i := 0; i < 10; i++ {
+		go func() {
+			for {
+				o := fmt.Sprintf("%d%s", time.Now().Unix(), qutil.GetRandom(2))
+				VarOrderCode.lock.Lock()
+				if _, ok := VarOrderCode.all.Load(o); ok {
+					VarOrderCode.lock.Unlock()
+					continue
+				}
+				VarOrderCode.all.Store(o, time.Now().Day())
+				VarOrderCode.lock.Unlock()
+				VarOrderCode.pool <- o
+			}
+		}()
+	}
+}
+func (o *orderCode) gc() {
+	VarOrderCode.all.Range(func(key, value interface{}) bool {
+		if time.Now().Day() != value.(int) {
+			VarOrderCode.all.Delete(key)
+		}
+		return true
+	})
+	time.AfterFunc(24*time.Hour, o.gc)
+}
+
+//创建订单号
+func (o *orderCode) Get() string {
+	return <-VarOrderCode.pool
+}
+
+//
+var VarBackup = &BackUp{}
+
+type BackUp struct{}
+
+func (b *BackUp) Save(tableName string, list *[]map[string]interface{}) {
+	if list == nil || len(*list) == 0 {
+		return
+	}
+	for _, v := range *list {
+		v["tablename"] = tableName
+		v["deletetime"] = time.Now().Unix()
+	}
+	MQFW.SaveBulk("dis_delete", (*list)...)
+}
+func SendRetryMail(retry int, from, user_mail, subject, content, fname string, bt []byte) bool {
+	for i := 1; i <= retry; i++ {
+		for _, v := range GmailAuth { //使用多个邮箱尝试发送
+			if mail.GSendMail_B(from, user_mail, "", "", subject, content, fname, bt, v) {
+				return true
+			}
+			t := time.Duration(i) * 30 * time.Second
+			log.Println(user_mail, fmt.Sprintf("第%d轮,使用%s发送邮件失败!%v后重试", i, v.User, t))
+			time.Sleep(t)
+		}
+		if i == retry {
+			log.Println(user_mail, fmt.Sprintf("发送邮件失败"))
+		}
+	}
+	return false
+}