case-api/api/service/User.go

786 lines
20 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"case-api/api/dao"
"case-api/api/model"
"case-api/api/requests"
"case-api/extend/aliyun"
"case-api/extend/app"
"case-api/extend/superKangaroo"
"case-api/utils"
"errors"
"fmt"
"gorm.io/gorm"
"io"
"math/rand"
"net/http"
"strconv"
"strings"
"time"
)
type UserService struct {
}
// HandleUserImage 处理用户图片
func (r *UserService) HandleUserImage(wxAvatar string) (ossPath string, err error) {
if wxAvatar == "" {
return "", nil
}
// 发送GET请求
resp, err := http.Get(wxAvatar)
if err != nil {
return "", err
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)
if resp.StatusCode != 200 {
return "", errors.New("请求失败")
}
// 读取响应体
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
// 设置文件名字
now := time.Now()
dateTimeString := now.Format("20060102150405") // 当前时间字符串
rand.New(rand.NewSource(time.Now().UnixNano())) // 设置随机数
ossPath = "user/avatar/" + dateTimeString + fmt.Sprintf("%d", rand.Intn(9000)+1000) + ".png"
// 上传oss
_, err = aliyun.PutObjectByte(ossPath, respBody)
if err != nil {
return "", err
}
ossPath = "/" + ossPath
return ossPath, nil
}
// GetUserInfo 获取用户数据-不存在时注册,存在时更新
func (r *UserService) GetUserInfo(tx *gorm.DB, req requests.Login) (user *model.User, err error) {
userDao := dao.UserDao{}
basicHospitalDao := dao.BasicHospitalDao{}
// 佳动力
if req.Source == 3 {
// 获取用户数据
maps := make(map[string]interface{})
if req.UserIden != "" {
maps["user_iden"] = req.UserIden // 以此字段来判别是否同一个用户
}
if req.UnionId != "" {
maps["union_id"] = req.UnionId // 以此字段来判别是否同一个用户
}
user, _ = userDao.GetUser(maps)
if user != nil {
// 获取用户医院
basicHospital, err := basicHospitalDao.GetBasicHospitalById(user.HospitalId)
if err != nil {
return nil, err
}
// 修改用户医院
basicHospitalData := make(map[string]interface{})
if basicHospital.HospitalName != req.HospitalName {
basicHospitalData["hospital_name"] = req.HospitalName
}
if len(basicHospitalData) > 0 {
err = basicHospitalDao.EditBasicHospitalById(tx, user.HospitalId, basicHospitalData)
if err != nil {
return nil, err
}
}
// 修改用户
userData := make(map[string]interface{})
if user.UserName != req.DoctorName {
userData["user_name"] = req.HospitalName
user.UserName = req.HospitalName
}
if user.MobileEncryption != req.MobileEncryption {
userData["mobile_encryption"] = req.MobileEncryption
}
if user.Title != utils.DoctorTitleToInt(req.Title) {
userData["title"] = utils.DoctorTitleToInt(req.Title)
}
if user.DepartmentName != req.DepartmentName {
userData["department_name"] = req.DepartmentName
}
if user.Address != req.Address {
userData["address"] = req.Address
}
if len(userData) > 0 {
err = userDao.EditUserById(tx, user.UserId, userData)
if err != nil {
return nil, err
}
}
// 处理用户白名单
err = r.HandleUserWhite(tx, req.IsWhite, req.PlatformKey, req.ProjectId, user.UserId)
if err != nil {
return nil, err
}
} else {
// 佳动力
// 检测医院是否存在
maps = make(map[string]interface{})
maps["source"] = 3
maps["hospital_name"] = req.HospitalName
basicHospital, _ := basicHospitalDao.GetBasicHospital(maps)
if basicHospital == nil {
// 添加医院
hospital := &model.BasicHospital{
HospitalName: req.HospitalName,
Source: req.Source,
HospitalLevel: "未知",
DoctorNumber: 0,
Province: "",
City: "",
County: "",
Address: "",
}
basicHospital, err = basicHospitalDao.AddBasicHospital(tx, hospital)
if err != nil {
return nil, err
}
}
// 添加用户
user = &model.User{
UserIden: req.UserIden,
UserName: req.DoctorName,
UserMobile: "",
MobileEncryption: req.MobileEncryption,
Status: 1,
RegisterSource: 3,
OpenId: "",
UnionId: "",
Sex: 0,
Avatar: "",
Title: utils.DoctorTitleToInt(req.Title),
DepartmentName: req.DepartmentName,
HospitalId: basicHospital.HospitalId,
Address: req.Address,
}
user, err = userDao.AddUser(tx, user)
if err != nil {
return nil, err
}
// 添加医院拥有医生人数
err = basicHospitalDao.Inc(tx, basicHospital.HospitalId, "doctor_number", 1)
if err != nil {
return nil, err
}
// 处理用户白名单
err = r.HandleUserWhite(tx, req.IsWhite, req.PlatformKey, req.ProjectId, user.UserId)
if err != nil {
return nil, err
}
}
}
if req.Source == 2 {
// 获取医生数据-app
user, err = r.GetAppUserInfo(tx, req)
if err != nil {
return nil, err
}
}
return user, nil
}
// AddCaseUserAnswer 增加用户答题记录
func (r *UserService) AddCaseUserAnswer(tx *gorm.DB, caseId, platformId, userId, caseUserId int64, answers []*requests.Answer) (err error) {
// 检测是否已经答题
caseUserAnswerDao := dao.CaseUserAnswerDao{}
maps := make(map[string]interface{})
maps["case_user_id"] = caseUserId
caseUserAnswer, _ := caseUserAnswerDao.GetCaseUserAnswer(maps)
if caseUserAnswer != nil {
return nil
}
// 新增答题记录
caseItemQuestionDao := dao.CaseItemQuestionDao{}
statCaseQuestionDao := dao.StatCaseQuestionDao{}
for _, answer := range answers {
questionId, err := strconv.ParseInt(answer.QuestionId, 10, 64)
if err != nil {
return err
}
// 获取题目数据
caseItemQuestion, err := caseItemQuestionDao.GetCaseItemQuestionById(questionId)
if err != nil {
return err
}
// 问答题不处理
if caseItemQuestion.QuestionType == 3 {
continue
}
if answer.OptionId == "" {
return errors.New("失败")
}
caseUserAnswer = &model.CaseUserAnswer{
CaseUserId: caseUserId,
PlatformId: platformId,
QuestionId: questionId,
UserId: userId,
Answer: answer.Answer,
IsTrue: 0,
}
// 判断是否正确
if caseItemQuestion.QuestionAnswer == answer.Answer {
caseUserAnswer.IsTrue = 1
}
_, err = caseUserAnswerDao.AddCaseUserAnswer(tx, caseUserAnswer)
if err != nil {
return err
}
// 处理回答统计
optionIds := strings.Split(answer.OptionId, ",")
for _, option := range optionIds {
optionId, err := strconv.ParseInt(option, 10, 64)
if err != nil {
return err
}
maps = make(map[string]interface{})
maps["case_id"] = caseId
maps["question_id"] = answer.QuestionId
maps["option_id"] = optionId
statCaseQuestion, _ := statCaseQuestionDao.GetStatCaseQuestion(maps)
if statCaseQuestion == nil {
// 新增回答统计
statCaseQuestion = &model.StatCaseQuestion{
CaseId: caseId,
QuestionId: questionId,
OptionId: optionId,
SelectNum: 1,
}
_, err := statCaseQuestionDao.AddStatCaseQuestion(tx, statCaseQuestion)
if err != nil {
return err
}
} else {
// 增加回答统计数量
err = statCaseQuestionDao.Inc(tx, statCaseQuestion.StatId, "select_num", 1)
if err != nil {
return err
}
}
}
}
return nil
}
// ReportCaseUserAnswer 上报用户答题记录
func (r *UserService) ReportCaseUserAnswer(caseId, caseUserId int64, user *model.User, caseUser *model.CaseUser) (err error) {
// 获取答题记录
caseUserAnswerDao := dao.CaseUserAnswerDao{}
maps := make(map[string]interface{})
maps["case_user_id"] = caseUserId
caseUserAnswers, err := caseUserAnswerDao.GetCaseUserAnswerPreloadList(maps)
if err != nil {
return err
}
// 上报用户答题数据
_, err = superKangaroo.ReportUserAnswerScore(caseId, user.UserIden, caseUserAnswers, caseUser)
if err != nil {
return err
}
return nil
}
// ReportUserScore 发放积分
// scoreType : 积分类型1:完成阅读 2:阅读时间满足 3:优质留言 4:再次优质留言
func (r *UserService) ReportUserScore(tx *gorm.DB, projectId, caseId, platformId int64, scoreType int, user *model.User) (err error) {
// 获取项目关联平台
projectPlatformDao := dao.ProjectPlatformDao{}
maps := make(map[string]interface{})
maps["project_id"] = projectId
maps["platform_id"] = platformId
projectPlatform, err := projectPlatformDao.GetProjectPlatform(maps)
if err != nil {
return err
}
// 检测福利开关
if projectPlatform.IsWelfare == 0 {
// 福利未开
return nil
}
// 默认为白名单用户
isWhite := true
if projectPlatform.IsWhite == 1 {
projectPlatformWhiteService := ProjectPlatformWhiteService{}
isWhite, err = projectPlatformWhiteService.CheckProjectPlatformWhiteByUser(user, projectId, platformId)
if err != nil {
return err
}
}
// 获取需发放积分
score := 0
appScoreTypeStr := "" // 积分发放原因-app
superScoreTypeStr := "" // 积分发放原因-超级袋鼠
nodeName := "" // 获取积分节点名称
if scoreType == 1 {
// 完成阅读
score = projectPlatform.CompleteRead
appScoreTypeStr = "互动病例-完成阅读"
superScoreTypeStr = "调研奖励(完成阅读)"
nodeName = "学习"
} else if scoreType == 2 {
// 阅读时间满足
score = projectPlatform.CompleteReadTime
appScoreTypeStr = "互动病例-阅读时间满足"
superScoreTypeStr = "调研奖励(阅读质量)"
nodeName = "阅读达标"
} else if scoreType == 3 {
// 优质留言
score = projectPlatform.FirstHighQuality
appScoreTypeStr = "互动病例-优质留言"
superScoreTypeStr = "调研奖励(社区贡献)"
nodeName = "优质留言"
} else if scoreType == 4 {
// 再次优质留言
score = projectPlatform.OnceMoreHighQuality
appScoreTypeStr = "互动病例-优质留言"
superScoreTypeStr = "调研奖励(社区贡献)"
nodeName = "优质留言"
}
// 佳动力需求:非白名单用户也需要请求积分记录
// 当用户为非白名单时,重置积分数
if isWhite == false {
score = 0
}
recordScoreDao := dao.RecordScoreDao{}
// 检测是否有相同手机号用户
userDao := dao.UserDao{}
maps = make(map[string]interface{})
maps["mobile_encryption"] = user.MobileEncryption
users, err := userDao.GetUserList(maps)
if err != nil {
return nil
}
for _, m := range users {
// 检测该类型积分是否已经发放(其他平台也算)
maps = make(map[string]interface{})
maps["project_id"] = projectId
maps["case_id"] = caseId
//maps["platform_id"] = platformId
maps["user_id"] = m.UserId
//maps["type"] = scoreType // 类型问题。查询时不要携带类型。如果只阅读完成,但是没有满足时间,满足时间的是否允许发放
recordScore, _ := recordScoreDao.GetRecordScore(maps)
if recordScore != nil {
// 积分已发放过
return nil
}
}
// 获取病例关联平台数据
casePlatformDao := dao.CasePlatformDao{}
maps = make(map[string]interface{})
maps["case_id"] = caseId
maps["platform_id"] = platformId
casePlatform, err := casePlatformDao.GetCasePlatform(maps)
if err != nil {
return err
}
// 检测全部积分是否已发放完毕
remainingScore := projectPlatform.SingleCaseScore - casePlatform.IssuedScore
if remainingScore <= 0 {
// 积分已发放完毕
return nil
}
// 新增发放记录-每发一次记录一次
recordScore := &model.RecordScore{
ProjectId: projectId,
CaseId: caseId,
PlatformId: platformId,
UserId: user.UserId,
UserName: user.UserName,
Type: scoreType,
NodeName: nodeName,
Score: score,
}
recordScore, err = recordScoreDao.AddRecordScore(tx, recordScore)
if err != nil {
return err
}
// 获取用户参与记录
caseUserDao := dao.CaseUserDao{}
maps = make(map[string]interface{})
maps["case_id"] = caseId
maps["platform_id"] = platformId
maps["user_id"] = user.UserId
caseUser, _ := caseUserDao.GetCaseUserUseTx(tx, maps)
if caseUser == nil {
return errors.New("积分发放失败")
}
// 累计用户领取积分数据
err = caseUserDao.Inc(tx, caseUser.CaseUserId, "total_score", score)
if err != nil {
return err
}
// 累计平台发放积分数据
err = casePlatformDao.Inc(tx, casePlatform.CasePlatformId, "issued_score", score)
if err != nil {
return err
}
// 累计发放积分数据
caseDao := dao.CaseDao{}
err = caseDao.Inc(tx, caseId, "issued_score", score)
if err != nil {
return err
}
// 发放积分-
if platformId != 1 && platformId != 2 {
return errors.New("积分发放失败")
}
// 肝胆相照
if platformId == 1 && score > 0 {
_, err = app.ReportUserScore(appScoreTypeStr, user.UserIden, score)
if err != nil {
return err
}
}
// 超级袋鼠
if platformId == 2 {
// 获取病例数据
caseDao := dao.CaseDao{}
result, err := caseDao.GetCaseById(caseId)
if err != nil {
return err
}
_, err = superKangaroo.ReportUserScore(caseId, user.UserIden, superScoreTypeStr, recordScore, result)
if err != nil {
return err
}
}
return nil
}
// GetAppUserInfo 获取医生数据-app
func (r *UserService) GetAppUserInfo(tx *gorm.DB, req requests.Login) (user *model.User, err error) {
userDao := dao.UserDao{}
// 医院唯一标识
var hospitalIden string
var g *app.GetDoctorInfoResponse
// 手机号
if req.MobileEncryption != "" {
g, err = app.GetDoctorInfoByMobile(req.MobileEncryption)
if err != nil {
return nil, err
}
}
// uuid
if req.UserIden != "" {
g, err = app.GetDoctorInfoByUuid(req.UserIden)
if err != nil {
return nil, err
}
}
// UnionId
if req.UnionId != "" {
g, err = app.GetDoctorInfoByUnionId(req.UnionId)
if err != nil {
return nil, err
}
}
// token
if req.Token != "" {
g, err = app.GetDoctorInfoByToken(req.Token)
if err != nil {
return nil, err
}
}
maps := make(map[string]interface{})
maps["user_iden"] = g.Data.Uuid // 以此字段来判别是否同一个用户
user, _ = userDao.GetUser(maps)
if user == nil {
// 肝胆相照
user = &model.User{
UserIden: g.Data.Uuid,
UserName: g.Data.RealName,
UserMobile: g.Data.Mobile,
MobileEncryption: utils.GenerateMD5(g.Data.Mobile),
Status: 1,
RegisterSource: 2,
OpenId: "",
UnionId: req.UnionId,
Sex: 0,
Avatar: "",
Title: utils.DoctorTitleToInt(g.Data.PositionName),
DepartmentName: g.Data.OfficeName,
Address: g.Data.ProvName,
}
user, err = userDao.AddUser(tx, user)
if err != nil {
return nil, err
}
} else {
userData := make(map[string]interface{})
if user.UserName != g.Data.RealName {
userData["user_name"] = g.Data.RealName
}
if user.UserMobile != g.Data.Mobile {
userData["user_mobile"] = g.Data.Mobile
userData["mobile_encryption"] = utils.GenerateMD5(g.Data.Mobile)
}
if user.Title != utils.DoctorTitleToInt(g.Data.PositionName) {
userData["title"] = utils.DoctorTitleToInt(g.Data.PositionName)
}
if user.DepartmentName != g.Data.OfficeName {
userData["department_name"] = g.Data.OfficeName
}
if user.Address != g.Data.ProvName {
userData["address"] = g.Data.ProvName
}
if len(userData) > 0 {
err = userDao.EditUserById(tx, user.UserId, userData)
if err != nil {
return nil, err
}
}
}
hospitalIden = g.Data.HospitalUuid
if hospitalIden == "" {
return nil, errors.New("失败")
}
// 检测医院是否存在
basicHospitalDao := dao.BasicHospitalDao{}
maps = make(map[string]interface{})
maps["source"] = 2
maps["hospital_iden"] = hospitalIden
basicHospital, _ := basicHospitalDao.GetBasicHospital(maps)
if basicHospital == nil {
// 获取医院数据
gHospital, err := app.GetHospitalByUuid(hospitalIden)
if err != nil {
return nil, err
}
// 添加医院
hospital := &model.BasicHospital{
HospitalIden: hospitalIden,
HospitalName: gHospital.Data.Name,
Source: req.Source,
HospitalLevel: gHospital.Data.Level,
DoctorNumber: gHospital.Data.ExpertNum,
Province: gHospital.Data.ProvName,
City: "",
County: "",
Address: "",
}
basicHospital, err = basicHospitalDao.AddBasicHospital(tx, hospital)
if err != nil {
return nil, err
}
}
// 修改用户所属医院
if basicHospital.HospitalId != user.HospitalId {
maps = make(map[string]interface{})
dataMaps := make(map[string]interface{})
dataMaps["hospital_id"] = basicHospital.HospitalId
err = userDao.EditUserById(tx, user.UserId, dataMaps)
if err != nil {
return nil, err
}
}
return user, nil
}
// HandleUserWhite 处理用户白名单
func (r *UserService) HandleUserWhite(tx *gorm.DB, isWhite int, platformKey, projectId string, userId int64) error {
platformDao := dao.PlatformDao{}
maps := make(map[string]interface{})
maps["platform_key"] = platformKey
platform, err := platformDao.GetPlatform(maps)
if err != nil {
return err
}
projectPlatformDao := dao.ProjectPlatformDao{}
maps = make(map[string]interface{})
maps["project_id"] = projectId
maps["platform_id"] = platform.PlatformId
projectPlatform, err := projectPlatformDao.GetProjectPlatform(maps)
if err != nil {
return err
}
// 获取白名单数据
ProjectPlatformDoctorDao := dao.ProjectPlatformDoctorDao{}
maps = make(map[string]interface{})
maps["project_platform_id"] = projectPlatform.ProjectPlatformId
maps["user_id"] = userId
projectPlatformDoctor, _ := ProjectPlatformDoctorDao.GetProjectPlatformDoctor(maps)
if projectPlatformDoctor == nil {
// 新增白名单
if isWhite == 1 {
projectPlatformDoctor = &model.ProjectPlatformDoctor{
ProjectPlatformId: projectPlatform.ProjectPlatformId,
UserId: userId,
}
projectPlatformDoctor, err = ProjectPlatformDoctorDao.AddProjectPlatformDoctor(tx, projectPlatformDoctor)
if err != nil {
return err
}
}
} else {
// 删除白名单
if isWhite == 0 {
maps = make(map[string]interface{})
maps["project_platform_id"] = projectPlatform.ProjectPlatformId
maps["user_id"] = userId
err = ProjectPlatformDoctorDao.DeleteProjectPlatformDoctor(tx, maps)
if err != nil {
return err
}
}
}
return nil
}
// ReportUserScore 获取需发放积分用户 -- 需考虑相同手机号的用户
func (r *UserService) getReportScoreUser(tx *gorm.DB, projectId, caseId, platformId int64, scoreType int, user *model.User) (u *model.User, id int64) {
// 检测是否有相同手机号用户
userDao := dao.UserDao{}
maps := make(map[string]interface{})
maps["mobile_encryption"] = user.MobileEncryption
users, err := userDao.GetUserList(maps)
if err != nil {
return nil, platformId
}
if len(users) > 2 {
// 存在相同手机号用户
for _, m := range users {
if m.UserId == user.UserId {
continue
}
// 检测积分是否已在其他平台发放过
recordScoreDao := dao.RecordScoreDao{}
maps = make(map[string]interface{})
maps["project_id"] = projectId
maps["case_id"] = caseId
maps["user_id"] = user.UserId
recordScore, _ := recordScoreDao.GetRecordScoreUseTx(tx, maps)
if recordScore != nil {
if recordScore.PlatformId != platformId {
// 由其他平台进行发放积分 修改平台id为其他平台id
return user, recordScore.PlatformId
}
}
// 检测该类型积分是否已经发放
maps = make(map[string]interface{})
maps["project_id"] = projectId
maps["case_id"] = caseId
maps["platform_id"] = platformId
maps["user_id"] = user.UserId
maps["type"] = scoreType
recordScore, _ = recordScoreDao.GetRecordScore(maps)
if recordScore != nil {
// 积分已发放过
return nil, platformId
}
}
}
return user, platformId
}
// CheckUserIsJoinCase 检测用户是否已参与过病例 -- 需考虑相同手机号的用户
func (r *UserService) CheckUserIsJoinCase(caseId int64, mobileEncryption string) (isJoin bool) {
// 获取全部相同手机号
userDao := dao.UserDao{}
maps := make(map[string]interface{})
maps["mobile_encryption"] = mobileEncryption
users, err := userDao.GetUserList(maps)
if err != nil {
return true
}
caseUserDao := dao.CaseUserDao{}
// 存在相同手机号用户
for _, m := range users {
// 检测积分是否已在其他平台发放过
maps = make(map[string]interface{})
maps["case_id"] = caseId
maps["user_id"] = m.UserId
caseUser, _ := caseUserDao.GetCaseUser(maps)
if caseUser != nil {
return true
}
}
return false
}