package pretreated

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	u "jy/util"
	qutil "qfw/util"
	"regexp"
	"strings"
	"unicode/utf8"
)

// 在解析时，判断表格元素是否隐藏
func IsHide(g *goquery.Selection) (b bool) {
	style, exists := g.Attr("style")
	if exists {
		b = display.MatchString(style)
	}
	return
}

// 对表格的key进行标准化处理，多个k相同时，出现覆盖问题
// 待扩展，暂不支持正则标签库  清理key
func CommonDataAnaly(k, tabletag, tabledesc string, v interface{}, isSite bool, codeSite string) (kvTags map[string][]*u.Tag, returntag string) {
	kvTags = map[string][]*u.Tag{}
	v1 := ""
	if sv, sok := v.(string); sok { //取KV
		v1 = sv
	} else if sv, sok := v.([]string); sok { //是数组先默认取第一个
		if len(sv) >= 1 {
			v1 = sv[0]
		}
	}
	if k == "本期概算(万元)" {
		//log.Debug("21323")
	}
	//对值单位的处理   (预算|费|价|额|规模|投资)
	if moneyReg.MatchString(k) || strings.Contains(k, "万") {
		v1 += GetMoneyUnit(k, v1)
	}
	//先清理key
	//u.Debug(1, k, v1)
	//指定-key不清理  拦标价(费率或单价等)
	k1 := ""
	if !noClearKeyReg.MatchString(k) {
		k1 = ClearKey(k, 2)
	}
	//u.Debug(2, k)
	//取标准key
	if tabletag == "中标情况" {
		if k1 == "价格" {
			k1 = "中标金额"
		}
	}
	res := u.GetTags(k1, isSite, codeSite)
	if len(res) == 0 && k1 != k {
		res = u.GetTags(k, isSite, codeSite)
		k1 = k
	}
	//log.Println(k, res)
	//	if len(res) == 0 {
	//		go u.AddtoNoMatchMap(tk)
	//	}
	//当取到标准化值时，放入数组
	if len(res) > 0 {
		for _, t1 := range res {
			//降低冒号值的权重-不适合日期格式的数据
			if MhSpilt.MatchString(v1) && !(UnTimeSpiltKey.MatchString(t1.Value) && UnTimeSpiltValue.MatchString(v1)) && t1.Value != "企业信用" {
				t1.Weight -= 50
			}
			if winnerOrderAndBidResult.MatchString(tabletag) && t1.Value == "采购单位联系人" { //处理table中项目负责人
				kvTags[k] = append(kvTags[k], &u.Tag{Key: k, Value: v1, IsInvalid: true})
			} else if regexp.MustCompile("(中标候选人|名单及其排序|排序)").MatchString(tabletag) && t1.Value == "采购单位" {
				kvTags[t1.Value] = append(kvTags[t1.Value], &u.Tag{Key: k1, Value: v1, Weight: t1.Weight - 150})
			} else {
				kvTags[t1.Value] = append(kvTags[t1.Value], &u.Tag{Key: k1, Value: v1, Weight: t1.Weight})
			}
		}
		res[0].IsInvalid = true
		//k1 = res[0].Value
	} /*else {
		kvTags[k] = append(kvTags[k], &u.Tag{Key: k, Value: v1, IsInvalid: true})
		//没有取到标准化key时，对中标金额和中标单位的逻辑处理
		if filter_zbje_k.MatchString(k) && !filter_zbje_kn.MatchString(k) && filter_zbje_v.MatchString(v1) && utf8.RuneCountInString(v1) < 20 {
			if tabletag == "" {
				returntag = "中标情况"
			}
			kvTags["中标金额"] = append(kvTags["中标金额"], &u.Tag{Key: k, Value: v1, Weight: -100, IsInvalid: true})
		} else if filter_zbdw_ky.MatchString(k) && !filter_zbdw_kn.MatchString(k) &&
			filter_zbdw_v.MatchString(v1) {
			kvTags["中标单位"] = append(kvTags["中标单位"], &u.Tag{Key: k, Value: v1, Weight: -100, IsInvalid: true})
			if tabletag == "" {
				returntag = "中标情况"
			}
		} else if !filter_zbje_jd.MatchString(tabletag) && !filter_zbje_jd.MatchString(k) && utf8.RuneCountInString(v1) < 13 {
			//对上一步没有取到标准化key的进一步处理
			if filter_tag_zb.MatchString(tabletag) || filter_tag_zb.MatchString(tabledesc) {
				//u.Debug(v1, k, "-----", filter_zbdw_jd.MatchString(k), filter_zbdw_v.MatchString(v1))
				if filter_zbje_jd.MatchString(k) && !filter_zbje_kn.MatchString(k) && filter_zbje_v.MatchString(v1) {
					if filter_ysje_jd.MatchString(k) {
						kvTags["预算金额"] = append(kvTags["预算金额"], &u.Tag{Key: k, Value: v1, Weight: -100})
					} else if !filter_zbdw_kn.MatchString(k) {
						kvTags["中标金额"] = append(kvTags["中标金额"], &u.Tag{Key: k, Value: v1, Weight: -100})
					}

				}
			}
		}
	}*/
	return
}

