ソースを参照

12.24---------------合并修改v1

jianghan7 5 年 前
コミット
4102549abb

+ 9 - 5
fullproject/src_v1/config.json

@@ -1,14 +1,18 @@
 {
-    "loadStart":-1,
+    "loadStart": 0,
 	"validdays":150,
 	"mongodbServers": "192.168.3.207:27082",
     "mongodbPoolSize": 10,
-    "mongodbName": "cesuo",
+    "mongodbName": "extract_kf",
 	"hints":"_id_1_publishtime_1",
-    "extractColl": "key1_biddingall",
-    "projectColl": "projectset_zjk",
+    "extractColl": "jh_info",
+    "projectColl": "jh_project",
+    "backupFlag": true,
+    "backupColl": "jh_project1",
+    "siteColl": "site",
+
     "jkmail": {
-        "to": "zhangjinkun@topnet.net.cn",
+        "to": "wangjianghan@topnet.net.cn",
         "api": "http://10.171.112.160:19281/_send/_mail"
     },
     "udpport": ":1482",

+ 15 - 2
fullproject/src_v1/init.go

@@ -23,7 +23,7 @@ const (
 var (
 	Sysconfig                map[string]interface{} //读取配置文件
 	MongoTool                *MongodbSim            //mongodb连接
-	ExtractColl, ProjectColl string                 //抽取表、项目
+	ExtractColl, ProjectColl, BackupColl, SiteColl string	//抽取表、项目表、项目快照表、站点
 	//NextNode                 []interface{}
 )
 
@@ -65,6 +65,8 @@ func init() {
 
 	ExtractColl = Sysconfig["extractColl"].(string)
 	ProjectColl = Sysconfig["projectColl"].(string)
+	BackupColl = Sysconfig["backupColl"].(string)
+	SiteColl = Sysconfig["siteColl"].(string)
 	//NextNode = Sysconfig["nextNode"].([]interface{})
 	udpport, _ := Sysconfig["udpport"].(string)
 	udpclient = mu.UdpClient{Local: udpport, BufSize: 1024}
@@ -201,7 +203,6 @@ type KeyMap struct {
 type ID struct {
 	Id   string
 	Lock sync.Mutex
-	pos  int
 	P    *ProjectInfo
 }
 type Key struct {
@@ -237,6 +238,7 @@ type Info struct {
 	Area        string                 `json:"area"`
 	City        string                 `json:"city"`
 	District    string                 `json:"district"`
+	Infoformat  int					   `json:"infoformat"`
 	HasPackage  bool                   // `json:"haspackage"`
 	Package     map[string]interface{} `json:"package"`
 	//PNum          string                 `json:"pnum"`
@@ -282,6 +284,8 @@ type ProjectInfo struct {
 	Area          string             `json:"area"`                    //地区
 	City          string             `json:"city"`                    //地市
 	District      string             `json:"district"`                //区县
+	Bidstatus     string			 `json:"bidstatus"`				  //
+	Bidtype		  string			 `json:"bidtype"`				  //
 	//HasPackage    bool                   `json:"haspackage"`              //是否有分包
 	Package     map[string]interface{} `json:"package,omitempty"`     //分包的对比对象
 	Buyerclass  string                 `json:"buyerclass"`            //采购单位分类
@@ -296,6 +300,15 @@ type ProjectInfo struct {
 	resVal, pjVal int
 }
 
+type Site struct {
+	Id			string				`json:"_id"`
+	Site		string				`json:"site"`			//站点名字
+	Area 		string				`json:"area"`			//省
+	City		string				`json:"city"`			//市
+	District	string				`json:"district"`		//区、县
+	Domain		string				`json:"domain"`			//地址
+}
+
 //二分字符串查找
 func BinarySearch(s []string, k string) int {
 	sort.Strings(s)

+ 48 - 4
fullproject/src_v1/load_data.go

@@ -9,7 +9,7 @@ import (
 //初始加载数据,默认加载最近6个月的数据
 
 func (p *ProjectTask) loadData(starttime int64) {
-	log.Println("load start..", starttime)
+	log.Println("load project start..", starttime)
 	p.findLock.Lock()
 	defer p.findLock.Unlock()
 	p.AllIdsMapLock.Lock()
@@ -23,7 +23,6 @@ func (p *ProjectTask) loadData(starttime int64) {
 		"list": 0,
 	}).Iter()
 	n := 0
-	//	tmp := &ProjectInfo{}
 	pool := make(chan *ProjectInfo, 100)
 	over := make(chan bool)
 	go func() {
@@ -86,7 +85,7 @@ func (p *ProjectTask) loadData(starttime int64) {
 			go func(res map[string]interface{}) {
 				bys, _ := json.Marshal(result)
 				var tmp *ProjectInfo
-				json.Unmarshal(bys, &tmp)
+				_ = json.Unmarshal(bys, &tmp)
 				pool <- tmp
 			}(result)
 		} else {
@@ -95,5 +94,50 @@ func (p *ProjectTask) loadData(starttime int64) {
 	}
 	time.Sleep(2 * time.Second)
 	over <- true
-	log.Println("load over..", n)
+	log.Println("load project over..", n)
+}
+
+func (p *ProjectTask) loadSite() {
+	log.Println("load site start..")
+	p.findLock.Lock()
+	defer p.findLock.Unlock()
+	p.mapSiteLock.Lock()
+	defer p.mapSiteLock.Unlock()
+	sess := MongoTool.GetMgoConn()
+	defer MongoTool.DestoryMongoConn(sess)
+	q := map[string]interface{}{}
+	it := sess.DB(MongoTool.DbName).C(SiteColl).Find(&q).Iter()
+	n := 0
+	pool := make(chan *Site, 100)
+	over := make(chan bool)
+	go func() {
+		for {
+			select {
+			case tmp := <-pool:
+				n++
+				if tmp != nil {
+					p.mapSite[tmp.Site] = tmp
+				}
+			case <-over:
+				return
+			}
+		}
+	}()
+	for {
+		result := make(map[string]interface{})
+		if it.Next(&result) {
+			go func(res map[string]interface{}) {
+				bys, _ := json.Marshal(result)
+				var tmp *Site
+				_ = json.Unmarshal(bys, &tmp)
+				pool <- tmp
+			}(result)
+		} else {
+			break
+		}
+	}
+	time.Sleep(2 * time.Second)
+	over <- true
+	log.Println("load site over..", n)
+
 }

+ 13 - 2
fullproject/src_v1/main.go

@@ -68,7 +68,8 @@ func main() {
 			P_QL.loadData(loadStart)
 		}
 	}
-	go checkMapJob()
+	P_QL.loadSite()
+	//go checkMapJob()
 	time.Sleep(99999 * time.Hour)
 }
 
@@ -80,7 +81,7 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 		err := json.Unmarshal(data, &mapInfo)
 		log.Println("err:", err, "mapInfo:", mapInfo)
 		if err != nil {
-			udpclient.WriteUdp([]byte("err:"+err.Error()), mu.OP_NOOP, ra)
+			_ = udpclient.WriteUdp([]byte("err:"+err.Error()), mu.OP_NOOP, ra)
 		} else if mapInfo != nil {
 			key, _ := mapInfo["key"].(string)
 			if key == "" {
@@ -110,6 +111,16 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 					P_QL.pici = time.Now().Unix()
 					P_QL.taskZl(mapInfo)
 				}()
+			case "updateInfo":		//招标字段变更
+				go func() {
+					defer func() {
+						<-SingleThread
+					}()
+					P_QL.currentType = tasktype
+					P_QL.pici = time.Now().Unix()
+					P_QL.taskUpdateInfo(mapInfo)
+				}()
+			case "updateProject":		//项目字段变更
 
 			case "history": //历史数据合并,暂时不写
 				go func() {

+ 10 - 0
fullproject/src_v1/mgotool.go

@@ -247,3 +247,13 @@ func (m *MongodbSim) Delete(c, id string) int64 {
 	}
 	return r.DeletedCount
 }
+
+func (m *MongodbSim) FindById(c, id string) map[string]interface{} {
+	m.Open()
+	defer m.Close()
+	coll := m.C.Database(m.DbName).Collection(c)
+	r := coll.FindOne(m.Ctx, map[string]interface{}{"_id": StringTOBsonId(id)})
+	result := map[string]interface{}{}
+	_ = r.Decode(&result)
+	return result
+}

+ 291 - 138
fullproject/src_v1/project.go

@@ -2,6 +2,8 @@ package main
 
 import (
 	"log"
+	"strconv"
+
 	//	"log"
 	"math"
 	qu "qfw/util"
@@ -124,7 +126,16 @@ func (p *ProjectTask) startProjectMerge(info *Info, tmp map[string]interface{})
 		//问题出地LastTime!!!!!
 		diffTime := int64(math.Abs(float64(info.Publishtime - compareProject.LastTime)))
 		if diffTime <= p.validTime {
-			//"A 相等 	B 被包含 	C 不相等	 	D不存在  E被包含
+
+			//代理机构完全不相同,直接新建项目
+			if CheckContain(compareProject.Agency, info.Agency) == 3 {
+				break
+			}
+			//地区(省、市、区)不同,直接新建项目
+			if ComparePlace(compareProject, info) {
+				break
+			}
+
 			info.PNBH = 0
 			info.PCBH = 0
 			info.PTCBH = 0
@@ -142,72 +153,7 @@ func (p *ProjectTask) startProjectMerge(info *Info, tmp map[string]interface{})
 				compareProject.pjVal = pjVal
 				compareProject.resVal = resVal
 				//log.Println(compareProject.comStr)
-				eqV := 0
-				switch resVal {
-				case 3:
-					if pjVal == 3 && comStr[3:] != "CCCDCCC" {
-						eqV = 1
-					} else if compareBuyer < "C" {
-						if pjVal > 1 {
-							eqV = 1
-						} else { //if (compareCity[1:1] != "C" || compareTime != "D") && score2 > 0
-							eqV = 2
-						}
-					} else if compareBuyer == "D" {
-						if pjVal > 1 && (compareCity[1:1] != "C" || score2 > 0) {
-							eqV = 2
-						} else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
-							eqV = 3
-						}
-					} else {
-						if pjVal == 3 && (score2 > 0 || compareCity[1:1] != "C") {
-							eqV = 2
-						} else if pjVal == 2 && compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
-							eqV = 3
-						} else if compareCity == "AA" && compareTime == "A" && score2 > 0 {
-							eqV = 3
-						}
-					}
-				case 2:
-					if compareBuyer < "C" {
-						if pjVal > 1 {
-							eqV = 2
-						} else if compareCity[1:1] != "C" && compareTime == "A" || score2 > 0 {
-							eqV = 3
-						}
-					} else if compareBuyer == "D" {
-						if pjVal > 1 && (score2 > 0 || compareCity[1:1] != "C") {
-							eqV = 2
-						} else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
-							eqV = 3
-						}
-
-					} else {
-						if pjVal > 1 && compareTime == "A" && (score2 > 0 || compareCity[1:1] != "C") {
-							eqV = 2
-						} else if compareCity[1:1] != "C" && compareTime == "A" && (compareAgency == "A" || score2 > 0) && (compareBudget == "A" || compareBidmount == "A") {
-							eqV = 3
-						}
-					}
-				case 1:
-					if compareBuyer < "C" {
-						if pjVal > 1 && (score2 > 0 || compareCity[1:1] != "C") {
-							eqV = 2
-						} else if compareCity[1:1] != "C" && compareTime == "A" && (compareAgency == "A" || score2 > 0) && (compareBudget == "A" || compareBidmount == "A") {
-							eqV = 3
-						}
-					} else if compareBuyer == "D" {
-						if pjVal > 1 && compareTime == "A" && (score2 > 0 || compareCity[1:1] != "C") {
-							eqV = 2
-						} else if compareCity[1:1] != "C" && compareTime == "A" && (compareAgency == "A" || score2 > 0) && (compareBudget == "A" || compareBidmount == "A") {
-							eqV = 3
-						}
-					} else {
-						if pjVal > 1 && compareTime == "A" && score2 > 0 && (compareBudget == "A" || compareBidmount == "A") && compareCity[1:1] != "C" {
-							eqV = 3
-						}
-					}
-				}
+				eqV := compareResult(resVal, pjVal, score2, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount)
 				if eqV == 1 {
 					comRes1 = append(comRes1, compareProject)
 				} else if eqV == 2 {
@@ -215,14 +161,11 @@ func (p *ProjectTask) startProjectMerge(info *Info, tmp map[string]interface{})
 				} else if eqV == 3 {
 					comRes3 = append(comRes3, compareProject)
 				}
-				//				else if resVal == 3 || pjVal > 1 {
-				//					log.Println("===", resVal, pjVal, comStr, info.ProjectCode, compareProject.ProjectCode,
-				//						info.ProjectName, compareProject.ProjectName, info.Buyer, compareProject.Buyer, info.Id, compareProject.Id.Hex())
-				//				}
 			}
 		}
 	}
 	//--------------------------------对比完成-----------------------
+
 	//更新数组、更新项目
 	for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} {
 		if len(resN) > 0 {
@@ -266,13 +209,18 @@ func (p *ProjectTask) startProjectMerge(info *Info, tmp map[string]interface{})
 					}
 				}
 			}
-			p.UpdateProject(tmp, info, resN[0], kv+1, resN[0].comStr)
+			log.Println("pid", findPid)
+			choose, ex := CompareStatus(resN[0], info)
+			if !choose {
+				p.UpdateProject(tmp, info, resN[0], kv+1, resN[0].comStr, ex)
+			}else {
+				bFindProject = false
+			}
 			break
 		}
 	}
 
 	if !bFindProject {
-		//没有找到
 		id, p1 := p.NewProject(tmp, info)
 		p.AllIdsMapLock.Lock()
 		p.AllIdsMap[id] = &ID{Id: id, P: p1}
@@ -281,7 +229,6 @@ func (p *ProjectTask) startProjectMerge(info *Info, tmp map[string]interface{})
 			m.Arr = append(m.Arr, id)
 		}
 	}
