Browse Source

Merge branch 'master' into yb/3.3

hsun 2 years ago
parent
commit
8ddadf4470

+ 2 - 1
.gitignore

@@ -6,4 +6,5 @@ latest_log
 go.sum
 /binlog
 latest_binlog
-hongze_yb
+hongze_yb
+/rdlucklog

+ 9 - 2
controller/chart/chart_info.go

@@ -12,7 +12,7 @@ import (
 	"hongze/hongze_yb/models/tables/chart_info_log"
 	edbDataModel "hongze/hongze_yb/models/tables/edb_data"
 	edbInfoModel "hongze/hongze_yb/models/tables/edb_info"
-	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/alarm_msg"
 	"hongze/hongze_yb/services/chart"
 	edbDataService "hongze/hongze_yb/services/edb_data"
 	"hongze/hongze_yb/services/user"
@@ -163,6 +163,7 @@ func GetChartInfoDetail(c *gin.Context)  {
 	}
 
 	// 指标列表
+	sourceArr := make([]string, 0)
 	edbList := make([]*chartEdbMappingModel.ChartEdbInfoMappingList, 0)
 	for _, v := range mappingList {
 		item := new(chartEdbMappingModel.ChartEdbInfoMappingList)
@@ -176,6 +177,9 @@ func GetChartInfoDetail(c *gin.Context)  {
 		item.StartDate = v.StartDate
 		item.EndDate = v.EndDate
 		item.ModifyTime = v.ModifyTime
+		if !utils.InArray(v.SourceName, sourceArr) {
+			sourceArr = append(sourceArr, v.SourceName)
+		}
 		if chartInfoId <= 0 {
 			item.IsAxis = 1
 			item.LeadValue = 0
@@ -330,6 +334,8 @@ func GetChartInfoDetail(c *gin.Context)  {
 		}
 		edbList = append(edbList, item)
 	}
+	sourceArr = append(sourceArr, "弘则研究")
+	chartInfo.ChartSource = strings.Join(sourceArr, ",")
 
 	// 访问记录-仅普通用户记录
 	userInfo := user.GetInfoByClaims(c)
@@ -408,7 +414,8 @@ func RefreshChartInfo(c *gin.Context)  {
 	if err = chart.RefreshChart(chartInfo.ChartInfoId); err != nil {
 		errContent := fmt.Sprint("ErrMsg: 刷新图表关联指标信息失败, " + err.Error())
 		if global.CONFIG.Serve.RunMode == "release" {
-			go services.SendEmail("弘则研报小程序-release-刷新图表报错", errContent, utils.EmailSendToUsers)
+			go alarm_msg.SendAlarmMsg("刷新图表报错"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+errContent, 3)
+			//go services.SendEmail("弘则研报小程序-release-刷新图表报错", errContent, utils.EmailSendToUsers)
 		} else {
 			global.LOG.Info(errContent)
 		}

+ 57 - 0
controller/public.go

@@ -6,6 +6,7 @@ import (
 	"hongze/hongze_yb/controller/response"
 	"hongze/hongze_yb/global"
 	"hongze/hongze_yb/logic"
+	"hongze/hongze_yb/models/tables/yb_suncode_pars"
 	"hongze/hongze_yb/services"
 	"hongze/hongze_yb/utils"
 	"os"
@@ -83,3 +84,59 @@ func Upload(c *gin.Context) {
 	response.OkData("文件上传成功", resourceUrl, c)
 
 }
+
+// GetSharePoster
+// @Tags 公共模块
+// @Summary  获取分享海报
+// @Description 获取分享海报
+// @Security ApiKeyAuth
+// @securityDefinitions.basic BasicAuth
+// @Param	request	body services.SharePosterReq true "type json string"
+// @Accept  application/json
+// @Success 200 {object} string "获取成功"
+// @failure 400 {string} string "获取失败"
+// @Router /public/get_share_poster [post]
+func GetSharePoster(c *gin.Context) {
+	var req services.SharePosterReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	if req.Source == "" {
+		response.Fail("来源有误", c)
+		return
+	}
+	imgUrl, err := services.CreatePosterFromSource(req.CodePage, req.CodeScene, req.Source, req.Version, req.Pars)
+	if err != nil {
+		response.FailData("获取分享海报失败", "获取分享海报失败, Err: "+err.Error(), c)
+		return
+	}
+	response.OkData("获取成功", imgUrl, c)
+}
+
+// GetSuncodeScene 获取小程序太阳码scene值
+// @Tags 公共模块
+// @Summary  获取小程序太阳码scene值
+// @Description 获取小程序太阳码scene值
+// @Security ApiKeyAuth
+// @Param Authorization	header string true "Bearer 31a165baebe6dec616b1f8f3207b4273"
+// @Param scene_key query string true "scene_key值"
+// @Success 200 {string} string "获取成功"
+// @failure 400 {string} string "获取失败"
+// @Router /public/get_suncode_scene [get]
+func GetSuncodeScene(c *gin.Context) {
+	reqKey := c.DefaultQuery("scene_key", "")
+	if reqKey == "" {
+		response.Fail("参数有误", c)
+	}
+	pars, err := yb_suncode_pars.GetSceneByKey(reqKey)
+	if err != nil && err != utils.ErrNoRow {
+		response.FailMsg("获取失败", "GetSuncodeScene获取失败, Err: " + err.Error(), c)
+		return
+	}
+	scene := ""
+	if pars != nil {
+		scene = pars.Scene
+	}
+	response.OkData("获取成功", scene, c)
+}

+ 3 - 3
go.mod

@@ -3,6 +3,7 @@ module hongze/hongze_yb
 go 1.15
 
 require (
+	github.com/PuerkitoBio/goquery v1.8.0
 	github.com/aliyun/aliyun-oss-go-sdk v1.9.8
 	github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
 	github.com/fsnotify/fsnotify v1.5.1
@@ -15,12 +16,12 @@ require (
 	github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
 	github.com/lestrrat-go/strftime v1.0.5 // indirect
 	github.com/mattn/go-isatty v0.0.14 // indirect
-	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/nosixtools/solarlunar v0.0.0-20211112060703-1b6dea7b4a19
 	github.com/olivere/elastic/v7 v7.0.31
 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
+	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/satori/go.uuid v1.2.0 // indirect
-	github.com/silenceper/wechat/v2 v2.0.9
+	github.com/silenceper/wechat/v2 v2.1.2
 	github.com/spf13/viper v1.9.0
 	github.com/swaggo/gin-swagger v1.3.3
 	github.com/swaggo/swag v1.7.4
@@ -28,7 +29,6 @@ require (
 	golang.org/x/image v0.0.0-20190802002840-cff245a6509b
 	golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 // indirect
 	golang.org/x/text v0.3.7 // indirect
-	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 	gorm.io/driver/mysql v1.1.3
 	gorm.io/gorm v1.22.2

+ 3 - 0
init_serve/router.go

@@ -8,6 +8,7 @@ import (
 	"hongze/hongze_yb/global"
 	"hongze/hongze_yb/middleware"
 	"hongze/hongze_yb/routers"
+	"net/http"
 )
 
 // InitRouter 初始化路由
@@ -49,5 +50,7 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitPurchase(r)
 	// 研报相关路由
 	routers.InitReport(r)
+	// 设置静态文件夹件路径
+	r.StaticFS("/static", http.Dir("./static"))
 	return
 }

+ 3 - 2
middleware/recover.go

@@ -5,7 +5,7 @@ import (
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
 	"hongze/hongze_yb/global"
-	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/alarm_msg"
 	"hongze/hongze_yb/utils"
 	"net/http"
 	"runtime"
@@ -49,7 +49,8 @@ func Recover() gin.HandlerFunc {
 				fmt.Println("stack:", stack)
 				response.Custom(http.StatusInternalServerError, "系统异常", c)
 				//c.JSON(http.StatusInternalServerError, Err)
-				go services.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+				//go services.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+				go alarm_msg.SendAlarmMsg(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05")+";Err:"+stack, 3)
 				return
 			}
 		}()

+ 12 - 11
models/tables/chart_info/query.go

@@ -34,6 +34,7 @@ type ChartInfoView struct {
 	LeftMax           string `description:"图表左侧最大值"`
 	RightMin          string `description:"图表右侧最小值"`
 	RightMax          string `description:"图表右侧最大值"`
+	ChartSource       string `description:"图表来源str"`
 	//ChartClassify     []*chart_classify.ChartClassifyView
 }
 
@@ -67,23 +68,23 @@ type ChartSaveItem struct {
 }
 
 type ChartSortInfo struct {
-	ChartInfoId			int		`description:"图表ID"`
-	MyChartId			int		`description:"我的图表ID"`
-	MyChartClassifyId	int		`description:"我的图表分类ID"`
-	MyChartClassifyName	string	`description:"我的图表分类名称"`
-	UniqueCode			string	`description:"图表唯一编码"`
-	Sort				int		`description:"排序"`
-	Switch				int		`description:"是否切换 0-未切换 1-已切换"`
+	ChartInfoId         int    `description:"图表ID"`
+	MyChartId           int    `description:"我的图表ID"`
+	MyChartClassifyId   int    `description:"我的图表分类ID"`
+	MyChartClassifyName string `description:"我的图表分类名称"`
+	UniqueCode          string `description:"图表唯一编码"`
+	Sort                int    `description:"排序"`
+	Switch              int    `description:"是否切换 0-未切换 1-已切换"`
 	//SwitchTips			string	`description:"切换分类提示信息"`
 }
 
 type ChartBeforeNext struct {
-	PrevChart	ChartSortInfo
-	NextChart	ChartSortInfo
+	PrevChart ChartSortInfo
+	NextChart ChartSortInfo
 }
 
 type RefreshChartInfoReq struct {
-	ChartInfoId	int
+	ChartInfoId int
 }
 
 // GetChartInfoViewById 通过Id获取图表展示信息
@@ -98,4 +99,4 @@ func GetChartInfoViewById(chartInfoId int) (item *ChartInfoView, err error) {
 func GetChartInfoById(chartInfoId int) (item *ChartInfo, err error) {
 	err = global.MYSQL["data"].Model(ChartInfo{}).Where("chart_info_id = ?", chartInfoId).First(&item).Error
 	return
-}
+}

+ 18 - 0
models/tables/yb_poster_resource/query.go

@@ -0,0 +1,18 @@
+package yb_poster_resource
+
+import (
+	"hongze/hongze_yb/global"
+)
+
+func (item *YbPosterResource) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(item).Error
+	return
+}
+
+// GetPosterByCondition 获取海报
+func GetPosterByCondition(path, resourceType, version string) (item *YbPosterResource, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbPosterResource{}).
+		Where("path = ? AND type = ? AND version = ?", path, resourceType, version).
+		First(&item).Error
+	return
+}

+ 37 - 0
models/tables/yb_poster_resource/yb_poster_resource.go

@@ -0,0 +1,37 @@
+package yb_poster_resource
+
+import (
+	"time"
+)
+
+// YbPosterResource 海报图片表
+type YbPosterResource struct {
+	ID         uint32    `gorm:"primaryKey;column:id;type:int(10) unsigned;not null" json:"-"`
+	Path       string    `gorm:"column:path;type:varchar(255);not null;default:''" json:"path"`                // 请求路径
+	ImgURL     string    `gorm:"column:img_url;type:varchar(255);not null;default:''" json:"imgUrl"`           // 图片地址
+	Type       string    `gorm:"column:type;type:varchar(20);not null;default:''" json:"type"`                 // 类型 poster-海报; qrcode-太阳码
+	Version    string    `gorm:"column:version;type:varchar(20);not null;default:''" json:"version"`           // 版本号
+	CreateTime time.Time `gorm:"column:create_time;type:datetime;default:CURRENT_TIMESTAMP" json:"createTime"` // 创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbPosterResource) TableName() string {
+	return "yb_poster_resource"
+}
+
+// YbPosterResourceColumns get sql column name.获取数据库列名
+var YbPosterResourceColumns = struct {
+	ID         string
+	Path       string
+	ImgURL     string
+	Type       string
+	Version    string
+	CreateTime string
+}{
+	ID:         "id",
+	Path:       "path",
+	ImgURL:     "img_url",
+	Type:       "type",
+	Version:    "version",
+	CreateTime: "create_time",
+}

+ 18 - 0
models/tables/yb_suncode_pars/query.go

@@ -0,0 +1,18 @@
+package yb_suncode_pars
+
+import (
+	"hongze/hongze_yb/global"
+)
+
+func (item *YbSuncodePars) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(item).Error
+	return
+}
+
+// GetSceneByKey 获取太阳码参数
+func GetSceneByKey(key string) (item *YbSuncodePars, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbSuncodePars{}).
+		Where("scene_key = ?", key).
+		First(&item).Error
+	return
+}

+ 31 - 0
models/tables/yb_suncode_pars/yb_suncode_pars.go

@@ -0,0 +1,31 @@
+package yb_suncode_pars
+
+import (
+	"time"
+)
+
+// YbSuncodePars 小程序太阳码scene参数
+type YbSuncodePars struct {
+	ID         uint32    `gorm:"primaryKey;column:id;type:int(10) unsigned;not null" json:"-"`
+	Scene      string    `gorm:"column:scene;type:varchar(255);not null;default:''" json:"scene"`        // scene参数
+	SceneKey   string    `gorm:"column:scene_key;type:varchar(32);not null;default:''" json:"scene_key"` // MD5值
+	CreateTime time.Time `gorm:"column:create_time;type:datetime;default:CURRENT_TIMESTAMP" json:"createTime"`
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbSuncodePars) TableName() string {
+	return "yb_suncode_pars"
+}
+
+// YbSuncodeParsColumns get sql column name.获取数据库列名
+var YbSuncodeParsColumns = struct {
+	ID         string
+	SceneKey   string
+	Key        string
+	CreateTime string
+}{
+	ID:         "id",
+	SceneKey:   "scene_key",
+	Key:        "key",
+	CreateTime: "create_time",
+}

+ 2 - 0
routers/public.go

@@ -23,5 +23,7 @@ func initPublic(r *gin.Engine) {
 	{
 		rGroup.GET("/get_apply_variety_list", controller.GetApplyVarietyList)
 		rGroup.POST("/upload", controller.Upload)
+		rGroup.POST("/get_share_poster", controller.GetSharePoster)
+		rGroup.GET("/get_suncode_scene", controller.GetSuncodeScene)
 	}
 }

+ 30 - 0
services/alarm_msg/alarm_msg.go

@@ -0,0 +1,30 @@
+package alarm_msg
+
+import (
+	"encoding/json"
+	"github.com/rdlucklib/rdluck_tools/http"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/utils"
+)
+
+var (
+	AlarmMsgUrl = "http://127.0.0.1:8606/api/alarm/send"
+)
+
+//projectName-项目名称
+//runMode-运行模式
+//msgBody-消息内容
+//level:消息基本,1:提示消息,2:警告消息,3:严重错误信息,默认为1 提示消息
+func SendAlarmMsg(msgBody string, level int) {
+	params := make(map[string]interface{})
+	params["ProjectName"] = utils.APPNAME
+	params["RunMode"] = global.CONFIG.Serve.RunMode
+	params["MsgBody"] = msgBody
+	params["Level"] = level
+	param, err := json.Marshal(params)
+	if err != nil {
+		global.LOG.Critical("SendAlarmMsg json.Marshal Err:" + err.Error())
+		return
+	}
+	http.Post(AlarmMsgUrl, string(param))
+}

+ 3 - 2
services/chart/chart_info.go

@@ -12,7 +12,7 @@ import (
 	"hongze/hongze_yb/models/tables/my_chart_classify"
 	"hongze/hongze_yb/models/tables/yb_chart_daily_visit_log"
 	"hongze/hongze_yb/models/tables/yb_chart_visit_log"
-	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/alarm_msg"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
 	"sort"
@@ -276,7 +276,8 @@ func RefreshChart(chartInfoId int) (err error) {
 	defer func() {
 		if err != nil {
 			if global.CONFIG.Serve.RunMode == "release" {
-				go services.SendEmail(utils.APPNAME+"【"+global.CONFIG.Serve.RunMode+"】"+"失败提醒", "RefreshChart:"+errMsg, utils.EmailSendToUsers)
+				//go services.SendEmail(utils.APPNAME+"【"+global.CONFIG.Serve.RunMode+"】"+"失败提醒", "RefreshChart:"+errMsg, utils.EmailSendToUsers)
+				go alarm_msg.SendAlarmMsg("RefreshChart Err:"+errMsg, 3)
 			}
 			fmt.Println("RefreshChart Err:" + errMsg)
 		}

+ 33 - 0
services/oss.go

@@ -88,3 +88,36 @@ func UploadVideoAliyun(filename, filepath, savePath string) error {
 	//return path,err
 	return err
 }
+
+
+var (
+	Bucketname       string = "hzchart"
+	Endpoint         string = "oss-cn-shanghai.aliyuncs.com"
+	Imghost          string = "https://hzstatic.hzinsights.com/"
+	UploadDir		 string = "static/images/"
+	AccessKeyId      string = "LTAIFMZYQhS2BTvW"
+	AccessKeySecret  string = "12kk1ptCHoGWedhBnKRVW5hRJzq9Fq"
+)
+
+// UploadAliyunToDir
+func UploadAliyunToDir(filename, filepath, fileDir string) (string, error) {
+	client, err := oss.New(Endpoint, AccessKeyId, AccessKeySecret)
+	if err != nil {
+		return "1", err
+	}
+	bucket, err := client.Bucket(Bucketname)
+	if err != nil {
+		return "2", err
+	}
+	if fileDir == "" {
+		fileDir = time.Now().Format("200601/20060102/")
+	}
+	path := UploadDir + fileDir
+	path += filename
+	err = bucket.PutObjectFromFile(path, filepath)
+	if err != nil {
+		return "3", err
+	}
+	path = Imghost + path
+	return path, err
+}

+ 2 - 1
services/report/report.go

@@ -779,7 +779,8 @@ func GetReportList(user user.UserInfo, keyWord string, classifyIdFirst, classify
 		for _, reportInfo := range list {
 			reportItem := new(response.ReportListItem)
 			reportItem.ReportId = reportInfo.Id
-			reportItem.Title = reportInfo.Title
+			// 样式限制行数
+			reportItem.Title = "<div style=\"-webkit-line-clamp: 2;-webkit-box-orient: vertical;display: -webkit-box;overflow: hidden;text-overflow: ellipsis;\">" + reportInfo.Title + "</div>"
 			reportItem.PublishTime = reportInfo.PublishTime
 			reportItem.ClassifyNameFirst = reportInfo.ClassifyNameFirst
 			reportItem.ClassifyNameSecond = reportInfo.ClassifyNameSecond

+ 460 - 0
services/share_poster.go

@@ -0,0 +1,460 @@
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/PuerkitoBio/goquery"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/tables/yb_poster_resource"
+	"hongze/hongze_yb/models/tables/yb_suncode_pars"
+	"hongze/hongze_yb/services/alarm_msg"
+	"hongze/hongze_yb/services/wx_app"
+	"hongze/hongze_yb/utils"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"strings"
+	"time"
+)
+
+var ServerUrl = "http://127.0.0.1:5008/"
+
+// SharePosterReq 分享海报请求体
+type SharePosterReq struct {
+	CodePage  string `json:"code_page" description:"太阳码page"`
+	CodeScene string `json:"code_scene" description:"太阳码scene"`
+	Source    string `json:"source" description:"来源"`
+	Version   string `json:"version" description:"海报版本号" `
+	Pars      string `json:"pars" description:"海报动态信息"`
+}
+
+// CreatePosterFromSource 生成分享海报
+func CreatePosterFromSource(codePage, codeScene, source, version, pars string) (imgUrl string, err error) {
+	var errMsg string
+	defer func() {
+		if err != nil {
+			global.LOG.Critical(fmt.Sprintf("CreatePosterFromSource: source=%s, pars:%s, errMsg:%s", source, pars, errMsg))
+			go alarm_msg.SendAlarmMsg("CreatePosterFromSource生成分享海报失败, Msg:"+errMsg+";Err:"+err.Error(), 2)
+		}
+	}()
+	if codePage == "" || source == "" || pars == "" {
+		errMsg = "参数有误"
+		err = errors.New(errMsg)
+		return
+	}
+	path := fmt.Sprint(codePage, "?", codeScene)
+	// 非列表来源获取历史图片,无则生成
+	if !strings.Contains(source, "list") {
+		poster, tmpErr := yb_poster_resource.GetPosterByCondition(path, "poster", version)
+		if tmpErr != nil && tmpErr != utils.ErrNoRow {
+			err = tmpErr
+			return
+		}
+		if poster != nil && poster.ImgURL != "" {
+			imgUrl = poster.ImgURL
+			return
+		}
+	}
+	// 图片长宽
+	heightMap := map[string]int{
+		"activity_detail":       1210,
+		"activity_list":         1948,
+		"special_column_detail": 1480,
+		"special_column_list":   1548,
+		"chart_detail":          1536,
+		"chart_list":            1352,
+		"report_detail":         1420,
+		"report_list":           1344,
+	}
+	widthMap := map[string]int{
+		"activity_detail":       1280,
+		"activity_list":         1280,
+		"special_column_detail": 1176,
+		"special_column_list":   1176,
+		"chart_detail":          1176,
+		"chart_list":            1176,
+		"report_detail":         1176,
+		"report_list":           1176,
+	}
+	width := widthMap[source]
+	height := heightMap[source]
+	if width == 0 || height == 0 {
+		errMsg = "图片长度有误"
+		err = errors.New(errMsg)
+		return "", err
+	}
+	// 生成太阳码
+	sunCodeUrl, err := CreateAndUploadSunCode(codePage, codeScene, version)
+	if err != nil {
+		return
+	}
+	// 填充html内容
+	contentStr, newHeight, err := fillContent2Html(source, pars, sunCodeUrl, height)
+	if err != nil {
+		errMsg = "html内容有误"
+		return
+	}
+	// 请求python服务htm2img
+	htm2ImgReq := make(map[string]interface{})
+	htm2ImgReq["html_content"] = contentStr
+	htm2ImgReq["width"] = width
+	htm2ImgReq["height"] = newHeight
+	res, err := postHtml2Img(htm2ImgReq)
+	if err != nil || res == nil {
+		errMsg = "html转图片请求失败"
+		return
+	}
+	if res.Code != 200 {
+		errMsg = "html转图片请求失败"
+		err = errors.New("html转图片失败: " + res.Msg)
+		return
+	}
+	imgUrl = res.Data
+	// 记录海报信息
+	newPoster := &yb_poster_resource.YbPosterResource{
+		Path:       path,
+		ImgURL:     imgUrl,
+		Type:       "poster",
+		Version:    version,
+		CreateTime: time.Now(),
+	}
+	err = newPoster.Create()
+	return
+}
+
+type Html2ImgResp struct {
+	Code int    `json:"code"`
+	Msg  string `json:"msg"`
+	Data string `json:"data"`
+}
+
+// postHtml2Img 请求htm2img接口
+func postHtml2Img(param map[string]interface{}) (resp *Html2ImgResp, err error) {
+	// 目前仅此处调用该接口,暂不加授权、校验等
+	postUrl := ServerUrl + "htm2img"
+	postData, err := json.Marshal(param)
+	if err != nil {
+		return
+	}
+	result, err := Html2ImgHttpPost(postUrl, string(postData), "application/json")
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(result, &resp); err != nil {
+		return
+	}
+	return resp, nil
+}
+
+// Html2ImgHttpPost post请求
+func Html2ImgHttpPost(url, postData string, params ...string) ([]byte, error) {
+	body := ioutil.NopCloser(strings.NewReader(postData))
+	client := &http.Client{}
+	req, err := http.NewRequest("POST", url, body)
+	if err != nil {
+		return nil, err
+	}
+	contentType := "application/x-www-form-urlencoded;charset=utf-8"
+	if len(params) > 0 && params[0] != "" {
+		contentType = params[0]
+	}
+	req.Header.Set("Content-Type", contentType)
+	resp, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	b, err := ioutil.ReadAll(resp.Body)
+	fmt.Println("HttpPost:" + string(b))
+	return b, err
+}
+
+// CreateAndUploadSunCode 生成太阳码并上传OSS
+func CreateAndUploadSunCode(page, scene, version string) (imgUrl string, err error) {
+	if page == "" {
+		err = errors.New("page不能为空")
+		return
+	}
+	path := fmt.Sprint(page, "?", scene)
+	exist, err := yb_poster_resource.GetPosterByCondition(path, "qrcode", version)
+	if err != nil && err != utils.ErrNoRow {
+		return
+	}
+	if exist != nil && exist.ImgURL != "" {
+		return exist.ImgURL, nil
+	}
+	// scene超过32位会生成失败,md5处理至32位
+	sceneMD5 := "a=1"
+	if scene != "" {
+		sceneMD5 = utils.MD5(scene)
+	}
+	picByte, err := wx_app.GetSunCode(page, sceneMD5)
+	if err != nil {
+		return
+	}
+	// 生成图片
+	localPath := "./static/img"
+	fileName := utils.GetRandStringNoSpecialChar(28) + ".png"
+	fpath := fmt.Sprint(localPath, "/", fileName)
+	f, err := os.Create(fpath)
+	if err != nil {
+		return
+	}
+	if _, err = f.Write(picByte); err != nil {
+		return
+	}
+	defer func() {
+		f.Close()
+		os.Remove(fpath)
+	}()
+	// 上传OSS
+	fileDir := "yb/suncode/"
+	imgUrl, err = UploadAliyunToDir(fileName, fpath, fileDir)
+	if err != nil {
+		return
+	}
+	// 记录二维码信息
+	newPoster := &yb_poster_resource.YbPosterResource{
+		Path:       path,
+		ImgURL:     imgUrl,
+		Type:       "qrcode",
+		Version:    version,
+		CreateTime: time.Now(),
+	}
+	err = newPoster.Create()
+	if err != nil {
+		return
+	}
+	// 记录参数md5
+	if scene != "" {
+		newPars := &yb_suncode_pars.YbSuncodePars{
+			Scene:      scene,
+			SceneKey:   sceneMD5,
+			CreateTime: time.Now(),
+		}
+		err = newPars.Create()
+	}
+	return
+}
+
+type PosterParsReq struct {
+	ActivityTitle   string `json:"activity_title"`
+	ActivityAvatar  string `json:"activity_avatar"`
+	ActivitySpeaker string `json:"activity_speaker"`
+	ActivityTime    string `json:"activity_time"`
+	ChartName       string `json:"chart_name"`
+	ChartImage      string `json:"chart_image"`
+	ReportType      string `json:"report_type"`
+	ReportAvatar    string `json:"report_avatar"`
+	ReportTitle     string `json:"report_title"`
+	ReportAbstract  string `json:"report_abstract"`
+	Stage1          string `json:"stage_1"`
+	Avatar1         string `json:"avatar_1"`
+	Title1          string `json:"title_1"`
+	Author1         string `json:"author_1"`
+	Tag1            string `json:"tag_1"`
+	Img1            string `json:"img_1"`
+	Time1           string `json:"time_1"`
+	Abstract1       string `json:"abstract_1"`
+	Status1         string `json:"status_1"`
+	Speaker1        string `json:"speaker_1"`
+	Stage2          string `json:"stage_2"`
+	Avatar2         string `json:"avatar_2"`
+	Title2          string `json:"title_2"`
+	Author2         string `json:"author_2"`
+	Tag2            string `json:"tag_2"`
+	Img2            string `json:"img_2"`
+	Abstract2       string `json:"abstract_2"`
+	Time2           string `json:"time_2"`
+	Status2         string `json:"status_2"`
+	Speaker2        string `json:"speaker_2"`
+	ListTitle       string `json:"list_title"`
+}
+
+// fillContent2Html 填充HTML动态内容
+func fillContent2Html(source, pars, sunCodeUrl string, height int) (contentStr string, newHeight int, err error) {
+	params := new(PosterParsReq)
+	if err = json.Unmarshal([]byte(pars), &params); err != nil {
+		return
+	}
+	template := fmt.Sprint("static/htm2img/", source, ".html")
+	contentByte, err := ioutil.ReadFile(template)
+	if err != nil {
+		return
+	}
+	newHeight = height
+	contentStr = string(contentByte)
+	// 列表的动态内容不完整的用默认内容的填充
+	var emptyTime1, emptyTime2 bool
+	if strings.Contains(source, "list") {
+		if params.Title1 == "" || params.Title2 == "" {
+			defaultAvatar := "https://hzstatic.hzinsights.com/static/images/202112/20211210/wn6c3oYKTfT4NbTZgRGflRuIBZaa.png"
+			switch source {
+			case "activity_list":
+				if params.Title1 == "" {
+					params.ListTitle = "线下沙龙"
+					params.Status1 = "未开始"
+					params.Avatar1 = defaultAvatar
+					params.Title1 = "周度报告"
+					params.Speaker1 = "FICC研究员"
+					params.Time1 = "2022-5-10"
+					emptyTime1 = true
+				}
+				params.Status2 = params.Status1
+				params.Avatar2 = defaultAvatar
+				params.Title2 = "周度报告"
+				params.Speaker2 = "FICC研究员"
+				params.Time2 = "2022-5-10"
+				emptyTime2 = true
+			case "special_column_list":
+				if params.Title1 == "" {
+					params.Stage1 = "第1期"
+					params.Avatar1 = defaultAvatar
+					params.Title1 = "弘则FICC专栏"
+					params.Author1 = "弘则研究"
+					params.Tag1 = "FICC研究员"
+				}
+				params.Stage2 = "第2期"
+				params.Avatar2 = defaultAvatar
+				params.Title2 = "弘则FICC专栏"
+				params.Author2 = "弘则研究"
+				params.Tag2 = "FICC研究员"
+			case "chart_list":
+				if params.Title1 == "" {
+					params.Title1 = "螺纹仓单-热卷仓单季节性"
+					params.Img1 = "https://hzstatic.hzinsights.com/static/images/202112/20211227/8VBIH1l6VraYpLCoBS6qOIXA5Zoq.png"
+				}
+				params.Title2 = "卷螺期货现货价差"
+				params.Img2 = "https://hzstatic.hzinsights.com/static/images/202204/20220427/d8GRfdR3Xfrvk397SnYudcwVs9pV.png"
+			case "report_list":
+				if params.Title1 == "" {
+					params.Img1 = defaultAvatar
+					params.Title1 = "弘则FICC研报"
+					params.Time1 = "1期"
+				}
+				params.Img2 = defaultAvatar
+				params.Title2 = "弘则FICC研报"
+				params.Time2 = "2期"
+			}
+		}
+	}
+	// 填充指定内容
+	switch source {
+	case "activity_detail":
+		contentStr = strings.Replace(contentStr, "{{ACTIVITY_TITLE}}", params.ActivityTitle, 1)
+		contentStr = strings.Replace(contentStr, "{{ACTIVITY_AVATAR}}", params.ActivityAvatar, 1)
+		contentStr = strings.Replace(contentStr, "{{ACTIVITY_SPEAKER}}", params.ActivitySpeaker, 1)
+		contentStr = strings.Replace(contentStr, "{{ACTIVITY_TIME}}", params.ActivityTime, 1)
+	case "special_column_detail":
+		contentStr = strings.Replace(contentStr, "{{REPORT_AVATAR}}", params.ReportAvatar, 1)
+		contentStr = strings.Replace(contentStr, "{{REPORT_TITLE}}", params.ReportTitle, 1)
+		contentStr = strings.Replace(contentStr, "{{REPORT_ABSTRACT}}", params.ReportAbstract, 1)
+	case "chart_detail":
+		contentStr = strings.Replace(contentStr, "{{CHART_NAME}}", params.ChartName, 1)
+		contentStr = strings.Replace(contentStr, "{{CHART_IMAGE}}", params.ChartImage, 1)
+	case "report_detail":
+		doc, tmpErr := goquery.NewDocumentFromReader(strings.NewReader(params.ReportAbstract))
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		abstract := ""
+		doc.Find("p").Each(func(i int, s *goquery.Selection) {
+			phtml, tmpErr := s.Html()
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			st := s.Text()
+			if st != "" && st != "<br>" && st != "<br style=\"max-width: 100%;\">" && !strings.Contains(phtml, "iframe") {
+				abstract = abstract + "<p>" + phtml + "</p>"
+			}
+		})
+		contentStr = strings.Replace(contentStr, "{{REPORT_TYPE}}", params.ReportType, 1)
+		contentStr = strings.Replace(contentStr, "{{REPORT_TITLE}}", params.ReportTitle, 1)
+		contentStr = strings.Replace(contentStr, "{{REPORT_ABSTRACT}}", abstract, 1)
+	case "special_column_list":
+		contentStr = strings.Replace(contentStr, "{{LIST_TITLE}}", params.ListTitle, 1)
+		contentStr = strings.Replace(contentStr, "{{STAGE_1}}", "第" + params.Stage1 + "期", 1)
+		contentStr = strings.Replace(contentStr, "{{AVATAR_1}}", params.Avatar1, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_1}}", params.Title1, 1)
+		contentStr = strings.Replace(contentStr, "{{AUTHOR_1}}", params.Author1, 1)
+		contentStr = strings.Replace(contentStr, "{{TAG_1}}", params.Tag1, 1)
+		contentStr = strings.Replace(contentStr, "{{STAGE_2}}", "第" + params.Stage2 + "期", 1)
+		contentStr = strings.Replace(contentStr, "{{AVATAR_2}}", params.Avatar2, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_2}}", params.Title2, 1)
+		contentStr = strings.Replace(contentStr, "{{AUTHOR_2}}", params.Author2, 1)
+		contentStr = strings.Replace(contentStr, "{{TAG_2}}", params.Tag2, 1)
+	case "chart_list":
+		contentStr = strings.Replace(contentStr, "{{LIST_TITLE}}", params.ListTitle, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_1}}", params.Title1, 1)
+		contentStr = strings.Replace(contentStr, "{{IMG_1}}", params.Img1, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_2}}", params.Title2, 1)
+		contentStr = strings.Replace(contentStr, "{{IMG_2}}", params.Img2, 1)
+	case "report_list":
+		contentStr = strings.Replace(contentStr, "{{LIST_TITLE}}", params.ListTitle, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_1}}", params.Title1, 1)
+		contentStr = strings.Replace(contentStr, "{{ABSTRACT_1}}", params.Abstract1, 1)
+		contentStr = strings.Replace(contentStr, "{{IMG_1}}", params.Img1, 1)
+		contentStr = strings.Replace(contentStr, "{{TIME_1}}", params.Time1, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_2}}", params.Title2, 1)
+		contentStr = strings.Replace(contentStr, "{{ABSTRACT_2}}", params.Abstract2, 1)
+		contentStr = strings.Replace(contentStr, "{{IMG_2}}", params.Img2, 1)
+		contentStr = strings.Replace(contentStr, "{{TIME_2}}", params.Time2, 1)
+	case "activity_list":
+		bgColorMap := map[string]string{
+			"未开始": "#E3B377",
+			"进行中": "#3385FF",
+			"已结束": "#A2A2A2",
+		}
+		statusItemMap := map[string]string{
+			"未开始": "block",
+			"进行中": "none",
+			"已结束": "none",
+		}
+		offlineMap := map[string]string{
+			"线上会议": "none",
+			"线下沙龙": "block",
+		}
+		onlineMap := map[string]string{
+			"线上会议": "block",
+			"线下沙龙": "none",
+		}
+		if params.Status1 != "未开始" {
+			newHeight = 1715
+		}
+		contentStr = strings.Replace(contentStr, "{{LIST_TITLE}}", "弘则FICC周度电话会安排", 1)
+		contentStr = strings.Replace(contentStr, "{{BG_COLORE_1}}", bgColorMap[params.Status1], 1)
+		contentStr = strings.Replace(contentStr, "{{STATUS_1}}", params.Status1, 1)
+		contentStr = strings.Replace(contentStr, "{{AVATAR_1}}", params.Avatar1, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_1}}", params.Title1, 1)
+		contentStr = strings.Replace(contentStr, "{{SPEAKER_1}}", params.Speaker1, 1)
+		contentStr = strings.Replace(contentStr, "{{TIME_1}}", params.Time1, 1)
+		contentStr = strings.Replace(contentStr, "{{SHOW_ITEM_1}}", statusItemMap[params.Status1], 1)
+		contentStr = strings.Replace(contentStr, "{{SHOW_OFFLINE_1}}", offlineMap[params.ListTitle], 1)
+		contentStr = strings.Replace(contentStr, "{{SHOW_ONLINE_1}}", onlineMap[params.ListTitle], 1)
+		contentStr = strings.Replace(contentStr, "{{BG_COLORE_2}}", bgColorMap[params.Status2], 1)
+		contentStr = strings.Replace(contentStr, "{{STATUS_2}}", params.Status2, 1)
+		contentStr = strings.Replace(contentStr, "{{AVATAR_2}}", params.Avatar2, 1)
+		contentStr = strings.Replace(contentStr, "{{TITLE_2}}", params.Title2, 1)
+		contentStr = strings.Replace(contentStr, "{{SPEAKER_2}}", params.Speaker2, 1)
+		contentStr = strings.Replace(contentStr, "{{TIME_2}}", params.Time2, 1)
+		contentStr = strings.Replace(contentStr, "{{SHOW_ITEM_2}}", statusItemMap[params.Status2], 1)
+		contentStr = strings.Replace(contentStr, "{{SHOW_OFFLINE_2}}", offlineMap[params.ListTitle], 1)
+		contentStr = strings.Replace(contentStr, "{{SHOW_ONLINE_2}}", onlineMap[params.ListTitle], 1)
+		// 用默认内容填充的活动时间字体颜色调至看不见
+		color1 := "#999"
+		color2 := "#999"
+		if emptyTime1 {
+			color1 = "#fff"
+		}
+		if emptyTime2 {
+			color2 = "#fff"
+		}
+		contentStr = strings.Replace(contentStr, "{{TIME_COLOR_1}}", color1, 1)
+		contentStr = strings.Replace(contentStr, "{{TIME_COLOR_2}}", color2, 1)
+	}
+	contentStr = strings.Replace(contentStr, "{{SUN_CODE}}", sunCodeUrl, 1)
+	return
+}

+ 9 - 4
services/sms.go

@@ -3,6 +3,7 @@ package services
 import (
 	"encoding/json"
 	"fmt"
+	"hongze/hongze_yb/services/alarm_msg"
 	"hongze/hongze_yb/utils"
 	"io/ioutil"
 	"net/http"
@@ -22,14 +23,16 @@ func SendSmsCode(mobile, vCode string) bool {
 	var netReturn map[string]interface{}
 	err = json.Unmarshal(result, &netReturn)
 	if err != nil {
-		go SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		//go SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		go alarm_msg.SendAlarmMsg("短信验证码发送失败, Err:"+err.Error()+";Result:"+string(result), 2)
 		flag = false
 	}
 	if netReturn["error_code"].(float64) == 0 {
 		fmt.Printf("接口返回result字段是:\r\n%v", netReturn["result"])
 		flag = true
 	} else {
-		go SendEmail("短信验证码发送失败", " result"+string(result), utils.EmailSendToUsers)
+		//go SendEmail("短信验证码发送失败", " result"+string(result), utils.EmailSendToUsers)
+		go alarm_msg.SendAlarmMsg("短信验证码发送失败, Result:"+string(result), 2)
 		flag = false
 	}
 	return flag
@@ -75,14 +78,16 @@ func SendSmsCodeGj(mobile, vCode, areaNum string) bool {
 	var netReturn map[string]interface{}
 	err = json.Unmarshal(result, &netReturn)
 	if err != nil {
-		go SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		//go SendEmail("短信验证码发送失败", "err:"+err.Error()+" result"+string(result), utils.EmailSendToUsers)
+		go alarm_msg.SendAlarmMsg("短信验证码发送失败, Err:"+err.Error()+";Result:"+string(result), 2)
 		flag = false
 	}
 	if netReturn["error_code"].(float64) == 0 {
 		fmt.Printf("接口返回result字段是:\r\n%v", netReturn["result"])
 		flag = true
 	} else {
-		go SendEmail("短信验证码发送失败", " result"+string(result), utils.EmailSendToUsers)
+		//go SendEmail("短信验证码发送失败", " result"+string(result), utils.EmailSendToUsers)
+		go alarm_msg.SendAlarmMsg("短信验证码发送失败, Result:"+string(result), 2)
 		flag = false
 	}
 	return flag

+ 19 - 16
services/wx_app/wx_app.go

@@ -8,6 +8,8 @@ import (
 	"github.com/silenceper/wechat/v2/miniprogram/auth"
 	"github.com/silenceper/wechat/v2/miniprogram/config"
 	"github.com/silenceper/wechat/v2/miniprogram/encryptor"
+	"github.com/silenceper/wechat/v2/miniprogram/qrcode"
+	"hongze/hongze_yb/global"
 )
 
 //微信小程序配置信息
@@ -15,7 +17,8 @@ var (
 	WxId        string //微信原始ID
 	WxAppId     string
 	WxAppSecret string
-	WxPlatform  int //用户来源,需要入库,用来保存该用户来自哪个平台,默认是:1
+	WxPlatform  int    //用户来源,需要入库,用来保存该用户来自哪个平台,默认是:1
+	EnvVersion  string // 小程序版本, release-正式版; trial-体验版; develop-开发版
 )
 
 func init() {
@@ -23,6 +26,10 @@ func init() {
 	WxId = `gh_75abb562a946`
 	WxAppSecret = `1737c73e9f69a21de1a345b8f0800258`
 	WxPlatform = 6 //弘则研报来源
+	EnvVersion = "trial"
+	if global.CONFIG.Serve.RunMode == "release" {
+		EnvVersion = "release"
+	}
 }
 
 func GetWxApp() (miniprogram *miniprogram.MiniProgram) {
@@ -64,18 +71,14 @@ func GetDecryptInfo(sessionKey, encryptedData, iv string) (decryptData *encrypto
 	return
 }
 
-//func GetCode() {
-//	codeParms := qrcode.QRCoder{
-//		Page:      "",
-//		Path:      "",
-//		Width:     0,
-//		Scene:     "",
-//		AutoColor: false,
-//		LineColor: qrcode.Color{},
-//		IsHyaline: false,
-//	}
-//	//wxApp := GetWxApp()
-//	//qrCode := wxApp.GetQRCode()
-//	//qrCode.
-//	//qrCode.GetWXACodeUnlimit()
-//}
+// GetSunCode 获取太阳码
+func GetSunCode(page, scene string) (resp []byte, err error) {
+	codePars := qrcode.QRCoder{
+		Page:       page,
+		Scene:      scene,
+		EnvVersion: EnvVersion,
+	}
+	wechatClient := GetWxApp()
+	qr := wechatClient.GetQRCode()
+	return qr.GetWXACodeUnlimit(codePars)
+}

+ 85 - 0
static/htm2img/activity_detail.html

@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        .box{
+            /* width: 320px;
+            height: 487px; */
+            width: 1280px;
+            height: 1210px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .title{
+            font-size: 64px;
+            font-weight: bold;
+            margin-bottom: 20px;
+        }
+        .flex{
+            height: 256px;
+            margin-top: 40px;
+            font-size: 56px;
+        }
+        .content-box{
+            /* height: 208px; */
+            margin: 60px 0;
+            overflow: hidden;
+            font-size: 56px;
+        }
+        .avatar{
+            width: 235px;
+            height: 235px;
+            object-fit: cover;
+            border-radius: 50%;
+            overflow: hidden;
+            display: block;
+            margin-left: auto;
+            margin-right: auto;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+        p,span{
+            margin: 0 !important;
+            padding: 0 !important;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{ACTIVITY_TITLE}}</div>
+        <div class="content-box" style="margin-bottom: 100px;">
+            <img src="{{ACTIVITY_AVATAR}}" alt="" class="avatar">
+            <div style="font-size: 48px;text-align: center;margin-top: 20px;font-weight: bold;">主讲人:{{ACTIVITY_SPEAKER}}</div>
+            <div style="font-size: 41px;text-align: center;margin-top: 20px;">活动时间:{{ACTIVITY_TIME}}</div>
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 165 - 0
static/htm2img/activity_list.html

@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        p,span{
+            margin: 0;
+            padding: 0;
+        }
+        .box{
+            /* width: 320px;
+            height: 487px; */
+            width: 1280px;
+            height: 1948px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .title{
+            font-size: 64px;
+            font-weight: bold;
+            margin-bottom: 20px;
+        }
+        .flex{
+            height: 256px;
+            margin-top: 40px;
+            font-size: 56px;
+        }
+        .content-box{
+            /* height: 208px; */
+            /*height: 1194px;*/
+            margin: 40px 0;
+            overflow: hidden;
+            font-size: 56px;
+        }
+        .item{
+            padding-top: 80px;
+            /* height: 95px; */
+            margin-bottom: 40px;
+            position: relative;
+            overflow: hidden;
+            background: #FFFFFF;
+            box-shadow: 1px 1px 20px 0px rgba(161,161,161,0.14);
+            border-radius: 24px;
+            border: 1px solid rgba(112, 112, 112, 0.2);
+        }
+        .avatar{
+            width: 284px;
+            height: 284px;
+            border-radius: 50%;
+            background-color: #f5f5f5;
+            float: left;
+            margin-right: 32px;
+            object-fit: cover;
+            display: block;
+        }
+        .item-con{
+            overflow: hidden;
+            margin-top: 28px;
+        }
+        .item-con .name{
+            font-size: 52px;
+            font-weight: bold;
+            padding-bottom: 32px;
+            border-bottom: 1px solid #EBEDF0;
+            margin-bottom: 36px;
+        }
+        .text-one{
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+        }
+        .stage{
+            position: absolute;
+            top: 0;
+            right: 0;
+            background-color: #E3B377;
+            color: #fff;
+            font-size: 40px;
+            display: block;
+            padding: 8px 32px;
+            border-top-right-radius: 24px;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{LIST_TITLE}}</div>
+        <div class="content-box">
+            <div class="item">
+                <!-- 如果是进行中则 background-color:#3385FF 已结束 background-color:#A2A2A2 本周预告 #E3B377 -->
+                <span class="stage" style="background-color: {{BG_COLORE_1}};">{{STATUS_1}}</span>
+                <div style="border-bottom: 1px solid #EBEDF0;padding: 0 48px 60px 48px;">
+                    <img class="avatar" src="{{AVATAR_1}}" alt="">
+                    <div class="item-con">
+                        <div class="text-one name" style="padding-top: 5px;">{{TITLE_1}}</div>
+                        <div style="color: #666;font-size: 48px;">主讲:{{SPEAKER_1}}</div>
+                        <div style="font-size: 40px;color: #999;margin-top: 20px;color: {{TIME_COLOR_1}};">{{TIME_1}}</div>
+                    </div>
+                </div>
+                <!-- 如果非预告则下面style 加上 display:none -->
+                <div style="display: {{SHOW_ITEM_1}}" >
+                    <!-- 如果是线下沙龙则设置 display:none -->
+                    <div style="text-align: center;color: #E3B377;font-size: 44px;line-height: 112px;display: {{SHOW_ONLINE_1}};">会议提醒</div>
+                    <!-- 如果是线上会议则设置 display:none -->
+                    <div style="display: {{SHOW_OFFLINE_1}}" >
+                        <div style="text-align: center;color: #E3B377;font-size: 44px;line-height: 112px;float: left;width: 50%;border-right: 1px solid #EBEDF0;">会议提醒</div>
+                        <div style="text-align: center;color: #E3B377;font-size: 44px;line-height: 112px;float: left;width: 50%;">报名线下参会</div>
+                    </div>
+                </div>
+            </div>
+            <div class="item">
+                <!-- 如果是进行中则 background-color:#3385FF 已结束 background-color:#A2A2A2 本周预告 #E3B377 -->
+                <span class="stage" style="background-color: {{BG_COLORE_2}};">{{STATUS_2}}</span>
+                <div style="border-bottom: 1px solid #EBEDF0;padding: 0 48px 60px 48px;">
+                    <img class="avatar" src="{{AVATAR_2}}" alt="">
+                    <div class="item-con">
+                        <div class="text-one name" style="padding-top: 5px;">{{TITLE_2}}</div>
+                        <div style="color: #666;font-size: 48px;">主讲:{{SPEAKER_2}}</div>
+                        <div style="font-size: 40px;color: #999;margin-top: 20px;color: {{TIME_COLOR_2}};">{{TIME_2}}</div>
+                    </div>
+                </div>
+                <!-- 如果非预告则下面style 加上 display:none -->
+                <div style="display: {{SHOW_ITEM_2}}" >
+                    <!-- 如果是线下沙龙则设置 display:none -->
+                    <div style="text-align: center;color: #E3B377;font-size: 44px;line-height: 112px;display: {{SHOW_ONLINE_2}};">会议提醒</div>
+                    <!-- 如果是线上会议则设置 display:none -->
+                    <div style="display: {{SHOW_OFFLINE_2}}" >
+                        <div style="text-align: center;color: #E3B377;font-size: 44px;line-height: 112px;float: left;width: 50%;border-right: 1px solid #EBEDF0;">会议提醒</div>
+                        <div style="text-align: center;color: #E3B377;font-size: 44px;line-height: 112px;float: left;width: 50%;">报名线下参会</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 75 - 0
static/htm2img/chart_detail.html

@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        .box{
+            /* width: 294px;
+            height: 381px; */
+            width: 1176px;
+            height: 1536px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .title{
+            font-size: 64px;
+            font-weight: bold;
+            display: -webkit-box;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            -webkit-line-clamp: 2;
+            -webkit-box-orient: vertical;
+            min-height: 152px;
+            margin-bottom: 40px;
+        }
+        .bg-img{
+            width: 1056px;
+            height: 756px;
+        }
+        .flex{
+            margin-top: 40px;
+            font-size: 56px;
+            height: 256px;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+        p,span{
+            margin: 0 !important;
+            padding: 0 !important;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{CHART_NAME}}</div>
+        <img class="bg-img" src="{{CHART_IMAGE}}" alt="">
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 106 - 0
static/htm2img/chart_list.html

@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        p,span{
+            margin: 0;
+            padding: 0;
+        }
+        .box{
+            /* width: 294px;
+            height: 338px; */
+            width: 1176px;
+            height: 1352px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .title{
+            font-size: 64px;
+            font-weight: bold;
+            margin-bottom: 40px;
+        }
+        .content-box{
+            height: 656px;
+            margin-bottom: 20px;
+        }
+        .content-box .item{
+            width: 500px;
+            height: 560px;
+            background: #FFFFFF;
+            box-shadow: 0px 0px 24px 0px rgba(154,141,123,0.16);
+            border-radius: 16px;
+            margin: 40px 0px;
+            padding: 40px;
+            float: left;
+            position: relative;
+        }
+        .content-box .item-title{
+            display: -webkit-box;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            -webkit-line-clamp: 2;
+            -webkit-box-orient: vertical;
+            font-size: 48px;
+        }
+        .content-box .item-img{
+            width: 420px;
+            height: 320px;
+            object-fit: cover;
+            position: absolute;
+            left: 40px;
+            bottom: 40px;
+        }
+
+        .flex{
+            height: 256px;
+            margin-top: 40px;
+            font-size: 56px;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{LIST_TITLE}}</div>
+        <div class="content-box">
+            <div class="item">
+                <div class="item-title">{{TITLE_1}}</div>
+                <img class="item-img" src="{{IMG_1}}" alt="">
+            </div>
+            <div class="item" style="float: right;">
+                <div class="item-title">{{TITLE_2}}</div>
+                <img class="item-img" src="{{IMG_2}}" alt="">
+            </div>
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 111 - 0
static/htm2img/report_detail.html

@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,
+        body {
+          margin: 0;
+          padding: 0;
+        }
+        div {
+          box-sizing: border-box;
+        }
+        .box {
+          /* width: 294px;
+              height: 355px; */
+          width: 1176px;
+          height: 1450px;
+          background-color: #fff;
+          padding: 100px 64px 64px 60px;
+          border-radius: 16px;
+          border: 1px solid #ececec;
+          background-image: url("https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png");
+          background-position: top right;
+          background-size: 336px 336px;
+          background-repeat: no-repeat;
+        }
+        .title {
+          font-size: 64px;
+          font-weight: bold;
+          margin-bottom: 20px;
+        }
+        .sub-title {
+          font-size: 60px;
+          font-weight: bold;
+          -webkit-line-clamp: 2;
+          -webkit-box-orient: vertical;
+          display: -webkit-box;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          min-height: 120px;
+        }
+        .flex {
+          height: 256px;
+          margin-top: 40px;
+          font-size: 56px;
+        }
+        .content-box {
+          height: 520px;
+          margin: 80px 0;
+          color: #000;
+          overflow: hidden;
+          font-size: 48px;
+        }
+        .xcx-img {
+          width: 256px;
+          height: 256px;
+          float: right;
+        }
+        .content-box div {
+          font-size: 48px !important;
+          overflow: inherit !important;
+          line-height: 1.7 !important;
+          color: #000 !important;
+        }
+        .content-box span {
+          font-size: 48px !important;
+          line-height: 1.7 !important;
+          color: #000 !important;
+        }
+        .content-box p {
+          font-size: 48px !important;
+          overflow: inherit !important;
+          line-height: 1.7 !important;
+          color: #000 !important;
+        }
+        .content-box section {
+          overflow: inherit !important;
+          line-height: 1.7 !important;
+          color: #000 !important;
+        }
+        .content-box iframe {
+          display: none;
+        }
+        p,span{
+            margin: 0 !important;
+            padding: 0 !important;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{REPORT_TYPE}}</div>
+        <div class="sub-title" style="padding-top: 5px;">{{REPORT_TITLE}}</div>
+        <div class="content-box">
+            {{REPORT_ABSTRACT}}
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 134 - 0
static/htm2img/report_list.html

@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        .box{
+            /* width: 294px;
+            height: 336px; */
+            width: 1176px;
+            height: 1344px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .title{
+            font-size: 64px;
+            font-weight: bold;
+            margin-bottom: 20px;
+        }
+        .flex{
+            height: 256px;
+            margin-top: 40px;
+            font-size: 56px;
+        }
+        .content-box{
+            height: 628px;
+            margin: 40px 0;
+            overflow: hidden;
+            font-size: 56px;
+        }
+        .text-one{
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+        }
+        .item-img{
+            width: 188px;
+            height: 252px;
+            float: left;
+            object-fit: cover;
+            border-radius: 16px;
+            margin-right: 20px;
+        }
+        .item-title{
+            font-size: 52px;
+        }
+        .item-des{
+            height: 80px;
+            font-size: 44px;
+        }
+        .audio-box{
+            width: 200px;
+            height: 80px;
+            background: #E3B377;
+            border-radius: 40px;
+            color: #fff;
+            font-size: 48px;
+            float: right;
+            text-align: center;
+            line-height: 80px;
+        }
+        .audio-box img{
+            width: 60px;
+            height: 60px;
+            object-fit: cover;
+            position: relative;
+            top: 12px;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+        p,span{
+            margin: 0 !important;
+            padding: 0 !important;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{LIST_TITLE}}</div>
+        <div class="content-box">
+            <div class="item" style="margin-bottom: 40px;">
+                <img class="item-img" src="{{IMG_1}}" alt="">
+                <div class="item-title text-one" style="margin:20px 0">{{TITLE_1}}</div>
+                <div class="item-des text-one" style="color:#666">{{ABSTRACT_1}}</div>
+                <div class="item-bot">
+                    <span class="item-time" style="color:#999;font-size: 44px;">{{TIME_1}}</span>
+                    <div class="audio-box" style="display: none">
+                        <img src="https://hzstatic.hzinsights.com/static/yb_wx/report_hongguan.png" alt="">
+                        <span>播放</span>
+                    </div>
+                </div>
+            </div>
+            <div class="item" style="margin-bottom: 40px;">
+                <img class="item-img" src="{{IMG_2}}" alt="">
+                <div class="item-title text-one" style="margin:20px 0">{{TITLE_2}}</div>
+                <div class="item-des text-one" style="color:#666">{{ABSTRACT_2}}</div>
+                <div class="item-bot">
+                    <span class="item-time" style="color:#999;font-size: 44px;">{{TIME_2}}</span>
+                    <div class="audio-box" style="display: none">
+                        <img src="https://hzstatic.hzinsights.com/static/yb_wx/report_hongguan.png" alt="">
+                        <span>播放</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 85 - 0
static/htm2img/special_column_detail.html

@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        .box{
+            /* width: 294px;
+            height: 370px; */
+            width: 1176px;
+            height: 1480px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .avatar{
+            width: 272px;
+            height: 272px;
+            display: block;
+            margin-left: auto;
+            margin-right: auto;
+            border-radius: 50%;
+            object-fit: cover;
+        }
+        .sub-title{
+            font-size: 64px;
+            font-weight: bold;
+            text-align: center;
+            margin-top: 40px;
+        }
+        .flex{
+            height: 256px;
+            margin-top: 40px;
+            font-size: 56px;
+        }
+        .content-box{
+            height: 388px;
+            margin: 40px 0;
+            color: #999;
+            overflow: hidden;
+            font-size: 56px;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+        p,span{
+            margin: 0 !important;
+            padding: 0 !important;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <img class="avatar" src="{{REPORT_AVATAR}}" alt="">
+        <div class="sub-title">{{REPORT_TITLE}}</div>
+        <div class="content-box" style="color: #333;">
+            {{REPORT_ABSTRACT}}
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 167 - 0
static/htm2img/special_column_list.html

@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+    <style>
+        html,body{
+            margin: 0;
+            padding: 0;
+        }
+        div{
+            box-sizing: border-box;
+        }
+        .box{
+            /* width: 294px;
+            height: 387px; */
+            width: 1176px;
+            height: 1548px;
+            background-color: #fff;
+            padding: 100px 64px 64px 60px;
+            border-radius: 16px;
+            border: 1px solid #ECECEC;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-position: top right;
+            background-size: 336px 336px;
+            background-repeat: no-repeat;
+        }
+        .title{
+            font-size: 64px;
+            font-weight: bold;
+            margin-bottom: 20px;
+        }
+        .flex{
+            height: 256px;
+            margin-top: 40px;
+            font-size: 56px;
+        }
+        .content-box{
+            height: 832px;
+            margin: 40px 0;
+            overflow: hidden;
+            font-size: 56px;
+        }
+        .item{
+            background: #FFFFFF;
+            box-shadow: 0px 0px 40px 1px rgba(0,0,0,0.08);
+            border-radius: 24px;
+            border: 1px solid #E6E6E6;
+            padding: 48px 60px;
+            height: 380px;
+            margin-bottom: 40px;
+            position: relative;
+            overflow: hidden;
+        }
+        .avatar{
+            width: 284px;
+            height: 284px;
+            border-radius: 50%;
+            background-color: #f5f5f5;
+            float: left;
+            margin-right: 32px;
+            object-fit: cover;
+            display: block;
+        }
+        .item-con{
+            overflow: hidden;
+            margin-top: 28px;
+        }
+        .item-con .name{
+            font-size: 52px;
+            font-weight: bold;
+            padding-bottom: 32px;
+            border-bottom: 1px solid #E6E6E6;
+            margin-bottom: 36px;
+        }
+        .text-one{
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+        }
+        .user-tag{
+            background-color: #FAF7EE;
+            max-width: 420px;
+            font-size: 40px;
+            padding: 8px 24px;
+            line-height: 1;
+            display: inline-block;
+            box-sizing: border-box;
+            border-radius: 36px;
+            padding-left: 80px;
+            position: relative;
+        }
+        .user-tag::before{
+            content: '';
+            display: block;
+            background-color: #ccc;
+            position: absolute;
+            left: 24px;
+            top: 12px;
+            width: 40px;
+            height: 40px;
+            background-image: url('https://hzchart.oss-cn-shanghai.aliyuncs.com/static/icon/hzyb/yb-bg-hzlogo.png');
+            background-size: cover;
+        }
+        .stage{
+            position: absolute;
+            top: 0;
+            right: 0;
+            background-color: #E3B377;
+            color: #fff;
+            font-size: 40px;
+            display: block;
+            padding: 8px 32px;
+            border-bottom-left-radius: 32px;
+            border-top-right-radius: 24px;
+        }
+        .xcx-img{
+            width: 256px;
+            height: 256px;
+            float: right;
+        }
+        p,span{
+            margin: 0 !important;
+            padding: 0 !important;
+        }
+    </style>
+</head>
+<body>
+    <div class="box">
+        <div class="title">{{LIST_TITLE}}</div>
+        <div class="content-box">
+            <div class="item">
+                <span class="stage">{{STAGE_1}}</span>
+                <img class="avatar" src="{{AVATAR_1}}" alt="">
+                <div class="item-con">
+                    <div class="text-one name">{{TITLE_1}}</div>
+                    <div>
+                        <span style="font-size: 44px;">{{AUTHOR_1}}</span>
+                        <span class="text-one" style="width: 400px;font-size: 44px;display: inline-block;margin-left: 20px;position: relative;">{{TAG_1}}</span>
+                    </div>
+                </div>
+            </div>
+            <div class="item">
+                <span class="stage">{{STAGE_2}}</span>
+                <img class="avatar" src="{{AVATAR_2}}" alt="">
+                <div class="item-con">
+                    <div class="text-one name">{{TITLE_2}}</div>
+                    <div>
+                        <span style="font-size: 44px;">{{AUTHOR_2}}</span>
+                        <span class="text-one" style="width: 400px;font-size: 44px;display: inline-block;margin-left: 20px;position: relative;">{{TAG_2}}</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div style="text-align:center;font-size:56px;color:#999">长按图片分享</div>
+        <div class="flex">
+            <div style="float: left;margin-top: 65px;">
+                <div>长按识别小程序码</div>
+                <div style="color:#999;margin-top: 20px;">查看更多</div>
+            </div>
+            <img class="xcx-img" src="{{SUN_CODE}}" alt="">
+        </div>
+    </div>
+</body>
+</html>

+ 3 - 2
task/task.go

@@ -3,7 +3,7 @@ package task
 import (
 	"fmt"
 	"hongze/hongze_yb/global"
-	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/alarm_msg"
 	"hongze/hongze_yb/utils"
 	"os"
 	"runtime"
@@ -51,7 +51,8 @@ func (e *Executor) Exec()  {       //执行任务
 					stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d</br>", file, line))
 				}
 				fmt.Println("stack:", stack)
-				go services.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+				//go services.SendEmail(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05"), stack, utils.EmailSendToUsers)
+				go alarm_msg.SendAlarmMsg(utils.APPNAME+"崩了"+time.Now().Format("2006-01-02 15:04:05")+";Msg:"+stack, 2)
 			}
 		}()
 		//time.Sleep(60*time.Second)

+ 1 - 2
utils/constants.go

@@ -24,8 +24,7 @@ const (
 
 const (
 	APPNAME = "弘则研报"
-	//EmailSendToUsers = "glji@hzinsights.com;pyan@hzinsights.com;cxzhang@hzinsights.com"
-	EmailSendToUsers = "glji@hzinsights.com;pyan@hzinsights.com;hsun@hzinsights.com;xyxie@hzinsights.com"
+	EmailSendToUsers = "317699326@qq.com;984198890@qq.com;hsun@hzinsights.com;xyxie@hzinsights.com"
 )
 
 //聚合短信