فهرست منبع

Merge branch 'dev/v4.8.70_dx' of qmx/jy into feature/v4.8.70

duxin 1 سال پیش
والد
کامیت
bb918171ba

+ 2 - 1
src/config.json

@@ -447,5 +447,6 @@
   "wxBrowserContent": ["content","bdcontent","advancedProject"],
   "hotSubjectMatter": "A4纸,安全标志,安全挡板,安全隔离网,安全网,办公耗材,办公家具,办公设备,办公椅,办公用房,办公用品,办公桌,保护装置,保密柜,笔记本,笔记本电脑,变压器,仓库,插线板,充电桩,触控一体机,传感器,打印机,打印机耗材,打印设备,档案袋,档案盒,道路工程,地铁,电池,电缆,电流互感器,电梯,电线,订书机,订书针,对讲机,多功能一体机,多媒体设备,发电机,防冻液,防护栏杆,防护门,防护棚,防雷设施,防水工程,服务器,服装,复印机,复印纸,钢板,钢结构,钢筋,工作服,工作站,公路,公用工程,固体胶,光伏,光盘,航标灯,回形针,机房空调,机柜,机油,鸡蛋,计算机,记号笔,记事本,继电器,家具,监测仪,监视器,检测报告,检测仪器,剪刀,建筑工程,交换机,交通设施,胶带,胶水,脚手架,井架,警示灯,救护车,救生设施,刻录机,空调,空气调节器,垃圾袋,垃圾桶,冷却塔,冷水机组,楼层呼唤器,路灯,绿化工程,毛巾,美工刀,门禁,密集架,灭火器,抹布,墨盒,逆变器,牛皮纸,配电箱,喷壶,起重机,汽油,桥梁,热泵机组,热水器,弱电系统,扫描仪,摄像头,生活用房,食堂,市政工程,双面胶,水电站,水桶,宿舍,碎纸机,台式机,太阳能,碳粉,天然气,投影仪,图书,土石方,拖把,挖掘机,网线,文件袋,文件柜,无人机,无线电,硒鼓,洗洁精,洗手液,洗衣粉,显示屏,橡皮,消防立管,消防器材,消防水泵,消防箱,新能源,蓄电池,液晶显示器,医疗器械,医疗设备,移动工作站,移动硬盘,预埋钢板,园林工程,纸杯,中性笔,桩基,装修工程",
   "biddingRelatesLevel": 0,
-  "ipInitAuthentication": "qwertyuiopzxcvbnm1234567890asdfghjkl"
+  "ipInitAuthentication": "qwertyuiopzxcvbnm1234567890asdfghjkl",
+  "node": 1
 }

+ 2 - 0
src/go.mod

