// front package front import ( //"container/list" "encoding/json" "fmt" "io/ioutil" qu "qfw/util" "sync/atomic" //"qfw/util/mongodb" mgo "mongodb" //"qfw/util/redis" "sort" "strings" "sync" "time" "util" "github.com/go-xweb/xweb" _ "github.com/influxdata/influxdb-client" "github.com/tealeg/xlsx" es "gopkg.in/olivere/elastic.v1" ) type Front struct { *xweb.Action //index xweb.Mapper `xweb:"/"` // pack xweb.Mapper `xweb:"/package"` listInfo xweb.Mapper `xweb:"/list"` elist xweb.Mapper `xweb:"/elist"` detail xweb.Mapper `xweb:"/detail/(.*).html"` biaozhu xweb.Mapper `xweb:"/biaozhu"` tj xweb.Mapper `xweb:"/tj"` importByExcel xweb.Mapper `xweb:"/importbyexcel"` importByEs xweb.Mapper `xweb:"/importbyes"` getEsCount xweb.Mapper `xweb:"/getescount"` finishCheck xweb.Mapper `xweb:"/finishcheck"` syncMarked xweb.Mapper `xweb:"/syncmarked"` } //var IdList *list.List //所有数据 //var IdPackList *list.List //含有分包的数据 var preKey = "ck_" var preErr = "err_" var SE = qu.SimpleEncrypt{Key: "topJYBX2019"} var Max, Min string var HasNo bool //预算和中标金额是否存在标记 var QueryFind map[string]interface{} //查询 /* status -1:初始未验证 1:正确 2:新增 3:修改 4:删除 */ /** //查询初始化的数据 func (i *Front) Index() error { _id := "" ran := 0 for { index, invalid := 0, 0 if IdList.Len() == 0 { return i.Render("finish.html") } ran = util.Getrand(IdList.Len()) for e := IdList.Front(); e != nil; e = e.Next() { //遍历IdList,获取id if index == ran { _id = qu.ObjToString(e.Value) invalid = redis.GetInt("extcheck", "extcheck_"+_id) break } index++ } if invalid == 0 { break } if IdList.Len() < 500 { //|| IdPackList.Len() < 100 qu.Debug("抽查数据剩余不足", IdList.Len()) break } } redis.Put("extcheck", "extcheck_"+_id, 1, 10*60) qu.Debug("_id", _id, "---", IdList.Len()) rep := getDetail(_id) //i.T["ispackage"] = ispackage //i.T["type"] = rep["type"] i.T["info"] = rep["info"] i.T["common"] = rep["common"] i.T["worder"] = rep["worder"] i.T["packs"] = rep["packs"] i.T["packskey"] = rep["packskey"] i.T["ck_pclisext"] = rep["ck_pclisext"] i.T["ck_wodrisext"] = rep["ck_wodrisext"] i.T["ck_pkgisext"] = rep["ck_pkgisext"] i.T["timeplace"] = rep["timeplace"] i.T["purchasinglist"] = rep["purchasinglist"] i.T["other"] = rep["other"] //qu.Debug(util.PurchasinglistField, util.WinnerorderField, util.PackageField) i.T["PurchasinglistField"] = util.PurchasinglistField i.T["WinnerorderField"] = util.WinnerorderField i.T["PackageField"] = util.PackageField i.T[preKey+"purchasinglist"] = rep[preKey+"purchasinglist"] i.T[preKey+"package"] = rep[preKey+"package"] i.T[preKey+"winnerorder"] = rep[preKey+"winnerorder"] i.T["worder_new"] = rep["worder_new"] i.T["pcl_new"] = rep["pcl_new"] i.T["pkg_new"] = rep["pkg_new"] return i.Render("detail.html", &i.T) } */ //列表 func (i *Front) ListInfo() error { spidercode := i.GetString("spidercode") coll := i.GetString("coll") field := i.GetString("field") stype := i.GetString("type") Min = i.GetString("minval") Max = i.GetString("maxval") HasNo, _ = i.GetBool("hasno") pagenum, _ := i.GetInteger("pagenum") if pagenum == 0 { pagenum = 1 } if coll != "" { //指定表 util.Coll = coll } if stype == "" { stype = "-1" } if field == "" { field = "-1" } listData := getListInfo(spidercode, stype, field, pagenum) //if len(listData) > 0 { //每次查询更新内存中标注数据 // IdList = list.New() // for _, v := range listData { // IdList.PushBack(mgo.BsonIdToSId(v["_id"])) // } //} i.T["list"] = listData i.T["type"] = stype i.T["field"] = field i.T["spidercode"] = spidercode i.T["coll"] = coll i.T["topsubtype"] = util.TopSubStypeArr i.T["allfield"] = util.AllFieldArr i.T["fromtable"] = util.Coll i.T["dbname"] = util.Config.Dbname i.T["max"] = Max i.T["min"] = Min i.T["hasno"] = HasNo checkedNum, allNum := GetCheckedAndAllDataInfo() //已标和总数信息 i.T["checkednum"] = checkedNum i.T["allnum"] = allNum i.T["pagenum"] = pagenum return i.Render("list.html", &i.T) } //标错列表 func (i *Front) Elist() error { attrname := i.GetString("attrname") common := util.Config.Biaozhu["common"] elist, _ := util.MgoM.Find(util.Config.Totablel, `{"ck_`+attrname+`":"0"}`, `{"_id":1}`, `{"_id":1}`, false, -1, -1) for _, v := range *elist { v["_id"] = mgo.BsonIdToSId(v["_id"]) } i.T["elist"] = *elist i.T["attrname"] = attrname i.T["common"] = common return i.Render("elist.html", &i.T) } //标注 func (i *Front) Biaozhu() error { b := false obj := []map[string]interface{}{} //ispackage := i.GetString("ispackage") key := i.GetString("key") _id := i.GetString("_id") stype, _ := i.GetInteger("stype") err := json.Unmarshal([]byte(key), &obj) if err != nil { i.ServeJson(b) return nil } //base := map[string]interface{}{} set := map[string]interface{}{} //更新、新增字段 unset := map[string]interface{}{} //删除字段 errset := map[string]interface{}{} //记录修改的字段信息 isSaveMarked := false if len(obj) == 1 { //单独保存某个一级 content, ok := obj[0]["content"].([]interface{}) if !ok || len(content) == 0 { i.ServeJson(b) return nil } title := qu.ObjToString(obj[0]["title"]) isext, _ := obj[0]["checkType"].(bool) status := qu.IntAll(obj[0]["status"]) switch title { case "基本字段": BzJBZD(content, set, unset, errset) case "时间地点": BzSJDD(content, set, unset, errset) case "标的信息": BzBDXX(content, set, unset, errset, isext, status) case "多包信息": BzDBXX(content, set, unset, errset, isext, status) case "中标候选人信息": BzZBHXRXX(content, set, unset, errset, isext, status) case "其余信息": BzQYXX(content, set, unset, errset) } } else { isSaveMarked = true for j, val := range obj { content, ok := val["content"].([]interface{}) status := qu.IntAll(val["status"]) if !ok { continue // i.ServeJson(b) // return nil } isext, _ := val["checkType"].(bool) if j == 0 { //基本信息 BzJBZD(content, set, unset, errset) } else if j == 1 { //时间地点 BzSJDD(content, set, unset, errset) } else if j == 2 { //标的物 BzBDXX(content, set, unset, errset, isext, status) } else if j == 3 { //多包 BzDBXX(content, set, unset, errset, isext, status) } else if j == 4 { //候选人 BzZBHXRXX(content, set, unset, errset, isext, status) } else { //其余信息 BzQYXX(content, set, unset, errset) } } } // qu.Debug("errset---", errset) // qu.Debug("set---", set) // qu.Debug("unset---", unset) unerrset := map[string]interface{}{} //记录errdata错误信息表删除 data, _ := util.MgoM.FindById(util.Coll, _id, nil) //标注误操作处理 if len(set) > 0 { //set中为本次标注保存的数据(ck_bidopentime:1;ck_buyer:2;buyer:"XXX") for s, sv := range set { //区分是标记字段,还是普通字段(标记字段:ck_buyer;普通字段:buyer) if strings.HasPrefix(s, preKey) { //标记字段 status := qu.IntAll(sv) field := s[3:] //去除前缀,获得字段 if s == preKey+"package" || s == preKey+"purchasinglist" || s == preKey+"winnerorder" { if (*data)[s] != nil { //package、purchasinglist、winnerorder已标注,不再修改 delete(set, s) delete(set, field) continue } } if set[field] == nil && status != 4 { //表示该字段没有要修改的值,此时标记为1或4(亦或是ck_wodrisext;ck_pkgisext;ck_pclisext) continue } else { //此时有修改的值和标记2、3、4 if checkedStatus := qu.IntAll((*data)[s]); checkedStatus != 0 { //已有标注信息的状态 if status == 2 && checkedStatus == 4 { //4>2,errdata删除,marked新增该字段,标记变为1 unerrset[field] = "" set[s] = 1 } else if status == 3 { if checkedStatus == 2 { //2>3,marked 修改该字段,标记变为2 set[s] = 2 } else if checkedStatus == 3 { //3>3,对比errdata错误值:相等变为1,errdata删除;不等变为3,marked修改该字段 errdata, _ := util.MgoM.FindById(util.Config.Totablel, _id, `{"`+field+`":1}`) if errdata != nil && len(*errdata) != 0 { errText := fmt.Sprint((*errdata)[field]) text := fmt.Sprint(set[field]) if errText == text { set[s] = 1 unerrset[field] = "" } } } } else if status == 4 { if checkedStatus == 2 { //2>4,errdata删除,marked删除该字段,标记变为1 unerrset[field] = "" set[s] = 1 unset[field] = "" } else if checkedStatus == 3 { //3>4,marked删除该字段,标记变为4 set[s] = 4 unset[field] = "" } } } } } } } //存储原错误信息 errUpdata := map[string]interface{}{} if len(errset) > 0 { for f, v := range errset { if (*data)[preKey+f] != nil { //已标注保存过不再记录错误信息 delete(errset, f) continue } // if ck, ok := (*data)[preKey+f].(int32); ok && ck != 1 { //已标注保存过不再记录错误信息 // delete(errset, f) // continue // } if f == "purchasinglist" || f == "winnerorder" { pcl, _ := (*data)[f].([]interface{}) pcl_err := v.([]interface{}) for j, perr := range pcl_err { perrMap := perr.(map[string]interface{}) if len(perrMap) > 0 { for k, status := range perrMap { if pMap, ok := pcl[j].(map[string]interface{}); ok && len(pMap) > 0 { //避免手动增加的子包找不到原数据 pMap[preErr+k] = status //打上错误标记 pMap[k] = pMap[k] } } } } errset[f] = (*data)[f] } else if f == "package" { pkg_err, _ := v.(map[string]interface{}) pkg := (*data)["package"].(map[string]interface{}) for num, v := range pkg_err { result_err := map[string]interface{}{} vMap := v.(map[string]interface{}) for k, status := range vMap { if pMap, ok := pkg[num].(map[string]interface{}); ok && len(pMap) > 0 { result_err[preErr+k] = status result_err[k] = pMap[k] } } pkg_err[num] = result_err } } else { errset[f] = (*data)[f] } } //qu.Debug("errset---", errset) errset["updatetime"] = time.Now().Unix() errUpdata["$set"] = errset } if len(unerrset) > 0 { //qu.Debug("unerrset---", unerrset) errUpdata["$unset"] = unerrset } if len(errUpdata) > 0 { util.MgoM.Update(util.Config.Totablel, `{"_id":"`+_id+`"}`, errUpdata, true, false) } //qu.Debug("set---", set) //更新正确信息 update := map[string]interface{}{} if len(set) > 0 { set["ck_data"] = stype set["updatetime"] = time.Now().Unix() update["$set"] = set } if len(unset) > 0 { update["$unset"] = unset } if len(update) > 0 { b = util.MgoM.Update(util.Coll, `{"_id":"`+_id+`"}`, update, false, false) if b { //for e := IdList.Front(); e != nil; e = e.Next() { //遍历IdList,删除元素 // if _id == qu.ObjToString(e.Value) { // IdList.Remove(e) // break // } //} if util.Coll != util.Config.Fromtable && isSaveMarked { //util.coll此时的标注表 util.Config.Fromtable默认标注表 data, _ := util.MgoM.FindById(util.Coll, _id, nil) if data != nil && len(*data) > 0 { update := map[string]interface{}{"$set": *data} if len(unset) > 0 { update["$unset"] = unset } if !util.MgoM.Update(util.Config.Fromtable, map[string]interface{}{"_id": (*data)["_id"]}, update, true, false) { qu.Debug("同步marked失败,", _id) } } } } i.ServeJson(b) } return nil } //查询信息 func (i *Front) Detail(id string) error { rep := getDetail(id) //i.T["type"] = rep["type"] i.T["info"] = rep["info"] i.T["common"] = rep["common"] i.T["worder"] = rep["worder"] i.T["packs"] = rep["packs"] i.T["packskey"] = rep["packskey"] i.T["ck_pclisext"] = rep["ck_pclisext"] i.T["ck_wodrisext"] = rep["ck_wodrisext"] i.T["ck_pkgisext"] = rep["ck_pkgisext"] i.T["timeplace"] = rep["timeplace"] i.T["purchasinglist"] = rep["purchasinglist"] i.T["other"] = rep["other"] i.T["PurchasinglistField"] = util.PurchasinglistField i.T["WinnerorderField"] = util.WinnerorderField i.T["PackageField"] = util.PackageField i.T[preKey+"purchasinglist"] = rep[preKey+"purchasinglist"] i.T[preKey+"package"] = rep[preKey+"package"] i.T[preKey+"winnerorder"] = rep[preKey+"winnerorder"] i.T["worder_new"] = rep["worder_new"] i.T["pcl_new"] = rep["pcl_new"] i.T["pkg_new"] = rep["pkg_new"] i.T["nextid"] = GetNextDataId(id) //下一条id checkedNum, allNum := GetCheckedAndAllDataInfo() //已标和总数信息 i.T["checkednum"] = checkedNum i.T["allnum"] = allNum return i.Render("detail.html", &i.T) } //通过excel表格导入 func (i *Front) ImportByExcel() { defer qu.Catch() //success := false msg := "" importNum := 0 successNum := int64(0) coll := i.GetString("excelcoll") if coll == "" { i.ServeJson(map[string]interface{}{"msg": "表名错误"}) return } mf, _, err := i.GetFile("xlsx") if err == nil { binary, _ := ioutil.ReadAll(mf) xls, _ := xlsx.OpenBinary(binary) sheet := xls.Sheets[0] rows := sheet.Rows idcolnum := -1 ids := []string{} cellFieldName := map[int]string{} //记录客户需求字段所在的列 tmpMap := map[string]map[string]interface{}{} //excel表中需要保存字段集合 for rn, row := range rows { if rn == 0 { for j, cell := range row.Cells { title := cell.Value if fieldName := util.Config.CustomerField[title]; fieldName != "" { //客户需求字段 cellFieldName[j] = fieldName } if title == "唯一标识" || title == "信息标识" { //id所在列 idcolnum = j } } if idcolnum == -1 { break } continue } if len(row.Cells) < len(rows[0].Cells) { break } tmp := map[string]interface{}{} for j, f := range cellFieldName { if val := row.Cells[j].Value; val != "" { if f == "capital" { //注册资金(万元) cf, _ := row.Cells[j].Float() tmp[f] = cf } else if f == "createtime" { //创建时间 ci, _ := row.Cells[j].Int64() tmp[f] = ci } else { tmp[f] = val } } } id := row.Cells[idcolnum].String() //加密的id if id == "" { break } id = SE.DecodeString(id) //解密后id tmpMap[id] = tmp ids = append(ids, id) } importNum = len(ids) //excel表数据个数 if importNum > 0 { _, msg, successNum = GetDataById(coll, ids, "excel", tmpMap) tmpMap = map[string]map[string]interface{}{} ids = []string{} } } msg = fmt.Sprintf("共查询%d条,导入成功%d条\n", importNum, successNum) + msg i.ServeJson(map[string]interface{}{"msg": msg}) } func (i *Front) GetEsCount() { defer qu.Catch() msg := "" count := int64(0) estext := i.GetString("estext") //es查询语句 esJson := map[string]interface{}{} if json.Unmarshal([]byte(estext), &esJson) != nil || len(esJson) == 0 { msg = "Es语句错误" } else { count = util.Es.Count(util.Index, util.Itype, estext) } i.ServeJson(map[string]interface{}{"count": count, "msg": msg}) } //通过es语句导入 func (i *Front) ImportByEs() { defer qu.Catch() //success := false msg := "" successNum := int64(0) estext := i.GetString("estext") //es查询语句 coll := i.GetString("coll") //导入表 if coll == "" { i.ServeJson(map[string]interface{}{"msg": "表名错误"}) return } client := util.Es.GetEsConn() defer util.Es.DestoryEsConn(client) ch := make(chan bool, 5) wg := &sync.WaitGroup{} lock := &sync.Mutex{} escount := util.Es.Count(util.Index, util.Itype, estext) qu.Debug("查询总数:", escount) if escount > 0 { //查询条件类型转换 var q es.Query tmpQuery := es.BoolQuery{ QueryStrings: estext, } q = tmpQuery //游标查询,index不支持别名,只能写索引库的名称 res, err := client.Scroll(util.Index).Query(q).Size(200).Do() //查询一条获取游标 ids := []string{} //id数据 if err == nil { numDocs := 0 scrollId := res.ScrollId for { if scrollId == "" { qu.Debug("ScrollId Is Error") break } searchResult, err := client.Scroll(util.Index).Size(200).ScrollId(scrollId).Do() //查询 if err != nil { if err.Error() == "EOS" { //迭代完毕 qu.Debug("Es Search Data Over:", err) } else { qu.Debug("Es Search Data Error:", err) } break } for _, hit := range searchResult.Hits.Hits { //开始处理数据 wg.Add(1) ch <- true go func(tmpHit *es.SearchHit) { defer func() { <-ch wg.Done() }() tmp := make(map[string]interface{}) if json.Unmarshal(*tmpHit.Source, &tmp) == nil { id := qu.ObjToString(tmp["_id"]) tmp["id"] = id //记录数据原有id lock.Lock() ids = append(ids, id) lock.Unlock() } }(hit) numDocs += 1 if numDocs%500 == 0 { qu.Debug("Current:", numDocs) } } scrollId = searchResult.ScrollId } wg.Wait() client.ClearScroll().ScrollId(scrollId).Do() //清理游标 //qu.Debug("Result Data Count:", numDocs) } else { qu.Debug("Es Search Data Error") } //判断数量 if int64(len(ids)) != escount { msg = "查询数据和结果不一致" } else { //入库 _, msg, successNum = GetDataById(coll, ids, "es", map[string]map[string]interface{}{}) } } else { msg = "无查询数据" } msg = fmt.Sprintf("共查询%d条,导入成功%d条\n", escount, successNum) + msg i.ServeJson(map[string]interface{}{"msg": msg}) } //同步数据 func (i *Front) SyncMarked() { syncColl := i.GetString("coll") sess := util.MgoM.GetMgoConn() defer util.MgoM.DestoryMongoConn(sess) it := sess.DB(util.Config.Dbname).C(syncColl).Find(nil).Iter() count, _ := sess.DB(util.Config.Dbname).C(syncColl).Find(nil).Count() qu.Debug(syncColl, count) n := 0 lock := &sync.Mutex{} wg := &sync.WaitGroup{} ch := make(chan bool, 3) result := map[string]map[string]interface{}{} idArr := []string{} for tmp := make(map[string]interface{}); it.Next(tmp); n++ { wg.Add(1) ch <- true go func(tmp map[string]interface{}) { defer func() { <-ch wg.Done() }() id := qu.ObjToString(tmp["id"]) if id == "" { return } tmpMap := map[string]interface{}{} for _, f := range util.Config.CustomerField { if val := tmp[f]; val != nil { tmpMap[f] = val } } lock.Lock() idArr = append(idArr, id) result[id] = tmpMap lock.Unlock() }(tmp) tmp = map[string]interface{}{} } wg.Wait() if count != int64(len(result)) { i.ServeJson(map[string]interface{}{"msg": "同步失败", "flag": false}) return } //util.MgoM.C.Database(util.Config.Dbname).Collection(syncColl).Drop(util.MgoM.Ctx) //删除syncColl表(清空数据) success, msg, successNum := GetDataById(syncColl, idArr, "syncoll", result) result = map[string]map[string]interface{}{} idArr = []string{} msg = fmt.Sprintf("共查询%d条,同步成功%d条\n", count, successNum) + msg i.ServeJson(map[string]interface{}{"msg": msg, "flag": success}) } //标注完成 func (i *Front) FinishCheck() { i.Render("finish.html") } //查询列表数据 func getListInfo(spidercode, stype, field string, currentpage int) []map[string]interface{} { QueryFind = map[string]interface{}{} if spidercode != "" { QueryFind["spidercode"] = spidercode } if stype != "-1" && stype != "" { if stype == util.SPECIALTYPE { QueryFind["subtype"] = map[string]interface{}{ "$exists": false, } } else { subtype := strings.Split(stype, "-")[1] QueryFind["subtype"] = subtype } } if field != "-1" && field != "" { //query[field] = map[string]interface{}{ // "$exists": true, //字段存在 //} QueryFind[preKey+field] = map[string]interface{}{ "$exists": false, //field未曾标记 } if field == "budget" || field == "bidamount" { //金额区间 numMap := map[string]interface{}{} if Min != "" { minint := qu.IntAll(Min) numMap["$gte"] = minint } if Max != "" { maxint := qu.IntAll(Max) numMap["$lte"] = maxint } queryArr := []interface{}{} if HasNo { //包含field不存在的数据 queryArr = append(queryArr, map[string]interface{}{ field: map[string]interface{}{ "$exists": false, }, }) } if len(numMap) > 0 { //给定了区间,查询此区间或者budget、bidamount不存在的数据 queryArr = append(queryArr, map[string]interface{}{ field: numMap, }) } if len(queryArr) > 0 { QueryFind["$or"] = queryArr } } else { HasNo = false //当字段不是budget、bidamount时,HasNo改为false,仅作用于页面展示 } } qu.Debug("query:", util.Coll, QueryFind) start := (currentpage - 1) * 50 infoList, _ := util.MgoM.Find(util.Coll, QueryFind, `{"_id":1}`, `{"_id":1,"title":1,"detail":1,"site":1,"href":1,"ck_data":1}`, false, start, 50) for k, v := range *infoList { ck_data := qu.IntAll(v["ck_data"]) if ck_data > 0 { v["checked"] = true } else { v["checked"] = false } href := fmt.Sprint(v["href"]) if !strings.HasPrefix(href, "http") { v["href"] = "http://" + href } v["_id"] = mgo.BsonIdToSId(v["_id"]) (*infoList)[k] = v v["num"] = k + 1 + start } return *infoList } func getDetail(id string) map[string]interface{} { rep := map[string]interface{}{} infoTmp, _ := util.MgoM.FindById(util.Coll, id, ``) info := *infoTmp // if qu.ObjToString(info["check"]) == "ok" && flag != "y" { // bz_info, _ := util.MgoM.FindById(util.Config.Totablel, id, ``) // for k, v := range *bz_info { // info[k] = v // } // } info["_id"] = mgo.BsonIdToSId(info["_id"]) ck_pclisext, _ := info["ck_pclisext"].(bool) ck_wodrisext, _ := info["ck_wodrisext"].(bool) ck_pkgisext, _ := info["ck_pkgisext"].(bool) rep["ck_pclisext"] = ck_pclisext rep["ck_wodrisext"] = ck_wodrisext rep["ck_pkgisext"] = ck_pkgisext href := qu.ObjToString(info["href"]) if !strings.HasPrefix(href, "http") { info["href"] = "http://" + href } info["filetext"] = util.GetFileText(info) //获取附件信息 //rep["type"] = ftype rep["info"] = info common, timeplace, other := setExtComMap(info) //拼装抽取common值 rep["common"] = common rep["timeplace"] = timeplace rep["other"] = other packs, packskey, pkg_new := setPaceMap(info) //拼装子包信息 rep["packs"] = packs rep["packskey"] = packskey rep["pkg_new"] = pkg_new purchasinglist, pcl_new := setPurchasingMap(info) //标的物 rep["purchasinglist"] = purchasinglist rep["pcl_new"] = pcl_new worder, worder_new := setWorderMap(info) //中标候选人 rep["worder"] = worder rep["worder_new"] = worder_new // if info[preKey+"purchasinglist"] != nil { rep[preKey+"purchasinglist"] = "1" } else { rep[preKey+"purchasinglist"] = "-1" } if info[preKey+"package"] != nil { rep[preKey+"package"] = "1" } else { rep[preKey+"package"] = "-1" } if info[preKey+"winnerorder"] != nil { rep[preKey+"winnerorder"] = "1" } else { rep[preKey+"winnerorder"] = "-1" } return rep } //拼装中标候选人 func setWorderMap(info map[string]interface{}) ([]interface{}, []bool) { //基本参数--中标候选人 winnerorder, _ := util.Config.Biaozhu["winnerorder"].([]interface{}) worders := []interface{}{} isNewWorder := []bool{} //记录子包是否是新增的 if tmpwds, ok := info["winnerorder"].([]interface{}); ok { for _, v := range tmpwds { if wd, ok := v.(map[string]interface{}); ok { isNew, _ := wd["ck_isnew"].(bool) isNewWorder = append(isNewWorder, isNew) wds := []interface{}{} for _, cp := range winnerorder { cp, _ := cp.(map[string]interface{}) tp := map[string]interface{}{ "key": cp["key"], "descript": cp["descript"], "value": wd[qu.ObjToString(cp["key"])], } if wd[preKey+fmt.Sprint(tp["key"])] == nil { tp["status"] = "-1" } else { tp["status"] = "1" } wds = append(wds, tp) } worders = append(worders, wds) } } } return worders, isNewWorder } //拼装标的物 func setPurchasingMap(info map[string]interface{}) ([]interface{}, []bool) { purchasinglist, _ := util.Config.Biaozhu["purchasinglist"].([]interface{}) purchasinglists := []interface{}{} isNewPcl := []bool{} //记录子包是否是新增的 if tmpcls, ok := info["purchasinglist"].([]interface{}); ok { for _, v := range tmpcls { if pcl, ok := v.(map[string]interface{}); ok { isNew, _ := pcl["ck_isnew"].(bool) isNewPcl = append(isNewPcl, isNew) pcls := []interface{}{} for _, ps := range purchasinglist { ps, _ := ps.(map[string]interface{}) value := pcl[qu.ObjToString(ps["key"])] if value == nil { value = "" } tp := map[string]interface{}{ "key": ps["key"], "descript": ps["descript"], "value": value, } if pcl[preKey+fmt.Sprint(tp["key"])] == nil { tp["status"] = "-1" } else { tp["status"] = "1" } pcls = append(pcls, tp) } purchasinglists = append(purchasinglists, pcls) } } } return purchasinglists, isNewPcl } //拼装子包信息 func setPaceMap(info map[string]interface{}) ([]map[string]interface{}, []string, map[string]bool) { var confpack []interface{} confpack, _ = util.Config.Biaozhu["package"].([]interface{}) packs := map[string]map[string]interface{}{} sortpackskey := []string{} isNewPkg := map[string]bool{} //记录子包是否是新增的 if packages, ok := info["package"].(map[string]interface{}); ok && len(packages) > 0 { for k, tmpackage := range packages { //遍历分包 if tmppack, ok := tmpackage.(map[string]interface{}); ok { isNew, _ := tmppack["ck_isnew"].(bool) isNewPkg[k] = isNew sortpackskey = append(sortpackskey, k) pack := []interface{}{} for _, cpack := range confpack { cpack, _ := cpack.(map[string]interface{}) tp := map[string]interface{}{ "key": cpack["key"], "descript": cpack["descript"], } if tmppack[fmt.Sprint(tp["key"])] != nil { tp["value"] = tmppack[qu.ObjToString(tp["key"])] } else { tp["value"] = "" } if tmppack[preKey+fmt.Sprint(tp["key"])] == nil { tp["status"] = "-1" } else { tp["status"] = "1" } pack = append(pack, tp) } packs[k] = map[string]interface{}{ "pack": pack, //"pack_worder": pack_worder, } } } } sort.Strings(sortpackskey) packages := []map[string]interface{}{} for _, v := range sortpackskey { packages = append(packages, packs[v]) } //qu.Debug("分包---", packages) return packages, sortpackskey, isNewPkg } //拼装抽取common值 func setExtComMap(info map[string]interface{}) ([]interface{}, []interface{}, []interface{}) { //基本参数 common, _ := util.Config.Biaozhu["common"].([]interface{}) for k, tmp := range common { if cp, ok := tmp.(map[string]interface{}); ok { if info[fmt.Sprint(cp["key"])] == nil { cp["value"] = "" } else { cp["value"] = info[fmt.Sprint(cp["key"])] } if info[preKey+fmt.Sprint(cp["key"])] == nil { cp["status"] = "-1" } else { cp["status"] = "1" } common[k] = cp } } //时间地点信息 timeplace, _ := util.Config.Biaozhu["timeplace"].([]interface{}) for k, tmp := range timeplace { if tp, ok := tmp.(map[string]interface{}); ok { if info[fmt.Sprint(tp["key"])] == nil { tp["value"] = "" } else { key := tp["key"] if key == "bidopentime" || key == "publishtime" || key == "bidendtime" || key == "project_startdate" || key == "project_completedate" { tmpTime := qu.Int64All(info[fmt.Sprint(tp["key"])]) if tmpTime > 0 { tp["value"] = qu.FormatDateByInt64(&tmpTime, qu.Date_Full_Layout) } else { tp["value"] = info[qu.ObjToString(tp["key"])] } } else { tp["value"] = info[fmt.Sprint(tp["key"])] } } if info[preKey+fmt.Sprint(tp["key"])] == nil { tp["status"] = "-1" } else { tp["status"] = "1" } timeplace[k] = tp } } //other信息 other, _ := util.Config.Biaozhu["other"].([]interface{}) for k, tmp := range other { if cp, ok := tmp.(map[string]interface{}); ok { if info[fmt.Sprint(cp["key"])] == nil { cp["value"] = "" } else { if cp["key"] == "signaturedate" { bidopentime := qu.Int64All(info[fmt.Sprint(cp["key"])]) if bidopentime > 0 { cp["value"] = qu.FormatDateByInt64(&bidopentime, qu.Date_Full_Layout) } else { cp["value"] = info[qu.ObjToString(cp["key"])] } } else { cp["value"] = info[fmt.Sprint(cp["key"])] } } //log.Println(cp) if info[preKey+fmt.Sprint(cp["key"])] == nil { cp["status"] = "-1" } else { cp["status"] = "1" } other[k] = cp } } return common, timeplace, other } //标注基本字段 func BzJBZD(content []interface{}, set, unset, errset map[string]interface{}) { info, _ := content[0].(map[string]interface{}) if uInputs, ok := info["uInput"].([]interface{}); ok { for _, tmp := range uInputs { if tmpMap, ok := tmp.(map[string]interface{}); ok { if status := qu.IntAll(tmpMap["status"]); status != -1 { key := qu.ObjToString(tmpMap["key"]) //字段 if key == "" { continue } if status == 2 || status == 3 { //新增、修改 input := tmpMap["input"] //值 if key == "attach_discern" || key == "attach_ext" { //附件识别、抽取select input = tmpMap["select"] } else if key == "budget" || key == "bidamount" { input = qu.Float64All(input) } set[key] = input errset[key] = status } else if status == 4 { //删除 unset[key] = "" errset[key] = status } set[preKey+key] = status } } } } //qu.Debug("set---", set) // qu.Debug("unset---", unset) } //标注时间地点 func BzSJDD(content []interface{}, set, unset, errset map[string]interface{}) { info, _ := content[0].(map[string]interface{}) if uInputs, ok := info["uInput"].([]interface{}); ok { for _, tmp := range uInputs { if tmpMap, ok := tmp.(map[string]interface{}); ok { if status := qu.IntAll(tmpMap["status"]); status != -1 { key := qu.ObjToString(tmpMap["key"]) //字段 if status == 2 || status == 3 { //新增、修改 input := tmpMap["input"] //值 if key == "bidopentime" || key == "publishtime" || key == "bidendtime" || key == "project_startdate" || key == "project_completedate" { inputTmp, _ := time.ParseInLocation(qu.Date_Full_Layout, input.(string), time.Local) input = inputTmp.Unix() } set[key] = input errset[key] = status } else if status == 4 { //删除 unset[key] = "" errset[key] = status } set[preKey+key] = status } } } } // qu.Debug("set---", set) // qu.Debug("unset---", unset) } //标注标的信息 func BzBDXX(content []interface{}, set, unset, errset map[string]interface{}, isext bool, status int) { //qu.Debug("是否抽取:", status, isext, len(content), errset) if status == -1 { return } set["ck_pclisext"] = isext //标的信息是否抽取标记 purchasinglist := []interface{}{} errList := []interface{}{} delpclson := 0 for _, con := range content { info, _ := con.(map[string]interface{}) isNew, _ := info["ck_isnew"].(bool) //是否是新增子包 pclSonStatus := qu.IntAll(info["status"]) if pclSonStatus == 4 { delpclson++ } if uInputs, ok := info["uInput"].([]interface{}); ok { result := map[string]interface{}{ "ck_isnew": isNew, } errResult := map[string]interface{}{} for _, tmp := range uInputs { if tmpMap, ok := tmp.(map[string]interface{}); ok { key := qu.ObjToString(tmpMap["key"]) //字段 input := tmpMap["input"] //值 status := qu.IntAll(tmpMap["status"]) isNull := false if key == "number" || key == "unitprice" || key == "totalprice" { if input != "" { //有值 isNull = false input = qu.Float64All(input) } else { isNull = true } } if !isNull { //避免数字类型的字段在没有填写值的情况默认给0 result[key] = input } result[preKey+key] = status if !isNew && (status == 2 || status == 3 || status == 4) { errResult[key] = status //记录哪个字段错误 } } } if len(result) > 0 && pclSonStatus != 4 { purchasinglist = append(purchasinglist, result) } errList = append(errList, errResult) } } errset["purchasinglist"] = errList if len(purchasinglist)+delpclson == len(content) { set["purchasinglist"] = purchasinglist set[preKey+"purchasinglist"] = status } } //标注多包信息 func BzDBXX(content []interface{}, set, unset, errset map[string]interface{}, isext bool, status int) { //qu.Debug("是否抽取:", status, isext, len(content), errset) if status == -1 { return } set["ck_pkgisext"] = isext //多包是否抽取标记 pkgs := map[string]interface{}{} errMap := map[string]interface{}{} newNum := 1 delpkgson := 0 //记录子包删除个数 for _, con := range content { info, _ := con.(map[string]interface{}) pkgSonStatus := qu.IntAll(info["status"]) if pkgSonStatus == 4 { delpkgson++ } num := fmt.Sprint(info["num"]) //包号 isNew, _ := info["ck_isnew"].(bool) //是否是新增子包 if isNew { //新增子包新建包名 num = "new" + fmt.Sprint(newNum) newNum++ } if uInputs, ok := info["uInput"].([]interface{}); ok { result := map[string]interface{}{ "ck_isnew": isNew, } errResult := map[string]interface{}{} for _, tmp := range uInputs { if tmpMap, ok := tmp.(map[string]interface{}); ok { key := qu.ObjToString(tmpMap["key"]) //字段 input := tmpMap["input"] //值 status := qu.IntAll(tmpMap["status"]) isNull := false if key == "bidamount" || key == "budget" { if input != "" { //有值 isNull = false input = qu.Float64All(input) } else { isNull = true } } if !isNull { //避免数字类型的字段在没有填写值的情况默认给0 result[key] = input } result[preKey+key] = status if !isNew && (status == 2 || status == 3 || status == 4) { errResult[key] = status //记录哪个字段错误 } } } if len(errResult) > 0 { errMap[num] = errResult } if len(result) > 0 && pkgSonStatus != 4 { //要删除的子包不再保存 pkgs[num] = result } } } if len(errMap) > 0 { errset["package"] = errMap } if len(pkgs)+delpkgson == len(content) { set["package"] = pkgs set[preKey+"package"] = status } // qu.Debug("set---", set) // qu.Debug("unset---", unset) } //标注中标候选人信息 func BzZBHXRXX(content []interface{}, set, unset, errset map[string]interface{}, isext bool, status int) { //qu.Debug("是否抽取:", status, isext, len(content), errset) if status == -1 { return } set["ck_wodrisext"] = isext //中标候选人是否抽取标记 winnerorder := []interface{}{} errList := []interface{}{} delwodrson := 0 for _, con := range content { info, _ := con.(map[string]interface{}) isNew, _ := info["ck_isnew"].(bool) //是否是新增子包 wodrSonStatus := qu.IntAll(info["status"]) if wodrSonStatus == 4 { delwodrson++ } if uInputs, ok := info["uInput"].([]interface{}); ok { result := map[string]interface{}{ "ck_isnew": isNew, } errResult := map[string]interface{}{} for _, tmp := range uInputs { if tmpMap, ok := tmp.(map[string]interface{}); ok { key := qu.ObjToString(tmpMap["key"]) //字段 input := tmpMap["input"] //值 status := qu.IntAll(tmpMap["status"]) isNull := false if key == "price" { if input != "" { //有值 isNull = false input = qu.Float64All(input) } else { isNull = true } } if !isNull { //避免数字类型的字段在没有填写值的情况默认给0 result[key] = input } result[preKey+key] = status if !isNew && (status == 2 || status == 3 || status == 4) { errResult[key] = status //记录哪个字段错误 } } } if len(result) > 0 && wodrSonStatus != 4 { winnerorder = append(winnerorder, result) } errList = append(errList, errResult) } } errset["winnerorder"] = errList if len(winnerorder)+delwodrson == len(content) { set["winnerorder"] = winnerorder set[preKey+"winnerorder"] = status } // qu.Debug("set---", set) // qu.Debug("unset---", unset) // qu.Debug("errset---", errset) } //标注其余信息 func BzQYXX(content []interface{}, set, unset, errset map[string]interface{}) { info, _ := content[0].(map[string]interface{}) if uInputs, ok := info["uInput"].([]interface{}); ok { for _, tmp := range uInputs { if tmpMap, ok := tmp.(map[string]interface{}); ok { if status := qu.IntAll(tmpMap["status"]); status != -1 { key := qu.ObjToString(tmpMap["key"]) //字段 if status == 2 || status == 3 { //新增、修改 input := tmpMap["input"] //值 if key == "isppp" || key == "contract_guarantee" || key == "bid_guarantee" { input = tmpMap["select"] } else if key == "signaturedate" { // inputTmp, _ := time.ParseInLocation(qu.Date_Full_Layout, input.(string), time.Local) input = inputTmp.Unix() } else if key == "bid_bond" || key == "contract_bond" || key == "supervisorrate" || key == "agencyrate" || key == "docamount" || key == "agencyfee" { input = qu.Float64All(input) } set[key] = input errset[key] = status } else if status == 4 { //删除 unset[key] = "" errset[key] = status } set[preKey+key] = status } } } } // qu.Debug("set---", set) // qu.Debug("unset---", unset) } func mapIntAdd(k, val string, tmp map[string]map[string]int) map[string]map[string]int { key := k[3:] var keyct map[string]int if tmp[key] == nil { keyct = map[string]int{ "ok": 0, "fail": 0, "default": 0, } } else { keyct = tmp[key] } if val == "1" { keyct["ok"] += 1 } else if val == "0" { keyct["fail"] += 1 } else { keyct["default"] += 1 } tmp[key] = keyct return tmp } //通过id查询数据 func GetDataById(coll string, ids []string, stype string, tmp map[string]map[string]interface{}) (bool, string, int64) { defer qu.Catch() success := true msg := "" wg := &sync.WaitGroup{} lock := &sync.Mutex{} ch := make(chan bool, 5) n := int64(0) for i, id := range ids { wg.Add(1) ch <- true go func(i int, id string, success *bool, msg *string) { defer func() { wg.Done() <-ch }() /* 1.查bidding 2.查extract 3.extract合并到bidding(删除item字段以为与客户需要的item不是一个含义) 4.对比marked表,替换已标注过的字段值,补充标记 5.合并客户所需字段信息,补充id字段 6.若为同步时,删除原有id对应的信息,新增该id对应的_id信息 */ tmpBidColl := util.BidColl1 //bidding //查询bidding if id < util.BIDDINGSTARTID { tmpBidColl = util.BidColl2 //bidding_back } bidData, _ := util.MgoB.FindById(tmpBidColl, id, nil) if bidData != nil && len(*bidData) > 0 { //bidding表数据存在 //查询extract extData, _ := util.MgoE.FindById(util.ExtColl1, id, nil) if extData == nil || len(*extData) == 0 { extData, _ = util.MgoE.FindById(util.ExtColl2, id, nil) } //抽取表字段合并到bidding if extData != nil && len(*extData) > 0 { for k, v := range *extData { (*bidData)[k] = v } } //删除item delete((*bidData), "item") //对比marked表是否已标注该数据 markData, _ := util.MgoM.FindById(util.Config.Fromtable, id, nil) if markData != nil && len(*markData) > 0 { UpdateMarkColl(bidData, markData) //比对更新数据 } else { (*bidData)["ck_data"] = 0 //设置ck_data默认值0 //多包、中标候选人、标的信息是否抽取 if packageMap, ok := (*bidData)["package"].(map[string]interface{}); ok && len(packageMap) > 0 { (*bidData)["ck_pkgisext"] = true } else { (*bidData)["ck_pkgisext"] = false } if winorderArr, ok := (*bidData)["winnerorder"].([]interface{}); ok && len(winorderArr) > 0 { (*bidData)["ck_wodrisext"] = true } else { (*bidData)["ck_wodrisext"] = false } if purchArr, ok := (*bidData)["purchasinglist"].([]interface{}); ok && len(purchArr) > 0 { (*bidData)["ck_pclisext"] = true } else { (*bidData)["ck_pclisext"] = false } } //合并导入表中客户所需的字段 if len(tmp) > 0 { for k, v := range tmp[id] { (*bidData)[k] = v } } //补充id (*bidData)["id"] = id if stype == "syncoll" { //同步数据时删除原始数据 if util.MgoM.Delete(coll, `{"id":"`+id+`"}`) == 0 { lock.Lock() *msg += "同步未删除成功数据id:" + id + ";\n" *success = false lock.Unlock() } } //保存数据 if util.MgoM.SaveByOriID(coll, bidData) { atomic.AddInt64(&n, 1) //计数 } else { lock.Lock() *success = false if stype == "excel" { *msg += "第" + fmt.Sprint(i+2) + "行未保存成功数据_id:" + id + ";\n" } else { *msg += "未保存成功数据_id:" + id + ";\n" } lock.Unlock() } } else { lock.Lock() *success = false if stype == "excel" { *msg += "第" + fmt.Sprint(i+2) + "行未查询到数据:" + id + ";\n" } else { *msg += "未查询到数据_id:" + id + ";\n" } lock.Unlock() } }(i, id, &success, &msg) } wg.Wait() return success, msg, n } //更新数据 func UpdateMarkColl(bidData, markData *map[string]interface{}) { defer qu.Catch() ck_data := qu.IntAll((*markData)["ck_data"]) if ck_data == 2 { //某些字段已标注 for fk, fv := range *markData { ckFieldArr := strings.Split(fk, preKey) if len(ckFieldArr) == 2 { field := ckFieldArr[1] (*bidData)[fk] = fv //补充标记 if (*markData)[field] != nil { (*bidData)[field] = (*markData)[field] //字段更新 } } } (*bidData)["ck_data"] = 0 //marked表中该条数据如果为字段验证,临时表ck_data:0;若为数据验证ck_data:1 } else if ck_data == 1 { *bidData = *markData (*bidData)["ck_data"] = 1 } } //获取当前数据下一条的id func GetNextDataId(id string) string { nextIdQuery := map[string]interface{}{ "_id": map[string]interface{}{ "$gt": mgo.StringTOBsonId(id), }, } for k, v := range QueryFind { nextIdQuery[k] = v } one, _ := util.MgoM.Find(util.Coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1) if one != nil && len(*one) == 1 { return mgo.BsonIdToSId((*one)[0]["_id"]) } return id } //获取已标注和数据总数的信息 func GetCheckedAndAllDataInfo() (int, int) { allCount := util.MgoM.Count(util.Coll, QueryFind) ckDataQuery := map[string]interface{}{ "ck_data": map[string]interface{}{ "$gt": 0, }, } for k, v := range QueryFind { ckDataQuery[k] = v } checkedCount := util.MgoM.Count(util.Coll, ckDataQuery) return checkedCount, allCount } //统计抽查 func (i *Front) Tj() error { comm := map[string]map[string]int{} comm_win := map[string]map[string]int{} pack := map[string]map[string]int{} pack_win := map[string]map[string]int{} list, _ := util.MgoM.Find(util.Config.Totablel, "{}", nil, nil, false, -1, -1) for _, tmp := range *list { for k, val := range tmp { if len(k) > 3 && k[:3] == preKey { comm = mapIntAdd(k, qu.ObjToString(val), comm) } } if winnerorder, ok := tmp["winnerorder"].([]interface{}); ok { for _, wd := range winnerorder { if winner, ok := wd.(map[string]interface{}); ok { for k, val := range winner { if len(k) > 3 && k[:3] == preKey { comm_win = mapIntAdd(k, qu.ObjToString(val), comm_win) } } } } } if ptmp, ok := tmp["package"].(map[string]interface{}); ok { for _, pktmp := range ptmp { if pkage, ok := pktmp.(map[string]interface{}); ok { for k, val := range pkage { if len(k) > 3 && k[:3] == preKey { pack = mapIntAdd(k, qu.ObjToString(val), pack) } if k == "winnerorder" { if wtmp, ok := val.([]interface{}); ok { for _, winner := range wtmp { if win, ok := winner.(map[string]interface{}); ok { for wk, wval := range win { if len(k) > 3 && k[:3] == preKey { pack_win = mapIntAdd(wk, qu.ObjToString(wval), pack_win) } } } } } } } } } } } //data := map[string]interface{}{"total": len(list), "comm": comm, "pack": pack, "pack_win": pack_win} //mongodb.Save("extcheck_tj", data) i.T["comm"] = comm i.T["pack"] = pack i.T["comm_win"] = comm_win i.T["pack_win"] = pack_win i.T["total"] = len(*list) return i.Render("tj.html", &i.T) }