Эх сурвалжийг харах

feat 定时任务新增同步报告到同花顺

Roc 3 жил өмнө
parent
commit
c0bb6125cc

+ 1 - 0
.gitignore

@@ -11,3 +11,4 @@ hongze_task
 go.sum
 go.mod
 /lastupdate.tmp
+.DS_Store

+ 15 - 20
go.sum

@@ -1,18 +1,18 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
-github.com/PuerkitoBio/goquery v1.7.1 h1:oE+T06D+1T7LNrn91B4aERsRIeCLJ/oPSa6xB9FPnz4=
-github.com/PuerkitoBio/goquery v1.7.1/go.mod h1:XY0pP4kfraEmmV1O7Uf6XyjoslwsneBbgeDjLYuN8xY=
+github.com/PuerkitoBio/goquery v1.6.1 h1:FgjbQZKl5HTmcn4sKBgvx8vv63nhyhIpv7lJpFGCWpk=
+github.com/PuerkitoBio/goquery v1.6.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
-github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible h1:D3gwOr9qUUmyyBRDbpnATqu+EkqqmigFd3Od6xO1QUU=
-github.com/aliyun/aliyun-oss-go-sdk v2.1.10+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
-github.com/andybalholm/cascadia v1.2.0 h1:vuRCkM5Ozh/BfmsaTm26kbjm0mIOM3yS5Ek/F5h18aE=
-github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
+github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible h1:hLUNPbx10wawWW7DeNExvTrlb90db3UnnNTFKHZEFhE=
+github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
+github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
+github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
 github.com/antlr/antlr4 v0.0.0-20190325153624-837aa60e2c47 h1:Lp5nUoQzppfVmfZadpzAytNyb5IMtxyOJLzoQS5dExg=
 github.com/antlr/antlr4 v0.0.0-20190325153624-837aa60e2c47/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
 github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ=
@@ -54,7 +54,6 @@ github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
 github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@@ -108,9 +107,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
+github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
-github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
@@ -181,9 +179,10 @@ github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
 github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
 github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
+github.com/wenzhenxi/gorsa v0.0.0-20210524035706-528c7050d703 h1:Tiqr9EWpYopXZf668mgTNWguzE6ssRIEviULO3gSWnU=
+github.com/wenzhenxi/gorsa v0.0.0-20210524035706-528c7050d703/go.mod h1:nfhBTKji6rC8lrjyikx8NJ85JHg6ZQam0a9Je+2RVOg=
 github.com/yidane/formula v0.0.0-20200220154705-ec0e6bc4831b h1:e9CwJGPvgp5/7wHQcQg0ImESNHOTQfyrrPj6QYloA6A=
 github.com/yidane/formula v0.0.0-20200220154705-ec0e6bc4831b/go.mod h1:vUhtXwXDSh8NKHxIGRY1HvLhoC4Hba1RL62whvmtPUk=
-github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod h1:Nv7wKD2/bCdKUFNKcJRa99a+1+aSLlCRJFriFYdjz/I=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
 go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
@@ -218,9 +217,9 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
-golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -239,18 +238,14 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
-golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
+golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

+ 257 - 0
models/classify.go