// 对解析后的表格的kv进行过滤
func (table *Table) KVFilter(isSite bool, codeSite string) {
	//1.标准化值查找
	//2.对数组的处理
	//3.对分包的处理
	//4.对KV的处理
	//判断表格是否有用，调用abandontable正则数组进行判断
	//遍历每一行
	table.analyTdKV() //1.遍历每行每列td的sortkv添加到table.SorkVK中;2.td有子表格的处理
	as := NewSortMap()

	//中标金额-单位-同时存在-且万元-重构
	isResetUnitAmountSortKV(table)
	//特殊类~总价需要累加
	isResetAmountAggregateSortKV(table)
	//特殊类~单价核算到金额上
	isResetUnitPriceSortKV(table)
	//特殊组-构建一个候选人编号
	isResetWinnerRankingSortKV(table)
	//针对序号组过长
	isReseterialNumberSortKV(table)

	//遍历table.sortkv，进行过滤处理，并放入标准化KV中，如果值是数组跳到下一步处理
	pre_k := ""
	for _, k := range table.SortKV.Keys {
		//遍历所有key sort.kv
		if glRex.MatchString(k) {
			table.Desc += "成交结果,"
		}
		if djReg.MatchString(k) {
			continue
		}
		v := table.SortKV.Map[k]
		if _, ok := v.(string); ok {
			//table.SortKV.Value为字符串，匹配抽取关键词table.SortKV.Key，匹配到添加k,v到table.StandKV,table.StandKVWeight
			k = pkgFilter.ReplaceAllString(k, "")
			k = regSpliteSegment.ReplaceAllString(regReplAllSpace.ReplaceAllString(k, ""), "")

			kvTags, tag := CommonDataAnaly(k, table.Tag, table.Desc, v, isSite, codeSite) //对key标准化处理，没有找到会走中标
			if tag != "" && table.Tag == "" {
				table.Tag = tag
			}
			MergeKvTags(table.StandKV, kvTags)
		} else {
			//同一行表格-相同值的标签 可能含义重复~影响分包抽取~需要过滤
			if k == "最高限价（元）" && pre_k == "项目预算（元）" {
				isE := false
				if v_arr, ok := v.([]string); ok && len(v_arr) > 1 {
					if pre_v_arr, ok := as.Map[pre_k].([]string); ok && len(pre_v_arr) == len(v_arr) && isRepeatArrString(v_arr, pre_v_arr) {
						isE = true
					}
				}
				if !isE {
					as.AddKey(k, v)
				}
			} else {
				as.AddKey(k, v)
			}
		}

		pre_k = k //记录上一个k
	}

	//重置as~特殊金额~构建
	resetAsKeysBidamount(as)

	//处理值是数组的kv   放入标准化kv中 standKV //处理table.SortKV.value为数组的情况
	table.sortKVArr(as, isSite, codeSite)

	if len(table.WinnerOrder) == 0 { //在计算一下是否拼接
		winsArr := []string{}
		sortsArr := []string{}
		for _, k := range table.SortKV.Keys {
			if hxrRex.MatchString(k) {
				v := table.SortKV.Map[k]
				if new_v, ok := v.(string); ok && (findCandidate2.MatchString(new_v) || new_v == "/") {
					winsArr = append(winsArr, new_v)
					sortsArr = append(sortsArr, k)
				}
			}
		}
		if len(winsArr) > 1 {
			as.AddKey("中标候选人名称", winsArr)
			as.AddKey("中标候选人排序", sortsArr)
			table.sortKVArr(as, isSite, codeSite)
		}
	}

	if len(table.WinnerOrder) > 0 || !table.BPackage {
		winnerOrder := []map[string]interface{}{}
		maxSort := 0
		//调整顺序
		for i := 0; i < 2; i++ {
			for _, v := range table.WinnerOrder {
				sortstr, _ := v["sortstr"].(string)
				if (i == 0 && sortstr == "") || (i == 1 && sortstr != "") {
					continue
				}
				sort, _ := v["sort"].(int)
				if i == 0 {
					if maxSort == 0 || sort > maxSort {
						maxSort = sort
					}
				} else {
					maxSort++
					v["sort"] = maxSort
				}
				winnerOrder = append(winnerOrder, v)
			}
			if len(winnerOrder) == len(table.WinnerOrder) {
				break
			}
		}
		table.WinnerOrder = winnerOrder
		if len(table.WinnerOrder) == 0 {
			winnerOrder = []map[string]interface{}{}
			//遍历每个td,查询中标人
			for _, tr := range table.TRs {
				for _, td := range tr.TDs {
					winnerOrder = winnerOrderEntity.Find(td.Val, true, 3, isSite, codeSite)
					if len(winnerOrder) > 0 {
						//中标候选人合并
						winnerOrderEntity.Merge(table.WinnerOrder, winnerOrder)
					}
				}
			}
		}
		if !table.BPackage { //没有table.WinnerOrder也没有分包 将td中的WinnerOrder赋值给table.WinnerOrder
			if len(winnerOrder) > 1 {
				table.WinnerOrder = winnerOrder
			}
		}
	}
	//对中标候选人进行排序
	winnerOrderEntity.Order(table.WinnerOrder)
	//该表格有一个分包，并且有中标候选人排序的情况下，把中标候选人放到包里面
	if table.BlockPackage != nil && table.BlockPackage.Keys != nil && len(table.BlockPackage.Keys) == 1 {
		if table.BlockPackage.Map != nil {
			onePkgKey := table.BlockPackage.Keys[0]
			onePkg, _ := table.BlockPackage.Map[onePkgKey].(*u.BlockPackage)
			if onePkg != nil && (onePkg.WinnerOrder != nil || len(onePkg.WinnerOrder) == 0) {
				onePkg.WinnerOrder = table.WinnerOrder
				table.BlockPackage.AddKey(onePkgKey, onePkg)
			}
		}
	}
}

