animeic há 2 anos atrás
pai
commit
8b0a8d6ed2

BIN
oilseal-train/20221212175741.xlsx


+ 315 - 0
oilseal-train/api/bank.go

@@ -2,11 +2,15 @@ package api
 
 
 import (
 import (
 	"errors"
 	"errors"
+	"fmt"
 	"oilseal-train/db/model"
 	"oilseal-train/db/model"
 	"oilseal-train/db/repo"
 	"oilseal-train/db/repo"
+	"oilseal-train/log"
+	"os"
 	"time"
 	"time"
 
 
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/xuri/excelize/v2"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 )
@@ -16,6 +20,8 @@ func Bank(r *GinRouter) {
 	r.GETJWT("/bank/list", BankList)
 	r.GETJWT("/bank/list", BankList)
 	r.POSTJWT("/bank/update", BankEdit)
 	r.POSTJWT("/bank/update", BankEdit)
 	r.POSTJWT("/bank/delete/:id", BankDelete)
 	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) {
 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)
 	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
+}

+ 1 - 3
oilseal-train/api/test.go

@@ -36,9 +36,7 @@ func TestAdd(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	if form.Question == "" {
 	if form.Question == "" {
 		return nil, errors.New("题目不能为空")
 		return nil, errors.New("题目不能为空")
 	}
 	}
-	if len(form.AnswerItems) < 1 {
-		return nil, errors.New("答题选项不能为空")
-	}
+
 	if len(form.Answer) < 1 {
 	if len(form.Answer) < 1 {
 		return nil, errors.New("答案不能为空")
 		return nil, errors.New("答案不能为空")
 	}
 	}

+ 8 - 9
oilseal-train/api/tmp.json

@@ -1,13 +1,12 @@
 {
 {
-  "_id": "6397fa6b642328e50ebf0c03",
-  "analyze": "CRF没有HMM那样严格的独立性假设条件,因而可以容纳任意的上下文信息。特征设计灵活与ME一样",
+  "bankId": "6397f71e94ab390229bb866e",
+  "question": "辅助存储器用于存储当前不参与运行或需要长久保存的程序和数据。其特点是存储容量大、价格低,但与主存储器相比,其存取速度较慢。",
+  "answerItem": {
+    "true": "正确",
+    "false": "错误"
+  },
   "answer": [
   "answer": [
-    "C"
+    "true"
   ],
   ],
-  "answerItems": {
-    "A": "特征灵活",
-    "B": "可容纳较多上下文信息",
-    "C": "速度快",
-    "D": "全局最优"
-  }
+  "type": 2
 }
 }

+ 2 - 2
oilseal-train/api/user.go

@@ -198,7 +198,7 @@ func UserExportXls(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	}
 	}
 	selections := c.Query("selections")
 	selections := c.Query("selections")
 	query := repo.Map{}
 	query := repo.Map{}
-	if len(selections) > 12 {
+	if len(selections) >= 12 {
 		selects := strings.Split(selections, ",")
 		selects := strings.Split(selections, ",")
 		query["_id"] = bson.M{"$in": selects}
 		query["_id"] = bson.M{"$in": selects}
 	}
 	}
@@ -212,7 +212,7 @@ func UserExportXls(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 	if len(users) < 1 {
 	if len(users) < 1 {
-		return users, nil
+		return nil, errors.New("没有数据")
 	}
 	}
 
 
 	f := excelize.NewFile()
 	f := excelize.NewFile()

+ 16 - 7
oilseal-train/db/model/Test.go

@@ -15,11 +15,20 @@ type Test struct {
 	// ["A"]
 	// ["A"]
 	// {"true":"正确","false":"错误"}
 	// {"true":"正确","false":"错误"}
 	// ["true"]
 	// ["true"]
-	AnswerItems map[string]string `bson:"answerItems,omitempty" json:"answerItems,omitempty"`
-	Answer      []string          `bson:"answer,omitempty" json:"answer,omitempty"`
-	Analyze     string            `bson:"analyze,omitempty" json:"analyze,omitempty"` // 解析
-	Type        int               `bson:"type,omitempty" json:"type,omitempty"`       // 1 选择题 2 判断题
-	State       int               `bson:"state,omitempty" json:"state,omitempty"`     //-1 禁用 1 正常
-	CreateTime  time.Time         `bson:"createTime,omitempty" json:"createTime,omitempty"`
-	UpdateTime  time.Time         `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+	AnswerItem *AnswerItem `bson:"answerItem,omitempty" json:"answerItem,omitempty"`
+	Answer     []string    `bson:"answer,omitempty" json:"answer,omitempty"`
+	Analyze    string      `bson:"analyze,omitempty" json:"analyze,omitempty"` // 解析
+	Type       int         `bson:"type,omitempty" json:"type,omitempty"`       // 1 选择题 2 判断题
+	State      int         `bson:"state,omitempty" json:"state,omitempty"`     //-1 禁用 1 正常
+	CreateTime time.Time   `bson:"createTime,omitempty" json:"createTime,omitempty"`
+	UpdateTime time.Time   `bson:"updateTime,omitempty" json:"updateTime,omitempty"`
+}
+
+type AnswerItem struct {
+	A     string `bson:"A,omitempty" json:"A,omitempty"`
+	B     string `bson:"B,omitempty" json:"B,omitempty"`
+	C     string `bson:"C,omitempty" json:"C,omitempty"`
+	D     string `bson:"D,omitempty" json:"D,omitempty"`
+	True  string `bson:"true,omitempty" json:"true,omitempty"`
+	False string `bson:"false,omitempty" json:"false,omitempty"`
 }
 }

BIN
oilseal-train/发动机附件油封台.xlsx