@@ -0,0 +1,257 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"rdluck_tools/paging"
+	"time"
+)
+
+type Classify struct {
+	Id             int       `orm:"column(id);pk"`
+	ClassifyName   string    `description:"分类名称"`
+	Sort           int       `json:"-"`
+	ParentId       int       `description:"父级分类id"`
+	CreateTime     time.Time `description:"创建时间"`
+	ModifyTime     time.Time `description:"修改时间"`
+	Abstract       string    `description:"栏目简介"`
+	Descript       string    `description:"分享描述"`
+	ReportAuthor   string    `description:"栏目作者"`
+	AuthorDescript string    `description:"作者简介"`
+	ColumnImgUrl   string    `description:"栏目配图"`
+	HeadImgUrl     string    `description:"头部banner"`
+	AvatarImgUrl   string    `description:"头像"`
+	ReportImgUrl   string    `description:"报告配图"`
+	HomeImgUrl     string    `description:"首页配图"`
+	ClassifyLabel  string    `description:"分类标签"`
+}
+
+type ClassifyAddReq struct {
+	ClassifyName   string `description:"分类名称"`
+	ParentId       int    `description:"父级分类id,没有父级分类传0"`
+	Abstract       string `description:"栏目简介"`
+	Descript       string `description:"分享描述"`
+	ReportAuthor   string `description:"栏目作者"`
+	AuthorDescript string `description:"作者简介"`
+	ColumnImgUrl   string `description:"栏目配图"`
+	ReportImgUrl   string `description:"报告配图"`
+	HeadImgUrl     string `description:"头部banner"`
+	AvatarImgUrl   string `description:"头像"`
+	HomeImgUrl     string `description:"首页配图"`
+	ClassifyLabel  string `description:"分类标签"`
+}
+
+func GetClassifyByName(classifyName string, parentId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE classify_name=? AND parent_id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, classifyName, parentId).QueryRow(&item)
+	return
+}
+
+func GetClassifyById(classifyId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+//添加分类
+func AddClassify(item *Classify) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Insert(item)
+	return
+}
+
+func GetReportCountByClassifyId(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT COUNT(1) AS count FROM report WHERE classify_id_second=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func GetClassifySubCountByClassifyId(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT COUNT(1) as num FROM classify AS a
+        INNER JOIN report AS b ON a.id=b.classify_id_second
+        WHERE a.parent_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func GetClassifySubCountByParentId(classifyId int) (count int, err error) {
+	sqlCount := `
+	SELECT COUNT(1) as num FROM classify AS a
+	WHERE a.parent_id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sqlCount, classifyId).QueryRow(&count)
+	return
+}
+
+//删除分类
+func DeleteClassify(classifyId int) (err error) {
+	sql := `DELETE FROM classify WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, classifyId).Exec()
+	if err != nil {
+		return
+	}
+	deleteImgSql := `DELETE FROM banner WHERE classify_id=? `
+	_, err = o.Raw(deleteImgSql, classifyId).Exec()
+	return
+}
+
+//classifyName, abstract, descript string, parentId, classifyId int
+//修改分类
+func EditClassify(req *EditClassifyReq) (err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `UPDATE classify SET classify_name = ?,abstract=?, parent_id= ?,descript=?,report_author=?,author_descript=?,column_img_url=?,head_img_url=?,avatar_img_url=?,report_img_url=?,home_img_url=?,classify_label=?, modify_time= NOW() WHERE id = ? `
+	_, err = o.Raw(sql, req.ClassifyName, req.Abstract, req.ParentId, req.Descript, req.ReportAuthor, req.AuthorDescript, req.ColumnImgUrl, req.HeadImgUrl, req.AvatarImgUrl, req.ReportImgUrl, req.HomeImgUrl, req.ClassifyLabel, req.ClassifyId).Exec()
+	return
+}
+
+//获取父级分类
+
+func ParentClassify() (items []*Classify, err error) {
+	sql := `SELECT * FROM classify WHERE parent_id=0 order by id desc `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+//根据id获取分类详情
+func FindByIdClassify(classifyId int) (item *Classify, err error) {
+	sql := `SELECT * FROM classify WHERE id=? `
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+type ClassifyList struct {
+	Id            int       `orm:"column(id);pk"`
+	ClassifyName  string    `description:"分类名称"`
+	Sort          int       `json:"-"`
+	ParentId      int       `description:"父级分类id"`
+	CreateTime    time.Time `description:"创建时间"`
+	ModifyTime    time.Time `description:"修改时间"`
+	Abstract      string    `description:"简介"`
+	Descript      string    `description:"描述"`
+	ClassifyLabel string    `description:"分类标签"`
+	Child         []*Classify
+}
+
+type ClassifyListResp struct {
+	List   []*ClassifyList
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+//获取分类列表
+func GetClassifyList(startSize, pageSize int, keyWord, companyType string) (items []*ClassifyList, err error) {
+	sql := ``
+	companyTypeSqlStr := ``
+	if companyType == "ficc" {
+		companyTypeSqlStr = " AND id != 40 AND parent_id != 40 "
+	} else if companyType == "权益" {
+		companyTypeSqlStr = " AND (id = 40 or parent_id = 40)  "
+	}
+	if keyWord != "" {
+		sql = `SELECT * FROM (
+                   SELECT * FROM classify
+                   WHERE parent_id=0 ` + companyTypeSqlStr + `  AND classify_name LIKE '%` + keyWord + `%'
+                   UNION
+                   SELECT * FROM classify
+                   WHERE id IN(SELECT parent_id FROM classify
+                   WHERE parent_id>0 ` + companyTypeSqlStr + `  AND classify_name LIKE '%` + keyWord + `%')
+                   )AS t
+                   ORDER BY create_time ASC
+                   LIMIT ?,? `
+	} else {
+		sql = `SELECT * FROM classify WHERE parent_id=0 ` + companyTypeSqlStr + ` ORDER BY create_time ASC LIMIT ?,? `
+	}
+	o := orm.NewOrm()
+	o.Using("rddp")
+	_, err = o.Raw(sql, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetClassifyListCount(keyWord, companyType string) (count int, err error) {
+	sqlCount := ``
+
+	companyTypeSqlStr := ``
+	if companyType == "ficc" {
+		companyTypeSqlStr = " AND id != 40 AND parent_id != 40 "
+	} else if companyType == "权益" {
+		companyTypeSqlStr = " AND (id = 40 or parent_id = 40)  "
+	}
+	if keyWord != "" {
+		sqlCount = `SELECT  COUNT(1) AS count FROM (
+               SELECT * FROM classify
+               WHERE parent_id=0 ` + companyTypeSqlStr + `  AND classify_name LIKE '%` + keyWord + `%'
+               UNION
+               SELECT * FROM classify
+               WHERE id IN(SELECT parent_id FROM classify
+               WHERE parent_id>0 ` + companyTypeSqlStr + `  AND classify_name LIKE '%` + keyWord + `%')
+               )AS t `
+
+	} else {
+		sqlCount = `SELECT COUNT(1) AS count FROM classify WHERE parent_id=0 ` + companyTypeSqlStr
+	}
+	o := orm.NewOrm()
+	o.Using("rddp")
+	err = o.Raw(sqlCount).QueryRow(&count)
+	return
+}
+
+type CheckDeleteClassifyReq struct {
+	ClassifyId int `description:"分类ID"`
+}
+
+type CheckDeleteClassifyResp struct {
+	Code int    `description:"编码:0:检测成功,可进行删除,1:分类不存在,2:该分类有关联报告,不允许删除,3:二级分类有关联报告,不允许删除,4:该分类下有关联分类,是否确认全部删除"`
+	Msg  string `description:"描述信息"`
+}
+
+type DeleteClassifyReq struct {
+	ClassifyId int `description:"分类ID"`
+}
+
+type EditClassifyReq struct {
+	ClassifyId     int    `description:"分类ID"`
+	ClassifyName   string `description:"分类名称"`
+	ParentId       int    `description:"父级分类id"`
+	Abstract       string `description:"栏目简介"`
+	Descript       string `description:"分享描述"`
+	ReportAuthor   string `description:"栏目作者"`
+	AuthorDescript string `description:"作者简介"`
+	ColumnImgUrl   string `description:"栏目配图"`
+	HeadImgUrl     string `description:"头部banner"`
+	AvatarImgUrl   string `description:"头像"`
+	ReportImgUrl   string `description:"报告配图"`
+	HomeImgUrl     string `description:"首页配图"`
+	ClassifyLabel  string `description:"分类标签"`
+}
+
+type FindByIdClassifyReq struct {
+	ClassifyId int `description:"分类ID"`
+}
+
+func GetClassifyChild(parentId int, keyWord string) (items []*Classify, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := ``
+	if keyWord != "" {
+		sql = `SELECT * FROM classify WHERE parent_id=? AND classify_name LIKE '%` + keyWord + `%' ORDER BY create_time ASC `
+	} else {
+		sql = `SELECT * FROM classify WHERE parent_id=? ORDER BY create_time ASC `
+	}
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}

+ 3 - 0
models/db.go

@@ -65,5 +65,8 @@ func init() {
 		new(data_manage.EdbDataPb),
 		new(LongzhongSurveyProduct),
 		new(LongzhongSurveyData),
+		new(Classify),
+		new(ReportSendThsDetail),
+		new(Report),
 	)
 }

+ 32 - 6
models/report.go

@@ -8,9 +8,35 @@ import (
 )
 
 type Report struct {
-	Id         int
-	Content    string
-	ContentSub string
+	Id                 int       `orm:"column(id)" description:"报告Id"`
+	AddType            int       `description:"新增方式:1:新增报告,2:继承报告"`
+	ClassifyIdFirst    int       `description:"一级分类id"`
+	ClassifyNameFirst  string    `description:"一级分类名称"`
+	ClassifyIdSecond   int       `description:"二级分类id"`
+	ClassifyNameSecond string    `description:"二级分类名称"`
+	Title              string    `description:"标题"`
+	Abstract           string    `description:"摘要"`
+	Author             string    `description:"作者"`
+	Frequency          string    `description:"频度"`
+	CreateTime         string    `description:"创建时间"`
+	ModifyTime         time.Time `description:"修改时间"`
+	State              int       `description:"1:未发布,2:已发布"`
+	PublishTime        time.Time `description:"发布时间"`
+	Stage              int       `description:"期数"`
+	MsgIsSend          int       `description:"消息是否已发送,0:否,1:是"`
+	Content            string    `description:"内容"`
+	VideoUrl           string    `description:"音频文件URL"`
+	VideoName          string    `description:"音频文件名称"`
+	VideoPlaySeconds   string    `description:"音频播放时长"`
+	ContentSub         string    `description:"内容前两个章节"`
+}
+
+func GetReportById(reportId int) (item *Report, err error) {
+	o := orm.NewOrm()
+	o.Using("rddp")
+	sql := `SELECT * FROM report WHERE id=?`
+	err = o.Raw(sql, reportId).QueryRow(&item)
+	return
 }
 
 func GetReport() (items []*Report, err error) {
@@ -46,8 +72,8 @@ func EditReportContent(reportId int, content, contentSub string) (err error) {
 }
 
 //删除报告日志记录-保留3个月
-func DeleteReportSaveLog()  {
-	startDateTime:=time.Now().AddDate(0,-3,0).Format(utils.FormatDateTime)
+func DeleteReportSaveLog() {
+	startDateTime := time.Now().AddDate(0, -3, 0).Format(utils.FormatDateTime)
 	fmt.Println(startDateTime)
 }
 
@@ -57,4 +83,4 @@ func EditReportContentHtml(reportId int, content string) (err error) {
 	sql := ` UPDATE report SET content=?,modify_time=NOW() WHERE id=? `
 	_, err = o.Raw(sql, content, reportId).Exec()
 	return
-}
+}

+ 61 - 0
models/report_send_ths_detail.go

@@ -0,0 +1,61 @@
+package models
+
+import (
+	"rdluck_tools/orm"
+	"time"
+)
+
+//报告推送给同花顺的表结构体
+type ReportSendThsDetail struct {
+	SendId     int       `orm:"column(send_id);pk" description:"发送给同花顺的Id"`
+	ReportId   int       `description:"报告id"`
+	ReportType string    `description:"报告类型"`
+	Status     int8      `description:"发送结果,0:待发送,-1发送失败,1发送成功"`
+	Remark     string    `description:"失败原因"`
+	PushTime   time.Time `description:"实际开始推送时间/预推送时间"`
+	CreateTime time.Time `description:"发送时间"`
+}
+
+//新增报告发送给同花顺的记录
+func AddReportSendThsDetail(item *ReportSendThsDetail) (lastId int64, err error) {
+	o := orm.NewOrm()
+	//o.Using("rddp")
+	lastId, err = o.Insert(item)
+	return
+}
+
+//修改报告发送给同花顺的记录状态
+func ModifyReportSendThsDetailStatus(sendId int, status int8, remark string) (err error) {
+	o := orm.NewOrm()
+	//o.Using("rddp")
+	sql := `UPDATE report_send_ths_detail SET status = ?,remark=? WHERE send_id = ? `
+	_, err = o.Raw(sql, status, remark, sendId).Exec()
+	return
+}
+
+//根据报告id获取发送记录
+func GetReportSendThsDetailByReportId(reportId int, reportType string) (item *ReportSendThsDetail, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM report_send_ths_detail WHERE report_id=? and report_type=? order by send_id desc`
+	//o.Using("rddp")
+	err = o.Raw(sql, reportId, reportType).QueryRow(&item)
+	return
+}
+
+// GetLatelyReportSendThsDetail 获取发送中/发送成功的 距离现在最近的一条记录
+func GetLatelyReportSendThsDetail() (item *ReportSendThsDetail, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM report_send_ths_detail WHERE status >=0  order by push_time,send_id desc`
+	//o.Using("rddp")
+	err = o.Raw(sql).QueryRow(&item)
+	return
+}
+
+// GetWaitReportSendThsDetailList 获取当前需要推送的报告记录
+func GetWaitReportSendThsDetailList() (list []*ReportSendThsDetail, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM report_send_ths_detail WHERE status = 2 and push_time <=now() order by send_id asc`
+	//o.Using("rddp")
+	_, err = o.Raw(sql).QueryRows(&list)
+	return
+}

+ 229 - 0
services/report_push.go

@@ -0,0 +1,229 @@
+package services
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/wenzhenxi/gorsa"
+	"hongze/hongze_task/models"
+	"hongze/hongze_task/utils"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"time"
+)
+
+//func init() {
+//	report, _ := models.GetReportById(836)
+//	SendReportToThs(report)
+//}
+
+// SendWaitReport 定时向同花顺推送报告
+func SendWaitReport(cont context.Context) (err error) {
+	defer func() {
+		if err != nil {
+			//fmt.Println(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送消息至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+			go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "延时任务发送报告至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+		}
+	}()
+	fmt.Println("进来了", time.Now().Format(utils.FormatDateTime))
+	list, err := models.GetWaitReportSendThsDetailList()
+	if err != nil {
+		return
+	}
+	for _, detail := range list {
+		//先标记为
+		_ = models.ModifyReportSendThsDetailStatus(detail.SendId, 0, "")
+		go SendToThs(detail.SendId, detail.ReportId, detail.ReportType)
+
+	}
+	return
+}
+
+var permissionMap map[string]string = map[string]string{
+	"化里化外日评":    "原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱",
+	"股债日评":      "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"贵金属复盘":     "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"每日经济数据备忘录": "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"宏观商品复盘":    "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"知白守黑日评":    "钢材,铁矿,双焦(焦煤、焦炭)",
+	"有声有色日度闲篇":  "有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"EIA原油库存点评": "原油",
+	"苯乙烯数据点评":   "苯乙烯",
+	"API原油库存点评": "原油",
+	"铁矿航运数据点评":  "铁矿",
+	"中观需求点评":    "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"聚酯数据点评":    "PTA,MEG",
+	"钢材周度数据点评":  "钢材",
+	"寻根知本":      "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"国际宏观":      "宏观,利率债,原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱,钢材,铁矿,双焦(焦煤、焦炭),有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"能化百家谈":     "原油,PTA,MEG,织造终端,甲醇,聚烯烃,沥青,橡胶,苯乙烯,玻璃纯碱",
+	"有色百家谈":     "有色(铜、铝),有色(锌、铅),镍+不锈钢",
+	"黑色百家谈":     "钢材,铁矿,双焦(焦煤、焦炭)",
+}
+
+//同花顺返回信息
+type TshResult struct {
+	ErrorCode int    `json:"error" description:"错误状态码"`
+	Message   string `json:"message" description:"提示信息"`
+}
+
+func SendToThs(sendDetailId, reportId int, reportType string) (err error) {
+	switch reportType {
+	case "日度点评":
+		tmpErr := SendReportToThs(reportId)
+		if tmpErr != nil {
+			err = tmpErr
+		}
+	default:
+		err = errors.New("异常类型")
+	}
+
+	if err != nil {
+		_ = models.ModifyReportSendThsDetailStatus(sendDetailId, -1, err.Error())
+		err = nil
+		return
+	}
+	_ = models.ModifyReportSendThsDetailStatus(sendDetailId, 1, "")
+	return
+}
+
+// SendReportToThs 发送报告到同花顺
+func SendReportToThs(reportId int) (err error) {
+	defer func() {
+		if err != nil {
+			//fmt.Println(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送消息至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+			go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送报告至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+		}
+	}()
+
+	report, tmpErr := models.GetReportById(reportId)
+	if tmpErr != nil {
+		err = tmpErr
+		return
+	}
+	//获取分类信息(标签)
+	permissionName := report.ClassifyNameSecond
+	classifyItem, err := models.GetClassifyById(report.ClassifyIdSecond)
+	if err != nil {
+		err = errors.New(fmt.Sprint("获取分类失败:", permissionName))
+	}
+
+	//获取权限标签名称
+	var permissionStr string
+	if classifyItem != nil {
+		permissionStr = classifyItem.ClassifyLabel
+		if permissionStr == "" {
+			var isOk bool
+			permissionStr, isOk = permissionMap[permissionName]
+			if !isOk {
+				err = errors.New(fmt.Sprint("没有该权限的标签,权限名:", permissionName))
+				return
+			}
+		}
+	} else {
+		var isOk bool
+		permissionStr, isOk = permissionMap[permissionName]
+		if !isOk {
+			err = errors.New(fmt.Sprint("没有该权限的标签,权限名:", permissionName))
+			return
+		}
+	}
+	if permissionStr == "" {
+		err = errors.New(fmt.Sprint("没有该权限的标签,权限名:", permissionName))
+		return
+	}
+
+	//fmt.Println("sendDetailId:", sendDetailId)
+	stageStr := fmt.Sprintf("%v", report.Stage)
+	createDate, err := time.Parse(utils.FormatDateTime, report.CreateTime)
+	createDateFrom := createDate.Format("0102")
+	title := `【第` + stageStr + `期|FICC】` + report.Title + `(` + createDateFrom + ")"
+
+	// 跳转地址
+	jumpBaseUrl := `http://rddpweb.brilliantstart.cn/reportdtl?id=`
+	//生产环境地址
+	if utils.RunMode == "release" {
+		jumpBaseUrl = `https://ficc.hzinsights.com/reportdtl?id=`
+	}
+	jumpUrl := fmt.Sprint(jumpBaseUrl, report.Id)
+
+	// logo 地址
+	logoUrl := `https://hongze.oss-cn-shanghai.aliyuncs.com/hzyj.png`
+
+	// 简介
+	abstract := report.Abstract
+
+	// 实际推送到同花顺
+	err = SendThs(title, permissionStr, abstract, jumpUrl, logoUrl)
+
+	return
+}
+
+// SendThs 发送消息到同花顺
+func SendThs(title, labelStr, abstract, jumpBaseUrl, logoUrl string) (err error) {
+	defer func() {
+		if err != nil {
+			//fmt.Println(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送消息至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+			go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "发送报告至同花顺失败 ErrMsg:"+err.Error(), utils.EmailSendToUsers)
+		}
+	}()
+	pubKey := utils.THS_PubKey
+	sendUrl := utils.THS_SendUrl
+	//fmt.Println("sendUrl:", sendUrl)
+
+	utils.FileLog.Info("title:%s", title)
+	title, err = gorsa.PublicEncrypt(title, pubKey)
+	utils.FileLog.Info("labelStr:%s", labelStr)
+	abstract, err = gorsa.PublicEncrypt(abstract, pubKey)
+	if err != nil {
+		return
+	}
+	label, err := gorsa.PublicEncrypt(labelStr, pubKey)
+	if err != nil {
+		return
+	}
+	jumpUrl, err := gorsa.PublicEncrypt(jumpBaseUrl, pubKey)
+	if err != nil {
+		return
+	}
+	picUrl, err := gorsa.PublicEncrypt(logoUrl, pubKey)
+	if err != nil {
+		return
+	}
+
+	//开始发送
+	client := http.Client{}
+	form := url.Values{}
+	form.Add("title", title)
+	form.Add("description", abstract)
+	form.Add("label", label)
+	form.Add("url", jumpUrl)
+	form.Add("icon", picUrl)
+
+	utils.FileLog.Info("SendThs parms:%s", form.Encode())
+	resp, err := client.PostForm(sendUrl, form)
+	if err != nil {
+		return
+	}
+	defer resp.Body.Close()
+
+	body, _ := ioutil.ReadAll(resp.Body)
+
+	//fmt.Println(string(body))
+	utils.FileLog.Info("ThsResult parms:%s", string(body))
+
+	//同花顺接口返回数据
+	var tshResult TshResult
+	err = json.Unmarshal(body, &tshResult)
+	if err != nil {
+		err = errors.New(fmt.Sprint("同花顺接口返回数据转换成结构体异常,Err:", err))
+		return
+	}
+	if tshResult.ErrorCode != 1 {
+		err = errors.New(fmt.Sprint("发送数据到同花顺接口异常,result:", string(body)))
+		return
+	}
+	return
+}

+ 4 - 0
services/task.go

@@ -44,6 +44,10 @@ func Task() {
 	stackCompanyStatistic := task.NewTask("stackCompanyStatistic", "0 35 0 * * *", StackCompanyStatistic)
 	task.AddTask("存量客户数据统计", stackCompanyStatistic)
 
+	// 定时往同花顺推送报告
+	sendWaitReport := task.NewTask("checkDataInterface", "0 */1 * * * * ", SendWaitReport)
+	task.AddTask("定时往同花顺推送报告", sendWaitReport)
+
 	task.StartTask()
 	//GetHistoryLzProductDetail()
 	//GetLzPrice()

+ 30 - 11
utils/config.go

@@ -14,18 +14,17 @@ var (
 
 var (
 	CompanyId int
-	AdminId int
-	RealName string
+	AdminId   int
+	RealName  string
 )
 
 var (
-	WxAppId     string
-	WxAppSecret string
-	TemplateId  string
+	WxAppId          string
+	WxAppSecret      string
+	TemplateId       string
 	RemindTemplateId string
 )
 
-
 //oss配置
 var (
 	Bucketname       string = "hongze"
@@ -38,6 +37,11 @@ var (
 	AccessKeySecret string = "12kk1ptCHoGWedhBnKRVW5hRJzq9Fq"
 )
 
+var (
+	THS_SendUrl string //同花顺地址url
+	THS_PubKey  string //同花顺公钥
+)
+
 func init() {
 	RunMode = beego.AppConfig.String("run_mode")
 	config, err := beego.AppConfig.GetSection(RunMode)
@@ -50,21 +54,36 @@ func init() {
 	MYSQL_URL_EDB = config["mysql_url_edb"]
 	MYSQL_URL_DATA = config["mysql_url_data"]
 
+	//同花顺公钥
+	THS_PubKey = `-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqugglfCboOEfWtHlGBOW
+40a4Y3xOs0MPBwjTOzHgcaWzx5XCc20VftGVXkWlpjs8u4dza/Bp1SV7SJ5Y7U95
+jgUOP8Js9Qgp6UVqBJDJf3i1KpjHzlk3ma8zxAYUAdieEUE+SKSxSY+BD9A6lpf5
+n+igXLmzR5GeVGFeLzoMhB1+pXgGhW30ao9wPwuRF7DBl+FKa/ACi7iXLiwXVgqT
+FFi29TKeerEENu3EpMXvPml7tNUiVmVW6d83hlascfbAlkShwuHLSGpLqK7brtg6
+jRS9hreKFKb0BUQ4TB26e7IDCstbMRvUp4+OGezexzic5NYPQ8uLo5OTaS7f7PrW
+ZwIDAQAB
+-----END PUBLIC KEY-----`
+
 	if RunMode == "release" {
 		CompanyId = 16
-		RealName="超级管理员"
+		RealName = "超级管理员"
 		WxAppId = "wx4a844c734d8c8e56"
 		WxAppSecret = "26c586e7ccb3c575433f0f37797b3eeb"
 		TemplateId = "P0klzaZjEI2UYth-z-WnmtOQgyxcF8klPoA_MlsA8Eo"
-		RemindTemplateId="PaHpQjVffrvmeW8wiOUcqlEhnD1LXyU9FnPVF-Jg9wM"
+		RemindTemplateId = "PaHpQjVffrvmeW8wiOUcqlEhnD1LXyU9FnPVF-Jg9wM"
+		//同花顺正式地址
+		THS_SendUrl = `https://board.10jqka.com.cn/gateway/ps/syncNews`
 	} else {
 		CompanyId = 16
-		RealName="超级管理员"
-		AdminId=11
+		RealName = "超级管理员"
+		AdminId = 11
 		WxAppId = "wx9b5d7291e581233a"
 		WxAppSecret = "f4d52e34021eee262dce9682b31f8861"
 		TemplateId = "P0klzaZjEI2UYth-z-WnmtOQgyxcF8klPoA_MlsA8Eo"
-		RemindTemplateId="9JYV6sHMJlu2EHRBIj_8ift6wkrrTb9_UO-M_-YXKBw"
+		RemindTemplateId = "9JYV6sHMJlu2EHRBIj_8ift6wkrrTb9_UO-M_-YXKBw"
+		//同花顺测试地址
+		THS_SendUrl = `https://mtest.10jqka.com.cn/gateway/ps/syncNews`
 	}
 }