bank.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. package api
  2. import (
  3. "errors"
  4. "fmt"
  5. "oilseal-train/db/model"
  6. "oilseal-train/db/repo"
  7. "oilseal-train/log"
  8. "os"
  9. "strings"
  10. "time"
  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. func Bank(r *GinRouter) {
  17. r.POSTJWT("/bank/create", BankAdd)
  18. r.GETJWT("/bank/list", BankList)
  19. r.POSTJWT("/bank/update", BankEdit)
  20. r.POSTJWT("/bank/delete/:id", BankDelete)
  21. r.GETJWT("/bank/exportXls/:bankId", BankExportXls)
  22. r.POSTJWT("/bank/importXls", BankImportXls)
  23. }
  24. func BankAdd(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  25. err := IsAdmin(apictx)
  26. if err != nil {
  27. return nil, err
  28. }
  29. var form model.Bank
  30. err = c.ShouldBindJSON(&form)
  31. if err != nil {
  32. return nil, errors.New("参数错误")
  33. }
  34. if form.Name == "" {
  35. return nil, errors.New("题库名称不能为空")
  36. }
  37. if form.State == 0 {
  38. form.State = 1
  39. }
  40. form.CreateTime = time.Now()
  41. form.UpdateTime = time.Now()
  42. return repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionBank, &form)
  43. }
  44. func BankList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  45. // err := IsAdmin(apictx)
  46. // if err != nil {
  47. // return nil, err
  48. // }
  49. page, size, query := UtilQueryPageSize(c)
  50. if _name, ok := query["name"]; ok {
  51. query["name"] = bson.M{"$regex": _name.(string)}
  52. }
  53. return repo.RepoPageSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  54. CollectName: repo.CollectionBank,
  55. Page: page,
  56. Size: size,
  57. Query: query,
  58. Project: []string{"name", "state", "desc", "createTime", "updateTime"},
  59. Sort: bson.M{"_id": -1},
  60. })
  61. }
  62. func BankEdit(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  63. // 操作用户为admin
  64. err := IsAdmin(apictx)
  65. if err != nil {
  66. return nil, err
  67. }
  68. var form model.Bank
  69. err = c.ShouldBindJSON(&form)
  70. if err != nil {
  71. return nil, errors.New("参数错误")
  72. }
  73. if len(form.Id) != 12 {
  74. return nil, errors.New("id不正确")
  75. }
  76. return repo.RepoUpdateSetDoc(apictx.CreateRepoCtx(), repo.CollectionBank, form.Id.Hex(), &form)
  77. }
  78. // 删除用户
  79. func BankDelete(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  80. // 操作用户为admin
  81. err := IsAdmin(apictx)
  82. if err != nil {
  83. return nil, err
  84. }
  85. _id := c.Param("id")
  86. _, err = primitive.ObjectIDFromHex(_id)
  87. if err != nil {
  88. return nil, errors.New("id错误")
  89. }
  90. return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBank, _id)
  91. }
  92. func BankExportXls(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  93. // 操作用户为admin
  94. err := IsAdmin(apictx)
  95. if err != nil {
  96. return nil, err
  97. }
  98. // 获取题库信息
  99. _bankId := c.Param("bankId")
  100. bankId, err := primitive.ObjectIDFromHex(_bankId)
  101. if err != nil || len(bankId) != 12 {
  102. return nil, errors.New("题库id错误")
  103. }
  104. bank := model.Bank{}
  105. found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
  106. CollectName: repo.CollectionBank,
  107. Query: repo.Map{"_id": bankId, "state": 1},
  108. }, &bank)
  109. if !found || err != nil {
  110. return nil, errors.New("未找到题库数据")
  111. }
  112. tests := make([]map[string]interface{}, 0)
  113. err = repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
  114. CollectName: repo.CollectionTest,
  115. Query: repo.Map{"bankId": bankId, "state": 1},
  116. Sort: bson.M{"_id": -1},
  117. Project: []string{"question", "type", "answerItem", "answer", "analyze"},
  118. }, &tests)
  119. if err != nil {
  120. return nil, err
  121. }
  122. if len(tests) < 1 {
  123. return nil, errors.New("该题库没有有效数据")
  124. }
  125. for _, test := range tests {
  126. for k, ts := range test {
  127. if k == "answerItem" {
  128. if a, ok := ts.(map[string]interface{})["A"]; ok {
  129. test["A"] = a
  130. }
  131. if b, ok := ts.(map[string]interface{})["B"]; ok {
  132. test["B"] = b
  133. }
  134. if c, ok := ts.(map[string]interface{})["C"]; ok {
  135. test["C"] = c
  136. }
  137. if d, ok := ts.(map[string]interface{})["D"]; ok {
  138. test["D"] = d
  139. }
  140. if _t, ok := ts.(map[string]interface{})["true"]; ok {
  141. test["true"] = _t
  142. }
  143. if _f, ok := ts.(map[string]interface{})["false"]; ok {
  144. test["false"] = _f
  145. }
  146. }
  147. if k == "answer" {
  148. for _, vi := range ts.(primitive.A) {
  149. if vi.(string) == "true" {
  150. test["formatAnswer"] = "正确"
  151. } else if vi.(string) == "false" {
  152. test["formatAnswer"] = "错误"
  153. } else {
  154. if test["formatAnswer"] != nil {
  155. test["formatAnswer"] = fmt.Sprintf("%v,%v", test["formatAnswer"], vi)
  156. } else {
  157. test["formatAnswer"] = fmt.Sprintf("%v", vi)
  158. }
  159. }
  160. }
  161. }
  162. if k == "type" {
  163. if ts.(int32) == 1 {
  164. test["formatType"] = "选择题"
  165. }
  166. if ts.(int32) == 2 {
  167. test["formatType"] = "判断题"
  168. }
  169. }
  170. }
  171. delete(test, "answerItem")
  172. delete(test, "answer")
  173. delete(test, "type")
  174. }
  175. f := excelize.NewFile()
  176. defer f.Close()
  177. // 表格名
  178. sheetName := bank.Name
  179. f.SetSheetName("Sheet1", sheetName)
  180. f.SetPageLayout(sheetName, excelize.PageLayoutOrientation("portrait"), excelize.PageLayoutPaperSize(9))
  181. f.SetHeaderFooter(sheetName, &excelize.FormatHeaderFooter{
  182. FirstHeader: bank.Name,
  183. FirstFooter: bank.Name,
  184. OddFooter: "第 &P 页,共 &N页",
  185. })
  186. center, _ := f.NewStyle(&excelize.Style{
  187. Alignment: &excelize.Alignment{
  188. Horizontal: "left",
  189. Vertical: "center",
  190. },
  191. })
  192. columns := []ExcelColumn{
  193. {
  194. Style: center,
  195. Width: 40,
  196. Header: "问题",
  197. Key: "question",
  198. },
  199. {
  200. Style: center,
  201. Width: 10,
  202. Header: "类型",
  203. Key: "formatType",
  204. },
  205. {
  206. Style: center,
  207. Width: 20,
  208. Header: "选项A",
  209. Key: "A",
  210. },
  211. {
  212. Style: center,
  213. Width: 20,
  214. Header: "选项B",
  215. Key: "B",
  216. },
  217. {
  218. Style: center,
  219. Width: 20,
  220. Header: "选项C",
  221. Key: "C",
  222. },
  223. {
  224. Style: center,
  225. Width: 20,
  226. Header: "选项D",
  227. Key: "D",
  228. },
  229. {
  230. Style: center,
  231. Width: 10,
  232. Header: "TRUE",
  233. Key: "true",
  234. },
  235. {
  236. Style: center,
  237. Width: 10,
  238. Header: "FALSE",
  239. Key: "false",
  240. },
  241. {
  242. Style: center,
  243. Width: 10,
  244. Header: "答案",
  245. Key: "formatAnswer",
  246. },
  247. {
  248. Style: center,
  249. Width: 30,
  250. Header: "解析",
  251. Key: "analyze",
  252. },
  253. }
  254. // 代表每列的单元格字符
  255. cos := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}
  256. // 设置列格式 和 表头内容(第一列)
  257. i := 1
  258. for k, col := range columns {
  259. f.SetColStyle(sheetName, cos[k], col.Style)
  260. f.SetColWidth(sheetName, cos[k], cos[k], col.Width) // A,A,10
  261. setstring := fmt.Sprintf("%s%d", cos[k], i)
  262. f.SetCellValue(sheetName, setstring, col.Header)
  263. }
  264. setCellKey := map[string]string{
  265. "A": "question",
  266. "B": "formatType",
  267. "C": "A",
  268. "D": "B",
  269. "E": "C",
  270. "F": "D",
  271. "G": "true",
  272. "H": "false",
  273. "I": "formatAnswer",
  274. "J": "analyze",
  275. }
  276. rowStyle, _ := f.NewStyle(&excelize.Style{
  277. Border: []excelize.Border{
  278. {Type: "bottom", Color: "#000000", Style: 2},
  279. },
  280. Alignment: &excelize.Alignment{
  281. Horizontal: "left",
  282. Vertical: "center",
  283. },
  284. })
  285. f.SetRowStyle(sheetName, i, len(tests)+1, rowStyle)
  286. i++
  287. // rows
  288. for _, test := range tests {
  289. // 每行的单元格
  290. for k, v := range test {
  291. f.SetRowHeight(sheetName, i, 25)
  292. for _, c := range cos {
  293. // "id" == "id" -- set A3
  294. if setCellKey[c] == k { // A,B,C与item.key的关系
  295. setString := fmt.Sprintf("%s%d", c, i)
  296. f.SetCellValue(sheetName, setString, v)
  297. }
  298. }
  299. }
  300. i++
  301. }
  302. // 另存为
  303. _ = os.MkdirAll("excel", os.ModePerm)
  304. // filename1 := time.Now().Format("20060102150405") + ".xlsx"
  305. filename1 := bank.Name + ".xlsx"
  306. err = f.SaveAs(filename1)
  307. if err != nil {
  308. return nil, err
  309. }
  310. filename := filename1
  311. // filename := time.Now().Format("20060102150405") + ".xlsx"
  312. c.Header("Content-Type", "application/octet-stream")
  313. c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
  314. c.Header("Content-Transfer-Encoding", "binary")
  315. err = f.Write(c.Writer)
  316. if err != nil {
  317. fmt.Println(err)
  318. return false, err
  319. }
  320. return true, nil
  321. }
  322. func BankImportXls(c *gin.Context, apictx *ApiSession) (interface{}, error) {
  323. // 操作用户为admin
  324. err := IsAdmin(apictx)
  325. if err != nil {
  326. return nil, err
  327. }
  328. _id := c.PostForm("id")
  329. id, err := primitive.ObjectIDFromHex(_id)
  330. if err != nil {
  331. return nil, err
  332. }
  333. file, _, err := c.Request.FormFile("file")
  334. if err != nil {
  335. return nil, errors.New("文件错误")
  336. }
  337. excel, err := excelize.OpenReader(file)
  338. if err != nil {
  339. return nil, err
  340. }
  341. excelIndex := excel.GetActiveSheetIndex()
  342. sheetName := excel.GetSheetName(excelIndex)
  343. tests, err := excel.GetRows(sheetName)
  344. if err != nil {
  345. return nil, err
  346. }
  347. // return tests, nil
  348. errors := []string{}
  349. if len(tests) > 0 {
  350. for index, ts := range tests {
  351. // 标题行
  352. if index == 0 {
  353. continue
  354. }
  355. test := &model.Test{}
  356. test.Question = ts[0]
  357. if ts[1] == "选择题" {
  358. test.Type = 1
  359. test.AnswerItem = &model.AnswerItem{
  360. A: ts[2],
  361. B: ts[3],
  362. C: ts[4],
  363. D: ts[5],
  364. }
  365. // 答案 ts[8]
  366. test.Answer = strings.Split(ts[8], ",")
  367. }
  368. if ts[1] == "判断题" {
  369. test.Type = 2
  370. test.AnswerItem = &model.AnswerItem{
  371. True: ts[6],
  372. False: ts[7],
  373. }
  374. // 答案 ts[8]
  375. if ts[8] == "正确" {
  376. test.Answer = append(test.Answer, "true")
  377. }
  378. if ts[8] == "错误" {
  379. test.Answer = append(test.Answer, "false")
  380. }
  381. }
  382. test.BankId = id
  383. if len(ts) > 9 {
  384. test.Analyze = ts[9]
  385. }
  386. test.State = 1
  387. test.CreateTime = time.Now()
  388. test.UpdateTime = time.Now()
  389. rowNum := index + 1
  390. _, err = repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionTest, test)
  391. if err != nil {
  392. errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "保存数据失败"))
  393. log.Error(err)
  394. }
  395. }
  396. }
  397. return errors, nil
  398. }