// 处理table.SortKV.value为数组的情况
func (table *Table) sortKVArr(as *SortMap, isSite bool, codeSite string) {
	winnertag := iswinnertabletag.MatchString(table.Tag) && !nswinnertabletag.MatchString(table.Tag) //table标签
	if !winnertag {
		winnertag = iswinnertabletag.MatchString(table.TableResult.BlockTag) && !nswinnertabletag.MatchString(table.TableResult.BlockTag) //块标签
	}
	if !winnertag {
		winnertag = iswinnertabletag.MatchString(table.Desc)
	}
	if !winnertag {
		winnertag = iswinnertabletag.MatchString(table.Html)
	}
	checkKey := map[int]bool{}
	//tmpBidmout := []string{}
	//log.Println(tmpBidmout)
	for kn, k := range as.Keys { //遍历table.SortKV.value为数组的key
		v := as.Map[k]
		if vm, ok := v.([]map[string]interface{}); ok && k == NullTxtBid {
			if table.WinnerOrder == nil {
				table.WinnerOrder = []map[string]interface{}{}
			}
			table.WinnerOrder = append(table.WinnerOrder, vm...)
		} else {
			//增加候选人排序逻辑
			if (table.WinnerOrder == nil || len(table.WinnerOrder) == 0) && !checkKey[kn] {
				if vs1, ok := v.([]string); ok {
					smap := make([]map[string]interface{}, len(vs1))
					for n1, _ := range vs1 {
						smap[n1] = map[string]interface{}{}
					}
					//hadSort := false
					tmpEntname := make([]string, len(vs1))
					tmpPrice := make([]string, len(vs1))
					for kn1, k := range as.Keys[kn:] {
						v := as.Map[k]
						if ContactType["采购单位"].MatchString(k) || ContactType["代理机构"].MatchString(k) {
							kvTags, _ := CommonDataAnaly(k, table.Tag, table.Desc, v, isSite, codeSite) //对key标准化处理，没有找到会走中标
							for k := range kvTags {
								if table.StandKV[k] == nil {
									MergeKvTags(table.StandKV, kvTags)
								}
							}
							continue
						}
						//目前对数组数据的key做判断，但是某些额可以是不满足情况的
						//载明内容:[第一中标候选人 第二中标候选人] id：5d00587da5cb26b9b75e367b
						if vs, ok := v.([]string); ok && len(vs) == len(vs1) { //数组值的个数相同
							res, _, _, _, repl := CheckCommon(k, "bidorder")
							kv := ""
							if !res {
								kt := u.GetTags(k, isSite, codeSite)
								if kt.Len() > 0 {
									if kt[0].Value == "单品报价" && winnertag {
										kv = "中标金额"
									} else {
										for _, v_kt := range kt {
											if v_kt.Value == "中标金额" {
												kv = "中标金额"
												break
											}
										}
										if kv == "" {
											kv = kt[0].Value
										}
									}
								}
							}
							if !res && kv == "" { //key未验证出，验证数组的val值
								checkKey[kn+kn1] = true
								if winnertag { //如果是中标信息 在根据val数组信息解析候选人
									for vsk, vsv := range vs {
										if NullTdReg.MatchString(vsv) { //数据先验证val是否有排序
											//hadSort = true
											smap[vsk]["sortstr"] = vsv
											smap[vsk]["sort"] = GetBidSort(vsv, vsk+1)
										} else if findCandidate2.MatchString(vsv) && tmpEntname[vsk] == "" && !noKeyValReg.MatchString(k) { //数据验证val是否是候选人
											entname, _ := winnerOrderEntity.clear("中标单位", vsv).(string)
											if entname != "" {
												tmpEntname[vsk] = entname
											}
										} else if winMoneyReg.MatchString(k) && !winNoMoneyReg.MatchString(k) && len(tmpPrice[vsk]) == 0 {
											kv = "中标金额"
										} else if k == "金额" && len(tmpPrice[vsk]) == 0 {
											kv = "中标金额"
										} else { //验证val时如果数组中的第一条数据既不满足sort或者entname 判定此数组数据错误
											break
										}
									}
								}
							}
							if res || kv != "" { //连续往下找几个key
								checkKey[kn+kn1] = true
							SORT:
								if repl == "sort" {
									//hadSort = true
									for vsk, vsv := range vs {
										smap[vsk]["sortstr"] = vsv
										smap[vsk]["sort"] = GetBidSort(vsv, vsk+1)
										if findCandidate2.MatchString(vsv) && kv == "中标单位" && tmpEntname[vsk] == "" { //数据验证val是否是候选人
											entname, _ := winnerOrderEntity.clear("中标单位", vsv).(string)
											if entname != "" {
												tmpEntname[vsk] = entname
											}
										}
									}
								} else if repl == "entname" || kv == "中标单位" {
									for vsk, vsv := range vs {
										if winnerReg6.MatchString(vsv) { //k:中标候选人 v:["第一名","第二名"]
											repl = "sort"
											goto SORT
										}
										//if entname, _ := smap[vsk]["entname"].(string); entname != "" || len([]rune(vsv)) < 3 {
										//	break
										//}
										//entname, _ := winnerOrderEntity.clear("中标单位", vsv).(string)
										//if entname != "" {
										//		smap[vsk]["entname"] = entname
										if tmpEntname[vsk] != "" || len([]rune(vsv)) < 4 { //排除 单位：["台","个","套"]
											break
										}
										entname, _ := winnerOrderEntity.clear("中标单位", vsv).(string)
										if entname != "" {
											tmpEntname[vsk] = entname
										}
									}
								} else if kv == "中标金额" {
									for vsk, vsv := range vs {
										//过滤price 2348273.432元(万元)-->2348273.432
										//tmp1, _ := smap[vsk]["price"].(string)
										tmp1 := tmpPrice[vsk]
										p1num := numberReg2.FindString(tmp1)
										p2num := numberReg2.FindString(vsv)
										p1 := qutil.Float64All(p1num)
										p2 := qutil.Float64All(p2num)
										if p2 > p1 {
											//smap[vsk]["price"] = winnerOrderEntity.clear("中标金额", vsv+GetMoneyUnit(k, vsv))
											price := winnerOrderEntity.clear("中标金额", vsv+GetMoneyUnit(k, vsv))
											if pricestr, _ := price.(string); len(pricestr) < 30 && len(pricestr) > 0 {
												tmpPrice[vsk] = pricestr
											}

										}
									}
								} else if kv == "预算" {
									if strings.Contains(k, "万元") {
										for vsk, vsv := range vs {
											if !strings.Contains(vsv, "万元") {
												vs[vsk] = vsv + "万元"
											}
										}
									}
								}
							}
						} else {
							//break
						}
					}
					newSmap := []map[string]interface{}{}
					//qutil.Debug("smap=======", smap)
					//qutil.Debug("tmpEntname--", len(tmpEntname), tmpEntname)
					//qutil.Debug("tmpPrice--", len(tmpPrice), tmpPrice)
					for n, smap_v := range smap {
						//if hadSort { //有排序，再添加entname和price
						if len(tmpEntname) > 0 && n < len(tmpEntname) && tmpEntname[n] != "" {
							smap_v["entname"] = tmpEntname[n]
							if len(tmpPrice) > 0 && n < len(tmpPrice) && tmpPrice[n] != "" {
								smap_v["price"] = tmpPrice[n]
							}
						}
						//} else if len(tmpEntname) > 0 {
						//fmt.Println("table winnerorder only has entname", tmpEntname)
						//}
						//qutil.Debug("len-smap_v--", len(smap_v))
						if len(smap_v) > 2 { //只有排序信息 sort和sortstr
							newSmap = append(newSmap, smap_v)
						}
					}
					if len(newSmap) > 0 {
						table.WinnerOrder = newSmap
					}
				}
			} else if vsss, ok := v.([]string); ok {
				if (len(table.WinnerOrder) > 0 && table.WinnerOrder[0]["price"] == nil && len(vsss) == len(table.WinnerOrder)) ||
					(len(table.WinnerOrder) > 0 && strings.Contains(k, "总报价") && len(vsss) == len(table.WinnerOrder)) {
					kv := ""
					if winMoneyReg.MatchString(k) && !winNoMoneyReg.MatchString(k) {
						kv = "中标金额"
					} else {
						kt := u.GetTags(k, isSite, codeSite)
						if kt.Len() > 0 {
							if kt[0].Value == "单品报价" && winnertag {
								kv = "中标金额"
							} else {
								kv = kt[0].Value
							}
						}
					}
					if kv == "中标金额" {
						for i, vx := range vsss {

							p1num := numberReg2.FindString(vx)
							if strings.Contains(p1num, ",") && strings.Contains(p1num, ".") {
								p1num = strings.ReplaceAll(p1num, ",", "")
							}
							p1 := qutil.Float64All(p1num)
							if p1 > 0 {
								//smap[vsk]["price"] = winnerOrderEntity.clear("中标金额", vsv+GetMoneyUnit(k, vsv))
								price := winnerOrderEntity.clear(kv, vx+GetMoneyUnit(k, vx))
								if pricestr, _ := price.(string); len(pricestr) < 30 && len(pricestr) > 0 && !clearnum.MatchString(pricestr) {
									table.WinnerOrder[i]["price"] = pricestr
								}
							}
						}
					}
				} else if table.StandKV[k] == nil {
					kvTags, _ := CommonDataAnaly(k, table.Tag, table.Desc, v, isSite, codeSite) //对key标准化处理，没有找到会走中标
					MergeKvTags(table.StandKV, kvTags)
				}
			}
		}
	}

	//特殊处理--组合候选人

}

// 1.遍历每行每列td的sortkv添加到table.SorkVK中;2.td有子表格的处理
func (table *Table) analyTdKV() {
	//遍历每一行
	for _, tr := range table.TRs {
		for _, td := range tr.TDs {
			//fmt.Println(td.BH, td.MustBH, td.Val, td.SortKV.Map)
			bc := false
			if !td.BH {
				//表头是否是无用内容
				if td.HeadTd != nil {
					bc, _, _, _, _ = CheckCommon(td.HeadTd.Val, "abandontable")
				}
			}
			if !bc {
				//td元素有内嵌kv,遍历放入table的Kv中
				if len(td.SortKV.Keys) > 0 {
					for _, k3 := range td.SortKV.Keys {
						_val := td.SortKV.Map[k3]
						//thisFlag := false
						if td.HeadTd != nil && len([]rune(k3)) < 4 {
							k3 = td.HeadTd.Val + k3
						}
						if table.SortKV.Map[k3] == nil && _val != nil && _val != "" {
							//u.Debug(k3, _val)
							//if !thisFlag || (thisFlag && table.SortKV.Map[k3] == nil) {
							table.SortKV.AddKey(k3, _val)
						}
					}
				}
			}
			//td有子表格的处理
			//u.Debug(td.BH, td.Val, td.SonTableResult)
			if td.SonTableResult != nil {
				//u.Debug(td.SonTableResult.SortKV.Map, "-------", td.SonTableResult.Tabs)
				for k3, v3 := range td.SonTableResult.KvTags {
					table.StandKV[k3] = append(table.StandKV[k3], v3...)
				}
				//中标候选人排序
				if table.WinnerOrder == nil || len(table.WinnerOrder) == 0 {
					table.WinnerOrder = td.SonTableResult.WinnerOrder
				} else {
					winnerOrderEntity.Merge(table.WinnerOrder, td.SonTableResult.WinnerOrder)
				}
			}
		}
	}
}

