Преглед изворни кода

add:添加研报模块, 添加微信配置

zqbao пре 10 месеци
родитељ
комит
ff06fffbda

+ 21 - 4
conf/app.conf

@@ -1,10 +1,27 @@
 appname = eta_mini_bridge
-httpport = 8080
+httpport = 8707
 runmode = dev
 autorender = false
 copyrequestbody = true
 EnableDocs = true
-sqlconn = 
 
-eta_mini_api_appid = "tubmafwrzhpgfiuf"
-eta_mini_api_secret = "eotpcqbvhycdshwscqnytiwzbgonposs"
+run_mode=debug
+
+[debug]
+mysql_url_rddp = hz_technology:hongze@2021@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/test_v2_hongze_rddp?charset=utf8mb4&loc=Asia%2FShanghai
+mysql_url_master = hz_technology:hongze@2021@tcp(rm-uf67kg347rhjfep5c1o.mysql.rds.aliyuncs.com:3306)/test_eta_mini_master?charset=utf8mb4&loc=Asia%2FShanghai
+; redis配置
+beego_cache = {"key":"redis","conn":"8.136.199.33:6379","password":"B6gVMFqzoM9JvyDU"}
+
+eta_mini_api_appid = "kmcitfwrzhpgfiuf"
+eta_mini_api_secret = "jotpcqbvhycdxhwscqnypiwzbgonqoss"
+
+; 微信相关配置
+wx_mini_appid = wx1c6d59a9ca4b42b3
+wx_mini_app_secret = 090716fa7b7fd89172cb26065fa4e6af
+
+dw_wx_id = gh_c76fc2dd625a
+dw_wx_appid = wx4dfe5a4c404e9f16
+dw_wx_app_secret = 090716fa7b7fd89172cb26065fa4e6af
+template_id_by_product = Cp2wF8gvBtxyWV4DeYuI172oqwyYXVRSm3AyJO42d84
+

+ 90 - 0
controllers/chart_permission.go

