package front

import (
	"encoding/json"
	"fmt"
	"github.com/shopspring/decimal"
	"go.mongodb.org/mongo-driver/bson"
	"math"
	mgo "mongodb"
	qu "qfw/util"
	"sort"
	"strconv"
	"strings"
	"time"
	"util"
)

func (f *Front) RemarkList() {
	qu.Catch()
	pid := qu.ObjToString(f.GetString("pid"))
	tid := qu.ObjToString(f.GetString("tid"))
	sourceinfo := qu.ObjToString(f.GetString("s_sourceinfo"))
	if f.Method() == "POST" {
		//user := f.GetSession("user").(map[string]interface{})
		start, _ := f.GetInteger("start")
		limit, _ := f.GetInteger("length")
		draw, _ := f.GetInteger("draw")
		searchStr := f.GetString("search[value]")
		search := strings.TrimSpace(searchStr)
		query := map[string]interface{}{"s_usertaskid": tid}
		ckdata, err := f.GetInteger("i_ckdata")
		if err != nil {
			ckdata = -1
		}
		if ckdata == 0 {
			query["b_istag"] = false
		} else if ckdata == 1 {
			query["b_istag"] = true
		}
		if search != "" {
			query["$or"] = []interface{}{
				bson.M{"v_baseinfo.title": bson.M{"$regex": search}},
			}
		}
		qu.Debug(query)
		field := map[string]interface{}{"v_baseinfo.title": 1, "b_istag": 1, "i_ckdata": 1}
		info, _ := util.Mgo.Find(sourceinfo, query, `{"_id": 1}`, field, false, start, limit)
		count := util.Mgo.Count(sourceinfo, query)
		qu.Debug(query, sourceinfo, count)
		f.ServeJson(map[string]interface{}{
			"draw":            draw,
			"data":            *info,
			"recordsFiltered": count,
			"recordsTotal":    count,
		})
	} else {
		f.T["pid"] = pid
		f.T["tid"] = tid
		f.T["s_sourceinfo"] = sourceinfo
		_ = f.Render("project/remark_list.html", &f.T)
	}
}

func (f *Front) RemarkDetail() {
	pid := f.GetString("pid")
	tid := f.GetString("tid")
	did := f.GetString("did")
	coll := f.GetString("s_sourceinfo")
	project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, `{"v_fields": 1}`)
	if len(*project) > 0 {
		field := make(map[string]bool)
		vf := (*project)["v_fields"].(map[string]interface{})
		for k := range vf {
			field[k] = true
		}
		f.T["fields"] = field
	}
	qu.Debug(pid, did, coll)
	rep := getDetail(did, coll)         //获取本条公告的信息
	f.T["otherInfo"] = rep["otherInfo"] //展示关联公告信息
	f.T["moreInfo"] = rep["moreInfo"]   //更多关联公告信息
	f.T["pid"] = pid
	f.T["tid"] = tid
	f.T["did"] = did
	f.T["coll"] = coll
	f.T["info"] = rep["info"]
	f.T["common"] = rep["common"]
	f.T["worder"] = rep["worder"]
	f.T["packs"] = rep["packs"]
	f.T["packskey"] = rep["packskey"]
	f.T["ck_pclistag"] = rep["purchasingTag"]
	f.T["timeplace"] = rep["timeplace"]
	f.T["purchasinglist"] = rep["purchasinglist"]
	f.T["other"] = rep["other"]
	f.T["PurchasinglistField"] = util.PurchasinglistField
	f.T["WinnerorderField"] = util.WinnerorderField
	f.T["PackageField"] = util.PackageField
	f.T["topsubtype"] = util.TopSubStypeArr2
	f.T["ck_purchasinglist"] = rep["ck_purchasinglist"]
	f.T["ck_package"] = rep["ck_package"]
	f.T["ck_winnerorder"] = rep["ck_winnerorder"]
	f.T["worder_new"] = rep["worder_new"]
	f.T["pcl_new"] = rep["pcl_new"]
	f.T["pkg_new"] = rep["pkg_new"]
	f.T["nextid"] = GetNextDataId(did, coll, tid) //下一条id
	_ = f.Render("project/remark_detail.html", &f.T)
}