// 表格结果合并到父表格集中
func (table *Table) MergerToTableresult() {
	//对多包表格的多包值的合并处理
	if table.BPackage {
		table.TableResult.IsMultiPackage = true
		for _, v2 := range table.BlockPackage.Keys {
			package1 := table.TableResult.PackageMap.Map[v2]
			if package1 == nil {
				table.TableResult.PackageMap.AddKey(v2, table.BlockPackage.Map[v2])
				if vvv, ok := table.BlockPackage.Map[v2].(*u.BlockPackage); ok {
					if vvv.TableKV != nil && len(vvv.TableKV.KvTags) > 0 {
						MergeKvTags(table.TableResult.KvTags, vvv.TableKV.KvTags)
					}
				}
			} else {
				bp := package1.(*u.BlockPackage)
				if bp.TableKV == nil {
					bp.TableKV = u.NewJobKv()
				}
				v1 := table.BlockPackage.Map[v2].(*u.BlockPackage)
				if v1.TableKV != nil && len(v1.TableKV.KvTags) > 0 {
					for k2, v2 := range v1.TableKV.KvTags {
						if k2 == "" {
							continue
						}
						isExists := false
						for _, v2v := range v2 {
							if v2v.Value == "" {
								continue
							}
							for _, v2vv := range bp.TableKV.KvTags[k2] {
								if v2v.Value == v2vv.Value {
									isExists = true
									break
								}
							}
							if !isExists {
								bp.TableKV.KvTags[k2] = append(bp.TableKV.KvTags[k2], v2v)
								bp.Text += fmt.Sprintf("%v:%v\n", k2, v2)
							}
						}
					}
				}
				if bp.Bidamount <= 0 && !bp.IsTrueBidamount {
					bp.Bidamount = v1.Bidamount
					bp.IsTrueBidamount = v1.IsTrueBidamount
				}
				if bp.Budget <= 0 && !bp.IsTrueBudget {
					bp.Budget = v1.Budget
					bp.IsTrueBudget = v1.IsTrueBudget
				}
				//fmt.Println(utf8.RuneCountInString(bp.Text))
				//bp.Text += bp.Text
				if len(v1.WinnerOrder) > 0 && len(bp.WinnerOrder) == 0 {
					bp.WinnerOrder = v1.WinnerOrder
				}
			}
		}
	}
	//遍历标准key到tableresult.sortkv中
	for fieldKey, v := range table.StandKV {
		for _, vv := range v {
			if fieldKey == "项目周期" || fieldKey == "工期单位" || fieldKey == "工期时长" {
				dateStr := dateReg.FindString(vv.Key)
				if dateStr != "" && !strings.Contains(vv.Value, dateStr) {
					vv.Value = vv.Value + dateStr
				}
			}
			vv.Value = strings.Replace(vv.Value, "__", "", -1)
		}
	}
	MergeKvTags(table.TableResult.KvTags, table.StandKV)
	//表格的块标签
	if table.TableResult.BlockTag == "" && table.Tag != "" {
		table.TableResult.BlockTag = table.Tag
	}
	//中标候选人(多个table，现在默认取第一个table的信息，考虑需不需要多个table分析合并数据？)
	if table.TableResult.WinnerOrder == nil || len(table.TableResult.WinnerOrder) == 0 {
		table.TableResult.WinnerOrder = table.WinnerOrder
	}
	//增加brand 并列table
	if len(table.BrandData) > 0 {
		for _, v := range table.BrandData {
			if len(v) > 0 {
				table.TableResult.BrandData = append(table.TableResult.BrandData, v)
			}
		}
	}
	//抽取prince和number 并列table
	if len(table.PriceNumberData) > 0 {
		for _, v := range table.PriceNumberData {
			if len(v) > 0 {
				table.TableResult.PriceNumberData = append(table.TableResult.PriceNumberData, v)
			}
		}
	}
	if table.BlockPackage != nil && len(table.BlockPackage.Keys) == 0 {
		for _, v := range table.BlockPackage.Keys {
			if table.BlockPackage.Map[v] != nil {
				if vvv, ok := table.BlockPackage.Map[v].((*u.BlockPackage)); ok {
					if vvv.TableKV != nil && len(vvv.TableKV.KvTags) > 0 {
						for kk, vv := range vvv.TableKV.KvTags {
							if kk == "" {
								continue
							}
							if len(table.TableResult.KvTags[kk]) == 0 {
								table.TableResult.KvTags[kk] = vv
							}
						}
					}
				}
			}

		}
	}
}

/*
*
解析表格入口
返回：汇总表格对象
*
*/
func AnalyTableV2(tabs *goquery.Selection, toptype, blockTag, con string, itype int, _id interface{}, ruleBlock *u.RuleBlock, isSite bool, codeSite string) (tabres *TableResult) {
	defer qutil.Catch()
	//u.Debug(con)
	if itype == 1 {
		//修复表格
		con = RepairCon(con)
	}
	//生成tableresult对象
	tabres = NewTableResult(_id, toptype, blockTag, con, itype, ruleBlock)
	if fblbReg.MatchString(blockTag) && utf8.RuneCountInString(blockTag) < 200 {
		//log.Debug(fblbReg.FindString(blockTag))
		return
	}
	//可以有多个table
	//for _, table := range tabs {
	//隐藏表格跳过
	if IsHide(tabs) {
		return
	}
	tabres.GoqueryTabs = tabs
	//}
	//解析表格集
	tabres.Analy(isSite, codeSite)
	return
}

