diff --git a/api/controller/Base.go b/api/controller/Base.go index 8551025..2698986 100644 --- a/api/controller/Base.go +++ b/api/controller/Base.go @@ -16,4 +16,5 @@ type Api struct { StatsCase // 统计数据-病例 Platform // 平台 CaseComment // 病例-评论 + Export // 导出 } diff --git a/api/controller/Export.go b/api/controller/Export.go new file mode 100644 index 0000000..c078cca --- /dev/null +++ b/api/controller/Export.go @@ -0,0 +1,52 @@ +package controller + +import ( + "case-admin-api/api/dao" + "case-admin-api/api/requests" + "case-admin-api/api/responses" + "case-admin-api/api/service" + "case-admin-api/global" + "case-admin-api/utils" + "github.com/gin-gonic/gin" +) + +type Export struct{} + +// ExportUserRecord 用户参与记录导出 +func (b *Export) ExportUserRecord(c *gin.Context) { + exportRequest := requests.ExportRequest{} + req := exportRequest.ExportUserRecord + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + // 获取数据 + userBehaviorRecordDao := dao.UserBehaviorRecordDao{} + userBehaviorRecords, err := userBehaviorRecordDao.GetExportUserRecordListSearch(req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if len(userBehaviorRecords) <= 0 { + responses.FailWithMessage("无数据,不可导出", c) + return + } + + // 业务处理 + exportService := service.ExportService{} + ossAddress, err := exportService.ExportUserRecord(userBehaviorRecords) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(ossAddress, c) +} diff --git a/api/dao/UserBehaviorRecord.go b/api/dao/UserBehaviorRecord.go new file mode 100644 index 0000000..e3cecc7 --- /dev/null +++ b/api/dao/UserBehaviorRecord.go @@ -0,0 +1,207 @@ +package dao + +import ( + "case-admin-api/api/model" + "case-admin-api/api/requests" + "case-admin-api/global" + "errors" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "strings" +) + +type UserBehaviorRecordDao struct { +} + +// GetUserBehaviorRecordById 获取数据-id +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordById(recordId int64) (m *model.UserBehaviorRecord, err error) { + err = global.Db.First(&m, recordId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetUserBehaviorRecordPreloadById 获取数据-加载全部关联-id +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordPreloadById(recordId int64) (m *model.UserBehaviorRecord, err error) { + err = global.Db.Preload(clause.Associations).First(&m, recordId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// DeleteUserBehaviorRecord 删除 +func (r *UserBehaviorRecordDao) DeleteUserBehaviorRecord(tx *gorm.DB, maps interface{}) error { + err := tx.Where(maps).Delete(&model.UserBehaviorRecord{}).Error + if err != nil { + return err + } + return nil +} + +// DeleteUserBehaviorRecordById 删除-id +func (r *UserBehaviorRecordDao) DeleteUserBehaviorRecordById(tx *gorm.DB, recordId int64) error { + if err := tx.Delete(&model.UserBehaviorRecord{}, recordId).Error; err != nil { + return err + } + return nil +} + +// EditUserBehaviorRecord 修改 +func (r *UserBehaviorRecordDao) EditUserBehaviorRecord(tx *gorm.DB, maps interface{}, data interface{}) error { + err := tx.Model(&model.UserBehaviorRecord{}).Where(maps).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// EditUserBehaviorRecordById 修改-id +func (r *UserBehaviorRecordDao) EditUserBehaviorRecordById(tx *gorm.DB, recordId int64, data interface{}) error { + err := tx.Model(&model.UserBehaviorRecord{}).Where("record_id = ?", recordId).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// GetUserBehaviorRecordList 获取列表 +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordList(maps interface{}) (m []*model.UserBehaviorRecord, err error) { + err = global.Db.Where(maps).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetUserBehaviorRecordCount 获取数量 +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordCount(maps interface{}) (total int64, err error) { + err = global.Db.Model(&model.UserBehaviorRecord{}).Where(maps).Count(&total).Error + if err != nil { + return 0, err + } + return total, nil +} + +// GetUserBehaviorRecordListRand 获取列表-随机 +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordListRand(maps interface{}, limit int) (m []*model.UserBehaviorRecord, err error) { + err = global.Db.Where(maps).Order("rand()").Limit(limit).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddUserBehaviorRecord 新增 +func (r *UserBehaviorRecordDao) AddUserBehaviorRecord(tx *gorm.DB, model *model.UserBehaviorRecord) (*model.UserBehaviorRecord, error) { + if err := tx.Create(model).Error; err != nil { + return nil, err + } + return model, nil +} + +// GetUserBehaviorRecord 获取 +func (r *UserBehaviorRecordDao) GetUserBehaviorRecord(maps interface{}) (m *model.UserBehaviorRecord, err error) { + err = global.Db.Where(maps).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetUserBehaviorRecordPreload 获取 +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordPreload(maps interface{}) (m *model.UserBehaviorRecord, err error) { + err = global.Db.Preload(clause.Associations).Where(maps).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetUserBehaviorRecordUseTx 获取 +func (r *UserBehaviorRecordDao) GetUserBehaviorRecordUseTx(tx *gorm.DB, maps interface{}) (m *model.UserBehaviorRecord, err error) { + err = tx.Where(maps).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// Inc 自增 +func (r *UserBehaviorRecordDao) Inc(tx *gorm.DB, recordId int64, field string, numeral int) error { + err := tx.Model(&model.UserBehaviorRecord{}).Where("record_id = ?", recordId).UpdateColumn(field, gorm.Expr(field+" + ?", numeral)).Error + if err != nil { + return err + } + return nil +} + +// Dec 自减 +func (r *UserBehaviorRecordDao) Dec(tx *gorm.DB, recordId int64, field string, numeral int) error { + err := tx.Model(&model.UserBehaviorRecord{}).Where("record_id = ?", recordId).UpdateColumn(field, gorm.Expr(field+" - ?", numeral)).Error + if err != nil { + return err + } + return nil +} + +// GetExportUserRecordListSearch 列表-导出 +func (r *UserBehaviorRecordDao) GetExportUserRecordListSearch(req requests.ExportUserRecord) (m []*model.UserBehaviorRecord, err error) { + // 构建查询条件 + query := global.Db.Model(&model.UserBehaviorRecord{}) + + // 病例 + query = query.Preload("Case") + + // 用户 + query = query.Preload("User") + + // 平台 + query = query.Preload("Platform") + + // 用户医院 + query = query.Preload("User.Hospital") + + if req.CaseId != "" { + query = query.Where("case_id = ?", req.CaseId) + } + + if req.PlatformId != "" { + query = query.Where("platform_id = ?", req.PlatformId) + } + + // 当前搜索数据 + if req.Type == 1 { + if req.PlatformId != "" { + query = query.Where("platform_id = ?", req.PlatformId) + } + + // 搜索关键字 + if req.Keyword != "" { + keyword := "%" + req.Keyword + "%" // + + // 执行组建 + query = query.Where("step LIKE ?", keyword) + } + } + + // 当前选择数据 + if req.Type == 2 { + if req.Id == "" { + return nil, errors.New("未提供需导出数据编号") + } + + id := strings.Split(req.Id, ",") + query = query.Where("record_id IN (?)", id) + } + + // 排序 + query = query.Order("created_at desc") + + err = query.Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} diff --git a/api/model/UserBehaviorRecord.go b/api/model/UserBehaviorRecord.go index 1f42d85..ea867d7 100644 --- a/api/model/UserBehaviorRecord.go +++ b/api/model/UserBehaviorRecord.go @@ -16,6 +16,9 @@ type UserBehaviorRecord struct { StartTime LocalTime `gorm:"column:start_time;type:datetime;comment:开始时间" json:"start_time"` EndTime LocalTime `gorm:"column:end_time;type:datetime;comment:结束时间" json:"end_time"` Model + Platform *Platform `gorm:"foreignKey:PlatformId;references:platform_id" json:"platform"` + Case []*Case `gorm:"foreignKey:CaseId;references:case_id" json:"case"` + User *User `gorm:"foreignKey:UserId;references:user_id" json:"user"` } func (m *UserBehaviorRecord) TableName() string { diff --git a/api/requests/Export.go b/api/requests/Export.go new file mode 100644 index 0000000..dc35fc6 --- /dev/null +++ b/api/requests/Export.go @@ -0,0 +1,14 @@ +package requests + +type ExportRequest struct { + ExportUserRecord // 用户参与记录导出 +} + +// ExportUserRecord 用户参与记录导出 +type ExportUserRecord struct { + Type int `json:"type" form:"type" label:"类型" validate:"required,oneof=1 2 3"` // 1:当前搜索数据 2:当前选择数据 3:全部数据 + Id string `json:"id" form:"id" label:"id"` + PlatformId string `json:"platform_id" form:"platform_id" label:"平台id"` + CaseId string `json:"case_id" form:"case_id" label:"病例id"` + Keyword string `json:"Keyword" form:"Keyword" label:"关键词" validate:"required"` +} diff --git a/api/router/router.go b/api/router/router.go index 1d5b1b7..f8a246d 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -355,4 +355,11 @@ func privateRouter(r *gin.Engine, api controller.Api) { editorGroup.POST("", api.Editor.EditorUpload) } } + + // 导出 + exportGroup := adminGroup.Group("/export") + { + // 用户参与记录导出 + exportGroup.POST("/record", api.Export.ExportUserRecord) + } } diff --git a/api/service/export.go b/api/service/export.go index 567cf2a..68e2307 100644 --- a/api/service/export.go +++ b/api/service/export.go @@ -49,6 +49,20 @@ type StatsCaseUserData struct { EndTime string // 结束参与时间 } +// UserRecordData 用户参与记录 +type UserRecordData struct { + Id string // id标识 + CaseName string // 病历名称 + UserName string // 姓名 + Province string // 省份 + UserMobile string // 手机号 + DoctorTitle string // 职称 + HospitalName string // 医院 + DepartmentName string // 科室 + PlatformName string // 平台名称 + OperateTime string // 操作时间 +} + // ProjectPlatformHospital 医院白名单 func (r *ExportService) ProjectPlatformHospital(projectPlatformHospitals []*model.ProjectPlatformHospital) (string, error) { header := []utils.HeaderCellData{ @@ -250,3 +264,96 @@ func (r *ExportService) StatsCaseUser(statsCaseUsers []*model.CaseUser) (string, ossPath = utils.AddOssDomain("/" + ossPath) return ossPath, nil } + +// ExportUserRecord 用户参与记录导出 +func (r *ExportService) ExportUserRecord(userBehaviorRecords []*model.UserBehaviorRecord) (string, error) { + header := []utils.HeaderCellData{ + {Value: "id标识", CellType: "string", NumberFmt: "", ColWidth: 25}, + {Value: "病历名称", CellType: "string", NumberFmt: "", ColWidth: 35}, + {Value: "姓名", CellType: "string", NumberFmt: "", ColWidth: 25}, + {Value: "省份", CellType: "string", NumberFmt: "", ColWidth: 25}, + {Value: "手机号", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "职称", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "医院", CellType: "string", NumberFmt: "", ColWidth: 35}, + {Value: "科室", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "平台名称", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "操作时间", CellType: "date", NumberFmt: "yyyy-mm-dd hh:mm:ss", ColWidth: 30}, + } + + var dataSlice []interface{} + for _, v := range userBehaviorRecords { + var createdAt string + if v.CreatedAt != (model.LocalTime{}) { + createdAt = time.Time(v.StartTime).Format("2006-01-02 15:04:05") + } + + userRecordData := UserRecordData{ + Id: fmt.Sprintf("%d", v.RecordId), + CaseName: "", + UserName: "", + Province: "", + UserMobile: "", + DoctorTitle: "", + HospitalName: "", + DepartmentName: "", + PlatformName: "", + OperateTime: createdAt, + } + + // 加载数据-平台名称 + if v.Platform != nil { + userRecordData.PlatformName = v.Platform.PlatformName + } + + if v.Case != nil { + userRecordData.CaseName = v.Platform.PlatformName + } + + if v.User != nil { + // 加载数据-手机号 + userRecordData.UserMobile = v.User.UserMobile + + // 加载数据-科室 + userRecordData.DepartmentName = v.User.DepartmentName + + // 加载数据-职称 + userRecordData.DoctorTitle = utils.DoctorTitleToString(v.User.Title) + + // 加载数据-用户名称 + userRecordData.UserName = v.User.UserName + + // 加载数据-省份 + if v.User.Hospital != nil { + userRecordData.Province = v.User.Hospital.Province + + userRecordData.HospitalName = v.User.Hospital.HospitalName + } + } + + dataSlice = append(dataSlice, userRecordData) + } + + file, err := utils.Export(header, dataSlice) + if err != nil { + return "", err + } + + ossPath := "dev/" + if config.C.Env == "prod" { + ossPath = "prod/" + } + // 设置文件名字 + now := time.Now() + dateTimeString := now.Format("20060102150405") // 当前时间字符串 + rand.New(rand.NewSource(time.Now().UnixNano())) // 设置随机数 + ossPath = ossPath + "export/用户参与记录" + dateTimeString + fmt.Sprintf("%d", rand.Intn(9000)+1000) + ".xlsx" + + // 上传oss + _, err = aliyun.PutObjectByte(ossPath, file.Bytes()) + if err != nil { + return "", err + } + + ossPath = utils.AddOssDomain("/" + ossPath) + return ossPath, nil +}