Procházet zdrojové kódy

Merge branch 'master' of http://8.136.199.33:3000/hongze/hz_crm_api into cygx_need_p1_812

xingzai před 1 rokem
rodič
revize
b606ee543e
64 změnil soubory, kde provedl 6361 přidání a 421 odebrání
  1. 2 2
      controllers/business_trip/business_apply.go
  2. 110 2
      controllers/company.go
  3. 31 12
      controllers/company_apply_v2.go
  4. 1 1
      controllers/company_seller.go
  5. 54 34
      controllers/cygx/activity.go
  6. 24 15
      controllers/cygx/activity_meet.go
  7. 15 4
      controllers/cygx/activity_signup.go
  8. 2 0
      controllers/cygx/activity_special.go
  9. 118 26
      controllers/cygx/activity_special_trip.go
  10. 17 2
      controllers/cygx/cygx_activity_type.go
  11. 9 2
      controllers/cygx/industrial_management.go
  12. 43 8
      controllers/cygx/user.go
  13. 12 3
      controllers/data_manage/excel_info.go
  14. 1197 0
      controllers/eta_business/eta_business.go
  15. 197 0
      controllers/eta_business/eta_business_menu.go
  16. 19 2
      controllers/eta_trial.go
  17. 401 0
      controllers/eta_version_update_log.go
  18. 1 1
      controllers/full_company.go
  19. 539 0
      controllers/help_doc/classify.go
  20. 429 0
      controllers/help_doc/doc.go
  21. 1 1
      controllers/sys_menu.go
  22. 1 1
      models/company/company.go
  23. 17 0
      models/company/company_permission.go
  24. 164 150
      models/cygx/activity.go
  25. 27 26
      models/cygx/activity_meet.go
  26. 26 25
      models/cygx/activity_signup.go
  27. 19 2
      models/cygx/activity_special_trip.go
  28. 110 2
      models/cygx/activity_special_trip_bill.go
  29. 1 1
      models/cygx/activity_type.go
  30. 1 1
      models/cygx/company_user_type.go
  31. 39 0
      models/cygx/cygx_activity_special_points_company.go
  32. 27 3
      models/cygx/cygx_user.go
  33. 0 18
      models/cygx/report_article.go
  34. 38 0
      models/cygx/report_mapping_celue.go
  35. 37 0
      models/db.go
  36. 325 0
      models/eta_business/eta_business.go
  37. 123 0
      models/eta_business/eta_business_contract.go
  38. 147 0
      models/eta_business/eta_business_menu.go
  39. 133 0
      models/eta_business/eta_business_menu_relate.go
  40. 136 0
      models/eta_business/eta_business_operation_record.go
  41. 144 0
      models/eta_version_update_log.go
  42. 248 0
      models/help_doc/classify.go
  43. 192 0
      models/help_doc/help_doc.go
  44. 4 1
      models/yb/apply_record.go
  45. 243 0
      routers/commentsRouter.go
  46. 19 0
      routers/router.go
  47. 24 0
      services/company_apply/company_approval.go
  48. 6 0
      services/company_approval_message.go
  49. 11 7
      services/cygx/acitvity.go
  50. 1 1
      services/cygx/activity_poster.go
  51. 13 0
      services/cygx/activity_power_check.go
  52. 1 1
      services/cygx/activity_signup.go
  53. 367 61
      services/cygx/activity_special.go
  54. 46 0
      services/cygx/report_mapping.go
  55. 12 4
      services/cygx/yidong.go
  56. 23 1
      services/data/excel_info.go
  57. 33 0
      services/data/help_doc_classify.go
  58. 10 0
      services/elastic/es_comprehensive.go
  59. 106 0
      services/eta_business/eta_business.go
  60. 15 0
      services/eta_business/eta_business_menu.go
  61. 148 0
      services/eta_trial.go
  62. 22 0
      services/task.go
  63. 73 0
      utils/common.go
  64. 7 1
      utils/constants.go

+ 2 - 2
controllers/business_trip/business_apply.go

@@ -166,7 +166,7 @@ func (this *BusinessTrip) ApplyAdd() {
 		}
 	}
 
-	approveItem, err := system.GetSysUserById(66)
+	approveItem, err := system.GetSysUserById(utils.ApproveUserId)
 	if err != nil {
 		br.Msg = "获取审批人信息失败!"
 		br.ErrMsg = "获取审批人信息失败,Err:" + err.Error()
@@ -508,7 +508,7 @@ func (this *BusinessTrip) ApplyEdit() {
 		}
 	}
 
-	approveItem, err := system.GetSysUserById(66)
+	approveItem, err := system.GetSysUserById(utils.ApproveUserId)
 	if err != nil {
 		br.Msg = "获取审批人信息失败!"
 		br.ErrMsg = "获取审批人信息失败,Err:" + err.Error()

+ 110 - 2
controllers/company.go

@@ -3248,7 +3248,7 @@ func (this *CompanyController) Detail() {
 				return
 			}
 			// cygx8.2专项产业调研展示
-			item.SpecialSurplus, err = cygxService.GetSpecialSurplusByCompany(companyId)
+			item.SpecialSurplus, err = cygxService.GetSpecialSurplusByCompanyNew(companyId)
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取专项调研信息失败,Err:" + err.Error()
@@ -3607,7 +3607,7 @@ func (this *CompanyController) DetailByCreditCode() {
 				//	checkList = append(checkList, n.ChartPermissionId)
 				//}
 			}
-			item.SpecialSurplus, err = cygxService.GetSpecialSurplusByCompany(companyId)
+			item.SpecialSurplus, err = cygxService.GetSpecialSurplusByCompanyNew(companyId)
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取专项调研信息失败,Err:" + err.Error()
@@ -9226,3 +9226,111 @@ func (this *CompanyController) DelRemark() {
 	br.Success = true
 	br.Msg = "操作成功"
 }
+
+// @Title 获取流水信息接口
+// @Description 获取流水信息接口
+// @Param   CompanyId   query   int  true       "客户id"
+// @Success 200 {object} company.CygxActivityPointsBillListResp
+// @router /company/activity/special/points/bill [get]
+func (this *CompanyTodoController) CompanyActivitySpecialPointsBill() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	companyId, _ := this.GetInt("CompanyId")
+	if companyId <= 0 {
+		br.Msg = "请选择客户"
+		return
+	}
+
+	// 获取流水信息
+	var condition string
+	var pars []interface{}
+
+	condition += ` AND company_id = ? `
+	pars = append(pars, companyId)
+
+	//查询当年的数据
+	//condition += ` AND b.create_time >= ?  `
+	//pars = append(pars, time.Now().Format(utils.FormatYearDate)+"-01-01")
+	list, err := cygx.GetCygxActivitySpecialTripBillDetailListAll(condition, pars)
+	if err != nil {
+		br.Msg = "获取任务信息失败"
+		br.ErrMsg = "获取任务信息失败,err:" + err.Error()
+		return
+	}
+
+	//userType, tripRemaining, mapChartName, err := cygxService.GetChartPermissionSpecialSurplusByCompany(companyId)
+	//if err != nil {
+	//	br.Msg = "获取专项调研剩余次数失败"
+	//	br.ErrMsg = "获取专项调研剩余次数失败,err:" + err.Error()
+	//	return
+	//}
+	//chartMap := map[int]string{utils.YI_YAO_ID: utils.YI_YAO_NAME, utils.XIAO_FEI_ID: utils.XIAO_FEI_NAME, utils.KE_JI_ID: utils.KE_JI_NAME, utils.ZHI_ZAO_ID: utils.ZHI_ZAO_NAME}
+	resp := new(cygx.CygxActivitySpecialPointsBillResp)
+	//lastTripRemaining := 0
+	for _, v := range list {
+		item := cygx.CygxActivitySpecialPointsBillRespItem{
+			Id:                  v.Id,
+			CreateTime:          v.CreateTime.Format(utils.FormatDateTime),
+			CompanyId:           v.CompanyId,
+			CompanyName:         v.CompanyName,
+			RealName:            v.RealName,
+			BillDetailed:        v.BillDetailed,
+			ActivityName:        v.ResearchTheme,
+			ChartPermissionId:   v.ChartPermissionId,
+			ChartPermissionName: v.ChartPermissionName,
+			Total:               v.Total,
+		}
+		if v.ActivityId == 0 {
+			item.Content = v.Content
+		} else {
+			if v.DoType == 1 && v.Way != 4 && v.Way != 3 {
+				item.Content = item.ActivityName + "--报名"
+			} else if v.DoType == 2 && v.Way != 4 && v.Way != 3  {
+				item.Content = item.ActivityName + "--取消报名"
+			} else if v.Way == 4 {
+				item.Content = item.ActivityName + "--活动取消"
+			}
+		}
+		//if userType == 2 {
+		//	if i== 0 {
+		//		item.Total += strconv.Itoa(tripRemaining) + "次"
+		//	} else {
+		//		item.Total += strconv.Itoa(tripRemaining-list[i-1].BillDetailed) + "次"
+		//	}
+		//	//if v.BillDetailed < 4 {
+		//	//	item.Total += strconv.Itoa(lastTripRemaining-list[i-1].BillDetailed) + "次"
+		//	//} else {
+		//	//	item.Total += strconv.Itoa(lastTripRemaining) + "次"
+		//	//}
+		//} else {
+		//	for k, num := range mapChartName {
+		//		if i== 0 {
+		//			item.Total += k + strconv.Itoa(num) + "次+"
+		//		} else {
+		//			if list[i-1].ActivityId == 0 {
+		//				item.Total += k + strconv.Itoa(num) + "次+"
+		//			} else {
+		//				item.Total += k + strconv.Itoa(num-list[i-1].BillDetailed) + "次+"
+		//			}
+		//		}
+		//		//if num > 0 {
+		//		//	if i== 0{
+		//		//		item.Total += k + strconv.Itoa(num) + "次+"
+		//		//	} else {
+		//		//		item.Total += k + strconv.Itoa(num-v.BillDetailed) + "次+"
+		//		//	}
+		//		//}
+		//	}
+		//	item.Total = strings.TrimRight(item.Total, "+")
+		//}
+		resp.List = append(resp.List, &item)
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 31 - 12
controllers/company_apply_v2.go

@@ -427,24 +427,42 @@ func (this *CompanyApplyController) ApplyTurnPositive() {
 		// 给升级的产业ID加一个极大值判断处理
 		permissionSlice := strings.Split(req.PermissionIds, ",")
 		mapPermissionId := make(map[int]int)
-		var permissionIdsNew string
+		//var permissionIdsNew string
 		var permissionIdOnly int //处理普通权限与升级权限同时勾选的时候的拦截
 		expId := utils.PERMISSION_ID_YANXUAN_DIFF + utils.CHART_PERMISSION_ID_YANXUAN
+
+		// 获取行业主观对应的客观ID
+		subObjMap, e := services.GetRaiSubObjPermissionIdMap()
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取行业主观对应的客观ID失败, Err: " + e.Error()
+			return
+		}
+
+		strPermissionIdArr := make([]string, 0) // 最终过滤后的权限IDs
 		for _, v := range permissionSlice {
 			permissionId, _ := strconv.Atoi(v)
 
 			// 研选5w的处理
 			if permissionId == expId {
-				permissionIdsNew += strconv.Itoa(utils.CHART_PERMISSION_ID_YANXUAN) + ","
+				//permissionIdsNew += strconv.Itoa(utils.CHART_PERMISSION_ID_YANXUAN) + ","
+				strPermissionIdArr = append(strPermissionIdArr, strconv.Itoa(utils.CHART_PERMISSION_ID_YANXUAN))
 				expensiveYx = 1
 				continue
 			}
 
 			if permissionId > utils.PERMISSION_ID_UPGRADE {
-				permissionIdsNew += strconv.Itoa(permissionId-utils.PERMISSION_ID_UPGRADE) + ","
+				//permissionIdsNew += strconv.Itoa(permissionId-utils.PERMISSION_ID_UPGRADE) + ","
 				permissionIdOnly = permissionId - utils.PERMISSION_ID_UPGRADE
+				// 升级权限, 需要加入客观的权限
+				subId := permissionId - utils.PERMISSION_ID_UPGRADE
+				strPermissionIdArr = append(strPermissionIdArr, strconv.Itoa(subId))
+				if subObjMap[subId] > 0 {
+					strPermissionIdArr = append(strPermissionIdArr, strconv.Itoa(subObjMap[subId]))
+				}
 			} else {
-				permissionIdsNew += strconv.Itoa(permissionId) + ","
+				//permissionIdsNew += strconv.Itoa(permissionId) + ","
+				strPermissionIdArr = append(strPermissionIdArr, v)
 				permissionIdOnly = permissionId
 			}
 			if _, ok := mapPermissionId[permissionIdOnly]; ok {
@@ -454,7 +472,8 @@ func (this *CompanyApplyController) ApplyTurnPositive() {
 			}
 			mapPermissionId[permissionIdOnly] = permissionIdOnly
 		}
-		req.PermissionIds = strings.TrimRight(permissionIdsNew, ",")
+		req.PermissionIds = strings.Join(strPermissionIdArr, ",")
+		//req.PermissionIds = strings.TrimRight(permissionIdsNew, ",")
 
 		// 是否为权益内部人员, 非权益内部人员只能勾选行业不能勾选单独的主客观, 需要通过主观的ID去查客观的ID
 		//isRai, e := services.CheckRaiAdmin(sysUser.AdminId)
@@ -464,13 +483,13 @@ func (this *CompanyApplyController) ApplyTurnPositive() {
 		//	return
 		//}
 		//if !isRai {
-		permissionStr, err := company.GetPermissionIdById(req.PermissionIds)
-		if err != nil {
-			br.Msg = "获取信息失败"
-			br.ErrMsg = "获取主观客观权限信息失败,Err:" + err.Error()
-			return
-		}
-		req.PermissionIds = permissionStr
+		//permissionStr, err := company.GetPermissionIdById(req.PermissionIds)
+		//if err != nil {
+		//	br.Msg = "获取信息失败"
+		//	br.ErrMsg = "获取主观客观权限信息失败,Err:" + err.Error()
+		//	return
+		//}
+		//req.PermissionIds = permissionStr
 		//}
 
 		// 升级map

+ 1 - 1
controllers/company_seller.go

@@ -2424,7 +2424,7 @@ func (this *CompanySellerController) RoadshowFiccList() {
 		utils.ROLE_TYPE_CODE_FICC_ADMIN, utils.ROLE_TYPE_CODE_FICC_DEPARTMENT, utils.ROLE_TYPE_CODE_FICC_GROUP,
 		utils.ROLE_TYPE_CODE_FICC_TEAM, utils.ROLE_TYPE_CODE_FICC_SELLER,
 	}
-	cond := fmt.Sprintf(` AND role_type_code IN (%s)`, utils.GetOrmInReplace(len(roleArr)))
+	cond := fmt.Sprintf(` AND role_type_code IN (%s) AND enabled = 1`, utils.GetOrmInReplace(len(roleArr)))
 	pars := make([]interface{}, 0)
 	pars = append(pars, roleArr)
 	sellers, e := system.GetSysUserItemsOrderByCreated(cond, pars)

+ 54 - 34
controllers/cygx/activity.go

@@ -108,6 +108,11 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 	videoDetail := req.VideoDetail
 	isBClass := req.IsBClass
 	isResearchPoints := req.IsResearchPoints
+	isShowHz := req.IsShowHz
+	isResearch := req.IsResearch //是否是研选类型的活动
+	if isResearch {
+		req.PermissionName = utils.CHART_PERMISSION_NAME_MF_YANXUAN
+	}
 	var items []*cygx.CygxActivity
 	//temporaryLabel := req.TemporaryLabel
 	industrialManagementIdS := req.IndustrialManagementIdS
@@ -276,17 +281,17 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 		}
 	}
 	permissionName := req.PermissionName
-	List := cygxService.GetActChartPermissionList()
-	var haveCheck bool
-	for _, v := range List {
-		if permissionName == v.PermissionName {
-			haveCheck = true
-		}
-	}
-	if !haveCheck {
-		br.Msg = "行业名称:" + permissionName + "不存在"
-		return
-	}
+	//List := cygxService.GetActChartPermissionList()
+	//var haveCheck bool
+	//for _, v := range List {
+	//	if permissionName == v.PermissionName {
+	//		haveCheck = true
+	//	}
+	//}
+	//if !haveCheck {
+	//	br.Msg = "行业名称:" + permissionName + "不存在"
+	//	return
+	//}
 	if strings.Contains(permissionName, utils.CHART_PERMISSION_NAME_YANXUAN) {
 		permissionName = utils.CHART_PERMISSION_NAME_MF_YANXUAN
 	}
@@ -435,6 +440,9 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 			item.Scale = scale
 			item.IsExternalLabel = isExternalLabel
 			item.IsAllCustomerType = req.IsAllCustomerType
+			item.IsShowHz = isShowHz
+			item.ChartPermissionIdDeputy = charInfo.ChartPermissionId
+			item.ChartPermissionNameDeputy = charInfo.PermissionName
 			if len(labelList) == 1 {
 				item.IsCanAppointmentMinutes = labelList[0].IsCanAppointmentMinutes
 			} else {
@@ -674,12 +682,10 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 				//更新活动音频
 				if int(voiceIdNew) > 0 {
 					go cygxService.UpdateResourceData(int(voiceIdNew), "activityvoice", "add", activityInfo.ActivityTime)
-					go elastic.AddComprehensiveActivityVoice(activityId) //更新ES中的活动音频内容
 				}
 				//更新活动视频
 				if int(videoIdNew) > 0 {
 					go cygxService.UpdateResourceData(int(videoIdNew), "activityvideo", "add", activityInfo.ActivityTime)
-					go elastic.AddComprehensiveActivityVideo(activityId) //更新ES中的活动视频内容
 				}
 
 				errAct = err
@@ -708,7 +714,6 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 						go cygxService.DoActivityOnenIdWxTemplateMsg(activityId)
 					}
 				}
-
 				//已结束或者进行中的活动修改时间后,修改活动状态以及重新发送邮件附件
 				if activeState != 0 && activeState != 1 {
 					resultTime := utils.StrTimeToTime(item.ActivityTime) //时间字符串格式转时间格式
@@ -731,10 +736,9 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 				if activityInfo.ActivityName != item.ActivityName || activityInfo.SigninImg == "" {
 					go cygxService.MakeActivitySigninImg(req.ActivityId)
 				}
-
+				//如果活动之前是发布的状态,那么就对公司的扣点进行更新(涉及到新老公司的扣点返点,不放在Redis统一处理了)
 				if activityInfo.PublishStatus == 1 {
-					go cygxService.UpdateYanXuanActivityPointsBillOldComapny(activityInfo, AdminUser.AdminId, itemPointsSet, itemPointsSetOld) //活动发布以及取消发布处理研选扣点,如果活动之前是发布的状态,那么就对公司的扣点进行更新(涉及到新老公司的扣点返点,不放在Redis统一处理了)
-					go elastic.AddComprehensiveActivity(item.ActivityId)                                                                       // Es添加活动
+					go cygxService.UpdateYanXuanActivityPointsBillOldComapny(activityInfo, AdminUser.AdminId, itemPointsSet, itemPointsSetOld) //活动发布以及取消发布处理研选扣点
 				}
 
 				//如果活动之前是未发布的状态,现在又发布了那么就对公司的扣点进行更新
@@ -758,15 +762,18 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 			br.ErrMsg = "发布失败,Err:" + err.Error()
 			return
 		}
-
 		//如果是添加多条活动那么就推送多次
 		for _, v := range activityIdArr {
 			if req.DoType == 1 {
-				go cygxService.DoActivityOnenIdWxTemplateMsg(v)
-				go cygxService.UpdateResourceData(v, "activity", "add", time.Now().Format(utils.FormatDateTime))
-				go cygxService.YiDongSaveRoadshowDetail(v)
-				go cygxService.YanXuanActivityPointsBillActivityPublishAndCancel(v, AdminUser.AdminId, 1) //活动发布以及取消发布处理研选扣点
-				go elastic.AddComprehensiveActivity(v)                                                    // Es添加活动
+				go func() {
+					//同时添加多个活动的时候,避免协程开的过多
+					cygxService.DoActivityOnenIdWxTemplateMsg(v)
+					cygxService.UpdateResourceData(v, "activity", "add", time.Now().Format(utils.FormatDateTime))
+					cygxService.YiDongSaveRoadshowDetail(v)
+					cygxService.YanXuanActivityPointsBillActivityPublishAndCancel(v, AdminUser.AdminId, 1) //活动发布以及取消发布处理研选扣
+					elastic.AddComprehensiveActivity(v)
+				}()
+
 			}
 			go cygxService.MakeActivitySigninImg(v)
 		}
@@ -776,8 +783,11 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 			go cygxService.UpdateResourceData(req.ActivityId, "activity", "add", time.Now().Format(utils.FormatDateTime))
 			go cygxService.YanXuanActivityPointsBillActivityPublishAndCancel(activityId, AdminUser.AdminId, 1) //活动发布以及取消发布处理研选扣点
 		}
+		//如果二次编辑的时候,取消了易董办会选项,那么就对易董发送取消发布到广场的通知
+		if req.IsYidongConduct == 0 {
+			go cygxService.YiDongUpdateActivityStatus(activityId)
+		}
 	}