-
 }
 
 func (p *ProjectTask) compareBCTABB(info *Info, cp *ProjectInfo, diffTime int64, score int) (compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount string, score2 int) {
@@ -384,6 +331,76 @@ func (p *ProjectTask) compareBCTABB(info *Info, cp *ProjectInfo, diffTime int64,
 	return
 }
 
+func compareResult(resVal, pjVal, score2 int, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount string) int {
+	eqV := 0
+	switch resVal {
+	case 3:
+		if pjVal == 3 && comStr[3:] != "CCCDCCC" {
+			eqV = 1
+		} else if compareBuyer < "C" {
+			if pjVal > 1 {
+				eqV = 1
+			} else { //if (compareCity[1:1] != "C" || compareTime != "D") && score2 > 0
+				eqV = 2
+			}
+		} else if compareBuyer == "D" {
+			if pjVal > 1 && (compareCity[1:1] != "C" || score2 > 0) {
+				eqV = 2
+			} else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
+				eqV = 3
+			}
+		} else {
+			if pjVal == 3 && (score2 > 0 || compareCity[1:1] != "C") {
+				eqV = 2
+			} else if pjVal == 2 && compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
+				eqV = 3
+			} else if compareCity == "AA" && compareTime == "A" && score2 > 0 {
+				eqV = 3
+			}
+		}
+	case 2:
+		if compareBuyer < "C" {
+			if pjVal > 1 {
+				eqV = 2
+			} else if compareCity[1:1] != "C" && compareTime == "A" || score2 > 0 {
+				eqV = 3
+			}
+		} else if compareBuyer == "D" {
+			if pjVal > 1 && (score2 > 0 || compareCity[1:1] != "C") {
+				eqV = 2
+			} else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
+				eqV = 3
+			}
+
+		} else {
+			if pjVal > 1 && compareTime == "A" && (score2 > 0 || compareCity[1:1] != "C") {
+				eqV = 2
+			} else if compareCity[1:1] != "C" && compareTime == "A" && (compareAgency == "A" || score2 > 0) && (compareBudget == "A" || compareBidmount == "A") {
+				eqV = 3
+			}
+		}
+	case 1:
+		if compareBuyer < "C" {
+			if pjVal > 1 && (score2 > 0 || compareCity[1:1] != "C") {
+				eqV = 2
+			} else if compareCity[1:1] != "C" && compareTime == "A" && (compareAgency == "A" || score2 > 0) && (compareBudget == "A" || compareBidmount == "A") {
+				eqV = 3
+			}
+		} else if compareBuyer == "D" {
+			if pjVal > 1 && compareTime == "A" && (score2 > 0 || compareCity[1:1] != "C") {
+				eqV = 2
+			} else if compareCity[1:1] != "C" && compareTime == "A" && (compareAgency == "A" || score2 > 0) && (compareBudget == "A" || compareBidmount == "A") {
+				eqV = 3
+			}
+		} else {
+			if pjVal > 1 && compareTime == "A" && score2 > 0 && (compareBudget == "A" || compareBidmount == "A") && compareCity[1:1] != "C" {
+				eqV = 3
+			}
+		}
+	}
+	return eqV
+}
+
 var FIELDS = []string{
 	"area",
 	"city",
@@ -409,33 +426,27 @@ var FIELDS = []string{
 
 var bidtype = map[string]string{
 	"招标": "招标",
-	"邀标": "邀标",
 	"询价": "询价",
 	"竞谈": "竞谈",
 	"单一": "单一",
 	"竞价": "竞价",
+	"变更": "变更",
+	"邀标": "邀标",
 }
 
-//var bidstatus = map[string]string{
-//	"中标": "中标",
-//	"成交": "成交",
-//	"废标": "废标",
-//	"流标": "流标",
-//	"合同": "合同",
-//}
 var bidstatus = map[string]string{
 	"预告": "预告",
 	"中标": "中标",
 	"成交": "成交",
 	"废标": "废标",
 	"流标": "流标",
+	"合同": "合同",
 }
 
 //招标时间zbtime、中标时间jgtime、项目状态bidstatus、招标类型bidtype、最后发布时间lasttime、首次发布时间firsttime
 
 func (p *ProjectTask) NewProject(tmp map[string]interface{}, thisinfo *Info) (string, *ProjectInfo) {
 	pId := primitive.NewObjectID() //NewObjectId()
-	p1 := p.NewCachePinfo(pId, thisinfo)
 	set := map[string]interface{}{}
 	set["_id"] = pId
 	for _, f := range FIELDS {
@@ -469,6 +480,17 @@ func (p *ProjectTask) NewProject(tmp map[string]interface{}, thisinfo *Info) (st
 	} else if thisinfo.TopType == "结果" {
 		set["jgtime"] = tmp["publishtime"]
 	}
+	//异常标记
+	if thisinfo.TopType != "招标" && thisinfo.TopType != "拟建" && thisinfo.TopType != "预告" {
+		set["exception"] = 1
+	}
+	//projecthref保存
+	if jsonData, ok := tmp["jsondata"].(map[string]interface{}); ok {
+		if jsonData != nil && jsonData["projecthref"] != "" {
+			set["projecthref"] = jsonData["projecthref"]
+		}
+	}
+
 	//招标类型
 	bt := bidtype[thisinfo.SubType]
 	if bt == "" {
@@ -480,8 +502,10 @@ func (p *ProjectTask) NewProject(tmp map[string]interface{}, thisinfo *Info) (st
 		set["bidstatus"] = bs
 	}
 	if set["bidstatus"] == nil && thisinfo.TopType == "结果" {
+		bs = thisinfo.SubType
 		set["bidstatus"] = thisinfo.SubType
 	}
+	p1, pkg := p.NewCachePinfo(pId, thisinfo, bs, bt)
 	if len(thisinfo.Subscopeclass) > 0 {
 		s_subscopeclass := strings.Join(thisinfo.Subscopeclass, ",")
 		set["s_subscopeclass"] = s_subscopeclass
@@ -492,6 +516,7 @@ func (p *ProjectTask) NewProject(tmp map[string]interface{}, thisinfo *Info) (st
 	}
 	if thisinfo.HasPackage {
 		set["multipackage"] = 1
+		set["package"] = pkg
 	} else {
 		set["multipackage"] = 0
 	}
@@ -501,10 +526,10 @@ func (p *ProjectTask) NewProject(tmp map[string]interface{}, thisinfo *Info) (st
 	}
 	//p.savePool <- set
 	p.updatePool <- []map[string]interface{}{
-		map[string]interface{}{
+		{
 			"_id": pId,
 		},
-		map[string]interface{}{
+		{
 			"$set": set,
 		},
 	}
@@ -534,6 +559,7 @@ var INFOFIELDS = []string{
 	"buyertel",
 	"area",
 	"city",
+	"list",
 }
 
 //项目中list的信息
@@ -550,7 +576,11 @@ func (p *ProjectTask) PushListInfo(tmp map[string]interface{}, infoid string) bs
 }
 
 //生成存放在内存中的对象
-func (p *ProjectTask) NewCachePinfo(id primitive.ObjectID, thisinfo *Info) ProjectInfo {
+func (p *ProjectTask) NewCachePinfo(id primitive.ObjectID, thisinfo *Info, bidstatus, bidtype string) (ProjectInfo, map[string]interface{}) {
+	pkg := map[string]interface{}{}
+	if thisinfo.HasPackage {
+		pkg, _, _ = PackageFormat(thisinfo, nil)
+	}
 	p1 := ProjectInfo{
 		Id:            id,
 		Ids:           []string{thisinfo.Id},
@@ -571,18 +601,20 @@ func (p *ProjectTask) NewCachePinfo(id primitive.ObjectID, thisinfo *Info) Proje
 		FirstTime:     thisinfo.Publishtime,
 		LastTime:      thisinfo.Publishtime,
 		Budget:        thisinfo.Budget,
-		Package:       thisinfo.Package,
+		Package: 	   pkg,
 		Bidamount:     thisinfo.Bidamount,
+		Bidstatus:	   bidstatus,
+		Bidtype:	   bidtype,
 	}
 	if thisinfo.LenPTC > 5 {
 		p1.MPC = append(p1.MPC, thisinfo.PTC)
 	}
-	return p1
+	return p1, pkg
 }
 
 //更新项目
-func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info, pInfo *ProjectInfo, weight int, comStr string) {
-	if p.currentType != "ql" {
+func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info, pInfo *ProjectInfo, weight int, comStr string, ex int) {
+	if p.currentType != "ql" && p.currentType != "updateInfo" {
 		if BinarySearch(pInfo.Ids, thisinfo.Id) > -1 {
 			log.Println("repeat", thisinfo.Id)
 			return
@@ -607,29 +639,26 @@ func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info,
 		if bt != "" {
 			set["bidtype"] = bt
 		}
-		//if thisinfo.TopType == "结果" {
-		//	set["bidstatus"] = thisinfo.SubType
-		//	set["jgtime"] = tmp["publishtime"]
-		//}
-		bs, _ := tmp["bidstatus"].(string)
+		bs, _ := tmp["subtype"].(string)
 		if bidstatus[bs] != "" {
 			set["bidstatus"] = thisinfo.SubType
-			if bidstatus[bs] != "预告" {
+			if bidstatus[bs] != "预告" && bidstatus[bs] != "合同" {
 				set["jgtime"] = tmp["publishtime"]
 			}
 		}else if tmp["infoformat"] == 2 {
 			set["bidstatus"] = "拟建"
-		}else if tmp["bidstatus"] == "招标" {
+		}else if tmp["subytpe"] == "招标" {
 			set["bidstatus"] = thisinfo.TopType
 		}else {
-			set["bidstatus"] = thisinfo.SubType
+			set["bidstatus"] = "其它"
 		}
-
 	}
-
+	//异常标记
+	if ex > 0 {
+		set["exception"] = ex
+	}
 	//3\4\5--省、市、县
 	if thisinfo.Area != "全国" {
-		//xt := true
 		if pInfo.Area == "全国" {
 			pInfo.Area = thisinfo.Area
 			set["area"] = thisinfo.Area
@@ -646,10 +675,6 @@ func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info,
 			pInfo.District = thisinfo.District
 			set["district"] = thisinfo.District
 		}
-		//省市县有不相同的
-		//		if !xt {
-		//			log.Println(pInfo.Area, pInfo.City, thisinfo.Area, thisinfo.District)
-		//		}
 	}
 	//6--项目名称
 	if (thisinfo.ProjectName != "" && pInfo.ProjectName == "") || (len([]rune(pInfo.ProjectName)) < 6 && thisinfo.LenPN > 6) {
@@ -699,13 +724,13 @@ func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info,
 		pInfo.Bidopentime = thisinfo.Bidopentime
 		set["bidopentime"] = pInfo.Bidopentime
 	}
-	if thisinfo.Bidamount > 0 && pInfo.Bidamount < 1 {
-		pInfo.Bidamount = thisinfo.Bidamount
+	if thisinfo.Bidamount > 0 {
+		pInfo.Bidamount = pInfo.Bidamount + thisinfo.Bidamount
 		set["bidamount"] = pInfo.Bidamount
 	}
 
-	if thisinfo.Budget > 0 && pInfo.Budget < 1 { //多包的会有问题,没有进行合计。
-		pInfo.Budget = thisinfo.Budget
+	if thisinfo.Budget > 0 {
+		pInfo.Budget = pInfo.Budget + thisinfo.Budget
 		set["budget"] = pInfo.Budget
 	}
 
@@ -745,42 +770,18 @@ func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info,
 	}
 
 	if thisinfo.HasPackage { //多包处理
-		p2, _ := tmp["package"].(map[string]interface{})
-		if p2 != nil {
-			if pInfo.Package != nil {
-				for pk2, pv2 := range p2 {
-					if pInfo.Package[pk2] != nil { //合并
-						item1, _ := pInfo.Package[pk2].(map[string]interface{})
-						item2, _ := pv2.(map[string]interface{})
-						if item1 != nil && item2 != nil { //原始项
-							for ik1, iv1 := range item2 {
-								if item1[ik1] == nil {
-									item1[ik1] = iv1
-								}
-							}
-						}
-						pInfo.Package[pk2] = item1
-					} else {
-						pInfo.Package[pk2] = pv2
-					}
-				}
-			} else {
-				pInfo.Package = p2
-			}
-		}
+		set["multipackage"] = 1
+		pkg, _, _:= PackageFormat(thisinfo, pInfo)
+		pInfo.Package = pkg
 		set["package"] = pInfo.Package
+	}else {
+		set["multipackage"] = 0
 	}
 
 	set["mpn"] = pInfo.MPN
 	set["mpc"] = pInfo.MPC
 	set["pici"] = p.pici
 
-	if thisinfo.HasPackage {
-		set["multipackage"] = 1
-	} else {
-		set["multipackage"] = 0
-	}
-
 	update := map[string]interface{}{}
 	if len(set) > 0 {
 		update["$set"] = set
@@ -804,3 +805,155 @@ func (p *ProjectTask) UpdateProject(tmp map[string]interface{}, thisinfo *Info,
 		p.updatePool <- updateInfo
 	}
 }
+
+
+/**
+ *	更新项目时,项目状态的处理
+ *	返回是否新增项目,异常标记
+ *	1、项目时,新项目时,招标信息的状态(toptype)不是招标、拟建、预告	异常:1
+ *	   异常1是在项目新建的时候才会产生
+ *	3、项目合并时,项目状态是”流标“/”废标“,招标信息状态不是”招标“		异常:2
+ *	4、项目合并时,项目状态是”合同“/”其它“,招标信息类型是”结果“		异常:3
+ */
+func CompareStatus(project *ProjectInfo, info *Info) (bool, int) {
+	if info.TopType == "拟建" || info.TopType == "预告" || info.TopType == "招标" {
+		if project.Bidstatus == "拟建" || project.Bidstatus == "预告" || project.Bidstatus == "招标" {
+			return false, 0
+		}else {
+			return true, 0
+		}
+	}else if info.TopType == "结果" {
+		if project.Bidstatus == "拟建" || project.Bidstatus == "预告" || project.Bidstatus == "招标" {
+			return false, 0
+		}else if project.Bidstatus == info.SubType {
+			return true, 0
+		}else if project.Bidstatus == "成交" {
+			if info.SubType == "中标" {
+				return true, 0
+			}else {
+				return false, 0
+			}
+		}else if project.Bidstatus == "流标" || project.Bidstatus == "废标" {
+			return false, 2
+		}else if project.Bidstatus == "合同" || project.Bidstatus == "其它" {
+			return false, 3
+		}else {
+			return false, 0
+		}
+	}else {
+		return false, 0
+	}
+}
+
+/*
+ *	对比地区(省、市、区),存在且不同,不能合并
+ *	返回是否新建项目
+ */
+func ComparePlace(project *ProjectInfo, info *Info) bool {
+	if info.Area == "全国" || info.Area == "" {
+		return false
+	}
+	if project.Area == "全国" || project.Area == "" {
+		return false
+	}
+	if info.Area == project.Area {
+		if info.City == "" {
+			return false
+		}else if info.City == project.City {
+			if info.District == "" || info.District == project.District {
+				return false
+			}else {
+				return true
+			}
+		}else {
+			return true
+		}
+	}else {
+		return true
+	}
+}
+
+var PackageEle = []string{
+	"origin",
+	"name",
+	"text",
+	"budget",
+	"winner",
+	"bidamount",
+	"bidamounttype",
+	"currency",
+	"bidstatus",
+}
+
+func packageEle(map1 map[string]interface{}) (map[string]interface{}, float64, float64) {
+	budget := 0.0
+	bidamount := 0.0
+	p2 := map[string]interface{}{}
+	for _, k := range PackageEle{
+		if map1[k] != nil {
+			p2[k] = map1[k]
+		}
+		if p2["budget"] != nil {
+			budget = budget + p2["budget"].(float64)
+		}
+		if p2["bidamount"] != nil {
+			bidamount = bidamount + p2["bidamount"].(float64)
+		}
+	}
+	return p2, budget, bidamount
+}
+
+func PackageFormat(info *Info, project *ProjectInfo) (map[string]interface{}, float64, float64) {
+	budget := 0.0
+	bidamount := 0.0
+	p1 := map[string]interface{}{}
+	if project != nil && project.Package != nil && len(project.Package) > 0 {
+		budget = project.Budget
+		bidamount = project.Bidamount
+		p1 = project.Package
+		ids := p1["ids"].([]string)
+		ids = append(ids, info.Id)
+		p1["ids"] = ids
+		for _, v := range info.Package {
+			if v1, ok := v.(map[string]interface{}); ok {
+				v2 := map[string]interface{}{}
+				v2, budget, bidamount = packageEle(v1)
+				if v2["bidstatus"] == nil {
+					v2["bidstatus"] = info.SubType
+				}
+				n := 0
+				addFlag := false
+				for k, v3 := range p1 {
+					if k == "ids" {
+						continue
+					}
+					if v4, ok := v3.([]map[string]interface{}); ok {
+						if v4[0]["origin"].(string) == v2["origin"].(string) && v4[0]["name"].(string) == v2["name"].(string) {
+							v4 = append(v4, v2)
+							p1[k] = v4
+							addFlag = true
+							break
+						}
+					}
+				}
+				if !addFlag {
+					n++
+					m := len(ids) + n
+					p1[strconv.Itoa(m)] = []map[string]interface{}{v2}
+				}
+			}
+		}
+	}else {
+		p1["ids"] = []string{info.Id}
+		for k, v := range info.Package {
+			v1 := v.(map[string]interface{})
+			p2 := map[string]interface{}{}
+			p2, budget, bidamount = packageEle(v1)
+			if p2["bidstatus"] == nil {
+				p2["bidstatus"] = info.SubType
+			}
+			p1[k] = []map[string]interface{}{p2}
+		}
+	}
+	return p1, budget, bidamount
+}

+ 227 - 162
fullproject/src_v1/task.go

@@ -37,7 +37,12 @@ type ProjectTask struct {
 	AllIdsMap map[string]*ID
 	//采购单位、项目名称、项目编号
 	mapPb, mapPn, mapPc map[string]*Key
-	//	mapPbLock, mapPnLock, mapPcLock sync.Mutex
+	//流程数据  字段相同,直接合并
+	mapHref map[string]string
+	mapHrefLock sync.Mutex
+	//站点
+	mapSite map[string]*Site
+	mapSiteLock sync.Mutex
 	//更新或新增通道
 	updatePool chan []map[string]interface{}
 	//savePool   chan map[string]interface{}
@@ -73,6 +78,8 @@ func NewPT() *ProjectTask {
 		mapPb:     make(map[string]*Key, 1500000),
 		mapPn:     make(map[string]*Key, 5000000),
 		mapPc:     make(map[string]*Key, 5000000),
+		mapHref:   make(map[string]string, 1500000),
+		mapSite:   make(map[string]*Site, 1000000),
 		saveSize:  400,
 
 		//saveSign:   make(chan bool, 1),
@@ -134,7 +141,7 @@ func (p *ProjectTask) clearMem() {
 	c := cron.New()
 	//在内存中保留最近6个月的信息
 	//跑全量时每4分钟跑一次,跑增量时400分钟跑一次
-	c.AddFunc("50 0/15 * * * *", func() {
+	_ = c.AddFunc("50 0/15 * * * *", func() {
 		if p.currentType == "ql" || p.clearContimes >= 60 {
 			//跳过的次数清零
 			p.clearContimes = 0
@@ -146,6 +153,7 @@ func (p *ProjectTask) clearMem() {
 			//遍历id
 			//所有内存中的项目信息
 			p.AllIdsMapLock.Lock()
+			p.mapHrefLock.Lock()
 
 			//清除计数
 			clearNum := 0
@@ -194,9 +202,15 @@ func (p *ProjectTask) clearMem() {
 							}
 						}
 					}
+					for kHref, pid := range p.mapHref{
+						if pid == k {
+							delete(p.mapHref, kHref)
+						}
+					}
 					v = nil
 				}
 			}
+			p.mapHrefLock.Unlock()
 			p.AllIdsMapLock.Unlock()
 			p.findLock.Unlock()
 			log.Println("清除完成:", clearNum, len(p.AllIdsMap), len(p.mapPn), len(p.mapPc), len(p.mapPb))
@@ -274,7 +288,7 @@ func (p *ProjectTask) taskZl(udpInfo map[string]interface{}) {
 	if q == nil {
 		q = map[string]interface{}{
 			"_id": map[string]interface{}{
-				"$gt":  StringTOBsonId(gtid),
+				"$gte":  StringTOBsonId(gtid),
 				"$lte": StringTOBsonId(lteid),
 			},
 		}
@@ -296,6 +310,37 @@ func (p *ProjectTask) taskZl(udpInfo map[string]interface{}) {
 	}
 }
 
+//招标字段更新
+func (p *ProjectTask) taskUpdateInfo(udpInfo map[string]interface{}) {
+	defer util.Catch()
+	db, _ := udpInfo["db"].(string)
+	if db == "" {
+		db = MongoTool.DbName
+	}
+	coll, _ := udpInfo["coll"].(string)
+	if coll == "" {
+		coll = ExtractColl
+	}
+	thread := util.IntAllDef(udpInfo["thread"], 4)
+	if thread > 0 {
+		p.thread = thread
+	}
+	q, _ := udpInfo["query"].(map[string]interface{})
+	gtid := udpInfo["gtid"].(string)
+	lteid := udpInfo["lteid"].(string)
+	if q == nil {
+		q = map[string]interface{}{
+			"_id": map[string]interface{}{
+				"$gt":  StringTOBsonId(gtid),
+				"$lte": StringTOBsonId(lteid),
+			},
+			"is_m": 1,
+		}
+	}
+	log.Println("查询语句:", q)
+	p.enter(db, coll, q)
+}
+
 func StringTOBsonId(id string) primitive.ObjectID {
 	objectId, _ := primitive.ObjectIDFromHex(id)
 	return objectId
@@ -313,7 +358,7 @@ func nextNode(mapInfo map[string]interface{}, pici int64) {
 		datas, _ := json.Marshal(mapInfo)
 		node := &udpNode{datas, to, time.Now().Unix(), 0}
 		udptaskmap.Store(key, node)
-		udpclient.WriteUdp(datas, mu.OP_TYPE_DATA, to)
+		_ = udpclient.WriteUdp(datas, mu.OP_TYPE_DATA, to)
 	}
 }
 
@@ -344,12 +389,15 @@ func (p *ProjectTask) enter(db, coll string, q map[string]interface{}) {
 						<-pool
 					}()
 					if util.IntAll(tmp["repeat"]) == 0 {
-						info := ParseInfo(tmp)
-						if info != nil && !((info.pnbval == 1 && info.Buyer != "") || info.pnbval == 0) {
-							p.currentTime = info.Publishtime
-							p.startProjectMerge(info, tmp)
+						p.fillInPlace(tmp)
+						if p.currentType == "updateInfo" {
+							//招标信息更改合并
+							p.updateJudge(tmp)
+						}else {
+							//普通合并
+							p.CommonMerge(tmp)
 						}
-					} else {
+					}else {
 						//信息错误,进行更新
 					}
 				}(tmp)
@@ -411,10 +459,43 @@ var (
 	StrOrNum2 = regexp.MustCompile("^[0-9_-]+$|^[a-zA-Z_-]+$")
 )
 
+func (p *ProjectTask) CommonMerge(tmp map[string]interface{}) {
+	info := ParseInfo(tmp)
+	if info != nil && !((info.pnbval == 1 && info.Buyer != "") || info.pnbval == 0) {
+		if jsonData, ok := tmp["jsondata"].(map[string]interface{}); ok {
+			if jsonData != nil && jsonData["projecthref"] != "" {
+				//projectHref字段合并
+				proHref := jsonData["projecthref"].(string)
+				tmp["projecthref"] = proHref
+				p.mapHrefLock.Lock()
+				defer p.mapHrefLock.Unlock()
+				if p.mapHref[proHref] != "" {
+					pid := p.mapHref[proHref]
+					p.AllIdsMapLock.Lock()
+					comparePro := p.AllIdsMap[pid].P
+					p.AllIdsMapLock.Unlock()
+					_, ex := CompareStatus(comparePro, info)
+					p.UpdateProject(tmp, info, comparePro, -1, "AAAAAAAAAA", ex)
+				} else {
+					id, p1 := p.NewProject(tmp, info)
+					p.mapHref[proHref] = id
+					p.AllIdsMapLock.Lock()
+					p.AllIdsMap[id] = &ID{Id: id, P: p1}
+					p.AllIdsMapLock.Unlock()
+				}
+			}
+		}else {
+			//项目合并
+			p.currentTime = info.Publishtime
+			p.startProjectMerge(info, tmp)
+		}
+	}
+}
+
 func ParseInfo(tmp map[string]interface{}) (info *Info) {
 	bys, _ := json.Marshal(tmp)
 	var thisinfo *Info
-	json.Unmarshal(bys, &thisinfo)
+	_ = json.Unmarshal(bys, &thisinfo)
 	if thisinfo == nil {
 		return nil
 	}
@@ -501,6 +582,141 @@ func ParseInfo(tmp map[string]interface{}) (info *Info) {
 	return thisinfo
 }
 
+func (p *ProjectTask) updateJudge(tmp map[string]interface{})  {
+	index := -1
+	pInfoId := ""
+	info := ParseInfo(tmp)
+	p.AllIdsMapLock.Lock()
+	F:
+	for k, ID := range p.AllIdsMap {
+		for i, id := range ID.P.Ids{
+			if info.Id == id {
+				pInfoId = k
+				index = i
+				break F
+			}
+		}
+	}
+	p.AllIdsMapLock.Unlock()
+	//未找到招标信息
+	if index == -1 {
+		if info != nil && !((info.pnbval == 1 && info.Buyer != "") || info.pnbval == 0) {
+			p.currentTime = info.Publishtime
+			p.startProjectMerge(info, tmp)
+		}
+	}else {
+		tmpPro := MongoTool.FindById(ProjectColl, pInfoId)
+		infoList := []interface{}(tmpPro["list"].(primitive.A))
+		infoMap := infoList[index].(map[string]interface{})
+		modifyMap, f := modifyEle(infoMap, tmp)
+
+		//projecthref字段
+		jsonData := tmp["jsondata"].(map[string]interface{})
+		if jsonData != nil && jsonData["projecthref"] != "" {
+			proHref := jsonData["projecthref"].(string)
+			tmp["projecthref"] = proHref
+			p.mapHrefLock.Lock()
+			defer p.mapHrefLock.Unlock()
+			pid := p.mapHref[proHref]
+			if  pid == pInfoId {
+				p.modifyUpdate(pInfoId, index, info, tmp, tmpPro, modifyMap)
+				return
+			}
+		}
+
+		if f {
+			//合并、修改
+			log.Println("合并修改更新", "----------------------------")
+			p.mergeAndModify(pInfoId, index, info, tmp, tmpPro, modifyMap)
+		}else {
+			//修改
+			log.Println("修改更新", "----------------------------")
+			p.modifyUpdate(pInfoId, index, info, tmp, tmpPro, modifyMap)
+		}
+	}
+}
+
+var Elements = []string{
+	"projectname",
+	"projectcode",
+	"agency",
+	"budget",
+	"bidamount",
+	"buyerperson",
+	"area",
+	"city",
+	"publishtime",
+}
+
+/**
+判断修改的字段是否是影响合并流程的要素字段
+ */
+func modifyEle(tmpPro map[string]interface{}, tmp map[string]interface{}) (map[string]interface{}, bool) {
+	modifyMap := map[string]interface{}{}
+	for k, _ := range tmpPro {
+		for k1, _ := range tmp {
+			if k == k1 && tmpPro[k] != tmp[k1] {
+				modifyMap[k] = tmp[k1]
+				break
+			}
+		}
+	}
+	for k, _ := range modifyMap {
+		for _, str := range Elements{
+			if k == str {
+				return modifyMap, true
+			}
+		}
+	}
+	delete(modifyMap, "_id")
+	return modifyMap, false
+}
+
+//补全位置信息
+func (p *ProjectTask) fillInPlace(tmp map[string]interface{})  {
+	area := tmp["area"].(string)
+	city := tmp["city"].(string)
+	district := tmp["district"].(string)
+	if area != "" && city != "" && district != "" {
+		return
+	}
+
+	p.mapSiteLock.Lock()
+	defer p.mapSiteLock.Unlock()
+	tmpSite := tmp["site"].(string)
+	site := p.mapSite[tmpSite]
+	if site != nil {
+		if area != "" {
+			if area == "全国" {
+				tmp["area"] = site.Area
+				tmp["city"] = site.City
+				tmp["district"] = site.District
+				return
+			}
+			if area != site.Area {
+				return
+			}else {
+				if city == site.City {
+					if district == "" {
+						tmp["district"] = site.District
+						return
+					}
+				}else if city == "" {
+					tmp["city"] = site.City
+					tmp["district"] = site.District
+					return
+				}
+			}
+		}else {
+			tmp["area"] = site.Area
+			tmp["city"] = site.City
+			tmp["district"] = site.District
+			return
+		}
+	}
+
+}
+
 //从数组中删除元素
 func deleteSlice(arr []string, v string) []string {
 	for k, v1 := range arr {
@@ -509,155 +725,4 @@ func deleteSlice(arr []string, v string) []string {
 		}
 	}
 	return arr
-}
-
-//			if taskcount > 0 && taskcount%50000 == 0 { //歇歇
-//				log.Println("pause start..", taskcount)
-//				for n := 0; n < p.thread; n++ {
-//					pool <- true
-//				}
-//				for n := 0; n < p.thread; n++ {
-//					<-pool
-//				}
-//				log.Println("pause over..")
-//			}
-//lastid = tmp["_id"]
-//tmp = make(map[string]interface{})
-//		if count > 40000 {
-//			query.Close()
-//			break
-//		}
-//over++
-//func (p *ProjectTask) saveQueue() {
-//	arr := make([]map[string]interface{}, p.saveSize)
-//	indexs := 0
-//	for {
-//		select {
-//		case <-p.saveSign:
-//			if indexs > 0 {
-//				MongoTool.SaveBulk(p.coll, arr[:indexs]...)
-//				arr = make([]map[string]interface{}, p.saveSize)
-//				indexs = 0
-//			}
-//			p.updateSign <- true
-//		case v := <-p.savePool:
-//			arr[indexs] = v
-//			indexs++
-//			if indexs == p.saveSize {
-//				MongoTool.SaveBulk(p.coll, arr...)
-//				arr = make([]map[string]interface{}, p.saveSize)
-//				indexs = 0
-//			}
-//		case <-time.After(100 * time.Millisecond):
-//			if indexs > 0 {
-//				MongoTool.SaveBulk(p.coll, arr[:indexs]...)
-//				arr = make([]map[string]interface{}, p.saveSize)
-//				indexs = 0
-//			}
-//		}
-//	}
-//}
-
-////项目保存和更新通道
-//func (p *ProjectTask) updateQueue() {
-//	arru := make([][]map[string]interface{}, p.saveSize)
-//	indexu := 0
-//	for {
-//		select {
-//		case v := <-p.updatePool:
-//			arru[indexu] = v
-//			indexu++
-//			if indexu == p.saveSize {
-//				//更新之前先保存
-//				p.saveSign <- true
-//				<-p.updateSign
-//				MongoTool.UpdateBulk(p.coll, arru...)
-//				arru = make([][]map[string]interface{}, p.saveSize)
-//				indexu = 0
-//			}
-//		case <-time.After(100 * time.Millisecond):
-//			if indexu > 0 {
-//				p.saveSign <- true
-//				<-p.updateSign
-//				MongoTool.UpdateBulk(p.coll, arru[:indexu]...)
-//				arru = make([][]map[string]interface{}, p.saveSize)
-//				indexu = 0
-//			}
-//		}
-//	}
-//}
-//func (p *ProjectTask) ConCurrentLock(n1, n2, n3, n4 int) {
-//	var lock *sync.Mutex
-//	p.LockPoolLock.Lock()
-//	if p.m1[n1] > 0 || p.m23[n2] > 0 || p.m23[n3] > 0 || p.m4[n4] > 0 {
-//		if p.l1[n1] != nil {
-//			lock = p.l1[n1]
-//		} else if p.l23[n2] != nil {
-//			lock = p.l23[n2]
-//		} else if p.l23[n3] != nil {
-//			lock = p.l23[n3]
-//		} else if p.l4[n4] != nil {
-//			lock = p.l4[n4]
-//		}
-//	} else {
-//		lock = <-p.LockPool
-//	}
-//	if n1 > 0 {
-//		p.m1[n1]++
-//		p.l1[n1] = lock
-//	}
-//	if n2 > 0 {
-//		p.m23[n2]++
-//		p.l23[n2] = lock
-//	}
-//	if n3 > 0 {
-//		p.m23[n3]++
-//		p.l23[n3] = lock
-//	}
-//	if n4 > 0 {
-//		p.m4[n4]++
-//		p.l4[n4] = lock
-//	}
-//	p.LockPoolLock.Unlock()
-//	lock.Lock()
-//}
-
-//func (p *ProjectTask) ConCurrentUnLock(n1, n2, n3, n4 int) {
-//	var lock1 *sync.Mutex
-//	p.LockPoolLock.Lock()
-//	if p.l1[n1] != nil {
-//		lock1 = p.l1[n1]
-//	} else if p.l23[n2] != nil {
-//		lock1 = p.l23[n2]
-//	} else if p.l23[n3] != nil {
-//		lock1 = p.l23[n3]
-//	} else if p.l4[n4] != nil {
-//		lock1 = p.l4[n4]
-//	}
-//	if p.m1[n1] > 0 {
-//		p.m1[n1]--
-//		if p.m1[n1] == 0 {
-//			p.l1[n1] = nil
-//		}
-//	}
-//	if p.m23[n2] > 0 {
-//		p.m23[n2]--
-//		if p.m23[n2] == 0 {
-//			p.l23[n2] = nil
-//		}
-//	}
-//	if p.m23[n3] > 0 {
-//		p.m23[n3]--
-//		if p.m23[n3] == 0 {
-//			p.l23[n3] = nil
-//		}
-//	}
-//	if p.m4[n4] > 0 {
-//		p.m4[n4]--
-//		if p.m4[n4] == 0 {
-//			p.l4[n4] = nil
-//		}
-//	}
-//	p.LockPoolLock.Unlock()
-//	lock1.Unlock()
-//}
+}

+ 440 - 0
fullproject/src_v1/update.go

@@ -0,0 +1,440 @@
+package main
+
+import (
+	"github.com/go-xweb/log"
+	"go.mongodb.org/mongo-driver/bson/primitive"
+	"math"
+	qu "qfw/util"
+	"reflect"
+	"sort"
+	"strings"
+)
+
+func (p *ProjectTask) modifyUpdate(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) {
+	backupPro(tmpPro)
+	infoList := []interface{}(tmpPro["list"].(primitive.A))
+	infoMap := infoList[index].(map[string]interface{})
+	infoList[index] = updateValue(infoMap, modifyMap)
+	set := map[string]interface{}{
+		"$set": tmpPro,
+	}
+	err := MongoTool.UpdateById(ProjectColl, pInfoId, set)
+	log.Println(err)
+}
+
+func (p *ProjectTask) mergeAndModify(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) {
+	p.AllIdsMapLock.Lock()
+	currentPro := p.AllIdsMap[pInfoId]
+	p.AllIdsMapLock.Unlock()
+	merge, pId, i, comStr, mergePro := p.updateMerge(index, info, pInfoId, tmp, tmpPro)
+	//招标信息在list中第1个
+	if index == 0 {
+		log.Println("第1条合并", "------1------")
+		//快照
+		backupPro(tmpPro)
+		p.AllIdsMapLock.Lock()
+		delete(p.AllIdsMap, pInfoId)
+		p.AllIdsMapLock.Unlock()
+		count := MongoTool.Delete(ProjectColl, pInfoId)
+		log.Println(count)
+		for _, infoId := range currentPro.P.Ids{
+			if infoId == info.Id {
+				continue
+			}
+			tmp1 := MongoTool.FindById(ExtractColl, infoId)
+			p.CommonMerge(tmp1)
+		}
+	}else {
+		log.Println("第n条合并", "------n------")
+		//快照    招标信息所在的项目
+		backupPro(tmpPro)
+		if merge {
+			//跟原项目list第0条信息作对比,可以合并
+			if pId == pInfoId {
+				//合并到当前项目
+				mergeProject(p, currentPro.P, info, tmpPro, index)
+				p.AllIdsMapLock.Lock()
+				p.AllIdsMap[currentPro.P.Id.Hex()].P = currentPro.P
+				p.AllIdsMapLock.Unlock()
+				infoList := []interface{}(tmpPro["list"].(primitive.A))
+				infoMap := infoList[index].(map[string]interface{})
+				infoList[index] = updateValue(infoMap, modifyMap)
+				set := map[string]interface{}{
+					"$set": tmpPro,
+				}
+				MongoTool.UpdateById(ProjectColl, pInfoId, set)
+			}else {
+				//合并到的其它项目里边
+				//更新其它的项目
+				pro := MongoTool.FindById(ProjectColl, mergePro.Id.Hex())
+				backupPro(pro, )
+				choose, ex := CompareStatus(mergePro, info)
+				if !choose {
+					p.UpdateProject(tmp, info, mergePro, i, comStr, ex)
+				}else {
+					id, p1 := p.NewProject(tmp, info)
+					p.AllIdsMapLock.Lock()
+					p.AllIdsMap[id] = &ID{Id: id, P: p1}
+					p.AllIdsMapLock.Unlock()
+				}
+				//内部合并
+				p.innerMerge(currentPro.P, info, tmp, tmpPro)
+			}
+		}else {
+			//合并到新建的项目里边,原有项目内部合并
+			p.innerMerge(currentPro.P, info, tmp, tmpPro)
+		}
+	}
+}
+
+func (p *ProjectTask) updateMerge(index int, info *Info, pInfoId string, tmp map[string]interface{}, tmpPro map[string]interface{}) (bool, string, int, string, *ProjectInfo) {
+	bpn, bpc, bptc, bpb, pids, _, IDArr := p.getCompareIds(info.ProjectName, info.ProjectCode, info.PTC, info.Buyer)
+	defer p.wg.Done()
+
+	for _, m := range pids {
+		defer m.Lock.Unlock()
+	}
+	for _, id := range IDArr {
+		defer id.Lock.Unlock()
+	}
+
+	bFindProject := false
+	findPid := ""
+	//获取完id,进行计算
+	//定义两组
+	comRes1 := []*ProjectInfo{} //优先级最高的对比结果数组
+	comRes2 := []*ProjectInfo{} //优化级其次
+	comRes3 := []*ProjectInfo{}
+	for _, v := range IDArr {
+		if index == 0 && pInfoId == v.P.Id.Hex() {
+			//招标条目信息在原项目中是第0条时,忽略
+			continue
+		}
+		comStr := ""
+		compareProject := v.P
+		compareProject.score = 0
+		diffTime := int64(math.Abs(float64(info.Publishtime - compareProject.LastTime)))
+		if diffTime <= p.validTime {
+
+			//代理机构完全不相同,直接新建项目
+			if CheckContain(compareProject.Agency, info.Agency) == 3 {
+				break
+			}
+
+			//地区(省、市、区)不同,直接新建项目
+			if ComparePlace(compareProject, info) {
+				break
+			}
+
+			info.PNBH = 0
+			info.PCBH = 0
+			info.PTCBH = 0
+			compareStr, score := comparePNC(info, compareProject)
+			resVal, pjVal := Select(compareStr, info, compareProject)
+			if resVal > 0 {
+				compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount, score2 := p.compareBCTABB(info, compareProject, diffTime, score)
+
+				//项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构
+				comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount
+				compareProject.comStr = comStr
+				compareProject.pjVal = pjVal
+				compareProject.resVal = resVal
+				eqV := compareResult(resVal, pjVal, score2, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount)
+				if eqV == 1 {
+					comRes1 = append(comRes1, compareProject)
+				} else if eqV == 2 {
+					comRes2 = append(comRes2, compareProject)
+				} else if eqV == 3 {
+					comRes3 = append(comRes3, compareProject)
+				}
+			}
+		}
+	}
+	//--------------------------------对比完成-----------------------
+	k := -1
+	comStr := ""
+	mergePro := &ProjectInfo{}
+	for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} {
+		if len(resN) > 0 {
+			if len(resN) > 1 {
+				sort.Slice(resN, func(i, j int) bool {
+					return resN[i].score > resN[j].score
+				})
+			}
+
+			bFindProject = true
+			findPid = resN[0].Id.Hex()
+			for k2, bv := range []int{bpn, bpc, bptc, bpb} {
+				if bv > -1 {
+					pids[bv].Arr = append(pids[bv].Arr, findPid)
+					if k2 == 0 {
+						if resN[0].ProjectName == "" {
+							resN[0].ProjectName = info.ProjectName
+						} else {
+							if resN[0].MPN == nil {
+								resN[0].MPN = []string{info.ProjectName}
+							} else {
+								resN[0].MPN = append(resN[0].MPN, info.ProjectName)
+							}
+						}
+
+					} else if k2 < 3 {
+						if resN[0].ProjectCode == "" {
+							resN[0].ProjectCode = qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)
+						} else {
+							if resN[0].MPC == nil {
+								resN[0].MPC = []string{qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)}
+							} else {
+								resN[0].MPC = append(resN[0].MPC, qu.If(k2 == 1, info.ProjectCode, info.PTC).(string))
+							}
+						}
+
+					} else {
+						if resN[0].Buyer == "" {
+							resN[0].Buyer = info.Buyer
+						}
+					}
+				}
+			}
+			if index != 0 {
+				//招标条目信息在原项目中是第非0条时,返回对比结果
+				k = kv+1
+				comStr = resN[0].comStr
+				mergePro = resN[0]
+			}else {
+				mergePro = resN[0]
+				choose, ex := CompareStatus(resN[0], info)
+				if !choose {
+					//如果有合并,合并之前备份(快照)
+					backupPro(tmpPro)
+					p.UpdateProject(tmp, info, resN[0], kv+1, resN[0].comStr, ex)
+				}else {
+					bFindProject = false
+				}
+			}
+			break
+		}
+	}
+
+	if !bFindProject {
+		id, p1 := p.NewProject(tmp, info)
+		p.AllIdsMapLock.Lock()
+		p.AllIdsMap[id] = &ID{Id: id, P: p1}
+		p.AllIdsMapLock.Unlock()
+		for _, m := range pids {
+			m.Arr = append(m.Arr, id)
+		}
+	}
+	return bFindProject, findPid, k, comStr, mergePro
+}
+
+//内部合并
+func (p *ProjectTask) innerMerge(pInfo *ProjectInfo, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}) {
+	infoList := []interface{}(tmpPro["list"].(primitive.A))
+	for index, info1 := range infoList{
+		info2 := info1.(map[string]interface{})
+		if info2["infoid"] == info.Id {
+			deleteSlice1(infoList, info1)
+			continue
+		}
+		mergeProject(p, pInfo, info, tmpPro, index)
+	}
+	p.AllIdsMapLock.Lock()
+	p.AllIdsMap[pInfo.Id.Hex()].P = pInfo
+	p.AllIdsMapLock.Unlock()
+	set := map[string]interface{}{
+		"$set": tmpPro,
+	}
+	MongoTool.UpdateById(ProjectColl, pInfo.Id.Hex(), set)
+}
+
+//合并字段到project
+func mergeProject(p *ProjectTask, pInfo *ProjectInfo, thisinfo *Info, set map[string]interface{}, index int) map[string]interface{} {
+	//1--firsttime
+	if thisinfo.Publishtime < pInfo.FirstTime && thisinfo.Publishtime > 0 {
+		pInfo.FirstTime = thisinfo.Publishtime
+		set["firsttime"] = thisinfo.Publishtime
+		if thisinfo.TopType == "招标" {
+			set["zbtime"] = thisinfo.Publishtime
+		}
+	}
+	//2--lasttime
+	if thisinfo.Publishtime > pInfo.LastTime {
+		pInfo.LastTime = thisinfo.Publishtime
+		set["lasttime"] = thisinfo.Publishtime
+		bt := bidtype[thisinfo.SubType]
+		if bt != "" {
+			set["bidtype"] = bt
+		}
+		if thisinfo.SubType != "" {
+			set["bidstatus"] = thisinfo.SubType
+			if thisinfo.SubType != "预告" {
+				set["jgtime"] = thisinfo.Publishtime
+			}
+		}else if thisinfo.Infoformat == 2 {
+			set["bidstatus"] = "拟建"
+		}else if thisinfo.SubType == "招标" {
+			set["bidstatus"] = thisinfo.TopType
+		}else {
+			set["bidstatus"] = thisinfo.SubType
+		}
+
+	}
+
+	//3\4\5--省、市、县
+	if thisinfo.Area != "全国" {
+		//xt := true
+		if pInfo.Area == "全国" {
+			pInfo.Area = thisinfo.Area
+			set["area"] = thisinfo.Area
+		} else if pInfo.Area != thisinfo.Area {
+			//xt = false
+		}
+		if pInfo.City == "" && thisinfo.City != "" {
+			pInfo.City = thisinfo.City
+			set["city"] = thisinfo.City
+		} else if pInfo.City != thisinfo.City {
+			//xt = false
+		}
+		if thisinfo.District != "" && pInfo.District == "" {
+			pInfo.District = thisinfo.District
+			set["district"] = thisinfo.District
+		}
+	}
+	//6--项目名称
+	if (thisinfo.ProjectName != "" && pInfo.ProjectName == "") || (len([]rune(pInfo.ProjectName)) < 6 && thisinfo.LenPN > 6) {
+		pInfo.ProjectName = thisinfo.ProjectName
+		set["projectname"] = thisinfo.ProjectName
+	}
+	//7--项目编号
+	if (pInfo.ProjectCode == "" && thisinfo.ProjectCode != "") || (len([]rune(pInfo.ProjectCode)) < 6 && len([]rune(thisinfo.ProjectCode)) > 6) {
+		pInfo.ProjectCode = thisinfo.ProjectCode
+		set["projectcode"] = thisinfo.ProjectCode
+	}
+	//7--采购单位
+	if (pInfo.Buyer == "" && thisinfo.Buyer != "") || (len([]rune(pInfo.Buyer)) < 5 && len([]rune(thisinfo.Buyer)) > 5) {
+		pInfo.Buyer = thisinfo.Buyer
+		set["buyer"] = thisinfo.Buyer
+
+		pInfo.Buyerclass = thisinfo.Buyerclass
+		set["buyerclass"] = thisinfo.Buyerclass
+	}
+	if pInfo.Buyer == "" {
+		set["buyerclass"] = ""
+	}
+
+	//8--代理机构
+	if (pInfo.Agency == "" && thisinfo.Agency != "") || (len([]rune(pInfo.Agency)) < 5 && len([]rune(thisinfo.Agency)) > 5) {
+		pInfo.Agency = thisinfo.Agency
+		set["agency"] = thisinfo.Agency
+	}
+	//9--采购单位联系人
+	if thisinfo.Buyerperson != "" && strings.Index(pInfo.Buyerperson, thisinfo.Buyerperson) < 0 {
+		pInfo.Buyerperson = thisinfo.Buyerperson
+		set["buyerperson"] = pInfo.Buyerperson
+	}
+	//10--采购单位電話
+	if thisinfo.Buyertel != "" && strings.Index(pInfo.Buyertel, thisinfo.Buyertel) < 0 {
+		pInfo.Buyertel = thisinfo.Buyertel
+		set["buyertel"] = pInfo.Buyertel
+	}
+
+	if thisinfo.Bidopentime > pInfo.Bidopentime {
+		pInfo.Bidopentime = thisinfo.Bidopentime
+		set["bidopentime"] = pInfo.Bidopentime
+	}
+	if thisinfo.Bidamount > 0 && pInfo.Bidamount < 1 {
+		pInfo.Bidamount = thisinfo.Bidamount
+		set["bidamount"] = pInfo.Bidamount
+	}
+
+	if thisinfo.Budget > 0 && pInfo.Budget < 1 { //多包的会有问题,没有进行合计。
+		pInfo.Budget = thisinfo.Budget
+		set["budget"] = pInfo.Budget
+	}
+
+	if len(thisinfo.Topscopeclass) > 0 {
+		sort.Strings(pInfo.Topscopeclass)
+		for _, k := range thisinfo.Topscopeclass {
+			if BinarySearch(pInfo.Topscopeclass, k) == -1 {
+				pInfo.Topscopeclass = append(pInfo.Topscopeclass, k)
+				sort.Strings(pInfo.Topscopeclass)
+			}
+		}
+		set["topscopeclass"] = pInfo.Topscopeclass
+	}
+
+	if len(thisinfo.Subscopeclass) > 0 {
+		sort.Strings(pInfo.Subscopeclass)
+		for _, k := range thisinfo.Subscopeclass {
+			if BinarySearch(pInfo.Subscopeclass, k) == -1 {
+				pInfo.Subscopeclass = append(pInfo.Subscopeclass, k)
+				sort.Strings(pInfo.Subscopeclass)
+			}
+		}
+		set["subscopeclass"] = pInfo.Subscopeclass
+		set["s_subscopeclass"] = strings.Join(pInfo.Subscopeclass, ",")
+	}
+	//winner
+	if len(thisinfo.Winners) > 0 {
+		sort.Strings(pInfo.Winners)
+		for _, k := range thisinfo.Winners {
+			if BinarySearch(pInfo.Winners, k) == -1 {
+				pInfo.Winners = append(pInfo.Winners, k)
+				sort.Strings(pInfo.Winners)
+			}
+		}
+		//set["winners"] = pInfo.Winners
+		set["s_winner"] = strings.Join(pInfo.Winners, ",")
+	}
+
+	if thisinfo.HasPackage {
+		pkg, _, _ := PackageFormat(thisinfo, pInfo)
+		pInfo.Package = pkg
+	}
+
+	set["mpn"] = pInfo.MPN
+	set["mpc"] = pInfo.MPC
+	set["pici"] = p.pici
+
+	if thisinfo.HasPackage {
+		set["multipackage"] = 1
+	} else {
+		set["multipackage"] = 0
+	}
+	return set
+}
+
+func deleteSlice1(arr []interface{}, v interface{}) []interface{} {
+	for k, v1 := range arr {
+		if reflect.DeepEqual(v1, v) {
+			return append(arr[:k], arr[k+1:]...)
+		}
+	}
+	return arr
+}
+
+func updateValue(info map[string]interface{}, tmp map[string]interface{}) map[string]interface{} {
+	for k := range info{
+		for k1 := range tmp {
+			if k == k1 && info[k] != tmp[k1] {
+				info[k] = tmp[k]
+				break
+			}
+		}
+	}
+	return info
+}
+
+//备份(快照)
+func backupPro(tmp map[string]interface{}) {
+	tmp1 := make(map[string]interface{})
+	for k, v := range tmp{
+		tmp1[k] = v
+	}
+	if Sysconfig["backupFlag"].(bool) {
+		tmp1["sourceprojectid"] = tmp1["_id"]
+		delete(tmp1, "_id")
+		MongoTool.Save(BackupColl, tmp1)
+	}
+}