package yb import ( "errors" "fmt" "hongze/hz_crm_api/models" "hongze/hz_crm_api/models/company" "hongze/hz_crm_api/models/system" "hongze/hz_crm_api/models/yb" "hongze/hz_crm_api/models/yb/response" "hongze/hz_crm_api/services" "hongze/hz_crm_api/services/alarm_msg" "hongze/hz_crm_api/utils" "strconv" "strings" "time" ) // GetQuestionList 问题列表 func GetQuestionList(condition string, pars []interface{}, orderStr string, startSize, pageSize int) (total int, resp *response.CommunityQuestionListResp, err error) { resp = new(response.CommunityQuestionListResp) total, list, e := yb.GetCommunityQuestionList(condition, pars, orderStr, startSize, pageSize) if e != nil { err = errors.New("获取问题列表失败 Err:" + e.Error()) return } if len(list) == 0 { return } // 判断是否存在已禁用的回复人, 需要重新分配回复人 adminIdArr := make([]string, 0) questionLen := len(list) userIdArr := make([]string, 0) for i := 0; i < questionLen; i++ { if list[i].ReplierAdminId > 0 { adminIdArr = append(adminIdArr, strconv.Itoa(list[i].ReplierAdminId)) } userIdArr = append(userIdArr, strconv.Itoa(list[i].UserId)) } adminIds := strings.Join(adminIdArr, ",") adminList, e := system.GetSysAdminByIds(adminIds) adminLen := len(adminList) adminEnableMap := make(map[int]int, 0) if adminLen > 0 { for i := 0; i < adminLen; i++ { adminEnableMap[adminList[i].AdminId] = adminList[i].Enabled } } // 是否有提问人详情(可能存在提问人被删除的情况,无详情) userDetailMap := make(map[int]bool, 0) if len(userIdArr) > 0 { userIdStr := strings.Join(userIdArr, ",") userList, e := company.GetFiccCompanyUserByUserIds(userIdStr) if e != nil { err = errors.New("获取提问人列表信息失败, Err:" + e.Error()) return } for i := range userList { userDetailMap[int(userList[i].UserId)] = true } } respList := make([]*response.CommunityQuestionItem, 0) for _, v := range list { // 根据回复人被禁用/待回答/已推送消息判断是否需要重新分配 needReset := false adminEnable := 1 if v.ReplierAdminId > 0 { adminEnable = adminEnableMap[v.ReplierAdminId] } if adminEnable == 0 && v.ReplyStatus == 2 && v.MsgSendStatus >= 1 { needReset = true } item := &response.CommunityQuestionItem{ CommunityQuestionId: v.CommunityQuestionId, UserId: v.UserId, Mobile: v.Mobile, RealName: v.RealName, QuestionContent: v.QuestionContent, ReplierUserId: v.ReplierUserId, ReplierAdminId: v.ReplierAdminId, ReplierRealName: v.ReplierRealName, ReplierAvatar: v.ReplierAvatar, ResearchGroupFirstId: v.ResearchGroupFirstId, ResearchGroupSecondId: v.ResearchGroupSecondId, ResearchGroupFirstName: v.ResearchGroupFirstName, ResearchGroupSecondName: v.ResearchGroupSecondName, ReplyStatus: v.ReplyStatus, MsgSendStatus: v.MsgSendStatus, NeedRedistribute: needReset, CreateTime: v.CreateTime.Format(utils.FormatDateTime), ReplyTime: v.ReplyTime.Format(utils.FormatDateTime), ClickNum: v.ClickNum, UserQaCount: v.UserQaCount, UserHasDetail: userDetailMap[v.UserId], StopReason: v.StopReason, } respList = append(respList, item) } // 数量统计 countList, e := yb.GetCommunityQuestionCount() if e != nil { err = errors.New("获取问题数量统计失败 Err:" + e.Error()) return } respCount := new(response.CommunityQuestionCount) for _, v := range countList { if v.ReplyStatus == 1 { respCount.Free = v.Total continue } if v.ReplyStatus == 2 { respCount.Wait = v.Total continue } if v.ReplyStatus == 3 { respCount.Replied = v.Total continue } } respCount.Total = respCount.Free + respCount.Wait + respCount.Replied resp.List = respList resp.Count = respCount return } func GetQuestionClickLogList(questionId, startSize, pageSize int) (pageTotal int64, resp *response.QuestionClickLogListResp, err error) { questionInfo, e := yb.GetQuestionById(questionId) if e != nil { err = errors.New("提问信息有误 Err:" + e.Error()) return } resp = new(response.QuestionClickLogListResp) list, e := yb.GetAudioLogListByQuestionId(questionId, startSize, pageSize) if e != nil { err = errors.New("获取问题列表失败 Err:" + e.Error()) return } pageTotal, err = yb.GetAudioLogListTotalByQuestionId(questionId) if err != nil { err = errors.New("查询该提问列表总点击量失败 Err:" + err.Error()) return } count, err := yb.GetAudioLogTotalByQuestionId(questionId) if err != nil { err = errors.New("查询该提问总点击量失败 Err:" + err.Error()) return } resp.Count = int(count) resp.QuestionContent = questionInfo.QuestionContent if len(list) == 0 { return } userIds := "" for _, v := range list { userIds += ", " + (strconv.Itoa(v.UserId)) } companyUsersMap := make(map[int]*company.CompanyUser) if userIds != "" { userIds = strings.Trim(userIds, ",") //查询用户相关的客户信息 companyUserList, tErr := company.GetFiccCompanyUserByUserIds(userIds) if tErr != nil { err = errors.New("获取客户信息失败 Err:" + tErr.Error()) return } for _, v := range companyUserList { companyUsersMap[int(v.UserId)] = v } } respList := make([]*response.QuestionClickLogListItem, 0) for _, v := range list { tmp := new(response.QuestionClickLogListItem) tmp.UserId = v.UserId tmp.ClickNum = v.ClickNum tmp.LastCreateTime = v.LastCreateTime tmp.SourceAgent = v.NewSourceAgent if u, ok := companyUsersMap[v.UserId]; ok { tmp.RealName = u.RealName tmp.CompanyName = u.CompanyName tmp.CompanyStatus = u.Status tmp.CompanyId = u.CompanyId } respList = append(respList, tmp) } resp.List = respList return } // GetQuestionCompanyUser 获取提问者详情 func GetQuestionCompanyUser(questionId int) (ret *response.QuestionCompanyUser, err error) { questionInfo, e := yb.GetQuestionById(questionId) if e != nil { err = errors.New("提问信息有误 Err:" + e.Error()) return } companyUserList, err := company.GetFiccCompanyUserByUserIds(strconv.Itoa(questionInfo.UserId)) if err != nil { err = errors.New("获取客户信息失败 Err:" + err.Error()) return } if len(companyUserList) > 0 { item := companyUserList[0] ret = &response.QuestionCompanyUser{ UserId: int(item.UserId), CompanyStatus: item.Status, CompanyName: item.CompanyName, RealName: item.RealName, CompanyId: item.CompanyId, QuestionContent: questionInfo.QuestionContent, CommunityQuestionId: questionInfo.CommunityQuestionId, SellerName: item.SellerName, } } else { err = errors.New("用户不存在") return } return } // DistributeQuestion 分配回复人 func DistributeQuestion(questionId, adminId, researchGroupFirstId, researchGroupSecondId, distributeId int) (errMsg string, err error) { errMsg = "操作成功" // 校验提问信息 item, e := yb.GetQuestionById(questionId) if e != nil { errMsg = "分配失败, 提问信息有误" err = errors.New("提问信息有误 Err:" + e.Error()) return } contentRune := []rune(item.QuestionContent) if len(contentRune) > 28 { errMsg = "问题字数不可超过28个字符" err = errors.New("问题字数不可超过28个字符") return } if item.ReplyStatus == 3 { errMsg = "分配失败, 回复状态有误" err = errors.New(fmt.Sprintf("分配失败, 回复状态有误, ReplyStatus:%d", item.ReplyStatus)) return } // 获取研究员信息 adminInfo, e := system.GetSysAdminById(adminId) if e != nil { errMsg = "分配失败, 研究员信息有误" err = errors.New("研究员信息有误 Err:" + e.Error()) return } if adminInfo.Mobile == "" { errMsg = "分配失败, 研究员手机号有误" err = errors.New("研究员手机号为空") return } if adminInfo.OpenId == "" { errMsg = "该研究员未关注公众号,无法收到消息通知" err = errors.New("该研究员未关注公众号,无法收到消息通知") return } // 获取研究员关联的联系人信息 companyId := 16 userInfo, e := models.GetWxUserByCompanyIdAndMobile(companyId, adminInfo.Mobile) if e != nil { if e.Error() == utils.ErrNoRow() { errMsg = "分配失败, 未找到研究员手机号对应的联系人信息" err = errors.New("未获取到相关联系人信息") return } errMsg = "分配失败" err = errors.New("获取手机号所属联系人失败, Err:" + e.Error()) return } // 回复人openid, 此处可能会出现取不到openid的情况, 可直接忽略掉 replierUserId := int(userInfo.UserId) replierOpenid := "" // 研究员研究方向分组-研报10.0替换成标签库 //firstGroup, e := system.GetResearchGroupById(researchGroupFirstId) firstGroup, e := models.GetVarietyClassifyById(researchGroupFirstId) if e != nil { errMsg = "分配失败, 一级分组信息有误" err = errors.New("获取一级分组信息失败, Err:" + e.Error()) return } //secondGroup, e := system.GetResearchGroupById(researchGroupSecondId) secondGroup, e := models.GetVarietyTagById(researchGroupSecondId) if e != nil { errMsg = "分配失败, 二级分组信息有误" err = errors.New("获取二级分组信息失败, Err:" + e.Error()) return } // 更新提问信息 updateCols := make([]string, 0) updateCols = append(updateCols, "ReplierUserId", "ReplierOpenid", "ReplierAdminId", "ReplierRealName", "ReplierAvatar", "ResearchGroupFirstId", "ResearchGroupSecondId", "ResearchGroupFirstName", "ResearchGroupSecondName", "VarietyTagId", "VarietyTagName", "DistributeAdminId", "DistributeTime", "ReplyStatus", "ReplierIsRead", "MsgSendStatus", "ModifyTime") item.ReplierUserId = replierUserId item.ReplierOpenid = replierOpenid item.ReplierAdminId = adminId item.ReplierRealName = adminInfo.RealName item.ReplierAvatar = adminInfo.AdminAvatar item.ResearchGroupFirstId = researchGroupFirstId item.ResearchGroupSecondId = researchGroupSecondId item.ResearchGroupFirstName = firstGroup.ClassifyName item.ResearchGroupSecondName = secondGroup.TagName item.VarietyTagId = secondGroup.VarietyTagId item.VarietyTagName = secondGroup.TagName item.DistributeAdminId = distributeId item.DistributeTime = time.Now().Local() item.ReplyStatus = 2 item.ReplierIsRead = 0 item.MsgSendStatus = 0 item.ModifyTime = time.Now().Local() if e := item.Update(updateCols); e != nil { errMsg = "分配失败,更新提问信息失败" err = errors.New("更新提问信息失败, Err:" + e.Error()) } return } // SoftDeleteQuestion 删除问题 func SoftDeleteQuestion(questionId int) (err error) { if _, e := yb.GetQuestionById(questionId); e != nil { err = errors.New("提问信息有误 Err:" + e.Error()) return } if e := yb.DeleteQuestion(questionId); e != nil { err = errors.New("删除提问失败 Err:" + e.Error()) } // 删除问答后的逻辑处理 go afterDeleteQuestion(questionId) return } // SendMsgToReplier 推送消息给回复人 func SendMsgToReplier(questionId int) (errMsg string, err error) { errMsg = "推送成功" item, e := yb.GetQuestionById(questionId) if e != nil { errMsg = "问答信息有误" err = errors.New("提问信息有误, Err:" + e.Error()) return } if item.MsgSendStatus >= 1 { return } if item.ReplierUserId == 0 { errMsg = "请先分配回复人" err = errors.New("未分配回复人, 不可推送") return } // 回复人openid为空时查询当前是否已有openid updateCols := make([]string, 0) // 找到研究员的手机号,并查到管理员绑定的账号,找到对应的openid adminInfo, e := system.GetSysAdminById(item.ReplierAdminId) if e != nil { errMsg = "发送失败, 研究员账号查询失败" err = errors.New("发送失败, 研究员账号查询失败, Err:" + e.Error()) return } if adminInfo.OpenId == "" { errMsg = "该研究员未关注公众号,无法发送消息通知" err = errors.New("回复人openid为空, 不可推送") return } // 推送消息 if e := services.SendYbQuestionDistributeWxMsg(item.CommunityQuestionId, adminInfo.AdminId, adminInfo.OpenId, item.QuestionContent, ""); e != nil { err = errors.New("推送模板消息失败, Err:" + e.Error()) return } // 更新问答信息 updateCols = append(updateCols, "ModifyTime", "MsgSendStatus") item.ModifyTime = time.Now().Local() item.MsgSendStatus = 1 if e := item.Update(updateCols); e != nil { err = errors.New("更新问答信息失败, Err:" + e.Error()) } return } // EditQuestion 编辑问题 func EditQuestion(questionId int, content string) (errMsg string, err error) { item, e := yb.GetQuestionById(questionId) if e != nil { errMsg = "提问信息有误" err = errors.New("提问信息有误 Err:" + e.Error()) return } if item.MsgSendStatus >= 1 { errMsg = "问题状态有误,不可编辑" err = errors.New(fmt.Sprintf("问题状态不可编辑, MsgSendStatus:%d", item.MsgSendStatus)) return } updateCols := make([]string, 0) updateCols = append(updateCols, "QuestionContent", "ModifyTime") item.QuestionContent = content item.ModifyTime = time.Now().Local() if e := item.Update(updateCols); e != nil { errMsg = "更新提问信息失败" err = errors.New("更新提问信息失败, Err:" + e.Error()) } return } // CheckCommunityQuestionPermission 查询当前操作用户是否运营管理员权限 func CheckCommunityQuestionPermission(adminId int) (errMsg string, err error) { roleInfo, e := system.GetSysRoleByRoleTypeCode("yb_question_admin") if e != nil { errMsg = "角色信息有误" if e.Error() == utils.ErrNoRow() { err = errors.New("角色不存在, Err: " + e.Error()) return } err = errors.New("角色信息有误, Err: " + e.Error()) return } _, e = system.GetRoleIdsByAdminIdRoleId(adminId, roleInfo.RoleId) if e != nil { errMsg = "无权操作" err = errors.New("无权操作, Err: " + e.Error()) return } return } // afterDeleteQuestion 删除问答后的逻辑处理 func afterDeleteQuestion(questionId int) { var err error defer func() { if err != nil { go alarm_msg.SendAlarmMsg("问答信息删除后,标记站内消息失败"+time.Now().Format(utils.FormatDateTime)+";Err:"+err.Error(), 3) } }() err = company.CancelCompanyApprovalMessage(questionId, services.CompanyApprovalMessageSourceTypeByQuestion) return } // TransferQuestion 转移问题并通知 func TransferQuestion(questionId, adminId, researchGroupFirstId, researchGroupSecondId, distributeId int, distributeName string) (errMsg string, err error) { errMsg = "操作失败" // 校验提问信息 item, e := yb.GetQuestionById(questionId) if e != nil { errMsg = "转移失败, 提问信息有误" err = errors.New("提问信息有误 Err:" + e.Error()) return } if item.ReplyStatus != yb.ReplyStatusWait { errMsg = "当前状态不可转移" err = errors.New("回复状态有误") return } // 获取分类 classifyItem, e := models.GetVarietyClassifyById(researchGroupFirstId) if e != nil { err = errors.New("获取问答标签分类失败 Err:" + e.Error()) return } // 获取标签 tagItem, e := models.GetVarietyTagById(researchGroupSecondId) if e != nil { err = errors.New("获取问答标签失败 Err:" + e.Error()) return } // 获取研究员信息失败 researcher, e := system.GetResearcherAdminAndWxUserByAdminId(adminId) if e != nil { errMsg = "该研究员未关注公众号或无法正确接收模板消息" err = errors.New("获取研究员信息失败 Err:" + e.Error()) return } // 更新问答 nowTime := time.Now().Local() updateCols := []string{ "ReplierIsRead", "ReplierUserId", "ReplierAdminId", "ReplierRealName", "ResearchGroupFirstId", "ResearchGroupFirstName", "ResearchGroupSecondId", "ResearchGroupSecondName", "VarietyTagId", "VarietyTagName", "DistributeAdminId", "DistributeTime", "ModifyTime", } item.ReplierIsRead = 0 item.ReplierUserId = researcher.UserId item.ReplierAdminId = researcher.AdminId item.ReplierRealName = researcher.AdminName item.ResearchGroupFirstId = classifyItem.VarietyClassifyId item.ResearchGroupFirstName = classifyItem.ClassifyName item.ResearchGroupSecondId = tagItem.VarietyTagId item.ResearchGroupSecondName = tagItem.TagName item.VarietyTagId = tagItem.VarietyTagId item.VarietyTagName = tagItem.TagName item.DistributeAdminId = distributeId item.DistributeTime = nowTime item.ModifyTime = nowTime if e = item.Update(updateCols); e != nil { err = errors.New("更新问答失败 Err:" + e.Error()) return } // 新增问答流程 go func() { pro := new(yb.CommunityQuestionProcess) pro.CommunityQuestionId = item.CommunityQuestionId pro.TransferUserId = 0 pro.TransferAdminId = distributeId pro.TransferAdminName = distributeName pro.ReplierUserId = researcher.UserId pro.ReplierAdminId = researcher.AdminId pro.ReplierAdminName = researcher.AdminName pro.VarietyClassifyId = classifyItem.VarietyClassifyId pro.VarietyTagId = tagItem.VarietyTagId pro.Remark = fmt.Sprintf("管理员%s转至%s", distributeName, researcher.AdminName) pro.ProcessType = yb.ProcessTypeTransfer pro.CreateTime = nowTime if e = pro.Create(); e != nil { return } }() // 推送转移模板消息给研究员 go func() { remark := fmt.Sprintf("管理员%s移交了新的问答给您, 请点击详情尽快处理", distributeName) _ = services.SendYbQuestionDistributeWxMsg(item.CommunityQuestionId, researcher.AdminId, researcher.OpenId, item.QuestionContent, remark) }() return }