dao-exam-record.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. package dao
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "exam_system/config"
  6. "exam_system/entity"
  7. "exam_system/result"
  8. "exam_system/utils"
  9. "exam_system/vo"
  10. "fmt"
  11. "strconv"
  12. "time"
  13. "github.com/gin-gonic/gin"
  14. "github.com/jmoiron/sqlx"
  15. uuid "github.com/satori/go.uuid"
  16. "github.com/xuri/excelize/v2"
  17. )
  18. func AddExamRecord(er *entity.ExamRecord) *result.Result {
  19. // 2、插入
  20. uuId := uuid.NewV4().String()
  21. sqlStr := "update exam_record er set create_at=?,update_at=?,token=?,ip=inet_aton(?),status=? where er.id = ? and er.user_id=?"
  22. _, err := config.DB.Exec(sqlStr, time.Now(), time.Now(), uuId, er.Ip, entity.TESTING, er.Id, er.UserId)
  23. if err != nil {
  24. return result.UNKNOW_ERROR.SetData(err)
  25. }
  26. return result.SuccessResult(gin.H{
  27. "id": er.Id,
  28. "token": uuId,
  29. })
  30. }
  31. func ExamRecordDetail(id, uid int) *result.Result {
  32. // 1、考试详情
  33. sqlStr := `select e.name,e.create_at,e.update_at,e.duration,e.start_at,e.end_at,e.publish_at,tp.score,tp.pass_score,er.score user_score,timestampdiff(minute,er.create_at,er.update_at) user_take_time
  34. from user u left join exam_record er on u.id = er.user_id
  35. LEFT JOIN exam e ON e.id = er.exam_id
  36. LEFT JOIN test_paper tp ON e.tp_id = tp.id
  37. LEFT JOIN exam_class ec ON e.id = ec.exam_id
  38. LEFT JOIN class c ON ec.class_id = c.id
  39. where er.id = ? and u.id = ? and e.delete_at is null `
  40. var t vo.ExamRecordVo1
  41. err := config.DB.Get(&t, sqlStr, id, uid)
  42. if err != nil {
  43. if err == sql.ErrNoRows {
  44. return result.DATA_NOT_FOUND
  45. }
  46. return result.UNKNOW_ERROR.SetMsg(err.Error())
  47. }
  48. if t.PublishAt.After(time.Now()) {
  49. t.UserScore = nil
  50. }
  51. // 题目答案, 用户答案
  52. sqlStr = "select er.answer from exam_record er where er.id = ? and er.delete_at is null"
  53. var answerStr string
  54. err = config.DB.Get(&answerStr, sqlStr, id)
  55. if err != nil {
  56. return result.UNKNOW_ERROR.SetMsg(err.Error())
  57. }
  58. var avs []*vo.AnswerVo
  59. err = json.Unmarshal([]byte(answerStr), &avs)
  60. if err != nil {
  61. return result.FORMATE_ERROR
  62. }
  63. for i := 0; i < len(avs); i++ {
  64. var av vo.AnswerVo
  65. sqlStr = "select * from subject where id = ?"
  66. err = config.DB.Get(&av, sqlStr, avs[i].Id)
  67. if err != nil {
  68. if err == sql.ErrNoRows {
  69. continue
  70. }
  71. return result.UNKNOW_ERROR.SetMsg(err.Error())
  72. }
  73. if t.PublishAt.After(time.Now()) {
  74. av.Answer = ""
  75. }
  76. av.OwnAnswer = avs[i].OwnAnswer
  77. avs[i] = &av
  78. }
  79. return result.SuccessResult(gin.H{
  80. "exam_detail": &t,
  81. "subject": &avs,
  82. })
  83. }
  84. func ExamRecordList(page, size int, query map[string]interface{}, uid int) *result.Result {
  85. // 1、获取list
  86. sqlStr := `select er.id,e.name,e.create_at,e.update_at,e.duration,e.start_at,e.end_at,e.publish_at,inet_ntoa(er.ip) ip,tp.score,tp.pass_score,er.score user_score,timestampdiff(minute,er.create_at,er.update_at) user_take_time
  87. from user u left join exam_record er on u.id = er.user_id
  88. LEFT JOIN exam e ON e.id = er.exam_id
  89. LEFT JOIN test_paper tp ON e.tp_id = tp.id
  90. LEFT JOIN exam_class ec ON e.id = ec.exam_id
  91. LEFT JOIN class c ON ec.class_id = c.id
  92. where u.id = ? and e.delete_at is null and er.status!=0 `
  93. params := []interface{}{uid}
  94. if query["name"] != nil {
  95. sqlStr += "and e.name like ? "
  96. params = append(params, "%"+query["name"].(string)+"%")
  97. }
  98. sqlStr += "group by er.id "
  99. if query["create_at"] != nil {
  100. if query["create_at"] == "desc" {
  101. sqlStr += "order by create_at desc "
  102. } else {
  103. sqlStr += "order by create_at asc "
  104. }
  105. } else if query["user_take_time"] != nil {
  106. if query["user_take_time"] == "desc" {
  107. sqlStr += "order by user_take_time desc "
  108. } else {
  109. sqlStr += "order by user_take_time asc "
  110. }
  111. } else if query["user_score"] != nil {
  112. if query["user_score"] == "desc" {
  113. sqlStr += "order by user_score desc "
  114. } else {
  115. sqlStr += "order by user_score asc "
  116. }
  117. } else {
  118. sqlStr += "order by create_at desc "
  119. }
  120. sqlStr += "limit ?,?"
  121. params = append(params, utils.PostionSize(page, size), size)
  122. var evos []*vo.ExamRecordVo1
  123. err := config.DB.Select(&evos, sqlStr, params...)
  124. if err != nil {
  125. return result.UNKNOW_ERROR.SetMsg(err.Error())
  126. }
  127. // 2、总数
  128. sqlStr = `select count(distinct(er.id))
  129. from user u left join exam_record er on u.id = er.user_id
  130. LEFT JOIN exam e ON e.id = er.exam_id
  131. LEFT JOIN test_paper tp ON e.tp_id = tp.id
  132. LEFT JOIN exam_class ec ON e.id = ec.exam_id
  133. LEFT JOIN class c ON ec.class_id = c.id
  134. where u.id = ? and e.delete_at is null and er.status!=0 `
  135. params = []interface{}{uid}
  136. if query["name"] != nil {
  137. sqlStr += "and e.name like ? "
  138. params = append(params, "%"+query["name"].(string)+"%")
  139. }
  140. sqlStr += "group by er.id"
  141. for _, e := range evos {
  142. if e.PublishAt.After(time.Now()) {
  143. e.UserScore = nil
  144. }
  145. }
  146. var total int
  147. err = config.DB.Get(&total, sqlStr, params...)
  148. if err != nil {
  149. return result.UNKNOW_ERROR.SetMsg(err.Error())
  150. }
  151. return result.SUCCESS.SetData(result.NewPage(page, len(evos), total, evos))
  152. }
  153. func UpdateExamRecord(erv *vo.ExamRecordVo) *result.Result {
  154. tx, err := config.DB.Beginx()
  155. return utils.Transation(tx, err, func(tx *sqlx.Tx) *result.Result {
  156. // 1、查询是否存在该记录
  157. sqlStr := `select er.id, er.exam_id
  158. from exam_record er
  159. left join exam e on e.id = er.exam_id
  160. where er.id = ?
  161. and er.token = ?
  162. and er.update_at - er.create_at <= e.duration
  163. and e.end_at > ?
  164. `
  165. err = tx.Get(erv, sqlStr, erv.Id, erv.Token, time.Now())
  166. if err != nil {
  167. if err == sql.ErrNoRows {
  168. return result.DATA_NOT_FOUND.SetMsg("该场考试已过期")
  169. }
  170. return result.UNKNOW_ERROR.SetMsg(err.Error())
  171. }
  172. sqlStr = "update exam_record set token = null,status = ? where id = ?"
  173. var res sql.Result
  174. _, err = tx.Exec(sqlStr, entity.TESTED, erv.Id)
  175. if err != nil {
  176. return result.UNKNOW_ERROR.SetMsg(err.Error())
  177. }
  178. // 2、查询出所需id
  179. sqlStr = "select c.sub_ids from chapter c left join exam e on c.tp_id = e.tp_id where e.id=?"
  180. var subIdStrs []string
  181. err = tx.Select(&subIdStrs, sqlStr, erv.ExamId)
  182. if err != nil {
  183. return result.UNKNOW_ERROR.SetMsg(err.Error())
  184. }
  185. subIds := make([]*vo.SubIdsVo, 0)
  186. for _, subIdStr := range subIdStrs {
  187. var subIdsVo []*vo.SubIdsVo
  188. err = json.Unmarshal([]byte(subIdStr), &subIdsVo)
  189. if err != nil {
  190. return result.UNKNOW_ERROR.SetMsg(err.Error())
  191. }
  192. subIds = append(subIds, subIdsVo...)
  193. }
  194. // 2.1 构造一个key为id的 map
  195. subIdMap := make(map[int]int, 0)
  196. for _, subId := range subIds {
  197. subIdMap[*subId.Id] = *subId.Score
  198. }
  199. // 2、 批量查询id
  200. toatalScore := 0
  201. for _, answerVo := range erv.AnswerVo {
  202. // 判断提交的试题是否在考试范围内
  203. if _, ok := subIdMap[*answerVo.Id]; !ok {
  204. return result.UNKNOW_ERROR.SetMsg("不存在该试题")
  205. }
  206. var score int
  207. sqlStr = "select count(id) from subject where id=? and answer=?"
  208. err = tx.Get(&score, sqlStr, answerVo.Id, utils.SubjectSort(answerVo.OwnAnswer))
  209. if err != nil {
  210. return result.UNKNOW_ERROR.SetMsg(err.Error())
  211. }
  212. toatalScore += score * subIdMap[*answerVo.Id]
  213. delete(subIdMap, *answerVo.Id)
  214. }
  215. if len(subIdMap) != 0 {
  216. return result.UNKNOW_ERROR.SetMsg("试题提交不完整")
  217. }
  218. var anwserData []byte
  219. anwserData, err = json.Marshal(erv.AnswerVo)
  220. // 插入记录表
  221. sqlStr = "update exam_record set score=?,answer=?,update_at=? where id=? and delete_at is null "
  222. res, err = tx.Exec(sqlStr, toatalScore, string(anwserData), time.Now(), erv.Id)
  223. if err != nil {
  224. return result.UNKNOW_ERROR.SetData(err)
  225. }
  226. affected, _ := res.RowsAffected()
  227. return result.SuccessResult(result.NewResultChange(affected))
  228. })
  229. }
  230. func DeleteExamRecords(ids []string) *result.Result {
  231. parm := []interface{}{time.Now()}
  232. parmStr := ""
  233. for k, id := range ids {
  234. parm = append(parm, id)
  235. if k == (len(ids) - 1) {
  236. parmStr += "?"
  237. } else {
  238. parmStr += "?,"
  239. }
  240. }
  241. sqlStr := fmt.Sprintf("update exam_record set delete_at=? where id in (%s)", parmStr)
  242. res, err := config.DB.Exec(sqlStr, parm...)
  243. if err != nil {
  244. return result.UNKNOW_ERROR.SetMsg(err.Error())
  245. }
  246. affected, _ := res.RowsAffected()
  247. return result.SUCCESS.SetData(result.NewResultChange(affected))
  248. }
  249. func AdminExamRecordDetail(id int) *result.Result {
  250. // 1、考试详情
  251. // sqlStr := `select e.name,e.create_at,e.update_at,e.duration,e.start_at,e.end_at,e.publish_at,tp.score,tp.pass_score,er.score user_score,timestampdiff(minute,er.create_at,er.update_at) user_take_time
  252. //from exam_record er left join exam e on er.exam_id = e.id
  253. // left join test_paper tp on e.tp_id = tp.id
  254. // left join exam_class ec on e.id = ec.exam_id
  255. // left join class c on ec.class_id = c.id
  256. // left join user u on u.class_id = c.id
  257. // where er.id=? and e.delete_at is null
  258. // GROUP BY er.id`
  259. //
  260. // var t vo.ExamRecordVo1
  261. // err := config.DB.Get(&t, sqlStr, id)
  262. // if err != nil {
  263. // if err == sql.ErrNoRows {
  264. // return result.DATA_NOT_FOUND
  265. // }
  266. // return result.UNKNOW_ERROR.SetMsg(err.Error())
  267. // }
  268. // 题目答案, 用户答案
  269. sqlStr := "select er.answer from exam_record er where er.id = ? and er.delete_at is null"
  270. // ! 20240305 这里修改answer为*string类型 数据库为null值会报错
  271. var answerStr *string
  272. err := config.DB.Get(&answerStr, sqlStr, id)
  273. if err != nil {
  274. return result.UNKNOW_ERROR.SetMsg(err.Error())
  275. }
  276. if answerStr == nil {
  277. return result.UNKNOW_ERROR.SetMsg("试卷数据不存在!")
  278. }
  279. var avs []*vo.AnswerVo
  280. err = json.Unmarshal([]byte(*answerStr), &avs)
  281. if err != nil {
  282. return result.FORMATE_ERROR
  283. }
  284. for i := 0; i < len(avs); i++ {
  285. var av vo.AnswerVo
  286. sqlStr = "select * from subject where id = ?"
  287. err = config.DB.Get(&av, sqlStr, avs[i].Id)
  288. if err != nil {
  289. if err.Error() == "sql: no rows in result set" {
  290. continue
  291. }
  292. return result.UNKNOW_ERROR.SetMsg(err.Error())
  293. }
  294. av.OwnAnswer = avs[i].OwnAnswer
  295. if avs[i].OwnAnswer == "-1" {
  296. av.OwnAnswer = ""
  297. }
  298. avs[i] = &av
  299. }
  300. return result.SuccessResult(gin.H{
  301. //"exam_detail": &t,
  302. "subject": &avs,
  303. })
  304. }
  305. func AdminExamRecordList(page, size int, query map[string]interface{}, examId int) *result.Result {
  306. // 1、获取list
  307. sqlStr := `select er.id,
  308. e.name,
  309. e.create_at,
  310. e.update_at,
  311. e.duration,
  312. e.start_at,
  313. e.end_at,
  314. e.publish_at,
  315. tp.score,
  316. tp.pass_score,
  317. er.score user_score,
  318. u.username,
  319. c.name classname,
  320. timestampdiff(minute, er.create_at, er.update_at) user_take_time
  321. from exam_record er
  322. LEFT JOIN exam e ON er.exam_id = e.id
  323. LEFT JOIN test_paper tp ON e.tp_id = tp.id
  324. LEFT JOIN user u on er.user_id = u.id
  325. LEFT JOIN class c on u.class_id = c.id
  326. where e.id = ?
  327. and e.delete_at is null `
  328. params := []interface{}{examId}
  329. if query["name"] != nil {
  330. sqlStr += "and e.name like ? "
  331. params = append(params, "%"+query["name"].(string)+"%")
  332. }
  333. if query["class_id"] != nil {
  334. sqlStr += "and c.id = ? "
  335. params = append(params, query["class_id"])
  336. }
  337. if query["create_at"] != nil {
  338. if query["create_at"] == "desc" {
  339. sqlStr += "order by create_at desc "
  340. } else {
  341. sqlStr += "order by create_at asc "
  342. }
  343. } else if query["user_take_time"] != nil {
  344. if query["user_take_time"] == "desc" {
  345. sqlStr += "order by user_take_time desc "
  346. } else {
  347. sqlStr += "order by user_take_time asc "
  348. }
  349. } else if query["user_score"] != nil {
  350. if query["user_score"] == "desc" {
  351. sqlStr += "order by user_score desc "
  352. } else {
  353. sqlStr += "order by user_score asc "
  354. }
  355. } else {
  356. sqlStr += "order by create_at desc "
  357. }
  358. sqlStr += "limit ?,?"
  359. params = append(params, utils.PostionSize(page, size), size)
  360. var evos []*vo.ExamRecordVo1
  361. err := config.DB.Select(&evos, sqlStr, params...)
  362. if err != nil {
  363. return result.UNKNOW_ERROR.SetMsg(err.Error())
  364. }
  365. // 2、总数
  366. sqlStr = `select count(er.id)
  367. from exam_record er
  368. LEFT JOIN exam e ON er.exam_id = e.id
  369. LEFT JOIN test_paper tp ON e.tp_id = tp.id
  370. LEFT JOIN user u on er.user_id = u.id
  371. LEFT JOIN class c on u.class_id = c.id
  372. where e.id = ? and e.delete_at is null `
  373. params = []interface{}{examId}
  374. if query["name"] != nil {
  375. sqlStr += "and e.name like ? "
  376. params = append(params, "%"+query["name"].(string)+"%")
  377. }
  378. if query["class_id"] != nil {
  379. sqlStr += "and c.id = ? "
  380. params = append(params, query["class_id"])
  381. }
  382. var total int
  383. err = config.DB.Get(&total, sqlStr, params...)
  384. if err != nil {
  385. return result.UNKNOW_ERROR.SetMsg(err.Error())
  386. }
  387. return result.SUCCESS.SetData(result.NewPage(page, len(evos), total, evos))
  388. }
  389. func AdminDownloadExamRecord(file *excelize.File, id string) *result.Result {
  390. // 1、获取list
  391. sqlStr := `SELECT
  392. e.name exam_name,
  393. u.username,
  394. CONCAT(t.name,c.name,'>') term_class,
  395. u.username name,
  396. u.sid,
  397. er.create_at,
  398. er.update_at,
  399. inet_ntoa( er.ip ) ip,
  400. er.score user_score,
  401. timestampdiff( MINUTE, er.create_at, er.update_at ) user_take_time
  402. FROM
  403. exam e left join exam_record er on e.id = er.exam_id
  404. LEFT JOIN user u ON u.id = er.user_id
  405. LEFT JOIN class c ON u.class_id = c.id
  406. LEFT JOIN term t on c.term_id = t.id
  407. WHERE
  408. u.delete_at IS NULL and e.id = ?
  409. `
  410. var evos []*vo.ExamRecordVo2
  411. err := config.DB.Select(&evos, sqlStr, id)
  412. if err != nil {
  413. if err == sql.ErrNoRows {
  414. return result.DATA_NOT_FOUND
  415. }
  416. return result.UNKNOW_ERROR.SetMsg(err.Error())
  417. }
  418. file.SetCellValue("Sheet1", "A1", evos[0].ExamName)
  419. i := 4
  420. for _, evo := range evos {
  421. if evo.TermClass != nil {
  422. file.SetCellValue("Sheet1", "A"+strconv.Itoa(i), *evo.TermClass)
  423. }
  424. file.SetCellValue("Sheet1", "B"+strconv.Itoa(i), evo.Name)
  425. file.SetCellValue("Sheet1", "C"+strconv.Itoa(i), evo.Sid)
  426. file.SetCellValue("Sheet1", "D"+strconv.Itoa(i), evo.CreateAt.Format("2006-01-02 15:04:05"))
  427. file.SetCellValue("Sheet1", "E"+strconv.Itoa(i), evo.UpdateAt.Format("2006-01-02 15:04:05"))
  428. if evo.UserScore != nil {
  429. file.SetCellValue("Sheet1", "F"+strconv.Itoa(i), *evo.UserScore)
  430. }
  431. i++
  432. }
  433. return result.SUCCESS
  434. }