func getDetail(id, coll string) map[string]interface{} {
	rep := map[string]interface{}{}
	infoTmp, _ := util.Mgo.FindById(coll, id, ``)
	baseInfo := (*infoTmp)["v_baseinfo"].(map[string]interface{}) //字段值
	var bzInfo map[string]interface{}                             //标注信息
	if (*infoTmp)["v_taginfo"] != nil {
		bzInfo = (*infoTmp)["v_taginfo"].(map[string]interface{})
	} else {
		bzInfo = make(map[string]interface{})
	}
	baseInfo["detail"] = qu.ObjToString(baseInfo["title"]) + "</br>" + qu.ObjToString(baseInfo["detail"])
	baseInfo["_id"] = mgo.BsonIdToSId(baseInfo["_id"])
	purchasingTag, _ := baseInfo["purchasinglist_alltag"].(bool)
	rep["purchasingTag"] = purchasingTag
	href := qu.ObjToString(baseInfo["href"])
	if !strings.HasPrefix(href, "http") {
		baseInfo["href"] = "https://" + href
	}
	rep["info"] = baseInfo
	common, timeplace, other := setExtComMap(baseInfo, bzInfo) //拼装抽取common值
	rep["common"] = common
	rep["timeplace"] = timeplace
	rep["other"] = other
	packs, packskey, pkg_new := setPaceMap(baseInfo) //拼装子包信息
	rep["packs"] = packs
	rep["packskey"] = packskey
	rep["pkg_new"] = pkg_new
	purchasinglist, isNewStatus := setPurchasingMap(baseInfo) //标的物
	rep["purchasinglist"] = purchasinglist
	rep["pcl_new"] = isNewStatus
	worder, worder_new := setWorderMap(baseInfo) //中标候选人
	rep["worder"] = worder
	rep["worder_new"] = worder_new
	otherInfo, moreInfo := setOtherInfo(baseInfo) //处理公告关联信息
	rep["otherInfo"] = otherInfo
	rep["moreInfo"] = moreInfo
	//
	if bzInfo["purchasinglist"] != nil {
		rep["ck_purchasinglist"] = "1"
	} else {
		rep["ck_purchasinglist"] = "-1"
	}
	if bzInfo["package"] != nil {
		rep["ck_package"] = "1"
	} else {
		rep["ck_package"] = "-1"
	}
	if bzInfo["winnerorder"] != nil {
		rep["ck_winnerorder"] = "1"
	} else {
		rep["ck_winnerorder"] = "-1"
	}
	return rep
}

//拼装抽取common值
func setExtComMap(info, bzInfo map[string]interface{}) ([]interface{}, []interface{}, []interface{}) {
	//基本参数
	common, _ := util.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 {
				if cp["key"] == "subtype" {
					if info["toptype"] != nil && info["subtype"] != nil {
						cp["value"] = qu.ObjToString(info["toptype"]) + "-" + qu.ObjToString(info[fmt.Sprint(cp["key"])])
					} else {
						cp["value"] = ""
					}
				} else {
					cp["value"] = info[fmt.Sprint(cp["key"])]
				}
			}
			if bzInfo[fmt.Sprint(cp["key"])] == nil {
				cp["status"] = "-1"
			} else {
				cp["status"] = "1"
			}
			common[k] = cp
		}
	}
	//时间地点信息
	timeplace, _ := util.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 bzInfo[fmt.Sprint(tp["key"])] == nil {
				tp["status"] = "-1"
			} else {
				tp["status"] = "1"
			}
			timeplace[k] = tp
		}
	}
	//other信息
	other, _ := util.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 bzInfo[fmt.Sprint(cp["key"])] == nil {
				cp["status"] = "-1"
			} else {
				cp["status"] = "1"
			}
			other[k] = cp
		}
	}
	return common, timeplace, other
}

//拼装子包信息
func setPaceMap(info map[string]interface{}) ([]map[string]interface{}, []string, []bool) {
	var confpack []interface{}
	confpack, _ = util.BiaoZhu["package"].([]interface{})
	//bzpack := bzInfo["package"].(map[string]interface{})
	packs := map[string]map[string]interface{}{}
	var 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["isnew"].(bool)
				isNew := false
				status := "-1"
				if tmppack["package_son"] != nil {
					status = "1"
				}
				isNewPkg[k] = isNew
				sortpackskey = append(sortpackskey, k)
				var pack []interface{}
				for _, cpack := range confpack {
					cpack, _ := cpack.(map[string]interface{})
					key := qu.ObjToString(cpack["key"])
					if key == "winner" || key == "bidamount" { //中标单位和中标金额winner_all特殊处理
						continue
					}
					tp := map[string]interface{}{
						"key":      key,
						"descript": cpack["descript"],
					}
					if tmppack[fmt.Sprint(tp["key"])] != nil {
						tp["value"] = tmppack[qu.ObjToString(tp["key"])]
					} else {
						tp["value"] = ""
					}
					tp["status"] = status
					pack = append(pack, tp)
				}
				//特殊处理中标单位和中标金额
				winnerall := []interface{}{}
				if tmpWinnerAll, ok := tmppack["winner_all"].([]interface{}); ok && len(tmpWinnerAll) > 0 {
					for _, tmp := range tmpWinnerAll {
						tmpMap := tmp.(map[string]interface{})
						win := map[string]interface{}{
							"descript": "标段（包）中标单位",
							"key":      "winner",
							"status":   status,
							"value":    qu.ObjToString(tmpMap["winner"]),
						}
						winnerall = append(winnerall, win)
						var bidamount interface{}
						if tmpMap["bidamount"] == nil {
							bidamount = ""
						} else {
							bidamount = strconv.FormatFloat(qu.Float64All(tmpMap["bidamount"]), 'f', -1, 64)
						}
						bid := map[string]interface{}{
							"descript": "标段（包）中标金额",
							"key":      "bidamount",
							"status":   status,
							"value":    bidamount,
						}
						winnerall = append(winnerall, bid)
					}
				} else {
					winnerall = append(winnerall, map[string]interface{}{
						"descript": "标段（包）中标单位",
						"key":      "winner",
						"status":   "-1",
						"value":    "",
					})
					winnerall = append(winnerall, map[string]interface{}{
						"descript": "标段（包）中标金额",
						"key":      "bidamount",
						"status":   "-1",
						"value":    "",
					})
				}
				packs[k] = map[string]interface{}{
					"pack":       pack,
					"packstatus": status,
					"winnerall":  winnerall,
				}
			}
		}
	}
	sort.Strings(sortpackskey)
	var packages []map[string]interface{}
	var isNewPkgArr []bool
	for _, v := range sortpackskey {
		packages = append(packages, packs[v])
		isNewPkgArr = append(isNewPkgArr, isNewPkg[v])
	}
	return packages, sortpackskey, isNewPkgArr
}

