package yb import ( "encoding/json" "fmt" "github.com/rdlucklib/rdluck_tools/paging" "hongze/hz_crm_api/controllers" "hongze/hz_crm_api/models" ybModels "hongze/hz_crm_api/models/yb" "hongze/hz_crm_api/models/yb/request" "hongze/hz_crm_api/services" "hongze/hz_crm_api/services/yb" "hongze/hz_crm_api/utils" "strings" "time" ) // RoadVideoController 研报视频社区 type RoadVideoController struct { controllers.BaseAuthController } // List // @Title 视频列表 // @Description 视频列表 // @Param Keywords query string false "关键词" // @Param SortParam query string false "排序字段参数,用来排序的字段, 枚举值:'ClickNum':点击量" // @Param SortType query string true "如何排序,是正序还是倒序,枚举值:`asc 正序`,`desc 倒叙`" // @Success 200 {object} response.CommunityQuestionListResp // @router /road/video/list [get] func (r *RoadVideoController) List() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } condition := "" pars := make([]interface{}, 0) keywords := r.GetString("Keywords", "") if keywords != "" { keywords = "%" + keywords + "%" condition += ` AND v.title LIKE ? ` pars = append(pars, keywords) } var startSize int pageSize, _ := r.GetInt("PageSize") currentIndex, _ := r.GetInt("CurrentIndex") if pageSize <= 0 { pageSize = utils.PageSize20 } if currentIndex <= 0 { currentIndex = 1 } startSize = paging.StartIndex(currentIndex, pageSize) // 排序相关 sortParam := r.GetString("SortParam") sortType := r.GetString("SortType") orderStr := "" if sortType != "" && strings.ToLower(sortType) != "desc" && strings.ToLower(sortType) != "asc" { br.Msg = "请输入正确的排序类型" return } if sortParam == "ClickNum" { orderStr = " ORDER BY l.click_num" if sortType != "" { orderStr += " " + sortType } else { orderStr += " DESC" } orderStr += ", v.modify_time DESC" } total, resp, err, errMsg := yb.GetRoadVideoList(condition, pars, orderStr, startSize, pageSize) if err != nil { br.Msg = errMsg br.ErrMsg = err.Error() return } page := paging.GetPaging(currentIndex, pageSize, total) resp.Paging = page br.Ret = 200 br.Success = true br.Msg = "获取成功" br.Data = resp } // Save // @Title 保存视频 // @Description 保存视频 // @Param request body request.RoadVideoSaveReq true "type json string" // @Success 200 string "操作成功" // @router /road/video/save [post] func (r *RoadVideoController) Save() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req request.RoadVideoSaveReq if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.Title == "" { br.Msg = "请输入标题" return } if req.ChartPermissionIds == "" { br.Msg = "请选择品种" return } if req.CoverImgUrl == "" { br.Msg = "请上传封面图" return } if req.VideoUrl == "" { br.Msg = "请上传视频" return } data, errMsg, err := yb.SaveRoadVideo(sysUser, req.VideoId, req.ReportId, req.ChartPermissionIds, req.Title, req.CoverImgUrl, req.VideoUrl, req.VideoSeconds) if err != nil { br.Msg = errMsg br.ErrMsg = "Yb-SaveVideo ErrMsg:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" br.Data = data } // Delete // @Title 删除视频 // @Description 删除视频 // @Param request body request.RoadVideoOptionReq true "type json string" // @Success 200 string "操作成功" // @router /road/video/delete [post] func (r *RoadVideoController) Delete() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req request.RoadVideoOptionReq if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.VideoId <= 0 { br.Msg = "参数有误" return } errMsg, err := yb.SoftDeleteRoadVideo(req.VideoId) if err != nil { br.Msg = errMsg br.ErrMsg = "Yb-DeleteVideo ErrMsg:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" } // Publish // @Title 发布/取消视频 // @Description 发布/取消视频 // @Param request body request.RoadVideoPublishReq true "type json string" // @Success 200 string "操作成功" // @router /road/video/publish [post] func (r *RoadVideoController) Publish() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req request.RoadVideoPublishReq if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.VideoId <= 0 { br.Msg = "参数有误" return } errMsg, err := yb.PublishRoadVideo(req.VideoId, req.PublishState) if err != nil { br.Msg = errMsg br.ErrMsg = "Yb-PublishVideo ErrMsg:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" } // SendThs // @Title 推送客群消息 // @Description 推送客群消息 // @Param request body request.RoadVideoOptionReq true "type json string" // @Success 200 string "操作成功" // @router /road/video/send_ths [post] func (r *RoadVideoController) SendThs() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req request.RoadVideoOptionReq if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.VideoId <= 0 { br.Msg = "参数有误" return } errMsg, err := yb.SendRoadVideoThsMsg(req.VideoId) if err != nil { br.Msg = errMsg br.ErrMsg = "Yb-SendVideoThsMsg ErrMsg:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" } // VideoPlayLogList // @Title 获取视频点击量列表 // @Description 获取视频点击量列表 // @Param VideoId query int false "视频ID" // @Param SortType query int false "播放时长排序:默认倒序; 1-倒序(多一个数方便前端回显); 2-正序" // @Success 200 {object} response.QuestionClickLogListResp // @router /road/video/click/logs [get] func (r *RoadVideoController) VideoPlayLogList() { br := new(models.BaseResponse).Init() defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } videoId, _ := r.GetInt("VideoId") if videoId <= 0 { br.Msg = "请输入正确的视频ID" return } // 播放时长排序:1-DESC; 2-ASC; sortType, _ := r.GetInt("SortType") var startSize int pageSize, _ := r.GetInt("PageSize") currentIndex, _ := r.GetInt("CurrentIndex") if pageSize <= 0 { pageSize = utils.PageSize20 } if currentIndex <= 0 { currentIndex = 1 } startSize = paging.StartIndex(currentIndex, pageSize) total, resp, err := yb.GetVideoPlayLogList(videoId, 2, startSize, pageSize, sortType) if err != nil { br.Msg = "获取点击量详情列表失败" br.ErrMsg = "VideoPlayLogList ErrMsg:" + err.Error() return } page := paging.GetPaging(currentIndex, pageSize, int(total)) resp.Paging = page br.Ret = 200 br.Success = true br.Msg = "获取成功" br.Data = resp } // SendTemplateMsg // @Title 推送模板消息 // @Description 推送模板消息 // @Param request body request.RoadVideoOptionReq true "type json string" // @Success 200 string "操作成功" // @router /road/video/send_template_msg [post] func (r *RoadVideoController) SendTemplateMsg() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req request.RoadVideoOptionReq if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.VideoId <= 0 { br.Msg = "参数有误" return } errMsg, err := yb.SendRoadVideoTemplateMsg(req.VideoId) if err != nil { br.Msg = errMsg br.ErrMsg = "Yb-SendRoadVideoTemplateMsg ErrMsg:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" } // GetPermission // @Title 查询品种权限 // @Description 查询品种权限 // @Param request body request.RoadVideoOptionReq true "type json string" // @Success 200 string "操作成功" // @router /road/permission [get] func (r *RoadVideoController) GetPermission() { br := new(models.BaseResponse).Init() defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } ret, err := yb.GetFiccPermission() if err != nil { br.Msg = "查询权限出错" br.ErrMsg = "Yb-SendVideoThsMsg ErrMsg:" + err.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" br.Data = ret } // TwoWeekClassifyList // @Title 路演视频-关联报告类型列表 // @Description 路演视频-关联报告类型列表 // @Success 200 {object} models.SimpleClassifyList // @router /road/video/two_week_classify_list [get] func (r *RoadVideoController) TwoWeekClassifyList() { br := new(models.BaseResponse).Init() defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } // 2023-04-19 取classify表relate_video=1的二级分类, 但是需要分层级, 所以对应的一级分类也要组合起来 list, e := models.GetAllClassifyByRelateVideo() if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取路演视频可选报告分类失败, Err: " + e.Error() return } // 获取父级的分类 { idMap := make(map[int]bool) currParentClassifyIdList := make([]int, 0) for _, v := range list { idMap[v.Id] = true if v.ParentId > 0 { currParentClassifyIdList = append(currParentClassifyIdList, v.ParentId) } } findList := list list = make([]*models.Classify, 0) tmpList, tmpErr := services.GetParentClassifyListByParentIdList(currParentClassifyIdList) if tmpErr != nil { br.Msg = "获取失败" br.ErrMsg = "获取上级分类信息失败,Err:" + tmpErr.Error() return } for _, v := range tmpList { if _, ok := idMap[v.Id]; !ok { list = append(list, v) } } list = append(list, findList...) } allList := make([]*models.SimpleClassifyList, 0) for _, v := range list { allList = append(allList, &models.SimpleClassifyList{ Id: v.Id, ClassifyName: v.ClassifyName, ParentId: v.ParentId, Sort: v.Sort, CreateTime: v.CreateTime, Child: make([]*models.SimpleClassifyList, 0), }) } // 先将分类列表排序 services.SortClassifyListBySortAndCreateTime(allList) // 接着转换结构 allList = services.GetClassifyListTreeRecursive(allList, 0) br.Ret = 200 br.Success = true br.Msg = "操作成功" br.Data = allList } // SimpleReportList // @Title 路演视频选择报告-列表 // @Description 路演视频选择报告-列表 // @Param ClassifyIdSecond query int false "二级分类ID" // @Param Keyword query string false "关键词-报告标题" // @Success 200 string "获取成功" // @router /road/video/simple_report_list [get] func (r *RoadVideoController) SimpleReportList() { br := new(models.BaseResponse).Init() defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } cond := ` AND state = 2` pars := make([]interface{}, 0) classifyIdSecond, _ := r.GetInt("ClassifyIdSecond", 0) if classifyIdSecond <= 0 { // 2023-03-03 直接取classify表relate_video=1的二级分类下的报告 //classifyCond := ` AND parent_id > 0 AND relate_video = 1` classifyCond := ` AND relate_video = 1` classifyPars := make([]interface{}, 0) classifyList, e := models.GetClassifyByCondition(classifyCond, "", classifyPars) if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取路演视频可选报告分类失败, Err: " + e.Error() return } var hasChild bool firstClassifyIds := make([]int, 0) secondClassifyIds := make([]int, 0) thirdClassifyIds := make([]int, 0) for _, c := range classifyList { switch c.Level { case 1: firstClassifyIds = append(firstClassifyIds, c.Id) hasChild = true case 2: secondClassifyIds = append(secondClassifyIds, c.Id) hasChild = true case 3: thirdClassifyIds = append(thirdClassifyIds, c.Id) hasChild = true } } if hasChild { classifyCondList := make([]string, 0) if len(firstClassifyIds) > 0 { classifyCondList = append(classifyCondList, ` classify_id_first IN ( `+utils.GetOrmInReplace(len(firstClassifyIds))+` ) `) pars = append(pars, firstClassifyIds) } if len(secondClassifyIds) > 0 { classifyCondList = append(classifyCondList, ` classify_id_second IN ( `+utils.GetOrmInReplace(len(secondClassifyIds))+` ) `) pars = append(pars, secondClassifyIds) } if len(thirdClassifyIds) > 0 { classifyCondList = append(classifyCondList, ` classify_id_third IN ( `+utils.GetOrmInReplace(len(thirdClassifyIds))+` ) `) pars = append(pars, thirdClassifyIds) } cond += fmt.Sprintf(` AND (%s) `, strings.Join(classifyCondList, " OR ")) } else { cond += ` AND 1 = 2` } } else { classifyItem, err := models.GetClassifyById(classifyIdSecond) if err != nil { br.Msg = "获取失败" br.ErrMsg = "获取分类失败, Err: " + err.Error() return } switch classifyItem.Level { case 1: cond += ` AND classify_id_first = ? ` pars = append(pars, classifyIdSecond) case 2: cond += ` AND classify_id_second = ? ` pars = append(pars, classifyIdSecond) case 3: cond += ` AND classify_id_third = ? ` pars = append(pars, classifyIdSecond) } } keyword := r.GetString("Keyword", "") if keyword != "" { kw := fmt.Sprint("%", keyword, "%") cond += ` AND title LIKE ?` pars = append(pars, kw) } fieldArr := []string{"id", "classify_id_first", "classify_id_second", "classify_id_third", "title", "publish_time"} orderRule := ` ORDER BY publish_time DESC, id DESC` reports, e := models.GetReportByCondition(cond, pars, fieldArr, orderRule, true, 0, 5) if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取双周报列表失败, Err: " + e.Error() return } // 查询报告权限 classifyPermissions := make(map[int][]int, 0) { classifyIds := make([]int, 0) for _, v := range reports { minClassifyId, _, e := services.GetMinClassify(v) if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取报告的最小分类失败, Err: " + e.Error() return } if utils.InArrayByInt(classifyIds, minClassifyId) { continue } classifyIds = append(classifyIds, minClassifyId) } if len(classifyIds) > 0 { classifyIdsPermissions, e := models.GetPermissionsByClassifyIds(classifyIds) if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取分类权限失败, Err: " + e.Error() return } for _, v := range classifyIdsPermissions { classifyPermissions[v.ClassifyId] = append(classifyPermissions[v.ClassifyId], v.ChartPermissionId) } } } type SimpleReportListResp struct { ReportId int Title string PublishTime string BindVideo int BindVideoTitle string PermissionIds []int } respList := make([]*SimpleReportListResp, 0) if len(reports) > 0 { reportIds := make([]int, 0) for i := range reports { reportIds = append(reportIds, reports[i].Id) } // 是否绑定 videos, e := ybModels.GetRoadVideoListByReportIds(reportIds) if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取路演视频列表失败, Err: " + e.Error() return } bindMap := make(map[int]int) bindTitleMap := make(map[int]string) for i := range videos { bindMap[videos[i].ReportId] = videos[i].RoadVideoId bindTitleMap[videos[i].ReportId] = videos[i].Title } for i := range reports { tmpReport := reports[i] minClassifyId, _, e := services.GetMinClassify(tmpReport) if e != nil { br.Msg = "获取失败" br.ErrMsg = "获取报告的最小分类失败, Err: " + e.Error() return } respList = append(respList, &SimpleReportListResp{ ReportId: tmpReport.Id, Title: tmpReport.Title, PublishTime: tmpReport.PublishTime.Format(utils.FormatDateTime), BindVideo: bindMap[tmpReport.Id], BindVideoTitle: bindTitleMap[tmpReport.Id], PermissionIds: classifyPermissions[minClassifyId], }) } } br.Ret = 200 br.Success = true br.Msg = "操作成功" br.Data = respList } // SendMsg // @Title 推送消息(模板/客群) // @Description 推送消息(模板/客群) // @Param request body request.RoadVideoOptionReq true "type json string" // @Success 200 string "操作成功" // @router /road/video/send_msg [post] func (r *RoadVideoController) SendMsg() { br := new(models.BaseResponse).Init() br.IsSendEmail = false defer func() { r.Data["json"] = br r.ServeJSON() }() sysUser := r.SysUser if sysUser == nil { br.Msg = "请登录" br.ErrMsg = "请登录,SysUser Is Empty" br.Ret = 408 return } var req request.RoadVideoOptionReq if err := json.Unmarshal(r.Ctx.Input.RequestBody, &req); err != nil { br.Msg = "参数解析异常!" br.ErrMsg = "参数解析失败,Err:" + err.Error() return } if req.VideoId <= 0 { br.Msg = "参数有误" return } // 加锁,避免重复点击造成的多次推送 { redisKey := fmt.Sprint("road_video:send:msg:", req.VideoId) ok := utils.Rc.SetNX(redisKey, 1, time.Second*300) if !ok { br.Msg = "消息已推送, 请勿重复推送" return } defer func() { _ = utils.Rc.Delete(redisKey) }() } item, e := ybModels.GetRoadVideoById(req.VideoId) if e != nil { br.Msg = "视频不存在或已被删除" br.ErrMsg = "获取路演视频失败, Err: " + e.Error() return } if item.PublishState != 1 { br.Msg = "视频未发布, 不可推送" return } if item.SendThsState == 1 && item.SendTemplateState == 1 { br.Msg = "请勿重复推送" return } nowTime := time.Now().Local() updateCols := make([]string, 0) // 可能存在历史数据两个只推了一个所以此处加个判断 // 模板消息 if item.SendTemplateState == 0 { updateCols = append(updateCols, "SendTemplateState", "SendTemplateTime") item.SendTemplateState = 1 item.SendTemplateTime = nowTime go func() { _ = services.SendYbRoadVideoWxMsg(item.RoadVideoId, item.Title, item.PublishTime.Format(utils.FormatDateTime), item.ChartPermissionIds) }() } // 客群消息 if item.SendThsState == 0 { updateCols = append(updateCols, "SendThsState", "SendThsTime") item.SendThsState = 1 item.SendThsTime = nowTime //go func() { // _ = services.SendYbRoadVideoThs(item.RoadVideoId, item.Title, item.ChartPermissionIds) //}() } // 更新状态 if e := item.Update(updateCols); e != nil { br.Msg = "推送失败" br.ErrMsg = "更新路演视频信息失败, Err: " + e.Error() return } br.Ret = 200 br.Success = true br.Msg = "操作成功" }