// 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)
}
