user.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. package api
  2. import (
  3. "copter-train/log"
  4. "copter-train/utils"
  5. "errors"
  6. "fmt"
  7. "net/url"
  8. "time"
  9. "copter-train/db/model"
  10. "copter-train/db/repo"
  11. "github.com/gin-gonic/gin"
  12. "github.com/xuri/excelize/v2"
  13. "go.mongodb.org/mongo-driver/bson"
  14. "go.mongodb.org/mongo-driver/bson/primitive"
  15. )
  16. type UserLoginPasswordReq struct {
  17. LoginName string `json:"loginName"`
  18. Password string `json:"password"`
  19. Role string `json:"role"`
  20. }
  21. func UserLoginPassword(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  22. var form UserLoginPasswordReq
  23. err := c.ShouldBindJSON(&form)
  24. if err != nil {
  25. return nil, err
  26. }
  27. // 查找用户:根据longinName/password/role是否在roles中
  28. user := &model.User{}
  29. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  30. CollectName: repo.CollectionUser,
  31. Query: repo.Map{
  32. "loginName": form.LoginName,
  33. "password": utils.UtilMd5(form.Password),
  34. "roles": bson.M{"$elemMatch": bson.M{"$eq": form.Role}},
  35. },
  36. }, user)
  37. if err != nil {
  38. return nil, err
  39. }
  40. if !found {
  41. return nil, errors.New("账号/密码/角色不正确")
  42. }
  43. jwtU := &JWTUser{ID: user.GetID()}
  44. token, _, err := apictx.Svc.JWT.JwtCreateToken(jwtU)
  45. if err != nil {
  46. return nil, err
  47. }
  48. // 前端返回处理
  49. user.Password = ""
  50. out := map[string]interface{}{
  51. "token": token,
  52. "user": user,
  53. }
  54. return out, nil
  55. }
  56. // 用户唯一
  57. // db.users.createIndex({ nid: 1 }, { unique: true })
  58. func CreateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  59. // 验证是否为管理员
  60. isAdmin, err := IsAdmin(c, apictx)
  61. if err != nil {
  62. return nil, err
  63. }
  64. if !isAdmin {
  65. return nil, errors.New("没有权限")
  66. }
  67. user := &model.User{}
  68. err = c.ShouldBindJSON(&user)
  69. if err != nil {
  70. log.Error(err)
  71. return nil, err
  72. }
  73. // 验证编号是否存在
  74. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  75. CollectName: repo.CollectionUser,
  76. Query: repo.Map{"nid": user.Nid},
  77. }, user)
  78. if err != nil {
  79. return nil, err
  80. }
  81. if found {
  82. return nil, errors.New("该编号已存在")
  83. }
  84. // ! 编号唯一 验证了编号就不用验证登录名是否存在
  85. // found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  86. // CollectName: repo.CollectionUser,
  87. // Query: repo.Map{"loginName": user.LoginName},
  88. // }, user)
  89. // if err != nil {
  90. // return nil, err
  91. // }
  92. // if found {
  93. // return nil, errors.New("该账号已存在")
  94. // }
  95. // student,teacher,admin
  96. if len(user.Roles) < 1 {
  97. user.Roles = []string{"student"}
  98. }
  99. user.Password = UtilMd5(user.Password)
  100. user.CreateTime = time.Now()
  101. user.UpdateTime = time.Now()
  102. return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionUser, &user)
  103. }
  104. func DeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  105. // 验证是否为管理员
  106. isAdmin, err := IsAdmin(c, apictx)
  107. if err != nil {
  108. return nil, err
  109. }
  110. if !isAdmin {
  111. return nil, errors.New("没有权限")
  112. }
  113. _id := c.Param("id")
  114. id, _ := primitive.ObjectIDFromHex(_id)
  115. if id.IsZero() {
  116. return nil, errors.New("id错误")
  117. }
  118. return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionUser, _id)
  119. }
  120. type BatchDeleteUserReq struct {
  121. Ids []string `json:"ids"`
  122. }
  123. func BatchDeleteUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  124. // 验证是否为管理员
  125. isAdmin, err := IsAdmin(c, apictx)
  126. if err != nil {
  127. return nil, err
  128. }
  129. if !isAdmin {
  130. return nil, errors.New("没有权限")
  131. }
  132. var form BatchDeleteUserReq
  133. err = c.ShouldBindJSON(&form)
  134. if err != nil {
  135. return nil, errors.New("参数错误")
  136. }
  137. if len(form.Ids) > 0 {
  138. for _, id := range form.Ids {
  139. repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionUser, id)
  140. }
  141. }
  142. return true, nil
  143. }
  144. // 用户列表
  145. // /user/list?role=student&name=xxx&nid=xxx&page=1&size=10
  146. func UserList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  147. // 验证是否为管理员
  148. isStudent, err := IsStudent(c, apictx)
  149. if err != nil {
  150. return nil, err
  151. }
  152. if isStudent {
  153. return nil, errors.New("没有权限")
  154. }
  155. page, size, query := UtilQueryPageSize(c)
  156. role := c.Query("role")
  157. name := c.Query("name")
  158. nid := c.Query("nid")
  159. if len(role) > 0 {
  160. query["roles"] = bson.M{"$elemMatch": bson.M{"$eq": role}}
  161. }
  162. if len(name) > 0 {
  163. query["name"] = bson.M{"$regex": name, "$options": "$i"}
  164. }
  165. if len(nid) > 0 {
  166. query["nid"] = bson.M{"$regex": nid, "$options": "$i"}
  167. }
  168. return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  169. CollectName: repo.CollectionUser,
  170. Page: page,
  171. Size: size,
  172. Query: query,
  173. Sort: bson.D{bson.E{Key: "createTime", Value: -1}, bson.E{Key: "_id", Value: -1}},
  174. Project: []string{"nid", "name", "loginName", "avatar", "roles", "createTime", "updateTime"},
  175. })
  176. }
  177. func UserDetail(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  178. // 验证是否为管理员
  179. isAdmin, err := IsAdmin(c, apictx)
  180. if err != nil {
  181. return nil, err
  182. }
  183. if !isAdmin {
  184. return nil, errors.New("没有权限")
  185. }
  186. _id := c.Param("id")
  187. id, _ := primitive.ObjectIDFromHex(_id)
  188. if id.IsZero() {
  189. return nil, errors.New("id错误")
  190. }
  191. return GetUserById(apictx, _id)
  192. }
  193. func UpdateUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  194. // 验证是否为管理员
  195. isAdmin, err := IsAdmin(c, apictx)
  196. if err != nil {
  197. return nil, err
  198. }
  199. if !isAdmin {
  200. return nil, errors.New("没有权限")
  201. }
  202. user := &model.User{}
  203. err = c.ShouldBindJSON(&user)
  204. if err != nil {
  205. log.Error(err)
  206. return nil, err
  207. }
  208. if user.Id.IsZero() {
  209. return nil, errors.New("id错误")
  210. }
  211. su := &model.User{}
  212. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  213. CollectName: repo.CollectionUser,
  214. Query: repo.Map{"nid": user.Nid},
  215. }, su)
  216. if err != nil {
  217. return nil, err
  218. }
  219. if found {
  220. return nil, errors.New("该编号已存在")
  221. }
  222. return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user.Id.Hex(), user)
  223. }
  224. // 获取自己的信息
  225. func UserProfile(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  226. return GetUserById(apictx, apictx.User.ID)
  227. }
  228. // 根据id获取用户信息
  229. func GetUserById(apictx *ApiSession, id string) (*model.User, error) {
  230. user := &model.User{}
  231. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  232. CollectName: repo.CollectionUser,
  233. Query: repo.Map{"_id": id},
  234. }, user)
  235. if err != nil {
  236. log.Error(err)
  237. return nil, err
  238. }
  239. if !found {
  240. return nil, errors.New("未找到该数据")
  241. }
  242. user.Password = ""
  243. return user, nil
  244. }
  245. // 是否是管理员
  246. func IsAdmin(c *gin.Context, apictx *ApiSession) (bool, error) {
  247. user, err := GetUserById(apictx, apictx.User.ID)
  248. if err != nil {
  249. return false, err
  250. }
  251. for _, v := range user.Roles {
  252. if v == "admin" {
  253. return true, nil
  254. }
  255. }
  256. return false, nil
  257. }
  258. // 是否是老师
  259. func IsTeacher(c *gin.Context, apictx *ApiSession) (bool, error) {
  260. user, err := GetUserById(apictx, apictx.User.ID)
  261. if err != nil {
  262. return false, err
  263. }
  264. for _, v := range user.Roles {
  265. if v == "teacher" {
  266. return true, nil
  267. }
  268. }
  269. return false, nil
  270. }
  271. // 是否是学生
  272. func IsStudent(c *gin.Context, apictx *ApiSession) (bool, error) {
  273. user, err := GetUserById(apictx, apictx.User.ID)
  274. if err != nil {
  275. return false, err
  276. }
  277. for _, v := range user.Roles {
  278. if v == "student" {
  279. return true, nil
  280. }
  281. }
  282. return false, nil
  283. }
  284. // 导入用户
  285. func ImportUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  286. isAdmin, err := IsAdmin(c, apictx)
  287. if err != nil {
  288. return nil, err
  289. }
  290. if !isAdmin {
  291. return nil, errors.New("没有权限")
  292. }
  293. file, _, err := c.Request.FormFile("file")
  294. if err != nil {
  295. return nil, errors.New("文件错误")
  296. }
  297. excel, err := excelize.OpenReader(file)
  298. if err != nil {
  299. return nil, err
  300. }
  301. excelIndex := excel.GetActiveSheetIndex()
  302. sheetName := excel.GetSheetName(excelIndex)
  303. users, err := excel.GetRows(sheetName)
  304. if err != nil {
  305. return nil, err
  306. }
  307. errors := []string{}
  308. if len(users) > 0 {
  309. for index, us := range users {
  310. rowNum := index + 1
  311. // 标题行
  312. if index == 0 {
  313. continue
  314. }
  315. // 表头
  316. if index == 1 {
  317. continue
  318. }
  319. // 去除可能的空行
  320. if len(us) == 0 {
  321. continue
  322. }
  323. // 用户名name 编号nid 密码password 角色roles
  324. user := &model.User{}
  325. user.Name = us[0]
  326. user.Nid = us[1]
  327. if len(us[0]) == 0 {
  328. errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "用户名不能为空"))
  329. continue
  330. }
  331. if len(us[1]) == 0 {
  332. errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "编号不能为空"))
  333. continue
  334. }
  335. roles := []string{}
  336. if us[2] == "管理员" {
  337. roles = []string{"admin"}
  338. }
  339. if us[2] == "教员" {
  340. roles = []string{"teacher"}
  341. }
  342. if us[2] == "学员" {
  343. roles = []string{"student"}
  344. }
  345. user.Roles = roles
  346. user.Password = UtilMd5(us[3])
  347. if len(us[3]) == 0 {
  348. user.Password = UtilMd5("123456")
  349. } else if len(us[3]) == 32 {
  350. user.Password = us[3]
  351. }
  352. user.LoginName = fmt.Sprintf("%s_%s", user.Name, user.Nid)
  353. user.CreateTime = time.Now()
  354. user.UpdateTime = time.Now()
  355. _, err = repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionUser, user)
  356. if err != nil {
  357. errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "保存数据失败, 请检查数据格式是否正确/编号是否重复"))
  358. log.Error(err)
  359. }
  360. }
  361. }
  362. return errors, nil
  363. }
  364. // 导出用户
  365. func ExportUser(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  366. isAdmin, err := IsAdmin(c, apictx)
  367. if err != nil {
  368. return nil, err
  369. }
  370. if !isAdmin {
  371. return nil, errors.New("没有权限")
  372. }
  373. f := excelize.NewFile()
  374. index, _ := f.NewSheet("Sheet1")
  375. f.SetActiveSheet(index)
  376. f.SetDefaultFont("宋体")
  377. testExcel := NewUserExcel(f)
  378. testExcel.Title = "用户信息"
  379. _, _, query := UtilQueryPageSize(c)
  380. // 获取试题列表
  381. users := make([]*model.User, 0)
  382. err = repo.RepoSeachDocs(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  383. CollectName: repo.CollectionUser,
  384. Query: query,
  385. Sort: bson.M{"createTime": 1},
  386. }, &users)
  387. if err != nil {
  388. return nil, err
  389. }
  390. testExcel.Content = users
  391. testExcel.Draws()
  392. fileName := url.PathEscape("用户信息.xlsx")
  393. c.Header("Content-Type", "application/octet-stream")
  394. c.Header("Content-Disposition", "attachment; filename="+fileName)
  395. c.Header("Content-Transfer-Encoding", "binary")
  396. err = f.Write(c.Writer)
  397. if err != nil {
  398. return nil, err
  399. }
  400. return nil, nil
  401. }
  402. // 下载用户模板
  403. func UserTmplate(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  404. filename := "用户信息模板.xlsx"
  405. // url.PathEscape将字符串中的特殊字符进行编码,使其符合URL规范
  406. filename = url.PathEscape(filename)
  407. // 设置下载的文件名
  408. c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
  409. // 设置文件类型
  410. c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  411. c.File(USERS_TMPLATE_FILE)
  412. return nil, nil
  413. }