Browse Source

Merge branch 'master' of http://8.136.199.33:3000/hongze/hongze_cygx into cygx_htgj

xingzai 2 years ago
parent
commit
cc2c6c60be

+ 1130 - 4
controllers/activity.go

@@ -256,6 +256,21 @@ func (this *ActivityCoAntroller) ActivityList() {
 	} else {
 		conditionOr += `	OR ( art.is_limit_people = 0 	  ` + condition + `) `
 	}
+
+	//判断客户规模是否属于可见范围的活动
+	companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+		}
+	}
+
 	condition += ` AND art.is_limit_people = 1 ` + permissionSqlStr + sqlExport + conditionOr
 	total, err := models.GetActivityCount(condition, pars)
 	if err != nil {
@@ -404,7 +419,6 @@ func (this *ActivityCoAntroller) ScheduleList() {
 		return
 	}
 	var list []*models.CygxActivityList
-	fmt.Println(totalCount)
 	//全部都是进行中的活动
 	if totalCount > currentIndex*pageSize {
 		condition += ` AND art.active_state IN(2) `
@@ -432,7 +446,6 @@ func (this *ActivityCoAntroller) ScheduleList() {
 			br.ErrMsg = "获取失败,Err:" + errList.Error()
 			return
 		}
-		fmt.Println("长度", len(listOther))
 		if len(listOther) > 0 {
 			for _, v := range listOther {
 				list = append(list, v)
@@ -576,7 +589,6 @@ func (this *ActivityCoAntroller) Detail() {
 		br.ErrMsg = "判断是否已申请过试用失败,Err:" + err.Error()
 		return
 	}
-
 	//获取FICC销售信息 如果是FICC的客户类型,则默认他申请过
 	sellerItem, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 1)
 	if err != nil && err.Error() != utils.ErrNoRow() {
@@ -651,6 +663,21 @@ func (this *ActivityCoAntroller) Detail() {
 			br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
 			return
 		}
+
+		//获取用户的产业规模,判断是否允许可见
+		companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+			return
+		}
+		if companyProduct != nil {
+			if companyProduct.Scale != "" {
+				if strings.Count(activityInfo.Scale, companyProduct.Scale) > 0 {
+					noPower = false
+				}
+			}
+		}
 		if noPower {
 			br.Msg = "您暂无查看该活动权限"
 			br.ErrMsg = "被分享客户不可见,获取信息失败"
@@ -685,7 +712,6 @@ func (this *ActivityCoAntroller) Detail() {
 
 	if user.CompanyId > 1 {
 		permissionStr, err := models.GetCompanyPermissionByUser(user.CompanyId)
-		fmt.Println(permissionStr)
 		if err != nil {
 			br.Msg = "获取信息失败"
 			br.ErrMsg = "获取客户权限信息失败,Err:" + err.Error()
@@ -2071,6 +2097,7 @@ func (this *ActivityCoAntroller) AskAdd() {
 	//		return
 	//	}
 	//}
+
 	companyDetail, err := models.GetCompanyDetailById(user.CompanyId)
 	if err != nil {
 		br.Msg = "提交失败!"
@@ -2097,6 +2124,60 @@ func (this *ActivityCoAntroller) AskAdd() {
 		br.ErrMsg = "提交带问失败,Err:" + err.Error()
 		return
 	}
+
+	var isSendMsg bool
+	resultTime := utils.StrTimeToTime(activityInfo.ActivityTime) //时间字符串格式转时间格式
+	if activityInfo.ActivityTypeId == 1 && activityInfo.ChartPermissionId != 31 {
+		if time.Now().After(resultTime.Add(-time.Minute * 15)) {
+			isSendMsg = true
+		}
+	} else {
+		if time.Now().After(resultTime.Add(-time.Minute * 60)) {
+			isSendMsg = true
+		}
+	}
+	if isSendMsg {
+		listEmail, err := models.GetAskEmail()
+		if err != nil {
+			br.Msg = "提交失败"
+			br.ErrMsg = "提交带问失败,Err:" + err.Error()
+			return
+		}
+		var sendMobile string
+		for _, v := range listEmail {
+			if strings.Index(activityInfo.Host, v.Name) > 0 {
+				sendMobile = v.Mobile
+			}
+		}
+		if activityInfo.ChartPermissionId == 31 {
+			sendMobile = utils.ActSendMsgMobile
+		}
+
+		//获取销售信息
+		sellerItem, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "提交失败"
+			br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+			return
+		}
+		//给研究员发送消息
+		if sendMobile != "" {
+			openIpItem, _ := models.GetUserRecordByMobile(4, sendMobile)
+			if openIpItem != nil && openIpItem.OpenId != "" {
+				if sellerItem != nil {
+					services.SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", time.Now().Format(utils.FormatDateTime), req.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
+				}
+			}
+		}
+		// 给所属销售发送消息
+		if sellerItem != nil {
+			openIpItem, _ := models.GetUserRecordByMobile(4, sellerItem.Mobile)
+			if openIpItem != nil && openIpItem.OpenId != "" {
+				services.SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", time.Now().Format(utils.FormatDateTime), req.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
+			}
+		}
+	}
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "提交成功"
@@ -2227,6 +2308,20 @@ func (this *ActivityCoAntroller) LabelTypeList() {
 		} else {
 			conditionOr += ` OR ( art.is_limit_people = 0 ` + condition + `) `
 		}
+		//判断客户规模是否属于可见范围的活动
+		companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+			return
+		}
+
+		if companyProduct != nil {
+			if companyProduct.Scale != "" {
+				conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+			}
+		}
+
 		condition += `AND art.is_limit_people = 1 ` + permissionSqlStr + sqlExport + conditionOr
 
 		sortTime = ` mintimesort ASC `
@@ -2376,6 +2471,19 @@ func (this *ActivityCoAntroller) LabelMoreList() {
 	} else {
 		conditionOr += ` OR ( art.is_limit_people = 0 ` + condition + `) `
 	}
+	//判断客户规模是否属于可见范围的活动
+	companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+		}
+	}
 	condition += `AND art.is_limit_people = 1 ` + permissionSqlStr + sqlExport + conditionOr
 
 	//进行中的活动
@@ -2567,6 +2675,18 @@ func (this *ActivityCoAntroller) ActivityListNew() {
 	} else {
 		conditionOr += `	OR ( art.is_limit_people = 0 	  ` + condition + `) `
 	}
+	//判断客户规模是否属于可见范围的活动
+	companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+		}
+	}
 
 	condition += ` AND art.is_limit_people = 1 ` + permissionSqlStr + sqlExport + conditionOr
 	total, err := models.GetActivityCount(condition, pars)
@@ -2801,6 +2921,18 @@ func (this *ActivityCoAntroller) LabelTypeListPc() {
 		} else {
 			conditionOr += ` OR ( art.is_limit_people = 0 ` + condition + `) `
 		}
+		//判断客户规模是否属于可见范围的活动
+		companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+			return
+		}
+		if companyProduct != nil {
+			if companyProduct.Scale != "" {
+				conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+			}
+		}
 		condition += `AND art.is_limit_people = 1 ` + permissionSqlStr + sqlExport + conditionOr
 		sortTime = ` mintimesort ASC `
 		labelList, err := models.GetActivityLabelListAll(condition, sortTime, pars, startSize, pageSize)
@@ -3036,3 +3168,997 @@ func (this *ActivityCoAntroller) CheckAsk() {
 	br.Success = true
 	br.Data = resp
 }
+
+// @Title 活动类型下的主题列表(5.3版本)
+// @Description 获取活动类型下的主题列表接口(5.3版本)
+// @Param   ChartPermissionIds   query   string  false     "行业id 多个用 , 隔开"
+// @Param   ActivityTypeIds   query   string  false     "活动类型id 多个用 , 隔开"
+// @Param   ActiveState   query   string  false       "活动进行状态 未开始:1、进行中2、已结束3"
+// @Param   WhichDay   query   string  false       "哪一天 今天:1、明天:2,多个用 , 隔开"
+// @Param   IsPower   query   int  false       "是否选择有权限行业 ,1是 0 否 默认0"
+// @Success 200 {object} models.ActivityTypeListHomeResp
+// @router /labelTypeListV5 [get]
+func (this *ActivityCoAntroller) LabelTypeListV5() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		return
+	}
+	pageSize, _ := this.GetInt("PageSize")
+	isPower, _ := this.GetInt("IsPower")
+	chartPermissionIds := this.GetString("ChartPermissionIds")
+	whichDay := this.GetString("WhichDay")
+	activeState := this.GetString("ActiveState")
+	//入参为 undefined 时的处理
+	if chartPermissionIds == "undefined" {
+		chartPermissionIds = ""
+	}
+	if whichDay == "undefined" {
+		whichDay = ""
+	}
+	if activeState == "undefined" || activeState == "" {
+		activeState = "1"
+	}
+	userType, permissionStr, err := services.GetUserType(user.CompanyId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	var startSize int
+	pageSize = 40
+	var sortTime string
+	var pars []interface{}
+	//活动可见限制
+	slicePer := strings.Split(permissionStr, ",")
+	var permissionSqlStr string
+	var permissionNameStr string
+	for _, v := range slicePer {
+		if userType == 1 {
+			if v != "研选" {
+				permissionNameStr += "'" + v + "',"
+			}
+		} else {
+			permissionNameStr += "'" + v + "',"
+		}
+	}
+	permissionNameStr = strings.Replace(permissionNameStr, "(主观)", "", -1)
+	permissionNameStr = strings.Replace(permissionNameStr, "(客观)", "", -1)
+	permissionNameStr = strings.TrimRight(permissionNameStr, ",")
+	list, err := models.GetActivityTypeHomeList()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	//判断客户规模是否属于可见范围的活动
+	companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+	var sqlExport string
+	resp := new(models.ActivityTypeListHomeResp)
+	for k, v := range list {
+		var condition string
+		permissionSqlStr = ` AND art.chart_permission_name  IN (` + permissionNameStr + `)`
+		sqlExport = ` AND (art.customer_type_ids LIKE '%` + strconv.Itoa(userType) + `%' `
+		if userType == 2 {
+			sqlExport += ` OR  art.customer_type_ids LIKE '%3%' `
+		}
+		if (userType == 2 || userType == 3) && strings.Contains(permissionStr, "专家") {
+			sqlExport += ` OR  art.customer_type_ids LIKE '%4%' `
+		}
+		sqlExport += `) `
+		condition = ` AND art.publish_status = 1  AND art.label != ''  AND art.activity_type_id = ` + strconv.Itoa(v.ActivityTypeId)
+		if isPower == 1 {
+			condition += permissionSqlStr
+		}
+		//行业名称
+		if len(chartPermissionIds) > 0 {
+			condition += ` AND art.chart_permission_id  IN (` + chartPermissionIds + `)`
+		}
+		var conditionOr string
+		if whichDay != "" {
+			var startDate string
+			var endDate string
+			if whichDay == "1" {
+				startDate = time.Now().Format(utils.FormatDate)
+				endDate = startDate
+			} else if whichDay == "2" {
+				startDate = time.Now().AddDate(0, 0, +1).Format(utils.FormatDate)
+				endDate = startDate
+			} else {
+				startDate = time.Now().Format(utils.FormatDate)
+				endDate = time.Now().AddDate(0, 0, +1).Format(utils.FormatDate)
+			}
+			condition += ` AND art.activity_time >= ` + "'" + startDate + " 00:00:00'"
+			condition += ` AND art.activity_time <= ` + "'" + endDate + " 23:59:59'"
+		}
+		if activeState != "" {
+			condition += ` AND art.active_state  IN (` + activeState + `)`
+		} else {
+			condition += ` AND art.active_state  IN (1)`
+		}
+		if (userType == 2 || userType == 3 || userType == 4) && strings.Contains(permissionStr, "专家") {
+			conditionOr += ` OR (  art.is_limit_people = 1 AND art.customer_type_ids LIKE '%4%'	 ` + condition + `) `
+		}
+		if (userType == 5) && strings.Contains(permissionStr, "专家") {
+			conditionOr += ` OR (  art.is_limit_people = 1 AND art.customer_type_ids LIKE '%5%'	 ` + condition + `) `
+		}
+		if userType == 1 {
+			conditionOr += ` OR ( art.is_limit_people = 0 ` + condition + permissionSqlStr + `) `
+		} else {
+			conditionOr += ` OR ( art.is_limit_people = 0 ` + condition + `) `
+		}
+		if companyProduct != nil {
+			if companyProduct.Scale != "" {
+				conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+			}
+		}
+		condition += `AND art.is_limit_people = 1 ` + permissionSqlStr + sqlExport + conditionOr
+		sortTime = ` mintimesort ASC `
+		labelList, err := models.GetActivityLabelListAll(condition, sortTime, pars, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取失败,Err:" + err.Error()
+			return
+		}
+		//标签字段关联的产业与标签处理
+		for k2, v2 := range labelList {
+			labelList[k2].KeyWord = services.LabelStrV5(v2.KeyWord, v2.IsShowSubjectName)
+			labelList[k2].ImgUrlBg = v.ImgUrlBgs
+		}
+		list[k].List = labelList
+		list[k].Resource = 1
+	}
+
+	//userType = 1
+	//查询专项产业调研展示权限
+	var condition string
+	condition = ` AND art.publish_status = 1  AND art.label != '' `
+	if isPower == 1 {
+		condition += permissionSqlStr
+	}
+	//行业名称
+	if len(chartPermissionIds) > 0 {
+		condition += ` AND art.chart_permission_id  IN (` + chartPermissionIds + `)`
+	}
+	var conditionOr string
+
+	if (userType == 2 || userType == 3 || userType == 4) && strings.Contains(permissionStr, "专家") {
+		conditionOr += ` OR (1=1 AND   art.customer_type_ids LIKE '%4%'	 ` + condition + `) `
+	}
+	if (userType == 5) && strings.Contains(permissionStr, "专家") {
+		conditionOr += ` OR (1=1 AND art.customer_type_ids LIKE '%5%'	 ` + condition + `) `
+	}
+	if userType == 1 {
+		conditionOr += ` OR (` + condition + permissionSqlStr + `) `
+	}
+
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+		}
+	}
+
+	condition += sqlExport + conditionOr
+	specialList, err := models.GetActivityLabelSpecialListAll(condition, pars, startSize, 8)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	for k2, v2 := range specialList {
+		specialList[k2].KeyWord = services.LabelStrV5(v2.KeyWord, v2.IsShowSubjectName)
+		specialList[k2].ImgUrlBg = "https://hzstatic.hzinsights.com/static/temp/20220426202204/20220426/XDLLsjC9XAAy8LIzQr7GsjrBbtX6.png"
+	}
+
+	itemList := new(models.ActivityTypeHome)
+	itemList.ActivityTypeName = "专项产业调研"
+	itemList.Resource = 2
+	itemList.List = specialList
+	itemList.ActivityTypeId = 7
+	itemList.ImgUrl = "https://hzstatic.hzinsights.com/static/temp/20220427202204/20220427/b2Bj3fGakP16iJRFKisQohCWnCNl.png"
+	itemList.ImgUrlBg = "https://hzstatic.hzinsights.com/static/temp/20220427202204/20220427/OkunjfKEgo5KRLifzwwLX8cDZnnN.png"
+	list = append(list, itemList)
+	//获取对应活动的数量并排序
+	intArr := make([]int, 0)
+	var items []*models.ActivityTypeHome
+	for _, v := range list {
+		item := new(models.ActivityTypeHome)
+		if len(v.List) > 0 {
+			item.List = v.List
+			item.ActivityTypeName = v.ActivityTypeName
+			item.ActivityTypeId = v.ActivityTypeId
+			item.ImgUrlBg = v.ImgUrlBg
+			item.ImgUrl = v.ImgUrl
+			item.Resource = v.Resource
+			items = append(items, item)
+			intArr = append(intArr, len(v.List))
+		}
+	}
+	sort.Sort(sort.Reverse(sort.IntSlice(intArr)))
+	var itemsNew []*models.ActivityTypeHome
+	activityMap := make(map[int]int)
+	for _, v := range intArr {
+		for _, v2 := range items {
+			item := new(models.ActivityTypeHome)
+			if len(v2.List) > 0 && v == len(v2.List) && activityMap[v2.ActivityTypeId] == 0 {
+				item.List = v2.List
+				item.ActivityTypeName = v2.ActivityTypeName
+				item.ActivityTypeId = v2.ActivityTypeId
+				item.ImgUrlBg = v2.ImgUrlBg
+				item.ImgUrl = v2.ImgUrl
+				item.Resource = v2.Resource
+				itemsNew = append(itemsNew, item)
+				activityMap[v2.ActivityTypeId] = len(v2.List)
+			}
+		}
+	}
+	//按照像素进行排序
+	rowHeight := 83     //每一行的行高
+	basicsHeight := 178 // 基础高度
+	position := 1       // 初始化位置 ,1,左边, 2 右边
+	var leftPx, rightPx int
+	for k, v := range itemsNew {
+		if leftPx <= rightPx {
+			position = 1
+		} else {
+			position = 2
+		}
+		itemsNew[k].Position = position
+		if position == 1 {
+			leftPx += basicsHeight + rowHeight*len(v.List)
+		} else {
+			rightPx += basicsHeight + rowHeight*len(v.List)
+		}
+	}
+	//记录用户搜索的筛选条件
+	item := new(models.CygxActivitySearchHistory)
+	item.UserId = user.UserId
+	item.Mobile = user.Mobile
+	item.CompanyId = user.CompanyId
+	item.CompanyName = user.CompanyName
+	item.CreateTime = time.Now()
+	item.ChartPermissionIds = chartPermissionIds
+	item.IsPower = isPower
+	item.WhichDay = whichDay
+	go models.AddCygxActivitySearchHistory(item)
+	resp.List = itemsNew
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 专项产业调研列表
+// @Description 获取专项产业调研列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Success 200 {object} models.GetCygxActivitySpecialDetailListResp
+// @router /special/list [get]
+func (this *ActivityCoAntroller) SpecialList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		return
+	}
+	uid := user.UserId
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	userType, permissionStr, err := services.GetUserType(user.CompanyId)
+
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	var condition string
+	var pars []interface{}
+	//活动可见限制
+	var sqlExport string
+	slicePer := strings.Split(permissionStr, ",")
+	var permissionSqlStr string
+	for _, v := range slicePer {
+		if userType == 1 {
+			if v != "研选" {
+				permissionSqlStr += "'" + v + "',"
+			}
+		} else {
+			permissionSqlStr += "'" + v + "',"
+		}
+	}
+
+	//判断客户规模是否属于可见范围的活动
+	companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+	permissionSqlStr = strings.TrimRight(permissionSqlStr, ",")
+	permissionSqlStr = strings.Replace(permissionSqlStr, "(主观)", "", -1)
+	permissionSqlStr = strings.Replace(permissionSqlStr, "(客观)", "", -1)
+	permissionSqlStr = ` AND art.chart_permission_name  IN (` + permissionSqlStr + `)`
+	sqlExport = ` AND (art.customer_type_ids LIKE '%` + strconv.Itoa(userType) + `%' `
+	if userType == 2 {
+		sqlExport += ` OR  art.customer_type_ids LIKE '%3%' `
+	}
+	if (userType == 2 || userType == 3) && strings.Contains(permissionStr, "专家") {
+		sqlExport += ` OR  art.customer_type_ids LIKE '%4%' `
+	}
+	sqlExport += `) `
+	condition += ` AND art.publish_status = 1 `
+	condition = ` AND art.publish_status = 1  AND art.label != '' `
+	var conditionOr string
+
+	if (userType == 2 || userType == 3 || userType == 4) && strings.Contains(permissionStr, "专家") {
+		conditionOr += ` OR (1=1 AND   art.customer_type_ids LIKE '%4%'	 ` + condition + `) `
+	}
+	if (userType == 5) && strings.Contains(permissionStr, "专家") {
+		conditionOr += ` OR (1=1 AND art.customer_type_ids LIKE '%5%'	 ` + condition + `) `
+	}
+	if userType == 1 {
+		conditionOr += ` OR (` + condition + permissionSqlStr + `) `
+	}
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+		}
+	}
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			conditionOr += ` OR (  art.scale LIKE '%` + companyProduct.Scale + `%'	 ` + condition + `) `
+		}
+	}
+	condition += sqlExport + conditionOr
+	total, err := models.GetActivitySpecialCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, errList := models.GetCygxActivitySpecialDetailList(condition, pars, uid, startSize, pageSize)
+	if errList != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + errList.Error()
+		return
+	}
+	detail, err := models.GetConfigByCode("city_img_url")
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "城市配置信息失败,Err:" + err.Error()
+		return
+	}
+	detailChart, err := models.GetConfigByCode("chart_img_url")
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "行业配置信息失败,Err:" + err.Error()
+		return
+	}
+
+	addressList := strings.Split(detail.ConfigValue, "{|}")
+	mapAddress := make(map[string]string)
+	chartList := strings.Split(detailChart.ConfigValue, "{|}")
+	mapChart := make(map[string]string)
+	var cityName string
+	var chartName string
+	var imgUrl string
+	var imgUrlChart string
+	for _, v := range addressList {
+		vslice := strings.Split(v, "_")
+		cityName = vslice[0]
+		imgUrl = vslice[len(vslice)-1]
+		mapAddress[cityName] = imgUrl
+	}
+	for _, v := range chartList {
+		vslice := strings.Split(v, "_")
+		chartName = vslice[0]
+		imgUrlChart = vslice[len(vslice)-1]
+		mapChart[chartName] = imgUrlChart
+	}
+	for k, v := range list {
+		//if v.ChartPermissionName == "研选" {
+		//	list[k].ActivityTypeName = "研选电话会"
+		//	list[k].ImgUrlText = "https://hongze.oss-cn-shanghai.aliyuncs.com/static/images/202112/20211221/bIdfv8t86xrFRpDOeGGHXOmKEuKl.png"
+		//}
+		list[k].ImgUrlText = "https://hongze.oss-cn-shanghai.aliyuncs.com/static/images/202112/20211221/bIdfv8t86xrFRpDOeGGHXOmKEuKl.png"
+		if mapChart[v.ChartPermissionName] != "" {
+			list[k].ImgUrl = mapChart[v.ChartPermissionName]
+		}
+		list[k].ActivityTypeName = "专项调研"
+
+	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.GetCygxActivitySpecialDetailListResp)
+	count, err := models.GetCygxUserFollowSpecial(user.UserId)
+	if err != nil {
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+		return
+	}
+	if count == 1 {
+		resp.IsFollow = true
+	}
+	resp.List = list
+	resp.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+
+}
+
+// @Title  专项产业调研详情
+// @Description 获取专项产业调研详情接口
+// @Param   ActivityId   query   int  true       "活动ID"
+// @Success Ret=200 {object} models.CygxActivitySpecialResp
+// @router /special/detail [get]
+func (this *ActivityCoAntroller) SpecialDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,用户信息为空"
+		br.Ret = 408
+		return
+	}
+	uid := user.UserId
+	activityId, _ := this.GetInt("ActivityId")
+	if activityId < 1 {
+		br.Msg = "请输入活动ID"
+		return
+	}
+	resp := new(models.CygxActivitySpecialResp)
+	hasPermission := 0
+
+	activityInfo, err := models.GetCygxActivitySpecialDetailById(uid, activityId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "判断是否已申请过试用失败,Err:" + err.Error()
+		return
+	}
+	if activityInfo == nil {
+		br.Msg = "活动不存在"
+		br.ErrMsg = "活动ID错误,Err:" + "activityId:" + strconv.Itoa(activityId)
+		return
+	}
+	applyCount, err := models.GetApplyRecordCount(uid)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "判断是否已申请过试用失败,Err:" + err.Error()
+		return
+	}
+	//获取FICC销售信息 如果是FICC的客户类型,则默认他申请过
+	sellerItem, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 1)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+		return
+	}
+	if user.CompanyId <= 1 {
+		//companyDetailStatus = ""
+	} else {
+		companyPermission, err := models.GetCompanyPermission(user.CompanyId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+			return
+		}
+		if companyPermission == "" {
+			if applyCount > 0 {
+				hasPermission = 4
+			} else {
+				if sellerItem != nil {
+					hasPermission = 5
+				} else {
+					//获取权益销售信息 如果是FICC的客户类型,则默认他申请过
+					sellerItemQy, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
+					if err != nil && err.Error() != utils.ErrNoRow() {
+						br.Msg = "获取信息失败"
+						br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+						return
+					}
+					if sellerItemQy != nil {
+						hasPermission = 2
+						resp.SellerMobile = sellerItemQy.Mobile
+						resp.SellerName = sellerItemQy.RealName
+					} else {
+						hasPermission = 3
+					}
+				}
+			}
+			resp.HasPermission = hasPermission
+			resp.OperationMode = "Apply"
+			resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
+		}
+		companyDetail, err := models.GetCompanyDetailById(user.CompanyId)
+		if err != nil {
+			br.Msg = "获取信息失败!"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+			return
+		}
+		if companyDetail == nil {
+			br.Msg = "获取信息失败!"
+			br.ErrMsg = "客户不存在,uid:" + strconv.Itoa(user.UserId) + "CompanyId:" + strconv.Itoa(user.CompanyId)
+			return
+		}
+	}
+	userType, permissionStr, err := services.GetUserType(user.CompanyId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+	itemAct := new(models.ActivityDetail)
+	itemAct.CustomerTypeIds = activityInfo.CustomerTypeIds
+	noPower, err := services.GetShareNoPowe(itemAct, permissionStr, userType)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+
+	//获取用户的产业规模,判断是否允许可见
+	companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+		return
+	}
+	if companyProduct != nil {
+		if companyProduct.Scale != "" {
+			if strings.Count(activityInfo.Scale, companyProduct.Scale) > 0 {
+				noPower = false
+			}
+		}
+	}
+	if noPower {
+		br.Msg = "您暂无查看该活动权限"
+		br.ErrMsg = "被分享客户不可见,获取信息失败"
+		return
+	}
+
+	if userType == 1 && activityInfo.ChartPermissionName == "研选" {
+		br.Msg = "您暂无查看该活动权限"
+		br.ErrMsg = "被分享客户不可见,永续客户无法查看研选行业"
+		return
+	}
+	//判断是否已经申请过
+	if user.CompanyId > 1 {
+		permissionStr, err := models.GetCompanyPermissionByUser(user.CompanyId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取客户权限信息失败,Err:" + err.Error()
+			return
+		}
+		companyItem, err := models.GetCompanyDetailById(user.CompanyId)
+		//冻结客户
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				if applyCount > 0 {
+					hasPermission = 4
+				} else {
+					if sellerItem != nil {
+						hasPermission = 5
+					} else {
+						//获取权益销售信息 如果是FICC的客户类型,则默认他申请过
+						sellerItemQy, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
+						if err != nil && err.Error() != utils.ErrNoRow() {
+							br.Msg = "获取信息失败"
+							br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+							return
+						}
+						if sellerItemQy != nil {
+							hasPermission = 2
+							resp.SellerMobile = sellerItemQy.Mobile
+							resp.SellerName = sellerItemQy.RealName
+						} else {
+							hasPermission = 3
+						}
+					}
+				}
+				resp.HasPermission = hasPermission
+				resp.OperationMode = "Apply"
+				resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				br.Data = resp
+				return
+			} else {
+				br.Msg = "获取信息失败"
+				br.ErrMsg = "获取客户公司信息失败,Err:" + err.Error()
+				return
+			}
+		}
+		var havePower bool
+		if strings.Contains(permissionStr, activityInfo.ActivityTypeName) {
+			havePower = true
+		}
+		if havePower {
+			hasPermission = 1
+			resp.HaqveJurisdiction = true
+		} else {
+			if permissionStr == "专家" {
+				resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+				resp.MsgType = "Type"
+			} else {
+				resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+				resp.MsgType = "Industry"
+			}
+			if companyItem.ProductId == 2 {
+				resp.SellerMobile = companyItem.Mobile
+				resp.SellerName = companyItem.SellerName
+				resp.OperationMode = "Call"
+				hasPermission = 2
+			} else {
+				hasPermission = 5
+			}
+		}
+	} else { //潜在客户
+		if applyCount > 0 {
+			hasPermission = 4
+		} else {
+			if sellerItem != nil {
+				hasPermission = 5
+			} else {
+				hasPermission = 3
+			}
+		}
+		resp.OperationMode = "Apply"
+		resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+	}
+	if hasPermission == 1 {
+		activityInfo.ActivityTypeName = "专项调研"
+		resp.Detail = activityInfo
+	}
+	resp.HasPermission = hasPermission
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 感兴趣、不感兴趣
+// @Description 感兴趣、不感兴趣接口
+// @Param	request	body models.ActivityIdRep true "type json string"
+// @Success Ret=200 {object} models.SignupSpecialStatus
+// @router /special/signup/add [post]
+func (this *ActivityCoAntroller) SpecialSignupAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,用户信息为空"
+		br.Ret = 408
+		return
+	}
+	uid := user.UserId
+	var req models.ActivityIdRep
+	resp := new(models.SignupSpecialStatus)
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	activityId := req.ActivityId
+	hasPermission := 0
+	//判断是否已经申请过
+	applyCount, err := models.GetApplyRecordCount(uid)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "判断是否已申请过试用失败,Err:" + err.Error()
+		return
+	}
+	//获取FICC销售信息
+	sellerItem, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 1)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "申请失败"
+		br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+		return
+	}
+
+	activityInfo, errInfo := models.GetCygxActivitySpecialDetail(activityId)
+	if activityInfo == nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "活动ID错误,不存在activityId:" + strconv.Itoa(activityId)
+		return
+	}
+	if errInfo != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作失败,Err:" + errInfo.Error()
+		return
+	}
+	//HasPermission "1:有该行业权限,正常展示,2:无该行业权限,3:潜在客户,未提交过申请,4:潜在客户,已提交过申请"`
+	//var companyDetailStatus string
+	if user.CompanyId > 1 {
+		companyPermission, err := models.GetCompanyPermission(user.CompanyId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+			return
+		}
+		if companyPermission == "" {
+			if applyCount > 0 {
+				hasPermission = 4
+			} else {
+				if sellerItem != nil {
+					hasPermission = 5
+				} else {
+					//获取权益销售信息 如果是FICC的客户类型,则默认他申请过
+					sellerItemQy, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
+					if err != nil && err.Error() != utils.ErrNoRow() {
+						br.Msg = "获取信息失败"
+						br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+						return
+					}
+					if sellerItemQy != nil {
+						hasPermission = 2
+						resp.SellerMobile = sellerItemQy.Mobile
+						resp.SellerName = sellerItemQy.RealName
+					} else {
+						hasPermission = 3
+					}
+				}
+			}
+			resp.HasPermission = hasPermission
+			resp.ActivityId = activityId
+			resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+			br.Ret = 200
+			br.Success = true
+			br.Msg = "获取成功"
+			br.Data = resp
+			return
+		}
+		companyDetail, err := models.GetCompanyDetailById(user.CompanyId)
+		if err != nil {
+			br.Msg = "获取信息失败!"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+			return
+		}
+		if companyDetail == nil {
+			br.Msg = "获取信息失败!"
+			br.ErrMsg = "客户不存在,uid:" + strconv.Itoa(user.UserId) + "CompanyId:" + strconv.Itoa(user.CompanyId)
+			return
+		}
+	}
+	var userType int
+	var permissionStr string
+	userType, permissionStr, err = services.GetUserType(user.CompanyId)
+	if err != nil {
+		br.Msg = "获取信息失败!"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	if userType == 1 && activityInfo.ChartPermissionName == "研选" {
+		br.Msg = "您暂无查看该活动权限"
+		br.ErrMsg = "被分享客户不可见,永续客户无法查看研选行业"
+		return
+	}
+
+	if user.CompanyId > 1 {
+		companyItem, err := models.GetCompanyDetailById(user.CompanyId)
+		//冻结客户
+		if err != nil {
+			if err.Error() == utils.ErrNoRow() {
+				if applyCount > 0 {
+					hasPermission = 4
+				} else {
+					if sellerItem != nil {
+						hasPermission = 5
+					} else {
+						hasPermission = 3
+					}
+				}
+				resp.ActivityId = activityId
+				resp.HasPermission = hasPermission
+				resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				br.Data = resp
+				return
+			} else {
+				br.Msg = "获取信息失败"
+				br.ErrMsg = "获取客户公司信息失败,Err:" + err.Error()
+				return
+			}
+		}
+		//判断是否有权限
+		var havePower bool
+		if strings.Contains(permissionStr, activityInfo.ActivityTypeName) {
+			havePower = true
+		}
+		if havePower {
+			hasPermission = 1
+		} else {
+			if companyItem.ProductId == 2 {
+				hasPermission = 2
+				resp.SellerMobile = companyItem.Mobile
+				resp.SellerName = companyItem.SellerName
+				if permissionStr == "专家" {
+					resp.PopupMsg = "您暂无权限参加【" + activityInfo.ActivityTypeName + "】类型活动,若想参加请联系对口销售--" + companyItem.SellerName + ":" + companyItem.Mobile
+				} else {
+					resp.PopupMsg = "您暂无权限参加【" + activityInfo.ChartPermissionName + "】行业活动,若想参加请联系对口销售--" + companyItem.SellerName + ":" + companyItem.Mobile
+				}
+			} else {
+				hasPermission = 5
+			}
+		}
+	} else { //潜在客户
+		if applyCount > 0 {
+			hasPermission = 4
+		} else {
+			if sellerItem != nil {
+				hasPermission = 5
+			} else {
+				hasPermission = 3
+			}
+		}
+		resp.PopupMsg = "您暂无权限参加此活动,若想参加可以申请开通对应的试用权限"
+	}
+	resp.HasPermission = hasPermission
+	resp.ActivityId = activityId
+	if hasPermission == 1 {
+		total, err := models.GetUserCygxActivitySpecialSignup(user.UserId, activityId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取日程数量信息失败,Err:" + err.Error()
+			return
+		}
+		//判断是删除还是添加
+		if total == 0 {
+			//获取销售信息
+			sellerItem, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
+			if err != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取销售信息失败,Err:" + err.Error()
+				return
+			}
+			item := new(models.CygxActivitySpecialSignup)
+			item.UserId = uid
+			item.RealName = user.RealName
+			item.ActivityId = activityId
+			item.CreateTime = time.Now()
+			item.Mobile = user.Mobile
+			item.Email = user.Email
+			item.CompanyId = user.CompanyId
+			item.CompanyName = user.CompanyName
+			if sellerItem != nil {
+				item.SellerName = sellerItem.RealName
+			}
+			err = models.AddCygxActivitySpecialSignup(item)
+			if err != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "操作失败,Err:" + err.Error()
+				return
+			}
+			resp.Status = 1
+
+			////给所属销售发送消息
+			if sellerItem.Mobile != "" {
+				openIpItem, _ := models.GetUserRecordByMobile(4, sellerItem.Mobile)
+				if openIpItem != nil && openIpItem.OpenId != "" {
+					if sellerItem != nil {
+						go services.SendSpecialTemplateMsg(user.RealName+"【"+user.CompanyName+"】", time.Now().Format(utils.FormatDateTime), user.Mobile, activityInfo.ResearchTheme, openIpItem.OpenId, "sale")
+					}
+				}
+			}
+			// 给芳姐发消息
+			cnf, _ := models.GetConfigByCode("tpl_msg")
+			if cnf != nil {
+				openIpItem, _ := models.GetUserRecordByMobile(4, cnf.ConfigValue)
+				if openIpItem != nil && openIpItem.OpenId != "" {
+					actList, _ := models.GetActivityListSpecialAll(activityId)
+					if len(actList) == 5 {
+						var companyName string
+						for _, v := range actList {
+							companyName += "【" + v.CompanyName + "】"
+						}
+						go services.SendSpecialTemplateMsg(companyName, "", "", activityInfo.ResearchTheme, openIpItem.OpenId, "")
+					}
+				}
+			}
+		} else {
+			err = models.DeleteCygxActivitySpecialSignup(user.UserId, activityId)
+			if err != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "操作失败,Err:" + err.Error()
+				return
+			}
+			resp.Status = 2
+		}
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+	br.Data = resp
+}
+
+// @Title 新调研通知取消跟添加
+// @Description 新调研通知取消跟添加接口
+// @Param	request	body models.ArticleCollectResp true "type json string"
+// @Success 200
+// @router /special/follow [post]
+func (this *ActivityCoAntroller) SpecialMsg() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	resp := new(models.ArticleCollectResp)
+	count, err := models.GetCygxUserFollowSpecial(user.UserId)
+	if err != nil {
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+		return
+	}
+	if count == 0 {
+		item := new(models.CygxUserFollowSpecial)
+		item.UserId = user.UserId
+		item.RealName = user.RealName
+		item.CreateTime = time.Now()
+		item.Mobile = user.Mobile
+		item.Email = user.Email
+		item.CompanyId = user.CompanyId
+		item.CompanyName = user.CompanyName
+		item.CreateTime = time.Now()
+		err := models.AddUserFollowSpecial(item)
+		if err != nil {
+			br.Msg = "操作失败!"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+			return
+		}
+		resp.Status = 1
+	} else {
+		err := models.DeleteCygxUserFollowSpecial(user.UserId)
+		if err != nil {
+			br.Msg = "操作失败!"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+			return
+		}
+		resp.Status = 2
+	}
+	br.Ret = 200
+	br.Data = resp
+	br.Success = true
+	br.Msg = "操作成功!"
+}

