فهرست منبع

新增报告访问报表

rdluck 4 سال پیش
والد
کامیت
57678a87ec
10فایلهای تغییر یافته به همراه1096 افزوده شده و 0 حذف شده
  1. 40 0
      models/db.go
  2. 85 0
      models/report_view.go
  3. 257 0
      services/report_view.go
  4. 11 0
      services/task.go
  5. 489 0
      utils/common.go
  6. 37 0
      utils/config.go
  7. 60 0
      utils/constants.go
  8. 60 0
      utils/email.go
  9. 45 0
      utils/jwt.go
  10. 12 0
      utils/logs.go

+ 40 - 0
models/db.go

@@ -0,0 +1,40 @@
+package models
+
+import (
+	"hongze/hongze_task/utils"
+	_ "github.com/go-sql-driver/mysql"
+	"time"
+
+	"rdluck_tools/orm"
+)
+
+func init() {
+
+	_ = orm.RegisterDataBase("default", "mysql", utils.MYSQL_URL)
+	orm.SetMaxIdleConns("default", 50)
+	orm.SetMaxOpenConns("default", 100)
+
+	db, _ := orm.GetDB("default")
+	db.SetConnMaxLifetime(10 * time.Minute)
+
+
+	_ = 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("edb", "mysql", utils.MYSQL_URL_EDB)
+	orm.SetMaxIdleConns("edb", 50)
+	orm.SetMaxOpenConns("edb", 100)
+
+	edb_db, _ := orm.GetDB("edb")
+	edb_db.SetConnMaxLifetime(10 * time.Minute)
+
+	//注册对象
+	orm.RegisterModel(
+
+	)
+}

+ 85 - 0
models/report_view.go

@@ -0,0 +1,85 @@
+package models
+
+import "rdluck_tools/orm"
+
+type ResearchReportViewers struct {
+	ResearchReportName string
+	ReportType         string
+	Count              int //访问次数
+	UserCount          int //访问人数
+	CreateDate         string
+}
+
+func GetResearchReportViewers(reportType string) (items []*ResearchReportViewers, err error) {
+	sql := `select rr.research_report_name,rr.type as report_type,count(*) AS count,count(DISTINCT user_id) AS user_count
+		from user_view_history uvh
+		inner join research_report rr on rr.research_report_id = uvh.research_report_id
+		where rr.type = ?
+		group by rr.research_report_id
+		order by rr.research_report_date desc`
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, reportType).QueryRows(&items)
+	return
+}
+
+func GetRddpReportViewers() (items []*ResearchReportViewers, err error) {
+	sql := `select b.title as research_report_name, replace(SUBSTRING(b.create_time,6,5),'-','') as create_date ,b.classify_name_second AS report_type,count(*) AS count,count(DISTINCT a.user_id) AS user_count 
+			from report_view_record as a
+			inner join report as b on a.report_id=b.id
+			group by b.id
+			order by b.create_time desc
+			`
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type ReportType struct {
+	TypeName  string
+	TypeValue string
+}
+
+type ResearchReportViewersDetail struct {
+	RealName           string
+	CompanyName        string
+	CreatedTime        string //访问时间
+	ResearchReportName string
+	ReportVariety      string
+	ResearchReportType string
+	ReportCreateDate string
+}
+
+func GetResearchReportViewersDetail(startTime, reportType string) (items []*ResearchReportViewersDetail, err error) {
+	sql := `
+			select u.real_name,c.company_name,uvh.created_time,rr.research_report_name,ifnull(rct.report_chapter_type_name,rr.report_variety) as report_variety,rr.type as research_report_type
+			from user_view_history uvh
+			inner join wx_user u on u.user_id = uvh.user_id
+			inner join company c on c.company_id = u.company_id
+			inner join research_report rr on rr.research_report_id = uvh.research_report_id
+			left join research_report_type rrt on rrt.research_report_type_id = uvh.research_report_type_id
+			left join report_chapter_type rct on rct.report_chapter_type_id	= rrt.type_id
+			where uvh.created_time > ?
+			and rr.type =?
+			and c.company_id not in (1,16)
+`
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, startTime, reportType).QueryRows(&items)
+	return
+}
+
+func GetRddpReportViewersDetail(startTime string) (items []*ResearchReportViewersDetail, err error) {
+	sql := `
+			SELECT u.real_name,c.company_name,uvh.create_time as created_time,REPLACE(SUBSTRING(r.create_time,6,5),'-','') AS report_create_date,r.title as research_report_name,r.classify_name_second as research_report_type
+			FROM hongze_rddp.report_view_record AS uvh
+			INNER JOIN hongze_rddp.report AS r ON uvh.report_id=r.id
+			INNER JOIN wx_user u ON u.user_id = uvh.user_id
+			INNER JOIN company c ON c.company_id = u.company_id
+			WHERE uvh.create_time >?
+			AND c.company_id NOT IN (1,16)
+			ORDER BY uvh.create_time DESC
+`
+	o := orm.NewOrm()
+	_, err = o.Raw(sql, startTime).QueryRows(&items)
+	return
+}