//拼装标的物
func setPurchasingMap(info map[string]interface{}) ([]interface{}, []map[string]interface{}) {
	purchasinglist, _ := util.BiaoZhu["purchasinglist"].([]interface{})
	var purchasinglists []interface{}
	//isNewPcl := []bool{} //记录子包是否是新增的
	var isNewAndStatus []map[string]interface{}
	if tmpcls, ok := info["purchasinglist"].([]interface{}); ok {
		for _, v := range tmpcls {
			if pcl, ok := v.(map[string]interface{}); ok {
				//isNew, _ := pcl["isnew"].(bool)
				isNew := false
				status := "-1"
				if pcl["purchasinglist_son"] != nil {
					status = "1"
				}
				//isNewPcl = append(isNewPcl, isNew)
				isNewAndStatus = append(isNewAndStatus, map[string]interface{}{"isnew": isNew, "status": status})
				var 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,
						"status":   status,
					}
					// 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, isNewAndStatus
}

//拼装中标候选人
func setWorderMap(info map[string]interface{}) ([]interface{}, []map[string]interface{}) {
	//基本参数--中标候选人
	winnerorder, _ := util.BiaoZhu["winnerorder"].([]interface{})
	worders := []interface{}{}
	isNewAndStatus := []map[string]interface{}{}
	if tmpwds, ok := info["winnerorder"].([]interface{}); ok {
		for _, v := range tmpwds {
			if wd, ok := v.(map[string]interface{}); ok {
				//isNew, _ := wd["isnew"].(bool)
				isNew := false
				status := "-1"
				if wd["winnerorder_son"] != nil {
					status = "1"
				}
				isNewAndStatus = append(isNewAndStatus, map[string]interface{}{"isnew": isNew, "status": status})
				wds := []interface{}{}
				for _, cp := range winnerorder {
					cp, _ := cp.(map[string]interface{})
					value := wd[qu.ObjToString(cp["key"])]
					if value == nil {
						value = ""
					}
					tp := map[string]interface{}{
						"key":      cp["key"],
						"descript": cp["descript"],
						"value":    value,
						"status":   status,
					}
					wds = append(wds, tp)
				}
				worders = append(worders, wds)
			}
		}
	}
	return worders, isNewAndStatus
}

//获取公告关联信息
func setOtherInfo(info map[string]interface{}) (result, moreArr []map[string]interface{}) {
	if otherInfo, ok := info["info"].([]interface{}); ok && len(otherInfo) > 0 {
		//中标，成交、合同、招标(不含变更)
		/*
			[
				{},
				{},
			]
		*/
		zbArr := []map[string]interface{}{}
		cjArr := []map[string]interface{}{}
		htArr := []map[string]interface{}{}
		zbbArr := []map[string]interface{}{}
		for _, tmp := range otherInfo {
			tmpInfo := tmp.(map[string]interface{})
			tmpInfo["detail"] = qu.ObjToString(tmpInfo["title"]) + "</br>" + qu.ObjToString(tmpInfo["title"])
			toptype := tmpInfo["toptype"]
			subtype := tmpInfo["subtype"]
			ptime := ""
			tmpPtime := qu.Int64All(tmpInfo["publishtime"])
			if tmpPtime > 0 {
				ptime = qu.FormatDateByInt64(&tmpPtime, qu.Date_Full_Layout)
			}
			tmpInfo["publishtime_str"] = ptime
			if subtype == "中标" {
				zbArr = append(zbArr, tmpInfo)
			} else if subtype == "成交" {
				cjArr = append(cjArr, tmpInfo)
			} else if subtype == "合同" {
				htArr = append(htArr, tmpInfo)
			} else if toptype == "招标" && subtype != "变更" {
				zbbArr = append(zbbArr, tmpInfo)
			} else { //标注页不展示的信息，更多中展示
				moreArr = append(moreArr, map[string]interface{}{
					"publishtime": tmpInfo["publishtime_str"],
					"subtype":     subtype,
					"title":       tmpInfo["title"],
					"href":        util.GetJyHref(qu.ObjToString(tmpInfo["id"])),
				})
			}
		}
		publishtime := qu.Float64All(info["publishtime"])
		//中标信息
		if zbLen := len(zbArr); zbLen > 0 {
			rzb := DealData(zbLen, publishtime, zbArr, &moreArr)
			result = append(result, rzb)
		}
		//成交
		if cjLen := len(cjArr); cjLen > 0 {
			rcj := DealData(cjLen, publishtime, cjArr, &moreArr)
			result = append(result, rcj)
		}
		//合同
		if htLen := len(htArr); htLen > 0 {
			rht := DealData(htLen, publishtime, htArr, &moreArr)
			result = append(result, rht)
		}
		result = append(result, zbbArr...)
	}
	return
}

func DealData(tmpLen int, publishtime float64, tmp []map[string]interface{}, moreArr *[]map[string]interface{}) (resultTmp map[string]interface{}) {
	if tmpLen == 1 || publishtime <= 0 { //相同类型只有一条或者原公告发布时间异常取第一条公告
		resultTmp = tmp[0]
		for _, t := range tmp[1:] { //将过滤掉的数据加入到更多中
			*moreArr = append(*moreArr, map[string]interface{}{
				"publishtime": t["publishtime_str"],
				"subtype":     t["subtype"],
				"title":       t["title"],
				"href":        util.GetJyHref(qu.ObjToString(t["id"])),
			})
		}
		return
	} else {
		diff := float64(0) //记录差值
		index := 0
		for i, zb := range tmp {
			pTmp := qu.Float64All(zb["publishtime"])
			diffTmp := math.Abs(publishtime - pTmp) //绝对值
			if i == 0 {
				diff = diffTmp
			} else if diffTmp < diff { //记录较小差值的数据索引位置
				diff = diffTmp
				index = i
			} else { //将过滤掉的数据加入到更多中
				*moreArr = append(*moreArr, map[string]interface{}{
					"publishtime": zb["publishtime_str"],
					"subtype":     zb["subtype"],
					"title":       zb["title"],
					"href":        util.GetJyHref(qu.ObjToString(zb["id"])),
				})
			}
		}
		resultTmp = tmp[index]
	}
	return
}

// GetNextDataId 获取当前数据下一条的id
func GetNextDataId(id, coll, tid string) string {
	nextIdQuery := map[string]interface{}{
		"_id": map[string]interface{}{
			"$gt": mgo.StringTOBsonId(id),
		},
	}
	if tid != "" {
		nextIdQuery["s_usertaskid"] = tid
	}
	one, _ := util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
	if len(*one) == 1 && len((*one)[0]) > 0 {
		return mgo.BsonIdToSId((*one)[0]["_id"])
	} else {
		delete(nextIdQuery, "_id")
		one, _ = util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
		if len(*one) == 1 && len((*one)[0]) > 0 {
			return mgo.BsonIdToSId((*one)[0]["_id"])
		}
	}
	return id
}

// GetNextDataId1 质检下一条
func GetNextDataId1(id, coll, tid string) string {
	nextIdQuery := map[string]interface{}{
		"_id": map[string]interface{}{
			"$gt": mgo.StringTOBsonId(id),
		},
	}
	if tid != "" {
		// 数据有任务 查询带上标注标记
		nextIdQuery["i_ckdata"] = 2
		nextIdQuery["s_usertaskid"] = tid
	} else {
		nextIdQuery["i_ckdata"] = 2
	}
	qu.Debug(nextIdQuery, coll)
	one, _ := util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
	if len(*one) == 1 && len((*one)[0]) > 0 {
		return mgo.BsonIdToSId((*one)[0]["_id"])
	} else {
		delete(nextIdQuery, "_id")
		one, _ = util.Mgo.Find(coll, nextIdQuery, `{"_id":1}`, `{"_id":1}`, true, 0, 1)
		if len(*one) == 1 && len((*one)[0]) > 0 {
			return mgo.BsonIdToSId((*one)[0]["_id"])
		}
	}
	return id
}

func (f *Front) CheckList() {
	qu.Catch()
	if f.Method() == "POST" {
		user := f.GetSession("user").(map[string]interface{})
		iRole := qu.ObjToString(user["i_role"])
		gid := qu.ObjToString(user["s_groupid"])
		start, _ := f.GetInteger("start")
		limit, _ := f.GetInteger("length")
		draw, _ := f.GetInteger("draw")
		status := f.GetString("s_status")
		searchStr := f.GetString("search[value]")
		search := strings.TrimSpace(searchStr)
		query := map[string]interface{}{
			"s_stype": "user",
		}
		if iRole != "0" {
			query["s_groupid"] = gid
		}
		if status != "-1" { //任务状态
			query["s_status"] = status
		}
		if search != "" {
			query["$or"] = []interface{}{
				map[string]interface{}{"s_projectname": map[string]interface{}{"$regex": search}},
			}
		}
		qu.Debug("Query：", query)
		count := util.Mgo.Count(util.TASKCOLLNAME, query)
		list, _ := util.Mgo.Find(util.TASKCOLLNAME, query, map[string]interface{}{"_id": -1}, nil, false, start, limit)
		for _, l := range *list {
			if status := qu.ObjToString(l["s_status"]); status == "进行中" { //更新任务进度
				giveNum := qu.IntAll(l["i_givenum"])
				sourceinfo := qu.ObjToString(l["s_sourceinfo"])
				tagNum := util.Mgo.Count(sourceinfo, map[string]interface{}{"s_usertaskid": mgo.BsonIdToSId(l["_id"]), "b_istag": true})
				progressFloat := float64(tagNum) / float64(giveNum)
				value, _ := strconv.ParseFloat(fmt.Sprintf("%.4f", progressFloat), 64)
				progress := fmt.Sprint(value*100) + "%"
				l["s_progress"] = progress
			}
		}
		f.ServeJson(map[string]interface{}{"draw": draw, "data": *list, "recordsFiltered": count, "recordsTotal": count})
	} else {
		_ = f.Render("project/check_task_list.html")
	}
}

func (f *Front) CheckData() {
	qu.Catch()
	pid := f.GetString("pid")
	tid := f.GetString("tid")
	stype := f.GetString("stype")
	sourceinfo := f.GetString("s_sourceinfo")
	datatype, _ := f.GetInteger("datatype")
	if f.Method() == "POST" {
		start, _ := f.GetInteger("start")
		limit, _ := f.GetInteger("length")
		draw, _ := f.GetInteger("draw")
		searchStr := f.GetString("search[value]")
		search := strings.TrimSpace(searchStr)
		query := make(map[string]interface{})
		if tid != "" {
			// 任务数据质检
			if stype == "group" {
				query["s_grouptaskid"] = tid
			} else {
				query["s_usertaskid"] = tid
			}
			query["b_istag"] = true
		} else {
			if stype == "notag" {
				if datatype == 1 {
					// 待分发数据
					query["b_isgivegroup"] = false
					query["b_istagging"] = false
				} else {
					// 标注数据
					query["i_ckdata"] = 2
					query["b_isgivegroup"] = false
				}
			} else if stype == "tag" {
				query["b_istagging"] = true //未达标
				query["i_ckdata"] = 2
			} else {
				query["i_ckdata"] = 2
			}
		}
		ckdata, err := f.GetInteger("i_ckdata")
		if err != nil {
			ckdata = -1
		}
		if ckdata == 0 {
			query["b_istag"] = false
		} else if ckdata == 1 {
			query["b_istag"] = true
		}
		if search != "" {
			query["$or"] = []interface{}{
				map[string]interface{}{"v_baseinfo.title": map[string]interface{}{"$regex": search}},
			}
		}
		qu.Debug("Query：", query)
		fields := map[string]interface{}{"v_baseinfo.title": 1, "b_check": 1, "i_ckdata": 1, "s_login": 1}
		info, _ := util.Mgo.Find(sourceinfo, query, `{"_id": 1}`, fields, false, start, limit)
		count := util.Mgo.Count(sourceinfo, query)
		qu.Debug(query, sourceinfo, count)
		f.ServeJson(map[string]interface{}{
			"draw":            draw,
			"data":            *info,
			"recordsFiltered": count,
			"recordsTotal":    count,
		})
	} else {
		if tid == "" {
			//project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, map[string]interface{}{"i_importnum": 1})
			//f.T["taskNum"] = (*project)["i_importnum"]
			query1 := make(map[string]interface{})
			if stype == "all" {
				query1["i_ckdata"] = 2
			} else if stype == "notag" {
				if datatype == 1 {
					// 待分发数据
					query1["b_isgivegroup"] = false
					query1["b_istagging"] = false
				} else {
					// 标注数据
					query1["i_ckdata"] = 2
					query1["b_isgivegroup"] = false
				}
			} else if stype == "tag" {
				query1["b_istagging"] = true //未达标
				query1["i_ckdata"] = 2
			} else {
				query1["i_ckdata"] = 2
			}
			qu.Debug(sourceinfo, query1)
			f.T["taskNum"] = util.Mgo.Count(sourceinfo, query1)
			query1["b_check"] = true // 已质检
			checkCount := util.Mgo.Count(sourceinfo, query1)
			f.T["taskTagNum"] = 0
			f.T["taskCheckNum"] = checkCount
		} else {
			task, _ := util.Mgo.FindById(util.TASKCOLLNAME, tid, map[string]interface{}{"i_givenum": 1})
			f.T["taskNum"] = (*task)["i_givenum"]
			tagCount, checkCount := 0, 0
			if stype == "group" {
				tagCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_istag": true})
				checkCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_check": true})
			} else {
				tagCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_usertaskid": tid, "b_istag": true})
				checkCount = util.Mgo.Count(sourceinfo, map[string]interface{}{"s_usertaskid": tid, "b_check": true})
			}
			f.T["taskTagNum"] = tagCount
			f.T["taskCheckNum"] = checkCount
		}
		f.T["pid"] = pid
		f.T["tid"] = tid
		f.T["sourceinfo"] = sourceinfo
		f.T["stype"] = stype
		f.T["datatype"] = datatype
		_ = f.Render("project/check_data_list.html", &f.T)
	}
}

func (f *Front) CheckDetail() {
	qu.Catch()
	tid := f.GetString("tid")
	pid := f.GetString("pid")
	did := f.GetString("did")
	coll := f.GetString("s_sourceinfo")
	project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, `{"v_fields": 1}`)
	if len(*project) > 0 {
		field := make(map[string]bool)
		vf := (*project)["v_fields"].(map[string]interface{})
		for k := range vf {
			field[k] = true
		}
		f.T["fields"] = field
	}
	qu.Debug(pid, did, coll)
	rep := getDetail(did, coll)         //获取本条公告的信息
	f.T["otherInfo"] = rep["otherInfo"] //展示关联公告信息
	f.T["moreInfo"] = rep["moreInfo"]   //更多关联公告信息
	f.T["pid"] = pid
	f.T["tid"] = tid
	f.T["did"] = did
	f.T["coll"] = coll
	f.T["info"] = rep["info"]
	f.T["common"] = rep["common"]
	f.T["worder"] = rep["worder"]
	f.T["packs"] = rep["packs"]
	f.T["packskey"] = rep["packskey"]
	f.T["ck_pclistag"] = rep["purchasingTag"]
	f.T["timeplace"] = rep["timeplace"]
	f.T["purchasinglist"] = rep["purchasinglist"]
	f.T["other"] = rep["other"]
	f.T["PurchasinglistField"] = util.PurchasinglistField
	f.T["WinnerorderField"] = util.WinnerorderField
	f.T["PackageField"] = util.PackageField
	f.T["topsubtype"] = util.TopSubStypeArr2
	f.T["ck_purchasinglist"] = rep["ck_purchasinglist"]
	f.T["ck_package"] = rep["ck_package"]
	f.T["ck_winnerorder"] = rep["ck_winnerorder"]
	f.T["worder_new"] = rep["worder_new"]
	f.T["pcl_new"] = rep["pcl_new"]
	f.T["pkg_new"] = rep["pkg_new"]
	f.T["nextid"] = GetNextDataId1(did, coll, tid) //下一条id
	_ = f.Render("project/check_detail.html", &f.T)
}

func (f *Front) CheckSave() {
	defer qu.Catch()
	success := false
	msg := ""
	user := f.GetSession("user").(map[string]interface{})
	username := qu.ObjToString(user["s_login"]) //当前登录用户
	userId := qu.ObjToString(user["id"])        //当前登录用户标识
	userRole := qu.ObjToString(user["i_role"])  //当前登录用户权限
	var obj []map[string]interface{}
	infoId := f.GetString("s_infoid")
	sourceInfo := f.GetString("s_sourceinfo")
	pid := f.GetString("pid")
	qu.Debug("Data ID：", infoId)
	project, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, map[string]interface{}{"s_name": 1, "v_fields": 1})
	data := f.GetString("data")
	err := json.Unmarshal([]byte(data), &obj)
	if err != nil {
		qu.Debug("Json Unmarshal Error")
		f.ServeJson(map[string]interface{}{"success": success, "msg": "解析数据失败"})
		return
	}
	tagSet := map[string]interface{}{}    //被标注字段状态
	baseSet := map[string]interface{}{}   //要修改的字段信息
	baseUnset := map[string]interface{}{} //要删除的字段信息
	if len(obj) == 1 {                    //单独保存某个一级
		content, ok := obj[0]["content"].([]interface{})
		if !ok || len(content) == 0 {
			f.ServeJson(map[string]interface{}{"success": success, "msg": "解析数据失败"})
			return
		}
		title := qu.ObjToString(obj[0]["title"])
		istag, _ := obj[0]["checkAllTag"].(bool)
		status := qu.IntAll(obj[0]["status"])
		switch title {
		case "基本字段":
			MarkBase(content, tagSet, baseSet, baseUnset)
		case "时间地点":
			MarkTimePlace(content, tagSet, baseSet, baseUnset)
		case "标的信息":
			MarkPurchasinglist(content, tagSet, baseSet, baseUnset, istag, status)
		case "多包信息":
			MarkPackage(content, tagSet, baseSet, baseUnset, status)
		case "中标候选人信息":
			MarkWonderorder(content, tagSet, baseSet, baseUnset, status)
		case "其余信息":
			MarkOther(content, tagSet, baseSet, baseUnset)
		}
	} else {
		for j, val := range obj {
			content, ok := val["content"].([]interface{})
			status := qu.IntAll(val["status"])
			if !ok {
				qu.Debug("Content Error")
				continue
			}
			istag, _ := val["checkAllTag"].(bool)
			if j == 0 { //基本信息
				MarkBase(content, tagSet, baseSet, baseUnset)
			} else if j == 1 { //时间地点
				MarkTimePlace(content, tagSet, baseSet, baseUnset)
			} else if j == 2 { //标的物
				MarkPurchasinglist(content, tagSet, baseSet, baseUnset, istag, status)
			} else if j == 3 { //多包
				MarkPackage(content, tagSet, baseSet, baseUnset, status)
			} else if j == 4 { //候选人
				MarkWonderorder(content, tagSet, baseSet, baseUnset, status)
			} else { //其余信息
				MarkOther(content, tagSet, baseSet, baseUnset)
			}
		}
	}
	dataInfo, _ := util.Mgo.FindById(sourceInfo, infoId, map[string]interface{}{"v_baseinfo": 1, "v_taginfo": 1}) //查询标注保存前的原始信息
	tagInfo, _ := (*dataInfo)["v_taginfo"].(map[string]interface{})
	baseInfo, _ := (*dataInfo)["v_baseinfo"].(map[string]interface{})
	if tagInfo != nil && len(tagInfo) > 0 {
		for field, tmpStatus := range tagSet { //比对本次标注信息和历史标注信息
			status := qu.IntAll(tmpStatus)            //此次被标注字段的状态
			markedStatus := qu.IntAll(tagInfo[field]) //历史标注状态
			if status == 1 && markedStatus != 0 {     //此次标注结果为正确，且有历史标注记录，不做修改
				qu.Debug("已标注字段field---", field)
				//delete(tagSet, field)
				delete(baseSet, field)
				//continue
			}
		}
	}

	allTagFields := map[string]interface{}{} //记录此此标注所有标注信息，用于日志记录
	for k, _ := range tagSet {
		allTagFields[k] = true
	}
	for k, v := range baseSet {
		allTagFields[k] = v
	}
	for k, _ := range baseUnset {
		allTagFields[k] = nil
	}
	qu.Debug("allTagFields===", allTagFields)
	qu.Debug("tagSet===", tagSet)

	// 质检时，标注标记变成质检标记
	checkFields, _ := (*project)["v_fields"].(map[string]interface{})
	checkSet := make(map[string]interface{})
	for k := range checkFields {
		checkSet[k] = tagSet[k]
	}

	if len(checkSet) > 0 || baseInfo["purchasinglist_alltag"] != nil { //purchasinglist_alltag特殊处理
		//1、更新数据源信息
		setResult := map[string]interface{}{ //更新字段集
			"i_updatetime":  time.Now().Unix(),
			"b_check":       true,
			"s_checkid":     userId,
			"b_istag":       true,
			"b_isgivegroup": true,
			"b_isgiveuser":  true,
			"s_userid":      userId,
		}
		for field, val := range checkSet { //更新质检字段
			setResult["v_taginfo."+field] = val
		}
		setResult["v_checkinfo"] = checkSet
		for field, val := range baseSet { //更新基本字段
			setResult["v_baseinfo."+field] = val
		}
		baseUnsetResult := map[string]interface{}{} //删除字段集
		for field, _ := range baseUnset {           //删除基本字段
			baseUnsetResult["v_baseinfo."+field] = ""
		}
		set := map[string]interface{}{
			"$set": setResult,
		}
		if len(baseUnsetResult) > 0 {
			set["$unset"] = baseUnsetResult
		}
		qu.Debug("set---", set)
		success = util.Mgo.UpdateById(sourceInfo, infoId, set)
		//2、更新marked表
		tmp, _ := util.Mgo.FindById(sourceInfo, infoId, map[string]interface{}{"v_baseinfo": 1, "v_taginfo": 1, "i_ckdata": 1})
		qu.Debug("infoId:", infoId)
		delete(*tmp, "_id")
		(*tmp)["updatetime"] = time.Now().Unix()
		b := util.Mgo.Update(util.AllToColl, map[string]interface{}{"_id": mgo.StringTOBsonId(infoId)}, map[string]interface{}{"$set": tmp}, true, false)
		qu.Debug("Update Marked：", b)
	}
	//3、保存标注日志
	b := SaveLog(infoId, "", username, userId, userRole, qu.ObjToString((*project)["s_name"]), "质检", baseInfo, allTagFields)
	qu.Debug("Save Log：", b)
	f.ServeJson(map[string]interface{}{"success": success, "msg": msg})
}