@@ -8,6 +8,7 @@ require (
 	app.yhyue.com/moapp/jylog v0.0.0-20230522075550-05d7230ca545
 	app.yhyue.com/moapp/jypkg v0.0.0-20231024062045-5c364be1561d
 	bp.jydev.jianyu360.cn/BaseService/userCenter v1.2.14
+	github.com/ClickHouse/clickhouse-go v1.5.4
 	github.com/SKatiyar/qr v0.0.0-20151201054752-25b6bdf44e67
 	github.com/bwmarrin/snowflake v0.3.0
 	github.com/fsnotify/fsnotify v1.6.0
@@ -31,6 +32,7 @@ require (
 	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/clbanning/mxj/v2 v2.5.5 // indirect
+	github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 // indirect
 	github.com/coreos/go-semver v0.3.1 // indirect
 	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect

+ 6 - 2
src/go.sum

@@ -74,6 +74,7 @@ github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I
 github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
+github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0=
 github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
 github.com/ClickHouse/clickhouse-go/v2 v2.2.0/go.mod h1:8f2XZUi7XoeU+uPIytSi1cvx8fmJxi7vIgqpvYTF1+o=
 github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
@@ -119,6 +120,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
 github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
 github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
 github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw=
 github.com/bos-hieu/mongostore v0.0.2/go.mod h1:8AbbVmDEb0yqJsBrWxZIAZOxIfv/tsP8CDtdHduZHGg=
@@ -140,6 +142,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
 github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
 github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -669,6 +672,7 @@ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNc
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pierrec/lz4 v2.5.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
 github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -1432,8 +1436,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20230710093759-d9d6c68de8b1 h1:BItxi1gkQUs3sjxaBk6tc34fZWSO4hUSXcTM3PcnY4I=
-jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20230710093759-d9d6c68de8b1/go.mod h1:p/595fgbj4r6GhSJhHDpx3Ru1NkD5UASFL8OuIQw09E=
+jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20231017031425-45003ca9f35a h1:kwjO4pqB3gnNGrQ9aXyz6f8s9qXAUenPUDWip8gYR/Q=
+jygit.jydev.jianyu360.cn/ApplicationCenter/publicService v0.0.0-20231017031425-45003ca9f35a/go.mod h1:p/595fgbj4r6GhSJhHDpx3Ru1NkD5UASFL8OuIQw09E=
 k8s.io/api v0.22.9/go.mod h1:rcjO/FPOuvc3x7nQWx29UcDrFJMx82RxDob71ntNH4A=
 k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU=
 k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE=

+ 15 - 0
src/jfw/config/config.go

@@ -6,7 +6,9 @@ import (
 	"app.yhyue.com/moapp/jybase/mail"
 	"app.yhyue.com/moapp/jypkg/middleground"
 	"app.yhyue.com/moapp/jypkg/public"
+	"database/sql"
 	"fmt"
+	_ "github.com/ClickHouse/clickhouse-go"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/os/gcfg"
 	"github.com/gogf/gf/v2/os/gctx"
@@ -30,6 +32,7 @@ var (
 	HotBuyerConfig       HotConfig
 	IpList               *ipmatch.WhiteIp
 	IpInitLock           sync.RWMutex //锁
+	ClickhouseDb         *sql.DB
 )
 
 type HotConfig struct {
@@ -47,6 +50,7 @@ func init() {
 	g.Cfg().GetAdapter().(*gcfg.AdapterFile).SetFileName("config.yaml")
 	util.ReadConfig(&Sysconfig)
 	IpInit()
+	//ClickhouseInit()
 	//log.Println("sysconfig:", Sysconfig)
 	WeixinConfig, _ = Sysconfig["wxJianyu"].(map[string]interface{})
 	Wxoauth = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=` + util.ObjToString(WeixinConfig["appid"]) + `&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect`
@@ -198,3 +202,14 @@ func convertToPinyin(word string) string {
 	}
 	return pinyinStr
 }
+
+func ClickhouseInit() *sql.DB {
+
+	// 创建ClickHouse连接
+	connect, err := sql.Open("clickhouse", util.InterfaceToStr(Seoconfig["clickhouseUrl"]))
+	if err != nil {
+		fmt.Println("连接失败:", err)
+		return nil
+	}
+	return connect
+}

+ 27 - 6
src/jfw/filter/anonymousUser.go

@@ -15,6 +15,7 @@ import (
 	"fmt"
 	"github.com/bwmarrin/snowflake"
 	"io/ioutil"
+	"jy/src/jfw/config"
 	"log"
 	"net/http"
 	"strings"
@@ -30,7 +31,7 @@ type AnonymousAuth struct {
 }
 
 var (
-	node, _ = snowflake.NewNode(1)
+	Node *snowflake.Node
 )
 
 func initPrivatePublicKey() {
@@ -102,15 +103,17 @@ func (sk *AnonymousAuth) Do() {
 		jyGuestUID, _ := sk.R.Cookie("JYGuestUID")
 		if jyGuestUID == nil || jyGuestUID.Value == "" { //不存在后端id 生成后端id 并创建匿名身份信息
 			accept := sk.R.Header.Get("Accept")
-			if sk.R.Method != "GET" || !strings.Contains(accept, "text/html") { //避免多请求
+			if !strings.Contains(accept, "text/html") { //避免多请求
 				return
 			}
-			guestUID := node.Generate()
+			guestUID := Node.Generate()
 			cookie := &http.Cookie{
 				Name:     "JYGuestUID",
 				Value:    util.InterfaceToStr(guestUID),
 				Path:     "/",
 				HttpOnly: true,
+				Domain:   util.ObjToString(config.Sysconfig["cookiedomain"]),
+				Expires:  time.Now().AddDate(10, 0, 0),
 			}
 			http.SetCookie(sk.W, cookie)
 			//未登录用户增加匿名身份信息
@@ -130,6 +133,15 @@ func (sk *AnonymousAuth) Do() {
 				"creation_time": time.Now().Unix(),
 			}
 			public.BaseMysql.Insert("anonymous_identity", data)
+			//stmt, err := config.ClickhouseDb.Prepare("INSERT INTO anonymous_identity (ip, client, os, browse, url, guestUID, mdescribe, refer, method, creation_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
+			//if err != nil {
+			//	return
+			//}
+			//defer stmt.Close()
+			//_, err = stmt.Exec(util.GetIp(sk.R), agent, util.GetOS(agent), util.GetBrowse(agent), sk.R.RequestURI, util.InterfaceToStr(guestUID), str, sk.R.Referer(), sk.R.Method, time.Now().Unix())
+			//if err != nil {
+			//	return
+			//}
 			return
 		}
 
@@ -140,17 +152,14 @@ func (sk *AnonymousAuth) Do() {
 		}
 		eid, err := sk.R.Cookie("eid")
 		if err != nil {
-			//log.Println("匿名用户获取eid失败", err.Error())
 			return
 		}
 		if fid.Value != "" && eid.Value != "" {
 			eData, err1 := Decryption(eid.Value)
 			if err1 != nil {
-				//log.Printf("匿名用户eid:%s,fid:%s 解密失败err:%s", eid.Value, fid.Value, err1.Error())
 				return
 			}
 			if fid.Value != eData {
-				//log.Printf("匿名用户身份验证不通过,eid:%s,fid:%s,eData:%s", eid.Value, fid.Value, eData)
 				return
 			}
 			trustedId := encrypt.SE.EncodeString(fid.Value + "***" + jyGuestUID.Value)
@@ -159,10 +168,22 @@ func (sk *AnonymousAuth) Do() {
 				Value:    trustedId,
 				Path:     "/",
 				HttpOnly: true,
+				Domain:   util.ObjToString(config.Sysconfig["cookiedomain"]),
+				Expires:  time.Now().AddDate(10, 0, 0),
 			}
 			http.SetCookie(sk.W, cookie)
 			public.BaseMysql.Update("anonymous_identity", map[string]interface{}{"guestUID": jyGuestUID.Value},
 				map[string]interface{}{"fid": fid.Value, "trustedId": trustedId})
+			//stmt, err := config.ClickhouseDb.Prepare("UPDATE anonymous_identity SET fid = ? and trustedId = ? WHERE guestUID = ?")
+			//if err != nil {
+			//	fmt.Println("Failed to prepare statement:", err)
+			//	return
+			//}
+			//defer stmt.Close()
+			//_, err = stmt.Exec(fid.Value, trustedId, jyGuestUID.Value)
+			//if err != nil {
+			//	return
+			//}
 		} else {
 			log.Println("无身份验证信息")
 		}

+ 3 - 1
src/jfw/filter/filter.go

@@ -2,8 +2,10 @@ package filter
 
 import (
 	"crypto/rsa"
+	"github.com/bwmarrin/snowflake"
 	. "jy/src/jfw/config"
 	"jy/src/jfw/jyutil"
+	"jy/src/jfw/modules/app/src/jfw/config"
 	"net/http"
 	"regexp"
 	"time"
@@ -27,7 +29,7 @@ var (
 func init() {
 	xweb.AddFilter(&Filter{})
 	go initPrivatePublicKey()
-
+	Node, _ = snowflake.NewNode(util.Int64All(config.Seoconfig["node"]))
 	//日志过滤 路由集合
 	go fs.FSNotifyFUNC("sword->%s", "./route.json", true, func() {
 		util.ReadConfig("./route.json", &RouteConf)

+ 18 - 0
src/jfw/front/login.go

@@ -400,6 +400,24 @@ func anonymousLogin(session *httpsession.Session, trustedId string) {
 
 	//匿名用户登录后创建关联信息
 	public.BaseMysql.Insert("anonymous_association", queryData)
+
+	//var count int
+	//err := config.ClickhouseDb.QueryRow(fmt.Sprintf(`SELECT count(*) FROM anonymous_association where positionId = %v and mgoUserId = "%v" and trustedId = "%v"`, positionId, mgoUserId, trustedId)).Scan(&count)
+	//if err != nil {
+	//	return
+	//}
+	////queryData := map[string]interface{}{"positionId": positionId, "mgoUserId": mgoUserId, "trustedId": trustedId, "creation_time": time.Now().Unix()}
+	//if count > 0 {
+	//	stmt, err := config.ClickhouseDb.Prepare("INSERT INTO anonymous_identity (positionId, mgoUserId, trustedId, creation_time) VALUES (?, ?, ?, ?)")
+	//	if err != nil {
+	//		return
+	//	}
+	//	defer stmt.Close()
+	//	_, err = stmt.Exec(positionId, mgoUserId, trustedId, time.Now().Unix())
+	//	if err != nil {
+	//		return
+	//	}
+	//}
 }
 
 func afterLogin(phone string, session *httpsession.Session, fool bool) (bool, *map[string]interface{}, map[string]interface{}) {

+ 2 - 1
src/jfw/modules/subscribepay/src/entity/dataexport.go

@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"io/ioutil"
 	"jy/src/jfw/modules/subscribepay/src/config"
+	"jy/src/jfw/modules/subscribepay/src/pay"
 	"jy/src/jfw/modules/subscribepay/src/util"
 	"log"
 	"os"
@@ -97,7 +98,7 @@ func (d *dataExportStruct) PayCallBack(param *CallBackParam) bool {
 			if update {
 				//先发个通知
 				go SendMailToBJFinance(orderdata, pay_time, param.TransactionId, 1, config.GmailAuth)
-
+				go pay.CheckSave(userId, qutil.InterfaceToStr((*orderdata)["filter_id"])) //数据导出成功保存筛选条件
 				//发送邮件移至定时任务
 				//go SendMailToPayUser(orderdata, float64(param.CashFee)/100, pay_time, download_url, config.GmailAuth)
 

+ 117 - 0
src/jfw/modules/subscribepay/src/pay/derivedCondition.go

@@ -0,0 +1,117 @@
+package pay
+
+import (
+	util "app.yhyue.com/moapp/jybase/common"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+	qutil "jy/src/jfw/modules/subscribepay/src/util"
+	"k8s.io/apimachinery/pkg/util/json"
+	"sort"
+	"strings"
+	"time"
+)
+
+func CheckSave(userid, filterId string) {
+	if filterId == "" || userid == "" {
+		return
+	}
+	id, _ := primitive.ObjectIDFromHex(filterId)
+	dataMap, ok := qutil.MQFW.FindOne("export_search", map[string]interface{}{
+		"s_userid":   userid,
+		"_id":        id,
+		"comeinfrom": "exportPage",
+	})
+	if !ok || dataMap == nil || len(*dataMap) == 0 {
+		return
+	}
+	data := make(map[string]interface{})
+	query := map[string]interface{}{
+		"user_id": userid,
+	}
+	area, _ := (*dataMap)["area"].([]interface{})
+	data["area"] = ArrSort(area)
+	city, _ := (*dataMap)["city"].([]interface{})
+	data["city"] = ArrSort(city)
+	region, _ := (*dataMap)["region"].([]interface{})
+	data["region"] = ArrSort(region)
+	industry, _ := (*dataMap)["industry"].([]interface{})
+	data["industry"] = ArrSort(industry)
+	buyerclass, _ := (*dataMap)["buyerclass"].([]interface{})
+	data["buyerclass"] = ArrSort(buyerclass)
+	buyer, _ := (*dataMap)["buyer"].([]interface{})
+	data["buyer"] = ArrSort(buyer)
+	winner, _ := (*dataMap)["winner"].([]interface{})
+	data["winner"] = ArrSort(winner)
+	keyword, _ := (*dataMap)["keyword"].([]interface{})
+	data["keyword"] = keywordSort(util.ObjArrToMapArr(keyword))
+
+	data["publishtime"] = util.InterfaceToStr((*dataMap)["publishtime"])
+	data["selectType"] = ValueSort(util.InterfaceToStr((*dataMap)["selectType"]))
+	data["minprice"] = util.InterfaceToStr((*dataMap)["minprice"])
+	data["maxprice"] = util.InterfaceToStr((*dataMap)["maxprice"])
+	data["subtype"] = ValueSort(util.InterfaceToStr((*dataMap)["subtype"]))
+
+	inKey := GetKeysByParam(data)
+	query["in_key"] = inKey
+	tm := time.Now()
+	if qutil.MQFW.Count("export_condition", query) > 0 {
+		qutil.MQFW.Update("export_condition", query, map[string]interface{}{
+			"$set": map[string]interface{}{
+				"update_time": tm.Unix(),
+			}}, false, false)
+	} else {
+		data["create_time"] = tm.Unix()
+		data["update_time"] = tm.Unix()
+		data["in_key"] = inKey
+		data["filter_id"] = filterId
+		data["user_id"] = userid
+		qutil.MQFW.Save("export_condition", data)
+	}
+}
+
+func keywordSort(data []map[string]interface{}) string {
+	var (
+		dataArr []map[string]string
+	)
+	if data == nil || len(data) == 0 {
+		return ""
+	}
+	for _, v := range data {
+		dm := make(map[string]string)
+		for k, v1 := range v {
+			var v2 string
+			if k == "keyword" {
+				v2 = ValueSort(util.InterfaceToStr(v1))
+			} else if (k == "appended" && v1 != "" && v1 != nil) || (k == "exclude" && v1 != "" && v1 != nil) {
+				vs, _ := v1.([]interface{})
+				v2 = ArrSort(vs)
+			}
+			dm[k] = v2
+		}
+		dataArr = append(dataArr, dm)
+	}
+	SortData(&dataArr, "keyword", false)
+	b, _ := json.Marshal(dataArr)
+	return string(b)
+}
+
+func ValueSort(v string) string {
+	if v == "" {
+		return ""
+	}
+	vs := strings.Split(v, ",")
+	sort.Slice(vs, func(i, j int) bool {
+		return vs[i] < vs[j]
+	})
+	return strings.Join(vs, ",")
+}
+
+func ArrSort(value []interface{}) string {
+	if value == nil || len(value) == 0 {
+		return ""
+	}
+	vs := util.ObjArrToStringArr(value)
+	sort.Slice(vs, func(i, j int) bool {
+		return vs[i] < vs[j]
+	})
+	return strings.Join(vs, ",")
+}

+ 160 - 7
src/jfw/modules/subscribepay/src/pay/util.go

@@ -1,12 +1,15 @@
 package pay
 
 import (
+	"bytes"
 	"crypto"
+	"crypto/md5"
 	"crypto/rand"
 	"crypto/rsa"
 	"crypto/sha256"
 	"crypto/x509"
 	"encoding/base64"
+	"encoding/json"
 	"encoding/pem"
 	"errors"
 	"fmt"
@@ -14,6 +17,9 @@ import (
 	"jy/src/jfw/modules/subscribepay/src/config"
 	"jy/src/jfw/modules/subscribepay/src/util"
 	"log"
+	"net/url"
+	"reflect"
+	"sort"
 	"strings"
 	"sync"
 	"time"
@@ -297,7 +303,7 @@ func GetCacheOrderCode(tradeNo string) (orderCode string) {
 	return redis.GetStr("other", fmt.Sprintf(CacheOrderTradeNo, tradeNo))
 }
 
-//关闭订单
+// 关闭订单
 func CloseOrderByOrderCode(ordercode string) error {
 	res := util.Mysql.FindOne("dataexport_order", map[string]interface{}{"order_code": ordercode}, "out_trade_no,pay_way", "")
 	if res == nil || len(*res) == 0 {
@@ -330,13 +336,13 @@ func CloseOrder(tradeno, payWay string) bool {
 	return false
 }
 
-//创建订单号
+// 创建订单号
 func GetOrderCode(id ...string) string {
 	//2020-08-01之前的规则 fmt.Sprintf("%s%s", time.Now().Format("150405"), qutil.GetRandom(6))
 	return <-varOrderCode.pool
 }
 
-//关闭订单
+// 关闭订单
 func CloseDataExportOrder(payWay, tradeno, prepayTime string) (status bool) {
 	//如果订单超时 则不用关闭订单
 	t, err := time.ParseInLocation(Date_Full_Layout, prepayTime, time.Local)
@@ -361,7 +367,7 @@ func CloseDataExportOrder(payWay, tradeno, prepayTime string) (status bool) {
 	return status
 }
 
-//加载秘钥
+// 加载秘钥
 func parsePrivateKey(key string) (*rsa.PrivateKey, error) {
 	block, _ := pem.Decode([]byte(key))
 	if block == nil {
@@ -377,7 +383,7 @@ func parsePrivateKey(key string) (*rsa.PrivateKey, error) {
 	return rsaPrivateKey.(*rsa.PrivateKey), nil
 }
 
-//加载支付宝后台公钥
+// 加载支付宝后台公钥
 func parseAliPayPublicKey(key string) (*rsa.PublicKey, error) {
 	publicKeyDecoded, err := base64.StdEncoding.DecodeString(key)
 	if err != nil {
@@ -393,7 +399,7 @@ func parseAliPayPublicKey(key string) (*rsa.PublicKey, error) {
 	return nil, errors.New("rsa.PublicKey 断言出错")
 }
 
-//生成加密token
+// 生成加密token
 func (a *aliPayStruct) getSign(data []byte) (signature string, err error) {
 	var h hash.Hash
 	var hType crypto.Hash
@@ -411,7 +417,7 @@ func (a *aliPayStruct) getSign(data []byte) (signature string, err error) {
 	return
 }
 
-//处理商户订单号
+// 处理商户订单号
 func processTradeno(tradeno string) string {
 	if devTradenoSign, _ := config.PayConf["devTradenoSign"].(string); devTradenoSign != "" {
 		tradeno = devTradenoSign + tradeno
@@ -419,3 +425,150 @@ func processTradeno(tradeno string) string {
 	}
 	return tradeno
 }
+
+type paramSorter struct {
+	Keys   []string
+	Values []string
+}
+
+var SP = strings.Replace
+
+func (ps *paramSorter) String() string {
+	str := ""
+	for n, k := range ps.Keys {
+		str += k + "=" + ps.Values[n]
+		if n < len(ps.Keys)-1 {
+			str += "&"
+		}
+	}
+	return str
+}
+
+func (ps *paramSorter) Sort() {
+	sort.Sort(ps)
+}
+func (ps *paramSorter) Len() int {
+	return len(ps.Values)
+}
+
+func (ps *paramSorter) Less(i, j int) bool {
+	return bytes.Compare([]byte(ps.Keys[i]), []byte(ps.Keys[j])) < 0
+}
+
+func (ps *paramSorter) Swap(i, j int) {
+	ps.Values[i], ps.Values[j] = ps.Values[j], ps.Values[i]
+	ps.Keys[i], ps.Keys[j] = ps.Keys[j], ps.Keys[i]
+}
+
+func percentEncode(str string) string {
+	str = url.QueryEscape(str)
+	str = SP(SP(SP(str, "+", "%20", -1), "*", "%2A", -1), "%7E", "~", -1)
+	return str
+}
+
+// 排序 排序键必须为数字类型
+type SortBy struct {
+	Data    []map[string]interface{}
+	Sortkey string
+}
+
+func (a SortBy) Len() int { return len(a.Data) }
+
+func (a SortBy) Swap(i, j int) {
+	a.Data[i], a.Data[j] = a.Data[j], a.Data[i]
+}
+
+func (a SortBy) Less(i, j int) bool {
+	//return Float64(a.Data[i][a.Sortkey]) < Float64(a.Data[j][a.Sortkey])
+	m := a.Data[i][a.Sortkey]
+	n := a.Data[j][a.Sortkey]
+	w := reflect.ValueOf(m)
+	v := reflect.ValueOf(n)
+	switch v.Kind() {
+	case reflect.String:
+		return w.String() < v.String()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return w.Int() < v.Int()
+	case reflect.Float64, reflect.Float32:
+		return w.Float() < v.Float()
+	default:
+		return fmt.Sprintf("%v", w) < fmt.Sprintf("%v", v)
+	}
+}
+
+// 根据指定字符排序
+//
+//	m := []map[string]int{
+//	   {"k": 2},
+//	   {"k": 1},
+//	   {"k": 3},
+//	}
+//
+// customer.SortData(&m, "k", true)
+// ture  倒序3, 2, 1
+// fmt.Println(m)
+func SortData(data interface{}, sortkey string, reverse bool) {
+	//func SortData(data interface{}, sortkey string, reverse bool) {
+	var db []map[string]interface{}
+	err := Bind(data, &db)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	stb := SortBy{db, sortkey}
+	if !reverse {
+		sort.Sort(stb)
+	} else {
+		sort.Sort(sort.Reverse(stb))
+	}
+	err = Bind(stb.Data, data)
+	if err != nil {
+		fmt.Println(err)
+	}
+
+}
+
+func Bind(data interface{}, ret interface{}) error {
+	v := reflect.ValueOf(ret)
+	if v.Kind() != reflect.Ptr {
+		return fmt.Errorf("ptr input ret needed as type as input type %s", v.Kind())
+	}
+	havdata := false
+	var bk interface{}
+	if v.Elem().Kind() == reflect.Slice {
+		t := reflect.Zero(reflect.TypeOf(v.Elem().Interface()))
+		bk = v.Elem().Interface()
+		v.Elem().Set(t)
+		havdata = true
+	}
+	_data, _ := json.MarshalIndent(data, "", "    ")
+	err := json.Unmarshal(_data, ret)
+	if err != nil {
+		fmt.Println(err)
+		if havdata {
+			v.Elem().Set(reflect.ValueOf(bk))
+		}
+		return err
+	}
+	return nil
+}
+
+func GetKeysByParam(param map[string]interface{}) string {
+	ps := &paramSorter{[]string{}, []string{}}
+	for k, v := range param {
+		ps.Keys = append(ps.Keys, k)
+		ps.Values = append(ps.Values, qutil.InterfaceToStr(v))
+	}
+	ps.Sort()
+	reqStr := ps.String()
+	str := percentEncode(reqStr)
+	str = SP(str, "%3A", "%253A", -1)
+	return MD5(str)
+}
+
+func MD5(str string) string {
+	data := []byte(str)
+	has := md5.Sum(data)
+	md5str := fmt.Sprintf("%x", has)
+	return md5str
+}

+ 58 - 1
src/jfw/modules/subscribepay/src/service/dataexportPack.go

@@ -2,7 +2,9 @@ package service
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
+	"go.mongodb.org/mongo-driver/bson/primitive"
 	"io/ioutil"
 	"jy/src/jfw/modules/subscribepay/src/config"
 	"jy/src/jfw/modules/subscribepay/src/entity"
@@ -37,6 +39,58 @@ type DataExportPack struct {
 	rechargeList   xweb.Mapper `xweb:"/dataExportPack/rechargeList"` //数据导出-流量包充值记录
 	recordList     xweb.Mapper `xweb:"/dataExportPack/recordList"`   //数据导出记录
 	sendExportMail xweb.Mapper `xweb:"/dataExportPack/sendMail"`     //移动端导出记录发送附件邮件
+
+	screenList   xweb.Mapper `xweb:"/dataExportPack/screenList"`   //数据导出_筛选列表
+	screenDelete xweb.Mapper `xweb:"/dataExportPack/screenDelete"` //数据导出_删除筛选
+
+}
+
+func (des *DataExportPack) ScreenList() {
+	data, err := func() (*[]map[string]interface{}, error) {
+		qMap := map[string]interface{}{
+			"user_id": des.GetSession("userId"),
+			"update_time": map[string]interface{}{
+				"$gte": time.Now().AddDate(-1, 0, 0).Unix(),
+			},
+		}
+		data, ok := util.MQFW.Find("export_condition", qMap, `{"update_time":-1}`, "", false, -1, -1)
+		if !ok {
+			log.Printf("获取筛选条件失败;qMap:%v", qMap)
+			return nil, errors.New("获取筛选条件失败")
+		}
+		if data != nil && len(*data) > 0 {
+			for _, v := range *data {
+				v["_id"] = encrypt.SE.EncodeString(qutil.InterfaceToStr(v["_id"]))
+			}
+		}
+		return data, nil
+	}()
+
+	des.ServeJson(NewResult(data, err))
+}
+
+func (des *DataExportPack) ScreenDelete() {
+	err := func() error {
+		userid := des.GetSession("userId")
+		ids := des.GetString("ids")
+		var idArr []primitive.ObjectID
+		for _, v := range strings.Split(ids, ",") {
+			if id := encrypt.SE.DecodeString(v); id != "" {
+				mgoId, _ := primitive.ObjectIDFromHex(id)
+				idArr = append(idArr, mgoId)
+			}
+		}
+		log.Println("userid", userid, idArr)
+		util.MQFW.Delete("export_condition", map[string]interface{}{
+			"user_id": userid,
+			"id": map[string]interface{}{
+				"$in": idArr,
+			},
+		})
+		return nil
+	}()
+
+	des.ServeJson(NewResult("", err))
 }
 
 // PackGoodsList 数据包规格及价格列表
@@ -303,11 +357,11 @@ func (this *DataExportPack) Statistics() {
 // return	serialNumber 流水号(暂定为记录id)
 func (this *DataExportPack) PackPay() {
 	userId, _ := this.GetSession("userId").(string)
+	filterId := encrypt.SE.Decode4Hex(this.GetString("filterId"))
 	rData, errMsg := func() (interface{}, error) {
 		//企业数据包、个人数据包流量包支付
 		//数据总量,扣除量
 		total_req, _ := this.GetInteger("total") //导出总量
-		filterId := encrypt.SE.Decode4Hex(this.GetString("filterId"))
 		if filterId == "" {
 			return nil, fmt.Errorf("请求参数异常")
 		}
@@ -380,6 +434,9 @@ func (this *DataExportPack) PackPay() {
 	}()
 	if errMsg != nil {
 		log.Printf("%s DataExportPack PackPay 异常:%s\n", userId, errMsg.Error())
+	} else {
+		//条件保存
+		go pay.CheckSave(userId, filterId)
 	}
 	this.ServeJson(NewResult(rData, errMsg))
 }