// 开始解析表格集
func (ts *TableResult) Analy(isSite bool, codeSite string) {
	tabs := []*Table{}
	contactFormat := &u.ContactFormat{
		IndexMap: map[int]string{},
		MatchMap: map[string]map[string]bool{},
	}
	//for _, table := range ts.GoqueryTabs {
	tn := NewTable(ts.Html, ts, ts.GoqueryTabs)
	//核心模块
	tsw := tn.Analy(contactFormat, isSite, codeSite)
	for _, tab := range tsw {
		if len(tab.TRs) > 0 {
			tabs = append(tabs, tab)
		}
		//fmt.Println("tab.SortKV.Map", tab.SortKV.Keys)
	}
	//tn.SonTables = append(tn.SonTables, tn)
	//}
	//统一合并，考虑统一多表格是多包的情况---新增   与子表格合并
	if len(tabs) > 1 {
		pns := map[string]string{}
		pnarr := []string{}
		for _, table := range tabs {
			if len(table.StandKV["项目名称"]) == 0 {
				continue
			}
			pn := table.StandKV["项目名称"][0]
			if pn != nil && pn.Value != "" && TitleReg.MatchString(pn.Value) {
				pnarr = append(pnarr, pn.Value)
				matchres := TitleReg.FindAllStringSubmatch(pn.Value, -1)
				if len(matchres) == 1 && len(matchres[0]) > 0 {
					v1 := u.PackageNumberConvert(matchres[0][0])
					pns[v1] = matchres[0][0]
					bp := &u.BlockPackage{}
					bp.Index = v1
					bp.Origin = matchres[0][0]
					if bp.TableKV == nil {
						bp.TableKV = u.NewJobKv()
					}
					for _, k := range []string{"中标金额", "中标单位", "预算", "成交状态", "项目名称", "项目编号", "采购范围"} {
						if len(table.StandKV[k]) > 0 {
							bp.TableKV.KvTags[k] = append(bp.TableKV.KvTags[k], &u.Tag{Key: k, Value: table.StandKV[k][0].Value})
						}
					}
					bp.WinnerOrder = table.WinnerOrder
					if table.BlockPackage.Map[v1] == nil {
						table.BPackage = true
						table.BlockPackage.AddKey(v1, bp)
					} else {
						table.BlockPackage.RemoveKey(v1)
						table.BlockPackage.AddKey(v1, bp)
					}
				}
			}
		}
		if len(tabs) == len(pns) {
			//多个表格，每个表格都是一个分包 http://www.cxzwfw.gov.cn/info/1009/6963.htm
			//项目名称、项目编号、采购单位、招标机构、预算
			pname := projectnameReg.ReplaceAllString(pnarr[0], "")
			btrue := true
			for _, pn := range pnarr[1:] {
				pn = projectnameReg.ReplaceAllString(pn, "")
				//u.Debug(pn, pname)
				if pn != pname {
					//项目名称不一致
					btrue = false
					break
				}
			}
			if btrue {
				ts.KvTags["项目名称"] = append(ts.KvTags["项目名称"], &u.Tag{Key: "项目名称", Value: pname, Weight: 100})
				for _, table := range tabs {
					table.BPackage = true
					//预算、中标金额、NullTxtBid成交供应商排名 中标单位 成交状态
					if table.BlockPackage != nil && len(table.BlockPackage.Keys) == 1 {
						bp := table.BlockPackage.Map[table.BlockPackage.Keys[0]].(*u.BlockPackage)
						if table.TableResult.WinnerOrder != nil {
							bp.WinnerOrder = table.WinnerOrder
						}
						if bp != nil && table.StandKV != nil {
							if bp.TableKV == nil {
								bp.TableKV = u.NewJobKv()
							}
							for nk, k := range []string{"中标金额", "中标单位", "预算", "成交状态", "项目名称", "项目编号", "采购范围"} {
								if len(table.StandKV[k]) > 0 {
									bp.TableKV.KvTags[k] = append(bp.TableKV.KvTags[k], &u.Tag{Key: k, Value: table.StandKV[k][0].Value})
								}
								if nk < 4 {
									delete(table.StandKV, k)
								}
							}
						}
					}
				}
			}
		}
	}
	for _, table := range tabs {
		table.MergerToTableresult()
		MergeKvTags(ts.KvTags, table.TableResult.KvTags)
		if !table.Brule {
			ts.isUnRulesTab = true
		}
	}
}

// 解析表格
func (table *Table) Analy(contactFormat *u.ContactFormat, isSite bool, codeSite string) []*Table {
	//查找表体中的tr对象
	trs := table.Goquery.ChildrenFiltered("tbody,thead,tfoot").ChildrenFiltered("tr")
	if trs.Size() == 0 {
		trs = table.Goquery.ChildrenFiltered("tr")
	}
	ztb := table.Goquery.Find("table").Size()
	//if ztb >= 9 {
	//	return []*Table{}
	//}
	if ztb > 20 {
		return []*Table{}
	}
	//遍历节点，初始化table 结构  TRs Sorts
	table.createTabe(trs, isSite, codeSite)
	if len(table.TRs) == 0 {
		return []*Table{}
	}
	//重置行列
	table.ComputeRowColSpan()
	//对table结构体进行整体解析处理
	ts := table.AnalyTables(contactFormat, isSite, codeSite)
	return ts
}

// 遍历节点，初始化table 结构体
func (table *Table) createTabe(trs *goquery.Selection, isSite bool, codeSite string) {
	trs.Each(func(n int, sel *goquery.Selection) {
		//隐藏行不处理
		if IsHide(sel) {
			return
		}
		//遍历每行的td
		tds := sel.ChildrenFiltered("td,th")
		TR := NewTR(table)
		tdTextIsNull := false
		var empty int
		tds.Each(func(m int, selm *goquery.Selection) {
			//对隐藏列不处理！！！
			if IsHide(selm) {
				return
			}
			//进入每一个单元格
			td := NewTD(selm, TR, table, isSite, codeSite) //初始化td,kv处理，td中有table处理，td的方向
			//num++
			TR.AddTD(td)
			if td.Val == "" && td.SonTableResult == nil && len(td.SortKV.Map) == 0 { //删除一个tr，tr中所有td是空值的
				empty++
				if tds.Size() == empty {
					tdTextIsNull = true
				}
			}
		})
		//向table添加每行不为空的tr
		if !tdTextIsNull {
			table.AddTR(TR)
		}
	})
}

// 分包，拆表
func (table *Table) tableSubDemolitionTable() []*Table {
	tm := []map[string]interface{}{}
	tmk := map[string]bool{}
	tmn := map[int]map[string]interface{}{}
	for rownum, tr := range table.TRs {
		if len(tr.TDs) == 1 && table.ColNum > 1 { //tr里面有一列，table里面有多列
			td := tr.TDs[0] //取每行第一个td
			//td开始列等于0 && td结束列+1等于table列数 && td长度大于1小于50
			if td.StartCol == 0 && td.EndCol+1 == table.ColNum && len([]rune(td.Val)) > 1 && len([]rune(td.Val)) < 50 {
				con, m1, b := CheckMultiPackage(td.Val) //判断分包
				if b {
					for k, _ := range m1 {
						numstr := u.PackageNumberConvert(k)
						m2 := map[string]interface{}{
							"tag": con,
							//"num":      numstr,
							//"numtxt":   v[0],
							"startrow": rownum,
						}
						tmk[numstr] = true
						tmn[rownum] = m2
						tm = append(tm, m2)
						break
					}
				}
			}
		}
	}
	//拆表
	ts := []*Table{}
	if len(tmk) > 1 && len(tmk) == len(tm) {
		var tab1 *Table
		for rownum, tr := range table.TRs {
			if tab1 == nil {
				tab1 = NewTable("", table.TableResult, table.Goquery)
				tab1.BSplit = true
				if tmn[rownum] != nil {
					tab1.StandKV["项目名称"] = append(tab1.StandKV["项目名称"], &u.Tag{Key: "项目名称", Value: tmn[rownum]["tag"].(string), Weight: -100})
				}
				ts = append(ts, tab1)
			}
			if tmn[rownum] != nil {
				tab1.Tag = tmn[rownum]["tag"].(string)
			} else {
				tab1.AddTR(tr)
			}
			if tmn[rownum+1] != nil {
				tab1 = nil
			}
		}
	} else {
		ts = append(ts, table)
	}
	return ts
}

