package api import ( "copter-train/log" "copter-train/utils" "errors" "fmt" "net/url" "time" "copter-train/db/model" "copter-train/db/repo" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) type UserLoginPasswordReq struct { LoginName string `json:"loginName"` Password string `json:"password"` Role string `json:"role"` } func UserLoginPassword(c *gin.Context, apictx *ApiSession) (interface{}, error) { var form UserLoginPasswordReq err := c.ShouldBindJSON(&form) if err != nil { return nil, err } // 查找用户:根据longinName/password/role是否在roles中 user := &model.User{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionUser, Query: repo.Map{ "loginName": form.LoginName, "password": utils.UtilMd5(form.Password), "roles": bson.M{"$elemMatch": bson.M{"$eq": form.Role}}, }, }, user) if err != nil { return nil, err } if !found { return nil, errors.New("账号/密码/角色不正确") } jwtU := &JWTUser{ID: user.GetID()} token, _, err := apictx.Svc.JWT.JwtCreateToken(jwtU) if err != nil { return nil, err } // 前端返回处理 user.Password = "" out := map[string]interface{}{ "token": token, "user": user, } return out, nil } // 用户唯一 // db.users.createIndex({ nid: 1 }, { unique: true }) func CreateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) { // 验证是否为管理员 isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } user := &model.User{} err = c.ShouldBindJSON(&user) if err != nil { log.Error(err) return nil, err } // 验证编号是否存在 found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionUser, Query: repo.Map{"nid": user.Nid}, }, user) if err != nil { return nil, err } if found { return nil, errors.New("该编号已存在") } // ! 编号唯一 验证了编号就不用验证登录名是否存在 // found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ // CollectName: repo.CollectionUser, // Query: repo.Map{"loginName": user.LoginName}, // }, user) // if err != nil { // return nil, err // } // if found { // return nil, errors.New("该账号已存在") // } // student,teacher,admin if len(user.Roles) < 1 { user.Roles = []string{"student"} } user.Password = UtilMd5(user.Password) user.CreateTime = time.Now() user.UpdateTime = time.Now() return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionUser, &user) } func DeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) { // 验证是否为管理员 isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } _id := c.Param("id") id, _ := primitive.ObjectIDFromHex(_id) if id.IsZero() { return nil, errors.New("id错误") } return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionUser, _id) } type BatchDeleteUserReq struct { Ids []string `json:"ids"` } func BatchDeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) { // 验证是否为管理员 isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } var form BatchDeleteUserReq err = c.ShouldBindJSON(&form) if err != nil { return nil, errors.New("参数错误") } if len(form.Ids) > 0 { for _, id := range form.Ids { repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionUser, id) } } return true, nil } // 用户列表 // /user/list?role=student&name=xxx&nid=xxx&page=1&size=10 func UserList(c *gin.Context, apictx *ApiSession) (interface{}, error) { // 验证是否为管理员 isStudent, err := IsStudent(c, apictx) if err != nil { return nil, err } if isStudent { return nil, errors.New("没有权限") } page, size, query := UtilQueryPageSize(c) role := c.Query("role") name := c.Query("name") nid := c.Query("nid") if len(role) > 0 { query["roles"] = bson.M{"$elemMatch": bson.M{"$eq": role}} } if len(name) > 0 { query["name"] = bson.M{"$regex": name, "$options": "$i"} } if len(nid) > 0 { query["nid"] = bson.M{"$regex": nid, "$options": "$i"} } return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{ CollectName: repo.CollectionUser, Page: page, Size: size, Query: query, Sort: bson.D{bson.E{Key: "createTime", Value: -1}, bson.E{Key: "_id", Value: -1}}, Project: []string{"nid", "name", "loginName", "avatar", "roles", "createTime", "updateTime"}, }) } func UserDetail(c *gin.Context, apictx *ApiSession) (interface{}, error) { // 验证是否为管理员 isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } _id := c.Param("id") id, _ := primitive.ObjectIDFromHex(_id) if id.IsZero() { return nil, errors.New("id错误") } return GetUserById(apictx, _id) } func UpdateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) { // 验证是否为管理员 isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } user := &model.User{} err = c.ShouldBindJSON(&user) if err != nil { log.Error(err) return nil, err } if user.Id.IsZero() { return nil, errors.New("id错误") } su := &model.User{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionUser, Query: repo.Map{"nid": user.Nid}, }, su) if err != nil { return nil, err } if found { return nil, errors.New("该编号已存在") } return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user.Id.Hex(), user) } // 获取自己的信息 func UserProfile(c *gin.Context, apictx *ApiSession) (interface{}, error) { return GetUserById(apictx, apictx.User.ID) } // 根据id获取用户信息 func GetUserById(apictx *ApiSession, id string) (*model.User, error) { user := &model.User{} found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionUser, Query: repo.Map{"_id": id}, }, user) if err != nil { log.Error(err) return nil, err } if !found { return nil, errors.New("未找到该数据") } user.Password = "" return user, nil } // 是否是管理员 func IsAdmin(c *gin.Context, apictx *ApiSession) (bool, error) { user, err := GetUserById(apictx, apictx.User.ID) if err != nil { return false, err } for _, v := range user.Roles { if v == "admin" { return true, nil } } return false, nil } // 是否是老师 func IsTeacher(c *gin.Context, apictx *ApiSession) (bool, error) { user, err := GetUserById(apictx, apictx.User.ID) if err != nil { return false, err } for _, v := range user.Roles { if v == "teacher" { return true, nil } } return false, nil } // 是否是学生 func IsStudent(c *gin.Context, apictx *ApiSession) (bool, error) { user, err := GetUserById(apictx, apictx.User.ID) if err != nil { return false, err } for _, v := range user.Roles { if v == "student" { return true, nil } } return false, nil } // 导入用户 func ImportUser(c *gin.Context, apictx *ApiSession) (interface{}, error) { isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } file, _, err := c.Request.FormFile("file") if err != nil { return nil, errors.New("文件错误") } excel, err := excelize.OpenReader(file) if err != nil { return nil, err } excelIndex := excel.GetActiveSheetIndex() sheetName := excel.GetSheetName(excelIndex) users, err := excel.GetRows(sheetName) if err != nil { return nil, err } errors := []string{} if len(users) > 0 { for index, us := range users { rowNum := index + 1 // 标题行 if index == 0 { continue } // 表头 if index == 1 { continue } // 去除可能的空行 if len(us) == 0 { continue } // 用户名name 编号nid 密码password 角色roles user := &model.User{} user.Name = us[0] user.Nid = us[1] if len(us[0]) == 0 { errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "用户名不能为空")) continue } if len(us[1]) == 0 { errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "编号不能为空")) continue } roles := []string{} if us[2] == "管理员" { roles = []string{"admin"} } if us[2] == "教员" { roles = []string{"teacher"} } if us[2] == "学员" { roles = []string{"student"} } user.Roles = roles user.Password = UtilMd5(us[3]) if len(us[3]) == 0 { user.Password = UtilMd5("123456") } else if len(us[3]) == 32 { user.Password = us[3] } user.LoginName = fmt.Sprintf("%s_%s", user.Name, user.Nid) user.CreateTime = time.Now() user.UpdateTime = time.Now() _, err = repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user) if err != nil { errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "保存数据失败, 请检查数据格式是否正确/编号是否重复")) log.Error(err) } } } return errors, nil } // 导出用户 func ExportUser(c *gin.Context, apictx *ApiSession) (interface{}, error) { isAdmin, err := IsAdmin(c, apictx) if err != nil { return nil, err } if !isAdmin { return nil, errors.New("没有权限") } f := excelize.NewFile() index, _ := f.NewSheet("Sheet1") f.SetActiveSheet(index) f.SetDefaultFont("宋体") testExcel := NewUserExcel(f) testExcel.Title = "用户信息" _, _, query := UtilQueryPageSize(c) // 获取试题列表 users := make([]*model.User, 0) err = repo.RepoSeachDocs(apictx.CreateRepoCtx(), &repo.DocSearchOptions{ CollectName: repo.CollectionUser, Query: query, Sort: bson.M{"createTime": 1}, }, &users) if err != nil { return nil, err } testExcel.Content = users testExcel.Draws() fileName := url.PathEscape("用户信息.xlsx") c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename="+fileName) c.Header("Content-Transfer-Encoding", "binary") err = f.Write(c.Writer) if err != nil { return nil, err } return nil, nil } // 下载用户模板 func UserTmplate(c *gin.Context, apictx *ApiSession) (interface{}, error) { filename := "用户信息模板.xlsx" // url.PathEscape将字符串中的特殊字符进行编码,使其符合URL规范 filename = url.PathEscape(filename) // 设置下载的文件名 c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) // 设置文件类型 c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") c.File(USERS_TMPLATE_FILE) return nil, nil }