|
@@ -2,11 +2,15 @@ package api
|
|
|
|
|
|
import (
|
|
|
"errors"
|
|
|
+ "fmt"
|
|
|
"oilseal-train/db/model"
|
|
|
"oilseal-train/db/repo"
|
|
|
+ "oilseal-train/log"
|
|
|
+ "os"
|
|
|
"time"
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
+ "github.com/xuri/excelize/v2"
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
|
)
|
|
@@ -16,6 +20,8 @@ func Bank(r *GinRouter) {
|
|
|
r.GETJWT("/bank/list", BankList)
|
|
|
r.POSTJWT("/bank/update", BankEdit)
|
|
|
r.POSTJWT("/bank/delete/:id", BankDelete)
|
|
|
+ r.GETJWT("/bank/exportXls/:bankId", BankExportXls)
|
|
|
+ r.POSTJWT("/bank/importXls", BankImportXls)
|
|
|
}
|
|
|
|
|
|
func BankAdd(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
@@ -93,3 +99,312 @@ func BankDelete(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
}
|
|
|
return repo.RepoDeleteDoc(apictx.CreateRepoCtx(), repo.CollectionBank, _id)
|
|
|
}
|
|
|
+
|
|
|
+func BankExportXls(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+ // 操作用户为admin
|
|
|
+
|
|
|
+ err := IsAdmin(apictx)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ // 获取题库信息
|
|
|
+ _bankId := c.Param("bankId")
|
|
|
+ bankId, err := primitive.ObjectIDFromHex(_bankId)
|
|
|
+ if err != nil || len(bankId) != 12 {
|
|
|
+ return nil, errors.New("题库id错误")
|
|
|
+ }
|
|
|
+
|
|
|
+ bank := model.Bank{}
|
|
|
+
|
|
|
+ found, err := repo.RepoSeachDoc(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
|
|
|
+ CollectName: repo.CollectionBank,
|
|
|
+ Query: repo.Map{"_id": bankId, "state": 1},
|
|
|
+ }, &bank)
|
|
|
+ if !found || err != nil {
|
|
|
+ return nil, errors.New("未找到题库数据")
|
|
|
+ }
|
|
|
+
|
|
|
+ tests := make([]map[string]interface{}, 0)
|
|
|
+
|
|
|
+ err = repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
|
|
|
+ CollectName: repo.CollectionTest,
|
|
|
+ Query: repo.Map{"bankId": bankId, "state": 1},
|
|
|
+ Sort: bson.M{"_id": -1},
|
|
|
+ Project: []string{"question", "type", "answerItem", "answer", "analyze"},
|
|
|
+ }, &tests)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ if len(tests) < 1 {
|
|
|
+ return nil, errors.New("该题库没有有效数据")
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, test := range tests {
|
|
|
+ for k, ts := range test {
|
|
|
+ if k == "answerItem" {
|
|
|
+ if a, ok := ts.(map[string]interface{})["A"]; ok {
|
|
|
+ test["A"] = a
|
|
|
+ }
|
|
|
+ if b, ok := ts.(map[string]interface{})["B"]; ok {
|
|
|
+ test["B"] = b
|
|
|
+ }
|
|
|
+ if c, ok := ts.(map[string]interface{})["C"]; ok {
|
|
|
+ test["C"] = c
|
|
|
+ }
|
|
|
+ if d, ok := ts.(map[string]interface{})["D"]; ok {
|
|
|
+ test["D"] = d
|
|
|
+ }
|
|
|
+ if _t, ok := ts.(map[string]interface{})["true"]; ok {
|
|
|
+ test["true"] = _t
|
|
|
+ }
|
|
|
+ if _f, ok := ts.(map[string]interface{})["false"]; ok {
|
|
|
+ test["false"] = _f
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if k == "answer" {
|
|
|
+ for _, vi := range ts.(primitive.A) {
|
|
|
+ if vi.(string) == "true" {
|
|
|
+ test["formatAnswer"] = "正确"
|
|
|
+ } else if vi.(string) == "false" {
|
|
|
+ test["formatAnswer"] = "错误"
|
|
|
+ } else {
|
|
|
+ if test["formatAnswer"] != nil {
|
|
|
+ test["formatAnswer"] = fmt.Sprintf("%v,%v", test["formatAnswer"], vi)
|
|
|
+ } else {
|
|
|
+ test["formatAnswer"] = fmt.Sprintf("%v", vi)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if k == "type" {
|
|
|
+ if ts.(int32) == 1 {
|
|
|
+ test["formatType"] = "选择题"
|
|
|
+ }
|
|
|
+ if ts.(int32) == 2 {
|
|
|
+ test["formatType"] = "判断题"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ delete(test, "answerItem")
|
|
|
+ delete(test, "answer")
|
|
|
+ delete(test, "type")
|
|
|
+ }
|
|
|
+
|
|
|
+ f := excelize.NewFile()
|
|
|
+ defer f.Close()
|
|
|
+ // 表格名
|
|
|
+ sheetName := bank.Name
|
|
|
+
|
|
|
+ f.SetSheetName("Sheet1", sheetName)
|
|
|
+ f.SetPageLayout(sheetName, excelize.PageLayoutOrientation("portrait"), excelize.PageLayoutPaperSize(9))
|
|
|
+ f.SetHeaderFooter(sheetName, &excelize.FormatHeaderFooter{
|
|
|
+ FirstHeader: bank.Name,
|
|
|
+ FirstFooter: bank.Name,
|
|
|
+ OddFooter: "第 &P 页,共 &N页",
|
|
|
+ })
|
|
|
+
|
|
|
+ center, _ := f.NewStyle(&excelize.Style{
|
|
|
+ Alignment: &excelize.Alignment{
|
|
|
+ Horizontal: "left",
|
|
|
+ Vertical: "center",
|
|
|
+ },
|
|
|
+ })
|
|
|
+ columns := []ExcelColumn{
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 40,
|
|
|
+ Header: "问题",
|
|
|
+ Key: "question",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 10,
|
|
|
+ Header: "类型",
|
|
|
+ Key: "formatType",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 20,
|
|
|
+ Header: "选项A",
|
|
|
+ Key: "A",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 20,
|
|
|
+ Header: "选项B",
|
|
|
+ Key: "B",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 20,
|
|
|
+ Header: "选项C",
|
|
|
+ Key: "C",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 20,
|
|
|
+ Header: "选项D",
|
|
|
+ Key: "D",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 10,
|
|
|
+ Header: "TRUE",
|
|
|
+ Key: "true",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ Style: center,
|
|
|
+ Width: 10,
|
|
|
+ Header: "FALSE",
|
|
|
+ Key: "false",
|
|
|
+ },
|
|
|
+ {
|
|
|
+
|
|
|
+ Style: center,
|
|
|
+ Width: 20,
|
|
|
+ Header: "答案",
|
|
|
+ Key: "formatAnswer",
|
|
|
+ },
|
|
|
+ {
|
|
|
+
|
|
|
+ Style: center,
|
|
|
+ Width: 40,
|
|
|
+ Header: "解析",
|
|
|
+ Key: "analyze",
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ // 代表每列的单元格字符
|
|
|
+ cos := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}
|
|
|
+ // 设置列格式 和 表头内容(第一列)
|
|
|
+ i := 1
|
|
|
+ for k, col := range columns {
|
|
|
+ f.SetColStyle(sheetName, cos[k], col.Style)
|
|
|
+ f.SetColWidth(sheetName, cos[k], cos[k], col.Width) // A,A,10
|
|
|
+ setstring := fmt.Sprintf("%s%d", cos[k], i)
|
|
|
+ f.SetCellValue(sheetName, setstring, col.Header)
|
|
|
+ }
|
|
|
+
|
|
|
+ setCellKey := map[string]string{
|
|
|
+ "A": "question",
|
|
|
+ "B": "formatType",
|
|
|
+ "C": "A",
|
|
|
+ "D": "B",
|
|
|
+ "E": "C",
|
|
|
+ "F": "D",
|
|
|
+ "G": "true",
|
|
|
+ "H": "false",
|
|
|
+ "I": "formatAnswer",
|
|
|
+ "J": "analyze",
|
|
|
+ }
|
|
|
+ rowStyle, _ := f.NewStyle(&excelize.Style{
|
|
|
+ Border: []excelize.Border{
|
|
|
+ {Type: "bottom", Color: "#000000", Style: 2},
|
|
|
+ },
|
|
|
+ Alignment: &excelize.Alignment{
|
|
|
+ Horizontal: "left",
|
|
|
+ Vertical: "center",
|
|
|
+ },
|
|
|
+ })
|
|
|
+ f.SetRowStyle(sheetName, i, len(tests)+1, rowStyle)
|
|
|
+
|
|
|
+ i++
|
|
|
+
|
|
|
+ // rows
|
|
|
+ for _, test := range tests {
|
|
|
+
|
|
|
+ // 每行的单元格
|
|
|
+ for k, v := range test {
|
|
|
+
|
|
|
+ f.SetRowHeight(sheetName, i, 25)
|
|
|
+
|
|
|
+ for _, c := range cos {
|
|
|
+ // "id" == "id" -- set A3
|
|
|
+ if setCellKey[c] == k { // A,B,C与item.key的关系
|
|
|
+ setString := fmt.Sprintf("%s%d", c, i)
|
|
|
+ f.SetCellValue(sheetName, setString, v)
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ i++
|
|
|
+
|
|
|
+ }
|
|
|
+ // 另存为
|
|
|
+ _ = os.MkdirAll("excel", os.ModePerm)
|
|
|
+ // filename1 := time.Now().Format("20060102150405") + ".xlsx"
|
|
|
+ filename1 := bank.Name + ".xlsx"
|
|
|
+ err = f.SaveAs(filename1)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ filename := filename1
|
|
|
+ // filename := time.Now().Format("20060102150405") + ".xlsx"
|
|
|
+ c.Header("Content-Type", "application/octet-stream")
|
|
|
+ c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
|
|
|
+ c.Header("Content-Transfer-Encoding", "binary")
|
|
|
+ err = f.Write(c.Writer)
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return true, nil
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func BankImportXls(c *gin.Context, apictx *ApiSession) (interface{}, error) {
|
|
|
+ // 操作用户为admin
|
|
|
+ err := IsAdmin(apictx)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ // _id := c.PostForm("id")
|
|
|
+ // id, err = primitive.ObjectIDFromHex(_id)
|
|
|
+ // if err != nil {
|
|
|
+ // return nil, err
|
|
|
+ // }
|
|
|
+ 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
|
|
|
+ }
|
|
|
+ return users, nil
|
|
|
+ errors := []string{}
|
|
|
+ if len(users) > 0 {
|
|
|
+ for index, user := range users {
|
|
|
+ if index == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ rowNum := index + 1
|
|
|
+ addUser, err := formatUser(user, rowNum)
|
|
|
+ if err != nil {
|
|
|
+ errors = append(errors, err.Error())
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ _, err = repo.RepoAddDoc(apictx.CreateRepoCtx(), repo.CollectionUser, addUser)
|
|
|
+ if err != nil {
|
|
|
+ errors = append(errors, fmt.Sprintf("第%d行错误: %s", rowNum, "保存数据失败"))
|
|
|
+ log.Error(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return errors, nil
|
|
|
+}
|