瀏覽代碼

Merge branch 'dev/v4.8.26_fuwencai' of qmx/jy into feature/v4.8.26

fuwencai 2 年之前
父節點
當前提交
ceb6848ee2

+ 4 - 4
src/jfw/modules/bigmember/src/db.json

@@ -36,11 +36,11 @@
   },
   "elasticsearch": {
     "main": {
-        "address": "http://192.168.3.206:9800,http://192.168.3.206:9801",
+        "address": "http://192.168.3.241:9205",
         "size": 30,
-		"version": "v7",
-		"userName": "",
-		"password": ""
+		    "version": "v7",
+		    "userName": "",
+		    "password": ""
     }
   },
   "redis": {

+ 13 - 6
src/jfw/modules/bigmember/src/entity/marketAnalysis/commonSearch.go

@@ -1,8 +1,8 @@
 package marketAnalysis
 
 import (
-	"fmt"
 	qutil "app.yhyue.com/moapp/jybase/common"
+	"fmt"
 	"strings"
 )
 
@@ -13,7 +13,7 @@ const (
 	query_bool_must     = `{"terms": {%s}}`
 )
 
-//GetCommonQuerySql 公共筛选
+// GetCommonQuerySql 公共筛选
 func (mae *MarketAnalysisEntity) GetCommonQuerySql() string {
 	var musts, bools []string
 	//时间
@@ -45,16 +45,23 @@ func (mae *MarketAnalysisEntity) GetCommonQuerySql() string {
 			bools = append(bools, sql)
 		}
 	}
-
+	//中标企业
+	if mae.FormatParam.Winner != "" {
+		musts = append(musts, fmt.Sprintf(`{"term":{"s_winner":"%s"}}`, mae.FormatParam.Winner))
+	}
+	//采购单位
+	if mae.FormatParam.Buyer != "" {
+		musts = append(musts, fmt.Sprintf(`{"term":{"buyer":"%s"}}`, mae.FormatParam.Buyer))
+	}
 	return fmt.Sprintf(`{"query":{"bool":{"must":[%s],"should":[%s],"minimum_should_match": %d}}%s}`, strings.Join(musts, ","), strings.Join(bools, ","), qutil.If(len(bools) > 0, 1, 0).(int), "%s")
 }
 
-//GetCommonQuerySqlWithAggs 此方法用于聚合查询
+// GetCommonQuerySqlWithAggs 此方法用于聚合查询
 func (mae *MarketAnalysisEntity) GetCommonQuerySqlWithAggs() string {
 	return fmt.Sprintf(mae.GetCommonQuerySql(), `,"aggs":{%s},"size":0`)
 }
 