+ 16 - 6
controllers/article.go

@@ -90,7 +90,7 @@ func (this *ArticleController) Detail() {
 		detail.Body = strings.Replace(detail.Body, "<p data-f-id=\"pbf\" style=\"text-align: center; font-size: 14px; margin-top: 30px; opacity: 0.65; font-family: sans-serif;\">Powered by <a href=\"https://www.froala.com/wysiwyg-editor?pb=1\" title=\"Froala Editor\">Froala Editor</a></p>", "", -1)
 		detail.Body = strings.Replace(detail.Body, "pre", "div", -1)
 		//detail.Abstract = html.UnescapeString(detail.Abstract)
-		detail.Abstract, _ = services.GetReportContentTextSub(detail.Abstract)
+		detail.Abstract, _ = services.GetReportContentTextSubNew(detail.Abstract)
 		if companyPermission == "" {
 			if applyCount > 0 {
 				hasPermission = 5
@@ -238,9 +238,9 @@ func (this *ArticleController) Detail() {
 		}
 		//获取销售手机号
 		sellerItem, err := models.GetSellerByCompanyId(user.CompanyId)
-		if err != nil {
+		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取信息失败"
-			br.ErrMsg = "获取销售数据失败2,Err:" + strconv.Itoa(uid) + ";articleId" + strconv.Itoa(articleId)
+			br.ErrMsg = "获取销售数据失败2,Err:" + err.Error() + strconv.Itoa(uid) + ";articleId" + strconv.Itoa(articleId)
 			return
 		}
 		if sellerItem != nil {
@@ -266,6 +266,13 @@ func (this *ArticleController) Detail() {
 			}
 		}
 		detail.SellerList = sellerList
+		//作者头像
+		if detail.DepartmentId > 0 {
+			departmentDetail, err := models.GetArticleDepartmentDateilById(detail.DepartmentId)
+			if err == nil {
+				detail.DepartmentImgUrl = departmentDetail.ImgUrl
+			}
+		}
 	} else { //潜在客户
 		if applyCount > 0 {
 			hasPermission = 5
@@ -298,7 +305,6 @@ Loop:
 		haveResearch = true
 	}
 
-	fmt.Println("hasPermission", hasPermission)
 	if hasPermission == 2 || hasPermission == 4 {
 		//获取销售手机号
 		sellerItemQy, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
@@ -313,6 +319,11 @@ Loop:
 			detail.SellerName = sellerItemQy.RealName
 		}
 	}
+	if detail.ArticleId < utils.SummaryArticleId {
+		detail.HttpUrl = utils.StrategyPlatform + strconv.Itoa(articleId)
+		detail.IsNeedJump = true
+	}
+
 	resp := new(models.ArticleDetailResp)
 	resp.HasPermission = hasPermission
 	resp.HaveResearch = haveResearch
@@ -871,7 +882,7 @@ func (this *ArticleController) Pdfwatermark() {
 	//缓存校验
 	cacheKey := fmt.Sprint("xygx:apply_record:add:", uid, "ArticleId_", articleId)
 	ttlTime := utils.Rc.GetRedisTTL(cacheKey)
-	if ttlTime > 0 {
+	if ttlTime > 0 && user.CompanyId != 16 {
 		br.Msg = "下载失败,下载过于频繁"
 		br.ErrMsg = "下载失败,下载过于频繁:mobile" + user.Mobile
 		return
@@ -933,7 +944,6 @@ func (this *ArticleController) Pdfwatermark() {
 		writer := bufio.NewWriter(file)
 		written, _ := io.Copy(writer, reader)
 		fmt.Printf("Total length: %d", written)
-
 	}
 	newFile = uploadDir + "new_" + pdfName
 	onTop := true

+ 5 - 0
controllers/home.go

@@ -6,6 +6,7 @@ import (
 	"hongze/hongze_cygx/services"
 	"hongze/hongze_cygx/utils"
 	"html"
+	"strconv"
 	"strings"
 )
 
@@ -159,6 +160,10 @@ func (this *HomeController) ListHome() {
 		} else {
 			list[k].ImgUrlPc = mapCategoryUrl[v.CategoryId]
 		}
+		if list[k].ArticleId < utils.SummaryArticleId {
+			list[k].HttpUrl = utils.StrategyPlatform + strconv.Itoa(v.ArticleId)
+			list[k].IsNeedJump = true
+		}
 	}
 	resp.List = list
 	resp.Paging = page

+ 139 - 2
controllers/report.go

@@ -1297,7 +1297,7 @@ func (this *ReportController) Detail() {
 	for _, v := range listLog {
 		item := new(models.ReportSelectionChartPermission)
 		if existMap[v.ChartPermissionId] == 0 {
-			item.PermissionName = v.PermissionName + "领域深度调研和报告"
+			item.PermissionName = v.PermissionName + "领域深度报告和调研"
 			item.IcoLink = v.IcoLink
 			listSonLog, err := models.GetReportSelectionlogSonListAll(articleId, v.ChartPermissionId)
 			if err != nil && err.Error() != utils.ErrNoRow() {
@@ -1717,7 +1717,7 @@ func (this *ReportController) RoadshowDetail() {
 			return
 		}
 		detail.Body = html.UnescapeString(detail.Body)
-		detail.Abstract, _ = services.GetReportContentTextSub(detail.Abstract)
+		detail.Abstract, _ = services.GetReportContentTextSubNew(detail.Abstract)
 		detail.PublishDate = utils.StrTimeToTime(detail.PublishDate).Format("2006-01-02")
 		detail.VideoPlaySeconds = utils.Mp3Time(detail.VideoPlaySeconds)
 		if detail.ReportLink == "0" {
@@ -2174,3 +2174,140 @@ func (this *ReportController) IndustryAndArticleListPc() {
 	br.Msg = "获取成功"
 	br.Data = resp
 }
+
+// @Title 报告搜索
+// @Description 报告搜索接口
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Success 200 {object} models.ReoprtSearchResp
+// @router /searchReport [get]
+func (this *ReportController) SearchReport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	keyWord := this.GetString("KeyWord")
+	var condition string
+	//匹配报告标题、对应产业名称、标的名称。
+	condition = `AND (
+	    a.title LIKE '%` + keyWord + `%'
+	    OR a.article_id IN ( SELECT article_id FROM cygx_industrial_article_group_subject WHERE industrial_subject_id IN ( SELECT industrial_subject_id FROM cygx_industrial_subject WHERE subject_name LIKE '%` + keyWord + `%' ) ) 
+	    OR a.article_id IN ( SELECT article_id FROM cygx_industrial_article_group_management WHERE industrial_management_id IN ( SELECT industrial_management_id FROM cygx_industrial_management WHERE industry_name LIKE '%` + keyWord + `%' ) ) 
+	)
+	GROUP BY  a.article_id  ORDER BY a.publish_date DESC  `
+	listYx, err := models.GetArticleCollectionList(` AND a.article_id >= 1000000 `+condition, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取文章列表失败,Err:" + err.Error()
+		return
+	}
+	for k, v := range listYx {
+		if v.MyCollectNum > 0 {
+			listYx[k].IsCollect = true
+		}
+	}
+	listHz, err := models.GetReoprtSearchList(` AND a.article_id < 1000000 `+condition, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取文章列表失败,Err:" + err.Error()
+		return
+	}
+	for k, v := range listHz {
+		if v.MyCollectNum > 0 {
+			listHz[k].IsCollect = true
+		}
+	}
+	if keyWord != "" {
+		keyWordItem := new(models.CygxUserSearchKeyWord)
+		keyWordItem.UserId = user.UserId
+		keyWordItem.KeyWord = keyWord
+		keyWordItem.PageType = "ReortSearch"
+		keyWordItem.CreateTime = time.Now()
+		go models.AddUserSearchKeyWord(keyWordItem)
+	}
+	resp := new(models.ReoprtSearchResp)
+	resp.ListYx = listYx
+	resp.ListHz = listHz
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 资源包搜索
+// @Description 资源包搜索接口
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Success 200 {object} models.SearchResourceResp
+// @router /searchResource [get]
+func (this *ReportController) SearchResource() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	keyWord := this.GetString("KeyWord")
+	var condition string
+	condition = `AND m.industry_name LIKE '%` + keyWord + `%' AND m.chart_permission_id != 31 GROUP BY m.industrial_management_id `
+	listHz, err := models.GetSearchResourceList(condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	condition = `AND m.industry_name LIKE '%` + keyWord + `%' AND m.chart_permission_id = 31 GROUP BY m.industrial_management_id `
+	listYx, err := models.GetSearchResourceList(condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取文章列表失败,Err:" + err.Error()
+		return
+	}
+	//合并产业关联的标的
+	listSubjcet, err := models.GetThemeHeatSubjectList("")
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取标的信息失败,Err:" + err.Error()
+		return
+	}
+	for k, v := range listHz {
+
+		for _, v2 := range listSubjcet {
+			if v2.IndustrialManagementId == v.IndustrialManagementId {
+				listHz[k].IndustrialSubjectList = append(listHz[k].IndustrialSubjectList, v2)
+			}
+		}
+	}
+	for k, v := range listYx {
+		for _, v2 := range listSubjcet {
+			if v2.IndustrialManagementId == v.IndustrialManagementId {
+				listYx[k].IndustrialSubjectList = append(listYx[k].IndustrialSubjectList, v2)
+			}
+		}
+	}
+	if keyWord != "" {
+		keyWordItem := new(models.CygxUserSearchKeyWord)
+		keyWordItem.UserId = user.UserId
+		keyWordItem.KeyWord = keyWord
+		keyWordItem.PageType = "ReortSearch"
+		keyWordItem.CreateTime = time.Now()
+		go models.AddUserSearchKeyWord(keyWordItem)
+	}
+	resp := new(models.SearchResourceResp)
+	resp.ListYx = listYx
+	resp.ListHz = listHz
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 512 - 0
controllers/research.go

@@ -0,0 +1,512 @@
+package controllers
+
+import (
+	"hongze/hongze_cygx/models"
+	"strconv"
+)
+
+//研选
+type ResearchController struct {
+	BaseAuthController
+}
+
+// @Title 近期更新主题列表
+// @Description 近期更新主题列表接口
+// @Param   ChartPermissionId   query   int  true       "分类ID"
+// @Success 200 {object} models.IndustrialManagementNewList
+// @router /theme/newList [get]
+func (this *ResearchController) NewList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	chartPermissionId, _ := this.GetInt("ChartPermissionId")
+	if chartPermissionId < 1 {
+		br.Msg = "请输入分类ID"
+		return
+	}
+	categoryinfo, err := models.GetChartPermissionById(chartPermissionId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetIndustrialManagementNewList(categoryinfo.PermissionName)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	mapHot := make(map[string]int)
+
+	condition := ` ORDER BY sum_num DESC LIMIT 3 `
+	listHot, err := models.GetThemeHeatList(categoryinfo.PermissionName, user.UserId, condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range listHot {
+		mapHot[v.IndustryName] = v.IndustrialManagementId
+	}
+	for k, v := range list {
+		if mapHot[v.IndustryName] > 0 {
+			list[k].IsHot = true
+		}
+	}
+	resp := new(models.IndustrialManagementNewList)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 用户收藏列表
+// @Description 用户收藏列表接口
+// @Param   ChartPermissionId   query   int  true       "分类ID"
+// @Success 200 {object} models.ArticleCollectionLIstResp
+// @router /collectionList [get]
+func (this *ResearchController) CollectionList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	chartPermissionId, _ := this.GetInt("ChartPermissionId")
+	if chartPermissionId < 1 {
+		br.Msg = "请输入分类ID"
+		return
+	}
+	categoryinfo, err := models.GetChartPermissionById(chartPermissionId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	var condition string
+	condition = `  AND a.category_name LIKE '%` + categoryinfo.PermissionName + `%' AND publish_status = 1 GROUP BY a.article_id ORDER BY collect_num DESC, publish_date DESC LIMIT 15 `
+	list, err := models.GetArticleCollectionList(condition, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	for k, v := range list {
+		if v.MyCollectNum > 0 {
+			list[k].IsCollect = true
+		}
+	}
+	resp := new(models.ArticleCollectionLIstResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 主题热度/近期更新更多,列表
+// @Description 主题热度/近期更新更多,列表接口
+// @Param   ChartPermissionId   query   int  true       "分类ID"
+// @Param   ThemeType   query   int  true       "主题类型,1主题热度、2近期更新 默认1"
+// @Success 200 {object} models.IndustrialManagementHotListResp
+// @router /hotList [get]
+func (this *ResearchController) HotList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	chartPermissionId, _ := this.GetInt("ChartPermissionId")
+	themeType, _ := this.GetInt("ThemeType")
+	if chartPermissionId < 1 {
+		br.Msg = "请输入分类ID"
+		return
+	}
+	var condition string
+	if themeType != 2 {
+		themeType = 1
+		condition = `ORDER BY sum_num DESC LIMIT 15`
+	} else {
+		condition = `ORDER BY publish_date DESC LIMIT 30`
+	}
+	categoryinfo, err := models.GetChartPermissionById(chartPermissionId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetThemeHeatList(categoryinfo.PermissionName, user.UserId, condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	newMap := make(map[int]string)
+	listNew, err := models.GetIndustrialManagementNewList(categoryinfo.PermissionName)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取产业最新信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range listNew {
+		newMap[v.IndustrialManagementId] = v.IndustryName
+	}
+	condition = ` AND a.category_name LIKE '%` + categoryinfo.PermissionName + `%' `
+	listSubjcet, err := models.GetThemeHeatSubjectList(condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取标的信息失败,Err:" + err.Error()
+		return
+	}
+	mapHot := make(map[string]int)
+
+	condition = ` ORDER BY sum_num DESC LIMIT 3 `
+	listHot, err := models.GetThemeHeatList(categoryinfo.PermissionName, user.UserId, condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range listHot {
+		mapHot[v.IndustryName] = v.IndustrialManagementId
+	}
+	for k, v := range list {
+		if newMap[v.IndustrialManagementId] != "" {
+			list[k].IsNew = true
+		}
+		if v.FllowNum > 0 {
+			list[k].IsFollw = true
+		}
+		for _, v2 := range listSubjcet {
+			if v2.IndustrialManagementId == v.IndustrialManagementId {
+				list[k].IndustrialSubjectList = append(list[k].IndustrialSubjectList, v2)
+			}
+		}
+		if mapHot[v.IndustryName] > 0 {
+			list[k].IsHot = true
+		}
+	}
+	resp := new(models.IndustrialManagementHotListResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title KOL榜列表
+// @Description KOL榜列表接口
+// @Param   ChartPermissionId   query   int  true       "分类ID"
+// @Success 200 {object} models.DepartmentListResp
+// @router /kolList [get]
+func (this *ResearchController) KolList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	chartPermissionId, _ := this.GetInt("ChartPermissionId")
+	if chartPermissionId < 1 {
+		br.Msg = "请输入分类ID"
+		return
+	}
+	categoryinfo, err := models.GetChartPermissionById(chartPermissionId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetDepartmentList(categoryinfo.PermissionName, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	listIndustrial, err := models.GetIndustrialDepartmentList(categoryinfo.PermissionName)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	departmentMap := make(map[string]string)
+	for k, v := range list {
+		if v.FllowNum > 0 {
+			list[k].IsFollw = true
+		}
+		for _, v2 := range listIndustrial {
+			if v2.DepartmentId == v.DepartmentId {
+				if departmentMap["D"+strconv.Itoa(v2.DepartmentId)+"In"+strconv.Itoa(v2.IndustrialManagementId)] == "" && len(list[k].List) < 4 {
+					list[k].List = append(list[k].List, v2)
+					departmentMap["D"+strconv.Itoa(v2.DepartmentId)+"In"+strconv.Itoa(v2.IndustrialManagementId)] = v.NickName
+				}
+			}
+		}
+	}
+	resp := new(models.DepartmentListResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 主题详情
+// @Description 主题详情接口
+// @Param   IndustrialManagementId   query   int  true       "分类ID"
+// @Success 200 {object} models.GetThemeDetailResp
+// @router /theme/detail [get]
+func (this *ResearchController) ThemeDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	industrialManagementId, _ := this.GetInt("IndustrialManagementId")
+	if industrialManagementId < 1 {
+		br.Msg = "请输入产业ID"
+		return
+	}
+	resp := new(models.GetThemeDetailResp)
+	list, err := models.GetThemeDetail(user.UserId, industrialManagementId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+
+	var itemsNull []*models.GetThemeAericleListResp
+	subjectMap := make(map[string]string)
+	for _, v := range list {
+		resp.IndustryName = v.IndustryName
+		resp.IndustrialManagementId = v.IndustrialManagementId
+		itemSubJect := new(models.IndustrialSubject)
+		itemSubJect.SubjectName = v.SubjectName
+		itemSubJect.IndustrialSubjectId = v.IndustrialSubjectId
+		if subjectMap[v.SubjectName] == "" && v.SubjectName != "" {
+			resp.ListSubject = append(resp.ListSubject, itemSubJect)
+		}
+
+		subjectMap[v.SubjectName] = v.IndustryName
+		if v.FllowNum > 0 {
+			resp.IsFollw = true
+		}
+		if v.SubjectName == "" {
+			item := new(models.GetThemeAericleListResp)
+			item.ArticleId = v.ArticleId
+			item.Title = v.Title
+			item.PublishDate = v.PublishDate
+			item.SubjectName = v.SubjectName
+			item.DepartmentId = v.DepartmentId
+			item.NickName = v.NickName
+			item.Pv = v.Pv
+			item.CollectNum = v.CollectNum
+			itemsNull = append(itemsNull, item)
+		}
+	}
+
+	for _, v := range resp.ListSubject {
+		subjetcGroup := new(models.GetThemeAericleListBuSubjectResp)
+		for _, v2 := range list {
+			if v2.IndustrialSubjectId == v.IndustrialSubjectId {
+				item := new(models.GetThemeAericleListResp)
+				item.ArticleId = v2.ArticleId
+				item.Title = v2.Title
+				item.PublishDate = v2.PublishDate
+				item.SubjectName = v2.SubjectName
+				item.IndustrialSubjectId = v2.IndustrialSubjectId
+				for _, v3 := range list {
+					if v3.ArticleId == v2.ArticleId && v3.SubjectName != v2.SubjectName && v3.SubjectName != "" {
+						item.SubjectName += "/" + v3.SubjectName
+					}
+				}
+				item.DepartmentId = v2.DepartmentId
+				item.NickName = v2.NickName
+				item.Pv = v2.Pv
+				item.CollectNum = v2.CollectNum
+				item.MyCollectNum = v2.MyCollectNum
+				if v2.MyCollectNum > 0 {
+					item.IsCollect = true
+				}
+				resp.List = append(resp.List, item)
+				//subjetcGroup.List = append(subjetcGroup.List, item)
+			}
+			subjetcGroup.SubjectName = v.SubjectName
+		}
+
+	}
+	//当标的为空时进行合并
+	if len(itemsNull) > 0 {
+		for _, v := range itemsNull {
+			resp.List = append(resp.List, v)
+		}
+
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 研选作者详情
+// @Description 研选作者详情接口
+// @Param   DepartmentId   query   int  true       "作者ID"
+// @Success 200 {object} models.DepartmentDetailResp
+// @router /departmentId/detail [get]
+func (this *ResearchController) DepartmentIdDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	departmentId, _ := this.GetInt("DepartmentId")
+	if departmentId < 1 {
+		br.Msg = "请输入作者ID"
+		return
+	}
+	resp := new(models.DepartmentDetailResp)
+	detail, err := models.GetDepartmentDetail(user.UserId, departmentId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取作者信息失败,Err:" + err.Error()
+		return
+	}
+	resp.DepartmentId = detail.DepartmentId
+	resp.NickName = detail.NickName
+	resp.ImgUrl = detail.ImgUrl
+	resp.FllowNum = detail.FllowNum
+	resp.ArticleNum = detail.ArticleNum
+	resp.CollectNum = detail.CollectNum
+	if detail.MyFllowNum > 0 {
+		resp.IsFllow = true
+	}
+	var condition string
+	condition = `  AND a.department_id = ` + strconv.Itoa(departmentId) + ` ORDER BY a.publish_date DESC  `
+	list, err := models.GetArticleCollectionList(condition, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取文章列表失败,Err:" + err.Error()
+		return
+	}
+	for k, v := range list {
+		if v.MyCollectNum > 0 {
+			list[k].IsCollect = true
+		}
+	}
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 文章相关热门收藏
+// @Description 文章相关热门收藏接口
+// @Param   ArticleId   query   int  true       "文章ID"
+// @Success 200 {object} models.ArticleCollectionLIstResp
+// @router /article/hotList [get]
+func (this *ResearchController) ArticleHotList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	articleId, _ := this.GetInt("ArticleId")
+	if articleId < 1 {
+		br.Msg = "请输入分类ID"
+		return
+	}
+	var condition string
+	condition = ` AND a.article_id IN (SELECT article_id FROM cygx_industrial_article_group_management WHERE industrial_management_id IN (SELECT industrial_management_id  FROM cygx_industrial_article_group_management  WHERE  article_id = ` + strconv.Itoa(articleId) + ` ) ) AND a.article_id != ` + strconv.Itoa(articleId) + ` AND a.category_name LIKE '%研选%' AND publish_status = 1 GROUP BY a.article_id ORDER BY collect_num DESC, publish_date DESC LIMIT 3 `
+	list, err := models.GetArticleCollectionList(condition, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	for k, v := range list {
+		if v.MyCollectNum > 0 {
+			list[k].IsCollect = true
+		}
+	}
+	resp := new(models.ArticleCollectionLIstResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 热搜关键词
+// @Description 热搜关键词接口
+// @Success 200 {object} models.UserSearchKeyWordListResp
+// @router /hotKeyWord [get]
+func (this *ResearchController) HotKeyWord() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	//本来应该放在config控制器下,与未上线的代码冲突,所以放在这里
+	list, err := models.GetUserSearchKeyWord()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.UserSearchKeyWordListResp)
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 59 - 5
controllers/resource.go

@@ -33,7 +33,7 @@ func (this *ResourceController) Upload() {
 	}
 	ext := path.Ext(h.Filename)
 	dateDir := time.Now().Format("20060102")
-	uploadDir := "./temp/" + dateDir
+	uploadDir := "static/temp/" + dateDir
 	err = os.MkdirAll(uploadDir, 777)
 	if err != nil {
 		br.Msg = "存储目录创建失败"
@@ -50,18 +50,29 @@ func (this *ResourceController) Upload() {
 		br.ErrMsg = "文件上传失败,Err:" + err.Error()
 		return
 	}
+	//
+	////上传到阿里云
+	//resourceUrl, err := services.UploadAliyun(fileName, fpath)
+	//if err != nil {
+	//	br.Msg = "文件上传失败"
+	//	br.ErrMsg = "文件上传失败,Err:" + err.Error()
+	//	return
+	//}
+
+	savePath := uploadDir + time.Now().Format("200601/20060102/")
+	savePath += fileName
 	//上传到阿里云
-	resourceUrl, err := services.UploadAliyun(fileName, fpath)
+	err = services.UploadFileToAliyun("", fpath, savePath)
 	if err != nil {
 		br.Msg = "文件上传失败"
 		br.ErrMsg = "文件上传失败,Err:" + err.Error()
 		return
 	}
-
+	fileHost := "https://hzstatic.hzinsights.com/"
+	resourceUrl := fileHost + savePath
 	defer func() {
 		os.Remove(fpath)
 	}()
-
 	item := new(models.Resource)
 	item.ResourceUrl = resourceUrl
 	item.ResourceType = 1
@@ -81,4 +92,47 @@ func (this *ResourceController) Upload() {
 	br.Success = true
 	br.Data = resp
 	return
-}
+}
+
+//type ChartPermissionRepMore struct {
+//	PermissionName string `description:"名称"`
+//}
+//
+//func init() {
+//	var list []*ChartPermissionRepMore
+//	//lista := []*ChartPermissionRepMore{{PermissionName: "A1"}}
+//	lista := []*ChartPermissionRepMore{{PermissionName: "A1"}, {PermissionName: "A2"}, {PermissionName: "A3"}, {PermissionName: "A4"}, {PermissionName: "A5"}, {PermissionName: "A6"}, {PermissionName: "A7"}, {PermissionName: "A8"}, {PermissionName: "A9"}, {PermissionName: "A10"}}
+//	//listb := []*ChartPermissionRepMore{{PermissionName: "B1"}, {PermissionName: "B2"}, {PermissionName: "B3"}, {PermissionName: "B4"}, {PermissionName: "B5"}, {PermissionName: "B6"}, {PermissionName: "B7"}, {PermissionName: "B8"}, {PermissionName: "B9"}, {PermissionName: "B10"}, {PermissionName: "11"}, {PermissionName: "B12"}}
+//	listb := []*ChartPermissionRepMore{{PermissionName: "B1"}, {PermissionName: "B2"}, {PermissionName: "B3"}, {PermissionName: "B4"}, {PermissionName: "B5"}, {PermissionName: "B6"}, {PermissionName: "B7"}, {PermissionName: "B8"}, {PermissionName: "B9"}, {PermissionName: "B10"}}
+//
+//	if len(lista) == 0 {
+//		list = listb
+//	} else if len(listb) == 0 {
+//		list = lista
+//	} else {
+//		var maxNum, forMinNum int
+//		if len(lista)-1 >= len(listb) {
+//			maxNum = len(lista)
+//		} else {
+//			maxNum = len(listb)
+//		}
+//		list = append(list, lista[0])
+//
+//		forMinNum = maxNum / 2
+//		for i := 0; i <= forMinNum; i++ {
+//			for k, v := range listb {
+//				if k/2 < i+1 && k/2 >= i {
+//					list = append(list, v)
+//				}
+//			}
+//			for k, v := range lista {
+//				if k > 2*i && k <= 2*(i+1) && k != 0 {
+//					list = append(list, v)
+//				}
+//			}
+//		}
+//	}
+//	for _, v := range list {
+//		fmt.Println(v)
+//	}
+//}

+ 245 - 123
controllers/user.go

@@ -157,10 +157,33 @@ func (this *UserController) Login() {
 		loginLog.Remark = token
 		go models.AddWxUserLog(loginLog)
 	}
-
+	//添加邀请绑定关系
+	{
+		if req.ShareUserCode != "" {
+			count, _ := models.GetUserInviteeCount(userId)
+			if count == 0 {
+				userItem := new(models.UserInvitee)
+				userItem.CreateTime = time.Now()
+				userItem.InviteedUserId = strconv.Itoa(userId)
+				userItem.InviteeUserId = req.ShareUserCode
+				shareUserId, _ := strconv.Atoi(req.ShareUserCode)
+				inviteeUser, _ := models.GetWxUserItemByUserId(shareUserId)
+				if inviteeUser != nil {
+					userItem.InviteeMobile = inviteeUser.Mobile
+					userItem.InviteeCompany = inviteeUser.CompanyName
+					userItem.InviteeCompanyId = inviteeUser.CompanyId
+					userItem.InviteeEmail = inviteeUser.Email
+				}
+				models.AddUserInvite(userItem)
+			}
+		}
+	}
 	resp := new(models.LoginResp)
 	resp.UserId = userId
 	resp.Authorization = token
+	if user.CompanyId == 1 {
+		resp.IsPotential = true
+	}
 	br.Ret = 200
 	br.Success = true
 	br.Data = resp
@@ -199,7 +222,9 @@ func (this *UserController) Detail() {
 		userRecord, _ := models.GetUserRecordByUserId(uid, utils.WxPlatform)
 		if userRecord != nil {
 			detail.NickName = userRecord.NickName
-			detail.Headimgurl = userRecord.Headimgurl
+			if detail.Headimgurl == "" {
+				detail.Headimgurl = userRecord.Headimgurl
+			}
 			if detail.Headimgurl == "" {
 				userRecord, _ = models.GetUserRecordByUserId(uid, 1)
 				if userRecord != nil {
@@ -275,6 +300,9 @@ func (this *UserController) Detail() {
 		hasPermission = 2
 		detail.HasPermission = hasPermission
 	}
+	if detail.Headimgurl == "" {
+		detail.Headimgurl = utils.DefaultHeadimgurl
+	}
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -742,6 +770,8 @@ func (this *UserController) ApplyTryOut() {
 			mobile = user.Email
 		}
 	}
+	//用户状态,1:潜在客户 、2:现有客户 、3:FICC客户 、4:现有客户(正式,无对应权限) 、5:现有客户(试用,无对应权限)  、6:现有客户(试用暂停) 、7:现有客户(冻结) 、8:现有客户(流失)?
+	CompanyIdType := 1
 	applyMethod := ""
 	cnf, _ := models.GetConfigByCode("tpl_msg")
 	if cnf != nil {
@@ -754,14 +784,28 @@ func (this *UserController) ApplyTryOut() {
 				return
 			}
 			if companyItem != nil && companyItem.CompanyId > 0 {
+				companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
+				if err != nil && err.Error() != utils.ErrNoRow() {
+					br.Msg = "获取信息失败"
+					br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
+					return
+				}
+				if companyProduct != nil && companyProduct.IsSuspend == 1 {
+					CompanyIdType = 6
+				} else {
+					switch companyItem.Status {
+					case "正式":
+						CompanyIdType = 4
+					case "试用":
+						CompanyIdType = 5
+					case "冻结":
+						CompanyIdType = 7
+					case "流失":
+						CompanyIdType = 8
+					}
+				}
 				applyMethod = companyItem.Status + "客户申请"
 				if detailId > 0 {
-					companyProduct, err := models.GetCompanyProductDetail(user.CompanyId, 2)
-					if err != nil && err.Error() != utils.ErrNoRow() {
-						br.Msg = "获取信息失败"
-						br.ErrMsg = "获取客户信息失败,Err:" + err.Error()
-						return
-					}
 					if companyProduct != nil && companyProduct.IsSuspend == 1 {
 						applyMethod = "试用暂停客户"
 					} else {
@@ -783,8 +827,10 @@ func (this *UserController) ApplyTryOut() {
 				return
 			}
 			if sellerItem != nil {
+				CompanyIdType = 3
 				applyMethod = "FICC客户"
 			} else {
+				CompanyIdType = 1
 				applyMethod = "潜在客户"
 			}
 			if detailId > 0 {
@@ -802,7 +848,7 @@ func (this *UserController) ApplyTryOut() {
 			go services.SendPermissionApplyTemplateMsg(req.RealName, req.CompanyName, mobile, openIpItem.OpenId, applyMethod)
 		}
 	}
-	err = models.AddApplyRecord(&req, user.Mobile, user.CompanyName, uid, user.CompanyId)
+	err = models.AddApplyRecord(&req, user.Mobile, user.CompanyName, uid, user.CompanyId, CompanyIdType)
 	if err != nil {
 		br.Msg = "申请失败"
 		br.ErrMsg = "申请失败,Err:" + err.Error()
@@ -898,40 +944,6 @@ func (this *UserController) AddCountryCcode() {
 	br.Msg = "新增成功"
 }
 
-//// @Title 是否需要填写外呼手机号
-//// @Description 获取是否需要填写外呼手机号接口
-//// @Success 200 {object} models.CountryCode
-//// @router /countryCcode/isNeedAddOutbound [get]
-//func (this *UserController) OutboundMobile() {
-//	br := new(models.BaseResponse).Init()
-//	defer func() {
-//		this.Data["json"] = br
-//		this.ServeJSON()
-//	}()
-//	user := this.User
-//	uid := user.UserId
-//	if user == nil {
-//		br.Msg = "请登录"
-//		br.ErrMsg = "请登录,用户信息为空"
-//		br.Ret = 408
-//		return
-//	}
-//	if uid == 0 {
-//		br.Msg = "请登录"
-//		br.ErrMsg = "请登录,用户信息为空"
-//		br.Ret = 408
-//		return
-//	}
-//	resp := new(models.OutboundMobile)
-//	if user.OutboundMobile == "" && user.CountryCode == "" {
-//		resp.IsNeedAddOutboundMobile = true
-//	}
-//	br.Ret = 200
-//	br.Success = true
-//	br.Msg = "获取成功"
-//	br.Data = resp
-//}
-
 // @Title 用户修改外呼手机号以及区号
 // @Description 用户修改外呼手机号以及区号接口
 // @Param	request	body models.OutboundMobileItem true "type json string"
@@ -1014,101 +1026,151 @@ func (this *UserController) AddOutboundMobile() {
 	br.Msg = "操作成功"
 }
 
-// @Title  白名单同步
-// @Description 获取是否需要填写区号接口
-// @Param   Keypd   query   string  false       "搜索主题 多个用 , 隔开 (空为活动主题,非空为更多主题)"
-// @Success 200 {object} models.CountryCode
-// @router /whiteUser [get]
-func (this *UserController) WhiteUser() {
+// @Title 获取我的提问
+// @Description 获取我的提问列表
+// @Success 200 {object} models.CygxAskListResp
+// @router /ask/list [get]
+func (this *UserController) AskList() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
 	user := this.User
-	uid := user.UserId
 	if user == nil {
 		br.Msg = "请登录"
 		br.ErrMsg = "请登录,用户信息为空"
 		br.Ret = 408
 		return
 	}
-	if uid == 0 {
-		br.Msg = "请登录"
-		br.ErrMsg = "请登录,用户信息为空"
-		br.Ret = 408
+	userId := this.User.UserId
+	listActcivity, err := models.GetActivityAskList(userId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取活动问题失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range listActcivity {
+		v.AskType = "Activity"
+	}
+	listArticle, err := models.GetArticleAskList(userId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取文章问题失败,Err:" + err.Error()
 		return
 	}
-	keypd := this.GetString("Keypd")
+	for _, v := range listArticle {
+		v.AskType = "Report"
+		listActcivity = append(listActcivity, v)
+	}
+	resp := new(models.CygxAskListResp)
+	resp.List = listActcivity
+	br.Msg = "获取成功!"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+}
 
-	if keypd != "888wqrerqesdfdsfsdwdsfasdqwerqwer" {
-		br.Msg = "密码错误"
+// @Title 是否展示免费试用按钮
+// @Description 获取是否展示免费试用按钮接口
+// @Param	request	body models.IsShow true "type json string"
+// @Success 200
+// @router /isShow/freeButton [get]
+func (this *UserController) IsShow() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
 		return
 	}
-	item := new(models.WxUserWhite)
-	fmt.Println(item)
-	var fieldStr string
-	var condition string
-	fieldStr = ` u.mobile,u.country_code,u.real_name,c.company_name,u.company_id,cp.seller_name,u.created_time,cp.status,`
-	condition = `  AND cp.status IN ( '正式', '试用' ) AND u.mobile != ''  `
-	list1, err := models.GetFormalUserWhiteList(fieldStr, condition)
+	var resp models.IsShow
+	detail, err := models.GetConfigByCode("free_trial_card")
 	if err != nil {
-		br.Msg = "获取失败,Err:" + err.Error()
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "城市配置信息失败,Err:" + err.Error()
+		return
+	}
+	companyDetail, err := models.GetCompanyDetailByIdGroup(user.CompanyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+		return
+	}
+	count, err := models.CountCygxUserFreeeButton(user.UserId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+		return
+	}
+	if companyDetail != nil && companyDetail.IsSuspend == 0 {
+		if detail.ConfigValue == "1" && (companyDetail.Status == "正式" || companyDetail.Status == "试用" || companyDetail.Status == "永续") && count == 0 {
+			resp.IsShow = true
+		}
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+}
+
+// @Title 隐藏当天的按钮
+// @Description 隐藏当天的按钮接口
+// @Success 200
+// @router /freeButton/update [post]
+func (this *UserController) FreeButtonUpdate() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
 		return
 	}
-	fieldStr = ` u.outbound_mobile as mobile,u.outbound_country_code as country_code,u.real_name,c.company_name,u.company_id,u.created_time,cp.status,`
-	condition = ` AND u.mobile != u.outbound_mobile AND cp.status IN ( '正式', '试用' ) AND u.outbound_mobile != ''  `
-	list2, err := models.GetFormalUserWhiteList(fieldStr, condition)
+	count, err := models.CountCygxUserFreeeButtonByUser(user.UserId)
 	if err != nil {
-		br.Msg = "获取失败,Err:" + err.Error()
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
 		return
 	}
-	fmt.Println(len(list1))
-	for k, v := range list1 {
-		item.Mobile = v.Mobile
-		item.CountryCode = v.CountryCode
-		item.CompanyName = v.CompanyName
-		item.PermissionName = v.Permission
-		item.CreatedTime = time.Now()
-		item.UserCreatedTime = v.CreatedTime
-		item.RealName = v.RealName
-		item.SellerName = v.SellerName
-		item.Status = v.Status
-		_, err := models.AddWxUserWhite(item)
+	if count == 0 {
+		item := new(models.CygxUserFreeeButton)
+		item.UserId = user.UserId
+		item.CompanyId = user.CompanyId
+		item.CreateTime = time.Now()
+		item.ModifyTime = time.Now()
+		item.EffectiveTime = time.Now().Format(utils.FormatDate)
+		_, err := models.AddCygxUserFreeeButton(item)
 		if err != nil {
-			br.Msg = "获取失败,Err:" + err.Error()
+			br.Msg = "操作失败!"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
 			return
 		}
-		fmt.Println(k)
-	}
-	item = new(models.WxUserWhite)
-	fmt.Println(len(list2))
-	for _, v := range list2 {
-		item.OutboundMobile = v.Mobile
-		item.OutboundCountryCode = v.CountryCode
-		item.CreatedTime = time.Now()
-		item.CompanyName = v.CompanyName
-		item.PermissionName = v.Permission
-		item.UserCreatedTime = v.CreatedTime
-		item.RealName = v.RealName
-		item.SellerName = v.SellerName
-		item.Status = v.Status
-		_, err := models.AddWxUserWhite(item)
+	} else {
+		err := models.UpdateCygxUserFreeeButton(user.UserId)
 		if err != nil {
-			br.Msg = "获取失败,Err:" + err.Error()
+			br.Msg = "操作失败!"
+			br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
 			return
 		}
 	}
 	br.Ret = 200
 	br.Success = true
-	br.Msg = "获取成功"
+	br.Msg = "操作成功!"
 }
 
-// @Title 获取我的提问
-// @Description 获取我的提问列表
-// @Success 200 {object} models.CygxAskListResp
-// @router /ask/list [get]
-func (this *UserController) AskList() {
+// @Title 权限弹窗是否展示免费月卡
+// @Description 获取权限弹窗是否展示免费月卡接口
+// @Param	request	body models.IsShow true "type json string"
+// @Success 200
+// @router /isShow/alert [get]
+func (this *UserController) AlertIsShow() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
 		this.Data["json"] = br
@@ -1116,35 +1178,95 @@ func (this *UserController) AskList() {
 	}()
 	user := this.User
 	if user == nil {
-		br.Msg = "请登录"
-		br.ErrMsg = "请登录,用户信息为空"
+		br.Msg = "请重新登录"
 		br.Ret = 408
 		return
 	}
-	userId := this.User.UserId
-	listActcivity, err := models.GetActivityAskList(userId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取活动问题失败,Err:" + err.Error()
+	var resp models.IsShow
+	detail, err := models.GetConfigByCode("free_trial_card")
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "城市配置信息失败,Err:" + err.Error()
 		return
 	}
-	for _, v := range listActcivity {
-		v.AskType = "Activity"
+	if user.CompanyId == 1 && detail.ConfigValue == "1" {
+		resp.IsShow = true
 	}
-	listArticle, err := models.GetArticleAskList(userId)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取文章问题失败,Err:" + err.Error()
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+}
+
+// @Title 分享的时候是否展示免费月卡
+// @Description 获取权限弹窗是否展示免费月卡接口
+// @Param	request	body models.IsShow true "type json string"
+// @Success 200
+// @router /isShow/share [get]
+func (this *UserController) ShareIsShow() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
 		return
 	}
-	for _, v := range listArticle {
-		v.AskType = "Report"
-		listActcivity = append(listActcivity, v)
+	var resp models.IsShow
+	detail, err := models.GetConfigByCode("free_trial_card")
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "城市配置信息失败,Err:" + err.Error()
+		return
+	}
+	if user.CompanyId != 16 && detail.ConfigValue == "1" {
+		resp.IsShow = true
 	}
-	resp := new(models.CygxAskListResp)
-	resp.List = listActcivity
-	br.Msg = "获取成功!"
 	br.Ret = 200
 	br.Success = true
 	br.Data = resp
 }
+
+// @Title 更改用户微信头像
+// @Description 更改用户微信头像
+// @Param	request	body models.Headimgurl true "type json string"
+// @Success 200 {object} models.ArticleDetailFileLink
+// @router /headimgurl/update [post]
+func (this *UserController) HeadimgurlUpdate() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,用户信息为空"
+		br.Ret = 408
+		return
+	}
+	var req models.Headimgurl
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	uid := user.UserId
+	headimgurl := req.Headimgurl
+	if headimgurl == "" {
+		br.Msg = "操作失败"
+		br.ErrMsg = "头像信息不能为空"
+		return
+	}
+	err = models.UpdateUserHeadimgurl(headimgurl, uid)
+	if err != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "头像信息不能为空"
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 139 - 0
controllers/wechat.go

@@ -7,7 +7,12 @@ import (
 	"hongze/hongze_cygx/models"
 	"hongze/hongze_cygx/services"
 	"hongze/hongze_cygx/utils"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"os"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -420,3 +425,137 @@ func (this *WechatCommonController) WechatLoginByxzs() {
 	br.Msg = "获取成功"
 	br.Data = item
 }
+
+// @Title 获取小程序分享二维码
+// @Description 获取小程序分享二维码
+// @Success 200 {object} models.ArticleDetailFileLink
+// @router /shareImage [post]
+func (this *WechatController) ShareImage() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,用户信息为空"
+		br.Ret = 408
+		return
+	}
+	uid := user.UserId
+	itemToken, err := services.WxGetToken()
+	if err != nil {
+		br.Msg = "分享失败"
+		br.ErrMsg = "获取itemToken失败,Err:" + err.Error()
+		return
+	}
+	if itemToken.AccessToken == "" {
+		br.Msg = "accessToken is empty"
+		return
+	}
+	var envVersion string
+	var resourceUrl string
+	if utils.RunMode == "release" {
+		envVersion = "release"
+	} else {
+		envVersion = "develop"
+	}
+	url := "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + itemToken.AccessToken
+	method := "POST"
+	payload := strings.NewReader(`{
+		"page":"pageMy/excessivePages/excessivePages",
+		"scene":"` + strconv.Itoa(uid) + `",
+		"env_version":"` + envVersion + `",
+		"check_path":false,
+		"auto_color":true
+				}`)
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, payload)
+	if err != nil {
+		br.Msg = "分享失败"
+		br.ErrMsg = "获取微信二维码失败,Err:" + err.Error()
+		return
+	}
+	req.Header.Add("Content-Type", "application/json")
+	postBody, err := client.Do(req)
+	if err != nil {
+		br.Msg = "分享失败"
+		br.ErrMsg = "获取微信二维码失败,Err:" + err.Error()
+		return
+	}
+	defer postBody.Body.Close()
+	uploadDir := "static/img/share/"
+	uuid := utils.GetRandStringNoSpecialChar(28)
+	if !utils.FileIsExist(uploadDir) {
+		err = os.MkdirAll(uploadDir, 0755)
+		if err != nil {
+			br.Msg = "分享失败"
+			br.ErrMsg = "生成文件夹失败,Err:" + err.Error()
+			return
+		}
+	}
+	imagePath := uploadDir + uuid + ".jpg"
+	switch header := postBody.Header.Get("Content-Type"); {
+	case strings.HasPrefix(header, "application/json"):
+		tokenResp := models.ReturnBodyRule{}
+		decoder := json.NewDecoder(postBody.Body)
+		if decodeErr := decoder.Decode(&tokenResp); decodeErr != nil {
+			br.Msg = "分享失败"
+			br.ErrMsg = "获取微信二维码失败,Err:" + decodeErr.Error()
+			return
+		}
+	case strings.HasPrefix(header, "image"):
+		reply, err := ioutil.ReadAll(postBody.Body)
+		if err != nil {
+			br.Msg = "分享失败"
+			br.ErrMsg = "获取微信二维码失败,Err:" + err.Error()
+			return
+		}
+		imageContent, createErr := os.Create(imagePath)
+		if createErr != nil {
+			br.Msg = "分享失败"
+			br.ErrMsg = "获取微信二维码失败,Err:" + createErr.Error()
+			return
+		}
+		writeStringRes, writeStringErr := io.WriteString(imageContent, string(reply))
+		if writeStringErr != nil {
+			fmt.Println(writeStringRes)
+			br.Msg = "分享失败"
+			br.ErrMsg = "获取微信二维码失败,Err:" + writeStringErr.Error()
+			return
+		}
+		closeErr := imageContent.Close()
+		if closeErr != nil {
+			br.Msg = "分享失败"
+			br.ErrMsg = "获取微信二维码失败,Err:" + closeErr.Error()
+			return
+		}
+		randStr := utils.GetRandStringNoSpecialChar(28)
+		fileName := randStr + ".jpg"
+		savePath := uploadDir + time.Now().Format("200601/20060102/")
+		savePath += fileName
+		//上传到阿里云
+		err = services.UploadFileToAliyun(fileName, imagePath, savePath)
+		if err != nil {
+			fmt.Println("文件上传失败,Err:" + err.Error())
+			return
+		}
+		fileHost := "https://hzstatic.hzinsights.com/"
+		resourceUrl = fileHost + savePath
+		defer func() {
+			os.Remove(imagePath)
+		}()
+	default:
+		br.Msg = "分享失败"
+		br.ErrMsg = "没有获取到分享二维码"
+		return
+	}
+	resp := new(models.ArticleDetailFileLink)
+	resp.FileLink = resourceUrl
+	resp.Scene = strconv.Itoa(uid)
+	br.Ret = 200
+	br.Data = resp
+	br.Success = true
+	br.Msg = "提交成功"
+}

+ 6 - 9
go.mod

@@ -4,20 +4,17 @@ go 1.16
 
 require (
 	github.com/PuerkitoBio/goquery v1.8.0
-	github.com/aliyun/aliyun-oss-go-sdk v2.2.1+incompatible
+	github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible
 	github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
-	github.com/beego/beego/v2 v2.0.1
+	github.com/beego/beego/v2 v2.0.2
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
-	github.com/elastic/go-elasticsearch/v7 v7.16.0
+	github.com/elastic/go-elasticsearch/v7 v7.17.1
 	github.com/go-sql-driver/mysql v1.6.0
-	github.com/medivhzhan/weapp/v2 v2.4.2
-	github.com/olivere/elastic/v7 v7.0.29
+	github.com/medivhzhan/weapp/v2 v2.5.0
+	github.com/olivere/elastic/v7 v7.0.32
 	github.com/pdfcpu/pdfcpu v0.3.13
-	github.com/prometheus/procfs v0.7.3 // indirect
-	github.com/rdlucklib/rdluck_tools v1.0.2
+	github.com/rdlucklib/rdluck_tools v1.0.3
 	github.com/satori/go.uuid v1.2.0 // indirect
 	github.com/tealeg/xlsx v1.0.5
-	golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
-	golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )

+ 340 - 51
go.sum

@@ -1,83 +1,145 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
 github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
+github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
+github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
-github.com/aliyun/aliyun-oss-go-sdk v2.2.0+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
-github.com/aliyun/aliyun-oss-go-sdk v2.2.1+incompatible h1:uuJIwCFhbZy+zdvLy5zrcIToPEQP0s5CFOZ0Zj03O/w=
-github.com/aliyun/aliyun-oss-go-sdk v2.2.1+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
+github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
+github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
 github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
 github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
 github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
-github.com/aws/aws-sdk-go v1.40.43/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
+github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
+github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.43.21/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
+github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
+github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
 github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
-github.com/beego/beego/v2 v2.0.1 h1:07a7Z0Ok5vbqyqh+q53sDPl9LdhKh0ZDy3gbyGrhFnE=
-github.com/beego/beego/v2 v2.0.1/go.mod h1:8zyHi1FnWO1mZLwTn62aKRIZF/aIKvkCBB2JYs+eqQI=
+github.com/beego/beego/v2 v2.0.2 h1:Mx2MWMHJN1oFBHewHWyIhR25tXB9IPceIK8X7OuMdZM=
+github.com/beego/beego/v2 v2.0.2/go.mod h1:4pxstbxq+2qE8IUzFsVK8X9BsqfRjbp7ohbapTrTLho=
 github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
 github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
+github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
 github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
+github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog=
+github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
+github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
+github.com/couchbase/go-couchbase v0.1.0/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
 github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
+github.com/couchbase/gomemcached v0.1.3/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
 github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
+github.com/couchbase/goutils v0.1.0/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
-github.com/elastic/go-elasticsearch/v7 v7.16.0 h1:GHsxDFXIAlhSleXun4kwA89P7kQFADRChqvgOPeYP5A=
-github.com/elastic/go-elasticsearch/v7 v7.16.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
+github.com/elastic/go-elasticsearch/v6 v6.8.10/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
+github.com/elastic/go-elasticsearch/v7 v7.17.1 h1:49mHcHx7lpCL8cW1aioEwSEVKQF3s+Igi4Ye/QTWwmk=
+github.com/elastic/go-elasticsearch/v7 v7.17.1/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
 github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
+github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
+github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
+github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
+github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/garyburd/redigo v1.6.3 h1:HCeeRluvAgMusMomi1+6Y5dmFOdYV/JzoRrrbFlkGIc=
 github.com/garyburd/redigo v1.6.3/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
+github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
 github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
 github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -85,11 +147,15 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -97,223 +163,431 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
+github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
+github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
+github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hhrutter/lzw v0.0.0-20190827003112-58b82c5a41cc/go.mod h1:yJBvOcu1wLQ9q9XZmfiPfur+3dQJuIhYQsMGLYcItZk=
 github.com/hhrutter/lzw v0.0.0-20190829144645-6f07a24e8650 h1:1yY/RQWNSBjJe2GDCIYoLmpWVidrooriUr4QS/zaATQ=
 github.com/hhrutter/lzw v0.0.0-20190829144645-6f07a24e8650/go.mod h1:yJBvOcu1wLQ9q9XZmfiPfur+3dQJuIhYQsMGLYcItZk=
 github.com/hhrutter/tiff v0.0.0-20190829141212-736cae8d0bc7 h1:o1wMw7uTNyA58IlEdDpxIrtFHTgnvYzA8sCQz8luv94=
 github.com/hhrutter/tiff v0.0.0-20190829141212-736cae8d0bc7/go.mod h1:WkUxfS2JUu3qPo6tRld7ISb8HiC0gVSU91kooBMDVok=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
 github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
+github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
+github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
 github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
 github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/medivhzhan/weapp/v2 v2.4.2 h1:A0Sdjs9Yhpreh+KIZfV2w+R9iB0hCsZ45SwSPqlTD+0=
-github.com/medivhzhan/weapp/v2 v2.4.2/go.mod h1:lcP2Go0ow4ElqGsEQwEeyTZiiEhr+lC5zMxGZGA7Bsc=
-github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
-github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/medivhzhan/weapp/v2 v2.5.0 h1:WfgSHdZ34xM47w4b/5nGTSzaqHo1uizdDDKJsCRB2bY=
+github.com/medivhzhan/weapp/v2 v2.5.0/go.mod h1:lcP2Go0ow4ElqGsEQwEeyTZiiEhr+lC5zMxGZGA7Bsc=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
+github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
+github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
+github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
+github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/olivere/elastic/v7 v7.0.29 h1:zvorjSPHFli/0owqfoLq0ZOtVhZSyHsMbRi29Vj7T14=
-github.com/olivere/elastic/v7 v7.0.29/go.mod h1:8PlkMD2Xb690IPhIPii2SypuuXtXX3dDcSKGqnEGXzE=
+github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E=
+github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
+github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
+github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
+github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
+github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
+github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
+github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pdfcpu/pdfcpu v0.3.13 h1:VFon2Yo1PJt+sA57vPAeXWGLSZ7Ux3Jl4h02M0+s3dg=
 github.com/pdfcpu/pdfcpu v0.3.13/go.mod h1:UJc5xsXg0fpmjp1zOPdyYcAQArc/Zf3V0nv5URe+9fg=
 github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
+github.com/pelletier/go-toml v1.9.2/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
 github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
+github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
+github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
+github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
 github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
+github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
+github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/rdlucklib/rdluck_tools v1.0.2 h1:Xf1khfttpAh4D1jtMVE5OxLXhFUaDnvG74vZH7FSZQY=
-github.com/rdlucklib/rdluck_tools v1.0.2/go.mod h1:9Onw9o4w19C8KE5lxb8GyxgRBbZweRVkQSc79v38EaA=
+github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rdlucklib/rdluck_tools v1.0.3 h1:iOtK2QPlPQ6CL6c1htCk5VnFCHzyG6DCfJtunrMswK0=
+github.com/rdlucklib/rdluck_tools v1.0.3/go.mod h1:9Onw9o4w19C8KE5lxb8GyxgRBbZweRVkQSc79v38EaA=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
-github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
+github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
+github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
 github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
 github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
 github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
+github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
 github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
 github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
 github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
+github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/ylywyn/jpush-api-go-client v0.0.0-20190906031852-8c4466c6e369/go.mod h1:Nv7wKD2/bCdKUFNKcJRa99a+1+aSLlCRJFriFYdjz/I=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
-go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
+go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
+go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
+go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.opentelemetry.io/otel v1.5.0/go.mod h1:Jm/m+rNp/z0eqJc74H7LPwQ3G87qkU/AnnAydAjSAHk=
+go.opentelemetry.io/otel/trace v1.5.0/go.mod h1:sq55kfhjXYr1zVSyexg0w1mpa03AYXR5eyTkB9NPPdE=
+go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
-golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
+golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/image v0.0.0-20190823064033-3a9bac650e44/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk=
 golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
-golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag=
-golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -322,30 +596,45 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
 google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
+sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

+ 124 - 7
models/activity.go

@@ -96,6 +96,7 @@ type ActivityDetail struct {
 	LinkParticipants        string `description:"链接参会"`
 	AppAttendance           string `description:"App参会"`
 	ConferencePassword      string `description:"会议密码"`
+	Scale                   string `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
 }
 
 type CygxActivityResp struct {
@@ -156,6 +157,7 @@ type CygxActivityList struct {
 	ImgUrl                  string `description:"图片链接"`
 	ImgUrlText              string `description:"图片链接文字"`
 	ActivityType            int    `description:"活动线上线下类型 1线上,0 线下"`
+	JmcjRoadshowTitle       string `description:"进门财经手动匹配的活动名称"`
 }
 
 type GetCygxActivityListRep struct {
@@ -429,8 +431,10 @@ type SignupExportRep struct {
 }
 
 type ActivityMsgExportRep struct {
+	UserId      int    `description:"用户ID"`
 	RealName    string `description:"姓名"`
 	CompanyName string `description:"公司名称"`
+	CompanyId   int    `description:"公司ID"`
 	Content     string `description:"内容"`
 	CreateTime  string `description:"提交时间"`
 }
@@ -459,16 +463,18 @@ func UPdateActivityIdToSendFile(activityId int) (err error) {
 
 //活动详情
 type CygxActivityLabelList struct {
-	KeyWord     string `orm:"column(label)";description:"主题"`
-	Timesort    string `description:"最大时间"`
-	Mintimesort string `description:"最小时间"`
-	ImgUrlBg    string `description:"背景图片"`
+	KeyWord           string `orm:"column(label)";description:"主题"`
+	Timesort          string `description:"最大时间"`
+	Mintimesort       string `description:"最小时间"`
+	ImgUrlBg          string `description:"背景图片"`
+	ActivityId        int    `description:"活动ID "`
+	IsShowSubjectName int    `description:"小程序内是否展示标的名称 1是 ,0否 默认0 "`
 }
 
 //主题列表
 func GetActivityLabelListAll(condition, sortTime string, pars []interface{}, startSize, pageSize int) (items []*CygxActivityLabelList, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT	label, MAX( art.activity_time ) AS timesort, MIn( art.activity_time ) AS mintimesort 
+	sql := `SELECT	label,is_show_subject_name, MAX( art.activity_time ) AS timesort, MIn( art.activity_time ) AS mintimesort 
 		FROM cygx_activity as art WHERE 1= 1 `
 	if condition != "" {
 		sql += condition
@@ -546,8 +552,9 @@ func UPdateActivityMsgToSendFile(activityId int) (err error) {
 }
 
 type AskEmailRep struct {
-	Name  string `description:"姓名"`
-	Email string `description:"邮箱"`
+	Name   string `description:"姓名"`
+	Email  string `description:"邮箱"`
+	Mobile string `description:"手机号"`
 }
 
 func GetAskEmail() (item []*AskEmailRep, err error) {
@@ -556,3 +563,113 @@ func GetAskEmail() (item []*AskEmailRep, err error) {
 	_, err = o.Raw(sql).QueryRows(&item)
 	return
 }
+
+//主题列表
+func GetActivityLabelSpecialListAll(condition string, pars []interface{}, startSize, pageSize int) (items []*CygxActivityLabelList, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT	label,activity_id,is_show_subject_name
+		FROM cygx_activity_special as art WHERE 1= 1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY art.last_updated_time DESC  LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+//专项调研活动列表
+type CygxActivitySpecialDetail struct {
+	ActivityId            int    `description:"活动ID "`
+	ActivityTypeName      string `description:"活动名称"`
+	SpecialType           int    `description:"调研形式、 1 线上 , 2 线下"`
+	City                  string `description:"调研城市"`
+	ChartPermissionName   string `description:"行业名称"`
+	ResearchTheme         string `description:"调研主题"`
+	ActivityTimeText      string `description:"活动预期时间带文字"`
+	TripImgLink           string `description:"行程图片链接"`
+	IsSignup              int    `description:"是否感兴趣 1是 ,0 否"`
+	Label                 string `description:"主题标签"`
+	ImgUrl                string `description:"图片链接"`
+	ImgUrlText            string `description:"图片链接文字"`
+	IndustrialName        string `description:"产业名称"`
+	IndustrialSubjectName string `description:"标的名称(相关公司)"`
+	Scale                 string `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
+	CustomerTypeIds       string `description:"活动可见的客户类型,多个ID用 , 隔开"`
+}
+
+type GetCygxActivitySpecialDetailListResp struct {
+	IsFollow bool               `description:"是否关注新调研通知"`
+	Paging   *paging.PagingItem `description:"分页数据"`
+	List     []*CygxActivitySpecialDetail
+}
+
+type CygxActivitySpecialResp struct {
+	HaqveJurisdiction bool   `description:"是否有权限"`
+	OperationMode     string `description:"操作方式 Apply:立即申请、Call:拨号 为空则为有权限"`
+	HasPermission     int    `description:"操作方式,1:有该行业权限,正常展示,2:无该行业权限,3:潜在客户,未提交过申请,4:潜在客户,已提交过申请,5:有IFCC、无权益"`
+	PopupMsg          string `description:"权限弹窗信息"`
+	MsgType           string `description:"Type : 类型 , Industry : 行业"`
+	SellerMobile      string `description:"销售电话"`
+	SellerName        string `description:"销售姓名"`
+	Detail            *CygxActivitySpecialDetail
+}
+
+//获取数量
+func GetActivitySpecialCount(condition string, pars []interface{}) (count int, err error) {
+	sqlCount := ` SELECT COUNT(1) AS count  FROM cygx_activity_special as art WHERE 1= 1  `
+	if condition != "" {
+		sqlCount += condition
+	}
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, pars).QueryRow(&count)
+	return
+}
+
+//获取专项调研活动列表
+func GetCygxActivitySpecialDetailList(condition string, pars []interface{}, uid, startSize, pageSize int) (items []*CygxActivitySpecialDetail, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+	art.*,
+	c.image_url AS img_url,
+	(
+	SELECT
+		COUNT( 1 ) 
+	FROM
+		cygx_activity_special_signup AS s 
+	WHERE
+		s.activity_id = art.activity_id 
+		AND s.user_id = ?
+	) AS is_signup
+FROM
+	cygx_activity_special AS art
+	INNER JOIN chart_permission AS c ON c.chart_permission_id = art.chart_permission_id 
+WHERE
+	1 = 1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY art.last_updated_time DESC  LIMIT ?,? `
+	_, err = o.Raw(sql, pars, uid, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+//通过活动ID获取活动详情
+func GetCygxActivitySpecialDetailById(uid, ActivityId int) (item *CygxActivitySpecialDetail, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT *,( SELECT COUNT( 1 ) FROM cygx_activity_special_signup AS s WHERE s.activity_id = a.activity_id AND s.user_id = ? ) AS is_signup 
+FROM
+	cygx_activity_special AS a 
+WHERE
+	activity_id = ?
+	AND publish_status = 1`
+	err = o.Raw(sql, uid, ActivityId).QueryRow(&item)
+	return
+}
+
+//通过活动ID获取活动详情
+func GetCygxActivitySpecialDetail(ActivityId int) (item *CygxActivitySpecialDetail, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_activity_special  WHERE activity_id=? AND publish_status = 1 `
+	err = o.Raw(sql, ActivityId).QueryRow(&item)
+	return
+}

+ 2 - 0
models/activity_attendance_detail.go

@@ -23,6 +23,7 @@ type CygxActivityAttendanceDetail struct {
 	CreateTime            time.Time `description:"创建时间"`
 	Position              string    `description:"职位"`
 	IsMeetingStr          int       `description:"是否到会,1到会,0未到会"`
+	UseridEntity          int       `description:"参会者身份. 1:主讲人, 2:主持人, 3:嘉宾, 4:普通参会者, 5:联席主讲人, 6:会议助理"`
 }
 
 //添加会议提醒信息
@@ -99,6 +100,7 @@ type RoadshowData struct {
 	JoinType          int       `description:"参与方式, 1网络, 2电话"`
 	DataType          int       `description:"数据类型: 1直播, 2回放"`
 	Occupation        string    `description:"职位"`
+	UseridEntity      int       `description:"参会者身份. 1:主讲人, 2:主持人, 3:嘉宾, 4:普通参会者, 5:联席主讲人, 6:会议助理"`
 }
 
 func AddAttendancDetail(items []*CygxActivityAttendanceDetail, activityId int, mobileStr string) (err error) {

+ 59 - 0
models/activity_special_signup.go

@@ -0,0 +1,59 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxActivitySpecialSignup struct {
+	Id          int       `orm:"column(id);pk"`
+	ActivityId  int       `description:"活动ID"`
+	UserId      int       `description:"用户ID"`
+	CreateTime  time.Time `description:"创建时间"`
+	Mobile      string    `description:"手机号"`
+	Email       string    `description:"邮箱"`
+	CompanyId   int       `description:"公司id"`
+	CompanyName string    `description:"公司名称"`
+	RealName    string    `description:"用户实际名称"`
+	SellerName  string    `description:"所属销售"`
+}
+
+type SignupSpecialStatus struct {
+	ActivityId    int    `description:"活动ID"`
+	HasPermission int    `description:"操作方式,1:有该行业权限,正常展示,2:无该行业权限,3:潜在客户,未提交过申请,4:潜在客户,已提交过申请"`
+	PopupMsg      string `description:"权限弹窗信息"`
+	Status        int    `description:"返回类型,1:添加,2:取消"`
+	SellerMobile  string `description:"销售电话"`
+	SellerName    string `description:"销售姓名"`
+}
+
+//添加
+func AddCygxActivitySpecialSignup(item *CygxActivitySpecialSignup) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Insert(item)
+	return
+}
+
+//获取某一用户的报名的数量
+func GetUserCygxActivitySpecialSignup(uid, activityId int) (count int, err error) {
+	sqlCount := `SELECT COUNT(1) AS count FROM cygx_activity_special_signup  WHERE  user_id=?  AND   activity_id =? `
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, uid, activityId).QueryRow(&count)
+	return
+}
+
+//删除
+func DeleteCygxActivitySpecialSignup(uid, activityId int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE  FROM cygx_activity_special_signup   WHERE   user_id=?   AND  activity_id=?    `
+	_, err = o.Raw(sql, uid, activityId).Exec()
+	return
+}
+
+//列表
+func GetActivityListSpecialAll(activityId int) (items []*CygxActivitySpecialSignup, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT art.*  FROM cygx_activity_special_signup as art WHERE 1= 1 AND  activity_id = ?  GROUP BY company_id`
+	_, err = o.Raw(sql, activityId).QueryRows(&items)
+	return
+}

+ 2 - 0
models/activity_type.go

@@ -47,6 +47,8 @@ type ActivityTypeHome struct {
 	ImgUrl           string `description:"图片"`
 	ImgUrlBg         string `description:"背景图片"`
 	ImgUrlBgs        string `description:"背景图片"`
+	Position         int    `description:"位置 ,1:左 ,2:右边"`
+	Resource         int    `description:"位置 ,1:活动 ,2:专项产业调研"`
 	List             []*CygxActivityLabelList
 }
 

+ 4 - 4
models/apply_record.go

@@ -15,7 +15,7 @@ type CygxApplyRecord struct {
 	ApplyMethod     int       `description:"1:已付费客户申请试用,2:非客户申请试用"`
 }
 
-func AddApplyRecord(item *ApplyTryReq, mobile, companyNamePay string, userId, companyIdPay int) (err error) {
+func AddApplyRecord(item *ApplyTryReq, mobile, companyNamePay string, userId, companyIdPay, CompanyIdType int) (err error) {
 	o, err := orm.NewOrm().Begin()
 	if err != nil {
 		return
@@ -28,9 +28,9 @@ func AddApplyRecord(item *ApplyTryReq, mobile, companyNamePay string, userId, co
 		}
 	}()
 
-	sql := `INSERT INTO cygx_apply_record (user_id,business_card_url, real_name,company_name, mobile,create_time, apply_method,company_id_pay,company_name_pay)
-          VALUES(?,?,?,?,?,?,?,?,?) `
-	_, err = o.Raw(sql, userId, item.BusinessCardUrl, item.RealName, item.CompanyName, mobile, time.Now(), item.ApplyMethod, companyIdPay, companyNamePay).Exec()
+	sql := `INSERT INTO cygx_apply_record (user_id,business_card_url, real_name,company_name, mobile,create_time, apply_method,company_id_pay,company_name_pay,company_id_type)
+          VALUES(?,?,?,?,?,?,?,?,?,?) `
+	_, err = o.Raw(sql, userId, item.BusinessCardUrl, item.RealName, item.CompanyName, mobile, time.Now(), item.ApplyMethod, companyIdPay, companyNamePay, CompanyIdType).Exec()
 	if err != nil {
 		return
 	}

+ 19 - 1
models/article.go

@@ -20,6 +20,7 @@ type CygxArticle struct {
 	SubCategoryName  string `description:"二级分类"`
 	PublishStatus    int    `description:"发布状态"`
 	CategoryId       int    `description:"分类id"`
+	CategoryIdTwo    int    `description:"分类id用作修改匹配类型使用"`
 	ExpertBackground string `description:"专家背景"`
 	ExpertNumber     string `description:"专家编号"`
 	InterviewDate    string `description:"访谈日期"`
@@ -31,7 +32,6 @@ type CygxArticle struct {
 	ReportType       int    `description:"报告类型,1行业报告,2产业报告,0无"`
 	FileLink         string `description:"下载预览链接"`
 	MatchTypeName    string `description:"匹配类型"`
-
 	Periods          string `description:"期数"`
 	ReportLink       string `description:"报告链接"`
 	ArticleType      string `description:"文章类型 文章类型,lyjh:路演精华 "`
@@ -41,6 +41,8 @@ type CygxArticle struct {
 	VideoUrl         string `description:"音频文件URL"`
 	VideoName        string `description:"音频文件名称"`
 	VideoPlaySeconds string `description:"音频播放时长"`
+	Stock            string `description:"个股标签"`
+	FieldName        string `description:"产业标签"`
 }
 
 type CygxArticleEs struct {
@@ -95,6 +97,8 @@ type HomeArticle struct {
 	Pv               int    `description:"PV"`
 	ImgUrlPc         string `description:"图片链接"`
 	CategoryId       string `description:"文章分类"`
+	HttpUrl          string `description:"文章链接跳转地址"`
+	IsNeedJump       bool   `description:"是否需要跳转链接地址"`
 }
 
 type ArticleDetail struct {
@@ -132,14 +136,18 @@ type ArticleDetail struct {
 	FollowNum               int    `description:"关注数量"`
 	CollectionNum           int    `description:"收藏数量"`
 	DepartmentId            int    `description:"作者ID"`
+	DepartmentImgUrl        string `description:"作者头像"`
 	SubjectIds              string `description:"文章关联标的的ID字符串"`
 	IndustrialAndSubjectIds string `description:"文章关联产业和标的的ID字符串"`
 	IndustrialManagementId  int    `description:"文章关联产业ID"`
 	SellerList              []*SellerRep
+	HttpUrl                 string `description:"文章链接跳转地址"`
+	IsNeedJump              bool   `description:"是否需要跳转链接地址"`
 }
 
 type ArticleDetailFileLink struct {
 	FileLink string `description:"下载预览链接"`
+	Scene    string `description:"资源参数"`
 }
 type SellerRep struct {
 	SellerMobile string `description:"销售手机号"`
@@ -500,6 +508,7 @@ type ArticleResultApi struct {
 type ArticleResultApidate struct {
 	ArticleId     int                      `json:"id"`
 	Title         string                   `json:"title"`
+	File          string                   `json:"file"`
 	TitleEn       string                   `json:"title_en"`
 	Frequency     string                   `json:"frequency"`
 	CreateDate    string                   `json:"create_date"`
@@ -513,6 +522,15 @@ type ArticleResultApidate struct {
 	Author        ArticleResultApiAuthor   `json:"author"`
 	Industry      ArticleResultApiIndustry `json:"industry"`
 	Type          ArticleResultApiType     `json:"type"`
+	Stock         []string                 `json:"stock"`
+	Field         ArticleField             `json:"field"`
+}
+
+type ArticleField struct {
+	Id          int    `json:"id"`
+	Name        string `json:"name"`
+	Description string `json:"description"`
+	IndustryId  int    `json:"industry_id"`
 }
 
 type ArticleSeries struct {

+ 24 - 2
models/company.go

@@ -10,6 +10,7 @@ type CompanyDetail struct {
 	SellerName  string `description:"销售名称"`
 	Mobile      string `description:"销售手机号"`
 	ProductId   int    `description:"1,FICC,2权益"`
+	IsSuspend   int    `description:"1:暂停,0:启用"`
 }
 
 func GetCompanyDetailById(companyId int) (item *CompanyDetail, err error) {
@@ -33,7 +34,7 @@ func GetCompanyDetailById(companyId int) (item *CompanyDetail, err error) {
 }
 
 func GetCompanyDetailByIdGroup(companyId int) (item *CompanyDetail, err error) {
-	sql := ` SELECT a.company_id,a.company_name,b.status,b.seller_id,b.seller_name,c.mobile 
+	sql := ` SELECT a.company_id,a.company_name,b.status,b.seller_id,b.seller_name,c.mobile ,b.is_suspend
             FROM company AS a
 			INNER JOIN company_product AS b ON a.company_id=b.company_id
 			INNER JOIN company_report_permission AS p ON p.company_id = a.company_id
@@ -105,6 +106,22 @@ func GetCompanyPermissionByUser(companyId int) (permission string, err error) {
 	return
 }
 
+//获取正式权限
+func GetCompanyPermissionByUserZhengShi(companyId int) (permission string, err error) {
+	sql := ` SELECT GROUP_CONCAT(DISTINCT b.remark  ORDER BY b.sort ASC  SEPARATOR ',') AS permission
+			FROM company_report_permission AS a
+			INNER JOIN chart_permission AS b ON a.chart_permission_id=b.chart_permission_id
+			INNER JOIN company_product AS c ON a.company_id=c.company_id AND a.product_id=c.product_id
+			WHERE  a.company_id=?
+			AND c.is_suspend=0
+            AND b.cygx_auth=1
+			AND c.status IN('正式')
+			AND a.status IN('正式') `
+	o := orm.NewOrm()
+	err = o.Raw(sql, companyId).QueryRow(&permission)
+	return
+}
+
 func GetCompanyPermissionByName(name string) (permission string, err error) {
 	sql := ` SELECT GROUP_CONCAT(DISTINCT b.chart_permission_name  ORDER BY b.sort ASC SEPARATOR '/') AS permission
 			FROM company_report_permission AS a
@@ -164,8 +181,13 @@ type CompanyProductStatus struct {
 	IsSuspend int `description:"1:暂停,0:启用"`
 }
 
+type CompanyProductDetial struct {
+	IsSuspend int    `description:"1:暂停,0:启用"`
+	Scale     string `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
+}
+
 //获取对应销售以及销售的手机号
-func GetCompanyProductDetail(companyId, productId int) (item *CompanyProductStatus, err error) {
+func GetCompanyProductDetail(companyId, productId int) (item *CompanyProductDetial, err error) {
 	sql := ` SELECT * FROM company_product WHERE company_id = ? AND product_id = ?; `
 	o := orm.NewOrm()
 	err = o.Raw(sql, companyId, productId).QueryRow(&item)

+ 10 - 0
models/db.go

@@ -93,5 +93,15 @@ func init() {
 		new(CompanyProduct),
 		new(CompanyProductLog),
 		new(UserSellerRelation),
+		new(CygxShanghaiCompanyLog),
+		new(CygxShanghaiErrLog),
+		new(CygxUserFreeeButton),
+		new(UserInvitee),
+		new(CygxActivitySpecialSignup),
+		new(CygxUserFollowSpecial),
 	)
+	// 记录ORM查询日志
+	orm.Debug = true
+	orm.DebugLog = orm.NewLog(utils.BinLog)
+
 }

+ 36 - 0
models/industrial_management.go

@@ -263,6 +263,7 @@ func GetcygxIndustrialSubject(industrialManagementId int) (items []*IndustrialSu
 	return
 }
 
+//通过名称获取
 func GetcygxIndustrialSubjectByName(name string) (industrial_management_id string, err error) {
 	o := orm.NewOrm()
 	sql := `	SELECT industrial_subject_id FROM cygx_industrial_subject  WHERE subject_name = ?`
@@ -343,3 +344,38 @@ ORDER BY
 	_, err = o.Raw(sql, articleId).QueryRows(&items)
 	return
 }
+
+type IndustrialManagementNewResp struct {
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	IsHot                  bool   `description:"是否是热门"`
+	ArticleReadNum         int    `description:"文章阅读数量"`
+}
+
+type IndustrialManagementNewList struct {
+	List []*IndustrialManagementNewResp
+}
+
+//近期更新主题列表
+func GetIndustrialManagementNewList(permissionName string) (items []*IndustrialManagementNewResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industrial_management_id,
+			m.industry_name,
+			m.article_read_num,
+			MAX( a.publish_date ) AS publish_date 
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id 
+		WHERE
+			1 = 1
+			AND a.category_name LIKE '%` + permissionName + `%' 
+			AND publish_status = 1 
+		GROUP BY
+			m.industrial_management_id 
+		ORDER BY
+			publish_date DESC LIMIT 8`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 360 - 0
models/report.go

@@ -305,4 +305,364 @@ func GetArticleIdsBySubId(subjectId string) (articleIds string, err error) {
 			WHERE subject_ids  LIKE '%` + subjectId + `%'`
 	err = o.Raw(sql).QueryRow(&articleIds)
 	return
+} //end
+
+//用户收藏榜start
+type ArticleCollectionResp struct {
+	ArticleId              int    `description:"文章id"`
+	Title                  string `description:"标题"`
+	PublishDate            string `description:"发布时间"`
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	DepartmentId           int    `description:"作者Id"`
+	NickName               string `description:"作者昵称"`
+	Pv                     int    `description:"PV"`
+	CollectNum             int    `description:"收藏人数"`
+	MyCollectNum           int    `description:"本人是否收藏"`
+	IsCollect              bool   `description:"本人是否收藏"`
+}
+
+type ArticleCollectionLIstResp struct {
+	List []*ArticleCollectionResp
+}
+
+//列表
+func GetArticleCollectionList(condition string, userId int) (items []*ArticleCollectionResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			a.article_id,
+			a.title,
+			date_format( a.publish_date, '%Y-%m-%d' ) AS publish_date,
+			m.industry_name,
+			m.industrial_management_id,
+			d.nick_name,
+			d.department_id,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id  ) AS collect_num, 
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id  AND user_id = ? ) AS my_collect_num
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+			INNER JOIN cygx_article_department AS d ON d.department_id = a.department_id 
+		WHERE
+			1 = 1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, userId).QueryRows(&items)
+	return
+} //end
+
+//用户收藏榜start
+type IndustrialManagementHotResp struct {
+	IndustrialManagementId int                  `orm:"column(industrial_management_id);pk" description:"产业id"`
+	IndustryName           string               `description:"产业名称"`
+	IsFollw                bool                 `description:"是否关注"`
+	FllowNum               int                  `description:"关注数量"`
+	IsNew                  bool                 `description:"是否新标签"`
+	IsHot                  bool                 `description:"是否新标签"`
+	PublishDate            string               `description:"发布时间"`
+	ArticleReadNum         int                  `description:"文章阅读数量"`
+	IndustrialSubjectList  []*IndustrialSubject `description:"标的列表"`
+}
+
+type IndustrialManagementHotListResp struct {
+	List []*IndustrialManagementHotResp
+}
+
+//产业列表
+func GetThemeHeatList(permissionName string, userId int, condition string) (items []*IndustrialManagementHotResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industry_name,
+			m.industrial_management_id,
+			m.article_read_num,
+            date_format(  MAX( a.publish_date ), '%Y-%m-%d' ) AS publish_date,	
+			( SELECT count( 1 ) FROM cygx_industry_fllow AS f  WHERE f.industrial_management_id = m.industrial_management_id  AND user_id =? AND f.type = 1  ) AS fllow_num,
+			m.article_read_num + ( SELECT count( 1 ) FROM cygx_activity_meet_detail_log AS la  WHERE la.activity_id  IN  (SELECT activity_id FROM cygx_industrial_activity_group_management WHERE industrial_management_id = m.industrial_management_id  )) AS sum_num
+		FROM
+			cygx_industrial_management AS m
+			LEFT JOIN cygx_industrial_article_group_management AS mg ON mg.industrial_management_id = m.industrial_management_id
+			LEFT JOIN cygx_article AS a ON a.article_id = mg.article_id 
+			LEFT JOIN cygx_industrial_activity_group_management as ag ON ag.industrial_management_id = mg.industrial_management_id
+		WHERE
+			1 = 1
+			AND a.category_name LIKE '%` + permissionName + `%' 
+			AND publish_status = 1 
+			GROUP BY m.industrial_management_id ` + condition
+	_, err = o.Raw(sql, userId).QueryRows(&items)
+	return
+}
+
+//标的列表
+func GetThemeHeatSubjectList(condition string) (items []*IndustrialSubject, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.subject_name,
+			m.industrial_management_id,
+			m.industrial_subject_id 
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_subject AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_subject AS m ON m.industrial_subject_id = mg.industrial_subject_id 
+		WHERE
+			1 = 1`
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` AND publish_status = 1 
+		GROUP BY
+			m.industrial_subject_id 
+		ORDER BY
+			publish_date DESC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+} //end
+
+//Kol sratr
+type DepartmentResp struct {
+	DepartmentId int    `description:"作者Id"`
+	NickName     string `description:"作者昵称"`
+	ImgUrl       string `description:"图片链接"`
+	IsFollw      bool   `description:"是否关注"`
+	FllowNum     int    `description:"关注数量"`
+	List         []*IndustrialDepartmentListResp
+}
+
+type DepartmentListResp struct {
+	List []*DepartmentResp
+}
+type IndustrialDepartmentListResp struct {
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	DepartmentId           int    `description:"作者Id"`
+}
+
+//作者列表
+func GetDepartmentList(permissionName string, userId int) (items []*DepartmentResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			d.nick_name,
+			d.department_id,
+			d.img_url,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS f  WHERE f.department_id = d.department_id  AND user_id =?  AND f.type= 1  ) AS fllow_num,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS f WHERE f.department_id = d.department_id AND f.type= 1 ) +( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id) AS sum_num
+		FROM
+		cygx_article_department AS d
+			INNER JOIN cygx_article AS a ON d.department_id = a.department_id
+		WHERE
+			1 = 1
+			AND a.category_name LIKE '%` + permissionName + `%' 
+			AND publish_status = 1 
+		GROUP BY
+				d.department_id
+		ORDER BY
+			sum_num DESC
+			LIMIT 15`
+	_, err = o.Raw(sql, userId).QueryRows(&items)
+	return
+}
+
+//作者文章所关联的产业列表
+func GetIndustrialDepartmentList(permissionName string) (items []*IndustrialDepartmentListResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industrial_management_id,
+			m.industry_name,
+			d.department_id 
+		FROM
+			cygx_article_department AS d
+			INNER JOIN cygx_article AS a ON d.department_id = a.department_id
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id 
+		WHERE
+			1 = 1
+			AND a.category_name LIKE '%` + permissionName + `%' 
+			AND publish_status = 1 
+		GROUP BY
+			a.article_id 
+		ORDER BY
+			a.publish_date DESC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+//主题详情start
+type GetThemeDetailListResp struct {
+	ArticleId              int    `description:"文章id"`
+	Title                  string `description:"标题"`
+	PublishDate            string `description:"发布时间"`
+	SubjectName            string `description:"标的名称"`
+	IndustrialSubjectId    int    `description:"标的id"`
+	DepartmentId           int    `description:"作者Id"`
+	NickName               string `description:"作者昵称"`
+	Pv                     int    `description:"PV"`
+	CollectNum             int    `description:"收藏人数"`
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	FllowNum               int    `description:"关注数量"`
+	MyCollectNum           int    `description:"本人是否收藏"`
+	IsCollect              bool   `description:"本人是否收藏"`
+}
+
+type GetThemeAericleListResp struct {
+	ArticleId           int    `description:"文章id"`
+	Title               string `description:"标题"`
+	PublishDate         string `description:"发布时间"`
+	SubjectName         string `description:"标的名称"`
+	IndustrialSubjectId int    `description:"标的ID"`
+	DepartmentId        int    `description:"作者Id"`
+	NickName            string `description:"作者昵称"`
+	Pv                  int    `description:"PV"`
+	CollectNum          int    `description:"收藏人数"`
+	FllowNum            int    `description:"关注数量"`
+	MyCollectNum        int    `description:"本人是否收藏"`
+	IsCollect           bool   `description:"本人是否收藏"`
+}
+
+type GetThemeAericleListBuSubjectResp struct {
+	SubjectName string `description:"标的名称"`
+	List        []*GetThemeAericleListResp
+}
+
+//主题详情start
+type GetThemeDetailResp struct {
+	IndustrialManagementId int                  `description:"产业Id"`
+	IndustryName           string               `description:"产业名称"`
+	IsFollw                bool                 `description:"是否关注"`
+	ListSubject            []*IndustrialSubject `description:"标的列表"`
+	List                   []*GetThemeAericleListResp
+}
+
+//列表
+func GetThemeDetail(userId, industrialManagementId int) (items []*GetThemeDetailListResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			a.article_id,
+			a.title,
+			date_format( a.publish_date, '%Y-%m-%d' ) AS publish_date,
+			m.industry_name,
+			m.industrial_management_id,
+			d.nick_name,
+			d.department_id,
+			s.industrial_subject_id,
+			s.subject_name,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id ) AS collect_num,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id and user_id = ? ) AS my_collect_num,
+			( SELECT count( 1 ) FROM cygx_industry_fllow AS ac WHERE user_id = ?  AND ac.industrial_management_id = m.industrial_management_id  AND ac.type= 1) AS fllow_num 
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			LEFT JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+			LEFT JOIN cygx_article_department AS d ON d.department_id = a.department_id
+			LEFT JOIN cygx_industrial_article_group_subject AS sg ON sg.article_id = a.article_id
+			LEFT JOIN cygx_industrial_subject AS s ON s.industrial_subject_id = sg.industrial_subject_id 
+		WHERE
+			1 = 1
+			AND m.industrial_management_id = ? 
+			AND publish_status = 1 
+			AND a.category_name LIKE '%研选%' 
+		ORDER BY
+			publish_date DESC`
+	_, err = o.Raw(sql, userId, userId, industrialManagementId).QueryRows(&items)
+	return
+} //end
+
+//用户收藏榜start
+type DepartmentDetailResp struct {
+	DepartmentId int    `description:"作者Id"`
+	NickName     string `description:"作者昵称"`
+	ImgUrl       string `description:"图片链接"`
+	FllowNum     int    `description:"多少人关注"`
+	ArticleNum   int    `description:"文章数量"`
+	CollectNum   int    `description:"收藏人数"`
+	IsFllow      bool   `description:"是否关注"`
+	List         []*ArticleCollectionResp
+}
+
+type DepartmentDetail struct {
+	DepartmentId int    `description:"作者Id"`
+	NickName     string `description:"作者昵称"`
+	ImgUrl       string `description:"图片链接"`
+	FllowNum     int    `description:"多少人关注"`
+	ArticleNum   int    `description:"文章数量"`
+	CollectNum   int    `description:"收藏人数"`
+	IsFllow      bool   `description:"是否关注"`
+	MyFllowNum   int    `description:"本人是否关注"`
+}
+
+//列表
+func GetDepartmentDetail(userId, departmentId int) (item DepartmentDetail, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			d.department_id,
+			d.nick_name,
+			d.img_url,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS af WHERE af.user_id = ? AND af.department_id = d.department_id AND af.type= 1 ) AS my_fllow_num,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS f INNER JOIN wx_user as u ON  u.user_id = f.user_id   WHERE f.department_id = d.department_id  AND f.type= 1 ) AS fllow_num,
+			( SELECT count( 1 ) FROM cygx_article AS a WHERE a.department_id = d.department_id  ) AS article_num,
+			( SELECT count( 1 ) FROM cygx_article_collect  AS c INNER JOIN wx_user as u ON  u.user_id = c.user_id   WHERE c.article_id IN (SELECT  article_id FROM cygx_article AS a WHERE a.department_id = d.department_id )) AS collect_num
+		FROM
+			cygx_article_department AS d 
+		WHERE
+			d.department_id = ?`
+	err = o.Raw(sql, userId, departmentId).QueryRow(&item)
+	return
+} //end
+
+//报告搜索start
+type ReoprtSearchResp struct {
+	ListYx []*ArticleCollectionResp `description:"研选报告"`
+	ListHz []*ArticleCollectionResp `description:"弘则报告"`
+}
+
+//列表
+func GetReoprtSearchList(condition string, userId int) (items []*ArticleCollectionResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			a.article_id,
+			a.title,
+			date_format( a.publish_date, '%Y-%m-%d' ) AS publish_date,
+			m.industry_name,
+			m.industrial_management_id,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id ) AS collect_num,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id  AND user_id = ?) AS my_collect_num
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+		WHERE
+			1 = 1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, userId).QueryRows(&items)
+	return
+} //end
+
+//搜索资源包 start
+type SearchResourceResp struct {
+	ListHz []*IndustrialManagementHotResp `description:"弘则"`
+	ListYx []*IndustrialManagementHotResp `description:"研选"`
+}
+
+//产业列表
+func GetSearchResourceList(condition string) (items []*IndustrialManagementHotResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industry_name,
+			m.industrial_management_id,
+			date_format( MAX( a.publish_date ), '%Y-%m-%d' ) AS publish_date 
+		FROM
+			cygx_industrial_management AS m
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.industrial_management_id = m.industrial_management_id
+			INNER JOIN cygx_article AS a ON a.article_id = mg.article_id 
+		WHERE
+			1 = 1 
+			AND publish_status = 1 ` + condition
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
 }

+ 2 - 2
models/report_selection.go

@@ -126,11 +126,11 @@ func GetReportSelectionlogListAll(articleId int) (items []*CygxReportSelectionLo
 //列表
 func GetReportSelectionlogSonListAll(articleId, chartPermissionId int) (items []*CygxReportSelectionLogDetail, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT c.permission_name ,s.subject_name , l.* 
+	sql := `SELECT c.permission_name , l.* 
 			FROM
 			cygx_report_selection_log AS l
 			INNER JOIN chart_permission AS c ON c.chart_permission_id = l.chart_permission_id 
-			INNER JOIN cygx_industrial_subject AS s ON s.industrial_subject_id = l.industrial_subject_id 
+			LEFT JOIN cygx_industrial_subject AS s ON s.industrial_subject_id = l.industrial_subject_id 
 			WHERE l.article_id = ? AND l.chart_permission_id =?`
 	_, err = o.Raw(sql, articleId, chartPermissionId).QueryRows(&items)
 	return

+ 1 - 1
models/seller.go

@@ -25,7 +25,7 @@ func GetSellerByCompanyId(companyId int) (item *AdminItem, err error) {
 	sql := ` SELECT b.*,c.open_id,c.user_id,a.company_name FROM company_product AS a
 			INNER JOIN admin AS b ON a.seller_id=b.admin_id
 			LEFT JOIN wx_user AS c ON b.mobile=c.mobile
-			WHERE a.company_id=? `
+			WHERE a.company_id=? AND role_type_code LIKE '%rai%'`
 	err = o.Raw(sql, companyId).QueryRow(&item)
 	return
 }

+ 218 - 0
models/send_company_user.go

@@ -0,0 +1,218 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CompanyJson struct {
+	CompanyName  string `json:"name"`        //公司名称
+	ShortName    string `json:"short_name"`  //公司简称
+	CreditCode   string `json:"social"`      //社会信用代码
+	City         string `json:"city"`        //所在地级市或直辖市
+	SignType     string `json:"sign_type"`   //客户重要度(A类、B类、C类、D类)
+	Fe           string `json:"f_e"`         //客户类型(FICC、权益、策略)
+	IndustryName string `json:"industry"`    //所属行业(公募、私募、券商资管、保险、海外、其他类型)
+	Mobile       string `json:"sale_phone"`  //所属销售(销售手机号)
+	Status       string `json:"status"`      //客户状态(正式、试用)
+	Permission   string `json:"permissions"` //客户权限(医药,科技,智造,消费,策略,专家,路演服务,研选)
+	StartDate    string `json:"start_time"`  //服务期限开始时间
+	EndDate      string `json:"end_time"`    //服务期限结束时间
+	Info         string `json:"info"`        //简介
+	CreatedTime  string `json:"create_time"` //创建时间
+	//CreatedTimes string //创建时间
+	EndDateTime time.Time //创建时间
+}
+
+type UserJson struct {
+	CreditCode          string `json:"social"`            //社会信用代码
+	RealName            string `json:"name"`              //昵称
+	Mobile              string `json:"phone"`             //手机号1
+	CountryCode         string `json:"area_code"`         //国家号1(+86..)
+	OutboundMobile      string `json:"phone2"`            //手机号2
+	OutboundCountryCode string `json:"area_code2"`        //国家号2(+86..)
+	Telephone           string `json:"machine"`           //座机
+	MachineAreaCode     string `json:"machine_area_code"` //座机国家号(+86..)
+	Sex                 string `json:"sex"`               //性别(男、女)
+	Email               string `json:"email"`             //电子邮箱,比如 example@qq.com
+	Department          string `json:"department"`        //部门
+	Position            string `json:"position"`          //职位
+	Level               string `json:"level"`             //职位等级(研究员、基金经理、部门总监)
+	IsMaker             string `json:"policymakers"`      //是否决策人(是、否)
+	CreatedTime         string `json:"create_time"`       //创建时间
+
+}
+type CompanyJsonList struct {
+	SyncData *[]CompanyJson `json:"sync_data"`
+}
+
+type CompanyUnJsonList struct {
+	SyncData []CompanyJson `json:"sync_data"`
+}
+
+//获取公司
+func GetSendCompanyList(condition string) (items []*CompanyJson, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+			c.company_name,
+			c.company_id as cid, 
+			c.credit_code,
+			c.city,
+			p.industry_name,
+			am.real_name,
+			am.mobile,
+			a.status,
+			p.end_date as end_date_time,
+			UNIX_TIMESTAMP( p.start_date ) AS start_date,
+			UNIX_TIMESTAMP( p.end_date ) AS end_date,
+			UNIX_TIMESTAMP( a.created_time ) AS created_time,
+			(SELECT GROUP_CONCAT(DISTINCT b.chart_permission_name  ORDER BY b.sort ASC  SEPARATOR ',')
+					FROM company_report_permission AS a
+					INNER JOIN chart_permission AS b ON a.chart_permission_id=b.chart_permission_id
+					INNER JOIN company_product AS c ON a.company_id=c.company_id AND a.product_id=c.product_id
+					WHERE  a.company_id=cid
+					AND c.enabled = 1 
+					AND b.cygx_auth=1
+					AND c.status IN('正式','试用')
+					AND a.status IN('正式','试用')) AS permission
+		FROM
+			company_report_permission AS a
+			INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id
+			INNER JOIN company_product AS p ON a.company_id = p.company_id
+			INNER JOIN company AS c ON c.company_id = a.company_id
+			INNER JOIN admin AS am ON am.admin_id = p.seller_id 
+			AND a.product_id = p.product_id 
+		WHERE
+			1 = 1 
+			AND c.enabled = 1 
+			AND b.cygx_auth = 1
+			AND p.STATUS IN ( '正式', '试用' ) 
+			AND a.STATUS IN ( '正式', '试用' )
+			AND( c.credit_code LIKE '91%'  OR  c.credit_code LIKE 'HZ%' )
+			AND p.product_id = 2 ` + condition +
+		`GROUP BY 
+			c.company_id  `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+//获取FICC公司
+func GetSendCompanyFiccList(condition string) (items []*CompanyJson, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+			c.company_name,
+			c.company_id AS cid,
+			c.credit_code,
+			c.city,
+			p.industry_name,
+			am.real_name,
+			am.mobile,
+			a.status,
+			p.end_date AS end_date_time,
+			UNIX_TIMESTAMP( p.start_date ) AS start_date,
+			UNIX_TIMESTAMP( p.end_date ) AS end_date,
+			UNIX_TIMESTAMP( a.created_time ) AS created_time,
+			(
+			SELECT
+				GROUP_CONCAT( DISTINCT b.chart_permission_name ORDER BY b.sort ASC SEPARATOR ',' ) 
+			FROM
+				company_report_permission AS a
+				INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id
+				INNER JOIN company_product AS c ON a.company_id = c.company_id 
+				AND a.product_id = c.product_id 
+			WHERE
+				a.company_id = cid 
+				AND c.enabled = 1 
+				AND b.cygx_auth = 1 
+				AND c.STATUS IN ( '正式', '试用' ) 
+			AND a.STATUS IN ( '正式', '试用' )) AS permission 
+		FROM
+			company_report_permission AS a
+			INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id
+			INNER JOIN company_product AS p ON a.company_id = p.company_id
+			INNER JOIN company AS c ON c.company_id = a.company_id
+			INNER JOIN admin AS am ON am.admin_id = p.seller_id 
+			AND a.product_id = p.product_id 
+		WHERE
+			1 = 1 
+			AND c.enabled = 1 
+			AND b.cygx_auth = 1
+			AND p.STATUS IN ( '正式', '试用' ) 
+			AND a.STATUS IN ( '正式', '试用' ) 
+			AND ( c.credit_code LIKE '91%' OR c.credit_code LIKE 'HZ%' ) 
+			AND p.product_id = 1 ` + condition +
+		`AND c.company_id NOT IN (
+			SELECT
+				c.company_id 
+			FROM
+				company_report_permission AS a
+				INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id
+				INNER JOIN company_product AS p ON a.company_id = p.company_id
+				INNER JOIN company AS c ON c.company_id = a.company_id
+				INNER JOIN admin AS am ON am.admin_id = p.seller_id 
+				AND a.product_id = p.product_id 
+			WHERE
+				1 = 1 
+				AND c.enabled = 1 
+				AND b.cygx_auth = 1 
+				AND p.STATUS IN ( '正式', '试用' ) 
+				AND a.STATUS IN ( '正式', '试用' ) 
+				AND ( c.credit_code LIKE '91%' OR c.credit_code LIKE 'HZ%' ) 
+				AND p.product_id = 2
+			GROUP BY
+				c.company_id 
+			) 
+		GROUP BY
+			c.company_id  `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+//获取用户
+func GetSendUserList(condition string) (items []*UserJson, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+			c.credit_code,
+			u.real_name,
+			u.mobile,
+			u.country_code,
+			u.outbound_mobile,
+			u.outbound_country_code,
+			u.telephone,
+			u.sex,
+			u.is_maker,
+			c.company_id,
+			UNIX_TIMESTAMP( us.create_time ) AS created_time 
+		FROM
+			wx_user AS u
+			INNER JOIN company AS c ON c.company_id = u.company_id
+			INNER JOIN user_seller_relation AS us ON us.user_id = u.user_id 
+		WHERE
+			1 = 1 
+			AND u.company_id IN (
+			SELECT
+				c.company_id 
+			FROM
+				company_report_permission AS a
+				INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id
+				INNER JOIN company_product AS p ON a.company_id = p.company_id
+				INNER JOIN company AS c ON c.company_id = a.company_id
+				INNER JOIN admin AS am ON am.admin_id = p.seller_id 
+				AND a.product_id = p.product_id 
+			WHERE
+				1 = 1 
+				AND c.enabled = 1 
+				AND b.cygx_auth = 1 
+				AND p.STATUS IN ( '正式', '试用' ) 
+				AND a.STATUS IN ( '正式', '试用' )
+				AND us.create_time  != '' ` + condition +
+		`GROUP BY
+				c.company_id 
+			)
+			AND us.create_time != '' 
+			AND u.real_name != '' 
+			AND u.mobile != '' 
+			AND ( c.credit_code LIKE '91%' OR c.credit_code LIKE 'HZ%' ) GROUP BY u.user_id   ORDER BY  c.company_id  DESC `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 52 - 0
models/shanghai_company_log.go

@@ -0,0 +1,52 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxShanghaiCompanyLog struct {
+	Id         int `orm:"column(id);pk"`
+	Url        string
+	Body       string
+	Result     string
+	CreateTime time.Time
+}
+
+//添加日志记录
+func AddCygxShanghaiCompanyLog(item *CygxShanghaiCompanyLog) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type CygxShanghaiErrLog struct {
+	Id         int `orm:"column(id);pk"`
+	ErrVal     string
+	ErrMsg     string
+	ErrType    string
+	CreateTime time.Time
+}
+
+//添加日志记录
+func AddCygxShanghaiErrLog(item *CygxShanghaiErrLog) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+//列表
+func GetCygxShanghaiCompanyLog() (items []*CygxShanghaiCompanyLog, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM cygx_shanghai_company_log WHERE create_time > date_format(now(),'%Y-%m-%d') AND url LIKE '%Customer/batchSyncFiccCustomer%'`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+//三十天之后的日志自行删除
+func DeleteCygxShanghaiCompanyLog() (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE FROM cygx_shanghai_company_log WHERE  DATE_SUB(CURDATE(), INTERVAL 30 DAY) > date(create_time)`
+	_, err = o.Raw(sql).Exec()
+	return
+}

+ 3 - 0
models/tactics.go

@@ -77,6 +77,9 @@ type Tactics2 struct {
 	IsSummary       int       `description:"是否是纪要库,1是,0否"`
 	IsReport        int       `description:"是否属于报告,1是,0否"`
 	ReportType      int       `description:"报告类型,1行业报告,2产业报告,0无"`
+	Stock           string    `description:"个股标签"`
+	FieldName       string    `description:"产业标签"`
+	File            string    `description:"Pdf下载链接"`
 }
 
 func GetTacticsList2(endDate string) (list []*Tactics2, err error) {

+ 31 - 7
models/user.go

@@ -23,12 +23,22 @@ type UserDetail struct {
 	CountryCode         string `description:"区号"`
 	OutboundMobile      string `description:"外呼手机号"`
 	OutboundCountryCode string `description:"外呼手机号区号"`
+	ConNum              int    `description:"收藏"`
+	HistoryNum          int    `description:"足迹"`
+	ScheduleNum         int    `description:"活动日程"`
 }
 
 func GetUserDetailByUserId(userId int) (item *UserDetail, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT * FROM wx_user WHERE user_id = ? `
-	err = o.Raw(sql, userId).QueryRow(&item)
+	sql := `SELECT *,
+	( SELECT COUNT( 1 ) AS count FROM cygx_article_collect AS a	INNER JOIN cygx_article AS art ON art.article_id = a.article_id  WHERE
+		a.user_id = ? AND art.publish_status = 1 ) AS con_num,
+	(SELECT	COUNT( 1 ) AS count FROM
+		( SELECT count(*) FROM cygx_article_history_record AS a WHERE a.user_id = ?  GROUP BY a.article_id ) b ) AS history_num ,
+	( SELECT COUNT( 1 ) AS count FROM	cygx_my_schedule AS a INNER JOIN cygx_activity AS art ON art.activity_id = a.activity_id WHERE
+		a.user_id = ? AND art.publish_status = 1 AND art.active_state != 3 ) AS schedule_num
+	FROM wx_user WHERE user_id = ? `
+	err = o.Raw(sql, userId, userId, userId, userId).QueryRow(&item)
 	return
 }
 
@@ -38,11 +48,12 @@ type UserPermission struct {
 }
 
 type LoginReq struct {
-	LoginType   int    `description:"登录方式:1:微信手机,2:邮箱,3:自定义手机登录"`
-	Mobile      string `description:"手机号"`
-	Email       string `description:"邮箱"`
-	VCode       string `description:"验证码"`
-	CountryCode string `description:"区号"`
+	LoginType     int    `description:"登录方式:1:微信手机,2:邮箱,3:自定义手机登录"`
+	Mobile        string `description:"手机号"`
+	Email         string `description:"邮箱"`
+	VCode         string `description:"验证码"`
+	CountryCode   string `description:"区号"`
+	ShareUserCode string `description:"分享人的分享码"`
 }
 
 func PcBindMobile(unionId, mobile string, userId, loginType int) (wxUserId int, err error) {
@@ -127,6 +138,7 @@ type LoginResp struct {
 	Status        string `description:"状态"`
 	EndDate       string `description:"到期日期"`
 	ProductName   string `description:"客户类型名称"`
+	IsPotential   bool   `description:"是否是潜在"`
 }
 
 type CheckStatusResp struct {
@@ -423,3 +435,15 @@ func GetSendEmailAllUserWithCompany() (items []*GetSendEmailAllUserWithCompanyRe
 	_, err = orm.NewOrm().Raw(sql).QueryRows(&items)
 	return
 }
+
+type Headimgurl struct {
+	Headimgurl string `description:"用户头像"`
+}
+
+//更改用户手机号
+func UpdateUserHeadimgurl(headimgurl string, userId int) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE wx_user SET headimgurl = ? WHERE user_id=? `
+	_, err = o.Raw(sql, headimgurl, userId).Exec()
+	return
+}

+ 40 - 0
models/user_follow_special.go

@@ -0,0 +1,40 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxUserFollowSpecial struct {
+	Id          int       `orm:"column(id);pk"`
+	UserId      int       `description:"用户ID"`
+	CreateTime  time.Time `description:"创建时间"`
+	Mobile      string    `description:"手机号"`
+	Email       string    `description:"邮箱"`
+	CompanyId   int       `description:"公司id"`
+	CompanyName string    `description:"公司名称"`
+	RealName    string    `description:"用户实际名称"`
+}
+
+//添加
+func AddUserFollowSpecial(item *CygxUserFollowSpecial) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Insert(item)
+	return
+}
+
+//获取某一用户的报名的数量
+func GetCygxUserFollowSpecial(uid int) (count int, err error) {
+	sqlCount := `SELECT COUNT(1) AS count FROM cygx_user_follow_special  WHERE  user_id=? `
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, uid).QueryRow(&count)
+	return
+}
+
+//删除
+func DeleteCygxUserFollowSpecial(uid int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE  FROM cygx_user_follow_special   WHERE  user_id=? `
+	_, err = o.Raw(sql, uid).Exec()
+	return
+}

+ 45 - 0
models/user_freee_button.go

@@ -0,0 +1,45 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxUserFreeeButton struct {
+	Id            int       `orm:"column(id);pk"`
+	UserId        int       `description:"用户id"`
+	CompanyId     int       `description:"公司id"`
+	CreateTime    time.Time `description:"创建时间"`
+	ModifyTime    time.Time `description:"修改时间"`
+	EffectiveTime string    `description:"有效隐藏时间"`
+}
+
+//添加历史信息
+func AddCygxUserFreeeButton(item *CygxUserFreeeButton) (lastId int64, err error) {
+	o := orm.NewOrm()
+	item.ModifyTime = time.Now()
+	lastId, err = o.Insert(item)
+	return
+}
+
+//更新当天隐藏时间
+func UpdateCygxUserFreeeButton(userId int) (err error) {
+	o := orm.NewOrm()
+	msql := ` UPDATE cygx_user_freee_button SET effective_time = NOW() ,modify_time = NOW() WHERE user_id = ? `
+	_, err = o.Raw(msql, userId).Exec()
+	return
+}
+
+func CountCygxUserFreeeButton(userId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM cygx_user_freee_button WHERE user_id = ? AND  effective_time = date_format(now(),'%Y-%m-%d')`
+	err = o.Raw(sql, userId).QueryRow(&count)
+	return
+}
+
+func CountCygxUserFreeeButtonByUser(userId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM cygx_user_freee_button WHERE user_id = ? `
+	err = o.Raw(sql, userId).QueryRow(&count)
+	return
+}

+ 33 - 0
models/user_invitee.go

@@ -0,0 +1,33 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type UserInvitee struct {
+	Id                int       `orm:"column(id);pk"`
+	InviteeUserId     string    `description:"产业D"`
+	InviteedUserId    string    `description:"用户ID"`
+	CreateTime        time.Time `description:"创建时间"`
+	InviteedMobile    string    `description:"手机号"`
+	InviteedCompanyId int       `description:"公司ID"`
+	InviteeMobile     string    `description:"邀请人手机号"`
+	InviteeCompany    string    `description:"邀请人公司名称"`
+	InviteeCompanyId  int       `description:"邀请人公司ID"`
+	InviteeEmail      string    `description:"邀请人邮箱"`
+}
+
+//添加收藏信息
+func AddUserInvite(item *UserInvitee) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+//获取数量
+func GetUserInviteeCount(userId int) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM user_invitee WHERE inviteed_user_id=? `
+	err = orm.NewOrm().Raw(sql, userId).QueryRow(&count)
+	return
+}

+ 1 - 0
models/user_record.go

@@ -113,6 +113,7 @@ func GetUserRecordByMobile(platform int, bindAccount string) (item *UserRecord,
 		platform = 1
 		sql = `SELECT open_id FROM	user_record  WHERE create_platform =? AND bind_account = ?`
 	}
+
 	err = orm.NewOrm().Raw(sql, platform, bindAccount).QueryRow(&item)
 	return
 }

+ 28 - 0
models/user_search_key_word.go

@@ -19,3 +19,31 @@ func AddUserSearchKeyWord(item *CygxUserSearchKeyWord) (lastId int64, err error)
 	lastId, err = o.Insert(item)
 	return
 }
+
+type UserSearchKeyWord struct {
+	KeyWord string `description:"关键词"`
+}
+
+type UserSearchKeyWordListResp struct {
+	List []*UserSearchKeyWord
+}
+
+//列表
+func GetUserSearchKeyWord() (items []*UserSearchKeyWord, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			key_word,
+			key_word AS kw,
+			( SELECT count( 1 ) FROM cygx_user_search_key_word AS k WHERE k.key_word = kw ) AS key_num 
+		FROM
+			cygx_user_search_key_word 
+		WHERE
+			page_type = 'ReortSearch' 
+		GROUP BY
+			key_word 
+		ORDER BY
+			key_num DESC 
+			LIMIT 8`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 20 - 0
models/wechat.go

@@ -20,6 +20,26 @@ type WxToken struct {
 	Id          int64
 }
 
+type SenceRule struct {
+	Scene     string `json:"scene"`
+	Page      string `json:"page,omitempty"`
+	Width     int    `json:"width,omitempty"`
+	AutoColor bool   `json:"auto_color,omitempty"`
+	LineColor string `json:"line_color,omitempty"`
+	IsHyaline bool   `json:"is_hyaline,omitempty"`
+}
+
+// BufferRule 图片buffer
+type BufferRule struct {
+	Buffer []byte `json:"Buffer"`
+}
+
+// ReturnBodyRule 微信返回通过结果集
+type ReturnBodyRule struct {
+	ErrorCode    int    `json:"errcode,omitempty"`
+	ErrorMessage string `json:"errmsg,omitempty"`
+}
+
 func GetWxAccessToken() (accessTokenStr string, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT * FROM wx_token LIMIT 1`

+ 185 - 5
routers/commentsRouter_controllers.go

@@ -97,6 +97,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"],
+        beego.ControllerComments{
+            Method: "LabelTypeListV5",
+            Router: "/labelTypeListV5",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"],
         beego.ControllerComments{
             Method: "ActivityList",
@@ -160,6 +169,42 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"],
+        beego.ControllerComments{
+            Method: "SpecialDetail",
+            Router: "/special/detail",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"],
+        beego.ControllerComments{
+            Method: "SpecialMsg",
+            Router: "/special/follow",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"],
+        beego.ControllerComments{
+            Method: "SpecialList",
+            Router: "/special/list",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ActivityCoAntroller"],
+        beego.ControllerComments{
+            Method: "SpecialSignupAdd",
+            Router: "/special/signup/add",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:AdviceController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:AdviceController"],
         beego.ControllerComments{
             Method: "ApplyApprove",
@@ -520,6 +565,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "SearchReport",
+            Router: "/searchReport",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ReportController"],
+        beego.ControllerComments{
+            Method: "SearchResource",
+            Router: "/searchResource",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ReportController"],
         beego.ControllerComments{
             Method: "ArticleCategoryList",
@@ -538,6 +601,78 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "ArticleHotList",
+            Router: "/article/hotList",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "CollectionList",
+            Router: "/collectionList",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "DepartmentIdDetail",
+            Router: "/departmentId/detail",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "HotKeyWord",
+            Router: "/hotKeyWord",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "HotList",
+            Router: "/hotList",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "KolList",
+            Router: "/kolList",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "ThemeDetail",
+            Router: "/theme/detail",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResearchController"],
+        beego.ControllerComments{
+            Method: "NewList",
+            Router: "/theme/newList",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResourceController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:ResourceController"],
         beego.ControllerComments{
             Method: "Upload",
@@ -664,6 +799,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
+        beego.ControllerComments{
+            Method: "FreeButtonUpdate",
+            Router: "/freeButton/update",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
+        beego.ControllerComments{
+            Method: "HeadimgurlUpdate",
+            Router: "/headimgurl/update",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
         beego.ControllerComments{
             Method: "InterviewApplyList",
@@ -675,22 +828,40 @@ func init() {
 
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
         beego.ControllerComments{
-            Method: "Login",
-            Router: "/login",
-            AllowHTTPMethods: []string{"post"},
+            Method: "AlertIsShow",
+            Router: "/isShow/alert",
+            AllowHTTPMethods: []string{"get"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})
 
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
         beego.ControllerComments{
-            Method: "WhiteUser",
-            Router: "/whiteUser",
+            Method: "IsShow",
+            Router: "/isShow/freeButton",
             AllowHTTPMethods: []string{"get"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
+        beego.ControllerComments{
+            Method: "ShareIsShow",
+            Router: "/isShow/share",
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:UserController"],
+        beego.ControllerComments{
+            Method: "Login",
+            Router: "/login",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:WechatCommonController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:WechatCommonController"],
         beego.ControllerComments{
             Method: "WechatLogin",
@@ -745,6 +916,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:WechatController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:WechatController"],
+        beego.ControllerComments{
+            Method: "ShareImage",
+            Router: "/shareImage",
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:WechatController"] = append(beego.GlobalControllerRouter["hongze/hongze_cygx/controllers:WechatController"],
         beego.ControllerComments{
             Method: "UpdateWxAccesstoken",

+ 5 - 0
routers/router.go

@@ -96,6 +96,11 @@ func init() {
 				&controllers.ActivityABaseController{},
 			),
 		),
+		web.NSNamespace("/research",
+			web.NSInclude(
+				&controllers.ResearchController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 221 - 194
services/activity.go

@@ -52,15 +52,16 @@ func SendActivityBeginMsg(cont context.Context) (err error) {
 		openIdItem.OpenId = v.OpenId
 		openIdList := make([]*models.OpenIdList, 0)
 		openIdList = append(openIdList, openIdItem)
-		if v.FailType == 0 {
-			reserveResults = "成功"
-		} else if v.FailType == 1 {
-			reserveResults = "失败(总人数已满)"
-		} else if v.FailType == 2 {
-			reserveResults = "失败(单机构超限制)"
-		} else if v.FailType == 3 {
-			reserveResults = "失败(爽约次数超限)"
-		}
+		//if v.FailType == 0 {
+		//	reserveResults = "成功"
+		//} else if v.FailType == 1 {
+		//	reserveResults = "失败(总人数已满)"
+		//} else if v.FailType == 2 {
+		//	reserveResults = "失败(单机构超限制)"
+		//} else if v.FailType == 3 {
+		//	reserveResults = "失败(爽约次数超限)"
+		//}
+		reserveResults = "--"
 		first = "您有一场【" + v.ActivityTypeName + "】将在1小时后开始"
 		SendWxMsgWithFrequency(first, v.ActivityName, reserveResults, v.ActivityTime, v.Address, remark, openIdList, v.ActivityId)
 	}
@@ -135,7 +136,7 @@ func SendEmailFileToExpert(cont context.Context) (err error) {
 			utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
 		}
 	}()
-	endDate := time.Now().Add(+time.Minute * 60).Format(utils.FormatDateTime)
+	endDate := time.Now().Add(+time.Minute * 30).Format(utils.FormatDateTime)
 	total, err := models.GetCountActivityIdToSendFile(endDate)
 
 	if total == 0 {
@@ -305,7 +306,7 @@ func EditUserOutboundMobile(cont context.Context) (err error) {
 //获取 用户类型   //1、永续客户 //2、大套餐客户(4个行业全开通的正式客户) //3、分行业套餐客户(开通对应行业的正式客户) //4、仅开通专家套餐的正式客户 //5、开通对应行业套餐或专家套餐的试用客户
 func GetUserType(companyId int) (userType int, permissionStrnew string, err error) {
 
-	var permissionStr string
+	var permissionStr, permissionZhegnshiStr string
 	if companyId <= 1 {
 		userType = 0
 	} else {
@@ -327,6 +328,12 @@ func GetUserType(companyId int) (userType int, permissionStrnew string, err erro
 				err = errs
 				return
 			}
+			permissionZhegnshiStr, errs = models.GetCompanyPermissionByUserZhengShi(companyId)
+			if errs != nil {
+				err = errs
+				return
+			}
+
 			//1、永续客户 //2、大套餐客户(4个行业全开通的正式客户) //3、分行业套餐客户(开通对应行业的正式客户) //4、仅开通专家套餐的正式客户 //5、开通对应行业套餐或专家套餐的试用客户
 			if companyDetail.Status == "永续" {
 				userType = 1
@@ -335,7 +342,7 @@ func GetUserType(companyId int) (userType int, permissionStrnew string, err erro
 			} else if companyDetail.Status == "正式" {
 				if permissionStr == "专家" {
 					userType = 4
-				} else if strings.Contains(permissionStr, "医药") && strings.Contains(permissionStr, "消费") && strings.Contains(permissionStr, "科技") && strings.Contains(permissionStr, "智造") {
+				} else if strings.Contains(permissionZhegnshiStr, "医药") && strings.Contains(permissionZhegnshiStr, "消费") && strings.Contains(permissionZhegnshiStr, "科技") && strings.Contains(permissionZhegnshiStr, "智造") {
 					userType = 2
 				} else {
 					userType = 3
@@ -407,7 +414,7 @@ func GetHavePower(activityInfo *models.ActivityDetail, permissionStr, companyDet
 //研选系列专家电话会,会前1小时将问题列表发送给邮箱
 func SendEmailFileForAskMsgResearch(cont context.Context) (err error) {
 	var msg string
-	var touser string
+	//var touser string
 	defer func() {
 		if err != nil {
 			fmt.Println("err:", err)
@@ -446,78 +453,37 @@ func SendEmailFileForAskMsgResearch(cont context.Context) (err error) {
 			msg = "获取失败,Err:" + errFile.Error()
 			return
 		}
-		//创建excel
-		dir, errFile := os.Executable()
-		exPath := filepath.Dir(dir)
-		downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + utils.GetRandDigit(5) + ".xlsx"
-		xlsxFile := xlsx.NewFile()
-		if errFile != nil {
-			msg = "生成文件失败Err:" + errFile.Error()
-			return
-		}
-		style := xlsx.NewStyle()
-		alignment := xlsx.Alignment{
-			Horizontal: "center",
-			Vertical:   "center",
-			WrapText:   true,
-		}
-		style.Alignment = alignment
-		style.ApplyAlignment = true
-		sheet, errFile := xlsxFile.AddSheet("外呼名单")
-		if errFile != nil {
-			msg = "新增Sheet失败,Err:" + errFile.Error()
-			return
-		}
-		//设置宽度
-		_ = sheet.SetColWidth(1, 1, 30)
-		_ = sheet.SetColWidth(2, 2, 60)
-		//标头
-		rowTitle := sheet.AddRow()
-		cellA := rowTitle.AddCell()
-		cellA.Value = "姓名"
-		cellB := rowTitle.AddCell()
-		cellB.Value = "公司名称"
-		cellC := rowTitle.AddCell()
-		cellC.Value = "问题"
-		cellD := rowTitle.AddCell()
-		cellD.Value = "提交时间"
 
-		for _, item := range list {
-			row := sheet.AddRow()
-			cellA := row.AddCell()
-			cellA.Value = item.RealName
-			cellB := row.AddCell()
-			cellB.Value = item.CompanyName
-			cellC := row.AddCell()
-			cellC.Value = item.Content
-			cellD := row.AddCell()
-			cellD.Value = item.CreateTime
+		for _, v2 := range list {
+			user, err := models.GetWxUserItemByUserId(v2.UserId)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				return err
+			}
+			//获取销售信息
+			sellerItem, err := models.GetSellerByCompanyIdCheckFicc(v2.CompanyId, 2)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				return err
+			}
+			//给研究员推送消息
+			if sellerItem != nil {
+				openIpItem, _ := models.GetUserRecordByMobile(4, utils.ActSendMsgMobile)
+				if openIpItem != nil && openIpItem.OpenId != "" {
+					SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
+				}
+			}
+			//给所属销售推送消息
+			if sellerItem != nil {
+				openIpItem, _ := models.GetUserRecordByMobile(4, sellerItem.Mobile)
+				if openIpItem != nil && openIpItem.OpenId != "" {
+					SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
+				}
+			}
 		}
-		errFile = xlsxFile.Save(downLoadnFilePath)
+		errFile = models.UPdateActivityMsgToSendFile(v.ActivityId)
 		if errFile != nil {
-			msg = "保存文件失败Err:" + errFile.Error()
+			msg = "获取失败,Err:" + errFile.Error()
 			return
 		}
-		title := activityInfo.ActivityName + "-活动带问"
-		content := "活动带问详情"
-		fileName := downLoadnFilePath
-		if utils.RunMode == "release" {
-			touser = "cxzhang@hzinsights.com;ywang@hzinsights.com;tshen@hzinsights.com"
-		} else {
-			touser = "cxzhang@hzinsights.com;jhwang@hzinsights.com;tshen@hzinsights.com"
-		}
-		sendResult := utils.SendEmailByHongze(title, content, touser, fileName, title+".xlsx")
-		if sendResult {
-			errFile = models.UPdateActivityMsgToSendFile(v.ActivityId)
-			if errFile != nil {
-				msg = "获取失败,Err:" + errFile.Error()
-				return
-			}
-			os.Remove(downLoadnFilePath)
-		} else {
-			go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.RunMode), msg+";Err:"+activityInfo.ActivityName, utils.EmailSendToUsers)
-			utils.FileLog.Info("发送附件模版消息失败,Err:%s", activityInfo.ActivityName)
-		}
 	}
 	return
 }
@@ -525,7 +491,7 @@ func SendEmailFileForAskMsgResearch(cont context.Context) (err error) {
 //非研选系列专家电话会,根据主持人姓名,会前15分钟将问题列表发送给至该主持人对应邮箱
 func SendEmailFileForAskMsg(cont context.Context) (err error) {
 	var msg string
-	var touser string
+	//var touser string
 	defer func() {
 		if err != nil {
 			go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
@@ -556,6 +522,7 @@ func SendEmailFileForAskMsg(cont context.Context) (err error) {
 		msg = "获取失败,Err:" + errEmail.Error()
 		return
 	}
+
 	for _, v := range listActivity {
 		activityInfo, _ := models.GetAddActivityInfoById(v.ActivityId)
 		if activityInfo == nil {
@@ -567,87 +534,43 @@ func SendEmailFileForAskMsg(cont context.Context) (err error) {
 			msg = "获取失败,Err:" + errFile.Error()
 			return
 		}
-		for _, v := range listEmail {
-			if strings.Index(activityInfo.Host, v.Name) > 0 {
-				touser += v.Email + ";"
-			}
-		}
-		if touser == "" {
-			msg = "没有对应的邮箱"
-			return
-		}
-		if utils.RunMode == "release" {
-			touser += "tshen@hzinsights.com;cxzhang@hzinsights.com"
-		} else {
-			touser = "tshen@hzinsights.com;cxzhang@hzinsights.com"
-		}
 
-		//创建excel
-		dir, errFile := os.Executable()
-		exPath := filepath.Dir(dir)
-		downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + utils.GetRandDigit(5) + ".xlsx"
-		xlsxFile := xlsx.NewFile()
-		if errFile != nil {
-			msg = "生成文件失败Err:" + errFile.Error()
-			return
-		}
-		style := xlsx.NewStyle()
-		alignment := xlsx.Alignment{
-			Horizontal: "center",
-			Vertical:   "center",
-			WrapText:   true,
-		}
-		style.Alignment = alignment
-		style.ApplyAlignment = true
-		sheet, errFile := xlsxFile.AddSheet("外呼名单")
-		if errFile != nil {
-			msg = "新增Sheet失败,Err:" + errFile.Error()
-			return
-		}
-		//设置宽度
-		_ = sheet.SetColWidth(1, 1, 30)
-		_ = sheet.SetColWidth(2, 2, 60)
-		//标头
-		rowTitle := sheet.AddRow()
-		cellA := rowTitle.AddCell()
-		cellA.Value = "姓名"
-		cellB := rowTitle.AddCell()
-		cellB.Value = "公司名称"
-		cellC := rowTitle.AddCell()
-		cellC.Value = "问题"
-		cellD := rowTitle.AddCell()
-		cellD.Value = "提交时间"
-		for _, item := range list {
-			row := sheet.AddRow()
-			cellA := row.AddCell()
-			cellA.Value = item.RealName
-			cellB := row.AddCell()
-			cellB.Value = item.CompanyName
-			cellC := row.AddCell()
-			cellC.Value = item.Content
-			cellD := row.AddCell()
-			cellD.Value = item.CreateTime
+		for _, v2 := range list {
+			user, err := models.GetWxUserItemByUserId(v2.UserId)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				return err
+			}
+			var sendMobile string
+			for _, vEmail := range listEmail {
+				if strings.Index(activityInfo.Host, vEmail.Name) > 0 {
+					sendMobile = vEmail.Mobile
+				}
+			}
+			//获取销售信息
+			sellerItem, err := models.GetSellerByCompanyIdCheckFicc(v2.CompanyId, 2)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				return err
+			}
+			//给研究员推送模板消息
+			if sellerItem != nil {
+				openIpItem, _ := models.GetUserRecordByMobile(4, sendMobile)
+				if openIpItem != nil && openIpItem.OpenId != "" {
+					SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
+				}
+			}
+			//给销售推送模板消息
+			if sellerItem != nil {
+				openIpItem, _ := models.GetUserRecordByMobile(4, sellerItem.Mobile)
+				if openIpItem != nil && openIpItem.OpenId != "" {
+					SendActivityAskApplyTemplateMsg(user.RealName+"——"+user.CompanyName+"(所属销售:"+sellerItem.RealName+")", v2.CreateTime, v2.Content, activityInfo.ActivityName, openIpItem.OpenId, activityInfo.ActivityId)
+				}
+			}
 		}
-		errFile = xlsxFile.Save(downLoadnFilePath)
+		errFile = models.UPdateActivityMsgToSendFile(v.ActivityId)
 		if errFile != nil {
-			msg = "保存文件失败Err:" + errFile.Error()
+			msg = "获取失败,Err:" + errFile.Error()
 			return
 		}
-		title := activityInfo.ActivityName + "-活动带问"
-		content := "活动带问详情"
-		fileName := downLoadnFilePath
-		sendResult := utils.SendEmailByHongze(title, content, touser, fileName, title+".xlsx")
-		if sendResult {
-			errFile = models.UPdateActivityMsgToSendFile(v.ActivityId)
-			if errFile != nil {
-				msg = "获取失败,Err:" + errFile.Error()
-				return
-			}
-			os.Remove(downLoadnFilePath)
-		} else {
-			go utils.SendEmail("发送附件模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format(utils.FormatDateTime), msg+";Err:"+activityInfo.ActivityName, utils.EmailSendToUsers)
-			utils.FileLog.Info("发送附件模版消息失败,Err:%s", activityInfo.ActivityName)
-		}
 	}
 	return
 }
@@ -663,6 +586,17 @@ func LabelStr(label string) (labelNew string) {
 	return labelNew
 }
 
+//5.3版本活动标签字符串处理
+func LabelStrV5(label string, isShowSubjectName int) (labelNew string) {
+	slicebr := strings.Split(label, "-")
+	if len(slicebr) < 2 || isShowSubjectName == 0 {
+		labelNew = label
+	} else {
+		labelNew = slicebr[1]
+	}
+	return labelNew
+}
+
 func ActivityAttendanceDetail(cont context.Context) (err error) {
 	defer func() {
 		if err != nil {
@@ -690,15 +624,21 @@ func ActivityAttendanceDetail(cont context.Context) (err error) {
 		findEndDate := doTime + " 23:59:59"
 		nameSlice := strings.Split(vAct.ActivityName, "】")
 		//fmt.Println(timeSlice[0])
+		//对于手动匹配到的活动数据也要更新
 		var activityName string
-		if len(nameSlice) > 1 {
-			activityName = nameSlice[len(nameSlice)-1]
+		if len(nameSlice) > 1 || vAct.JmcjRoadshowTitle != "" {
+			if vAct.JmcjRoadshowTitle != "" {
+				activityName = vAct.JmcjRoadshowTitle
+			} else {
+				activityName = nameSlice[len(nameSlice)-1]
+			}
 			if activityName != "" {
 				list, err := models.GetRoadshowDataList(activityName, findStartDate, findEndDate)
 				if err != nil {
 					fmt.Println("GetTacticsList Err:", err.Error())
 					return err
 				}
+
 				needAddAttendanc := make([]*models.CygxActivityAttendanceDetail, 0)
 				fmt.Println("原来的", vAct.ActivityName)
 				fmt.Println("处理的", activityName)
@@ -727,6 +667,7 @@ func ActivityAttendanceDetail(cont context.Context) (err error) {
 								item.MeetingStatusStr = "回放"
 							}
 							item.Position = v.Occupation
+							item.UseridEntity = v.UseridEntity
 							item.CreateTime = time.Now()
 							mobileStr += "'" + v.UserPhone + "'" + ","
 							needAddAttendanc = append(needAddAttendanc, item)
@@ -882,45 +823,131 @@ func AddCygxActivityRestrictSignupByAdmin(activityId int) (err error) {
 	return
 }
 
-// UserViewRedisData 阅读数据
-type UserViewRedisData struct {
-	Mobile      string `json:"mobile"`
-	Email       string `json:"email"`
-	RealName    string `json:"real_name"`
-	CompanyName string `json:"company_name"`
-	ViewTime    string `json:"view_time" description:"阅读时间,格式:2022-02-17 13:06:13"`
-	ProductId   int    `json:"product_id" description:"报告所属产品,ficc:1,权益:2"`
-	CompanyId   int    `json:"company_id" description:"客户id"`
-}
+//活动带问提醒
+func SendActivityAskApplyTemplateMsg(applyName, applyTime, askContent, activityName, openId string, activityId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go utils.SendEmail("发送模版消息失败"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
+		}
+		if msg != "" {
+			utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
+		}
+	}()
 
-type ReportViewRecord struct {
-	Id          int       `orm:"column(id);pk"`
-	UserId      int       `description:"用户id"`
-	ReportId    int       `description:"报告id"`
-	Mobile      string    `description:"手机号"`
-	Email       string    `description:"邮箱"`
-	RealName    string    `description:"用户实际姓名"`
-	CompanyName string    `description:"公司名称"`
-	CreateTime  time.Time `description:"创建时间"`
+	var accessToken string
+	if utils.RunMode == "release" {
+		accessToken, err = models.GetWxAccessTokenByXzs()
+		if err != nil {
+			msg = "GetWxAccessToken Err:" + err.Error()
+			return
+		}
+		if accessToken == "" {
+			msg = "accessToken is empty"
+			return
+		}
+	} else {
+		accessToken, err = models.GetWxAccessToken()
+		if err != nil {
+			msg = "GetWxAccessToken Err:" + err.Error()
+			return
+		}
+		if accessToken == "" {
+			msg = "accessToken is empty"
+			return
+		}
+	}
+
+	sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
+
+	sendMap := make(map[string]interface{})
+	sendData := make(map[string]interface{})
+
+	first := "有新的客户提问"
+	keyword1 := applyName
+	keyword2 := "-"
+	keyword3 := applyTime
+	keyword4 := askContent
+	remark := activityName
+	fontColor := "#D9001B"
+	sendData["first"] = map[string]interface{}{"value": first, "color": fontColor}
+	sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": fontColor}
+	sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": fontColor}
+	sendData["keyword3"] = map[string]interface{}{"value": keyword3, "color": fontColor}
+	sendData["keyword4"] = map[string]interface{}{"value": keyword4, "color": fontColor}
+	sendData["remark"] = map[string]interface{}{"value": remark, "color": fontColor}
+	if utils.RunMode == "release" {
+		sendMap["template_id"] = utils.WxMsgTemplateIdApplyXzs
+	} else {
+		sendMap["template_id"] = utils.WxMsgTemplateIdApply
+	}
+	sendMap["miniprogram"] = map[string]interface{}{"appid": utils.WxAppId, "pagepath": "activityPages/activityDetail/activityDetail?id=" + strconv.Itoa(activityId)}
+	sendMap["data"] = sendData
+	sendTemplateMsg(sendUrl, openId, sendMap)
+	fmt.Println("send end")
+	return
 }
 
-// PushViewRecordNewRedisData 阅读数据加入到redis
-func PushViewRecordNewRedisData(reportViewRecord *ReportViewRecord, companyId int) bool {
-	data := &UserViewRedisData{
-		Mobile:      reportViewRecord.Mobile,
-		Email:       reportViewRecord.Email,
-		RealName:    reportViewRecord.RealName,
-		CompanyName: reportViewRecord.CompanyName,
-		ViewTime:    reportViewRecord.CreateTime.Format(utils.FormatDateTime),
-		ProductId:   2,
-		CompanyId:   companyId,
-	}
-	if utils.Re == nil {
-		err := utils.Rc.LPush(utils.CACHE_KEY_USER_VIEW, data)
+//专项产业调研模板消息推送
+func SendSpecialTemplateMsg(applyName, applyTime, mobile, activityName, openId, resource string) (err error) {
+	var msg string
+	defer func() {
 		if err != nil {
-			fmt.Println("PushViewRecordNewRedisData LPush Err:" + err.Error())
+			go utils.SendEmail("发送模版消息失败"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
 		}
-		return true
+		if msg != "" {
+			utils.FileLog.Info("发送模版消息失败,msg:%s", msg)
+		}
+	}()
+	var accessToken string
+	if utils.RunMode == "release" {
+		accessToken, err = models.GetWxAccessTokenByXzs()
+		if err != nil {
+			msg = "GetWxAccessToken Err:" + err.Error()
+			return
+		}
+		if accessToken == "" {
+			msg = "accessToken is empty"
+			return
+		}
+	} else {
+		accessToken, err = models.GetWxAccessToken()
+		if err != nil {
+			msg = "GetWxAccessToken Err:" + err.Error()
+			return
+		}
+		if accessToken == "" {
+			msg = "accessToken is empty"
+			return
+		}
+	}
+	sendUrl := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken
+	sendMap := make(map[string]interface{})
+	sendData := make(map[string]interface{})
+	var first string
+	if resource == "sale" {
+		first = "有客户对专项调研感兴趣"
+	} else {
+		first = "有5家公司预报名专项调研"
+	}
+
+	keyword1 := applyName
+	keyword2 := mobile
+	keyword3 := applyTime
+	keyword4 := activityName
+
+	fontColor := "#D9001B"
+	sendData["first"] = map[string]interface{}{"value": first, "color": fontColor}
+	sendData["keyword1"] = map[string]interface{}{"value": keyword1, "color": fontColor}
+	sendData["keyword2"] = map[string]interface{}{"value": keyword2, "color": fontColor}
+	sendData["keyword3"] = map[string]interface{}{"value": keyword3, "color": fontColor}
+	sendData["keyword4"] = map[string]interface{}{"value": keyword4, "color": fontColor}
+	if utils.RunMode == "release" {
+		sendMap["template_id"] = utils.WxMsgTemplateIdApplyXzs
+	} else {
+		sendMap["template_id"] = utils.WxMsgTemplateIdApply
 	}
-	return false
+	sendMap["data"] = sendData
+	sendTemplateMsg(sendUrl, openId, sendMap)
+	return
 }

+ 76 - 5
services/article.go

@@ -56,6 +56,18 @@ func GetReportContentTextSub(content string) (contentSub string, err error) {
 	return
 }
 
+func GetReportContentTextSubNew(content string) (contentSub string, err error) {
+	content = html.UnescapeString(content)
+	doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
+	docText := doc.Text()
+	bodyRune := []rune(docText)
+	bodyRuneLen := len(bodyRune)
+	body := string(bodyRune[:bodyRuneLen])
+	contentSub = body
+	contentSub = strings.Replace(body, "Powered by Froala Editor", "", -1)
+	return
+}
+
 //解析文章内容
 func GetArticleAll() {
 	var err error
@@ -294,7 +306,7 @@ func GetArticleListByApi(cont context.Context) (err error) {
 			go utils.SendEmail(utils.APPNAME+"【"+utils.RunMode+"】"+"失败提醒", "GetArticleListByApi ErrMsg:"+err.Error(), utils.EmailSendToUsers)
 		}
 	}()
-	url := "https://vmp.hzinsights.com/v2api/articles/mp?take=100&skip=0&publish_status=2"
+	url := "https://vmp.hzinsights.com/v2api/articles/mp?take=100&skip=0&publish_status=2,4&order=publish_date&sort=DESC"
 	method := "GET"
 	client := &nhttp.Client{}
 	req, err := nhttp.NewRequest(method, url, nil)
@@ -346,13 +358,15 @@ func GetArticleListByApi(cont context.Context) (err error) {
 	var list []*models.Tactics2
 	var listAuthor []*models.CygxArticleAuthor
 	for _, v := range listData {
-		if exitMap[v.SeriesId] > 0 {
+		//状态等于 2 跟 4 的进行同步
+		if exitMap[v.SeriesId] > 0 && (v.PublishStatus == 2 || v.PublishStatus == 4) {
 			v.PublishDate = time.Date(v.PublishDate.Year(), v.PublishDate.Month(), v.PublishDate.Day(), v.PublishDate.Hour(), v.PublishDate.Minute(), v.PublishDate.Second(), v.PublishDate.Nanosecond(), time.Local)
 			item := new(models.Tactics2)
 			itemAuthor := new(models.CygxArticleAuthor)
 			item.ArticleId = v.ArticleId
 			item.Title = v.Title
 			item.TitleEn = v.TitleEn
+			item.File = v.File
 			if v.Frequency == "日度" {
 				item.UpdateFrequency = "daily"
 			} else if v.Frequency == "周度" {
@@ -374,6 +388,15 @@ func GetArticleListByApi(cont context.Context) (err error) {
 			item.CategoryName = v.Industry.Name
 			item.CategoryId = exitMap[v.SeriesId]
 			item.SubCategoryName = v.Series.Name
+			if len(v.Stock) > 0 {
+				var stock string
+				for _, vS := range v.Stock {
+					stock += vS + "/"
+				}
+				stock = strings.TrimRight(stock, "/")
+				item.Stock = stock
+			}
+			item.FieldName = v.Field.Name
 			list = append(list, item)
 			itemAuthor.ArticleId = v.ArticleId
 			itemAuthor.Name = v.Author.Name
@@ -452,7 +475,7 @@ func GetArticleListByApi(cont context.Context) (err error) {
 			return err
 		}
 		v.Body = strings.Replace(v.Body, "http://vmp.hzinsights.com", "https://vmp.hzinsights.com", -1)
-		expertNumStr, expertContentStr, interviewDateStr, fileLink, bodyReturn := BodyAnalysis2(v.Body)
+		expertNumStr, expertContentStr, interviewDateStr, _, bodyReturn := BodyAnalysis2(v.Body)
 		if strings.Index(v.Body, "报告全文(") > 0 && strings.Index(v.Body, "PDF格式报告下载.pdf") > 0 {
 			v.Body = strings.Replace(v.Body, "报告全文(", "", -1)
 			v.Body = strings.Replace(v.Body, "PDF格式报告下载.pdf", "", -1)
@@ -514,7 +537,9 @@ func GetArticleListByApi(cont context.Context) (err error) {
 			//updateParams["IsClass"] = v.IsClass
 			v.Department = "弘则权益研究"
 			updateParams["Department"] = v.Department
-			updateParams["FileLink"] = fileLink
+			updateParams["FileLink"] = v.File
+			updateParams["Stock"] = v.Stock
+			updateParams["FieldName"] = v.FieldName
 			whereParam := map[string]interface{}{"article_id": v.ArticleId}
 			err = models.UpdateByExpr(models.CygxArticle{}, whereParam, updateParams)
 			if err != nil {
@@ -538,6 +563,7 @@ func GetArticleListByApi(cont context.Context) (err error) {
 			item.CategoryName = v.CategoryName
 			item.SubCategoryName = v.SubCategoryName
 			item.CategoryId = v.CategoryId
+			item.CategoryIdTwo = v.CategoryId
 			item.PublishStatus = 1
 			item.ExpertBackground = expertContentStr
 			item.ExpertNumber = expertNumStr
@@ -548,8 +574,10 @@ func GetArticleListByApi(cont context.Context) (err error) {
 			item.IsSummary = v.IsSummary
 			item.IsReport = v.IsReport
 			item.ReportType = v.ReportType
-			item.FileLink = fileLink
+			item.FileLink = v.File
 			item.MatchTypeName = matchTypeName
+			item.Stock = v.Stock
+			item.FieldName = v.FieldName
 			_, err = models.AddCygxArticles(item)
 			if err != nil {
 				fmt.Println("AddCygxArticle Err:", err.Error())
@@ -726,3 +754,46 @@ func StatisticalReport() {
 	return
 
 }
+
+// UserViewRedisData 阅读数据
+type UserViewRedisData struct {
+	Mobile      string `json:"mobile"`
+	Email       string `json:"email"`
+	RealName    string `json:"real_name"`
+	CompanyName string `json:"company_name"`
+	ViewTime    string `json:"view_time" description:"阅读时间,格式:2022-02-17 13:06:13"`
+	ProductId   int    `json:"product_id" description:"报告所属产品,ficc:1,权益:2"`
+	CompanyId   int    `json:"company_id" description:"客户id"`
+}
+
+type ReportViewRecord struct {
+	Id          int       `orm:"column(id);pk"`
+	UserId      int       `description:"用户id"`
+	ReportId    int       `description:"报告id"`
+	Mobile      string    `description:"手机号"`
+	Email       string    `description:"邮箱"`
+	RealName    string    `description:"用户实际姓名"`
+	CompanyName string    `description:"公司名称"`
+	CreateTime  time.Time `description:"创建时间"`
+}
+
+// PushViewRecordNewRedisData 阅读数据加入到redis
+func PushViewRecordNewRedisData(reportViewRecord *ReportViewRecord, companyId int) bool {
+	data := &UserViewRedisData{
+		Mobile:      reportViewRecord.Mobile,
+		Email:       reportViewRecord.Email,
+		RealName:    reportViewRecord.RealName,
+		CompanyName: reportViewRecord.CompanyName,
+		ViewTime:    reportViewRecord.CreateTime.Format(utils.FormatDateTime),
+		ProductId:   2,
+		CompanyId:   companyId,
+	}
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_KEY_USER_VIEW, data)
+		if err != nil {
+			fmt.Println("PushViewRecordNewRedisData LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}

+ 393 - 0
services/send_company_user.go

@@ -0,0 +1,393 @@
+package services
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/tealeg/xlsx"
+	"hongze/hongze_cygx/models"
+	"hongze/hongze_cygx/utils"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type GetShangHaiTokenResultApi struct {
+	Code int                   `json:"code"`
+	Msg  string                `json:"msg"`
+	Time int                   `json:"time"`
+	Data ShangHaiResultApidate `json:"data"`
+}
+
+type ShangHaiResultApidate struct {
+	AccessToken string `json:"access_token"`
+	ExpireIn    int    `json:"expire_in"`
+}
+
+type GetShangHaiTokenResultApiComPany struct {
+	Code int       `json:"code"`
+	Msg  string    `json:"msg"`
+	Time int       `json:"time"`
+	Data FailInfos `json:"data"`
+}
+type FailInfos struct {
+	TotalCount int                            `json:"total_count"`
+	FailInfo   []ShangHaiResultApidateComPany `json:"fail_info"`
+}
+
+type ShangHaiResultApidateComPany struct {
+	ErrVal string `json:"errVal"`
+	ErrMsg string `json:"errMsg"`
+}
+
+//c
+func SendComapnyToShanghai(url, jsonCompany, postType string) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go utils.SendEmail("同步策略平台获取数据信息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToExpert)
+		}
+	}()
+	method := "POST"
+	//fmt.Println(string(jsonCompany))
+	//utils.FileLog.Info(string(jsonCompany))
+	payload := strings.NewReader(jsonCompany)
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, payload)
+	if err != nil {
+		msg = "NewRequest Err:" + err.Error()
+		return err
+	}
+	req.Header.Add("Content-Type", "application/json")
+	res, err := client.Do(req)
+	if err != nil {
+		msg = "client.Do Err:" + err.Error()
+		return err
+	}
+	defer res.Body.Close()
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		msg = "ioutil.ReadAll Err:" + err.Error()
+		return err
+	}
+	var result GetShangHaiTokenResultApiComPany
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		msg = "json.Unmarshal Err:" + err.Error()
+		return err
+
+	}
+	//if result.Code != 1 {
+	//	go utils.SendEmail("同步策略平台信息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), url, utils.EmailSendToExpert)
+	//}
+	item := new(models.CygxShanghaiCompanyLog)
+	item.CreateTime = time.Now()
+	item.Url = url
+	item.Body = jsonCompany
+	item.Result = string(body)
+	go models.AddCygxShanghaiCompanyLog(item)
+
+	if strings.Index(string(body), "必填") > 0 || strings.Index(string(body), "失败") > 0 || strings.Index(string(body), "社会信用代码格式错误") > 0 {
+		go utils.SendEmail("同步策略平台信息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), string(body), utils.EmailSendToExpert)
+	}
+	//var companyCode string
+	for _, v := range result.Data.FailInfo {
+		if v.ErrMsg != "" {
+			//companyCode += "'" + v.ErrVal + "',"
+			item := new(models.CygxShanghaiErrLog)
+			item.CreateTime = time.Now()
+			item.ErrMsg = v.ErrMsg
+			item.ErrVal = v.ErrVal
+			item.ErrType = postType
+			go models.AddCygxShanghaiErrLog(item)
+		}
+	}
+	return
+	//给产品导数据用,别删
+	//companyCode = postType + companyCode
+	////fmt.Println(result.Data.FailInfo)
+	//utils.FileLog.Info(string(companyCode))
+	//utils.FileLog.Info(string(body))
+	//fmt.Println(string(body))
+}
+
+func DotongbuShangHai(cont context.Context) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go utils.SendEmail("同步策略平台获取数据信息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToExpert)
+		}
+	}()
+	//同步24小时之前的数据到上海平台,为防止遗漏改成30小时
+	var condition string
+	updateTime := time.Now().Add(-time.Hour * 30).Format("2006-01-02 15:04:05")
+	condition = ` AND p.modify_time > ` + "'" + updateTime + "'"
+	fmt.Println(condition)
+	//获取token
+	url := "https://crm.hzinsights.com/openapi/v1/auth/getAccessToken?app_key=26945134&app_secret=b99cb2bdec70d20156000f664ec5ac30"
+	method := "GET"
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, nil)
+	if err != nil {
+		msg = "GetToken Err:" + err.Error()
+		return err
+	}
+	res, err := client.Do(req)
+	if err != nil {
+		msg = "client Err:" + err.Error()
+		return err
+	}
+	defer res.Body.Close()
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		msg = "body Err:" + err.Error()
+		return
+	}
+	var result GetShangHaiTokenResultApi
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		msg = "Get result Err:" + err.Error()
+		return
+	}
+	accessToken := result.Data.AccessToken
+	fmt.Println(accessToken)
+	//同步权益客户
+	companyList, err := models.GetSendCompanyList(condition)
+	if err != nil {
+		msg = "GetSendCompanyList Err:" + err.Error()
+		return
+	}
+	fmt.Println("权益客户", len(companyList))
+	var companyItems []*models.CompanyJson
+	if len(companyList) > 0 {
+		url = "https://crm.hzinsights.com/openapi/v1/Customer/batchSyncFiccCustomer?access_token=" + accessToken
+		for k, _ := range companyList {
+			companyList[k].Fe = "权益"
+			companyList[k].EndDate = strconv.Itoa(int(companyList[k].EndDateTime.Unix()))
+			//一次同步一百条
+			companyItems = append(companyItems, companyList[k])
+			if (k+1)%100 == 0 {
+				data, err := json.Marshal(companyItems)
+				if err != nil {
+					msg = "companyItems Err:" + err.Error()
+					return err
+				}
+				jsonstr := string(data)
+				jsonstr = "{\"sync_data\": " + jsonstr + " }"
+				SendComapnyToShanghai(url, jsonstr, "权益")
+				companyItems = make([]*models.CompanyJson, 0)
+			}
+		}
+		//如果剩下还有则同步剩下的部分
+		if len(companyItems) > 0 {
+			data, err := json.Marshal(companyItems)
+			if err != nil {
+				msg = "companyItems Err:" + err.Error()
+				return err
+			}
+			jsonstr := string(data)
+			jsonstr = "{\"sync_data\": " + jsonstr + " }"
+			SendComapnyToShanghai(url, jsonstr, "权益")
+			companyItems = make([]*models.CompanyJson, 0)
+		}
+	}
+	//同步FICC客户
+	companyFiccList, err := models.GetSendCompanyFiccList(condition)
+	if err != nil {
+		msg = "GetSendCompanyFiccList Err:" + err.Error()
+		return err
+	}
+	fmt.Println("FICC客户", len(companyFiccList))
+	var companyFiccItems []*models.CompanyJson
+	if len(companyFiccList) > 0 {
+		url = "https://crm.hzinsights.com/openapi/v1/Customer/batchSyncFiccCustomer?access_token=" + accessToken
+		for k, _ := range companyFiccList {
+			companyFiccList[k].Fe = "FICC"
+			companyFiccList[k].EndDate = strconv.Itoa(int(companyFiccList[k].EndDateTime.Unix()))
+			//一次同步一百条
+			companyFiccItems = append(companyFiccItems, companyFiccList[k])
+			if (k+1)%100 == 0 {
+				data, err := json.Marshal(companyFiccItems)
+				if err != nil {
+					msg = "companyFiccItems Err:" + err.Error()
+					return err
+				}
+				jsonstr := string(data)
+				jsonstr = "{\"sync_data\": " + jsonstr + " }"
+				SendComapnyToShanghai(url, jsonstr, "FICC")
+				companyFiccItems = make([]*models.CompanyJson, 0)
+			}
+		}
+		//如果剩下还有则同步剩下的部分
+		if len(companyFiccItems) > 0 {
+			data, err := json.Marshal(companyFiccItems)
+			if err != nil {
+				msg = "companyFiccItems Err:" + err.Error()
+				return err
+			}
+			jsonstr := string(data)
+			jsonstr = "{\"sync_data\": " + jsonstr + " }"
+			SendComapnyToShanghai(url, jsonstr, "FICC")
+		}
+	}
+
+	userList, err := models.GetSendUserList(condition)
+	if err != nil {
+		msg = "GetSendUserList Err:" + err.Error()
+		return err
+	}
+	fmt.Println("用户", len(userList))
+	var userItems []*models.UserJson
+	if len(userList) > 0 {
+		url = "https://crm.hzinsights.com/openapi/v1/CustomerContact/batchSyncFiccCustomerContact?access_token=" + accessToken
+		for k, v := range userList {
+			if v.Sex == "1" {
+				userList[k].Sex = "男"
+			} else {
+				userList[k].Sex = "女"
+			}
+			if v.IsMaker == "1" {
+				userList[k].IsMaker = "是"
+			} else {
+				userList[k].IsMaker = "否"
+			}
+			userList[k].CountryCode = "+" + v.CountryCode
+			userList[k].OutboundCountryCode = "+" + v.OutboundCountryCode
+			if userList[k].Mobile != "" && userList[k].OutboundMobile != "" && userList[k].Mobile == userList[k].OutboundMobile {
+				userList[k].OutboundMobile = ""
+				userList[k].OutboundCountryCode = ""
+			}
+			//一次同步一百条
+			userItems = append(userItems, userList[k])
+			if (k+1)%100 == 0 {
+				data, err := json.Marshal(userItems)
+				if err != nil {
+					msg = "userItems Err:" + err.Error()
+					return err
+				}
+				fmt.Println(k)
+				jsonstr := string(data)
+				jsonstr = "{\"sync_data\": " + jsonstr + " }"
+				SendComapnyToShanghai(url, jsonstr, "user")
+				userItems = make([]*models.UserJson, 0)
+			}
+		}
+
+		//如果剩下还有则同步剩下的部分
+		if len(userItems) > 0 {
+			data, err := json.Marshal(userItems)
+			if err != nil {
+				msg = "userItems Err:" + err.Error()
+				return err
+			}
+			jsonstr := string(data)
+			jsonstr = "{\"sync_data\": " + jsonstr + " }"
+			SendComapnyToShanghai(url, jsonstr, "user")
+			companyItems = make([]*models.CompanyJson, 0)
+		}
+	}
+	return
+}
+
+func DotongbuShangHaiSendEmail(cont context.Context) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go utils.SendEmail("发送邮件同步策略平台获取数据信息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToExpert)
+		}
+	}()
+	list, err := models.GetCygxShanghaiCompanyLog()
+	if err != nil {
+		msg = "GetCygxShanghaiCompanyLog Err:" + err.Error()
+		return err
+	}
+	mapErrMsg := make(map[string]string)
+	for _, v := range list {
+		data := new(GetShangHaiTokenResultApiComPany)
+		err := json.Unmarshal([]byte(v.Result), &data)
+		if err != nil {
+			msg = "GetShangHaiTokenResultApiComPany Err:" + err.Error()
+			return err
+		}
+		if len(data.Data.FailInfo) > 0 {
+			for _, vCompany := range data.Data.FailInfo {
+				mapErrMsg[vCompany.ErrVal] = vCompany.ErrMsg
+			}
+		}
+	}
+	//创建excel
+	dir, err := os.Executable()
+	exPath := filepath.Dir(dir)
+	downLoadnFilePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + utils.GetRandDigit(5) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+	if err != nil {
+		return
+	}
+	style := xlsx.NewStyle()
+	alignment := xlsx.Alignment{
+		Horizontal: "center",
+		Vertical:   "center",
+		WrapText:   true,
+	}
+	style.Alignment = alignment
+	style.ApplyAlignment = true
+	sheet, err := xlsxFile.AddSheet("上海策略品台同步名单")
+	if err != nil {
+		return
+	}
+	//设置宽度
+	_ = sheet.SetColWidth(0, 1, 30)
+	_ = sheet.SetColWidth(2, 2, 10)
+	_ = sheet.SetColWidth(3, 3, 30)
+
+	//标头
+	rowTitle := sheet.AddRow()
+	cellA := rowTitle.AddCell()
+	cellA.Value = "客户名称"
+	cellB := rowTitle.AddCell()
+	cellB.Value = "社会信用码"
+	cellC := rowTitle.AddCell()
+	cellC.Value = "客户类型"
+	cellD := rowTitle.AddCell()
+	cellD.Value = "错误消息"
+	for _, v := range list {
+		data := new(models.CompanyUnJsonList)
+		err := json.Unmarshal([]byte(v.Body), &data)
+		if err != nil {
+			msg = "CompanyUnJsonList Err:" + err.Error()
+			return err
+		}
+		if len(data.SyncData) > 0 {
+			for _, item := range data.SyncData {
+				row := sheet.AddRow()
+				cellA := row.AddCell()
+				cellA.Value = item.CompanyName
+				cellB := row.AddCell()
+				cellB.Value = item.CreditCode
+				cellC := row.AddCell()
+				cellC.Value = item.Fe
+				if mapErrMsg[item.CreditCode] != "" {
+					cellD := row.AddCell()
+					cellD.Value = mapErrMsg[item.CreditCode]
+				}
+			}
+		}
+	}
+	title := time.Now().Format(utils.FormatDate) + "上海策略品台同步名单"
+	content := time.Now().Format(utils.FormatDate) + "上海策略品台同步名单"
+	fileName := downLoadnFilePath
+	err = xlsxFile.Save(downLoadnFilePath)
+	if err != nil {
+		return
+	}
+	if len(list) > 0 {
+		utils.SendEmailByHongze(title, content, "cxzhang@hzinsights.com;tshen@hzinsights.com", fileName, title+".xlsx")
+	}
+	os.Remove(downLoadnFilePath)
+	go models.DeleteCygxShanghaiCompanyLog()
+	return
+}

+ 12 - 6
services/task.go

@@ -31,14 +31,14 @@ func Task() {
 		sendEmailFileToExpert := task.NewTask("sendEmailFileToExpert", "0 */5 8-22 * * *", SendEmailFileToExpert) //预约外呼名单,会前1小时自动发送邮件给专家组
 		task.AddTask("sendEmailFileToExpert", sendEmailFileToExpert)
 
-		sendEmailFileForAskMsgResearch := task.NewTask("sendEmailFileForAskMsgResearch", "0 */5 8-22 * * *", SendEmailFileForAskMsgResearch) //研选系列专家电话会,会前1小时将问题列表发送给邮箱
-		task.AddTask("sendEmailFileForAskMsgResearch", sendEmailFileForAskMsgResearch)
-
-		sendEmailFileForAskMsg := task.NewTask("sendEmailFileForAskMsg", "0 */5 8-22 * * *", SendEmailFileForAskMsg) //非研选系列专家电话会,根据主持人姓名,会前15分钟将问题列表发送给至该主持人对应邮箱
-		task.AddTask("sendEmailFileForAskMsg", sendEmailFileForAskMsg)
-
 		sendEmailUserWhiteListChange := task.NewTask("sendEmailUserWhiteListChange", "0 00 17 * * *", SendEmailUserWhiteListChange) //新增 和冻结的客户白名单
 		task.AddTask("白名单发送", sendEmailUserWhiteListChange)
+
+		dotongbuShangHai := task.NewTask("dotongbuShangHai", "0 30 3 * * *", DotongbuShangHai) //把信息同步到上海策略品台
+		task.AddTask("同步用户到上海", dotongbuShangHai)
+
+		dotongbuShangHaiSendEmail := task.NewTask("dotongbuShangHaiSendEmail", "0 00 4 * * *", DotongbuShangHaiSendEmail) //发送上海策略品台同步结果名单的邮件附件
+		task.AddTask("发送上海策略品台同步结果名单的邮件附件", dotongbuShangHaiSendEmail)
 	}
 
 	if utils.IsTask {
@@ -55,6 +55,12 @@ func Task() {
 		task.AddTask("chageIndustrialArticleNum", chageIndustrialArticleNum)
 		activityAttendanceDetail := task.NewTask("activityAttendanceDetail", "0 00 3 * * *", ActivityAttendanceDetail) //同步进门财经的路演信息
 		task.AddTask("sendEmailUserWhiteListChange", activityAttendanceDetail)
+
+		sendEmailFileForAskMsgResearch := task.NewTask("sendEmailFileForAskMsgResearch", "0 */5 8-22 * * *", SendEmailFileForAskMsgResearch) //研选系列专家电话会,会前1小时将问题列表发送给邮箱
+		task.AddTask("sendEmailFileForAskMsgResearch", sendEmailFileForAskMsgResearch)
+
+		sendEmailFileForAskMsg := task.NewTask("sendEmailFileForAskMsg", "0 */5 8-22 * * *", SendEmailFileForAskMsg) //非研选系列专家电话会,根据主持人姓名,会前15分钟将问题列表发送给至该主持人对应邮箱
+		task.AddTask("sendEmailFileForAskMsg", sendEmailFileForAskMsg)
 	}
 
 	//ActivityAttendanceDetail()

+ 5 - 0
services/user.go

@@ -613,6 +613,7 @@ func SendEmailUserWhiteListChange(cont context.Context) (err error) {
 	if mobileStr == "" {
 		mobileStr = "1"
 	}
+	mobileStr = strings.Replace(mobileStr, " ", "", -1)
 	//手机号新增
 	fieldStr = ` u.mobile,u.country_code,u.real_name,c.company_name,u.company_id,cp.seller_name,cp.status,`
 	condition = `  AND cp.status IN ( '正式', '试用' ) AND u.mobile IN (` + mobileStr + `) `
@@ -626,6 +627,7 @@ func SendEmailUserWhiteListChange(cont context.Context) (err error) {
 	if outboundMobileStr == "" {
 		outboundMobileStr = "1"
 	}
+	outboundMobileStr = strings.Replace(outboundMobileStr, " ", "", -1)
 	fieldStr = ` u.outbound_mobile as mobile,u.outbound_country_code as country_code,u.real_name,c.company_name,u.company_id,cp.status,`
 	condition = `  AND cp.status IN ( '正式', '试用' ) AND u.outbound_mobile IN (` + outboundMobileStr + `) `
 	listOutboundMobile, err := models.GetFormalUserWhiteList(fieldStr, condition)
@@ -1161,6 +1163,9 @@ func SendEmailAllUserWithCompany() (err error) {
 			if item.CountryCode != "" && item.Mobile != "" {
 				cellC.Value = "+" + item.CountryCode
 			}
+			if item.CountryCode == "" && item.Mobile != "" {
+				cellC.Value = "+86"
+			}
 			cellD := row.AddCell()
 			cellD.Value = ""
 			cellE := row.AddCell()

+ 1 - 5
services/wechat.go

@@ -63,16 +63,12 @@ type WxToken struct {
 func WxGetToken() (item *WxToken, err error) {
 	requestUrl := `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s`
 	requestUrl = fmt.Sprintf(requestUrl, utils.WxAppId, utils.WxAppSecret)
-	fmt.Println("requestUrl:", requestUrl)
 	result, err := http.Get(requestUrl)
-	utils.FileLog.Info("WxGetToken Result:%s ", string(result))
 	if err != nil {
+		utils.FileLog.Info("WxGetToken Result:%s ", string(result))
 		return nil, err
 	}
 	err = json.Unmarshal(result, &item)
-	fmt.Println("WxGetToken start")
-	fmt.Println(string(result))
-	fmt.Println("WxGetToken end")
 	return
 }
 

+ 7 - 2
utils/config.go

@@ -66,6 +66,8 @@ var (
 	HtgjDefaultSaleName       string //海通默认销售名称
 	HtgjSalt                  string //海通加密使用的盐
 	HtgjName                  string //海通国际名称
+	ActSendMsgMobile          string //活动带问发送模板消息接收者的手机号
+	StrategyPlatform          string //策略品台跳转链接地址
 )
 
 func init() {
@@ -114,6 +116,7 @@ func init() {
 	HtgjDefaultSaleName = "王芳"
 	HtgjSalt = "HTGJ&HZ"
 	HtgjName = "海通国际"
+	StrategyPlatform = "https://vmp.hzinsights.com/v2/articles/"
 	if RunMode == "release" {
 		WxAppId = "wxcc32b61f96720d2f"
 		WxAppSecret = "06894933fafb24dafead7eaae09c08e0"
@@ -126,18 +129,19 @@ func init() {
 		WxPublicAppId = "wx4a844c734d8c8e56"
 		WxPublicAppSecret = "26c586e7ccb3c575433f0f37797b3eeb"
 		WxPublicId = "gh_b67e0049fb8c"
-		IndexName = "cygx_article_v0125"
+		IndexName = "cygx_article_v0225"
 
 		//接收附件邮箱
 		EmailTechnology = "mlluo@hzinsights.com;jxu@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com"    //科技行业专家邮箱
 		EmailMedicine = "xlzheng@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com"                       //医药行业专家邮箱
 		EmailConsumption = "yrhuang@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com;jxu@hzinsights.com" //消费行业专家邮箱
 		EmailZhizao = "xfma@hzinsights.com;agne@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com"        //智造行业专家邮箱
-		EmailStrategy = "xfma@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com"                          //策略行业专家邮箱
+		EmailStrategy = "experts@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com"                       //策略行业专家邮箱
 		EmailExpert = "experts@hzinsights.com;tshen@hzinsights.com;cxzhang@hzinsights.com;jhwang@hzinsights.com"                         //研选行业专家邮箱
 		EmaiWhiteUserList = "tshen@hzinsights.com;cxzhang@hzinsights.com;yyli@hzinsights.com"                                            //白名单邮箱
 		WxMsgTemplateIdAskMsg = "PaoDanHGlt1kFw5q-4_ipJSwO3FyZpxSSNg4rwB7YCk"
 		WxMsgTemplateIdAskMsgMobile = ""
+		ActSendMsgMobile = "15618524605"
 
 	} else {
 		WxAppId = "wxcc32b61f96720d2f"
@@ -165,6 +169,7 @@ func init() {
 		EmaiWhiteUserList = "cxzhang@hzinsights.com"
 		WxMsgTemplateIdAskMsg = "qfNuops-sKrfIkbA7U97A7gSrX03mUpoEpJksRUdloo"
 		WxMsgTemplateIdAskMsgMobile = "15557270714,17634786714,18767183922,17516315016"
+		ActSendMsgMobile = "17634786714"
 	}
 
 	//查研观向小助手

+ 1 - 0
utils/constants.go

@@ -23,6 +23,7 @@ const (
 	APPNAME           = "弘则-查研观向"
 	EmailSendToUsers  = "glji@hzinsights.com;pyan@hzinsights.com;cxzhang@hzinsights.com"
 	EmailSendToExpert = "cxzhang@hzinsights.com"
+	DefaultHeadimgurl = "https://hzstatic.hzinsights.com/static/temp/20220426202204/20220426/P5qLR2zzfBdKItp3eX2Du1tvq9Ba.jpg"
 )
 
 //手机号,电子邮箱正则

+ 12 - 1
utils/logs.go

@@ -1,10 +1,21 @@
 package utils
 
-import "github.com/beego/beego/v2/adapter/logs"
+import (
+	//"github.com/beego/beego/v2/adapter/logs"
+	"github.com/beego/beego/v2/core/logs"
+	"os"
+	"time"
+)
 
 var FileLog *logs.BeeLogger
+var BinLog *logs.BeeLogger
 
 func init() {
 	FileLog = logs.NewLogger(1000000)
 	FileLog.SetLogger(logs.AdapterFile, `{"filename":"./rdlucklog/hongze_cygx.log"}`)
+
+	binLogDir := `./binlog`
+	os.MkdirAll(binLogDir, os.ModePerm)
+	BinLog = logs.NewLogger(1000000)
+	BinLog.SetLogger(logs.AdapterMultiFile, `{"filename":"./binlog/binlog.`+time.Now().Format(FormatDate)+`.log","maxdays":30}`)
 }