@@ -0,0 +1,90 @@
+package controllers
+
+import "eta/eta_mini_bridge/models"
+
+type ChartPermissionController struct {
+	BaseAuthController
+}
+
+// List
+// @Title 系统品种一级列表
+// @Description 系统品种一级列表
+// @Param   UserId   query   int  true       "角色ID"
+// @Success 200 {object} models.LoginResp
+// @router /list [get]
+func (this *ChartPermissionController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	items, err := models.GetChildChartPermissionListById(0)
+	if err != nil {
+		br.Msg = "权限列表获取失败"
+		br.ErrMsg = "权限列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Data = items
+	br.Msg = "列表获取成功"
+	br.Success = true
+}
+
+// SecondList
+// @Title 系统品种二级列表
+// @Description 系统品种二级列表
+// @Param   chartPermissonId   query   int  true       "品种ID"
+// @Success 200 {object} []models.ChartPermission
+// @router /second/list [get]
+func (this *ChartPermissionController) SecondList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	id, _ := this.GetInt("chartPermissonId", 0)
+	if id <= 0 {
+		br.Msg = "品种id错误,获取失败"
+		return
+	}
+
+	items, err := models.GetChildChartPermissionListById(id)
+	if err != nil {
+		br.Msg = "权限列表获取失败"
+		br.ErrMsg = "权限列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Data = items
+	br.Msg = "列表获取成功"
+	br.Success = true
+}
+
+// AllList
+// @Title 系统所有品种列表
+// @Description 系统所有品种列表
+// @Success 200 {object} []models.ChartPermission
+// @router /allList [get]
+func (this *ChartPermissionController) AllList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	items, err := models.GetChartPermissionList()
+	if err != nil {
+		br.Msg = "权限列表获取失败"
+		br.ErrMsg = "权限列表获取失败,系统错误,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Data = items
+	br.Msg = "列表获取成功"
+	br.Success = true
+}

+ 0 - 92
controllers/object.go

@@ -1,92 +0,0 @@
-package controllers
-
-import (
-	"eta/eta_mini_bridge/models"
-	"encoding/json"
-
-	beego "github.com/beego/beego/v2/server/web"
-)
-
-// Operations about object
-type ObjectController struct {
-	beego.Controller
-}
-
-// @Title Create
-// @Description create object
-// @Param	body		body 	models.Object	true		"The object content"
-// @Success 200 {string} models.Object.Id
-// @Failure 403 body is empty
-// @router / [post]
-func (o *ObjectController) Post() {
-	var ob models.Object
-	json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
-	objectid := models.AddOne(ob)
-	o.Data["json"] = map[string]string{"ObjectId": objectid}
-	o.ServeJSON()
-}
-
-// @Title Get
-// @Description find object by objectid
-// @Param	objectId		path 	string	true		"the objectid you want to get"
-// @Success 200 {object} models.Object
-// @Failure 403 :objectId is empty
-// @router /:objectId [get]
-func (o *ObjectController) Get() {
-	objectId := o.Ctx.Input.Param(":objectId")
-	if objectId != "" {
-		ob, err := models.GetOne(objectId)
-		if err != nil {
-			o.Data["json"] = err.Error()
-		} else {
-			o.Data["json"] = ob
-		}
-	}
-	o.ServeJSON()
-}
-
-// @Title GetAll
-// @Description get all objects
-// @Success 200 {object} models.Object
-// @Failure 403 :objectId is empty
-// @router / [get]
-func (o *ObjectController) GetAll() {
-	obs := models.GetAll()
-	o.Data["json"] = obs
-	o.ServeJSON()
-}
-
-// @Title Update
-// @Description update the object
-// @Param	objectId		path 	string	true		"The objectid you want to update"
-// @Param	body		body 	models.Object	true		"The body"
-// @Success 200 {object} models.Object
-// @Failure 403 :objectId is empty
-// @router /:objectId [put]
-func (o *ObjectController) Put() {
-	objectId := o.Ctx.Input.Param(":objectId")
-	var ob models.Object
-	json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
-
-	err := models.Update(objectId, ob.Score)
-	if err != nil {
-		o.Data["json"] = err.Error()
-	} else {
-		o.Data["json"] = "update success!"
-	}
-	o.ServeJSON()
-}
-
-// @Title Delete
-// @Description delete the object
-// @Param	objectId		path 	string	true		"The objectId you want to delete"
-// @Success 200 {string} delete success!
-// @Failure 403 objectId is empty
-// @router /:objectId [delete]
-func (o *ObjectController) Delete() {
-	objectId := o.Ctx.Input.Param(":objectId")
-	models.Delete(objectId)
-	o.Data["json"] = "delete success!"
-	o.ServeJSON()
-}
-

+ 144 - 8
controllers/report.go

@@ -4,6 +4,7 @@ import (
 	"eta/eta_mini_bridge/models"
 	"eta/eta_mini_bridge/models/response"
 	"eta/eta_mini_bridge/utils"
+	"html"
 
 	"github.com/rdlucklib/rdluck_tools/paging"
 )
@@ -12,7 +13,7 @@ type ReportController struct {
 	BaseAuthController
 }
 
-// @Title CreateUser
+// @Title List
 // @Description create users
 // @Param	body		body 	models.User	true		"body for user content"
 // @Success 200 {int} models.User.Id
@@ -25,13 +26,13 @@ func (this *ReportController) List() {
 		this.ServeJSON()
 	}()
 
-	userId, _ := this.GetInt("UserId")
 	pageSize, _ := this.GetInt("PageSize")
 	currentIndex, _ := this.GetInt("CurrentIndex")
-	classifyId, _ := this.GetInt("ClassifyId")
-	if classifyId <= 0 {
-		br.Msg = "参数错误"
-		br.ErrMsg = "参数错误,分类id小于等于0"
+	chartPermissionId, _ := this.GetInt("ChartPermissionId")
+	level, _ := this.GetInt("Level")
+
+	if chartPermissionId <= 0 {
+		br.Msg = "品种参数错误"
 		return
 	}
 
@@ -44,14 +45,149 @@ func (this *ReportController) List() {
 	}
 	startSize = utils.StartIndex(currentIndex, pageSize)
 
-	total, err := models.GetReportListCount(classifyId)
+	var total int
+	var reportList []*models.ReportList
+	switch level {
+	case 2:
+		classifyIds, err := models.GetClassifyIdsListById(chartPermissionId)
+		if err != nil {
+			br.Msg = "获取报告列表失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		tmptotal, err := models.GetReportCountByClassifyIds(classifyIds)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		total = tmptotal
+		tmpReportList, err := models.GetReportListByClassifyIds(classifyIds, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取报告列表失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		reportList = tmpReportList
+	case 1:
+		chartPermissionIds, err := models.GetChildChartPermissionIdsById(chartPermissionId)
+		if err != nil {
+			br.Msg = "获取报告列表失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		classifyIds, err := models.GetClassifyIdsListByIds(chartPermissionIds)
+		if err != nil {
+			br.Msg = "获取报告列表失败"
+			br.ErrMsg = "获取报告列表失败,Err:" + err.Error()
+			return
+		}
+		tmptotal, err := models.GetReportCountByClassifyIds(classifyIds)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		total = tmptotal
+		tmpReportList, err := models.GetReportListByClassifyIds(classifyIds, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取报告列表失败"
+			br.ErrMsg = "获取报告列表失败,Err:" + err.Error()
+			return
+		}
+		reportList = tmpReportList
+	default:
+		br.Msg = "层级参数错误"
+		return
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(response.ReportListResp)
+	resp.Paging = page
+	resp.List = reportList
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 日评详情
+// @Description 日评详情接口
+// @Param   ReportId   query   int  true       "报告id"
+// @Success 200 {object} models.ReportDetailResp
+// @router /detail [get]
+func (this *ReportController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	reportId, err := this.GetInt("ReportId")
+	if err != nil {
+		br.Msg = "参数获取失败"
+		br.ErrMsg = "参数获取失败,Err:" + err.Error()
+		return
+	}
+	if reportId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,报告id小于等于0"
+		return
+	}
+
+	report, err := models.GetReportById(reportId)
+	if err != nil {
+		br.Msg = "该报告已删除"
+		br.ErrMsg = "获取报告详情失败,Err:" + err.Error()
+		return
+	}
+
+	if report == nil {
+		br.Msg = "报告不存在"
+		return
+	}
+	report.ContentSub = html.UnescapeString(report.ContentSub)
+	report.Content = html.UnescapeString(report.Content)
+
+	br.Data = report
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// @Title List
+// @Description create users
+// @Param	body		body 	models.User	true		"body for user content"
+// @Success 200 {int} models.User.Id
+// @Failure 403 body is empty
+// @router /daily/list [get]
+func (this *ReportController) Today() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize30
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	total, err := models.GetReportDailyListCount()
 	if err != nil {
 		br.Msg = "获取数据失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
 		return
 	}
 
-	list, err := models.GetReportList(classifyId, startSize, pageSize)
+	list, err := models.GetReportDailyList(startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取失败,Err:" + err.Error()

+ 30 - 0
controllers/wechat.go

@@ -0,0 +1,30 @@
+package controllers
+
+import (
+	"encoding/json"
+	"eta/eta_mini_bridge/models"
+	"eta/eta_mini_bridge/models/request"
+)
+
+type WeChatController struct {
+	BaseAuthController
+}
+
+// @Title 发送微信模板接口
+// @Description 发送微信模板接口
+// @Param   Url   query   string  true       "url地址"
+// @Success 200 {object} models.WechatSign
+// @router /send_template_msg [post]
+func (this *WeChatController) SendTemplateMsg() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req request.SendWxTemplateReq
+	if err := json.Unmarshal(this.Ctx.Input.RequestBody, &req); err != nil {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数解析错误,Err:" + err.Error()
+		return
+	}
+}

+ 10 - 1
go.mod

@@ -7,13 +7,17 @@ require github.com/beego/beego/v2 v2.1.0
 require (
 	github.com/beego/bee/v2 v2.1.0
 	github.com/go-redis/redis/v8 v8.11.5
+	github.com/go-sql-driver/mysql v1.7.0
 	github.com/rdlucklib/rdluck_tools v1.0.3
+	github.com/silenceper/wechat/v2 v2.1.6
 )
 
 require (
 	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/fatih/structs v1.1.0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/kr/text v0.2.0 // indirect
@@ -25,7 +29,12 @@ require (
 	github.com/prometheus/common v0.42.0 // indirect
 	github.com/prometheus/procfs v0.9.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
-	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
+	github.com/sirupsen/logrus v1.9.0 // indirect
+	github.com/spf13/cast v1.4.1 // indirect
+	github.com/tidwall/gjson v1.14.1 // indirect
+	github.com/tidwall/match v1.1.1 // indirect
+	github.com/tidwall/pretty v1.2.0 // indirect
+	golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
 	golang.org/x/net v0.7.0 // indirect
 	golang.org/x/sys v0.6.0 // indirect
 	golang.org/x/text v0.7.0 // indirect

+ 85 - 0
models/chart_permission.go

@@ -0,0 +1,85 @@
+package models
+
+import (
+	"eta/eta_mini_bridge/utils"
+	"fmt"
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type ChartPermission struct {
+	ChartPermissionId     int       `orm:"column(chart_permission_id);pk" description:"问题ID" json:"chart_permission_id"`
+	ChartPermissionName   string    `description:"名称" json:"chart_permission_name"`
+	PermissionName        string    `description:"权限名" json:"permission_name"`
+	Sort                  int       `description:"排序" json:"sort"`
+	Enabled               int       `description:"是否可用" json:"enabled"`
+	CreatedTime           time.Time `description:"创建时间" json:"created_time"`
+	LastUpdatedTime       time.Time `description:"更新时间" json:"last_updated_time"`
+	TeleconferenceSort    int       `description:"电话会类型排序" json:"teleconference_sort"`
+	Remark                string    `description:"备注" json:"remark"`
+	ClassifyName          string    `description:"分类名称" json:"classify_name"`
+	ProductName           string    `description:"产品名称" json:"product_name"`
+	ProductId             int       `description:"产品ID" json:"product_id"`
+	ImageURL              string    `orm:"column(image_url);" description:"图片地址" json:"image_url"`
+	ShowType              int       `description:"1:查研观向小程序展示" json:"show_type"`
+	IsOther               int       `description:"是否是其他,用于查研观向小程序后台展示" json:"is_other"`
+	IsReport              int       `description:"是否是报告,用于查研观向小程序前台报告展示" json:"is_report"`
+	CygxAuth              int       `description:"是否是权限,用于查研观向小程序前台权限校验" json:"cygx_auth"`
+	PermissionType        int       `description:"1主观,2客观" json:"permission_type"`
+	YbImgUrl              string    `description:"研报小程序报告列表icon" json:"yb_img_url"`
+	ProductPermissionName string    `description:"种类权限名称" json:"product_permission_name"`
+	PriceDrivenState      int       `description:"品种价格驱动开启状态 0-关闭 1-开启" json:"price_driven_state"`
+	ImageUrlM             string    `description:"图片地址(查研观向移动端)" json:"image_url_m"`
+	ParentId              int       `description:"父级权限id" json:"parent_id"`
+	IsPublic              int       `description:"是否是公有权限1:公有权限,0私有权限" json:"is_public"`
+}
+
+// GetChildChartPermissionListById 获取品种权限列表
+func GetChartPermissionList() (items []*ChartPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM chart_permission WHERE enabled=1 ORDER BY sort ASC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// GetChildChartPermissionListById 获取品种权限列表
+func GetChildChartPermissionListById(chartPermissionId int) (items []*ChartPermission, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM chart_permission WHERE enabled=1 AND parent_id=? ORDER BY sort ASC`
+	_, err = o.Raw(sql, chartPermissionId).QueryRows(&items)
+	return
+}
+
+// GetChildChartPermissionListById 获取品种权限列表
+func GetChildChartPermissionIdsById(chartPermissionId int) (items []string, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT chart_permission_id FROM chart_permission WHERE enabled=1 AND parent_id=? ORDER BY sort ASC`
+	_, err = o.Raw(sql, chartPermissionId).QueryRows(&items)
+	return
+}
+
+// GetDefaultChartPermissionCount 获取默认的权限数目
+func GetDefaultChartPermissionCount(productId int) (count int, err error) {
+	sql := ` select count(1) COUNT from chart_permission where product_id=?`
+	o := orm.NewOrm()
+	err = o.Raw(sql, productId).QueryRow(&count)
+	return
+}
+
+func GetDefaultChartPermissionCountByCache(productId int) (maxPermissionCount int, err error) {
+	maxPermissionCountKey := fmt.Sprint(`hongze_api:max_permission_count:product_id:`, productId)
+	maxPermissionCount, err = utils.Rc.RedisInt(maxPermissionCountKey)
+	if err != nil || maxPermissionCount <= 0 {
+		maxPermissionCount, err = GetDefaultChartPermissionCount(productId)
+		if err != nil {
+			return
+		}
+		utils.Rc.SetNX(maxPermissionCountKey, maxPermissionCount, time.Second*3600)
+	}
+	//ficc需要移除策略的权限
+	if productId == 1 {
+		maxPermissionCount = maxPermissionCount - 1
+	}
+	return
+}

+ 29 - 0
models/chart_permission_search_key_word_mapping.go

@@ -0,0 +1,29 @@
+package models
+
+import (
+	"strings"
+
+	"github.com/beego/beego/v2/client/orm"
+)
+
+func GetClassifyIdsListById(chartPermissionId int) (classifyIds []string, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT classify_id
+		FROM chart_permission_search_key_word_mapping	
+		WHERE chart_permission_id = ? `
+	_, err = o.Raw(sql, chartPermissionId).QueryRows(&classifyIds)
+	return
+}
+
+func GetClassifyIdsListByIds(chartPermissionIds []string) (classifyIds []string, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT classify_id
+		FROM chart_permission_search_key_word_mapping	
+		WHERE chart_permission_id in (?) `
+	var idsStr string
+	if len(chartPermissionIds) > 0 {
+		idsStr = strings.Join(chartPermissionIds, ",")
+	}
+	_, err = o.Raw(sql, idsStr).QueryRows(&classifyIds)
+	return
+}

+ 3 - 1
models/classify.go

@@ -1,6 +1,8 @@
 package models
 
-import "time"
+import (
+	"time"
+)
 
 type ClassifyDetail struct {
 	ClassifyId     int       `description:"分类id"`

+ 36 - 0
models/db.go

@@ -0,0 +1,36 @@
+package models
+
+import (
+	"eta/eta_mini_bridge/utils"
+	"time"
+
+	"github.com/beego/beego/v2/client/orm"
+	_ "github.com/go-sql-driver/mysql"
+)
+
+func init() {
+	_ = orm.RegisterDataBase("rddp", "mysql", utils.MYSQL_URL_RDDP)
+	orm.SetMaxIdleConns("rddp", 50)
+	orm.SetMaxOpenConns("rddp", 100)
+
+	report_db, _ := orm.GetDB("rddp")
+	report_db.SetConnMaxLifetime(10 * time.Minute)
+
+	_ = orm.RegisterDataBase("master", "mysql", utils.MYSQL_URL_MASTER)
+	orm.SetMaxIdleConns("master", 50)
+	orm.SetMaxOpenConns("master", 100)
+
+	master_db, _ := orm.GetDB("master")
+	master_db.SetConnMaxLifetime(10 * time.Minute)
+
+	orm.Debug = true
+	orm.DebugLog = orm.NewLog(utils.BinLog)
+
+	// register model
+	orm.RegisterModel(
+		new(User),
+		new(UserRecord),
+		new(UserTemplateRecord),
+	)
+
+}

+ 0 - 53
models/object.go

@@ -1,53 +0,0 @@
-package models
-
-import (
-	"errors"
-	"strconv"
-	"time"
-)
-
-var (
-	Objects map[string]*Object
-)
-
-type Object struct {
-	ObjectId   string
-	Score      int64
-	PlayerName string
-}
-
-func init() {
-	Objects = make(map[string]*Object)
-	Objects["hjkhsbnmn123"] = &Object{"hjkhsbnmn123", 100, "astaxie"}
-	Objects["mjjkxsxsaa23"] = &Object{"mjjkxsxsaa23", 101, "someone"}
-}
-
-func AddOne(object Object) (ObjectId string) {
-	object.ObjectId = "astaxie" + strconv.FormatInt(time.Now().UnixNano(), 10)
-	Objects[object.ObjectId] = &object
-	return object.ObjectId
-}
-
-func GetOne(ObjectId string) (object *Object, err error) {
-	if v, ok := Objects[ObjectId]; ok {
-		return v, nil
-	}
-	return nil, errors.New("ObjectId Not Exist")
-}
-
-func GetAll() map[string]*Object {
-	return Objects
-}
-
-func Update(ObjectId string, Score int64) (err error) {
-	if v, ok := Objects[ObjectId]; ok {
-		v.Score = Score
-		return nil
-	}
-	return errors.New("ObjectId Not Exist")
-}
-
-func Delete(ObjectId string) {
-	delete(Objects, ObjectId)
-}
-

+ 123 - 6
models/report.go

@@ -1,6 +1,8 @@
 package models
 
 import (
+	"fmt"
+	"strings"
 	"time"
 
 	"github.com/beego/beego/v2/client/orm"
@@ -34,14 +36,89 @@ type ReportList struct {
 	ClassifyDetail
 }
 
-func GetReportListCount(classifyId int) (count int, err error) {
+func GetReportListCount(condition string, pars []interface{}) (count int, err error) {
 	o := orm.NewOrmUsingDB("rddp")
-	sql := ` SELECT COUNT(*) AS count FROM report WHERE 1=1 AND state=2 AND classify_id_second=? `
-	err = o.Raw(sql, classifyId).QueryRow(&count)
+	sql := ` SELECT COUNT(*) AS count FROM report WHERE 1=1 AND state=2 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars...).QueryRow(&count)
 	return
 }
 
-func GetReportList(classifyId, startSize, pageSize int) (items []*ReportList, err error) {
+// GetReportDailyListCount 获得今日报告数量
+func GetReportDailyListCount() (count int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT COUNT(*) AS count FROM report WHERE 1=1 AND state=2 AND DATE(modify_time)=DATE(NOW()) `
+	err = o.Raw(sql).QueryRow(&count)
+	return
+}
+
+func GetReportDailyList(startSize, pageSize int) (items []*ReportList, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := ` SELECT a.id,a.add_type,a.classify_id_first,a.classify_name_first,a.classify_id_second,a.classify_name_second,a.title,a.abstract,a.author,a.frequency,
+			a.create_time,a.modify_time,a.state,a.publish_time,a.stage,a.msg_is_send,b.id AS classify_id,b.classify_name,b.descript,b.report_author,b.author_descript,
+            b.report_img_url,b.head_img_url,b.avatar_img_url,b.column_img_url,a.video_url,a.video_name,a.video_play_seconds,a.video_size,
+            CASE WHEN DATE(a.modify_time)=DATE(NOW()) THEN 1 ELSE 0 END AS is_current_date
+            FROM report AS a
+			INNER JOIN  classify AS b ON a.classify_id_second=b.id
+			WHERE a.state=2 AND DATE(a.modify_time)=DATE(NOW()) 
+			ORDER BY  a.publish_time DESC LIMIT ?,?  `
+	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetReportListByIds(reportIds []string, startSize, pageSize int) (items []*ReportList, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT a.id,a.add_type,a.classify_id_first,a.classify_name_first,a.classify_id_second,a.classify_name_second,a.title,a.abstract,a.author,a.frequency,
+			a.create_time,a.modify_time,a.state,a.publish_time,a.stage,a.msg_is_send,b.id AS classify_id,b.classify_name,b.descript,b.report_author,b.author_descript,
+            b.report_img_url,b.head_img_url,b.avatar_img_url,b.column_img_url,a.video_url,a.video_name,a.video_play_seconds,a.video_size,
+            CASE WHEN DATE(a.modify_time)=DATE(NOW()) THEN 1 ELSE 0 END AS is_current_date
+            FROM report AS a
+			INNER JOIN  classify AS b ON a.classify_id_second=b.id
+			WHERE a.state=2 AND a.id IN (?) 
+			ORDER BY  a.publish_time DESC LIMIT ?,? `
+	var reportIdsStr string
+	if len(reportIds) > 0 {
+		reportIdsStr = strings.Join(reportIds, ",")
+	}
+	_, err = o.Raw(sql, reportIdsStr, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetReportCountByClassifyIds(classifyIds []string) (count int, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT  COUNT(*) AS count  FROM report
+			WHERE state=2 AND classify_id_second IN (%s) `
+	var reportIdsStr string
+	if len(classifyIds) > 0 {
+		reportIdsStr = strings.Join(classifyIds, ",")
+		sql = fmt.Sprintf(sql, reportIdsStr)
+	}
+	err = o.Raw(sql).QueryRow(&count)
+	return
+}
+
+func GetReportListByClassifyIds(classifyIds []string, startSize, pageSize int) (items []*ReportList, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT a.id,a.add_type,a.classify_id_first,a.classify_name_first,a.classify_id_second,a.classify_name_second,a.title,a.abstract,a.author,a.frequency,
+			a.create_time,a.modify_time,a.state,a.publish_time,a.stage,a.msg_is_send,b.id AS classify_id,b.classify_name,b.descript,b.report_author,b.author_descript,
+            b.report_img_url,b.head_img_url,b.avatar_img_url,b.column_img_url,a.video_url,a.video_name,a.video_play_seconds,a.video_size,
+            CASE WHEN DATE(a.modify_time)=DATE(NOW()) THEN 1 ELSE 0 END AS is_current_date
+            FROM report AS a
+			INNER JOIN  classify AS b ON a.classify_id_second=b.id
+			WHERE a.state=2 AND a.classify_id_second IN (%s) 
+			ORDER BY  a.publish_time DESC LIMIT ?,? `
+	var reportIdsStr string
+	if len(classifyIds) > 0 {
+		reportIdsStr = strings.Join(classifyIds, ",")
+		sql = fmt.Sprintf(sql, reportIdsStr)
+	}
+	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetReportList(condition string, pars []interface{}, startSize, pageSize int) (items []*ReportList, err error) {
 	o := orm.NewOrmUsingDB("rddp")
 	sql := ` SELECT a.id,a.add_type,a.classify_id_first,a.classify_name_first,a.classify_id_second,a.classify_name_second,a.title,a.abstract,a.author,a.frequency,
 			a.create_time,a.modify_time,a.state,a.publish_time,a.stage,a.msg_is_send,b.id AS classify_id,b.classify_name,b.descript,b.report_author,b.author_descript,
@@ -49,8 +126,12 @@ func GetReportList(classifyId, startSize, pageSize int) (items []*ReportList, er
             CASE WHEN DATE(a.modify_time)=DATE(NOW()) THEN 1 ELSE 0 END AS is_current_date
             FROM report AS a
 			INNER JOIN  classify AS b ON a.classify_id_second=b.id
-			WHERE a.state=2 AND a.classify_id_second=? ORDER BY  a.publish_time DESC LIMIT ?,? `
-	_, err = o.Raw(sql, classifyId, startSize, pageSize).QueryRows(&items)
+			WHERE a.state=2 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY  a.publish_time DESC LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
 	return
 }
 
@@ -68,3 +149,39 @@ func GetReportPermission(userId int, classifyNameSecond string) (count int, err
 	err = o.Raw(sql, userId, classifyNameSecond).QueryRow(&count)
 	return
 }
+
+type ReportDetail struct {
+	Id                 int    `description:"报告Id"`
+	AddType            int    `description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int    `description:"一级分类id"`
+	ClassifyNameFirst  string `description:"一级分类名称"`
+	ClassifyIdSecond   int    `description:"二级分类id"`
+	ClassifyNameSecond string `description:"二级分类名称"`
+	Title              string `description:"标题"`
+	Abstract           string `description:"摘要"`
+	Author             string `description:"作者"`
+	Frequency          string `description:"频度"`
+	CreateTime         string `description:"创建时间"`
+	ModifyTime         string `description:"修改时间"`
+	State              int    `description:"1:未发布,2:已发布"`
+	PublishTime        string `description:"发布时间"`
+	Stage              int    `description:"期数"`
+	MsgIsSend          int    `description:"消息是否已发送,0:否,1:是"`
+	Content            string `description:"内容"`
+	VideoUrl           string `description:"音频文件URL"`
+	VideoName          string `description:"音频文件名称"`
+	VideoPlaySeconds   string `description:"音频播放时长"`
+	VideoSize          string `description:"音频文件大小,单位M"`
+	ContentSub         string `description:"内容前两个章节"`
+	IsShowNewLabel     int    `description:"是否显示新标签"`
+	IsCurrentDate      int    `description:"是否当前日期"`
+	ClassifyName       string `description:"分类名称"`
+	TitleType          string `description:"标题类型,FICC或者权益"`
+}
+
+func GetReportById(reportId int) (item *ReportDetail, err error) {
+	o := orm.NewOrmUsingDB("rddp")
+	sql := `SELECT * FROM report WHERE id=?`
+	err = o.Raw(sql, reportId).QueryRow(&item)
+	return
+}

+ 5 - 0
models/request/wechat.go

@@ -0,0 +1,5 @@
+package request
+
+type SendWxTemplateReq struct {
+	ReportId int
+}

+ 5 - 0
models/response/report.go

@@ -10,3 +10,8 @@ type ReportListResp struct {
 	List   []*models.ReportList
 	Paging *paging.PagingItem
 }
+
+type ReportDetailResp struct {
+	Report   *models.ReportDetail   `description:"报告"`
+	Classify *models.ClassifyDetail `description:"对应专栏"`
+}

+ 10 - 0
models/user.go

@@ -66,6 +66,16 @@ func GetUserById(userId int) (item *User, err error) {
 	return
 }
 
+func GetUserList(condition string, pars []interface{}) (items []*User, err error) {
+	o := orm.NewOrmUsingDB("master")
+	sql := `SELECT * FROM user WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars...).QueryRows(&items)
+	return
+}
+
 func GetUserItemByPhone(phone string) (item *UserItem, err error) {
 	o := orm.NewOrmUsingDB("master")
 	sql := `SELECT * FROM user WHERE phone=? `

+ 16 - 0
models/user_chart_permission_mapping.go

@@ -0,0 +1,16 @@
+package models
+
+import "github.com/beego/beego/v2/client/orm"
+
+type UserChartPermissionMapping struct {
+	UserChartPermissionMappingId int `orm:"pk" description:"id"`
+	UserId                       int `description:"用户id"`
+	ChartPermissionId            int `description:"品种id"`
+}
+
+func GetChartPermissionIdByUserId(UserId int) (items []int, err error) {
+	o := orm.NewOrmUsingDB("master")
+	sql := `SELECT chart_permission_id FROM user_chart_permission_mapping WHERE user_id=?`
+	_, err = o.Raw(sql, UserId).QueryRows(&items)
+	return
+}

+ 21 - 0
models/user_template_record.go

@@ -0,0 +1,21 @@
+package models
+
+import "github.com/beego/beego/v2/client/orm"
+
+type UserTemplateRecord struct {
+	ID         int    `description:"id"`
+	UserID     int    `description:"用户id"`
+	OpenID     string `description:"用户openid"`
+	SendData   string `description:"发送内容"`
+	Result     string `description:"响应结果"`
+	CreateDate string `description:"创建日期"`
+	CreateTime string `description:"创建时间"`
+	SendStatus int    `description:"发送状态"`   // 1:发送成功,0:发送失败
+	SendType   int    `description:"发送消息类型"` // 1:报告模板消息
+}
+
+func (u *UserTemplateRecord) Insert() (err error) {
+	o := orm.NewOrmUsingDB("master")
+	_, err = o.Insert(u)
+	return
+}

+ 26 - 0
models/wx_token.go

@@ -0,0 +1,26 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type WxToken struct {
+	AccessToken string `description:"微信token"` //  微信token
+	ExpiresIn   int64  `description:"过期时间"`    // 过期时间
+	Id          int    `description:"id"`      // id
+}
+
+// Update 更新对应字段数据
+func (w *WxToken) Update(cols []string) (err error) {
+	o := orm.NewOrmUsingDB("master")
+	_, err = o.Update(w, cols...)
+	return
+}
+
+// GetById 根据id获取accessToken信息
+func GetWxTokenById() (info WxToken, err error) {
+	o := orm.NewOrmUsingDB("master")
+	sql := `SELECT * FROM wx_token WHERE id = ?`
+	err = o.Raw(sql, 0).QueryRow(&info)
+	return
+}

+ 73 - 0
routers/commentsRouter.go

@@ -0,0 +1,73 @@
+package routers
+
+import (
+	beego "github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/context/param"
+)
+
+func init() {
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "AllList",
+            Router: `/allList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ChartPermissionController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ChartPermissionController"],
+        beego.ControllerComments{
+            Method: "SecondList",
+            Router: `/second/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ReportController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "Today",
+            Router: `/daily/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ReportController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ReportController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:WeChatController"] = append(beego.GlobalControllerRouter["eta/eta_mini_bridge/controllers:WeChatController"],
+        beego.ControllerComments{
+            Method: "SendTemplateMsg",
+            Router: `/send_template_msg`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+}

+ 12 - 4
routers/router.go

@@ -11,18 +11,26 @@ import (
 	"eta/eta_mini_bridge/controllers"
 
 	"github.com/beego/beego/v2/server/web"
+	"github.com/beego/beego/v2/server/web/filter/cors"
 )
 
 func init() {
+	web.InsertFilter("*", web.BeforeRouter, cors.Allow(&cors.Options{
+		AllowAllOrigins:  true,
+		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
+		AllowHeaders:     []string{"Origin", "Authorization", "Uuid", "Accesstoken", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		ExposeHeaders:    []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		AllowCredentials: true,
+	}))
 	ns := web.NewNamespace("/v1",
-		web.NSNamespace("/object",
+		web.NSNamespace("/report",
 			web.NSInclude(
-				&controllers.ObjectController{},
+				&controllers.ReportController{},
 			),
 		),
-		web.NSNamespace("/user",
+		web.NSNamespace("/chart_permission",
 			web.NSInclude(
-				&controllers.UserController{},
+				&controllers.ChartPermissionController{},
 			),
 		),
 	)

+ 180 - 0
services/template_msg.go

@@ -0,0 +1,180 @@
+package services
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"eta/eta_mini_bridge/models"
+	"eta/eta_mini_bridge/utils"
+	"fmt"
+	"io"
+	"net/http"
+	"time"
+)
+
+var (
+	TemplateMsgSendUrl       = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s"
+	TemplateMsgClearQuotaUrl = "https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=%s"
+)
+
+type TemplateMsgSendClient struct {
+	AccessToken string
+	Data        []byte
+}
+
+type SendTemplateResponse struct {
+	Errcode int    `json:"errcode"`
+	Errmsg  string `json:"errmsg"`
+	MsgID   int    `json:"msgid"`
+}
+
+type ClearQuotaResponse struct {
+	Errcode int    `json:"errcode"`
+	Errmsg  string `json:"errmsg"`
+}
+
+type OpenIdList struct {
+	OpenId string
+	UserId int
+}
+
+// TemplateMsgSendClient.ClearQuota 清除发送超过当日10万次限制
+func (c *TemplateMsgSendClient) ClearQuota() (result *ClearQuotaResponse, err error) {
+	key := "CACHE_SendTemplateMsg_ERR"
+	exists := utils.Rc.IsExist(key)
+	if exists {
+		return
+	}
+	_ = utils.Rc.SetEX(key, 1, 6*time.Minute)
+
+	sendUrl := fmt.Sprintf(TemplateMsgClearQuotaUrl, c.AccessToken)
+	client := http.Client{}
+	clearData := make(map[string]interface{})
+	clearData["appid"] = utils.DW_WX_APPID
+	clearJson, _ := json.Marshal(clearData)
+	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(clearJson))
+	if err != nil {
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	clearBody, err := io.ReadAll(resp.Body)
+	err = json.Unmarshal(clearBody, &result)
+	return
+}
+
+// TemplateMsgSendClient.SendMsg 推送消息
+func (c *TemplateMsgSendClient) SendMsg() (sendRes *SendTemplateResponse, err error) {
+	// 请求接口
+	sendUrl := fmt.Sprintf(TemplateMsgSendUrl, c.AccessToken)
+	client := http.Client{}
+	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(c.Data))
+	if err != nil {
+		return
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	body, _ := io.ReadAll(resp.Body)
+	if err = json.Unmarshal(body, &sendRes); err != nil {
+		return
+	}
+	// 模板消息发送超过当日10万次限制错误处理
+	if sendRes.Errcode == 45009 {
+		// 发送提示邮件
+		// go alarm_msg.SendAlarmMsg("模板消息发送超过当日10万次限制, SendTemplateResponse: "+string(body), 3)
+		// 清理限制
+		clearRes, e := c.ClearQuota()
+		if e != nil {
+			err = e
+			return
+		}
+		if clearRes.Errcode != 0 {
+			clearJson, er := json.Marshal(clearRes)
+			if er != nil {
+				return nil, er
+			}
+			fmt.Println("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: " + string(clearJson))
+			// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: "+string(clearJson), 3)
+			return
+		}
+		// 发送成功邮件
+		// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用成功", 1)
+		// 重新推送
+		go func() {
+			_, e := c.SendMsg()
+			if e != nil {
+				return
+				// reSendJson, _ := json.Marshal(reSend)
+				// alarm_msg.SendAlarmMsg("重新推送模板消息失败, SendTemplateResponse: "+string(reSendJson), 3)
+			}
+		}()
+	}
+	if sendRes.Errcode != 0 {
+		err = errors.New("推送模板消息失败, SendTemplateResponse: " + string(body))
+	}
+	return
+}
+
+// AddUserTemplateRecord 新增模板消息推送记录
+func AddUserTemplateRecord(userId, sendStatus, sendType int, openid, sendData, result string) (err error) {
+	item := &models.UserTemplateRecord{
+		UserID:     userId,
+		OpenID:     openid,
+		SendData:   sendData,
+		Result:     result,
+		CreateDate: time.Now().Format(utils.FormatDate),
+		CreateTime: time.Now().Format(utils.FormatDateTime),
+		SendStatus: sendStatus,
+		SendType:   sendType,
+	}
+	err = item.Insert()
+	return
+}
+
+// SendMultiTemplateMsg 推送模板消息至多个用户
+func SendMultiTemplateMsg(sendMap map[string]interface{}, items []*OpenIdList, sendType int) (err error) {
+	ws := GetWxChat()
+	accessToken, err := ws.GetAccessToken()
+	if err != nil {
+		return
+	}
+	for _, item := range items {
+		sendMap["touser"] = item.OpenId
+		sendMap["template_id"] = utils.TEMPLATE_ID_BY_PRODUCT
+		sendMap["miniprogram"] = map[string]string{
+			"appid":    utils.WX_MINI_APPID,
+			"pagepath": "report?report_id",
+		}
+		data, e := json.Marshal(sendMap)
+		if e != nil {
+			err = e
+			return
+		}
+		ts := &TemplateMsgSendClient{
+			AccessToken: accessToken,
+			Data:        data,
+		}
+		result, e := ts.SendMsg()
+		if result == nil {
+			return
+		}
+		// 推送消息记录
+		{
+			go func(v *OpenIdList) {
+				sendStatus := 1
+				if e != nil {
+					sendStatus = 0
+				}
+				resultJson, _ := json.Marshal(result)
+				_ = AddUserTemplateRecord(v.UserId, sendStatus, sendType, v.OpenId, string(data), string(resultJson))
+			}(item)
+		}
+		if e != nil {
+			err = e
+			return
+		}
+	}
+	return
+}

+ 92 - 0
services/wechat.go

@@ -0,0 +1,92 @@
+package services
+
+import (
+	"eta/eta_mini_bridge/models"
+	"eta/eta_mini_bridge/utils"
+	"fmt"
+	"time"
+
+	"github.com/silenceper/wechat/v2"
+	"github.com/silenceper/wechat/v2/cache"
+	"github.com/silenceper/wechat/v2/credential"
+	"github.com/silenceper/wechat/v2/officialaccount"
+	"github.com/silenceper/wechat/v2/officialaccount/config"
+	"github.com/silenceper/wechat/v2/officialaccount/js"
+	"github.com/silenceper/wechat/v2/officialaccount/user"
+)
+
+var (
+	WxAppId     string
+	WxAppSecret string
+)
+
+type WechatAccessToken struct {
+}
+
+func GetWxChat() (officialAccount *officialaccount.OfficialAccount) {
+	wc := wechat.NewWechat()
+	memory := cache.NewMemory()
+	conf := &config.Config{
+		AppID:          utils.DW_WX_APPID,
+		AppSecret:      utils.DW_WX_APP_SECRET,
+		Token:          "",
+		EncodingAESKey: "",
+		Cache:          memory,
+	}
+	officialAccount = wc.GetOfficialAccount(conf)
+	wechatAccessToken := &WechatAccessToken{}
+	officialAccount.SetAccessTokenHandle(wechatAccessToken)
+	return
+}
+
+// GetAccessToken 获取accessToken
+func (wechat WechatAccessToken) GetAccessToken() (accessToken string, err error) {
+	wxToken, err := models.GetWxTokenById()
+	if err != nil {
+		return
+	}
+	//如果300s就要过期了,那么就去刷新accessToken
+	if wxToken.ExpiresIn < time.Now().Unix()+300 {
+		tmpAccessToken, expires, tmpErr := getTokenFromServer(WxAppId, WxAppSecret)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		var updateCols = []string{"access_token", "expires_in"}
+		wxToken.AccessToken = tmpAccessToken
+		wxToken.ExpiresIn = expires - 600 //快过期前10分钟就刷新掉
+		wxToken.Update(updateCols)
+	}
+	accessToken = wxToken.AccessToken
+	return
+}
+
+// getTokenFromServer 服务端获取accessToken
+func getTokenFromServer(appid, wxSecret string) (accessToken string, expires int64, err error) {
+	apiUrl := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
+	resAccessToken, err := credential.GetTokenFromServer(fmt.Sprintf(apiUrl, appid, wxSecret))
+	if err != nil {
+		return
+	}
+
+	expires = resAccessToken.ExpiresIn
+	accessToken = resAccessToken.AccessToken
+	return
+}
+
+// GetUserInfo 获取微信用户详情
+func GetUserInfo(openid string) (userInfo *user.Info, err error) {
+	wechatClient := GetWxChat()
+	userClient := wechatClient.GetUser()
+	userInfo, err = userClient.GetUserInfo(openid)
+	return
+}
+
+// GetJsConfig 获取公众号jsConfig
+func GetJsConfig(signUrl string) (jsConf *js.Config, err error) {
+	wechatClient := GetWxChat()
+	j := wechatClient.GetJs()
+	jsConf, err = j.GetConfig(signUrl)
+	return
+}

+ 18 - 0
utils/config.go

@@ -33,6 +33,16 @@ var (
 	ETA_MINI_API_SECRET string
 )
 
+// 微信相关
+var (
+	WX_MINI_APPID          string
+	WX_MINI_APP_SECRET     string
+	DW_WX_Id               string //微信原始ID
+	DW_WX_APPID            string
+	DW_WX_APP_SECRET       string
+	TEMPLATE_ID_BY_PRODUCT string
+)
+
 func init() {
 	tmpRunMode, err := web.AppConfig.String("run_mode")
 	if err != nil {
@@ -53,6 +63,14 @@ func init() {
 	MYSQL_URL_RDDP = config["mysql_url_rddp"]
 	MYSQL_URL_MASTER = config["mysql_url_master"]
 
+	// 微信配置
+	WX_MINI_APPID = config["wx_mini_appid"]
+	WX_MINI_APP_SECRET = config["wx_mini_app_secret"]
+	DW_WX_Id = config["dw_wx_id"]
+	DW_WX_APPID = config["dw_wx_appid"]
+	DW_WX_APP_SECRET = config["dw_wx_app_secret"]
+	TEMPLATE_ID_BY_PRODUCT = config["template_id_by_product"]
+
 	// redis缓存配置
 	REDIS_CACHE = config["beego_cache"]
 	if len(REDIS_CACHE) <= 0 {

+ 1 - 0
utils/redis.go

@@ -12,6 +12,7 @@ type RedisClient interface {
 	RedisInt(key string) (data int, err error)
 	Put(key string, val interface{}, timeout time.Duration) error
 	SetNX(key string, val interface{}, timeout time.Duration) bool
+	SetEX(key string, val interface{}, timeout time.Duration) bool
 	Delete(key string) error
 	IsExist(key string) bool
 	LPush(key string, val interface{}) error

+ 18 - 0
utils/redis/cluster_redis.go

@@ -155,6 +155,24 @@ func (rc *ClusterRedisClient) SetNX(key string, val interface{}, timeout time.Du
 	return result
 }
 
+// SetEX
+// @Description: 设置一个会过期时间的值
+// @receiver rc
+// @param key
+// @param val
+// @param timeout
+// @return bool
+func (rc *ClusterRedisClient) SetEX(key string, val interface{}, timeout time.Duration) (ok bool) {
+	result, err := rc.redisClient.SetEX(context.TODO(), key, val, timeout).Result()
+	if err != nil {
+		return false
+	}
+	if result == "OK" {
+		ok = true
+	}
+	return
+}
+
 // Delete
 // @Description: 删除redis中的键值对
 // @receiver rc

+ 20 - 1
utils/redis/standalone_redis.go

@@ -5,9 +5,10 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/go-redis/redis/v8"
 	"strconv"
 	"time"
+
+	"github.com/go-redis/redis/v8"
 )
 
 // StandaloneRedisClient
@@ -149,6 +150,24 @@ func (rc *StandaloneRedisClient) SetNX(key string, val interface{}, timeout time
 	return result
 }
 
+// SetEX
+// @Description: 设置一个会过期时间的值
+// @receiver rc
+// @param key
+// @param val
+// @param timeout
+// @return bool
+func (rc *StandaloneRedisClient) SetEX(key string, val interface{}, timeout time.Duration) (ok bool) {
+	result, err := rc.redisClient.SetEX(context.TODO(), key, val, timeout).Result()
+	if err != nil {
+		return false
+	}
+	if result == "OK" {
+		ok = true
+	}
+	return
+}
+
 // Delete
 // @Description: 删除redis中的键值对
 // @receiver rc