func (f *Front) CheckResult() {
	qu.Catch()
	pid := f.GetString("pid")
	tid := f.GetString("tid")
	sourceinfo := f.GetString("s_sourceinfo")
	stype := f.GetString("stype")
	datatype, _ := f.GetInteger("datatype")
	task, _ := util.Mgo.FindById(util.TASKCOLLNAME, tid, map[string]interface{}{"i_givenum": 1})
	projcet, _ := util.Mgo.FindById(util.PROJECTCOLLNAME, pid, map[string]interface{}{"v_fields": 1})
	//tagCount := util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_istag": true})
	//checkCount := util.Mgo.Count(sourceinfo, map[string]interface{}{"s_grouptaskid": tid, "b_check": true})
	allNum := (*task)["i_givenum"]          //任务数据量
	markNum, checkNum, checkNumR := 0, 0, 0 // 标注数量，	审核数据量，	审核数据完全正确的数据量
	cmaps := make(map[string]int)           // 标注字段整体准确率
	umaps := make(map[string]interface{})   // 按人员 字段准确率
	for k := range (*projcet)["v_fields"].(map[string]interface{}) {
		cmaps[k] = 0
	}
	sess := util.Mgo.GetMgoConn()
	defer util.Mgo.DestoryMongoConn(sess)
	query := make(map[string]interface{})
	if tid == "" {
		query1 := make(map[string]interface{})
		if stype == "all" {
			query1["i_ckdata"] = 2
		} else if stype == "notag" {
			if datatype == 1 {
				// 待分发数据
				query1["b_isgivegroup"] = false
				query1["b_istagging"] = false
			} else {
				// 标注数据
				query1["i_ckdata"] = 2
				query1["b_isgivegroup"] = false
			}
		} else if stype == "tag" {
			query1["b_istagging"] = true //未达标
			query1["i_ckdata"] = 2
		}
		f.T["taskNum"] = util.Mgo.Count(sourceinfo, query1)
	} else {
		if stype == "group" {
			query["s_grouptaskid"] = tid
		} else {
			query["s_usertaskid"] = tid
		}
	}
	query["b_check"] = true
	qu.Debug(query)
	checkNum = util.Mgo.Count(sourceinfo, query)
	result := sess.DB(util.Mgo.DbName).C(sourceinfo).Find(query).Iter()
	if checkNum == 0 {
		f.ServeJson(map[string]interface{}{"rep": false, "msg": "无质检审核数据！"})
		return
	}
	for tmp := make(map[string]interface{}); result.Next(&tmp); markNum++ {
		user := qu.ObjToString(tmp["s_login"])
		var up map[string]int
		if umaps[user] == nil {
			up = make(map[string]int)
		} else {
			up = umaps[user].(map[string]int)
		}
		up["ck_count"] += 1
		umaps[user] = up
		if tmp["b_check"].(bool) {
			if f, ok := tmp["v_checkinfo"].(map[string]interface{}); ok {
				flag := true // 数据整体准确率
				// 按人员统计字段准备率
				var up map[string]int
				if umaps[user] == nil {
					up = make(map[string]int)
				} else {
					up = umaps[user].(map[string]int)
				}
				for k1 := range cmaps {
					if qu.IntAll(f[k1]) == 1 {
						cmaps[k1] += 1 // 字段整体正确率
						up[k1] += 1
					} else {
						flag = false
					}
				}
				up["re_count"] += 1
				umaps[user] = up
				if flag {
					checkNumR++
					up["re_rg_count"] += 1
				}
			}
		}
	}

	qu.Debug(cmaps)
	qu.Debug(umaps)
	// 前台页面数据
	dataSource := make(map[string]interface{})
	var userSelect []string
	var dataSelect []map[string]interface{}
	userSelect = append(userSelect, "全部")
	tmp := make(map[string]interface{})
	tmp["name"] = "全部"
	tmp["num1"] = allNum
	tmp["num2"] = checkNum
	tmp["num3"] = checkNumR
	tmp["num4"] = CountPr(checkNumR, checkNum)
	dataSelect = append(dataSelect, tmp)
	for k, v := range (*projcet)["v_fields"].(map[string]interface{}) {
		tmp1 := make(map[string]interface{})
		tmp1["name"] = v
		tmp1["num1"] = markNum
		tmp1["num2"] = checkNum
		tmp1["num3"] = cmaps[k]
		tmp1["num4"] = CountPr(cmaps[k], checkNum)
		dataSelect = append(dataSelect, tmp1)
	}
	dataSource["全部"] = dataSelect
	for k1, v1 := range umaps {
		if v2, o := v1.(map[string]int); o {
			userSelect = append(userSelect, k1)
			var dataSelect1 []map[string]interface{}
			tmp2 := make(map[string]interface{})
			tmp2["name"] = "全部"
			tmp2["num1"] = v2["ck_count"]
			tmp2["num2"] = v2["re_count"]
			tmp2["num3"] = v2["re_rg_count"]
			tmp2["num4"] = CountPr(v2["re_rg_count"], v2["re_count"])
			dataSelect1 = append(dataSelect1, tmp2)
			for k, v := range (*projcet)["v_fields"].(map[string]interface{}) {
				tmp1 := make(map[string]interface{})
				tmp1["name"] = v
				tmp1["num1"] = v2["ck_count"]
				tmp1["num2"] = v2["re_count"]
				tmp1["num3"] = v2[k]
				tmp1["num4"] = CountPr(v2[k], v2["re_count"])
				dataSelect1 = append(dataSelect1, tmp1)
			}
			dataSource[k1] = dataSelect1
		}
	}
	f.T["pid"] = pid
	f.T["tid"] = tid
	f.T["taskNum"] = allNum
	f.T["taskTagNum"] = markNum
	f.T["taskCheckNum"] = checkNum
	f.T["taskCheckRight"] = checkNumR
	f.T["tableData"] = dataSource
	f.T["userSelect"] = userSelect
	_ = f.Render("project/check_result.html", &f.T)
}

// CountPr 计算百分比
func CountPr(c1, c2 int) string {
	decimal.DivisionPrecision = 2
	if c1 == 0 || c2 == 0 {
		return "0"
	}
	d := decimal.NewFromInt32(int32(c1)).Div(decimal.NewFromInt32(int32(c2))).Mul(decimal.NewFromInt32(100))
	return d.String() + "%"
}