// 分割表格
func (table *Table) bSplit(n int, ts []*Table, isSite bool, codeSite string) {
	if table.BSplit {
		if !table.BHeader && n > 0 {
			for i := n - 1; i > -1; i-- {
				if ts[i].BHeader {
					if ts[i].BFirstRow {
						//取第一行插入到
						table.InsertTR(ts[i].TRs[0])
						table.Adjust(isSite, codeSite)
					}
					break
				}
			}
		}
	}
}

// 删除尾部空白行
func (table *Table) deleteTrimTr() {
	for len(table.TRs) > 0 {
		npos := len(table.TRs)
		tailTR := table.TRs[npos-1] //最后一个tr，取最后一行
		bspace := true
		for _, v := range tailTR.TDs {
			if v.Val != "" || v.SonTableResult != nil || len(v.SortKV.Keys) > 0 {
				bspace = false
				break
			}
		}
		//删除尾部空行,是空行的话就删除
		if bspace {
			table.TRs = table.TRs[:npos-1]
		} else {
			break
		}
	}
}

// 校对表格
func (table *Table) Adjust(isSite bool, codeSite string) {
	//计算行列起止位置，跨行跨列处理
	table.ComputeRowColSpan()
	//	for k1, tr := range table.TRs {
	//		for k2, td := range tr.TDs {
	//			qutil.Debug(k1, k2, td.Val, td.StartRow, td.EndRow, td.StartCol, td.EndCol)
	//		}
	//	}
	//大概计算每个起止行列的概率
	table.GetKeyRation()
	/*
		for k, v := range table.StartAndEndRation {
			for k1, v1 := range v.Poss {
				bs, _ := json.Marshal(v1)
				str := ""
				for _, td := range v.Tdmap[v1] {
					str += "__" + td.Val + fmt.Sprintf("%d_%d_%d_%d", td.StartRow, td.EndRow, td.StartCol, td.EndCol)
				}
				qutil.Debug(k, k1, string(bs), v.Rationmap[v1], str)
			}
		}
	*/
	//u.Debug("tdnum:", num, table.RowNum, table.ColNum)
	//是否是规则的表格，单元各个数=行数*列数
	table.Brule = table.TDNum == table.RowNum*table.ColNum
	count := 0
	for _, trs := range table.TRs {
		for _, td := range trs.TDs {
			if td.BH {
				count++
			}
		}
	}
	if float32(count)/float32(table.TDNum) < 0.85 {
		//精确计算起止行列是表头的概率
		table.ComputeRowColIsKeyRation(isSite, codeSite)
		bhead := false
	L:
		for i, tr := range table.TRs {
			for _, td := range tr.TDs {
				if td.BH {
					//qutil.Debug("----=====---", td.Val, len(table.TRs[len(table.TRs)-1].TDs), i, len(table.TRs)-1)
					if i == len(table.TRs)-1 && len(table.TRs[len(table.TRs)-1].TDs) == 2 {
						res, _, _, _, _ := CheckCommon(td.Val, "abandontable")
						if res {
							//删除此行
							table.TRs = table.TRs[:len(table.TRs)-1]
							table.Adjust(isSite, codeSite)
							return
						}
					}
					bhead = true
					break L
				}
			}
		}
		table.BHeader = bhead
	}
}

// 计算行/列表格的结束位置 StartRow=0 EndRow=0,table.TDNum td个数 table.RowNum 行数
func (table *Table) ComputeRowColSpan() {
	n := 0                         //td总个数
	mapRC := map[int]map[int]int{} //记录第几行pos，起始列对应的合并值
	for k, v := range table.TRs {
		n += len(v.TDs) //每行的td总数相加
		nk := 0         //nk列的起始,k行的起始||如果有合并，起始就不是0
		ball := true
		rowspans := v.TDs[0].Rowspan //某一行第一个td的rowspan
		for k1, v1 := range v.TDs {
			if k1 == 0 && k == 0 {
				table.TRs[k].TDs[k1].MustBH = true
				table.TRs[k].TDs[k1].BH = true
			}
			if v1.Rowspan != rowspans {
				ball = false
				break
			}
		}
		for _, v1 := range v.TDs {
			if ball {
				v1.Rowspan = 1
			}
			mc := mapRC[k]
			for {
				if mc != nil && mc[nk] > 0 {
					nk += mc[nk]
				} else {
					break
				}
			}
			v1.StartCol = nk
			nk += v1.Colspan - 1
			v1.EndCol = nk
			if nk >= table.ColNum {
				table.ColNum = nk + 1
			}
			nk++
			v1.StartRow = k
			v1.EndRow = k + v1.Rowspan - 1
			ck := fmtkey("c", v1.StartCol, v1.EndCol)
			tdcs := table.StartAndEndRation[ck]
			if tdcs == nil {
				tdcs = NewTDRationScope(ck)
				table.StartAndEndRation[ck] = tdcs
				table.StartAndEndRationKSort.AddKey(ck, 1)
			}
			tdcs.Addtd(v1)
			rk := fmtkey("r", v1.StartRow, v1.EndRow)
			tdrs := table.StartAndEndRation[rk]
			if tdrs == nil {
				tdrs = NewTDRationScope(rk)
				table.StartAndEndRation[rk] = tdrs
				table.StartAndEndRationKSort.AddKey(rk, 1)
			}
			tdrs.Addtd(v1)
			if v1.Rowspan > 1 {
				for i := 1; i < v1.Rowspan; i++ {
					r := k + i
					if r < len(table.TRs) {
						mc := mapRC[r]
						if mc == nil {
							mc = map[int]int{}
						}
						mc[v1.StartCol] = v1.Colspan
						mapRC[r] = mc
					}
				}
			}
		}
	}
	table.TDNum = n               //td总个数
	table.RowNum = len(table.TRs) //tr总行数
}

func fmtkey(t string, start, end int) string {
	return fmt.Sprintf("%s_%d_%d", t, start, end)
}

// 查找每个table的标签，如果有标签可按标签处理，否则根据表格去判断
func (table *Table) FindTag() {
	//查找每个table的标签，如果有标签可按标签处理，否则根据表格去判断
	if table.Tag != "" {
		return
	}
	if table.Tag == "" {
		table.Tag = table.TableResult.BlockTag
	}
	//u.Debug(table.Tag)
}

// 计算r/c_start_end的概率
func (table *Table) GetKeyRation() {
	for _, vn := range table.StartAndEndRationKSort.Keys {
		v := table.StartAndEndRation[vn]
		for _, v1 := range v.Poss {
			count := 0
			n := 0
			for _, td := range v.Tdmap[v1] {
				n++
				if td.BH {
					count++
				}
			}
			v.Rationmap[v1] = float32(count) / float32(n)
		}
	}
}