-
 	// 查研观向7.4-更新产业布局时间
 	if len(industryIds) > 0 {
 		go cygxService.UpdateIndustryLayoutTime(industryIds, false)
@@ -802,6 +812,7 @@ func (this *ActivityCoAntroller) PreserveAndPublish() {
 // @Param   PublishEndDate   query   string  false       "发布结束时间,列如2021-03-06 "
 // @Param   KeyWord   query   string  false       "搜索关键词"
 // @Param   ActiveState   query   string  false       "活动进行状态 未开始:NotStarted、进行中HaveInHand、已结束Complete"
+// @Param   IsResearch   query   bool  true       "是否为研选"
 // @Success 200 {object} cygx.GetCygxActivityListRep
 // @router /activity/list [get]
 func (this *ActivityCoAntroller) ActivityList() {
@@ -828,10 +839,12 @@ func (this *ActivityCoAntroller) ActivityList() {
 	publishEndDate := this.GetString("PublishEndDate")
 	keyWord := this.GetString("KeyWord")
 	activeState := this.GetString("ActiveState")
-	activityLabel := this.GetString("ActivityLabel") // 查研观向7.4-活动标签
+	activityLabel := this.GetString("ActivityLabel")   // 查研观向7.4-活动标签
+	isResearch, _ := this.GetBool("IsResearch", false) // 是否为研选 查研观向11.0 (研选活动独立显示)
 	if activeState != "HaveInHand" && activeState != "Complete" {
 		activeState = "NotStarted"
 	}
+
 	var startSize int
 	if pageSize <= 0 {
 		pageSize = utils.PageSize20
@@ -846,6 +859,11 @@ func (this *ActivityCoAntroller) ActivityList() {
 	if keyWord != "" {
 		condition += ` AND (art.activity_name LIKE '%` + keyWord + `%' )  `
 	}
+	if isResearch {
+		chartPermissionId = utils.CHART_PERMISSION_ID_YANXUAN
+	} else {
+		condition += ` AND art.chart_permission_id  !=  '` + strconv.Itoa(utils.CHART_PERMISSION_ID_YANXUAN) + `'`
+	}
 	//行业名称
 	if chartPermissionId > 0 {
 		condition += ` AND art.chart_permission_id  =  '` + strconv.Itoa(chartPermissionId) + `'`
@@ -886,9 +904,7 @@ func (this *ActivityCoAntroller) ActivityList() {
 	}
 	// 活动标签
 	if activityLabel != "" {
-		keywords := "%" + activityLabel + "%"
-		condition += ` AND art.label LIKE ?`
-		pars = append(pars, keywords)
+		condition += ` AND (art.label LIKE '%` + activityLabel + `%' )  `
 	}
 
 	//C类电话会,仅本组销售、部门管理员、admin、权益研究员账号能看到。
@@ -997,13 +1013,16 @@ func (this *ActivityCoAntroller) ActivityList() {
 		}
 		if v.YidongActivityId != "" {
 			list[k].ActivityTypeName += utils.YI_DONG_NAME
+			if v.ChartPermissionNameDeputy != "" && v.ChartPermissionNameDeputy != v.ChartPermissionName {
+				v.ChartPermissionName = v.ChartPermissionNameDeputy // 易董同步过来的活动展示副权限  v11.0
+			}
 		}
 		if v.IsYidongConduct == 1 {
 			list[k].ActivityTypeName += utils.YI_DONG_NAME_TWO
 		}
 		list[k].IsUpload = mapUpload[v.ActivityId]
 		//是否展示签到码
-		if (v.ActivityTypeId == 5 || v.ActivityTypeId == 6) && v.SigninImg != "" && v.ActiveState == 1 && v.PublishStatus == 1 {
+		if (v.ActivityTypeId == 5 || v.ActivityTypeId == 6 || v.ActivityTypeId == 8) && v.SigninImg != "" && v.ActiveState == 1 && v.PublishStatus == 1 {
 			list[k].IsShowSigninButton = true
 		}
 	}
@@ -1190,10 +1209,10 @@ func (this *ActivityCoAntroller) PublishAndCancel() {
 		br.Msg = popupMsg
 		return
 	}
-	if activityInfo.ActiveState != 1 {
-		br.Msg = "活动已经开始,无法修改"
-		return
-	}
+	//if activityInfo.ActiveState != 1 {
+	//	br.Msg = "活动已经开始,无法修改"
+	//	return
+	//}
 	if activityInfo.PublishStatus == 0 {
 		item.PublishStatus = 1
 		item.IsCancel = 0
@@ -1234,7 +1253,7 @@ func (this *ActivityCoAntroller) PublishAndCancel() {
 	}
 	go cygxService.YanXuanActivityPointsBillActivityPublishAndCancel(activityId, AdminUser.AdminId, item.PublishStatus) //活动发布以及取消发布处理研选扣点
 
-	go elastic.AddComprehensiveActivity(activityId) // Es添加活动
+	go elastic.AddComprehensiveActivity(activityId) // 同步Es添加活动
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"
@@ -1316,6 +1335,7 @@ func (this *ActivityCoAntroller) Delete() {
 
 // @Title 获取活动行业分类
 // @Description 获取活动行业分类接口
+// @Param   IsHideResearch  query  bool  false  "是否隐藏买方研选(默认不隐藏)"
 // @Success 200 {object} cygx.ChartPermissionRepMoreList
 // @router /activity/chartPermission/list [get]
 func (this *ActivityCoAntroller) ChartPermissionListAct() {

+ 24 - 15
controllers/cygx/activity_meet.go

@@ -35,6 +35,7 @@ type ActivityMeetCoAntroller struct {
 // @Param   EndDate   query   string  false       "结束时间,列如2021-03-06 "
 // @Param   KeyWord   query   string  false       "搜索关键词"
 // @Param   MeetType   query   int  true       "会议类型 1线上、2线下"
+// @Param   IsResearch   query   bool  true       "是否为研选"
 // @Success 200 {object} cygx.GetCygxMeetListRep
 // @router /activityMeet/list [get]
 func (this *ActivityMeetCoAntroller) MeetList() {
@@ -58,7 +59,7 @@ func (this *ActivityMeetCoAntroller) MeetList() {
 	endDate := this.GetString("EndDate")
 	keyWord := this.GetString("KeyWord")
 	meetType, _ := this.GetInt("MeetType")
-
+	isResearch, _ := this.GetBool("IsResearch", false) // 是否为研选 查研观向11.0 (研选活动独立显示)
 	var startSize int
 	if pageSize <= 0 {
 		pageSize = utils.PageSize20
@@ -78,11 +79,16 @@ func (this *ActivityMeetCoAntroller) MeetList() {
 	if meetType == 1 {
 		condition += ` AND a.activity_type_id  IN (1,2,3,7)  `
 	} else {
-		condition += ` AND a.activity_type_id  IN (4,5,6) ` //默认
+		condition += ` AND a.activity_type_id  IN (4,5,6,8) ` //默认
 	}
 	if ActivityTypeId != "" {
 		condition += ` AND a.activity_type_id IN (` + ActivityTypeId + `) `
 	}
+	if isResearch {
+		chartPermissionId = utils.CHART_PERMISSION_ID_YANXUAN
+	} else {
+		condition += ` AND a.chart_permission_id  !=  '` + strconv.Itoa(utils.CHART_PERMISSION_ID_YANXUAN) + `'`
+	}
 	//行业名称
 	if chartPermissionId > 0 {
 		condition += ` AND a.chart_permission_id  =  '` + strconv.Itoa(chartPermissionId) + `'`
@@ -173,6 +179,10 @@ func (this *ActivityMeetCoAntroller) MeetList() {
 			if v.IsSubmitMeeting == 1 {
 				list[k].IsShowAttendanceDetails = true
 			}
+
+			if v.ChartPermissionNameDeputy != "" && v.ChartPermissionNameDeputy != v.ChartPermissionName {
+				v.ChartPermissionName = v.ChartPermissionNameDeputy // 易董同步过来的活动展示副权限  v11.0
+			}
 		}
 
 		//判断是否是易董在易董举办的会议
@@ -182,7 +192,7 @@ func (this *ActivityMeetCoAntroller) MeetList() {
 			list[k].IsShowUpdateMeeting = false
 		}
 		//是否展示签到码
-		if (v.ActivityTypeId == 5 || v.ActivityTypeId == 6) && v.SigninImg != "" {
+		if (v.ActivityTypeId == 5 || v.ActivityTypeId == 6 || v.ActivityTypeId == 8) && v.SigninImg != "" {
 			list[k].IsShowSigninButton = true
 		}
 		list[k].MeetPeopleNum += v.PotentialPeopleNum //加上潜在客户人数
@@ -341,18 +351,17 @@ func (this *ActivityMeetCoAntroller) MeetingDo() {
 		br.ErrMsg = "操作失败,Err:" + errInfo.Error()
 		return
 	}
-	//校验活动后台管理员、销售是否有修改权限 校验需求取消 2023-7-10
-	//havePower, popupMsg, err := cygxService.CheckActivityUpdatePower(AdminUser.AdminId, activityInfo)
-	//if err != nil {
-	//	br.Msg = "获取管理员身份信息失败"
-	//	br.ErrMsg = "获取管理员身份信息失败,Err:" + err.Error()
-	//	return
-	//}
-	//if !havePower {
-	//	br.Msg = popupMsg
-	//	return
-	//}
-
+	//校验活动后台管理员、销售是否有修改权限
+	havePower, popupMsg, err := cygxService.CheckActivityUpdatePower(AdminUser.AdminId, activityInfo)
+	if err != nil {
+		br.Msg = "获取管理员身份信息失败"
+		br.ErrMsg = "获取管理员身份信息失败,Err:" + err.Error()
+		return
+	}
+	if !havePower {
+		br.Msg = popupMsg
+		return
+	}
 	noMeetingUids, err := cygx.GetSignupUserIds(activityId, meetingUids) //未到会的用户ID
 	if err != nil {
 		br.Msg = "获取信息失败"

+ 15 - 4
controllers/cygx/activity_signup.go

@@ -34,9 +34,10 @@ type ActivitySignupCoAntroller struct {
 // @Param   StartDate   query   string  false       "开始时间 ,列如2021-03-06 "
 // @Param   EndDate   query   string  false       "结束时间,列如2021-03-06 "
 // @Param   KeyWord   query   string  false       "搜索关键词"
-// @Param   SearchType   query   int  true       "筛选类型 1专家/分析师电话会、2专家/分析师线下沙龙 、3公司调研/、4C类电话会"
+// @Param   SearchType   query   int  true       "筛选类型 1专家/分析师电话会、2专家/分析师线下沙龙 、3公司调研/、4C类电话会、5买方线下交流"
 // @Param   ActiveState   query   int  false       "发布状态 ,1未开始、2进行中、3已结束 ,默认1未开始"
 // @Param   PublishStatus   query   int  false       "发布状态 ,0未发布,1已发布,3已取消,传2查询所有"
+// @Param   IsResearch   query   bool  true       "是否为研选"
 // @Success 200 {object} cygx.GetCygxSignupListRep
 // @router /activitySignup/list [get]
 func (this *ActivitySignupCoAntroller) SignupList() {
@@ -62,6 +63,7 @@ func (this *ActivitySignupCoAntroller) SignupList() {
 	activeState, _ := this.GetInt("ActiveState")
 	searchType, _ := this.GetInt("SearchType")
 	publishStatus, _ := this.GetInt("PublishStatus")
+	isResearch, _ := this.GetBool("IsResearch", false) // 是否为研选 查研观向11.0 (研选活动独立显示)
 	if activeState == 0 {
 		activeState = 1
 	}
@@ -78,7 +80,6 @@ func (this *ActivitySignupCoAntroller) SignupList() {
 	var pars []interface{}
 	if keyWord != "" {
 		template.HTMLEscapeString(keyWord)
-		fmt.Println("keyWord", keyWord)
 		keyWord = "%" + keyWord + "%"
 		condition += ` AND (art.activity_name LIKE  ? )  `
 		pars = append(pars, keyWord)
@@ -86,7 +87,9 @@ func (this *ActivitySignupCoAntroller) SignupList() {
 	condition += ` 	 AND art.active_state =  ?  `
 	pars = append(pars, activeState)
 	if ActivityTypeId == "" {
-		if searchType == 4 {
+		if searchType == 5 {
+			condition += ` AND art.activity_type_id  IN (8) `
+		} else if searchType == 4 {
 			condition += ` AND art.activity_type_id  IN (7) `
 		} else if searchType == 3 {
 			condition += ` AND art.activity_type_id  IN (3,4) `
@@ -99,6 +102,11 @@ func (this *ActivitySignupCoAntroller) SignupList() {
 	if ActivityTypeId != "" {
 		condition += ` AND art.activity_type_id IN (` + ActivityTypeId + `) `
 	}
+	if isResearch {
+		chartPermissionId = utils.CHART_PERMISSION_ID_YANXUAN
+	} else {
+		condition += ` AND art.chart_permission_id  !=  '` + strconv.Itoa(utils.CHART_PERMISSION_ID_YANXUAN) + `'`
+	}
 	//行业名称
 	if chartPermissionId > 0 {
 		condition += ` AND art.chart_permission_id  =  '` + strconv.Itoa(chartPermissionId) + `'`
@@ -157,6 +165,10 @@ func (this *ActivitySignupCoAntroller) SignupList() {
 		//	list[k].IsShowAppointment = cygxService.IsShowAppointmentByadminSet(v.IsCanAppointmentMinutes)
 		//}
 		activityIds += strconv.Itoa(v.ActivityId) + ","
+
+		if v.ChartPermissionNameDeputy != "" && v.ChartPermissionNameDeputy != v.ChartPermissionName && v.YidongActivityId != "" {
+			v.ChartPermissionName = v.ChartPermissionNameDeputy // 易董同步过来的活动展示副权限  v11.0
+		}
 	}
 	activityIds = strings.TrimRight(activityIds, ",")
 	mapIndustrial := make(map[int]string)
@@ -1726,7 +1738,6 @@ func (this *ActivitySignupCoAntroller) AddSignuUser() {
 					br.ErrMsg = "活动ID:" + strconv.Itoa(activityId) + "活动名称:" + activityInfo.ActivityName + "用户ID:" + strconv.Itoa(int(wxUser.UserId))
 					return
 				}
-
 				popupMsg, err := cygxService.CheckActivityUserAll(activityInfo, wxUser)
 				if err != nil {
 					br.Msg = "报名失败!"

+ 2 - 0
controllers/cygx/activity_special.go

@@ -521,6 +521,8 @@ func (this *ActivitySpecialCoAntroller) PublishAndCancel() {
 		updateParams["PublishDate"] = time.Now()
 	} else {
 		item.PublishStatus = 0
+		// 取消专项调研返点
+		go cygxService.ActivitySpecialPublishAndCancel(activityInfo)
 	}
 	updateParams["PublishStatus"] = item.PublishStatus
 	item.ActivityId = req.ActivityId

+ 118 - 26
controllers/cygx/activity_special_trip.go

@@ -63,7 +63,7 @@ func (this *ActivitySpecialTripCoAntroller) AddUser() {
 		uids += strconv.Itoa(v.UserId) + ","
 	}
 	uids = strings.TrimRight(uids, ",")
-	for _, v := range uidList {
+	for i, v := range uidList {
 		uid := v.UserId
 		wxUser, userErr := models.GetWxUserByUserId(uid)
 		if userErr != nil {
@@ -128,6 +128,12 @@ func (this *ActivitySpecialTripCoAntroller) AddUser() {
 				return
 			}
 			if total == 0 {
+				totalAll, err := cygx.GetUserActivitySpecialTripCount(uid, activityId)
+				if err != nil {
+					br.Msg = "获取信息失败"
+					br.ErrMsg = "获取日程数量信息失败,Err:" + err.Error()
+					return
+				}
 				//流水记录表
 				itemBill := new(cygx.CygxActivitySpecialTripBill)
 				itemBill.UserId = infoUser.UserId
@@ -145,36 +151,68 @@ func (this *ActivitySpecialTripCoAntroller) AddUser() {
 				itemBill.ChartPermissionId = activityInfo.ChartPermissionId
 				itemBill.AdminId = AdminUser.AdminId
 
-				item := new(cygx.CygxActivitySpecialTrip)
-				item.UserId = infoUser.UserId
-				item.RealName = infoUser.RealName
-				item.SellerName = infoUser.SellerName
-				item.ActivityId = activityId
-				item.CreateTime = time.Now()
-				item.Mobile = infoUser.Mobile
-				item.Email = infoUser.Email
-				item.Email = infoUser.Email
-				item.CompanyId = infoUser.CompanyId
-				item.CompanyName = infoUser.CompanyName
-				item.AdminId = AdminUser.AdminId
-				item.Source = 2
-				//优先绑定用户修改过的外呼手机号
-				if infoUser.OutboundMobile != "" {
-					item.OutboundMobile = infoUser.OutboundMobile
-					if infoUser.OutboundCountryCode == "" {
-						item.CountryCode = "86"
+				if totalAll == 0 {
+					item := new(cygx.CygxActivitySpecialTrip)
+					item.UserId = infoUser.UserId
+					item.RealName = infoUser.RealName
+					item.SellerName = infoUser.SellerName
+					item.ActivityId = activityId
+					item.CreateTime = time.Now()
+					item.Mobile = infoUser.Mobile
+					item.Email = infoUser.Email
+					item.Email = infoUser.Email
+					item.CompanyId = infoUser.CompanyId
+					item.CompanyName = infoUser.CompanyName
+					item.AdminId = AdminUser.AdminId
+					item.Source = 2
+					//优先绑定用户修改过的外呼手机号
+					if infoUser.OutboundMobile != "" {
+						item.OutboundMobile = infoUser.OutboundMobile
+						if infoUser.OutboundCountryCode == "" {
+							item.CountryCode = "86"
+						} else {
+							item.CountryCode = infoUser.OutboundCountryCode
+						}
 					} else {
-						item.CountryCode = infoUser.OutboundCountryCode
+						item.OutboundMobile = infoUser.Mobile
+						if infoUser.CountryCode == "" {
+							item.CountryCode = "86"
+						} else {
+							item.CountryCode = infoUser.CountryCode
+						}
 					}
+					items = append(items, item)
 				} else {
-					item.OutboundMobile = infoUser.Mobile
-					if infoUser.CountryCode == "" {
-						item.CountryCode = "86"
-					} else {
-						item.CountryCode = infoUser.CountryCode
+					err = cygx.UpdateSpecialTrip(1,0,uid, activityId)
+					if err != nil {
+						br.Msg = "报名失败,"
+						br.ErrMsg = "二次报名,更改报名是否有效状态失败,Err:" + err.Error()
+						return
+					}
+					resultTime := utils.StrTimeToTime(activityInfo.ActivityTime)
+					//48小时之内的取消也扣除一次参会记录
+					if time.Now().Add(+time.Hour * 48).After(resultTime) {
+						itemBill.BillDetailed = 0 //48小时之内,取消报名之后二次报名,不扣除流水记录
 					}
 				}
-				items = append(items, item)
+				userType, tripRemaining, mapChartName, err := cygxService.GetChartPermissionSpecialSurplusByCompany(infoUser.CompanyId)
+				if err != nil {
+					br.Msg = "获取专项调研剩余次数失败"
+					br.ErrMsg = "获取专项调研剩余次数失败,err:" + err.Error()
+					return
+				}
+				if userType == 2 {
+					tripRemaining = tripRemaining + itemBill.BillDetailed-i
+					itemBill.Total = strconv.Itoa(tripRemaining) + "次"
+				} else {
+					for k, num := range mapChartName {
+						if activityInfo.ChartPermissionName == k {
+							num = num + itemBill.BillDetailed - i
+						}
+						itemBill.Total += k + strconv.Itoa(num) + "次+"
+					}
+					itemBill.Total = strings.TrimRight(itemBill.Total, "+")
+				}
 				itemsBill = append(itemsBill, itemBill)
 			}
 
@@ -508,6 +546,24 @@ func (this *ActivitySpecialTripCoAntroller) TripCancel() {
 		br.ErrMsg = "修改失败 Err:" + err.Error()
 		return
 	}
+	userType, tripRemaining, mapChartName, err := cygxService.GetChartPermissionSpecialSurplusByCompany(infoUser.CompanyId)
+	if err != nil {
+		br.Msg = "获取专项调研剩余次数失败"
+		br.ErrMsg = "获取专项调研剩余次数失败,err:" + err.Error()
+		return
+	}
+	if userType == 2 {
+		tripRemaining += itemBill.BillDetailed
+		itemBill.Total = strconv.Itoa(tripRemaining) + "次"
+	} else {
+		for k, num := range mapChartName {
+			if activityInfo.ChartPermissionName == k {
+				num += itemBill.BillDetailed
+			}
+			itemBill.Total += k + strconv.Itoa(num) + "次+"
+		}
+		itemBill.Total = strings.TrimRight(itemBill.Total, "+")
+	}
 	err = cygx.AddCygxActivitySpecialTripBill(itemBill)
 	if err != nil {
 		br.Msg = "修改失败"
@@ -736,6 +792,24 @@ func (this *ActivitySpecialTripCoAntroller) MeetingDo() {
 				itemBill.ChartPermissionId = activityInfo.ChartPermissionId
 				itemBill.AdminId = AdminUser.AdminId
 				itemBill.Way = 2
+				userType, tripRemaining, mapChartName, err := cygxService.GetChartPermissionSpecialSurplusByCompany(v.CompanyId)
+				if err != nil {
+					br.Msg = "获取专项调研剩余次数失败"
+					br.ErrMsg = "获取专项调研剩余次数失败,err:" + err.Error()
+					return
+				}
+				if userType == 2 {
+					tripRemaining += itemBill.BillDetailed
+					itemBill.Total = strconv.Itoa(tripRemaining) + "次"
+				} else {
+					for k, num := range mapChartName {
+						if activityInfo.ChartPermissionName == k {
+							num += itemBill.BillDetailed
+						}
+						itemBill.Total += k + strconv.Itoa(num) + "次+"
+					}
+					itemBill.Total = strings.TrimRight(itemBill.Total, "+")
+				}
 				itemsBill = append(itemsBill, itemBill)
 			}
 		}
@@ -775,6 +849,24 @@ func (this *ActivitySpecialTripCoAntroller) MeetingDo() {
 			itemBill.ChartPermissionId = activityInfo.ChartPermissionId
 			itemBill.AdminId = AdminUser.AdminId
 			itemBill.Way = 2
+			userType, tripRemaining, mapChartName, err := cygxService.GetChartPermissionSpecialSurplusByCompany(v.CompanyId)
+			if err != nil {
+				br.Msg = "获取专项调研剩余次数失败"
+				br.ErrMsg = "获取专项调研剩余次数失败,err:" + err.Error()
+				return
+			}
+			if userType == 2 {
+				tripRemaining -= 1
+				itemBill.Total = strconv.Itoa(tripRemaining) + "次"
+			} else {
+				for k, num := range mapChartName {
+					if activityInfo.ChartPermissionName == k {
+						num -= 1
+					}
+					itemBill.Total += k + strconv.Itoa(num) + "次+"
+				}
+				itemBill.Total = strings.TrimRight(itemBill.Total, "+")
+			}
 			itemsBill = append(itemsBill, itemBill)
 		}
 		items = append(items, item)

+ 17 - 2
controllers/cygx/cygx_activity_type.go

@@ -15,6 +15,7 @@ type ActivityTypeCoAntroller struct {
 
 // @Title 活动类型列表
 // @Description活动类型列表接口
+// @Param   IsResearch   query   bool  true       "是否为研选"
 // @Success 200 {object} cygx.ActivityTypeListResp
 // @router /activityType/list [get]
 func (this *ActivityTypeCoAntroller) List() {
@@ -30,8 +31,15 @@ func (this *ActivityTypeCoAntroller) List() {
 		br.Ret = 408
 		return
 	}
+	isResearch, _ := this.GetBool("IsResearch", false)
+	var condition string
 	resp := new(cygx.ActivityTypeListResp)
-	list, err := cygx.GetActivityTypeList()
+	if isResearch {
+		condition = " source_type IN (0,2) "
+	} else {
+		condition = " source_type IN (0,1) "
+	}
+	list, err := cygx.GetActivityTypeSearchList(condition)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取数据失败,Err:" + err.Error()
@@ -94,7 +102,7 @@ func (this *ActivityTypeCoAntroller) Detail() {
 
 // @Title 活动类型列表小分类筛选
 // @Description 获取活动类型列表小分类筛选接口
-// @Param   SearchType   query   int  true       "筛选类型 1专家/分析师话会、2专家/分析师线下沙龙 、3公司调研/ 4、C类电话会"
+// @Param   SearchType   query   int  true       "筛选类型 1专家/分析师话会、2专家/分析师线下沙龙 、3公司调研/ 4、C类电话会"
 // @Success 200 {object} cygx.ActivityTypeListResp
 // @router /activityType/listSearch [get]
 func (this *ActivityTypeCoAntroller) ListSearch() {
@@ -138,6 +146,7 @@ func (this *ActivityTypeCoAntroller) ListSearch() {
 // @Title 线上、线下会议类型
 // @Description 线上、线下会议类型
 // @Param   MeetType   query   int  true       "会议类型 1线上、2线下"
+// @Param   IsResearch   query   bool  true       "是否为研选"
 // @Success 200 {object} cygx.ActivityTypeListResp
 // @router /activityType/meetType [get]
 func (this *ActivityTypeCoAntroller) MeetType() {
@@ -154,6 +163,7 @@ func (this *ActivityTypeCoAntroller) MeetType() {
 		return
 	}
 	meetType, _ := this.GetInt("MeetType")
+	isResearch, _ := this.GetBool("IsResearch", false) // 是否为研选 查研观向11.0 (研选活动独立显示)
 	resp := new(cygx.ActivityTypeListResp)
 	var condition string
 	if meetType == 1 {
@@ -161,6 +171,11 @@ func (this *ActivityTypeCoAntroller) MeetType() {
 	} else {
 		condition += ` activity_type  = 0 `
 	}
+	if isResearch {
+		condition += " AND  source_type IN (0,2) "
+	} else {
+		condition += " AND source_type IN (0,1) "
+	}
 	list, err := cygx.GetActivityTypeSearchList(condition)
 	if err != nil {
 		br.Msg = "获取失败"

+ 9 - 2
controllers/cygx/industrial_management.go

@@ -30,6 +30,7 @@ type IndustrialManagementController struct {
 // @Title 获取一级分类
 // @Description 获取一级分类接口
 // @Param   HideMacro  query  bool  false  "是否隐藏宏观(默认不隐藏)"
+// @Param   IsHideResearch  query  bool  false  "是否隐藏买方研选(默认不隐藏)"
 // @Param   IsCeLueReport  query  bool  false  "是否是策略平台的报告类型"
 // @Success 200 {object} cygx.ChartPermissionResp
 // @router /chartPermission/first [get]
@@ -41,6 +42,7 @@ func (this *IndustrialManagementController) ChartPermissionList() {
 	}()
 	// 是否隐藏宏观
 	hideMacro, _ := this.GetBool("HideMacro")
+	isHideResearch, _ := this.GetBool("IsHideResearch")
 	isCeLueReport, _ := this.GetBool("IsCeLueReport")
 	resp := new(cygx.ChartPermissionResp)
 	list, err := cygx.GetChartPermissionAll()
@@ -61,15 +63,20 @@ func (this *IndustrialManagementController) ChartPermissionList() {
 		item.ChartPermissionId = utils.GU_SHOU_ID
 		resp.List = append(resp.List, item)
 	} else {
+		for _, v := range list {
+			if v.PermissionName == utils.CHART_PERMISSION_NAME_MF_YANXUAN && isHideResearch {
+				continue
+			}
+			resp.List = append(resp.List, v)
+		}
 		// 查研观向7.4-新增一个宏观
 		if !hideMacro {
 			macro := &cygx.ChartPermission{
 				ChartPermissionId: 1,
 				PermissionName:    "宏观",
 			}
-			list = append(list, macro)
+			resp.List = append(resp.List, macro)
 		}
-		resp.List = list
 	}
 
 	br.Ret = 200

+ 43 - 8
controllers/cygx/user.go

@@ -622,7 +622,7 @@ func (this *UserController) TableList() {
 		{PermissionName: "音视频播放", Source: 9, TotalNum: countDetail.RoadshowVideoNum + countDetail.ActivityVideoNum + countDetail.ActivityVoiceNum},
 		{PermissionName: "首页标签点击", Source: 10, TotalNum: countDetail.TagNum}}
 
-resp := new(cygx.CygxUserTableListRep)
+	resp := new(cygx.CygxUserTableListRep)
 	resp.List = List
 	resp.UserName = wxUser.RealName
 	resp.Mobile = wxUser.Mobile
@@ -730,31 +730,67 @@ func (this *UserController) TableDetail() {
 			endDate += " 23:59:59"
 			condition += ` AND r.create_time <= '` + endDate + `' `
 		}
+		if wxUser.Mobile == "" {
+			wxUser.Mobile = wxUser.Email
+		}
 		total, err = cygx.GetCygxArticleHistoryCount(wxUser.Mobile, wxUser.Email, condition)
 		if err != nil {
 			br.Msg = "获取信息失败"
 			br.ErrMsg = "获取用户阅读记录总数失败,Err:" + err.Error()
 			return
 		}
-		list, err = cygx.GetCygxArticleHistoryRecordByUser(wxUser.Mobile, wxUser.Email, condition, startSize, pageSize)
+		list, err = cygx.GetCygxArticleHistoryRecordByUserNew(wxUser.Mobile, wxUser.Email, condition, startSize, pageSize)
 		if err != nil && err.Error() != utils.ErrNoRow() {
 			br.Msg = "获取信息失败"
 			br.ErrMsg = "获取用户阅读记录,Err:" + err.Error()
 			return
 		}
+		var articleIds string
+		var articleIdArr []int
 		if len(list) > 0 {
+			articleIds = ""
+			mapAricleId := make(map[int]int)
+			mapAricleIndustrialSubjectName := make(map[int]*cygx.ArticleIndustrialSubjectNameResp)
 			for k, v := range list {
-				list[k].RegisterPlatform = cygxService.GetArticleSourcePlatform(v.SourcePlatform)
 				if v.ArticleId >= utils.SummaryArticleId {
 					list[k].ArticleType = 1
 				} else {
 					list[k].ArticleType = 2
 				}
-				if list[k].PermissionName == "" {
-					list[k].PermissionName = v.CategoryName
+				if mapAricleId[v.ArticleId] == 0 {
+					articleIds += strconv.Itoa(v.ArticleId) + ","
+					mapAricleId[v.ArticleId] = v.ArticleId
 				}
+				list[k].RegisterPlatform = cygxService.GetArticleSourcePlatform(v.SourcePlatform)
+				articleIdArr = append(articleIdArr, v.ArticleId)
+			}
+			articleIds = strings.TrimRight(articleIds, ",")
+
+			listArticleIndustrialSubjectList, err := cygx.GetCygxArticleIndustrialSubjectName(articleIds)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取信息失败"
+				br.ErrMsg = "获取用户阅读记录,Err:" + err.Error()
+				return
+			}
+			if len(listArticleIndustrialSubjectList) > 0 {
+				for _, v := range listArticleIndustrialSubjectList {
+					mapAricleIndustrialSubjectName[v.ArticleId] = v
+				}
+				for k, v := range list {
+					if mapAricleIndustrialSubjectName[v.ArticleId] != nil {
+						list[k].IndustryName = mapAricleIndustrialSubjectName[v.ArticleId].IndustryName     // 产业
+						list[k].SubjectNameStr = mapAricleIndustrialSubjectName[v.ArticleId].SubjectNameStr // 标的
+					}
+				}
+			}
+
+			//行业
+			mapPerssionName := cygxService.GetCygxArticlePerssionNameListMap(articleIdArr)
+			for k, v := range list {
+				list[k].PermissionName = mapPerssionName[v.ArticleId]
 			}
 		}
+
 	} else if source == 2 {
 		if mobile != "" {
 			condition = ` AND s.mobile = '` + mobile + `' `
@@ -1919,7 +1955,7 @@ func (this *UserController) CompanyTableList() {
 		br.ErrMsg = "获取搜索记录失败,Err:" + err.Error()
 		return
 	}
-	tagNum, err := cygx.GetCygxTagHistoryCountByCompanyId(companyId,"")
+	tagNum, err := cygx.GetCygxTagHistoryCountByCompanyId(companyId, "")
 	if err != nil {
 		br.ErrMsg = "获取信息失败,Err:" + err.Error()
 		br.Msg = "获取搜索记录失败"
@@ -4163,7 +4199,7 @@ func (this *UserController) TableCompanyList() {
 		br.ErrMsg = "获取搜索记录失败,Err:" + err.Error()
 		return
 	}
-	tagNum, err := cygx.GetCygxTagHistoryCountByCompanyIds(companyCondition,"")
+	tagNum, err := cygx.GetCygxTagHistoryCountByCompanyIds(companyCondition, "")
 	if err != nil {
 		br.ErrMsg = "获取信息失败,Err:" + err.Error()
 		br.Msg = "获取搜索记录失败"
@@ -4319,4 +4355,3 @@ func (this *UserController) UserRemind() {
 	br.Success = true
 	br.Data = resp
 }
-

+ 12 - 3
controllers/data_manage/excel_info.go

@@ -1242,12 +1242,21 @@ func (this *ExcelInfoController) Calculate() {
 		br.ErrMsg = "计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr
 		return
 	}
-	calVal := calResult.String()
-	if err != nil {
+	// 计算结果格式化
+	calFloat, e := calResult.Float64()
+	if e != nil {
 		br.Msg = "计算失败"
-		br.ErrMsg = "计算失败,结果转 string 失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr
+		br.ErrMsg = "计算失败, Err: " + e.Error()
 		return
 	}
+	calVal := utils.FormatTableDataShowValue(calFloat)
+
+	//calVal := calResult.String()
+	//if err != nil {
+	//	br.Msg = "计算失败"
+	//	br.ErrMsg = "计算失败,结果转 string 失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr
+	//	return
+	//}
 
 	br.Ret = 200
 	br.Success = true

+ 1197 - 0
controllers/eta_business/eta_business.go

@@ -0,0 +1,1197 @@
+package eta_business
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hz_crm_api/controllers"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/eta_business"
+	etaBusinessService "hongze/hz_crm_api/services/eta_business"
+	"hongze/hz_crm_api/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// EtaBusinessController ETA商家
+type EtaBusinessController struct {
+	controllers.BaseAuthController
+}
+
+// PageList
+// @Title 商家列表-分页
+// @Description 商家列表-分页
+// @Param   Keyword			query	string	false	"关键词: 商家名称/社会信用码/商家编码"
+// @Param   SellerIds		query	string	false	"销售IDs"
+// @Param   SigningStatus	query	string	false	"签约状态: 1-首次签约; 2-续约中; 3-已终止"
+// @Param   Province		query	string	false	"省份筛选"
+// @Param   City			query	string	false	"城市筛选"
+// @Param   IndustryId		query	int	false	"行业ID"
+// @Param   SortParam		query	int	false	"排序字段: 1-签约时间; 2-到期时间; 3-创建时间; 4-用户上限"
+// @Param   SortType		query	int	false	"排序类型: 1-正序; 2-倒序"
+// @Success 200 Ret=200 获取成功
+// @router /page_list [get]
+func (this *EtaBusinessController) PageList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 分页
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	// 权限校验
+	resp := new(eta_business.EtaBusinessListResp)
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		resp.Paging = paging.GetPaging(currentIndex, pageSize, 0)
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	cond := ``
+	pars := make([]interface{}, 0)
+	// 筛选项
+	{
+		// 关键词
+		keyword := this.GetString("Keyword", "")
+		keyword = strings.TrimSpace(keyword)
+		if keyword != "" {
+			kw := fmt.Sprint("%", keyword, "%")
+			cond += fmt.Sprintf(` AND (%s LIKE ? OR %s LIKE ? OR %s LIKE ?)`, eta_business.EtaBusinessColumns.BusinessName, eta_business.EtaBusinessColumns.BusinessCode, eta_business.EtaBusinessColumns.CreditCode)
+			pars = append(pars, kw, kw, kw)
+		}
+
+		// 销售
+		sellerIds := this.GetString("SellerIds", "")
+		if sellerIds != "" {
+			arr := strings.Split(sellerIds, ",")
+			ids := make([]int, 0)
+			for _, s := range arr {
+				v, e := strconv.Atoi(s)
+				if e != nil {
+					br.Msg = "销售ID有误"
+					return
+				}
+				ids = append(ids, v)
+			}
+			if len(ids) == 0 {
+				resp.Paging = paging.GetPaging(currentIndex, pageSize, 0)
+				br.Data = resp
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
+			}
+			cond += fmt.Sprintf(` AND %s IN (%s)`, eta_business.EtaBusinessColumns.SellerId, utils.GetOrmInReplace(len(ids)))
+			pars = append(pars, ids)
+		}
+
+		// 签约状态
+		signingStatus, _ := this.GetInt("SigningStatus", 0)
+		if signingStatus > 0 {
+			cond += fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessColumns.SigningStatus)
+			pars = append(pars, signingStatus)
+		}
+
+		// 商家地址
+		province := this.GetString("Province", "")
+		province = strings.TrimSpace(province)
+		if province != "" {
+			provinceArr := strings.Split(province, ",")
+			if len(provinceArr) == 0 {
+				resp.Paging = paging.GetPaging(currentIndex, pageSize, 0)
+				br.Data = resp
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
+			}
+			cond += fmt.Sprintf(` AND %s IN (%s)`, eta_business.EtaBusinessColumns.Province, utils.GetOrmInReplace(len(provinceArr)))
+			pars = append(pars, provinceArr)
+		}
+		city := this.GetString("City", "")
+		city = strings.TrimSpace(city)
+		if city != "" {
+			cityArr := strings.Split(city, ",")
+			if len(cityArr) == 0 {
+				resp.Paging = paging.GetPaging(currentIndex, pageSize, 0)
+				br.Data = resp
+				br.Ret = 200
+				br.Success = true
+				br.Msg = "获取成功"
+				return
+			}
+			cond += fmt.Sprintf(` AND %s IN (%s)`, eta_business.EtaBusinessColumns.City, utils.GetOrmInReplace(len(cityArr)))
+			pars = append(pars, cityArr)
+		}
+
+		// 行业
+		industryId, _ := this.GetInt("IndustryId", 0)
+		if industryId > 0 {
+			cond += fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessColumns.IndustryId)
+			pars = append(pars, industryId)
+		}
+	}
+
+	order := ``
+	// 排序
+	{
+		fieldArr := []int{1, 2, 3, 4}
+		typeArr := []int{1, 2}
+		fieldMap := map[int]string{
+			1: "signing_time",
+			2: "expired_time",
+			3: "create_time",
+			4: "user_max",
+		}
+		typeMap := map[int]string{
+			1: "ASC",
+			2: "DESC",
+		}
+
+		sortParam, _ := this.GetInt("SortParam", 0)
+		sortType, _ := this.GetInt("SortType", 0)
+		if utils.InArrayByInt(fieldArr, sortParam) && utils.InArrayByInt(typeArr, sortType) {
+			order = fmt.Sprintf("%s %s", fieldMap[sortParam], typeMap[sortType])
+		}
+		fmt.Println("order: ", order)
+	}
+
+	// 获取列表
+	businessOb := new(eta_business.EtaBusiness)
+	total, e := businessOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家总数失败, Err: " + e.Error()
+		return
+	}
+	list, e := businessOb.GetPageItemsByCondition(cond, pars, []string{}, order, startSize, pageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家列表失败, Err: " + e.Error()
+		return
+	}
+	items := make([]*eta_business.EtaBusinessItem, 0)
+	for _, v := range list {
+		b := new(eta_business.EtaBusinessItem)
+		b.EtaBusinessId = v.EtaBusinessId
+		b.BusinessName = v.BusinessName
+		b.BusinessCode = v.BusinessCode
+		b.CreditCode = v.CreditCode
+		b.RegionType = v.RegionType
+		b.Province = v.Province
+		b.City = v.City
+		b.Address = v.Address
+		b.SellerId = v.SellerId
+		b.SellerName = v.SellerName
+		b.Leader = v.Leader
+		b.IndustryId = v.IndustryId
+		b.IndustryName = v.IndustryName
+		b.CapitalScale = v.CapitalScale
+		b.ResearchTeamSize = v.ResearchTeamSize
+		b.UserMax = v.UserMax
+		b.SigningStatus = v.SigningStatus
+		b.Enable = v.Enable
+		b.ContractId = v.ContractId
+		b.SigningTime = v.SigningTime.Format(utils.FormatDate)
+		b.ExpiredTime = v.ExpiredTime.Format(utils.FormatDate)
+		b.CreateTime = v.CreateTime.Format(utils.FormatDateTime)
+		b.ModifyTime = v.ModifyTime.Format(utils.FormatDateTime)
+		items = append(items, b)
+	}
+
+	resp.List = items
+	resp.Paging = paging.GetPaging(currentIndex, pageSize, total)
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Add
+// @Title 新增商家
+// @Description 新增商家
+// @Param	request	body eta_business.EtaBusinessAddReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /add [post]
+func (this *EtaBusinessController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 操作权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	// 参数校验
+	var req eta_business.EtaBusinessAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	req.BusinessName = strings.TrimSpace(req.BusinessName)
+	if req.BusinessName == "" {
+		br.Msg = "商家名称不可为空"
+		return
+	}
+	if req.CreditCode == "" {
+		br.Msg = "社会统一信用码不可为空"
+		return
+	}
+	req.Province = strings.TrimSpace(req.Province)
+	if req.Province == "" {
+		br.Msg = "省份不可为空"
+		return
+	}
+	req.City = strings.TrimSpace(req.City)
+	if req.City == "" {
+		br.Msg = "城市不可为空"
+		return
+	}
+	req.Leader = strings.TrimSpace(req.Leader)
+	if req.Leader == "" {
+		br.Msg = "决策人不可为空"
+		return
+	}
+	if req.IndustryId <= 0 || req.IndustryName == "" {
+		br.Msg = "所属行业不可为空"
+		return
+	}
+	if req.ResearchTeamSize == "" {
+		br.Msg = "研究团队规模不可为空"
+		return
+	}
+	if req.UserMax <= 0 {
+		br.Msg = "用户上限不可小于0"
+		return
+	}
+	req.CapitalScale = strings.TrimSpace(req.CapitalScale)
+
+	// 如果仅校验不新增, 那么不做第二页签约时间的校验
+	var signTime, expiredTime time.Time
+	if !req.IsCheck {
+		if req.SigningTime == "" {
+			br.Msg = "签约时间不可为空"
+			return
+		}
+		if req.ExpiredTime == "" {
+			br.Msg = "到期时间不可为空"
+			return
+		}
+		signTime, e = time.ParseInLocation(utils.FormatDate, req.SigningTime, time.Local)
+		if e != nil {
+			br.Msg = "签约时间格式有误"
+			br.ErrMsg = "签约时间格式有误, Err: " + e.Error()
+			return
+		}
+		expiredTime, e = time.ParseInLocation(utils.FormatDate, req.ExpiredTime, time.Local)
+		if e != nil {
+			br.Msg = "到期时间格式有误"
+			br.ErrMsg = "到期时间格式有误, Err: " + e.Error()
+			return
+		}
+		if !expiredTime.After(signTime) {
+			br.Msg = "到期时间不得早于签约时间"
+			return
+		}
+	}
+
+	// 重名校验
+	{
+		item := new(eta_business.EtaBusiness)
+		cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessColumns.BusinessName)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.BusinessName)
+		exist, e := item.GetItemByCondition(cond, pars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取重名商家失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil {
+			br.Msg = "商家名称已存在"
+			return
+		}
+	}
+
+	// 社会信用码重复校验
+	{
+		item := new(eta_business.EtaBusiness)
+		cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessColumns.CreditCode)
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.CreditCode)
+		exist, e := item.GetItemByCondition(cond, pars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取重复信用码商家失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil {
+			br.Msg = "商家社会信用码已存在"
+			return
+		}
+	}
+
+	// 如果只做校验不新增, 此处校验通过后直接返回true
+	if req.IsCheck {
+		br.Data = true
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "校验通过"
+		return
+	}
+
+	// 商家编码
+	businessCode, e := eta_business.CreateEtaBusinessCode()
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "生成商家编码失败, Err: " + e.Error()
+		return
+	}
+	codeEncrypt := utils.MD5(fmt.Sprintf("%s%s", businessCode, utils.BusinessCodeSalt))
+
+	now := time.Now().Local()
+	// 若当前时间不在首次签约时间内, 也算作已终止, 进入合约期时会由定时任务改为首次签约
+	status := eta_business.EtaBusinessSigningStatusFirst
+	isTerminate := true
+	if now.Equal(signTime) || now.Equal(expiredTime) {
+		isTerminate = false
+	}
+	if now.After(signTime) && now.Before(expiredTime) {
+		isTerminate = false
+	}
+	if isTerminate {
+		status = eta_business.EtaBusinessSigningStatusTerminate
+	}
+
+	// 新增商家和签约
+	businessItem := new(eta_business.EtaBusiness)
+	businessItem.BusinessName = req.BusinessName
+	businessItem.BusinessCode = businessCode
+	businessItem.CodeEncrypt = codeEncrypt
+	businessItem.CreditCode = req.CreditCode
+	businessItem.RegionType = req.RegionType
+	businessItem.Province = req.Province
+	businessItem.City = req.City
+	businessItem.Address = req.Province + req.City
+	businessItem.SellerId = req.SellerId
+	businessItem.SellerName = req.SellerName
+	businessItem.Leader = req.Leader
+	businessItem.IndustryId = req.IndustryId
+	businessItem.IndustryName = req.IndustryName
+	businessItem.CapitalScale = req.CapitalScale
+	businessItem.ResearchTeamSize = req.ResearchTeamSize
+	businessItem.UserMax = req.UserMax
+	businessItem.Enable = 1
+	businessItem.SigningStatus = status
+	businessItem.SigningTime = signTime
+	businessItem.ExpiredTime = expiredTime
+	businessItem.CreateTime = now
+	businessItem.ModifyTime = now
+	contractItem := new(eta_business.EtaBusinessContract)
+	contractItem.SigningTime = signTime
+	contractItem.ExpiredTime = expiredTime
+	contractItem.IsFirst = 1
+	contractItem.CreateTime = now
+	contractItem.ModifyTime = now
+	if e = eta_business.CreateEtaBusinessAndContract(businessItem, contractItem); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增商家和签约失败, Err: " + e.Error()
+		return
+	}
+
+	// 操作日志
+	go func() {
+		recordOb := new(eta_business.EtaBusinessOperationRecord)
+		recordOb.EtaBusinessId = businessItem.EtaBusinessId
+		recordOb.SellerId = businessItem.SellerId
+		recordOb.SysUserId = sysUser.AdminId
+		recordOb.SysRealName = sysUser.RealName
+		recordOb.OperationType = eta_business.EtaBusinessOperationTypeAdd
+		recordOb.OperationRemark = fmt.Sprintf("%s新增商户", sysUser.RealName)
+		recordOb.CreateTime = time.Now().Local()
+		_ = recordOb.Create()
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑商家
+// @Description 编辑商家
+// @Param	request	body eta_business.EtaBusinessEditReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /edit [post]
+func (this *EtaBusinessController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req eta_business.EtaBusinessEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID为空"
+		return
+	}
+	req.Province = strings.TrimSpace(req.Province)
+	if req.Province == "" {
+		br.Msg = "省份不可为空"
+		return
+	}
+	req.City = strings.TrimSpace(req.City)
+	if req.City == "" {
+		br.Msg = "城市不可为空"
+		return
+	}
+	req.Leader = strings.TrimSpace(req.Leader)
+	if req.Leader == "" {
+		br.Msg = "决策人不可为空"
+		return
+	}
+	if req.IndustryId <= 0 || req.IndustryName == "" {
+		br.Msg = "所属行业不可为空"
+		return
+	}
+	if req.ResearchTeamSize == "" {
+		br.Msg = "研究团队规模不可为空"
+		return
+	}
+	if req.UserMax <= 0 {
+		br.Msg = "用户上限不可小于0"
+		return
+	}
+	req.CapitalScale = strings.TrimSpace(req.CapitalScale)
+
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	ob := new(eta_business.EtaBusiness)
+	item, e := ob.GetItemById(req.EtaBusinessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+	item.Province = req.Province
+	item.City = req.City
+	item.Address = req.Province + req.City
+	item.Leader = req.Leader
+	item.IndustryId = req.IndustryId
+	item.IndustryName = req.IndustryName
+	item.CapitalScale = req.CapitalScale
+	item.ResearchTeamSize = req.ResearchTeamSize
+	item.UserMax = req.UserMax
+	item.ModifyTime = time.Now().Local()
+	cols := []string{
+		"Province", "City", "Address", "Leader", "IndustryId", "IndustryName", "CapitalScale", "ResearchTeamSize", "UserMax", "ModifyTime",
+	}
+	if e := item.Update(cols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "编辑商家失败, Err: " + e.Error()
+		return
+	}
+
+	// 操作日志
+	go func() {
+		recordOb := new(eta_business.EtaBusinessOperationRecord)
+		recordOb.EtaBusinessId = item.EtaBusinessId
+		recordOb.SellerId = item.SellerId
+		recordOb.SysUserId = sysUser.AdminId
+		recordOb.SysRealName = sysUser.RealName
+		recordOb.OperationType = eta_business.EtaBusinessOperationTypeEdit
+		recordOb.OperationRemark = fmt.Sprintf("%s编辑商户", sysUser.RealName)
+		recordOb.CreateTime = time.Now().Local()
+		_ = recordOb.Create()
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Signing
+// @Title 签约续约
+// @Description 签约续约(业务上仅用于续约, 兼容首次签约)
+// @Param	request	body eta_business.EtaBusinessSigningReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /signing [post]
+func (this *EtaBusinessController) Signing() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req eta_business.EtaBusinessSigningReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID为空"
+		return
+	}
+	if req.SigningTime == "" {
+		br.Msg = "签约时间不可为空"
+		return
+	}
+	if req.ExpiredTime == "" {
+		br.Msg = "到期时间不可为空"
+		return
+	}
+	signTime, e := time.ParseInLocation(utils.FormatDate, req.SigningTime, time.Local)
+	if e != nil {
+		br.Msg = "签约时间格式有误"
+		br.ErrMsg = "签约时间格式有误, Err: " + e.Error()
+		return
+	}
+	expiredTime, e := time.ParseInLocation(utils.FormatDate, req.ExpiredTime, time.Local)
+	if e != nil {
+		br.Msg = "到期时间格式有误"
+		br.ErrMsg = "到期时间格式有误, Err: " + e.Error()
+		return
+	}
+	if !expiredTime.After(signTime) {
+		br.Msg = "到期时间不得早于签约时间"
+		return
+	}
+
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	// 获取商家信息
+	businessOb := new(eta_business.EtaBusiness)
+	business, e := businessOb.GetItemById(req.EtaBusinessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+
+	// 续约不可早于当前生效合约的到期时间
+	if business.ContractId > 0 {
+		{
+			ob := new(eta_business.EtaBusinessContract)
+			item, e := ob.GetItemById(business.ContractId)
+			if e != nil {
+				br.Msg = "操作失败"
+				br.ErrMsg = "获取商家当前合同失败, Err: " + e.Error()
+				return
+			}
+			if !signTime.After(item.ExpiredTime) {
+				br.Msg = "签约时间不可早于当前合同的到期时间"
+				return
+			}
+		}
+	}
+
+	// 获取历史签约, 签约日期不可交叠
+	contract := new(eta_business.EtaBusinessContract)
+	cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessContractColumns.EtaBusinessId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, req.EtaBusinessId)
+	contracts, e := contract.GetItemsByCondition(cond, pars, []string{}, "")
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家签约列表失败, Err: " + e.Error()
+		return
+	}
+
+	// 校验签约时间是否重叠
+	isFirst := true // 是否为首次签约
+	if len(contracts) > 0 {
+		isFirst = false
+		for _, c := range contracts {
+			pass := false
+			if expiredTime.Before(c.SigningTime) {
+				pass = true
+			}
+			if signTime.After(c.ExpiredTime) {
+				pass = true
+			}
+			if !pass {
+				br.Msg = "签约时间在存续期内, 请检查"
+				return
+			}
+		}
+	}
+
+	// 新增签约
+	contract.EtaBusinessId = req.EtaBusinessId
+	contract.SigningTime = signTime
+	contract.ExpiredTime = expiredTime
+	contract.CreateTime = time.Now().Local()
+	contract.ModifyTime = time.Now().Local()
+	if isFirst {
+		contract.IsFirst = 1
+	}
+	if e = contract.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增签约失败, Err: " + e.Error()
+		return
+	}
+
+	// 签约后续操作
+	go func() {
+		_ = etaBusinessService.UpdateEtaBusinessAfterSigning(business.EtaBusinessId)
+	}()
+
+	// 续约操作日志
+	if !isFirst {
+		go func() {
+			recordOb := new(eta_business.EtaBusinessOperationRecord)
+			recordOb.EtaBusinessId = business.EtaBusinessId
+			recordOb.SellerId = business.SellerId
+			recordOb.SysUserId = sysUser.AdminId
+			recordOb.SysRealName = sysUser.RealName
+			recordOb.OperationType = eta_business.EtaBusinessOperationTypeRenewalContract
+			recordOb.OperationRemark = fmt.Sprintf("%s添加续约", sysUser.RealName)
+			recordOb.CreateTime = time.Now().Local()
+			_ = recordOb.Create()
+		}()
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Enable
+// @Title 禁用启用
+// @Description 禁用启用
+// @Param	request	body eta_business.EtaBusinessEnableReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /enable [post]
+func (this *EtaBusinessController) Enable() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req eta_business.EtaBusinessEnableReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID为空"
+		return
+	}
+
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	// 获取商家信息
+	businessOb := new(eta_business.EtaBusiness)
+	business, e := businessOb.GetItemById(req.EtaBusinessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+
+	// 禁启用
+	typeMap := map[int]int{
+		0: eta_business.EtaBusinessOperationTypeEnable,
+		1: eta_business.EtaBusinessOperationTypeDisable,
+	}
+	typeRemarkMap := map[int]string{
+		0: "启用",
+		1: "禁用",
+	}
+	operateType := typeMap[business.Enable]
+	operateRemark := typeRemarkMap[business.Enable]
+
+	business.Enable = business.Enable ^ 1
+	business.ModifyTime = time.Now().Local()
+	cols := []string{"Enable", "ModifyTime"}
+	if e = business.Update(cols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "更新商家状态失败, Err: " + e.Error()
+		return
+	}
+
+	// 操作日志
+	go func() {
+		recordOb := new(eta_business.EtaBusinessOperationRecord)
+		recordOb.EtaBusinessId = business.EtaBusinessId
+		recordOb.SellerId = business.SellerId
+		recordOb.SysUserId = sysUser.AdminId
+		recordOb.SysRealName = sysUser.RealName
+		recordOb.OperationType = operateType
+		recordOb.OperationRemark = fmt.Sprintf("%s%s商户", sysUser.RealName, operateRemark)
+		recordOb.CreateTime = time.Now().Local()
+		_ = recordOb.Create()
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// MoveSeller
+// @Title 移动销售
+// @Description 移动销售
+// @Param	request	body eta_business.EtaBusinessMoveSellerReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /move_seller [post]
+func (this *EtaBusinessController) MoveSeller() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req eta_business.EtaBusinessMoveSellerReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID为空"
+		return
+	}
+	if req.SellerId <= 0 || req.SellerName == "" {
+		br.Msg = "销售不可为空"
+		return
+	}
+
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	// 获取商家信息
+	businessOb := new(eta_business.EtaBusiness)
+	business, e := businessOb.GetItemById(req.EtaBusinessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+
+	// 更新销售
+	business.SellerId = req.SellerId
+	business.SellerName = req.SellerName
+	business.ModifyTime = time.Now().Local()
+	cols := []string{"SellerId", "SellerName", "ModifyTime"}
+	if e = business.Update(cols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "移动至销售失败, Err: " + e.Error()
+		return
+	}
+
+	// 操作日志
+	go func() {
+		recordOb := new(eta_business.EtaBusinessOperationRecord)
+		recordOb.EtaBusinessId = business.EtaBusinessId
+		recordOb.SellerId = req.SellerId
+		recordOb.SysUserId = sysUser.AdminId
+		recordOb.SysRealName = sysUser.RealName
+		recordOb.OperationType = eta_business.EtaBusinessOperationTypeMoveSeller
+		recordOb.OperationRemark = fmt.Sprintf("%s移动到: %s", sysUser.RealName, req.SellerName)
+		recordOb.CreateTime = time.Now().Local()
+		_ = recordOb.Create()
+	}()
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Detail
+// @Title 商家详情
+// @Description 商家详情
+// @Param   EtaBusinessId	query	int		true	"商家ID"
+// @Success 200 Ret=200 获取成功
+// @router /detail [get]
+func (this *EtaBusinessController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	businessId, _ := this.GetInt("EtaBusinessId", 0)
+	if businessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID"
+		return
+	}
+
+	businessOb := new(eta_business.EtaBusiness)
+	item, e := businessOb.GetItemById(businessId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "商家不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家信息失败, Err: " + e.Error()
+		return
+	}
+
+	resp := new(eta_business.EtaBusinessItem)
+	resp.EtaBusinessId = item.EtaBusinessId
+	resp.BusinessName = item.BusinessName
+	resp.BusinessCode = item.BusinessCode
+	resp.CreditCode = item.CreditCode
+	resp.RegionType = item.RegionType
+	resp.Province = item.Province
+	resp.City = item.City
+	resp.Address = item.Address
+	resp.SellerId = item.SellerId
+	resp.SellerName = item.SellerName
+	resp.Leader = item.Leader
+	resp.IndustryId = item.IndustryId
+	resp.IndustryName = item.IndustryName
+	resp.CapitalScale = item.CapitalScale
+	resp.ResearchTeamSize = item.ResearchTeamSize
+	resp.UserMax = item.UserMax
+	resp.SigningStatus = item.SigningStatus
+	resp.Enable = item.Enable
+	resp.ContractId = item.ContractId
+	resp.SigningTime = item.SigningTime.Format(utils.FormatDate)
+	resp.ExpiredTime = item.ExpiredTime.Format(utils.FormatDate)
+	resp.CreateTime = item.CreateTime.Format(utils.FormatDateTime)
+	resp.ModifyTime = item.ModifyTime.Format(utils.FormatDateTime)
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// ContractList
+// @Title 商家签约列表
+// @Description 商家签约列表
+// @Param   EtaBusinessId	query	int		true	"商家ID"
+// @Success 200 Ret=200 获取成功
+// @router /contract_list [get]
+func (this *EtaBusinessController) ContractList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 权限校验
+	resp := make([]*eta_business.EtaBusinessContractItem, 0)
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	businessId, _ := this.GetInt("EtaBusinessId", 0)
+	if businessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID"
+		return
+	}
+
+	cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessContractColumns.EtaBusinessId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, businessId)
+	order := `signing_time DESC`
+
+	contractOb := new(eta_business.EtaBusinessContract)
+	list, e := contractOb.GetItemsByCondition(cond, pars, []string{}, order)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家签约列表失败, Err: " + e.Error()
+		return
+	}
+	now := time.Now().Local()
+	for _, v := range list {
+		b := new(eta_business.EtaBusinessContractItem)
+		b.EtaBusinessContractId = v.EtaBusinessContractId
+		b.EtaBusinessId = v.EtaBusinessId
+		b.SigningTime = v.SigningTime.Format(utils.FormatDate)
+		b.ExpiredTime = v.ExpiredTime.Format(utils.FormatDate)
+		// 到期天数, 终止日按当天的23:59:59算
+		strEnd := v.ExpiredTime.Format(utils.FormatDate)
+		strEnd = strEnd + " 23:59:59"
+		endTime, e := time.ParseInLocation(utils.FormatDateTime, strEnd, time.Local)
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "签约日期有误, Err: " + e.Error()
+			return
+		}
+		b.ExpireDay = "-"
+		if now.After(v.SigningTime) && now.Before(endTime) {
+			diff := utils.GetDiffDays(v.ExpiredTime, now)
+			b.ExpireDay = strconv.Itoa(diff)
+			b.Using = true
+		}
+		resp = append(resp, b)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// OperateRecordList
+// @Title 操作日志列表
+// @Description 操作日志列表
+// @Param   EtaBusinessId	query	int		true	"商家ID"
+// @Success 200 Ret=200 获取成功
+// @router /operate_record_list [get]
+func (this *EtaBusinessController) OperateRecordList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	// 权限校验
+	resp := make([]*eta_business.EtaBusinessOperationRecordItem, 0)
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+	businessId, _ := this.GetInt("EtaBusinessId", 0)
+	if businessId <= 0 {
+		br.Msg = "参数有误"
+		br.ErrMsg = "参数有误, 商家ID"
+		return
+	}
+
+	cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessOperationRecordColumns.EtaBusinessId)
+	pars := make([]interface{}, 0)
+	pars = append(pars, businessId)
+
+	recordOb := new(eta_business.EtaBusinessOperationRecord)
+	list, e := recordOb.GetItemsByCondition(cond, pars, []string{}, "")
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家操作日志列表失败, Err: " + e.Error()
+		return
+	}
+	for _, v := range list {
+		r := new(eta_business.EtaBusinessOperationRecordItem)
+		r.EtaBusinessId = v.EtaBusinessId
+		r.SysUserId = v.SysUserId
+		r.SysRealName = v.SysRealName
+		r.OperationType = v.OperationType
+		r.OperationRemark = v.OperationRemark
+		r.CreateTime = v.CreateTime.Format(utils.FormatDateTime)
+		resp = append(resp, r)
+	}
+
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}

+ 197 - 0
controllers/eta_business/eta_business_menu.go

@@ -0,0 +1,197 @@
+package eta_business
+
+import (
+	"encoding/json"
+	"hongze/hz_crm_api/controllers"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/eta_business"
+	etaBusinessService "hongze/hz_crm_api/services/eta_business"
+)
+
+// EtaBusinessMenuController ETA商家菜单
+type EtaBusinessMenuController struct {
+	controllers.BaseAuthController
+}
+
+// List
+// @Title 商家菜单列表
+// @Description 商家菜单列表
+// @Param   BusinessId	query	int	false	"商家ID"
+// @Success 200 Ret=200 获取成功
+// @router /menu/list [get]
+func (this *EtaBusinessMenuController) List() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	resp := new(eta_business.EtaBusinessMenuListResp)
+	resp.ChoiceList = make([]int, 0)
+	resp.HalfChoiceList = make([]int, 0)
+	resp.List = make([]*eta_business.EtaBusinessMenuItem, 0)
+	// 权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Data = resp
+		br.Ret = 200
+		br.Success = true
+		br.Msg = "获取成功"
+		return
+	}
+
+	// 商家勾选的权限
+	businessId, _ := this.GetInt("EtaBusinessId", 0)
+	if businessId > 0 {
+		relateOb := new(eta_business.EtaBusinessMenuRelate)
+		cond := ` AND eta_business_id = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, businessId)
+		relates, e := relateOb.GetItemsByCondition(cond, pars, []string{}, "")
+		if e != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取商家菜单关联列表失败, Err: " + e.Error()
+			return
+		}
+		for _, r := range relates {
+			if r.Type == 1 {
+				resp.HalfChoiceList = append(resp.HalfChoiceList, r.MenuId)
+				continue
+			}
+			resp.ChoiceList = append(resp.ChoiceList, r.MenuId)
+		}
+	}
+
+	menuOb := new(eta_business.EtaBusinessMenu)
+	order := `sort ASC, create_time DESC, menu_id DESC`
+	list, e := menuOb.GetItemsByCondition("", make([]interface{}, 0), []string{}, order)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取商家菜单列表失败, Err: " + e.Error()
+		return
+	}
+
+	items := make([]*eta_business.EtaBusinessMenuItem, 0)
+	for _, v := range list {
+		t := &eta_business.EtaBusinessMenuItem{
+			MenuId:       v.MenuId,
+			ParentId:     v.ParentId,
+			Name:         v.Name,
+			Sort:         v.Sort,
+			Path:         v.Path,
+			PathName:     v.PathName,
+			IconPath:     v.IconPath,
+			Component:    v.Component,
+			Hidden:       v.Hidden,
+			HiddenLayout: v.HiddenLayout,
+			Level:        v.Level,
+			MenuType:     v.MenuType,
+			ButtonCode:   v.ButtonCode,
+			Children:     make([]*eta_business.EtaBusinessMenuItem, 0),
+		}
+		items = append(items, t)
+	}
+
+	// 递归返回树形结构
+	items = etaBusinessService.GetMenuTreeRecursive(items, 0)
+
+	resp.List = items
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// SaveRelate
+// @Title 保存商家菜单关联
+// @Description 保存商家菜单关联
+// @Param	request	body eta_business.EtaBusinessAddReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /menu/relate/save [post]
+func (this *EtaBusinessMenuController) SaveRelate() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 操作权限校验
+	ok, e := etaBusinessService.CheckEtaBusinessOperateAuth(sysUser.RoleTypeCode)
+	if e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作权限校验失败, ErrMsg: " + e.Error()
+		return
+	}
+	if !ok {
+		br.Msg = "无权操作"
+		return
+	}
+
+	// 参数校验
+	var req eta_business.EtaBusinessMenuRelateSaveReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.EtaBusinessId <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+	if len(req.MenuIds) == 0 {
+		br.Msg = "请选择菜单"
+		return
+	}
+
+	ob := new(eta_business.EtaBusinessMenuRelate)
+	items := make([]*eta_business.EtaBusinessMenuRelate, 0)
+	for _, v := range req.MenuIds {
+		t := new(eta_business.EtaBusinessMenuRelate)
+		t.MenuId = v
+		t.EtaBusinessId = req.EtaBusinessId
+		items = append(items, t)
+	}
+	for _, v := range req.HalfMenuIds {
+		t := new(eta_business.EtaBusinessMenuRelate)
+		t.MenuId = v
+		t.Type = 1
+		t.EtaBusinessId = req.EtaBusinessId
+		items = append(items, t)
+	}
+	if e := ob.CreateMulti(req.EtaBusinessId, items); e != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存商家菜单关联失败, Err: " + e.Error()
+		return
+	}
+
+	// TODO:后续需要生成SQL脚本文件
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 19 - 2
controllers/eta_trial.go

@@ -240,6 +240,7 @@ func (this *ETATrialController) Add() {
 	resp := new(eta_trial.ETATrialListResp)
 
 	//提交审批
+	approvalIds := make([]int, 0)
 	for _, v := range req.List {
 		if v.CompanyName == "" {
 			br.Msg = "请填写公司名称"
@@ -381,7 +382,7 @@ func (this *ETATrialController) Add() {
 		msgItem := new(company.CompanyApprovalMessage)
 		msgItem.CreateUserId = sysUser.AdminId
 		msgItem.ReceiveUserId = -1
-		msgItem.MessageStatus = 0
+		msgItem.MessageStatus = 1 // 已读, 不再亮红点, 但是消息要有
 		msgItem.Remark = seller.RealName + "申请试用账号"
 		msgItem.Content = seller.RealName + "申请试用账号"
 		msgItem.CompanyName = v.CompanyName
@@ -393,6 +394,17 @@ func (this *ETATrialController) Add() {
 		msgItem.SourceType = 9     //消息来源
 		msgItem.ApprovalStatus = 1 //审批状态,1:待审批,2:已审批,3:已驳回
 		err = company.AddCompanyApprovalMessage(msgItem)
+
+		approvalIds = append(approvalIds, int(approvalId))
+	}
+
+	// 2023-08-01默认审批通过, 不再进行人工审批, 也不发送待办消息
+	if len(approvalIds) > 0 {
+		go func() {
+			for _, v := range approvalIds {
+				_ = services.ApprovalApply(v)
+			}
+		}()
 	}
 
 	br.Ret = 200
@@ -484,7 +496,7 @@ func (this *ETATrialController) ApplyEnable() {
 	msgItem := new(company.CompanyApprovalMessage)
 	msgItem.CreateUserId = sysUser.AdminId
 	msgItem.ReceiveUserId = -1
-	msgItem.MessageStatus = 0
+	msgItem.MessageStatus = 1 // 已读, 不再亮红点, 但是消息要有
 	msgItem.Remark = seller.RealName + "申请账号启用"
 	msgItem.Content = seller.RealName + "申请账号启用"
 	msgItem.CompanyName = req.CompanyName
@@ -497,6 +509,11 @@ func (this *ETATrialController) ApplyEnable() {
 	msgItem.ApprovalStatus = 1 //审批状态,1:待审批,2:已审批,3:已驳回
 	err = company.AddCompanyApprovalMessage(msgItem)
 
+	// 2023-08-01默认审批通过, 不再进行人工审批
+	go func() {
+		_ = services.ApprovalApply(int(approvalId))
+	}()
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "提交成功"

+ 401 - 0
controllers/eta_version_update_log.go

@@ -0,0 +1,401 @@
+package controllers
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// EtaVersionUpdateLogController ETA版本更新日志
+type EtaVersionUpdateLogController struct {
+	BaseAuthController
+}
+
+// PageList
+// @Title 更新日志列表-分页
+// @Description 更新日志列表-分页
+// @Param   Keyword		query	string	false	"关键词"
+// @Param   SortType	query	string	false	"排序方式, 1-ASC; 2-DESC"
+// @Success 200 Ret=200 获取成功
+// @router /page_list [get]
+func (this *EtaVersionUpdateLogController) PageList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 分页
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	cond := ``
+	pars := make([]interface{}, 0)
+	// 关键词
+	keyword := this.GetString("Keyword", "")
+	keyword = strings.TrimSpace(keyword)
+	if keyword != "" {
+		kw := fmt.Sprint("%", keyword, "%")
+		cond += ` AND content LIKE ?`
+		pars = append(pars, kw)
+	}
+
+	sortType, _ := this.GetInt("SortType", 0)
+	orderMap := map[int]string{0: "", 1: "update_date ASC", 2: "update_date DESC"}
+	order := orderMap[sortType]
+
+	// 获取列表
+	businessOb := new(models.EtaVersionUpdateLog)
+	total, e := businessOb.GetCountByCondition(cond, pars)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取更新日志总数失败, Err: " + e.Error()
+		return
+	}
+	list, e := businessOb.GetPageItemsByCondition(cond, pars, []string{}, order, startSize, pageSize)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取更新日志列表失败, Err: " + e.Error()
+		return
+	}
+
+	items := make([]*models.EtaVersionUpdateLogItem, 0)
+	for _, v := range list {
+		b := new(models.EtaVersionUpdateLogItem)
+		b.Id = v.Id
+		b.Version = v.Version
+		b.Content = v.Content
+		b.UpdateDate = v.UpdateDate.Format(utils.FormatDate)
+		b.CreateTime = v.CreateTime.Format(utils.FormatDateTime)
+		b.ModifyTime = v.ModifyTime.Format(utils.FormatDateTime)
+		items = append(items, b)
+	}
+
+	resp := new(models.EtaVersionUpdateLogListResp)
+	resp.List = items
+	resp.Paging = paging.GetPaging(currentIndex, pageSize, total)
+	br.Data = resp
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+}
+
+// Add
+// @Title 新增
+// @Description 新增
+// @Param	request	body models.EtaVersionUpdateLogAddReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /add [post]
+func (this *EtaVersionUpdateLogController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 参数校验
+	var req models.EtaVersionUpdateLogAddReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	req.Version = strings.TrimSpace(req.Version)
+	if req.Version == "" {
+		br.Msg = "版本号不可为空"
+		return
+	}
+	// 版本号格式: X.X.X
+	versionArr := strings.Split(req.Version, ".")
+	if len(versionArr) != 3 {
+		br.Msg = "请输入正确格式的版本号"
+		return
+	}
+	for _, n := range versionArr {
+		if _, e := strconv.Atoi(n); e != nil {
+			br.Msg = "请输入正确格式的版本号"
+			return
+		}
+	}
+
+	req.Content = strings.TrimSpace(req.Content)
+	if req.Content == "" {
+		br.Msg = "更新内容不可为空"
+		return
+	}
+	updateDate, e := time.ParseInLocation(utils.FormatDate, req.UpdateDate, time.Local)
+	if e != nil {
+		br.Msg = "更新日期格式有误"
+		br.ErrMsg = "更新日期格式有误, Err: " + e.Error()
+		return
+	}
+
+	// 版本号重复校验
+	{
+		item := new(models.EtaVersionUpdateLog)
+		cond := ` AND version = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.Version)
+		exist, e := item.GetItemByCondition(cond, pars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取更新日志重复版本号失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil {
+			br.Msg = "该版本号已有更新日志, 请重新输入"
+			return
+		}
+	}
+
+	// 更新日期重复校验
+	{
+		item := new(models.EtaVersionUpdateLog)
+		cond := ` AND update_date = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.UpdateDate)
+		exist, e := item.GetItemByCondition(cond, pars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取更新日志重复日期失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil {
+			br.Msg = "该日期已有更新日志, 请重新选择"
+			return
+		}
+	}
+
+	// 新增
+	item := new(models.EtaVersionUpdateLog)
+	item.Version = req.Version
+	item.UpdateDate = updateDate
+	item.Content = req.Content
+	item.CreateTime = time.Now().Local()
+	item.ModifyTime = time.Now().Local()
+	if e = item.Create(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "新增更新日志失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Edit
+// @Title 编辑
+// @Description 编辑
+// @Param	request	body models.EtaVersionUpdateLogEditReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /edit [post]
+func (this *EtaVersionUpdateLogController) Edit() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 参数校验
+	var req models.EtaVersionUpdateLogEditReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.Id <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+	req.Version = strings.TrimSpace(req.Version)
+	if req.Version == "" {
+		br.Msg = "版本号不可为空"
+		return
+	}
+	// 版本号格式: X.X.X
+	versionArr := strings.Split(req.Version, ".")
+	if len(versionArr) != 3 {
+		br.Msg = "请输入正确格式的版本号"
+		return
+	}
+	for _, n := range versionArr {
+		if _, e := strconv.Atoi(n); e != nil {
+			br.Msg = "请输入正确格式的版本号"
+			return
+		}
+	}
+	req.Content = strings.TrimSpace(req.Content)
+	if req.Content == "" {
+		br.Msg = "更新内容不可为空"
+		return
+	}
+	updateDate, e := time.ParseInLocation(utils.FormatDate, req.UpdateDate, time.Local)
+	if e != nil {
+		br.Msg = "更新日期格式有误"
+		br.ErrMsg = "更新日期格式有误, Err: " + e.Error()
+		return
+	}
+
+	// 版本号重复校验
+	{
+		item := new(models.EtaVersionUpdateLog)
+		cond := ` AND version = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.Version)
+		exist, e := item.GetItemByCondition(cond, pars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取更新日志重复版本号失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil && exist.Id != req.Id {
+			br.Msg = "该版本号已有更新日志, 请重新输入"
+			return
+		}
+	}
+
+	// 更新日期重复校验
+	{
+		item := new(models.EtaVersionUpdateLog)
+		cond := ` AND update_date = ?`
+		pars := make([]interface{}, 0)
+		pars = append(pars, req.UpdateDate)
+		exist, e := item.GetItemByCondition(cond, pars)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			br.Msg = "操作失败"
+			br.ErrMsg = "获取更新日志重复日期失败, Err: " + e.Error()
+			return
+		}
+		if exist != nil && exist.Id != req.Id {
+			br.Msg = "该日期已有更新日志, 请重新选择"
+			return
+		}
+	}
+
+	ob := new(models.EtaVersionUpdateLog)
+	item, e := ob.GetItemById(req.Id)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "更新日志不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取更新日志信息失败, Err: " + e.Error()
+		return
+	}
+	item.Version = req.Version
+	item.Content = req.Content
+	item.UpdateDate = updateDate
+	item.ModifyTime = time.Now().Local()
+	cols := []string{"Version", "Content", "UpdateDate", "ModifyTime"}
+	if e := item.Update(cols); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "编辑更新日志失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}
+
+// Del
+// @Title 删除
+// @Description 删除
+// @Param	request	body models.EtaVersionUpdateLogDelReq true "type json string"
+// @Success 200 Ret=200 操作成功
+// @router /del [post]
+func (this *EtaVersionUpdateLogController) Del() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		if br.ErrMsg == "" {
+			br.IsSendEmail = false
+		}
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	// 参数校验
+	var req models.EtaVersionUpdateLogDelReq
+	if e := json.Unmarshal(this.Ctx.Input.RequestBody, &req); e != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + e.Error()
+		return
+	}
+	if req.Id <= 0 {
+		br.Msg = "参数有误"
+		return
+	}
+
+	ob := new(models.EtaVersionUpdateLog)
+	item, e := ob.GetItemById(req.Id)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "更新日志不存在, 请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = "获取更新日志信息失败, Err: " + e.Error()
+		return
+	}
+	if e := item.Del(); e != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "删除更新日志失败, Err: " + e.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+}

+ 1 - 1
controllers/full_company.go

@@ -2453,7 +2453,7 @@ func (this *FullCompanyController) Detail() {
 				return
 			}
 			// cygx8.2专项产业调研展示
-			item.SpecialSurplus, err = cygxService.GetSpecialSurplusByCompany(companyId)
+			item.SpecialSurplus, err = cygxService.GetSpecialSurplusByCompanyNew(companyId)
 			if err != nil {
 				br.Msg = "获取失败"
 				br.ErrMsg = "获取专项调研信息失败,Err:" + err.Error()

+ 539 - 0
controllers/help_doc/classify.go

@@ -0,0 +1,539 @@
+package help_doc
+
+import (
+	"encoding/json"
+	"hongze/hz_crm_api/controllers"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/help_doc"
+	"hongze/hz_crm_api/services/data"
+	"hongze/hz_crm_api/utils"
+	"time"
+)
+
+// HelpDocClassifyController 帮助文档分类
+type HelpDocClassifyController struct {
+	controllers.BaseAuthController
+}
+
+// ListClassify
+// @Title 获取分类列表
+// @Description 获取分类列表
+// @Param   KeyWord   query   string  true       "检索关键词"
+// @Success 200 {object} models.HelpDocClassifyListResp
+// @router /classify/list [get]
+func (this *HelpDocClassifyController) ListClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	keyWord := this.GetString("KeyWord")
+
+	resp := new(help_doc.HelpDocClassifyListResp)
+
+	rootList, err := help_doc.GetHelpDocClassifyByParentId(0, "")
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	docAll, err := help_doc.GetAllHelpDoc()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	classifyMap := make(map[int]int,0)
+	for _, v := range docAll {
+		classifyMap[v.ClassifyId] = 1
+	}
+
+	classifyAll := make([]*help_doc.HelpDocClassifyItems, 0)
+	newClassifyAll := make([]*help_doc.HelpDocClassifyItems, 0)
+	newRootList := make([]help_doc.HelpDocClassifyItems, 0)
+	//parentMap := make(map[int]int)
+	classifyAllMap := make(map[int]*help_doc.HelpDocClassifyItems, 0)
+	classifyKeyMap := make(map[int]*help_doc.HelpDocClassifyItems, 0)
+	rootMap := make(map[*help_doc.HelpDocClassifyItems]int, 0)
+	if keyWord != "" {
+		classifyAll, err = help_doc.GetAllHelpDocClassifyByKeyword("")
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range classifyAll {
+			classifyAllMap[v.ClassifyId] = v
+		}
+
+		keywordClassify, err := help_doc.GetAllHelpDocClassifyByKeyword(keyWord)
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		for _, v := range keywordClassify {
+			if v.Level == 3 {
+				ppid := classifyAllMap[v.ParentId].ParentId
+				//newRootList = append(newRootList, *classifyAllMap[ppid])
+				rootMap[classifyAllMap[ppid]] = 1
+				classifyKeyMap[v.ClassifyId] = v
+				classifyKeyMap[v.ParentId] = classifyAllMap[v.ParentId]
+			} else if v.Level == 2{
+				pid := classifyAllMap[v.ParentId].ClassifyId
+				//newRootList = append(newRootList, *classifyAllMap[pid])
+				rootMap[classifyAllMap[pid]] = 1
+				classifyKeyMap[v.ClassifyId] = v
+			} else if v.Level == 1 {
+				//newRootList = append(newRootList, *v)
+				rootMap[v] = 1
+			}
+		}
+		// 重新组合 newRootList
+		//for _, v := range rootList {
+		//	if root,ok := rootMap[v.ClassifyId]; ok{
+		//		newRootList = append(newRootList, *root)
+		//	}
+		//}
+		for v, _ := range rootMap {
+			newRootList = append(newRootList, *v)
+		}
+		// 重新组合 newClassifyAll
+		for _, v := range classifyKeyMap {
+			if v.Level != 1 {
+				newClassifyAll = append(newClassifyAll, v)
+			}
+		}
+	} else {
+		classifyAll, err = help_doc.GetHelpDocClassifyAll("")
+		if err != nil {
+			br.Msg = "获取失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		newRootList = rootList
+		newClassifyAll = classifyAll
+	}
+
+	for k := range newClassifyAll {
+		_,ok := classifyMap[newClassifyAll[k].ClassifyId]
+		newClassifyAll[k].Disabled = ok
+	}
+
+	//rootListAll := make([]help_doc.HelpDocClassifyItems, 0)
+	//rootListAll = rootList
+	nodeAll := make([]*help_doc.HelpDocClassifyItems, 0)
+	for k := range newRootList {
+		rootNode := newRootList[k]
+		data.HelpDocClassifyItemsMakeTree(newClassifyAll, &rootNode)
+		nodeAll = append(nodeAll, &rootNode)
+	}
+
+	//添加分类用,只有一二级目录
+	classifyLevel, err := help_doc.GetHelpDocClassifyLevel()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	for k := range classifyLevel {
+		_,ok := classifyMap[classifyLevel[k].ClassifyId]
+		classifyLevel[k].Disabled = ok
+	}
+
+	//rootListLevel := make([]help_doc.HelpDocClassifyItems, 0)
+	//rootListLevel = rootList
+	nodeAllTwoLevel := make([]*help_doc.HelpDocClassifyItems, 0)
+	for k := range rootList {
+		rootNode := rootList[k]
+		data.HelpDocClassifyItemsMakeTree(classifyLevel, &rootNode)
+		nodeAllTwoLevel = append(nodeAllTwoLevel, &rootNode)
+	}
+
+	resp.AllNodes = nodeAll
+	resp.TwoLevelNodes = nodeAllTwoLevel
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 新增分类
+// @Description 新增分类接口
+// @Param   ClassifyName   int  true       "分类名称"
+// @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
+// @Param   Sort   query   string  false       "排序"
+// @Success 200 新增成功
+// @router /classify/add [post]
+func (this *HelpDocClassifyController) AddClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req help_doc.AddHelpDocClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.HelpDocClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		br.IsSendEmail = false
+		return
+	}
+	if req.ParentId < 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	count, err := help_doc.GetHelpDocClassifyCount(req.HelpDocClassifyName, req.ParentId)
+	if err != nil {
+		br.Msg = "判断名称是否已存在失败"
+		br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+		return
+	}
+	if count > 0 {
+		br.Msg = "分类名称已存在,请重新输入"
+		br.IsSendEmail = false
+		return
+	}
+	//获取该层级下最大的排序数
+	maxSort, err := help_doc.GetHelpDocClassifyMaxSort(req.ParentId)
+
+	classify := new(help_doc.HelpDocClassify)
+	classify.ParentId = req.ParentId
+	classify.ClassifyName = req.HelpDocClassifyName
+	classify.CreateTime = time.Now()
+	classify.ModifyTime = time.Now()
+	classify.SysUserId = this.SysUser.AdminId
+	classify.SysUserRealName = this.SysUser.RealName
+	classify.Level = req.Level + 1
+	classify.Sort = maxSort + 1
+
+	_, err = help_doc.AddHelpDocClassify(classify)
+	if err != nil {
+		br.Msg = "保存分类失败"
+		br.ErrMsg = "保存分类失败,Err:" + err.Error()
+		return
+	}
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+}
+
+// @Title 编辑分类
+// @Description 编辑分类接口
+// @Param   ClassifyId   int  true       "分类Id"
+// @Param   ClassifyName   string  true       "分类名称"
+// @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
+// @Param   Sort   query   string  false       "排序"
+// @Success 200 保存成功
+// @router /classify/edit [post]
+func (this *HelpDocClassifyController) EditClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req help_doc.EditHelpDocClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.HelpDocClassifyName == "" {
+		br.Msg = "请输入分类名称"
+		br.IsSendEmail = false
+		return
+	}
+
+	if req.HelpDocClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	item, err := help_doc.GetHelpDocClassifyById(req.HelpDocClassifyId)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.Msg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	if item.ClassifyName != req.HelpDocClassifyName {
+		count, err := help_doc.GetHelpDocClassifyCount(req.HelpDocClassifyName, item.ParentId)
+		if err != nil {
+			br.Msg = "判断名称是否已存在失败"
+			br.ErrMsg = "判断名称是否已存在失败,Err:" + err.Error()
+			return
+		}
+		if count > 0 {
+			br.Msg = "分类名称已存在,请重新输入"
+			br.IsSendEmail = false
+			return
+		}
+
+		err = help_doc.EditHelpDocClassify(req.HelpDocClassifyId, req.HelpDocClassifyName)
+		if err != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = "保存失败,Err:" + err.Error()
+			return
+		}
+	}
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.IsAddLog = true
+}
+
+// @Title 删除分类列表
+// @Description 删除分类列表
+// @Param   ClassifyId   int  true       "分类名称"
+// @Success 200 删除成功
+// @router /classify/delete [get]
+func (this *HelpDocClassifyController) DelClassify() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	classifyId, _ := this.GetInt("ClassifyId")
+
+	_, err := help_doc.GetHelpDocClassifyById(classifyId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "当前分类不存在"
+			br.ErrMsg = "当前分类不存在"
+			return
+		}
+		br.Msg = "获取分类信息失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+
+	count, err := help_doc.GetHelpDocClassifyChildCounts(classifyId)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	if count > 0 {
+		br.Msg = "请先删除该分类下关联分类"
+		br.Ret = 403
+		return
+	}
+
+	reportCount, e := help_doc.GetHelpDocCounts(classifyId)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取失败,Err:" + e.Error()
+		return
+	}
+
+	if reportCount > 0 {
+		br.Msg = "该分类已关联文章,不允许删除!"
+		br.Ret = 403
+		return
+	}
+
+	if err = help_doc.DeleteHelpDocClassify(classifyId); err != nil {
+		br.Msg = "删除失败"
+		br.ErrMsg = "删除分类失败, Err: " + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}
+
+// ChartClassifyMove
+// @Title 分类移动接口
+// @Description 分类移动接口
+// @Success 200 {object} data_manage.MoveChartClassifyReq
+// @router /classify/move [post]
+func (this *HelpDocClassifyController) ClassifyMove() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	var req help_doc.MoveClassifyReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.ClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "分类id小于等于0"
+		return
+	}
+	//判断分类是否存在
+	classifyInfo, err := help_doc.GetHelpDocClassifyById(req.ClassifyId)
+	if err != nil {
+		br.Msg = "移动失败"
+		br.ErrMsg = "获取分类信息失败,Err:" + err.Error()
+		return
+	}
+	updateCol := make([]string, 0)
+
+	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
+	if classifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
+		parentClassifyInfo, err := help_doc.GetHelpDocClassifyById(req.ParentClassifyId)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取上级分类信息失败,Err:" + err.Error()
+			return
+		}
+		classifyInfo.ParentId = parentClassifyInfo.ClassifyId
+		classifyInfo.Level = parentClassifyInfo.Level + 1
+		classifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
+	}
+
+	//如果有传入 上一个兄弟节点分类id
+	if req.PrevClassifyId > 0 {
+		//上一个兄弟节点
+		prevClassify, err := help_doc.GetHelpDocClassifyById(req.PrevClassifyId)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取上一个兄弟节点分类信息失败,Err:" + err.Error()
+			return
+		}
+
+		//如果是移动在两个兄弟节点之间
+		if req.NextClassifyId > 0 {
+			//下一个兄弟节点
+			nextClassify, err := help_doc.GetHelpDocClassifyById(req.NextClassifyId)
+			if err != nil {
+				br.Msg = "移动失败"
+				br.ErrMsg = "获取下一个兄弟节点分类信息失败,Err:" + err.Error()
+				return
+			}
+			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
+			if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == classifyInfo.Sort {
+				//变更兄弟节点的排序
+				updateSortStr := `sort + 2`
+				_ = help_doc.UpdateHelpDocClassifySortByParentId(prevClassify.ParentId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr)
+			} else {
+				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
+				if nextClassify.Sort-prevClassify.Sort == 1 {
+					//变更兄弟节点的排序
+					updateSortStr := `sort + 1`
+					_ = help_doc.UpdateHelpDocClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
+				}
+			}
+		}
+
+		classifyInfo.Sort = prevClassify.Sort + 1
+		classifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+
+	} else {
+		firstClassify, err := help_doc.GetFirstHelpDocClassifyByParentId(classifyInfo.ParentId)
+		if err != nil && err.Error() != utils.ErrNoRow() {
+			br.Msg = "移动失败"
+			br.ErrMsg = "获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + err.Error()
+			return
+		}
+
+		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
+		if firstClassify != nil && firstClassify.Sort == 0 {
+			updateSortStr := ` sort + 1 `
+			_ = help_doc.UpdateHelpDocClassifySortByParentId(firstClassify.ParentId, firstClassify.ClassifyId-1, 0, updateSortStr)
+		}
+
+		classifyInfo.Sort = 0 //那就是排在第一位
+		classifyInfo.ModifyTime = time.Now()
+		updateCol = append(updateCol, "Sort", "ModifyTime")
+	}
+
+	//更新
+	if len(updateCol) > 0 {
+		err = classifyInfo.Update(updateCol)
+		if err != nil {
+			br.Msg = "移动失败"
+			br.ErrMsg = "修改失败,Err:" + err.Error()
+			return
+		}
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "移动成功"
+}
+
+// @Title 编辑分类可见权限
+// @Description 编辑分类可见权限接口
+// @Param   ClassifyId   int  true       "分类Id"
+// @Param   ClassifyName   string  true       "分类名称"
+// @Param   ParentId   query   int  true       "父级Id 添加父级时为0"
+// @Param   Sort   query   string  false       "排序"
+// @Success 200 保存成功
+// @router /classify/visible/edit [post]
+func (this *HelpDocClassifyController) EditClassifyVisible() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req help_doc.EditHelpDocClassifyVisibleReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.HelpDocClassifyId <= 0 {
+		br.Msg = "参数错误"
+		br.IsSendEmail = false
+		return
+	}
+
+	//item, err := help_doc.GetHelpDocClassifyById(req.HelpDocClassifyId)
+	//if err != nil {
+	//	br.Msg = "保存失败"
+	//	br.Msg = "获取分类信息失败,Err:" + err.Error()
+	//	return
+	//}
+
+	err = help_doc.EditHelpDocClassifyVisible(req.HelpDocClassifyId, req.VisibleBusinessIds)
+	if err != nil {
+		br.Msg = "保存失败"
+		br.ErrMsg = "保存失败,Err:" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Msg = "保存成功"
+	br.Success = true
+	br.IsAddLog = true
+}

+ 429 - 0
controllers/help_doc/doc.go

@@ -0,0 +1,429 @@
+package help_doc
+
+import (
+	"encoding/json"
+	"fmt"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hz_crm_api/controllers"
+	"hongze/hz_crm_api/models"
+	"hongze/hz_crm_api/models/help_doc"
+	"hongze/hz_crm_api/utils"
+	"html"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// HelpDocController 帮助文档
+type HelpDocController struct {
+	controllers.BaseAuthController
+}
+
+// @Title 新增报告接口
+// @Description 新增报告
+// @Param	request	body help_doc.AddHelpDocReq true "type json string"
+// @Success 200 {object} models.AddEnglishReportResp
+// @router /add [post]
+func (this *HelpDocController) Add() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+	var req help_doc.AddHelpDocReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	fmt.Println("Id:", req.Id)
+	if req.Content == "" {
+		br.Msg = "请输入内容"
+		return
+	}
+	var anchor []byte
+	if req.AnchorData != nil {
+		anchor, err = json.Marshal(req.AnchorData)
+		if err != nil {
+			br.Msg = "参数解析异常!"
+			br.ErrMsg = "参数解析失败,Err:" + err.Error()
+			return
+		}
+	}
+	var recommend []byte
+	if req.RecommendData != nil {
+		recommend, err = json.Marshal(req.RecommendData)
+		if err != nil {
+			br.Msg = "参数解析异常!"
+			br.ErrMsg = "参数解析失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	item := new(help_doc.HelpDoc)
+	item.ClassifyId = req.ClassifyId
+	item.Title = req.Title
+	item.Author = req.Author
+	item.Status = req.Status
+	item.Content = html.EscapeString(req.Content)
+	item.CreateTime = time.Now()
+	item.ModifyTime = time.Now()
+	item.AdminId = sysUser.AdminId
+	item.AdminRealName = sysUser.RealName
+	item.Anchor = string(anchor)
+	item.Recommend = string(recommend)
+	if req.Status == 2 {
+		item.PublishTime = time.Now()
+	}
+
+	if req.Id == 0 {
+		_, err = help_doc.AddHelpDoc(item)
+		if err != nil {
+			br.Msg = "新增失败"
+			br.ErrMsg = "保存失败,Err:" + err.Error()
+			return
+		}
+	} else {
+		err = help_doc.EditHelpDoc(item, req.Id)
+		if err != nil {
+			br.Msg = "保存失败"
+			br.ErrMsg = "保存失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	if req.Status == 1 {
+		br.Msg = "保存成功"
+	} else {
+		br.Msg = "发布成功"
+	}
+	br.Ret = 200
+	br.Success = true
+
+}
+
+// @Title 获取报告详情接口
+// @Description 获取报告详情
+// @Param	request	body models.ReportDetailReq true "type json string"
+// @Success 200 {object} models.EnglishReportDetailView
+// @router /detail [get]
+func (this *HelpDocController) Detail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+
+	docId, err := this.GetInt("DocId")
+	if err != nil {
+		br.Msg = "获取参数失败!"
+		br.ErrMsg = "获取参数失败,Err:" + err.Error()
+		return
+	}
+	if docId <= 0 {
+		br.Msg = "参数错误"
+		return
+	}
+	item, err := help_doc.GetHelpDocById(docId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	item.Content = html.UnescapeString(item.Content)
+
+	var anchor []help_doc.AnchorList
+	if item.Anchor != "" {
+		err = json.Unmarshal([]byte(item.Anchor), &anchor)
+		if err != nil {
+			br.Msg = "解析失败"
+			br.ErrMsg = "解析失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	var recommend []help_doc.RecommendList
+	if item.Recommend != "" {
+		err = json.Unmarshal([]byte(item.Recommend), &recommend)
+		if err != nil {
+			br.Msg = "解析失败"
+			br.ErrMsg = "解析失败,Err:" + err.Error()
+			return
+		}
+	}
+
+	resp := help_doc.HelpDocResp{
+		Id:            item.Id,
+		ClassifyId:    item.ClassifyId,
+		Title:         item.Title,
+		Author:        item.Author,
+		CreateTime:    item.CreateTime,
+		ModifyTime:    item.ModifyTime,
+		Status:        item.Status,
+		PublishTime:   item.PublishTime,
+		Content:       item.Content,
+		AdminId:       item.AdminId,
+		AdminRealName: item.AdminRealName,
+		Anchor:        anchor,
+		Recommend:     recommend,
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 获取报告列表接口
+// @Description 获取报告列表
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   KeyWord   query   string  true       "搜索关键词"
+// @Success 200 {object} models.ReportListResp
+// @router /list [get]
+func (this *HelpDocController) ListReport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	sysUser := this.SysUser
+	if sysUser == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,SysUser Is Empty"
+		br.Ret = 408
+		return
+	}
+
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+
+	classifyIds := this.GetString("ClassifyIds")
+	keyWord := this.GetString("KeyWord")
+
+	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{}
+
+	if keyWord != "" {
+		condition += ` AND title LIKE '%` + keyWord + `%' `
+	}
+
+	if len(classifyIds) > 0 {
+		classifyIdSlice := strings.Split(classifyIds, ",")
+		condition += ` AND classify_id IN ( ` + utils.GetOrmInReplace(len(classifyIdSlice)) + ` ) `
+		pars = append(pars, classifyIdSlice)
+	}
+
+	//拿到所有分类信息,显示路径用
+	classifyAll, err := help_doc.GetAllHelpDocClassify()
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+
+	parentMap := make(map[int]int)
+	classifyNameMap := make(map[int]string)
+	for _, v := range classifyAll {
+		classifyNameMap[v.ClassifyId] = v.ClassifyName
+		if v.ParentId != 0 {
+			parentMap[v.ClassifyId] = v.ParentId
+		}
+	}
+
+	total, err := help_doc.GetHelpDocListCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := help_doc.GetHelpDocList(condition, pars, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+
+	resp := new(help_doc.HelpDocListResp)
+	for _, item := range list {
+		var anchor []help_doc.AnchorList
+		if item.Anchor != "" {
+			err = json.Unmarshal([]byte(item.Anchor), &anchor)
+			if err != nil {
+				br.Msg = "解析失败"
+				br.ErrMsg = "解析失败,Err:" + err.Error()
+				return
+			}
+		}
+
+		var recommend []help_doc.RecommendList
+		if item.Recommend != "" {
+			err = json.Unmarshal([]byte(item.Recommend), &recommend)
+			if err != nil {
+				br.Msg = "解析失败"
+				br.ErrMsg = "解析失败,Err:" + err.Error()
+				return
+			}
+		}
+		respItem := help_doc.HelpDocResp{
+			Id:            item.Id,
+			ClassifyId:    item.ClassifyId,
+			Title:         item.Title,
+			Author:        item.Author,
+			CreateTime:    item.CreateTime,
+			ModifyTime:    item.ModifyTime,
+			Status:        item.Status,
+			PublishTime:   item.PublishTime,
+			Content:       item.Content,
+			AdminId:       item.AdminId,
+			AdminRealName: item.AdminRealName,
+			Anchor:        anchor,
+			Recommend:     recommend,
+		}
+		if pid, ok := parentMap[respItem.ClassifyId]; ok {
+			pName := classifyNameMap[pid]
+			if ppid, ok := parentMap[pid]; ok {
+				ppName := classifyNameMap[ppid]
+				respItem.ClassifyName = ppName + "/" + pName + "/" + classifyNameMap[respItem.ClassifyId]
+			} else {
+				respItem.ClassifyName = pName + "/" + classifyNameMap[respItem.ClassifyId]
+			}
+		} else {
+			respItem.ClassifyName = classifyNameMap[respItem.ClassifyId]
+		}
+		resp.List = append(resp.List, &respItem)
+	}
+
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 发布报告接口
+// @Description 发布报告
+// @Param	request	body models.PublishReq true "type json string"
+// @Success 200 Ret=200 发布成功
+// @router /publish [post]
+func (this *HelpDocController) PublishReport() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req help_doc.PublishReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	docId := req.DocId
+	if docId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,报告id不可为空"
+		return
+	}
+
+	doc, err := help_doc.GetHelpDocById(docId)
+	if err != nil {
+		br.Msg = "获取报告信息失败"
+		br.ErrMsg = "获取报告信息失败,Err:" + err.Error()
+		return
+	}
+	if doc == nil {
+		br.Msg = "报告不存在"
+		return
+	}
+
+	var tmpErr error
+
+	if doc.Content == "" {
+		br.Msg = "报告内容为空,不可发布"
+		br.ErrMsg = "报告内容为空,不需要生成,report_id:" + strconv.Itoa(doc.Id)
+		return
+	}
+	if tmpErr = help_doc.PublishHelpDocById(docId, req.Status); tmpErr != nil {
+		br.Msg = "报告发布失败"
+		br.ErrMsg = "报告发布失败, Err:" + tmpErr.Error() + ", doc_id:" + strconv.Itoa(docId)
+		return
+	}
+
+	if req.Status == 1 {
+		br.Msg = "取消发布成功"
+	} else {
+		br.Msg = "发布成功"
+	}
+
+	br.Ret = 200
+	br.Success = true
+
+}
+
+// @Title 删除报告接口
+// @Description 删除报告
+// @Param	request	body models.DeleteReq true "type json string"
+// @Success 200 Ret=200 删除成功
+// @router /delete [post]
+func (this *HelpDocController) Delete() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	var req help_doc.DeleteReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.DocId <= 0 {
+		br.Msg = "参数错误"
+		br.ErrMsg = "参数错误,报告id不可为空"
+		return
+	}
+	_, err = help_doc.GetHelpDocById(req.DocId)
+	if err != nil {
+		if err.Error() == utils.ErrNoRow() {
+			br.Msg = "报告不存在"
+			return
+		}
+		br.Msg = "查询报告信息失败"
+		br.ErrMsg = "查询报告信息失败, Err" + err.Error()
+		return
+	}
+
+	err = help_doc.DeleteHelpDoc(req.DocId)
+	if err != nil {
+		br.Msg = "删除报告失败"
+		br.ErrMsg = "删除报告失败, Err" + err.Error()
+		return
+	}
+
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "删除成功"
+}

+ 1 - 1
controllers/sys_menu.go

@@ -100,7 +100,7 @@ func (this *SysRoleController) SysMenuList() {
 			}
 		}
 
-		if strings.Contains(item.Name, "出差管理") && sysUser.AdminId == 66 {
+		if strings.Contains(item.Name, "出差管理") && sysUser.AdminId == utils.ApproveUserId {
 			cm := new(system.ChildMenu)
 			cm.MenuId = 10000
 			cm.Name = "出差审批"

+ 1 - 1
models/company/company.go

@@ -109,7 +109,7 @@ func GetCompanySearchList(condition string, pars []interface{}, limitParam ...in
 			b.freeze_time,b.loss_time,a.lose_reason,b.is_suspend,b.seller_id,b.product_id,b.group_id,b.formal_time,b.freeze_time,
 			GROUP_CONCAT(b.start_date ORDER BY b.product_id ASC SEPARATOR '/') AS start_date,
 			GROUP_CONCAT(b.end_date ORDER BY b.product_id ASC SEPARATOR '/') AS end_date,
-			GROUP_CONCAT(DISTINCT b.company_type ORDER BY b.product_id ASC SEPARATOR '/') AS company_type,
+			GROUP_CONCAT(DISTINCT b.product_name ORDER BY b.product_id ASC SEPARATOR '/') AS company_type,
             GROUP_CONCAT(DISTINCT b.approve_status ORDER BY b.product_id ASC SEPARATOR '/') AS approve_status,
             GROUP_CONCAT(DISTINCT b.freeze_start_date ORDER BY b.product_id ASC SEPARATOR '/') AS freeze_start_date,
             GROUP_CONCAT(DISTINCT b.freeze_end_date ORDER BY b.product_id ASC SEPARATOR '/') AS freeze_end_date

+ 17 - 0
models/company/company_permission.go

@@ -623,3 +623,20 @@ func GetReportPermissionIdsByCompanyIds(companyIds []int) (items []*CompanyListP
 	_, err = o.Raw(sql, companyIds).QueryRows(&items)
 	return
 }
+
+
+// GetCompanyReportPermissionByCompanyIdAndProductId 获取权限类型
+func GetCompanyReportPermissionByCompanyIdAndProductId(companyId, productId int) (items []*CompanyReportPermission, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+	re.*
+FROM
+	company_report_permission  as re 
+	INNER JOIN chart_permission as  c ON c.chart_permission_id = re.chart_permission_id
+WHERE
+	re.company_id = ? 
+	AND re.product_id = ? 
+	AND STATUS = '正式' `
+	_, err = o.Raw(sql, companyId, productId).QueryRows(&items)
+	return
+}

+ 164 - 150
models/cygx/activity.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hz_crm_api/utils"
 	"time"
 )
 
@@ -76,6 +77,8 @@ type ActivityRep struct {
 	IsNeedEmail             int                       `description:"是否需要提供邮箱 1是,0否"`
 	SiginupDeadline         string                    `description:"报名截止时间"`
 	IsResearchPoints        int                       `description:"是否为研选扣点  1是,0否"`
+	IsResearch              bool                      `description:"是否为研选"`
+	IsShowHz                int                       `description:"是否同时在弘则展示  1是,0否"`
 	PointsSet               *CygxActivityPointsSetRsq `description:"研选扣点明细"`
 	IsAllCustomerType       int                       `description:"是否全选活动可见类型 0无 1全选"`
 	List                    []*ActivityGroupIndustrialRep
@@ -94,72 +97,74 @@ type ActivityGroupIndustrialRep struct {
 
 // 活动详情
 type ActivityDetail struct {
-	ActivityId              int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
-	ActivityTypeId          int    `description:"活动类型id"`
-	ActivityTypeName        string `description:"活动类型名称"`
-	ChartPermissionId       int    `description:"行业id"`
-	ChartPermissionName     string `description:"行业名称"`
-	Body                    string `description:"内容"`
-	CreateTime              string `description:"创建时间"`
-	IsLimitPeople           int    `description:"是否限制人数 1是,0否"`
-	LimitPeopleNum          string `description:"限制的人数数量"`
-	CustomerTypeIds         string `description:"活动可见的客户类型,多个ID用 , 隔开"`
-	PublishStatus           int    `description:"发布状态 1已发布,0未发布"`
-	LastUpdatedTime         string `description:"更新时间"`
-	ActivityTime            string `description:"活动时间"`
-	ActivityTimeText        string `description:"活动时间带文字"`
-	DistinguishedGuest      string `description:"嘉宾"`
-	Host                    string `description:"主持人"`
-	MainlandTell            string `description:"大陆拨入号"`
-	HongKongTell            string `description:"香港拨入号"`
-	TaiwanTell              string `description:"台湾拨入号"`
-	AmericaTell             string `description:"美国拨入号"`
-	ParticipationCode       string `description:"参会密码"`
-	Theme                   string `description:"主题"`
-	Expert                  string `description:"专家"`
-	ActivityName            string `description:"活动名称"`
-	OnlineParticipation     string `description:"网络参会"`
-	ReportLink              string `description:"报告链接"`
-	City                    string `description:"城市"`
-	Address                 string `description:"活动地址"`
-	Highlights              string `description:"活动亮点"`
-	Remarks                 string `description:"备注"`
-	ShowType                string `description:"人数限制类型,1不展示限制,2可选限制,3强制限制"`
-	Speaker                 string `description:"主讲人"`
-	ActiveState             int    `description:"活动进行状态 未开始:1、进行中2、已结束3"`
-	IsSubmitMeeting         int    `description:"是否提交过到会情况,1是,0否"`
-	TemporaryLabel          string `description:"临时标签"`
-	IsMakerShow             int    `description:"是否仅决策人可见 0,否 、1,是"`
-	VisibleRange            int    `description:"可见范围 1,仅本组可见 、2,全部客户可见"`
-	Scale                   string `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
-	IsShowSubjectName       int    `description:"小程序内是否展示标的名称 1是 ,0 否 默认0 "`
-	AdminId                 int    `description:"销售/管理员ID"`
-	AdminName               string `description:"销售/管理员姓名"`
-	IsHideAppointment       int    `description:"是否隐藏预约纪要按钮  1是,0 否"`
-	PermissionType          int    `description:"1主观,2客观"`
-	Label                   string `description:"标签"`
-	ListIndustrial          []*IndustrialActivityGroupManagementRep
-	ListSubject             []*SubjectActivityGroupManagementRep
-	IsCanAppointmentMinutes int    `description:"是否可预约纪要 1是 ,0 否 默认0 "`
-	YidongActivityId        string `description:"易董的活动ID"`
-	YidongActivityEndTime   string `description:"易董活动截止时间"`
-	VoiceList               []*CygxActivityVoiceReq
-	VideoDetail             *CygxActivityVideo
-	ActivityJoinType        string                    `description:"活动入会类型01报名审核后可入会 02预约即可入会 03仅定向邀请人员可入会"`
-	YidongSignUpEnd         string                    `description:"易董活动截止时间"` // 报名结束时间,适应于报名审核后可入会,为空表示不限制报名时间
-	YidongSignUpStart       string                    `description:"易董活动截止时间"` // 报名开始时间,适应于报名审核后可入会,为空表示不限制报名时间
-	PublishDate             string                    `description:"发布时间"`
-	IsYidongConduct         int                       `description:"是否属于易董办会 1:是 、0:否"`
-	IsCanOutboundCall       int                       `description:"是否提供外呼 1:是 、0:否"`
-	YidongActivityIdByCygx  string                    `description:"通过查研观向建会易董返回的活动ID"`
-	TencentConferenceNumber string                    `description:"腾讯会议号"`
-	IsExternalLabel         int                       `description:"是否为外部资源 1是,0否"`
-	SigninImg               string                    `description:"签到码图片"`
-	IsResearchPoints        int                       `description:"是否为研选扣点  1是,0否"`
-	IsBClass                int                       `description:"是否为B类电话会 1是,0否"`
-	IsNeedEmail             int                       `description:"是否需要提供邮箱 1是,0否"`
-	SiginupDeadline         string                    `description:"报名截止时间"`
-	PointsSet               *CygxActivityPointsSetRsq `description:"研选扣点明细"`
+	ActivityId                int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
+	ActivityTypeId            int    `description:"活动类型id"`
+	ActivityTypeName          string `description:"活动类型名称"`
+	ChartPermissionId         int    `description:"行业id"`
+	ChartPermissionName       string `description:"行业名称"`
+	Body                      string `description:"内容"`
+	CreateTime                string `description:"创建时间"`
+	IsLimitPeople             int    `description:"是否限制人数 1是,0否"`
+	LimitPeopleNum            string `description:"限制的人数数量"`
+	CustomerTypeIds           string `description:"活动可见的客户类型,多个ID用 , 隔开"`
+	PublishStatus             int    `description:"发布状态 1已发布,0未发布"`
+	LastUpdatedTime           string `description:"更新时间"`
+	ActivityTime              string `description:"活动时间"`
+	ActivityTimeText          string `description:"活动时间带文字"`
+	DistinguishedGuest        string `description:"嘉宾"`
+	Host                      string `description:"主持人"`
+	MainlandTell              string `description:"大陆拨入号"`
+	HongKongTell              string `description:"香港拨入号"`
+	TaiwanTell                string `description:"台湾拨入号"`
+	AmericaTell               string `description:"美国拨入号"`
+	ParticipationCode         string `description:"参会密码"`
+	Theme                     string `description:"主题"`
+	Expert                    string `description:"专家"`
+	ActivityName              string `description:"活动名称"`
+	OnlineParticipation       string `description:"网络参会"`
+	ReportLink                string `description:"报告链接"`
+	City                      string `description:"城市"`
+	Address                   string `description:"活动地址"`
+	Highlights                string `description:"活动亮点"`
+	Remarks                   string `description:"备注"`
+	ShowType                  string `description:"人数限制类型,1不展示限制,2可选限制,3强制限制"`
+	Speaker                   string `description:"主讲人"`
+	ActiveState               int    `description:"活动进行状态 未开始:1、进行中2、已结束3"`
+	IsSubmitMeeting           int    `description:"是否提交过到会情况,1是,0否"`
+	TemporaryLabel            string `description:"临时标签"`
+	IsMakerShow               int    `description:"是否仅决策人可见 0,否 、1,是"`
+	VisibleRange              int    `description:"可见范围 1,仅本组可见 、2,全部客户可见"`
+	Scale                     string `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
+	IsShowSubjectName         int    `description:"小程序内是否展示标的名称 1是 ,0 否 默认0 "`
+	AdminId                   int    `description:"销售/管理员ID"`
+	AdminName                 string `description:"销售/管理员姓名"`
+	IsHideAppointment         int    `description:"是否隐藏预约纪要按钮  1是,0 否"`
+	PermissionType            int    `description:"1主观,2客观"`
+	Label                     string `description:"标签"`
+	ListIndustrial            []*IndustrialActivityGroupManagementRep
+	ListSubject               []*SubjectActivityGroupManagementRep
+	IsCanAppointmentMinutes   int    `description:"是否可预约纪要 1是 ,0 否 默认0 "`
+	YidongActivityId          string `description:"易董的活动ID"`
+	YidongActivityEndTime     string `description:"易董活动截止时间"`
+	VoiceList                 []*CygxActivityVoiceReq
+	VideoDetail               *CygxActivityVideo
+	ActivityJoinType          string                    `description:"活动入会类型01报名审核后可入会 02预约即可入会 03仅定向邀请人员可入会"`
+	YidongSignUpEnd           string                    `description:"易董活动截止时间"` // 报名结束时间,适应于报名审核后可入会,为空表示不限制报名时间
+	YidongSignUpStart         string                    `description:"易董活动截止时间"` // 报名开始时间,适应于报名审核后可入会,为空表示不限制报名时间
+	PublishDate               string                    `description:"发布时间"`
+	IsYidongConduct           int                       `description:"是否属于易董办会 1:是 、0:否"`
+	IsCanOutboundCall         int                       `description:"是否提供外呼 1:是 、0:否"`
+	YidongActivityIdByCygx    string                    `description:"通过查研观向建会易董返回的活动ID"`
+	TencentConferenceNumber   string                    `description:"腾讯会议号"`
+	IsExternalLabel           int                       `description:"是否为外部资源 1是,0否"`
+	SigninImg                 string                    `description:"签到码图片"`
+	IsResearchPoints          int                       `description:"是否为研选扣点  1是,0否"`
+	IsBClass                  int                       `description:"是否为B类电话会 1是,0否"`
+	IsNeedEmail               int                       `description:"是否需要提供邮箱 1是,0否"`
+	SiginupDeadline           string                    `description:"报名截止时间"`
+	PointsSet                 *CygxActivityPointsSetRsq `description:"研选扣点明细"`
+	IsShowHz                  int                       `description:"是否同时在弘则展示  1是,0否"`
+	ChartPermissionNameDeputy string                    `description:"副行业名称"`
 }
 
 type ActivityDetailRep struct {
@@ -170,65 +175,68 @@ type ActivityDetailRep struct {
 
 // 活动详情
 type CygxActivity struct {
-	ActivityId              int       `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
-	ActivityTypeId          int       `description:"活动类型id"`
-	ActivityTypeName        string    `description:"活动类型名称"`
-	ChartPermissionId       int       `description:"行业id"`
-	ChartPermissionName     string    `description:"行业名称"`
-	ChartPermissionNames    string    `description:"行业名称辅助字段,区分研选子分类"`
-	Body                    string    `description:"内容"`
-	CreateTime              time.Time `description:"创建时间"`
-	PublishDate             time.Time `description:"发布时间"`
-	IsLimitPeople           int       `description:"是否限制人数 1是,0否"`
-	LimitPeopleNum          int       `description:"限制的人数数量"`
-	CustomerTypeIds         string    `description:"活动可见的客户类型,多个ID用 , 隔开"`
-	PublishStatus           int       `description:"发布状态 1已发布,0未发布"`
-	LastUpdatedTime         time.Time `description:"更新时间"`
-	ActivityTime            string    `description:"活动时间"`
-	ActivityTimeText        string    `description:"活动时间带文字"`
-	DistinguishedGuest      string    `description:"嘉宾"`
-	Host                    string    `description:"主持人"`
-	MainlandTell            string    `description:"大陆拨入号"`
-	HongKongTell            string    `description:"香港拨入号"`
-	TaiwanTell              string    `description:"台湾拨入号"`
-	AmericaTell             string    `description:"美国拨入号"`
-	ParticipationCode       string    `description:"参会密码"`
-	Theme                   string    `description:"主题"`
-	Expert                  string    `description:"专家"`
-	ActivityName            string    `description:"活动名称"`
-	ActivityNameTask        string    `description:"活动名称定时任务同步的时候使用"`
-	OnlineParticipation     string    `description:"网络参会"`
-	ReportLink              string    `description:"报告链接"`
-	City                    string    `description:"城市"`
-	Address                 string    `description:"活动地址"`
-	Highlights              string    `description:"活动亮点"`
-	Remarks                 string    `description:"备注"`
-	Speaker                 string    `description:"主讲人"`
-	ArticleId               int       `description:"关联报告id"`
-	Label                   string    `description:"标签"`
-	LinkParticipants        string    `description:"链接参会"`
-	AppAttendance           string    `description:"App参会"`
-	ConferencePassword      string    `description:"会议密码"`
-	TemporaryLabel          string    `description:"临时标签"`
-	IsMakerShow             int       `description:"是否仅决策人可见 0,否 、1,是"`
-	VisibleRange            int       `description:"可见范围 1,仅本组可见 、2,全部客户可见"`
-	Scale                   string    `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
-	IsShowSubjectName       int       `description:"小程序内是否展示标的名称 1是 ,0 否 默认0 "`
-	IsHideAppointment       int       `description:"是否隐藏预约纪要按钮 1是 ,0 否 默认0 "`
-	AdminId                 int       `description:"销售/管理员ID"`
-	AdminName               string    `description:"销售/管理员姓名"`
-	IsCanAppointmentMinutes int       `description:"是否可预约纪要 1是 ,0 否 默认0 "`
-	IsYidongConduct         int       `description:"是否属于易董办会 1:是 、0:否"`
-	IsCanOutboundCall       int       `description:"是否提供外呼 1:是 、0:否"`
-	IsCancel                int       `description:"是否取消,1是,0否"`
-	TencentConferenceNumber string    `description:"腾讯会议号"`
-	IsExternalLabel         int       `description:"是否为外部资源 1是,0否"`
-	IsBClass                int       `description:"是否为B类电话会 1是,0否"`
-	IsNeedEmail             int       `description:"是否需要提供邮箱 1是,0否"`
-	SiginupDeadline         string    `description:"报名截止时间"`
-	CancelDeadline          string    `description:"取消报名截止时间"`
-	IsResearchPoints        int       `description:"是否为研选扣点  1是,0否"`
-	IsAllCustomerType       int       `description:"是否全选活动可见类型 0无 1全选"`
+	ActivityId                int       `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
+	ActivityTypeId            int       `description:"活动类型id"`
+	ActivityTypeName          string    `description:"活动类型名称"`
+	ChartPermissionId         int       `description:"行业id"`
+	ChartPermissionName       string    `description:"行业名称"`
+	ChartPermissionNames      string    `description:"行业名称辅助字段,区分研选子分类"`
+	Body                      string    `description:"内容"`
+	CreateTime                time.Time `description:"创建时间"`
+	PublishDate               time.Time `description:"发布时间"`
+	IsLimitPeople             int       `description:"是否限制人数 1是,0否"`
+	LimitPeopleNum            int       `description:"限制的人数数量"`
+	CustomerTypeIds           string    `description:"活动可见的客户类型,多个ID用 , 隔开"`
+	PublishStatus             int       `description:"发布状态 1已发布,0未发布"`
+	LastUpdatedTime           time.Time `description:"更新时间"`
+	ActivityTime              string    `description:"活动时间"`
+	ActivityTimeText          string    `description:"活动时间带文字"`
+	DistinguishedGuest        string    `description:"嘉宾"`
+	Host                      string    `description:"主持人"`
+	MainlandTell              string    `description:"大陆拨入号"`
+	HongKongTell              string    `description:"香港拨入号"`
+	TaiwanTell                string    `description:"台湾拨入号"`
+	AmericaTell               string    `description:"美国拨入号"`
+	ParticipationCode         string    `description:"参会密码"`
+	Theme                     string    `description:"主题"`
+	Expert                    string    `description:"专家"`
+	ActivityName              string    `description:"活动名称"`
+	ActivityNameTask          string    `description:"活动名称定时任务同步的时候使用"`
+	OnlineParticipation       string    `description:"网络参会"`
+	ReportLink                string    `description:"报告链接"`
+	City                      string    `description:"城市"`
+	Address                   string    `description:"活动地址"`
+	Highlights                string    `description:"活动亮点"`
+	Remarks                   string    `description:"备注"`
+	Speaker                   string    `description:"主讲人"`
+	ArticleId                 int       `description:"关联报告id"`
+	Label                     string    `description:"标签"`
+	LinkParticipants          string    `description:"链接参会"`
+	AppAttendance             string    `description:"App参会"`
+	ConferencePassword        string    `description:"会议密码"`
+	TemporaryLabel            string    `description:"临时标签"`
+	IsMakerShow               int       `description:"是否仅决策人可见 0,否 、1,是"`
+	VisibleRange              int       `description:"可见范围 1,仅本组可见 、2,全部客户可见"`
+	Scale                     string    `description:"管理规模,空不填,1::50亿以下,2:50~100亿,3:100亿以上。多个用, 隔开"`
+	IsShowSubjectName         int       `description:"小程序内是否展示标的名称 1是 ,0 否 默认0 "`
+	IsHideAppointment         int       `description:"是否隐藏预约纪要按钮 1是 ,0 否 默认0 "`
+	AdminId                   int       `description:"销售/管理员ID"`
+	AdminName                 string    `description:"销售/管理员姓名"`
+	IsCanAppointmentMinutes   int       `description:"是否可预约纪要 1是 ,0 否 默认0 "`
+	IsYidongConduct           int       `description:"是否属于易董办会 1:是 、0:否"`
+	IsCanOutboundCall         int       `description:"是否提供外呼 1:是 、0:否"`
+	IsCancel                  int       `description:"是否取消,1是,0否"`
+	TencentConferenceNumber   string    `description:"腾讯会议号"`
+	IsExternalLabel           int       `description:"是否为外部资源 1是,0否"`
+	IsBClass                  int       `description:"是否为B类电话会 1是,0否"`
+	IsNeedEmail               int       `description:"是否需要提供邮箱 1是,0否"`
+	SiginupDeadline           string    `description:"报名截止时间"`
+	IsResearchPoints          int       `description:"是否为研选扣点  1是,0否"`
+	IsAllCustomerType         int       `description:"是否全选活动可见类型 0无 1全选"`
+	IsShowHz                  int       `description:"是否同时在弘则展示  1是,0否"`
+	ChartPermissionIdDeputy   int       `description:"行业id"`
+	ChartPermissionNameDeputy string    `description:"行业名称"`
+	CancelDeadline            string    `description:"取消报名截止时间"`
 }
 
 type CygxActivityEditDetail struct {
@@ -393,8 +401,13 @@ func EditActivity(item *CygxActivity, oldPublishStatus int, industrialActivityIt
 	updateParams["IsNeedEmail"] = item.IsNeedEmail
 	updateParams["SiginupDeadline"] = item.SiginupDeadline
 	updateParams["IsResearchPoints"] = item.IsResearchPoints
-	updateParams["CancelDeadline"] = item.CancelDeadline
 	updateParams["IsAllCustomerType"] = item.IsAllCustomerType
+	if item.ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+		updateParams["IsShowHz"] = item.IsShowHz //研选的才做修改
+	}
+	updateParams["ChartPermissionNameDeputy"] = item.ChartPermissionNameDeputy
+	updateParams["ChartPermissionIdDeputy"] = item.ChartPermissionIdDeputy
+	updateParams["CancelDeadline"] = item.CancelDeadline
 	//修改活动信息
 	ptrStructOrTableName := "cygx_activity"
 	whereParam := map[string]interface{}{"activity_id": item.ActivityId}
@@ -557,30 +570,31 @@ func EditActivityStatus(activityId int) (err error) {
 
 // 活动详情
 type CygxActivityList struct {
-	ActivityId           int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
-	ActivityTypeId       int    `description:"活动类型id"`
-	ActivityName         string `description:"活动名称"`
-	ActivityTypeName     string `description:"活动类型名称"`
-	ActiveState          int    `description:"活动进行状态 未开始:1、进行中2、已结束3"`
-	ChartPermissionId    int    `description:"行业id"`
-	ChartPermissionName  string `description:"行业名称"`
-	ChartPermissionNames string `description:"行业名称辅助字段,区分研选子分类"`
-	Body                 string `description:"内容"`
-	IsLimitPeople        int    `description:"是否限制人数 1是,0否"`
-	LimitPeopleNum       int    `description:"限制的人数数量"`
-	CustomerTypeIds      string `description:"活动可见的客户类型,多个ID用 , 隔开"`
-	PublishStatus        int    `description:"发布状态 1已发布,0未发布"`
-	LastUpdatedTime      string `description:"更新时间"`
-	ActivityTime         string `description:"活动时间"`
-	ActivityTimeText     string `description:"活动时间带文字"`
-	Label                string `description:"标签"`
-	YidongActivityId     string `description:"易董的活动ID"`
-	TemporaryLabel       string `description:"临时标签"`
-	IsCancel             int    `description:"是否取消,1是,0否"`
-	IsUpload             bool   `description:"是否上传"`
-	IsYidongConduct      int    `description:"是否属于易董办会 1:是 、0:否"`
-	IsShowSigninButton   bool   `description:"是否展示签到码按钮"`
-	SigninImg            string `description:"签到码图片"`
+	ActivityId                int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
+	ActivityTypeId            int    `description:"活动类型id"`
+	ActivityName              string `description:"活动名称"`
+	ActivityTypeName          string `description:"活动类型名称"`
+	ActiveState               int    `description:"活动进行状态 未开始:1、进行中2、已结束3"`
+	ChartPermissionId         int    `description:"行业id"`
+	ChartPermissionName       string `description:"行业名称"`
+	ChartPermissionNames      string `description:"行业名称辅助字段,区分研选子分类"`
+	Body                      string `description:"内容"`
+	IsLimitPeople             int    `description:"是否限制人数 1是,0否"`
+	LimitPeopleNum            int    `description:"限制的人数数量"`
+	CustomerTypeIds           string `description:"活动可见的客户类型,多个ID用 , 隔开"`
+	PublishStatus             int    `description:"发布状态 1已发布,0未发布"`
+	LastUpdatedTime           string `description:"更新时间"`
+	ActivityTime              string `description:"活动时间"`
+	ActivityTimeText          string `description:"活动时间带文字"`
+	Label                     string `description:"标签"`
+	YidongActivityId          string `description:"易董的活动ID"`
+	TemporaryLabel            string `description:"临时标签"`
+	IsCancel                  int    `description:"是否取消,1是,0否"`
+	IsUpload                  bool   `description:"是否上传"`
+	IsYidongConduct           int    `description:"是否属于易董办会 1:是 、0:否"`
+	IsShowSigninButton        bool   `description:"是否展示签到码按钮"`
+	SigninImg                 string `description:"签到码图片"`
+	ChartPermissionNameDeputy string `description:"副行业名称"`
 }
 
 type GetCygxActivityListRep struct {

+ 27 - 26
models/cygx/activity_meet.go

@@ -12,32 +12,33 @@ import (
 
 // 活动详情
 type CygxMeetList struct {
-	ActivityId              int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
-	ActivityName            string `description:"活动名称"`
-	ActivityTypeName        string `description:"活动类型名称"`
-	ActivityTypeId          int    `description:"活动类型ID"`
-	ChartPermissionName     string `description:"行业名称"`
-	ChartPermissionNames    string `description:"行业名称"`
-	ActivityTime            string `description:"活动时间"`
-	ActivityTimeText        string `description:"活动时间带文字"`
-	SignupPeopleNum         int    `description:"报名人数/预约外呼人数"`
-	MeetPeopleNum           int    `description:"实际参会人数"`
-	PotentialPeopleNum      int    `description:"潜在参会人数"`
-	OmeetPeopleNum          int    `description:"实际参会人数(辅助字段不使用)"`
-	IsSubmitMeeting         int    `description:"是否提交过到会信息 ,1是,0否"`
-	OperationStyle          int    `description:"操作方式,1提交到会情况/上传参会表格,2修改到会详情/重新上传"`
-	UpdateTime              string `description:"更新时间"`
-	IsCClassMeeting         bool   `description:"是否是c类电话会"`
-	SubmitMeetingType       int    `description:"操作展示类型 ,1修改到会详情"`
-	IsShowAttendanceDetails bool   `description:"是否展示到会详情"`
-	IsShowHandMovement      bool   `description:"是否展示手动匹配"`
-	IsShowSubmitMeeting     bool   `description:"是否展示提交到会情况"`
-	IsShowUpdateMeeting     bool   `description:"是否展示修改到会情况"`
-	YidongActivityId        string `description:"易董的活动ID"`
-	ActivityJoinType        string `description:"易董活动入会类型01报名审核后可入会 02预约即可入会 03仅定向邀请人员可入会"`
-	IsYidongConduct         int    `description:"是否属于易董办会 1:是 、0:否"`
-	IsShowSigninButton      bool   `description:"是否展示签到码按钮"`
-	SigninImg               string `description:"签到码图片"`
+	ActivityId                int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
+	ActivityName              string `description:"活动名称"`
+	ActivityTypeName          string `description:"活动类型名称"`
+	ActivityTypeId            int    `description:"活动类型ID"`
+	ChartPermissionName       string `description:"行业名称"`
+	ChartPermissionNames      string `description:"行业名称"`
+	ActivityTime              string `description:"活动时间"`
+	ActivityTimeText          string `description:"活动时间带文字"`
+	SignupPeopleNum           int    `description:"报名人数/预约外呼人数"`
+	MeetPeopleNum             int    `description:"实际参会人数"`
+	PotentialPeopleNum        int    `description:"潜在参会人数"`
+	OmeetPeopleNum            int    `description:"实际参会人数(辅助字段不使用)"`
+	IsSubmitMeeting           int    `description:"是否提交过到会信息 ,1是,0否"`
+	OperationStyle            int    `description:"操作方式,1提交到会情况/上传参会表格,2修改到会详情/重新上传"`
+	UpdateTime                string `description:"更新时间"`
+	IsCClassMeeting           bool   `description:"是否是c类电话会"`
+	SubmitMeetingType         int    `description:"操作展示类型 ,1修改到会详情"`
+	IsShowAttendanceDetails   bool   `description:"是否展示到会详情"`
+	IsShowHandMovement        bool   `description:"是否展示手动匹配"`
+	IsShowSubmitMeeting       bool   `description:"是否展示提交到会情况"`
+	IsShowUpdateMeeting       bool   `description:"是否展示修改到会情况"`
+	YidongActivityId          string `description:"易董的活动ID"`
+	ActivityJoinType          string `description:"易董活动入会类型01报名审核后可入会 02预约即可入会 03仅定向邀请人员可入会"`
+	IsYidongConduct           int    `description:"是否属于易董办会 1:是 、0:否"`
+	IsShowSigninButton        bool   `description:"是否展示签到码按钮"`
+	SigninImg                 string `description:"签到码图片"`
+	ChartPermissionNameDeputy string `description:"副行业名称"`
 }
 
 type GetCygxMeetListRep struct {

+ 26 - 25
models/cygx/activity_signup.go

@@ -13,31 +13,32 @@ import (
 
 // 活动详情
 type CygxSignupList struct {
-	ActivityId              int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
-	ActivityName            string `description:"活动名称"`
-	ActivityTypeName        string `description:"活动类型名称"`
-	ChartPermissionName     string `description:"行业名称"`
-	ChartPermissionNames    string `description:"行业名称辅助字段,区分研选子分类"`
-	LimitPeopleNum          int    `description:"限制的人数数量"`
-	ActivityTime            string `description:"活动时间"`
-	ActivityTimeText        string `description:"活动时间带文字"`
-	SignupPeopleNum         int    `description:"报名人数/预约外呼人数"`
-	SignupFailPeopleNum     int    `description:"报名/预约外呼失败人数"`
-	AskNum                  int    `description:"带问人数"`
-	AppointmentPeopleNum    int    `description:"预约纪要人数"`
-	ReminderPeopleNum       int    `description:"设置会议提醒人数"`
-	IsShowAppointment       bool   `description:"是否展示预约纪要"`
-	IsHideAppointment       int    `description:"是否隐藏预约纪要按钮  1是,0 否"`
-	ActivityTypeId          int    `description:"活动类型id"`
-	Label                   string `description:"标签"`
-	ActiveState             int    `description:"活动进行状态 未开始:1、进行中2、已结束3"`
-	PublishStatus           int    `description:"发布状态 1已发布,0未发布"`
-	TemporaryLabel          string `description:"临时标签"`
-	YidongActivityId        string `description:"易董的活动ID"`
-	IsCanAppointmentMinutes int    `description:"是否可预约纪要 1是 ,0 否 默认0 "`
-	IsCancel                int    `description:"是否取消,1是,0否"`
-	IsYidongConduct         int    `description:"是否属于易董办会 1:是 、0:否"`
-	IsResearchPoints        int    `description:"是否为研选扣点  1是,0否"`
+	ActivityId                int    `orm:"column(activity_id);pk";description:"活动ID 等于0新增活动,大于0修改活动"`
+	ActivityName              string `description:"活动名称"`
+	ActivityTypeName          string `description:"活动类型名称"`
+	ChartPermissionName       string `description:"行业名称"`
+	ChartPermissionNames      string `description:"行业名称辅助字段,区分研选子分类"`
+	LimitPeopleNum            int    `description:"限制的人数数量"`
+	ActivityTime              string `description:"活动时间"`
+	ActivityTimeText          string `description:"活动时间带文字"`
+	SignupPeopleNum           int    `description:"报名人数/预约外呼人数"`
+	SignupFailPeopleNum       int    `description:"报名/预约外呼失败人数"`
+	AskNum                    int    `description:"带问人数"`
+	AppointmentPeopleNum      int    `description:"预约纪要人数"`
+	ReminderPeopleNum         int    `description:"设置会议提醒人数"`
+	IsShowAppointment         bool   `description:"是否展示预约纪要"`
+	IsHideAppointment         int    `description:"是否隐藏预约纪要按钮  1是,0 否"`
+	ActivityTypeId            int    `description:"活动类型id"`
+	Label                     string `description:"标签"`
+	ActiveState               int    `description:"活动进行状态 未开始:1、进行中2、已结束3"`
+	PublishStatus             int    `description:"发布状态 1已发布,0未发布"`
+	TemporaryLabel            string `description:"临时标签"`
+	YidongActivityId          string `description:"易董的活动ID"`
+	IsCanAppointmentMinutes   int    `description:"是否可预约纪要 1是 ,0 否 默认0 "`
+	IsCancel                  int    `description:"是否取消,1是,0否"`
+	IsYidongConduct           int    `description:"是否属于易董办会 1:是 、0:否"`
+	IsResearchPoints          int    `description:"是否为研选扣点  1是,0否"`
+	ChartPermissionNameDeputy string `description:"副行业名称"`
 }
 
 type GetCygxSignupListRep struct {

+ 19 - 2
models/cygx/activity_special_trip.go

@@ -113,8 +113,9 @@ func AddCygxActivitySpecialTrip(items []*CygxActivitySpecialTrip, itemsBill []*C
 	}
 
 	//添加流水记录
-	for _, item := range itemsBill {
-		_, err = to.Insert(item)
+	//倒序插入,让流水表看起来是正的
+	for i := len(itemsBill) - 1; i >= 0; i-- {
+		_, err = to.Insert(itemsBill[i])
 		if err != nil {
 			return
 		}
@@ -280,3 +281,19 @@ func GetCygxActivitySpecialTripListCondition(condition string, pars []interface{
 	}
 	return
 }
+
+//获取某一用户的报名的数量
+func GetUserActivitySpecialTripCount(uid, activityId int) (count int, err error) {
+	sqlCount := `SELECT COUNT(1) AS count FROM cygx_activity_special_trip  WHERE  user_id=?  AND   activity_id =? `
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, uid, activityId).QueryRow(&count)
+	return
+}
+
+
+func UpdateSpecialTrip(isValid, isCancel, userId, activityId int) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE cygx_activity_special_trip SET is_valid = ?,create_time=NOW(),is_cancel=?  WHERE user_id=? AND activity_id=? `
+	_, err = o.Raw(sql, isValid, isCancel, userId, activityId).Exec()
+	return
+}

+ 110 - 2
models/cygx/activity_special_trip_bill.go

@@ -21,7 +21,9 @@ type CygxActivitySpecialTripBill struct {
 	DoType            int       `description:"操作方式,1报名,2取消报名"`
 	RegisterPlatform  int       `description:"来源 1小程序,2:网页"`
 	ChartPermissionId int       `description:"行业id"`
-	Way               int       `description:"1报名,取消报名。2到会取消到会"`
+	Way               int       `description:"1报名,取消报名。2到会取消到会 3转正或清零 4取消活动"`
+	Content           string    `description:"内容"`
+	Total             string    `description:"总和"`
 }
 
 type CygxActivitySpecialTripBillList struct {
@@ -41,6 +43,8 @@ type CygxActivitySpecialTripBillList struct {
 	RegisterPlatform    int       `description:"来源 1小程序,2:网页"`
 	ChartPermissionId   int       `description:"行业id"`
 	ChartPermissionName string    `description:"行业名称"`
+	Way                 int       `description:"1报名,取消报名。2到会取消到会 3转正或清零 4取消活动"`
+	Content             string    `description:"内容"`
 }
 
 // 添加
@@ -70,13 +74,31 @@ func GetCygxActivitySpecialTripBillList(condition string, pars []interface{}) (i
 			c.chart_permission_name 
 		FROM
 			cygx_activity_special_trip_bill AS b
-			INNER JOIN chart_permission AS c ON c.chart_permission_id = b.chart_permission_id 
+			LEFT JOIN chart_permission AS c ON c.chart_permission_id = b.chart_permission_id 
 		WHERE
 			1 = 1` + condition
 	_, err = o.Raw(sql, pars).QueryRows(&item)
 	return
 }
 
+type AirborneCount struct {
+	Count             int
+	ChartPermissionId int ` description:"品种权限ID"`
+}
+
+// 获取空降的公司报名的记录
+func GetActivitySpecialTripAirborneListByActivitySpecial(condition string, pars []interface{}) (items []*AirborneCount, err error) {
+	sqlCount := ` SELECT chart_permission_id,COUNT(1) AS count
+		FROM
+			cygx_activity_special_meeting_detail AS t
+			INNER JOIN cygx_activity_special AS a ON a.activity_id = t.activity_id 
+		WHERE
+			 1= 1  	AND YEAR ( t.create_time )= YEAR (NOW()) ` + condition + `GROUP BY chart_permission_id`
+	o := orm.NewOrm()
+	_, err = o.Raw(sqlCount, pars).QueryRows(&items)
+	return
+}
+
 // 获取空降的公司报名的记录
 func GetActivitySpecialTripAirborneCountByActivitySpecial(condition string, pars []interface{}) (count int, err error) {
 	sqlCount := ` SELECT COUNT(1) AS count
@@ -89,3 +111,89 @@ func GetActivitySpecialTripAirborneCountByActivitySpecial(condition string, pars
 	err = o.Raw(sqlCount, pars).QueryRow(&count)
 	return
 }
+
+type CygxActivitySpecialTripBillDetailList struct {
+	Id                  int       `orm:"column(id);pk"`
+	UserId              int       `description:"用户id,多个用,隔开"`
+	ActivityId          int       `description:"活动ID"`
+	ResearchTheme       string    `description:"调研主题"`
+	CreateTime          time.Time `description:"创建时间"`
+	Mobile              string    `description:"手机号"`
+	Email               string    `description:"邮箱号"`
+	CompanyId           int       `description:"公司ID"`
+	CompanyName         string    `description:"公司名称"`
+	RealName            string    `description:"用户实际名称"`
+	AdminId             int       `description:"销售/管理员ID"`
+	Source              int       `description:"来源,1小程序,2后台添加, 3开发人员手动添加"`
+	BillDetailed        int       `description:"流水明细,判断是进账还是出账"`
+	DoType              int       `description:"操作方式,1报名,2取消报名"`
+	RegisterPlatform    int       `description:"来源 1小程序,2:网页"`
+	ChartPermissionId   int       `description:"行业id"`
+	ChartPermissionName string    `description:"行业名称"`
+	Content             string    `description:"内容"`
+	Way                 int       `description:"1报名,取消报名。2到会取消到会 3转正或清零 4取消活动"`
+	Total               string    `description:"总和"`
+}
+
+func GetCygxActivitySpecialTripBillDetailList(condition string, pars []interface{}) (item []*CygxActivitySpecialTripBillDetailList, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			b.*,
+			a.research_theme,
+			c.chart_permission_name 
+		FROM
+			cygx_activity_special_trip_bill AS b
+			INNER JOIN chart_permission AS c ON c.chart_permission_id = b.chart_permission_id 
+			INNER JOIN cygx_activity_special AS a ON a.activity_id = b.activity_id
+		WHERE
+			1 = 1` + condition
+	_, err = o.Raw(sql, pars).QueryRows(&item)
+	return
+}
+
+type CygxActivitySpecialPointsBillRespItem struct {
+	Id                  int    `gorm:"column:id;primary_key;AUTO_INCREMENT"`
+	Content             string `gorm:"column:content" `                                 // 内容说明
+	Total               string `gorm:"column:points;default:0;NOT NULL" `               // 合计
+	CreateTime          string `gorm:"column:create_time" `                             // 创建时间
+	CompanyId           int    `gorm:"column:company_id;default:0" `                    // 公司ID
+	CompanyName         string `gorm:"column:company_name" `                            // 公司名称
+	RealName            string `gorm:"column:real_name"`                                // 用户实际名称
+	BillDetailed        int    `gorm:"column:bill_detailed;default:0;NOT NULL" json:""` // 流水明细,判断是进账还是出账
+	ActivityName        string `description:"活动标题"`
+	ChartPermissionId   int    `description:"行业id"`
+	ChartPermissionName string `description:"行业名称"`
+}
+
+type CygxActivitySpecialPointsBillResp struct {
+	List []*CygxActivitySpecialPointsBillRespItem
+}
+
+func GetCygxActivitySpecialTripBillDetailListAll(condition string, pars []interface{}) (item []*CygxActivitySpecialTripBillDetailList, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			b.*,
+			a.research_theme,
+			c.chart_permission_name 
+		FROM
+			cygx_activity_special_trip_bill AS b
+			LEFT JOIN chart_permission AS c ON c.chart_permission_id = b.chart_permission_id 
+			LEFT JOIN cygx_activity_special AS a ON a.activity_id = b.activity_id
+		WHERE
+			1 = 1` + condition
+
+	sql += ` ORDER BY b.create_time DESC`
+	_, err = o.Raw(sql, pars).QueryRows(&item)
+	return
+}
+
+func GetCygxActivitySpecialTripBillByCompanyId(companyId int) (item *CygxActivitySpecialTripBill, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			*
+		FROM
+			cygx_activity_special_trip_bill WHERE company_id = ? ORDER BY create_time DESC LIMIT 1
+		`
+	err = o.Raw(sql, companyId).QueryRow(&item)
+	return
+}

+ 1 - 1
models/cygx/activity_type.go

@@ -6,7 +6,7 @@ import (
 
 type ActivityType struct {
 	ActivityTypeId   int    `description:"活动类型id"`
-	ActivityTypeName string `description:"活动名称"`
+	ActivityTypeName string `description:"活动类型名称"`
 	TemplateP        string `description:"活动模板,带P标签"`
 	Template         string `description:"活动模板"`
 	ZoomTemplateP    string `description:"Zoom活动模板,带P标签"`

+ 1 - 1
models/cygx/company_user_type.go

@@ -55,7 +55,7 @@ func GetCygxCompanyUserTypeList() (items []*CygxCompanyUserType, err error) {
 // CygxCompanyUserType 更新权益客户身份类型
 func UpdateCygxCompanyUserTypeAndPackageType(companyId, useType, packageType int) (err error) {
 	o := orm.NewOrm()
-	sql := `UPDATE cygx_company_user_type SET customer_type_id=? AND package_type = ? WHERE company_id=? `
+	sql := `UPDATE cygx_company_user_type SET customer_type_id=?, package_type = ? WHERE company_id=? `
 	_, err = o.Raw(sql, useType, packageType, companyId).Exec()
 	return
 }

+ 39 - 0
models/cygx/cygx_activity_special_points_company.go

@@ -0,0 +1,39 @@
+package cygx
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxActivitySpecialInheritPointsCompany struct {
+	Id                  int       `orm:"column(id);pk"`
+	CompanyId           int       // 公司ID
+	CompanyName         string    // 公司名称
+	Points              int   // 公司剩余点数
+	CreateTime          time.Time // 创建时间
+	ModifyTime          time.Time // 更新时间
+	ChartPermissionId   int       // 品种ID
+	ChartPermissionName string    // 品种名称
+}
+
+func AddCygxActivitySpecialPointsCompany(item *CygxActivitySpecialInheritPointsCompany) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Insert(item)
+	if err != nil {
+		return
+	}
+	return
+}
+
+func AddCygxActivitySpecialInheritPointsCompanyMulti(items []*CygxActivitySpecialInheritPointsCompany) (err error) {
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(1, items)
+	return
+}
+
+func GetCygxActivitySpecialInheritPointsByCompanyId(companyId int) (list []*CygxActivitySpecialInheritPointsCompany, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM cygx_activity_special_inherit_points_company WHERE company_id = ?  `
+	_, err = o.Raw(sql,companyId).QueryRows(&list)
+	return
+}

+ 27 - 3
models/cygx/cygx_user.go

@@ -332,7 +332,6 @@ type UserInteraction struct {
 	SubjectNames          string `orm:"column(subject_names);NOT NULL"`  // 标的
 }
 
-
 // 查研观向图表
 type CygxChartResp struct {
 	Title       string `description:"标题"`
@@ -354,8 +353,8 @@ type CygxChartResp struct {
 // 获取阅读记录数量
 func GetCygxArticleHistoryCount(mobile, email, condition string) (count int, err error) {
 	o := orm.NewOrm()
-	sqlCount := ` SELECT COUNT(1) AS count  FROM cygx_article_history_record_all as r  INNER JOIN cygx_article  as art  ON  art.article_id = r.article_id  WHERE   r.mobile  = ?  AND is_del = 0 ` + condition + `  OR ( email = ? AND email <> ''  AND is_del = 0  ` + condition + `) `
-	err = o.Raw(sqlCount, mobile, email).QueryRow(&count)
+	sqlCount := ` SELECT COUNT(1) AS count  FROM cygx_article_history_record_all as r  INNER JOIN cygx_article  as art  ON  art.article_id = r.article_id  WHERE   r.mobile  = '` + mobile + `'  AND is_del = 0 ` + condition
+	err = o.Raw(sqlCount).QueryRow(&count)
 	return
 }
 
@@ -404,6 +403,31 @@ func GetCygxArticleHistoryRecordByUser(mobile, email, condition string, startSiz
 	return
 }
 
+// 用户阅读记录列表 2023-08-02 优化拆分
+func GetCygxArticleHistoryRecordByUserNew(mobile, email, condition string, startSize, pageSize int) (items []*UserInteraction, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT
+			art.title,
+			art.article_id,
+			art.article_id_md5,
+			art.publish_date,
+			art.category_name,
+			r.create_time,
+			r.stop_time,
+			r.source as source_platform
+		FROM
+			cygx_article_history_record_all AS r
+			INNER JOIN cygx_article AS art ON art.article_id = r.article_id
+		WHERE
+			 r.mobile  = ?  AND is_del = 0 ` + condition + `  OR ( email = ? AND email <>''  AND is_del = 0 ` + condition + `  )
+			 ORDER BY  r.create_time DESC   `
+	if startSize > 0 || pageSize > 0 {
+		sql += ` LIMIT ` + strconv.Itoa(startSize) + "," + strconv.Itoa(pageSize)
+	}
+	_, err = o.Raw(sql, mobile, email).QueryRows(&items)
+	return
+}
+
 // 收藏列表数量
 func GetCygxArticleCollectCount(uid int) (count int, err error) {
 	o := orm.NewOrm()

+ 0 - 18
models/cygx/report_article.go

@@ -1278,24 +1278,6 @@ type CygxCelueArticleHistoryRecord struct {
 	RealName       string    `description:"用户姓名"`
 }
 
-func GetArticleHistoryRecordMobile(articleIds string) (mobiles string, err error) {
-	sql := `SELECT  GROUP_CONCAT( DISTINCT mobile SEPARATOR ',' ) as mobiles   FROM cygx_article_history_record_newpv WHERE article_id IN (` + articleIds + `) AND mobile!= ''`
-	o := orm.NewOrm()
-	err = o.Raw(sql).QueryRow(&mobiles)
-	return
-}
-
-func GetCygxCelueArticleHistoryRecordPv(articleIds, mobiles string) (item []*ArticleHistoryRep, err error) {
-	o := orm.NewOrm()
-	sql := `SELECT * FROM cygx_celue_article_history_record WHERE article_id IN ( ` + articleIds + ` ) AND  `
-	if mobiles != "" {
-		sql += `	AND mobile NOT IN ( ` + mobiles + `)`
-	}
-	sql += ` ORDER BY create_time DESC  `
-	_, err = o.Raw(sql).QueryRows(&item)
-	return
-}
-
 func GetCygxCelueArticleHistoryRecordPvAll(articleIds string) (item []*ArticleHistoryRep, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT * FROM cygx_article_history_record_all as  h WHERE article_id IN ( ` + articleIds + ` )  AND   h.is_del = 0   AND h.platfor = 2 `

+ 38 - 0
models/cygx/report_mapping_celue.go

@@ -21,6 +21,22 @@ type CygxReportMappingCelue struct {
 	ModifyTime          time.Time `description:"更新时间"`
 }
 
+type CygxReportMappingCelueResp struct {
+	Id                  int       `orm:"column(id);pk" description:"id"`
+	ChartPermissionId   int       `description:"行业ID"`
+	CategoryId          int       `description:"分类ID"`
+	ChartPermissionName string    `description:"行业名称"`
+	SubCategoryName     string    `description:"主题"`
+	ReportType          int       `description:"报告类型,2产业报告,1行业报告"`
+	Sort                int       `description:"排序"`
+	IsCustom            int       `description:"是否属于自定义的匹配类型 ,1是,0否"`
+	IsSummary           int       `description:"是否是纪要库,1是,0否"`
+	IsReport            int       `description:"是否是报告,1是,0否"`
+	PermissionType      int       `description:"1主观,2客观"`
+	CreateTime          time.Time `description:"创建时间"`
+	ModifyTime          time.Time `description:"更新时间"`
+}
+
 // 获取category_id 最大的值,进行累加
 func GetCygxReportMappingCelueMaxDetail() (item *CygxReportMappingCelue, err error) {
 	o := orm.NewOrm()
@@ -28,3 +44,25 @@ func GetCygxReportMappingCelueMaxDetail() (item *CygxReportMappingCelue, err err
 	err = o.Raw(sql).QueryRow(&item)
 	return
 }
+
+// 列表
+func GetCygxReportMappingList(condition string, pars []interface{}) (items []*CygxReportMappingCelueResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_report_mapping   WHERE 1= 1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// 列表
+func GetCygxReportMappingCelueList(condition string, pars []interface{}) (items []*CygxReportMappingCelueResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_report_mapping_celue   WHERE 1= 1 `
+	if condition != "" {
+		sql += condition
+	}
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}

+ 37 - 0
models/db.go

@@ -15,7 +15,9 @@ import (
 	future_good2 "hongze/hz_crm_api/models/data_manage/future_good"
 	"hongze/hz_crm_api/models/data_manage/supply_analysis"
 	"hongze/hz_crm_api/models/day_new"
+	"hongze/hz_crm_api/models/eta_business"
 	"hongze/hz_crm_api/models/eta_trial"
+	"hongze/hz_crm_api/models/help_doc"
 	"hongze/hz_crm_api/models/roadshow"
 	"hongze/hz_crm_api/models/seal"
 	"hongze/hz_crm_api/models/system"
@@ -182,6 +184,15 @@ func init() {
 
 	//AI 聊天记录
 	initAiChat()
+
+	// ETA商家
+	initEtaBusiness()
+
+	// ETA版本更新日志
+	initEtaVersionUpdateLog()
+
+	// 帮助文档
+	initHelpDoc()
 }
 
 // initSystem 系统表 数据表
@@ -632,3 +643,29 @@ func initAiChat() {
 		new(aimod.AiChat),      //聊天
 	)
 }
+
+// initEtaBusiness ETA商家相关表
+func initEtaBusiness() {
+	orm.RegisterModel(
+		new(eta_business.EtaBusiness),                // ETA商家表
+		new(eta_business.EtaBusinessContract),        // ETA合同表
+		new(eta_business.EtaBusinessOperationRecord), // ETA操作记录表
+		new(eta_business.EtaBusinessMenu),            // ETA商家菜单表
+		new(eta_business.EtaBusinessMenuRelate),      // ETA商家菜单关联表
+	)
+}
+
+// initEtaVersionUpdateLog ETA版本更新日志
+func initEtaVersionUpdateLog() {
+	orm.RegisterModel(
+		new(EtaVersionUpdateLog), // 更新日志表
+	)
+}
+
+func initHelpDoc() {
+	//注册对象
+	orm.RegisterModel(
+		new(help_doc.HelpDocClassify), //分类
+		new(help_doc.HelpDoc),         //文章
+	)
+}

+ 325 - 0
models/eta_business/eta_business.go

@@ -0,0 +1,325 @@
+package eta_business
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hz_crm_api/utils"
+	"strings"
+	"time"
+)
+
+const (
+	EtaBusinessSigningStatusFirst = iota + 1
+	EtaBusinessSigningStatusContinue
+	EtaBusinessSigningStatusTerminate
+)
+
+type EtaBusiness struct {
+	EtaBusinessId    int       `orm:"column(eta_business_id);pk"`
+	BusinessName     string    `description:"商家名称"`
+	BusinessCode     string    `description:"商家编码"`
+	CodeEncrypt      string    `description:"商家编码加密"`
+	CreditCode       string    `description:"社会统一信用码"`
+	RegionType       string    `description:"所属区域:国内;海外"`
+	Province         string    `description:"省份"`
+	City             string    `description:"城市"`
+	Address          string    `description:"商家地址"`
+	SellerId         int       `description:"销售ID"`
+	SellerName       string    `description:"销售名称"`
+	Leader           string    `description:"决策人"`
+	IndustryId       int       `description:"行业ID"`
+	IndustryName     string    `description:"行业名称"`
+	CapitalScale     string    `description:"资金规模"`
+	ResearchTeamSize string    `description:"研究团队规模"`
+	UserMax          int       `description:"用户上限"`
+	SigningStatus    int       `description:"签约状态:1-首次签约;2-续约中;3-已终止"`
+	Enable           int       `description:"状态:0-禁用;1-启用"`
+	ContractId       int       `description:"当前合约ID"`
+	SigningTime      time.Time `description:"当前合约的签约时间"`
+	ExpiredTime      time.Time `description:"当前合约的到期时间"`
+	CreateTime       time.Time `description:"创建时间"`
+	ModifyTime       time.Time `description:"更新时间"`
+}
+
+func (m *EtaBusiness) TableName() string {
+	return "eta_business"
+}
+
+func (m *EtaBusiness) PrimaryId() string {
+	return EtaBusinessColumns.EtaBusinessId
+}
+
+var EtaBusinessColumns = struct {
+	EtaBusinessId    string
+	BusinessName     string
+	BusinessCode     string
+	CreditCode       string
+	RegionType       string
+	Province         string
+	City             string
+	Address          string
+	SellerId         string
+	SellerName       string
+	Leader           string
+	IndustryId       string
+	IndustryName     string
+	CapitalScale     string
+	ResearchTeamSize string
+	UserMax          string
+	SigningStatus    string
+	Enable           string
+	ContractId       string
+	SigningTime      string
+	ExpiredTime      string
+	CreateTime       string
+	ModifyTime       string
+}{
+	EtaBusinessId:    "eta_business_id",
+	BusinessName:     "business_name",
+	BusinessCode:     "business_code",
+	CreditCode:       "credit_code",
+	RegionType:       "region_type",
+	Province:         "province",
+	City:             "city",
+	Address:          "address",
+	SellerId:         "seller_id",
+	SellerName:       "seller_name",
+	Leader:           "leader",
+	IndustryId:       "industry_id",
+	IndustryName:     "industry_name",
+	CapitalScale:     "capital_scale",
+	ResearchTeamSize: "research_team_size",
+	UserMax:          "user_max",
+	SigningStatus:    "signing_status",
+	Enable:           "enable",
+	ContractId:       "contract_id",
+	SigningTime:      "signing_time",
+	ExpiredTime:      "expired_time",
+	CreateTime:       "create_time",
+	ModifyTime:       "modify_time",
+}
+
+func (m *EtaBusiness) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.EtaBusinessId = int(id)
+	return
+}
+
+func (m *EtaBusiness) CreateMulti(items []*EtaBusiness) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *EtaBusiness) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *EtaBusiness) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.EtaBusinessId).Exec()
+	return
+}
+
+func (m *EtaBusiness) GetItemById(id int) (item *EtaBusiness, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusiness) GetItemByCondition(condition string, pars []interface{}) (item *EtaBusiness, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusiness) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *EtaBusiness) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*EtaBusiness, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *EtaBusiness) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*EtaBusiness, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// CreateEtaBusinessAndContract 新增商家和签约
+func CreateEtaBusinessAndContract(businessItem *EtaBusiness, contractItem *EtaBusinessContract) (err error) {
+	if businessItem == nil || contractItem == nil {
+		err = fmt.Errorf("item empty")
+		return
+	}
+
+	o := orm.NewOrm()
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	// 商家
+	businessId, e := tx.Insert(businessItem)
+	if e != nil {
+		err = fmt.Errorf("business insert err: %s", e.Error())
+		return
+	}
+	businessItem.EtaBusinessId = int(businessId)
+
+	// 签约
+	contractItem.EtaBusinessId = businessItem.EtaBusinessId
+	contractId, e := tx.Insert(contractItem)
+	if e != nil {
+		err = fmt.Errorf("contract insert err: %s", e.Error())
+		return
+	}
+
+	// 更新商家当前签约ID
+	businessItem.ContractId = int(contractId)
+	cols := []string{"ContractId"}
+	_, err = tx.Update(businessItem, cols...)
+	return
+}
+
+// EtaBusinessAddReq 新增商家请求体
+type EtaBusinessAddReq struct {
+	BusinessName     string `description:"商家名称"`
+	CreditCode       string `description:"社会统一信用码"`
+	RegionType       string `description:"所属区域:国内;海外"`
+	Province         string `description:"省份"`
+	City             string `description:"城市"`
+	SellerId         int    `description:"销售ID"`
+	SellerName       string `description:"销售名称"`
+	Leader           string `description:"决策人"`
+	IndustryId       int    `description:"行业ID"`
+	IndustryName     string `description:"行业名称"`
+	CapitalScale     string `description:"资金规模"`
+	ResearchTeamSize string `description:"研究团队规模"`
+	UserMax          int    `description:"用户上限"`
+	SigningTime      string `description:"签约时间"`
+	ExpiredTime      string `description:"到期时间"`
+	IsCheck          bool   `description:"是否只做校验而不实际新增(业务操作上基础信息和签约时间分成两个步骤了)"`
+}
+
+// EtaBusinessEditReq 编辑商家请求体
+type EtaBusinessEditReq struct {
+	EtaBusinessId    int    `description:"商家ID"`
+	Province         string `description:"省份"`
+	City             string `description:"城市"`
+	Leader           string `description:"决策人"`
+	IndustryId       int    `description:"行业ID"`
+	IndustryName     string `description:"行业名称"`
+	CapitalScale     string `description:"资金规模"`
+	ResearchTeamSize string `description:"研究团队规模"`
+	UserMax          int    `description:"用户上限"`
+}
+
+// EtaBusinessSigningReq 商家签约请求体
+type EtaBusinessSigningReq struct {
+	EtaBusinessId int    `description:"商家ID"`
+	SigningTime   string `description:"当前合约的签约时间"`
+	ExpiredTime   string `description:"当前合约的到期时间"`
+}
+
+// EtaBusinessEnableReq 禁启用商家请求体
+type EtaBusinessEnableReq struct {
+	EtaBusinessId int `description:"商家ID"`
+}
+
+// EtaBusinessMoveSellerReq 移动商家销售请求体
+type EtaBusinessMoveSellerReq struct {
+	EtaBusinessId int    `description:"商家ID"`
+	SellerId      int    `description:"销售ID"`
+	SellerName    string `description:"销售名称"`
+}
+
+// CreateEtaBusinessCode 生成ETA商家编码
+func CreateEtaBusinessCode() (code string, err error) {
+	var num int
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS num FROM eta_business WHERE create_time >= ? `
+	err = o.Raw(sql, time.Now().Format(utils.FormatDate)).QueryRow(&num)
+	if err != nil {
+		return
+	}
+	code = "E" + time.Now().Format("20060102") + fmt.Sprintf("%02d", num)
+	return
+}
+
+// EtaBusinessListResp 商家分页列表响应体
+type EtaBusinessListResp struct {
+	List   []*EtaBusinessItem `description:"商家列表数据"`
+	Paging *paging.PagingItem `description:"分页数据"`
+}
+
+// EtaBusinessItem ETA商家信息
+type EtaBusinessItem struct {
+	EtaBusinessId    int
+	BusinessName     string `description:"商家名称"`
+	BusinessCode     string `description:"商家编码"`
+	CreditCode       string `description:"社会统一信用码"`
+	RegionType       string `description:"所属区域:国内;海外"`
+	Province         string `description:"省份"`
+	City             string `description:"城市"`
+	Address          string `description:"商家地址"`
+	SellerId         int    `description:"销售ID"`
+	SellerName       string `description:"销售名称"`
+	Leader           string `description:"决策人"`
+	IndustryId       int    `description:"行业ID"`
+	IndustryName     string `description:"行业名称"`
+	CapitalScale     string `description:"资金规模"`
+	ResearchTeamSize string `description:"研究团队规模"`
+	UserMax          int    `description:"用户上限"`
+	SigningStatus    int    `description:"签约状态:1-首次签约;2-续约中;3-已终止"`
+	Enable           int    `description:"状态:0-禁用;1-启用"`
+	ContractId       int    `description:"当前合约ID"`
+	SigningTime      string `description:"当前合约的签约时间"`
+	ExpiredTime      string `description:"当前合约的到期时间"`
+	CreateTime       string `description:"创建时间"`
+	ModifyTime       string `description:"更新时间"`
+}

+ 123 - 0
models/eta_business/eta_business_contract.go

@@ -0,0 +1,123 @@
+package eta_business
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// EtaBusinessContract ETA商家合同表
+type EtaBusinessContract struct {
+	EtaBusinessContractId int       `orm:"column(eta_business_contract_id);pk"`
+	EtaBusinessId         int       `description:"ETA商家ID"`
+	SigningTime           time.Time `description:"签约时间"`
+	ExpiredTime           time.Time `description:"到期时间"`
+	IsFirst               int       `description:"是否为首份签约"`
+	CreateTime            time.Time `description:"创建时间"`
+	ModifyTime            time.Time `description:"更新时间"`
+}
+
+func (m *EtaBusinessContract) TableName() string {
+	return "eta_business_contract"
+}
+
+func (m *EtaBusinessContract) PrimaryId() string {
+	return EtaBusinessContractColumns.EtaBusinessContractId
+}
+
+var EtaBusinessContractColumns = struct {
+	EtaBusinessContractId string
+	EtaBusinessId         string
+	SigningTime           string
+	ExpiredTime           string
+	IsFirst               string
+	CreateTime            string
+	ModifyTime            string
+}{
+	EtaBusinessContractId: "eta_business_contract_id",
+	EtaBusinessId:         "eta_business_id",
+	SigningTime:           "signing_time",
+	ExpiredTime:           "expired_time",
+	IsFirst:               "is_first",
+	CreateTime:            "create_time",
+	ModifyTime:            "modify_time",
+}
+
+func (m *EtaBusinessContract) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.EtaBusinessContractId = int(id)
+	return
+}
+
+func (m *EtaBusinessContract) CreateMulti(items []*EtaBusinessContract) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *EtaBusinessContract) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *EtaBusinessContract) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.EtaBusinessContractId).Exec()
+	return
+}
+
+func (m *EtaBusinessContract) GetItemById(id int) (item *EtaBusinessContract, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusinessContract) GetItemByCondition(condition string, pars []interface{}) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&m)
+	return
+}
+
+func (m *EtaBusinessContract) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *EtaBusinessContract) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*EtaBusinessContract, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// EtaBusinessContractItem 商家签约信息
+type EtaBusinessContractItem struct {
+	EtaBusinessContractId int
+	EtaBusinessId         int    `description:"ETA商家ID"`
+	SigningTime           string `description:"签约时间"`
+	ExpiredTime           string `description:"到期时间"`
+	ExpireDay             string `description:"到期天数"`
+	Using                 bool   `description:"是否当前合约"`
+}

+ 147 - 0
models/eta_business/eta_business_menu.go

@@ -0,0 +1,147 @@
+package eta_business
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// EtaBusinessMenu ETA商家基础菜单表
+type EtaBusinessMenu struct {
+	MenuId       int       `orm:"column(menu_id);pk"`
+	ParentId     int       `description:"父级菜单ID"`
+	Name         string    `description:"菜单名称或者按钮名称"`
+	RootId       int       `description:"顶层菜单ID"`
+	Sort         string    `description:"排序"`
+	Path         string    `description:"路由地址"`
+	PathName     string    `description:"路由名称"`
+	IconPath     string    `description:"菜单图标地址"`
+	Component    int       `description:"组件路径"`
+	Hidden       int       `description:"是否隐藏:1-隐藏 0-显示"`
+	HiddenLayout int       `description:"是否隐藏layout:1-隐藏 0-显示"`
+	Level        int       `description:"菜单等级:1-2-3"`
+	IsLevel      int       `description:"是否为多级菜单:1,只有一级;2,有多级"`
+	LevelPath    string    `description:"兼容以前menu表的字段"`
+	MenuType     int       `description:"菜单类型: 0-菜单; 1-按钮; 2-字段(需要特殊处理)"`
+	ButtonCode   string    `description:"按钮/菜单唯一标识"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"更新时间"`
+}
+
+func (m *EtaBusinessMenu) TableName() string {
+	return "eta_business_menu"
+}
+
+func (m *EtaBusinessMenu) PrimaryId() string {
+	return "menu_id"
+}
+
+func (m *EtaBusinessMenu) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.MenuId = int(id)
+	return
+}
+
+func (m *EtaBusinessMenu) CreateMulti(items []*EtaBusinessMenu) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *EtaBusinessMenu) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *EtaBusinessMenu) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.MenuId).Exec()
+	return
+}
+
+func (m *EtaBusinessMenu) GetItemById(id int) (item *EtaBusinessMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusinessMenu) GetItemByCondition(condition string, pars []interface{}) (item *EtaBusinessMenu, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusinessMenu) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *EtaBusinessMenu) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*EtaBusinessMenu, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *EtaBusinessMenu) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*EtaBusinessMenu, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// EtaBusinessMenuListResp ETA商家菜单列表响应体
+type EtaBusinessMenuListResp struct {
+	ChoiceList     []int                  `description:"已选菜单"`
+	HalfChoiceList []int                  `description:"半选菜单-方便前端回显用的"`
+	List           []*EtaBusinessMenuItem `description:"菜单列表"`
+}
+
+// EtaBusinessMenuItem ETA商家菜单
+type EtaBusinessMenuItem struct {
+	MenuId       int
+	ParentId     int                    `description:"父级菜单ID"`
+	Name         string                 `description:"菜单名称或者按钮名称"`
+	RootId       int                    `description:"顶层菜单ID"`
+	Sort         string                 `description:"排序"`
+	Path         string                 `description:"路由地址"`
+	PathName     string                 `description:"路由名称"`
+	IconPath     string                 `description:"菜单图标地址"`
+	Component    int                    `description:"组件路径"`
+	Hidden       int                    `description:"是否隐藏:1-隐藏 0-显示"`
+	HiddenLayout int                    `description:"是否隐藏layout:1-隐藏 0-显示"`
+	Level        int                    `description:"菜单等级:1-2-3"`
+	MenuType     int                    `description:"菜单类型: 0-菜单; 1-按钮; 2-字段(需要特殊处理)"`
+	ButtonCode   string                 `description:"按钮/菜单唯一标识"`
+	Children     []*EtaBusinessMenuItem `description:"子菜单"`
+}

+ 133 - 0
models/eta_business/eta_business_menu_relate.go

@@ -0,0 +1,133 @@
+package eta_business
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+)
+
+// EtaBusinessMenuRelate ETA商家菜单关联表
+type EtaBusinessMenuRelate struct {
+	Id            int `orm:"column(id);pk"`
+	EtaBusinessId int `description:"商家ID"`
+	MenuId        int `description:"菜单ID"`
+	Type          int `description:"类型: 0-全选; 1-半选(此字段仅供前端回显做区分)"`
+}
+
+func (m *EtaBusinessMenuRelate) TableName() string {
+	return "eta_business_menu_relate"
+}
+
+func (m *EtaBusinessMenuRelate) PrimaryId() string {
+	return "id"
+}
+
+func (m *EtaBusinessMenuRelate) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.MenuId = int(id)
+	return
+}
+
+func (m *EtaBusinessMenuRelate) CreateMulti(businessId int, items []*EtaBusinessMenuRelate) (err error) {
+	if businessId == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	tx, err := o.Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		if err != nil {
+			_ = tx.Rollback()
+			return
+		}
+		_ = tx.Commit()
+	}()
+
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE eta_business_id = ?`, m.TableName())
+	_, err = tx.Raw(sql, businessId).Exec()
+	if err != nil {
+		return
+	}
+
+	if len(items) > 0 {
+		_, err = tx.InsertMulti(len(items), items)
+	}
+	return
+}
+
+func (m *EtaBusinessMenuRelate) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *EtaBusinessMenuRelate) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.MenuId).Exec()
+	return
+}
+
+func (m *EtaBusinessMenuRelate) GetItemById(id int) (item *EtaBusinessMenuRelate, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusinessMenuRelate) GetItemByCondition(condition string, pars []interface{}) (item *EtaBusinessMenuRelate, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusinessMenuRelate) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *EtaBusinessMenuRelate) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*EtaBusinessMenuRelate, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *EtaBusinessMenuRelate) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*EtaBusinessMenuRelate, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := ``
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// EtaBusinessMenuRelateSaveReq 保存商家菜单关联
+type EtaBusinessMenuRelateSaveReq struct {
+	EtaBusinessId int   `description:"商家ID"`
+	MenuIds       []int `description:"菜单IDs"`
+	HalfMenuIds   []int `description:"半选菜单IDs-仅供前端回显用的"`
+}

+ 136 - 0
models/eta_business/eta_business_operation_record.go

@@ -0,0 +1,136 @@
+package eta_business
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"strings"
+	"time"
+)
+
+// 操作类型
+const (
+	EtaBusinessOperationTypeAdd = iota + 1
+	EtaBusinessOperationTypeEdit
+	EtaBusinessOperationTypeDisable
+	EtaBusinessOperationTypeEnable
+	EtaBusinessOperationTypeMoveSeller
+	EtaBusinessOperationTypeRenewalContract
+)
+
+// EtaBusinessOperationRecord ETA商家操作日志表
+type EtaBusinessOperationRecord struct {
+	Id              int       `orm:"column(id);pk"`
+	EtaBusinessId   int       `description:"ETA商家ID"`
+	SellerId        int       `description:"操作时所对应的销售ID"`
+	SysUserId       int       `description:"操作人ID"`
+	SysRealName     string    `description:"操作人姓名"`
+	OperationType   int       `description:"操作类型:1-新增;2-编辑;3-禁用;4-启用;5-移动销售;6-添加续约"`
+	OperationRemark string    `description:"操作内容"`
+	CreateTime      time.Time `description:"创建时间"`
+}
+
+func (m *EtaBusinessOperationRecord) TableName() string {
+	return "eta_business_operation_record"
+}
+
+func (m *EtaBusinessOperationRecord) PrimaryId() string {
+	return EtaBusinessOperationRecordColumns.Id
+}
+
+var EtaBusinessOperationRecordColumns = struct {
+	Id              string
+	EtaBusinessId   string
+	SellerId        string
+	SysUserId       string
+	SysRealName     string
+	OperationType   string
+	OperationRemark string
+	CreateTime      string
+}{
+	Id:              "id",
+	EtaBusinessId:   "eta_business_id",
+	SellerId:        "seller_id",
+	SysUserId:       "sys_user_id",
+	SysRealName:     "sys_real_name",
+	OperationType:   "operation_type",
+	OperationRemark: "operation_remark",
+	CreateTime:      "create_time",
+}
+
+func (m *EtaBusinessOperationRecord) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.Id = int(id)
+	return
+}
+
+func (m *EtaBusinessOperationRecord) CreateMulti(items []*EtaBusinessOperationRecord) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *EtaBusinessOperationRecord) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *EtaBusinessOperationRecord) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.Id).Exec()
+	return
+}
+
+func (m *EtaBusinessOperationRecord) GetItemById(id int) (item *EtaBusinessOperationRecord, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *EtaBusinessOperationRecord) GetItemByCondition(condition string, pars []interface{}) (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&m)
+	return
+}
+
+func (m *EtaBusinessOperationRecord) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *EtaBusinessOperationRecord) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*EtaBusinessOperationRecord, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// EtaBusinessOperationRecordItem ETA商家操作日志信息
+type EtaBusinessOperationRecordItem struct {
+	EtaBusinessId   int    `description:"ETA商家ID"`
+	SysUserId       int    `description:"操作人ID"`
+	SysRealName     string `description:"操作人姓名"`
+	OperationType   int    `description:"操作类型:1-新增;2-编辑;3-禁用;4-启用;5-移动销售;6-添加续约"`
+	OperationRemark string `description:"操作内容"`
+	CreateTime      string `description:"创建时间"`
+}

+ 144 - 0
models/eta_version_update_log.go

@@ -0,0 +1,144 @@
+package models
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"strings"
+	"time"
+)
+
+// EtaVersionUpdateLog ETA版本更新日志表
+type EtaVersionUpdateLog struct {
+	Id         int       `orm:"column(id);pk"`
+	Version    string    `description:"版本号"`
+	Content    string    `description:"更新内容"`
+	UpdateDate time.Time `description:"更新日期"`
+	CreateTime time.Time
+	ModifyTime time.Time
+}
+
+func (m *EtaVersionUpdateLog) TableName() string {
+	return "eta_version_update_log"
+}
+
+func (m *EtaVersionUpdateLog) PrimaryId() string {
+	return "id"
+}
+
+func (m *EtaVersionUpdateLog) Create() (err error) {
+	o := orm.NewOrm()
+	id, err := o.Insert(m)
+	if err != nil {
+		return
+	}
+	m.Id = int(id)
+	return
+}
+
+func (m *EtaVersionUpdateLog) CreateMulti(items []*EtaVersionUpdateLog) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	o := orm.NewOrm()
+	_, err = o.InsertMulti(len(items), items)
+	return
+}
+
+func (m *EtaVersionUpdateLog) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(m, cols...)
+	return
+}
+
+func (m *EtaVersionUpdateLog) Del() (err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	_, err = o.Raw(sql, m.Id).Exec()
+	return
+}
+
+func (m *EtaVersionUpdateLog) GetItemById(id int) (item *EtaVersionUpdateLog, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.PrimaryId())
+	err = o.Raw(sql, id).QueryRow(&item)
+	return
+}
+
+func (m *EtaVersionUpdateLog) GetItemByCondition(condition string, pars []interface{}) (item *EtaVersionUpdateLog, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+func (m *EtaVersionUpdateLog) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func (m *EtaVersionUpdateLog) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*EtaVersionUpdateLog, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func (m *EtaVersionUpdateLog) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*EtaVersionUpdateLog, err error) {
+	o := orm.NewOrm()
+	fields := strings.Join(fieldArr, ",")
+	if len(fieldArr) == 0 {
+		fields = `*`
+	}
+	order := `ORDER BY create_time DESC`
+	if orderRule != "" {
+		order = ` ORDER BY ` + orderRule
+	}
+	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// EtaVersionUpdateLogItem 更新日志信息
+type EtaVersionUpdateLogItem struct {
+	Id         int
+	Version    string `description:"版本号"`
+	Content    string `description:"更新内容"`
+	UpdateDate string `description:"更新日期"`
+	CreateTime string
+	ModifyTime string
+}
+
+// EtaVersionUpdateLogListResp 更新日志列表响应体
+type EtaVersionUpdateLogListResp struct {
+	List   []*EtaVersionUpdateLogItem
+	Paging *paging.PagingItem
+}
+
+// EtaVersionUpdateLogAddReq 新增更新日志请求体
+type EtaVersionUpdateLogAddReq struct {
+	Version    string `description:"版本号"`
+	Content    string `description:"更新内容"`
+	UpdateDate string `description:"更新日期"`
+}
+
+// EtaVersionUpdateLogEditReq 编辑更新日志请求体
+type EtaVersionUpdateLogEditReq struct {
+	Id int
+	EtaVersionUpdateLogAddReq
+}
+
+// EtaVersionUpdateLogDelReq 删除更新日志请求体
+type EtaVersionUpdateLogDelReq struct {
+	Id int
+}

+ 248 - 0
models/help_doc/classify.go

@@ -0,0 +1,248 @@
+package help_doc
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type HelpDocClassify struct {
+	ClassifyId      int       `orm:"column(classify_id);pk"`
+	ClassifyName    string    `description:"分类名称"`
+	ParentId        int       `description:"父级id"`
+	CreateTime      time.Time `description:"创建时间"`
+	ModifyTime      time.Time `description:"修改时间"`
+	SysUserId       int       `description:"创建人id"`
+	SysUserRealName string    `description:"创建人姓名"`
+	Level           int       `description:"层级"`
+	Sort            int       `description:"排序字段,越小越靠前,默认值:10"`
+}
+
+func AddHelpDocClassify(item *HelpDocClassify) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type AddHelpDocClassifyReq struct {
+	HelpDocClassifyName string `description:"分类名称"`
+	ParentId            int    `description:"父级id,第一级传0"`
+	Level               int    `description:"层级,第一级传0,其余传上一级的层级"`
+}
+
+func GetHelpDocClassifyCount(HelpDocClassifyName string, parentId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM help_doc_classify WHERE parent_id=? AND classify_name=? `
+	err = o.Raw(sql, parentId, HelpDocClassifyName).QueryRow(&count)
+	return
+}
+
+type EditHelpDocClassifyReq struct {
+	HelpDocClassifyName string `description:"分类名称"`
+	HelpDocClassifyId   int    `description:"分类id"`
+}
+
+func GetHelpDocClassifyById(classifyId int) (item *HelpDocClassify, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM help_doc_classify WHERE classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&item)
+	return
+}
+
+func GetHelpDocClassifyCountById(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT count(1) AS count FROM help_doc_classify WHERE classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+func EditHelpDocClassify(classifyId int, HelpDocClassifyName string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE help_doc_classify SET classify_name=?, modify_time=NOW() WHERE classify_id=? `
+	_, err = o.Raw(sql, HelpDocClassifyName, classifyId).Exec()
+	return
+}
+
+// GetHelpDocClassifyByParentId
+func GetHelpDocClassifyByParentId(parentId int, keyWord string) (items []HelpDocClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ``
+	if keyWord != "" {
+		sql = ` SELECT * FROM help_doc_classify WHERE parent_id=? AND (classify_name LIKE '%` + keyWord + `%' ) order by sort asc,classify_id asc`
+	} else {
+		sql = ` SELECT * FROM help_doc_classify WHERE parent_id=? order by sort asc,classify_id asc`
+	}
+	_, err = o.Raw(sql, parentId).QueryRows(&items)
+	return
+}
+
+// GetHelpDocClassifyAll
+func GetHelpDocClassifyAll(keyWord string) (items []*HelpDocClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ``
+	if keyWord != "" {
+		sql = ` SELECT * FROM help_doc_classify WHERE parent_id<>0 AND (classify_name LIKE '%` + keyWord + `%' ) order by sort asc,classify_id asc`
+	} else {
+		sql = ` SELECT * FROM help_doc_classify WHERE parent_id<>0 order by sort asc,classify_id asc`
+	}
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type HelpDocClassifyItems struct {
+	ClassifyId         int `description:"分类id"`
+	ClassifyName       string
+	ParentId           int
+	Level              int    `description:"层级"`
+	Sort               int    `description:"排序字段,越小越靠前,默认值:10"`
+	SysUserId          int    `description:"创建人id"`
+	SysUserRealName    string `description:"创建人姓名"`
+	VisibleBusinessIds string
+	Disabled           bool `description:"是否能选 true不能 false可以"`
+	Children           []*HelpDocClassifyItems
+}
+
+type HelpDocClassifyListResp struct {
+	AllNodes      []*HelpDocClassifyItems
+	TwoLevelNodes []*HelpDocClassifyItems
+}
+
+type HelpDocClassifyDeleteCheckResp struct {
+	DeleteStatus int    `description:"检测状态:0:默认值,如果为0,继续走其他校验,1:该分类下关联不可删除,2:确认删除当前目录及包含的子目录吗"`
+	TipsMsg      string `description:"提示信息"`
+}
+
+type HelpDocClassifyDeleteCheckReq struct {
+	HelpDocClassifyId int `description:"分类id"`
+	ChartInfoId       int `description:"指标id"`
+}
+
+func GetHelpDocClassifyByCondition(condition string, pars []interface{}) (item *HelpDocClassify, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM help_doc_classify WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&item)
+	return
+}
+
+// MoveHelpDocClassifyReq 移动分类请求参数
+type MoveHelpDocClassifyReq struct {
+	ClassifyId       int `description:"分类id"`
+	ParentClassifyId int `description:"父级分类id"`
+	PrevClassifyId   int `description:"上一个兄弟节点分类id"`
+	NextClassifyId   int `description:"下一个兄弟节点分类id"`
+}
+
+// GetFirstHelpDocClassifyByParentId 获取当前父级分类下的排序第一条的数据
+func GetFirstHelpDocClassifyByParentId(parentId int) (item *HelpDocClassify, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM help_doc_classify WHERE parent_id=? order by sort asc,classify_id asc limit 1`
+	err = o.Raw(sql, parentId).QueryRow(&item)
+	return
+}
+
+// UpdateHelpDocClassifySortByParentId 根据父类id更新排序
+func UpdateHelpDocClassifySortByParentId(parentId, classifyId, nowSort int, updateSort string) (err error) {
+	o := orm.NewOrm()
+	sql := ` update help_doc_classify set sort = ` + updateSort + ` WHERE parent_id=? and sort > ? `
+	if classifyId > 0 {
+		sql += ` or ( classify_id > ` + fmt.Sprint(classifyId) + ` and sort= ` + fmt.Sprint(nowSort) + `)`
+	}
+	_, err = o.Raw(sql, parentId, nowSort).Exec()
+	return
+}
+
+// Update 更新分类基础信息
+func (HelpDocClassify *HelpDocClassify) Update(cols []string) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Update(HelpDocClassify, cols...)
+	return
+}
+
+// GetHelpDocClassifyMaxSort 获取分类下最大的排序数
+func GetHelpDocClassifyMaxSort(parentId int) (sort int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT Max(sort) AS sort FROM help_doc_classify WHERE parent_id=?  `
+	err = o.Raw(sql, parentId).QueryRow(&sort)
+	return
+}
+
+type HelpDocClassifyView struct {
+	HelpDocClassifyId   int    `orm:"column(classify_id);pk"`
+	HelpDocClassifyName string `description:"分类名称"`
+	ParentId            int    `description:"父级id"`
+}
+
+func EditHelpDocClassifySysUser(classifyId, sysUserId int, HelpDocClassifyName string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE help_doc_classify SET sys_user_id=?,sys_user_real_name=?,modify_time=NOW() WHERE parent_id=?  AND level=3 `
+	_, err = o.Raw(sql, sysUserId, HelpDocClassifyName, classifyId).Exec()
+	return
+}
+
+func GetHelpDocClassifyChildCounts(parentId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM help_doc_classify WHERE parent_id=? `
+	err = o.Raw(sql, parentId).QueryRow(&count)
+	return
+}
+
+func GetHelpDocCounts(classifyId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM help_doc WHERE classify_id=? `
+	err = o.Raw(sql, classifyId).QueryRow(&count)
+	return
+}
+
+// DeleteHelpDocClassify 删除分类
+func DeleteHelpDocClassify(classifyId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM help_doc_classify WHERE classify_id =? `
+	_, err = o.Raw(sql, classifyId).Exec()
+	return
+}
+
+// MoveClassifyReq 移动分类请求参数
+type MoveClassifyReq struct {
+	ClassifyId       int `description:"分类id"`
+	ParentClassifyId int `description:"父级分类id"`
+	PrevClassifyId   int `description:"上一个兄弟节点分类id"`
+	NextClassifyId   int `description:"下一个兄弟节点分类id"`
+}
+
+// GetHelpDocClassifyLevel
+func GetHelpDocClassifyLevel() (items []*HelpDocClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := ``
+	sql = ` SELECT * FROM help_doc_classify WHERE level IN (1,2) `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type EditHelpDocClassifyVisibleReq struct {
+	HelpDocClassifyId  int `description:"分类id"`
+	VisibleBusinessIds string
+}
+
+func EditHelpDocClassifyVisible(classifyId int, visibleBusinessIds string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE help_doc_classify SET visible_business_ids=?, modify_time=NOW() WHERE classify_id=? `
+	_, err = o.Raw(sql, visibleBusinessIds, classifyId).Exec()
+	return
+}
+
+func GetAllHelpDocClassify() (items []*HelpDocClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM help_doc_classify `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+func GetAllHelpDocClassifyByKeyword(keyword string) (items []*HelpDocClassifyItems, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM help_doc_classify WHERE classify_name LIKE '%` + keyword + `%' `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 192 - 0
models/help_doc/help_doc.go

@@ -0,0 +1,192 @@
+package help_doc
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"time"
+)
+
+type HelpDoc struct {
+	Id            int       `orm:"column(id);pk"`
+	ClassifyId    int       // 分类id
+	Title         string    // 标题
+	Author        string    // 作者
+	CreateTime    time.Time // 创建时间
+	ModifyTime    time.Time // 修改时间
+	Status        int       // 1:未发布,2:已发布
+	PublishTime   time.Time // 发布时间
+	Content       string    // 内容
+	AdminId       int       // 创建人
+	AdminRealName string    // 创建人姓名
+	Anchor        string    // 锚点
+	Recommend     string    // 推荐
+}
+
+type HelpDocItem struct {
+	Id            int    `orm:"column(id);pk"`
+	ClassifyId    int    // 分类id
+	Title         string // 标题
+	Author        string // 作者
+	CreateTime    string // 创建时间
+	ModifyTime    string // 修改时间
+	Status        int    // 1:未发布,2:已发布
+	PublishTime   string // 发布时间
+	Content       string // 内容
+	AdminId       int    // 创建人
+	AdminRealName string // 创建人姓名
+	Anchor        string // 锚点
+	Recommend     string // 推荐
+}
+
+func EditHelpDocClassifyId(classifyId int, classifyName string) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE help_doc SET classify_name=?,modify_time=NOW() WHERE classify_id=? `
+	_, err = o.Raw(sql, classifyId, classifyName).Exec()
+	return
+}
+
+type AddHelpDocReq struct {
+	Id            int64  `description:"文章id"`
+	ClassifyId    int    `description:"分类id"`
+	Title         string `description:"标题"`
+	Author        string `description:"作者"`
+	Status        int    `description:"状态:1:未发布,2:已发布"`
+	Content       string `description:"内容"`
+	AnchorData    []AnchorList
+	RecommendData []RecommendList
+}
+
+type AnchorList struct {
+	AnchorId   string
+	Anchor     string
+	AnchorName string
+	Child      []AnchorList
+}
+
+type RecommendList struct {
+	Name string
+	Url  string
+}
+
+func AddHelpDoc(item *HelpDoc) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type EditHelpDocReq struct {
+	Id            int64  `description:"文章id"`
+	ClassifyId    int    `description:"分类id"`
+	Title         string `description:"标题"`
+	Author        string `description:"作者"`
+	Status        int    `description:"状态:1:未发布,2:已发布"`
+	Content       string `description:"内容"`
+	AnchorData    []AnchorList
+	RecommendData []RecommendList
+}
+
+func EditHelpDoc(item *HelpDoc, reportId int64) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE help_doc
+			SET
+			  classify_id =?,
+			  title = ?,
+			  author = ?,
+			  content = ?,
+			  modify_time = ?,
+			  status = ?,
+			  publish_time = ?,
+			  anchor = ?,
+			  recommend = ? 
+			WHERE id = ? `
+	_, err = o.Raw(sql, item.ClassifyId, item.Title, item.Author, item.Content, item.ModifyTime,
+		item.Status, item.PublishTime, item.Anchor, item.Recommend, reportId).Exec()
+	return
+}
+
+func GetHelpDocById(docId int) (item *HelpDocItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM help_doc WHERE id=?`
+	err = o.Raw(sql, docId).QueryRow(&item)
+	return
+}
+
+type HelpDocResp struct {
+	Id            int             `orm:"column(id);pk"`
+	ClassifyId    int             // 分类id
+	ClassifyName  string          // 分类路径
+	Title         string          // 标题
+	Author        string          // 作者
+	CreateTime    string          // 创建时间
+	ModifyTime    string          // 修改时间
+	Status        int             // 1:未发布,2:已发布
+	PublishTime   string          // 发布时间
+	Content       string          // 内容
+	AdminId       int             // 创建人
+	AdminRealName string          // 创建人姓名
+	Anchor        []AnchorList    // 锚点
+	Recommend     []RecommendList // 推荐
+}
+
+func GetHelpDocListCount(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM help_doc WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql, pars).QueryRow(&count)
+	return
+}
+
+func GetHelpDocList(condition string, pars []interface{}, startSize, pageSize int) (items []*HelpDocItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM help_doc WHERE 1=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += `ORDER BY create_time DESC LIMIT ?,?`
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+type HelpDocListResp struct {
+	List         []*HelpDocResp
+	ClassifyName string
+	Paging       *paging.PagingItem `description:"分页数据"`
+}
+
+type PublishReq struct {
+	DocId  int
+	Status int `description:"状态:1:未发布,2:已发布"`
+}
+
+// 发布报告
+func PublishHelpDocById(reportId, status int) (err error) {
+	o := orm.NewOrm()
+	sql := ``
+	if status == 1 {
+		sql = `UPDATE help_doc SET status=1,publish_time=NULL,modify_time=NOW() WHERE id = ? `
+	} else {
+		sql = `UPDATE help_doc SET status=2,publish_time=now(),modify_time=NOW() WHERE id = ? `
+	}
+	_, err = o.Raw(sql, reportId).Exec()
+	return
+}
+
+type DeleteReq struct {
+	DocId int `description:"id"`
+}
+
+func DeleteHelpDoc(reportIds int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM help_doc WHERE id =? `
+	_, err = o.Raw(sql, reportIds).Exec()
+	return
+}
+
+func GetAllHelpDoc() (items []*HelpDocItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM help_doc `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 4 - 1
models/yb/apply_record.go

@@ -49,7 +49,7 @@ type ApplyList struct {
 	IsMove          int       `description:"是否已移动"`
 	Source          int       `description:"申请来源 1-我的 2-活动 3-图库"`
 	SourceAgent     int       `description:"申请入口来源,1:小程序,2:pc"`
-	FromPage        string    `description:"申请来源具体页面`
+	FromPage        string    `description:"申请来源具体页面"`
 	CreateTime      time.Time `description:"申请时间"`
 }
 
@@ -175,6 +175,7 @@ WHERE
 	AND ( a.mobile <> '' OR a.email <> '' ) 
 	AND ( c.create_platform <> 4 OR c.create_platform IS NULL )
     AND ((y.apply_record_id > 0 and y.create_time > ?) OR (y.apply_record_id is null AND a.created_time > ?) )
+	AND ( y.source > 0 )
 `
 	sql += condition
 	sql += ` GROUP BY a.user_id ORDER BY last_time desc`
@@ -205,6 +206,7 @@ WHERE
 	AND ( a.mobile <> '' OR a.email <> '' ) 
 	AND ( c.create_platform <> 4 OR c.create_platform IS NULL )
     AND ((y.apply_record_id > 0 and y.create_time > ?) OR (y.apply_record_id is null AND a.created_time > ?) )
+	AND ( y.source > 0 )
 `
 	pars = append(pars, startTime)
 	pars = append(pars, startTime)
@@ -259,6 +261,7 @@ WHERE
 	AND ( a.mobile <> '' OR a.email <> '' ) 
 	AND ( c.create_platform <> 4 OR c.create_platform IS NULL )
     AND ((y.apply_record_id > 0 and y.create_time > ?) OR (y.apply_record_id is null AND a.created_time > ?) )
+	AND ( y.source > 0 )
 `
 	sql += condition
 	sql += ` GROUP BY a.user_id ORDER BY last_time desc`

+ 243 - 0
routers/commentsRouter.go

@@ -6469,6 +6469,204 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "ContractList",
+            Router: `/contract_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "Enable",
+            Router: `/enable`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "MoveSeller",
+            Router: `/move_seller`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "OperateRecordList",
+            Router: `/operate_record_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "PageList",
+            Router: `/page_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessController"],
+        beego.ControllerComments{
+            Method: "Signing",
+            Router: `/signing`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessMenuController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessMenuController"],
+        beego.ControllerComments{
+            Method: "List",
+            Router: `/menu/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessMenuController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/eta_business:EtaBusinessMenuController"],
+        beego.ControllerComments{
+            Method: "SaveRelate",
+            Router: `/menu/relate/save`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"],
+        beego.ControllerComments{
+            Method: "AddClassify",
+            Router: `/classify/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"],
+        beego.ControllerComments{
+            Method: "DelClassify",
+            Router: `/classify/delete`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"],
+        beego.ControllerComments{
+            Method: "EditClassify",
+            Router: `/classify/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"],
+        beego.ControllerComments{
+            Method: "ListClassify",
+            Router: `/classify/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"],
+        beego.ControllerComments{
+            Method: "ClassifyMove",
+            Router: `/classify/move`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocClassifyController"],
+        beego.ControllerComments{
+            Method: "EditClassifyVisible",
+            Router: `/classify/visible/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"],
+        beego.ControllerComments{
+            Method: "Delete",
+            Router: `/delete`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"],
+        beego.ControllerComments{
+            Method: "Detail",
+            Router: `/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"],
+        beego.ControllerComments{
+            Method: "ListReport",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/help_doc:HelpDocController"],
+        beego.ControllerComments{
+            Method: "PublishReport",
+            Router: `/publish`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers/roadshow:CalendarController"],
         beego.ControllerComments{
             Method: "Accept",
@@ -8818,6 +9016,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:CompanyTodoController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:CompanyTodoController"],
+        beego.ControllerComments{
+            Method: "CompanyActivitySpecialPointsBill",
+            Router: `/company/activity/special/points/bill`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:CompanyTodoController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:CompanyTodoController"],
         beego.ControllerComments{
             Method: "CompanyTryOutDayList",
@@ -9277,6 +9484,42 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"],
+        beego.ControllerComments{
+            Method: "Add",
+            Router: `/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"],
+        beego.ControllerComments{
+            Method: "Del",
+            Router: `/del`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"],
+        beego.ControllerComments{
+            Method: "Edit",
+            Router: `/edit`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:EtaVersionUpdateLogController"],
+        beego.ControllerComments{
+            Method: "PageList",
+            Router: `/page_list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:FullCompanyController"] = append(beego.GlobalControllerRouter["hongze/hz_crm_api/controllers:FullCompanyController"],
         beego.ControllerComments{
             Method: "Detail",

+ 19 - 0
routers/router.go

@@ -21,6 +21,8 @@ import (
 	"hongze/hz_crm_api/controllers/data_manage/line_feature"
 	"hongze/hz_crm_api/controllers/data_manage/supply_analysis"
 	"hongze/hz_crm_api/controllers/english_report"
+	"hongze/hz_crm_api/controllers/eta_business"
+	"hongze/hz_crm_api/controllers/help_doc"
 	"hongze/hz_crm_api/controllers/roadshow"
 	"hongze/hz_crm_api/controllers/seal"
 	"hongze/hz_crm_api/controllers/yb"
@@ -299,6 +301,23 @@ func init() {
 				&english_report.EnPermissionController{},
 			),
 		),
+		web.NSNamespace("/eta_business",
+			web.NSInclude(
+				&eta_business.EtaBusinessController{},
+				&eta_business.EtaBusinessMenuController{},
+			),
+		),
+		web.NSNamespace("/eta_version_update_log",
+			web.NSInclude(
+				&controllers.EtaVersionUpdateLogController{},
+			),
+		),
+		web.NSNamespace("/help_doc",
+			web.NSInclude(
+				&help_doc.HelpDocClassifyController{},
+				&help_doc.HelpDocController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 24 - 0
services/company_apply/company_approval.go

@@ -391,6 +391,29 @@ func Approved(approvalRecord *contract.ContractApprovalRecord, opUser *system.Ad
 				// 处理权益客户的身份信息()
 				cygxService.UpdateCygxCompanyUserType(recordInfo.CompanyContractId)
 
+				if recordInfo.ApplyMethod == 1{
+					//获取合同信息
+					contractInfo, tmpErr := company.GetCompanyContractDetail(recordInfo.CompanyId, recordInfo.ProductId, recordInfo.CompanyContractId)
+					if tmpErr != nil {
+						err = errors.New(fmt.Sprint("待审批信息不存在,CompanyId:", recordInfo.CompanyId, ";productId:", recordInfo.ProductId, ";Err:"+tmpErr.Error()))
+						return
+					}
+					if contractInfo == nil {
+						err = errors.New(fmt.Sprint("待审批信息不存在,CompanyId:", recordInfo.CompanyId, ";productId:", recordInfo.ProductId))
+						return
+					}
+
+					//格式化合同开始时间
+					contractStartDate, tmpErr := time.Parse(utils.FormatDate, contractInfo.StartDate)
+					if tmpErr != nil {
+						err = errors.New("合同开始时间转换失败,Err:" + tmpErr.Error())
+						return
+					}
+					if time.Now().After(contractStartDate) {
+						cygxService.ActivitySpecialCompanyApproval(recordInfo.CompanyId, companyInfo.CompanyName) //审批通过的时候专项调研次数更新
+					}
+				}
+
 				//权益销售客户申请转正后,消息群发给所有销售
 				services.AddCompanyApprovalMessageRai(recordInfo.CompanyId, recordInfo.CompanyContractId, recordInfo.ApplyRealName, companyInfo.CompanyName)
 
@@ -398,6 +421,7 @@ func Approved(approvalRecord *contract.ContractApprovalRecord, opUser *system.Ad
 				services.AddCompanyApprovalMessageWangYang(recordInfo.CompanyId, recordInfo.CompanyContractId, recordInfo.ApplyRealName, companyInfo.CompanyName)
 
 				go cygxService.YanXuanCompanyApproval(recordInfo.CompanyId) //研选审批通过的时候研选扣点更新
+
 			}
 		}()
 	} else {

+ 6 - 0
services/company_approval_message.go

@@ -212,6 +212,9 @@ func AddCompanyApprovalMessageRai(companyId, companyContractId int, applyRealNam
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		return err
 	}
+	if len(openIdList) == 0 {
+		return
+	}
 	go SendWxMsgWithRaiSell(first, keyword1, keyword2, keyword3, keyword4, openIdList)
 	return
 }
@@ -246,6 +249,9 @@ func AddCompanyApprovalMessageWangYang(companyId, companyContractId int, applyRe
 	if err != nil && err.Error() != utils.ErrNoRow() {
 		return err
 	}
+	if len(openIdList) == 0 {
+		return
+	}
 	go SendWxMsgWithRaiWangYang(keyword1, keyword2, keyword3, keyword4, openIdList)
 	return
 }

+ 11 - 7
services/cygx/acitvity.go

@@ -526,8 +526,12 @@ func ActivityBodyAnalysis(body string, activeState int, req cygx.ActivityRep) (i
 
 	//活动地址,活动地点,地点,地址,办会地点,办会地址。对地址字眼进行替换,对上述字段兼容做内容解析
 	body = strings.Replace(body, "活动地点:", "活动地址:", -1)
-	body = strings.Replace(body, "地点:", "活动地址:", -1)
-	body = strings.Replace(body, "地址:", "活动地址:", -1)
+	if !strings.Contains(body, "活动地点:") && !strings.Contains(body, "办会地点:") {
+		body = strings.Replace(body, "地点:", "活动地址:", -1)
+	}
+	if !strings.Contains(body, "办会地址:") && !strings.Contains(body, "活动地址:") {
+		body = strings.Replace(body, "地址:", "活动地址:", -1)
+	}
 	body = strings.Replace(body, "办会地点:", "活动地址:", -1)
 	body = strings.Replace(body, "办会地址:", "活动地址:", -1)
 	doc, _ := goquery.NewDocumentFromReader(strings.NewReader(body))
@@ -1417,11 +1421,11 @@ func GetActChartPermissionList() []*cygx.ChartPermissionRepMore {
 		{PermissionName: "智造"},
 		{PermissionName: "策略"},
 		{PermissionName: "宏观"},
-		{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN},
-		{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(医药)"},
-		{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(消费)"},
-		{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(科技)"},
-		{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(智造)"},
+		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN},
+		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(医药)"},
+		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(消费)"},
+		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(科技)"},
+		//{PermissionName: utils.CHART_PERMISSION_NAME_MF_YANXUAN + "(智造)"},
 	}
 	return list
 }

+ 1 - 1
services/cygx/activity_poster.go

@@ -92,7 +92,7 @@ func MakeActivitySigninImg(activityId int) (imgUrl string, err error) {
 	if activityInfo == nil {
 		return
 	}
-	if activityInfo.ActivityTypeId != 5 && activityInfo.ActivityTypeId != 6 {
+	if activityInfo.ActivityTypeId != 5 && activityInfo.ActivityTypeId != 6 && activityInfo.ActivityTypeId != 8 {
 		return
 	}
 	itemToken, err := models.GetWxToken(utils.WxCygxAppId, utils.WxCygxAppSecret)

+ 13 - 0
services/cygx/activity_power_check.go

@@ -236,6 +236,19 @@ func GetActivityDetailUserPower(user *models.WxUser, adminInfo *system.Admin, ac
 		return
 	}
 
+	//如果是易董的活动,主、副权限有一个满足即可
+	if activityInfo.YidongActivityId != "" {
+		if strings.Contains(permissionStr, activityInfo.ChartPermissionName) || strings.Contains(permissionStr, activityInfo.ChartPermissionNameDeputy) {
+			havePower = true
+			return
+		}
+	}
+
+	//如果权限不包含那么直接返回
+	if !strings.Contains(permissionStr, activityInfo.ChartPermissionName) {
+		return
+	}
+
 	//处理决策人可见权限
 	if user.IsMaker == 0 && activityInfo.IsMakerShow == 1 {
 		havePower = false

+ 1 - 1
services/cygx/activity_signup.go

@@ -303,7 +303,7 @@ func MakeActivitySigninImg12(activityId int) (err error) {
 // 校验报名截止时间
 func CheckSiginupDeadline(activityInfo *cygx.ActivityDetail) (checkTime bool, popupMsg string) {
 	checkTime = true
-	if activityInfo.SiginupDeadline != utils.EmptyDateTimeStr {
+	if activityInfo.SiginupDeadline != utils.EmptyDateTimeStr && activityInfo.SiginupDeadline != "" {
 		timeResp := utils.StrTimeToTime(activityInfo.SiginupDeadline)
 		if timeResp.Before(time.Now()) {
 			checkTime = false

+ 367 - 61
services/cygx/activity_special.go

@@ -223,48 +223,55 @@ func GetSpecialSurplusByCompany(companyId int) (specialSurplus string, err error
 	if companyDetail.Status == "永续" {
 		specialSurplus = "不限次数"
 	}
+	// 获取继承点数
+	inheritList, e := cygx.GetCygxActivitySpecialInheritPointsByCompanyId(companyId)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetCygxActivitySpecialInheritPointsByCompanyId, Err: " + e.Error())
+	}
+	//chartMap := map[int]string{utils.YI_YAO_ID:utils.YI_YAO_NAME, utils.XIAO_FEI_ID:utils.XIAO_FEI_NAME, utils.KE_JI_ID:utils.KE_JI_NAME, utils.ZHI_ZAO_ID:utils.ZHI_ZAO_NAME}
+	//chartNumMap := map[int]int{utils.YI_YAO_ID:0, utils.XIAO_FEI_ID:0, utils.KE_JI_ID:0, utils.ZHI_ZAO_ID:0}
+	chartNameMap := map[string]int{utils.YI_YAO_NAME: 0, utils.XIAO_FEI_NAME: 0, utils.KE_JI_NAME: 0, utils.ZHI_ZAO_NAME: 0}
+	var condition string
+	var pars []interface{}
+
+	condition += ` AND company_id = ? `
+	pars = append(pars, companyId)
+
+	//查询当年的数据
+	//condition += ` AND b.create_time >= ?  `
+	//pars = append(pars, time.Now().Format(utils.FormatYearDate)+"-01-01")
+	listTripBill, e := cygx.GetCygxActivitySpecialTripBillList(condition, pars)
+	if e != nil {
+		err = errors.New("GetActivitySpecialTripCountByActivitySpecial, Err: " + e.Error())
+		return
+	}
 
 	if companyDetail.Status == "正式" {
-		userType, packageType, _, _, _ := GetUserType(companyId)
-		var airborneTota int
+		userType, _, _, _, _ := GetUserType(companyId)
 		if userType == 2 {
-			var condition string
-			var pars []interface{}
-
-			condition += ` AND company_id = ? `
-			pars = append(pars, companyId)
-
-			//到会空降的也加入流水记录表,这里不在做单独计算 2023-07-10
-			//airborneTota, e = cygx.GetActivitySpecialTripAirborneCountByActivitySpecial(condition, pars)
-			//if e != nil {
-			//	err = errors.New("GetActivitySpecialTripAirborneCountByActivitySpecial, Err: " + e.Error())
-			//	return
-			//}
-			//condition += ` AND is_valid = 1 `
-			//查询当年的数据
-			condition += ` AND create_time >= ?  `
-			pars = append(pars, time.Now().Format(utils.FormatYearDate)+"-01-01")
-			listTripBill, e := cygx.GetCygxActivitySpecialTripBill(condition, pars)
-			if e != nil {
-				err = errors.New("GetActivitySpecialTripCountByActivitySpecial, Err: " + e.Error())
-				return
-			}
-			var TripBillNum int
+			var tripBillNum int
 			for _, v := range listTripBill {
-				TripBillNum += v.BillDetailed
+				//if v.ActivityId == 0 {
+				//	continue
+				//}
+				tripBillNum += v.BillDetailed
 			}
-			// CRM13.2 70w客户有16次专项调研, 45w有10次
-			packageTypeMap := map[int]int{1: 16, 2: 10}
-			totalTrip := packageTypeMap[packageType]
 
-			tripRemaining := totalTrip - airborneTota + TripBillNum
+			if len(inheritList) > 0 {
+				for _, v := range inheritList {
+					if v.ChartPermissionId == 0 {
+						tripBillNum += v.Points
+					}
+				}
+			}
+			tripRemaining := tripBillNum
 			if tripRemaining < 0 {
 				tripRemaining = 0
 			}
+
 			specialSurplus = strconv.Itoa(tripRemaining) + "次"
-			//tripRemaining = 12 - tripTota
 		} else {
-			list, e := company.GetCompanyReportPermissionUpgrade(companyId, 2)
+			list, e := company.GetCompanyReportPermissionByCompanyIdAndProductId(companyId, 2)
 			if e != nil && e.Error() != utils.ErrNoRow() {
 				err = errors.New("GetCompanyReportPermissionUpgrade, Err: " + e.Error())
 			}
@@ -273,51 +280,57 @@ func GetSpecialSurplusByCompany(companyId int) (specialSurplus string, err error
 			}
 			var chartPermissionIdSlice []string
 			mapChartName := make(map[string]int)
+			mapUpgradeId := make(map[int]int)
 			mapPermissionNameTrip := make(map[string]int)
+			mapInheritChartName := make(map[string]int)
 			//mapPermissionName := make(map[int]string)
 			for _, v := range list {
 				chartPermissionIdSlice = append(chartPermissionIdSlice, strconv.Itoa(v.ChartPermissionId))
-
+				//是升级套餐才有点数
+				if v.IsUpgrade == 1 {
+					mapUpgradeId[v.ChartPermissionId] = 1
+				}
 			}
-			chartList, e := models.GetChartPermissionByIds(chartPermissionIdSlice)
-			if e != nil {
-				err = errors.New("获取品种信息失败, Err:" + e.Error())
-				return
+			chartList := make([]*models.ChartPermission, 0)
+			if len(chartPermissionIdSlice) > 0 {
+				chartList, e = models.GetChartPermissionByIds(chartPermissionIdSlice)
+				if e != nil {
+					err = errors.New("获取品种信息失败, Err:" + e.Error())
+					return
+				}
 			}
+
 			if len(chartList) == 0 {
 				return
 			}
-			//到会空降的也加入流水记录表,这里不在做单独计算 2023-07-10
-			//airborneList, e := cygx.GetCygxActivitySpecialTripAirborneListByComapnyId(companyId)
-			//if e != nil {
-			//	err = errors.New("获取品种信息失败, Err:" + e.Error())
-			//	return
-			//}
-			//for _, v := range airborneList {
-			//	mapPermissionNameTrip[v.ChartPermissionName] += 1
-			//}
-
-			var condition string
-			var pars []interface{}
-
-			condition += ` AND company_id = ? `
-			pars = append(pars, companyId)
-
-			//查询当年的数据
-			condition += ` AND b.create_time >= ?  `
-			pars = append(pars, time.Now().Format(utils.FormatYearDate)+"-01-01")
-			listTripBill, e := cygx.GetCygxActivitySpecialTripBillList(condition, pars)
-			if e != nil {
-				err = errors.New("GetActivitySpecialTripCountByActivitySpecial, Err: " + e.Error())
-				return
-			}
+
 			//var TripBillNum int
 			for _, v := range listTripBill {
+				if v.ActivityId == 0 {
+					continue
+				}
 				mapPermissionNameTrip[v.ChartPermissionName] += v.BillDetailed
 			}
 			for _, v := range chartList {
-				mapChartName[v.PermissionName] = 5 + mapPermissionNameTrip[v.ChartPermissionName]
+				//如果是升级则加点
+				if _, ok := mapUpgradeId[v.ChartPermissionId]; ok {
+					mapChartName[v.PermissionName] = 5 + mapPermissionNameTrip[v.ChartPermissionName]
+				} else {
+					mapChartName[v.PermissionName] = mapPermissionNameTrip[v.ChartPermissionName]
+				}
+			}
+			// 通过继承获得的加点
+			for _, v := range inheritList {
+				mapInheritChartName[v.ChartPermissionName] = v.Points
+			}
+			for k, _ := range chartNameMap {
+				if _, ok := mapChartName[k]; ok {
+					if inherit, ok2 := mapInheritChartName[k]; ok2 {
+						mapChartName[k] += inherit
+					}
+				}
 			}
+
 			for k, v := range mapChartName {
 				if v > 0 {
 					specialSurplus += k + strconv.Itoa(v) + "次+"
@@ -391,3 +404,296 @@ func CheckActivitySpecialUpdatePower(adminId int, activityInfo *cygx.ActivitySpe
 	havePower = true
 	return
 }
+
+// GetChartPermissionSpecialSurplusByCompany 获取公司专项调研次数-分品种
+func GetChartPermissionSpecialSurplusByCompany(companyId int) (userType int, tripRemaining int, mapChartName map[string]int, err error) {
+	companyDetail, e := cygx.GetCompanyDetailByIdGroup(companyId)
+	if e != nil {
+		err = errors.New("GetCompanyDetailByIdGroup, Err: " + e.Error())
+	}
+	if companyDetail == nil {
+		return
+	}
+	if companyDetail.Status != "永续" && companyDetail.Status != "正式" {
+		return
+	}
+	var specialSurplus string
+	if companyDetail.Status == "永续" {
+		specialSurplus = "不限次数"
+	}
+	//chartMap := map[int]string{utils.YI_YAO_ID:utils.YI_YAO_NAME, utils.XIAO_FEI_ID:utils.XIAO_FEI_NAME, utils.KE_JI_ID:utils.KE_JI_NAME, utils.ZHI_ZAO_ID:utils.ZHI_ZAO_NAME}
+	//chartNumMap := map[int]int{utils.YI_YAO_ID:0, utils.XIAO_FEI_ID:0, utils.KE_JI_ID:0, utils.ZHI_ZAO_ID:0}
+	chartNameMap := map[string]int{utils.YI_YAO_NAME: 0, utils.XIAO_FEI_NAME: 0, utils.KE_JI_NAME: 0, utils.ZHI_ZAO_NAME: 0}
+	if companyDetail.Status == "正式" {
+		//var packageType int
+		userType, _, _, _, _ = GetUserType(companyId)
+		var condition string
+		var pars []interface{}
+
+		condition += ` AND company_id = ? `
+		pars = append(pars, companyId)
+
+		//查询当年的数据
+		//condition += ` AND b.create_time >= ?  `
+		//pars = append(pars, time.Now().Format(utils.FormatYearDate)+"-01-01")
+		listTripBill, e := cygx.GetCygxActivitySpecialTripBillList(condition, pars)
+		if e != nil {
+			err = errors.New("GetActivitySpecialTripCountByActivitySpecial, Err: " + e.Error())
+			return
+		}
+		// 获取继承点数
+		inheritList, e := cygx.GetCygxActivitySpecialInheritPointsByCompanyId(companyId)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = errors.New("GetCygxActivitySpecialInheritPointsByCompanyId, Err: " + e.Error())
+		}
+		if userType == 2 {
+
+			var tripBillNum int
+			for _, v := range listTripBill {
+				//if v.ActivityId == 0 {
+				//	continue
+				//}
+				tripBillNum += v.BillDetailed
+			}
+			if len(inheritList) > 0 {
+				for _, v := range inheritList {
+					if v.ChartPermissionId == 0 {
+						tripBillNum += v.Points
+					}
+				}
+			}
+
+			tripRemaining = tripBillNum
+			if tripRemaining < 0 {
+				tripRemaining = 0
+			}
+
+		} else {
+			list, e := company.GetCompanyReportPermissionByCompanyIdAndProductId(companyId, 2)
+			if e != nil && e.Error() != utils.ErrNoRow() {
+				err = errors.New("GetCompanyReportPermissionUpgrade, Err: " + e.Error())
+			}
+			if len(list) == 0 {
+				return
+			}
+			var chartPermissionIdSlice []string
+			mapChartName = make(map[string]int)
+			mapUpgradeId := make(map[int]int)
+			mapPermissionNameTrip := make(map[string]int)
+			mapInheritChartName := make(map[string]int)
+			//mapPermissionName := make(map[int]string)
+			for _, v := range list {
+				chartPermissionIdSlice = append(chartPermissionIdSlice, strconv.Itoa(v.ChartPermissionId))
+				//是升级套餐才有点数
+				if v.IsUpgrade == 1 {
+					mapUpgradeId[v.ChartPermissionId] = 1
+				}
+			}
+			chartList := make([]*models.ChartPermission, 0)
+			if len(chartPermissionIdSlice) > 0 {
+				chartList, e = models.GetChartPermissionByIds(chartPermissionIdSlice)
+				if e != nil {
+					err = errors.New("获取品种信息失败, Err:" + e.Error())
+					return
+				}
+			}
+
+			if len(chartList) == 0 {
+				return
+			}
+
+			for _, v := range listTripBill {
+				if v.ActivityId == 0 {
+					continue
+				}
+				mapPermissionNameTrip[v.ChartPermissionName] += v.BillDetailed
+			}
+			for _, v := range chartList {
+				//如果是升级则加点
+				if _, ok := mapUpgradeId[v.ChartPermissionId]; ok {
+					mapChartName[v.PermissionName] = 5 + mapPermissionNameTrip[v.ChartPermissionName]
+				} else {
+					mapChartName[v.PermissionName] = mapPermissionNameTrip[v.ChartPermissionName]
+				}
+			}
+			// 通过继承获得的加点
+			for _, v := range inheritList {
+				mapInheritChartName[v.ChartPermissionName] = v.Points
+			}
+			for k, _ := range chartNameMap {
+				if _, ok := mapChartName[k]; ok {
+					if inherit, ok2 := mapInheritChartName[k]; ok2 {
+						mapChartName[k] += inherit
+					}
+				}
+			}
+
+			for k, v := range mapChartName {
+				if v > 0 {
+					specialSurplus += k + strconv.Itoa(v) + "次+"
+				}
+			}
+			specialSurplus = strings.TrimRight(specialSurplus, "+")
+		}
+	}
+	return
+}
+
+// 审批通过的时候专项调研次数更新
+func ActivitySpecialCompanyApproval(companyId int, companyName string) (err error) {
+	userType, packageType, _, _, _ := GetUserType(companyId)
+	// 获取继承点数
+	inheritList, e := cygx.GetCygxActivitySpecialInheritPointsByCompanyId(companyId)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetCygxActivitySpecialInheritPointsByCompanyId, Err: " + e.Error())
+	}
+	chartNameMap := map[string]int{utils.YI_YAO_NAME: 0, utils.XIAO_FEI_NAME: 0, utils.KE_JI_NAME: 0, utils.ZHI_ZAO_NAME: 0}
+
+	itemBill := new(cygx.CygxActivitySpecialTripBill)
+	itemBill.CreateTime = time.Now()
+	itemBill.CompanyId = companyId
+	itemBill.CompanyName = companyName
+	itemBill.Source = 2
+	itemBill.DoType = 2
+	itemBill.Way = 3
+	if userType == 2{
+		packageTypeMap := map[int]int{1: 16, 2: 10}
+		totalTrip := packageTypeMap[packageType]
+		if len(inheritList) > 0 {
+			for _, v := range inheritList {
+				if v.ChartPermissionId == 0 {
+					itemBill.BillDetailed = totalTrip + v.Points
+				} else {
+					itemBill.BillDetailed = totalTrip
+				}
+			}
+		} else {
+			itemBill.BillDetailed = totalTrip
+		}
+
+		itemBill.Total = strconv.Itoa(itemBill.BillDetailed) + "次"
+		if totalTrip == 10 {
+			itemBill.Content = "45w大套餐转正"
+		} else {
+			itemBill.Content = "70w大套餐转正"
+		}
+	} else {
+		list, e := company.GetCompanyReportPermissionByCompanyIdAndProductId(companyId, 2)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = errors.New("GetCompanyReportPermissionUpgrade, Err: " + e.Error())
+		}
+		if len(list) == 0 {
+			return
+		}
+		var chartPermissionIdSlice []string
+		mapChartName := make(map[string]int)
+		mapUpgradeId := make(map[int]int)
+		mapInheritChartName := make(map[string]int)
+		mapPermissionNameTrip := make(map[string]int)
+		//mapPermissionName := make(map[int]string)
+		for _, v := range list {
+			chartPermissionIdSlice = append(chartPermissionIdSlice, strconv.Itoa(v.ChartPermissionId))
+			//是升级套餐才有点数
+			if v.IsUpgrade == 1 {
+				mapUpgradeId[v.ChartPermissionId] = 1
+			}
+		}
+		chartList := make([]*models.ChartPermission, 0)
+		if len(chartPermissionIdSlice) > 0 {
+			chartList, e = models.GetChartPermissionByIds(chartPermissionIdSlice)
+			if e != nil {
+				err = errors.New("获取品种信息失败, Err:" + e.Error())
+				return
+			}
+		}
+		if len(chartList) == 0 {
+			return
+		}
+		for _, v := range chartList {
+			//如果是升级则加点
+			if _, ok := mapUpgradeId[v.ChartPermissionId]; ok {
+				mapChartName[v.PermissionName] = 5 + mapPermissionNameTrip[v.ChartPermissionName]
+			} else {
+				mapChartName[v.PermissionName] = mapPermissionNameTrip[v.ChartPermissionName]
+			}
+		}
+		// 通过继承获得的加点
+		for _, v := range inheritList {
+			mapInheritChartName[v.ChartPermissionName] = v.Points
+		}
+		for k, _ := range chartNameMap {
+			if _, ok := mapChartName[k]; ok {
+				if inherit, ok2 := mapInheritChartName[k]; ok2 {
+					mapChartName[k] += inherit
+				}
+			}
+		}
+		for k, v := range mapChartName {
+			if v > 0 {
+				itemBill.BillDetailed += v
+				itemBill.Total += k + strconv.Itoa(v) + "次+"
+			}
+		}
+		itemBill.Content = "行业升级套餐转正"
+		itemBill.Total = strings.TrimRight(itemBill.Total, "+")
+	}
+	err = cygx.AddCygxActivitySpecialTripBill(itemBill)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// 取消专项调研返点
+func ActivitySpecialPublishAndCancel(activityInfo *cygx.ActivitySpecialDetail) (err error) {
+	//userType, tripRemaining, mapChartName, err := GetChartPermissionSpecialSurplusByCompany(companyId)
+	//if err != nil {
+	//	br.Msg = "获取专项调研剩余次数失败"
+	//	br.ErrMsg = "获取专项调研剩余次数失败,err:" + err.Error()
+	//	return
+	//}
+	//itemBill := new(cygx.CygxActivitySpecialTripBill)
+	//itemBill.CreateTime = time.Now()
+	//itemBill.ActivityId = activityInfo.ActivityId
+	//itemBill.Content = activityInfo.ResearchTheme + "--活动取消"
+	//itemBill.Source = 2
+	//itemBill.DoType = 2
+	//itemBill.Way = 4
+	//itemBill.BillDetailed = 1
+	//err = cygx.AddCygxActivitySpecialTripBill(itemBill)
+	//if err != nil {
+	//	return
+	//}
+	return
+}
+
+// GetSpecialSurplusByCompanyNew 获取公司专项调研剩余次数-用流水表数据不计算了,计算都丢在流水里
+func GetSpecialSurplusByCompanyNew(companyId int) (specialSurplus string, err error) {
+	companyDetail, e := cygx.GetCompanyDetailByIdGroup(companyId)
+	if e != nil {
+		err = errors.New("GetCompanyDetailByIdGroup, Err: " + e.Error())
+	}
+	if companyDetail == nil {
+		return
+	}
+	if companyDetail.Status != "永续" && companyDetail.Status != "正式" {
+		return
+	}
+	if companyDetail.Status == "永续" {
+		specialSurplus = "不限次数"
+	}
+	//chartMap := map[int]string{utils.YI_YAO_ID:utils.YI_YAO_NAME, utils.XIAO_FEI_ID:utils.XIAO_FEI_NAME, utils.KE_JI_ID:utils.KE_JI_NAME, utils.ZHI_ZAO_ID:utils.ZHI_ZAO_NAME}
+	//chartNumMap := map[int]int{utils.YI_YAO_ID:0, utils.XIAO_FEI_ID:0, utils.KE_JI_ID:0, utils.ZHI_ZAO_ID:0}
+	if companyDetail.Status == "正式" {
+		billItem,e := cygx.GetCygxActivitySpecialTripBillByCompanyId(companyId)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = e
+			return
+		}
+		if billItem != nil {
+			specialSurplus = billItem.Total
+		}
+		return
+	}
+	return
+}

+ 46 - 0
services/cygx/report_mapping.go

@@ -1,9 +1,11 @@
 package cygx
 
 import (
+	"errors"
 	"fmt"
 	"hongze/hz_crm_api/models/cygx"
 	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
 )
 
 // 报告匹配类型映射
@@ -27,3 +29,47 @@ func GetCygxReportMappingCygxListMap() (mapResp map[int]string) {
 	}
 	return
 }
+
+// 根据文章ID获取文章行业分类
+func GetCygxArticlePerssionNameListMap(articleIdArr []int) (mapResp map[int]string) {
+	lenArr := len(articleIdArr)
+	if lenArr == 0 {
+		return
+	}
+	var err error
+	defer func() {
+		if err != nil {
+			fmt.Println(err)
+			go alarm_msg.SendAlarmMsg("根据文章ID获取文章行业分类,信息失败,GetCygxArticlePerssionNameListMap Err:"+err.Error(), 3)
+		}
+	}()
+	var condition string
+	var pars []interface{}
+	//获取分类名称
+	perssionNameList, e := cygx.GetCygxReportMappingList(condition, pars)
+	if e != nil {
+		err = errors.New("GetCygxReportMappingCelueList, Err: " + e.Error())
+		return
+	}
+	mapName := make(map[int]string)
+	for _, v := range perssionNameList {
+		mapName[v.CategoryId] = v.ChartPermissionName
+	}
+	pars = make([]interface{}, 0)
+	condition = ` AND  article_id IN (` + utils.GetOrmInReplace(lenArr) + `)`
+	pars = append(pars, articleIdArr)
+	listArticle, e := cygx.GetArticlList(condition, pars, 0, 999)
+	if e != nil && e.Error() != utils.ErrNoRow() {
+		err = errors.New("GetArticlList, Err: " + e.Error())
+		return
+	}
+	mapResp = make(map[int]string, 0)
+	for _, v := range listArticle {
+		if v.CategoryId == 0 {
+			mapResp[v.ArticleId] = utils.CHART_PERMISSION_NAME_MF_YANXUAN
+		} else {
+			mapResp[v.ArticleId] = mapName[v.CategoryId]
+		}
+	}
+	return
+}

+ 12 - 4
services/cygx/yidong.go

@@ -670,7 +670,7 @@ func YiDongUpdateActivityStatus(activityId int) {
 	defer func() {
 		if err != nil {
 			fmt.Println(err)
-			go alarm_msg.SendAlarmMsg("发布路演到活动广场(新);err:"+err.Error(), 3)
+			go alarm_msg.SendAlarmMsg(" 删除路演活动(新);err:"+err.Error(), 3)
 		}
 	}()
 	activityInfo, err := cygx.GetAddActivityInfoById(activityId)
@@ -685,14 +685,22 @@ func YiDongUpdateActivityStatus(activityId int) {
 	if activityInfo.ActivityTypeId == 7 {
 		activityInfo.PublishStatus = 0
 	}
+	//如果关联的易董活动ID为空,那么不做处理
+	if activityInfo.YidongActivityIdByCygx == "" {
+		return
+	}
+	//如果状态是已发布,而且是易董办会那么就不做处理
+	if activityInfo.IsYidongConduct == 1 && activityInfo.PublishStatus == 1 {
+		return
+	}
 	token, _ := GetYidongToken()
 	if token == "" {
 		return
 	}
 	url := utils.YiDongZhengTongYunUrl + "interact/activityThirdApi/updateActivityStatus" + "?access_token=" + token
-	if activityInfo.IsYidongConduct == 0 || activityInfo.YidongActivityIdByCygx == "" {
-		return
-	}
+	//if activityInfo.IsYidongConduct == 0 || activityInfo.YidongActivityIdByCygx == "" {
+	//	return
+	//}
 	params := YiDongUpdateActivityPublishResp{
 		Id: activityInfo.YidongActivityIdByCygx,
 	}

+ 23 - 1
services/data/excel_info.go

@@ -752,6 +752,28 @@ func GetDataByTableDataConfig(tableDataConfig TableDataConfig) (resultResp reque
 		data = append(data, tmpEdbInfoData)
 	}
 
+	// 处理一下数据格式
+	for _, d := range data {
+		for k2, d2 := range d.Data {
+			// 可能有ShowValue非数值, 转换一下报错则continue
+			vf, e := strconv.ParseFloat(d2.ShowValue, 64)
+			if e != nil {
+				continue
+			}
+			d.Data[k2].ShowValue = utils.FormatTableDataShowValue(vf)
+		}
+	}
+	for _, d := range textRowListDataResp {
+		for k2, d2 := range d {
+			// 可能有ShowValue非数值, 转换一下报错则continue
+			vf, e := strconv.ParseFloat(d2.ShowValue, 64)
+			if e != nil {
+				continue
+			}
+			d[k2].ShowValue = utils.FormatTableDataShowValue(vf)
+		}
+	}
+
 	resultResp = request.TableDataReq{
 		EdbInfoIdList: edbInfoIdList,
 		Sort:          tableDataConfig.Sort,
@@ -1259,7 +1281,7 @@ func GetMixedTableCellData(config [][]request.MixedTableCellDataReq) (newMixedTa
 			} else if cell.DataType == 4 {
 				if dateValMap, ok := edbDataListMap[cell.EdbInfoId]; ok {
 					if val, ok2 := dateValMap[cell.DataTime]; ok2 {
-						cell.ShowValue = fmt.Sprint(val)
+						cell.ShowValue = utils.FormatTableDataShowValue(val)
 					}
 				}
 			}

+ 33 - 0
services/data/help_doc_classify.go

@@ -0,0 +1,33 @@
+package data
+
+import "hongze/hz_crm_api/models/help_doc"
+
+func helpDocClassifyHaveChild(allNode []*help_doc.HelpDocClassifyItems, node *help_doc.HelpDocClassifyItems) (childs []*help_doc.HelpDocClassifyItems, yes bool) {
+	for _, v := range allNode {
+		if v.ParentId == node.ClassifyId {
+			childs = append(childs, v)
+		}
+	}
+	if len(childs) > 0 {
+		yes = true
+	}
+	return
+}
+
+func HelpDocClassifyItemsMakeTree(allNode []*help_doc.HelpDocClassifyItems, node *help_doc.HelpDocClassifyItems) {
+	childs, _ := helpDocClassifyHaveChild(allNode, node) //判断节点是否有子节点并返回
+	if len(childs) > 0 {
+		node.Children = append(node.Children, childs[0:]...) //添加子节点
+		for _, v := range childs {                           //查询子节点的子节点,并添加到子节点
+			_, has := helpDocClassifyHaveChild(allNode, v)
+			if has {
+				HelpDocClassifyItemsMakeTree(allNode, v) //递归添加节点
+			} else {
+				v.Children = nil
+			}
+		}
+	} else {
+		node.Children = nil
+	}
+}
+

+ 10 - 0
services/elastic/es_comprehensive.go

@@ -12,6 +12,7 @@ import (
 	"html"
 	"strconv"
 	"strings"
+	"time"
 )
 
 type ElasticComprehensiveDetail struct {
@@ -138,6 +139,7 @@ func EsDeleteComprehensiveData(item *ElasticComprehensiveDetail) (err error) {
 
 // ES添加文章:报告、纪要
 func AddComprehensiveArticle(sourceId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -176,6 +178,7 @@ func AddComprehensiveArticle(sourceId int) {
 
 // Es添加活动
 func AddComprehensiveActivity(sourceId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -229,6 +232,7 @@ func AddComprehensiveActivity(sourceId int) {
 
 // Es添加专项调研活动
 func AddComprehensiveActivitySpecial(sourceId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -286,6 +290,7 @@ func AddComprehensiveActivitySpecial(sourceId int) {
 
 // Es添加活动视频
 func AddComprehensiveActivityVideo(activityId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -344,6 +349,7 @@ func AddComprehensiveActivityVideo(activityId int) {
 
 // Es添加活动音频
 func AddComprehensiveActivityVoice(activityId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -403,6 +409,7 @@ func AddComprehensiveActivityVoice(activityId int) {
 
 // Es添加微路演
 func AddComprehensiveRoadshow(sourceId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -432,6 +439,7 @@ func AddComprehensiveRoadshow(sourceId int) {
 
 // Es添加晨会精华
 func AddComprehensiveMeetingreviewchapt(sourceId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -463,6 +471,7 @@ func AddComprehensiveMeetingreviewchapt(sourceId int) {
 
 // Es删除晨会精华
 func DeleteComprehensiveMeetingreviewchapt(sourceId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {
@@ -479,6 +488,7 @@ func DeleteComprehensiveMeetingreviewchapt(sourceId int) {
 
 // 添加产业资源包
 func AddComprehensiveIndustrialSource(sourceType string, articleId int) {
+	time.Sleep(3 * time.Second) // 延迟三秒处理
 	var err error
 	defer func() {
 		if err != nil {

+ 106 - 0
services/eta_business/eta_business.go

@@ -0,0 +1,106 @@
+package eta_business
+
+import (
+	"fmt"
+	"hongze/hz_crm_api/models/company"
+	"hongze/hz_crm_api/models/eta_business"
+	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
+	"strings"
+	"time"
+)
+
+// CheckEtaBusinessOperateAuth 校验ETA商家操作权限
+func CheckEtaBusinessOperateAuth(roleCode string) (ok bool, err error) {
+	confKey := "eta_business_auth_role"
+	conf, e := company.GetConfigDetailByCode(confKey)
+	if e != nil {
+		err = fmt.Errorf("获取权限配置失败, Err: %s", e.Error())
+		return
+	}
+	if conf.ConfigValue == "" {
+		err = fmt.Errorf("权限配置信息有误")
+		return
+	}
+	authArr := strings.Split(conf.ConfigValue, ",")
+	if utils.InArrayByStr(authArr, roleCode) {
+		ok = true
+	}
+	return
+}
+
+// UpdateEtaBusinessAfterSigning 签约后的后置操作
+func UpdateEtaBusinessAfterSigning(businessId int) (err error) {
+	if businessId <= 0 {
+		return
+	}
+	defer func() {
+		if err != nil {
+			tips := "签约后更新商家信息失败, Err: " + err.Error()
+			utils.FileLog.Info("%s", tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	businessOb := new(eta_business.EtaBusiness)
+	business, e := businessOb.GetItemById(businessId)
+	if e != nil {
+		err = fmt.Errorf("获取商家信息失败, Err: %s", e.Error())
+		return
+	}
+
+	contracts := make([]*eta_business.EtaBusinessContract, 0)
+	{
+		ob := new(eta_business.EtaBusinessContract)
+		cond := fmt.Sprintf(` AND %s = ?`, eta_business.EtaBusinessContractColumns.EtaBusinessId)
+		pars := make([]interface{}, 0)
+		pars = append(pars, businessId)
+		list, e := ob.GetItemsByCondition(cond, pars, []string{}, "")
+		if e != nil {
+			err = fmt.Errorf("获取商家合同列表失败, Err: " + e.Error())
+			return
+		}
+		contracts = list
+	}
+	if len(contracts) == 0 {
+		return
+	}
+
+	strToday := time.Now().Format(utils.FormatDate)
+	today, _ := time.ParseInLocation(utils.FormatDate, strToday, time.Local)
+	using := false // 是否在任一存续期内
+	for _, c := range contracts {
+		// 当前合约
+		if today.Equal(c.SigningTime) || today.Equal(c.ExpiredTime) || (today.After(c.SigningTime) && today.Before(c.ExpiredTime)) {
+			business.ContractId = c.EtaBusinessContractId
+			business.SigningTime = c.SigningTime
+			business.ExpiredTime = c.ExpiredTime
+			business.ModifyTime = time.Now().Local()
+			// 是否为首次签约
+			if c.IsFirst == 1 {
+				business.SigningStatus = eta_business.EtaBusinessSigningStatusFirst
+			} else {
+				business.SigningStatus = eta_business.EtaBusinessSigningStatusContinue
+			}
+			using = true
+			break
+		}
+	}
+	// 不存在任一合同期内, 当前合同不变, 更新状态
+	if !using {
+		business.SigningStatus = eta_business.EtaBusinessSigningStatusTerminate
+		business.ModifyTime = time.Now().Local()
+		cols := []string{"SigningStatus", "ModifyTime"}
+		if e = business.Update(cols); e != nil {
+			err = fmt.Errorf("更新商家信息失败, Err: %s", e.Error())
+			return
+		}
+		return
+	}
+	// 合同期内
+	cols := []string{"ContractId", "SigningStatus", "SigningTime", "ExpiredTime", "ModifyTime"}
+	if e = business.Update(cols); e != nil {
+		err = fmt.Errorf("更新商家信息失败, Err: %s", e.Error())
+	}
+	return
+}

+ 15 - 0
services/eta_business/eta_business_menu.go

@@ -0,0 +1,15 @@
+package eta_business
+
+import "hongze/hz_crm_api/models/eta_business"
+
+// GetMenuTreeRecursive 递归菜单树
+func GetMenuTreeRecursive(list []*eta_business.EtaBusinessMenuItem, parentId int) []*eta_business.EtaBusinessMenuItem {
+	res := make([]*eta_business.EtaBusinessMenuItem, 0)
+	for _, v := range list {
+		if v.ParentId == parentId {
+			v.Children = GetMenuTreeRecursive(list, v.MenuId)
+			res = append(res, v)
+		}
+	}
+	return res
+}

+ 148 - 0
services/eta_trial.go

@@ -2,8 +2,13 @@ package services
 
 import (
 	"fmt"
+	"github.com/mozillazg/go-pinyin"
+	"hongze/hz_crm_api/models/company"
 	"hongze/hz_crm_api/models/eta_trial"
 	"hongze/hz_crm_api/services/alarm_msg"
+	"hongze/hz_crm_api/utils"
+	"strconv"
+	"time"
 )
 
 // UpdateOldTrialUsersManualAuth 更新原试用客户手工录入权限(一次性)
@@ -73,3 +78,146 @@ func CreateTrialUserManualAuth(adminId int, adminRealName string) (err error) {
 	}
 	return
 }
+
+// ApprovalApply 同意审批
+func ApprovalApply(approvalId int) (err error) {
+	defer func() {
+		if err != nil {
+			tips := fmt.Sprintf("ETA试用-自动审批失败, ApprovalId: %d, Err: %s", approvalId, err.Error())
+			utils.FileLog.Info("%s", tips)
+			go alarm_msg.SendAlarmMsg(tips, 3)
+		}
+	}()
+
+	// 获取审批
+	approval, e := eta_trial.GetETATrialApprovalById(approvalId)
+	if e != nil {
+		err = fmt.Errorf("获取审批失败, Err: %s", e.Error())
+		return
+	}
+
+	// 更新审批
+	if e = eta_trial.ApprovalTrial(approvalId); e != nil {
+		err = fmt.Errorf("更新审批失败, Err: %s", e.Error())
+		return
+	}
+
+	// 如果是新客户申请就新增,旧客户更改账号状态即可
+	if approval.ApplyMethod == 2 {
+		if e = eta_trial.UpdateETATrialEnable(approval.Mobile); e != nil {
+			err = fmt.Errorf("启用失败, Err: %s", e.Error())
+			return
+		}
+		if e = eta_trial.UpdateAdminEnable(approval.Mobile); e != nil {
+			err = fmt.Errorf("启用用户失败, Err: %s", e.Error())
+			return
+		}
+	} else {
+		//新增客户
+		newItem := eta_trial.EtaTrial{
+			UserName:    approval.UserName,
+			CompanyName: approval.CompanyName,
+			Position:    approval.Position,
+			Mobile:      approval.Mobile,
+			Enabled:     1,
+			SellerId:    approval.SellerId,
+			Seller:      approval.Seller,
+			CreateTime:  time.Now(),
+			ModifyTime:  time.Now(),
+		}
+
+		strResult := ""
+		a := pinyin.NewArgs()
+		rows := pinyin.Pinyin(newItem.UserName, a)
+		for i := 0; i < len(rows); i++ {
+			strResult += rows[i][0]
+		}
+
+		//若非中文
+		if strResult == "" {
+			strResult = newItem.UserName
+		}
+		list, e := eta_trial.GetETATrialByAccount(strResult)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = fmt.Errorf("获取ETA试用账号失败, Err: %s", e.Error())
+			return
+		}
+		if list != nil && len(list) > 0 {
+			newItem.Account = strResult + strconv.Itoa(len(list))
+		} else {
+			newItem.Account = strResult
+		}
+
+		// 初始密码固定
+		newItem.Password = "123456a"
+
+		_, e = eta_trial.AddETATrial(&newItem)
+		if e != nil {
+			err = fmt.Errorf("新增ETA试用账号失败, Err: %s", e.Error())
+			return
+		}
+
+		// 新增至试用平台的Admin
+		adminItem, e := eta_trial.GetSysUserByRoleAndDepartment("试用", "ETA试用客户")
+		if e != nil {
+			err = fmt.Errorf("获取ETA试用admin失败, Err: %s", e.Error())
+			return
+		}
+
+		admin := new(eta_trial.ETATrialAdmin)
+		admin.AdminName = newItem.Account
+		admin.RealName = newItem.UserName
+		admin.Password = utils.MD5(newItem.Password)
+		admin.LastUpdatedPasswordTime = time.Now().Format(utils.FormatDateTime)
+		admin.Enabled = 1
+		admin.LastLoginTime = time.Now().Format(utils.FormatDateTime)
+		admin.CreatedTime = time.Now()
+		admin.LastUpdatedTime = time.Now().Format(utils.FormatDateTime)
+		admin.Mobile = newItem.Mobile
+		admin.RoleType = 0
+		admin.RoleId = adminItem.RoleId
+		admin.RoleName = "试用"
+		admin.RoleTypeCode = "管理员"
+		admin.DepartmentId = adminItem.DepartmentId
+		admin.DepartmentName = "ETA试用客户"
+		admin.Role = "admin"
+		admin.Position = approval.Position
+
+		newId, e := eta_trial.AddAdmin(admin)
+		if e != nil {
+			err = fmt.Errorf("新增ETA试用admin失败, Err: %s", e.Error())
+			return
+		}
+
+		// 新增试用客户手工权限
+		go func() {
+			_ = CreateTrialUserManualAuth(newId, admin.RealName)
+		}()
+	}
+
+	// 推送消息给销售
+	msgItem := new(company.CompanyApprovalMessage)
+	msgItem.CreateUserId = 0 // 系统自动创建的消息
+	msgItem.ReceiveUserId = approval.SellerId
+	msgItem.MessageStatus = 0
+	msgItem.Remark = approval.UserName + approval.ApprovalContent + "通过"
+	msgItem.Content = approval.UserName + approval.ApprovalContent + "通过"
+	msgItem.CompanyName = approval.CompanyName
+	msgItem.CreateTime = time.Now()
+	msgItem.ModifyTime = time.Now()
+	msgItem.CompanyApprovalId = approvalId
+	msgItem.OperationStatus = 1
+	msgItem.MessageType = 2    //1:申请消息,2:审批结果,3:文字消息
+	msgItem.SourceType = 9     //消息来源
+	msgItem.ApprovalStatus = 2 //审批状态,1:待审批,2:已审批,3:已驳回
+	err = company.AddCompanyApprovalMessage(msgItem)
+
+	// 更新审批消息(发给所有管理员的)为已读
+	//go func() {
+	//	cond := ` AND company_approval_id = ? AND source_type = ? AND message_status = ? AND receive_user_id = -1 `
+	//	pars := make([]interface{}, 0)
+	//	pars = append(pars, approvalId, 9, 0)
+	//	_ = company.ModifyCompanyApprovalMessageStatusByCond(cond, pars)
+	//}()
+	return
+}

+ 22 - 0
services/task.go

@@ -2,6 +2,8 @@ package services
 
 import (
 	"fmt"
+	"hongze/hz_crm_api/models/eta_business"
+	"hongze/hz_crm_api/utils"
 )
 
 func Task() {
@@ -11,5 +13,25 @@ func Task() {
 
 	go AutoInsertAdminOperateRecordToDB()
 
+	//go FixEtaBusinessCodeEncrypt()
+
 	fmt.Println("task end")
 }
+
+// FixEtaBusinessCodeEncrypt 修复商家编码
+func FixEtaBusinessCodeEncrypt() {
+	ob := new(eta_business.EtaBusiness)
+	list, e := ob.GetItemsByCondition("", make([]interface{}, 0), []string{}, "")
+	if e != nil {
+		fmt.Println(e.Error())
+		return
+	}
+
+	for _, v := range list {
+		v.CodeEncrypt = utils.MD5(fmt.Sprintf("%s%s", v.BusinessCode, utils.BusinessCodeSalt))
+		if e = v.Update([]string{"CodeEncrypt"}); e != nil {
+			fmt.Println(e.Error())
+			return
+		}
+	}
+}

+ 73 - 0
utils/common.go

@@ -2014,3 +2014,76 @@ func GetPredictEdbDayListByNum(startDate time.Time, num int, frequency string) (
 	}
 	return
 }
+
+// GetDiffDays 计算两个日期相差的天数
+func GetDiffDays(t1, t2 time.Time) int {
+	t1 = time.Date(t1.Year(), t1.Month(), t1.Day(), 0, 0, 0, 0, time.Local)
+	t2 = time.Date(t2.Year(), t2.Month(), t2.Day(), 0, 0, 0, 0, time.Local)
+	return int(t1.Sub(t2).Hours() / 24)
+}
+
+// FormatTableDataShowValue 格式化自定表格显示数据
+func FormatTableDataShowValue(x float64) (res string) {
+	if x > 1 || x < -1 {
+		res = decimal.NewFromFloat(x).Round(2).String()
+		return
+	}
+	// 介于-1到1之间
+	xStr := strconv.FormatFloat(x, 'f', -10, 64)
+
+	// 使用 strings.Split 函数将小数拆分为整数部分和小数部分
+	xParts := strings.Split(xStr, ".")
+	if len(xParts) < 2 {
+		res = fmt.Sprint(x)
+		return
+	}
+
+	// 计算小数部分的长度,即小数点后面的位数
+	xDecimals := len(xParts[1])
+	if xDecimals > 2 {
+		parts := xParts[1]
+		// 小数点后小于等于两位, 直接拼接返回
+		partLen := len(xParts[1])
+		if partLen <= 2 {
+			res = xParts[0] + "." + parts
+			return
+		}
+		// 找出第一个有效数字, 算出n
+		one := 0
+		for k, p := range parts {
+			// 48->0
+			if p != 48 {
+				if one == 0 {
+					one = k + 1
+				}
+			}
+		}
+		n := partLen - one
+		if n >= 1 {
+			n -= 1
+		} else {
+			one -= 1
+		}
+
+		var partFloat float64
+		partInt, _ := strconv.Atoi(parts)
+		partFloat, _ = decimal.NewFromInt(int64(partInt)).Div(decimal.NewFromFloat(math.Pow(10, float64(n)))).Float64()
+		partFloat = math.Round(partFloat)
+		partFloat, _ = decimal.NewFromFloat(partFloat).Div(decimal.NewFromFloat(math.Pow(10, float64(one+1)))).Float64()
+		resParts := strings.Split(fmt.Sprint(partFloat), ".")
+		resPart := ""
+		if len(resParts) > 1 {
+			resPart = resParts[1]
+		} else {
+			resPart = resParts[0]
+		}
+		res = xParts[0] + "." + resPart
+	}
+
+	if xDecimals < 2 {
+		xDecimalsStr := xParts[1]
+		x, _ = strconv.ParseFloat(xParts[0]+"."+xDecimalsStr, 64)
+		res = xParts[0] + "." + xDecimalsStr
+	}
+	return
+}

+ 7 - 1
utils/constants.go

@@ -413,7 +413,6 @@ const (
 	CYGX_OBJ_ROADSHOW           string = "roadshow"           // 对象类型:路演
 )
 
-
 const (
 	SendTemplateMsgAuthorization = "dc855fce962a639faa779cbdd4cd332f"
 )
@@ -508,3 +507,10 @@ const (
 	SOURCE_CRM_FLAG = 1
 	SOURCE_ETA_FLAG = 2
 )
+
+// BusinessCodeSalt 商家编码盐值
+const BusinessCodeSalt = "dr7WY0OZgGR7upw1"
+
+const (
+	ApproveUserId = 2 //施琪-出差审批人
+)