+ 257 - 0
services/report_view.go

@@ -0,0 +1,257 @@
+package services
+
+import (
+	"fmt"
+	"github.com/tealeg/xlsx"
+	"hongze/hongze_task/models"
+	"hongze/hongze_task/utils"
+	"os"
+	"strconv"
+	"time"
+)
+
+//报告历史访问次数
+func ReportViewTimes() (err error) {
+	defer func() {
+		if err!=nil {
+			fmt.Println("crete ReportViewTimes err:",err.Error())
+			utils.FileLog.Info("crete ReportViewTimes err: %s",err.Error())
+		}
+	}()
+	typeList:=make([]*models.ReportType,0)
+	day:=new(models.ReportType)
+	day.TypeName="晨报"
+	day.TypeValue="day"
+	typeList=append(typeList,day)
+
+	week:=new(models.ReportType)
+	week.TypeName="周报"
+	week.TypeValue="week"
+	typeList=append(typeList,week)
+
+	two_week:=new(models.ReportType)
+	two_week.TypeName="双周报"
+	two_week.TypeValue="week"
+	typeList=append(typeList,two_week)
+
+	month:=new(models.ReportType)
+	month.TypeName="月报"
+	month.TypeValue="month"
+	typeList=append(typeList,month)
+
+	other:=new(models.ReportType)
+	other.TypeName="数据点评"
+	other.TypeValue="other"
+	typeList=append(typeList,other)
+
+	rddp:=new(models.ReportType)
+	rddp.TypeName="日度点评"
+	rddp.TypeValue="rddp"
+	typeList=append(typeList,rddp)
+
+	//创建excel
+	file:=xlsx.NewFile()
+	for _, v := range typeList {
+		fmt.Println(v.TypeValue,v.TypeName)
+		sheet,err:=file.AddSheet(v.TypeName+"阅读人次数")
+		if err!=nil {
+			return err
+		}
+		//标头
+		rowTitle:=sheet.AddRow()
+		cellA:=rowTitle.AddCell()
+		cellA.Value="访问标题"
+		cellB:=rowTitle.AddCell()
+		cellB.Value="报告类型"
+		cellC:=rowTitle.AddCell()
+		cellC.Value="历史访问次数"
+		cellD:=rowTitle.AddCell()
+		cellD.Value="历史访问人数"
+
+		fmt.Println(v.TypeName, v.TypeValue)
+		if v.TypeValue == "rddp" {
+			items, err := models.GetRddpReportViewers()
+			if err != nil {
+				return err
+			}
+			for _, item := range items {
+				row := sheet.AddRow()
+				cellA:=row.AddCell()
+				cellA.Value=item.ResearchReportName+"("+item.CreateDate+")"
+				cellB:=row.AddCell()
+				cellB.Value=item.ReportType
+				cellC:=row.AddCell()
+				cellC.Value=strconv.Itoa(item.Count)
+				cellD:=row.AddCell()
+				cellD.Value=strconv.Itoa(item.UserCount)
+			}
+		} else {
+			items, err := models.GetResearchReportViewers(v.TypeValue)
+			if err != nil {
+				return err
+			}
+			for _, item := range items {
+				row := sheet.AddRow()
+				cellA:=row.AddCell()
+				cellA.Value=item.ResearchReportName
+				cellB:=row.AddCell()
+				cellB.Value=item.ReportType
+				cellC:=row.AddCell()
+				cellC.Value=strconv.Itoa(item.Count)
+				cellD:=row.AddCell()
+				cellD.Value=strconv.Itoa(item.UserCount)
+			}
+		}
+	}
+	savePath:="report_view_times"+time.Now().Format(utils.FormatDateTimeUnSpace)+".xlsx"
+	err=file.Save("./"+savePath)
+	if err!=nil {
+		return
+	}
+	//发送邮件
+	title:="用户访问次数',\"你好,上周用户访问次数见附件。"
+	fmt.Println("start send email")
+	sendResult:=utils.SendEmailByHongze(title,"",utils.EmailSendToUsers,savePath)
+	if sendResult {
+		os.Remove(savePath)
+	}
+	fmt.Println("send result:",sendResult)
+	fmt.Println("end send email")
+	return nil
+}
+
+
+//报告访问详情
+func ReportViewDetail() (err error) {
+	defer func() {
+		if err!=nil {
+			fmt.Println("crete ReportViewDetail err:",err.Error())
+			utils.FileLog.Info("crete ReportViewDetail err: %s",err.Error())
+		}
+	}()
+	typeList:=make([]*models.ReportType,0)
+	day:=new(models.ReportType)
+	day.TypeName="晨报"
+	day.TypeValue="day"
+	typeList=append(typeList,day)
+
+	week:=new(models.ReportType)
+	week.TypeName="周报"
+	week.TypeValue="week"
+	typeList=append(typeList,week)
+
+	two_week:=new(models.ReportType)
+	two_week.TypeName="双周报"
+	two_week.TypeValue="week"
+	typeList=append(typeList,two_week)
+
+	month:=new(models.ReportType)
+	month.TypeName="月报"
+	month.TypeValue="month"
+	typeList=append(typeList,month)
+
+	other:=new(models.ReportType)
+	other.TypeName="数据点评"
+	other.TypeValue="other"
+	typeList=append(typeList,other)
+
+	rddp:=new(models.ReportType)
+	rddp.TypeName="日度点评"
+	rddp.TypeValue="rddp"
+	typeList=append(typeList,rddp)
+
+	startTime:=time.Now().AddDate(0,0,-7).Format(utils.FormatDateTime)
+	//创建excel
+	file:=xlsx.NewFile()
+	for _, v := range typeList {
+		fmt.Println(v.TypeValue,v.TypeName)
+		sheet,err:=file.AddSheet(v.TypeName+"阅读人次数")
+		if err!=nil {
+			return err
+		}
+
+		fmt.Println(v.TypeName, v.TypeValue)
+		if v.TypeValue == "rddp" {
+			//标头
+			rowTitle:=sheet.AddRow()
+			cellA:=rowTitle.AddCell()
+			cellA.Value="用户名称"
+			cellB:=rowTitle.AddCell()
+			cellB.Value="公司名称"
+			cellC:=rowTitle.AddCell()
+			cellC.Value="访问时间"
+			cellD:=rowTitle.AddCell()
+			cellD.Value="访问标题"
+			cellF:=rowTitle.AddCell()
+			cellF.Value="报告类型"
+
+			items, err := models.GetRddpReportViewersDetail(startTime)
+			if err != nil {
+				return err
+			}
+			for _, item := range items {
+				row := sheet.AddRow()
+				cellA:=row.AddCell()
+				cellA.Value=item.RealName
+				cellB:=row.AddCell()
+				cellB.Value=item.CompanyName
+				cellC:=row.AddCell()
+				cellC.Value=item.CreatedTime
+				cellD:=row.AddCell()
+				cellD.Value=item.ResearchReportName+"("+item.ReportCreateDate+")"
+				cellE:=row.AddCell()
+				cellE.Value=v.TypeName
+			}
+		} else {
+			//标头
+			rowTitle:=sheet.AddRow()
+			cellA:=rowTitle.AddCell()
+			cellA.Value="用户名称"
+			cellB:=rowTitle.AddCell()
+			cellB.Value="公司名称"
+			cellC:=rowTitle.AddCell()
+			cellC.Value="访问时间"
+			cellD:=rowTitle.AddCell()
+			cellD.Value="访问标题"
+			cellE:=rowTitle.AddCell()
+			cellE.Value="访问页面"
+			cellF:=rowTitle.AddCell()
+			cellF.Value="报告类型"
+
+			items, err := models.GetResearchReportViewersDetail(startTime,v.TypeValue)
+			if err != nil {
+				return err
+			}
+			for _, item := range items {
+				row := sheet.AddRow()
+				cellA:=row.AddCell()
+				cellA.Value=item.RealName
+				cellB:=row.AddCell()
+				cellB.Value=item.CompanyName
+				cellC:=row.AddCell()
+				cellC.Value=item.CreatedTime
+				cellD:=row.AddCell()
+				cellD.Value=item.ResearchReportName
+				cellE:=row.AddCell()
+				cellE.Value=item.ReportVariety
+				cellF:=row.AddCell()
+				cellF.Value=v.TypeName
+			}
+		}
+	}
+	savePath:="report_view_times"+time.Now().Format(utils.FormatDateTimeUnSpace)+".xlsx"
+	err=file.Save("./"+savePath)
+	if err!=nil {
+		return
+	}
+	//发送邮件
+	title:="研报阅读统计报表"
+	fmt.Println("start send email")
+	sendResult:=utils.SendEmailByHongze(title,"你好,上周研报阅读统计见附件。",utils.EmailSendToUsers,savePath)
+	if sendResult {
+		//os.Remove(savePath)
+	}
+	fmt.Println("send result:",sendResult)
+	fmt.Println("end send email")
+	return nil
+}