// 计算行列是表头的概率调用GetKeyRation
func (table *Table) ComputeRowColIsKeyRation(isSite bool, codeSite string) {
	//增加对跨行校正限止
	//	u.Debug(table.Brule, table.ColNum, table.RowNum, table.TDNum)
	bkeyfirstrow := false
	bkeyfirstcol := false
	if table.Brule { //不存在跨行跨列的情况，规则表格
		checkCompute := map[string]bool{}
		for k, tr := range table.TRs {
			rk := fmtkey("r", tr.TDs[0].StartRow, tr.TDs[0].EndRow)
			if k == 0 { //第1行的概率
				ck := fmtkey("c", tr.TDs[0].StartCol, tr.TDs[0].EndCol)
				//u.Debug(table.BFirstRow, "--", table.StartAndEndRation[rk], table.StartAndEndRation[ck])
				ration1, _ := table.StartAndEndRation[rk].GetTDRation(tr.TDs[0])
				ration2, _ := table.StartAndEndRation[ck].GetTDRation(tr.TDs[0])
				if (len(tr.TDs) == 2 && ration2 < 0.55) && (len(tr.TDs) == 2 && ration1 > 0.5) { //第一行为key
					bkeyfirstrow = true
					ball := true
					for _, td := range tr.TDs {
						if MoneyReg.MatchString(td.Val) {
							bkeyfirstrow = false
							ball = false
							td.BH = false
							break
						}
					}
					for _, td := range tr.TDs {
						if ball {
							//td.BH = true
							td.KeyDirect = 1
							td.KVDirect = 2
						}
					}
				} else if ration2 > 0.55 { //第1列
					bkeyfirstcol = true
					if !checkCompute[ck] {
						checkCompute[ck] = true
						//重置第1列
						for _, tr1 := range table.TRs {
							for _, td1 := range tr1.TDs {
								if td1.StartCol == 0 {
									if !MoneyReg.MatchString(td1.Val) {
										//td1.BH = true
										td1.KeyDirect = 2
										td1.KVDirect = 1
									}
								}
							}
						}
					}
				}
				if !bkeyfirstrow && !bkeyfirstcol {
					if len(tr.TDs) > 1 && ration1 > ration2 && ration1 > 0.5 {
						bkeyfirstrow = true
						for _, td := range tr.TDs {
							if !MoneyReg.MatchString(td.Val) {
								//td.BH = true
								if specHeadReg.MatchString(td.Val) {
									td.BH = true
								}
								td.KeyDirect = 1
								td.KVDirect = 2
							}
						}
					} else if tr.Table.ColNum > 1 && ration2 > 0.5 {
						bkeyfirstcol = true
						if !checkCompute[ck] {
							checkCompute[ck] = true
							//重置第1列
							for _, tr1 := range table.TRs {
								for _, td1 := range tr1.TDs {
									if td1.StartCol == 0 {
										if !MoneyReg.MatchString(td1.Val) {
											td1.BH = true
											td1.KeyDirect = 2
											td1.KVDirect = 1
										}
									}
								}
							}
						}
					}
				}
			} else {
				if bkeyfirstrow {
					//第一列的概率
					ration1, _ := table.StartAndEndRation[rk].GetTDRation(tr.TDs[0])
					if k == 1 || ration1 < checkval {
						for _, td := range tr.TDs {
							if !td.MustBH {
								td.BH = false
								td.KeyDirect = 0
								td.KVDirect = 0
							}
						}
					} //else {for _, td := range tr.TDs {}}
				} else {
					//列在起作用
					if bkeyfirstcol {
						for _, td := range tr.TDs {
							ck := fmtkey("c", td.StartCol, td.EndCol)
							ration1, _ := table.StartAndEndRation[ck].GetTDRation(td)
							if !checkCompute[ck] {
								checkCompute[ck] = true
								if ration1 >= checkval && td.ColPos != 1 {
									for _, tr1 := range table.TRs {
										for _, td1 := range tr1.TDs {
											if td1.StartCol == td.StartCol {
												if !MoneyReg.MatchString(td1.Val) {
													td1.BH = true
													td1.KeyDirect = 2
													td1.KVDirect = 1
												}
											}
										}
									}
								} else {
									for _, tr1 := range table.TRs[1:] {
										for _, td1 := range tr1.TDs[1:] {
											if td1.StartCol == td.StartCol && !td1.MustBH {
												td1.BH = false
												td1.KeyDirect = 0
												td1.KVDirect = 0
											}
										}
									}
								}
							}

						}
					}
				}
			}
		}
	}
	//qutil.Debug("table.Brule", table.Brule, !bkeyfirstcol && !bkeyfirstrow)
	if !table.Brule || (!bkeyfirstcol && !bkeyfirstrow) {
		//断行问题，虽然同列或同行，但中间被跨行截断，表格方向调整
		for _, k := range table.StartAndEndRationKSort.Keys {
			v := table.StartAndEndRation[k]
			//横向判断,要判断最多的方向，否则会出现不定的情况（map遍历问题）
			k1 := k[:1]
			for _, v2 := range v.Poss {
				lentds := len(v.Tdmap[v2])
				if v.Rationmap[v2] > checkval {
					for _, td := range v.Tdmap[v2] {
						if td.KeyDirect == 0 && !MoneyReg.MatchString(td.Val) && !GSReg.MatchString(td.Val) {
							if k1 == "r" {
								ck := fmtkey("c", td.StartCol, td.EndCol)
								rt := table.StartAndEndRation[ck]
								//clen := 0
								var fv float32
								var tdn []*TD
								if rt != nil {
									fv, tdn = rt.GetTDRation(td)
									//clen = len(tdn)
								}
								if lentds > 1 {
									if ((tdn != nil && v.Rationmap[v2] > fv) || tdn == nil) && td.Valtype != "BO" {
										td.KeyDirect = 1
										td.KVDirect = 2
										//td.BH = true
									}
								}
							} else {
								ck := fmtkey("r", td.StartRow, td.EndRow)
								rt := table.StartAndEndRation[ck]
								var fv float32
								var tdn []*TD
								//clen := 0
								if rt != nil {
									fv, tdn = rt.GetTDRation(td)
									//clen = len(tdn)
								}
								if lentds > 1 {
									if td.Valtype != "NOHEAD" && utf8.RuneCountInString(td.Val) < 15 && ((tdn != nil && v.Rationmap[v2] > fv) || tdn == nil) && td.Valtype != "BO" {
										td.KeyDirect = 2
										td.KVDirect = 1
										td.BH = true
										//特殊情况-不能为表头
										if noStartHeadReg.MatchString(td.Val) {
											td.BH = false
										}
									}
								}
							}
						} else {
							break
						}
					}
				} else if v.Rationmap[v2] < 0.5 && len(v.Tdmap[v2]) > 3 {
					for _, td := range v.Tdmap[v2] {
						//						u.Debug(td.Val, "-----", td.BH)
						if td.KeyDirect == 0 && td.BH && !td.MustBH {
							if k1 == "r" {
								ck := fmtkey("c", td.StartCol, td.EndCol)
								rt := table.StartAndEndRation[ck]
								clen := 0
								var fv float32
								var tdn []*TD
								if rt != nil {
									fv, tdn = rt.GetTDRation(td)
									clen = len(tdn)
								}
								if lentds >= clen && lentds > 1 {
									if (tdn != nil && v.Rationmap[v2] < fv) || tdn == nil {
										td.BH = false
									}
								}
							} else {
								ck := fmtkey("r", td.StartRow, td.EndRow)
								rt := table.StartAndEndRation[ck]
								var fv float32
								var tdn []*TD
								clen := 0
								if rt != nil {
									fv, tdn = rt.GetTDRation(td)
									clen = len(tdn)
								}
								if lentds >= clen && lentds > 1 {
									if (tdn != nil && v.Rationmap[v2] < fv) || tdn == nil {
										td.BH = false
									}
								}
							}

						} else {
							break
						}
					}
				}
			}
		}
	}
	table.GetKeyRation()
	if len(table.TRs) > 0 && len(table.TRs[0].TDs) > 0 {
		t0 := table.TRs[0].TDs[0]
		key := fmtkey("r", t0.StartRow, t0.EndRow)
		r, t := table.StartAndEndRation[key].GetTDRation(t0)
		if r > 0.9 && len(t) > 1 {
			table.BFirstRow = true
		}
		for k, tr := range table.TRs {
			if len(tr.TDs) == 1 && tr.TDs[0].StartCol == 0 && tr.TDs[0].EndCol+1 == table.ColNum {
				tr.TDs[0].BH = false
				tr.TDs[0].KVDirect = 0
				sv := FindKv(tr.TDs[0].Val, "", 2)
				_, resm := colonkvEntity.entrance(tr.TDs[0].Val, "", nil, 2, isSite, codeSite)
				for k, v := range resm {
					sv.AddKey(k, v)
				}
				if len(sv.Keys) > 0 {
					for _, v1 := range sv.Keys {
						if tr.TDs[0].SortKV.Map[v1] == nil {
							table.SortKV.AddKey(v1, sv.Map[v1])
						}
					}
				} else if table.Tag == "" && k == 0 && len(tr.TDs[0].Val) > 11 {
					table.Tag = tr.TDs[0].Val
				}
			}
		}
	}
}