-//getGroupKeywordArr 模糊拆分为多个精准匹配
+// getGroupKeywordArr 模糊拆分为多个精准匹配
 func getGroupKeywordArr(res []viewKeyWord) (rData []viewKeyWord) {
 	for _, kw := range res {
 		if kw.MatchWay == 1 {
@@ -77,7 +84,7 @@ func getGroupKeywordArr(res []viewKeyWord) (rData []viewKeyWord) {
 	return
 }
 
-//getAllKeywordArr 获取所有匹配词
+// getAllKeywordArr 获取所有匹配词
 func getAllKeywordArr(res []keyWordGroup) (rData []viewKeyWord) {
 	for _, kwg := range res {
 		rData = append(rData, getGroupKeywordArr(kwg.A_Key)...)

+ 105 - 15
src/jfw/modules/bigmember/src/entity/marketAnalysis/marketAnalysisEntity.go

@@ -1,18 +1,19 @@
 package marketAnalysis
 
 import (
-	"jy/src/jfw/modules/bigmember/src/config"
-	"jy/src/jfw/modules/bigmember/src/db"
-	"encoding/json"
-	"fmt"
-	"log"
-	"app.yhyue.com/moapp/jybase/mongodb"
 	qutil "app.yhyue.com/moapp/jybase/common"
+	"app.yhyue.com/moapp/jybase/encrypt"
 	elastic "app.yhyue.com/moapp/jybase/es"
+	"app.yhyue.com/moapp/jybase/mongodb"
 	"app.yhyue.com/moapp/jybase/redis"
+	"encoding/json"
+	"fmt"
+	"jy/src/jfw/modules/bigmember/src/config"
+	"jy/src/jfw/modules/bigmember/src/db"
+	"jy/src/jfw/modules/bigmember/src/util"
+	"log"
 	"strings"
 	"time"
-	"jy/src/jfw/modules/bigmember/src/util"
 )
 
 const (
@@ -38,7 +39,7 @@ func init() {
 	}
 }
 
-//AnalysisRequestParam 接口原请求参数
+// AnalysisRequestParam 接口原请求参数
 type AnalysisRequestParam struct {
 	KeysItemsStr   string //分析内容【字符串】结构和o_member_jy.a_items保持一致
 	RangeTime      string //时间【字符串】 时间戳开始-结束时间戳
@@ -46,6 +47,12 @@ type AnalysisRequestParam struct {
 	Area           string //省份【对象字符串】
 	Industry       string //行业【对象字符串】
 	BuyerClass     string //采购单位类型【字符串】多个采购单位类型用逗号拼接
+	Buyer          string //采购单位
+	Winner         string //中标单位
+	Sort           int    //排序:默认0:成交时间倒序;1:项目金额倒序
+	PageSize       int    //默认每页10条
+	PageNum        int    //默认当前第一页
+	IsDetail       bool   //是否是项目明细请求
 }
 
 type viewKeyWord struct {
@@ -55,20 +62,25 @@ type viewKeyWord struct {
 	MatchWay int      `json:"matchway"`  //匹配模式
 }
 
-//keyWordGroup 订阅词结构体
+// keyWordGroup 订阅词结构体
 type keyWordGroup struct {
 	A_Key      []viewKeyWord `json:"a_key"`
 	ItemName   string        `json:"s_item"`
 	UpdateTime int64         `json:"updatetime"`
 }
 
-//AnalysisRequestFormat 格式化后参数
+// AnalysisRequestFormat 格式化后参数
 type AnalysisRequestFormat struct {
 	KeysItems    []keyWordGroup
 	Area, City   []string //省份城市
 	STime, ETime int64    //开始结束时间
 	Industry     []string //行业
 	BuyerClass   []string //采购单位类型
+	Buyer        string   //采购单位
+	Winner       string   //中标单位
+	Sort         int      //排序:默认0:成交时间倒序;1:项目金额倒序
+	PageSize     int      //默认每页10条
+	PageNum      int      //默认当前第一页
 }
 
 type MarketAnalysisEntity struct {
@@ -76,9 +88,29 @@ type MarketAnalysisEntity struct {
 	BaseParam   AnalysisRequestParam
 	FormatParam AnalysisRequestFormat
 	UId, Pid    string
+	ProjectInfo projectInfo
+}
+
+type projectInfo struct {
+	Count int64
+	List  []ProjectList
 }
 
-//ForMatData 获取格式化请求参数
+type ProjectList struct {
+	Name       string  `json:"name"`       //项目名称
+	Id         string  `json:"id"`         //项目id
+	Area       string  `json:"area"`       //地区
+	DealTime   int64   `json:"dealTime"`   //成交时间
+	BidStatus  string  `json:"bidStatus"`  //项目类型
+	BuyerClass string  `json:"buyerClass"` //采购单位类型
+	Winner     string  `json:"winner"`     //中标单位
+	WinnerId   string  `json:"winnerId"`   //中标单位id
+	Buyer      string  `json:"buyer"`      //采购单位
+	BidAmount  float64 `json:"bidAmount"`  //中标金额
+	Budget     float64 `json:"budget"`     //预算
+}
+
+// ForMatData 获取格式化请求参数
 func (mae *MarketAnalysisEntity) ForMatData() error {
 	//格式化订阅词
 	if err := json.Unmarshal([]byte(mae.BaseParam.KeysItemsStr), &mae.FormatParam.KeysItems); err != nil {
@@ -134,10 +166,68 @@ func (mae *MarketAnalysisEntity) ForMatData() error {
 	if buyerClassStr := strings.TrimSpace(mae.BaseParam.BuyerClass); buyerClassStr != "" {
 		mae.FormatParam.BuyerClass = strings.Split(buyerClassStr, ",")
 	}
+	//中标企业
+	mae.FormatParam.Winner = mae.BaseParam.Winner
+	//采购单位
+	mae.FormatParam.Buyer = mae.BaseParam.Buyer
+	//排序
+	mae.FormatParam.Sort = qutil.If(mae.BaseParam.Sort != 0 && mae.BaseParam.Sort != 1, 0, mae.BaseParam.Sort).(int)
+	//当前页码
+	mae.FormatParam.PageNum = qutil.If(mae.BaseParam.PageNum < 1 || mae.BaseParam.PageNum > 100, 1, mae.BaseParam.PageNum).(int)
+	//默认每页10条
+	mae.FormatParam.PageSize = qutil.If(mae.BaseParam.PageSize < 1 || mae.BaseParam.PageSize > 50, 50, mae.BaseParam.PageSize).(int)
+	return nil
+}
+
+// GetProjectInfoList 项目明细
+func (mae *MarketAnalysisEntity) GetProjectInfoList() error {
+	var (
+		queryDefault = `,"sort": [{%s}],"from": %d,"size": %d`
+		start        = (mae.FormatParam.PageNum - 1) * mae.FormatParam.PageSize
+		sort         = `"jgtime": "desc"`
+	)
+	if mae.FormatParam.Sort > 0 {
+		sort = `"bidamount": "desc","budget": "desc"`
+	}
+	countSql := fmt.Sprintf(mae.GetCommonQuerySql(), "")
+	queryDefault = fmt.Sprintf(queryDefault, sort, start, mae.FormatParam.PageSize)
+	finalSql := fmt.Sprintf(mae.GetCommonQuerySql(), queryDefault)
+	log.Println("finalSql:", finalSql)
+	count, hits := elastic.GetWithCount("projectset", "projectset", countSql, finalSql)
+	//hits, count := elastic.GetOA("projectset", "projectset", finalSql)
+	if count > 0 {
+		mae.ProjectInfo.Count = count
+		source := *hits
+		for _, v := range source {
+			var winnerIdArr []string
+			if qutil.ObjToString(v["s_winner"]) != "" && v["entidlist"] != nil {
+				idObjs, _ := v["entidlist"].([]interface{})
+				for _, v := range qutil.ObjArrToStringArr(idObjs) {
+					if v != "" && v != "-" {
+						v = encrypt.EncodeArticleId2ByCheck(v)
+					}
+					winnerIdArr = append(winnerIdArr, v)
+				}
+			}
+			mae.ProjectInfo.List = append(mae.ProjectInfo.List, ProjectList{
+				Name:       qutil.ObjToString(v["projectname"]),
+				Id:         encrypt.EncodeArticleId2ByCheck(qutil.ObjToString(v["id"])),
+				Area:       qutil.ObjToString(v["area"]),
+				DealTime:   qutil.Int64All(v["jgtime"]), //截止时间
+				BidStatus:  qutil.ObjToString(v["bidstatus"]),
+				BuyerClass: qutil.ObjToString(v["buyerclass"]),
+				Winner:     qutil.ObjToString(v["s_winner"]),
+				WinnerId:   strings.Join(winnerIdArr, ","),
+				Buyer:      qutil.ObjToString(v["buyer"]),
+				BidAmount:  qutil.Float64All(v["bidamount"]), //中标金额
+				Budget:     qutil.Float64All(v["budget"]),    //预算
+			})
+		}
+	}
 	return nil
 }
 
-//SaveAnalysisRecord 保存分析记录
+// SaveAnalysisRecord 保存分析记录
 func (mae *MarketAnalysisEntity) SaveAnalysisRecord() error {
 	mae.MgoRecordId = db.Mgo.Save(ReportHistoryTable, map[string]interface{}{
 		"s_keysItems":      mae.BaseParam.KeysItemsStr,
@@ -156,7 +246,7 @@ func (mae *MarketAnalysisEntity) SaveAnalysisRecord() error {
 	return nil
 }
 
-//GetAnalysisFromMgoDb 从数据库中获取分析记录
+// GetAnalysisFromMgoDb 从数据库中获取分析记录
 func (mae *MarketAnalysisEntity) GetAnalysisFromMgoDb() error {
 	if mae.MgoRecordId == "" {
 		return fmt.Errorf("缺少参数")
@@ -199,7 +289,7 @@ func (mae *MarketAnalysisEntity) removeEmptyRecord() {
 	//log.Println("删除空报告", queryMap)
 }
 
-//GetRecordList 获取分析记录
+// GetRecordList 获取分析记录
 func (mae *MarketAnalysisEntity) GetRecordList(pageNum, PageSize int) (total int, list []map[string]interface{}) {
 	queryMap := map[string]interface{}{
 		"i_del": map[string]interface{}{"$ne": 1},
@@ -248,7 +338,7 @@ func (mae *MarketAnalysisEntity) getQueryItem() (map[string]interface{}, error)
 	}, nil
 }
 
-//GetPartResult 分块儿获取报告内容
+// GetPartResult 分块儿获取报告内容
 func (mae *MarketAnalysisEntity) GetPartResult(flag int) (map[string]interface{}, error) {
 	defer qutil.Catch()
 	if flag == marketQueryItem { //返回查询内容

+ 7 - 8
src/jfw/modules/bigmember/src/go.mod

@@ -3,14 +3,14 @@ module jy/src/jfw/modules/bigmember/src
 go 1.20
 
 require (
-	app.yhyue.com/moapp/jybase v0.0.0-20230511020847-9b0fbc33ff1c
+	app.yhyue.com/moapp/jybase v0.0.0-20230523020646-528a068dac39
 	app.yhyue.com/moapp/jylog v0.0.0-20230522075550-05d7230ca545
-	app.yhyue.com/moapp/jypkg v0.0.0-20230506115817-6f55523ae3f1
+	app.yhyue.com/moapp/jypkg v0.0.0-20230531014856-12e9a04b5c44
 	bp.jydev.jianyu360.cn/BaseService/userCenter v1.2.13
-	github.com/donnie4w/go-logger v0.0.0-20170827050443-4740c51383f4
-	github.com/gogf/gf/v2 v2.0.6
-	github.com/olivere/elastic/v7 v7.0.22
-	go.mongodb.org/mongo-driver v1.11.1
+	github.com/donnie4w/go-logger v0.0.0-20230316073421-36a48f87a69a
+	github.com/gogf/gf/v2 v2.4.2
+	github.com/olivere/elastic/v7 v7.0.32
+	go.mongodb.org/mongo-driver v1.11.6
 )
 
 require (
@@ -20,7 +20,7 @@ require (
 	bp.jydev.jianyu360.cn/BaseService/entManageApplication v0.0.0-20230214091519-89a98c01ab0e // indirect
 	bp.jydev.jianyu360.cn/BaseService/powerCheckCenter v0.0.0-20230222052351-9d6fad062447 // indirect
 	bp.jydev.jianyu360.cn/BaseService/resourceCenter v0.0.7 // indirect
-	github.com/BurntSushi/toml v0.4.1 // indirect
+	github.com/BurntSushi/toml v1.1.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cenkalti/backoff/v4 v4.2.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -57,7 +57,6 @@ require (
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/compress v1.15.11 // indirect
-	github.com/longbridgeapp/sqlparser v0.3.1 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-colorable v0.1.12 // indirect

+ 17 - 11
src/jfw/modules/bigmember/src/go.sum

@@ -5,12 +5,12 @@ app.yhyue.com/moapp/jyMarketing v0.0.2-0.20230304035551-21bb1eedf547/go.mod h1:J
 app.yhyue.com/moapp/jyPoints v1.1.1/go.mod h1:SvP8p5L3jGrejHiH2LXfgCg/NPlFiKBC5Yd0gsI12FU=
 app.yhyue.com/moapp/jybase v0.0.0-20220427020729-974c1a148186/go.mod h1:qNRA0sHuYqcLoYoP8irpaWnW9YsXixe6obBIkwaXpD0=
 app.yhyue.com/moapp/jybase v0.0.0-20230117032034-ad7c00ffe11a/go.mod h1:zB47XTeJvpcbtBRYgkQuxOICWNexiZfbUO+7aUf6mNs=
-app.yhyue.com/moapp/jybase v0.0.0-20230511020847-9b0fbc33ff1c h1:bYfxHP2uLcQlnsLuJSFHsvDpPTcEVqBgNOZ6E1B+Fl8=
-app.yhyue.com/moapp/jybase v0.0.0-20230511020847-9b0fbc33ff1c/go.mod h1:zB47XTeJvpcbtBRYgkQuxOICWNexiZfbUO+7aUf6mNs=
+app.yhyue.com/moapp/jybase v0.0.0-20230523020646-528a068dac39 h1:Cr68N8jdrNskP2fBhFhFGJhPlyt7H6o44fu8ob5nBVs=
+app.yhyue.com/moapp/jybase v0.0.0-20230523020646-528a068dac39/go.mod h1:zB47XTeJvpcbtBRYgkQuxOICWNexiZfbUO+7aUf6mNs=
 app.yhyue.com/moapp/jylog v0.0.0-20230522075550-05d7230ca545 h1:+Lak4m1zgsigQloOsvp8AJ+0XeX/+PGp9QP550xlbBQ=
 app.yhyue.com/moapp/jylog v0.0.0-20230522075550-05d7230ca545/go.mod h1:uFrsdUBFbETiJlEmr4PtJWPsZlUpPj2bHQRhryu6ggk=
-app.yhyue.com/moapp/jypkg v0.0.0-20230506115817-6f55523ae3f1 h1:d5VcH9qiJbFPypLNj42/d+bQ0webGqODZ1ALlBCWSso=
-app.yhyue.com/moapp/jypkg v0.0.0-20230506115817-6f55523ae3f1/go.mod h1:1QozRpU+mHTRhIYwrXemUt3sXSBWQRWZerqBwoHsBVM=
+app.yhyue.com/moapp/jypkg v0.0.0-20230531014856-12e9a04b5c44 h1:u7Y263EJvcCZDqJTwOfT+QkVQ6sJ/ZCBZxejEk8H9cI=
+app.yhyue.com/moapp/jypkg v0.0.0-20230531014856-12e9a04b5c44/go.mod h1:Ize93SJEPkBR0Tz8PM2KTJK3bpzlD/qp1JwJ4kdmlss=
 app.yhyue.com/moapp/message v0.0.0-20221223100203-6402e389d9ae h1:6rDDaz6yxvE8viTSzEBwKYOFWq14TMfuBivSazUZMz4=
 app.yhyue.com/moapp/message v0.0.0-20221223100203-6402e389d9ae/go.mod h1:b0zZHev3gmJao1Fo+2Z2KPVjsuLOJVvVxf+kCnu9WkA=
 bp.jydev.jianyu360.cn/BaseService/entManageApplication v0.0.0-20230214091519-89a98c01ab0e h1:h+VEI3o1qC0jeCzkFGTrLI4f27cfa/W/y+0sXokWMgE=
@@ -395,8 +395,9 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935
 github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
 github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+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/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
@@ -495,8 +496,9 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/donnie4w/go-logger v0.0.0-20170827050443-4740c51383f4 h1:T9PR91sjTtrA1HmZB4G+M7OLCelch0f6rIEY7Mm1T4U=
 github.com/donnie4w/go-logger v0.0.0-20170827050443-4740c51383f4/go.mod h1:L7S4x0R7vv3xoOhGuyAJyCO2MYzWOpccM4Isn8jIUgY=
+github.com/donnie4w/go-logger v0.0.0-20230316073421-36a48f87a69a h1:gXZfDEfrtcyyohaFVDBCVA7SjsAGJqr/aDQz26+4eDg=
+github.com/donnie4w/go-logger v0.0.0-20230316073421-36a48f87a69a/go.mod h1:/soYK7VeLIgdBS9B1+V+hZ2pffgKOyYSRHaBV+nj8xY=
 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
@@ -534,6 +536,7 @@ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 github.com/fullstorydev/grpcurl v1.8.7/go.mod h1:pVtM4qe3CMoLaIzYS8uvTuDj2jVYmXqMUkZeijnXp/E=
@@ -587,7 +590,6 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ
 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
-github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
 github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
 github.com/go-xorm/builder v0.3.4/go.mod h1:KxkQkNN1DpPKTedxXyTQcmH+rXfvk4LZ9SOOBoZBAxw=
 github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
@@ -620,8 +622,9 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
-github.com/gogf/gf/v2 v2.0.6 h1:2etb4FMpbQKWIJO+UjtIWrZUp01HUsFb6Po8pgizAWk=
 github.com/gogf/gf/v2 v2.0.6/go.mod h1:8uYzw7qNzuq8vrhVlWke1b1925FFqOJIgmyYW1sr/0M=
+github.com/gogf/gf/v2 v2.4.2 h1:31ekx+YKisG84/iEC2Ih6lB+g92+sB9R+VrfIbqfpac=
+github.com/gogf/gf/v2 v2.4.2/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
@@ -897,8 +900,8 @@ github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
-github.com/longbridgeapp/sqlparser v0.3.1 h1:iWOZWGIFgQrJRgobLXUNJdvqGRpbVXkyKUKUA5CNJBE=
 github.com/longbridgeapp/sqlparser v0.3.1/go.mod h1:GIHaUq8zvYyHLCLMJJykx1CdM6LHtkUih/QaJXySSx4=
+github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -969,8 +972,9 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/olivere/elastic v6.2.37+incompatible h1:UfSGJem5czY+x/LqxgeCBgjDn6St+z8OnsCuxwD3L0U=
 github.com/olivere/elastic v6.2.37+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
-github.com/olivere/elastic/v7 v7.0.22 h1:esBA6JJwvYgfms0EVlH7Z+9J4oQ/WUADF2y/nCNDw7s=
 github.com/olivere/elastic/v7 v7.0.22/go.mod h1:VDexNy9NjmtAkrjNoI7tImv7FR4tf5zUA3ickqu5Pc8=
+github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E=
+github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -1195,8 +1199,9 @@ go.etcd.io/etcd/client/v3 v3.5.6/go.mod h1:f6GRinRMCsFVv9Ht42EyY7nfsVGwrNO0WEoS2
 go.mongodb.org/mongo-driver v1.5.0/go.mod h1:boiGPFqyBs5R0R5qf2ErokGRekMfwn+MqKaUyHs7wy0=
 go.mongodb.org/mongo-driver v1.9.0/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
 go.mongodb.org/mongo-driver v1.9.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
-go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8=
 go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
+go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o=
+go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -1234,6 +1239,7 @@ go.opentelemetry.io/otel/exporters/zipkin v1.15.1 h1:B6s/o48bx00ayJu7F+jIMJfhPTy
 go.opentelemetry.io/otel/exporters/zipkin v1.15.1/go.mod h1:EjjV7/YfYXG+khxCOfG6PPeRGoOmtcSusyW66qPqpRQ=
 go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
 go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
+go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
 go.opentelemetry.io/otel/sdk v1.8.0/go.mod h1:uPSfc+yfDH2StDM/Rm35WE8gXSNdvCg023J6HeGNO0c=
 go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE=
 go.opentelemetry.io/otel/sdk v1.15.1 h1:5FKR+skgpzvhPQHIEfcwMYjCBr14LWzs3uSqKiQzETI=

+ 506 - 506
src/jfw/modules/bigmember/src/service/analysis/forecastwinner.go

@@ -8,26 +8,26 @@
 package analysis
 
 import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	. "jy/src/jfw/modules/bigmember/src/config"
-	"jy/src/jfw/modules/bigmember/src/db"
-	"jy/src/jfw/modules/bigmember/src/entity"
-	"jy/src/jfw/modules/bigmember/src/util"
-	"log"
-	"regexp"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
+    "encoding/json"
+    "errors"
+    "fmt"
+    . "jy/src/jfw/modules/bigmember/src/config"
+    "jy/src/jfw/modules/bigmember/src/db"
+    "jy/src/jfw/modules/bigmember/src/entity"
+    "jy/src/jfw/modules/bigmember/src/util"
+    "log"
+    "regexp"
+    "strconv"
+    "strings"
+    "sync"
+    "time"
 
-	. "app.yhyue.com/moapp/jybase/api"
-	qutil "app.yhyue.com/moapp/jybase/common"
-	"app.yhyue.com/moapp/jybase/encrypt"
-	elastic "app.yhyue.com/moapp/jybase/es"
-	. "app.yhyue.com/moapp/jybase/mongodb"
-	"app.yhyue.com/moapp/jybase/redis"
+    . "app.yhyue.com/moapp/jybase/api"
+    qutil "app.yhyue.com/moapp/jybase/common"
+    "app.yhyue.com/moapp/jybase/encrypt"
+    elastic "app.yhyue.com/moapp/jybase/es"
+    . "app.yhyue.com/moapp/jybase/mongodb"
+    "app.yhyue.com/moapp/jybase/redis"
 )
 
 var redis_forecast_status = "forecast_status_" //预测状态
@@ -36,526 +36,526 @@ var redis_forecast_date = "forecast_date_"     //预测时间
 var forecast_time = 300                        //超过五分钟 预测失败 清记录
 var reg = regexp.MustCompile("^[0-9]+.*$")
 
-//中标预测-项目信息当前是否已完成招标
+// 中标预测-项目信息当前是否已完成招标
 func (this *Analysis) BdInfoStatus() {
-	defer qutil.Catch()
-	userId := qutil.ObjToString(this.GetSession("userId"))
-	rData, errMsg := func() (interface{}, error) {
-		pid := this.GetString("pid") //项目信息id
-		sid := this.GetString("sid") //招标信息id
-		var pids, sids []string
-		var isBool = false
-		if pid != "" {
-			pids = encrypt.DecodeArticleId2ByCheck(pid)
-			isBool = true
-		}
-		if sid != "" {
-			sids = encrypt.DecodeArticleId2ByCheck(sid)
-			isBool = true
-		}
-		if !isBool {
-			return nil, errors.New("项目信息id或招标信息id不能同时为空")
-		}
-		//log.Println("pids:", pids, "--sids:", sids)
-		var res = entity.GetProInfoById(pids, sids)
-		if res == nil || len(res) == 0 {
-			return nil, errors.New("未查询到此项目")
-		}
-		bidstatus := qutil.ObjToString(res[0]["bidstatus"])
-		if strings.Contains(bidstatus, "中标") || strings.Contains(bidstatus, "成交") || strings.Contains(bidstatus, "废标") || strings.Contains(bidstatus, "流标") {
-			return 1, nil
-		}
-		return 0, nil
-	}()
-	if errMsg != nil {
-		log.Printf("%s   获取此项目状态出错-%s", userId, errMsg)
-	}
-	this.ServeJson(NewResult(rData, errMsg))
+    defer qutil.Catch()
+    userId := qutil.ObjToString(this.GetSession("userId"))
+    rData, errMsg := func() (interface{}, error) {
+        pid := this.GetString("pid") //项目信息id
+        sid := this.GetString("sid") //招标信息id
+        var pids, sids []string
+        var isBool = false
+        if pid != "" {
+            pids = encrypt.DecodeArticleId2ByCheck(pid)
+            isBool = true
+        }
+        if sid != "" {
+            sids = encrypt.DecodeArticleId2ByCheck(sid)
+            isBool = true
+        }
+        if !isBool {
+            return nil, errors.New("项目信息id或招标信息id不能同时为空")
+        }
+        //log.Println("pids:", pids, "--sids:", sids)
+        var res = entity.GetProInfoById(pids, sids)
+        if res == nil || len(res) == 0 {
+            return nil, errors.New("未查询到此项目")
+        }
+        bidstatus := qutil.ObjToString(res[0]["bidstatus"])
+        if strings.Contains(bidstatus, "中标") || strings.Contains(bidstatus, "成交") || strings.Contains(bidstatus, "废标") || strings.Contains(bidstatus, "流标") {
+            return 1, nil
+        }
+        return 0, nil
+    }()
+    if errMsg != nil {
+        log.Printf("%s   获取此项目状态出错-%s", userId, errMsg)
+    }
+    this.ServeJson(NewResult(rData, errMsg))
 }
 
-//中标预测超时处理
+// 中标预测超时处理
 func (this *Analysis) FWOvertime() {
-	defer qutil.Catch()
-	userId, _ := this.GetSession("userId").(string)
-	//中标信息预测结束
-	go ClearRedisInfo(userId)
+    defer qutil.Catch()
+    userId, _ := this.GetSession("userId").(string)
+    //中标信息预测结束
+    go ClearRedisInfo(userId)
 }
 
-//预测数据
+// 预测数据
 func (this *Analysis) FWData() {
-	defer qutil.Catch()
-	var regMap = Result{
-		Data:       []map[string]interface{}{},
-		Error_code: Error_code,
-		Error_msg:  "",
-	}
-	if this.Method() == METHOD {
-		userId, _ := this.GetSession("userId").(string)
-		//有正在预测的数据或已预测未查看的数据
-		success, id := isExistsFIng(userId)
-		status := 0
-		if success {
-			if success && id != "" {
-				status = 1 //success=true; id!=""  ---未查看的预测数据
-			} else if success && id == "" {
-				status = 2 //success=true; id=""  ---正在预测
-			}
-			var getRes map[string]interface{}
-			if redis.GetNewInterface("other", redis_forecast_status+userId, &getRes) != nil {
-				log.Println("redis 1获取预测参数有误-", userId)
-			}
-			regMap.Data = map[string]interface{}{
-				"status": status,
-				"id":     id,
-				"pname":  getRes["pname"],
-			}
-		} else {
-			if string(this.Body()) != "" {
-				//success=false; id=""  ---没有正在预测 也没有未查看的预测数据
-				//接受参数 调rpc 预测中标数据
-				getRes := new(util.ForecastS)
-				//接收参数
-				json.Unmarshal(this.Body(), &getRes)
-				if getRes.Type == "" && getRes.Id != "" {
-					//是否是子账号
-					var s_phone, _ = this.GetSession("s_phone").(string)
-					if s_phone == "" {
-						s_phone, _ = this.GetSession("s_m_phone").(string)
-					}
-					main_userId, phone, member_status := util.MainUserId(this.Session())
-					entity.UIL.Lock()
-					if entity.UIL.ForWLock[main_userId] == nil {
-						entity.UIL.ForWLock[main_userId] = &sync.Mutex{}
-					}
-					entity.UIL.Unlock()
-					entity.UIL.ForWLock[main_userId].Lock()
-					defer entity.UIL.ForWLock[main_userId].Unlock()
-					// log.Println(getRes.ServiceId, "----------", phone)
-					//判断是否有中标预测权限
-					var currentCount = 0
-					getRes.ServiceId = 15
-					ai, base64Key, currentCount := AnalysisPower("W", main_userId, getRes.Pname, getRes.Infoid, getRes.ServiceId)
-					// log.Println("ai:", ai)
-					if ai > 0 {
-						log.Println(main_userId, "---ai:", ai)
-						if ai == 2 {
-							// 订阅及搜索优化版本dev4.3.4调整为预测成功后才扣次数
-							// UpdatePower(main_userId, getRes.ServiceId) //更新sql库权限次数
-							redis.Put("newother", "jyPredictedDeduction_"+main_userId, base64Key, 3*24*60*60) //是否需要扣除次数 默认存3天
-						}
+    defer qutil.Catch()
+    var regMap = Result{
+        Data:       []map[string]interface{}{},
+        Error_code: Error_code,
+        Error_msg:  "",
+    }
+    if this.Method() == METHOD {
+        userId, _ := this.GetSession("userId").(string)
+        //有正在预测的数据或已预测未查看的数据
+        success, id := isExistsFIng(userId)
+        status := 0
+        if success {
+            if success && id != "" {
+                status = 1 //success=true; id!=""  ---未查看的预测数据
+            } else if success && id == "" {
+                status = 2 //success=true; id=""  ---正在预测
+            }
+            var getRes map[string]interface{}
+            if redis.GetNewInterface("other", redis_forecast_status+userId, &getRes) != nil {
+                log.Println("redis 1获取预测参数有误-", userId)
+            }
+            regMap.Data = map[string]interface{}{
+                "status": status,
+                "id":     id,
+                "pname":  getRes["pname"],
+            }
+        } else {
+            if string(this.Body()) != "" {
+                //success=false; id=""  ---没有正在预测 也没有未查看的预测数据
+                //接受参数 调rpc 预测中标数据
+                getRes := new(util.ForecastS)
+                //接收参数
+                json.Unmarshal(this.Body(), &getRes)
+                if getRes.Type == "" && getRes.Id != "" {
+                    //是否是子账号
+                    var s_phone, _ = this.GetSession("s_phone").(string)
+                    if s_phone == "" {
+                        s_phone, _ = this.GetSession("s_m_phone").(string)
+                    }
+                    main_userId, phone, member_status := util.MainUserId(this.Session())
+                    entity.UIL.Lock()
+                    if entity.UIL.ForWLock[main_userId] == nil {
+                        entity.UIL.ForWLock[main_userId] = &sync.Mutex{}
+                    }
+                    entity.UIL.Unlock()
+                    entity.UIL.ForWLock[main_userId].Lock()
+                    defer entity.UIL.ForWLock[main_userId].Unlock()
+                    // log.Println(getRes.ServiceId, "----------", phone)
+                    //判断是否有中标预测权限
+                    var currentCount = 0
+                    getRes.ServiceId = 15
+                    ai, base64Key, currentCount := AnalysisPower("W", main_userId, getRes.Pname, getRes.Infoid, getRes.ServiceId)
+                    // log.Println("ai:", ai)
+                    if ai > 0 {
+                        log.Println(main_userId, "---ai:", ai)
+                        if ai == 2 {
+                            // 订阅及搜索优化版本dev4.3.4调整为预测成功后才扣次数
+                            // UpdatePower(main_userId, getRes.ServiceId) //更新sql库权限次数
+                            redis.Put("newother", "jyPredictedDeduction_"+main_userId, base64Key, 3*24*60*60) //是否需要扣除次数 默认存3天
+                        }
 
-						//中标预测是否有缓存dev4.3.4-王山(项目名称+地区+城市+采购单位+标的物) 默认缓存保留一天
-						redisKeys := GetRedisBase64Key(getRes.Pname, getRes.Area, getRes.City, getRes.Buyer, getRes.BuyerContent)
-						if forecstId := redis.GetStr("newother", "jyPredicted_"+redisKeys); forecstId != "" {
-							if f_id := db.Mgo.Save(C_ForecastData, map[string]interface{}{
-								"userId":      userId,
-								"createtime":  time.Now().Unix(),
-								"status":      1, //预测完成待查看
-								"requestData": getRes,
-								"cacheId":     forecstId,
-								"upeatetime":  time.Now().Unix(),
-							}); f_id != "" {
-								regMap.Data = map[string]interface{}{
-									"status": 3, //缓存数据
-									"id":     util.EncodeId(forecstId),
-									"pname":  getRes.Pname,
-								}
-							} else {
-								regMap.Data = map[string]interface{}{
-									"status": -4, //缓存数据保存异常
-									"pname":  getRes.Pname,
-								}
-							}
-						} else {
-							// 项目信息加密key缓存5+分钟 - 预测成功后提供 项目加密key 把结果id存入redis缓存中时间默认一天
-							redis.Put("newother", "jyPredicted_five_"+main_userId, redisKeys, forecast_time+20)
-							getRes.RedisFKey = redis_forecast_res + userId
-							getRes.Id = util.DecodeId(getRes.Id)
-							if getRes.Infoid != "" {
-								getRes.Infoid = util.DecodeId(getRes.Infoid)
-							}
-							//中标预测数据处理ing
-							if util.JyForecastByRpc(getRes) {
-								//redis 存正在预测标识
-								redis.Put("other", redis_forecast_status+userId, getRes, -1)
-								//预测参数--保存mongodb中
-								f_id := db.Mgo.Save(C_ForecastData, map[string]interface{}{
-									"userId":      userId,
-									"createtime":  time.Now().Unix(),
-									"status":      -1, //预测完成待查看
-									"requestData": getRes,
-									"upeatetime":  time.Now().Unix(),
-								})
-								if f_id != "" {
-									redis.Put("other", redis_forecast_date+userId, f_id, forecast_time)
-								}
-								status = 2 //rpc 已接受参数 正在预测
-							} else {
-								status = -1
-								s_nickname, _ := this.GetSession("s_nickname").(string)
-								if s_nickname == "" {
-									s_nickname, _ = this.GetSession("app_name").(string)
-								}
-								go SaveFalseLogAndSendMail(userId, "rpc 接口调用出错", "", s_nickname, *getRes)
-							}
-							//保存中标预测记录
-							go SaveFWHistorys(status, userId, main_userId, base64Key, phone, currentCount, this.Request, getRes, ai)
-							regMap.Data = map[string]interface{}{
-								"status": status,
-								"pname":  getRes.Pname,
-							}
-						}
-					} else {
-						if member_status == 4 {
-							status = -3 //是否是试用用户
-						} else {
-							status = -2 //账号权限已经用完
-							if main_userId != userId {
-								status = -21 //子账号权限
-							}
-						}
-						regMap.Data = map[string]interface{}{
-							"status": status,
-							"pname":  getRes.Pname,
-						}
-					}
-				}
-			} else {
-				regMap.Error_code = Error_code_1002
-				regMap.Error_msg = Error_msg_1002
-			}
-		}
-	} else {
-		regMap.Error_code = Error_code_1005
-		regMap.Error_msg = Error_msg_1005
-	}
-	this.ServeJson(regMap)
+                        //中标预测是否有缓存dev4.3.4-王山(项目名称+地区+城市+采购单位+标的物) 默认缓存保留一天
+                        redisKeys := GetRedisBase64Key(getRes.Pname, getRes.Area, getRes.City, getRes.Buyer, getRes.BuyerContent)
+                        if forecstId := redis.GetStr("newother", "jyPredicted_"+redisKeys); forecstId != "" {
+                            if f_id := db.Mgo.Save(C_ForecastData, map[string]interface{}{
+                                "userId":      userId,
+                                "createtime":  time.Now().Unix(),
+                                "status":      1, //预测完成待查看
+                                "requestData": getRes,
+                                "cacheId":     forecstId,
+                                "upeatetime":  time.Now().Unix(),
+                            }); f_id != "" {
+                                regMap.Data = map[string]interface{}{
+                                    "status": 3, //缓存数据
+                                    "id":     util.EncodeId(forecstId),
+                                    "pname":  getRes.Pname,
+                                }
+                            } else {
+                                regMap.Data = map[string]interface{}{
+                                    "status": -4, //缓存数据保存异常
+                                    "pname":  getRes.Pname,
+                                }
+                            }
+                        } else {
+                            // 项目信息加密key缓存5+分钟 - 预测成功后提供 项目加密key 把结果id存入redis缓存中时间默认一天
+                            redis.Put("newother", "jyPredicted_five_"+main_userId, redisKeys, forecast_time+20)
+                            getRes.RedisFKey = redis_forecast_res + userId
+                            getRes.Id = util.DecodeId(getRes.Id)
+                            if getRes.Infoid != "" {
+                                getRes.Infoid = util.DecodeId(getRes.Infoid)
+                            }
+                            //中标预测数据处理ing
+                            if util.JyForecastByRpc(getRes) {
+                                //redis 存正在预测标识
+                                redis.Put("other", redis_forecast_status+userId, getRes, -1)
+                                //预测参数--保存mongodb中
+                                f_id := db.Mgo.Save(C_ForecastData, map[string]interface{}{
+                                    "userId":      userId,
+                                    "createtime":  time.Now().Unix(),
+                                    "status":      -1, //预测完成待查看
+                                    "requestData": getRes,
+                                    "upeatetime":  time.Now().Unix(),
+                                })
+                                if f_id != "" {
+                                    redis.Put("other", redis_forecast_date+userId, f_id, forecast_time)
+                                }
+                                status = 2 //rpc 已接受参数 正在预测
+                            } else {
+                                status = -1
+                                s_nickname, _ := this.GetSession("s_nickname").(string)
+                                if s_nickname == "" {
+                                    s_nickname, _ = this.GetSession("app_name").(string)
+                                }
+                                go SaveFalseLogAndSendMail(userId, "rpc 接口调用出错", "", s_nickname, *getRes)
+                            }
+                            //保存中标预测记录
+                            go SaveFWHistorys(status, userId, main_userId, base64Key, phone, currentCount, this.Request, getRes, ai)
+                            regMap.Data = map[string]interface{}{
+                                "status": status,
+                                "pname":  getRes.Pname,
+                            }
+                        }
+                    } else {
+                        if member_status == 4 {
+                            status = -3 //是否是试用用户
+                        } else {
+                            status = -2 //账号权限已经用完
+                            if main_userId != userId {
+                                status = -21 //子账号权限
+                            }
+                        }
+                        regMap.Data = map[string]interface{}{
+                            "status": status,
+                            "pname":  getRes.Pname,
+                        }
+                    }
+                }
+            } else {
+                regMap.Error_code = Error_code_1002
+                regMap.Error_msg = Error_msg_1002
+            }
+        }
+    } else {
+        regMap.Error_code = Error_code_1005
+        regMap.Error_msg = Error_msg_1005
+    }
+    this.ServeJson(regMap)
 }
 
-//是否有正在预测或已预测未查看的信息
+// 是否有正在预测或已预测未查看的信息
 func isExistsFIng(userId string) (success bool, id string) {
-	rfsExist, _ := redis.Exists("other", redis_forecast_status+userId)
-	rfrExist, _ := redis.Exists("other", redis_forecast_res+userId)
-	rfdExist, _ := redis.Exists("other", redis_forecast_date+userId)
-	// log.Println(rfsExist, "--------", rfrExist)
-	//五分钟之内 有预测数据 或正在预测。。。。
-	if rfdExist && (rfsExist || (rfsExist && rfrExist)) {
-		success = true
-	} else {
-		//有预测过但是没查看的信息
-		list, ok := db.Mgo.Find(C_ForecastData, map[string]interface{}{
-			"userId": userId,
-			"status": 0,
-		}, `{"createtime":-1}`, `{"requestData":1,"responseData":1}`, false, -1, -1)
-		if ok && list != nil && len(*list) > 0 {
-			r := qutil.ObjToMap((*list)[0])
-			id = util.EncodeId(BsonIdToSId((*r)["_id"]))
-			success = true
-		}
-	}
-	return
+    rfsExist, _ := redis.Exists("other", redis_forecast_status+userId)
+    rfrExist, _ := redis.Exists("other", redis_forecast_res+userId)
+    rfdExist, _ := redis.Exists("other", redis_forecast_date+userId)
+    // log.Println(rfsExist, "--------", rfrExist)
+    //五分钟之内 有预测数据 或正在预测。。。。
+    if rfdExist && (rfsExist || (rfsExist && rfrExist)) {
+        success = true
+    } else {
+        //有预测过但是没查看的信息
+        list, ok := db.Mgo.Find(C_ForecastData, map[string]interface{}{
+            "userId": userId,
+            "status": 0,
+        }, `{"createtime":-1}`, `{"requestData":1,"responseData":1}`, false, -1, -1)
+        if ok && list != nil && len(*list) > 0 {
+            r := qutil.ObjToMap((*list)[0])
+            id = util.EncodeId(BsonIdToSId((*r)["_id"]))
+            success = true
+        }
+    }
+    return
 }
 
 type EntInfo struct {
-	EntName     string  `json:"entName"`     //企业名称
-	Score       float64 `json:"score"`       //中标概率
-	Weight      float64 `json:"weight"`      //权重
-	DateStr     string  `json:"dateStr"`     //establish_date 成立日期
-	Phone       string  `json:"phone"`       //company_phone 联系方式
-	Area        string  `json:"area"`        //company_area 地区
-	City        string  `json:"city"`        //company_city 城市
-	Capital     float64 `json:"capital"`     //capital 注册资本
-	Employee_no string  `json:"employee_no"` //employee_no 员工人数
-	Id          string  `json:"id"`
+    EntName     string  `json:"entName"`     //企业名称
+    Score       float64 `json:"score"`       //中标概率
+    Weight      float64 `json:"weight"`      //权重
+    DateStr     string  `json:"dateStr"`     //establish_date 成立日期
+    Phone       string  `json:"phone"`       //company_phone 联系方式
+    Area        string  `json:"area"`        //company_area 地区
+    City        string  `json:"city"`        //company_city 城市
+    Capital     float64 `json:"capital"`     //capital 注册资本
+    Employee_no string  `json:"employee_no"` //employee_no 员工人数
+    Id          string  `json:"id"`
 }
 
-//前端每5秒查一次 预测是否完成
+// 前端每5秒查一次 预测是否完成
 func (this *Analysis) FWStatus() {
-	defer qutil.Catch()
-	var regMap = Result{
-		Data:       []map[string]interface{}{},
-		Error_code: Error_code,
-		Error_msg:  "",
-	}
-	if this.Method() == METHOD {
-		userId, _ := this.GetSession("userId").(string)
-		if userId != "" {
-			//父级userid
-			// userid := util.MainUserId(userId)
-			main_userId, _, _ := util.MainUserId(this.Session())
-			rfrExist, _ := redis.Exists("other", redis_forecast_res+userId)
-			f_id := redis.GetStr("other", redis_forecast_date+userId)
-			var isFFalse = 0  //是否预测失败
-			var falseMsg = "" //预测失败备注
-			// log.Println("---1--", rfrExist)
-			if rfrExist && f_id != "" {
-				var resp = []*EntInfo{}
-				f_res := redis.Get("other", redis_forecast_res+userId)
-				if f_res != nil && f_res.(string) != "" {
-					json.Unmarshal([]byte(f_res.(string)), &resp)
-					//获取数据为空
-					if resp != nil && len(resp) > 0 {
-						//rpc 返回预测数据只有企业名称和中标概率  还需要查询企业得成立日期 注册资本 员工人数 地区 城市 联系电话 企业信用库id
-						handleData := handleResp(resp)
-						//结果更新mongodb中
-						if db.Mgo.UpdateById(C_ForecastData, f_id, map[string]interface{}{
-							"$set": map[string]interface{}{
-								"status":       0,
-								"responseData": handleData,
-								"upeatetime":   time.Now().Unix(),
-							},
-						}) {
-							regMap.Data = map[string]interface{}{
-								"id":      util.EncodeId(f_id),
-								"success": true,
-							}
-							// 订阅及搜索优化版本dev4.3.4调整为预测成功后才扣次数
-							go func(userId, f_id string) {
-								main_userId, _, _ := util.MainUserId(this.Session())
-								if ok, _ := redis.Exists("newother", "jyPredictedDeduction_"+main_userId); ok {
-									//扣除次数
-									UpdatePower(main_userId, 15)
-									redis.Del("newother", "jyPredictedDeduction_"+main_userId)
-								}
-								// 预测项目信息  缓存 五分钟
-								redisKeys := redis.GetStr("newother", "jyPredicted_five_"+main_userId)
-								if redisKeys != "" {
-									//缓存默认一天
-									redis.Put("newother", "jyPredicted_"+redisKeys, f_id, qutil.IntAllDef(Config.ForecastTime, 86400))
-								}
-							}(userId, f_id)
-						} else {
-							isFFalse = 1
-							falseMsg = "中标预测二次更新状态出错"
-							log.Println(falseMsg, " :", f_id)
-						}
-					} else {
-						isFFalse = 2
-						falseMsg = "中标预测redis序列化数据出错" + f_res.(string)
-						log.Println(falseMsg, " :", f_id)
-					}
-				} else {
-					isFFalse = 3
-					falseMsg = "从redis获取预测数据出错" + f_res.(string)
-					log.Println(falseMsg, " :", f_id, f_res)
-				}
-				//保存请求日志
-				go func(f_id, userId, main_userId string, resp []*EntInfo) {
-					//log.Println("--resp--", resp)
-					var getRes map[string]interface{}
-					if redis.GetNewInterface("other", redis_forecast_status+userId, &getRes) != nil {
-						log.Println("redis 获取预测参数有误-", userId)
-					}
-					forecastLog(userId, main_userId, f_id, getRes, resp)
-				}(f_id, userId, main_userId, resp)
-			} else {
-				//预测中
-				rfdExist, _ := redis.Exists("other", redis_forecast_date+userId)
-				if rfdExist {
-					regMap.Data = map[string]interface{}{
-						"id":      "",
-						"success": true,
-					}
-				} else {
-					isFFalse = 4
-					falseMsg = "预测超时(五分钟)"
-					log.Println(falseMsg, " :", userId)
-				}
-			}
-			if isFFalse > 0 {
-				if rfrExist && f_id != "" {
-					go func() {
-						//发送失败邮件提醒
-						getRes := new(util.ForecastS)
-						if redis.GetNewInterface("other", redis_forecast_status+userId, &getRes) != nil {
-							log.Println("redis 1获取预测参数有误-", userId)
-						}
-						s_nickname, _ := this.GetSession("s_nickname").(string)
-						if s_nickname == "" {
-							s_nickname, _ = this.GetSession("app_name").(string)
-						}
-						SaveFalseLogAndSendMail(userId, falseMsg, f_id, s_nickname, *getRes)
-					}()
-				}
-				//预测失败 清除redis数据
-				ClearRedisInfo(userId)
-				regMap.Data = map[string]interface{}{
-					"id":      "",
-					"success": false,
-				}
-			}
-		} else {
-			regMap.Error_code = Error_code_1001
-			regMap.Error_msg = Error_msg_1001
-		}
-	} else {
-		regMap.Error_code = Error_code_1005
-		regMap.Error_msg = Error_msg_1005
-	}
-	this.ServeJson(regMap)
+    defer qutil.Catch()
+    var regMap = Result{
+        Data:       []map[string]interface{}{},
+        Error_code: Error_code,
+        Error_msg:  "",
+    }
+    if this.Method() == METHOD {
+        userId, _ := this.GetSession("userId").(string)
+        if userId != "" {
+            //父级userid
+            // userid := util.MainUserId(userId)
+            main_userId, _, _ := util.MainUserId(this.Session())
+            rfrExist, _ := redis.Exists("other", redis_forecast_res+userId)
+            f_id := redis.GetStr("other", redis_forecast_date+userId)
+            var isFFalse = 0  //是否预测失败
+            var falseMsg = "" //预测失败备注
+            // log.Println("---1--", rfrExist)
+            if rfrExist && f_id != "" {
+                var resp = []*EntInfo{}
+                f_res := redis.Get("other", redis_forecast_res+userId)
+                if f_res != nil && f_res.(string) != "" {
+                    json.Unmarshal([]byte(f_res.(string)), &resp)
+                    //获取数据为空
+                    if resp != nil && len(resp) > 0 {
+                        //rpc 返回预测数据只有企业名称和中标概率  还需要查询企业得成立日期 注册资本 员工人数 地区 城市 联系电话 企业信用库id
+                        handleData := handleResp(resp)
+                        //结果更新mongodb中
+                        if db.Mgo.UpdateById(C_ForecastData, f_id, map[string]interface{}{
+                            "$set": map[string]interface{}{
+                                "status":       0,
+                                "responseData": handleData,
+                                "upeatetime":   time.Now().Unix(),
+                            },
+                        }) {
+                            regMap.Data = map[string]interface{}{
+                                "id":      util.EncodeId(f_id),
+                                "success": true,
+                            }
+                            // 订阅及搜索优化版本dev4.3.4调整为预测成功后才扣次数
+                            go func(userId, f_id string) {
+                                main_userId, _, _ := util.MainUserId(this.Session())
+                                if ok, _ := redis.Exists("newother", "jyPredictedDeduction_"+main_userId); ok {
+                                    //扣除次数
+                                    UpdatePower(main_userId, 15)
+                                    redis.Del("newother", "jyPredictedDeduction_"+main_userId)
+                                }
+                                // 预测项目信息  缓存 五分钟
+                                redisKeys := redis.GetStr("newother", "jyPredicted_five_"+main_userId)
+                                if redisKeys != "" {
+                                    //缓存默认一天
+                                    redis.Put("newother", "jyPredicted_"+redisKeys, f_id, qutil.IntAllDef(Config.ForecastTime, 86400))
+                                }
+                            }(userId, f_id)
+                        } else {
+                            isFFalse = 1
+                            falseMsg = "中标预测更新异常"
+                            log.Println("中标预测二次更新状态出错", " :", f_id)
+                        }
+                    } else {
+                        isFFalse = 2
+                        falseMsg = "暂无预测结果"
+                        log.Println("中标预测redis序列化数据出错", " :", f_id, "---", f_res.(string))
+                    }
+                } else {
+                    isFFalse = 3
+                    falseMsg = "暂无预测结果-"
+                    log.Println("从redis获取预测数据出错", f_res.(string), " :", f_id, f_res)
+                }
+                //保存请求日志
+                go func(f_id, userId, main_userId string, resp []*EntInfo) {
+                    //log.Println("--resp--", resp)
+                    var getRes map[string]interface{}
+                    if redis.GetNewInterface("other", redis_forecast_status+userId, &getRes) != nil {
+                        log.Println("redis 获取预测参数有误-", userId)
+                    }
+                    forecastLog(userId, main_userId, f_id, getRes, resp)
+                }(f_id, userId, main_userId, resp)
+            } else {
+                //预测中
+                rfdExist, _ := redis.Exists("other", redis_forecast_date+userId)
+                if rfdExist {
+                    regMap.Data = map[string]interface{}{
+                        "id":      "",
+                        "success": true,
+                    }
+                } else {
+                    isFFalse = 4
+                    falseMsg = "预测超时(五分钟)"
+                    log.Println(falseMsg, " :", userId)
+                }
+            }
+            if isFFalse > 0 {
+                if rfrExist && f_id != "" {
+                    go func() {
+                        //发送失败邮件提醒
+                        getRes := new(util.ForecastS)
+                        if redis.GetNewInterface("other", redis_forecast_status+userId, &getRes) != nil {
+                            log.Println("redis 1获取预测参数有误-", userId)
+                        }
+                        s_nickname, _ := this.GetSession("s_nickname").(string)
+                        if s_nickname == "" {
+                            s_nickname, _ = this.GetSession("app_name").(string)
+                        }
+                        SaveFalseLogAndSendMail(userId, falseMsg, f_id, s_nickname, *getRes)
+                    }()
+                }
+                //预测失败 清除redis数据
+                ClearRedisInfo(userId)
+                regMap.Data = map[string]interface{}{
+                    "id":      "",
+                    "success": false,
+                }
+            }
+        } else {
+            regMap.Error_code = Error_code_1001
+            regMap.Error_msg = Error_msg_1001
+        }
+    } else {
+        regMap.Error_code = Error_code_1005
+        regMap.Error_msg = Error_msg_1005
+    }
+    this.ServeJson(regMap)
 
 }
 
-//查询中标企业名称【带曾用名检索】
+// 查询中标企业名称【带曾用名检索】
 const queryFullEntName = `{"query":{"function_score":{"query":{"multi_match":{"query":"%s","type":"phrase","fields":["name","history_name"]}},"field_value_factor":{"field":"company_type_int","modifier":"reciprocal","factor":2}}},"_source":["name","history_name","company_type_int","_id"],"size":%d}`
 
-//数据填充
+// 数据填充
 func handleResp(r []*EntInfo) []*EntInfo {
-	if len(r) > 0 {
-		for _, v := range r {
-			entInfo, _ := db.Mgo_Ent.FindOne(C_FW_qyxy, `{"company_name":"`+v.EntName+`"}`)
-			if entInfo == nil || (*entInfo)["_id"] == nil {
-				list := elastic.Get("qyxy", "qyxy", fmt.Sprintf(queryFullEntName, v.EntName, 1))
-				if list != nil && len(*list) > 0 {
-					entInfo = &(*list)[0]
-				}
-			}
-			if entInfo != nil {
-				if (*entInfo)["company_area"] != nil {
-					v.Area = qutil.ObjToString((*entInfo)["company_area"])
-				}
-				if (*entInfo)["company_city"] != nil {
-					v.City = qutil.ObjToString((*entInfo)["company_city"])
-				}
-				if (*entInfo)["company_phone"] != nil {
-					v.Phone = qutil.ObjToString((*entInfo)["company_phone"])
-				}
-				if (*entInfo)["establish_date"] != nil {
-					v.DateStr = qutil.ObjToString((*entInfo)["establish_date"])
-				}
-				if (*entInfo)["capital"] != nil {
-					v.Capital = qutil.Float64All((*entInfo)["capital"])
-				}
-				if (*entInfo)["_id"] != nil {
-					v.Id = qutil.ObjToString((*entInfo)["_id"])
-				}
-				if (*entInfo)["annual_reports"] != nil {
-					annual_reports := qutil.ObjArrToMapArr((*entInfo)["annual_reports"].([]interface{}))
-					if len(annual_reports) > 0 {
-						reportOne := annual_reports[0]
-						if reportOne["employee_no"] != nil && qutil.ObjToString(reportOne["employee_no"]) != "" {
-							employee_no := qutil.ObjToString(reportOne["employee_no"])
-							if reg.MatchString(employee_no) {
-								v.Employee_no = employee_no
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-	return r
+    if len(r) > 0 {
+        for _, v := range r {
+            entInfo, _ := db.Mgo_Ent.FindOne(C_FW_qyxy, `{"company_name":"`+v.EntName+`"}`)
+            if entInfo == nil || (*entInfo)["_id"] == nil {
+                list := elastic.Get("qyxy", "qyxy", fmt.Sprintf(queryFullEntName, v.EntName, 1))
+                if list != nil && len(*list) > 0 {
+                    entInfo = &(*list)[0]
+                }
+            }
+            if entInfo != nil {
+                if (*entInfo)["company_area"] != nil {
+                    v.Area = qutil.ObjToString((*entInfo)["company_area"])
+                }
+                if (*entInfo)["company_city"] != nil {
+                    v.City = qutil.ObjToString((*entInfo)["company_city"])
+                }
+                if (*entInfo)["company_phone"] != nil {
+                    v.Phone = qutil.ObjToString((*entInfo)["company_phone"])
+                }
+                if (*entInfo)["establish_date"] != nil {
+                    v.DateStr = qutil.ObjToString((*entInfo)["establish_date"])
+                }
+                if (*entInfo)["capital"] != nil {
+                    v.Capital = qutil.Float64All((*entInfo)["capital"])
+                }
+                if (*entInfo)["_id"] != nil {
+                    v.Id = qutil.ObjToString((*entInfo)["_id"])
+                }
+                if (*entInfo)["annual_reports"] != nil {
+                    annual_reports := qutil.ObjArrToMapArr((*entInfo)["annual_reports"].([]interface{}))
+                    if len(annual_reports) > 0 {
+                        reportOne := annual_reports[0]
+                        if reportOne["employee_no"] != nil && qutil.ObjToString(reportOne["employee_no"]) != "" {
+                            employee_no := qutil.ObjToString(reportOne["employee_no"])
+                            if reg.MatchString(employee_no) {
+                                v.Employee_no = employee_no
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return r
 }
 
-//结果
+// 结果
 func (this *Analysis) FWResult() {
-	defer qutil.Catch()
-	var regMap = Result{
-		Data:       []map[string]interface{}{},
-		Error_code: Error_code,
-		Error_msg:  "",
-	}
-	if true || this.Method() == METHOD {
-		userId, _ := this.GetSession("userId").(string)
-		f_id := this.GetString("id")
-		// f_id = util.EncodeId(f_id)
-		if f_id != "" {
-			f_id = util.DecodeId(f_id)
-			res, ok := db.Mgo.FindById(C_ForecastData, f_id, `{"requestData":1,"responseData":1}`)
-			if ok {
-				if !db.Mgo.UpdateById(C_ForecastData, f_id, map[string]interface{}{
-					"$set": map[string]interface{}{"status": 1}, //中标预测信息已读
-				}) {
-					log.Println("中标预测信息已读修改报错:", userId, time.Now().Unix())
-				} else {
-					if res != nil {
-						delete((*res), "_id")
-						requestData := *qutil.ObjToMap((*res)["requestData"])
-						if requestData != nil && requestData["id"] != nil {
-							abstract := *elastic.GetById(P_INDEX, P_TYPE, requestData["id"].(string))
-							if len(abstract) > 0 {
-								requestData["agency"] = abstract[0]["agency"]
-								requestData["_area"] = abstract[0]["area"]
-								requestData["_city"] = abstract[0]["city"]
-								requestData["buyerperson"] = abstract[0]["buyerperson"]
-								requestData["buyertel"] = abstract[0]["buyertel"]
-							}
-							requestData["id"] = util.EncodeId(requestData["id"].(string))
-							requestData["infoid"] = util.EncodeId(requestData["infoid"].(string))
-						}
-						delete(requestData, "redisfkey")
-						//结果
-						responseData := qutil.ObjArrToMapArr((*res)["responseData"].([]interface{}))
-						if responseData != nil && len(responseData) > 0 {
-							for _, v := range responseData {
-								rdv := *qutil.ObjToMap(v)
-								entId := qutil.ObjToString(rdv["id"])
-								if rdv["id"] == nil || qutil.ObjToString(rdv["id"]) == "" {
-									entName := qutil.ObjToString(rdv["entname"])
-									entId = entity.GetEntIdByQYXY(entName)
-								}
-								rdv["entId"] = util.EncodeId(entId)
-							}
-						}
-					}
-					regMap.Data = res
-					go ClearRedisInfo(userId)
-				}
-			} else {
-				log.Println("forecast_find_err:")
-			}
-		} else {
-			regMap.Error_code = Error_code_1002
-			regMap.Error_msg = Error_msg_1002
-		}
-	} else {
-		regMap.Error_code = Error_code_1005
-		regMap.Error_msg = Error_msg_1005
-	}
-	this.ServeJson(regMap)
+    defer qutil.Catch()
+    var regMap = Result{
+        Data:       []map[string]interface{}{},
+        Error_code: Error_code,
+        Error_msg:  "",
+    }
+    if true || this.Method() == METHOD {
+        userId, _ := this.GetSession("userId").(string)
+        f_id := this.GetString("id")
+        // f_id = util.EncodeId(f_id)
+        if f_id != "" {
+            f_id = util.DecodeId(f_id)
+            res, ok := db.Mgo.FindById(C_ForecastData, f_id, `{"requestData":1,"responseData":1}`)
+            if ok {
+                if !db.Mgo.UpdateById(C_ForecastData, f_id, map[string]interface{}{
+                    "$set": map[string]interface{}{"status": 1}, //中标预测信息已读
+                }) {
+                    log.Println("中标预测信息已读修改报错:", userId, time.Now().Unix())
+                } else {
+                    if res != nil {
+                        delete((*res), "_id")
+                        requestData := *qutil.ObjToMap((*res)["requestData"])
+                        if requestData != nil && requestData["id"] != nil {
+                            abstract := *elastic.GetById(P_INDEX, P_TYPE, requestData["id"].(string))
+                            if len(abstract) > 0 {
+                                requestData["agency"] = abstract[0]["agency"]
+                                requestData["_area"] = abstract[0]["area"]
+                                requestData["_city"] = abstract[0]["city"]
+                                requestData["buyerperson"] = abstract[0]["buyerperson"]
+                                requestData["buyertel"] = abstract[0]["buyertel"]
+                            }
+                            requestData["id"] = util.EncodeId(requestData["id"].(string))
+                            requestData["infoid"] = util.EncodeId(requestData["infoid"].(string))
+                        }
+                        delete(requestData, "redisfkey")
+                        //结果
+                        responseData := qutil.ObjArrToMapArr((*res)["responseData"].([]interface{}))
+                        if responseData != nil && len(responseData) > 0 {
+                            for _, v := range responseData {
+                                rdv := *qutil.ObjToMap(v)
+                                entId := qutil.ObjToString(rdv["id"])
+                                if rdv["id"] == nil || qutil.ObjToString(rdv["id"]) == "" {
+                                    entName := qutil.ObjToString(rdv["entname"])
+                                    entId = entity.GetEntIdByQYXY(entName)
+                                }
+                                rdv["entId"] = util.EncodeId(entId)
+                            }
+                        }
+                    }
+                    regMap.Data = res
+                    go ClearRedisInfo(userId)
+                }
+            } else {
+                log.Println("forecast_find_err:")
+            }
+        } else {
+            regMap.Error_code = Error_code_1002
+            regMap.Error_msg = Error_msg_1002
+        }
+    } else {
+        regMap.Error_code = Error_code_1005
+        regMap.Error_msg = Error_msg_1005
+    }
+    this.ServeJson(regMap)
 }
 
-//预测结果日志
+// 预测结果日志
 func forecastLog(userId, userid, f_id string, getRes map[string]interface{}, resp []*EntInfo) {
-	id := db.Mgo.Save(C_ForecastLog, map[string]interface{}{
-		"userId":       userId,
-		"f_userId":     userid,
-		"createtime":   time.Now().Unix(),
-		"f_id":         f_id,
-		"requestData":  getRes,
-		"responseData": resp,
-	})
-	if id == "" {
-		log.Println("forecast-log-err:")
-	}
+    id := db.Mgo.Save(C_ForecastLog, map[string]interface{}{
+        "userId":       userId,
+        "f_userId":     userid,
+        "createtime":   time.Now().Unix(),
+        "f_id":         f_id,
+        "requestData":  getRes,
+        "responseData": resp,
+    })
+    if id == "" {
+        log.Println("forecast-log-err:")
+    }
 }
 
-//中标信息预测结束
+// 中标信息预测结束
 func ClearRedisInfo(userId string) {
-	redis.Del("other", redis_forecast_res+userId)
-	redis.Del("other", redis_forecast_status+userId)
-	redis.Del("other", redis_forecast_date+userId)
+    redis.Del("other", redis_forecast_res+userId)
+    redis.Del("other", redis_forecast_status+userId)
+    redis.Del("other", redis_forecast_date+userId)
 }
 
-//报错预测失败日志 并发送邮件
+// 报错预测失败日志 并发送邮件
 func SaveFalseLogAndSendMail(userId, msg, f_id, nickname string, res util.ForecastS) {
-	email := Config.WarnMailbox
-	if len(email) > 0 {
-		var resHtml = ``
-		var divH2 = "420px"
-		// log.Println("res:", res)
-		if len(res.BuyerContent) > 0 {
-			divH2 = "535px"
-			resHtml = `<p>中标预测内容:<div style="margin-left: 30px;font-size: 13px;"><p style="line-height: 12px;">项目名称:"` + res.Pname + `"</p><p style="line-height: 12px;">采购内容:"` + strings.Join(res.BuyerContent, ",") + `"</p><p style="line-height: 12px;">采购单位:"` + res.Buyer + `"</p><p style="line-height: 12px;">采购预算:"` + strconv.FormatFloat(res.Budget, 'f', -1, 64) + `"</p><p style="line-height: 12px;">区域:"` + res.Area + " " + res.City + `"</p></div></p>`
-		}
-		content := `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body style="margin: 0;padding: 0;"><div class="Email" id="Email" style="width: 100%%;height: 100%%;display: flex;flex-direction: column;align-items: center; background: #E5E5E5;"><div class="emailmain" style="width: 1200px;height: ` + divH2 + `;border-top: 8px solid #2CB7CA;border-radius: 8px; background: #fff; margin-top: 107px; padding: 0 40px;"><div class="emailmain_top" style="height: 88px;width: 100%%; border-bottom: 1px solid #F7F7F7; display: flex;justify-content: center;align-items: center;"><img src="https://www.jianyu360.com/images/swordfish/sf_01.png" alt="" style="width: 130px;"></div><div class="emailmain_bottom" style="display: flex;flex-direction: column; align-items: center;"><p class="emailmain_text" style="margin-top: 10px;width: 960px;font-size: 16px;line-height: 24px;color: #1D1D1D;">尊敬的管理员:<br>&nbsp;&nbsp;&nbsp;&nbsp;您好,中标预测失败信息如下:</p> <div class="download" style="margin-top: 0px;width: 100%%; height: 30px;justify-content: center;align-items: center;"><p>用户昵称:"` + nickname + `"</p><p>用户userid:"` + userId + `"</p><p>中标预测信息id:"` + f_id + `"</p><p>中标预测失败原因:"` + msg + `"</p>` + resHtml + `</div></div></div><p class="havapro"style="font-size: 14px;height: 24px;color: #686868;margin-top: 32px;">如有问题请<a href="mailto:bd@topnet.net.cn" class="click_here" id="click_here" style="color: #0987FF;cursor: pointer;text-decoration:none;">点击此处</a>,进行意见反馈</p></div></body></html>`
-		for _, v := range email {
-			if regexp.MustCompile("^\\d+$").MatchString(v) {
-				continue
-			}
-			if !util.SendRetryMail(Config.ReTry, v, Config.WarnMbTitle, content, "", nil, GmailAuth) {
-				log.Println("预测失败邮件发送失败")
-			}
-		}
-	}
+    email := Config.WarnMailbox
+    if len(email) > 0 {
+        var resHtml = ``
+        var divH2 = "420px"
+        // log.Println("res:", res)
+        if len(res.BuyerContent) > 0 {
+            divH2 = "535px"
+            resHtml = `<p>中标预测内容:<div style="margin-left: 30px;font-size: 13px;"><p style="line-height: 12px;">项目名称:"` + res.Pname + `"</p><p style="line-height: 12px;">采购内容:"` + strings.Join(res.BuyerContent, ",") + `"</p><p style="line-height: 12px;">采购单位:"` + res.Buyer + `"</p><p style="line-height: 12px;">采购预算:"` + strconv.FormatFloat(res.Budget, 'f', -1, 64) + `"</p><p style="line-height: 12px;">区域:"` + res.Area + " " + res.City + `"</p></div></p>`
+        }
+        content := `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body style="margin: 0;padding: 0;"><div class="Email" id="Email" style="width: 100%%;height: 100%%;display: flex;flex-direction: column;align-items: center; background: #E5E5E5;"><div class="emailmain" style="width: 1200px;height: ` + divH2 + `;border-top: 8px solid #2CB7CA;border-radius: 8px; background: #fff; margin-top: 107px; padding: 0 40px;"><div class="emailmain_top" style="height: 88px;width: 100%%; border-bottom: 1px solid #F7F7F7; display: flex;justify-content: center;align-items: center;"><img src="https://www.jianyu360.com/images/swordfish/sf_01.png" alt="" style="width: 130px;"></div><div class="emailmain_bottom" style="display: flex;flex-direction: column; align-items: center;"><p class="emailmain_text" style="margin-top: 10px;width: 960px;font-size: 16px;line-height: 24px;color: #1D1D1D;">尊敬的管理员:<br>&nbsp;&nbsp;&nbsp;&nbsp;您好,中标预测失败信息如下:</p> <div class="download" style="margin-top: 0px;width: 100%%; height: 30px;justify-content: center;align-items: center;"><p>用户昵称:"` + nickname + `"</p><p>用户userid:"` + userId + `"</p><p>中标预测信息id:"` + f_id + `"</p><p>中标预测失败原因:"` + msg + `"</p>` + resHtml + `</div></div></div><p class="havapro"style="font-size: 14px;height: 24px;color: #686868;margin-top: 32px;">如有问题请<a href="mailto:bd@topnet.net.cn" class="click_here" id="click_here" style="color: #0987FF;cursor: pointer;text-decoration:none;">点击此处</a>,进行意见反馈</p></div></body></html>`
+        for _, v := range email {
+            if regexp.MustCompile("^\\d+$").MatchString(v) {
+                continue
+            }
+            if !util.SendRetryMail(Config.ReTry, v, Config.WarnMbTitle, content, "", nil, GmailAuth) {
+                log.Println("预测失败邮件发送失败")
+            }
+        }
+    }
 }

+ 49 - 0
src/jfw/modules/bigmember/src/service/report/marketAnalysis.go

@@ -22,6 +22,55 @@ type MarketAnalysis struct {
 	getAnalysisResult xweb.Mapper `xweb:"/marketAnalysis/getAnalysisResult"` //获取分析报告结果(根据记录id查询报告结果)
 	analysisHistory   xweb.Mapper `xweb:"/marketAnalysis/analysisHistory"`   //市场分析报告历史记录
 	analysisKeyWord   xweb.Mapper `xweb:"/marketAnalysis/analysisKeyWord"`   //市场分析报告订阅词
+	projectInfo       xweb.Mapper `xweb:"/marketAnalysis/projectInfo"`       //项目明细
+}
+
+// 项目明细
+func (this *MarketAnalysis) ProjectInfo() {
+	userId := qutil.ObjToString(this.GetSession("userId"))
+	rData, errMsg := func() (interface{}, error) {
+		pid, powerErr := checkPower(this.Session())
+		if powerErr != nil {
+			return nil, powerErr
+		}
+		var (
+			sort, _     = this.GetInteger("sort")
+			pageSize, _ = this.GetInteger("pageSize")
+			pageNum, _  = this.GetInteger("pageNum")
+		)
+		log.Println("-----:", this.GetString("keysItems"))
+		//接受参数
+		bParam := marketAnalysis.AnalysisRequestParam{
+			KeysItemsStr:   this.GetString("keysItems"),      //分析内容【字符串】结构和o_member_jy.a_items保持一致
+			RangeTime:      this.GetString("rangeTime"),      //时间【字符串】 时间戳开始-结束时间戳
+			RangeTimeExtra: this.GetString("rangeTimeExtra"), //时间【字符串】 时间戳开始-结束时间戳
+			Area:           this.GetString("area"),           //省份【字符串】多个省份用逗号拼接
+			Industry:       this.GetString("industry"),       //行业【字符串】多个行业用逗号拼接
+			BuyerClass:     this.GetString("buyerclass"),     //采购单位类型【字符串】多个采购单位类型用逗号拼接
+			Buyer:          this.GetString("buyer"),          //采购单位
+			Winner:         this.GetString("winner"),         //中标单位
+			Sort:           sort,                             //排序
+			PageSize:       pageSize,                         //每页数据量
+			PageNum:        pageNum,                          //当前页码
+			IsDetail:       true,                             //是否是项目明细请求
+		}
+		mae := &marketAnalysis.MarketAnalysisEntity{BaseParam: bParam, UId: userId, Pid: pid}
+		if err := mae.ForMatData(); err != nil {
+			return nil, err
+		}
+		//项目明细
+		if err := mae.GetProjectInfoList(); err != nil {
+			return nil, err
+		}
+		return map[string]interface{}{
+			"total": mae.ProjectInfo.Count,
+			"list":  mae.ProjectInfo.List,
+		}, nil
+	}()
+	if errMsg != nil {
+		log.Printf("%s MarketAnalysis DoAnalysis Error:%s\n", userId, errMsg.Error())
+	}
+	this.ServeJson(NewResult(rData, errMsg))
 }
 
 // checkPower 权限校验