+ 11 - 0
services/task.go

@@ -1,5 +1,16 @@
 package services
 
+import (
+	"github.com/astaxie/beego/toolbox"
+)
+
 func Task() {
+	//报告历史访问次数
+	reportViewTimes := toolbox.NewTask("reportViewTimes", "0 0 17 * * 4 ", ReportViewTimes)
+	toolbox.AddTask("reportViewTimes", reportViewTimes)
+	//报告访问详情
+	reportViewDetail := toolbox.NewTask("reportViewDetail", "0 0 17 * * 4 ", ReportViewDetail)
+	toolbox.AddTask("reportViewDetail", reportViewDetail)
 
+	toolbox.StartTask()
 }

+ 489 - 0
utils/common.go

@@ -0,0 +1,489 @@
+
+package utils
+
+import (
+	"crypto/md5"
+	"crypto/sha1"
+	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"image"
+	"image/png"
+	"math"
+	"math/rand"
+	"os"
+	"regexp"
+	"strconv"
+	"strings"
+	"time"
+)
+
+//随机数种子
+var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+func GetRandString(size int) string {
+	allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "@", "#", "$", "%", "^", "&", "*"}
+	randomSb := ""
+	digitSize := len(allLetterDigit)
+	for i := 0; i < size; i++ {
+		randomSb += allLetterDigit[rnd.Intn(digitSize)]
+	}
+	return randomSb
+}
+
+func GetRandStringNoSpecialChar(size int) string {
+	allLetterDigit := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
+	randomSb := ""
+	digitSize := len(allLetterDigit)
+	for i := 0; i < size; i++ {
+		randomSb += allLetterDigit[rnd.Intn(digitSize)]
+	}
+	return randomSb
+}
+
+func StringsToJSON(str string) string {
+	rs := []rune(str)
+	jsons := ""
+	for _, r := range rs {
+		rint := int(r)
+		if rint < 128 {
+			jsons += string(r)
+		} else {
+			jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
+		}
+	}
+	return jsons
+}
+
+//序列化
+func ToString(v interface{}) string {
+	data, _ := json.Marshal(v)
+	return string(data)
+}
+
+//md5加密
+func MD5(data string) string {
+	m := md5.Sum([]byte(data))
+	return hex.EncodeToString(m[:])
+}
+
+// 获取数字随机字符
+func GetRandDigit(n int) string {
+	return fmt.Sprintf("%0"+strconv.Itoa(n)+"d", rnd.Intn(int(math.Pow10(n))))
+}
+
+// 获取随机数
+func GetRandNumber(n int) int {
+	return rnd.Intn(n)
+}
+
+func GetRandInt(min, max int) int {
+	if min >= max || min == 0 || max == 0 {
+		return max
+	}
+	return rand.Intn(max-min) + min
+}
+
+func GetToday(format string) string {
+	today := time.Now().Format(format)
+	return today
+}
+
+//获取今天剩余秒数
+func GetTodayLastSecond() time.Duration {
+	today := GetToday(FormatDate) + " 23:59:59"
+	end, _ := time.ParseInLocation(FormatDateTime, today, time.Local)
+	return time.Duration(end.Unix()-time.Now().Local().Unix()) * time.Second
+}
+
+// 处理出生日期函数
+func GetBrithDate(idcard string) string {
+	l := len(idcard)
+	var s string
+	if l == 15 {
+		s = "19" + idcard[6:8] + "-" + idcard[8:10] + "-" + idcard[10:12]
+		return s
+	}
+	if l == 18 {
+		s = idcard[6:10] + "-" + idcard[10:12] + "-" + idcard[12:14]
+		return s
+	}
+	return GetToday(FormatDate)
+}
+
+//处理性别
+func WhichSexByIdcard(idcard string) string {
+	var sexs = [2]string{"女", "男"}
+	length := len(idcard)
+	if length == 18 {
+		sex, _ := strconv.Atoi(string(idcard[16]))
+		return sexs[sex%2]
+	} else if length == 15 {
+		sex, _ := strconv.Atoi(string(idcard[14]))
+		return sexs[sex%2]
+	}
+	return "男"
+}
+
+//截取小数点后几位
+func SubFloatToString(f float64, m int) string {
+	n := strconv.FormatFloat(f, 'f', -1, 64)
+	if n == "" {
+		return ""
+	}
+	if m >= len(n) {
+		return n
+	}
+	newn := strings.Split(n, ".")
+	if m == 0 {
+		return newn[0]
+	}
+	if len(newn) < 2 || m >= len(newn[1]) {
+		return n
+	}
+	return newn[0] + "." + newn[1][:m]
+}
+
+//截取小数点后几位
+func SubFloatToFloat(f float64, m int) float64 {
+	newn := SubFloatToString(f, m)
+	newf, _ := strconv.ParseFloat(newn, 64)
+	return newf
+}
+
+//获取相差时间-年
+func GetYearDiffer(start_time, end_time string) int {
+	t1, _ := time.ParseInLocation("2006-01-02", start_time, time.Local)
+	t2, _ := time.ParseInLocation("2006-01-02", end_time, time.Local)
+	age := t2.Year() - t1.Year()
+	if t2.Month() < t1.Month() || (t2.Month() == t1.Month() && t2.Day() < t1.Day()) {
+		age--
+	}
+	return age
+}
+
+//获取相差时间-秒
+func GetSecondDifferByTime(start_time, end_time time.Time) int64 {
+	diff := end_time.Unix() - start_time.Unix()
+	return diff
+}
+
+func FixFloat(f float64, m int) float64 {
+	newn := SubFloatToString(f+0.00000001, m)
+	newf, _ := strconv.ParseFloat(newn, 64)
+	return newf
+}
+
+// 将字符串数组转化为逗号分割的字符串形式  ["str1","str2","str3"] >>> "str1,str2,str3"
+func StrListToString(strList []string) (str string) {
+	if len(strList) > 0 {
+		for k, v := range strList {
+			if k == 0 {
+				str = v
+			} else {
+				str = str + "," + v
+			}
+		}
+		return
+	}
+	return ""
+}
+
+//Token
+func GetToken() string {
+	randStr := GetRandString(64)
+	token := MD5(randStr + Md5Key)
+	tokenLen := 64 - len(token)
+	return strings.ToUpper(token + GetRandString(tokenLen))
+}
+
+//数据没有记录
+func ErrNoRow() string {
+	return "<QuerySeter> no row found"
+}
+
+//校验邮箱格式
+func ValidateEmailFormatat(email string) bool {
+	reg := regexp.MustCompile(RegularEmail)
+	return reg.MatchString(email)
+}
+
+//验证是否是手机号
+func ValidateMobileFormatat(mobileNum string) bool {
+	reg := regexp.MustCompile(RegularMobile)
+	return reg.MatchString(mobileNum)
+}
+
+//判断文件是否存在
+func FileIsExist(filePath string) bool {
+	_, err := os.Stat(filePath)
+	return err == nil || os.IsExist(err)
+}
+
+//获取图片扩展名
+func GetImgExt(file string) (ext string, err error) {
+	var headerByte []byte
+	headerByte = make([]byte, 8)
+	fd, err := os.Open(file)
+	if err != nil {
+		return "", err
+	}
+	defer fd.Close()
+	_, err = fd.Read(headerByte)
+	if err != nil {
+		return "", err
+	}
+	xStr := fmt.Sprintf("%x", headerByte)
+	switch {
+	case xStr == "89504e470d0a1a0a":
+		ext = ".png"
+	case xStr == "0000010001002020":
+		ext = ".ico"
+	case xStr == "0000020001002020":
+		ext = ".cur"
+	case xStr[:12] == "474946383961" || xStr[:12] == "474946383761":
+		ext = ".gif"
+	case xStr[:10] == "0000020000" || xStr[:10] == "0000100000":
+		ext = ".tga"
+	case xStr[:8] == "464f524d":
+		ext = ".iff"
+	case xStr[:8] == "52494646":
+		ext = ".ani"
+	case xStr[:4] == "4d4d" || xStr[:4] == "4949":
+		ext = ".tiff"
+	case xStr[:4] == "424d":
+		ext = ".bmp"
+	case xStr[:4] == "ffd8":
+		ext = ".jpg"
+	case xStr[:2] == "0a":
+		ext = ".pcx"
+	default:
+		ext = ""
+	}
+	return ext, nil
+}
+
+//保存图片
+func SaveImage(path string, img image.Image) (err error) {
+	//需要保持的文件
+	imgfile, err := os.Create(path)
+	defer imgfile.Close()
+	// 以PNG格式保存文件
+	err = png.Encode(imgfile, img)
+	return err
+}
+
+//保存base64数据为文件
+func SaveBase64ToFile(content, path string) error {
+	data, err := base64.StdEncoding.DecodeString(content)
+	if err != nil {
+		return err
+	}
+	f, err := os.Create(path)
+	defer f.Close()
+	if err != nil {
+		return err
+	}
+	f.Write(data)
+	return nil
+}
+
+func SaveBase64ToFileBySeek(content, path string) (err error) {
+	data, err := base64.StdEncoding.DecodeString(content)
+	exist,err:=PathExists(path)
+	if err!=nil {
+		return
+	}
+	if !exist {
+		f, err := os.Create(path)
+		if err!=nil {
+			return err
+		}
+		n, _ := f.Seek(0, 2)
+		// 从末尾的偏移量开始写入内容
+		_, err = f.WriteAt([]byte(data), n)
+		defer f.Close()
+	}else{
+		f, err := os.OpenFile(path, os.O_WRONLY, 0644)
+		if err!=nil {
+			return err
+		}
+		n, _ := f.Seek(0, 2)
+		// 从末尾的偏移量开始写入内容
+		_, err = f.WriteAt([]byte(data), n)
+		defer f.Close()
+	}
+
+	return nil
+}
+
+func PathExists(path string) (bool,error) {
+	_, err := os.Stat(path)
+	if err == nil {
+		return true, nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
+
+func StartIndex(page, pagesize int) int {
+	if page > 1 {
+		return (page - 1) * pagesize
+	}
+	return 0
+}
+func PageCount(count, pagesize int) int {
+	if count%pagesize > 0 {
+		return count/pagesize + 1
+	} else {
+		return count / pagesize
+	}
+}
+
+func TrimHtml(src string) string {
+	//将HTML标签全转换成小写
+	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllStringFunc(src, strings.ToLower)
+
+	re, _ = regexp.Compile("\\<img[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "[图片]")
+
+	re, _ = regexp.Compile("class[\\S\\s]+?>")
+	src = re.ReplaceAllString(src, "")
+	re, _ = regexp.Compile("\\<[\\S\\s]+?\\>")
+	src = re.ReplaceAllString(src, "")
+	return strings.TrimSpace(src)
+}
+
+//1556164246  ->  2019-04-25 03:50:46 +0000
+//timestamp
+
+func TimeToTimestamp() {
+	fmt.Println(time.Unix(1556164246, 0).Format("2006-01-02 15:04:05"))
+}
+
+func ToUnicode(text string) string {
+	textQuoted := strconv.QuoteToASCII(text)
+	textUnquoted := textQuoted[1 : len(textQuoted)-1]
+	return textUnquoted
+}
+
+func VersionToInt(version string) int {
+	version = strings.Replace(version, ".", "", -1)
+	n, _ := strconv.Atoi(version)
+	return n
+}
+func IsCheckInList(list []int, s int) bool {
+	for _, v := range list {
+		if v == s {
+			return true
+		}
+	}
+	return false
+
+}
+
+func round(num float64) int {
+	return int(num + math.Copysign(0.5, num))
+}
+
+func toFixed(num float64, precision int) float64 {
+	output := math.Pow(10, float64(precision))
+	return float64(round(num*output)) / output
+}
+
+// GetWilsonScore returns Wilson Score
+func GetWilsonScore(p, n float64) float64 {
+	if p == 0 && n == 0 {
+		return 0
+	}
+
+	return toFixed(((p+1.9208)/(p+n)-1.96*math.Sqrt(p*n/(p+n)+0.9604)/(p+n))/(1+3.8416/(p+n)), 2)
+}
+
+//将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
+func ChangeWordsToNum(str string) (numStr string) {
+	words := ([]rune)(str)
+	num := 0
+	n := 0
+	for i := 0; i < len(words); i++ {
+		word := string(words[i : i+1])
+		switch word {
+		case "万":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 10000
+			num = num*10000 + n
+			n = 0
+		case "千":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 1000
+			num += n
+			n = 0
+		case "百":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 100
+			num += n
+			n = 0
+		case "十":
+			if n == 0 {
+				n = 1
+			}
+			n = n * 10
+			num += n
+			n = 0
+		case "一":
+			n += 1
+		case "二":
+			n += 2
+		case "三":
+			n += 3
+		case "四":
+			n += 4
+		case "五":
+			n += 5
+		case "六":
+			n += 6
+		case "七":
+			n += 7
+		case "八":
+			n += 8
+		case "九":
+			n += 9
+		case "零":
+		default:
+			if n > 0 {
+				num += n
+				n = 0
+			}
+			if num == 0 {
+				numStr += word
+			} else {
+				numStr += strconv.Itoa(num) + word
+				num = 0
+			}
+		}
+	}
+	if n > 0 {
+		num += n
+		n = 0
+	}
+	if num != 0 {
+		numStr += strconv.Itoa(num)
+	}
+	return
+}
+
+func Sha1(data string) string {
+	sha1 := sha1.New()
+	sha1.Write([]byte(data))
+	return hex.EncodeToString(sha1.Sum([]byte("")))
+}

+ 37 - 0
utils/config.go

@@ -0,0 +1,37 @@
+package utils
+
+import (
+	"github.com/astaxie/beego"
+)
+
+var (
+	RunMode        string //运行模式
+	MYSQL_URL      string //数据库连接
+	MYSQL_URL_RDDP      string //数据库连接
+	MYSQL_URL_EDB  string
+)
+
+var (
+	CompanyId int
+)
+
+func init() {
+	RunMode = beego.AppConfig.String("run_mode")
+	config, err := beego.AppConfig.GetSection(RunMode)
+	if err != nil {
+		panic("配置文件读取错误 " + err.Error())
+	}
+	beego.Info(RunMode+" 模式")
+	MYSQL_URL = config["mysql_url"]
+	MYSQL_URL_RDDP = config["mysql_url_rddp"]
+	MYSQL_URL_EDB=config["mysql_url_edb"]
+
+	if RunMode == "release" {
+		CompanyId=16
+	}else{
+		CompanyId=16
+	}
+}
+
+//http://entryapi.brilliantstart.cn
+//http://entryapi.brilliantstart.cn/swagger/

+ 60 - 0
utils/constants.go

@@ -0,0 +1,60 @@
+package utils
+
+const (
+	Md5Key = "Ks@h64WJ#tcVgG8$&WlNfqvLAtMgpxWN"
+)
+
+//常量定义
+const (
+	FormatTime            = "15:04:05"                //时间格式
+	FormatDate            = "2006-01-02"              //日期格式
+	FormatDateTime        = "2006-01-02 15:04:05"     //完整时间格式
+	HlbFormatDateTime     = "2006-01-02_15:04:05.999" //完整时间格式
+	FormatDateTimeUnSpace = "20060102150405"          //完整时间格式
+	PageSize15            = 15                        //列表页每页数据量
+	PageSize5             = 5
+	PageSize10            = 10
+	PageSize20            = 20
+	PageSize30            = 30
+)
+
+const (
+	APPNAME          = "弘则-数据录入"
+	EmailSendToUsers = "317699326@qq.com"
+)
+
+//手机号,电子邮箱正则
+const (
+	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
+	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
+)
+
+//验证码code
+const (
+	REGISTER_CODE = iota + 1 //注册
+	LOGIN_CODE               //登录
+)
+
+//聚合短信
+var (
+	TplId    = "65692"
+	JhAppKey = "4c8504c49dd335e99cfd7b6a3a9e2415"
+)
+
+//科大讯飞--语音合成
+const (
+	XfSTATUS_FIRST_FRAME    = 0 //第一帧标识
+	XfSTATUS_CONTINUE_FRAME = 1 //中间帧标识
+	XfSTATUS_LAST_FRAME     = 2 //最后一帧标识
+	XfAPPID               = "5ed70e9d"
+	XfAPIKey                = "d580509ca262e9586fb65a7064d5ce77"
+	XfAPISecret             = "a085720dc55850c720fa5576335f847a"
+	XfHostUrl               = "wss://tts-api.xfyun.cn/v2/tts"
+	XfOrigin                = "http://tts-api.xfyun.cn/"
+	XfHost                  = "tts-api.xfyun.cn"
+)
+
+const (
+	EmailSendToHzUsers = "544935339@qq.com;lnyan@hzinsights.com;pdzhao@hzinsights.com;317699326@qq.com"
+)
+

+ 60 - 0
utils/email.go

@@ -0,0 +1,60 @@
+package utils
+
+import (
+	"fmt"
+	"gopkg.in/gomail.v2"
+	"strings"
+)
+
+//发送邮件
+func SendEmail(title, content string, touser string)bool {
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	}else{
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "local.circle@qq.com")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title+" "+GetRandString(16))
+	m.SetBody("text/html", content)
+
+	d := gomail.NewDialer("smtp.qq.com", 587, "local.circle@qq.com", "iyrzdcsrmmbabbge")
+	if err := d.DialAndSend(m); err != nil {
+		return false
+	}
+	return true
+}
+
+//发送邮件
+func SendEmailByHongze(title, content string, touser,attachPath string)bool {
+	var arr []string
+	sub := strings.Index(touser, ";")
+	if sub >= 0 {
+		spArr := strings.Split(touser, ";")
+		for _, v := range spArr {
+			arr = append(arr, v)
+		}
+	}else{
+		arr = append(arr, touser)
+	}
+	m := gomail.NewMessage()
+	m.SetHeader("From", "lnyan@hzinsights.com")
+	m.SetHeader("To", arr...)
+	m.SetHeader("Subject", title+" "+GetRandStringNoSpecialChar(8))
+	m.SetBody("text/html", content)
+
+	//body := new(bytes.Buffer)
+	m.Attach(attachPath)
+	d := gomail.NewDialer("smtp.mxhichina.com", 465, "lnyan@hzinsights.com", "sxbjYLN1988")
+	if err := d.DialAndSend(m); err != nil {
+		fmt.Println("send err:",err.Error())
+		return false
+	}
+	return true
+}

+ 45 - 0
utils/jwt.go

@@ -0,0 +1,45 @@
+package utils
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/astaxie/beego/logs"
+	"github.com/dgrijalva/jwt-go"
+)
+
+var (
+	KEY = []byte("5Mb5Gdmb5x")
+)
+
+// 发放token
+func GenToken(account string) string {
+	token := jwt.New(jwt.SigningMethodHS256)
+	token.Claims = &jwt.StandardClaims{
+		NotBefore: int64(time.Now().Unix()),
+		ExpiresAt: int64(time.Now().Unix() + 3600*3),
+		Issuer:    "csdp",
+		Subject:   account,
+	}
+	ss, err := token.SignedString(KEY)
+	if err != nil {
+		logs.Error(err)
+		return ""
+	}
+	return ss
+}
+
+// 校验token
+func CheckToken(account, token string) bool {
+	t, err := jwt.Parse(token, func(*jwt.Token) (interface{}, error) {
+		return KEY, nil
+	})
+	if err != nil {
+		fmt.Println(err.Error())
+		return false
+	}
+	if account != t.Claims.(jwt.MapClaims)["sub"] {
+		return false
+	}
+	return t.Valid
+}

+ 12 - 0
utils/logs.go

@@ -0,0 +1,12 @@
+package utils
+
+import (
+	"github.com/astaxie/beego/logs"
+)
+
+var FileLog *logs.BeeLogger
+
+func init() {
+	FileLog = logs.NewLogger(1000000)
+	FileLog.SetLogger(logs.AdapterFile, `{"filename":"./rdlucklog/hongze_task.log"}`)
+}