// 查找表格的kv，调用FindTdVal
func (table *Table) FindKV(isSite bool, codeSite string) {
	//判断全是key的表格不再查找
	if table.BHeader { //只要一个是key即为true
		direct := If(table.BFirstRow, 2, 1).(int) //kv，2查找方向，向上查找
		vdirect := If(direct == 2, 1, 2).(int)
		//控制跨行表格
		bcon := false
		//增加表格切块判断，只判断切块分包
		//控制中标人排序方向
		//bodirect := 0
		//控制中标人排序数值
		//sort := 1
		nextdirect, nextvdirect := 0, 0
		//开始抽取
		than_once_1, than_once_2 := false, false
		//特殊候选人结构
		winnerOrderHeader := false
		if judgmentWinnerOrderHeaderInfo(table.TRs) {
			winnerOrderHeader = true
		}
		for tr_index, tr := range table.TRs {
			bcon = trSingleColumn(tr, bcon, table) //tr单列,是否丢弃内容
			if bcon {
				continue
			}
			if tr.TDs[0].StartRow >= 0 {
				numbh := 0
				for _, td := range tr.TDs {
					if td.BH {
						numbh++
					}
				}
				if numbh != 0 && numbh == len(tr.TDs) { //5e0d53ef0cf41612e0640495
					if tr_index == 0 {
						than_once_1, than_once_2 = true, true
					}
					nextdirect, nextvdirect = 2, 1
					continue
				} else if nextdirect > 0 && nextvdirect > 0 {
					direct, vdirect = 2, 1
				} else if numbh > 0 && numbh <= len(tr.TDs)/2 {
					direct, vdirect = 1, 2
				} else {
					direct, vdirect = 2, 1
				}
			}
			//计算一下表格结构是否为指定候选人
			for _, td := range tr.TDs {
				if winnerOrderHeader { //特殊类-候选人结构表格
					if tr_index == 0 {
						td.KVDirect, td.KeyDirect = 2, 1
					} else {
						td.KVDirect, td.KeyDirect = 0, 0
						td.BH = false
						if td.Val == "" {
							td.Val = "/"
						}
					}
				}
				if !td.BH && td.KVDirect < 3 {
					if !table.FindTdVal(td, direct, vdirect) { //table.FindTdVal()存储了table.SortKV
						table.FindTdVal(td, vdirect, direct)
					}
					if than_once_1 && tr_index == 1 {
						table.FindTdVal(td, 1, 2) //table.FindTdVal()存储了table.SortKV
						than_once_1 = false
					}
				} else {
					if than_once_2 && tr_index == 1 && td.BH && findCandidate.MatchString(td.Val) {
						table.FindTdVal(td, 1, 2) //特殊计算表头异常-情况
					}
				}
			}
			nextdirect, nextvdirect = 0, 0
		}
		//qutil.Debug("FindKV", table.SortKV.Map)
	} else if len(table.TRs) > 0 { //没有表头的表格处理,默认纵向吧
		res := initLongitudinalData(table) //拼装纵向数组
		//再拆值，类似http://www.ggzy.hi.gov.cn/cgzbgg/16553.jhtml第二列，有多个值
		nmapkeys := []int{}
		nmap := map[int][]*u.Kv{}
	L:
		for _, r1 := range res {
			for n, r := range r1 {
				if len([]rune(r)) < 60 { // 长度小于60才去分
					//res1, _ := GetKVAll(r, "", nil)
					res1, _ := colonkvEntity.entrance(r, "", nil, 2, isSite, codeSite)
					if res1 != nil {
						nmap[n] = res1
						nmapkeys = append(nmapkeys, n)
						/**
						//截取串
						for _k1, _ := range res1 {
							r = regexp.MustCompile(_k1+".*").ReplaceAllString(r, "")
						}
						r1[n] = r
						res[pos] = r1
						**/
					} else if nmap[n] != nil {
						//放空值
						nmap[n] = append(nmap[n], &u.Kv{})
					}
				} else {
					nmap = nil
					nmapkeys = nil
					break L
				}
			}
		}
		//调整
		if len(nmap) > 0 {
			kmapkeys := []string{}
			kmap := map[string][]string{}
			for _, mk := range nmapkeys { //同是第n列
				for pos, m1 := range nmap[mk] {
					k, v := m1.Key, m1.Value
					kv := kmap[k]
					if kv == nil {
						kv = []string{}
					}
					kv = append(kv, v)
					kmap[k] = kv
					kmapkeys = append(kmapkeys, k)
					for _, k := range kmapkeys {
						arr := kmap[k]
						if len(arr) < pos {
							arr = append(arr, "")
							kmap[k] = arr
							kmapkeys = append(kmapkeys, k)
						}
					}
				}
			}
			if len(kmap) > 0 {
				for _, k := range kmapkeys {
					if len(kmap[k]) == 1 {
						table.SortKV.AddKey(k, kmap[k][0])
					} else if len(kmap[k]) > 1 {
						table.SortKV.AddKey(k, kmap[k])
					}
				}
			}
		}
		//=================
		//解析值放到map中
		for _, arr := range res {
			if len(arr) > 0 {
				v1 := arr[0]
				_, _, _, _, repl := CheckCommon(v1, "con")
				if repl == "ENT" {
					table.SortKV.AddKey("中标单位", arr)
					continue
				} else if repl == "BO" {
					table.SortKV.AddKey("排名", arr)
					continue
				}
			}
		}
	}
	//qutil.Debug("Table-FindKV", table.SortKV.Map)
}
